1*9712c20fSFrederick Mayle // Copyright 2019 Google LLC
2*9712c20fSFrederick Mayle //
3*9712c20fSFrederick Mayle // Redistribution and use in source and binary forms, with or without
4*9712c20fSFrederick Mayle // modification, are permitted provided that the following conditions are
5*9712c20fSFrederick Mayle // met:
6*9712c20fSFrederick Mayle //
7*9712c20fSFrederick Mayle // * Redistributions of source code must retain the above copyright
8*9712c20fSFrederick Mayle // notice, this list of conditions and the following disclaimer.
9*9712c20fSFrederick Mayle // * Redistributions in binary form must reproduce the above
10*9712c20fSFrederick Mayle // copyright notice, this list of conditions and the following disclaimer
11*9712c20fSFrederick Mayle // in the documentation and/or other materials provided with the
12*9712c20fSFrederick Mayle // distribution.
13*9712c20fSFrederick Mayle // * Neither the name of Google LLC nor the names of its
14*9712c20fSFrederick Mayle // contributors may be used to endorse or promote products derived from
15*9712c20fSFrederick Mayle // this software without specific prior written permission.
16*9712c20fSFrederick Mayle //
17*9712c20fSFrederick Mayle // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
18*9712c20fSFrederick Mayle // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
19*9712c20fSFrederick Mayle // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
20*9712c20fSFrederick Mayle // A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
21*9712c20fSFrederick Mayle // OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
22*9712c20fSFrederick Mayle // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
23*9712c20fSFrederick Mayle // LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24*9712c20fSFrederick Mayle // DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25*9712c20fSFrederick Mayle // THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26*9712c20fSFrederick Mayle // (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27*9712c20fSFrederick Mayle // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28*9712c20fSFrederick Mayle
29*9712c20fSFrederick Mayle #ifdef HAVE_CONFIG_H
30*9712c20fSFrederick Mayle #include <config.h> // Must come first
31*9712c20fSFrederick Mayle #endif
32*9712c20fSFrederick Mayle
33*9712c20fSFrederick Mayle #include "pe_util.h"
34*9712c20fSFrederick Mayle
35*9712c20fSFrederick Mayle #include <windows.h>
36*9712c20fSFrederick Mayle #include <winnt.h>
37*9712c20fSFrederick Mayle #include <atlbase.h>
38*9712c20fSFrederick Mayle #include <ImageHlp.h>
39*9712c20fSFrederick Mayle
40*9712c20fSFrederick Mayle #include <functional>
41*9712c20fSFrederick Mayle #include <memory>
42*9712c20fSFrederick Mayle
43*9712c20fSFrederick Mayle #include "common/windows/string_utils-inl.h"
44*9712c20fSFrederick Mayle #include "common/windows/guid_string.h"
45*9712c20fSFrederick Mayle
46*9712c20fSFrederick Mayle namespace {
47*9712c20fSFrederick Mayle
48*9712c20fSFrederick Mayle /*
49*9712c20fSFrederick Mayle * Not defined in WinNT.h prior to SDK 10.0.20348.0 for some reason.
50*9712c20fSFrederick Mayle * Definitions taken from: http://uninformed.org/index.cgi?v=4&a=1&p=13
51*9712c20fSFrederick Mayle *
52*9712c20fSFrederick Mayle */
53*9712c20fSFrederick Mayle typedef unsigned char UBYTE;
54*9712c20fSFrederick Mayle
55*9712c20fSFrederick Mayle #if !defined(UNW_FLAG_EHANDLER)
56*9712c20fSFrederick Mayle #define UNW_FLAG_EHANDLER 0x01
57*9712c20fSFrederick Mayle #endif
58*9712c20fSFrederick Mayle #if !defined(UNW_FLAG_UHANDLER)
59*9712c20fSFrederick Mayle #define UNW_FLAG_UHANDLER 0x02
60*9712c20fSFrederick Mayle #endif
61*9712c20fSFrederick Mayle #if !defined(UNW_FLAG_CHAININFO)
62*9712c20fSFrederick Mayle #define UNW_FLAG_CHAININFO 0x04
63*9712c20fSFrederick Mayle #endif
64*9712c20fSFrederick Mayle
65*9712c20fSFrederick Mayle union UnwindCode {
66*9712c20fSFrederick Mayle struct {
67*9712c20fSFrederick Mayle UBYTE offset_in_prolog;
68*9712c20fSFrederick Mayle UBYTE unwind_operation_code : 4;
69*9712c20fSFrederick Mayle UBYTE operation_info : 4;
70*9712c20fSFrederick Mayle };
71*9712c20fSFrederick Mayle USHORT frame_offset;
72*9712c20fSFrederick Mayle };
73*9712c20fSFrederick Mayle
74*9712c20fSFrederick Mayle enum UnwindOperationCodes {
75*9712c20fSFrederick Mayle UWOP_PUSH_NONVOL = 0, /* info == register number */
76*9712c20fSFrederick Mayle UWOP_ALLOC_LARGE, /* no info, alloc size in next 2 slots */
77*9712c20fSFrederick Mayle UWOP_ALLOC_SMALL, /* info == size of allocation / 8 - 1 */
78*9712c20fSFrederick Mayle UWOP_SET_FPREG, /* no info, FP = RSP + UNWIND_INFO.FPRegOffset*16 */
79*9712c20fSFrederick Mayle UWOP_SAVE_NONVOL, /* info == register number, offset in next slot */
80*9712c20fSFrederick Mayle UWOP_SAVE_NONVOL_FAR, /* info == register number, offset in next 2 slots */
81*9712c20fSFrederick Mayle // XXX: these are missing from MSDN!
82*9712c20fSFrederick Mayle // See: http://www.osronline.com/ddkx/kmarch/64bitamd_4rs7.htm
83*9712c20fSFrederick Mayle UWOP_SAVE_XMM,
84*9712c20fSFrederick Mayle UWOP_SAVE_XMM_FAR,
85*9712c20fSFrederick Mayle UWOP_SAVE_XMM128, /* info == XMM reg number, offset in next slot */
86*9712c20fSFrederick Mayle UWOP_SAVE_XMM128_FAR, /* info == XMM reg number, offset in next 2 slots */
87*9712c20fSFrederick Mayle UWOP_PUSH_MACHFRAME /* info == 0: no error-code, 1: error-code */
88*9712c20fSFrederick Mayle };
89*9712c20fSFrederick Mayle
90*9712c20fSFrederick Mayle // See: http://msdn.microsoft.com/en-us/library/ddssxxy8.aspx
91*9712c20fSFrederick Mayle // Note: some fields removed as we don't use them.
92*9712c20fSFrederick Mayle struct UnwindInfo {
93*9712c20fSFrederick Mayle UBYTE version : 3;
94*9712c20fSFrederick Mayle UBYTE flags : 5;
95*9712c20fSFrederick Mayle UBYTE size_of_prolog;
96*9712c20fSFrederick Mayle UBYTE count_of_codes;
97*9712c20fSFrederick Mayle UBYTE frame_register : 4;
98*9712c20fSFrederick Mayle UBYTE frame_offset : 4;
99*9712c20fSFrederick Mayle UnwindCode unwind_code[1];
100*9712c20fSFrederick Mayle };
101*9712c20fSFrederick Mayle
102*9712c20fSFrederick Mayle struct CV_INFO_PDB70 {
103*9712c20fSFrederick Mayle ULONG cv_signature;
104*9712c20fSFrederick Mayle GUID signature;
105*9712c20fSFrederick Mayle ULONG age;
106*9712c20fSFrederick Mayle CHAR pdb_filename[ANYSIZE_ARRAY];
107*9712c20fSFrederick Mayle };
108*9712c20fSFrederick Mayle
109*9712c20fSFrederick Mayle #define CV_SIGNATURE_RSDS 'SDSR'
110*9712c20fSFrederick Mayle
111*9712c20fSFrederick Mayle // A helper class to scope a PLOADED_IMAGE.
112*9712c20fSFrederick Mayle class AutoImage {
113*9712c20fSFrederick Mayle public:
AutoImage(PLOADED_IMAGE img)114*9712c20fSFrederick Mayle explicit AutoImage(PLOADED_IMAGE img) : img_(img) {}
~AutoImage()115*9712c20fSFrederick Mayle ~AutoImage() {
116*9712c20fSFrederick Mayle if (img_)
117*9712c20fSFrederick Mayle ImageUnload(img_);
118*9712c20fSFrederick Mayle }
119*9712c20fSFrederick Mayle
operator PLOADED_IMAGE()120*9712c20fSFrederick Mayle operator PLOADED_IMAGE() { return img_; }
operator ->()121*9712c20fSFrederick Mayle PLOADED_IMAGE operator->() { return img_; }
122*9712c20fSFrederick Mayle
123*9712c20fSFrederick Mayle private:
124*9712c20fSFrederick Mayle PLOADED_IMAGE img_;
125*9712c20fSFrederick Mayle };
126*9712c20fSFrederick Mayle } // namespace
127*9712c20fSFrederick Mayle
128*9712c20fSFrederick Mayle namespace google_breakpad {
129*9712c20fSFrederick Mayle
130*9712c20fSFrederick Mayle using std::unique_ptr;
131*9712c20fSFrederick Mayle using google_breakpad::GUIDString;
132*9712c20fSFrederick Mayle
ReadModuleInfo(const wstring & pe_file,PDBModuleInfo * info)133*9712c20fSFrederick Mayle bool ReadModuleInfo(const wstring & pe_file, PDBModuleInfo * info) {
134*9712c20fSFrederick Mayle // Convert wchar to native charset because ImageLoad only takes
135*9712c20fSFrederick Mayle // a PSTR as input.
136*9712c20fSFrederick Mayle string img_file;
137*9712c20fSFrederick Mayle if (!WindowsStringUtils::safe_wcstombs(pe_file, &img_file)) {
138*9712c20fSFrederick Mayle fprintf(stderr, "Image path '%S' contains unrecognized characters.\n",
139*9712c20fSFrederick Mayle pe_file.c_str());
140*9712c20fSFrederick Mayle return false;
141*9712c20fSFrederick Mayle }
142*9712c20fSFrederick Mayle
143*9712c20fSFrederick Mayle AutoImage img(ImageLoad((PSTR)img_file.c_str(), NULL));
144*9712c20fSFrederick Mayle if (!img) {
145*9712c20fSFrederick Mayle fprintf(stderr, "Failed to load %s\n", img_file.c_str());
146*9712c20fSFrederick Mayle return false;
147*9712c20fSFrederick Mayle }
148*9712c20fSFrederick Mayle
149*9712c20fSFrederick Mayle info->cpu = FileHeaderMachineToCpuString(
150*9712c20fSFrederick Mayle img->FileHeader->FileHeader.Machine);
151*9712c20fSFrederick Mayle
152*9712c20fSFrederick Mayle PIMAGE_OPTIONAL_HEADER64 optional_header =
153*9712c20fSFrederick Mayle &(reinterpret_cast<PIMAGE_NT_HEADERS64>(img->FileHeader))->OptionalHeader;
154*9712c20fSFrederick Mayle
155*9712c20fSFrederick Mayle // Search debug directories for a guid signature & age
156*9712c20fSFrederick Mayle DWORD debug_rva = optional_header->
157*9712c20fSFrederick Mayle DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress;
158*9712c20fSFrederick Mayle DWORD debug_size = optional_header->
159*9712c20fSFrederick Mayle DataDirectory[IMAGE_DIRECTORY_ENTRY_DEBUG].Size;
160*9712c20fSFrederick Mayle PIMAGE_DEBUG_DIRECTORY debug_directories =
161*9712c20fSFrederick Mayle static_cast<PIMAGE_DEBUG_DIRECTORY>(
162*9712c20fSFrederick Mayle ImageRvaToVa(img->FileHeader,
163*9712c20fSFrederick Mayle img->MappedAddress,
164*9712c20fSFrederick Mayle debug_rva,
165*9712c20fSFrederick Mayle &img->LastRvaSection));
166*9712c20fSFrederick Mayle
167*9712c20fSFrederick Mayle for (DWORD i = 0; i < debug_size / sizeof(*debug_directories); i++) {
168*9712c20fSFrederick Mayle if (debug_directories[i].Type != IMAGE_DEBUG_TYPE_CODEVIEW ||
169*9712c20fSFrederick Mayle debug_directories[i].SizeOfData < sizeof(CV_INFO_PDB70)) {
170*9712c20fSFrederick Mayle continue;
171*9712c20fSFrederick Mayle }
172*9712c20fSFrederick Mayle
173*9712c20fSFrederick Mayle struct CV_INFO_PDB70* cv_info = static_cast<CV_INFO_PDB70*>(ImageRvaToVa(
174*9712c20fSFrederick Mayle img->FileHeader,
175*9712c20fSFrederick Mayle img->MappedAddress,
176*9712c20fSFrederick Mayle debug_directories[i].AddressOfRawData,
177*9712c20fSFrederick Mayle &img->LastRvaSection));
178*9712c20fSFrederick Mayle if (cv_info->cv_signature != CV_SIGNATURE_RSDS) {
179*9712c20fSFrederick Mayle continue;
180*9712c20fSFrederick Mayle }
181*9712c20fSFrederick Mayle
182*9712c20fSFrederick Mayle info->debug_identifier = GenerateDebugIdentifier(cv_info->age,
183*9712c20fSFrederick Mayle cv_info->signature);
184*9712c20fSFrederick Mayle
185*9712c20fSFrederick Mayle // This code assumes that the pdb_filename is stored as ASCII without
186*9712c20fSFrederick Mayle // multibyte characters, but it's not clear if that's true.
187*9712c20fSFrederick Mayle size_t debug_file_length = strnlen_s(cv_info->pdb_filename, MAX_PATH);
188*9712c20fSFrederick Mayle if (debug_file_length < 0 || debug_file_length >= MAX_PATH) {
189*9712c20fSFrederick Mayle fprintf(stderr, "PE debug directory is corrupt.\n");
190*9712c20fSFrederick Mayle return false;
191*9712c20fSFrederick Mayle }
192*9712c20fSFrederick Mayle std::string debug_file(cv_info->pdb_filename, debug_file_length);
193*9712c20fSFrederick Mayle if (!WindowsStringUtils::safe_mbstowcs(debug_file, &info->debug_file)) {
194*9712c20fSFrederick Mayle fprintf(stderr, "PDB filename '%s' contains unrecognized characters.\n",
195*9712c20fSFrederick Mayle debug_file.c_str());
196*9712c20fSFrederick Mayle return false;
197*9712c20fSFrederick Mayle }
198*9712c20fSFrederick Mayle info->debug_file = WindowsStringUtils::GetBaseName(info->debug_file);
199*9712c20fSFrederick Mayle
200*9712c20fSFrederick Mayle return true;
201*9712c20fSFrederick Mayle }
202*9712c20fSFrederick Mayle
203*9712c20fSFrederick Mayle fprintf(stderr, "Image is missing debug information.\n");
204*9712c20fSFrederick Mayle return false;
205*9712c20fSFrederick Mayle }
206*9712c20fSFrederick Mayle
ReadPEInfo(const wstring & pe_file,PEModuleInfo * info)207*9712c20fSFrederick Mayle bool ReadPEInfo(const wstring & pe_file, PEModuleInfo * info) {
208*9712c20fSFrederick Mayle // Convert wchar to native charset because ImageLoad only takes
209*9712c20fSFrederick Mayle // a PSTR as input.
210*9712c20fSFrederick Mayle string img_file;
211*9712c20fSFrederick Mayle if (!WindowsStringUtils::safe_wcstombs(pe_file, &img_file)) {
212*9712c20fSFrederick Mayle fprintf(stderr, "Image path '%S' contains unrecognized characters.\n",
213*9712c20fSFrederick Mayle pe_file.c_str());
214*9712c20fSFrederick Mayle return false;
215*9712c20fSFrederick Mayle }
216*9712c20fSFrederick Mayle
217*9712c20fSFrederick Mayle AutoImage img(ImageLoad((PSTR)img_file.c_str(), NULL));
218*9712c20fSFrederick Mayle if (!img) {
219*9712c20fSFrederick Mayle fprintf(stderr, "Failed to open PE file: %S\n", pe_file.c_str());
220*9712c20fSFrederick Mayle return false;
221*9712c20fSFrederick Mayle }
222*9712c20fSFrederick Mayle
223*9712c20fSFrederick Mayle info->code_file = WindowsStringUtils::GetBaseName(pe_file);
224*9712c20fSFrederick Mayle
225*9712c20fSFrederick Mayle // The date and time that the file was created by the linker.
226*9712c20fSFrederick Mayle DWORD TimeDateStamp = img->FileHeader->FileHeader.TimeDateStamp;
227*9712c20fSFrederick Mayle // The size of the file in bytes, including all headers.
228*9712c20fSFrederick Mayle DWORD SizeOfImage = 0;
229*9712c20fSFrederick Mayle PIMAGE_OPTIONAL_HEADER64 opt =
230*9712c20fSFrederick Mayle &((PIMAGE_NT_HEADERS64)img->FileHeader)->OptionalHeader;
231*9712c20fSFrederick Mayle if (opt->Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
232*9712c20fSFrederick Mayle // 64-bit PE file.
233*9712c20fSFrederick Mayle SizeOfImage = opt->SizeOfImage;
234*9712c20fSFrederick Mayle }
235*9712c20fSFrederick Mayle else {
236*9712c20fSFrederick Mayle // 32-bit PE file.
237*9712c20fSFrederick Mayle SizeOfImage = img->FileHeader->OptionalHeader.SizeOfImage;
238*9712c20fSFrederick Mayle }
239*9712c20fSFrederick Mayle wchar_t code_identifier[32];
240*9712c20fSFrederick Mayle swprintf(code_identifier,
241*9712c20fSFrederick Mayle sizeof(code_identifier) / sizeof(code_identifier[0]),
242*9712c20fSFrederick Mayle L"%08X%X", TimeDateStamp, SizeOfImage);
243*9712c20fSFrederick Mayle info->code_identifier = code_identifier;
244*9712c20fSFrederick Mayle
245*9712c20fSFrederick Mayle return true;
246*9712c20fSFrederick Mayle }
247*9712c20fSFrederick Mayle
PrintPEFrameData(const wstring & pe_file,FILE * out_file)248*9712c20fSFrederick Mayle bool PrintPEFrameData(const wstring & pe_file, FILE * out_file)
249*9712c20fSFrederick Mayle {
250*9712c20fSFrederick Mayle // Convert wchar to native charset because ImageLoad only takes
251*9712c20fSFrederick Mayle // a PSTR as input.
252*9712c20fSFrederick Mayle string img_file;
253*9712c20fSFrederick Mayle if (!WindowsStringUtils::safe_wcstombs(pe_file, &img_file)) {
254*9712c20fSFrederick Mayle fprintf(stderr, "Image path '%S' contains unrecognized characters.\n",
255*9712c20fSFrederick Mayle pe_file.c_str());
256*9712c20fSFrederick Mayle return false;
257*9712c20fSFrederick Mayle }
258*9712c20fSFrederick Mayle
259*9712c20fSFrederick Mayle AutoImage img(ImageLoad((PSTR)img_file.c_str(), NULL));
260*9712c20fSFrederick Mayle if (!img) {
261*9712c20fSFrederick Mayle fprintf(stderr, "Failed to load %s\n", img_file.c_str());
262*9712c20fSFrederick Mayle return false;
263*9712c20fSFrederick Mayle }
264*9712c20fSFrederick Mayle PIMAGE_OPTIONAL_HEADER64 optional_header =
265*9712c20fSFrederick Mayle &(reinterpret_cast<PIMAGE_NT_HEADERS64>(img->FileHeader))->OptionalHeader;
266*9712c20fSFrederick Mayle if (optional_header->Magic != IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
267*9712c20fSFrederick Mayle fprintf(stderr, "Not a PE32+ image\n");
268*9712c20fSFrederick Mayle return false;
269*9712c20fSFrederick Mayle }
270*9712c20fSFrederick Mayle
271*9712c20fSFrederick Mayle // Read Exception Directory
272*9712c20fSFrederick Mayle DWORD exception_rva = optional_header->
273*9712c20fSFrederick Mayle DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].VirtualAddress;
274*9712c20fSFrederick Mayle DWORD exception_size = optional_header->
275*9712c20fSFrederick Mayle DataDirectory[IMAGE_DIRECTORY_ENTRY_EXCEPTION].Size;
276*9712c20fSFrederick Mayle PIMAGE_RUNTIME_FUNCTION_ENTRY funcs =
277*9712c20fSFrederick Mayle static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
278*9712c20fSFrederick Mayle ImageRvaToVa(img->FileHeader,
279*9712c20fSFrederick Mayle img->MappedAddress,
280*9712c20fSFrederick Mayle exception_rva,
281*9712c20fSFrederick Mayle &img->LastRvaSection));
282*9712c20fSFrederick Mayle for (DWORD i = 0; i < exception_size / sizeof(*funcs); i++) {
283*9712c20fSFrederick Mayle DWORD unwind_rva = funcs[i].UnwindInfoAddress;
284*9712c20fSFrederick Mayle // handle chaining
285*9712c20fSFrederick Mayle while (unwind_rva & 0x1) {
286*9712c20fSFrederick Mayle unwind_rva ^= 0x1;
287*9712c20fSFrederick Mayle PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
288*9712c20fSFrederick Mayle static_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
289*9712c20fSFrederick Mayle ImageRvaToVa(img->FileHeader,
290*9712c20fSFrederick Mayle img->MappedAddress,
291*9712c20fSFrederick Mayle unwind_rva,
292*9712c20fSFrederick Mayle &img->LastRvaSection));
293*9712c20fSFrederick Mayle unwind_rva = chained_func->UnwindInfoAddress;
294*9712c20fSFrederick Mayle }
295*9712c20fSFrederick Mayle
296*9712c20fSFrederick Mayle UnwindInfo *unwind_info = static_cast<UnwindInfo*>(
297*9712c20fSFrederick Mayle ImageRvaToVa(img->FileHeader,
298*9712c20fSFrederick Mayle img->MappedAddress,
299*9712c20fSFrederick Mayle unwind_rva,
300*9712c20fSFrederick Mayle &img->LastRvaSection));
301*9712c20fSFrederick Mayle
302*9712c20fSFrederick Mayle DWORD stack_size = 8; // minimal stack size is 8 for RIP
303*9712c20fSFrederick Mayle DWORD rip_offset = 8;
304*9712c20fSFrederick Mayle do {
305*9712c20fSFrederick Mayle for (UBYTE c = 0; c < unwind_info->count_of_codes; c++) {
306*9712c20fSFrederick Mayle UnwindCode *unwind_code = &unwind_info->unwind_code[c];
307*9712c20fSFrederick Mayle switch (unwind_code->unwind_operation_code) {
308*9712c20fSFrederick Mayle case UWOP_PUSH_NONVOL: {
309*9712c20fSFrederick Mayle stack_size += 8;
310*9712c20fSFrederick Mayle break;
311*9712c20fSFrederick Mayle }
312*9712c20fSFrederick Mayle case UWOP_ALLOC_LARGE: {
313*9712c20fSFrederick Mayle if (unwind_code->operation_info == 0) {
314*9712c20fSFrederick Mayle c++;
315*9712c20fSFrederick Mayle if (c < unwind_info->count_of_codes)
316*9712c20fSFrederick Mayle stack_size += (unwind_code + 1)->frame_offset * 8;
317*9712c20fSFrederick Mayle }
318*9712c20fSFrederick Mayle else {
319*9712c20fSFrederick Mayle c += 2;
320*9712c20fSFrederick Mayle if (c < unwind_info->count_of_codes)
321*9712c20fSFrederick Mayle stack_size += (unwind_code + 1)->frame_offset |
322*9712c20fSFrederick Mayle ((unwind_code + 2)->frame_offset << 16);
323*9712c20fSFrederick Mayle }
324*9712c20fSFrederick Mayle break;
325*9712c20fSFrederick Mayle }
326*9712c20fSFrederick Mayle case UWOP_ALLOC_SMALL: {
327*9712c20fSFrederick Mayle stack_size += unwind_code->operation_info * 8 + 8;
328*9712c20fSFrederick Mayle break;
329*9712c20fSFrederick Mayle }
330*9712c20fSFrederick Mayle case UWOP_SET_FPREG:
331*9712c20fSFrederick Mayle case UWOP_SAVE_XMM:
332*9712c20fSFrederick Mayle case UWOP_SAVE_XMM_FAR:
333*9712c20fSFrederick Mayle break;
334*9712c20fSFrederick Mayle case UWOP_SAVE_NONVOL:
335*9712c20fSFrederick Mayle case UWOP_SAVE_XMM128: {
336*9712c20fSFrederick Mayle c++; // skip slot with offset
337*9712c20fSFrederick Mayle break;
338*9712c20fSFrederick Mayle }
339*9712c20fSFrederick Mayle case UWOP_SAVE_NONVOL_FAR:
340*9712c20fSFrederick Mayle case UWOP_SAVE_XMM128_FAR: {
341*9712c20fSFrederick Mayle c += 2; // skip 2 slots with offset
342*9712c20fSFrederick Mayle break;
343*9712c20fSFrederick Mayle }
344*9712c20fSFrederick Mayle case UWOP_PUSH_MACHFRAME: {
345*9712c20fSFrederick Mayle if (unwind_code->operation_info) {
346*9712c20fSFrederick Mayle stack_size += 88;
347*9712c20fSFrederick Mayle }
348*9712c20fSFrederick Mayle else {
349*9712c20fSFrederick Mayle stack_size += 80;
350*9712c20fSFrederick Mayle }
351*9712c20fSFrederick Mayle rip_offset += 80;
352*9712c20fSFrederick Mayle break;
353*9712c20fSFrederick Mayle }
354*9712c20fSFrederick Mayle }
355*9712c20fSFrederick Mayle }
356*9712c20fSFrederick Mayle if (unwind_info->flags & UNW_FLAG_CHAININFO) {
357*9712c20fSFrederick Mayle PIMAGE_RUNTIME_FUNCTION_ENTRY chained_func =
358*9712c20fSFrederick Mayle reinterpret_cast<PIMAGE_RUNTIME_FUNCTION_ENTRY>(
359*9712c20fSFrederick Mayle (unwind_info->unwind_code +
360*9712c20fSFrederick Mayle ((unwind_info->count_of_codes + 1) & ~1)));
361*9712c20fSFrederick Mayle
362*9712c20fSFrederick Mayle unwind_info = static_cast<UnwindInfo*>(
363*9712c20fSFrederick Mayle ImageRvaToVa(img->FileHeader,
364*9712c20fSFrederick Mayle img->MappedAddress,
365*9712c20fSFrederick Mayle chained_func->UnwindInfoAddress,
366*9712c20fSFrederick Mayle &img->LastRvaSection));
367*9712c20fSFrederick Mayle }
368*9712c20fSFrederick Mayle else {
369*9712c20fSFrederick Mayle unwind_info = NULL;
370*9712c20fSFrederick Mayle }
371*9712c20fSFrederick Mayle } while (unwind_info);
372*9712c20fSFrederick Mayle fprintf(out_file, "STACK CFI INIT %lx %lx .cfa: $rsp .ra: .cfa %lu - ^\n",
373*9712c20fSFrederick Mayle funcs[i].BeginAddress,
374*9712c20fSFrederick Mayle funcs[i].EndAddress - funcs[i].BeginAddress, rip_offset);
375*9712c20fSFrederick Mayle fprintf(out_file, "STACK CFI %lx .cfa: $rsp %lu +\n",
376*9712c20fSFrederick Mayle funcs[i].BeginAddress, stack_size);
377*9712c20fSFrederick Mayle }
378*9712c20fSFrederick Mayle
379*9712c20fSFrederick Mayle return true;
380*9712c20fSFrederick Mayle }
381*9712c20fSFrederick Mayle
GenerateDebugIdentifier(DWORD age,GUID signature)382*9712c20fSFrederick Mayle wstring GenerateDebugIdentifier(DWORD age, GUID signature)
383*9712c20fSFrederick Mayle {
384*9712c20fSFrederick Mayle // Use the same format that the MS symbol server uses in filesystem
385*9712c20fSFrederick Mayle // hierarchies.
386*9712c20fSFrederick Mayle wchar_t age_string[9];
387*9712c20fSFrederick Mayle swprintf(age_string, sizeof(age_string) / sizeof(age_string[0]),
388*9712c20fSFrederick Mayle L"%x", age);
389*9712c20fSFrederick Mayle
390*9712c20fSFrederick Mayle // remove when VC++7.1 is no longer supported
391*9712c20fSFrederick Mayle age_string[sizeof(age_string) / sizeof(age_string[0]) - 1] = L'\0';
392*9712c20fSFrederick Mayle
393*9712c20fSFrederick Mayle wstring debug_identifier = GUIDString::GUIDToSymbolServerWString(&signature);
394*9712c20fSFrederick Mayle debug_identifier.append(age_string);
395*9712c20fSFrederick Mayle
396*9712c20fSFrederick Mayle return debug_identifier;
397*9712c20fSFrederick Mayle }
398*9712c20fSFrederick Mayle
GenerateDebugIdentifier(DWORD age,DWORD signature)399*9712c20fSFrederick Mayle wstring GenerateDebugIdentifier(DWORD age, DWORD signature)
400*9712c20fSFrederick Mayle {
401*9712c20fSFrederick Mayle // Use the same format that the MS symbol server uses in filesystem
402*9712c20fSFrederick Mayle // hierarchies.
403*9712c20fSFrederick Mayle wchar_t identifier_string[17];
404*9712c20fSFrederick Mayle swprintf(identifier_string,
405*9712c20fSFrederick Mayle sizeof(identifier_string) / sizeof(identifier_string[0]),
406*9712c20fSFrederick Mayle L"%08X%x", signature, age);
407*9712c20fSFrederick Mayle
408*9712c20fSFrederick Mayle // remove when VC++7.1 is no longer supported
409*9712c20fSFrederick Mayle identifier_string[sizeof(identifier_string) /
410*9712c20fSFrederick Mayle sizeof(identifier_string[0]) - 1] = L'\0';
411*9712c20fSFrederick Mayle
412*9712c20fSFrederick Mayle return wstring(identifier_string);
413*9712c20fSFrederick Mayle }
414*9712c20fSFrederick Mayle
415*9712c20fSFrederick Mayle } // namespace google_breakpad
416