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 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 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 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