1 /* 2 Copyright (C) 2000-2006 Silicon Graphics, Inc. All Rights Reserved. 3 Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved. 4 Portions Copyright 2008-2010 Arxan Technologies, Inc. All rights reserved. 5 Portions Copyright 2011-2019 David Anderson. All rights reserved. 6 Portions Copyright 2012 SN Systems Ltd. All rights reserved. 7 8 This program is free software; you can redistribute it and/or modify it 9 under the terms of version 2.1 of the GNU Lesser General Public License 10 as published by the Free Software Foundation. 11 12 This program is distributed in the hope that it would be useful, but 13 WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 15 16 Further, this software is distributed without any warranty that it is 17 free of the rightful claim of any third person regarding infringement 18 or the like. Any license provided herein, whether implied or 19 otherwise, applies only to this software file. Patent licenses, if 20 any, provided herein do not apply to combinations of this program with 21 other software, or any other product whatsoever. 22 23 You should have received a copy of the GNU Lesser General Public 24 License along with this program; if not, write the Free Software 25 Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston MA 02110-1301, 26 USA. 27 28 */ 29 30 #include "config.h" 31 #ifdef HAVE_LIBELF_H 32 #include <libelf.h> 33 #else 34 #ifdef HAVE_LIBELF_LIBELF_H 35 #include <libelf/libelf.h> 36 #endif 37 #endif 38 #include <stdio.h> 39 #include <sys/types.h> 40 #include <sys/stat.h> 41 #include <fcntl.h> 42 #include <string.h> 43 #ifdef HAVE_STDLIB_H 44 #include <stdlib.h> 45 #endif /* HAVE_STDLIB_H */ 46 #ifdef HAVE_MALLOC_H 47 /* Useful include for some Windows compilers. */ 48 #include <malloc.h> 49 #endif /* HAVE_MALLOC_H */ 50 #ifdef HAVE_UNISTD_H 51 #include <unistd.h> 52 #elif defined(_WIN32) && defined(_MSC_VER) 53 #include <io.h> 54 #endif /* HAVE_UNISTD_H */ 55 56 #include "dwarf_incl.h" 57 #include "dwarf_error.h" 58 #include "dwarf_object_detector.h" 59 #include "dwarf_elf_access.h" /* Needed while libelf in use */ 60 61 #ifndef O_BINARY 62 #define O_BINARY 0 63 #endif /* O_BINARY */ 64 65 /* This is the initialization set intended to 66 handle multiple object formats. 67 Created September 2018 68 69 The init functions here cannot process archives. 70 For archives the libelf-only dwarf_elf_init*() 71 functions are used if present, else archives 72 cannot be read. 73 */ 74 75 76 #define DWARF_DBG_ERROR(dbg,errval,retval) \ 77 _dwarf_error(dbg, error, errval); return(retval); 78 79 80 #define FALSE 0 81 #define TRUE 1 82 /* An original basic dwarf initializer function for consumers. 83 Return a libdwarf error code on error, return DW_DLV_OK 84 if this succeeds. 85 dwarf_init_b() is a better choice where there 86 are section groups in an object file. */ 87 int 88 dwarf_init(int fd, 89 Dwarf_Unsigned access, 90 Dwarf_Handler errhand, 91 Dwarf_Ptr errarg, Dwarf_Debug * ret_dbg, Dwarf_Error * error) 92 { 93 return dwarf_init_b(fd,access, DW_GROUPNUMBER_ANY, 94 errhand,errarg,ret_dbg,error); 95 } 96 97 static int 98 open_a_file(const char * name) 99 { 100 /* Set to a file number that cannot be legal. */ 101 int fd = -1; 102 103 #if HAVE_ELF_OPEN 104 /* It is not possible to share file handles 105 between applications or DLLs. Each application has its own 106 file-handle table. For two applications to use the same file 107 using a DLL, they must both open the file individually. 108 Let the 'libelf' dll open and close the file. */ 109 fd = elf_open(name, O_RDONLY | O_BINARY); 110 #else 111 fd = open(name, O_RDONLY | O_BINARY); 112 #endif 113 return fd; 114 } 115 116 static int 117 set_global_paths_init(Dwarf_Debug dbg, Dwarf_Error* error) 118 { 119 int res = 0; 120 121 res = dwarf_add_debuglink_global_path(dbg, 122 "/usr/lib/debug",error); 123 return res; 124 } 125 126 /* New in December 2018. */ 127 int dwarf_init_path(const char *path, 128 char *true_path_out_buffer, 129 unsigned true_path_bufferlen, 130 Dwarf_Unsigned access, 131 unsigned groupnumber, 132 Dwarf_Handler errhand, 133 Dwarf_Ptr errarg, 134 Dwarf_Debug* ret_dbg, 135 UNUSEDARG const char * reserved1, 136 UNUSEDARG Dwarf_Unsigned reserved2, 137 UNUSEDARG Dwarf_Unsigned * reserved3, 138 Dwarf_Error* error) 139 { 140 unsigned ftype = 0; 141 unsigned endian = 0; 142 unsigned offsetsize = 0; 143 Dwarf_Unsigned filesize = 0; 144 int res = 0; 145 int errcode = 0; 146 int fd = -1; 147 Dwarf_Debug dbg = 0; 148 char *file_path = 0; 149 150 if (!ret_dbg) { 151 DWARF_DBG_ERROR(NULL,DW_DLE_DWARF_INIT_DBG_NULL,DW_DLV_ERROR); 152 } 153 res = dwarf_object_detector_path(path, 154 true_path_out_buffer, 155 true_path_bufferlen, 156 &ftype,&endian,&offsetsize,&filesize,&errcode); 157 if (res == DW_DLV_NO_ENTRY) { 158 return res; 159 } 160 if (res == DW_DLV_ERROR) { 161 DWARF_DBG_ERROR(NULL, errcode, DW_DLV_ERROR); 162 } 163 if (true_path_out_buffer) { 164 file_path = true_path_out_buffer; 165 fd = open_a_file(true_path_out_buffer); 166 } else { 167 file_path = (char *)path; 168 fd = open_a_file(path); 169 } 170 if(fd == -1) { 171 DWARF_DBG_ERROR(NULL, DW_DLE_FILE_UNAVAILABLE, 172 DW_DLV_ERROR); 173 } 174 switch(ftype) { 175 case DW_FTYPE_ELF: { 176 res = _dwarf_elf_nlsetup(fd, 177 file_path, 178 ftype,endian,offsetsize,filesize, 179 access,groupnumber,errhand,errarg,&dbg,error); 180 if (res != DW_DLV_OK) { 181 *ret_dbg = dbg; 182 close(fd); 183 return res; 184 } 185 dbg->de_path = strdup(file_path); 186 dbg->de_fd = fd; 187 dbg->de_owns_fd = TRUE; 188 res = set_global_paths_init(dbg,error); 189 *ret_dbg = dbg; 190 return res; 191 } 192 case DW_FTYPE_MACH_O: { 193 res = _dwarf_macho_setup(fd, 194 file_path, 195 ftype,endian,offsetsize,filesize, 196 access,groupnumber,errhand,errarg,&dbg,error); 197 if (res != DW_DLV_OK) { 198 close(fd); 199 *ret_dbg = dbg; 200 return res; 201 } 202 dbg->de_path = strdup(file_path); 203 dbg->de_fd = fd; 204 dbg->de_owns_fd = TRUE; 205 set_global_paths_init(dbg,error); 206 *ret_dbg = dbg; 207 return res; 208 } 209 case DW_FTYPE_PE: { 210 res = _dwarf_pe_setup(fd, 211 file_path, 212 ftype,endian,offsetsize,filesize, 213 access,groupnumber,errhand,errarg,&dbg,error); 214 if (res != DW_DLV_OK) { 215 close(fd); 216 *ret_dbg = dbg; 217 } 218 dbg->de_path = strdup(file_path); 219 dbg->de_fd = fd; 220 dbg->de_owns_fd = TRUE; 221 set_global_paths_init(dbg,error); 222 *ret_dbg = dbg; 223 return res; 224 } 225 default: 226 close(fd); 227 DWARF_DBG_ERROR(NULL, DW_DLE_FILE_WRONG_TYPE, DW_DLV_ERROR); 228 } 229 return DW_DLV_NO_ENTRY; /* placeholder for now */ 230 } 231 232 233 /* New March 2017, this provides for reading 234 object files with multiple elf section groups. */ 235 int 236 dwarf_init_b(int fd, 237 Dwarf_Unsigned access, 238 unsigned group_number, 239 Dwarf_Handler errhand, 240 Dwarf_Ptr errarg, 241 Dwarf_Debug * ret_dbg, 242 Dwarf_Error * error) 243 { 244 unsigned ftype = 0; 245 unsigned endian = 0; 246 unsigned offsetsize = 0; 247 Dwarf_Unsigned filesize = 0; 248 int res = 0; 249 int errcode = 0; 250 251 if (!ret_dbg) { 252 DWARF_DBG_ERROR(NULL,DW_DLE_DWARF_INIT_DBG_NULL,DW_DLV_ERROR); 253 } 254 res = dwarf_object_detector_fd(fd, &ftype, 255 &endian,&offsetsize,&filesize,&errcode); 256 if (res == DW_DLV_NO_ENTRY) { 257 return res; 258 } else if (res == DW_DLV_ERROR) { 259 DWARF_DBG_ERROR(NULL, DW_DLE_FILE_WRONG_TYPE, DW_DLV_ERROR); 260 } 261 262 switch(ftype) { 263 case DW_FTYPE_ELF: { 264 int res2 = 0; 265 266 res2 = _dwarf_elf_nlsetup(fd,"", 267 ftype,endian,offsetsize,filesize, 268 access,group_number,errhand,errarg,ret_dbg,error); 269 if (res2 != DW_DLV_OK) { 270 return res2; 271 } 272 set_global_paths_init(*ret_dbg,error); 273 return res2; 274 } 275 case DW_FTYPE_MACH_O: { 276 int resm = 0; 277 278 resm = _dwarf_macho_setup(fd,"", 279 ftype,endian,offsetsize,filesize, 280 access,group_number,errhand,errarg,ret_dbg,error); 281 if (resm != DW_DLV_OK) { 282 return resm; 283 } 284 set_global_paths_init(*ret_dbg,error); 285 return resm; 286 } 287 288 case DW_FTYPE_PE: { 289 int resp = 0; 290 291 resp = _dwarf_pe_setup(fd, 292 "", 293 ftype,endian,offsetsize,filesize, 294 access,group_number,errhand,errarg,ret_dbg,error); 295 if (resp != DW_DLV_OK) { 296 return resp; 297 } 298 set_global_paths_init(*ret_dbg,error); 299 return resp; 300 } 301 } 302 DWARF_DBG_ERROR(NULL, DW_DLE_FILE_WRONG_TYPE, DW_DLV_ERROR); 303 return res; 304 } 305 306 /* 307 Frees all memory that was not previously freed 308 by dwarf_dealloc. 309 Aside from certain categories. 310 311 Applicable when dwarf_init() or dwarf_elf_init() 312 or the -b() form was used to init 'dbg'. 313 */ 314 int 315 dwarf_finish(Dwarf_Debug dbg, Dwarf_Error * error) 316 { 317 if(!dbg) { 318 DWARF_DBG_ERROR(NULL, DW_DLE_DBG_NULL, DW_DLV_ERROR); 319 } 320 if (dbg->de_obj_file) { 321 /* The initial character of a valid 322 dbg->de_obj_file->object struct is a letter: 323 E, F, M, or P */ 324 char otype = *(char *)(dbg->de_obj_file->object); 325 326 switch(otype) { 327 case 'E': 328 #ifdef DWARF_WITH_LIBELF 329 dwarf_elf_object_access_finish(dbg->de_obj_file); 330 #endif /* DWARF_WITH_LIBELF */ 331 break; 332 case 'F': 333 /* Non-libelf elf access */ 334 _dwarf_destruct_elf_nlaccess(dbg->de_obj_file); 335 break; 336 case 'M': 337 _dwarf_destruct_macho_access(dbg->de_obj_file); 338 break; 339 case 'P': 340 _dwarf_destruct_pe_access(dbg->de_obj_file); 341 break; 342 default: 343 /* Do nothing. A serious internal error */ 344 break; 345 } 346 } 347 if (dbg->de_owns_fd) { 348 close(dbg->de_fd); 349 dbg->de_owns_fd = FALSE; 350 } 351 free((void *)dbg->de_path); 352 dbg->de_path = 0; 353 /* dwarf_object_finish() also frees de_path, 354 but that is safe because we set it to zero 355 here so no duplicate free will occur. 356 Not all code uses libdwarf exactly as we do 357 hence the free() there. */ 358 return dwarf_object_finish(dbg, error); 359 } 360 361 /* 362 tieddbg should be the executable or .o 363 that has the .debug_addr section that 364 the base dbg refers to. See Split Objects in DWARF5. 365 366 Allows setting to NULL (NULL is the default 367 of de_tied_data.td_tied_object). 368 New September 2015. 369 */ 370 int 371 dwarf_set_tied_dbg(Dwarf_Debug dbg, Dwarf_Debug tieddbg,Dwarf_Error*error) 372 { 373 if(!dbg) { 374 DWARF_DBG_ERROR(NULL, DW_DLE_DBG_NULL, DW_DLV_ERROR); 375 } 376 dbg->de_tied_data.td_tied_object = tieddbg; 377 if (tieddbg) { 378 tieddbg->de_tied_data.td_is_tied_object = TRUE; 379 } 380 return DW_DLV_OK; 381 } 382 383 /* Unsure of the use-case of this. 384 New September 2015. */ 385 int 386 dwarf_get_tied_dbg(Dwarf_Debug dbg, Dwarf_Debug *tieddbg_out, 387 UNUSEDARG Dwarf_Error*error) 388 { 389 *tieddbg_out = dbg->de_tied_data.td_tied_object; 390 return DW_DLV_OK; 391 } 392