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
dwarf_init(int fd,Dwarf_Unsigned access,Dwarf_Handler errhand,Dwarf_Ptr errarg,Dwarf_Debug * ret_dbg,Dwarf_Error * error)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
open_a_file(const char * name)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
set_global_paths_init(Dwarf_Debug dbg,Dwarf_Error * error)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. */
dwarf_init_path(const char * path,char * true_path_out_buffer,unsigned true_path_bufferlen,Dwarf_Unsigned access,unsigned groupnumber,Dwarf_Handler errhand,Dwarf_Ptr errarg,Dwarf_Debug * ret_dbg,UNUSEDARG const char * reserved1,UNUSEDARG Dwarf_Unsigned reserved2,UNUSEDARG Dwarf_Unsigned * reserved3,Dwarf_Error * error)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
dwarf_init_b(int fd,Dwarf_Unsigned access,unsigned group_number,Dwarf_Handler errhand,Dwarf_Ptr errarg,Dwarf_Debug * ret_dbg,Dwarf_Error * error)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
dwarf_finish(Dwarf_Debug dbg,Dwarf_Error * error)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
dwarf_set_tied_dbg(Dwarf_Debug dbg,Dwarf_Debug tieddbg,Dwarf_Error * error)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
dwarf_get_tied_dbg(Dwarf_Debug dbg,Dwarf_Debug * tieddbg_out,UNUSEDARG Dwarf_Error * error)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