message: resolve nwn addresses when printing stack traces
diff: #include "Platform/Debug.hpp"
  +#include "Platform/ASLR.hpp"
  #include <cstring>
  #include <cstdio>
  #include <execinfo.h>
  #include <signal.h>
  +#include <map>
  namespace NWNXLib::Platform::Debug {
  @@ -40,43 +42,52 @@ std::string GetStackTrace(uint8_t levels)
  std::strncat(buffer, "\n Backtrace:\n", sizeof(buffer)-1);
  for (int i = 0; i < numCapturedFrames; ++i)
  {
  + uintptr_t addr, addr2;
  char backtraceBuffer[2048];
  std::snprintf(backtraceBuffer, sizeof(backtraceBuffer), " %s\n", resolvedFrames[i]);
  + if (std::sscanf(backtraceBuffer, " ./nwserver-linux(+%lx) [%lx]", &addr, &addr2) == 2)
  + {
  + std::snprintf(backtraceBuffer, sizeof(backtraceBuffer),
  + " ./nwserver-linux(%s) [0x%lx]\n", ResolveAddress(addr).c_str(), addr2);
  + }
  std::strncat(buffer, backtraceBuffer, sizeof(buffer)-1);
  }
  }
  return std::string(buffer);
  }
  -static struct {
  - uintptr_t address;
  - std::string name;
  -} s_FunctionMap[] =
  +static std::map<uintptr_t, std::string> s_FunctionMap;
  +using namespace NWNXLib::Platform::Debug;
  +
  +static void InitFunctionMap()
  {
  + if (s_FunctionMap.size()) return;
  +
  #define NWNXLIB_FUNCTION_NO_VERSION_CHECK
  -#define NWNXLIB_FUNCTION(name, address) { address, #name},
  +#define NWNXLIB_FUNCTION(name, address) s_FunctionMap[address] = #name;
  #include "API/FunctionsLinux.hpp"
  -};
  +}
  -using namespace NWNXLib::Platform::Debug;
  std::string ResolveAddress(uintptr_t address)
  {
  - uint32_t best = 0;
  - for (uint32_t i = 1; i < sizeof(s_FunctionMap) / sizeof(s_FunctionMap[0]); i++)
  - {
  - if (address < s_FunctionMap[i].address && s_FunctionMap[best].address > s_FunctionMap[i].address)
  - best = i;
  - }
  + InitFunctionMap();
  +
  + if (address > ASLR::GetRelocatedAddress(0))
  + address -= ASLR::GetRelocatedAddress(0);
  - return s_FunctionMap[best].name;
  + auto it = --s_FunctionMap.upper_bound(address);
  + char offset[64];
  + std::snprintf(offset, sizeof(offset), "+0x%lx", address - it->first);
  + return it->second + offset;
  }
  uintptr_t GetFunctionAddress(const std::string& mangledname)
  {
  - for (uint32_t i = 0; i < sizeof(s_FunctionMap) / sizeof(s_FunctionMap[0]); i++)
  + InitFunctionMap();
  + for (auto it: s_FunctionMap)
  {
  - if (s_FunctionMap[i].name == mangledname)
  - return s_FunctionMap[i].address;
  + if (it.second == mangledname)
  + return it.first;
  }
  return 0;
  }
  