3 Copyright (C) 2000,2001,2004 Silicon Graphics, Inc. All Rights Reserved.
4 Portions Copyright 2002-2010 Sun Microsystems, Inc. All rights reserved.
5 Portions Copyright 2008-2010 David Anderson, Inc. All rights reserved.
7 This program is free software; you can redistribute it and/or modify it
8 under the terms of version 2.1 of the GNU Lesser General Public License
9 as published by the Free Software Foundation.
11 This program is distributed in the hope that it would be useful, but
12 WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 Further, this software is distributed without any warranty that it is
16 free of the rightful claim of any third person regarding infringement
17 or the like. Any license provided herein, whether implied or
18 otherwise, applies only to this software file. Patent licenses, if
19 any, provided herein do not apply to combinations of this program with
20 other software, or any other product whatsoever.
22 You should have received a copy of the GNU Lesser General Public
23 License along with this program; if not, write the Free Software
24 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301,
27 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
28 Mountain View, CA 94043, or:
32 For further information regarding this notice, see:
34 http://oss.sgi.com/projects/GenInfo/NoticeExplan
41 #include "libdwarfdefs.h"
44 #ifdef HAVE_ELFACCESS_H
45 #include <elfaccess.h>
47 /* Set r_info as defined by ELF generic ABI */
48 #define Set_REL32_info(r,s,t) ((r).r_info = ELF32_R_INFO(s,t))
49 #define Set_REL64_info(r,s,t) ((r).r_info = ELF64_R_INFO(s,t))
52 #include "pro_section.h"
53 #include "pro_reloc.h"
54 #include "pro_reloc_stream.h"
57 Return DW_DLV_ERROR on malloc error or reltarget_length error.
58 Return DW_DLV_OK otherwise
64 _dwarf_pro_reloc_name_stream64(Dwarf_P_Debug dbg
,
66 Dwarf_Unsigned offset
, /* r_offset of reloc */
67 Dwarf_Unsigned symidx
,
68 enum Dwarf_Rel_Type type
,
71 #if HAVE_ELF64_GETEHDR
72 REL64
*elf64_reloc
= 0;
73 void *relrec_to_fill
= 0;
77 res
= _dwarf_pro_reloc_get_a_slot(dbg
, base_sec_index
,
83 if (type
== dwarf_drt_data_reloc
) {
84 if (reltarget_length
== dbg
->de_offset_size
) {
85 rel_type
= dbg
->de_offset_reloc
;
86 } else if (reltarget_length
== dbg
->de_pointer_size
) {
87 rel_type
= dbg
->de_ptr_reloc
;
91 } else if (type
== dwarf_drt_segment_rel
) {
92 rel_type
= dbg
->de_exc_reloc
;
94 /* We are in trouble: improper use of stream relocations.
95 Someone else will diagnose */
99 elf64_reloc
= (REL64
*)relrec_to_fill
;
100 elf64_reloc
->r_offset
= offset
;
101 Set_REL64_info(*elf64_reloc
, symidx
, rel_type
);
103 #else /* !HAVE_ELF64_GETEHDR */
105 #endif /* #if HAVE_ELF64_GETEHDR */
109 Return DW_DLV_ERROR on malloc error or reltarget_length error.
110 Return DW_DLV_OK otherwise
111 a binary reloc: 32bit ABI
114 _dwarf_pro_reloc_name_stream32(Dwarf_P_Debug dbg
, int base_sec_index
,
115 Dwarf_Unsigned offset
, /* r_offset of reloc */
116 Dwarf_Unsigned symidx
,
117 enum Dwarf_Rel_Type type
,
118 int reltarget_length
)
120 REL32
*elf32_reloc
= 0;
121 void *relrec_to_fill
= 0;
125 res
= _dwarf_pro_reloc_get_a_slot(dbg
, base_sec_index
,
127 if (res
!= DW_DLV_OK
)
129 if (type
== dwarf_drt_data_reloc
) {
130 if (reltarget_length
== dbg
->de_offset_size
) {
131 rel_type
= dbg
->de_offset_reloc
;
132 } else if (reltarget_length
== dbg
->de_pointer_size
) {
133 rel_type
= dbg
->de_ptr_reloc
;
137 } else if (type
== dwarf_drt_segment_rel
) {
138 rel_type
= dbg
->de_exc_reloc
;
140 /* We are in trouble: improper use of stream relocations.
141 Someone else will diagnose */
145 elf32_reloc
= (REL32
*)relrec_to_fill
;
146 elf32_reloc
->r_offset
= (Elf32_Addr
) offset
;
147 Set_REL32_info(*elf32_reloc
, (Dwarf_Word
) symidx
, rel_type
);
150 /* get a slot, fill in the slot entry */
157 Never can really do anything: lengths cannot
158 be represented as end-start in a stream.
162 _dwarf_pro_reloc_length_stream(Dwarf_P_Debug dbg
,
164 Dwarf_Unsigned offset
, /* r_offset of reloc */
165 Dwarf_Unsigned start_symidx
,
166 Dwarf_Unsigned end_symidx
,
167 enum Dwarf_Rel_Type type
,
168 int reltarget_length
)
170 /* get a slot, fill in the slot entry */
176 Ensure each stream is a single buffer and
177 add that single buffer to the set of stream buffers.
179 By creating a new buffer and copying if necessary.
181 Free the input set of buffers if we consolidate.
182 Return -1 on error (malloc failure)
185 Return DW_DLV_OK on success. Any other return indicates
190 _dwarf_stream_relocs_to_disk(Dwarf_P_Debug dbg
,
191 Dwarf_Signed
* new_sec_count
)
193 unsigned long total_size
= 0;
194 Dwarf_Small
*data
= 0;
198 Dwarf_Error
*error
= &err
;
200 Dwarf_Signed sec_count
= 0;
202 Dwarf_P_Per_Reloc_Sect p_reloc
= &dbg
->de_reloc_sect
[0];
204 for (i
= 0; i
< NUM_DEBUG_SECTIONS
; ++i
, ++p_reloc
) {
205 unsigned long ct
= p_reloc
->pr_reloc_total_count
;
207 struct Dwarf_P_Relocation_Block_s
*p_blk
= 0;
208 struct Dwarf_P_Relocation_Block_s
*p_blk_last
= 0;
209 Dwarf_P_Per_Reloc_Sect prb
= 0;
214 prb
= &dbg
->de_reloc_sect
[i
];
215 len
= dbg
->de_relocation_record_size
;
218 total_size
= ct
* len
;
219 sec_index
= prb
->pr_sect_num_of_reloc_sect
;
220 if (sec_index
== 0) {
221 /* Call de_callback_func or de_callback_func_b, getting
222 section number of reloc section. */
223 int rel_section_index
= 0;
224 Dwarf_Unsigned name_idx
= 0;
228 if (dbg
->de_callback_func_b
) {
230 dbg
->de_callback_func_b(_dwarf_rel_section_names
[i
],
232 dbg
->de_relocation_record_size
,
235 /* link to symtab, which we cannot
237 /* info == link to sec rels apply to
239 dbg
->de_elf_sects
[i
],
243 dbg
->de_callback_func(_dwarf_rel_section_names
[i
],
245 dbg
->de_relocation_record_size
,
248 /* link to symtab, which we cannot
250 /* info == link to sec rels apply to */
251 dbg
->de_elf_sects
[i
], &int_name
, &err
);
254 if (rel_section_index
== -1) {
256 _dwarf_p_error(dbg
, error
, DW_DLE_ELF_SECT_ERR
);
257 return (DW_DLV_ERROR
);
261 prb
->pr_sect_num_of_reloc_sect
= rel_section_index
;
262 sec_index
= rel_section_index
;
264 GET_CHUNK(dbg
, sec_index
, data
, total_size
, &err
);
265 p_blk
= p_reloc
->pr_first_block
;
267 /* following loop executes at least once. Effects the
268 consolidation to a single block or, if already a single
269 block, simply copies to the output buffer. And frees the
270 input block. The new block is in the de_debug_sects list. */
274 p_blk
->rb_where_to_add_next
- p_blk
->rb_data
;
276 memcpy(data
, p_blk
->rb_data
, len
);
282 p_blk
= p_blk
->rb_next
;
284 _dwarf_p_dealloc(dbg
, (Dwarf_Small
*) p_blk_last
);
286 /* ASSERT: sum of len copied == total_size */
289 We have copied the input, now drop the pointers to it. For
290 debugging, leave the other data untouched. */
291 p_reloc
->pr_first_block
= 0;
292 p_reloc
->pr_last_block
= 0;
295 *new_sec_count
= sec_count
;