Merge branch 'upstream-KWSys' into update-kwsys

# By KWSys Upstream
* upstream-KWSys:
  KWSys 2026-08-14 (f87534bd)
This commit is contained in:
Brad King
2026-08-14 06:29:09 -04:00
2 changed files with 69 additions and 17 deletions
+55 -5
View File
@@ -3981,12 +3981,18 @@ std::string SystemInformationImplementation::GetProgramStack(int firstFrame,
void* stack[TRACE_MAX_STACK_FRAMES];
HANDLE process = GetCurrentProcess();
// SymSetOptions affects the process-global symbol handler options, so
// save the caller's options and restore them before returning.
DWORD options = SymGetOptions();
SymSetOptions(options | SYMOPT_UNDNAME | SYMOPT_DEFERRED_LOADS |
SYMOPT_LOAD_LINES);
SymInitialize(process, nullptr, TRUE);
WORD numberOfFrames =
CaptureStackBackTrace(firstFrame, TRACE_MAX_STACK_FRAMES, stack, nullptr);
SYMBOL_INFO* symbol = static_cast<SYMBOL_INFO*>(
malloc(sizeof(SYMBOL_INFO) +
(TRACE_MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR)));
calloc(1,
sizeof(SYMBOL_INFO) +
(TRACE_MAX_FUNCTION_NAME_LENGTH - 1) * sizeof(TCHAR)));
symbol->MaxNameLen = TRACE_MAX_FUNCTION_NAME_LENGTH;
symbol->SizeOfStruct = sizeof(SYMBOL_INFO);
DWORD displacement;
@@ -3994,15 +4000,59 @@ std::string SystemInformationImplementation::GetProgramStack(int firstFrame,
line.SizeOfStruct = sizeof(IMAGEHLP_LINE64);
for (int i = 0; i < numberOfFrames; i++) {
DWORD64 address = reinterpret_cast<DWORD64>(stack[i]);
SymFromAddr(process, address, nullptr, symbol);
if (SymGetLineFromAddr64(process, address, &displacement, &line)) {
DWORD64 symDisplacement = 0;
bool haveName =
SymFromAddr(process, address, &symDisplacement, symbol) != FALSE;
DWORD64 moduleBase = SymGetModuleBase64(process, address);
// When a module has no matching PDB, dbghelp falls back to its export
// table and reports the nearest preceding export, which is generally not
// the (non-exported) function the address really belongs to. Names are
// only exact when real debug info was loaded for the module, so ask the
// module how its symbols were obtained rather than trusting the name.
// Inexact names are still printed, but marked and always accompanied by
// the module-relative address so they cannot be mistaken for the truth.
bool exactName = haveName;
if (exactName) {
IMAGEHLP_MODULE64 moduleInfo;
memset(&moduleInfo, 0, sizeof(moduleInfo));
moduleInfo.SizeOfStruct = sizeof(moduleInfo);
if (!SymGetModuleInfo64(process, address, &moduleInfo) ||
moduleInfo.SymType == SymNone || moduleInfo.SymType == SymExport ||
moduleInfo.SymType == SymDeferred) {
exactName = false;
}
}
if (exactName &&
SymGetLineFromAddr64(process, address, &displacement, &line)) {
oss << " at " << symbol->Name << " in " << line.FileName << " line "
<< line.LineNumber << std::endl;
} else if (exactName) {
oss << " at " << symbol->Name << "+0x" << std::hex << symDisplacement
<< std::dec << std::endl;
} else {
oss << " at " << symbol->Name << std::endl;
// Report the module containing the address together with the offset
// into that module, which is what a disassembler needs, plus the
// nearest export as an approximate location hint when one is known.
wchar_t modulePath[MAX_PATH];
DWORD64 moduleBase = SymGetModuleBase64(process, address);
if (moduleBase &&
GetModuleFileNameW(reinterpret_cast<HMODULE>(moduleBase), modulePath,
MAX_PATH) > 0) {
oss << " at " << modulePath << "+0x" << std::hex
<< (address - moduleBase) << std::dec;
} else {
oss << " at 0x" << std::hex << address << std::dec;
}
if (haveName) {
oss << " (near " << symbol->Name << "+0x" << std::hex
<< symDisplacement << std::dec << ")";
}
oss << std::endl;
}
}
free(symbol);
SymSetOptions(options);
SymCleanup(process);
#else
programStack += ""
+14 -12
View File
@@ -298,7 +298,7 @@ static time_t windows_filetime_to_posix_time(const FILETIME& ft)
typedef KWSYS_NAMESPACE::SystemTools::mode_t mode_t;
# endif
inline int Mkdir(std::string const& dir, mode_t const* mode)
static inline int Mkdir(std::string const& dir, mode_t const* mode)
{
int ret =
_wmkdir(KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str());
@@ -306,12 +306,12 @@ inline int Mkdir(std::string const& dir, mode_t const* mode)
KWSYS_NAMESPACE::SystemTools::SetPermissions(dir, *mode);
return ret;
}
inline int Rmdir(std::string const& dir)
static inline int Rmdir(std::string const& dir)
{
return _wrmdir(
KWSYS_NAMESPACE::Encoding::ToWindowsExtendedPath(dir).c_str());
}
inline char const* Getcwd(char* buf, unsigned int len)
static inline char const* Getcwd(char* buf, unsigned int len)
{
std::vector<wchar_t> w_buf(len);
if (_wgetcwd(&w_buf[0], len)) {
@@ -329,15 +329,16 @@ inline char const* Getcwd(char* buf, unsigned int len)
}
return 0;
}
inline int Chdir(std::string const& dir)
static inline int Chdir(std::string const& dir)
{
// We cannot use ToWindowsExtendedPath here because that causes a
// UNC path to be recorded as the process working directory, and
// can break child processes.
return _wchdir(KWSYS_NAMESPACE::Encoding::ToWide(dir).c_str());
}
inline void Realpath(std::string const& path, std::string& resolved_path,
std::string* errorMessage = nullptr)
static inline void Realpath(std::string const& path,
std::string& resolved_path,
std::string* errorMessage = nullptr)
{
std::wstring tmp = KWSYS_NAMESPACE::Encoding::ToWide(path);
wchar_t fullpath[MAX_PATH];
@@ -372,25 +373,26 @@ inline void Realpath(std::string const& path, std::string& resolved_path,
# include <fcntl.h>
# include <unistd.h>
inline int Mkdir(std::string const& dir, mode_t const* mode)
static inline int Mkdir(std::string const& dir, mode_t const* mode)
{
return mkdir(dir.c_str(), mode ? *mode : 00777);
}
inline int Rmdir(std::string const& dir)
static inline int Rmdir(std::string const& dir)
{
return rmdir(dir.c_str());
}
inline char const* Getcwd(char* buf, unsigned int len)
static inline char const* Getcwd(char* buf, unsigned int len)
{
return getcwd(buf, len);
}
inline int Chdir(std::string const& dir)
static inline int Chdir(std::string const& dir)
{
return chdir(dir.c_str());
}
inline void Realpath(std::string const& path, std::string& resolved_path,
std::string* errorMessage = nullptr)
static inline void Realpath(std::string const& path,
std::string& resolved_path,
std::string* errorMessage = nullptr)
{
char resolved_name[KWSYS_SYSTEMTOOLS_MAXPATH];