Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Resolution of symbols by the server #1009

Open
wants to merge 25 commits into
base: master
Choose a base branch
from

Conversation

GabrielSiliceum
Copy link

The main features in this pull request is to make the server be able to locally resolve the symbol and serialize them in trace file.
For this the client sends his image data to the server.

Why this can be a improvement

  • The client has less work to do.
  • You can resolve symbols in the profiler even if the client machine doesn't have the files containing debug information
  • Less bandwidth used for communication between client and server over time (except at the begin of the recording).
  • Working on unification of the symbols resolution code.
  • By disabling automatic symbol resolution entirely, this can speed up the capture time and size.

Implementation details

  • In the global settings you can specify symbol resolution behaviour (Attempt profiler resolution by profiler, Prevent resolution by application ).
  • Tracy_callstack is now used by Tracy server (in the common folder).
  • Tracy_callstack can use debug GUIDs sent by the client to locate and load symbol information.
  • Only working for Windows right now
    • Designed to work for Linux/mac later on
    • On linux, we already store the GNU build id, so this will be forward compatible
  • Client caches its image information and sends it to the server after the handshake. If new images are loaded later on, a symbol query will be issued (as before) leading to discovery of the module and its debug id will be sent to the server.

Areas of improvements/TODO list

  • Make the resolution of symbols on the server asynchronous (similarly to the symbol worker of the client).
  • Attempt to load debug information using a user-provided path.
  • Provide a way for the user to specify the symbols location from the UI (we can with this make the server totally independent of the client for image caching).
  • ELF/Macho-o resolution by modifying libbacktrace to support resolution of another process. (Apparently not that many modifications required)
  • Rework the content of Tracy_callstack.cpp to provide an API without global state (ie: some "context"/"state" that we could store in the Worker instead of relying on a global cache)
  • Offline symbol resolution (the update program) should use the same mechanism.
    • For now it only uses the image path, never the GUID. This means that you could in theory end up using incorrect symbols (if program was recompiled, OS kernel modules updated, etc).
    • It uses addr2line which is slow and should only serve as a fallback mechanism, after having confirmed the path to the executable matches the one from the capture

The main idea for this feature is to make Tracy more flexible, especially when you can't or don't want the application make the symbol resolution job.

@wolfpld
Copy link
Owner

wolfpld commented Mar 20, 2025

How does the server-side symbol resolution work? Let's say I'm running the server on Linux and the client is a Windows application.

@Lectem
Copy link
Contributor

Lectem commented Mar 20, 2025

For now it will simply fallback to querying the client for the symbols.
We rely on the debug guid (type is known and sent to the server) to ensure we are using the correct symbol file (and also possibly locate it, using symbol servers).

The idea for the first step is to only allow to resolve symbols on the server when the client has a similar executable format (ELF, Macho, PE with pdb). Which means mostly windows ciuld resolve windows, Linux can resolve Linux+Android+... And Macos could resolve macos/ios.

In the future however, I'd like to make it possible to resolve GNU binaries (first elf, macho, perhaps later PE files with mingw) using a windows server too. (The other way is harder since it would require something to replace DbgHelp)
This seems feasible by modifying libbacktrace (or using another library if you're up to it).

@Lectem
Copy link
Contributor

Lectem commented Mar 20, 2025

I also just saw that the CI build is failing, seemingly due to the enum using an underlying type. (weirdly we didn't get this while building on our private CI, probably missed some executable that does not enable c++11)

I'll fix this tomorrow at work, but would like to check with you what the minimal supported version of C++ we should be using (ie: should we not use such enums or should we fix the projects to target c++11?)

Edit: actually after reading the error log again, it could just be that were missing the <stdint.h> include

@@ -1157,7 +1157,8 @@ void SourceView::RenderSymbolView( Worker& worker, View& view )

const auto shortenName = view.GetShortenName();
auto sym = worker.GetSymbolData( m_symAddr );
assert( sym );
if( sym == nullptr ) return; // Might no have received symbol info yet
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

User should be informed why there is nothing displayed.

@@ -36,7 +36,7 @@ namespace tracy
double s_time = 0;

View::View( void(*cbMainThread)(const std::function<void()>&, bool), const char* addr, uint16_t port, ImFont* fixedWidth, ImFont* smallFont, ImFont* bigFont, SetTitleCallback stcb, SetScaleCallback sscb, AttentionCallback acb, const Config& config, AchievementsMgr* amgr )
: m_worker( addr, port, config.memoryLimit == 0 ? -1 : ( config.memoryLimitPercent * tracy::GetPhysicalMemorySize() / 100 ) )
: m_worker( addr, port, config.memoryLimit == 0 ? -1 : ( config.memoryLimitPercent * tracy::GetPhysicalMemorySize() / 100 ), Worker::SymbolResolutionConfig{ config.symbolsAttemptResolutionByServer, config.symbolsPreventResolutionByClient } )
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It feels that the data structure being created here should just accept the config and extract what it needs on its own.

tracy::Worker worker( address, port, memoryLimit );

tracy::Worker::SymbolResolutionConfig symConfig{};
symConfig.m_attemptResolutionByWorker = false;
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the reason for setting this explicitly?

@@ -13,7 +13,7 @@
#endif

#ifndef TracyLine
# define TracyLine __LINE__
# define TracyLine TracyConcat(__LINE__,U) // MSVC Edit and continue __LINE__ is non-constant. See https://developercommunity.visualstudio.com/t/-line-cannot-be-used-as-an-argument-for-constexpr/195665
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does this do?

#ifdef _MSC_VER
# pragma comment(lib, "ws2_32.lib")
# pragma comment(lib, "dbghelp.lib")
Copy link
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How are all these removals handled now? They are still needed, aren't they?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants