xref: /titanic_50/usr/src/lib/libdwarf/common/pro_reloc_stream.c (revision f3e7f55e73a39377d55a030f124cc86b3b66a9cc)
1*f3e7f55eSRobert Mustacchi /*
2*f3e7f55eSRobert Mustacchi 
3*f3e7f55eSRobert Mustacchi   Copyright (C) 2000,2001,2004 Silicon Graphics, Inc.  All Rights Reserved.
4*f3e7f55eSRobert Mustacchi   Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
5*f3e7f55eSRobert Mustacchi   Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved.
6*f3e7f55eSRobert Mustacchi 
7*f3e7f55eSRobert Mustacchi   This program is free software; you can redistribute it and/or modify it
8*f3e7f55eSRobert Mustacchi   under the terms of version 2.1 of the GNU Lesser General Public License
9*f3e7f55eSRobert Mustacchi   as published by the Free Software Foundation.
10*f3e7f55eSRobert Mustacchi 
11*f3e7f55eSRobert Mustacchi   This program is distributed in the hope that it would be useful, but
12*f3e7f55eSRobert Mustacchi   WITHOUT ANY WARRANTY; without even the implied warranty of
13*f3e7f55eSRobert Mustacchi   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14*f3e7f55eSRobert Mustacchi 
15*f3e7f55eSRobert Mustacchi   Further, this software is distributed without any warranty that it is
16*f3e7f55eSRobert Mustacchi   free of the rightful claim of any third person regarding infringement
17*f3e7f55eSRobert Mustacchi   or the like.  Any license provided herein, whether implied or
18*f3e7f55eSRobert Mustacchi   otherwise, applies only to this software file.  Patent licenses, if
19*f3e7f55eSRobert Mustacchi   any, provided herein do not apply to combinations of this program with
20*f3e7f55eSRobert Mustacchi   other software, or any other product whatsoever.
21*f3e7f55eSRobert Mustacchi 
22*f3e7f55eSRobert Mustacchi   You should have received a copy of the GNU Lesser General Public
23*f3e7f55eSRobert Mustacchi   License along with this program; if not, write the Free Software
24*f3e7f55eSRobert Mustacchi   Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
25*f3e7f55eSRobert Mustacchi   USA.
26*f3e7f55eSRobert Mustacchi 
27*f3e7f55eSRobert Mustacchi   Contact information:  Silicon Graphics, Inc., 1500 Crittenden Lane,
28*f3e7f55eSRobert Mustacchi   Mountain View, CA 94043, or:
29*f3e7f55eSRobert Mustacchi 
30*f3e7f55eSRobert Mustacchi   http://www.sgi.com
31*f3e7f55eSRobert Mustacchi 
32*f3e7f55eSRobert Mustacchi   For further information regarding this notice, see:
33*f3e7f55eSRobert Mustacchi 
34*f3e7f55eSRobert Mustacchi   http://oss.sgi.com/projects/GenInfo/NoticeExplan
35*f3e7f55eSRobert Mustacchi 
36*f3e7f55eSRobert Mustacchi */
37*f3e7f55eSRobert Mustacchi 
38*f3e7f55eSRobert Mustacchi 
39*f3e7f55eSRobert Mustacchi 
40*f3e7f55eSRobert Mustacchi #include "config.h"
41*f3e7f55eSRobert Mustacchi #include "libdwarfdefs.h"
42*f3e7f55eSRobert Mustacchi #include <stdio.h>
43*f3e7f55eSRobert Mustacchi #include <string.h>
44*f3e7f55eSRobert Mustacchi #ifdef HAVE_ELFACCESS_H
45*f3e7f55eSRobert Mustacchi #include <elfaccess.h>
46*f3e7f55eSRobert Mustacchi #else
47*f3e7f55eSRobert Mustacchi /* Set r_info  as defined by ELF generic ABI */
48*f3e7f55eSRobert Mustacchi #define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t))
49*f3e7f55eSRobert Mustacchi #define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t))
50*f3e7f55eSRobert Mustacchi #endif
51*f3e7f55eSRobert Mustacchi #include "pro_incl.h"
52*f3e7f55eSRobert Mustacchi #include "pro_section.h"
53*f3e7f55eSRobert Mustacchi #include "pro_reloc.h"
54*f3e7f55eSRobert Mustacchi #include "pro_reloc_stream.h"
55*f3e7f55eSRobert Mustacchi 
56*f3e7f55eSRobert Mustacchi /*
57*f3e7f55eSRobert Mustacchi         Return DW_DLV_ERROR on malloc error or reltarget_length error.
58*f3e7f55eSRobert Mustacchi         Return DW_DLV_OK otherwise
59*f3e7f55eSRobert Mustacchi 
60*f3e7f55eSRobert Mustacchi 
61*f3e7f55eSRobert Mustacchi 
62*f3e7f55eSRobert Mustacchi */
63*f3e7f55eSRobert Mustacchi  /*ARGSUSED*/ int
_dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg,int base_sec_index,Dwarf_Unsigned offset,Dwarf_Unsigned symidx,enum Dwarf_Rel_Type type,int reltarget_length)64*f3e7f55eSRobert Mustacchi _dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg,
65*f3e7f55eSRobert Mustacchi     int base_sec_index,
66*f3e7f55eSRobert Mustacchi     Dwarf_Unsigned offset,      /* r_offset of reloc */
67*f3e7f55eSRobert Mustacchi     Dwarf_Unsigned symidx,
68*f3e7f55eSRobert Mustacchi     enum Dwarf_Rel_Type type,
69*f3e7f55eSRobert Mustacchi     int reltarget_length)
70*f3e7f55eSRobert Mustacchi {
71*f3e7f55eSRobert Mustacchi #if HAVE_ELF64_GETEHDR
72*f3e7f55eSRobert Mustacchi     REL64 *elf64_reloc = 0;
73*f3e7f55eSRobert Mustacchi     void *relrec_to_fill = 0;
74*f3e7f55eSRobert Mustacchi     int res = 0;
75*f3e7f55eSRobert Mustacchi     int rel_type = 0;
76*f3e7f55eSRobert Mustacchi 
77*f3e7f55eSRobert Mustacchi     res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
78*f3e7f55eSRobert Mustacchi                                       &relrec_to_fill);
79*f3e7f55eSRobert Mustacchi     if (res != DW_DLV_OK)
80*f3e7f55eSRobert Mustacchi         return res;
81*f3e7f55eSRobert Mustacchi 
82*f3e7f55eSRobert Mustacchi 
83*f3e7f55eSRobert Mustacchi     if (type == dwarf_drt_data_reloc) {
84*f3e7f55eSRobert Mustacchi         if (reltarget_length == dbg->de_offset_size) {
85*f3e7f55eSRobert Mustacchi             rel_type = dbg->de_offset_reloc;
86*f3e7f55eSRobert Mustacchi         } else if (reltarget_length == dbg->de_pointer_size) {
87*f3e7f55eSRobert Mustacchi             rel_type = dbg->de_ptr_reloc;
88*f3e7f55eSRobert Mustacchi         } else {
89*f3e7f55eSRobert Mustacchi             return DW_DLV_ERROR;
90*f3e7f55eSRobert Mustacchi         }
91*f3e7f55eSRobert Mustacchi     } else if (type == dwarf_drt_segment_rel) {
92*f3e7f55eSRobert Mustacchi         rel_type = dbg->de_exc_reloc;
93*f3e7f55eSRobert Mustacchi     } else {
94*f3e7f55eSRobert Mustacchi         /* We are in trouble: improper use of stream relocations.
95*f3e7f55eSRobert Mustacchi            Someone else will diagnose */
96*f3e7f55eSRobert Mustacchi         rel_type = 0;
97*f3e7f55eSRobert Mustacchi     }
98*f3e7f55eSRobert Mustacchi 
99*f3e7f55eSRobert Mustacchi     elf64_reloc = (REL64 *)relrec_to_fill;
100*f3e7f55eSRobert Mustacchi     elf64_reloc->r_offset = offset;
101*f3e7f55eSRobert Mustacchi     Set_REL64_info(*elf64_reloc, symidx, rel_type);
102*f3e7f55eSRobert Mustacchi     return DW_DLV_OK;
103*f3e7f55eSRobert Mustacchi #else /* !HAVE_ELF64_GETEHDR */
104*f3e7f55eSRobert Mustacchi     return DW_DLV_ERROR;
105*f3e7f55eSRobert Mustacchi #endif /* #if HAVE_ELF64_GETEHDR */
106*f3e7f55eSRobert Mustacchi }
107*f3e7f55eSRobert Mustacchi 
108*f3e7f55eSRobert Mustacchi /*
109*f3e7f55eSRobert Mustacchi         Return DW_DLV_ERROR on malloc error or reltarget_length error.
110*f3e7f55eSRobert Mustacchi         Return DW_DLV_OK otherwise
111*f3e7f55eSRobert Mustacchi         a binary reloc: 32bit ABI
112*f3e7f55eSRobert Mustacchi */
113*f3e7f55eSRobert Mustacchi int
_dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg,int base_sec_index,Dwarf_Unsigned offset,Dwarf_Unsigned symidx,enum Dwarf_Rel_Type type,int reltarget_length)114*f3e7f55eSRobert Mustacchi _dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg, int base_sec_index,
115*f3e7f55eSRobert Mustacchi     Dwarf_Unsigned offset,      /* r_offset of reloc */
116*f3e7f55eSRobert Mustacchi     Dwarf_Unsigned symidx,
117*f3e7f55eSRobert Mustacchi     enum Dwarf_Rel_Type type,
118*f3e7f55eSRobert Mustacchi     int reltarget_length)
119*f3e7f55eSRobert Mustacchi {
120*f3e7f55eSRobert Mustacchi     REL32 *elf32_reloc = 0;
121*f3e7f55eSRobert Mustacchi     void *relrec_to_fill = 0;
122*f3e7f55eSRobert Mustacchi     int res = 0;
123*f3e7f55eSRobert Mustacchi     int rel_type = 0;
124*f3e7f55eSRobert Mustacchi 
125*f3e7f55eSRobert Mustacchi     res = _dwarf_pro_reloc_get_a_slot(dbg, base_sec_index,
126*f3e7f55eSRobert Mustacchi                                       &relrec_to_fill);
127*f3e7f55eSRobert Mustacchi     if (res != DW_DLV_OK)
128*f3e7f55eSRobert Mustacchi         return res;
129*f3e7f55eSRobert Mustacchi     if (type == dwarf_drt_data_reloc) {
130*f3e7f55eSRobert Mustacchi         if (reltarget_length == dbg->de_offset_size) {
131*f3e7f55eSRobert Mustacchi             rel_type = dbg->de_offset_reloc;
132*f3e7f55eSRobert Mustacchi         } else if (reltarget_length == dbg->de_pointer_size) {
133*f3e7f55eSRobert Mustacchi             rel_type = dbg->de_ptr_reloc;
134*f3e7f55eSRobert Mustacchi         } else {
135*f3e7f55eSRobert Mustacchi             return DW_DLV_ERROR;
136*f3e7f55eSRobert Mustacchi         }
137*f3e7f55eSRobert Mustacchi     } else if (type == dwarf_drt_segment_rel) {
138*f3e7f55eSRobert Mustacchi         rel_type = dbg->de_exc_reloc;
139*f3e7f55eSRobert Mustacchi     } else {
140*f3e7f55eSRobert Mustacchi         /* We are in trouble: improper use of stream relocations.
141*f3e7f55eSRobert Mustacchi            Someone else will diagnose */
142*f3e7f55eSRobert Mustacchi         rel_type = 0;
143*f3e7f55eSRobert Mustacchi     }
144*f3e7f55eSRobert Mustacchi 
145*f3e7f55eSRobert Mustacchi     elf32_reloc = (REL32*)relrec_to_fill;
146*f3e7f55eSRobert Mustacchi     elf32_reloc->r_offset = (Elf32_Addr) offset;
147*f3e7f55eSRobert Mustacchi     Set_REL32_info(*elf32_reloc, (Dwarf_Word) symidx, rel_type);
148*f3e7f55eSRobert Mustacchi     return DW_DLV_OK;
149*f3e7f55eSRobert Mustacchi 
150*f3e7f55eSRobert Mustacchi     /* get a slot, fill in the slot entry */
151*f3e7f55eSRobert Mustacchi }
152*f3e7f55eSRobert Mustacchi 
153*f3e7f55eSRobert Mustacchi 
154*f3e7f55eSRobert Mustacchi 
155*f3e7f55eSRobert Mustacchi /*
156*f3e7f55eSRobert Mustacchi         Return DW_DLV_OK.
157*f3e7f55eSRobert Mustacchi         Never can really do anything: lengths cannot
158*f3e7f55eSRobert Mustacchi         be represented as end-start in a stream.
159*f3e7f55eSRobert Mustacchi 
160*f3e7f55eSRobert Mustacchi */
161*f3e7f55eSRobert Mustacchi  /*ARGSUSED*/ int
_dwarf_pro_reloc_length_stream(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)162*f3e7f55eSRobert Mustacchi _dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg,
163*f3e7f55eSRobert Mustacchi     int base_sec_index,
164*f3e7f55eSRobert Mustacchi     Dwarf_Unsigned offset,    /* r_offset of reloc */
165*f3e7f55eSRobert Mustacchi     Dwarf_Unsigned start_symidx,
166*f3e7f55eSRobert Mustacchi     Dwarf_Unsigned end_symidx,
167*f3e7f55eSRobert Mustacchi     enum Dwarf_Rel_Type type,
168*f3e7f55eSRobert Mustacchi     int reltarget_length)
169*f3e7f55eSRobert Mustacchi {
170*f3e7f55eSRobert Mustacchi     /* get a slot, fill in the slot entry */
171*f3e7f55eSRobert Mustacchi     return DW_DLV_OK;
172*f3e7f55eSRobert Mustacchi }
173*f3e7f55eSRobert Mustacchi 
174*f3e7f55eSRobert Mustacchi 
175*f3e7f55eSRobert Mustacchi /*
176*f3e7f55eSRobert Mustacchi         Ensure each stream is a single buffer and
177*f3e7f55eSRobert Mustacchi         add that single buffer to the set of stream buffers.
178*f3e7f55eSRobert Mustacchi 
179*f3e7f55eSRobert Mustacchi         By creating a new buffer and copying if necessary.
180*f3e7f55eSRobert Mustacchi 
181*f3e7f55eSRobert Mustacchi         Free the input set of buffers if we consolidate.
182*f3e7f55eSRobert Mustacchi         Return -1 on error (malloc failure)
183*f3e7f55eSRobert Mustacchi 
184*f3e7f55eSRobert Mustacchi 
185*f3e7f55eSRobert Mustacchi         Return DW_DLV_OK on success. Any other return indicates
186*f3e7f55eSRobert Mustacchi         malloc failed.
187*f3e7f55eSRobert Mustacchi 
188*f3e7f55eSRobert Mustacchi */
189*f3e7f55eSRobert Mustacchi int
_dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg,Dwarf_Signed * new_sec_count)190*f3e7f55eSRobert Mustacchi _dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg,
191*f3e7f55eSRobert Mustacchi     Dwarf_Signed * new_sec_count)
192*f3e7f55eSRobert Mustacchi {
193*f3e7f55eSRobert Mustacchi     unsigned long total_size = 0;
194*f3e7f55eSRobert Mustacchi     Dwarf_Small *data = 0;
195*f3e7f55eSRobert Mustacchi     int sec_index = 0;
196*f3e7f55eSRobert Mustacchi     unsigned long i = 0;
197*f3e7f55eSRobert Mustacchi     Dwarf_Error err = 0;
198*f3e7f55eSRobert Mustacchi     Dwarf_Error *error = &err;
199*f3e7f55eSRobert Mustacchi 
200*f3e7f55eSRobert Mustacchi     Dwarf_Signed sec_count = 0;
201*f3e7f55eSRobert Mustacchi 
202*f3e7f55eSRobert Mustacchi     Dwarf_P_Per_Reloc_Sect p_reloc = &dbg->de_reloc_sect[0];
203*f3e7f55eSRobert Mustacchi 
204*f3e7f55eSRobert Mustacchi     for (i = 0; i < NUM_DEBUG_SECTIONS; ++i, ++p_reloc) {
205*f3e7f55eSRobert Mustacchi         unsigned long ct = p_reloc->pr_reloc_total_count;
206*f3e7f55eSRobert Mustacchi         unsigned len = 0;
207*f3e7f55eSRobert Mustacchi         struct Dwarf_P_Relocation_Block_s *p_blk = 0;
208*f3e7f55eSRobert Mustacchi         struct Dwarf_P_Relocation_Block_s *p_blk_last = 0;
209*f3e7f55eSRobert Mustacchi         Dwarf_P_Per_Reloc_Sect prb = 0;
210*f3e7f55eSRobert Mustacchi 
211*f3e7f55eSRobert Mustacchi         if (ct == 0) {
212*f3e7f55eSRobert Mustacchi             continue;
213*f3e7f55eSRobert Mustacchi         }
214*f3e7f55eSRobert Mustacchi         prb = &dbg->de_reloc_sect[i];
215*f3e7f55eSRobert Mustacchi         len = dbg->de_relocation_record_size;
216*f3e7f55eSRobert Mustacchi         ++sec_count;
217*f3e7f55eSRobert Mustacchi 
218*f3e7f55eSRobert Mustacchi         total_size = ct * len;
219*f3e7f55eSRobert Mustacchi         sec_index = prb->pr_sect_num_of_reloc_sect;
220*f3e7f55eSRobert Mustacchi         if (sec_index == 0) {
221*f3e7f55eSRobert Mustacchi             /* Call de_callback_func or de_callback_func_b, getting
222*f3e7f55eSRobert Mustacchi                section number of reloc section. */
223*f3e7f55eSRobert Mustacchi             int rel_section_index = 0;
224*f3e7f55eSRobert Mustacchi             Dwarf_Unsigned name_idx = 0;
225*f3e7f55eSRobert Mustacchi             int int_name = 0;
226*f3e7f55eSRobert Mustacchi             int err = 0;
227*f3e7f55eSRobert Mustacchi 
228*f3e7f55eSRobert Mustacchi             if (dbg->de_callback_func_b) {
229*f3e7f55eSRobert Mustacchi                 rel_section_index =
230*f3e7f55eSRobert Mustacchi                     dbg->de_callback_func_b(_dwarf_rel_section_names[i],
231*f3e7f55eSRobert Mustacchi                                    /* size */
232*f3e7f55eSRobert Mustacchi                                    dbg->de_relocation_record_size,
233*f3e7f55eSRobert Mustacchi                                    /* type */ SHT_REL,
234*f3e7f55eSRobert Mustacchi                                    /* flags */ 0,
235*f3e7f55eSRobert Mustacchi                                    /* link to symtab, which we cannot
236*f3e7f55eSRobert Mustacchi                                       know */ 0,
237*f3e7f55eSRobert Mustacchi                                    /* info == link to sec rels apply to
238*f3e7f55eSRobert Mustacchi                                     */
239*f3e7f55eSRobert Mustacchi                                    dbg->de_elf_sects[i],
240*f3e7f55eSRobert Mustacchi                                    &name_idx, &err);
241*f3e7f55eSRobert Mustacchi             } else {
242*f3e7f55eSRobert Mustacchi                 rel_section_index =
243*f3e7f55eSRobert Mustacchi                     dbg->de_callback_func(_dwarf_rel_section_names[i],
244*f3e7f55eSRobert Mustacchi                                  /* size */
245*f3e7f55eSRobert Mustacchi                                  dbg->de_relocation_record_size,
246*f3e7f55eSRobert Mustacchi                                  /* type */ SHT_REL,
247*f3e7f55eSRobert Mustacchi                                  /* flags */ 0,
248*f3e7f55eSRobert Mustacchi                                  /* link to symtab, which we cannot
249*f3e7f55eSRobert Mustacchi                                     know */ 0,
250*f3e7f55eSRobert Mustacchi                                  /* info == link to sec rels apply to */
251*f3e7f55eSRobert Mustacchi                                  dbg->de_elf_sects[i], &int_name, &err);
252*f3e7f55eSRobert Mustacchi                 name_idx = int_name;
253*f3e7f55eSRobert Mustacchi             }
254*f3e7f55eSRobert Mustacchi             if (rel_section_index == -1) {
255*f3e7f55eSRobert Mustacchi                 {
256*f3e7f55eSRobert Mustacchi                     _dwarf_p_error(dbg, error, DW_DLE_ELF_SECT_ERR);
257*f3e7f55eSRobert Mustacchi                     return (DW_DLV_ERROR);
258*f3e7f55eSRobert Mustacchi                 }
259*f3e7f55eSRobert Mustacchi 
260*f3e7f55eSRobert Mustacchi             }
261*f3e7f55eSRobert Mustacchi             prb->pr_sect_num_of_reloc_sect = rel_section_index;
262*f3e7f55eSRobert Mustacchi             sec_index = rel_section_index;
263*f3e7f55eSRobert Mustacchi         }
264*f3e7f55eSRobert Mustacchi         GET_CHUNK(dbg, sec_index, data, total_size, &err);
265*f3e7f55eSRobert Mustacchi         p_blk = p_reloc->pr_first_block;
266*f3e7f55eSRobert Mustacchi 
267*f3e7f55eSRobert Mustacchi         /* following loop executes at least once. Effects the
268*f3e7f55eSRobert Mustacchi            consolidation to a single block or, if already a single
269*f3e7f55eSRobert Mustacchi            block, simply copies to the output buffer. And frees the
270*f3e7f55eSRobert Mustacchi            input block. The new block is in the de_debug_sects list. */
271*f3e7f55eSRobert Mustacchi         while (p_blk) {
272*f3e7f55eSRobert Mustacchi 
273*f3e7f55eSRobert Mustacchi             unsigned long len =
274*f3e7f55eSRobert Mustacchi                 p_blk->rb_where_to_add_next - p_blk->rb_data;
275*f3e7f55eSRobert Mustacchi 
276*f3e7f55eSRobert Mustacchi             memcpy(data, p_blk->rb_data, len);
277*f3e7f55eSRobert Mustacchi 
278*f3e7f55eSRobert Mustacchi 
279*f3e7f55eSRobert Mustacchi             data += len;
280*f3e7f55eSRobert Mustacchi 
281*f3e7f55eSRobert Mustacchi             p_blk_last = p_blk;
282*f3e7f55eSRobert Mustacchi             p_blk = p_blk->rb_next;
283*f3e7f55eSRobert Mustacchi 
284*f3e7f55eSRobert Mustacchi             _dwarf_p_dealloc(dbg, (Dwarf_Small *) p_blk_last);
285*f3e7f55eSRobert Mustacchi         }
286*f3e7f55eSRobert Mustacchi         /* ASSERT: sum of len copied == total_size */
287*f3e7f55eSRobert Mustacchi 
288*f3e7f55eSRobert Mustacchi         /*
289*f3e7f55eSRobert Mustacchi            We have copied the input, now drop the pointers to it. For
290*f3e7f55eSRobert Mustacchi            debugging, leave the other data untouched. */
291*f3e7f55eSRobert Mustacchi         p_reloc->pr_first_block = 0;
292*f3e7f55eSRobert Mustacchi         p_reloc->pr_last_block = 0;
293*f3e7f55eSRobert Mustacchi     }
294*f3e7f55eSRobert Mustacchi 
295*f3e7f55eSRobert Mustacchi     *new_sec_count = sec_count;
296*f3e7f55eSRobert Mustacchi     return DW_DLV_OK;
297*f3e7f55eSRobert Mustacchi }
298