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