1 /*
2
3 Copyright (C) 2000,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.
6
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.
10
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.
14
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.
21
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,
25 USA.
26
27 Contact information: Silicon Graphics, Inc., 1500 Crittenden Lane,
28 Mountain View, CA 94043, or:
29
30 http://www.sgi.com
31
32 For further information regarding this notice, see:
33
34 http://oss.sgi.com/projects/GenInfo/NoticeExplan
35
36 */
37
38
39
40 #include "config.h"
41 #include "libdwarfdefs.h"
42 #include <stdio.h>
43 #include <string.h>
44 #include "pro_incl.h"
45 #include "pro_section.h" /* for MAGIC_SECT_NO */
46 #include "pro_reloc_symbolic.h"
47 #include "pro_reloc_stream.h"
48
49
50 static void common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags);
51
52 void *_dwarf_memcpy_swap_bytes(void *s1, const void *s2, size_t len);
53
54 /*--------------------------------------------------------------------
55 This function sets up a new dwarf producing region.
56 flags: Indicates type of access method, one of DW_DLC* macros
57 func(): Used to create a new object file, a call back function
58 errhand(): Error Handler provided by user
59 errarg: Argument to errhand()
60 error: returned error value
61 --------------------------------------------------------------------*/
62 /* We want the following to have an elf section number that matches
63 'nothing' */
64 static struct Dwarf_P_Section_Data_s init_sect = {
65 MAGIC_SECT_NO, 0, 0, 0, 0
66 };
67
68 Dwarf_P_Debug
dwarf_producer_init_b(Dwarf_Unsigned flags,Dwarf_Callback_Func_b func,Dwarf_Handler errhand,Dwarf_Ptr errarg,Dwarf_Error * error)69 dwarf_producer_init_b(Dwarf_Unsigned flags,
70 Dwarf_Callback_Func_b func,
71 Dwarf_Handler errhand,
72 Dwarf_Ptr errarg, Dwarf_Error * error)
73 {
74 Dwarf_P_Debug dbg;
75 dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL,
76 sizeof(struct
77 Dwarf_P_Debug_s));
78 if (dbg == NULL) {
79 DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC,
80 (Dwarf_P_Debug) DW_DLV_BADADDR);
81 }
82 memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s));
83 /* For the time being */
84 if (func == NULL) {
85 DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC,
86 (Dwarf_P_Debug) DW_DLV_BADADDR);
87 }
88 dbg->de_callback_func_b = func;
89 dbg->de_errhand = errhand;
90 dbg->de_errarg = errarg;
91 common_init(dbg, flags);
92 return dbg;
93
94 }
95
96 Dwarf_P_Debug
dwarf_producer_init(Dwarf_Unsigned flags,Dwarf_Callback_Func func,Dwarf_Handler errhand,Dwarf_Ptr errarg,Dwarf_Error * error)97 dwarf_producer_init(Dwarf_Unsigned flags,
98 Dwarf_Callback_Func func,
99 Dwarf_Handler errhand,
100 Dwarf_Ptr errarg, Dwarf_Error * error)
101 {
102
103 Dwarf_P_Debug dbg;
104
105
106
107 dbg = (Dwarf_P_Debug) _dwarf_p_get_alloc(NULL,
108 sizeof(struct
109 Dwarf_P_Debug_s));
110 if (dbg == NULL) {
111 DWARF_P_DBG_ERROR(dbg, DW_DLE_DBG_ALLOC,
112 (Dwarf_P_Debug) DW_DLV_BADADDR);
113 }
114 memset((void *) dbg, 0, sizeof(struct Dwarf_P_Debug_s));
115 /* For the time being */
116 if (func == NULL) {
117 DWARF_P_DBG_ERROR(dbg, DW_DLE_NO_CALLBACK_FUNC,
118 (Dwarf_P_Debug) DW_DLV_BADADDR);
119 }
120 dbg->de_callback_func = func;
121 dbg->de_errhand = errhand;
122 dbg->de_errarg = errarg;
123 common_init(dbg, flags);
124 return dbg;
125 }
126 static void
common_init(Dwarf_P_Debug dbg,Dwarf_Unsigned flags)127 common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags)
128 {
129 unsigned int k;
130
131
132 dbg->de_version_magic_number = PRO_VERSION_MAGIC;
133 dbg->de_n_debug_sect = 0;
134 dbg->de_debug_sects = &init_sect;
135 dbg->de_current_active_section = &init_sect;
136 dbg->de_flags = flags;
137
138 /* Now, with flags set, can use 64bit tests */
139
140
141
142 #if defined(HAVE_STRICT_DWARF2_32BIT_OFFSET)
143 /* This is cygnus 32bit offset, as specified in pure dwarf2 v2.0.0.
144 It is consistent with normal DWARF2/3 generation of always
145 generating 32 bit offsets. */
146 dbg->de_64bit_extension = 0;
147 dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4);
148 dbg->de_offset_size = (IS_64BIT(dbg) ? 4 : 4);
149 dbg->de_ptr_reloc =
150 IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg);
151 /* non-MIPS, dwarf lengths and offsets are 32 bits even for 64bit
152 pointer environments. */
153 /* Get_REL32_isa here supports 64-bit-pointer dwarf with pure
154 dwarf2 v2.0.0 32bit offsets, as emitted by cygnus tools. And
155 pure 32 bit offset dwarf for 32bit pointer apps. */
156
157 dbg->de_offset_reloc = Get_REL32_isa(dbg);
158 #elif defined(HAVE_SGI_IRIX_OFFSETS)
159 /* MIPS-SGI-IRIX 32 or 64, where offsets and lengths are both 64 bit for
160 64bit pointer objects and both 32 bit for 32bit pointer objects.
161 And a dwarf-reader must check elf info to tell which applies. */
162 dbg->de_64bit_extension = 0;
163 dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4);
164 dbg->de_offset_size = (IS_64BIT(dbg) ? 8 : 4);
165 dbg->de_ptr_reloc =
166 IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg);
167 dbg->de_offset_reloc = dbg->de_ptr_reloc;
168 #else /* HAVE_DWARF2_99_EXTENSION or default. */
169 /* Revised 64 bit output, using distingushed values. Per 1999
170 dwarf3. This allows run-time selection of offset size. */
171 dbg->de_64bit_extension = (IS_64BIT(dbg) ? 1 : 0);
172 dbg->de_pointer_size = (IS_64BIT(dbg) ? 8 : 4);
173 if( flags & DW_DLC_OFFSET_SIZE_64 && (dbg->de_pointer_size == 8)) {
174 /* When it's 64 bit address, a 64bit offset is sensible.
175 Arguably a 32 bit address with 64 bit offset could be
176 sensible, but who would want that? */
177 dbg->de_offset_size = 8;
178 dbg->de_64bit_extension = 1;
179 } else {
180 dbg->de_offset_size = 4;
181 dbg->de_64bit_extension = 0;
182 }
183 dbg->de_ptr_reloc =
184 IS_64BIT(dbg) ? Get_REL64_isa(dbg) : Get_REL32_isa(dbg);
185 /* Non-MIPS, dwarf lengths and offsets are 32 bits even for 64bit
186 pointer environments. */
187 /* Get_REL??_isa here supports 64bit-offset dwarf. For 64bit, we
188 emit the extension bytes. */
189
190 dbg->de_offset_reloc = IS_64BIT(dbg) ? Get_REL64_isa(dbg)
191 : Get_REL32_isa(dbg);
192 #endif /* HAVE_DWARF2_99_EXTENSION etc. */
193
194 dbg->de_exc_reloc = Get_REL_SEGREL_isa(dbg);
195
196 dbg->de_is_64bit = IS_64BIT(dbg);
197
198
199 if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
200 dbg->de_relocation_record_size =
201 sizeof(struct Dwarf_Relocation_Data_s);
202 } else {
203
204 #if HAVE_ELF64_GETEHDR
205 dbg->de_relocation_record_size =
206 IS_64BIT(dbg)? sizeof(REL64) : sizeof(REL32);
207 #else
208 dbg->de_relocation_record_size = sizeof(REL32);
209 #endif
210
211 }
212
213 if (dbg->de_offset_size == 8) {
214 dbg->de_ar_data_attribute_form = DW_FORM_data8;
215 dbg->de_ar_ref_attr_form = DW_FORM_ref8;
216 } else {
217 dbg->de_ar_data_attribute_form = DW_FORM_data4;
218 dbg->de_ar_ref_attr_form = DW_FORM_ref4;
219 }
220
221 if (flags & DW_DLC_SYMBOLIC_RELOCATIONS) {
222 dbg->de_reloc_name = _dwarf_pro_reloc_name_symbolic;
223 dbg->de_reloc_pair = _dwarf_pro_reloc_length_symbolic;
224 dbg->de_transform_relocs_to_disk =
225 _dwarf_symbolic_relocs_to_disk;
226 } else {
227 if (IS_64BIT(dbg)) {
228 dbg->de_reloc_name = _dwarf_pro_reloc_name_stream64;
229 } else {
230 dbg->de_reloc_name = _dwarf_pro_reloc_name_stream32;
231 }
232 dbg->de_reloc_pair = 0;
233 dbg->de_transform_relocs_to_disk = _dwarf_stream_relocs_to_disk;
234 }
235 for (k = 0; k < NUM_DEBUG_SECTIONS; ++k) {
236
237 Dwarf_P_Per_Reloc_Sect prel = &dbg->de_reloc_sect[k];
238
239 prel->pr_slots_per_block_to_alloc = DEFAULT_SLOTS_PER_BLOCK;
240 }
241 /* First assume host, target same endianness */
242 dbg->de_same_endian = 1;
243 dbg->de_copy_word = memcpy;
244 #ifdef WORDS_BIGENDIAN
245 /* host is big endian, so what endian is target? */
246 if (flags & DW_DLC_TARGET_LITTLEENDIAN) {
247 dbg->de_same_endian = 0;
248 dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
249 }
250 #else /* little endian */
251 /* host is little endian, so what endian is target? */
252 if (flags & DW_DLC_TARGET_BIGENDIAN) {
253 dbg->de_same_endian = 0;
254 dbg->de_copy_word = _dwarf_memcpy_swap_bytes;
255 }
256 #endif /* !WORDS_BIGENDIAN */
257
258
259 return;
260
261 }
262