1*4d9fdb46SRobert Mustacchi /* Copyright (c) 2018-2018, David Anderson
2*4d9fdb46SRobert Mustacchi All rights reserved.
3*4d9fdb46SRobert Mustacchi 
4*4d9fdb46SRobert Mustacchi Redistribution and use in source and binary forms, with
5*4d9fdb46SRobert Mustacchi or without modification, are permitted provided that the
6*4d9fdb46SRobert Mustacchi following conditions are met:
7*4d9fdb46SRobert Mustacchi 
8*4d9fdb46SRobert Mustacchi     Redistributions of source code must retain the above
9*4d9fdb46SRobert Mustacchi     copyright notice, this list of conditions and the following
10*4d9fdb46SRobert Mustacchi     disclaimer.
11*4d9fdb46SRobert Mustacchi 
12*4d9fdb46SRobert Mustacchi     Redistributions in binary form must reproduce the above
13*4d9fdb46SRobert Mustacchi     copyright notice, this list of conditions and the following
14*4d9fdb46SRobert Mustacchi     disclaimer in the documentation and/or other materials
15*4d9fdb46SRobert Mustacchi     provided with the distribution.
16*4d9fdb46SRobert Mustacchi 
17*4d9fdb46SRobert Mustacchi THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
18*4d9fdb46SRobert Mustacchi CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
19*4d9fdb46SRobert Mustacchi INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20*4d9fdb46SRobert Mustacchi OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21*4d9fdb46SRobert Mustacchi ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
22*4d9fdb46SRobert Mustacchi CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23*4d9fdb46SRobert Mustacchi SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
24*4d9fdb46SRobert Mustacchi NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
25*4d9fdb46SRobert Mustacchi LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26*4d9fdb46SRobert Mustacchi HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27*4d9fdb46SRobert Mustacchi CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
28*4d9fdb46SRobert Mustacchi OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
29*4d9fdb46SRobert Mustacchi EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30*4d9fdb46SRobert Mustacchi */
31*4d9fdb46SRobert Mustacchi 
32*4d9fdb46SRobert Mustacchi #include "config.h"
33*4d9fdb46SRobert Mustacchi #include <stdio.h>
34*4d9fdb46SRobert Mustacchi #include <sys/types.h> /* open() */
35*4d9fdb46SRobert Mustacchi #include <sys/stat.h> /* open() */
36*4d9fdb46SRobert Mustacchi #include <fcntl.h> /* O_RDONLY */
37*4d9fdb46SRobert Mustacchi #ifdef HAVE_UNISTD_H
38*4d9fdb46SRobert Mustacchi #include <unistd.h> /* lseek read close */
39*4d9fdb46SRobert Mustacchi #elif defined(_WIN32) && defined(_MSC_VER)
40*4d9fdb46SRobert Mustacchi #include <io.h>
41*4d9fdb46SRobert Mustacchi #include <basetsd.h>
42*4d9fdb46SRobert Mustacchi typedef SSIZE_T ssize_t; /* MSVC does not have POSIX ssize_t */
43*4d9fdb46SRobert Mustacchi #endif /* HAVE_UNISTD_H */
44*4d9fdb46SRobert Mustacchi #ifdef HAVE_STRING_H
45*4d9fdb46SRobert Mustacchi #include <string.h> /* memcpy, strcpy */
46*4d9fdb46SRobert Mustacchi #endif /* HAVE_STRING_H */
47*4d9fdb46SRobert Mustacchi 
48*4d9fdb46SRobert Mustacchi /* Windows specific header files */
49*4d9fdb46SRobert Mustacchi #if defined(_WIN32) && defined(HAVE_STDAFX_H)
50*4d9fdb46SRobert Mustacchi #include "stdafx.h"
51*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDAFX_H */
52*4d9fdb46SRobert Mustacchi 
53*4d9fdb46SRobert Mustacchi #include "libdwarf.h"
54*4d9fdb46SRobert Mustacchi #include "memcpy_swap.h"
55*4d9fdb46SRobert Mustacchi #include "dwarf_object_read_common.h"
56*4d9fdb46SRobert Mustacchi #include "dwarf_object_detector.h"
57*4d9fdb46SRobert Mustacchi 
58*4d9fdb46SRobert Mustacchi #ifndef O_BINARY
59*4d9fdb46SRobert Mustacchi #define O_BINARY 0
60*4d9fdb46SRobert Mustacchi #endif /* O_BINARY */
61*4d9fdb46SRobert Mustacchi 
62*4d9fdb46SRobert Mustacchi /* This is the main() program for the object_detector executable. */
63*4d9fdb46SRobert Mustacchi 
64*4d9fdb46SRobert Mustacchi #ifndef TRUE
65*4d9fdb46SRobert Mustacchi #define TRUE 1
66*4d9fdb46SRobert Mustacchi #define FALSE 0
67*4d9fdb46SRobert Mustacchi #endif /* TRUE */
68*4d9fdb46SRobert Mustacchi 
69*4d9fdb46SRobert Mustacchi #ifndef O_RDONLY
70*4d9fdb46SRobert Mustacchi #define O_RDONLY 0
71*4d9fdb46SRobert Mustacchi #endif
72*4d9fdb46SRobert Mustacchi 
73*4d9fdb46SRobert Mustacchi /*  TYP, SIZEOFT32 and ASNAR
74*4d9fdb46SRobert Mustacchi     mean we can use correctly-sized arrays of char for the
75*4d9fdb46SRobert Mustacchi     struct members instead of determing a proper integer
76*4d9fdb46SRobert Mustacchi     that size.
77*4d9fdb46SRobert Mustacchi 
78*4d9fdb46SRobert Mustacchi     We are dealing with carefully constructed structs
79*4d9fdb46SRobert Mustacchi     that do not have any alignment-forced (hidden)
80*4d9fdb46SRobert Mustacchi     unused bytes so reading lengths from the real structs
81*4d9fdb46SRobert Mustacchi     works for each variable.  */
82*4d9fdb46SRobert Mustacchi 
83*4d9fdb46SRobert Mustacchi #define TYP(n,l) char n[l]
84*4d9fdb46SRobert Mustacchi #define SIZEOFT32 4
85*4d9fdb46SRobert Mustacchi 
86*4d9fdb46SRobert Mustacchi 
87*4d9fdb46SRobert Mustacchi #define DW_DLV_NO_ENTRY -1
88*4d9fdb46SRobert Mustacchi #define DW_DLV_OK        0
89*4d9fdb46SRobert Mustacchi #define DW_DLV_ERROR     1
90*4d9fdb46SRobert Mustacchi 
91*4d9fdb46SRobert Mustacchi #ifndef EI_NIDENT
92*4d9fdb46SRobert Mustacchi #define EI_NIDENT 16
93*4d9fdb46SRobert Mustacchi #define EI_CLASS  4
94*4d9fdb46SRobert Mustacchi #define EI_DATA   5
95*4d9fdb46SRobert Mustacchi #define EI_VERSION 6
96*4d9fdb46SRobert Mustacchi #define ELFCLASS32 1
97*4d9fdb46SRobert Mustacchi #define ELFCLASS64 2
98*4d9fdb46SRobert Mustacchi #define ELFDATA2LSB 1
99*4d9fdb46SRobert Mustacchi #define ELFDATA2MSB 2
100*4d9fdb46SRobert Mustacchi #endif /* EI_NIDENT */
101*4d9fdb46SRobert Mustacchi 
102*4d9fdb46SRobert Mustacchi #define DSYM_SUFFIX ".dSYM/Contents/Resources/DWARF/"
103*4d9fdb46SRobert Mustacchi #define PATHSIZE 2000
104*4d9fdb46SRobert Mustacchi 
105*4d9fdb46SRobert Mustacchi #ifndef  MH_MAGIC
106*4d9fdb46SRobert Mustacchi /* mach-o 32bit */
107*4d9fdb46SRobert Mustacchi #define MH_MAGIC        0xfeedface
108*4d9fdb46SRobert Mustacchi #define MH_CIGAM        0xcefaedfe
109*4d9fdb46SRobert Mustacchi #endif /*  MH_MAGIC */
110*4d9fdb46SRobert Mustacchi #ifndef  MH_MAGIC_64
111*4d9fdb46SRobert Mustacchi /* mach-o 64bit */
112*4d9fdb46SRobert Mustacchi #define MH_MAGIC_64 0xfeedfacf
113*4d9fdb46SRobert Mustacchi #define MH_CIGAM_64 0xcffaedfe
114*4d9fdb46SRobert Mustacchi #endif /*  MH_MAGIC_64 */
115*4d9fdb46SRobert Mustacchi 
116*4d9fdb46SRobert Mustacchi static unsigned long
magic_copy(unsigned char * d,unsigned len)117*4d9fdb46SRobert Mustacchi magic_copy(unsigned char *d, unsigned len)
118*4d9fdb46SRobert Mustacchi {
119*4d9fdb46SRobert Mustacchi     unsigned i = 0;
120*4d9fdb46SRobert Mustacchi     unsigned long v = 0;
121*4d9fdb46SRobert Mustacchi 
122*4d9fdb46SRobert Mustacchi     v = d[0];
123*4d9fdb46SRobert Mustacchi     for(i = 1 ; i < len; ++i) {
124*4d9fdb46SRobert Mustacchi         v <<= 8;
125*4d9fdb46SRobert Mustacchi         v |=  d[i];
126*4d9fdb46SRobert Mustacchi     }
127*4d9fdb46SRobert Mustacchi     return v;
128*4d9fdb46SRobert Mustacchi }
129*4d9fdb46SRobert Mustacchi 
130*4d9fdb46SRobert Mustacchi 
131*4d9fdb46SRobert Mustacchi #ifdef WORDS_BIGENDIAN
132*4d9fdb46SRobert Mustacchi #define ASNAR(func,t,s)                         \
133*4d9fdb46SRobert Mustacchi     do {                                        \
134*4d9fdb46SRobert Mustacchi         unsigned tbyte = sizeof(t) - sizeof(s); \
135*4d9fdb46SRobert Mustacchi         t = 0;                                  \
136*4d9fdb46SRobert Mustacchi         func(((char *)&t)+tbyte ,&s[0],sizeof(s));  \
137*4d9fdb46SRobert Mustacchi     } while (0)
138*4d9fdb46SRobert Mustacchi #else /* LITTLE ENDIAN */
139*4d9fdb46SRobert Mustacchi #define ASNAR(func,t,s)                         \
140*4d9fdb46SRobert Mustacchi     do {                                        \
141*4d9fdb46SRobert Mustacchi         t = 0;                                  \
142*4d9fdb46SRobert Mustacchi         func(&t,&s[0],sizeof(s));               \
143*4d9fdb46SRobert Mustacchi     } while (0)
144*4d9fdb46SRobert Mustacchi #endif /* end LITTLE- BIG-ENDIAN */
145*4d9fdb46SRobert Mustacchi 
146*4d9fdb46SRobert Mustacchi 
147*4d9fdb46SRobert Mustacchi #define EI_NIDENT 16
148*4d9fdb46SRobert Mustacchi /* An incomplete elf header, good for 32 and 64bit elf */
149*4d9fdb46SRobert Mustacchi struct elf_header {
150*4d9fdb46SRobert Mustacchi     unsigned char  e_ident[EI_NIDENT];
151*4d9fdb46SRobert Mustacchi     TYP(e_type,2);
152*4d9fdb46SRobert Mustacchi     TYP(e_machine,2);
153*4d9fdb46SRobert Mustacchi     TYP(e_version,4);
154*4d9fdb46SRobert Mustacchi #ifdef HAVE_CUSTOM_LIBELF
155*4d9fdb46SRobert Mustacchi     /* In the case of custom ELF, use extra space */
156*4d9fdb46SRobert Mustacchi     TYP(e_custom,64);
157*4d9fdb46SRobert Mustacchi #endif /* HAVE_CUSTOM_LIBELF */
158*4d9fdb46SRobert Mustacchi };
159*4d9fdb46SRobert Mustacchi 
160*4d9fdb46SRobert Mustacchi /*  Windows. Certain PE objects.
161*4d9fdb46SRobert Mustacchi     The following references may be of interest.
162*4d9fdb46SRobert Mustacchi https://msdn.microsoft.com/library/windows/desktop/ms680547(v=vs.85).aspx       #PE format overview and various machine magic numbers
163*4d9fdb46SRobert Mustacchi 
164*4d9fdb46SRobert Mustacchi https://msdn.microsoft.com/en-us/library/ms809762.aspx  # describes some details of PE headers, basically an overview
165*4d9fdb46SRobert Mustacchi 
166*4d9fdb46SRobert Mustacchi https://msdn.microsoft.com/en-us/library/windows/desktop/aa383751(v=vs.85).aspx #defines sizes of various types
167*4d9fdb46SRobert Mustacchi 
168*4d9fdb46SRobert Mustacchi https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms680313(v=vs.85).aspx #defines IMAGE_FILE_HEADER and Machine fields (32/64)
169*4d9fdb46SRobert Mustacchi 
170*4d9fdb46SRobert Mustacchi https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms680305(v=vs.85).aspx #defines IMAGE_DATA_DIRECTORY
171*4d9fdb46SRobert Mustacchi 
172*4d9fdb46SRobert Mustacchi https://msdn.microsoft.com/en-us/library/windows/desktop/ms680339(v=vs.85).aspx #Defines IMAGE_OPTIONAL_HEADER and some magic numbers
173*4d9fdb46SRobert Mustacchi 
174*4d9fdb46SRobert Mustacchi https://msdn.microsoft.com/fr-fr/library/windows/desktop/ms680336(v=vs.85).aspx # defines _IMAGE_NT_HEADERS 32 64
175*4d9fdb46SRobert Mustacchi 
176*4d9fdb46SRobert Mustacchi https://msdn.microsoft.com/en-us/library/windows/desktop/ms680341(v=vs.85).aspx # defines _IMAGE_SECTION_HEADER
177*4d9fdb46SRobert Mustacchi 
178*4d9fdb46SRobert Mustacchi */
179*4d9fdb46SRobert Mustacchi 
180*4d9fdb46SRobert Mustacchi /* ===== START pe structures */
181*4d9fdb46SRobert Mustacchi 
182*4d9fdb46SRobert Mustacchi struct dos_header {
183*4d9fdb46SRobert Mustacchi     TYP(dh_mz,2);
184*4d9fdb46SRobert Mustacchi     TYP(dh_dos_data,58);
185*4d9fdb46SRobert Mustacchi     TYP(dh_image_offset,4);
186*4d9fdb46SRobert Mustacchi };
187*4d9fdb46SRobert Mustacchi 
188*4d9fdb46SRobert Mustacchi #define IMAGE_DOS_SIGNATURE_dw      0x5A4D
189*4d9fdb46SRobert Mustacchi #define IMAGE_DOS_REVSIGNATURE_dw   0x4D5A
190*4d9fdb46SRobert Mustacchi #define IMAGE_NT_SIGNATURE_dw       0x00004550
191*4d9fdb46SRobert Mustacchi #define IMAGE_FILE_MACHINE_I386_dw  0x14c
192*4d9fdb46SRobert Mustacchi #define IMAGE_FILE_MACHINE_IA64_dw  0x200
193*4d9fdb46SRobert Mustacchi #define IMAGE_FILE_MACHINE_AMD64_dw 0x8664
194*4d9fdb46SRobert Mustacchi 
195*4d9fdb46SRobert Mustacchi 
196*4d9fdb46SRobert Mustacchi struct pe_image_file_header {
197*4d9fdb46SRobert Mustacchi     TYP(im_machine,2);
198*4d9fdb46SRobert Mustacchi     TYP(im_sectioncount,2);
199*4d9fdb46SRobert Mustacchi     TYP(im_ignoring,(3*4));
200*4d9fdb46SRobert Mustacchi     TYP(im_opt_header_size,2);
201*4d9fdb46SRobert Mustacchi     TYP(im_ignoringb,2);
202*4d9fdb46SRobert Mustacchi };
203*4d9fdb46SRobert Mustacchi 
204*4d9fdb46SRobert Mustacchi /* ===== END pe structures */
205*4d9fdb46SRobert Mustacchi 
206*4d9fdb46SRobert Mustacchi 
207*4d9fdb46SRobert Mustacchi /*  For following MacOS file naming convention */
208*4d9fdb46SRobert Mustacchi static const char *
getseparator(const char * f)209*4d9fdb46SRobert Mustacchi getseparator (const char *f)
210*4d9fdb46SRobert Mustacchi {
211*4d9fdb46SRobert Mustacchi     const char *p = 0;
212*4d9fdb46SRobert Mustacchi     const char *q = 0;
213*4d9fdb46SRobert Mustacchi     char c = 0;;
214*4d9fdb46SRobert Mustacchi 
215*4d9fdb46SRobert Mustacchi     p = NULL;
216*4d9fdb46SRobert Mustacchi     q = f;
217*4d9fdb46SRobert Mustacchi     do  {
218*4d9fdb46SRobert Mustacchi         c = *q++;
219*4d9fdb46SRobert Mustacchi         if (c == '\\' || c == '/' || c == ':') {
220*4d9fdb46SRobert Mustacchi             p = q;
221*4d9fdb46SRobert Mustacchi         }
222*4d9fdb46SRobert Mustacchi     } while (c);
223*4d9fdb46SRobert Mustacchi     return p;
224*4d9fdb46SRobert Mustacchi }
225*4d9fdb46SRobert Mustacchi 
226*4d9fdb46SRobert Mustacchi static const char *
getbasename(const char * f)227*4d9fdb46SRobert Mustacchi getbasename (const char *f)
228*4d9fdb46SRobert Mustacchi {
229*4d9fdb46SRobert Mustacchi     const char *pseparator = getseparator (f);
230*4d9fdb46SRobert Mustacchi     if (!pseparator) {
231*4d9fdb46SRobert Mustacchi         return f;
232*4d9fdb46SRobert Mustacchi     }
233*4d9fdb46SRobert Mustacchi     return pseparator;
234*4d9fdb46SRobert Mustacchi }
235*4d9fdb46SRobert Mustacchi 
236*4d9fdb46SRobert Mustacchi /*  Not a standard function, though part of GNU libc
237*4d9fdb46SRobert Mustacchi     since 2008 (I have never examined the GNU version).  */
238*4d9fdb46SRobert Mustacchi static char *
dw_stpcpy(char * dest,const char * src)239*4d9fdb46SRobert Mustacchi dw_stpcpy(char *dest,const char *src)
240*4d9fdb46SRobert Mustacchi {
241*4d9fdb46SRobert Mustacchi     const char *cp = src;
242*4d9fdb46SRobert Mustacchi     char *dp = dest;
243*4d9fdb46SRobert Mustacchi 
244*4d9fdb46SRobert Mustacchi     for ( ; *cp; ++cp,++dp) {
245*4d9fdb46SRobert Mustacchi         *dp = *cp;
246*4d9fdb46SRobert Mustacchi     }
247*4d9fdb46SRobert Mustacchi     *dp = 0;
248*4d9fdb46SRobert Mustacchi     return dp;
249*4d9fdb46SRobert Mustacchi }
250*4d9fdb46SRobert Mustacchi 
251*4d9fdb46SRobert Mustacchi 
252*4d9fdb46SRobert Mustacchi 
253*4d9fdb46SRobert Mustacchi /* This started like Elf, so check initial fields. */
254*4d9fdb46SRobert Mustacchi static int
fill_in_elf_fields(struct elf_header * h,unsigned * endian,unsigned * objoffsetsize,int * errcode)255*4d9fdb46SRobert Mustacchi fill_in_elf_fields(struct elf_header *h,
256*4d9fdb46SRobert Mustacchi     unsigned *endian,
257*4d9fdb46SRobert Mustacchi     /*  Size of the object file offsets, not DWARF offset
258*4d9fdb46SRobert Mustacchi         size. */
259*4d9fdb46SRobert Mustacchi     unsigned *objoffsetsize,
260*4d9fdb46SRobert Mustacchi     int *errcode)
261*4d9fdb46SRobert Mustacchi {
262*4d9fdb46SRobert Mustacchi     unsigned locendian = 0;
263*4d9fdb46SRobert Mustacchi     unsigned locoffsetsize = 0;
264*4d9fdb46SRobert Mustacchi 
265*4d9fdb46SRobert Mustacchi     switch(h->e_ident[EI_CLASS]) {
266*4d9fdb46SRobert Mustacchi     case ELFCLASS32:
267*4d9fdb46SRobert Mustacchi         locoffsetsize = 32;
268*4d9fdb46SRobert Mustacchi         break;
269*4d9fdb46SRobert Mustacchi     case ELFCLASS64:
270*4d9fdb46SRobert Mustacchi         locoffsetsize = 64;
271*4d9fdb46SRobert Mustacchi         break;
272*4d9fdb46SRobert Mustacchi     default:
273*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_ELF_CLASS_BAD;
274*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
275*4d9fdb46SRobert Mustacchi     }
276*4d9fdb46SRobert Mustacchi     switch(h->e_ident[EI_DATA]) {
277*4d9fdb46SRobert Mustacchi     case ELFDATA2LSB:
278*4d9fdb46SRobert Mustacchi         locendian = DW_ENDIAN_LITTLE;
279*4d9fdb46SRobert Mustacchi         break;
280*4d9fdb46SRobert Mustacchi     case ELFDATA2MSB:
281*4d9fdb46SRobert Mustacchi         locendian = DW_ENDIAN_BIG;
282*4d9fdb46SRobert Mustacchi         break;
283*4d9fdb46SRobert Mustacchi     default:
284*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_ELF_ENDIAN_BAD;
285*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
286*4d9fdb46SRobert Mustacchi     }
287*4d9fdb46SRobert Mustacchi     if (h->e_ident[EI_VERSION] != 1 /* EV_CURRENT */) {
288*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_ELF_VERSION_BAD;
289*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
290*4d9fdb46SRobert Mustacchi     }
291*4d9fdb46SRobert Mustacchi     *endian = locendian;
292*4d9fdb46SRobert Mustacchi     *objoffsetsize = locoffsetsize;
293*4d9fdb46SRobert Mustacchi     return DW_DLV_OK;
294*4d9fdb46SRobert Mustacchi }
295*4d9fdb46SRobert Mustacchi static char archive_magic[8] = {
296*4d9fdb46SRobert Mustacchi '!','<','a','r','c','h','>',0x0a
297*4d9fdb46SRobert Mustacchi };
298*4d9fdb46SRobert Mustacchi static int
is_archive_magic(struct elf_header * h)299*4d9fdb46SRobert Mustacchi is_archive_magic(struct elf_header *h) {
300*4d9fdb46SRobert Mustacchi     int i = 0;
301*4d9fdb46SRobert Mustacchi     int len = sizeof(archive_magic);
302*4d9fdb46SRobert Mustacchi     const char *cp = (const char *)h;
303*4d9fdb46SRobert Mustacchi     for( ; i < len; ++i) {
304*4d9fdb46SRobert Mustacchi         if (cp[i] != archive_magic[i]) {
305*4d9fdb46SRobert Mustacchi             return FALSE;
306*4d9fdb46SRobert Mustacchi         }
307*4d9fdb46SRobert Mustacchi     }
308*4d9fdb46SRobert Mustacchi     return TRUE;
309*4d9fdb46SRobert Mustacchi }
310*4d9fdb46SRobert Mustacchi 
311*4d9fdb46SRobert Mustacchi /*  A bit unusual in that it always sets *is_pe_flag
312*4d9fdb46SRobert Mustacchi     Return of DW_DLV_OK  it is a PE file we recognize. */
313*4d9fdb46SRobert Mustacchi static int
is_pe_object(int fd,unsigned long filesize,unsigned * endian,unsigned * offsetsize,int * errcode)314*4d9fdb46SRobert Mustacchi is_pe_object(int fd,
315*4d9fdb46SRobert Mustacchi     unsigned long filesize,
316*4d9fdb46SRobert Mustacchi     unsigned *endian,
317*4d9fdb46SRobert Mustacchi     unsigned *offsetsize,
318*4d9fdb46SRobert Mustacchi     int *errcode)
319*4d9fdb46SRobert Mustacchi {
320*4d9fdb46SRobert Mustacchi     unsigned dos_sig = 0;
321*4d9fdb46SRobert Mustacchi     unsigned locendian = 0;
322*4d9fdb46SRobert Mustacchi     void (*word_swap) (void *, const void *, unsigned long);
323*4d9fdb46SRobert Mustacchi     unsigned long nt_address = 0;
324*4d9fdb46SRobert Mustacchi     struct dos_header dhinmem;
325*4d9fdb46SRobert Mustacchi     char nt_sig_array[4];
326*4d9fdb46SRobert Mustacchi     unsigned long nt_sig = 0;
327*4d9fdb46SRobert Mustacchi     struct pe_image_file_header ifh;
328*4d9fdb46SRobert Mustacchi     int res = 0;
329*4d9fdb46SRobert Mustacchi 
330*4d9fdb46SRobert Mustacchi     if (filesize < (sizeof (struct dos_header) +
331*4d9fdb46SRobert Mustacchi         SIZEOFT32 + sizeof(struct pe_image_file_header))) {
332*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_TOO_SMALL;
333*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
334*4d9fdb46SRobert Mustacchi     }
335*4d9fdb46SRobert Mustacchi     res = _dwarf_object_read_random(fd,(char *)&dhinmem,
336*4d9fdb46SRobert Mustacchi         0,sizeof(dhinmem),filesize,errcode);
337*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
338*4d9fdb46SRobert Mustacchi         return res;
339*4d9fdb46SRobert Mustacchi     }
340*4d9fdb46SRobert Mustacchi     /* No swap here, want it as in the file */
341*4d9fdb46SRobert Mustacchi     dos_sig = magic_copy((unsigned char *)dhinmem.dh_mz,
342*4d9fdb46SRobert Mustacchi         sizeof(dhinmem.dh_mz));
343*4d9fdb46SRobert Mustacchi     if (dos_sig == IMAGE_DOS_SIGNATURE_dw) {
344*4d9fdb46SRobert Mustacchi         /*  IMAGE_DOS_SIGNATURE_dw assumes bytes reversed by little-endian
345*4d9fdb46SRobert Mustacchi             load, so we intrepet a match the other way. */
346*4d9fdb46SRobert Mustacchi         /* BIG ENDIAN. From looking at hex characters in object  */
347*4d9fdb46SRobert Mustacchi #ifdef  WORDS_BIGENDIAN
348*4d9fdb46SRobert Mustacchi         word_swap = _dwarf_memcpy_noswap_bytes;
349*4d9fdb46SRobert Mustacchi #else   /* LITTLE ENDIAN */
350*4d9fdb46SRobert Mustacchi         word_swap =  _dwarf_memcpy_swap_bytes;
351*4d9fdb46SRobert Mustacchi #endif  /* LITTLE- BIG-ENDIAN */
352*4d9fdb46SRobert Mustacchi         locendian = DW_ENDIAN_BIG;
353*4d9fdb46SRobert Mustacchi     } else if (dos_sig == IMAGE_DOS_REVSIGNATURE_dw) {
354*4d9fdb46SRobert Mustacchi         /* raw load, so  intrepet a match the other way. */
355*4d9fdb46SRobert Mustacchi         /* LITTLE ENDIAN */
356*4d9fdb46SRobert Mustacchi #ifdef  WORDS_BIGENDIAN
357*4d9fdb46SRobert Mustacchi         word_swap =  _dwarf_memcpy_swap_bytes;
358*4d9fdb46SRobert Mustacchi #else   /* LITTLE ENDIAN */
359*4d9fdb46SRobert Mustacchi         word_swap = _dwarf_memcpy_noswap_bytes;
360*4d9fdb46SRobert Mustacchi #endif  /* LITTLE- BIG-ENDIAN */
361*4d9fdb46SRobert Mustacchi         locendian = DW_ENDIAN_LITTLE;
362*4d9fdb46SRobert Mustacchi     } else {
363*4d9fdb46SRobert Mustacchi         /* Not dos header not a PE file we recognize */
364*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_WRONG_TYPE;
365*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
366*4d9fdb46SRobert Mustacchi     }
367*4d9fdb46SRobert Mustacchi     ASNAR(word_swap,nt_address, dhinmem.dh_image_offset);
368*4d9fdb46SRobert Mustacchi     if (filesize < nt_address) {
369*4d9fdb46SRobert Mustacchi         /* Not dos header not a PE file we recognize */
370*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_TOO_SMALL;
371*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
372*4d9fdb46SRobert Mustacchi     }
373*4d9fdb46SRobert Mustacchi     if (filesize < (nt_address + SIZEOFT32 +
374*4d9fdb46SRobert Mustacchi         sizeof(struct pe_image_file_header))) {
375*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_TOO_SMALL;
376*4d9fdb46SRobert Mustacchi         /* Not dos header not a PE file we recognize */
377*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
378*4d9fdb46SRobert Mustacchi     }
379*4d9fdb46SRobert Mustacchi     res =  _dwarf_object_read_random(fd,(char *)&nt_sig_array[0],
380*4d9fdb46SRobert Mustacchi         nt_address, sizeof(nt_sig_array),filesize,errcode);
381*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
382*4d9fdb46SRobert Mustacchi         return res;
383*4d9fdb46SRobert Mustacchi     }
384*4d9fdb46SRobert Mustacchi     {   unsigned long lsig = 0;
385*4d9fdb46SRobert Mustacchi 
386*4d9fdb46SRobert Mustacchi         ASNAR(word_swap,lsig,nt_sig_array);
387*4d9fdb46SRobert Mustacchi         nt_sig = lsig;
388*4d9fdb46SRobert Mustacchi     }
389*4d9fdb46SRobert Mustacchi     if (nt_sig != IMAGE_NT_SIGNATURE_dw) {
390*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_WRONG_TYPE;
391*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
392*4d9fdb46SRobert Mustacchi     }
393*4d9fdb46SRobert Mustacchi     res = _dwarf_object_read_random(fd,(char *)&ifh,
394*4d9fdb46SRobert Mustacchi         nt_address + SIZEOFT32,
395*4d9fdb46SRobert Mustacchi         sizeof(struct pe_image_file_header),
396*4d9fdb46SRobert Mustacchi         filesize,
397*4d9fdb46SRobert Mustacchi         errcode);
398*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
399*4d9fdb46SRobert Mustacchi         return res;
400*4d9fdb46SRobert Mustacchi     }
401*4d9fdb46SRobert Mustacchi     {
402*4d9fdb46SRobert Mustacchi         unsigned long machine = 0;
403*4d9fdb46SRobert Mustacchi 
404*4d9fdb46SRobert Mustacchi         ASNAR(word_swap,machine,ifh.im_machine);
405*4d9fdb46SRobert Mustacchi         switch(machine) {
406*4d9fdb46SRobert Mustacchi         case IMAGE_FILE_MACHINE_I386_dw:
407*4d9fdb46SRobert Mustacchi             *offsetsize = 32;
408*4d9fdb46SRobert Mustacchi             *endian = locendian;
409*4d9fdb46SRobert Mustacchi             return DW_DLV_OK;
410*4d9fdb46SRobert Mustacchi         case IMAGE_FILE_MACHINE_IA64_dw:
411*4d9fdb46SRobert Mustacchi         case IMAGE_FILE_MACHINE_AMD64_dw:
412*4d9fdb46SRobert Mustacchi             *offsetsize = 64;
413*4d9fdb46SRobert Mustacchi             *endian = locendian;
414*4d9fdb46SRobert Mustacchi             return DW_DLV_OK;
415*4d9fdb46SRobert Mustacchi         }
416*4d9fdb46SRobert Mustacchi     }
417*4d9fdb46SRobert Mustacchi     *errcode = DW_DLE_IMAGE_FILE_UNKNOWN_TYPE;
418*4d9fdb46SRobert Mustacchi     return DW_DLV_ERROR;
419*4d9fdb46SRobert Mustacchi }
420*4d9fdb46SRobert Mustacchi 
421*4d9fdb46SRobert Mustacchi static int
is_mach_o_magic(struct elf_header * h,unsigned * endian,unsigned * offsetsize)422*4d9fdb46SRobert Mustacchi is_mach_o_magic(struct elf_header *h,
423*4d9fdb46SRobert Mustacchi     unsigned *endian,
424*4d9fdb46SRobert Mustacchi     unsigned *offsetsize)
425*4d9fdb46SRobert Mustacchi {
426*4d9fdb46SRobert Mustacchi     unsigned long magicval = 0;
427*4d9fdb46SRobert Mustacchi     unsigned locendian = 0;
428*4d9fdb46SRobert Mustacchi     unsigned locoffsetsize = 0;
429*4d9fdb46SRobert Mustacchi 
430*4d9fdb46SRobert Mustacchi     /*  No swapping here. Need to match size of
431*4d9fdb46SRobert Mustacchi         Mach-o magic field. */
432*4d9fdb46SRobert Mustacchi     magicval = magic_copy(h->e_ident,4);
433*4d9fdb46SRobert Mustacchi     if (magicval == MH_MAGIC) {
434*4d9fdb46SRobert Mustacchi         locendian = DW_ENDIAN_BIG;
435*4d9fdb46SRobert Mustacchi         locoffsetsize = 32;
436*4d9fdb46SRobert Mustacchi     } else if (magicval == MH_CIGAM) {
437*4d9fdb46SRobert Mustacchi         locendian = DW_ENDIAN_LITTLE;
438*4d9fdb46SRobert Mustacchi         locoffsetsize = 32;
439*4d9fdb46SRobert Mustacchi     }else if (magicval == MH_MAGIC_64) {
440*4d9fdb46SRobert Mustacchi         locendian = DW_ENDIAN_BIG;
441*4d9fdb46SRobert Mustacchi         locoffsetsize = 64;
442*4d9fdb46SRobert Mustacchi     } else if (magicval == MH_CIGAM_64) {
443*4d9fdb46SRobert Mustacchi         locendian = DW_ENDIAN_LITTLE;
444*4d9fdb46SRobert Mustacchi         locoffsetsize = 64;
445*4d9fdb46SRobert Mustacchi     } else {
446*4d9fdb46SRobert Mustacchi         return FALSE;
447*4d9fdb46SRobert Mustacchi     }
448*4d9fdb46SRobert Mustacchi     *endian = locendian;
449*4d9fdb46SRobert Mustacchi     *offsetsize = locoffsetsize;
450*4d9fdb46SRobert Mustacchi     return TRUE;
451*4d9fdb46SRobert Mustacchi }
452*4d9fdb46SRobert Mustacchi 
453*4d9fdb46SRobert Mustacchi int
dwarf_object_detector_fd(int fd,unsigned * ftype,unsigned * endian,unsigned * offsetsize,Dwarf_Unsigned * filesize,int * errcode)454*4d9fdb46SRobert Mustacchi dwarf_object_detector_fd(int fd,
455*4d9fdb46SRobert Mustacchi     unsigned *ftype,
456*4d9fdb46SRobert Mustacchi     unsigned *endian,
457*4d9fdb46SRobert Mustacchi     unsigned *offsetsize,
458*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned  *filesize,
459*4d9fdb46SRobert Mustacchi     int *errcode)
460*4d9fdb46SRobert Mustacchi {
461*4d9fdb46SRobert Mustacchi     struct elf_header h;
462*4d9fdb46SRobert Mustacchi     size_t readlen = sizeof(h);
463*4d9fdb46SRobert Mustacchi     int res = 0;
464*4d9fdb46SRobert Mustacchi     off_t fsize = 0;
465*4d9fdb46SRobert Mustacchi     off_t lsval = 0;
466*4d9fdb46SRobert Mustacchi     ssize_t readval = 0;
467*4d9fdb46SRobert Mustacchi 
468*4d9fdb46SRobert Mustacchi     fsize = lseek(fd,0L,SEEK_END);
469*4d9fdb46SRobert Mustacchi     if(fsize < 0) {
470*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_SEEK_ERROR;
471*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
472*4d9fdb46SRobert Mustacchi     }
473*4d9fdb46SRobert Mustacchi     if (fsize <= (off_t)readlen) {
474*4d9fdb46SRobert Mustacchi         /* Not a real object file */
475*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_TOO_SMALL;
476*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
477*4d9fdb46SRobert Mustacchi     }
478*4d9fdb46SRobert Mustacchi     lsval  = lseek(fd,0L,SEEK_SET);
479*4d9fdb46SRobert Mustacchi     if(lsval < 0) {
480*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_SEEK_ERROR;
481*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
482*4d9fdb46SRobert Mustacchi     }
483*4d9fdb46SRobert Mustacchi     readval = read(fd,&h,readlen);
484*4d9fdb46SRobert Mustacchi     if (readval != (ssize_t)readlen) {
485*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_READ_ERROR;
486*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
487*4d9fdb46SRobert Mustacchi     }
488*4d9fdb46SRobert Mustacchi     if (h.e_ident[0] == 0x7f &&
489*4d9fdb46SRobert Mustacchi         h.e_ident[1] == 'E' &&
490*4d9fdb46SRobert Mustacchi         h.e_ident[2] == 'L' &&
491*4d9fdb46SRobert Mustacchi         h.e_ident[3] == 'F') {
492*4d9fdb46SRobert Mustacchi         /* is ELF */
493*4d9fdb46SRobert Mustacchi 
494*4d9fdb46SRobert Mustacchi         res = fill_in_elf_fields(&h,endian,offsetsize,errcode);
495*4d9fdb46SRobert Mustacchi         if (res != DW_DLV_OK) {
496*4d9fdb46SRobert Mustacchi             return res;
497*4d9fdb46SRobert Mustacchi         }
498*4d9fdb46SRobert Mustacchi         *ftype = DW_FTYPE_ELF;
499*4d9fdb46SRobert Mustacchi         *filesize = (size_t)fsize;
500*4d9fdb46SRobert Mustacchi         return DW_DLV_OK;
501*4d9fdb46SRobert Mustacchi     }
502*4d9fdb46SRobert Mustacchi     if (is_mach_o_magic(&h,endian,offsetsize)) {
503*4d9fdb46SRobert Mustacchi         *ftype = DW_FTYPE_MACH_O;
504*4d9fdb46SRobert Mustacchi         *filesize = (size_t)fsize;
505*4d9fdb46SRobert Mustacchi         return DW_DLV_OK;
506*4d9fdb46SRobert Mustacchi     }
507*4d9fdb46SRobert Mustacchi     if (is_archive_magic(&h)) {
508*4d9fdb46SRobert Mustacchi         *ftype = DW_FTYPE_ARCHIVE;
509*4d9fdb46SRobert Mustacchi         *filesize = (size_t)fsize;
510*4d9fdb46SRobert Mustacchi         return DW_DLV_OK;
511*4d9fdb46SRobert Mustacchi     }
512*4d9fdb46SRobert Mustacchi     res = is_pe_object(fd,fsize,endian,offsetsize,errcode);
513*4d9fdb46SRobert Mustacchi     if (res == DW_DLV_OK ) {
514*4d9fdb46SRobert Mustacchi         *ftype = DW_FTYPE_PE;
515*4d9fdb46SRobert Mustacchi         *filesize = (size_t)fsize;
516*4d9fdb46SRobert Mustacchi         return DW_DLV_OK;
517*4d9fdb46SRobert Mustacchi     }
518*4d9fdb46SRobert Mustacchi     /* Check for custom ELF format. */
519*4d9fdb46SRobert Mustacchi #ifdef HAVE_CUSTOM_LIBELF
520*4d9fdb46SRobert Mustacchi     res = elf_is_custom_format(&h,readlen,&fsize,endian,offsetsize,errcode);
521*4d9fdb46SRobert Mustacchi     if (res == DW_DLV_OK) {
522*4d9fdb46SRobert Mustacchi         *ftype = DW_FTYPE_CUSTOM_ELF;
523*4d9fdb46SRobert Mustacchi         *filesize = (size_t)fsize;
524*4d9fdb46SRobert Mustacchi         return res;
525*4d9fdb46SRobert Mustacchi     }
526*4d9fdb46SRobert Mustacchi #endif /* HAVE_CUSTOM_LIBELF */
527*4d9fdb46SRobert Mustacchi 
528*4d9fdb46SRobert Mustacchi     /* Unknown object format. */
529*4d9fdb46SRobert Mustacchi     return DW_DLV_NO_ENTRY;
530*4d9fdb46SRobert Mustacchi }
531*4d9fdb46SRobert Mustacchi 
532*4d9fdb46SRobert Mustacchi int
dwarf_object_detector_path(const char * path,char * outpath,unsigned long outpath_len,unsigned * ftype,unsigned * endian,unsigned * offsetsize,Dwarf_Unsigned * filesize,int * errcode)533*4d9fdb46SRobert Mustacchi dwarf_object_detector_path(const char  *path,
534*4d9fdb46SRobert Mustacchi     char *outpath,unsigned long outpath_len,
535*4d9fdb46SRobert Mustacchi     unsigned *ftype,
536*4d9fdb46SRobert Mustacchi     unsigned *endian,
537*4d9fdb46SRobert Mustacchi     unsigned *offsetsize,
538*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned  *filesize,
539*4d9fdb46SRobert Mustacchi     int *errcode)
540*4d9fdb46SRobert Mustacchi {
541*4d9fdb46SRobert Mustacchi     char *cp = 0;
542*4d9fdb46SRobert Mustacchi     size_t plen = strlen(path);
543*4d9fdb46SRobert Mustacchi     size_t dsprefixlen = sizeof(DSYM_SUFFIX);
544*4d9fdb46SRobert Mustacchi     int fd = -1;
545*4d9fdb46SRobert Mustacchi     int res = 0;
546*4d9fdb46SRobert Mustacchi     int have_outpath = outpath && outpath_len;
547*4d9fdb46SRobert Mustacchi 
548*4d9fdb46SRobert Mustacchi #if !defined(S_ISREG)
549*4d9fdb46SRobert Mustacchi #define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
550*4d9fdb46SRobert Mustacchi #endif
551*4d9fdb46SRobert Mustacchi #if !defined(S_ISDIR)
552*4d9fdb46SRobert Mustacchi #define S_ISDIR(mode) (((mode) & S_IFMT) == S_IFDIR)
553*4d9fdb46SRobert Mustacchi #endif
554*4d9fdb46SRobert Mustacchi 
555*4d9fdb46SRobert Mustacchi     if (have_outpath) {
556*4d9fdb46SRobert Mustacchi         if ((2*plen + dsprefixlen +2) >= outpath_len) {
557*4d9fdb46SRobert Mustacchi             *errcode =  DW_DLE_PATH_SIZE_TOO_SMALL;
558*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
559*4d9fdb46SRobert Mustacchi         }
560*4d9fdb46SRobert Mustacchi         cp = dw_stpcpy(outpath,path);
561*4d9fdb46SRobert Mustacchi         cp = dw_stpcpy(cp,DSYM_SUFFIX);
562*4d9fdb46SRobert Mustacchi         dw_stpcpy(cp,getbasename(path));
563*4d9fdb46SRobert Mustacchi         fd = open(outpath,O_RDONLY|O_BINARY);
564*4d9fdb46SRobert Mustacchi         if (fd < 0) {
565*4d9fdb46SRobert Mustacchi             *outpath = 0;
566*4d9fdb46SRobert Mustacchi             fd = open(path,O_RDONLY|O_BINARY);
567*4d9fdb46SRobert Mustacchi             dw_stpcpy(outpath,path);
568*4d9fdb46SRobert Mustacchi         }
569*4d9fdb46SRobert Mustacchi     } else {
570*4d9fdb46SRobert Mustacchi         fd = open(path,O_RDONLY|O_BINARY);
571*4d9fdb46SRobert Mustacchi     }
572*4d9fdb46SRobert Mustacchi     if (fd < 0) {
573*4d9fdb46SRobert Mustacchi         if (have_outpath) {
574*4d9fdb46SRobert Mustacchi             *outpath = 0;
575*4d9fdb46SRobert Mustacchi         }
576*4d9fdb46SRobert Mustacchi         return DW_DLV_NO_ENTRY;
577*4d9fdb46SRobert Mustacchi     }
578*4d9fdb46SRobert Mustacchi     res = dwarf_object_detector_fd(fd,
579*4d9fdb46SRobert Mustacchi         ftype,endian,offsetsize,filesize,errcode);
580*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK && have_outpath) {
581*4d9fdb46SRobert Mustacchi         *outpath = 0;
582*4d9fdb46SRobert Mustacchi     }
583*4d9fdb46SRobert Mustacchi     close(fd);
584*4d9fdb46SRobert Mustacchi     return res;
585*4d9fdb46SRobert Mustacchi }
586