xref: /illumos-gate/usr/src/lib/libdwarf/common/dwarf_peread.c (revision 4d9fdb46b215739778ebc12079842c9905586999)
1*4d9fdb46SRobert Mustacchi /*
2*4d9fdb46SRobert Mustacchi Copyright (c) 2019, David Anderson 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 
33*4d9fdb46SRobert Mustacchi /*  This file reads the parts of a Windows PE
34*4d9fdb46SRobert Mustacchi     file appropriate to reading DWARF debugging data.
35*4d9fdb46SRobert Mustacchi */
36*4d9fdb46SRobert Mustacchi 
37*4d9fdb46SRobert Mustacchi #ifdef _WIN32
38*4d9fdb46SRobert Mustacchi #define _CRT_SECURE_NO_WARNINGS
39*4d9fdb46SRobert Mustacchi #endif /* _WIN32 */
40*4d9fdb46SRobert Mustacchi 
41*4d9fdb46SRobert Mustacchi #include "config.h"
42*4d9fdb46SRobert Mustacchi #include <stdio.h>
43*4d9fdb46SRobert Mustacchi #ifdef HAVE_MALLOC_H
44*4d9fdb46SRobert Mustacchi /* Useful include for some Windows compilers. */
45*4d9fdb46SRobert Mustacchi #include <malloc.h>
46*4d9fdb46SRobert Mustacchi #endif /* HAVE_MALLOC_H */
47*4d9fdb46SRobert Mustacchi #ifdef HAVE_STDLIB_H
48*4d9fdb46SRobert Mustacchi #include <stdlib.h>
49*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDLIB_H */
50*4d9fdb46SRobert Mustacchi #include <string.h> /* memcpy */
51*4d9fdb46SRobert Mustacchi #include <sys/types.h> /* open() */
52*4d9fdb46SRobert Mustacchi #include <sys/stat.h> /* open() */
53*4d9fdb46SRobert Mustacchi #include <fcntl.h> /* open() */
54*4d9fdb46SRobert Mustacchi #include <time.h>
55*4d9fdb46SRobert Mustacchi #ifdef HAVE_UNISTD_H
56*4d9fdb46SRobert Mustacchi #include <unistd.h> /* lseek read close */
57*4d9fdb46SRobert Mustacchi #elif defined(_WIN32) && defined(_MSC_VER)
58*4d9fdb46SRobert Mustacchi #include <io.h>
59*4d9fdb46SRobert Mustacchi #endif /* HAVE_UNISTD_H */
60*4d9fdb46SRobert Mustacchi 
61*4d9fdb46SRobert Mustacchi /* Windows specific header files */
62*4d9fdb46SRobert Mustacchi #if defined(_WIN32) && defined(HAVE_STDAFX_H)
63*4d9fdb46SRobert Mustacchi #include "stdafx.h"
64*4d9fdb46SRobert Mustacchi #endif /* HAVE_STDAFX_H */
65*4d9fdb46SRobert Mustacchi 
66*4d9fdb46SRobert Mustacchi #include "libdwarf.h"
67*4d9fdb46SRobert Mustacchi #include "libdwarfdefs.h"
68*4d9fdb46SRobert Mustacchi #include "dwarf_base_types.h"
69*4d9fdb46SRobert Mustacchi #include "dwarf_opaque.h"
70*4d9fdb46SRobert Mustacchi #include "memcpy_swap.h"
71*4d9fdb46SRobert Mustacchi #include "dwarf_error.h" /* for _dwarf_error() declaration */
72*4d9fdb46SRobert Mustacchi #include "dwarf_reading.h"
73*4d9fdb46SRobert Mustacchi #include "dwarf_object_read_common.h"
74*4d9fdb46SRobert Mustacchi #include "dwarf_object_detector.h"
75*4d9fdb46SRobert Mustacchi #include "dwarf_pe_descr.h"
76*4d9fdb46SRobert Mustacchi #include "dwarf_peread.h"
77*4d9fdb46SRobert Mustacchi 
78*4d9fdb46SRobert Mustacchi #ifdef HAVE_UNUSED_ATTRIBUTE
79*4d9fdb46SRobert Mustacchi #define  UNUSEDARG __attribute__ ((unused))
80*4d9fdb46SRobert Mustacchi #else
81*4d9fdb46SRobert Mustacchi #define  UNUSEDARG
82*4d9fdb46SRobert Mustacchi #endif
83*4d9fdb46SRobert Mustacchi 
84*4d9fdb46SRobert Mustacchi #define DOS_HEADER_LEN 64
85*4d9fdb46SRobert Mustacchi 
86*4d9fdb46SRobert Mustacchi #ifndef TYP
87*4d9fdb46SRobert Mustacchi #define TYP(n,l) char n[l]
88*4d9fdb46SRobert Mustacchi #endif /* TYP */
89*4d9fdb46SRobert Mustacchi 
90*4d9fdb46SRobert Mustacchi 
91*4d9fdb46SRobert Mustacchi #ifndef SIZEOFT32
92*4d9fdb46SRobert Mustacchi #define SIZEOFT32 4
93*4d9fdb46SRobert Mustacchi #endif /* SIZEOFT32 */
94*4d9fdb46SRobert Mustacchi 
95*4d9fdb46SRobert Mustacchi static int _dwarf_pe_object_access_init(
96*4d9fdb46SRobert Mustacchi     int  fd,
97*4d9fdb46SRobert Mustacchi     unsigned ftype,
98*4d9fdb46SRobert Mustacchi     unsigned endian,
99*4d9fdb46SRobert Mustacchi     unsigned offsetsize,
100*4d9fdb46SRobert Mustacchi     size_t filesize,
101*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned access,
102*4d9fdb46SRobert Mustacchi     Dwarf_Obj_Access_Interface **binary_interface,
103*4d9fdb46SRobert Mustacchi     int *localerrnum);
104*4d9fdb46SRobert Mustacchi 
105*4d9fdb46SRobert Mustacchi static unsigned long
magic_copy(char * d,unsigned len)106*4d9fdb46SRobert Mustacchi magic_copy(char *d, unsigned len)
107*4d9fdb46SRobert Mustacchi {
108*4d9fdb46SRobert Mustacchi     unsigned i = 0;
109*4d9fdb46SRobert Mustacchi     unsigned long v = 0;
110*4d9fdb46SRobert Mustacchi 
111*4d9fdb46SRobert Mustacchi     v = d[0];
112*4d9fdb46SRobert Mustacchi     for(i = 1 ; i < len; ++i) {
113*4d9fdb46SRobert Mustacchi         v <<= 8;
114*4d9fdb46SRobert Mustacchi         v |=  0xff&d[i];
115*4d9fdb46SRobert Mustacchi     }
116*4d9fdb46SRobert Mustacchi     return v;
117*4d9fdb46SRobert Mustacchi }
118*4d9fdb46SRobert Mustacchi 
119*4d9fdb46SRobert Mustacchi #ifdef WORDS_BIGENDIAN
120*4d9fdb46SRobert Mustacchi #define ASNAR(func,t,s)                         \
121*4d9fdb46SRobert Mustacchi     do {                                        \
122*4d9fdb46SRobert Mustacchi         unsigned tbyte = sizeof(t) - sizeof(s); \
123*4d9fdb46SRobert Mustacchi         t = 0;                                  \
124*4d9fdb46SRobert Mustacchi         func(((char *)&t)+tbyte ,&s[0],sizeof(s));  \
125*4d9fdb46SRobert Mustacchi     } while (0)
126*4d9fdb46SRobert Mustacchi #else /* LITTLE ENDIAN */
127*4d9fdb46SRobert Mustacchi #define ASNAR(func,t,s)                         \
128*4d9fdb46SRobert Mustacchi     do {                                        \
129*4d9fdb46SRobert Mustacchi         t = 0;                                  \
130*4d9fdb46SRobert Mustacchi         func(&t,&s[0],sizeof(s));               \
131*4d9fdb46SRobert Mustacchi     } while (0)
132*4d9fdb46SRobert Mustacchi #endif /* end LITTLE- BIG-ENDIAN */
133*4d9fdb46SRobert Mustacchi 
134*4d9fdb46SRobert Mustacchi /*  name_array is 8 byte string */
135*4d9fdb46SRobert Mustacchi static int
pe_section_name_get(dwarf_pe_object_access_internals_t * pep,const char * name_array,const char ** name_out,int * errcode)136*4d9fdb46SRobert Mustacchi pe_section_name_get(dwarf_pe_object_access_internals_t *pep,
137*4d9fdb46SRobert Mustacchi     const char *name_array,
138*4d9fdb46SRobert Mustacchi     const char ** name_out,
139*4d9fdb46SRobert Mustacchi     int *errcode)
140*4d9fdb46SRobert Mustacchi {
141*4d9fdb46SRobert Mustacchi 
142*4d9fdb46SRobert Mustacchi     if (name_array[0] == '/') {
143*4d9fdb46SRobert Mustacchi         long v = 0;
144*4d9fdb46SRobert Mustacchi         unsigned long u = 0;
145*4d9fdb46SRobert Mustacchi         const char *s = 0;
146*4d9fdb46SRobert Mustacchi         char temp_array[9];
147*4d9fdb46SRobert Mustacchi 
148*4d9fdb46SRobert Mustacchi         memcpy(temp_array,name_array+1,7);
149*4d9fdb46SRobert Mustacchi         temp_array[7] = 0;
150*4d9fdb46SRobert Mustacchi         v = atoi(temp_array);
151*4d9fdb46SRobert Mustacchi         if (v < 0) {
152*4d9fdb46SRobert Mustacchi             *errcode = DW_DLE_STRING_OFFSET_BAD;
153*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
154*4d9fdb46SRobert Mustacchi         }
155*4d9fdb46SRobert Mustacchi         u = v;
156*4d9fdb46SRobert Mustacchi         if (u > pep->pe_string_table_size) {
157*4d9fdb46SRobert Mustacchi             *errcode = DW_DLE_STRING_OFFSET_BAD;
158*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
159*4d9fdb46SRobert Mustacchi         }
160*4d9fdb46SRobert Mustacchi         s = pep->pe_string_table +u;
161*4d9fdb46SRobert Mustacchi         *name_out = s;
162*4d9fdb46SRobert Mustacchi         return DW_DLV_OK;
163*4d9fdb46SRobert Mustacchi     }
164*4d9fdb46SRobert Mustacchi     *name_out = name_array;
165*4d9fdb46SRobert Mustacchi     return DW_DLV_OK;
166*4d9fdb46SRobert Mustacchi }
167*4d9fdb46SRobert Mustacchi 
168*4d9fdb46SRobert Mustacchi 
169*4d9fdb46SRobert Mustacchi static Dwarf_Endianness
pe_get_byte_order(void * obj)170*4d9fdb46SRobert Mustacchi pe_get_byte_order (void *obj)
171*4d9fdb46SRobert Mustacchi {
172*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep =
173*4d9fdb46SRobert Mustacchi         (dwarf_pe_object_access_internals_t*)(obj);
174*4d9fdb46SRobert Mustacchi     return pep->pe_endian;
175*4d9fdb46SRobert Mustacchi }
176*4d9fdb46SRobert Mustacchi 
177*4d9fdb46SRobert Mustacchi 
178*4d9fdb46SRobert Mustacchi static Dwarf_Small
pe_get_length_size(void * obj)179*4d9fdb46SRobert Mustacchi pe_get_length_size (void *obj)
180*4d9fdb46SRobert Mustacchi {
181*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep =
182*4d9fdb46SRobert Mustacchi         (dwarf_pe_object_access_internals_t*)(obj);
183*4d9fdb46SRobert Mustacchi     return pep->pe_offsetsize/8;
184*4d9fdb46SRobert Mustacchi }
185*4d9fdb46SRobert Mustacchi 
186*4d9fdb46SRobert Mustacchi static Dwarf_Small
pe_get_pointer_size(void * obj)187*4d9fdb46SRobert Mustacchi pe_get_pointer_size (void *obj)
188*4d9fdb46SRobert Mustacchi {
189*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep =
190*4d9fdb46SRobert Mustacchi         (dwarf_pe_object_access_internals_t*)(obj);
191*4d9fdb46SRobert Mustacchi     return pep->pe_pointersize/8;
192*4d9fdb46SRobert Mustacchi }
193*4d9fdb46SRobert Mustacchi 
194*4d9fdb46SRobert Mustacchi 
195*4d9fdb46SRobert Mustacchi static Dwarf_Unsigned
pe_get_section_count(void * obj)196*4d9fdb46SRobert Mustacchi pe_get_section_count (void *obj)
197*4d9fdb46SRobert Mustacchi {
198*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep =
199*4d9fdb46SRobert Mustacchi         (dwarf_pe_object_access_internals_t*)(obj);
200*4d9fdb46SRobert Mustacchi     return pep->pe_section_count;
201*4d9fdb46SRobert Mustacchi }
202*4d9fdb46SRobert Mustacchi 
203*4d9fdb46SRobert Mustacchi static int
pe_get_section_info(void * obj,Dwarf_Half section_index,Dwarf_Obj_Access_Section * return_section,UNUSEDARG int * error)204*4d9fdb46SRobert Mustacchi pe_get_section_info (void *obj,
205*4d9fdb46SRobert Mustacchi     Dwarf_Half section_index,
206*4d9fdb46SRobert Mustacchi     Dwarf_Obj_Access_Section *return_section,
207*4d9fdb46SRobert Mustacchi     UNUSEDARG int *error)
208*4d9fdb46SRobert Mustacchi {
209*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep =
210*4d9fdb46SRobert Mustacchi         (dwarf_pe_object_access_internals_t*)(obj);
211*4d9fdb46SRobert Mustacchi 
212*4d9fdb46SRobert Mustacchi 
213*4d9fdb46SRobert Mustacchi     if (section_index < pep->pe_section_count) {
214*4d9fdb46SRobert Mustacchi         struct dwarf_pe_generic_image_section_header *sp = 0;
215*4d9fdb46SRobert Mustacchi         sp = pep->pe_sectionptr + section_index;
216*4d9fdb46SRobert Mustacchi         return_section->addr = pep->pe_OptionalHeader.ImageBase +
217*4d9fdb46SRobert Mustacchi             sp->VirtualAddress; ;
218*4d9fdb46SRobert Mustacchi         return_section->type = 0;
219*4d9fdb46SRobert Mustacchi         /*  SizeOfRawData can be rounded or truncated,
220*4d9fdb46SRobert Mustacchi             use VirtualSize for the real analog of Elf
221*4d9fdb46SRobert Mustacchi             section size. */
222*4d9fdb46SRobert Mustacchi         return_section->size = sp->VirtualSize;
223*4d9fdb46SRobert Mustacchi         return_section->name = sp->dwarfsectname;
224*4d9fdb46SRobert Mustacchi         return_section->link = 0;
225*4d9fdb46SRobert Mustacchi         return_section->info = 0;
226*4d9fdb46SRobert Mustacchi         return_section->entrysize = 0;
227*4d9fdb46SRobert Mustacchi         return DW_DLV_OK;
228*4d9fdb46SRobert Mustacchi     }
229*4d9fdb46SRobert Mustacchi     return DW_DLV_NO_ENTRY;
230*4d9fdb46SRobert Mustacchi }
231*4d9fdb46SRobert Mustacchi 
232*4d9fdb46SRobert Mustacchi 
233*4d9fdb46SRobert Mustacchi static int
load_optional_header32(dwarf_pe_object_access_internals_t * pep,Dwarf_Unsigned offset,int * errcode)234*4d9fdb46SRobert Mustacchi load_optional_header32(dwarf_pe_object_access_internals_t *pep,
235*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned offset, int*errcode)
236*4d9fdb46SRobert Mustacchi {
237*4d9fdb46SRobert Mustacchi     int res = 0;
238*4d9fdb46SRobert Mustacchi     IMAGE_OPTIONAL_HEADER32_dw hdr;
239*4d9fdb46SRobert Mustacchi 
240*4d9fdb46SRobert Mustacchi     pep->pe_optional_header_size = sizeof(IMAGE_OPTIONAL_HEADER32_dw);
241*4d9fdb46SRobert Mustacchi 
242*4d9fdb46SRobert Mustacchi     if ((pep->pe_optional_header_size + offset) >
243*4d9fdb46SRobert Mustacchi         pep->pe_filesize) {
244*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_TOO_SMALL;
245*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
246*4d9fdb46SRobert Mustacchi     }
247*4d9fdb46SRobert Mustacchi 
248*4d9fdb46SRobert Mustacchi     res =  _dwarf_object_read_random(pep->pe_fd,
249*4d9fdb46SRobert Mustacchi         (char *)&hdr,
250*4d9fdb46SRobert Mustacchi         (off_t)offset, sizeof(IMAGE_OPTIONAL_HEADER32_dw),
251*4d9fdb46SRobert Mustacchi         (off_t)pep->pe_filesize,
252*4d9fdb46SRobert Mustacchi         errcode);
253*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
254*4d9fdb46SRobert Mustacchi         return res;
255*4d9fdb46SRobert Mustacchi     }
256*4d9fdb46SRobert Mustacchi 
257*4d9fdb46SRobert Mustacchi     /* This is a subset of fields. */
258*4d9fdb46SRobert Mustacchi     ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.Magic,
259*4d9fdb46SRobert Mustacchi         hdr.Magic);
260*4d9fdb46SRobert Mustacchi     pep->pe_OptionalHeader.MajorLinkerVersion= hdr.MajorLinkerVersion;
261*4d9fdb46SRobert Mustacchi     pep->pe_OptionalHeader.MinorLinkerVersion= hdr.MinorLinkerVersion;
262*4d9fdb46SRobert Mustacchi     ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.ImageBase,
263*4d9fdb46SRobert Mustacchi         hdr.ImageBase);
264*4d9fdb46SRobert Mustacchi     ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfCode,
265*4d9fdb46SRobert Mustacchi         hdr.SizeOfCode);
266*4d9fdb46SRobert Mustacchi     ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfImage,
267*4d9fdb46SRobert Mustacchi         hdr.SizeOfImage);
268*4d9fdb46SRobert Mustacchi     ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfHeaders,
269*4d9fdb46SRobert Mustacchi         hdr.SizeOfHeaders);
270*4d9fdb46SRobert Mustacchi     pep->pe_OptionalHeader.SizeOfDataDirEntry =
271*4d9fdb46SRobert Mustacchi         sizeof(IMAGE_DATA_DIRECTORY_dw);
272*4d9fdb46SRobert Mustacchi     return DW_DLV_OK;
273*4d9fdb46SRobert Mustacchi }
274*4d9fdb46SRobert Mustacchi static int
load_optional_header64(dwarf_pe_object_access_internals_t * pep,Dwarf_Unsigned offset,int * errcode)275*4d9fdb46SRobert Mustacchi load_optional_header64(dwarf_pe_object_access_internals_t *pep,
276*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned offset, int*errcode )
277*4d9fdb46SRobert Mustacchi {
278*4d9fdb46SRobert Mustacchi     IMAGE_OPTIONAL_HEADER64_dw hdr;
279*4d9fdb46SRobert Mustacchi     int res = 0;
280*4d9fdb46SRobert Mustacchi 
281*4d9fdb46SRobert Mustacchi     pep->pe_optional_header_size = sizeof(IMAGE_OPTIONAL_HEADER64_dw);
282*4d9fdb46SRobert Mustacchi     if ((pep->pe_optional_header_size + offset) >
283*4d9fdb46SRobert Mustacchi         pep->pe_filesize) {
284*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_TOO_SMALL;
285*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
286*4d9fdb46SRobert Mustacchi     }
287*4d9fdb46SRobert Mustacchi     res =  _dwarf_object_read_random(pep->pe_fd,
288*4d9fdb46SRobert Mustacchi         (char *)&hdr,
289*4d9fdb46SRobert Mustacchi         (off_t)offset, sizeof(IMAGE_OPTIONAL_HEADER64_dw),
290*4d9fdb46SRobert Mustacchi         (off_t)pep->pe_filesize,
291*4d9fdb46SRobert Mustacchi         errcode);
292*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
293*4d9fdb46SRobert Mustacchi         return res;
294*4d9fdb46SRobert Mustacchi     }
295*4d9fdb46SRobert Mustacchi 
296*4d9fdb46SRobert Mustacchi     /* This is a subset of fields. */
297*4d9fdb46SRobert Mustacchi     ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.Magic,
298*4d9fdb46SRobert Mustacchi         hdr.Magic);
299*4d9fdb46SRobert Mustacchi     pep->pe_OptionalHeader.MajorLinkerVersion= hdr.MajorLinkerVersion;
300*4d9fdb46SRobert Mustacchi     pep->pe_OptionalHeader.MinorLinkerVersion= hdr.MinorLinkerVersion;
301*4d9fdb46SRobert Mustacchi     ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfCode,
302*4d9fdb46SRobert Mustacchi         hdr.SizeOfCode);
303*4d9fdb46SRobert Mustacchi     ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfImage,
304*4d9fdb46SRobert Mustacchi         hdr.SizeOfImage);
305*4d9fdb46SRobert Mustacchi     ASNAR(pep->pe_copy_word,pep->pe_OptionalHeader.SizeOfHeaders,
306*4d9fdb46SRobert Mustacchi         hdr.SizeOfHeaders);
307*4d9fdb46SRobert Mustacchi     pep->pe_OptionalHeader.SizeOfDataDirEntry =
308*4d9fdb46SRobert Mustacchi         sizeof(IMAGE_DATA_DIRECTORY_dw);
309*4d9fdb46SRobert Mustacchi     return DW_DLV_OK;
310*4d9fdb46SRobert Mustacchi }
311*4d9fdb46SRobert Mustacchi 
312*4d9fdb46SRobert Mustacchi static int
pe_load_section(void * obj,Dwarf_Half section_index,Dwarf_Small ** return_data,int * error)313*4d9fdb46SRobert Mustacchi pe_load_section (void *obj, Dwarf_Half section_index,
314*4d9fdb46SRobert Mustacchi     Dwarf_Small **return_data, int *error)
315*4d9fdb46SRobert Mustacchi {
316*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep =
317*4d9fdb46SRobert Mustacchi         (dwarf_pe_object_access_internals_t*)(obj);
318*4d9fdb46SRobert Mustacchi 
319*4d9fdb46SRobert Mustacchi     if (0 < section_index &&
320*4d9fdb46SRobert Mustacchi         section_index < pep->pe_section_count) {
321*4d9fdb46SRobert Mustacchi         int res = 0;
322*4d9fdb46SRobert Mustacchi         struct dwarf_pe_generic_image_section_header *sp =
323*4d9fdb46SRobert Mustacchi             pep->pe_sectionptr + section_index;
324*4d9fdb46SRobert Mustacchi         Dwarf_Unsigned read_length = 0;
325*4d9fdb46SRobert Mustacchi 
326*4d9fdb46SRobert Mustacchi         if(sp->loaded_data) {
327*4d9fdb46SRobert Mustacchi             *return_data = sp->loaded_data;
328*4d9fdb46SRobert Mustacchi             return DW_DLV_OK;
329*4d9fdb46SRobert Mustacchi         }
330*4d9fdb46SRobert Mustacchi         if (!sp->VirtualSize) {
331*4d9fdb46SRobert Mustacchi             return DW_DLV_NO_ENTRY;
332*4d9fdb46SRobert Mustacchi         }
333*4d9fdb46SRobert Mustacchi         read_length = sp->SizeOfRawData;
334*4d9fdb46SRobert Mustacchi         if(sp->VirtualSize < read_length) {
335*4d9fdb46SRobert Mustacchi             /* Don't read padding that wasn't allocated in memory */
336*4d9fdb46SRobert Mustacchi             read_length = sp->VirtualSize;
337*4d9fdb46SRobert Mustacchi         }
338*4d9fdb46SRobert Mustacchi         if ((read_length + sp->PointerToRawData) >
339*4d9fdb46SRobert Mustacchi             pep->pe_filesize) {
340*4d9fdb46SRobert Mustacchi             *error = DW_DLE_FILE_TOO_SMALL;
341*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
342*4d9fdb46SRobert Mustacchi         }
343*4d9fdb46SRobert Mustacchi         sp->loaded_data = malloc((size_t)sp->SizeOfRawData);
344*4d9fdb46SRobert Mustacchi         if(!sp->loaded_data) {
345*4d9fdb46SRobert Mustacchi             *error = DW_DLE_ALLOC_FAIL;
346*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
347*4d9fdb46SRobert Mustacchi         }
348*4d9fdb46SRobert Mustacchi         res = _dwarf_object_read_random(pep->pe_fd,
349*4d9fdb46SRobert Mustacchi             (char *)sp->loaded_data,
350*4d9fdb46SRobert Mustacchi             (off_t)sp->PointerToRawData, (size_t)read_length,
351*4d9fdb46SRobert Mustacchi             (off_t)pep->pe_filesize,
352*4d9fdb46SRobert Mustacchi             error);
353*4d9fdb46SRobert Mustacchi         if (res != DW_DLV_OK) {
354*4d9fdb46SRobert Mustacchi             free(sp->loaded_data);
355*4d9fdb46SRobert Mustacchi             sp->loaded_data = 0;
356*4d9fdb46SRobert Mustacchi             return res;
357*4d9fdb46SRobert Mustacchi         }
358*4d9fdb46SRobert Mustacchi         if(sp->VirtualSize > read_length) {
359*4d9fdb46SRobert Mustacchi             /*  Zero space that was allocated but
360*4d9fdb46SRobert Mustacchi                 truncated from the file */
361*4d9fdb46SRobert Mustacchi             memset(sp->loaded_data + read_length, 0,
362*4d9fdb46SRobert Mustacchi                 (size_t)(sp->VirtualSize - read_length));
363*4d9fdb46SRobert Mustacchi         }
364*4d9fdb46SRobert Mustacchi         *return_data = sp->loaded_data;
365*4d9fdb46SRobert Mustacchi         return DW_DLV_OK;
366*4d9fdb46SRobert Mustacchi     }
367*4d9fdb46SRobert Mustacchi     return DW_DLV_NO_ENTRY;
368*4d9fdb46SRobert Mustacchi }
369*4d9fdb46SRobert Mustacchi 
370*4d9fdb46SRobert Mustacchi void
_dwarf_destruct_pe_access(struct Dwarf_Obj_Access_Interface_s * aip)371*4d9fdb46SRobert Mustacchi _dwarf_destruct_pe_access(
372*4d9fdb46SRobert Mustacchi     struct Dwarf_Obj_Access_Interface_s *aip)
373*4d9fdb46SRobert Mustacchi {
374*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep = 0;
375*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned i = 0;
376*4d9fdb46SRobert Mustacchi 
377*4d9fdb46SRobert Mustacchi     if (!aip) {
378*4d9fdb46SRobert Mustacchi         return;
379*4d9fdb46SRobert Mustacchi     }
380*4d9fdb46SRobert Mustacchi     pep = (dwarf_pe_object_access_internals_t*)(aip->object);
381*4d9fdb46SRobert Mustacchi     if (pep->pe_destruct_close_fd) {
382*4d9fdb46SRobert Mustacchi         close(pep->pe_fd);
383*4d9fdb46SRobert Mustacchi         pep->pe_fd = -1;
384*4d9fdb46SRobert Mustacchi     }
385*4d9fdb46SRobert Mustacchi     free((char *)pep->pe_path);
386*4d9fdb46SRobert Mustacchi     pep->pe_path = 0;
387*4d9fdb46SRobert Mustacchi     if (pep->pe_sectionptr) {
388*4d9fdb46SRobert Mustacchi         struct dwarf_pe_generic_image_section_header  *sp = 0;
389*4d9fdb46SRobert Mustacchi 
390*4d9fdb46SRobert Mustacchi         sp = pep->pe_sectionptr;
391*4d9fdb46SRobert Mustacchi         for( i=0; i < pep->pe_section_count; ++i,++sp) {
392*4d9fdb46SRobert Mustacchi             if (sp->loaded_data) {
393*4d9fdb46SRobert Mustacchi                 free(sp->loaded_data);
394*4d9fdb46SRobert Mustacchi                 sp->loaded_data = 0;
395*4d9fdb46SRobert Mustacchi             }
396*4d9fdb46SRobert Mustacchi             free(sp->name);
397*4d9fdb46SRobert Mustacchi             sp->name = 0;
398*4d9fdb46SRobert Mustacchi             free(sp->dwarfsectname);
399*4d9fdb46SRobert Mustacchi             sp->dwarfsectname = 0;
400*4d9fdb46SRobert Mustacchi         }
401*4d9fdb46SRobert Mustacchi         free(pep->pe_sectionptr);
402*4d9fdb46SRobert Mustacchi         pep->pe_section_count = 0;
403*4d9fdb46SRobert Mustacchi     }
404*4d9fdb46SRobert Mustacchi     free(pep->pe_string_table);
405*4d9fdb46SRobert Mustacchi     pep->pe_string_table = 0;
406*4d9fdb46SRobert Mustacchi     free(pep);
407*4d9fdb46SRobert Mustacchi     free(aip);
408*4d9fdb46SRobert Mustacchi     return;
409*4d9fdb46SRobert Mustacchi }
410*4d9fdb46SRobert Mustacchi 
411*4d9fdb46SRobert Mustacchi 
412*4d9fdb46SRobert Mustacchi static int
dwarf_pe_load_dwarf_section_headers(dwarf_pe_object_access_internals_t * pep,int * errcode)413*4d9fdb46SRobert Mustacchi dwarf_pe_load_dwarf_section_headers(
414*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep,int *errcode)
415*4d9fdb46SRobert Mustacchi {
416*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned i = 0;
417*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned input_count =
418*4d9fdb46SRobert Mustacchi         pep->pe_FileHeader.NumberOfSections;
419*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned offset_in_input = pep->pe_section_table_offset;
420*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned section_hdr_size = sizeof(IMAGE_SECTION_HEADER_dw);
421*4d9fdb46SRobert Mustacchi     struct dwarf_pe_generic_image_section_header *sec_outp = 0;
422*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned cur_offset = offset_in_input;
423*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned past_end_hdrs = offset_in_input +
424*4d9fdb46SRobert Mustacchi         section_hdr_size*input_count;
425*4d9fdb46SRobert Mustacchi 
426*4d9fdb46SRobert Mustacchi     /* internal sections include null initial section */
427*4d9fdb46SRobert Mustacchi     pep->pe_section_count = input_count+1;
428*4d9fdb46SRobert Mustacchi 
429*4d9fdb46SRobert Mustacchi     if (past_end_hdrs > pep->pe_filesize) {
430*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_TOO_SMALL;
431*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
432*4d9fdb46SRobert Mustacchi     }
433*4d9fdb46SRobert Mustacchi 
434*4d9fdb46SRobert Mustacchi     if (!offset_in_input) {
435*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_PE_OFFSET_BAD;
436*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
437*4d9fdb46SRobert Mustacchi     }
438*4d9fdb46SRobert Mustacchi     pep->pe_sectionptr =
439*4d9fdb46SRobert Mustacchi         (struct dwarf_pe_generic_image_section_header * )
440*4d9fdb46SRobert Mustacchi         calloc((size_t)pep->pe_section_count,
441*4d9fdb46SRobert Mustacchi         sizeof(struct dwarf_pe_generic_image_section_header));
442*4d9fdb46SRobert Mustacchi 
443*4d9fdb46SRobert Mustacchi 
444*4d9fdb46SRobert Mustacchi 
445*4d9fdb46SRobert Mustacchi     if (!pep->pe_sectionptr) {
446*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_ALLOC_FAIL;
447*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
448*4d9fdb46SRobert Mustacchi     }
449*4d9fdb46SRobert Mustacchi     sec_outp = pep->pe_sectionptr;
450*4d9fdb46SRobert Mustacchi     sec_outp->name = strdup("");
451*4d9fdb46SRobert Mustacchi     sec_outp->dwarfsectname = strdup("");
452*4d9fdb46SRobert Mustacchi     sec_outp++;
453*4d9fdb46SRobert Mustacchi     for ( ;  i < input_count;
454*4d9fdb46SRobert Mustacchi         ++i, cur_offset += section_hdr_size, sec_outp++) {
455*4d9fdb46SRobert Mustacchi 
456*4d9fdb46SRobert Mustacchi         int res = 0;
457*4d9fdb46SRobert Mustacchi         IMAGE_SECTION_HEADER_dw filesect;
458*4d9fdb46SRobert Mustacchi         char safe_name[IMAGE_SIZEOF_SHORT_NAME +1];
459*4d9fdb46SRobert Mustacchi         const char *expname = 0;
460*4d9fdb46SRobert Mustacchi 
461*4d9fdb46SRobert Mustacchi         res =  _dwarf_object_read_random(pep->pe_fd,
462*4d9fdb46SRobert Mustacchi             (char *)&filesect,(off_t)cur_offset,
463*4d9fdb46SRobert Mustacchi             sizeof(filesect),
464*4d9fdb46SRobert Mustacchi             (off_t)pep->pe_filesize,
465*4d9fdb46SRobert Mustacchi             errcode);
466*4d9fdb46SRobert Mustacchi         if (res != DW_DLV_OK) {
467*4d9fdb46SRobert Mustacchi             return res;
468*4d9fdb46SRobert Mustacchi         }
469*4d9fdb46SRobert Mustacchi         /*  The following is safe. filesect.Name is
470*4d9fdb46SRobert Mustacchi             IMAGE_SIZEOF_SHORT_NAME bytes long and may
471*4d9fdb46SRobert Mustacchi             not (not sure) have a NUL terminator. */
472*4d9fdb46SRobert Mustacchi         strncpy(safe_name,filesect.Name,IMAGE_SIZEOF_SHORT_NAME);
473*4d9fdb46SRobert Mustacchi         /*  Then add NUL terminator. */
474*4d9fdb46SRobert Mustacchi         safe_name[IMAGE_SIZEOF_SHORT_NAME] = 0;
475*4d9fdb46SRobert Mustacchi         sec_outp->name = strdup(safe_name);
476*4d9fdb46SRobert Mustacchi         res = pe_section_name_get(pep,
477*4d9fdb46SRobert Mustacchi             safe_name,&expname,errcode);
478*4d9fdb46SRobert Mustacchi         if (res != DW_DLV_OK) {
479*4d9fdb46SRobert Mustacchi             return res;
480*4d9fdb46SRobert Mustacchi         }
481*4d9fdb46SRobert Mustacchi         sec_outp->dwarfsectname = strdup(expname);
482*4d9fdb46SRobert Mustacchi 
483*4d9fdb46SRobert Mustacchi         if ( !sec_outp->name || !sec_outp->dwarfsectname) {
484*4d9fdb46SRobert Mustacchi             *errcode = DW_DLE_ALLOC_FAIL;
485*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
486*4d9fdb46SRobert Mustacchi         }
487*4d9fdb46SRobert Mustacchi         sec_outp->SecHeaderOffset = cur_offset;
488*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,sec_outp->VirtualSize,
489*4d9fdb46SRobert Mustacchi             filesect.Misc.VirtualSize);
490*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,sec_outp->VirtualAddress,
491*4d9fdb46SRobert Mustacchi             filesect.VirtualAddress);
492*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,sec_outp->SizeOfRawData,
493*4d9fdb46SRobert Mustacchi             filesect.SizeOfRawData);
494*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,sec_outp->PointerToRawData,
495*4d9fdb46SRobert Mustacchi             filesect.PointerToRawData);
496*4d9fdb46SRobert Mustacchi         if(sec_outp->SizeOfRawData > pep->pe_filesize ||
497*4d9fdb46SRobert Mustacchi             sec_outp->PointerToRawData > pep->pe_filesize ||
498*4d9fdb46SRobert Mustacchi             (sec_outp->SizeOfRawData+
499*4d9fdb46SRobert Mustacchi                 sec_outp->PointerToRawData > pep->pe_filesize)) {
500*4d9fdb46SRobert Mustacchi             *errcode = DW_DLE_FILE_TOO_SMALL;
501*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
502*4d9fdb46SRobert Mustacchi         }
503*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,sec_outp->PointerToRelocations,
504*4d9fdb46SRobert Mustacchi             filesect.PointerToRelocations);
505*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,sec_outp->PointerToLinenumbers,
506*4d9fdb46SRobert Mustacchi             filesect.PointerToLinenumbers);
507*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,sec_outp->NumberOfRelocations,
508*4d9fdb46SRobert Mustacchi             filesect.NumberOfRelocations);
509*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,sec_outp->NumberOfLinenumbers,
510*4d9fdb46SRobert Mustacchi             filesect.NumberOfLinenumbers);
511*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,sec_outp->Characteristics,
512*4d9fdb46SRobert Mustacchi             filesect.Characteristics);
513*4d9fdb46SRobert Mustacchi         /* sec_outp->loaded data set when we load a section */
514*4d9fdb46SRobert Mustacchi     }
515*4d9fdb46SRobert Mustacchi     return DW_DLV_OK;
516*4d9fdb46SRobert Mustacchi }
517*4d9fdb46SRobert Mustacchi 
518*4d9fdb46SRobert Mustacchi 
519*4d9fdb46SRobert Mustacchi static int
dwarf_load_pe_sections(dwarf_pe_object_access_internals_t * pep,int * errcode)520*4d9fdb46SRobert Mustacchi dwarf_load_pe_sections(
521*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep,int *errcode)
522*4d9fdb46SRobert Mustacchi {
523*4d9fdb46SRobert Mustacchi     struct dos_header_dw dhinmem;
524*4d9fdb46SRobert Mustacchi     IMAGE_FILE_HEADER_dw ifh;
525*4d9fdb46SRobert Mustacchi     void (*word_swap) (void *, const void *, unsigned long);
526*4d9fdb46SRobert Mustacchi     unsigned locendian = 0;
527*4d9fdb46SRobert Mustacchi     int res = 0;
528*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned dos_sig = 0;
529*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned nt_address = 0;
530*4d9fdb46SRobert Mustacchi     char nt_sig_array[4];
531*4d9fdb46SRobert Mustacchi     unsigned long nt_signature = 0;
532*4d9fdb46SRobert Mustacchi 
533*4d9fdb46SRobert Mustacchi     if ( (sizeof(ifh) + sizeof(dhinmem))  >= pep->pe_filesize) {
534*4d9fdb46SRobert Mustacchi         /* corrupt object. */
535*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_PE_SIZE_SMALL;
536*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
537*4d9fdb46SRobert Mustacchi     }
538*4d9fdb46SRobert Mustacchi     res = _dwarf_object_read_random(pep->pe_fd,(char *)&dhinmem,
539*4d9fdb46SRobert Mustacchi         0, sizeof(dhinmem),(off_t)pep->pe_filesize, errcode);
540*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
541*4d9fdb46SRobert Mustacchi         return res;
542*4d9fdb46SRobert Mustacchi     }
543*4d9fdb46SRobert Mustacchi     dos_sig = magic_copy((char *)dhinmem.dh_mz,
544*4d9fdb46SRobert Mustacchi         sizeof(dhinmem.dh_mz));
545*4d9fdb46SRobert Mustacchi     if (dos_sig == IMAGE_DOS_SIGNATURE_dw) {
546*4d9fdb46SRobert Mustacchi         /*  IMAGE_DOS_SIGNATURE_dw assumes bytes reversed by little-endian
547*4d9fdb46SRobert Mustacchi             load, so we intrepet a match the other way. */
548*4d9fdb46SRobert Mustacchi         /* BIG ENDIAN. From looking at hex characters in object  */
549*4d9fdb46SRobert Mustacchi #ifdef WORDS_BIGENDIAN
550*4d9fdb46SRobert Mustacchi         word_swap = _dwarf_memcpy_noswap_bytes;
551*4d9fdb46SRobert Mustacchi #else  /* LITTLE ENDIAN */
552*4d9fdb46SRobert Mustacchi         word_swap = _dwarf_memcpy_swap_bytes;
553*4d9fdb46SRobert Mustacchi #endif /* LITTLE- BIG-ENDIAN */
554*4d9fdb46SRobert Mustacchi         locendian = DW_OBJECT_MSB;
555*4d9fdb46SRobert Mustacchi     } else if (dos_sig == IMAGE_DOS_REVSIGNATURE_dw) {
556*4d9fdb46SRobert Mustacchi         /* raw load, so  intrepet a match the other way. */
557*4d9fdb46SRobert Mustacchi         /* LITTLE ENDIAN */
558*4d9fdb46SRobert Mustacchi #ifdef WORDS_BIGENDIAN
559*4d9fdb46SRobert Mustacchi         word_swap = _dwarf_memcpy_swap_bytes;
560*4d9fdb46SRobert Mustacchi #else   /* LITTLE ENDIAN */
561*4d9fdb46SRobert Mustacchi         word_swap = _dwarf_memcpy_noswap_bytes;
562*4d9fdb46SRobert Mustacchi #endif  /* LITTLE- BIG-ENDIAN */
563*4d9fdb46SRobert Mustacchi         locendian = DW_OBJECT_LSB;
564*4d9fdb46SRobert Mustacchi     } else {
565*4d9fdb46SRobert Mustacchi         /* Not dos header not a PE file we recognize */
566*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_WRONG_TYPE;
567*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
568*4d9fdb46SRobert Mustacchi     }
569*4d9fdb46SRobert Mustacchi     if (locendian != pep->pe_endian) {
570*4d9fdb46SRobert Mustacchi         /*  Really this is a coding botch somewhere here,
571*4d9fdb46SRobert Mustacchi             not an object corruption. */
572*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_WRONG_TYPE;
573*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
574*4d9fdb46SRobert Mustacchi     }
575*4d9fdb46SRobert Mustacchi     pep->pe_copy_word = word_swap;
576*4d9fdb46SRobert Mustacchi     ASNAR(word_swap,nt_address,dhinmem.dh_image_offset);
577*4d9fdb46SRobert Mustacchi     if (pep->pe_filesize < (nt_address + sizeof(nt_sig_array))) {
578*4d9fdb46SRobert Mustacchi         /*  The nt_address is really a file offset. */
579*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_TOO_SMALL;
580*4d9fdb46SRobert Mustacchi         /* Not dos header not a PE file we recognize */
581*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
582*4d9fdb46SRobert Mustacchi     }
583*4d9fdb46SRobert Mustacchi 
584*4d9fdb46SRobert Mustacchi     res =  _dwarf_object_read_random(pep->pe_fd,
585*4d9fdb46SRobert Mustacchi         (char *)&nt_sig_array[0],
586*4d9fdb46SRobert Mustacchi         (off_t)nt_address, sizeof(nt_sig_array),
587*4d9fdb46SRobert Mustacchi         (off_t)pep->pe_filesize,errcode);
588*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
589*4d9fdb46SRobert Mustacchi         return res;
590*4d9fdb46SRobert Mustacchi     }
591*4d9fdb46SRobert Mustacchi     {   unsigned long lsig = 0;
592*4d9fdb46SRobert Mustacchi 
593*4d9fdb46SRobert Mustacchi         ASNAR(word_swap,lsig,nt_sig_array);
594*4d9fdb46SRobert Mustacchi         nt_signature = lsig;
595*4d9fdb46SRobert Mustacchi     }
596*4d9fdb46SRobert Mustacchi     if (nt_signature != IMAGE_NT_SIGNATURE_dw) {
597*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_WRONG_TYPE;
598*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
599*4d9fdb46SRobert Mustacchi     }
600*4d9fdb46SRobert Mustacchi 
601*4d9fdb46SRobert Mustacchi     pep->pe_nt_header_offset = nt_address  + SIZEOFT32;
602*4d9fdb46SRobert Mustacchi     if (pep->pe_filesize < (pep->pe_nt_header_offset +
603*4d9fdb46SRobert Mustacchi         sizeof(ifh))) {
604*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_FILE_TOO_SMALL;
605*4d9fdb46SRobert Mustacchi         /* Not image header not a PE file we recognize */
606*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
607*4d9fdb46SRobert Mustacchi     }
608*4d9fdb46SRobert Mustacchi     res = _dwarf_object_read_random(pep->pe_fd,(char *)&ifh,
609*4d9fdb46SRobert Mustacchi         (off_t)pep->pe_nt_header_offset, sizeof(ifh),
610*4d9fdb46SRobert Mustacchi         (off_t)pep->pe_filesize,errcode);
611*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
612*4d9fdb46SRobert Mustacchi         return res;
613*4d9fdb46SRobert Mustacchi     }
614*4d9fdb46SRobert Mustacchi     ASNAR(word_swap,pep->pe_FileHeader.Machine,ifh.Machine);
615*4d9fdb46SRobert Mustacchi     ASNAR(word_swap,pep->pe_FileHeader.NumberOfSections,
616*4d9fdb46SRobert Mustacchi         ifh.NumberOfSections);
617*4d9fdb46SRobert Mustacchi     ASNAR(word_swap,pep->pe_FileHeader.TimeDateStamp,
618*4d9fdb46SRobert Mustacchi         ifh.TimeDateStamp);
619*4d9fdb46SRobert Mustacchi     ASNAR(word_swap,pep->pe_FileHeader.PointerToSymbolTable,
620*4d9fdb46SRobert Mustacchi         ifh.PointerToSymbolTable);
621*4d9fdb46SRobert Mustacchi     ASNAR(word_swap,pep->pe_FileHeader.NumberOfSymbols,
622*4d9fdb46SRobert Mustacchi         ifh.NumberOfSymbols);
623*4d9fdb46SRobert Mustacchi     ASNAR(word_swap,pep->pe_FileHeader.SizeOfOptionalHeader,
624*4d9fdb46SRobert Mustacchi         ifh.SizeOfOptionalHeader);
625*4d9fdb46SRobert Mustacchi     ASNAR(word_swap,pep->pe_FileHeader.Characteristics,
626*4d9fdb46SRobert Mustacchi         ifh.Characteristics);
627*4d9fdb46SRobert Mustacchi 
628*4d9fdb46SRobert Mustacchi     pep->pe_optional_header_offset = pep->pe_nt_header_offset+
629*4d9fdb46SRobert Mustacchi         sizeof(ifh);
630*4d9fdb46SRobert Mustacchi     if (pep->pe_offsetsize == 32) {
631*4d9fdb46SRobert Mustacchi         res = load_optional_header32(pep,
632*4d9fdb46SRobert Mustacchi             pep->pe_optional_header_offset,errcode);
633*4d9fdb46SRobert Mustacchi         pep->pe_optional_header_size = sizeof(IMAGE_OPTIONAL_HEADER32_dw);
634*4d9fdb46SRobert Mustacchi     } else if (pep->pe_offsetsize == 64) {
635*4d9fdb46SRobert Mustacchi         res = load_optional_header64(pep,
636*4d9fdb46SRobert Mustacchi             pep->pe_optional_header_offset,errcode);
637*4d9fdb46SRobert Mustacchi         pep->pe_optional_header_size = sizeof(IMAGE_OPTIONAL_HEADER64_dw);
638*4d9fdb46SRobert Mustacchi     } else {
639*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_OFFSET_SIZE;
640*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
641*4d9fdb46SRobert Mustacchi     }
642*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
643*4d9fdb46SRobert Mustacchi         return res;
644*4d9fdb46SRobert Mustacchi     }
645*4d9fdb46SRobert Mustacchi 
646*4d9fdb46SRobert Mustacchi     pep->pe_section_table_offset = pep->pe_optional_header_offset
647*4d9fdb46SRobert Mustacchi         + pep->pe_optional_header_size;
648*4d9fdb46SRobert Mustacchi     pep->pe_symbol_table_offset =
649*4d9fdb46SRobert Mustacchi         pep->pe_FileHeader.PointerToSymbolTable;
650*4d9fdb46SRobert Mustacchi     if (pep->pe_symbol_table_offset >= pep->pe_filesize) {
651*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_OFFSET_SIZE;
652*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
653*4d9fdb46SRobert Mustacchi     }
654*4d9fdb46SRobert Mustacchi     if (pep->pe_symbol_table_offset) {
655*4d9fdb46SRobert Mustacchi         pep->pe_string_table_offset  =
656*4d9fdb46SRobert Mustacchi             pep->pe_symbol_table_offset +
657*4d9fdb46SRobert Mustacchi             (pep->pe_FileHeader.NumberOfSymbols *
658*4d9fdb46SRobert Mustacchi             IMAGE_SIZEOF_SYMBOL);
659*4d9fdb46SRobert Mustacchi     }
660*4d9fdb46SRobert Mustacchi 
661*4d9fdb46SRobert Mustacchi     if (pep->pe_string_table_offset >= pep->pe_filesize) {
662*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_OFFSET_SIZE;
663*4d9fdb46SRobert Mustacchi         pep->pe_string_table_size = 0;
664*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
665*4d9fdb46SRobert Mustacchi     }
666*4d9fdb46SRobert Mustacchi     if (pep->pe_string_table_offset) {
667*4d9fdb46SRobert Mustacchi         /*  https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#coff-string-table  */
668*4d9fdb46SRobert Mustacchi         /* The first 4 bytes of the string table contain
669*4d9fdb46SRobert Mustacchi             the size of the string table. */
670*4d9fdb46SRobert Mustacchi         char size_field[4];
671*4d9fdb46SRobert Mustacchi 
672*4d9fdb46SRobert Mustacchi         if ((pep->pe_string_table_offset+sizeof(size_field)) >
673*4d9fdb46SRobert Mustacchi             pep->pe_filesize) {
674*4d9fdb46SRobert Mustacchi             *errcode = DW_DLE_FILE_TOO_SMALL;
675*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
676*4d9fdb46SRobert Mustacchi         }
677*4d9fdb46SRobert Mustacchi         memset(size_field,0,sizeof(size_field));
678*4d9fdb46SRobert Mustacchi         res =  _dwarf_object_read_random(pep->pe_fd,
679*4d9fdb46SRobert Mustacchi             (char *)size_field, (off_t)pep->pe_string_table_offset,
680*4d9fdb46SRobert Mustacchi             sizeof(size_field),
681*4d9fdb46SRobert Mustacchi             (off_t)pep->pe_filesize,errcode);
682*4d9fdb46SRobert Mustacchi         if (res != DW_DLV_OK) {
683*4d9fdb46SRobert Mustacchi             return res;
684*4d9fdb46SRobert Mustacchi         }
685*4d9fdb46SRobert Mustacchi         ASNAR(pep->pe_copy_word,pep->pe_string_table_size,
686*4d9fdb46SRobert Mustacchi             size_field);
687*4d9fdb46SRobert Mustacchi         if( pep->pe_string_table_size >= pep->pe_filesize ) {
688*4d9fdb46SRobert Mustacchi             *errcode = DW_DLE_PE_OFFSET_BAD;
689*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
690*4d9fdb46SRobert Mustacchi         }
691*4d9fdb46SRobert Mustacchi         if ((pep->pe_string_table_offset+pep->pe_string_table_size) >
692*4d9fdb46SRobert Mustacchi             pep->pe_filesize) {
693*4d9fdb46SRobert Mustacchi             *errcode = DW_DLE_FILE_TOO_SMALL;
694*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
695*4d9fdb46SRobert Mustacchi         }
696*4d9fdb46SRobert Mustacchi         pep->pe_string_table =
697*4d9fdb46SRobert Mustacchi             (char *)malloc((size_t)pep->pe_string_table_size);
698*4d9fdb46SRobert Mustacchi         if (!pep->pe_string_table) {
699*4d9fdb46SRobert Mustacchi             *errcode = DW_DLE_ALLOC_FAIL;
700*4d9fdb46SRobert Mustacchi             return DW_DLV_ERROR;
701*4d9fdb46SRobert Mustacchi         }
702*4d9fdb46SRobert Mustacchi         res = _dwarf_object_read_random(pep->pe_fd,
703*4d9fdb46SRobert Mustacchi             (char *)pep->pe_string_table, (off_t)pep->pe_string_table_offset,
704*4d9fdb46SRobert Mustacchi             (size_t)pep->pe_string_table_size,
705*4d9fdb46SRobert Mustacchi             (off_t)pep->pe_filesize,errcode);
706*4d9fdb46SRobert Mustacchi         if (res != DW_DLV_OK) {
707*4d9fdb46SRobert Mustacchi             return res;
708*4d9fdb46SRobert Mustacchi         }
709*4d9fdb46SRobert Mustacchi     }
710*4d9fdb46SRobert Mustacchi     res = dwarf_pe_load_dwarf_section_headers(pep,errcode);
711*4d9fdb46SRobert Mustacchi     return res;
712*4d9fdb46SRobert Mustacchi }
713*4d9fdb46SRobert Mustacchi 
714*4d9fdb46SRobert Mustacchi int
_dwarf_pe_setup(int fd,char * true_path,unsigned ftype,unsigned endian,unsigned offsetsize,size_t filesize,Dwarf_Unsigned access,unsigned groupnumber,Dwarf_Handler errhand,Dwarf_Ptr errarg,Dwarf_Debug * dbg,Dwarf_Error * error)715*4d9fdb46SRobert Mustacchi _dwarf_pe_setup(int fd,
716*4d9fdb46SRobert Mustacchi     char *true_path,
717*4d9fdb46SRobert Mustacchi     unsigned ftype,
718*4d9fdb46SRobert Mustacchi     unsigned endian,
719*4d9fdb46SRobert Mustacchi     unsigned offsetsize,
720*4d9fdb46SRobert Mustacchi     size_t filesize,
721*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned access,
722*4d9fdb46SRobert Mustacchi     unsigned groupnumber,
723*4d9fdb46SRobert Mustacchi     Dwarf_Handler errhand,
724*4d9fdb46SRobert Mustacchi     Dwarf_Ptr errarg,
725*4d9fdb46SRobert Mustacchi     Dwarf_Debug *dbg,Dwarf_Error *error)
726*4d9fdb46SRobert Mustacchi {
727*4d9fdb46SRobert Mustacchi     Dwarf_Obj_Access_Interface *binary_interface = 0;
728*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *pep = 0;
729*4d9fdb46SRobert Mustacchi     int res = DW_DLV_OK;
730*4d9fdb46SRobert Mustacchi     int localerrnum = 0;
731*4d9fdb46SRobert Mustacchi 
732*4d9fdb46SRobert Mustacchi     res = _dwarf_pe_object_access_init(
733*4d9fdb46SRobert Mustacchi         fd,
734*4d9fdb46SRobert Mustacchi         ftype,endian,offsetsize,filesize,access,
735*4d9fdb46SRobert Mustacchi         &binary_interface,
736*4d9fdb46SRobert Mustacchi         &localerrnum);
737*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
738*4d9fdb46SRobert Mustacchi         if (res == DW_DLV_NO_ENTRY) {
739*4d9fdb46SRobert Mustacchi             return res;
740*4d9fdb46SRobert Mustacchi         }
741*4d9fdb46SRobert Mustacchi         _dwarf_error(NULL, error, localerrnum);
742*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
743*4d9fdb46SRobert Mustacchi     }
744*4d9fdb46SRobert Mustacchi     /*  allocates and initializes Dwarf_Debug,
745*4d9fdb46SRobert Mustacchi         generic code */
746*4d9fdb46SRobert Mustacchi     res = dwarf_object_init_b(binary_interface, errhand, errarg,
747*4d9fdb46SRobert Mustacchi         groupnumber, dbg, error);
748*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK){
749*4d9fdb46SRobert Mustacchi         _dwarf_destruct_pe_access(binary_interface);
750*4d9fdb46SRobert Mustacchi         return res;
751*4d9fdb46SRobert Mustacchi     }
752*4d9fdb46SRobert Mustacchi     pep = binary_interface->object;
753*4d9fdb46SRobert Mustacchi     pep->pe_path = strdup(true_path);
754*4d9fdb46SRobert Mustacchi     return res;
755*4d9fdb46SRobert Mustacchi }
756*4d9fdb46SRobert Mustacchi 
757*4d9fdb46SRobert Mustacchi static Dwarf_Obj_Access_Methods pe_methods = {
758*4d9fdb46SRobert Mustacchi     pe_get_section_info,
759*4d9fdb46SRobert Mustacchi     pe_get_byte_order,
760*4d9fdb46SRobert Mustacchi     pe_get_length_size,
761*4d9fdb46SRobert Mustacchi     pe_get_pointer_size,
762*4d9fdb46SRobert Mustacchi     pe_get_section_count,
763*4d9fdb46SRobert Mustacchi     pe_load_section,
764*4d9fdb46SRobert Mustacchi     0 /* ignore pe relocations. */
765*4d9fdb46SRobert Mustacchi };
766*4d9fdb46SRobert Mustacchi 
767*4d9fdb46SRobert Mustacchi /* On any error this frees internals. */
768*4d9fdb46SRobert Mustacchi static int
_dwarf_pe_object_access_internals_init(dwarf_pe_object_access_internals_t * internals,int fd,unsigned ftype,unsigned endian,unsigned offsetsize,size_t filesize,UNUSEDARG Dwarf_Unsigned access,int * errcode)769*4d9fdb46SRobert Mustacchi _dwarf_pe_object_access_internals_init(
770*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t * internals,
771*4d9fdb46SRobert Mustacchi     int  fd,
772*4d9fdb46SRobert Mustacchi     unsigned ftype,
773*4d9fdb46SRobert Mustacchi     unsigned endian,
774*4d9fdb46SRobert Mustacchi     unsigned offsetsize,
775*4d9fdb46SRobert Mustacchi     size_t filesize,
776*4d9fdb46SRobert Mustacchi     UNUSEDARG Dwarf_Unsigned access,
777*4d9fdb46SRobert Mustacchi     int *errcode)
778*4d9fdb46SRobert Mustacchi {
779*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t * intfc = internals;
780*4d9fdb46SRobert Mustacchi     struct Dwarf_Obj_Access_Interface_s *localdoas = 0;
781*4d9fdb46SRobert Mustacchi     int res = 0;
782*4d9fdb46SRobert Mustacchi 
783*4d9fdb46SRobert Mustacchi     /*  Must malloc as _dwarf_destruct_pe_access()
784*4d9fdb46SRobert Mustacchi         forces that due to other uses. */
785*4d9fdb46SRobert Mustacchi     localdoas = (struct Dwarf_Obj_Access_Interface_s *)
786*4d9fdb46SRobert Mustacchi         malloc(sizeof(struct Dwarf_Obj_Access_Interface_s));
787*4d9fdb46SRobert Mustacchi     if (!localdoas) {
788*4d9fdb46SRobert Mustacchi         free(internals);
789*4d9fdb46SRobert Mustacchi         *errcode = DW_DLE_ALLOC_FAIL;
790*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
791*4d9fdb46SRobert Mustacchi     }
792*4d9fdb46SRobert Mustacchi     memset(localdoas,0,sizeof(struct Dwarf_Obj_Access_Interface_s));
793*4d9fdb46SRobert Mustacchi     intfc->pe_ident[0]    = 'P';
794*4d9fdb46SRobert Mustacchi     intfc->pe_ident[1]    = '1';
795*4d9fdb46SRobert Mustacchi     intfc->pe_fd          = fd;
796*4d9fdb46SRobert Mustacchi     intfc->pe_is_64bit    = ((offsetsize==64)?TRUE:FALSE);
797*4d9fdb46SRobert Mustacchi     intfc->pe_offsetsize  = offsetsize;
798*4d9fdb46SRobert Mustacchi     intfc->pe_pointersize = offsetsize;
799*4d9fdb46SRobert Mustacchi     intfc->pe_filesize    = filesize;
800*4d9fdb46SRobert Mustacchi     intfc->pe_ftype       = ftype;
801*4d9fdb46SRobert Mustacchi     /* pe_path set by caller */
802*4d9fdb46SRobert Mustacchi 
803*4d9fdb46SRobert Mustacchi #ifdef WORDS_BIGENDIAN
804*4d9fdb46SRobert Mustacchi     if (endian == DW_ENDIAN_LITTLE ) {
805*4d9fdb46SRobert Mustacchi         intfc->pe_copy_word = _dwarf_memcpy_swap_bytes;
806*4d9fdb46SRobert Mustacchi         intfc->pe_endian = DW_OBJECT_LSB;
807*4d9fdb46SRobert Mustacchi     } else {
808*4d9fdb46SRobert Mustacchi         intfc->pe_copy_word = _dwarf_memcpy_noswap_bytes;
809*4d9fdb46SRobert Mustacchi         intfc->pe_endian = DW_OBJECT_MSB;
810*4d9fdb46SRobert Mustacchi     }
811*4d9fdb46SRobert Mustacchi #else  /* LITTLE ENDIAN */
812*4d9fdb46SRobert Mustacchi     if (endian == DW_ENDIAN_LITTLE ) {
813*4d9fdb46SRobert Mustacchi         intfc->pe_copy_word = _dwarf_memcpy_noswap_bytes;
814*4d9fdb46SRobert Mustacchi         intfc->pe_endian = DW_OBJECT_LSB;
815*4d9fdb46SRobert Mustacchi     } else {
816*4d9fdb46SRobert Mustacchi         intfc->pe_copy_word = _dwarf_memcpy_swap_bytes;
817*4d9fdb46SRobert Mustacchi         intfc->pe_endian = DW_OBJECT_MSB;
818*4d9fdb46SRobert Mustacchi     }
819*4d9fdb46SRobert Mustacchi #endif /* LITTLE- BIG-ENDIAN */
820*4d9fdb46SRobert Mustacchi     res = dwarf_load_pe_sections(intfc,errcode);
821*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK) {
822*4d9fdb46SRobert Mustacchi         localdoas->object = intfc;
823*4d9fdb46SRobert Mustacchi         localdoas->methods = 0;
824*4d9fdb46SRobert Mustacchi         _dwarf_destruct_pe_access(localdoas);
825*4d9fdb46SRobert Mustacchi         localdoas = 0;
826*4d9fdb46SRobert Mustacchi         return res;
827*4d9fdb46SRobert Mustacchi     }
828*4d9fdb46SRobert Mustacchi     free(localdoas);
829*4d9fdb46SRobert Mustacchi     localdoas = 0;
830*4d9fdb46SRobert Mustacchi     return DW_DLV_OK;
831*4d9fdb46SRobert Mustacchi }
832*4d9fdb46SRobert Mustacchi 
833*4d9fdb46SRobert Mustacchi 
834*4d9fdb46SRobert Mustacchi static int
_dwarf_pe_object_access_init(int fd,unsigned ftype,unsigned endian,unsigned offsetsize,size_t filesize,Dwarf_Unsigned access,Dwarf_Obj_Access_Interface ** binary_interface,int * localerrnum)835*4d9fdb46SRobert Mustacchi _dwarf_pe_object_access_init(
836*4d9fdb46SRobert Mustacchi     int  fd,
837*4d9fdb46SRobert Mustacchi     unsigned ftype,
838*4d9fdb46SRobert Mustacchi     unsigned endian,
839*4d9fdb46SRobert Mustacchi     unsigned offsetsize,
840*4d9fdb46SRobert Mustacchi     size_t filesize,
841*4d9fdb46SRobert Mustacchi     Dwarf_Unsigned access,
842*4d9fdb46SRobert Mustacchi     Dwarf_Obj_Access_Interface **binary_interface,
843*4d9fdb46SRobert Mustacchi     int *localerrnum)
844*4d9fdb46SRobert Mustacchi {
845*4d9fdb46SRobert Mustacchi 
846*4d9fdb46SRobert Mustacchi     int res = 0;
847*4d9fdb46SRobert Mustacchi     dwarf_pe_object_access_internals_t *internals = 0;
848*4d9fdb46SRobert Mustacchi     Dwarf_Obj_Access_Interface *intfc = 0;
849*4d9fdb46SRobert Mustacchi 
850*4d9fdb46SRobert Mustacchi     internals = malloc(sizeof(dwarf_pe_object_access_internals_t));
851*4d9fdb46SRobert Mustacchi     if (!internals) {
852*4d9fdb46SRobert Mustacchi         *localerrnum = DW_DLE_ALLOC_FAIL;
853*4d9fdb46SRobert Mustacchi         /* Impossible case, we hope. Give up. */
854*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
855*4d9fdb46SRobert Mustacchi     }
856*4d9fdb46SRobert Mustacchi     memset(internals,0,sizeof(*internals));
857*4d9fdb46SRobert Mustacchi     res = _dwarf_pe_object_access_internals_init(internals,
858*4d9fdb46SRobert Mustacchi         fd,
859*4d9fdb46SRobert Mustacchi         ftype, endian, offsetsize, filesize,
860*4d9fdb46SRobert Mustacchi         access,
861*4d9fdb46SRobert Mustacchi         localerrnum);
862*4d9fdb46SRobert Mustacchi     if (res != DW_DLV_OK){
863*4d9fdb46SRobert Mustacchi         /* *err is already set. and the call freed internals */
864*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
865*4d9fdb46SRobert Mustacchi     }
866*4d9fdb46SRobert Mustacchi 
867*4d9fdb46SRobert Mustacchi     intfc = malloc(sizeof(Dwarf_Obj_Access_Interface));
868*4d9fdb46SRobert Mustacchi     if (!intfc) {
869*4d9fdb46SRobert Mustacchi         /* Impossible case, we hope. Give up. */
870*4d9fdb46SRobert Mustacchi         free(internals);
871*4d9fdb46SRobert Mustacchi         *localerrnum = DW_DLE_ALLOC_FAIL;
872*4d9fdb46SRobert Mustacchi         return DW_DLV_ERROR;
873*4d9fdb46SRobert Mustacchi     }
874*4d9fdb46SRobert Mustacchi     /* Initialize the interface struct */
875*4d9fdb46SRobert Mustacchi     intfc->object = internals;
876*4d9fdb46SRobert Mustacchi     intfc->methods = &pe_methods;
877*4d9fdb46SRobert Mustacchi     *binary_interface = intfc;
878*4d9fdb46SRobert Mustacchi     return DW_DLV_OK;
879*4d9fdb46SRobert Mustacchi }
880