diff --git a/mozglue/misc/StackWalk.cpp b/mozglue/misc/StackWalk.cpp index 7e54588c620..dbf668cbb83 100644 --- a/mozglue/misc/StackWalk.cpp +++ b/mozglue/misc/StackWalk.cpp @@ -817,7 +817,7 @@ MozDescribeCodeAddress(void* aPC, MozCodeAddressDetails* aDetails) modInfoRes = SymGetModuleInfoEspecial64(myProcess, addr, &modInfo, &lineInfo); if (modInfoRes) { - strncpy(aDetails->library, modInfo.ModuleName, + strncpy(aDetails->library, modInfo.LoadedImageName, sizeof(aDetails->library)); aDetails->library[mozilla::ArrayLength(aDetails->library) - 1] = '\0'; aDetails->loffset = (char*)aPC - (char*)modInfo.BaseOfImage; diff --git a/testing/tools/fileid/moz.build b/testing/tools/fileid/moz.build index b15641bf587..701886f6650 100644 --- a/testing/tools/fileid/moz.build +++ b/testing/tools/fileid/moz.build @@ -4,6 +4,8 @@ # License, v. 2.0. If a copy of the MPL was not distributed with this # file, You can obtain one at http://mozilla.org/MPL/2.0/. +GeckoProgram('fileid', linkage=None, msvcrt='static') + if CONFIG['OS_ARCH'] == 'Linux': USE_LIBS += [ 'breakpad_linux_common_s', @@ -25,4 +27,9 @@ if CONFIG['OS_ARCH'] == 'Linux' or CONFIG['OS_ARCH'] == 'Darwin': LOCAL_INCLUDES += [ '/toolkit/crashreporter/google-breakpad/src', ] - GeckoProgram('fileid', linkage=None) + +if CONFIG['OS_ARCH'] == 'WINNT': + SOURCES += ['win_fileid.cpp'] + OS_LIBS += ['dbghelp'] + +NO_PGO = True diff --git a/testing/tools/fileid/win_fileid.cpp b/testing/tools/fileid/win_fileid.cpp new file mode 100644 index 00000000000..7151baa9238 --- /dev/null +++ b/testing/tools/fileid/win_fileid.cpp @@ -0,0 +1,90 @@ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include +#include +#include +#include + +const DWORD CV_SIGNATURE_RSDS = 0x53445352; // 'SDSR' + +struct CV_INFO_PDB70 { + DWORD CvSignature; + GUID Signature; + DWORD Age; + BYTE PdbFileName[1]; +}; + +void print_guid(const GUID& guid, DWORD age) +{ + printf("%08X%04X%04X%02X%02X%02X%02X%02X%02X%02X%02X%X", + guid.Data1, guid.Data2, guid.Data3, + guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], + guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7], + age); +} + +int main(int argc, char** argv) +{ + if (argc != 2) { + fprintf(stderr, "usage: fileid \n"); + return 1; + } + + HANDLE file = CreateFileA(argv[1], + GENERIC_READ, + FILE_SHARE_READ, + nullptr, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + nullptr); + if (file == INVALID_HANDLE_VALUE) { + fprintf(stderr, "Couldn't open file: %s\n", argv[1]); + return 1; + } + + HANDLE mapFile = CreateFileMappingA(file, NULL, PAGE_READONLY, 0, 0, 0); + if (mapFile == nullptr) { + fprintf(stderr, "Couldn't create file mapping\n"); + CloseHandle(file); + return 1; + } + + uint8_t* base = reinterpret_cast(MapViewOfFile(mapFile, + FILE_MAP_READ, + 0, + 0, + 0)); + if (base == nullptr) { + fprintf(stderr, "Couldn't map file\n"); + CloseHandle(mapFile); + CloseHandle(file); + return 1; + } + + DWORD size; + PIMAGE_DEBUG_DIRECTORY debug_dir = + reinterpret_cast( + ImageDirectoryEntryToDataEx(base, + FALSE, + IMAGE_DIRECTORY_ENTRY_DEBUG, + &size, + nullptr)); + + bool found = false; + if (debug_dir->Type == IMAGE_DEBUG_TYPE_CODEVIEW) { + CV_INFO_PDB70* cv = + reinterpret_cast(base + debug_dir->PointerToRawData); + if (cv->CvSignature == CV_SIGNATURE_RSDS) { + found = true; + print_guid(cv->Signature, cv->Age); + } + } + + UnmapViewOfFile(base); + CloseHandle(mapFile); + CloseHandle(file); + + return found ? 0 : 1; +} diff --git a/tools/rb/fix_stack_using_bpsyms.py b/tools/rb/fix_stack_using_bpsyms.py index ed89345d1bd..156acb5882c 100755 --- a/tools/rb/fix_stack_using_bpsyms.py +++ b/tools/rb/fix_stack_using_bpsyms.py @@ -85,7 +85,14 @@ def findIdForPath(path): # We should always be packaged with a "fileid" executable. fileid_exe = os.path.join(here, 'fileid') if not os.path.isfile(fileid_exe): - raise Exception("Could not find fileid executable in %s" % here) + fileid_exe = fileid_exe + '.exe' + if not os.path.isfile(fileid_exe): + raise Exception("Could not find fileid executable in %s" % here) + + if not os.path.isfile(path): + for suffix in ('.exe', '.dll'): + if os.path.isfile(path + suffix): + path = path + suffix try: return subprocess.check_output([fileid_exe, path]).rstrip() except subprocess.CalledProcessError as e: @@ -96,11 +103,12 @@ def guessSymbolFile(full_path, symbolsDir): """Guess a symbol file based on an object file's basename, ignoring the path and UUID.""" fn = os.path.basename(full_path) d1 = os.path.join(symbolsDir, fn) + root, _ = os.path.splitext(fn) + if os.path.exists(os.path.join(symbolsDir, root) + '.pdb'): + d1 = os.path.join(symbolsDir, root) + '.pdb' + fn = root if not os.path.exists(d1): - fn = fn + ".pdb" - d1 = os.path.join(symbolsDir, fn) - if not os.path.exists(d1): - return None + return None uuids = os.listdir(d1) if len(uuids) == 0: raise Exception("Missing symbol file for " + fn) @@ -108,8 +116,6 @@ def guessSymbolFile(full_path, symbolsDir): uuid = findIdForPath(full_path) else: uuid = uuids[0] - if fn.endswith(".pdb"): - fn = fn[:-4] return os.path.join(d1, uuid, fn + ".sym") parsedSymbolFiles = {}