xref: /illumos-gate/usr/src/lib/libdwarf/common/pro_reloc_symbolic.c (revision 2aeafac3612e19716bf8164f89c3c9196342979c)
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
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
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
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
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