Skip to content

[swift-inspect] implement basic GNU/Linux support #77938

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

Merged
merged 21 commits into from
Dec 18, 2024

Conversation

andrurogerz
Copy link
Contributor

@andrurogerz andrurogerz commented Dec 3, 2024

Purpose

Implement support for Linux in the swift-inspect tool. Omits support for heap iteration, for which there is no standard GNU/Linux mechanism (see #63576). Currently supports only 64-bit processes, though minimal changes are required to support 32-bit (elf32 parsing is included).

Overview

  • Extends the existing swift-inspect implementation to support Linux along side the existing Darwin and Windows implementations
  • Excludes DumpArray functionality from Linux builds (does not work without heap iteration)
  • Adds a new SwiftInspectLinux build target with the Linux-specific implementation:
    • Remote process reading using process_vm_readv
    • Memory map parsing of /proc/<pid>/maps
    • Aux vector parsing of /proc/<pid>/auxv used to locate debugger link map
    • Remote process debugger link map parsing to generate the list of modules loaded within the target process
    • Minimal elf32 and elf64 parsing required to read string and symbol tables from executable files
  • Adds a new SwiftInspectLinux/SystemHeaders target to pull-in the required Linux C headers
  • Updates README.md to reflect Linux support

Background

I have a locally working implementation of swift-inspect for Android, and I realized that, other than the heap iteration implementation, it is not Android-specific. This PR extracts the GNU/Linux functionality into stand-alone Linux support.

Linux support has one glaring omission: heap iteration is not supported. There is no standard GNU/Linux heap iteration interface. Further, Linux programs often use alternative heap implementations (scudo, jemalloc, mimalloc, etc) so parsing raw heap structures gets complex (see see #63576). Fortunately, only the dump-arrays and dump-concurrency commands rely on heap iteration-- the other commands work fine without it.

Validation

  • Built with swift build on Fedora Linux (6.11.8-200.fc40.x86_64)
  • Manually tested all commands against a trivial command-line Swift app run with SWIFT_DEBUG_ENABLE_METADATA_ALLOCATION_ITERATION=1 and SWIFT_DEBUG_ENABLE_METADATA_BACKTRACE_LOGGING=1
  • Confirmed backtraces are printed with the --backtrace and --backtrace-long arguments.

Note to reviewers

This is my first non-trivial Swift project, so feedback on Swift style/patterns/etc is appreciated.

@andrurogerz andrurogerz marked this pull request as ready for review December 3, 2024 22:48
@al45tair
Copy link
Contributor

al45tair commented Dec 4, 2024

The ELF code should probably not be here; we should share (and if need be extend) the existing ELF reading code in stdlib/public/Backtracing (which is going to move to stdlib/public/RuntimeModule when I get enough time to finish working on that).

(I know @weissi was encouraging me to move it out into a separate package, which probably does make sense also. But having two sets of it doesn't.)

Copy link
Contributor

@mikeash mikeash left a comment

Choose a reason for hiding this comment

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

I left a few comments, didn't look too deeply into the Linux-specific parts as I don't know that stuff, but it looks great overall.

@andrurogerz
Copy link
Contributor Author

The ELF code should probably not be here; we should share (and if need be extend) the existing ELF reading code in stdlib/public/Backtracing (which is going to move to stdlib/public/RuntimeModule when I get enough time to finish working on that).

@al45tair thanks for pointing out the duplication here. I took a quick look at stdlib/public/Backtracing/Elf.swift and I think it has the functionality needed by swift-inspect for symbol lookup. Do you have any pointers on how share it between the projects? I'm new to Swift and am not sure how to go about that.

@andrurogerz
Copy link
Contributor Author

Thank you @compnerd, @mikeash, and @al45tair for the feedback. I believe I have addressed the bulk of your comments.

I have revised the ELF parsing code to be as small as possible: it contains only what is required for loading symbol tables from ELF64 files. Dropping ELF32 (which wasn't supported yet for other reasons) simplified it quite a bit. Since there is no clear way to share the ELF parsing code with the swift/stdlib/public/Backtracing library right now, I have added a TODO to the new ElfFile.swift file indicating it should be replaced in the future (specifically if/when the internal ELF code is refactored to a public location.

Copy link
Contributor

@mikeash mikeash left a comment

Choose a reason for hiding this comment

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

One more tiny suggestion, looking good!

@andrurogerz
Copy link
Contributor Author

@al45tair do you have any additional thoughts on this PR? It seems worth the minimal code duplication of ELF parsing (I've reduced it to a single 160 line source file) to enable swift-inspect support for Linux and Android (coming next). It can eventually be updated to share the ELF code with the backtrace library if that gets extracted to its own foundation library.

@al45tair
Copy link
Contributor

@andrurogerz I'm OK with it if Mike is; the duplication is something we should aim to remove in the medium to long term, to avoid having to maintain two sets of ELF code, but I have no objection to this going in.

@al45tair
Copy link
Contributor

@swift-ci Please smoke test

1 similar comment
@DougGregor
Copy link
Member

@swift-ci Please smoke test

@andrurogerz
Copy link
Contributor Author

@swift-ci please test

@compnerd
Copy link
Member

@swift-ci please smoke test

@compnerd
Copy link
Member

@swift-ci please smoke test

@andrurogerz
Copy link
Contributor Author

Hm, the Windows test failure doesn't look like it could have been caused by this PR

@DougGregor
Copy link
Member

@swift-ci please smoke test Windows

@compnerd compnerd merged commit ea000d6 into swiftlang:main Dec 18, 2024
3 checks passed
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.

5 participants