addr2line-pdb.c revision 5821806d5e7f356e8fa4b058a389a808ea183019
1/* Copyright (c) 2008, Google Inc. 2 * All rights reserved. 3 * 4 * Redistribution and use in source and binary forms, with or without 5 * modification, are permitted provided that the following conditions are 6 * met: 7 * 8 * * Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * * Redistributions in binary form must reproduce the above 11 * copyright notice, this list of conditions and the following disclaimer 12 * in the documentation and/or other materials provided with the 13 * distribution. 14 * * Neither the name of Google Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived from 16 * this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 29 * 30 * --- 31 * Author: David Vitek 32 * 33 * Dump function addresses using Microsoft debug symbols. This works 34 * on PDB files. Note that this program will download symbols to 35 * c:\websymbols without asking. 36 */ 37 38#define WIN32_LEAN_AND_MEAN 39#define _CRT_SECURE_NO_WARNINGS 40#define _CRT_SECURE_NO_DEPRECATE 41 42#include <stdio.h> 43#include <stdlib.h> 44 45#include <windows.h> 46#include <dbghelp.h> 47 48#define SEARCH_CAP (1024*1024) 49#define WEBSYM "SRV*c:\\websymbols*http://msdl.microsoft.com/download/symbols" 50 51void usage() { 52 fprintf(stderr, "usage: " 53 "addr2line-pdb [-f|--functions] [-C|--demangle] [-e filename]\n"); 54 fprintf(stderr, "(Then list the hex addresses on stdin, one per line)\n"); 55} 56 57int main(int argc, char *argv[]) { 58 DWORD error; 59 HANDLE process; 60 ULONG64 module_base; 61 int i; 62 char* search; 63 char buf[256]; /* Enough to hold one hex address, I trust! */ 64 int rv = 0; 65 /* We may add SYMOPT_UNDNAME if --demangle is specified: */ 66 DWORD symopts = SYMOPT_DEFERRED_LOADS | SYMOPT_DEBUG | SYMOPT_LOAD_LINES; 67 char* filename = "a.out"; /* The default if -e isn't specified */ 68 int print_function_name = 0; /* Set to 1 if -f is specified */ 69 70 for (i = 1; i < argc; i++) { 71 if (strcmp(argv[i], "--functions") == 0 || strcmp(argv[i], "-f") == 0) { 72 print_function_name = 1; 73 } else if (strcmp(argv[i], "--demangle") == 0 || 74 strcmp(argv[i], "-C") == 0) { 75 symopts |= SYMOPT_UNDNAME; 76 } else if (strcmp(argv[i], "-e") == 0) { 77 if (i + 1 >= argc) { 78 fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n"); 79 return 1; 80 } 81 filename = argv[i+1]; 82 i++; /* to skip over filename too */ 83 } else if (strcmp(argv[i], "--help") == 0) { 84 usage(); 85 exit(0); 86 } else { 87 usage(); 88 exit(1); 89 } 90 } 91 92 process = GetCurrentProcess(); 93 94 if (!SymInitialize(process, NULL, FALSE)) { 95 error = GetLastError(); 96 fprintf(stderr, "SymInitialize returned error : %d\n", error); 97 return 1; 98 } 99 100 search = malloc(SEARCH_CAP); 101 if (SymGetSearchPath(process, search, SEARCH_CAP)) { 102 if (strlen(search) + sizeof(";" WEBSYM) > SEARCH_CAP) { 103 fprintf(stderr, "Search path too long\n"); 104 SymCleanup(process); 105 return 1; 106 } 107 strcat(search, ";" WEBSYM); 108 } else { 109 error = GetLastError(); 110 fprintf(stderr, "SymGetSearchPath returned error : %d\n", error); 111 rv = 1; /* An error, but not a fatal one */ 112 strcpy(search, WEBSYM); /* Use a default value */ 113 } 114 if (!SymSetSearchPath(process, search)) { 115 error = GetLastError(); 116 fprintf(stderr, "SymSetSearchPath returned error : %d\n", error); 117 rv = 1; /* An error, but not a fatal one */ 118 } 119 120 SymSetOptions(symopts); 121 module_base = SymLoadModuleEx(process, NULL, filename, NULL, 0, 0, NULL, 0); 122 if (!module_base) { 123 /* SymLoadModuleEx failed */ 124 error = GetLastError(); 125 fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n", 126 error, filename); 127 SymCleanup(process); 128 return 1; 129 } 130 131 buf[sizeof(buf)-1] = '\0'; /* Just to be safe */ 132 while (fgets(buf, sizeof(buf)-1, stdin)) { 133 /* GNU addr2line seems to just do a strtol and ignore any 134 * weird characters it gets, so we will too. 135 */ 136 unsigned __int64 addr = _strtoui64(buf, NULL, 16); 137 ULONG64 buffer[(sizeof(SYMBOL_INFO) + 138 MAX_SYM_NAME*sizeof(TCHAR) + 139 sizeof(ULONG64) - 1) 140 / sizeof(ULONG64)]; 141 PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer; 142 IMAGEHLP_LINE64 line; 143 DWORD dummy; 144 pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO); 145 pSymbol->MaxNameLen = MAX_SYM_NAME; 146 if (print_function_name) { 147 if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) { 148 printf("%s\n", pSymbol->Name); 149 } else { 150 printf("??\n"); 151 } 152 } 153 line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); 154 if (SymGetLineFromAddr64(process, (DWORD64)addr, &dummy, &line)) { 155 printf("%s:%d\n", line.FileName, (int)line.LineNumber); 156 } else { 157 printf("??:0\n"); 158 } 159 } 160 SymUnloadModule64(process, module_base); 161 SymCleanup(process); 162 return rv; 163} 164