OLD | NEW |
1 /* Copyright (c) 2008, Google Inc. | 1 /* Copyright (c) 2008, Google Inc. |
2 * All rights reserved. | 2 * All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 17 matching lines...) Expand all Loading... |
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
29 * | 29 * |
30 * --- | 30 * --- |
31 * Author: David Vitek | 31 * Author: David Vitek |
32 * | 32 * |
33 * Dump function addresses using Microsoft debug symbols. This works | 33 * Dump function addresses using Microsoft debug symbols. This works |
34 * on PDB files. Note that this program will download symbols to | 34 * on PDB files. Note that this program will download symbols to |
35 * c:\websymbols without asking. | 35 * c:\websymbols without asking. |
36 */ | 36 */ |
37 | 37 |
| 38 #ifndef WIN32_LEAN_AND_MEAN |
38 #define WIN32_LEAN_AND_MEAN | 39 #define WIN32_LEAN_AND_MEAN |
| 40 #endif |
| 41 |
| 42 #ifndef _CRT_SECURE_NO_WARNINGS |
39 #define _CRT_SECURE_NO_WARNINGS | 43 #define _CRT_SECURE_NO_WARNINGS |
| 44 #endif |
| 45 |
| 46 #ifndef _CRT_SECURE_NO_DEPRECATE |
40 #define _CRT_SECURE_NO_DEPRECATE | 47 #define _CRT_SECURE_NO_DEPRECATE |
| 48 #endif |
41 | 49 |
42 #include <stdio.h> | 50 #include <stdio.h> |
43 #include <stdlib.h> | 51 #include <stdlib.h> |
44 | 52 |
45 #include <windows.h> | 53 #include <windows.h> |
46 #include <dbghelp.h> | 54 #include <dbghelp.h> |
47 | 55 |
48 #define SEARCH_CAP (1024*1024) | 56 #define SEARCH_CAP (1024*1024) |
49 #define WEBSYM "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols" | 57 #define WEBSYM "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols" |
50 | 58 |
51 int main(int argc, char *argv[]) { | 59 int main(int argc, char *argv[]) { |
52 DWORD error; | 60 DWORD error; |
53 HANDLE process; | 61 HANDLE process; |
54 ULONG64 module_base; | 62 ULONG64 module_base; |
55 int i; | 63 int i; |
56 char* search; | 64 char* search; |
57 char buf[256]; /* Enough to hold one hex address, I trust! */ | 65 char buf[256]; /* Enough to hold one hex address, I trust! */ |
58 int rv = 0; | 66 int rv = 0; |
59 /* We may add SYMOPT_UNDNAME if --demangle is specified: */ | 67 /* We may add SYMOPT_UNDNAME if --demangle is specified: */ |
60 DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES; | 68 DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES; |
61 char* filename = "a.out"; /* The default if -e isn't specified */ | 69 char* filename = "a.out"; /* The default if -e isn't specified */ |
62 int print_function_name = 0; /* Set to 1 if -f is specified */ | 70 int print_function_name = 0; /* Set to 1 if -f is specified */ |
63 | 71 |
64 for (i = 1; i < argc; i++) { | 72 for (i = 1; i < argc; i++) { |
65 if (strcmp(argv[i], "--functions") == 0 || strcmp(argv[i], "-f") == 0) { | 73 if (strcmp(argv[i], "--functions") == 0 || strcmp(argv[i], "-f") == 0) { |
66 print_function_name = 1; | 74 print_function_name = 1; |
67 } else if (strcmp(argv[i], "--demangle") == 0 || | 75 } else if (strcmp(argv[i], "--demangle") == 0 || |
68 strcmp(argv[i], "-C") == 0) { | 76 strcmp(argv[i], "-C") == 0) { |
69 symopts |= SYMOPT_UNDNAME; | 77 symopts |= SYMOPT_UNDNAME; |
70 } else if (strcmp(argv[i], "-e") == 0) { | 78 } else if (strcmp(argv[i], "--exe") == 0 || |
| 79 strcmp(argv[i], "-e") == 0) { |
71 if (i + 1 >= argc) { | 80 if (i + 1 >= argc) { |
72 fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n"); | 81 fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n"); |
73 return 1; | 82 return 1; |
74 } | 83 } |
75 filename = argv[i+1]; | 84 filename = argv[i+1]; |
76 i++; /* to skip over filename too */ | 85 i++; /* to skip over filename too */ |
77 } else { | 86 } else { |
78 fprintf(stderr, "usage: " | 87 fprintf(stderr, "usage: " |
79 "addr2line-pdb [-f|--functions] [-C|--demangle] [-e filename]\n"); | 88 "addr2line-pdb [-f|--functions] [-C|--demangle] [-e filename]\n"); |
80 fprintf(stderr, "(Then list the hex addresses on stdin, one per line)\n"); | 89 fprintf(stderr, "(Then list the hex addresses on stdin, one per line)\n"); |
81 exit(1); | 90 exit(1); |
82 } | 91 } |
83 } | 92 } |
84 | 93 |
85 process = GetCurrentProcess(); | 94 process = GetCurrentProcess(); |
86 | 95 |
87 if (!SymInitialize(process, NULL, FALSE)) { | 96 if (!SymInitialize(process, NULL, FALSE)) { |
88 error = GetLastError(); | 97 error = GetLastError(); |
89 fprintf(stderr, "SymInitialize returned error : %d\n", error); | 98 fprintf(stderr, "SymInitialize returned error : %lu\n", error); |
90 return 1; | 99 return 1; |
91 } | 100 } |
92 | 101 |
93 search = malloc(SEARCH_CAP); | 102 search = malloc(SEARCH_CAP); |
94 if (SymGetSearchPath(process, search, SEARCH_CAP)) { | 103 if (SymGetSearchPath(process, search, SEARCH_CAP)) { |
95 if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) { | 104 if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) { |
96 fprintf(stderr, "Search path too long\n"); | 105 fprintf(stderr, "Search path too long\n"); |
97 SymCleanup(process); | 106 SymCleanup(process); |
98 return 1; | 107 return 1; |
99 } | 108 } |
100 strcat(search, ";" WEBSYM); | 109 strcat(search, ";" WEBSYM); |
101 } else { | 110 } else { |
102 error = GetLastError(); | 111 error = GetLastError(); |
103 fprintf(stderr, "SymGetSearchPath returned error : %d\n", error); | 112 fprintf(stderr, "SymGetSearchPath returned error : %lu\n", error); |
104 rv = 1; /* An error, but not a fatal one */ | 113 rv = 1; /* An error, but not a fatal one */ |
105 strcpy(search, WEBSYM); /* Use a default value */ | 114 strcpy(search, WEBSYM); /* Use a default value */ |
106 } | 115 } |
107 if (!SymSetSearchPath(process, search)) { | 116 if (!SymSetSearchPath(process, search)) { |
108 error = GetLastError(); | 117 error = GetLastError(); |
109 fprintf(stderr, "SymSetSearchPath returned error : %d\n", error); | 118 fprintf(stderr, "SymSetSearchPath returned error : %lu\n", error); |
110 rv = 1; /* An error, but not a fatal one */ | 119 rv = 1; /* An error, but not a fatal one */ |
111 } | 120 } |
112 | 121 |
113 SymSetOptions(symopts); | 122 SymSetOptions(symopts); |
114 module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0); | 123 module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0); |
115 if (!module_base) { | 124 if (!module_base) { |
116 /* SymLoadModuleEx failed */ | 125 /* SymLoadModuleEx failed */ |
117 error = GetLastError(); | 126 error = GetLastError(); |
118 fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n", | 127 fprintf(stderr, "SymLoadModuleEx returned error : %lu for %s\n", |
119 error, filename); | 128 error, filename); |
120 SymCleanup(process); | 129 SymCleanup(process); |
121 return 1; | 130 return 1; |
122 } | 131 } |
123 | 132 |
124 buf[sizeof(buf)-1] = '\0'; /* Just to be safe */ | 133 buf[sizeof(buf)-1] = '\0'; /* Just to be safe */ |
125 while (fgets(buf, sizeof(buf)-1, stdin)) { | 134 while (fgets(buf, sizeof(buf)-1, stdin)) { |
126 /* GNU addr2line seems to just do a strtol and ignore any | 135 /* GNU addr2line seems to just do a strtol and ignore any |
127 * weird characters it gets, so we will too. | 136 * weird characters it gets, so we will too. |
128 */ | 137 */ |
129 unsigned __int64 addr = _strtoui64(buf, NULL, 16); | 138 unsigned __int64 reladdr = _strtoui64(buf, NULL, 16); |
130 ULONG64 buffer[(sizeof(SYMBOL_INFO) + | 139 ULONG64 buffer[(sizeof(SYMBOL_INFO) + |
131 MAX_SYM_NAME*sizeof(TCHAR) + | 140 MAX_SYM_NAME*sizeof(TCHAR) + |
132 sizeof(ULONG64) - 1) | 141 sizeof(ULONG64) - 1) |
133 / sizeof(ULONG64)]; | 142 / sizeof(ULONG64)]; |
134 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; | 143 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; |
135 IMAGEHLP_LINE64 line; | 144 IMAGEHLP_LINE64 line; |
136 DWORD dummy; | 145 DWORD dummy; |
| 146 |
| 147 // Just ignore overflow. In an overflow scenario, the resulting address |
| 148 // will be lower than module_base which hasn't been mapped by any prior |
| 149 // SymLoadModuleEx() command. This will cause SymFromAddr() and |
| 150 // SymGetLineFromAddr64() both to return failures and print the correct |
| 151 // ?? and ??:0 message variant. |
| 152 ULONG64 absaddr = reladdr + module_base; |
| 153 |
137 pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); | 154 pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); |
138 pSymbol->MaxNameLen = MAX_SYM_NAME; | 155 pSymbol->MaxNameLen = MAX_SYM_NAME; |
139 if (print_function_name) { | 156 if (print_function_name) { |
140 if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) { | 157 if (SymFromAddr(process, (DWORD64)absaddr, NULL, pSymbol)) { |
141 printf("%s\n", pSymbol->Name); | 158 printf("%s\n", pSymbol->Name); |
142 } else { | 159 } else { |
143 printf("??\n"); | 160 printf("??\n"); |
144 } | 161 } |
145 } | 162 } |
146 line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); | 163 line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); |
147 if (SymGetLineFromAddr64(process, (DWORD64)addr, &dummy, &line)) { | 164 if (SymGetLineFromAddr64(process, (DWORD64)absaddr, &dummy, &line)) { |
148 printf("%s:%d\n", line.FileName, (int)line.LineNumber); | 165 printf("%s:%d\n", line.FileName, (int)line.LineNumber); |
149 } else { | 166 } else { |
150 printf("??:0\n"); | 167 printf("??:0\n"); |
151 } | 168 } |
152 } | 169 } |
153 SymUnloadModule64(process, module_base); | 170 SymUnloadModule64(process, module_base); |
154 SymCleanup(process); | 171 SymCleanup(process); |
155 return rv; | 172 return rv; |
156 } | 173 } |
OLD | NEW |