1/*
2
3  Copyright (C) 2000,2001,2002,2005,2006 Silicon Graphics, Inc.  All Rights Reserved.
4  Portions Copyright 2007-2010 Sun Microsystems, Inc. All rights reserved.
5  Portions Copyright 2008-2010 Arxan Technologies, 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#include "config.h"
40#include "dwarf_incl.h"
41#include "dwarf_elf_access.h"
42
43#ifdef HAVE_ELF_H
44#include <elf.h>
45#endif
46#ifdef HAVE_LIBELF_H
47#include <libelf.h>
48#else
49#ifdef HAVE_LIBELF_LIBELF_H
50#include <libelf/libelf.h>
51#endif
52#endif
53
54#include <stdio.h>
55#include <sys/stat.h>
56#include <sys/types.h>
57#include <string.h>
58#include <stdlib.h>
59
60#define DWARF_DBG_ERROR(dbg,errval,retval) \
61     _dwarf_error(dbg, error, errval); return(retval);
62
63#define FALSE  0
64#define TRUE   1
65
66static int
67dwarf_elf_init_file_ownership(dwarf_elf_handle elf_file_pointer,
68                              int libdwarf_owns_elf,
69                              Dwarf_Unsigned access,
70                              Dwarf_Handler errhand,
71                              Dwarf_Ptr errarg,
72                              Dwarf_Debug * ret_dbg,
73                              Dwarf_Error * error);
74
75
76/*
77    The basic dwarf initializer function for consumers using
78    libelf.
79    Return a libdwarf error code on error, return DW_DLV_OK
80    if this succeeds.
81*/
82int
83dwarf_init(int fd,
84    Dwarf_Unsigned access,
85    Dwarf_Handler errhand,
86    Dwarf_Ptr errarg, Dwarf_Debug * ret_dbg, Dwarf_Error * error)
87{
88    struct stat fstat_buf;
89    dwarf_elf_handle elf_file_pointer = 0;
90    /* ELF_C_READ is a portable value */
91    Elf_Cmd what_kind_of_elf_read = ELF_C_READ;
92
93#if !defined(S_ISREG)
94#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
95#endif
96    if (fstat(fd, &fstat_buf) != 0) {
97        DWARF_DBG_ERROR(NULL, DW_DLE_FSTAT_ERROR, DW_DLV_ERROR);
98    }
99    if (!S_ISREG(fstat_buf.st_mode)) {
100        DWARF_DBG_ERROR(NULL, DW_DLE_FSTAT_MODE_ERROR, DW_DLV_ERROR);
101    }
102
103    if (access != DW_DLC_READ) {
104        DWARF_DBG_ERROR(NULL, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR);
105    }
106
107    elf_version(EV_CURRENT);
108    /* changed to mmap request per bug 281217. 6/95 */
109#ifdef HAVE_ELF_C_READ_MMAP
110    /* ELF_C_READ_MMAP is an SGI IRIX specific enum value from IRIX
111       libelf.h meaning read but use mmap */
112    what_kind_of_elf_read = ELF_C_READ_MMAP;
113#endif /* !HAVE_ELF_C_READ_MMAP */
114
115    elf_file_pointer = elf_begin(fd, what_kind_of_elf_read, 0);
116    if (elf_file_pointer == NULL) {
117        DWARF_DBG_ERROR(NULL, DW_DLE_ELF_BEGIN_ERROR, DW_DLV_ERROR);
118    }
119
120    return dwarf_elf_init_file_ownership(elf_file_pointer,
121                                         TRUE,
122                                         access,
123                                         errhand,
124                                         errarg,
125                                         ret_dbg,
126                                         error);
127}
128
129/*
130    An alternate dwarf setup call for consumers using
131    libelf.
132    When the caller has opened libelf already, so the
133    caller must free libelf.
134*/
135int
136dwarf_elf_init(dwarf_elf_handle elf_file_pointer,
137    Dwarf_Unsigned access,
138    Dwarf_Handler errhand,
139    Dwarf_Ptr errarg,
140    Dwarf_Debug * ret_dbg, Dwarf_Error * error)
141{
142  return dwarf_elf_init_file_ownership(elf_file_pointer,
143                                       FALSE,
144                                       access,
145                                       errhand,
146                                       errarg,
147                                       ret_dbg,
148                                       error);
149}
150
151
152/*
153    Initialize the ELF object access for libdwarf.
154 */
155static int
156dwarf_elf_init_file_ownership(dwarf_elf_handle elf_file_pointer,
157                              int libdwarf_owns_elf,
158                              Dwarf_Unsigned access,
159                              Dwarf_Handler errhand,
160                              Dwarf_Ptr errarg,
161                              Dwarf_Debug * ret_dbg,
162                              Dwarf_Error * error)
163{
164    /* ELF is no longer tied to libdwarf. */
165    Dwarf_Obj_Access_Interface *binary_interface = 0;
166    int res = DW_DLV_OK;
167    int err = 0;
168
169    if (access != DW_DLC_READ) {
170        DWARF_DBG_ERROR(NULL, DW_DLE_INIT_ACCESS_WRONG, DW_DLV_ERROR);
171    }
172
173    /* This allocates and fills in *binary_interface. */
174    res = dwarf_elf_object_access_init(
175        elf_file_pointer,
176        libdwarf_owns_elf,
177        &binary_interface,
178        &err);
179    if(res != DW_DLV_OK){
180        DWARF_DBG_ERROR(NULL, err, DW_DLV_ERROR);
181    }
182
183    /* This mallocs space and returns pointer thru ret_dbg,
184       saving  the binary interface in 'ret-dbg' */
185    res = dwarf_object_init(binary_interface, errhand, errarg,
186                         ret_dbg, error);
187    if(res != DW_DLV_OK){
188        dwarf_elf_object_access_finish(binary_interface);
189    }
190    return res;
191}
192
193
194/*
195    Frees all memory that was not previously freed
196    by dwarf_dealloc.
197    Aside from certain categories.
198
199    This is only applicable when dwarf_init() or dwarf_elf_init()
200    was used to init 'dbg'.
201*/
202int
203dwarf_finish(Dwarf_Debug dbg, Dwarf_Error * error)
204{
205    dwarf_elf_object_access_finish(dbg->de_obj_file);
206
207    return dwarf_object_finish(dbg, error);
208}
209
210