Build addr2line-pdb from tcmalloc for use in memory-infra symbolization

The memory-infra tools were first written on linux where the
symbolization was done using addr2line. Turns out tcmalloc has some old
code (with a few small bugs) that wraps the windows dbghelp.dll
symbolization APIs in an addr2line-like interface called addr2line-pdb.

This CL
  * fixes the small format string bugs
  * makes the windows library configuration #defines more friendly
    for chromium build
  * modifies addr2line to expect addresses relative to DllBase to better
    simulate how addr2line works with modules in linux.

The last point is important. Windows DLL have a concept of "default load
address" which hints to the OS where to load the binary image after
relocation. The dbghelp.dll symbolization library will load the module
at this location in the virtual address space meaning the caller of
these functions would need to be aware of the base address. This makes
things unnecessarily complex in the face of ASLR and also diverges from
the behavior of addr2line when used with linux-style DSOs. This CL
simply adds the module base address to the incoming addresses thereby
making the input relative addresses for the module which both is easier
to use and lines up better with linux's addr2line behavior.

BUG=694792

Review-Url: https://codereview.chromium.org/2730473002
Cr-Original-Commit-Position: refs/heads/master@{#457271}
Cr-Mirrored-From: https://chromium.googlesource.com/chromium/src
Cr-Mirrored-Commit: bf193279edce86f900ae5b222dc93ea427ae1ff0
diff --git a/src/windows/addr2line-pdb.c b/src/windows/addr2line-pdb.c
index 97b614b..7a2bf3e 100644
--- a/src/windows/addr2line-pdb.c
+++ b/src/windows/addr2line-pdb.c
@@ -35,9 +35,17 @@
  * c:\websymbols without asking.
  */
 
+#ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN
+#endif 
+
+#ifndef _CRT_SECURE_NO_WARNINGS
 #define _CRT_SECURE_NO_WARNINGS
+#endif 
+
+#ifndef _CRT_SECURE_NO_DEPRECATE
 #define _CRT_SECURE_NO_DEPRECATE
+#endif
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -67,7 +75,8 @@
     } else if (strcmp(argv[i], "--demangle") == 0 ||
                strcmp(argv[i], "-C") == 0) {
       symopts |= SYMOPT_UNDNAME;
-    } else if (strcmp(argv[i], "-e") == 0) {
+    } else if (strcmp(argv[i], "--exe") == 0 ||
+               strcmp(argv[i], "-e") == 0) {
       if (i + 1 >= argc) {
         fprintf(stderr, "FATAL ERROR: -e must be followed by a filename\n");
         return 1;
@@ -86,7 +95,7 @@
 
   if (!SymInitialize(process, NULL, FALSE)) {
     error = GetLastError();
-    fprintf(stderr, "SymInitialize returned error : %d\n", error);
+    fprintf(stderr, "SymInitialize returned error : %lu\n", error);
     return 1;
   }
 
@@ -100,13 +109,13 @@
     strcat(search, ";" WEBSYM);
   } else {
     error = GetLastError();
-    fprintf(stderr, "SymGetSearchPath returned error : %d\n", error);
+    fprintf(stderr, "SymGetSearchPath returned error : %lu\n", error);
     rv = 1;                   /* An error, but not a fatal one */
     strcpy(search, WEBSYM);   /* Use a default value */
   }
   if (!SymSetSearchPath(process, search)) {
     error = GetLastError();
-    fprintf(stderr, "SymSetSearchPath returned error : %d\n", error);
+    fprintf(stderr, "SymSetSearchPath returned error : %lu\n", error);
     rv = 1;                   /* An error, but not a fatal one */
   }
 
@@ -115,7 +124,7 @@
   if (!module_base) {
     /* SymLoadModuleEx failed */
     error = GetLastError();
-    fprintf(stderr, "SymLoadModuleEx returned error : %d for %s\n",
+    fprintf(stderr, "SymLoadModuleEx returned error : %lu for %s\n",
             error, filename);
     SymCleanup(process);
     return 1;
@@ -126,7 +135,7 @@
     /* GNU addr2line seems to just do a strtol and ignore any
      * weird characters it gets, so we will too.
      */
-    unsigned __int64 addr = _strtoui64(buf, NULL, 16);
+    unsigned __int64 reladdr = _strtoui64(buf, NULL, 16);
     ULONG64 buffer[(sizeof(SYMBOL_INFO) +
                     MAX_SYM_NAME*sizeof(TCHAR) +
                     sizeof(ULONG64) - 1)
@@ -134,17 +143,25 @@
     PSYMBOL_INFO pSymbol = (PSYMBOL_INFO)buffer;
     IMAGEHLP_LINE64 line;
     DWORD dummy;
+
+    // Just ignore overflow. In an overflow scenario, the resulting address
+    // will be lower than module_base which hasn't been mapped by any prior
+    // SymLoadModuleEx() command. This will cause SymFromAddr() and
+    // SymGetLineFromAddr64() both to return failures and print the correct
+    // ?? and ??:0 message variant.
+    ULONG64 absaddr = reladdr + module_base;
+
     pSymbol->SizeOfStruct = sizeof(SYMBOL_INFO);
     pSymbol->MaxNameLen = MAX_SYM_NAME;
     if (print_function_name) {
-      if (SymFromAddr(process, (DWORD64)addr, NULL, pSymbol)) {
+      if (SymFromAddr(process, (DWORD64)absaddr, NULL, pSymbol)) {
         printf("%s\n", pSymbol->Name);
       } else {
         printf("??\n");
       }
     }
     line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
-    if (SymGetLineFromAddr64(process, (DWORD64)addr, &dummy, &line)) {
+    if (SymGetLineFromAddr64(process, (DWORD64)absaddr, &dummy, &line)) {
       printf("%s:%d\n", line.FileName, (int)line.LineNumber);
     } else {
       printf("??:0\n");