@@ -537,6 +537,157 @@ the pipeline. Here is a quick summary of the various options:
537537 When printing IR for functions for print-[ before|after] -all options, Only
538538 print the IR for functions whose name is in this comma separated list.
539539
540+ ## Debugging assembly and object code
541+
542+ Understanding layout of compiler-generated metadata
543+ can sometimes involve looking at assembly and object code.
544+
545+ ### Working with a single file
546+
547+ Here's how to generate assembly or object code:
548+
549+ ```
550+ # Emit assembly in Intel syntax (AT&T syntax is the default)
551+ swiftc tmp.swift -emit-assembly -Xllvm -x86-asm-syntax=intel -o tmp.S
552+
553+ # Emit object code
554+ swiftc tmp.swift -emit-object -o tmp.o
555+ ```
556+
557+ Understanding mangled names can be hard though: ` swift demangle ` to the rescue!
558+
559+ ```
560+ swiftc tmp.swift -emit-assembly -Xllvm -x86-asm-syntax=intel -o - \
561+ | swift demangle > tmp-demangled.S
562+
563+ swiftc tmp.swift -emit-object -o tmp.o
564+
565+ # Look at where different symbols are located, sorting by address (-n)
566+ # and displaying section names (-m)
567+ nm -n -m tmp.o | swift demangle > tmp.txt
568+
569+ # Inspect disassembly of an existing dylib (AT&T syntax is the default)
570+ objdump -d -macho --x86-asm-syntax=intel /path/to/libcake.dylib \
571+ | swift demangle > libcake.S
572+ ```
573+
574+ ### Working with multiple files
575+
576+ Some bugs only manifest in WMO, and may involve complicated Xcode projects.
577+ Moreover, Xcode may be passing arguments via ` -filelist `
578+ and expecting outputs via ` -output-filelist ` , and those file lists
579+ may be in temporary directories.
580+
581+ If you want to inspect assembly or object code for individual files when
582+ compiling under WMO, you can mimic this by doing the following:
583+
584+ ```
585+ # Assuming all .swift files from the MyProject/Sources directory
586+ # need to be included
587+ find MyProject/Sources -name '*.swift' -type f > input-files.txt
588+
589+ # In some cases, projects may use multiple files with the same
590+ # name but in different directories (for different schemes),
591+ # which can be a problem. Having a file list makes working around
592+ # this convenient as you can manually manually edit out the files
593+ # that are not of interest at this stage.
594+
595+ mkdir Output
596+
597+ # 1. -output-filelist doesn't recreate a subdirectory structure,
598+ # so first strip out directories
599+ # 2. map .swift files to assembly files
600+ sed -e 's|.*/|Output/|;s|\.swift|.S|' input-files.txt > output-files.txt
601+
602+ # Save command-line arguments from Xcode's 'CompileSwiftSources' phase in
603+ # the build log to a file for convenience, say args.txt.
604+ #
605+ # -sdk /path/to/sdk <... other args ...>
606+
607+ xcrun swift-frontend @args.txt \
608+ -filelist input-files.txt \
609+ -output-filelist output-files.txt \
610+ -O -whole-module-optimization \
611+ -emit-assembly
612+ ```
613+
614+ If you are manually calling ` swift-frontend ` without an Xcode invocation to
615+ use as a template, you will need to at least add
616+ ` -sdk "$(xcrun --show-sdk-path macosx)" ` (if compiling for macOS),
617+ and ` -I /path/to/includedir ` to include necessary swift modules and interfaces.
618+
619+ ### Working with multi-architecture binaries
620+
621+ On macOS, one might be interested in debugging multi-architecture binaries
622+ such as [ universal binaries] [ ] . By default ` nm ` will show symbols from all
623+ architectures, so a universal binary might look funny due to two copies of
624+ everything. Use ` nm -arch ` to look at a specific architecture:
625+
626+ ```
627+ nm -n -m -arch x86_64 path/to/libcake.dylib | swift demangle
628+ ```
629+
630+ [ universal binaries ] : https://en.wikipedia.org/wiki/Universal_binary
631+
632+ ### Other helpful tools
633+
634+ TODO: This section should mention information about non-macOS platforms:
635+ maybe we can have a table with rows for use cases and columns for
636+ platforms (macOS, Linux, Windows), and the cells would be tool names.
637+ We could also mention platforms next to the tool names.
638+
639+ In the previous sub-sections, we've seen how using different tools can
640+ make working with assembly and object code much nicer. Here is a short
641+ listing of commonly used tools on macOS, along with some example use cases:
642+
643+ - Miscellaneous:
644+ - ` strings ` : Find printable strings in a binary file.
645+ - Potential use cases: If you're building a binary in multiple configurations,
646+ and forgot which binary corresponds to which configuration, you can look
647+ through the output of ` strings ` to identify differences.
648+ - ` c++filt ` : The C++ equivalent of ` swift-demangle ` .
649+ - Potential use cases: Looking at the generated code for the
650+ Swift runtime, investigating C++ interop issues.
651+
652+ - Linking:
653+ - ` libtool ` : A tool to create static and dynamic libraries. Generally, it's
654+ easier to instead ask ` swiftc ` to link files, but potentially handy as
655+ a higher-level alternative to ` ld ` , ` ar ` and ` lipo ` .
656+
657+ - Debug info:
658+ - ` dwarfdump ` : Extract debug info in human-readable form.
659+ - Potential use cases: If you want to quickly check if two binaries
660+ are identical, you can compare their UUIDs. For on-disk binaries,
661+ you can obtain the UUID using ` dwarfdump --uuid ` For binaries
662+ loaded by a running application, you can obtain the UUID using
663+ ` image list ` in LLDB.
664+ - ` objdump ` : Dump object files.
665+ Some examples of using ` objdump ` are documented in the previous subsection.
666+ If you have a Swift compiler build, you can use ` llvm-objdump ` from
667+ ` $LLVM_BUILD_DIR/bin ` instead of using the system ` objdump ` .
668+
669+ Compared to other tools on this list, ` objdump ` packs a LOT of
670+ functionality; it can show information about sections, relocations
671+ and more. It also supports many flags to format and filter the output.
672+
673+ - Linker information (symbol table, sections, binding):
674+ - ` nm ` : Display symbol tables.
675+ Some examples of using ` nm ` are documented in the previous subsection.
676+ - ` size ` : Get high-level information about sections in a binary,
677+ such as the sizes of sections and where they are located.
678+ - ` dyldinfo ` : Display information used by dyld, such as which dylibs
679+ an image depends on.
680+ - ` install_name_tool ` : Change the name for a dynamic shared library,
681+ and query or modify the runpath search paths (aka 'rpaths') it uses.
682+
683+ - Multi-architecture binaries:
684+ - ` lipo ` : A tool that can be used to create, inspect and dissect
685+ [ universal binaries] [ universal binaries ] .
686+ - Potential use cases: If you have a universal binary on an
687+ Apple Silicon Mac, but want to quickly test if the issue would reproduce
688+ on ` x86_64 ` , you can extract the ` x86_64 ` slice by using ` lipo ` .
689+ The ` x86_64 ` binary will automatically run under Rosetta 2.
690+
540691## Bisecting Compiler Errors
541692
542693### Bisecting on SIL optimizer pass counts to identify optimizer bugs
0 commit comments