1 /*
2
3 Copyright (C) 2000,2004 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., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
23 USA.
24
25 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
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 #include "pro_section.h"
45 #include "pro_reloc.h"
46 #include "pro_reloc_symbolic.h"
47
48 /*
49 Return DW_DLV_ERROR on malloc error.
50 Return DW_DLV_OK otherwise
51 */
52
53 int
_dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg,int base_sec_index,Dwarf_Unsigned offset,Dwarf_Unsigned symidx,enum Dwarf_Rel_Type type,int reltarget_length)54 _dwarf_pro_reloc_name_symbolic(Dwarf_P_Debug dbg,
55 int base_sec_index,
56 Dwarf_Unsigned offset, /* r_offset of reloc */
57 Dwarf_Unsigned symidx,
58 enum Dwarf_Rel_Type type,
59 int reltarget_length)
60 {
61 /* get a slot, fill in the slot entry */
62 void *relrec_to_fill = 0;
63 int res = 0;
64 struct Dwarf_Relocation_Data_s *slotp;
65
66 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
67 &relrec_to_fill);
68 if (res != DW_DLV_OK)
69 return res;
70 slotp = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
71 slotp->drd_type = type;
72 slotp->drd_length = reltarget_length;
73 slotp->drd_offset = offset;
74 slotp->drd_symbol_index = symidx;
75 return DW_DLV_OK;
76 }
77
78
79
80 /*
81 Return DW_DLV_ERROR on malloc error.
82 Return DW_DLV_OK otherwise
83 */
84 int
_dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg,int base_sec_index,Dwarf_Unsigned offset,Dwarf_Unsigned start_symidx,Dwarf_Unsigned end_symidx,enum Dwarf_Rel_Type type,int reltarget_length)85 _dwarf_pro_reloc_length_symbolic(Dwarf_P_Debug dbg,
86 int base_sec_index,
87 Dwarf_Unsigned offset, /* r_offset of reloc */
88 Dwarf_Unsigned start_symidx,
89 Dwarf_Unsigned end_symidx,
90 enum Dwarf_Rel_Type type,
91 int reltarget_length)
92 {
93 /* get a slot, fill in the slot entry */
94 void *relrec_to_fill = 0;
95 int res = 0;
96 struct Dwarf_Relocation_Data_s *slotp1 = 0;
97 struct Dwarf_Relocation_Data_s *slotp2 = 0;
98
99 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
100 &relrec_to_fill);
101 if (res != DW_DLV_OK)
102 return res;
103 slotp1 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
104 res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
105 &relrec_to_fill);
106 if (res != DW_DLV_OK)
107 return res;
108 slotp2 = (struct Dwarf_Relocation_Data_s *) relrec_to_fill;
109
110 /* ASSERT: type == dwarf_drt_first_of_length_type_pair */
111 slotp1->drd_type = type;
112 slotp1->drd_length = reltarget_length;
113 slotp1->drd_offset = offset;
114 slotp1->drd_symbol_index = start_symidx;
115
116 slotp2->drd_type = dwarf_drt_second_of_length_pair;
117 slotp2->drd_length = reltarget_length;
118 slotp2->drd_offset = offset;
119 slotp2->drd_symbol_index = end_symidx;
120 return DW_DLV_OK;
121 }
122
123 /*
124 Reset whatever fields of Dwarf_P_Per_Reloc_Sect_s
125 we must to allow adding a fresh new single
126 block easily (block consolidation use only).
127
128 */
129 static void
_dwarf_reset_reloc_sect_info(struct Dwarf_P_Per_Reloc_Sect_s * pblk,unsigned long ct)130 _dwarf_reset_reloc_sect_info(struct Dwarf_P_Per_Reloc_Sect_s *pblk,
131 unsigned long ct)
132 {
133
134
135 /* Do not zero pr_sect_num_of_reloc_sect */
136 pblk->pr_reloc_total_count = 0;
137 pblk->pr_first_block = 0;
138 pblk->pr_last_block = 0;
139 pblk->pr_block_count = 0;
140 pblk->pr_slots_per_block_to_alloc = ct;
141 }
142
143 /*
144 Ensure each stream is a single buffer and
145 add that single buffer to the set of stream buffers.
146
147 By creating a new buffer and copying if necessary.
148 (If > 1 block, reduce to 1 block)
149
150 Free the input set of buffers if we consolidate.
151
152 We pass back *new_sec_count as zero because we
153 are not creating normal sections for a .o, but
154 symbolic relocations, separately counted.
155
156 Return -1 on error (malloc failure)
157
158 Return DW_DLV_OK on success. Any other return indicates
159 malloc failed.
160 */
161 int
_dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg,Dwarf_Signed * new_sec_count)162 _dwarf_symbolic_relocs_to_disk(Dwarf_P_Debug dbg,
163 Dwarf_Signed * new_sec_count)
164 {
165 /* unsigned long total_size =0; */
166 Dwarf_Small *data = 0;
167 int sec_index = 0;
168 int res = 0;
169 unsigned long i = 0;
170 Dwarf_Error error = 0;
171 Dwarf_Signed sec_count = 0;
172 Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0];
173
174 for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) {
175 unsigned long ct = p_reloc->pr_reloc_total_count;
176 struct Dwarf_P_Relocation_Block_s *p_blk;
177 struct Dwarf_P_Relocation_Block_s *p_blk_last;
178 int err;
179 if (ct == 0) {
180 continue;
181 }
182
183 /* len = dbg->de_relocation_record_size; */
184 ++sec_count;
185
186 /* total_size = ct *len; */
187 sec_index = p_reloc->pr_sect_num_of_reloc_sect;
188 if (sec_index == 0) {
189 /* Call de_callback_func or de_callback_func_b,
190 getting section number of reloc section. */
191 int rel_section_index = 0;
192 int int_name = 0;
193 Dwarf_Unsigned name_idx = 0;
194
195 /*
196 This is a bit of a fake, as we do not really have true
197 elf sections at all. Just the data such might contain.
198 But this lets the caller eventually link things
199 together: without this call we would not know what rel
200 data goes with what section when we are asked for the
201 real arrays. */
202
203 if (dbg->de_callback_func_b) {
204 rel_section_index =
205 dbg->de_callback_func_b(_dwarf_rel_section_names[i],
206 dbg->de_relocation_record_size,
207 /* type */ SHT_REL,
208 /* flags */ 0,
209 /* link to symtab, which we cannot
210 know */ SHN_UNDEF,
211 /* sec rels apply to */
212 dbg->de_elf_sects[i],
213 &name_idx, &err);
214 } else {
215 rel_section_index =
216 dbg->de_callback_func(_dwarf_rel_section_names[i],
217 dbg->de_relocation_record_size,
218 /* type */ SHT_REL,
219 /* flags */ 0,
220 /* link to symtab, which we cannot
221 know */ SHN_UNDEF,
222 /* sec rels apply to, in elf, sh_info */
223 dbg->de_elf_sects[i], &int_name, &err);
224 name_idx = int_name;
225 }
226 if (rel_section_index == -1) {
227 {
228 _dwarf_p_error(dbg, &error, DW_DLE_ELF_SECT_ERR);
229 return (DW_DLV_ERROR);
230 }
231 }
232 p_reloc->pr_sect_num_of_reloc_sect = rel_section_index;
233 sec_index = rel_section_index;
234 }
235
236 p_blk = p_reloc->pr_first_block;
237
238 if (p_reloc->pr_block_count > 1) {
239 struct Dwarf_P_Relocation_Block_s *new_blk;
240
241 /* HACK , not normal interfaces, trashing p_reloc current
242 contents! */
243 _dwarf_reset_reloc_sect_info(p_reloc, ct);
244
245 /* Creating new single block for all 'ct' entries */
246 res = _dwarf_pro_pre_alloc_n_reloc_slots(dbg, (int) i, ct);
247 if (res != DW_DLV_OK) {
248 return res;
249 }
250 new_blk = p_reloc->pr_first_block;
251
252 data = (Dwarf_Small *) new_blk->rb_data;
253
254 /* The following loop does the consolidation to a single
255 block and frees the input block(s). */
256 do {
257 unsigned long len =
258 p_blk->rb_where_to_add_next - p_blk->rb_data;
259 memcpy(data, p_blk->rb_data, len);
260 data += len;
261 p_blk_last = p_blk;
262 p_blk = p_blk->rb_next;
263 _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last);
264 } while (p_blk);
265 /* ASSERT: sum of len copied == total_size */
266 new_blk->rb_next_slot_to_use = ct;
267 new_blk->rb_where_to_add_next = (char *) data;
268 p_reloc->pr_reloc_total_count = ct;
269
270 /* have now created a single block, but no change in slots
271 used (pr_reloc_total_count) */
272 }
273 }
274 *new_sec_count = 0;
275 return DW_DLV_OK;
276 }
277