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
50static void common_init(Dwarf_P_Debug dbg, Dwarf_Unsigned flags);
51
52void *_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' */
64static struct Dwarf_P_Section_Data_s init_sect = {
65    MAGIC_SECT_NO, 0, 0, 0, 0
66};
67
68Dwarf_P_Debug
69dwarf_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
96Dwarf_P_Debug
97dwarf_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}
126static void
127common_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