| author | |
| committer | |
| log | 3e08b3a4f89ee8e6102fcc67fc7e77c5e3eba104 |
| tree | e45ce5ccef05c44a202de42901bb3513ac0b178b |
| parent | 91baa574a5f7224b48e4499a9db0c5283d800ec3 |
| signature | Commit is signed but in an unrecognized format. |
713 files changed, 20169 insertions(+), 5796 deletions(-)
CMakeLists.txt+4-1| ... | ... | @@ -113,6 +113,7 @@ else() |
| 113 | 113 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/MachO/WriterMachO.cpp" |
| 114 | 114 | "${CMAKE_SOURCE_DIR}/deps/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp" |
| 115 | 115 | ) |
| 116 | ||
| 116 | 117 | set(EMBEDDED_LLD_ELF_SOURCES |
| 117 | 118 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/AArch64ErrataFix.cpp" |
| 118 | 119 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/AArch64.cpp" |
| ... | ... | @@ -120,19 +121,21 @@ else() |
| 120 | 121 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/ARM.cpp" |
| 121 | 122 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/AVR.cpp" |
| 122 | 123 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/Hexagon.cpp" |
| 124 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/MSP430.cpp" | |
| 123 | 125 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/Mips.cpp" |
| 124 | 126 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/MipsArchTree.cpp" |
| 125 | 127 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/PPC.cpp" |
| 126 | 128 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/PPC64.cpp" |
| 129 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/RISCV.cpp" | |
| 127 | 130 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/SPARCV9.cpp" |
| 128 | 131 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/X86.cpp" |
| 129 | 132 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Arch/X86_64.cpp" |
| 130 | 133 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/CallGraphSort.cpp" |
| 134 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/DWARF.cpp" | |
| 131 | 135 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Driver.cpp" |
| 132 | 136 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/DriverUtils.cpp" |
| 133 | 137 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/EhFrame.cpp" |
| 134 | 138 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Filesystem.cpp" |
| 135 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/GdbIndex.cpp" | |
| 136 | 139 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/ICF.cpp" |
| 137 | 140 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputFiles.cpp" |
| 138 | 141 | "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputSection.cpp" |
deps/lld-prebuilt/COFF/Options.inc+17-14| ... | ... | @@ -55,10 +55,8 @@ OPTION(prefix_2, "color-diagnostics=", color_diagnostics_eq, Joined, INVALID, IN |
| 55 | 55 | "Use colors in diagnostics; one of 'always', 'never', 'auto'", nullptr, nullptr) |
| 56 | 56 | OPTION(prefix_2, "color-diagnostics", color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 57 | 57 | "Use colors in diagnostics", nullptr, nullptr) |
| 58 | OPTION(prefix_1, "debug:dwarf", debug_dwarf, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 59 | OPTION(prefix_1, "debug:full", debug_full, Flag, INVALID, debug, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 60 | OPTION(prefix_1, "debug:ghash", debug_ghash, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 61 | OPTION(prefix_1, "debug:symtab", debug_symtab, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 58 | OPTION(prefix_1, "debug:", debug_opt, Joined, INVALID, INVALID, nullptr, 0, 0, | |
| 59 | "Embed a symbol table in the image with option", nullptr, nullptr) | |
| 62 | 60 | OPTION(prefix_1, "debugtype:", debugtype, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 63 | 61 | "Debug Info Options", nullptr, nullptr) |
| 64 | 62 | OPTION(prefix_1, "debug", debug, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | ... | @@ -95,9 +93,12 @@ OPTION(prefix_1, "fixed:no", fixed_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 95 | 93 | "Enable base relocations (default)", nullptr, nullptr) |
| 96 | 94 | OPTION(prefix_1, "fixed", fixed, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 97 | 95 | "Disable base relocations", nullptr, nullptr) |
| 98 | OPTION(prefix_1, "force:unresolved", force_unresolved, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 99 | OPTION(prefix_1, "force", force, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 96 | OPTION(prefix_1, "force:multiple", force_multiple, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 97 | "Allow multiply defined symbols when creating executables", nullptr, nullptr) | |
| 98 | OPTION(prefix_1, "force:unresolved", force_unresolved, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 100 | 99 | "Allow undefined symbols when creating executables", nullptr, nullptr) |
| 100 | OPTION(prefix_1, "force", force, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 101 | "Allow undefined and multiply defined symbols when creating executables", nullptr, nullptr) | |
| 101 | 102 | OPTION(prefix_1, "functionpadmin", functionpadmin, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 102 | 103 | OPTION(prefix_1, "guard:", guard, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 103 | 104 | "Control flow guard", nullptr, nullptr) |
| ... | ... | @@ -148,30 +149,32 @@ OPTION(prefix_1, "lldsavetemps", lldsavetemps, Flag, INVALID, INVALID, nullptr, |
| 148 | 149 | OPTION(prefix_1, "machine:", machine, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 149 | 150 | "Specify target platform", nullptr, nullptr) |
| 150 | 151 | OPTION(prefix_1, "manifest:", manifest_colon, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 151 | "Create manifest file", nullptr, nullptr) | |
| 152 | "NO disables manifest output; EMBED[,ID=#] embeds manifest as resource in the image", nullptr, nullptr) | |
| 152 | 153 | OPTION(prefix_1, "manifestdependency:", manifestdependency, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 153 | "Attributes for <dependency> in manifest file", nullptr, nullptr) | |
| 154 | "Attributes for <dependency> element in manifest file; implies /manifest", nullptr, nullptr) | |
| 154 | 155 | OPTION(prefix_1, "manifestfile:", manifestfile, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 155 | "Manifest file path", nullptr, nullptr) | |
| 156 | "Manifest output path, with /manifest", nullptr, nullptr) | |
| 156 | 157 | OPTION(prefix_1, "manifestinput:", manifestinput, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 157 | "Specify manifest file", nullptr, nullptr) | |
| 158 | "Additional manifest inputs; only valid with /manifest:embed", nullptr, nullptr) | |
| 158 | 159 | OPTION(prefix_1, "manifestuac:", manifestuac, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 159 | 160 | "User access control", nullptr, nullptr) |
| 160 | OPTION(prefix_1, "manifest", manifest, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 161 | OPTION(prefix_1, "manifest", manifest, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 162 | "Create .manifest file", nullptr, nullptr) | |
| 161 | 163 | OPTION(prefix_1, "maxilksize:", maxilksize, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 162 | 164 | OPTION(prefix_1, "merge:", merge, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 163 | 165 | "Combine sections", nullptr, nullptr) |
| 164 | 166 | OPTION(prefix_1, "mllvm:", mllvm, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 165 | 167 | "Options to pass to LLVM", nullptr, nullptr) |
| 166 | OPTION(prefix_1, "msvclto", msvclto, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 167 | 168 | OPTION(prefix_1, "natvis:", natvis, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 168 | 169 | "Path to natvis file to embed in the PDB", nullptr, nullptr) |
| 169 | 170 | OPTION(prefix_1, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 170 | 171 | "Do not use colors in diagnostics", nullptr, nullptr) |
| 171 | 172 | OPTION(prefix_1, "nodefaultlib:", nodefaultlib, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 172 | 173 | "Remove a default library", nullptr, nullptr) |
| 173 | OPTION(prefix_1, "nodefaultlib", nodefaultlib_all, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 174 | OPTION(prefix_1, "noentry", noentry, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 174 | OPTION(prefix_1, "nodefaultlib", nodefaultlib_all, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 175 | "Remove all default libraries", nullptr, nullptr) | |
| 176 | OPTION(prefix_1, "noentry", noentry, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 177 | "Don't add reference to DllMainCRTStartup; only valid with /dll", nullptr, nullptr) | |
| 175 | 178 | OPTION(prefix_1, "nologo", nologo, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 176 | 179 | OPTION(prefix_1, "nxcompat:no", nxcompat_no, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 177 | 180 | "Disable data execution provention", nullptr, nullptr) |
deps/lld-prebuilt/ELF/Options.inc+19-1| ... | ... | @@ -62,6 +62,8 @@ OPTION(prefix_1, "b", anonymous_16, Separate, INVALID, format, nullptr, 0, 0, |
| 62 | 62 | OPTION(prefix_2, "call-graph-ordering-file=", call_graph_ordering_file_eq, Joined, INVALID, call_graph_ordering_file, nullptr, 0, 0, |
| 63 | 63 | "Layout sections to optimize the given callgraph", nullptr, nullptr) |
| 64 | 64 | OPTION(prefix_2, "call-graph-ordering-file", call_graph_ordering_file, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 65 | OPTION(prefix_2, "call-graph-profile-sort", call_graph_profile_sort, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 66 | "Reorder sections with call graph profile (default)", nullptr, nullptr) | |
| 65 | 67 | OPTION(prefix_2, "call_shared", anonymous_1, Flag, INVALID, Bdynamic, nullptr, 0, 0, |
| 66 | 68 | "Alias for --Bdynamic", nullptr, nullptr) |
| 67 | 69 | OPTION(prefix_2, "check-sections", check_sections, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | ... | @@ -133,7 +135,7 @@ OPTION(prefix_2, "exclude-libs=", exclude_libs_eq, Joined, INVALID, exclude_libs |
| 133 | 135 | "Exclude static libraries from automatic export", nullptr, nullptr) |
| 134 | 136 | OPTION(prefix_2, "exclude-libs", exclude_libs, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 135 | 137 | OPTION(prefix_2, "execute-only", execute_only, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 136 | "Do not mark executable sections readable", nullptr, nullptr) | |
| 138 | "Mark executable sections unreadable", nullptr, nullptr) | |
| 137 | 139 | OPTION(prefix_2, "export-dynamic-symbol=", export_dynamic_symbol_eq, Joined, INVALID, export_dynamic_symbol, nullptr, 0, 0, |
| 138 | 140 | "Put a symbol in the dynamic symbol table", nullptr, nullptr) |
| 139 | 141 | OPTION(prefix_2, "export-dynamic-symbol", export_dynamic_symbol, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| ... | ... | @@ -245,6 +247,8 @@ OPTION(prefix_2, "no-apply-dynamic-relocs", no_apply_dynamic_relocs, Flag, INVAL |
| 245 | 247 | "Do not apply link-time values for dynamic relocations (default)", nullptr, nullptr) |
| 246 | 248 | OPTION(prefix_2, "no-as-needed", no_as_needed, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 247 | 249 | "Always set DT_NEEDED for shared libraries (default)", nullptr, nullptr) |
| 250 | OPTION(prefix_2, "no-call-graph-profile-sort", no_call_graph_profile_sort, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 251 | "Do not reorder sections with call graph profile", nullptr, nullptr) | |
| 248 | 252 | OPTION(prefix_2, "no-check-sections", no_check_sections, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 249 | 253 | "Do not check section addresses for overlaps", nullptr, nullptr) |
| 250 | 254 | OPTION(prefix_2, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | ... | @@ -291,6 +295,8 @@ OPTION(prefix_2, "no-rosegment", no_rosegment, Flag, INVALID, INVALID, nullptr, |
| 291 | 295 | "Do not put read-only non-executable sections in their own segment", nullptr, nullptr) |
| 292 | 296 | OPTION(prefix_2, "no-threads", no_threads, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 293 | 297 | "Do not run the linker multi-threaded", nullptr, nullptr) |
| 298 | OPTION(prefix_2, "no-toc-optimize", no_toc_optimize, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 299 | "(PowerPC64) Disable TOC related optimizations", nullptr, nullptr) | |
| 294 | 300 | OPTION(prefix_2, "no-undefined-version", no_undefined_version, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 295 | 301 | "Report version scripts that refer undefined symbols", nullptr, nullptr) |
| 296 | 302 | OPTION(prefix_2, "no-undefined", no_undefined, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | ... | @@ -301,6 +307,8 @@ OPTION(prefix_2, "no-warn-backrefs", no_warn_backrefs, Flag, INVALID, INVALID, n |
| 301 | 307 | "Do not warn about backward symbol references to fetch archive members (default)", nullptr, nullptr) |
| 302 | 308 | OPTION(prefix_2, "no-warn-common", no_warn_common, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 303 | 309 | "Do not warn about duplicate common symbols (default)", nullptr, nullptr) |
| 310 | OPTION(prefix_2, "no-warn-ifunc-textrel", no_warn_ifunc_textrel, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 311 | "Do not warn about using ifunc symbols with text relocations (default)", nullptr, nullptr) | |
| 304 | 312 | OPTION(prefix_2, "no-warn-mismatch", anonymous_57, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 305 | 313 | OPTION(prefix_2, "no-warn-symbol-ordering", no_warn_symbol_ordering, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 306 | 314 | "Do not warn about problems with the symbol ordering file", nullptr, nullptr) |
| ... | ... | @@ -338,6 +346,8 @@ OPTION(prefix_2, "pack-dyn-relocs=", pack_dyn_relocs_eq, Joined, INVALID, pack_d |
| 338 | 346 | OPTION(prefix_2, "pack-dyn-relocs", pack_dyn_relocs, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "[none,android,relr,android+relr]", nullptr) |
| 339 | 347 | OPTION(prefix_2, "pic-executable", anonymous_23, Flag, INVALID, pie, nullptr, 0, 0, |
| 340 | 348 | "Alias for --pie", nullptr, nullptr) |
| 349 | OPTION(prefix_2, "pic-veneer", pic_veneer, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 350 | "Always generate position independent thunks (veneers)", nullptr, nullptr) | |
| 341 | 351 | OPTION(prefix_2, "pie", pie, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 342 | 352 | "Create a position independent executable", nullptr, nullptr) |
| 343 | 353 | OPTION(prefix_2, "plugin-opt=-fresolution=", plugin_opt_fresolution_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| ... | ... | @@ -349,6 +359,7 @@ OPTION(prefix_2, "plugin-opt=disable-verify", anonymous_41, Flag, INVALID, disab |
| 349 | 359 | "Alias for -disable-verify", nullptr, nullptr) |
| 350 | 360 | OPTION(prefix_2, "plugin-opt=dwo_dir=", plugin_opt_dwo_dir_eq, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 351 | 361 | "Directory to store .dwo files when LTO and debug fission are used", nullptr, nullptr) |
| 362 | OPTION(prefix_2, "plugin-opt=emit-llvm", plugin_opt_emit_llvm, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 352 | 363 | OPTION(prefix_2, "plugin-opt=jobs=", anonymous_42, Joined, INVALID, thinlto_jobs, nullptr, 0, 0, |
| 353 | 364 | "Alias for -thinlto-jobs", nullptr, nullptr) |
| 354 | 365 | OPTION(prefix_2, "plugin-opt=lto-partitions=", anonymous_43, Joined, INVALID, lto_partitions, nullptr, 0, 0, |
| ... | ... | @@ -424,6 +435,9 @@ OPTION(prefix_2, "sort-common", anonymous_60, Flag, INVALID, INVALID, nullptr, 0 |
| 424 | 435 | OPTION(prefix_2, "sort-section=", sort_section_eq, Joined, INVALID, sort_section, nullptr, 0, 0, |
| 425 | 436 | "Specifies sections sorting rule when linkerscript is used", nullptr, nullptr) |
| 426 | 437 | OPTION(prefix_2, "sort-section", sort_section, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 438 | OPTION(prefix_2, "split-stack-adjust-size=", split_stack_adjust_size_eq, Joined, INVALID, split_stack_adjust_size, nullptr, 0, 0, | |
| 439 | "Specify adjustment to stack size when a split-stack function calls a non-split-stack function", "<value>", nullptr) | |
| 440 | OPTION(prefix_2, "split-stack-adjust-size", split_stack_adjust_size, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<value>", nullptr) | |
| 427 | 441 | OPTION(prefix_2, "start-group", start_group, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 428 | 442 | "Ignored for compatibility with GNU unless you pass --warn-backrefs", nullptr, nullptr) |
| 429 | 443 | OPTION(prefix_2, "start-lib", start_lib, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | ... | @@ -467,6 +481,8 @@ OPTION(prefix_2, "thinlto-jobs=", thinlto_jobs, Joined, INVALID, INVALID, nullpt |
| 467 | 481 | "Number of ThinLTO jobs", nullptr, nullptr) |
| 468 | 482 | OPTION(prefix_2, "threads", threads, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 469 | 483 | "Run the linker multi-threaded (default)", nullptr, nullptr) |
| 484 | OPTION(prefix_2, "toc-optimize", toc_optimize, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 485 | "(PowerPC64) Enable TOC related optimizations (default)", nullptr, nullptr) | |
| 470 | 486 | OPTION(prefix_2, "trace-symbol=", trace_symbol_eq, Joined, INVALID, trace_symbol, nullptr, 0, 0, |
| 471 | 487 | "Trace references to symbols", nullptr, nullptr) |
| 472 | 488 | OPTION(prefix_2, "trace-symbol", trace_symbol, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| ... | ... | @@ -511,6 +527,8 @@ OPTION(prefix_2, "warn-backrefs", warn_backrefs, Flag, INVALID, INVALID, nullptr |
| 511 | 527 | OPTION(prefix_2, "warn-common", warn_common, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 512 | 528 | "Warn about duplicate common symbols", nullptr, nullptr) |
| 513 | 529 | OPTION(prefix_2, "warn-execstack", anonymous_62, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 530 | OPTION(prefix_2, "warn-ifunc-textrel", warn_ifunc_textrel, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 531 | "Warn about using ifunc symbols with text relocations", nullptr, nullptr) | |
| 514 | 532 | OPTION(prefix_2, "warn-once", anonymous_63, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 515 | 533 | OPTION(prefix_2, "warn-shared-textrel", anonymous_64, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 516 | 534 | OPTION(prefix_2, "warn-symbol-ordering", warn_symbol_ordering, Flag, INVALID, INVALID, nullptr, 0, 0, |
deps/lld-prebuilt/MinGW/Options.inc+7| ... | ... | @@ -90,6 +90,13 @@ OPTION(prefix_1, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, |
| 90 | 90 | OPTION(prefix_2, "pdb", pdb, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 91 | 91 | "Specify output PDB debug information file", nullptr, nullptr) |
| 92 | 92 | OPTION(prefix_2, "pic-executable", pic_executable, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 93 | OPTION(prefix_2, "plugin-opt=", anonymous_3, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 94 | OPTION(prefix_2, "plugin-opt", anonymous_2, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 95 | OPTION(prefix_2, "plugin=", anonymous_1, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 96 | OPTION(prefix_2, "plugin", anonymous_0, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 97 | OPTION(prefix_2, "require-defined=", require_defined_eq, Joined, INVALID, require_defined, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 98 | OPTION(prefix_2, "require-defined", require_defined, Separate, INVALID, INVALID, nullptr, 0, 0, | |
| 99 | "Force symbol to be added to symbol table as an undefined one", nullptr, nullptr) | |
| 93 | 100 | OPTION(prefix_2, "shared", shared, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 94 | 101 | "Build a shared object", nullptr, nullptr) |
| 95 | 102 | OPTION(prefix_2, "stack", stack, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
deps/lld-prebuilt/lld/Common/Version.inc+3-3| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | #define LLD_VERSION 7.0.0 | |
| 2 | #define LLD_VERSION_STRING "7.0.0" | |
| 3 | #define LLD_VERSION_MAJOR 7 | |
| 1 | #define LLD_VERSION 8.0.0 | |
| 2 | #define LLD_VERSION_STRING "8.0.0" | |
| 3 | #define LLD_VERSION_MAJOR 8 | |
| 4 | 4 | #define LLD_VERSION_MINOR 0 |
| 5 | 5 | #define LLD_REVISION_STRING "" |
| 6 | 6 | #define LLD_REPOSITORY_STRING "" |
deps/lld-prebuilt/wasm/Options.inc+29-12| ... | ... | @@ -36,23 +36,28 @@ OPTION(prefix_1, "color-diagnostics=", color_diagnostics_eq, Joined, INVALID, IN |
| 36 | 36 | "Use colors in diagnostics; one of 'always', 'never', 'auto'", nullptr, nullptr) |
| 37 | 37 | OPTION(prefix_1, "color-diagnostics", color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 38 | 38 | "Use colors in diagnostics", nullptr, nullptr) |
| 39 | OPTION(prefix_1, "compress-relocations", compress_relocations, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 40 | "Compress the relocation targets in the code section.", nullptr, nullptr) | |
| 39 | 41 | OPTION(prefix_1, "demangle", demangle, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 40 | 42 | "Demangle symbol names", nullptr, nullptr) |
| 41 | 43 | OPTION(prefix_1, "disable-verify", disable_verify, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 42 | OPTION(prefix_1, "entry=", alias_entry_entry, Joined, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 44 | OPTION(prefix_1, "entry=", anonymous_1, Joined, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 43 | 45 | OPTION(prefix_1, "entry", entry, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 44 | 46 | "Name of entry point symbol", "<entry>", nullptr) |
| 45 | 47 | OPTION(prefix_1, "error-limit=", error_limit, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 46 | 48 | "Maximum number of errors to emit before stopping (0 = no limit)", nullptr, nullptr) |
| 47 | 49 | OPTION(prefix_1, "export-all", export_all, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 48 | 50 | "Export all symbols (normally combined with --no-gc-sections)", nullptr, nullptr) |
| 51 | OPTION(prefix_1, "export-dynamic", export_dynamic, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 52 | "Put symbols in the dynamic symbol table", nullptr, nullptr) | |
| 49 | 53 | OPTION(prefix_1, "export-table", export_table, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 50 | 54 | "Export function table to the environment", nullptr, nullptr) |
| 51 | 55 | OPTION(prefix_1, "export=", export_eq, Joined, INVALID, export, nullptr, 0, 0, |
| 52 | 56 | "Force a symbol to be exported", nullptr, nullptr) |
| 53 | OPTION(prefix_1, "export", export, Separate, INVALID, INVALID, nullptr, 0, 0, | |
| 54 | "Force a symbol to be exported", nullptr, nullptr) | |
| 55 | OPTION(prefix_2, "e", alias_entry_e, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 57 | OPTION(prefix_1, "export", export, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 58 | OPTION(prefix_2, "E", anonymous_2, Flag, INVALID, export_dynamic, nullptr, 0, 0, | |
| 59 | "Alias for --export-dynamic", nullptr, nullptr) | |
| 60 | OPTION(prefix_2, "e", anonymous_0, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 56 | 61 | OPTION(prefix_1, "fatal-warnings", fatal_warnings, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 57 | 62 | "Treat warnings as errors", nullptr, nullptr) |
| 58 | 63 | OPTION(prefix_1, "gc-sections", gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | ... | @@ -67,7 +72,7 @@ OPTION(prefix_1, "import-table", import_table, Flag, INVALID, INVALID, nullptr, |
| 67 | 72 | "Import function table from the environment", nullptr, nullptr) |
| 68 | 73 | OPTION(prefix_1, "initial-memory=", initial_memory, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 69 | 74 | "Initial size of the linear memory", nullptr, nullptr) |
| 70 | OPTION(prefix_2, "i", alias_initial_memory_i, Flag, INVALID, initial_memory, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 75 | OPTION(prefix_2, "i", anonymous_3, Flag, INVALID, initial_memory, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 71 | 76 | OPTION(prefix_1, "lto-O", lto_O, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 72 | 77 | "Optimization level for LTO", "<opt-level>", nullptr) |
| 73 | 78 | OPTION(prefix_1, "lto-partitions=", lto_partitions, Joined, INVALID, INVALID, nullptr, 0, 0, |
| ... | ... | @@ -82,18 +87,22 @@ OPTION(prefix_1, "merge-data-segments", merge_data_segments, Flag, INVALID, INVA |
| 82 | 87 | "Enable merging data segments", nullptr, nullptr) |
| 83 | 88 | OPTION(prefix_1, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0, |
| 84 | 89 | "Options to pass to LLVM", nullptr, nullptr) |
| 85 | OPTION(prefix_2, "m", alias_max_memory_m, Flag, INVALID, max_memory, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 90 | OPTION(prefix_2, "m", anonymous_4, Flag, INVALID, max_memory, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 86 | 91 | OPTION(prefix_1, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 87 | 92 | "Do not use colors in diagnostics", nullptr, nullptr) |
| 88 | 93 | OPTION(prefix_1, "no-demangle", no_demangle, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 89 | 94 | "Do not demangle symbol names", nullptr, nullptr) |
| 90 | 95 | OPTION(prefix_1, "no-entry", no_entry, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 91 | 96 | "Do not output any entry point", nullptr, nullptr) |
| 97 | OPTION(prefix_1, "no-export-dynamic", no_export_dynamic, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 98 | "Do not put symbols in the dynamic symbol table (default)", nullptr, nullptr) | |
| 92 | 99 | OPTION(prefix_1, "no-fatal-warnings", no_fatal_warnings, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 93 | 100 | OPTION(prefix_1, "no-gc-sections", no_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 94 | 101 | "Disable garbage collection of unused sections", nullptr, nullptr) |
| 95 | 102 | OPTION(prefix_1, "no-merge-data-segments", no_merge_data_segments, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 96 | 103 | "Disable merging data segments", nullptr, nullptr) |
| 104 | OPTION(prefix_1, "no-pie", no_pie, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 105 | "Do not create a position independent executable (default)", nullptr, nullptr) | |
| 97 | 106 | OPTION(prefix_1, "no-print-gc-sections", no_print_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 98 | 107 | "Do not list removed unused sections", nullptr, nullptr) |
| 99 | 108 | OPTION(prefix_1, "no-threads", no_threads, Flag, INVALID, INVALID, nullptr, 0, 0, |
| ... | ... | @@ -104,33 +113,41 @@ OPTION(prefix_2, "O", O, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, |
| 104 | 113 | "Optimize output file size", nullptr, nullptr) |
| 105 | 114 | OPTION(prefix_2, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, |
| 106 | 115 | "Path to file to write output", "<path>", nullptr) |
| 116 | OPTION(prefix_1, "pie", pie, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 117 | "Create a position independent executable", nullptr, nullptr) | |
| 107 | 118 | OPTION(prefix_1, "print-gc-sections", print_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 108 | 119 | "List removed unused sections", nullptr, nullptr) |
| 109 | 120 | OPTION(prefix_1, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 110 | 121 | "Create relocatable object file", nullptr, nullptr) |
| 111 | OPTION(prefix_2, "r", alias_relocatable_r, Flag, INVALID, relocatable, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 122 | OPTION(prefix_2, "r", anonymous_5, Flag, INVALID, relocatable, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 112 | 123 | OPTION(prefix_1, "save-temps", save_temps, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) |
| 124 | OPTION(prefix_1, "shared-memory", shared_memory, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 125 | "Use shared linear memory", nullptr, nullptr) | |
| 126 | OPTION(prefix_1, "shared", shared, Flag, INVALID, INVALID, nullptr, 0, 0, | |
| 127 | "Build a shared object", nullptr, nullptr) | |
| 113 | 128 | OPTION(prefix_1, "stack-first", stack_first, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 114 | 129 | "Place stack at start of linear memory rather than after data", nullptr, nullptr) |
| 115 | 130 | OPTION(prefix_1, "strip-all", strip_all, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 116 | 131 | "Strip all symbols", nullptr, nullptr) |
| 117 | 132 | OPTION(prefix_1, "strip-debug", strip_debug, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 118 | 133 | "Strip debugging information", nullptr, nullptr) |
| 134 | OPTION(prefix_2, "S", anonymous_7, Flag, INVALID, strip_debug, nullptr, 0, 0, | |
| 135 | "Alias for --strip-debug", nullptr, nullptr) | |
| 136 | OPTION(prefix_2, "s", anonymous_6, Flag, INVALID, strip_all, nullptr, 0, 0, | |
| 137 | "Alias for --strip-all", nullptr, nullptr) | |
| 119 | 138 | OPTION(prefix_1, "thinlto-cache-dir=", thinlto_cache_dir, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 120 | 139 | "Path to ThinLTO cached object file directory", nullptr, nullptr) |
| 121 | 140 | OPTION(prefix_1, "thinlto-cache-policy=", thinlto_cache_policy_eq, Joined, INVALID, thinlto_cache_policy, nullptr, 0, 0, |
| 122 | 141 | "Pruning policy for the ThinLTO cache", nullptr, nullptr) |
| 123 | OPTION(prefix_1, "thinlto-cache-policy", thinlto_cache_policy, Separate, INVALID, INVALID, nullptr, 0, 0, | |
| 124 | "Pruning policy for the ThinLTO cache", nullptr, nullptr) | |
| 142 | OPTION(prefix_1, "thinlto-cache-policy", thinlto_cache_policy, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 125 | 143 | OPTION(prefix_1, "thinlto-jobs=", thinlto_jobs, Joined, INVALID, INVALID, nullptr, 0, 0, |
| 126 | 144 | "Number of ThinLTO jobs", nullptr, nullptr) |
| 127 | 145 | OPTION(prefix_1, "threads", threads, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 128 | 146 | "Run the linker multi-threaded", nullptr, nullptr) |
| 129 | 147 | OPTION(prefix_1, "undefined=", undefined_eq, Joined, INVALID, undefined, nullptr, 0, 0, |
| 130 | 148 | "Force undefined symbol during linking", nullptr, nullptr) |
| 131 | OPTION(prefix_1, "undefined", undefined, Separate, INVALID, INVALID, nullptr, 0, 0, | |
| 132 | "Force undefined symbol during linking", nullptr, nullptr) | |
| 133 | OPTION(prefix_2, "u", alias_undefined_u, JoinedOrSeparate, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 149 | OPTION(prefix_1, "undefined", undefined, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 150 | OPTION(prefix_2, "u", anonymous_8, JoinedOrSeparate, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr) | |
| 134 | 151 | OPTION(prefix_1, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0, |
| 135 | 152 | "Verbose mode", nullptr, nullptr) |
| 136 | 153 | OPTION(prefix_1, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0, |
deps/lld/COFF/Chunks.cpp+293-54| ... | ... | @@ -11,6 +11,7 @@ |
| 11 | 11 | #include "InputFiles.h" |
| 12 | 12 | #include "Symbols.h" |
| 13 | 13 | #include "Writer.h" |
| 14 | #include "SymbolTable.h" | |
| 14 | 15 | #include "lld/Common/ErrorHandler.h" |
| 15 | 16 | #include "llvm/ADT/Twine.h" |
| 16 | 17 | #include "llvm/BinaryFormat/COFF.h" |
| ... | ... | @@ -44,6 +45,22 @@ SectionChunk::SectionChunk(ObjFile *F, const coff_section *H) |
| 44 | 45 | Live = !Config->DoGC || !isCOMDAT(); |
| 45 | 46 | } |
| 46 | 47 | |
| 48 | // Initialize the RelocTargets vector, to allow redirecting certain relocations | |
| 49 | // to a thunk instead of the actual symbol the relocation's symbol table index | |
| 50 | // indicates. | |
| 51 | void SectionChunk::readRelocTargets() { | |
| 52 | assert(RelocTargets.empty()); | |
| 53 | RelocTargets.reserve(Relocs.size()); | |
| 54 | for (const coff_relocation &Rel : Relocs) | |
| 55 | RelocTargets.push_back(File->getSymbol(Rel.SymbolTableIndex)); | |
| 56 | } | |
| 57 | ||
| 58 | // Reset RelocTargets to their original targets before thunks were added. | |
| 59 | void SectionChunk::resetRelocTargets() { | |
| 60 | for (size_t I = 0, E = Relocs.size(); I < E; ++I) | |
| 61 | RelocTargets[I] = File->getSymbol(Relocs[I].SymbolTableIndex); | |
| 62 | } | |
| 63 | ||
| 47 | 64 | static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); } |
| 48 | 65 | static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); } |
| 49 | 66 | static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); } |
| ... | ... | @@ -58,7 +75,8 @@ static bool checkSecRel(const SectionChunk *Sec, OutputSection *OS) { |
| 58 | 75 | return true; |
| 59 | 76 | if (Sec->isCodeView()) |
| 60 | 77 | return false; |
| 61 | fatal("SECREL relocation cannot be applied to absolute symbols"); | |
| 78 | error("SECREL relocation cannot be applied to absolute symbols"); | |
| 79 | return false; | |
| 62 | 80 | } |
| 63 | 81 | |
| 64 | 82 | static void applySecRel(const SectionChunk *Sec, uint8_t *Off, |
| ... | ... | @@ -98,7 +116,7 @@ void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS, |
| 98 | 116 | case IMAGE_REL_AMD64_SECTION: applySecIdx(Off, OS); break; |
| 99 | 117 | case IMAGE_REL_AMD64_SECREL: applySecRel(this, Off, OS, S); break; |
| 100 | 118 | default: |
| 101 | fatal("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + | |
| 119 | error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + | |
| 102 | 120 | toString(File)); |
| 103 | 121 | } |
| 104 | 122 | } |
| ... | ... | @@ -113,7 +131,7 @@ void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, OutputSection *OS, |
| 113 | 131 | case IMAGE_REL_I386_SECTION: applySecIdx(Off, OS); break; |
| 114 | 132 | case IMAGE_REL_I386_SECREL: applySecRel(this, Off, OS, S); break; |
| 115 | 133 | default: |
| 116 | fatal("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + | |
| 134 | error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + | |
| 117 | 135 | toString(File)); |
| 118 | 136 | } |
| 119 | 137 | } |
| ... | ... | @@ -123,16 +141,22 @@ static void applyMOV(uint8_t *Off, uint16_t V) { |
| 123 | 141 | write16le(Off + 2, (read16le(Off + 2) & 0x8f00) | ((V & 0x700) << 4) | (V & 0xff)); |
| 124 | 142 | } |
| 125 | 143 | |
| 126 | static uint16_t readMOV(uint8_t *Off) { | |
| 144 | static uint16_t readMOV(uint8_t *Off, bool MOVT) { | |
| 127 | 145 | uint16_t Op1 = read16le(Off); |
| 146 | if ((Op1 & 0xfbf0) != (MOVT ? 0xf2c0 : 0xf240)) | |
| 147 | error("unexpected instruction in " + Twine(MOVT ? "MOVT" : "MOVW") + | |
| 148 | " instruction in MOV32T relocation"); | |
| 128 | 149 | uint16_t Op2 = read16le(Off + 2); |
| 150 | if ((Op2 & 0x8000) != 0) | |
| 151 | error("unexpected instruction in " + Twine(MOVT ? "MOVT" : "MOVW") + | |
| 152 | " instruction in MOV32T relocation"); | |
| 129 | 153 | return (Op2 & 0x00ff) | ((Op2 >> 4) & 0x0700) | ((Op1 << 1) & 0x0800) | |
| 130 | 154 | ((Op1 & 0x000f) << 12); |
| 131 | 155 | } |
| 132 | 156 | |
| 133 | 157 | void applyMOV32T(uint8_t *Off, uint32_t V) { |
| 134 | uint16_t ImmW = readMOV(Off); // read MOVW operand | |
| 135 | uint16_t ImmT = readMOV(Off + 4); // read MOVT operand | |
| 158 | uint16_t ImmW = readMOV(Off, false); // read MOVW operand | |
| 159 | uint16_t ImmT = readMOV(Off + 4, true); // read MOVT operand | |
| 136 | 160 | uint32_t Imm = ImmW | (ImmT << 16); |
| 137 | 161 | V += Imm; // add the immediate offset |
| 138 | 162 | applyMOV(Off, V); // set MOVW operand |
| ... | ... | @@ -141,7 +165,7 @@ void applyMOV32T(uint8_t *Off, uint32_t V) { |
| 141 | 165 | |
| 142 | 166 | static void applyBranch20T(uint8_t *Off, int32_t V) { |
| 143 | 167 | if (!isInt<21>(V)) |
| 144 | fatal("relocation out of range"); | |
| 168 | error("relocation out of range"); | |
| 145 | 169 | uint32_t S = V < 0 ? 1 : 0; |
| 146 | 170 | uint32_t J1 = (V >> 19) & 1; |
| 147 | 171 | uint32_t J2 = (V >> 18) & 1; |
| ... | ... | @@ -151,7 +175,7 @@ static void applyBranch20T(uint8_t *Off, int32_t V) { |
| 151 | 175 | |
| 152 | 176 | void applyBranch24T(uint8_t *Off, int32_t V) { |
| 153 | 177 | if (!isInt<25>(V)) |
| 154 | fatal("relocation out of range"); | |
| 178 | error("relocation out of range"); | |
| 155 | 179 | uint32_t S = V < 0 ? 1 : 0; |
| 156 | 180 | uint32_t J1 = ((~V >> 23) & 1) ^ S; |
| 157 | 181 | uint32_t J2 = ((~V >> 22) & 1) ^ S; |
| ... | ... | @@ -176,7 +200,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, |
| 176 | 200 | case IMAGE_REL_ARM_SECTION: applySecIdx(Off, OS); break; |
| 177 | 201 | case IMAGE_REL_ARM_SECREL: applySecRel(this, Off, OS, S); break; |
| 178 | 202 | default: |
| 179 | fatal("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + | |
| 203 | error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + | |
| 180 | 204 | toString(File)); |
| 181 | 205 | } |
| 182 | 206 | } |
| ... | ... | @@ -184,7 +208,7 @@ void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, |
| 184 | 208 | // Interpret the existing immediate value as a byte offset to the |
| 185 | 209 | // target symbol, then update the instruction with the immediate as |
| 186 | 210 | // the page offset from the current instruction to the target. |
| 187 | static void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift) { | |
| 211 | void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift) { | |
| 188 | 212 | uint32_t Orig = read32le(Off); |
| 189 | 213 | uint64_t Imm = ((Orig >> 29) & 0x3) | ((Orig >> 3) & 0x1FFFFC); |
| 190 | 214 | S += Imm; |
| ... | ... | @@ -198,7 +222,7 @@ static void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift) { |
| 198 | 222 | // Update the immediate field in a AARCH64 ldr, str, and add instruction. |
| 199 | 223 | // Optionally limit the range of the written immediate by one or more bits |
| 200 | 224 | // (RangeLimit). |
| 201 | static void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit) { | |
| 225 | void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit) { | |
| 202 | 226 | uint32_t Orig = read32le(Off); |
| 203 | 227 | Imm += (Orig >> 10) & 0xFFF; |
| 204 | 228 | Orig &= ~(0xFFF << 10); |
| ... | ... | @@ -221,7 +245,7 @@ static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) { |
| 221 | 245 | if ((Orig & 0x4800000) == 0x4800000) |
| 222 | 246 | Size += 4; |
| 223 | 247 | if ((Imm & ((1 << Size) - 1)) != 0) |
| 224 | fatal("misaligned ldr/str offset"); | |
| 248 | error("misaligned ldr/str offset"); | |
| 225 | 249 | applyArm64Imm(Off, Imm >> Size, Size); |
| 226 | 250 | } |
| 227 | 251 | |
| ... | ... | @@ -250,21 +274,21 @@ static void applySecRelLdr(const SectionChunk *Sec, uint8_t *Off, |
| 250 | 274 | applyArm64Ldr(Off, (S - OS->getRVA()) & 0xfff); |
| 251 | 275 | } |
| 252 | 276 | |
| 253 | static void applyArm64Branch26(uint8_t *Off, int64_t V) { | |
| 277 | void applyArm64Branch26(uint8_t *Off, int64_t V) { | |
| 254 | 278 | if (!isInt<28>(V)) |
| 255 | fatal("relocation out of range"); | |
| 279 | error("relocation out of range"); | |
| 256 | 280 | or32(Off, (V & 0x0FFFFFFC) >> 2); |
| 257 | 281 | } |
| 258 | 282 | |
| 259 | 283 | static void applyArm64Branch19(uint8_t *Off, int64_t V) { |
| 260 | 284 | if (!isInt<21>(V)) |
| 261 | fatal("relocation out of range"); | |
| 285 | error("relocation out of range"); | |
| 262 | 286 | or32(Off, (V & 0x001FFFFC) << 3); |
| 263 | 287 | } |
| 264 | 288 | |
| 265 | 289 | static void applyArm64Branch14(uint8_t *Off, int64_t V) { |
| 266 | 290 | if (!isInt<16>(V)) |
| 267 | fatal("relocation out of range"); | |
| 291 | error("relocation out of range"); | |
| 268 | 292 | or32(Off, (V & 0x0000FFFC) << 3); |
| 269 | 293 | } |
| 270 | 294 | |
| ... | ... | @@ -287,11 +311,37 @@ void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, |
| 287 | 311 | case IMAGE_REL_ARM64_SECREL_LOW12L: applySecRelLdr(this, Off, OS, S); break; |
| 288 | 312 | case IMAGE_REL_ARM64_SECTION: applySecIdx(Off, OS); break; |
| 289 | 313 | default: |
| 290 | fatal("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + | |
| 314 | error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " + | |
| 291 | 315 | toString(File)); |
| 292 | 316 | } |
| 293 | 317 | } |
| 294 | 318 | |
| 319 | static void maybeReportRelocationToDiscarded(const SectionChunk *FromChunk, | |
| 320 | Defined *Sym, | |
| 321 | const coff_relocation &Rel) { | |
| 322 | // Don't report these errors when the relocation comes from a debug info | |
| 323 | // section or in mingw mode. MinGW mode object files (built by GCC) can | |
| 324 | // have leftover sections with relocations against discarded comdat | |
| 325 | // sections. Such sections are left as is, with relocations untouched. | |
| 326 | if (FromChunk->isCodeView() || FromChunk->isDWARF() || Config->MinGW) | |
| 327 | return; | |
| 328 | ||
| 329 | // Get the name of the symbol. If it's null, it was discarded early, so we | |
| 330 | // have to go back to the object file. | |
| 331 | ObjFile *File = FromChunk->File; | |
| 332 | StringRef Name; | |
| 333 | if (Sym) { | |
| 334 | Name = Sym->getName(); | |
| 335 | } else { | |
| 336 | COFFSymbolRef COFFSym = | |
| 337 | check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex)); | |
| 338 | File->getCOFFObj()->getSymbolName(COFFSym, Name); | |
| 339 | } | |
| 340 | ||
| 341 | error("relocation against symbol in discarded section: " + Name + | |
| 342 | getSymbolLocations(File, Rel.SymbolTableIndex)); | |
| 343 | } | |
| 344 | ||
| 295 | 345 | void SectionChunk::writeTo(uint8_t *Buf) const { |
| 296 | 346 | if (!hasData()) |
| 297 | 347 | return; |
| ... | ... | @@ -302,46 +352,40 @@ void SectionChunk::writeTo(uint8_t *Buf) const { |
| 302 | 352 | |
| 303 | 353 | // Apply relocations. |
| 304 | 354 | size_t InputSize = getSize(); |
| 305 | for (const coff_relocation &Rel : Relocs) { | |
| 355 | for (size_t I = 0, E = Relocs.size(); I < E; I++) { | |
| 356 | const coff_relocation &Rel = Relocs[I]; | |
| 357 | ||
| 306 | 358 | // Check for an invalid relocation offset. This check isn't perfect, because |
| 307 | 359 | // we don't have the relocation size, which is only known after checking the |
| 308 | 360 | // machine and relocation type. As a result, a relocation may overwrite the |
| 309 | 361 | // beginning of the following input section. |
| 310 | if (Rel.VirtualAddress >= InputSize) | |
| 311 | fatal("relocation points beyond the end of its parent section"); | |
| 362 | if (Rel.VirtualAddress >= InputSize) { | |
| 363 | error("relocation points beyond the end of its parent section"); | |
| 364 | continue; | |
| 365 | } | |
| 312 | 366 | |
| 313 | 367 | uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress; |
| 314 | 368 | |
| 369 | // Use the potentially remapped Symbol instead of the one that the | |
| 370 | // relocation points to. | |
| 371 | auto *Sym = dyn_cast_or_null<Defined>(RelocTargets[I]); | |
| 372 | ||
| 315 | 373 | // Get the output section of the symbol for this relocation. The output |
| 316 | 374 | // section is needed to compute SECREL and SECTION relocations used in debug |
| 317 | 375 | // info. |
| 318 | auto *Sym = | |
| 319 | dyn_cast_or_null<Defined>(File->getSymbol(Rel.SymbolTableIndex)); | |
| 320 | if (!Sym) { | |
| 321 | if (isCodeView() || isDWARF()) | |
| 322 | continue; | |
| 323 | // Symbols in early discarded sections are represented using null pointers, | |
| 324 | // so we need to retrieve the name from the object file. | |
| 325 | COFFSymbolRef Sym = | |
| 326 | check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex)); | |
| 327 | StringRef Name; | |
| 328 | File->getCOFFObj()->getSymbolName(Sym, Name); | |
| 329 | fatal("relocation against symbol in discarded section: " + Name); | |
| 330 | } | |
| 331 | Chunk *C = Sym->getChunk(); | |
| 376 | Chunk *C = Sym ? Sym->getChunk() : nullptr; | |
| 332 | 377 | OutputSection *OS = C ? C->getOutputSection() : nullptr; |
| 333 | 378 | |
| 334 | // Only absolute and __ImageBase symbols lack an output section. For any | |
| 335 | // other symbol, this indicates that the chunk was discarded. Normally | |
| 336 | // relocations against discarded sections are an error. However, debug info | |
| 337 | // sections are not GC roots and can end up with these kinds of relocations. | |
| 338 | // Skip these relocations. | |
| 339 | if (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym)) { | |
| 340 | if (isCodeView() || isDWARF()) | |
| 341 | continue; | |
| 342 | fatal("relocation against symbol in discarded section: " + | |
| 343 | Sym->getName()); | |
| 379 | // Skip the relocation if it refers to a discarded section, and diagnose it | |
| 380 | // as an error if appropriate. If a symbol was discarded early, it may be | |
| 381 | // null. If it was discarded late, the output section will be null, unless | |
| 382 | // it was an absolute or synthetic symbol. | |
| 383 | if (!Sym || | |
| 384 | (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym))) { | |
| 385 | maybeReportRelocationToDiscarded(this, Sym, Rel); | |
| 386 | continue; | |
| 344 | 387 | } |
| 388 | ||
| 345 | 389 | uint64_t S = Sym->getRVA(); |
| 346 | 390 | |
| 347 | 391 | // Compute the RVA of the relocation for relative relocations. |
| ... | ... | @@ -399,17 +443,125 @@ static uint8_t getBaserelType(const coff_relocation &Rel) { |
| 399 | 443 | // fixed by the loader if load-time relocation is needed. |
| 400 | 444 | // Only called when base relocation is enabled. |
| 401 | 445 | void SectionChunk::getBaserels(std::vector<Baserel> *Res) { |
| 402 | for (const coff_relocation &Rel : Relocs) { | |
| 446 | for (size_t I = 0, E = Relocs.size(); I < E; I++) { | |
| 447 | const coff_relocation &Rel = Relocs[I]; | |
| 403 | 448 | uint8_t Ty = getBaserelType(Rel); |
| 404 | 449 | if (Ty == IMAGE_REL_BASED_ABSOLUTE) |
| 405 | 450 | continue; |
| 406 | Symbol *Target = File->getSymbol(Rel.SymbolTableIndex); | |
| 451 | // Use the potentially remapped Symbol instead of the one that the | |
| 452 | // relocation points to. | |
| 453 | Symbol *Target = RelocTargets[I]; | |
| 407 | 454 | if (!Target || isa<DefinedAbsolute>(Target)) |
| 408 | 455 | continue; |
| 409 | 456 | Res->emplace_back(RVA + Rel.VirtualAddress, Ty); |
| 410 | 457 | } |
| 411 | 458 | } |
| 412 | 459 | |
| 460 | // MinGW specific. | |
| 461 | // Check whether a static relocation of type Type can be deferred and | |
| 462 | // handled at runtime as a pseudo relocation (for references to a module | |
| 463 | // local variable, which turned out to actually need to be imported from | |
| 464 | // another DLL) This returns the size the relocation is supposed to update, | |
| 465 | // in bits, or 0 if the relocation cannot be handled as a runtime pseudo | |
| 466 | // relocation. | |
| 467 | static int getRuntimePseudoRelocSize(uint16_t Type) { | |
| 468 | // Relocations that either contain an absolute address, or a plain | |
| 469 | // relative offset, since the runtime pseudo reloc implementation | |
| 470 | // adds 8/16/32/64 bit values to a memory address. | |
| 471 | // | |
| 472 | // Given a pseudo relocation entry, | |
| 473 | // | |
| 474 | // typedef struct { | |
| 475 | // DWORD sym; | |
| 476 | // DWORD target; | |
| 477 | // DWORD flags; | |
| 478 | // } runtime_pseudo_reloc_item_v2; | |
| 479 | // | |
| 480 | // the runtime relocation performs this adjustment: | |
| 481 | // *(base + .target) += *(base + .sym) - (base + .sym) | |
| 482 | // | |
| 483 | // This works for both absolute addresses (IMAGE_REL_*_ADDR32/64, | |
| 484 | // IMAGE_REL_I386_DIR32, where the memory location initially contains | |
| 485 | // the address of the IAT slot, and for relative addresses (IMAGE_REL*_REL32), | |
| 486 | // where the memory location originally contains the relative offset to the | |
| 487 | // IAT slot. | |
| 488 | // | |
| 489 | // This requires the target address to be writable, either directly out of | |
| 490 | // the image, or temporarily changed at runtime with VirtualProtect. | |
| 491 | // Since this only operates on direct address values, it doesn't work for | |
| 492 | // ARM/ARM64 relocations, other than the plain ADDR32/ADDR64 relocations. | |
| 493 | switch (Config->Machine) { | |
| 494 | case AMD64: | |
| 495 | switch (Type) { | |
| 496 | case IMAGE_REL_AMD64_ADDR64: | |
| 497 | return 64; | |
| 498 | case IMAGE_REL_AMD64_ADDR32: | |
| 499 | case IMAGE_REL_AMD64_REL32: | |
| 500 | case IMAGE_REL_AMD64_REL32_1: | |
| 501 | case IMAGE_REL_AMD64_REL32_2: | |
| 502 | case IMAGE_REL_AMD64_REL32_3: | |
| 503 | case IMAGE_REL_AMD64_REL32_4: | |
| 504 | case IMAGE_REL_AMD64_REL32_5: | |
| 505 | return 32; | |
| 506 | default: | |
| 507 | return 0; | |
| 508 | } | |
| 509 | case I386: | |
| 510 | switch (Type) { | |
| 511 | case IMAGE_REL_I386_DIR32: | |
| 512 | case IMAGE_REL_I386_REL32: | |
| 513 | return 32; | |
| 514 | default: | |
| 515 | return 0; | |
| 516 | } | |
| 517 | case ARMNT: | |
| 518 | switch (Type) { | |
| 519 | case IMAGE_REL_ARM_ADDR32: | |
| 520 | return 32; | |
| 521 | default: | |
| 522 | return 0; | |
| 523 | } | |
| 524 | case ARM64: | |
| 525 | switch (Type) { | |
| 526 | case IMAGE_REL_ARM64_ADDR64: | |
| 527 | return 64; | |
| 528 | case IMAGE_REL_ARM64_ADDR32: | |
| 529 | return 32; | |
| 530 | default: | |
| 531 | return 0; | |
| 532 | } | |
| 533 | default: | |
| 534 | llvm_unreachable("unknown machine type"); | |
| 535 | } | |
| 536 | } | |
| 537 | ||
| 538 | // MinGW specific. | |
| 539 | // Append information to the provided vector about all relocations that | |
| 540 | // need to be handled at runtime as runtime pseudo relocations (references | |
| 541 | // to a module local variable, which turned out to actually need to be | |
| 542 | // imported from another DLL). | |
| 543 | void SectionChunk::getRuntimePseudoRelocs( | |
| 544 | std::vector<RuntimePseudoReloc> &Res) { | |
| 545 | for (const coff_relocation &Rel : Relocs) { | |
| 546 | auto *Target = | |
| 547 | dyn_cast_or_null<Defined>(File->getSymbol(Rel.SymbolTableIndex)); | |
| 548 | if (!Target || !Target->IsRuntimePseudoReloc) | |
| 549 | continue; | |
| 550 | int SizeInBits = getRuntimePseudoRelocSize(Rel.Type); | |
| 551 | if (SizeInBits == 0) { | |
| 552 | error("unable to automatically import from " + Target->getName() + | |
| 553 | " with relocation type " + | |
| 554 | File->getCOFFObj()->getRelocationTypeName(Rel.Type) + " in " + | |
| 555 | toString(File)); | |
| 556 | continue; | |
| 557 | } | |
| 558 | // SizeInBits is used to initialize the Flags field; currently no | |
| 559 | // other flags are defined. | |
| 560 | Res.emplace_back( | |
| 561 | RuntimePseudoReloc(Target, this, Rel.VirtualAddress, SizeInBits)); | |
| 562 | } | |
| 563 | } | |
| 564 | ||
| 413 | 565 | bool SectionChunk::hasData() const { |
| 414 | 566 | return !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA); |
| 415 | 567 | } |
| ... | ... | @@ -447,6 +599,13 @@ void SectionChunk::replace(SectionChunk *Other) { |
| 447 | 599 | Other->Live = false; |
| 448 | 600 | } |
| 449 | 601 | |
| 602 | uint32_t SectionChunk::getSectionNumber() const { | |
| 603 | DataRefImpl R; | |
| 604 | R.p = reinterpret_cast<uintptr_t>(Header); | |
| 605 | SectionRef S(R, File->getCOFFObj()); | |
| 606 | return S.getIndex() + 1; | |
| 607 | } | |
| 608 | ||
| 450 | 609 | CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) { |
| 451 | 610 | // Common symbols are aligned on natural boundaries up to 32 bytes. |
| 452 | 611 | // This is what MSVC link.exe does. |
| ... | ... | @@ -460,6 +619,7 @@ uint32_t CommonChunk::getOutputCharacteristics() const { |
| 460 | 619 | |
| 461 | 620 | void StringChunk::writeTo(uint8_t *Buf) const { |
| 462 | 621 | memcpy(Buf + OutputSectionOff, Str.data(), Str.size()); |
| 622 | Buf[OutputSectionOff + Str.size()] = '\0'; | |
| 463 | 623 | } |
| 464 | 624 | |
| 465 | 625 | ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) { |
| ... | ... | @@ -502,13 +662,50 @@ void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const { |
| 502 | 662 | applyArm64Ldr(Buf + OutputSectionOff + 4, Off); |
| 503 | 663 | } |
| 504 | 664 | |
| 665 | // A Thumb2, PIC, non-interworking range extension thunk. | |
| 666 | const uint8_t ArmThunk[] = { | |
| 667 | 0x40, 0xf2, 0x00, 0x0c, // P: movw ip,:lower16:S - (P + (L1-P) + 4) | |
| 668 | 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4) | |
| 669 | 0xe7, 0x44, // L1: add pc, ip | |
| 670 | }; | |
| 671 | ||
| 672 | size_t RangeExtensionThunkARM::getSize() const { | |
| 673 | assert(Config->Machine == ARMNT); | |
| 674 | return sizeof(ArmThunk); | |
| 675 | } | |
| 676 | ||
| 677 | void RangeExtensionThunkARM::writeTo(uint8_t *Buf) const { | |
| 678 | assert(Config->Machine == ARMNT); | |
| 679 | uint64_t Offset = Target->getRVA() - RVA - 12; | |
| 680 | memcpy(Buf + OutputSectionOff, ArmThunk, sizeof(ArmThunk)); | |
| 681 | applyMOV32T(Buf + OutputSectionOff, uint32_t(Offset)); | |
| 682 | } | |
| 683 | ||
| 684 | // A position independent ARM64 adrp+add thunk, with a maximum range of | |
| 685 | // +/- 4 GB, which is enough for any PE-COFF. | |
| 686 | const uint8_t Arm64Thunk[] = { | |
| 687 | 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest | |
| 688 | 0x10, 0x02, 0x00, 0x91, // add x16, x16, :lo12:Dest | |
| 689 | 0x00, 0x02, 0x1f, 0xd6, // br x16 | |
| 690 | }; | |
| 691 | ||
| 692 | size_t RangeExtensionThunkARM64::getSize() const { | |
| 693 | assert(Config->Machine == ARM64); | |
| 694 | return sizeof(Arm64Thunk); | |
| 695 | } | |
| 696 | ||
| 697 | void RangeExtensionThunkARM64::writeTo(uint8_t *Buf) const { | |
| 698 | assert(Config->Machine == ARM64); | |
| 699 | memcpy(Buf + OutputSectionOff, Arm64Thunk, sizeof(Arm64Thunk)); | |
| 700 | applyArm64Addr(Buf + OutputSectionOff + 0, Target->getRVA(), RVA, 12); | |
| 701 | applyArm64Imm(Buf + OutputSectionOff + 4, Target->getRVA() & 0xfff, 0); | |
| 702 | } | |
| 703 | ||
| 505 | 704 | void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) { |
| 506 | 705 | Res->emplace_back(getRVA()); |
| 507 | 706 | } |
| 508 | 707 | |
| 509 | size_t LocalImportChunk::getSize() const { | |
| 510 | return Config->is64() ? 8 : 4; | |
| 511 | } | |
| 708 | size_t LocalImportChunk::getSize() const { return Config->Wordsize; } | |
| 512 | 709 | |
| 513 | 710 | void LocalImportChunk::writeTo(uint8_t *Buf) const { |
| 514 | 711 | if (Config->is64()) { |
| ... | ... | @@ -528,6 +725,34 @@ void RVATableChunk::writeTo(uint8_t *Buf) const { |
| 528 | 725 | "RVA tables should be de-duplicated"); |
| 529 | 726 | } |
| 530 | 727 | |
| 728 | // MinGW specific, for the "automatic import of variables from DLLs" feature. | |
| 729 | size_t PseudoRelocTableChunk::getSize() const { | |
| 730 | if (Relocs.empty()) | |
| 731 | return 0; | |
| 732 | return 12 + 12 * Relocs.size(); | |
| 733 | } | |
| 734 | ||
| 735 | // MinGW specific. | |
| 736 | void PseudoRelocTableChunk::writeTo(uint8_t *Buf) const { | |
| 737 | if (Relocs.empty()) | |
| 738 | return; | |
| 739 | ||
| 740 | ulittle32_t *Table = reinterpret_cast<ulittle32_t *>(Buf + OutputSectionOff); | |
| 741 | // This is the list header, to signal the runtime pseudo relocation v2 | |
| 742 | // format. | |
| 743 | Table[0] = 0; | |
| 744 | Table[1] = 0; | |
| 745 | Table[2] = 1; | |
| 746 | ||
| 747 | size_t Idx = 3; | |
| 748 | for (const RuntimePseudoReloc &RPR : Relocs) { | |
| 749 | Table[Idx + 0] = RPR.Sym->getRVA(); | |
| 750 | Table[Idx + 1] = RPR.Target->getRVA() + RPR.TargetOffset; | |
| 751 | Table[Idx + 2] = RPR.Flags; | |
| 752 | Idx += 3; | |
| 753 | } | |
| 754 | } | |
| 755 | ||
| 531 | 756 | // Windows-specific. This class represents a block in .reloc section. |
| 532 | 757 | // The format is described here. |
| 533 | 758 | // |
| ... | ... | @@ -613,13 +838,16 @@ void MergeChunk::addSection(SectionChunk *C) { |
| 613 | 838 | } |
| 614 | 839 | |
| 615 | 840 | void MergeChunk::finalizeContents() { |
| 616 | for (SectionChunk *C : Sections) | |
| 617 | if (C->isLive()) | |
| 618 | Builder.add(toStringRef(C->getContents())); | |
| 619 | Builder.finalize(); | |
| 841 | if (!Finalized) { | |
| 842 | for (SectionChunk *C : Sections) | |
| 843 | if (C->Live) | |
| 844 | Builder.add(toStringRef(C->getContents())); | |
| 845 | Builder.finalize(); | |
| 846 | Finalized = true; | |
| 847 | } | |
| 620 | 848 | |
| 621 | 849 | for (SectionChunk *C : Sections) { |
| 622 | if (!C->isLive()) | |
| 850 | if (!C->Live) | |
| 623 | 851 | continue; |
| 624 | 852 | size_t Off = Builder.getOffset(toStringRef(C->getContents())); |
| 625 | 853 | C->setOutputSection(Out); |
| ... | ... | @@ -640,5 +868,16 @@ void MergeChunk::writeTo(uint8_t *Buf) const { |
| 640 | 868 | Builder.write(Buf + OutputSectionOff); |
| 641 | 869 | } |
| 642 | 870 | |
| 871 | // MinGW specific. | |
| 872 | size_t AbsolutePointerChunk::getSize() const { return Config->Wordsize; } | |
| 873 | ||
| 874 | void AbsolutePointerChunk::writeTo(uint8_t *Buf) const { | |
| 875 | if (Config->is64()) { | |
| 876 | write64le(Buf + OutputSectionOff, Value); | |
| 877 | } else { | |
| 878 | write32le(Buf + OutputSectionOff, Value); | |
| 879 | } | |
| 880 | } | |
| 881 | ||
| 643 | 882 | } // namespace coff |
| 644 | 883 | } // namespace lld |
deps/lld/COFF/Chunks.h+114-16| ... | ... | @@ -36,6 +36,7 @@ class DefinedImportData; |
| 36 | 36 | class DefinedRegular; |
| 37 | 37 | class ObjFile; |
| 38 | 38 | class OutputSection; |
| 39 | class RuntimePseudoReloc; | |
| 39 | 40 | class Symbol; |
| 40 | 41 | |
| 41 | 42 | // Mask for permissions (discardable, writable, readable, executable, etc). |
| ... | ... | @@ -63,6 +64,13 @@ public: |
| 63 | 64 | // before calling this function. |
| 64 | 65 | virtual void writeTo(uint8_t *Buf) const {} |
| 65 | 66 | |
| 67 | // Called by the writer once before assigning addresses and writing | |
| 68 | // the output. | |
| 69 | virtual void readRelocTargets() {} | |
| 70 | ||
| 71 | // Called if restarting thunk addition. | |
| 72 | virtual void resetRelocTargets() {} | |
| 73 | ||
| 66 | 74 | // Called by the writer after an RVA is assigned, but before calling |
| 67 | 75 | // getSize(). |
| 68 | 76 | virtual void finalizeContents() {} |
| ... | ... | @@ -114,6 +122,10 @@ protected: |
| 114 | 122 | public: |
| 115 | 123 | // The offset from beginning of the output section. The writer sets a value. |
| 116 | 124 | uint64_t OutputSectionOff = 0; |
| 125 | ||
| 126 | // Whether this section needs to be kept distinct from other sections during | |
| 127 | // ICF. This is set by the driver using address-significance tables. | |
| 128 | bool KeepUnique = false; | |
| 117 | 129 | }; |
| 118 | 130 | |
| 119 | 131 | // A chunk corresponding a section of an input file. |
| ... | ... | @@ -140,6 +152,8 @@ public: |
| 140 | 152 | |
| 141 | 153 | SectionChunk(ObjFile *File, const coff_section *Header); |
| 142 | 154 | static bool classof(const Chunk *C) { return C->kind() == SectionKind; } |
| 155 | void readRelocTargets() override; | |
| 156 | void resetRelocTargets() override; | |
| 143 | 157 | size_t getSize() const override { return Header->SizeOfRawData; } |
| 144 | 158 | ArrayRef<uint8_t> getContents() const; |
| 145 | 159 | void writeTo(uint8_t *Buf) const override; |
| ... | ... | @@ -157,6 +171,8 @@ public: |
| 157 | 171 | void applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S, |
| 158 | 172 | uint64_t P) const; |
| 159 | 173 | |
| 174 | void getRuntimePseudoRelocs(std::vector<RuntimePseudoReloc> &Res); | |
| 175 | ||
| 160 | 176 | // Called if the garbage collector decides to not include this chunk |
| 161 | 177 | // in a final output. It's supposed to print out a log message to stdout. |
| 162 | 178 | void printDiscardedMessage() const; |
| ... | ... | @@ -167,16 +183,6 @@ public: |
| 167 | 183 | |
| 168 | 184 | StringRef getDebugName() override; |
| 169 | 185 | |
| 170 | // Returns true if the chunk was not dropped by GC. | |
| 171 | bool isLive() { return Live; } | |
| 172 | ||
| 173 | // Used by the garbage collector. | |
| 174 | void markLive() { | |
| 175 | assert(Config->DoGC && "should only mark things live from GC"); | |
| 176 | assert(!isLive() && "Cannot mark an already live section!"); | |
| 177 | Live = true; | |
| 178 | } | |
| 179 | ||
| 180 | 186 | // True if this is a codeview debug info chunk. These will not be laid out in |
| 181 | 187 | // the image. Instead they will end up in the PDB, if one is requested. |
| 182 | 188 | bool isCodeView() const { |
| ... | ... | @@ -197,10 +203,13 @@ public: |
| 197 | 203 | // Allow iteration over the associated child chunks for this section. |
| 198 | 204 | ArrayRef<SectionChunk *> children() const { return AssocChildren; } |
| 199 | 205 | |
| 206 | // The section ID this chunk belongs to in its Obj. | |
| 207 | uint32_t getSectionNumber() const; | |
| 208 | ||
| 200 | 209 | // A pointer pointing to a replacement for this chunk. |
| 201 | 210 | // Initially it points to "this" object. If this chunk is merged |
| 202 | 211 | // with other chunk by ICF, it points to another chunk, |
| 203 | // and this chunk is considrered as dead. | |
| 212 | // and this chunk is considered as dead. | |
| 204 | 213 | SectionChunk *Repl; |
| 205 | 214 | |
| 206 | 215 | // The CRC of the contents as described in the COFF spec 4.5.5. |
| ... | ... | @@ -217,13 +226,17 @@ public: |
| 217 | 226 | |
| 218 | 227 | ArrayRef<coff_relocation> Relocs; |
| 219 | 228 | |
| 229 | // Used by the garbage collector. | |
| 230 | bool Live; | |
| 231 | ||
| 232 | // When inserting a thunk, we need to adjust a relocation to point to | |
| 233 | // the thunk instead of the actual original target Symbol. | |
| 234 | std::vector<Symbol *> RelocTargets; | |
| 235 | ||
| 220 | 236 | private: |
| 221 | 237 | StringRef SectionName; |
| 222 | 238 | std::vector<SectionChunk *> AssocChildren; |
| 223 | 239 | |
| 224 | // Used by the garbage collector. | |
| 225 | bool Live; | |
| 226 | ||
| 227 | 240 | // Used for ICF (Identical COMDAT Folding) |
| 228 | 241 | void replace(SectionChunk *Other); |
| 229 | 242 | uint32_t Class[2] = {0, 0}; |
| ... | ... | @@ -254,6 +267,7 @@ public: |
| 254 | 267 | |
| 255 | 268 | private: |
| 256 | 269 | llvm::StringTableBuilder Builder; |
| 270 | bool Finalized = false; | |
| 257 | 271 | }; |
| 258 | 272 | |
| 259 | 273 | // A chunk for common symbols. Common chunks don't have actual data. |
| ... | ... | @@ -297,7 +311,7 @@ static const uint8_t ImportThunkARM64[] = { |
| 297 | 311 | }; |
| 298 | 312 | |
| 299 | 313 | // Windows-specific. |
| 300 | // A chunk for DLL import jump table entry. In a final output, it's | |
| 314 | // A chunk for DLL import jump table entry. In a final output, its | |
| 301 | 315 | // contents will be a JMP instruction to some __imp_ symbol. |
| 302 | 316 | class ImportThunkChunkX64 : public Chunk { |
| 303 | 317 | public: |
| ... | ... | @@ -341,11 +355,31 @@ private: |
| 341 | 355 | Defined *ImpSymbol; |
| 342 | 356 | }; |
| 343 | 357 | |
| 358 | class RangeExtensionThunkARM : public Chunk { | |
| 359 | public: | |
| 360 | explicit RangeExtensionThunkARM(Defined *T) : Target(T) {} | |
| 361 | size_t getSize() const override; | |
| 362 | void writeTo(uint8_t *Buf) const override; | |
| 363 | ||
| 364 | Defined *Target; | |
| 365 | }; | |
| 366 | ||
| 367 | class RangeExtensionThunkARM64 : public Chunk { | |
| 368 | public: | |
| 369 | explicit RangeExtensionThunkARM64(Defined *T) : Target(T) {} | |
| 370 | size_t getSize() const override; | |
| 371 | void writeTo(uint8_t *Buf) const override; | |
| 372 | ||
| 373 | Defined *Target; | |
| 374 | }; | |
| 375 | ||
| 344 | 376 | // Windows-specific. |
| 345 | 377 | // See comments for DefinedLocalImport class. |
| 346 | 378 | class LocalImportChunk : public Chunk { |
| 347 | 379 | public: |
| 348 | explicit LocalImportChunk(Defined *S) : Sym(S) {} | |
| 380 | explicit LocalImportChunk(Defined *S) : Sym(S) { | |
| 381 | Alignment = Config->Wordsize; | |
| 382 | } | |
| 349 | 383 | size_t getSize() const override; |
| 350 | 384 | void getBaserels(std::vector<Baserel> *Res) override; |
| 351 | 385 | void writeTo(uint8_t *Buf) const override; |
| ... | ... | @@ -414,9 +448,73 @@ public: |
| 414 | 448 | uint8_t Type; |
| 415 | 449 | }; |
| 416 | 450 | |
| 451 | // This is a placeholder Chunk, to allow attaching a DefinedSynthetic to a | |
| 452 | // specific place in a section, without any data. This is used for the MinGW | |
| 453 | // specific symbol __RUNTIME_PSEUDO_RELOC_LIST_END__, even though the concept | |
| 454 | // of an empty chunk isn't MinGW specific. | |
| 455 | class EmptyChunk : public Chunk { | |
| 456 | public: | |
| 457 | EmptyChunk() {} | |
| 458 | size_t getSize() const override { return 0; } | |
| 459 | void writeTo(uint8_t *Buf) const override {} | |
| 460 | }; | |
| 461 | ||
| 462 | // MinGW specific, for the "automatic import of variables from DLLs" feature. | |
| 463 | // This provides the table of runtime pseudo relocations, for variable | |
| 464 | // references that turned out to need to be imported from a DLL even though | |
| 465 | // the reference didn't use the dllimport attribute. The MinGW runtime will | |
| 466 | // process this table after loading, before handling control over to user | |
| 467 | // code. | |
| 468 | class PseudoRelocTableChunk : public Chunk { | |
| 469 | public: | |
| 470 | PseudoRelocTableChunk(std::vector<RuntimePseudoReloc> &Relocs) | |
| 471 | : Relocs(std::move(Relocs)) { | |
| 472 | Alignment = 4; | |
| 473 | } | |
| 474 | size_t getSize() const override; | |
| 475 | void writeTo(uint8_t *Buf) const override; | |
| 476 | ||
| 477 | private: | |
| 478 | std::vector<RuntimePseudoReloc> Relocs; | |
| 479 | }; | |
| 480 | ||
| 481 | // MinGW specific; information about one individual location in the image | |
| 482 | // that needs to be fixed up at runtime after loading. This represents | |
| 483 | // one individual element in the PseudoRelocTableChunk table. | |
| 484 | class RuntimePseudoReloc { | |
| 485 | public: | |
| 486 | RuntimePseudoReloc(Defined *Sym, SectionChunk *Target, uint32_t TargetOffset, | |
| 487 | int Flags) | |
| 488 | : Sym(Sym), Target(Target), TargetOffset(TargetOffset), Flags(Flags) {} | |
| 489 | ||
| 490 | Defined *Sym; | |
| 491 | SectionChunk *Target; | |
| 492 | uint32_t TargetOffset; | |
| 493 | // The Flags field contains the size of the relocation, in bits. No other | |
| 494 | // flags are currently defined. | |
| 495 | int Flags; | |
| 496 | }; | |
| 497 | ||
| 498 | // MinGW specific. A Chunk that contains one pointer-sized absolute value. | |
| 499 | class AbsolutePointerChunk : public Chunk { | |
| 500 | public: | |
| 501 | AbsolutePointerChunk(uint64_t Value) : Value(Value) { | |
| 502 | Alignment = getSize(); | |
| 503 | } | |
| 504 | size_t getSize() const override; | |
| 505 | void writeTo(uint8_t *Buf) const override; | |
| 506 | ||
| 507 | private: | |
| 508 | uint64_t Value; | |
| 509 | }; | |
| 510 | ||
| 417 | 511 | void applyMOV32T(uint8_t *Off, uint32_t V); |
| 418 | 512 | void applyBranch24T(uint8_t *Off, int32_t V); |
| 419 | 513 | |
| 514 | void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift); | |
| 515 | void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit); | |
| 516 | void applyArm64Branch26(uint8_t *Off, int64_t V); | |
| 517 | ||
| 420 | 518 | } // namespace coff |
| 421 | 519 | } // namespace lld |
| 422 | 520 |
deps/lld/COFF/Config.h+4-1| ... | ... | @@ -84,6 +84,7 @@ struct Configuration { |
| 84 | 84 | bool is64() { return Machine == AMD64 || Machine == ARM64; } |
| 85 | 85 | |
| 86 | 86 | llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN; |
| 87 | size_t Wordsize; | |
| 87 | 88 | bool Verbose = false; |
| 88 | 89 | WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN; |
| 89 | 90 | Symbol *Entry = nullptr; |
| ... | ... | @@ -94,7 +95,8 @@ struct Configuration { |
| 94 | 95 | bool DoICF = true; |
| 95 | 96 | bool TailMerge; |
| 96 | 97 | bool Relocatable = true; |
| 97 | bool Force = false; | |
| 98 | bool ForceMultiple = false; | |
| 99 | bool ForceUnresolved = false; | |
| 98 | 100 | bool Debug = false; |
| 99 | 101 | bool DebugDwarf = false; |
| 100 | 102 | bool DebugGHashes = false; |
| ... | ... | @@ -195,6 +197,7 @@ struct Configuration { |
| 195 | 197 | bool MinGW = false; |
| 196 | 198 | bool WarnMissingOrderSymbol = true; |
| 197 | 199 | bool WarnLocallyDefinedImported = true; |
| 200 | bool WarnDebugInfoUnusable = true; | |
| 198 | 201 | bool Incremental = true; |
| 199 | 202 | bool IntegrityCheck = false; |
| 200 | 203 | bool KillAt = false; |
deps/lld/COFF/DLL.cpp+83-35| ... | ... | @@ -35,8 +35,6 @@ namespace { |
| 35 | 35 | |
| 36 | 36 | // Import table |
| 37 | 37 | |
| 38 | static int ptrSize() { return Config->is64() ? 8 : 4; } | |
| 39 | ||
| 40 | 38 | // A chunk for the import descriptor table. |
| 41 | 39 | class HintNameChunk : public Chunk { |
| 42 | 40 | public: |
| ... | ... | @@ -49,6 +47,7 @@ public: |
| 49 | 47 | } |
| 50 | 48 | |
| 51 | 49 | void writeTo(uint8_t *Buf) const override { |
| 50 | memset(Buf + OutputSectionOff, 0, getSize()); | |
| 52 | 51 | write16le(Buf + OutputSectionOff, Hint); |
| 53 | 52 | memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size()); |
| 54 | 53 | } |
| ... | ... | @@ -61,11 +60,14 @@ private: |
| 61 | 60 | // A chunk for the import descriptor table. |
| 62 | 61 | class LookupChunk : public Chunk { |
| 63 | 62 | public: |
| 64 | explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = ptrSize(); } | |
| 65 | size_t getSize() const override { return ptrSize(); } | |
| 63 | explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = Config->Wordsize; } | |
| 64 | size_t getSize() const override { return Config->Wordsize; } | |
| 66 | 65 | |
| 67 | 66 | void writeTo(uint8_t *Buf) const override { |
| 68 | write32le(Buf + OutputSectionOff, HintName->getRVA()); | |
| 67 | if (Config->is64()) | |
| 68 | write64le(Buf + OutputSectionOff, HintName->getRVA()); | |
| 69 | else | |
| 70 | write32le(Buf + OutputSectionOff, HintName->getRVA()); | |
| 69 | 71 | } |
| 70 | 72 | |
| 71 | 73 | Chunk *HintName; |
| ... | ... | @@ -76,8 +78,10 @@ public: |
| 76 | 78 | // See Microsoft PE/COFF spec 7.1. Import Header for details. |
| 77 | 79 | class OrdinalOnlyChunk : public Chunk { |
| 78 | 80 | public: |
| 79 | explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { Alignment = ptrSize(); } | |
| 80 | size_t getSize() const override { return ptrSize(); } | |
| 81 | explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) { | |
| 82 | Alignment = Config->Wordsize; | |
| 83 | } | |
| 84 | size_t getSize() const override { return Config->Wordsize; } | |
| 81 | 85 | |
| 82 | 86 | void writeTo(uint8_t *Buf) const override { |
| 83 | 87 | // An import-by-ordinal slot has MSB 1 to indicate that |
| ... | ... | @@ -99,6 +103,8 @@ public: |
| 99 | 103 | size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); } |
| 100 | 104 | |
| 101 | 105 | void writeTo(uint8_t *Buf) const override { |
| 106 | memset(Buf + OutputSectionOff, 0, getSize()); | |
| 107 | ||
| 102 | 108 | auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff); |
| 103 | 109 | E->ImportLookupTableRVA = LookupTab->getRVA(); |
| 104 | 110 | E->NameRVA = DLLName->getRVA(); |
| ... | ... | @@ -118,6 +124,10 @@ public: |
| 118 | 124 | bool hasData() const override { return false; } |
| 119 | 125 | size_t getSize() const override { return Size; } |
| 120 | 126 | |
| 127 | void writeTo(uint8_t *Buf) const override { | |
| 128 | memset(Buf + OutputSectionOff, 0, Size); | |
| 129 | } | |
| 130 | ||
| 121 | 131 | private: |
| 122 | 132 | size_t Size; |
| 123 | 133 | }; |
| ... | ... | @@ -160,6 +170,8 @@ public: |
| 160 | 170 | } |
| 161 | 171 | |
| 162 | 172 | void writeTo(uint8_t *Buf) const override { |
| 173 | memset(Buf + OutputSectionOff, 0, getSize()); | |
| 174 | ||
| 163 | 175 | auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff); |
| 164 | 176 | E->Attributes = 1; |
| 165 | 177 | E->Name = DLLName->getRVA(); |
| ... | ... | @@ -230,6 +242,36 @@ static const uint8_t ThunkARM[] = { |
| 230 | 242 | 0x60, 0x47, // bx ip |
| 231 | 243 | }; |
| 232 | 244 | |
| 245 | static const uint8_t ThunkARM64[] = { | |
| 246 | 0x11, 0x00, 0x00, 0x90, // adrp x17, #0 __imp_<FUNCNAME> | |
| 247 | 0x31, 0x02, 0x00, 0x91, // add x17, x17, #0 :lo12:__imp_<FUNCNAME> | |
| 248 | 0xfd, 0x7b, 0xb3, 0xa9, // stp x29, x30, [sp, #-208]! | |
| 249 | 0xfd, 0x03, 0x00, 0x91, // mov x29, sp | |
| 250 | 0xe0, 0x07, 0x01, 0xa9, // stp x0, x1, [sp, #16] | |
| 251 | 0xe2, 0x0f, 0x02, 0xa9, // stp x2, x3, [sp, #32] | |
| 252 | 0xe4, 0x17, 0x03, 0xa9, // stp x4, x5, [sp, #48] | |
| 253 | 0xe6, 0x1f, 0x04, 0xa9, // stp x6, x7, [sp, #64] | |
| 254 | 0xe0, 0x87, 0x02, 0xad, // stp q0, q1, [sp, #80] | |
| 255 | 0xe2, 0x8f, 0x03, 0xad, // stp q2, q3, [sp, #112] | |
| 256 | 0xe4, 0x97, 0x04, 0xad, // stp q4, q5, [sp, #144] | |
| 257 | 0xe6, 0x9f, 0x05, 0xad, // stp q6, q7, [sp, #176] | |
| 258 | 0xe1, 0x03, 0x11, 0xaa, // mov x1, x17 | |
| 259 | 0x00, 0x00, 0x00, 0x90, // adrp x0, #0 DELAY_IMPORT_DESCRIPTOR | |
| 260 | 0x00, 0x00, 0x00, 0x91, // add x0, x0, #0 :lo12:DELAY_IMPORT_DESCRIPTOR | |
| 261 | 0x00, 0x00, 0x00, 0x94, // bl #0 __delayLoadHelper2 | |
| 262 | 0xf0, 0x03, 0x00, 0xaa, // mov x16, x0 | |
| 263 | 0xe6, 0x9f, 0x45, 0xad, // ldp q6, q7, [sp, #176] | |
| 264 | 0xe4, 0x97, 0x44, 0xad, // ldp q4, q5, [sp, #144] | |
| 265 | 0xe2, 0x8f, 0x43, 0xad, // ldp q2, q3, [sp, #112] | |
| 266 | 0xe0, 0x87, 0x42, 0xad, // ldp q0, q1, [sp, #80] | |
| 267 | 0xe6, 0x1f, 0x44, 0xa9, // ldp x6, x7, [sp, #64] | |
| 268 | 0xe4, 0x17, 0x43, 0xa9, // ldp x4, x5, [sp, #48] | |
| 269 | 0xe2, 0x0f, 0x42, 0xa9, // ldp x2, x3, [sp, #32] | |
| 270 | 0xe0, 0x07, 0x41, 0xa9, // ldp x0, x1, [sp, #16] | |
| 271 | 0xfd, 0x7b, 0xcd, 0xa8, // ldp x29, x30, [sp], #208 | |
| 272 | 0x00, 0x02, 0x1f, 0xd6, // br x16 | |
| 273 | }; | |
| 274 | ||
| 233 | 275 | // A chunk for the delay import thunk. |
| 234 | 276 | class ThunkChunkX64 : public Chunk { |
| 235 | 277 | public: |
| ... | ... | @@ -298,11 +340,35 @@ public: |
| 298 | 340 | Defined *Helper = nullptr; |
| 299 | 341 | }; |
| 300 | 342 | |
| 343 | class ThunkChunkARM64 : public Chunk { | |
| 344 | public: | |
| 345 | ThunkChunkARM64(Defined *I, Chunk *D, Defined *H) | |
| 346 | : Imp(I), Desc(D), Helper(H) {} | |
| 347 | ||
| 348 | size_t getSize() const override { return sizeof(ThunkARM64); } | |
| 349 | ||
| 350 | void writeTo(uint8_t *Buf) const override { | |
| 351 | memcpy(Buf + OutputSectionOff, ThunkARM64, sizeof(ThunkARM64)); | |
| 352 | applyArm64Addr(Buf + OutputSectionOff + 0, Imp->getRVA(), RVA + 0, 12); | |
| 353 | applyArm64Imm(Buf + OutputSectionOff + 4, Imp->getRVA() & 0xfff, 0); | |
| 354 | applyArm64Addr(Buf + OutputSectionOff + 52, Desc->getRVA(), RVA + 52, 12); | |
| 355 | applyArm64Imm(Buf + OutputSectionOff + 56, Desc->getRVA() & 0xfff, 0); | |
| 356 | applyArm64Branch26(Buf + OutputSectionOff + 60, | |
| 357 | Helper->getRVA() - RVA - 60); | |
| 358 | } | |
| 359 | ||
| 360 | Defined *Imp = nullptr; | |
| 361 | Chunk *Desc = nullptr; | |
| 362 | Defined *Helper = nullptr; | |
| 363 | }; | |
| 364 | ||
| 301 | 365 | // A chunk for the import descriptor table. |
| 302 | 366 | class DelayAddressChunk : public Chunk { |
| 303 | 367 | public: |
| 304 | explicit DelayAddressChunk(Chunk *C) : Thunk(C) { Alignment = ptrSize(); } | |
| 305 | size_t getSize() const override { return ptrSize(); } | |
| 368 | explicit DelayAddressChunk(Chunk *C) : Thunk(C) { | |
| 369 | Alignment = Config->Wordsize; | |
| 370 | } | |
| 371 | size_t getSize() const override { return Config->Wordsize; } | |
| 306 | 372 | |
| 307 | 373 | void writeTo(uint8_t *Buf) const override { |
| 308 | 374 | if (Config->is64()) { |
| ... | ... | @@ -338,6 +404,8 @@ public: |
| 338 | 404 | } |
| 339 | 405 | |
| 340 | 406 | void writeTo(uint8_t *Buf) const override { |
| 407 | memset(Buf + OutputSectionOff, 0, getSize()); | |
| 408 | ||
| 341 | 409 | auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff); |
| 342 | 410 | E->NameRVA = DLLName->getRVA(); |
| 343 | 411 | E->OrdinalBase = 0; |
| ... | ... | @@ -362,6 +430,8 @@ public: |
| 362 | 430 | size_t getSize() const override { return Size * 4; } |
| 363 | 431 | |
| 364 | 432 | void writeTo(uint8_t *Buf) const override { |
| 433 | memset(Buf + OutputSectionOff, 0, getSize()); | |
| 434 | ||
| 365 | 435 | for (const Export &E : Config->Exports) { |
| 366 | 436 | uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4; |
| 367 | 437 | uint32_t Bit = 0; |
| ... | ... | @@ -418,30 +488,6 @@ private: |
| 418 | 488 | |
| 419 | 489 | } // anonymous namespace |
| 420 | 490 | |
| 421 | uint64_t IdataContents::getDirSize() { | |
| 422 | return Dirs.size() * sizeof(ImportDirectoryTableEntry); | |
| 423 | } | |
| 424 | ||
| 425 | uint64_t IdataContents::getIATSize() { | |
| 426 | return Addresses.size() * ptrSize(); | |
| 427 | } | |
| 428 | ||
| 429 | // Returns a list of .idata contents. | |
| 430 | // See Microsoft PE/COFF spec 5.4 for details. | |
| 431 | std::vector<Chunk *> IdataContents::getChunks() { | |
| 432 | create(); | |
| 433 | ||
| 434 | // The loader assumes a specific order of data. | |
| 435 | // Add each type in the correct order. | |
| 436 | std::vector<Chunk *> V; | |
| 437 | V.insert(V.end(), Dirs.begin(), Dirs.end()); | |
| 438 | V.insert(V.end(), Lookups.begin(), Lookups.end()); | |
| 439 | V.insert(V.end(), Addresses.begin(), Addresses.end()); | |
| 440 | V.insert(V.end(), Hints.begin(), Hints.end()); | |
| 441 | V.insert(V.end(), DLLNames.begin(), DLLNames.end()); | |
| 442 | return V; | |
| 443 | } | |
| 444 | ||
| 445 | 491 | void IdataContents::create() { |
| 446 | 492 | std::vector<std::vector<DefinedImportData *>> V = binImports(Imports); |
| 447 | 493 | |
| ... | ... | @@ -465,8 +511,8 @@ void IdataContents::create() { |
| 465 | 511 | Hints.push_back(C); |
| 466 | 512 | } |
| 467 | 513 | // Terminate with null values. |
| 468 | Lookups.push_back(make<NullChunk>(ptrSize())); | |
| 469 | Addresses.push_back(make<NullChunk>(ptrSize())); | |
| 514 | Lookups.push_back(make<NullChunk>(Config->Wordsize)); | |
| 515 | Addresses.push_back(make<NullChunk>(Config->Wordsize)); | |
| 470 | 516 | |
| 471 | 517 | for (int I = 0, E = Syms.size(); I < E; ++I) |
| 472 | 518 | Syms[I]->setLocation(Addresses[Base + I]); |
| ... | ... | @@ -555,6 +601,8 @@ Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) { |
| 555 | 601 | return make<ThunkChunkX86>(S, Dir, Helper); |
| 556 | 602 | case ARMNT: |
| 557 | 603 | return make<ThunkChunkARM>(S, Dir, Helper); |
| 604 | case ARM64: | |
| 605 | return make<ThunkChunkARM64>(S, Dir, Helper); | |
| 558 | 606 | default: |
| 559 | 607 | llvm_unreachable("unsupported machine type"); |
| 560 | 608 | } |
deps/lld/COFF/DLL.h+1-8| ... | ... | @@ -19,19 +19,12 @@ namespace coff { |
| 19 | 19 | // Windows-specific. |
| 20 | 20 | // IdataContents creates all chunks for the DLL import table. |
| 21 | 21 | // You are supposed to call add() to add symbols and then |
| 22 | // call getChunks() to get a list of chunks. | |
| 22 | // call create() to populate the chunk vectors. | |
| 23 | 23 | class IdataContents { |
| 24 | 24 | public: |
| 25 | 25 | void add(DefinedImportData *Sym) { Imports.push_back(Sym); } |
| 26 | 26 | bool empty() { return Imports.empty(); } |
| 27 | std::vector<Chunk *> getChunks(); | |
| 28 | 27 | |
| 29 | uint64_t getDirRVA() { return Dirs[0]->getRVA(); } | |
| 30 | uint64_t getDirSize(); | |
| 31 | uint64_t getIATRVA() { return Addresses[0]->getRVA(); } | |
| 32 | uint64_t getIATSize(); | |
| 33 | ||
| 34 | private: | |
| 35 | 28 | void create(); |
| 36 | 29 | |
| 37 | 30 | std::vector<DefinedImportData *> Imports; |
deps/lld/COFF/Driver.cpp+276-185| ... | ... | @@ -32,6 +32,7 @@ |
| 32 | 32 | #include "llvm/Option/ArgList.h" |
| 33 | 33 | #include "llvm/Option/Option.h" |
| 34 | 34 | #include "llvm/Support/Debug.h" |
| 35 | #include "llvm/Support/LEB128.h" | |
| 35 | 36 | #include "llvm/Support/Path.h" |
| 36 | 37 | #include "llvm/Support/Process.h" |
| 37 | 38 | #include "llvm/Support/TarWriter.h" |
| ... | ... | @@ -56,7 +57,7 @@ Configuration *Config; |
| 56 | 57 | LinkerDriver *Driver; |
| 57 | 58 | |
| 58 | 59 | bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) { |
| 59 | errorHandler().LogName = sys::path::filename(Args[0]); | |
| 60 | errorHandler().LogName = args::getFilenameWithoutExe(Args[0]); | |
| 60 | 61 | errorHandler().ErrorOS = &Diag; |
| 61 | 62 | errorHandler().ColorDiagnostics = Diag.has_colors(); |
| 62 | 63 | errorHandler().ErrorLimitExceededMsg = |
| ... | ... | @@ -370,13 +371,30 @@ Optional<StringRef> LinkerDriver::findFile(StringRef Filename) { |
| 370 | 371 | return Path; |
| 371 | 372 | } |
| 372 | 373 | |
| 374 | // MinGW specific. If an embedded directive specified to link to | |
| 375 | // foo.lib, but it isn't found, try libfoo.a instead. | |
| 376 | StringRef LinkerDriver::doFindLibMinGW(StringRef Filename) { | |
| 377 | if (Filename.contains('/') || Filename.contains('\\')) | |
| 378 | return Filename; | |
| 379 | ||
| 380 | SmallString<128> S = Filename; | |
| 381 | sys::path::replace_extension(S, ".a"); | |
| 382 | StringRef LibName = Saver.save("lib" + S.str()); | |
| 383 | return doFindFile(LibName); | |
| 384 | } | |
| 385 | ||
| 373 | 386 | // Find library file from search path. |
| 374 | 387 | StringRef LinkerDriver::doFindLib(StringRef Filename) { |
| 375 | 388 | // Add ".lib" to Filename if that has no file extension. |
| 376 | 389 | bool HasExt = Filename.contains('.'); |
| 377 | 390 | if (!HasExt) |
| 378 | 391 | Filename = Saver.save(Filename + ".lib"); |
| 379 | return doFindFile(Filename); | |
| 392 | StringRef Ret = doFindFile(Filename); | |
| 393 | // For MinGW, if the find above didn't turn up anything, try | |
| 394 | // looking for a MinGW formatted library name. | |
| 395 | if (Config->MinGW && Ret == Filename) | |
| 396 | return doFindLibMinGW(Filename); | |
| 397 | return Ret; | |
| 380 | 398 | } |
| 381 | 399 | |
| 382 | 400 | // Resolves a library path. /nodefaultlib options are taken into |
| ... | ... | @@ -429,29 +447,48 @@ StringRef LinkerDriver::findDefaultEntry() { |
| 429 | 447 | assert(Config->Subsystem != IMAGE_SUBSYSTEM_UNKNOWN && |
| 430 | 448 | "must handle /subsystem before calling this"); |
| 431 | 449 | |
| 432 | // As a special case, if /nodefaultlib is given, we directly look for an | |
| 433 | // entry point. This is because, if no default library is linked, users | |
| 434 | // need to define an entry point instead of a "main". | |
| 435 | bool FindMain = !Config->NoDefaultLibAll; | |
| 450 | if (Config->MinGW) | |
| 451 | return mangle(Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI | |
| 452 | ? "WinMainCRTStartup" | |
| 453 | : "mainCRTStartup"); | |
| 454 | ||
| 436 | 455 | if (Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) { |
| 437 | if (findUnderscoreMangle(FindMain ? "WinMain" : "WinMainCRTStartup")) | |
| 438 | return mangle("WinMainCRTStartup"); | |
| 439 | if (findUnderscoreMangle(FindMain ? "wWinMain" : "wWinMainCRTStartup")) | |
| 440 | return mangle("wWinMainCRTStartup"); | |
| 441 | } | |
| 442 | if (findUnderscoreMangle(FindMain ? "main" : "mainCRTStartup")) | |
| 443 | return mangle("mainCRTStartup"); | |
| 444 | if (findUnderscoreMangle(FindMain ? "wmain" : "wmainCRTStartup")) | |
| 445 | return mangle("wmainCRTStartup"); | |
| 446 | return ""; | |
| 456 | if (findUnderscoreMangle("wWinMain")) { | |
| 457 | if (!findUnderscoreMangle("WinMain")) | |
| 458 | return mangle("wWinMainCRTStartup"); | |
| 459 | warn("found both wWinMain and WinMain; using latter"); | |
| 460 | } | |
| 461 | return mangle("WinMainCRTStartup"); | |
| 462 | } | |
| 463 | if (findUnderscoreMangle("wmain")) { | |
| 464 | if (!findUnderscoreMangle("main")) | |
| 465 | return mangle("wmainCRTStartup"); | |
| 466 | warn("found both wmain and main; using latter"); | |
| 467 | } | |
| 468 | return mangle("mainCRTStartup"); | |
| 447 | 469 | } |
| 448 | 470 | |
| 449 | 471 | WindowsSubsystem LinkerDriver::inferSubsystem() { |
| 450 | 472 | if (Config->DLL) |
| 451 | 473 | return IMAGE_SUBSYSTEM_WINDOWS_GUI; |
| 452 | if (findUnderscoreMangle("main") || findUnderscoreMangle("wmain")) | |
| 474 | if (Config->MinGW) | |
| 475 | return IMAGE_SUBSYSTEM_WINDOWS_CUI; | |
| 476 | // Note that link.exe infers the subsystem from the presence of these | |
| 477 | // functions even if /entry: or /nodefaultlib are passed which causes them | |
| 478 | // to not be called. | |
| 479 | bool HaveMain = findUnderscoreMangle("main"); | |
| 480 | bool HaveWMain = findUnderscoreMangle("wmain"); | |
| 481 | bool HaveWinMain = findUnderscoreMangle("WinMain"); | |
| 482 | bool HaveWWinMain = findUnderscoreMangle("wWinMain"); | |
| 483 | if (HaveMain || HaveWMain) { | |
| 484 | if (HaveWinMain || HaveWWinMain) { | |
| 485 | warn(std::string("found ") + (HaveMain ? "main" : "wmain") + " and " + | |
| 486 | (HaveWinMain ? "WinMain" : "wWinMain") + | |
| 487 | "; defaulting to /subsystem:console"); | |
| 488 | } | |
| 453 | 489 | return IMAGE_SUBSYSTEM_WINDOWS_CUI; |
| 454 | if (findUnderscoreMangle("WinMain") || findUnderscoreMangle("wWinMain")) | |
| 490 | } | |
| 491 | if (HaveWinMain || HaveWWinMain) | |
| 455 | 492 | return IMAGE_SUBSYSTEM_WINDOWS_GUI; |
| 456 | 493 | return IMAGE_SUBSYSTEM_UNKNOWN; |
| 457 | 494 | } |
| ... | ... | @@ -497,26 +534,65 @@ static std::string createResponseFile(const opt::InputArgList &Args, |
| 497 | 534 | return Data.str(); |
| 498 | 535 | } |
| 499 | 536 | |
| 500 | static unsigned getDefaultDebugType(const opt::InputArgList &Args) { | |
| 501 | unsigned DebugTypes = static_cast<unsigned>(DebugType::CV); | |
| 537 | enum class DebugKind { Unknown, None, Full, FastLink, GHash, Dwarf, Symtab }; | |
| 538 | ||
| 539 | static DebugKind parseDebugKind(const opt::InputArgList &Args) { | |
| 540 | auto *A = Args.getLastArg(OPT_debug, OPT_debug_opt); | |
| 541 | if (!A) | |
| 542 | return DebugKind::None; | |
| 543 | if (A->getNumValues() == 0) | |
| 544 | return DebugKind::Full; | |
| 545 | ||
| 546 | DebugKind Debug = StringSwitch<DebugKind>(A->getValue()) | |
| 547 | .CaseLower("none", DebugKind::None) | |
| 548 | .CaseLower("full", DebugKind::Full) | |
| 549 | .CaseLower("fastlink", DebugKind::FastLink) | |
| 550 | // LLD extensions | |
| 551 | .CaseLower("ghash", DebugKind::GHash) | |
| 552 | .CaseLower("dwarf", DebugKind::Dwarf) | |
| 553 | .CaseLower("symtab", DebugKind::Symtab) | |
| 554 | .Default(DebugKind::Unknown); | |
| 555 | ||
| 556 | if (Debug == DebugKind::FastLink) { | |
| 557 | warn("/debug:fastlink unsupported; using /debug:full"); | |
| 558 | return DebugKind::Full; | |
| 559 | } | |
| 560 | if (Debug == DebugKind::Unknown) { | |
| 561 | error("/debug: unknown option: " + Twine(A->getValue())); | |
| 562 | return DebugKind::None; | |
| 563 | } | |
| 564 | return Debug; | |
| 565 | } | |
| 566 | ||
| 567 | static unsigned parseDebugTypes(const opt::InputArgList &Args) { | |
| 568 | unsigned DebugTypes = static_cast<unsigned>(DebugType::None); | |
| 569 | ||
| 570 | if (auto *A = Args.getLastArg(OPT_debugtype)) { | |
| 571 | SmallVector<StringRef, 3> Types; | |
| 572 | A->getSpelling().split(Types, ',', /*KeepEmpty=*/false); | |
| 573 | ||
| 574 | for (StringRef Type : Types) { | |
| 575 | unsigned V = StringSwitch<unsigned>(Type.lower()) | |
| 576 | .Case("cv", static_cast<unsigned>(DebugType::CV)) | |
| 577 | .Case("pdata", static_cast<unsigned>(DebugType::PData)) | |
| 578 | .Case("fixup", static_cast<unsigned>(DebugType::Fixup)) | |
| 579 | .Default(0); | |
| 580 | if (V == 0) { | |
| 581 | warn("/debugtype: unknown option: " + Twine(A->getValue())); | |
| 582 | continue; | |
| 583 | } | |
| 584 | DebugTypes |= V; | |
| 585 | } | |
| 586 | return DebugTypes; | |
| 587 | } | |
| 588 | ||
| 589 | // Default debug types | |
| 590 | DebugTypes = static_cast<unsigned>(DebugType::CV); | |
| 502 | 591 | if (Args.hasArg(OPT_driver)) |
| 503 | 592 | DebugTypes |= static_cast<unsigned>(DebugType::PData); |
| 504 | 593 | if (Args.hasArg(OPT_profile)) |
| 505 | 594 | DebugTypes |= static_cast<unsigned>(DebugType::Fixup); |
| 506 | return DebugTypes; | |
| 507 | } | |
| 508 | ||
| 509 | static unsigned parseDebugType(StringRef Arg) { | |
| 510 | SmallVector<StringRef, 3> Types; | |
| 511 | Arg.split(Types, ',', /*KeepEmpty=*/false); | |
| 512 | 595 | |
| 513 | unsigned DebugTypes = static_cast<unsigned>(DebugType::None); | |
| 514 | for (StringRef Type : Types) | |
| 515 | DebugTypes |= StringSwitch<unsigned>(Type.lower()) | |
| 516 | .Case("cv", static_cast<unsigned>(DebugType::CV)) | |
| 517 | .Case("pdata", static_cast<unsigned>(DebugType::PData)) | |
| 518 | .Case("fixup", static_cast<unsigned>(DebugType::Fixup)) | |
| 519 | .Default(0); | |
| 520 | 596 | return DebugTypes; |
| 521 | 597 | } |
| 522 | 598 | |
| ... | ... | @@ -676,131 +752,6 @@ static void parseModuleDefs(StringRef Path) { |
| 676 | 752 | } |
| 677 | 753 | } |
| 678 | 754 | |
| 679 | // A helper function for filterBitcodeFiles. | |
| 680 | static bool needsRebuilding(MemoryBufferRef MB) { | |
| 681 | // The MSVC linker doesn't support thin archives, so if it's a thin | |
| 682 | // archive, we always need to rebuild it. | |
| 683 | std::unique_ptr<Archive> File = | |
| 684 | CHECK(Archive::create(MB), "Failed to read " + MB.getBufferIdentifier()); | |
| 685 | if (File->isThin()) | |
| 686 | return true; | |
| 687 | ||
| 688 | // Returns true if the archive contains at least one bitcode file. | |
| 689 | for (MemoryBufferRef Member : getArchiveMembers(File.get())) | |
| 690 | if (identify_magic(Member.getBuffer()) == file_magic::bitcode) | |
| 691 | return true; | |
| 692 | return false; | |
| 693 | } | |
| 694 | ||
| 695 | // Opens a given path as an archive file and removes bitcode files | |
| 696 | // from them if exists. This function is to appease the MSVC linker as | |
| 697 | // their linker doesn't like archive files containing non-native | |
| 698 | // object files. | |
| 699 | // | |
| 700 | // If a given archive doesn't contain bitcode files, the archive path | |
| 701 | // is returned as-is. Otherwise, a new temporary file is created and | |
| 702 | // its path is returned. | |
| 703 | static Optional<std::string> | |
| 704 | filterBitcodeFiles(StringRef Path, std::vector<std::string> &TemporaryFiles) { | |
| 705 | std::unique_ptr<MemoryBuffer> MB = CHECK( | |
| 706 | MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path); | |
| 707 | MemoryBufferRef MBRef = MB->getMemBufferRef(); | |
| 708 | file_magic Magic = identify_magic(MBRef.getBuffer()); | |
| 709 | ||
| 710 | if (Magic == file_magic::bitcode) | |
| 711 | return None; | |
| 712 | if (Magic != file_magic::archive) | |
| 713 | return Path.str(); | |
| 714 | if (!needsRebuilding(MBRef)) | |
| 715 | return Path.str(); | |
| 716 | ||
| 717 | std::unique_ptr<Archive> File = | |
| 718 | CHECK(Archive::create(MBRef), | |
| 719 | MBRef.getBufferIdentifier() + ": failed to parse archive"); | |
| 720 | ||
| 721 | std::vector<NewArchiveMember> New; | |
| 722 | for (MemoryBufferRef Member : getArchiveMembers(File.get())) | |
| 723 | if (identify_magic(Member.getBuffer()) != file_magic::bitcode) | |
| 724 | New.emplace_back(Member); | |
| 725 | ||
| 726 | if (New.empty()) | |
| 727 | return None; | |
| 728 | ||
| 729 | log("Creating a temporary archive for " + Path + " to remove bitcode files"); | |
| 730 | ||
| 731 | SmallString<128> S; | |
| 732 | if (std::error_code EC = sys::fs::createTemporaryFile( | |
| 733 | "lld-" + sys::path::stem(Path), ".lib", S)) | |
| 734 | fatal("cannot create a temporary file: " + EC.message()); | |
| 735 | std::string Temp = S.str(); | |
| 736 | TemporaryFiles.push_back(Temp); | |
| 737 | ||
| 738 | Error E = | |
| 739 | llvm::writeArchive(Temp, New, /*WriteSymtab=*/true, Archive::Kind::K_GNU, | |
| 740 | /*Deterministics=*/true, | |
| 741 | /*Thin=*/false); | |
| 742 | handleAllErrors(std::move(E), [&](const ErrorInfoBase &EI) { | |
| 743 | error("failed to create a new archive " + S.str() + ": " + EI.message()); | |
| 744 | }); | |
| 745 | return Temp; | |
| 746 | } | |
| 747 | ||
| 748 | // Create response file contents and invoke the MSVC linker. | |
| 749 | void LinkerDriver::invokeMSVC(opt::InputArgList &Args) { | |
| 750 | std::string Rsp = "/nologo\n"; | |
| 751 | std::vector<std::string> Temps; | |
| 752 | ||
| 753 | // Write out archive members that we used in symbol resolution and pass these | |
| 754 | // to MSVC before any archives, so that MSVC uses the same objects to satisfy | |
| 755 | // references. | |
| 756 | for (ObjFile *Obj : ObjFile::Instances) { | |
| 757 | if (Obj->ParentName.empty()) | |
| 758 | continue; | |
| 759 | SmallString<128> S; | |
| 760 | int Fd; | |
| 761 | if (auto EC = sys::fs::createTemporaryFile( | |
| 762 | "lld-" + sys::path::filename(Obj->ParentName), ".obj", Fd, S)) | |
| 763 | fatal("cannot create a temporary file: " + EC.message()); | |
| 764 | raw_fd_ostream OS(Fd, /*shouldClose*/ true); | |
| 765 | OS << Obj->MB.getBuffer(); | |
| 766 | Temps.push_back(S.str()); | |
| 767 | Rsp += quote(S) + "\n"; | |
| 768 | } | |
| 769 | ||
| 770 | for (auto *Arg : Args) { | |
| 771 | switch (Arg->getOption().getID()) { | |
| 772 | case OPT_linkrepro: | |
| 773 | case OPT_lldmap: | |
| 774 | case OPT_lldmap_file: | |
| 775 | case OPT_lldsavetemps: | |
| 776 | case OPT_msvclto: | |
| 777 | // LLD-specific options are stripped. | |
| 778 | break; | |
| 779 | case OPT_opt: | |
| 780 | if (!StringRef(Arg->getValue()).startswith("lld")) | |
| 781 | Rsp += toString(*Arg) + " "; | |
| 782 | break; | |
| 783 | case OPT_INPUT: { | |
| 784 | if (Optional<StringRef> Path = doFindFile(Arg->getValue())) { | |
| 785 | if (Optional<std::string> S = filterBitcodeFiles(*Path, Temps)) | |
| 786 | Rsp += quote(*S) + "\n"; | |
| 787 | continue; | |
| 788 | } | |
| 789 | Rsp += quote(Arg->getValue()) + "\n"; | |
| 790 | break; | |
| 791 | } | |
| 792 | default: | |
| 793 | Rsp += toString(*Arg) + "\n"; | |
| 794 | } | |
| 795 | } | |
| 796 | ||
| 797 | std::vector<StringRef> ObjFiles = Symtab->compileBitcodeFiles(); | |
| 798 | runMSVCLinker(Rsp, ObjFiles); | |
| 799 | ||
| 800 | for (StringRef Path : Temps) | |
| 801 | sys::fs::remove(Path); | |
| 802 | } | |
| 803 | ||
| 804 | 755 | void LinkerDriver::enqueueTask(std::function<void()> Task) { |
| 805 | 756 | TaskQueue.push_back(std::move(Task)); |
| 806 | 757 | } |
| ... | ... | @@ -856,6 +807,97 @@ static void parseOrderFile(StringRef Arg) { |
| 856 | 807 | } |
| 857 | 808 | } |
| 858 | 809 | |
| 810 | static void markAddrsig(Symbol *S) { | |
| 811 | if (auto *D = dyn_cast_or_null<Defined>(S)) | |
| 812 | if (Chunk *C = D->getChunk()) | |
| 813 | C->KeepUnique = true; | |
| 814 | } | |
| 815 | ||
| 816 | static void findKeepUniqueSections() { | |
| 817 | // Exported symbols could be address-significant in other executables or DSOs, | |
| 818 | // so we conservatively mark them as address-significant. | |
| 819 | for (Export &R : Config->Exports) | |
| 820 | markAddrsig(R.Sym); | |
| 821 | ||
| 822 | // Visit the address-significance table in each object file and mark each | |
| 823 | // referenced symbol as address-significant. | |
| 824 | for (ObjFile *Obj : ObjFile::Instances) { | |
| 825 | ArrayRef<Symbol *> Syms = Obj->getSymbols(); | |
| 826 | if (Obj->AddrsigSec) { | |
| 827 | ArrayRef<uint8_t> Contents; | |
| 828 | Obj->getCOFFObj()->getSectionContents(Obj->AddrsigSec, Contents); | |
| 829 | const uint8_t *Cur = Contents.begin(); | |
| 830 | while (Cur != Contents.end()) { | |
| 831 | unsigned Size; | |
| 832 | const char *Err; | |
| 833 | uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err); | |
| 834 | if (Err) | |
| 835 | fatal(toString(Obj) + ": could not decode addrsig section: " + Err); | |
| 836 | if (SymIndex >= Syms.size()) | |
| 837 | fatal(toString(Obj) + ": invalid symbol index in addrsig section"); | |
| 838 | markAddrsig(Syms[SymIndex]); | |
| 839 | Cur += Size; | |
| 840 | } | |
| 841 | } else { | |
| 842 | // If an object file does not have an address-significance table, | |
| 843 | // conservatively mark all of its symbols as address-significant. | |
| 844 | for (Symbol *S : Syms) | |
| 845 | markAddrsig(S); | |
| 846 | } | |
| 847 | } | |
| 848 | } | |
| 849 | ||
| 850 | // link.exe replaces each %foo% in AltPath with the contents of environment | |
| 851 | // variable foo, and adds the two magic env vars _PDB (expands to the basename | |
| 852 | // of pdb's output path) and _EXT (expands to the extension of the output | |
| 853 | // binary). | |
| 854 | // lld only supports %_PDB% and %_EXT% and warns on references to all other env | |
| 855 | // vars. | |
| 856 | static void parsePDBAltPath(StringRef AltPath) { | |
| 857 | SmallString<128> Buf; | |
| 858 | StringRef PDBBasename = | |
| 859 | sys::path::filename(Config->PDBPath, sys::path::Style::windows); | |
| 860 | StringRef BinaryExtension = | |
| 861 | sys::path::extension(Config->OutputFile, sys::path::Style::windows); | |
| 862 | if (!BinaryExtension.empty()) | |
| 863 | BinaryExtension = BinaryExtension.substr(1); // %_EXT% does not include '.'. | |
| 864 | ||
| 865 | // Invariant: | |
| 866 | // +--------- Cursor ('a...' might be the empty string). | |
| 867 | // | +----- FirstMark | |
| 868 | // | | +- SecondMark | |
| 869 | // v v v | |
| 870 | // a...%...%... | |
| 871 | size_t Cursor = 0; | |
| 872 | while (Cursor < AltPath.size()) { | |
| 873 | size_t FirstMark, SecondMark; | |
| 874 | if ((FirstMark = AltPath.find('%', Cursor)) == StringRef::npos || | |
| 875 | (SecondMark = AltPath.find('%', FirstMark + 1)) == StringRef::npos) { | |
| 876 | // Didn't find another full fragment, treat rest of string as literal. | |
| 877 | Buf.append(AltPath.substr(Cursor)); | |
| 878 | break; | |
| 879 | } | |
| 880 | ||
| 881 | // Found a full fragment. Append text in front of first %, and interpret | |
| 882 | // text between first and second % as variable name. | |
| 883 | Buf.append(AltPath.substr(Cursor, FirstMark - Cursor)); | |
| 884 | StringRef Var = AltPath.substr(FirstMark, SecondMark - FirstMark + 1); | |
| 885 | if (Var.equals_lower("%_pdb%")) | |
| 886 | Buf.append(PDBBasename); | |
| 887 | else if (Var.equals_lower("%_ext%")) | |
| 888 | Buf.append(BinaryExtension); | |
| 889 | else { | |
| 890 | warn("only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping " + | |
| 891 | Var + " as literal"); | |
| 892 | Buf.append(Var); | |
| 893 | } | |
| 894 | ||
| 895 | Cursor = SecondMark + 1; | |
| 896 | } | |
| 897 | ||
| 898 | Config->PDBAltPath = Buf; | |
| 899 | } | |
| 900 | ||
| 859 | 901 | void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 860 | 902 | // If the first command line argument is "/lib", link.exe acts like lib.exe. |
| 861 | 903 | // We call our own implementation of lib.exe that understands bitcode files. |
| ... | ... | @@ -944,11 +986,17 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 944 | 986 | |
| 945 | 987 | // Handle /ignore |
| 946 | 988 | for (auto *Arg : Args.filtered(OPT_ignore)) { |
| 947 | if (StringRef(Arg->getValue()) == "4037") | |
| 948 | Config->WarnMissingOrderSymbol = false; | |
| 949 | else if (StringRef(Arg->getValue()) == "4217") | |
| 950 | Config->WarnLocallyDefinedImported = false; | |
| 951 | // Other warning numbers are ignored. | |
| 989 | SmallVector<StringRef, 8> Vec; | |
| 990 | StringRef(Arg->getValue()).split(Vec, ','); | |
| 991 | for (StringRef S : Vec) { | |
| 992 | if (S == "4037") | |
| 993 | Config->WarnMissingOrderSymbol = false; | |
| 994 | else if (S == "4099") | |
| 995 | Config->WarnDebugInfoUnusable = false; | |
| 996 | else if (S == "4217") | |
| 997 | Config->WarnLocallyDefinedImported = false; | |
| 998 | // Other warning numbers are ignored. | |
| 999 | } | |
| 952 | 1000 | } |
| 953 | 1001 | |
| 954 | 1002 | // Handle /out |
| ... | ... | @@ -962,20 +1010,26 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 962 | 1010 | |
| 963 | 1011 | // Handle /force or /force:unresolved |
| 964 | 1012 | if (Args.hasArg(OPT_force, OPT_force_unresolved)) |
| 965 | Config->Force = true; | |
| 1013 | Config->ForceUnresolved = true; | |
| 1014 | ||
| 1015 | // Handle /force or /force:multiple | |
| 1016 | if (Args.hasArg(OPT_force, OPT_force_multiple)) | |
| 1017 | Config->ForceMultiple = true; | |
| 966 | 1018 | |
| 967 | 1019 | // Handle /debug |
| 968 | if (Args.hasArg(OPT_debug, OPT_debug_dwarf, OPT_debug_ghash)) { | |
| 1020 | DebugKind Debug = parseDebugKind(Args); | |
| 1021 | if (Debug == DebugKind::Full || Debug == DebugKind::Dwarf || | |
| 1022 | Debug == DebugKind::GHash) { | |
| 969 | 1023 | Config->Debug = true; |
| 970 | 1024 | Config->Incremental = true; |
| 971 | if (auto *Arg = Args.getLastArg(OPT_debugtype)) | |
| 972 | Config->DebugTypes = parseDebugType(Arg->getValue()); | |
| 973 | else | |
| 974 | Config->DebugTypes = getDefaultDebugType(Args); | |
| 975 | 1025 | } |
| 976 | 1026 | |
| 1027 | // Handle /debugtype | |
| 1028 | Config->DebugTypes = parseDebugTypes(Args); | |
| 1029 | ||
| 977 | 1030 | // Handle /pdb |
| 978 | bool ShouldCreatePDB = Args.hasArg(OPT_debug, OPT_debug_ghash); | |
| 1031 | bool ShouldCreatePDB = | |
| 1032 | (Debug == DebugKind::Full || Debug == DebugKind::GHash); | |
| 979 | 1033 | if (ShouldCreatePDB) { |
| 980 | 1034 | if (auto *Arg = Args.getLastArg(OPT_pdb)) |
| 981 | 1035 | Config->PDBPath = Arg->getValue(); |
| ... | ... | @@ -1096,7 +1150,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1096 | 1150 | Config->Implib = Arg->getValue(); |
| 1097 | 1151 | |
| 1098 | 1152 | // Handle /opt. |
| 1099 | bool DoGC = !Args.hasArg(OPT_debug) || Args.hasArg(OPT_profile); | |
| 1153 | bool DoGC = Debug == DebugKind::None || Args.hasArg(OPT_profile); | |
| 1100 | 1154 | unsigned ICFLevel = |
| 1101 | 1155 | Args.hasArg(OPT_profile) ? 0 : 1; // 0: off, 1: limited, 2: on |
| 1102 | 1156 | unsigned TailMerge = 1; |
| ... | ... | @@ -1181,6 +1235,12 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1181 | 1235 | parseMerge(".xdata=.rdata"); |
| 1182 | 1236 | parseMerge(".bss=.data"); |
| 1183 | 1237 | |
| 1238 | if (Config->MinGW) { | |
| 1239 | parseMerge(".ctors=.rdata"); | |
| 1240 | parseMerge(".dtors=.rdata"); | |
| 1241 | parseMerge(".CRT=.rdata"); | |
| 1242 | } | |
| 1243 | ||
| 1184 | 1244 | // Handle /section |
| 1185 | 1245 | for (auto *Arg : Args.filtered(OPT_section)) |
| 1186 | 1246 | parseSection(Arg->getValue()); |
| ... | ... | @@ -1234,9 +1294,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1234 | 1294 | Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true); |
| 1235 | 1295 | Config->TerminalServerAware = |
| 1236 | 1296 | !Config->DLL && Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true); |
| 1237 | Config->DebugDwarf = Args.hasArg(OPT_debug_dwarf); | |
| 1238 | Config->DebugGHashes = Args.hasArg(OPT_debug_ghash); | |
| 1239 | Config->DebugSymtab = Args.hasArg(OPT_debug_symtab); | |
| 1297 | Config->DebugDwarf = Debug == DebugKind::Dwarf; | |
| 1298 | Config->DebugGHashes = Debug == DebugKind::GHash; | |
| 1299 | Config->DebugSymtab = Debug == DebugKind::Symtab; | |
| 1240 | 1300 | |
| 1241 | 1301 | Config->MapFile = getMapFile(Args); |
| 1242 | 1302 | |
| ... | ... | @@ -1266,10 +1326,14 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1266 | 1326 | return; |
| 1267 | 1327 | |
| 1268 | 1328 | std::set<sys::fs::UniqueID> WholeArchives; |
| 1269 | for (auto *Arg : Args.filtered(OPT_wholearchive_file)) | |
| 1270 | if (Optional<StringRef> Path = doFindFile(Arg->getValue())) | |
| 1329 | AutoExporter Exporter; | |
| 1330 | for (auto *Arg : Args.filtered(OPT_wholearchive_file)) { | |
| 1331 | if (Optional<StringRef> Path = doFindFile(Arg->getValue())) { | |
| 1271 | 1332 | if (Optional<sys::fs::UniqueID> ID = getUniqueID(*Path)) |
| 1272 | 1333 | WholeArchives.insert(*ID); |
| 1334 | Exporter.addWholeArchive(*Path); | |
| 1335 | } | |
| 1336 | } | |
| 1273 | 1337 | |
| 1274 | 1338 | // A predicate returning true if a given path is an argument for |
| 1275 | 1339 | // /wholearchive:, or /wholearchive is enabled globally. |
| ... | ... | @@ -1300,12 +1364,16 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1300 | 1364 | // Read all input files given via the command line. |
| 1301 | 1365 | run(); |
| 1302 | 1366 | |
| 1367 | if (errorCount()) | |
| 1368 | return; | |
| 1369 | ||
| 1303 | 1370 | // We should have inferred a machine type by now from the input files, but if |
| 1304 | 1371 | // not we assume x64. |
| 1305 | 1372 | if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) { |
| 1306 | 1373 | warn("/machine is not specified. x64 is assumed"); |
| 1307 | 1374 | Config->Machine = AMD64; |
| 1308 | 1375 | } |
| 1376 | Config->Wordsize = Config->is64() ? 8 : 4; | |
| 1309 | 1377 | |
| 1310 | 1378 | // Input files can be Windows resource files (.res files). We use |
| 1311 | 1379 | // WindowsResource to convert resource files to a regular COFF file, |
| ... | ... | @@ -1418,6 +1486,9 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1418 | 1486 | // tools won't work correctly if these assumptions are not held. |
| 1419 | 1487 | sys::fs::make_absolute(Config->PDBAltPath); |
| 1420 | 1488 | sys::path::remove_dots(Config->PDBAltPath); |
| 1489 | } else { | |
| 1490 | // Don't do this earlier, so that Config->OutputFile is ready. | |
| 1491 | parsePDBAltPath(Config->PDBAltPath); | |
| 1421 | 1492 | } |
| 1422 | 1493 | } |
| 1423 | 1494 | |
| ... | ... | @@ -1441,6 +1512,13 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1441 | 1512 | // Needed for MSVC 2017 15.5 CRT. |
| 1442 | 1513 | Symtab->addAbsolute(mangle("__enclave_config"), 0); |
| 1443 | 1514 | |
| 1515 | if (Config->MinGW) { | |
| 1516 | Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0); | |
| 1517 | Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0); | |
| 1518 | Symtab->addAbsolute(mangle("__CTOR_LIST__"), 0); | |
| 1519 | Symtab->addAbsolute(mangle("__DTOR_LIST__"), 0); | |
| 1520 | } | |
| 1521 | ||
| 1444 | 1522 | // This code may add new undefined symbols to the link, which may enqueue more |
| 1445 | 1523 | // symbol resolution tasks, so we need to continue executing tasks until we |
| 1446 | 1524 | // converge. |
| ... | ... | @@ -1480,18 +1558,29 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1480 | 1558 | if (errorCount()) |
| 1481 | 1559 | return; |
| 1482 | 1560 | |
| 1483 | // If /msvclto is given, we use the MSVC linker to link LTO output files. | |
| 1484 | // This is useful because MSVC link.exe can generate complete PDBs. | |
| 1485 | if (Args.hasArg(OPT_msvclto)) { | |
| 1486 | invokeMSVC(Args); | |
| 1487 | return; | |
| 1488 | } | |
| 1489 | ||
| 1490 | 1561 | // Do LTO by compiling bitcode input files to a set of native COFF files then |
| 1491 | 1562 | // link those files. |
| 1492 | 1563 | Symtab->addCombinedLTOObjects(); |
| 1493 | 1564 | run(); |
| 1494 | 1565 | |
| 1566 | if (Config->MinGW) { | |
| 1567 | // Load any further object files that might be needed for doing automatic | |
| 1568 | // imports. | |
| 1569 | // | |
| 1570 | // For cases with no automatically imported symbols, this iterates once | |
| 1571 | // over the symbol table and doesn't do anything. | |
| 1572 | // | |
| 1573 | // For the normal case with a few automatically imported symbols, this | |
| 1574 | // should only need to be run once, since each new object file imported | |
| 1575 | // is an import library and wouldn't add any new undefined references, | |
| 1576 | // but there's nothing stopping the __imp_ symbols from coming from a | |
| 1577 | // normal object file as well (although that won't be used for the | |
| 1578 | // actual autoimport later on). If this pass adds new undefined references, | |
| 1579 | // we won't iterate further to resolve them. | |
| 1580 | Symtab->loadMinGWAutomaticImports(); | |
| 1581 | run(); | |
| 1582 | } | |
| 1583 | ||
| 1495 | 1584 | // Make sure we have resolved all symbols. |
| 1496 | 1585 | Symtab->reportRemainingUndefines(); |
| 1497 | 1586 | if (errorCount()) |
| ... | ... | @@ -1510,7 +1599,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1510 | 1599 | // are chosen to be exported. |
| 1511 | 1600 | if (Config->DLL && ((Config->MinGW && Config->Exports.empty()) || |
| 1512 | 1601 | Args.hasArg(OPT_export_all_symbols))) { |
| 1513 | AutoExporter Exporter; | |
| 1602 | Exporter.initSymbolExcludes(); | |
| 1514 | 1603 | |
| 1515 | 1604 | Symtab->forEachSymbol([=](Symbol *S) { |
| 1516 | 1605 | auto *Def = dyn_cast<Defined>(S); |
| ... | ... | @@ -1574,8 +1663,10 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 1574 | 1663 | markLive(Symtab->getChunks()); |
| 1575 | 1664 | |
| 1576 | 1665 | // Identify identical COMDAT sections to merge them. |
| 1577 | if (Config->DoICF) | |
| 1666 | if (Config->DoICF) { | |
| 1667 | findKeepUniqueSections(); | |
| 1578 | 1668 | doICF(Symtab->getChunks()); |
| 1669 | } | |
| 1579 | 1670 | |
| 1580 | 1671 | // Write the result. |
| 1581 | 1672 | writeResult(); |
deps/lld/COFF/Driver.h+1-2| ... | ... | @@ -89,6 +89,7 @@ private: |
| 89 | 89 | Optional<StringRef> findLib(StringRef Filename); |
| 90 | 90 | StringRef doFindFile(StringRef Filename); |
| 91 | 91 | StringRef doFindLib(StringRef Filename); |
| 92 | StringRef doFindLibMinGW(StringRef Filename); | |
| 92 | 93 | |
| 93 | 94 | // Parses LIB environment which contains a list of search paths. |
| 94 | 95 | void addLibSearchPaths(); |
| ... | ... | @@ -114,8 +115,6 @@ private: |
| 114 | 115 | StringRef findDefaultEntry(); |
| 115 | 116 | WindowsSubsystem inferSubsystem(); |
| 116 | 117 | |
| 117 | void invokeMSVC(llvm::opt::InputArgList &Args); | |
| 118 | ||
| 119 | 118 | void addBuffer(std::unique_ptr<MemoryBuffer> MB, bool WholeArchive); |
| 120 | 119 | void addArchiveBuffer(MemoryBufferRef MBRef, StringRef SymName, |
| 121 | 120 | StringRef ParentName); |
deps/lld/COFF/DriverUtils.cpp+3-21| ... | ... | @@ -713,26 +713,6 @@ MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs) { |
| 713 | 713 | return MBRef; |
| 714 | 714 | } |
| 715 | 715 | |
| 716 | // Run MSVC link.exe for given in-memory object files. | |
| 717 | // Command line options are copied from those given to LLD. | |
| 718 | // This is for the /msvclto option. | |
| 719 | void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects) { | |
| 720 | // Write the in-memory object files to disk. | |
| 721 | std::vector<TemporaryFile> Temps; | |
| 722 | for (StringRef S : Objects) { | |
| 723 | Temps.emplace_back("lto", "obj", S); | |
| 724 | Rsp += quote(Temps.back().Path) + "\n"; | |
| 725 | } | |
| 726 | ||
| 727 | log("link.exe " + Rsp); | |
| 728 | ||
| 729 | // Run MSVC link.exe. | |
| 730 | Temps.emplace_back("lto", "rsp", Rsp); | |
| 731 | Executor E("link.exe"); | |
| 732 | E.add(Twine("@" + Temps.back().Path)); | |
| 733 | E.run(); | |
| 734 | } | |
| 735 | ||
| 736 | 716 | // Create OptTable |
| 737 | 717 | |
| 738 | 718 | // Create prefix string literals used in Options.td |
| ... | ... | @@ -883,7 +863,9 @@ std::vector<const char *> ArgParser::tokenize(StringRef S) { |
| 883 | 863 | } |
| 884 | 864 | |
| 885 | 865 | void printHelp(const char *Argv0) { |
| 886 | COFFOptTable().PrintHelp(outs(), Argv0, "LLVM Linker", false); | |
| 866 | COFFOptTable().PrintHelp(outs(), | |
| 867 | (std::string(Argv0) + " [options] file...").c_str(), | |
| 868 | "LLVM Linker", false); | |
| 887 | 869 | } |
| 888 | 870 | |
| 889 | 871 | } // namespace coff |
deps/lld/COFF/ICF.cpp+24-7| ... | ... | @@ -22,6 +22,7 @@ |
| 22 | 22 | #include "Chunks.h" |
| 23 | 23 | #include "Symbols.h" |
| 24 | 24 | #include "lld/Common/ErrorHandler.h" |
| 25 | #include "lld/Common/Threads.h" | |
| 25 | 26 | #include "lld/Common/Timer.h" |
| 26 | 27 | #include "llvm/ADT/Hashing.h" |
| 27 | 28 | #include "llvm/Support/Debug.h" |
| ... | ... | @@ -80,7 +81,7 @@ private: |
| 80 | 81 | bool ICF::isEligible(SectionChunk *C) { |
| 81 | 82 | // Non-comdat chunks, dead chunks, and writable chunks are not elegible. |
| 82 | 83 | bool Writable = C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE; |
| 83 | if (!C->isCOMDAT() || !C->isLive() || Writable) | |
| 84 | if (!C->isCOMDAT() || !C->Live || Writable) | |
| 84 | 85 | return false; |
| 85 | 86 | |
| 86 | 87 | // Code sections are eligible. |
| ... | ... | @@ -93,7 +94,11 @@ bool ICF::isEligible(SectionChunk *C) { |
| 93 | 94 | return true; |
| 94 | 95 | |
| 95 | 96 | // So are vtables. |
| 96 | return C->Sym && C->Sym->getName().startswith("??_7"); | |
| 97 | if (C->Sym && C->Sym->getName().startswith("??_7")) | |
| 98 | return true; | |
| 99 | ||
| 100 | // Anything else not in an address-significance table is eligible. | |
| 101 | return !C->KeepUnique; | |
| 97 | 102 | } |
| 98 | 103 | |
| 99 | 104 | // Split an equivalence class into smaller classes. |
| ... | ... | @@ -222,10 +227,10 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) { |
| 222 | 227 | size_t Boundaries[NumShards + 1]; |
| 223 | 228 | Boundaries[0] = 0; |
| 224 | 229 | Boundaries[NumShards] = Chunks.size(); |
| 225 | for_each_n(parallel::par, size_t(1), NumShards, [&](size_t I) { | |
| 230 | parallelForEachN(1, NumShards, [&](size_t I) { | |
| 226 | 231 | Boundaries[I] = findBoundary((I - 1) * Step, Chunks.size()); |
| 227 | 232 | }); |
| 228 | for_each_n(parallel::par, size_t(1), NumShards + 1, [&](size_t I) { | |
| 233 | parallelForEachN(1, NumShards + 1, [&](size_t I) { | |
| 229 | 234 | if (Boundaries[I - 1] < Boundaries[I]) { |
| 230 | 235 | forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn); |
| 231 | 236 | } |
| ... | ... | @@ -257,11 +262,23 @@ void ICF::run(ArrayRef<Chunk *> Vec) { |
| 257 | 262 | SC->Class[0] = NextId++; |
| 258 | 263 | |
| 259 | 264 | // Initially, we use hash values to partition sections. |
| 260 | for_each(parallel::par, Chunks.begin(), Chunks.end(), [&](SectionChunk *SC) { | |
| 261 | // Set MSB to 1 to avoid collisions with non-hash classs. | |
| 262 | SC->Class[0] = xxHash64(SC->getContents()) | (1 << 31); | |
| 265 | parallelForEach(Chunks, [&](SectionChunk *SC) { | |
| 266 | SC->Class[0] = xxHash64(SC->getContents()); | |
| 263 | 267 | }); |
| 264 | 268 | |
| 269 | // Combine the hashes of the sections referenced by each section into its | |
| 270 | // hash. | |
| 271 | for (unsigned Cnt = 0; Cnt != 2; ++Cnt) { | |
| 272 | parallelForEach(Chunks, [&](SectionChunk *SC) { | |
| 273 | uint32_t Hash = SC->Class[Cnt % 2]; | |
| 274 | for (Symbol *B : SC->symbols()) | |
| 275 | if (auto *Sym = dyn_cast_or_null<DefinedRegular>(B)) | |
| 276 | Hash += Sym->getChunk()->Class[Cnt % 2]; | |
| 277 | // Set MSB to 1 to avoid collisions with non-hash classs. | |
| 278 | SC->Class[(Cnt + 1) % 2] = Hash | (1U << 31); | |
| 279 | }); | |
| 280 | } | |
| 281 | ||
| 265 | 282 | // From now on, sections in Chunks are ordered so that sections in |
| 266 | 283 | // the same group are consecutive in the vector. |
| 267 | 284 | std::stable_sort(Chunks.begin(), Chunks.end(), |
deps/lld/COFF/InputFiles.cpp+35-8| ... | ... | @@ -54,8 +54,16 @@ std::vector<BitcodeFile *> BitcodeFile::Instances; |
| 54 | 54 | static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F, |
| 55 | 55 | Symbol *Source, Symbol *Target) { |
| 56 | 56 | if (auto *U = dyn_cast<Undefined>(Source)) { |
| 57 | if (U->WeakAlias && U->WeakAlias != Target) | |
| 57 | if (U->WeakAlias && U->WeakAlias != Target) { | |
| 58 | // Weak aliases as produced by GCC are named in the form | |
| 59 | // .weak.<weaksymbol>.<othersymbol>, where <othersymbol> is the name | |
| 60 | // of another symbol emitted near the weak symbol. | |
| 61 | // Just use the definition from the first object file that defined | |
| 62 | // this weak symbol. | |
| 63 | if (Config->MinGW) | |
| 64 | return; | |
| 58 | 65 | Symtab->reportDuplicate(Source, F); |
| 66 | } | |
| 59 | 67 | U->WeakAlias = Target; |
| 60 | 68 | } |
| 61 | 69 | } |
| ... | ... | @@ -147,9 +155,10 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber, |
| 147 | 155 | const coff_aux_section_definition *Def, |
| 148 | 156 | StringRef LeaderName) { |
| 149 | 157 | const coff_section *Sec; |
| 150 | StringRef Name; | |
| 151 | 158 | if (auto EC = COFFObj->getSection(SectionNumber, Sec)) |
| 152 | 159 | fatal("getSection failed: #" + Twine(SectionNumber) + ": " + EC.message()); |
| 160 | ||
| 161 | StringRef Name; | |
| 153 | 162 | if (auto EC = COFFObj->getSectionName(Sec, Name)) |
| 154 | 163 | fatal("getSectionName failed: #" + Twine(SectionNumber) + ": " + |
| 155 | 164 | EC.message()); |
| ... | ... | @@ -161,6 +170,11 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber, |
| 161 | 170 | return nullptr; |
| 162 | 171 | } |
| 163 | 172 | |
| 173 | if (Name == ".llvm_addrsig") { | |
| 174 | AddrsigSec = Sec; | |
| 175 | return nullptr; | |
| 176 | } | |
| 177 | ||
| 164 | 178 | // Object files may have DWARF debug info or MS CodeView debug info |
| 165 | 179 | // (or both). |
| 166 | 180 | // |
| ... | ... | @@ -168,8 +182,8 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber, |
| 168 | 182 | // of the linker; they are just a data section containing relocations. |
| 169 | 183 | // We can just link them to complete debug info. |
| 170 | 184 | // |
| 171 | // CodeView needs a linker support. We need to interpret and debug | |
| 172 | // info, and then write it to a separate .pdb file. | |
| 185 | // CodeView needs linker support. We need to interpret debug info, | |
| 186 | // and then write it to a separate .pdb file. | |
| 173 | 187 | |
| 174 | 188 | // Ignore DWARF debug info unless /debug is given. |
| 175 | 189 | if (!Config->Debug && Name.startswith(".debug_")) |
| ... | ... | @@ -267,10 +281,17 @@ Symbol *ObjFile::createRegular(COFFSymbolRef Sym) { |
| 267 | 281 | COFFObj->getSymbolName(Sym, Name); |
| 268 | 282 | if (SC) |
| 269 | 283 | return Symtab->addRegular(this, Name, Sym.getGeneric(), SC); |
| 284 | // For MinGW symbols named .weak.* that point to a discarded section, | |
| 285 | // don't create an Undefined symbol. If nothing ever refers to the symbol, | |
| 286 | // everything should be fine. If something actually refers to the symbol | |
| 287 | // (e.g. the undefined weak alias), linking will fail due to undefined | |
| 288 | // references at the end. | |
| 289 | if (Config->MinGW && Name.startswith(".weak.")) | |
| 290 | return nullptr; | |
| 270 | 291 | return Symtab->addUndefined(Name, this, false); |
| 271 | 292 | } |
| 272 | 293 | if (SC) |
| 273 | return make<DefinedRegular>(this, /*Name*/ "", false, | |
| 294 | return make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false, | |
| 274 | 295 | /*IsExternal*/ false, Sym.getGeneric(), SC); |
| 275 | 296 | return nullptr; |
| 276 | 297 | } |
| ... | ... | @@ -318,7 +339,7 @@ void ObjFile::initializeSymbols() { |
| 318 | 339 | |
| 319 | 340 | for (uint32_t I : PendingIndexes) { |
| 320 | 341 | COFFSymbolRef Sym = check(COFFObj->getSymbol(I)); |
| 321 | if (auto *Def = Sym.getSectionDefinition()) { | |
| 342 | if (const coff_aux_section_definition *Def = Sym.getSectionDefinition()) { | |
| 322 | 343 | if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) |
| 323 | 344 | readAssociativeDefinition(Sym, Def); |
| 324 | 345 | else if (Config->MinGW) |
| ... | ... | @@ -401,7 +422,7 @@ Optional<Symbol *> ObjFile::createDefined( |
| 401 | 422 | std::tie(Leader, Prevailing) = |
| 402 | 423 | Symtab->addComdat(this, GetName(), Sym.getGeneric()); |
| 403 | 424 | } else { |
| 404 | Leader = make<DefinedRegular>(this, /*Name*/ "", false, | |
| 425 | Leader = make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false, | |
| 405 | 426 | /*IsExternal*/ false, Sym.getGeneric()); |
| 406 | 427 | Prevailing = true; |
| 407 | 428 | } |
| ... | ... | @@ -421,7 +442,7 @@ Optional<Symbol *> ObjFile::createDefined( |
| 421 | 442 | // leader symbol by setting the section's ComdatDefs pointer if we encounter a |
| 422 | 443 | // non-associative comdat. |
| 423 | 444 | if (SparseChunks[SectionNumber] == PendingComdat) { |
| 424 | if (auto *Def = Sym.getSectionDefinition()) { | |
| 445 | if (const coff_aux_section_definition *Def = Sym.getSectionDefinition()) { | |
| 425 | 446 | if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE) |
| 426 | 447 | readAssociativeDefinition(Sym, Def); |
| 427 | 448 | else |
| ... | ... | @@ -429,8 +450,10 @@ Optional<Symbol *> ObjFile::createDefined( |
| 429 | 450 | } |
| 430 | 451 | } |
| 431 | 452 | |
| 453 | // readAssociativeDefinition() writes to SparseChunks, so need to check again. | |
| 432 | 454 | if (SparseChunks[SectionNumber] == PendingComdat) |
| 433 | 455 | return None; |
| 456 | ||
| 434 | 457 | return createRegular(Sym); |
| 435 | 458 | } |
| 436 | 459 | |
| ... | ... | @@ -481,6 +504,10 @@ void ImportFile::parse() { |
| 481 | 504 | ExternalName = ExtName; |
| 482 | 505 | |
| 483 | 506 | ImpSym = Symtab->addImportData(ImpName, this); |
| 507 | // If this was a duplicate, we logged an error but may continue; | |
| 508 | // in this case, ImpSym is nullptr. | |
| 509 | if (!ImpSym) | |
| 510 | return; | |
| 484 | 511 | |
| 485 | 512 | if (Hdr->getType() == llvm::COFF::IMPORT_CONST) |
| 486 | 513 | static_cast<void>(Symtab->addImportData(Name, this)); |
deps/lld/COFF/InputFiles.h+12-1| ... | ... | @@ -15,6 +15,7 @@ |
| 15 | 15 | #include "llvm/ADT/ArrayRef.h" |
| 16 | 16 | #include "llvm/ADT/DenseMap.h" |
| 17 | 17 | #include "llvm/ADT/DenseSet.h" |
| 18 | #include "llvm/DebugInfo/CodeView/TypeRecord.h" | |
| 18 | 19 | #include "llvm/LTO/LTO.h" |
| 19 | 20 | #include "llvm/Object/Archive.h" |
| 20 | 21 | #include "llvm/Object/COFF.h" |
| ... | ... | @@ -122,9 +123,12 @@ public: |
| 122 | 123 | return Symbols[SymbolIndex]; |
| 123 | 124 | } |
| 124 | 125 | |
| 125 | // Returns the underying COFF file. | |
| 126 | // Returns the underlying COFF file. | |
| 126 | 127 | COFFObjectFile *getCOFFObj() { return COFFObj.get(); } |
| 127 | 128 | |
| 129 | // Whether the object was already merged into the final PDB or not | |
| 130 | bool wasProcessedForPDB() const { return !!ModuleDBI; } | |
| 131 | ||
| 128 | 132 | static std::vector<ObjFile *> Instances; |
| 129 | 133 | |
| 130 | 134 | // Flags in the absolute @feat.00 symbol if it is present. These usually |
| ... | ... | @@ -145,6 +149,13 @@ public: |
| 145 | 149 | // if we are not producing a PDB. |
| 146 | 150 | llvm::pdb::DbiModuleDescriptorBuilder *ModuleDBI = nullptr; |
| 147 | 151 | |
| 152 | const coff_section *AddrsigSec = nullptr; | |
| 153 | ||
| 154 | // When using Microsoft precompiled headers, this is the PCH's key. | |
| 155 | // The same key is used by both the precompiled object, and objects using the | |
| 156 | // precompiled object. Any difference indicates out-of-date objects. | |
| 157 | llvm::Optional<uint32_t> PCHSignature; | |
| 158 | ||
| 148 | 159 | private: |
| 149 | 160 | void initializeChunks(); |
| 150 | 161 | void initializeSymbols(); |
deps/lld/COFF/LTO.cpp+3| ... | ... | @@ -60,6 +60,9 @@ static std::unique_ptr<lto::LTO> createLTO() { |
| 60 | 60 | C.DisableVerify = true; |
| 61 | 61 | C.DiagHandler = diagnosticHandler; |
| 62 | 62 | C.OptLevel = Config->LTOO; |
| 63 | C.CPU = GetCPUStr(); | |
| 64 | C.MAttrs = GetMAttrs(); | |
| 65 | ||
| 63 | 66 | if (Config->SaveTemps) |
| 64 | 67 | checkError(C.addSaveTemps(std::string(Config->OutputFile) + ".", |
| 65 | 68 | /*UseInputModulePath*/ true)); |
deps/lld/COFF/MapFile.cpp+1-1| ... | ... | @@ -110,7 +110,7 @@ void coff::writeMapFile(ArrayRef<OutputSection *> OutputSections) { |
| 110 | 110 | writeHeader(OS, Sec->getRVA(), Sec->getVirtualSize(), /*Align=*/PageSize); |
| 111 | 111 | OS << Sec->Name << '\n'; |
| 112 | 112 | |
| 113 | for (Chunk *C : Sec->getChunks()) { | |
| 113 | for (Chunk *C : Sec->Chunks) { | |
| 114 | 114 | auto *SC = dyn_cast<SectionChunk>(C); |
| 115 | 115 | if (!SC) |
| 116 | 116 | continue; |
deps/lld/COFF/MarkLive.cpp+4-4| ... | ... | @@ -32,13 +32,13 @@ void markLive(ArrayRef<Chunk *> Chunks) { |
| 32 | 32 | // COMDAT section chunks are dead by default. Add non-COMDAT chunks. |
| 33 | 33 | for (Chunk *C : Chunks) |
| 34 | 34 | if (auto *SC = dyn_cast<SectionChunk>(C)) |
| 35 | if (SC->isLive()) | |
| 35 | if (SC->Live) | |
| 36 | 36 | Worklist.push_back(SC); |
| 37 | 37 | |
| 38 | 38 | auto Enqueue = [&](SectionChunk *C) { |
| 39 | if (C->isLive()) | |
| 39 | if (C->Live) | |
| 40 | 40 | return; |
| 41 | C->markLive(); | |
| 41 | C->Live = true; | |
| 42 | 42 | Worklist.push_back(C); |
| 43 | 43 | }; |
| 44 | 44 | |
| ... | ... | @@ -57,7 +57,7 @@ void markLive(ArrayRef<Chunk *> Chunks) { |
| 57 | 57 | |
| 58 | 58 | while (!Worklist.empty()) { |
| 59 | 59 | SectionChunk *SC = Worklist.pop_back_val(); |
| 60 | assert(SC->isLive() && "We mark as live when pushing onto the worklist!"); | |
| 60 | assert(SC->Live && "We mark as live when pushing onto the worklist!"); | |
| 61 | 61 | |
| 62 | 62 | // Mark all symbols listed in the relocation table for this section. |
| 63 | 63 | for (Symbol *B : SC->symbols()) |
deps/lld/COFF/MinGW.cpp+36-6| ... | ... | @@ -19,7 +19,23 @@ using namespace lld::coff; |
| 19 | 19 | using namespace llvm; |
| 20 | 20 | using namespace llvm::COFF; |
| 21 | 21 | |
| 22 | AutoExporter::AutoExporter() { | |
| 22 | void AutoExporter::initSymbolExcludes() { | |
| 23 | ExcludeSymbolPrefixes = { | |
| 24 | // Import symbols | |
| 25 | "__imp_", | |
| 26 | "__IMPORT_DESCRIPTOR_", | |
| 27 | // Extra import symbols from GNU import libraries | |
| 28 | "__nm_", | |
| 29 | // C++ symbols | |
| 30 | "__rtti_", | |
| 31 | "__builtin_", | |
| 32 | // Artifical symbols such as .refptr | |
| 33 | ".", | |
| 34 | }; | |
| 35 | ExcludeSymbolSuffixes = { | |
| 36 | "_iname", | |
| 37 | "_NULL_THUNK_DATA", | |
| 38 | }; | |
| 23 | 39 | if (Config->Machine == I386) { |
| 24 | 40 | ExcludeSymbols = { |
| 25 | 41 | "__NULL_IMPORT_DESCRIPTOR", |
| ... | ... | @@ -36,9 +52,10 @@ AutoExporter::AutoExporter() { |
| 36 | 52 | "_DllEntryPoint@12", |
| 37 | 53 | "_DllMainCRTStartup@12", |
| 38 | 54 | }; |
| 55 | ExcludeSymbolPrefixes.insert("__head_"); | |
| 39 | 56 | } else { |
| 40 | 57 | ExcludeSymbols = { |
| 41 | "_NULL_IMPORT_DESCRIPTOR", | |
| 58 | "__NULL_IMPORT_DESCRIPTOR", | |
| 42 | 59 | "_pei386_runtime_relocator", |
| 43 | 60 | "do_pseudo_reloc", |
| 44 | 61 | "impure_ptr", |
| ... | ... | @@ -52,8 +69,11 @@ AutoExporter::AutoExporter() { |
| 52 | 69 | "DllEntryPoint", |
| 53 | 70 | "DllMainCRTStartup", |
| 54 | 71 | }; |
| 72 | ExcludeSymbolPrefixes.insert("_head_"); | |
| 55 | 73 | } |
| 74 | } | |
| 56 | 75 | |
| 76 | AutoExporter::AutoExporter() { | |
| 57 | 77 | ExcludeLibs = { |
| 58 | 78 | "libgcc", |
| 59 | 79 | "libgcc_s", |
| ... | ... | @@ -64,6 +84,7 @@ AutoExporter::AutoExporter() { |
| 64 | 84 | "libsupc++", |
| 65 | 85 | "libobjc", |
| 66 | 86 | "libgcj", |
| 87 | "libclang_rt.builtins", | |
| 67 | 88 | "libclang_rt.builtins-aarch64", |
| 68 | 89 | "libclang_rt.builtins-arm", |
| 69 | 90 | "libclang_rt.builtins-i386", |
| ... | ... | @@ -90,6 +111,13 @@ AutoExporter::AutoExporter() { |
| 90 | 111 | }; |
| 91 | 112 | } |
| 92 | 113 | |
| 114 | void AutoExporter::addWholeArchive(StringRef Path) { | |
| 115 | StringRef LibName = sys::path::filename(Path); | |
| 116 | // Drop the file extension, to match the processing below. | |
| 117 | LibName = LibName.substr(0, LibName.rfind('.')); | |
| 118 | ExcludeLibs.erase(LibName); | |
| 119 | } | |
| 120 | ||
| 93 | 121 | bool AutoExporter::shouldExport(Defined *Sym) const { |
| 94 | 122 | if (!Sym || !Sym->isLive() || !Sym->getChunk()) |
| 95 | 123 | return false; |
| ... | ... | @@ -101,10 +129,12 @@ bool AutoExporter::shouldExport(Defined *Sym) const { |
| 101 | 129 | if (ExcludeSymbols.count(Sym->getName())) |
| 102 | 130 | return false; |
| 103 | 131 | |
| 104 | // Don't export anything that looks like an import symbol (which also can be | |
| 105 | // a manually defined data symbol with such a name). | |
| 106 | if (Sym->getName().startswith("__imp_")) | |
| 107 | return false; | |
| 132 | for (StringRef Prefix : ExcludeSymbolPrefixes.keys()) | |
| 133 | if (Sym->getName().startswith(Prefix)) | |
| 134 | return false; | |
| 135 | for (StringRef Suffix : ExcludeSymbolSuffixes.keys()) | |
| 136 | if (Sym->getName().endswith(Suffix)) | |
| 137 | return false; | |
| 108 | 138 | |
| 109 | 139 | // If a corresponding __imp_ symbol exists and is defined, don't export it. |
| 110 | 140 | if (Symtab->find(("__imp_" + Sym->getName()).str())) |
deps/lld/COFF/MinGW.h+6| ... | ... | @@ -23,7 +23,13 @@ class AutoExporter { |
| 23 | 23 | public: |
| 24 | 24 | AutoExporter(); |
| 25 | 25 | |
| 26 | void initSymbolExcludes(); | |
| 27 | ||
| 28 | void addWholeArchive(StringRef Path); | |
| 29 | ||
| 26 | 30 | llvm::StringSet<> ExcludeSymbols; |
| 31 | llvm::StringSet<> ExcludeSymbolPrefixes; | |
| 32 | llvm::StringSet<> ExcludeSymbolSuffixes; | |
| 27 | 33 | llvm::StringSet<> ExcludeLibs; |
| 28 | 34 | llvm::StringSet<> ExcludeObjects; |
| 29 | 35 |
deps/lld/COFF/Options.td+22-15| ... | ... | @@ -66,13 +66,18 @@ def wholearchive_file : P<"wholearchive", "Include all object files from this ar |
| 66 | 66 | |
| 67 | 67 | def disallowlib : Joined<["/", "-", "-?"], "disallowlib:">, Alias<nodefaultlib>; |
| 68 | 68 | |
| 69 | def manifest : F<"manifest">; | |
| 70 | def manifest_colon : P<"manifest", "Create manifest file">; | |
| 69 | def manifest : F<"manifest">, HelpText<"Create .manifest file">; | |
| 70 | def manifest_colon : P< | |
| 71 | "manifest", | |
| 72 | "NO disables manifest output; EMBED[,ID=#] embeds manifest as resource in the image">; | |
| 71 | 73 | def manifestuac : P<"manifestuac", "User access control">; |
| 72 | def manifestfile : P<"manifestfile", "Manifest file path">; | |
| 73 | def manifestdependency : P<"manifestdependency", | |
| 74 | "Attributes for <dependency> in manifest file">; | |
| 75 | def manifestinput : P<"manifestinput", "Specify manifest file">; | |
| 74 | def manifestfile : P<"manifestfile", "Manifest output path, with /manifest">; | |
| 75 | def manifestdependency : P< | |
| 76 | "manifestdependency", | |
| 77 | "Attributes for <dependency> element in manifest file; implies /manifest">; | |
| 78 | def manifestinput : P< | |
| 79 | "manifestinput", | |
| 80 | "Additional manifest inputs; only valid with /manifest:embed">; | |
| 76 | 81 | |
| 77 | 82 | // We cannot use multiclass P because class name "incl" is different |
| 78 | 83 | // from its command line option name. We do this because "include" is |
| ... | ... | @@ -85,22 +90,28 @@ def deffile : Joined<["/", "-"], "def:">, |
| 85 | 90 | HelpText<"Use module-definition file">; |
| 86 | 91 | |
| 87 | 92 | def debug : F<"debug">, HelpText<"Embed a symbol table in the image">; |
| 88 | def debug_full : F<"debug:full">, Alias<debug>; | |
| 93 | def debug_opt : P<"debug", "Embed a symbol table in the image with option">; | |
| 89 | 94 | def debugtype : P<"debugtype", "Debug Info Options">; |
| 90 | 95 | def dll : F<"dll">, HelpText<"Create a DLL">; |
| 91 | 96 | def driver : P<"driver", "Generate a Windows NT Kernel Mode Driver">; |
| 92 | def nodefaultlib_all : F<"nodefaultlib">; | |
| 93 | def noentry : F<"noentry">; | |
| 97 | def nodefaultlib_all : F<"nodefaultlib">, | |
| 98 | HelpText<"Remove all default libraries">; | |
| 99 | def noentry : F<"noentry">, | |
| 100 | HelpText<"Don't add reference to DllMainCRTStartup; only valid with /dll">; | |
| 94 | 101 | def profile : F<"profile">; |
| 95 | def repro : F<"Brepro">, HelpText<"Use a hash of the executable as the PE header timestamp">; | |
| 102 | def repro : F<"Brepro">, | |
| 103 | HelpText<"Use a hash of the executable as the PE header timestamp">; | |
| 96 | 104 | def swaprun_cd : F<"swaprun:cd">; |
| 97 | 105 | def swaprun_net : F<"swaprun:net">; |
| 98 | 106 | def verbose : F<"verbose">; |
| 99 | 107 | def wholearchive_flag : F<"wholearchive">; |
| 100 | 108 | |
| 101 | 109 | def force : F<"force">, |
| 110 | HelpText<"Allow undefined and multiply defined symbols when creating executables">; | |
| 111 | def force_unresolved : F<"force:unresolved">, | |
| 102 | 112 | HelpText<"Allow undefined symbols when creating executables">; |
| 103 | def force_unresolved : F<"force:unresolved">; | |
| 113 | def force_multiple : F<"force:multiple">, | |
| 114 | HelpText<"Allow multiply defined symbols when creating executables">; | |
| 104 | 115 | defm WX : B<"WX", "Treat warnings as errors", "Don't treat warnings as errors">; |
| 105 | 116 | |
| 106 | 117 | defm allowbind : B<"allowbind", "Enable DLL binding (default)", |
| ... | ... | @@ -139,13 +150,9 @@ def help : F<"help">; |
| 139 | 150 | def help_q : Flag<["/?", "-?"], "">, Alias<help>; |
| 140 | 151 | |
| 141 | 152 | // LLD extensions |
| 142 | def debug_ghash : F<"debug:ghash">; | |
| 143 | def debug_dwarf : F<"debug:dwarf">; | |
| 144 | def debug_symtab : F<"debug:symtab">; | |
| 145 | 153 | def export_all_symbols : F<"export-all-symbols">; |
| 146 | 154 | def kill_at : F<"kill-at">; |
| 147 | 155 | def lldmingw : F<"lldmingw">; |
| 148 | def msvclto : F<"msvclto">; | |
| 149 | 156 | def output_def : Joined<["/", "-"], "output-def:">; |
| 150 | 157 | def pdb_source_path : P<"pdbsourcepath", |
| 151 | 158 | "Base path used to make relative source file path absolute in PDB">; |
deps/lld/COFF/PDB.cpp+720-283| ... | ... | @@ -16,12 +16,14 @@ |
| 16 | 16 | #include "Writer.h" |
| 17 | 17 | #include "lld/Common/ErrorHandler.h" |
| 18 | 18 | #include "lld/Common/Timer.h" |
| 19 | #include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h" | |
| 19 | 20 | #include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h" |
| 20 | 21 | #include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h" |
| 21 | 22 | #include "llvm/DebugInfo/CodeView/LazyRandomTypeCollection.h" |
| 22 | 23 | #include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h" |
| 23 | 24 | #include "llvm/DebugInfo/CodeView/RecordName.h" |
| 24 | 25 | #include "llvm/DebugInfo/CodeView/SymbolDeserializer.h" |
| 26 | #include "llvm/DebugInfo/CodeView/SymbolRecordHelpers.h" | |
| 25 | 27 | #include "llvm/DebugInfo/CodeView/SymbolSerializer.h" |
| 26 | 28 | #include "llvm/DebugInfo/CodeView/TypeDeserializer.h" |
| 27 | 29 | #include "llvm/DebugInfo/CodeView/TypeDumpVisitor.h" |
| ... | ... | @@ -48,8 +50,10 @@ |
| 48 | 50 | #include "llvm/Object/CVDebugRecord.h" |
| 49 | 51 | #include "llvm/Support/BinaryByteStream.h" |
| 50 | 52 | #include "llvm/Support/Endian.h" |
| 53 | #include "llvm/Support/Errc.h" | |
| 51 | 54 | #include "llvm/Support/FormatVariadic.h" |
| 52 | 55 | #include "llvm/Support/JamCRC.h" |
| 56 | #include "llvm/Support/Parallel.h" | |
| 53 | 57 | #include "llvm/Support/Path.h" |
| 54 | 58 | #include "llvm/Support/ScopedPrinter.h" |
| 55 | 59 | #include <memory> |
| ... | ... | @@ -79,9 +83,14 @@ struct CVIndexMap { |
| 79 | 83 | SmallVector<TypeIndex, 0> TPIMap; |
| 80 | 84 | SmallVector<TypeIndex, 0> IPIMap; |
| 81 | 85 | bool IsTypeServerMap = false; |
| 86 | bool IsPrecompiledTypeMap = false; | |
| 82 | 87 | }; |
| 83 | 88 | |
| 89 | class DebugSHandler; | |
| 90 | ||
| 84 | 91 | class PDBLinker { |
| 92 | friend DebugSHandler; | |
| 93 | ||
| 85 | 94 | public: |
| 86 | 95 | PDBLinker(SymbolTable *Symtab) |
| 87 | 96 | : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc), |
| ... | ... | @@ -93,7 +102,7 @@ public: |
| 93 | 102 | } |
| 94 | 103 | |
| 95 | 104 | /// Emit the basic PDB structure: initial streams, headers, etc. |
| 96 | void initialize(const llvm::codeview::DebugInfo &BuildId); | |
| 105 | void initialize(llvm::codeview::DebugInfo *BuildId); | |
| 97 | 106 | |
| 98 | 107 | /// Add natvis files specified on the command line. |
| 99 | 108 | void addNatvisFiles(); |
| ... | ... | @@ -101,8 +110,10 @@ public: |
| 101 | 110 | /// Link CodeView from each object file in the symbol table into the PDB. |
| 102 | 111 | void addObjectsToPDB(); |
| 103 | 112 | |
| 104 | /// Link CodeView from a single object file into the PDB. | |
| 105 | void addObjFile(ObjFile *File); | |
| 113 | /// Link CodeView from a single object file into the target (output) PDB. | |
| 114 | /// When a precompiled headers object is linked, its TPI map might be provided | |
| 115 | /// externally. | |
| 116 | void addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap = nullptr); | |
| 106 | 117 | |
| 107 | 118 | /// Produce a mapping from the type and item indices used in the object |
| 108 | 119 | /// file to those in the destination PDB. |
| ... | ... | @@ -115,18 +126,60 @@ public: |
| 115 | 126 | /// If the object does not use a type server PDB (compiled with /Z7), we merge |
| 116 | 127 | /// all the type and item records from the .debug$S stream and fill in the |
| 117 | 128 | /// caller-provided ObjectIndexMap. |
| 118 | Expected<const CVIndexMap&> mergeDebugT(ObjFile *File, | |
| 119 | CVIndexMap &ObjectIndexMap); | |
| 129 | Expected<const CVIndexMap &> mergeDebugT(ObjFile *File, | |
| 130 | CVIndexMap *ObjectIndexMap); | |
| 131 | ||
| 132 | /// Reads and makes available a PDB. | |
| 133 | Expected<const CVIndexMap &> maybeMergeTypeServerPDB(ObjFile *File, | |
| 134 | const CVType &FirstType); | |
| 135 | ||
| 136 | /// Merges a precompiled headers TPI map into the current TPI map. The | |
| 137 | /// precompiled headers object will also be loaded and remapped in the | |
| 138 | /// process. | |
| 139 | Expected<const CVIndexMap &> | |
| 140 | mergeInPrecompHeaderObj(ObjFile *File, const CVType &FirstType, | |
| 141 | CVIndexMap *ObjectIndexMap); | |
| 142 | ||
| 143 | /// Reads and makes available a precompiled headers object. | |
| 144 | /// | |
| 145 | /// This is a requirement for objects compiled with cl.exe /Yu. In that | |
| 146 | /// case, the referenced object (which was compiled with /Yc) has to be loaded | |
| 147 | /// first. This is mainly because the current object's TPI stream has external | |
| 148 | /// references to the precompiled headers object. | |
| 149 | /// | |
| 150 | /// If the precompiled headers object was already loaded, this function will | |
| 151 | /// simply return its (remapped) TPI map. | |
| 152 | Expected<const CVIndexMap &> aquirePrecompObj(ObjFile *File, | |
| 153 | PrecompRecord Precomp); | |
| 154 | ||
| 155 | /// Adds a precompiled headers object signature -> TPI mapping. | |
| 156 | std::pair<CVIndexMap &, bool /*already there*/> | |
| 157 | registerPrecompiledHeaders(uint32_t Signature); | |
| 120 | 158 | |
| 121 | Expected<const CVIndexMap&> maybeMergeTypeServerPDB(ObjFile *File, | |
| 122 | TypeServer2Record &TS); | |
| 159 | void mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap, | |
| 160 | std::vector<ulittle32_t *> &StringTableRefs, | |
| 161 | BinaryStreamRef SymData); | |
| 123 | 162 | |
| 124 | 163 | /// Add the section map and section contributions to the PDB. |
| 125 | 164 | void addSections(ArrayRef<OutputSection *> OutputSections, |
| 126 | 165 | ArrayRef<uint8_t> SectionTable); |
| 127 | 166 | |
| 128 | /// Write the PDB to disk. | |
| 129 | void commit(); | |
| 167 | /// Get the type table or the global type table if /DEBUG:GHASH is enabled. | |
| 168 | TypeCollection &getTypeTable() { | |
| 169 | if (Config->DebugGHashes) | |
| 170 | return GlobalTypeTable; | |
| 171 | return TypeTable; | |
| 172 | } | |
| 173 | ||
| 174 | /// Get the ID table or the global ID table if /DEBUG:GHASH is enabled. | |
| 175 | TypeCollection &getIDTable() { | |
| 176 | if (Config->DebugGHashes) | |
| 177 | return GlobalIDTable; | |
| 178 | return IDTable; | |
| 179 | } | |
| 180 | ||
| 181 | /// Write the PDB to disk and store the Guid generated for it in *Guid. | |
| 182 | void commit(codeview::GUID *Guid); | |
| 130 | 183 | |
| 131 | 184 | private: |
| 132 | 185 | BumpPtrAllocator Alloc; |
| ... | ... | @@ -161,14 +214,101 @@ private: |
| 161 | 214 | std::vector<pdb::SecMapEntry> SectionMap; |
| 162 | 215 | |
| 163 | 216 | /// Type index mappings of type server PDBs that we've loaded so far. |
| 164 | std::map<GUID, CVIndexMap> TypeServerIndexMappings; | |
| 217 | std::map<codeview::GUID, CVIndexMap> TypeServerIndexMappings; | |
| 218 | ||
| 219 | /// Type index mappings of precompiled objects type map that we've loaded so | |
| 220 | /// far. | |
| 221 | std::map<uint32_t, CVIndexMap> PrecompTypeIndexMappings; | |
| 165 | 222 | |
| 166 | 223 | /// List of TypeServer PDBs which cannot be loaded. |
| 167 | 224 | /// Cached to prevent repeated load attempts. |
| 168 | std::set<GUID> MissingTypeServerPDBs; | |
| 225 | std::map<codeview::GUID, std::string> MissingTypeServerPDBs; | |
| 226 | }; | |
| 227 | ||
| 228 | class DebugSHandler { | |
| 229 | PDBLinker &Linker; | |
| 230 | ||
| 231 | /// The object file whose .debug$S sections we're processing. | |
| 232 | ObjFile &File; | |
| 233 | ||
| 234 | /// The result of merging type indices. | |
| 235 | const CVIndexMap &IndexMap; | |
| 236 | ||
| 237 | /// The DEBUG_S_STRINGTABLE subsection. These strings are referred to by | |
| 238 | /// index from other records in the .debug$S section. All of these strings | |
| 239 | /// need to be added to the global PDB string table, and all references to | |
| 240 | /// these strings need to have their indices re-written to refer to the | |
| 241 | /// global PDB string table. | |
| 242 | DebugStringTableSubsectionRef CVStrTab; | |
| 243 | ||
| 244 | /// The DEBUG_S_FILECHKSMS subsection. As above, these are referred to | |
| 245 | /// by other records in the .debug$S section and need to be merged into the | |
| 246 | /// PDB. | |
| 247 | DebugChecksumsSubsectionRef Checksums; | |
| 248 | ||
| 249 | /// The DEBUG_S_FRAMEDATA subsection(s). There can be more than one of | |
| 250 | /// these and they need not appear in any specific order. However, they | |
| 251 | /// contain string table references which need to be re-written, so we | |
| 252 | /// collect them all here and re-write them after all subsections have been | |
| 253 | /// discovered and processed. | |
| 254 | std::vector<DebugFrameDataSubsectionRef> NewFpoFrames; | |
| 255 | ||
| 256 | /// Pointers to raw memory that we determine have string table references | |
| 257 | /// that need to be re-written. We first process all .debug$S subsections | |
| 258 | /// to ensure that we can handle subsections written in any order, building | |
| 259 | /// up this list as we go. At the end, we use the string table (which must | |
| 260 | /// have been discovered by now else it is an error) to re-write these | |
| 261 | /// references. | |
| 262 | std::vector<ulittle32_t *> StringTableReferences; | |
| 263 | ||
| 264 | public: | |
| 265 | DebugSHandler(PDBLinker &Linker, ObjFile &File, const CVIndexMap &IndexMap) | |
| 266 | : Linker(Linker), File(File), IndexMap(IndexMap) {} | |
| 267 | ||
| 268 | void handleDebugS(lld::coff::SectionChunk &DebugS); | |
| 269 | void finish(); | |
| 169 | 270 | }; |
| 170 | 271 | } |
| 171 | 272 | |
| 273 | // Visual Studio's debugger requires absolute paths in various places in the | |
| 274 | // PDB to work without additional configuration: | |
| 275 | // https://docs.microsoft.com/en-us/visualstudio/debugger/debug-source-files-common-properties-solution-property-pages-dialog-box | |
| 276 | static void pdbMakeAbsolute(SmallVectorImpl<char> &FileName) { | |
| 277 | // The default behavior is to produce paths that are valid within the context | |
| 278 | // of the machine that you perform the link on. If the linker is running on | |
| 279 | // a POSIX system, we will output absolute POSIX paths. If the linker is | |
| 280 | // running on a Windows system, we will output absolute Windows paths. If the | |
| 281 | // user desires any other kind of behavior, they should explicitly pass | |
| 282 | // /pdbsourcepath, in which case we will treat the exact string the user | |
| 283 | // passed in as the gospel and not normalize, canonicalize it. | |
| 284 | if (sys::path::is_absolute(FileName, sys::path::Style::windows) || | |
| 285 | sys::path::is_absolute(FileName, sys::path::Style::posix)) | |
| 286 | return; | |
| 287 | ||
| 288 | // It's not absolute in any path syntax. Relative paths necessarily refer to | |
| 289 | // the local file system, so we can make it native without ending up with a | |
| 290 | // nonsensical path. | |
| 291 | if (Config->PDBSourcePath.empty()) { | |
| 292 | sys::path::native(FileName); | |
| 293 | sys::fs::make_absolute(FileName); | |
| 294 | return; | |
| 295 | } | |
| 296 | ||
| 297 | // Try to guess whether /PDBSOURCEPATH is a unix path or a windows path. | |
| 298 | // Since PDB's are more of a Windows thing, we make this conservative and only | |
| 299 | // decide that it's a unix path if we're fairly certain. Specifically, if | |
| 300 | // it starts with a forward slash. | |
| 301 | SmallString<128> AbsoluteFileName = Config->PDBSourcePath; | |
| 302 | sys::path::Style GuessedStyle = AbsoluteFileName.startswith("/") | |
| 303 | ? sys::path::Style::posix | |
| 304 | : sys::path::Style::windows; | |
| 305 | sys::path::append(AbsoluteFileName, GuessedStyle, FileName); | |
| 306 | sys::path::native(AbsoluteFileName, GuessedStyle); | |
| 307 | sys::path::remove_dots(AbsoluteFileName, true, GuessedStyle); | |
| 308 | ||
| 309 | FileName = std::move(AbsoluteFileName); | |
| 310 | } | |
| 311 | ||
| 172 | 312 | static SectionChunk *findByName(ArrayRef<SectionChunk *> Sections, |
| 173 | 313 | StringRef Name) { |
| 174 | 314 | for (SectionChunk *C : Sections) |
| ... | ... | @@ -242,27 +382,79 @@ static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder, |
| 242 | 382 | }); |
| 243 | 383 | } |
| 244 | 384 | |
| 245 | static Optional<TypeServer2Record> | |
| 246 | maybeReadTypeServerRecord(CVTypeArray &Types) { | |
| 247 | auto I = Types.begin(); | |
| 248 | if (I == Types.end()) | |
| 249 | return None; | |
| 250 | const CVType &Type = *I; | |
| 251 | if (Type.kind() != LF_TYPESERVER2) | |
| 252 | return None; | |
| 253 | TypeServer2Record TS; | |
| 254 | if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(Type), TS)) | |
| 255 | fatal("error reading type server record: " + toString(std::move(EC))); | |
| 256 | return std::move(TS); | |
| 385 | // OBJs usually start their symbol stream with a S_OBJNAME record. This record | |
| 386 | // also contains the signature/key of the current PCH session. The signature | |
| 387 | // must be same for all objects which depend on the precompiled object. | |
| 388 | // Recompiling the precompiled headers will generate a new PCH key and thus | |
| 389 | // invalidate all the dependent objects. | |
| 390 | static uint32_t extractPCHSignature(ObjFile *File) { | |
| 391 | auto DbgIt = find_if(File->getDebugChunks(), [](SectionChunk *C) { | |
| 392 | return C->getSectionName() == ".debug$S"; | |
| 393 | }); | |
| 394 | if (!DbgIt) | |
| 395 | return 0; | |
| 396 | ||
| 397 | ArrayRef<uint8_t> Contents = | |
| 398 | consumeDebugMagic((*DbgIt)->getContents(), ".debug$S"); | |
| 399 | DebugSubsectionArray Subsections; | |
| 400 | BinaryStreamReader Reader(Contents, support::little); | |
| 401 | ExitOnErr(Reader.readArray(Subsections, Contents.size())); | |
| 402 | ||
| 403 | for (const DebugSubsectionRecord &SS : Subsections) { | |
| 404 | if (SS.kind() != DebugSubsectionKind::Symbols) | |
| 405 | continue; | |
| 406 | ||
| 407 | // If it's there, the S_OBJNAME record shall come first in the stream. | |
| 408 | Expected<CVSymbol> Sym = readSymbolFromStream(SS.getRecordData(), 0); | |
| 409 | if (!Sym) { | |
| 410 | consumeError(Sym.takeError()); | |
| 411 | continue; | |
| 412 | } | |
| 413 | if (auto ObjName = SymbolDeserializer::deserializeAs<ObjNameSym>(Sym.get())) | |
| 414 | return ObjName->Signature; | |
| 415 | } | |
| 416 | return 0; | |
| 257 | 417 | } |
| 258 | 418 | |
| 259 | Expected<const CVIndexMap&> PDBLinker::mergeDebugT(ObjFile *File, | |
| 260 | CVIndexMap &ObjectIndexMap) { | |
| 419 | Expected<const CVIndexMap &> | |
| 420 | PDBLinker::mergeDebugT(ObjFile *File, CVIndexMap *ObjectIndexMap) { | |
| 261 | 421 | ScopedTimer T(TypeMergingTimer); |
| 262 | 422 | |
| 423 | bool IsPrecompiledHeader = false; | |
| 424 | ||
| 263 | 425 | ArrayRef<uint8_t> Data = getDebugSection(File, ".debug$T"); |
| 426 | if (Data.empty()) { | |
| 427 | // Try again, Microsoft precompiled headers use .debug$P instead of | |
| 428 | // .debug$T | |
| 429 | Data = getDebugSection(File, ".debug$P"); | |
| 430 | IsPrecompiledHeader = true; | |
| 431 | } | |
| 264 | 432 | if (Data.empty()) |
| 265 | return ObjectIndexMap; | |
| 433 | return *ObjectIndexMap; // no debug info | |
| 434 | ||
| 435 | // Precompiled headers objects need to save the index map for further | |
| 436 | // reference by other objects which use the precompiled headers. | |
| 437 | if (IsPrecompiledHeader) { | |
| 438 | uint32_t PCHSignature = extractPCHSignature(File); | |
| 439 | if (PCHSignature == 0) | |
| 440 | fatal("No signature found for the precompiled headers OBJ (" + | |
| 441 | File->getName() + ")"); | |
| 442 | ||
| 443 | // When a precompiled headers object comes first on the command-line, we | |
| 444 | // update the mapping here. Otherwise, if an object referencing the | |
| 445 | // precompiled headers object comes first, the mapping is created in | |
| 446 | // aquirePrecompObj(), thus we would skip this block. | |
| 447 | if (!ObjectIndexMap->IsPrecompiledTypeMap) { | |
| 448 | auto R = registerPrecompiledHeaders(PCHSignature); | |
| 449 | if (R.second) | |
| 450 | fatal( | |
| 451 | "A precompiled headers OBJ with the same signature was already " | |
| 452 | "provided! (" + | |
| 453 | File->getName() + ")"); | |
| 454 | ||
| 455 | ObjectIndexMap = &R.first; | |
| 456 | } | |
| 457 | } | |
| 266 | 458 | |
| 267 | 459 | BinaryByteStream Stream(Data, support::little); |
| 268 | 460 | CVTypeArray Types; |
| ... | ... | @@ -270,13 +462,32 @@ Expected<const CVIndexMap&> PDBLinker::mergeDebugT(ObjFile *File, |
| 270 | 462 | if (auto EC = Reader.readArray(Types, Reader.getLength())) |
| 271 | 463 | fatal("Reader::readArray failed: " + toString(std::move(EC))); |
| 272 | 464 | |
| 273 | // Look through type servers. If we've already seen this type server, don't | |
| 274 | // merge any type information. | |
| 275 | if (Optional<TypeServer2Record> TS = maybeReadTypeServerRecord(Types)) | |
| 276 | return maybeMergeTypeServerPDB(File, *TS); | |
| 465 | auto FirstType = Types.begin(); | |
| 466 | if (FirstType == Types.end()) | |
| 467 | return *ObjectIndexMap; | |
| 468 | ||
| 469 | if (FirstType->kind() == LF_TYPESERVER2) { | |
| 470 | // Look through type servers. If we've already seen this type server, | |
| 471 | // don't merge any type information. | |
| 472 | return maybeMergeTypeServerPDB(File, *FirstType); | |
| 473 | } else if (FirstType->kind() == LF_PRECOMP) { | |
| 474 | // This object was compiled with /Yu, so process the corresponding | |
| 475 | // precompiled headers object (/Yc) first. Some type indices in the current | |
| 476 | // object are referencing data in the precompiled headers object, so we need | |
| 477 | // both to be loaded. | |
| 478 | auto E = mergeInPrecompHeaderObj(File, *FirstType, ObjectIndexMap); | |
| 479 | if (!E) | |
| 480 | return E.takeError(); | |
| 481 | ||
| 482 | // Drop LF_PRECOMP record from the input stream, as it needs to be replaced | |
| 483 | // with the precompiled headers object type stream. | |
| 484 | // Note that we can't just call Types.drop_front(), as we explicitly want to | |
| 485 | // rebase the stream. | |
| 486 | Types.setUnderlyingStream( | |
| 487 | Types.getUnderlyingStream().drop_front(FirstType->RecordData.size())); | |
| 488 | } | |
| 277 | 489 | |
| 278 | // This is a /Z7 object. Fill in the temporary, caller-provided | |
| 279 | // ObjectIndexMap. | |
| 490 | // Fill in the temporary, caller-provided ObjectIndexMap. | |
| 280 | 491 | if (Config->DebugGHashes) { |
| 281 | 492 | ArrayRef<GloballyHashedType> Hashes; |
| 282 | 493 | std::vector<GloballyHashedType> OwnedHashes; |
| ... | ... | @@ -288,20 +499,28 @@ Expected<const CVIndexMap&> PDBLinker::mergeDebugT(ObjFile *File, |
| 288 | 499 | } |
| 289 | 500 | |
| 290 | 501 | if (auto Err = mergeTypeAndIdRecords(GlobalIDTable, GlobalTypeTable, |
| 291 | ObjectIndexMap.TPIMap, Types, Hashes)) | |
| 502 | ObjectIndexMap->TPIMap, Types, Hashes, | |
| 503 | File->PCHSignature)) | |
| 292 | 504 | fatal("codeview::mergeTypeAndIdRecords failed: " + |
| 293 | 505 | toString(std::move(Err))); |
| 294 | 506 | } else { |
| 295 | if (auto Err = mergeTypeAndIdRecords(IDTable, TypeTable, | |
| 296 | ObjectIndexMap.TPIMap, Types)) | |
| 507 | if (auto Err = | |
| 508 | mergeTypeAndIdRecords(IDTable, TypeTable, ObjectIndexMap->TPIMap, | |
| 509 | Types, File->PCHSignature)) | |
| 297 | 510 | fatal("codeview::mergeTypeAndIdRecords failed: " + |
| 298 | 511 | toString(std::move(Err))); |
| 299 | 512 | } |
| 300 | return ObjectIndexMap; | |
| 513 | return *ObjectIndexMap; | |
| 301 | 514 | } |
| 302 | 515 | |
| 303 | 516 | static Expected<std::unique_ptr<pdb::NativeSession>> |
| 304 | tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) { | |
| 517 | tryToLoadPDB(const codeview::GUID &GuidFromObj, StringRef TSPath) { | |
| 518 | // Ensure the file exists before anything else. We want to return ENOENT, | |
| 519 | // "file not found", even if the path points to a removable device (in which | |
| 520 | // case the return message would be EAGAIN, "resource unavailable try again") | |
| 521 | if (!llvm::sys::fs::exists(TSPath)) | |
| 522 | return errorCodeToError(std::error_code(ENOENT, std::generic_category())); | |
| 523 | ||
| 305 | 524 | ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile( |
| 306 | 525 | TSPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false); |
| 307 | 526 | if (!MBOrErr) |
| ... | ... | @@ -326,21 +545,27 @@ tryToLoadPDB(const GUID &GuidFromObj, StringRef TSPath) { |
| 326 | 545 | // PDB file doesn't mean it matches. For it to match the InfoStream's GUID |
| 327 | 546 | // must match the GUID specified in the TypeServer2 record. |
| 328 | 547 | if (ExpectedInfo->getGuid() != GuidFromObj) |
| 329 | return make_error<pdb::GenericError>( | |
| 330 | pdb::generic_error_code::type_server_not_found, TSPath); | |
| 548 | return make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date); | |
| 331 | 549 | |
| 332 | 550 | return std::move(NS); |
| 333 | 551 | } |
| 334 | 552 | |
| 335 | Expected<const CVIndexMap&> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, | |
| 336 | TypeServer2Record &TS) { | |
| 337 | const GUID& TSId = TS.getGuid(); | |
| 553 | Expected<const CVIndexMap &> | |
| 554 | PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, const CVType &FirstType) { | |
| 555 | TypeServer2Record TS; | |
| 556 | if (auto EC = | |
| 557 | TypeDeserializer::deserializeAs(const_cast<CVType &>(FirstType), TS)) | |
| 558 | fatal("error reading record: " + toString(std::move(EC))); | |
| 559 | ||
| 560 | const codeview::GUID &TSId = TS.getGuid(); | |
| 338 | 561 | StringRef TSPath = TS.getName(); |
| 339 | 562 | |
| 340 | 563 | // First, check if the PDB has previously failed to load. |
| 341 | if (MissingTypeServerPDBs.count(TSId)) | |
| 342 | return make_error<pdb::GenericError>( | |
| 343 | pdb::generic_error_code::type_server_not_found, TSPath); | |
| 564 | auto PrevErr = MissingTypeServerPDBs.find(TSId); | |
| 565 | if (PrevErr != MissingTypeServerPDBs.end()) | |
| 566 | return createFileError( | |
| 567 | TSPath, | |
| 568 | make_error<StringError>(PrevErr->second, inconvertibleErrorCode())); | |
| 344 | 569 | |
| 345 | 570 | // Second, check if we already loaded a PDB with this GUID. Return the type |
| 346 | 571 | // index mapping if we have it. |
| ... | ... | @@ -355,20 +580,39 @@ Expected<const CVIndexMap&> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, |
| 355 | 580 | // Check for a PDB at: |
| 356 | 581 | // 1. The given file path |
| 357 | 582 | // 2. Next to the object file or archive file |
| 358 | auto ExpectedSession = tryToLoadPDB(TSId, TSPath); | |
| 359 | if (!ExpectedSession) { | |
| 360 | consumeError(ExpectedSession.takeError()); | |
| 361 | StringRef LocalPath = | |
| 362 | !File->ParentName.empty() ? File->ParentName : File->getName(); | |
| 363 | SmallString<128> Path = sys::path::parent_path(LocalPath); | |
| 364 | sys::path::append( | |
| 365 | Path, sys::path::filename(TSPath, sys::path::Style::windows)); | |
| 366 | ExpectedSession = tryToLoadPDB(TSId, Path); | |
| 367 | } | |
| 583 | auto ExpectedSession = handleExpected( | |
| 584 | tryToLoadPDB(TSId, TSPath), | |
| 585 | [&]() { | |
| 586 | StringRef LocalPath = | |
| 587 | !File->ParentName.empty() ? File->ParentName : File->getName(); | |
| 588 | SmallString<128> Path = sys::path::parent_path(LocalPath); | |
| 589 | // Currently, type server PDBs are only created by cl, which only runs | |
| 590 | // on Windows, so we can assume type server paths are Windows style. | |
| 591 | sys::path::append( | |
| 592 | Path, sys::path::filename(TSPath, sys::path::Style::windows)); | |
| 593 | return tryToLoadPDB(TSId, Path); | |
| 594 | }, | |
| 595 | [&](std::unique_ptr<ECError> EC) -> Error { | |
| 596 | auto SysErr = EC->convertToErrorCode(); | |
| 597 | // Only re-try loading if the previous error was "No such file or | |
| 598 | // directory" | |
| 599 | if (SysErr.category() == std::generic_category() && | |
| 600 | SysErr.value() == ENOENT) | |
| 601 | return Error::success(); | |
| 602 | return Error(std::move(EC)); | |
| 603 | }); | |
| 604 | ||
| 368 | 605 | if (auto E = ExpectedSession.takeError()) { |
| 369 | 606 | TypeServerIndexMappings.erase(TSId); |
| 370 | MissingTypeServerPDBs.emplace(TSId); | |
| 371 | return std::move(E); | |
| 607 | ||
| 608 | // Flatten the error to a string, for later display, if the error occurs | |
| 609 | // again on the same PDB. | |
| 610 | std::string ErrMsg; | |
| 611 | raw_string_ostream S(ErrMsg); | |
| 612 | S << E; | |
| 613 | MissingTypeServerPDBs.emplace(TSId, S.str()); | |
| 614 | ||
| 615 | return createFileError(TSPath, std::move(E)); | |
| 372 | 616 | } |
| 373 | 617 | |
| 374 | 618 | pdb::NativeSession *Session = ExpectedSession->get(); |
| ... | ... | @@ -394,9 +638,10 @@ Expected<const CVIndexMap&> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, |
| 394 | 638 | auto IpiHashes = |
| 395 | 639 | GloballyHashedType::hashIds(ExpectedIpi->typeArray(), TpiHashes); |
| 396 | 640 | |
| 641 | Optional<uint32_t> EndPrecomp; | |
| 397 | 642 | // Merge TPI first, because the IPI stream will reference type indices. |
| 398 | 643 | if (auto Err = mergeTypeRecords(GlobalTypeTable, IndexMap.TPIMap, |
| 399 | ExpectedTpi->typeArray(), TpiHashes)) | |
| 644 | ExpectedTpi->typeArray(), TpiHashes, EndPrecomp)) | |
| 400 | 645 | fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err))); |
| 401 | 646 | |
| 402 | 647 | // Merge IPI. |
| ... | ... | @@ -419,6 +664,103 @@ Expected<const CVIndexMap&> PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, |
| 419 | 664 | return IndexMap; |
| 420 | 665 | } |
| 421 | 666 | |
| 667 | Expected<const CVIndexMap &> | |
| 668 | PDBLinker::mergeInPrecompHeaderObj(ObjFile *File, const CVType &FirstType, | |
| 669 | CVIndexMap *ObjectIndexMap) { | |
| 670 | PrecompRecord Precomp; | |
| 671 | if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(FirstType), | |
| 672 | Precomp)) | |
| 673 | fatal("error reading record: " + toString(std::move(EC))); | |
| 674 | ||
| 675 | auto E = aquirePrecompObj(File, Precomp); | |
| 676 | if (!E) | |
| 677 | return E.takeError(); | |
| 678 | ||
| 679 | const CVIndexMap &PrecompIndexMap = *E; | |
| 680 | assert(PrecompIndexMap.IsPrecompiledTypeMap); | |
| 681 | ||
| 682 | if (PrecompIndexMap.TPIMap.empty()) | |
| 683 | return PrecompIndexMap; | |
| 684 | ||
| 685 | assert(Precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex); | |
| 686 | assert(Precomp.getTypesCount() <= PrecompIndexMap.TPIMap.size()); | |
| 687 | // Use the previously remapped index map from the precompiled headers. | |
| 688 | ObjectIndexMap->TPIMap.append(PrecompIndexMap.TPIMap.begin(), | |
| 689 | PrecompIndexMap.TPIMap.begin() + | |
| 690 | Precomp.getTypesCount()); | |
| 691 | return *ObjectIndexMap; | |
| 692 | } | |
| 693 | ||
| 694 | static bool equals_path(StringRef path1, StringRef path2) { | |
| 695 | #if defined(_WIN32) | |
| 696 | return path1.equals_lower(path2); | |
| 697 | #else | |
| 698 | return path1.equals(path2); | |
| 699 | #endif | |
| 700 | } | |
| 701 | ||
| 702 | // Find by name an OBJ provided on the command line | |
| 703 | static ObjFile *findObjByName(StringRef FileNameOnly) { | |
| 704 | SmallString<128> CurrentPath; | |
| 705 | ||
| 706 | for (ObjFile *F : ObjFile::Instances) { | |
| 707 | StringRef CurrentFileName = sys::path::filename(F->getName()); | |
| 708 | ||
| 709 | // Compare based solely on the file name (link.exe behavior) | |
| 710 | if (equals_path(CurrentFileName, FileNameOnly)) | |
| 711 | return F; | |
| 712 | } | |
| 713 | return nullptr; | |
| 714 | } | |
| 715 | ||
| 716 | std::pair<CVIndexMap &, bool /*already there*/> | |
| 717 | PDBLinker::registerPrecompiledHeaders(uint32_t Signature) { | |
| 718 | auto Insertion = PrecompTypeIndexMappings.insert({Signature, CVIndexMap()}); | |
| 719 | CVIndexMap &IndexMap = Insertion.first->second; | |
| 720 | if (!Insertion.second) | |
| 721 | return {IndexMap, true}; | |
| 722 | // Mark this map as a precompiled types map. | |
| 723 | IndexMap.IsPrecompiledTypeMap = true; | |
| 724 | return {IndexMap, false}; | |
| 725 | } | |
| 726 | ||
| 727 | Expected<const CVIndexMap &> | |
| 728 | PDBLinker::aquirePrecompObj(ObjFile *File, PrecompRecord Precomp) { | |
| 729 | // First, check if we already loaded the precompiled headers object with this | |
| 730 | // signature. Return the type index mapping if we've already seen it. | |
| 731 | auto R = registerPrecompiledHeaders(Precomp.getSignature()); | |
| 732 | if (R.second) | |
| 733 | return R.first; | |
| 734 | ||
| 735 | CVIndexMap &IndexMap = R.first; | |
| 736 | ||
| 737 | // Cross-compile warning: given that Clang doesn't generate LF_PRECOMP | |
| 738 | // records, we assume the OBJ comes from a Windows build of cl.exe. Thusly, | |
| 739 | // the paths embedded in the OBJs are in the Windows format. | |
| 740 | SmallString<128> PrecompFileName = sys::path::filename( | |
| 741 | Precomp.getPrecompFilePath(), sys::path::Style::windows); | |
| 742 | ||
| 743 | // link.exe requires that a precompiled headers object must always be provided | |
| 744 | // on the command-line, even if that's not necessary. | |
| 745 | auto PrecompFile = findObjByName(PrecompFileName); | |
| 746 | if (!PrecompFile) | |
| 747 | return createFileError( | |
| 748 | PrecompFileName.str(), | |
| 749 | make_error<pdb::PDBError>(pdb::pdb_error_code::external_cmdline_ref)); | |
| 750 | ||
| 751 | addObjFile(PrecompFile, &IndexMap); | |
| 752 | ||
| 753 | if (!PrecompFile->PCHSignature) | |
| 754 | fatal(PrecompFile->getName() + " is not a precompiled headers object"); | |
| 755 | ||
| 756 | if (Precomp.getSignature() != PrecompFile->PCHSignature.getValueOr(0)) | |
| 757 | return createFileError( | |
| 758 | Precomp.getPrecompFilePath().str(), | |
| 759 | make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date)); | |
| 760 | ||
| 761 | return IndexMap; | |
| 762 | } | |
| 763 | ||
| 422 | 764 | static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) { |
| 423 | 765 | if (TI.isSimple()) |
| 424 | 766 | return true; |
| ... | ... | @@ -429,9 +771,11 @@ static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) { |
| 429 | 771 | } |
| 430 | 772 | |
| 431 | 773 | static void remapTypesInSymbolRecord(ObjFile *File, SymbolKind SymKind, |
| 432 | MutableArrayRef<uint8_t> Contents, | |
| 774 | MutableArrayRef<uint8_t> RecordBytes, | |
| 433 | 775 | const CVIndexMap &IndexMap, |
| 434 | 776 | ArrayRef<TiReference> TypeRefs) { |
| 777 | MutableArrayRef<uint8_t> Contents = | |
| 778 | RecordBytes.drop_front(sizeof(RecordPrefix)); | |
| 435 | 779 | for (const TiReference &Ref : TypeRefs) { |
| 436 | 780 | unsigned ByteSize = Ref.Count * sizeof(TypeIndex); |
| 437 | 781 | if (Contents.size() < Ref.Offset + ByteSize) |
| ... | ... | @@ -477,7 +821,7 @@ recordStringTableReferences(SymbolKind Kind, MutableArrayRef<uint8_t> Contents, |
| 477 | 821 | switch (Kind) { |
| 478 | 822 | case SymbolKind::S_FILESTATIC: |
| 479 | 823 | // FileStaticSym::ModFileOffset |
| 480 | recordStringTableReferenceAtOffset(Contents, 4, StrTableRefs); | |
| 824 | recordStringTableReferenceAtOffset(Contents, 8, StrTableRefs); | |
| 481 | 825 | break; |
| 482 | 826 | case SymbolKind::S_DEFRANGE: |
| 483 | 827 | case SymbolKind::S_DEFRANGE_SUBFIELD: |
| ... | ... | @@ -542,58 +886,26 @@ static void translateIdSymbols(MutableArrayRef<uint8_t> &RecordData, |
| 542 | 886 | |
| 543 | 887 | /// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned. |
| 544 | 888 | /// The object file may not be aligned. |
| 545 | static MutableArrayRef<uint8_t> copySymbolForPdb(const CVSymbol &Sym, | |
| 546 | BumpPtrAllocator &Alloc) { | |
| 889 | static MutableArrayRef<uint8_t> | |
| 890 | copyAndAlignSymbol(const CVSymbol &Sym, MutableArrayRef<uint8_t> &AlignedMem) { | |
| 547 | 891 | size_t Size = alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb)); |
| 548 | 892 | assert(Size >= 4 && "record too short"); |
| 549 | 893 | assert(Size <= MaxRecordLength && "record too long"); |
| 550 | void *Mem = Alloc.Allocate(Size, 4); | |
| 894 | assert(AlignedMem.size() >= Size && "didn't preallocate enough"); | |
| 551 | 895 | |
| 552 | 896 | // Copy the symbol record and zero out any padding bytes. |
| 553 | MutableArrayRef<uint8_t> NewData(reinterpret_cast<uint8_t *>(Mem), Size); | |
| 897 | MutableArrayRef<uint8_t> NewData = AlignedMem.take_front(Size); | |
| 898 | AlignedMem = AlignedMem.drop_front(Size); | |
| 554 | 899 | memcpy(NewData.data(), Sym.data().data(), Sym.length()); |
| 555 | 900 | memset(NewData.data() + Sym.length(), 0, Size - Sym.length()); |
| 556 | 901 | |
| 557 | 902 | // Update the record prefix length. It should point to the beginning of the |
| 558 | 903 | // next record. |
| 559 | auto *Prefix = reinterpret_cast<RecordPrefix *>(Mem); | |
| 904 | auto *Prefix = reinterpret_cast<RecordPrefix *>(NewData.data()); | |
| 560 | 905 | Prefix->RecordLen = Size - 2; |
| 561 | 906 | return NewData; |
| 562 | 907 | } |
| 563 | 908 | |
| 564 | /// Return true if this symbol opens a scope. This implies that the symbol has | |
| 565 | /// "parent" and "end" fields, which contain the offset of the S_END or | |
| 566 | /// S_INLINESITE_END record. | |
| 567 | static bool symbolOpensScope(SymbolKind Kind) { | |
| 568 | switch (Kind) { | |
| 569 | case SymbolKind::S_GPROC32: | |
| 570 | case SymbolKind::S_LPROC32: | |
| 571 | case SymbolKind::S_LPROC32_ID: | |
| 572 | case SymbolKind::S_GPROC32_ID: | |
| 573 | case SymbolKind::S_BLOCK32: | |
| 574 | case SymbolKind::S_SEPCODE: | |
| 575 | case SymbolKind::S_THUNK32: | |
| 576 | case SymbolKind::S_INLINESITE: | |
| 577 | case SymbolKind::S_INLINESITE2: | |
| 578 | return true; | |
| 579 | default: | |
| 580 | break; | |
| 581 | } | |
| 582 | return false; | |
| 583 | } | |
| 584 | ||
| 585 | static bool symbolEndsScope(SymbolKind Kind) { | |
| 586 | switch (Kind) { | |
| 587 | case SymbolKind::S_END: | |
| 588 | case SymbolKind::S_PROC_ID_END: | |
| 589 | case SymbolKind::S_INLINESITE_END: | |
| 590 | return true; | |
| 591 | default: | |
| 592 | break; | |
| 593 | } | |
| 594 | return false; | |
| 595 | } | |
| 596 | ||
| 597 | 909 | struct ScopeRecord { |
| 598 | 910 | ulittle32_t PtrParent; |
| 599 | 911 | ulittle32_t PtrEnd; |
| ... | ... | @@ -625,11 +937,10 @@ static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack, |
| 625 | 937 | S.OpeningRecord->PtrEnd = CurOffset; |
| 626 | 938 | } |
| 627 | 939 | |
| 628 | static bool symbolGoesInModuleStream(const CVSymbol &Sym) { | |
| 940 | static bool symbolGoesInModuleStream(const CVSymbol &Sym, bool IsGlobalScope) { | |
| 629 | 941 | switch (Sym.kind()) { |
| 630 | 942 | case SymbolKind::S_GDATA32: |
| 631 | 943 | case SymbolKind::S_CONSTANT: |
| 632 | case SymbolKind::S_UDT: | |
| 633 | 944 | // We really should not be seeing S_PROCREF and S_LPROCREF in the first place |
| 634 | 945 | // since they are synthesized by the linker in response to S_GPROC32 and |
| 635 | 946 | // S_LPROC32, but if we do see them, don't put them in the module stream I |
| ... | ... | @@ -637,6 +948,9 @@ static bool symbolGoesInModuleStream(const CVSymbol &Sym) { |
| 637 | 948 | case SymbolKind::S_PROCREF: |
| 638 | 949 | case SymbolKind::S_LPROCREF: |
| 639 | 950 | return false; |
| 951 | // S_UDT records go in the module stream if it is not a global S_UDT. | |
| 952 | case SymbolKind::S_UDT: | |
| 953 | return !IsGlobalScope; | |
| 640 | 954 | // S_GDATA32 does not go in the module stream, but S_LDATA32 does. |
| 641 | 955 | case SymbolKind::S_LDATA32: |
| 642 | 956 | default: |
| ... | ... | @@ -644,7 +958,7 @@ static bool symbolGoesInModuleStream(const CVSymbol &Sym) { |
| 644 | 958 | } |
| 645 | 959 | } |
| 646 | 960 | |
| 647 | static bool symbolGoesInGlobalsStream(const CVSymbol &Sym) { | |
| 961 | static bool symbolGoesInGlobalsStream(const CVSymbol &Sym, bool IsGlobalScope) { | |
| 648 | 962 | switch (Sym.kind()) { |
| 649 | 963 | case SymbolKind::S_CONSTANT: |
| 650 | 964 | case SymbolKind::S_GDATA32: |
| ... | ... | @@ -658,20 +972,16 @@ static bool symbolGoesInGlobalsStream(const CVSymbol &Sym) { |
| 658 | 972 | case SymbolKind::S_PROCREF: |
| 659 | 973 | case SymbolKind::S_LPROCREF: |
| 660 | 974 | return true; |
| 661 | // FIXME: For now, we drop all S_UDT symbols (i.e. they don't go in the | |
| 662 | // globals stream or the modules stream). These have special handling which | |
| 663 | // needs more investigation before we can get right, but by putting them all | |
| 664 | // into the globals stream WinDbg fails to display local variables of class | |
| 665 | // types saying that it cannot find the type Foo *. So as a stopgap just to | |
| 666 | // keep things working, we drop them. | |
| 975 | // S_UDT records go in the globals stream if it is a global S_UDT. | |
| 667 | 976 | case SymbolKind::S_UDT: |
| 977 | return IsGlobalScope; | |
| 668 | 978 | default: |
| 669 | 979 | return false; |
| 670 | 980 | } |
| 671 | 981 | } |
| 672 | 982 | |
| 673 | static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, ObjFile &File, | |
| 674 | const CVSymbol &Sym) { | |
| 983 | static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, uint16_t ModIndex, | |
| 984 | unsigned SymOffset, const CVSymbol &Sym) { | |
| 675 | 985 | switch (Sym.kind()) { |
| 676 | 986 | case SymbolKind::S_CONSTANT: |
| 677 | 987 | case SymbolKind::S_UDT: |
| ... | ... | @@ -687,12 +997,12 @@ static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, ObjFile &File, |
| 687 | 997 | if (Sym.kind() == SymbolKind::S_LPROC32) |
| 688 | 998 | K = SymbolRecordKind::LocalProcRef; |
| 689 | 999 | ProcRefSym PS(K); |
| 690 | PS.Module = static_cast<uint16_t>(File.ModuleDBI->getModuleIndex()); | |
| 1000 | PS.Module = ModIndex; | |
| 691 | 1001 | // For some reason, MSVC seems to add one to this value. |
| 692 | 1002 | ++PS.Module; |
| 693 | 1003 | PS.Name = getSymbolName(Sym); |
| 694 | 1004 | PS.SumName = 0; |
| 695 | PS.SymOffset = File.ModuleDBI->getNextSymbolOffset(); | |
| 1005 | PS.SymOffset = SymOffset; | |
| 696 | 1006 | Builder.addGlobalSymbol(PS); |
| 697 | 1007 | break; |
| 698 | 1008 | } |
| ... | ... | @@ -701,20 +1011,62 @@ static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, ObjFile &File, |
| 701 | 1011 | } |
| 702 | 1012 | } |
| 703 | 1013 | |
| 704 | static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjFile *File, | |
| 705 | pdb::GSIStreamBuilder &GsiBuilder, | |
| 706 | const CVIndexMap &IndexMap, | |
| 707 | TypeCollection &IDTable, | |
| 708 | std::vector<ulittle32_t *> &StringTableRefs, | |
| 709 | BinaryStreamRef SymData) { | |
| 710 | // FIXME: Improve error recovery by warning and skipping records when | |
| 711 | // possible. | |
| 1014 | void PDBLinker::mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap, | |
| 1015 | std::vector<ulittle32_t *> &StringTableRefs, | |
| 1016 | BinaryStreamRef SymData) { | |
| 712 | 1017 | ArrayRef<uint8_t> SymsBuffer; |
| 713 | 1018 | cantFail(SymData.readBytes(0, SymData.getLength(), SymsBuffer)); |
| 714 | 1019 | SmallVector<SymbolScope, 4> Scopes; |
| 715 | 1020 | |
| 1021 | // Iterate every symbol to check if any need to be realigned, and if so, how | |
| 1022 | // much space we need to allocate for them. | |
| 1023 | bool NeedsRealignment = false; | |
| 1024 | unsigned TotalRealignedSize = 0; | |
| 716 | 1025 | auto EC = forEachCodeViewRecord<CVSymbol>( |
| 717 | SymsBuffer, [&](const CVSymbol &Sym) -> llvm::Error { | |
| 1026 | SymsBuffer, [&](CVSymbol Sym) -> llvm::Error { | |
| 1027 | unsigned RealignedSize = | |
| 1028 | alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb)); | |
| 1029 | NeedsRealignment |= RealignedSize != Sym.length(); | |
| 1030 | TotalRealignedSize += RealignedSize; | |
| 1031 | return Error::success(); | |
| 1032 | }); | |
| 1033 | ||
| 1034 | // If any of the symbol record lengths was corrupt, ignore them all, warn | |
| 1035 | // about it, and move on. | |
| 1036 | if (EC) { | |
| 1037 | warn("corrupt symbol records in " + File->getName()); | |
| 1038 | consumeError(std::move(EC)); | |
| 1039 | return; | |
| 1040 | } | |
| 1041 | ||
| 1042 | // If any symbol needed realignment, allocate enough contiguous memory for | |
| 1043 | // them all. Typically symbol subsections are small enough that this will not | |
| 1044 | // cause fragmentation. | |
| 1045 | MutableArrayRef<uint8_t> AlignedSymbolMem; | |
| 1046 | if (NeedsRealignment) { | |
| 1047 | void *AlignedData = | |
| 1048 | Alloc.Allocate(TotalRealignedSize, alignOf(CodeViewContainer::Pdb)); | |
| 1049 | AlignedSymbolMem = makeMutableArrayRef( | |
| 1050 | reinterpret_cast<uint8_t *>(AlignedData), TotalRealignedSize); | |
| 1051 | } | |
| 1052 | ||
| 1053 | // Iterate again, this time doing the real work. | |
| 1054 | unsigned CurSymOffset = File->ModuleDBI->getNextSymbolOffset(); | |
| 1055 | ArrayRef<uint8_t> BulkSymbols; | |
| 1056 | cantFail(forEachCodeViewRecord<CVSymbol>( | |
| 1057 | SymsBuffer, [&](CVSymbol Sym) -> llvm::Error { | |
| 1058 | // Align the record if required. | |
| 1059 | MutableArrayRef<uint8_t> RecordBytes; | |
| 1060 | if (NeedsRealignment) { | |
| 1061 | RecordBytes = copyAndAlignSymbol(Sym, AlignedSymbolMem); | |
| 1062 | Sym = CVSymbol(Sym.kind(), RecordBytes); | |
| 1063 | } else { | |
| 1064 | // Otherwise, we can actually mutate the symbol directly, since we | |
| 1065 | // copied it to apply relocations. | |
| 1066 | RecordBytes = makeMutableArrayRef( | |
| 1067 | const_cast<uint8_t *>(Sym.data().data()), Sym.length()); | |
| 1068 | } | |
| 1069 | ||
| 718 | 1070 | // Discover type index references in the record. Skip it if we don't |
| 719 | 1071 | // know where they are. |
| 720 | 1072 | SmallVector<TiReference, 32> TypeRefs; |
| ... | ... | @@ -724,57 +1076,62 @@ static void mergeSymbolRecords(BumpPtrAllocator &Alloc, ObjFile *File, |
| 724 | 1076 | return Error::success(); |
| 725 | 1077 | } |
| 726 | 1078 | |
| 727 | // Copy the symbol record so we can mutate it. | |
| 728 | MutableArrayRef<uint8_t> NewData = copySymbolForPdb(Sym, Alloc); | |
| 729 | ||
| 730 | 1079 | // Re-map all the type index references. |
| 731 | MutableArrayRef<uint8_t> Contents = | |
| 732 | NewData.drop_front(sizeof(RecordPrefix)); | |
| 733 | remapTypesInSymbolRecord(File, Sym.kind(), Contents, IndexMap, | |
| 1080 | remapTypesInSymbolRecord(File, Sym.kind(), RecordBytes, IndexMap, | |
| 734 | 1081 | TypeRefs); |
| 735 | 1082 | |
| 736 | 1083 | // An object file may have S_xxx_ID symbols, but these get converted to |
| 737 | 1084 | // "real" symbols in a PDB. |
| 738 | translateIdSymbols(NewData, IDTable); | |
| 1085 | translateIdSymbols(RecordBytes, getIDTable()); | |
| 1086 | Sym = CVSymbol(symbolKind(RecordBytes), RecordBytes); | |
| 739 | 1087 | |
| 740 | 1088 | // If this record refers to an offset in the object file's string table, |
| 741 | 1089 | // add that item to the global PDB string table and re-write the index. |
| 742 | recordStringTableReferences(Sym.kind(), Contents, StringTableRefs); | |
| 743 | ||
| 744 | SymbolKind NewKind = symbolKind(NewData); | |
| 1090 | recordStringTableReferences(Sym.kind(), RecordBytes, StringTableRefs); | |
| 745 | 1091 | |
| 746 | 1092 | // Fill in "Parent" and "End" fields by maintaining a stack of scopes. |
| 747 | CVSymbol NewSym(NewKind, NewData); | |
| 748 | if (symbolOpensScope(NewKind)) | |
| 749 | scopeStackOpen(Scopes, File->ModuleDBI->getNextSymbolOffset(), | |
| 750 | NewSym); | |
| 751 | else if (symbolEndsScope(NewKind)) | |
| 752 | scopeStackClose(Scopes, File->ModuleDBI->getNextSymbolOffset(), File); | |
| 1093 | if (symbolOpensScope(Sym.kind())) | |
| 1094 | scopeStackOpen(Scopes, CurSymOffset, Sym); | |
| 1095 | else if (symbolEndsScope(Sym.kind())) | |
| 1096 | scopeStackClose(Scopes, CurSymOffset, File); | |
| 753 | 1097 | |
| 754 | 1098 | // Add the symbol to the globals stream if necessary. Do this before |
| 755 | 1099 | // adding the symbol to the module since we may need to get the next |
| 756 | 1100 | // symbol offset, and writing to the module's symbol stream will update |
| 757 | 1101 | // that offset. |
| 758 | if (symbolGoesInGlobalsStream(NewSym)) | |
| 759 | addGlobalSymbol(GsiBuilder, *File, NewSym); | |
| 760 | ||
| 761 | // Add the symbol to the module. | |
| 762 | if (symbolGoesInModuleStream(NewSym)) | |
| 763 | File->ModuleDBI->addSymbol(NewSym); | |
| 1102 | if (symbolGoesInGlobalsStream(Sym, Scopes.empty())) | |
| 1103 | addGlobalSymbol(Builder.getGsiBuilder(), | |
| 1104 | File->ModuleDBI->getModuleIndex(), CurSymOffset, Sym); | |
| 1105 | ||
| 1106 | if (symbolGoesInModuleStream(Sym, Scopes.empty())) { | |
| 1107 | // Add symbols to the module in bulk. If this symbol is contiguous | |
| 1108 | // with the previous run of symbols to add, combine the ranges. If | |
| 1109 | // not, close the previous range of symbols and start a new one. | |
| 1110 | if (Sym.data().data() == BulkSymbols.end()) { | |
| 1111 | BulkSymbols = makeArrayRef(BulkSymbols.data(), | |
| 1112 | BulkSymbols.size() + Sym.length()); | |
| 1113 | } else { | |
| 1114 | File->ModuleDBI->addSymbolsInBulk(BulkSymbols); | |
| 1115 | BulkSymbols = RecordBytes; | |
| 1116 | } | |
| 1117 | CurSymOffset += Sym.length(); | |
| 1118 | } | |
| 764 | 1119 | return Error::success(); |
| 765 | }); | |
| 766 | cantFail(std::move(EC)); | |
| 1120 | })); | |
| 1121 | ||
| 1122 | // Add any remaining symbols we've accumulated. | |
| 1123 | File->ModuleDBI->addSymbolsInBulk(BulkSymbols); | |
| 767 | 1124 | } |
| 768 | 1125 | |
| 769 | // Allocate memory for a .debug$S section and relocate it. | |
| 1126 | // Allocate memory for a .debug$S / .debug$F section and relocate it. | |
| 770 | 1127 | static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc, |
| 771 | SectionChunk *DebugChunk) { | |
| 772 | uint8_t *Buffer = Alloc.Allocate<uint8_t>(DebugChunk->getSize()); | |
| 773 | assert(DebugChunk->OutputSectionOff == 0 && | |
| 1128 | SectionChunk &DebugChunk) { | |
| 1129 | uint8_t *Buffer = Alloc.Allocate<uint8_t>(DebugChunk.getSize()); | |
| 1130 | assert(DebugChunk.OutputSectionOff == 0 && | |
| 774 | 1131 | "debug sections should not be in output sections"); |
| 775 | DebugChunk->writeTo(Buffer); | |
| 776 | return consumeDebugMagic(makeArrayRef(Buffer, DebugChunk->getSize()), | |
| 777 | ".debug$S"); | |
| 1132 | DebugChunk.readRelocTargets(); | |
| 1133 | DebugChunk.writeTo(Buffer); | |
| 1134 | return makeArrayRef(Buffer, DebugChunk.getSize()); | |
| 778 | 1135 | } |
| 779 | 1136 | |
| 780 | 1137 | static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) { |
| ... | ... | @@ -803,25 +1160,137 @@ static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) { |
| 803 | 1160 | return SC; |
| 804 | 1161 | } |
| 805 | 1162 | |
| 806 | void PDBLinker::addObjFile(ObjFile *File) { | |
| 1163 | static uint32_t | |
| 1164 | translateStringTableIndex(uint32_t ObjIndex, | |
| 1165 | const DebugStringTableSubsectionRef &ObjStrTable, | |
| 1166 | DebugStringTableSubsection &PdbStrTable) { | |
| 1167 | auto ExpectedString = ObjStrTable.getString(ObjIndex); | |
| 1168 | if (!ExpectedString) { | |
| 1169 | warn("Invalid string table reference"); | |
| 1170 | consumeError(ExpectedString.takeError()); | |
| 1171 | return 0; | |
| 1172 | } | |
| 1173 | ||
| 1174 | return PdbStrTable.insert(*ExpectedString); | |
| 1175 | } | |
| 1176 | ||
| 1177 | void DebugSHandler::handleDebugS(lld::coff::SectionChunk &DebugS) { | |
| 1178 | DebugSubsectionArray Subsections; | |
| 1179 | ||
| 1180 | ArrayRef<uint8_t> RelocatedDebugContents = consumeDebugMagic( | |
| 1181 | relocateDebugChunk(Linker.Alloc, DebugS), DebugS.getSectionName()); | |
| 1182 | ||
| 1183 | BinaryStreamReader Reader(RelocatedDebugContents, support::little); | |
| 1184 | ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size())); | |
| 1185 | ||
| 1186 | for (const DebugSubsectionRecord &SS : Subsections) { | |
| 1187 | switch (SS.kind()) { | |
| 1188 | case DebugSubsectionKind::StringTable: { | |
| 1189 | assert(!CVStrTab.valid() && | |
| 1190 | "Encountered multiple string table subsections!"); | |
| 1191 | ExitOnErr(CVStrTab.initialize(SS.getRecordData())); | |
| 1192 | break; | |
| 1193 | } | |
| 1194 | case DebugSubsectionKind::FileChecksums: | |
| 1195 | assert(!Checksums.valid() && | |
| 1196 | "Encountered multiple checksum subsections!"); | |
| 1197 | ExitOnErr(Checksums.initialize(SS.getRecordData())); | |
| 1198 | break; | |
| 1199 | case DebugSubsectionKind::Lines: | |
| 1200 | // We can add the relocated line table directly to the PDB without | |
| 1201 | // modification because the file checksum offsets will stay the same. | |
| 1202 | File.ModuleDBI->addDebugSubsection(SS); | |
| 1203 | break; | |
| 1204 | case DebugSubsectionKind::FrameData: { | |
| 1205 | // We need to re-write string table indices here, so save off all | |
| 1206 | // frame data subsections until we've processed the entire list of | |
| 1207 | // subsections so that we can be sure we have the string table. | |
| 1208 | DebugFrameDataSubsectionRef FDS; | |
| 1209 | ExitOnErr(FDS.initialize(SS.getRecordData())); | |
| 1210 | NewFpoFrames.push_back(std::move(FDS)); | |
| 1211 | break; | |
| 1212 | } | |
| 1213 | case DebugSubsectionKind::Symbols: { | |
| 1214 | Linker.mergeSymbolRecords(&File, IndexMap, StringTableReferences, | |
| 1215 | SS.getRecordData()); | |
| 1216 | break; | |
| 1217 | } | |
| 1218 | default: | |
| 1219 | // FIXME: Process the rest of the subsections. | |
| 1220 | break; | |
| 1221 | } | |
| 1222 | } | |
| 1223 | } | |
| 1224 | ||
| 1225 | void DebugSHandler::finish() { | |
| 1226 | pdb::DbiStreamBuilder &DbiBuilder = Linker.Builder.getDbiBuilder(); | |
| 1227 | ||
| 1228 | // We should have seen all debug subsections across the entire object file now | |
| 1229 | // which means that if a StringTable subsection and Checksums subsection were | |
| 1230 | // present, now is the time to handle them. | |
| 1231 | if (!CVStrTab.valid()) { | |
| 1232 | if (Checksums.valid()) | |
| 1233 | fatal(".debug$S sections with a checksums subsection must also contain a " | |
| 1234 | "string table subsection"); | |
| 1235 | ||
| 1236 | if (!StringTableReferences.empty()) | |
| 1237 | warn("No StringTable subsection was encountered, but there are string " | |
| 1238 | "table references"); | |
| 1239 | return; | |
| 1240 | } | |
| 1241 | ||
| 1242 | // Rewrite string table indices in the Fpo Data and symbol records to refer to | |
| 1243 | // the global PDB string table instead of the object file string table. | |
| 1244 | for (DebugFrameDataSubsectionRef &FDS : NewFpoFrames) { | |
| 1245 | const ulittle32_t *Reloc = FDS.getRelocPtr(); | |
| 1246 | for (codeview::FrameData FD : FDS) { | |
| 1247 | FD.RvaStart += *Reloc; | |
| 1248 | FD.FrameFunc = | |
| 1249 | translateStringTableIndex(FD.FrameFunc, CVStrTab, Linker.PDBStrTab); | |
| 1250 | DbiBuilder.addNewFpoData(FD); | |
| 1251 | } | |
| 1252 | } | |
| 1253 | ||
| 1254 | for (ulittle32_t *Ref : StringTableReferences) | |
| 1255 | *Ref = translateStringTableIndex(*Ref, CVStrTab, Linker.PDBStrTab); | |
| 1256 | ||
| 1257 | // Make a new file checksum table that refers to offsets in the PDB-wide | |
| 1258 | // string table. Generally the string table subsection appears after the | |
| 1259 | // checksum table, so we have to do this after looping over all the | |
| 1260 | // subsections. | |
| 1261 | auto NewChecksums = make_unique<DebugChecksumsSubsection>(Linker.PDBStrTab); | |
| 1262 | for (FileChecksumEntry &FC : Checksums) { | |
| 1263 | SmallString<128> FileName = | |
| 1264 | ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); | |
| 1265 | pdbMakeAbsolute(FileName); | |
| 1266 | ExitOnErr(Linker.Builder.getDbiBuilder().addModuleSourceFile( | |
| 1267 | *File.ModuleDBI, FileName)); | |
| 1268 | NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum); | |
| 1269 | } | |
| 1270 | File.ModuleDBI->addDebugSubsection(std::move(NewChecksums)); | |
| 1271 | } | |
| 1272 | ||
| 1273 | void PDBLinker::addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap) { | |
| 1274 | if (File->wasProcessedForPDB()) | |
| 1275 | return; | |
| 807 | 1276 | // Add a module descriptor for every object file. We need to put an absolute |
| 808 | 1277 | // path to the object into the PDB. If this is a plain object, we make its |
| 809 | 1278 | // path absolute. If it's an object in an archive, we make the archive path |
| 810 | 1279 | // absolute. |
| 811 | 1280 | bool InArchive = !File->ParentName.empty(); |
| 812 | 1281 | SmallString<128> Path = InArchive ? File->ParentName : File->getName(); |
| 813 | sys::fs::make_absolute(Path); | |
| 814 | sys::path::native(Path, sys::path::Style::windows); | |
| 1282 | pdbMakeAbsolute(Path); | |
| 815 | 1283 | StringRef Name = InArchive ? File->getName() : StringRef(Path); |
| 816 | 1284 | |
| 817 | File->ModuleDBI = &ExitOnErr(Builder.getDbiBuilder().addModuleInfo(Name)); | |
| 1285 | pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); | |
| 1286 | File->ModuleDBI = &ExitOnErr(DbiBuilder.addModuleInfo(Name)); | |
| 818 | 1287 | File->ModuleDBI->setObjFileName(Path); |
| 819 | 1288 | |
| 820 | 1289 | auto Chunks = File->getChunks(); |
| 821 | 1290 | uint32_t Modi = File->ModuleDBI->getModuleIndex(); |
| 822 | 1291 | for (Chunk *C : Chunks) { |
| 823 | 1292 | auto *SecChunk = dyn_cast<SectionChunk>(C); |
| 824 | if (!SecChunk || !SecChunk->isLive()) | |
| 1293 | if (!SecChunk || !SecChunk->Live) | |
| 825 | 1294 | continue; |
| 826 | 1295 | pdb::SectionContrib SC = createSectionContrib(SecChunk, Modi); |
| 827 | 1296 | File->ModuleDBI->setFirstSectionContrib(SC); |
| ... | ... | @@ -833,119 +1302,54 @@ void PDBLinker::addObjFile(ObjFile *File) { |
| 833 | 1302 | // the PDB first, so that we can get the map from object file type and item |
| 834 | 1303 | // indices to PDB type and item indices. |
| 835 | 1304 | CVIndexMap ObjectIndexMap; |
| 836 | auto IndexMapResult = mergeDebugT(File, ObjectIndexMap); | |
| 1305 | auto IndexMapResult = | |
| 1306 | mergeDebugT(File, ExternIndexMap ? ExternIndexMap : &ObjectIndexMap); | |
| 837 | 1307 | |
| 838 | 1308 | // If the .debug$T sections fail to merge, assume there is no debug info. |
| 839 | 1309 | if (!IndexMapResult) { |
| 840 | warn("Type server PDB for " + Name + " is invalid, ignoring debug info. " + | |
| 841 | toString(IndexMapResult.takeError())); | |
| 1310 | if (!Config->WarnDebugInfoUnusable) { | |
| 1311 | consumeError(IndexMapResult.takeError()); | |
| 1312 | return; | |
| 1313 | } | |
| 1314 | StringRef FileName = sys::path::filename(Path); | |
| 1315 | warn("Cannot use debug info for '" + FileName + "' [LNK4099]\n" + | |
| 1316 | ">>> failed to load reference " + | |
| 1317 | StringRef(toString(IndexMapResult.takeError()))); | |
| 842 | 1318 | return; |
| 843 | 1319 | } |
| 844 | 1320 | |
| 845 | const CVIndexMap &IndexMap = *IndexMapResult; | |
| 846 | ||
| 847 | 1321 | ScopedTimer T(SymbolMergingTimer); |
| 848 | 1322 | |
| 849 | // Now do all live .debug$S sections. | |
| 850 | DebugStringTableSubsectionRef CVStrTab; | |
| 851 | DebugChecksumsSubsectionRef Checksums; | |
| 852 | std::vector<ulittle32_t *> StringTableReferences; | |
| 1323 | DebugSHandler DSH(*this, *File, *IndexMapResult); | |
| 1324 | // Now do all live .debug$S and .debug$F sections. | |
| 853 | 1325 | for (SectionChunk *DebugChunk : File->getDebugChunks()) { |
| 854 | if (!DebugChunk->isLive() || DebugChunk->getSectionName() != ".debug$S") | |
| 1326 | if (!DebugChunk->Live || DebugChunk->getSize() == 0) | |
| 855 | 1327 | continue; |
| 856 | 1328 | |
| 857 | ArrayRef<uint8_t> RelocatedDebugContents = | |
| 858 | relocateDebugChunk(Alloc, DebugChunk); | |
| 859 | if (RelocatedDebugContents.empty()) | |
| 1329 | if (DebugChunk->getSectionName() == ".debug$S") { | |
| 1330 | DSH.handleDebugS(*DebugChunk); | |
| 860 | 1331 | continue; |
| 861 | ||
| 862 | DebugSubsectionArray Subsections; | |
| 863 | BinaryStreamReader Reader(RelocatedDebugContents, support::little); | |
| 864 | ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size())); | |
| 865 | ||
| 866 | for (const DebugSubsectionRecord &SS : Subsections) { | |
| 867 | switch (SS.kind()) { | |
| 868 | case DebugSubsectionKind::StringTable: { | |
| 869 | assert(!CVStrTab.valid() && | |
| 870 | "Encountered multiple string table subsections!"); | |
| 871 | ExitOnErr(CVStrTab.initialize(SS.getRecordData())); | |
| 872 | break; | |
| 873 | } | |
| 874 | case DebugSubsectionKind::FileChecksums: | |
| 875 | assert(!Checksums.valid() && | |
| 876 | "Encountered multiple checksum subsections!"); | |
| 877 | ExitOnErr(Checksums.initialize(SS.getRecordData())); | |
| 878 | break; | |
| 879 | case DebugSubsectionKind::Lines: | |
| 880 | // We can add the relocated line table directly to the PDB without | |
| 881 | // modification because the file checksum offsets will stay the same. | |
| 882 | File->ModuleDBI->addDebugSubsection(SS); | |
| 883 | break; | |
| 884 | case DebugSubsectionKind::Symbols: | |
| 885 | if (Config->DebugGHashes) { | |
| 886 | mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap, | |
| 887 | GlobalIDTable, StringTableReferences, | |
| 888 | SS.getRecordData()); | |
| 889 | } else { | |
| 890 | mergeSymbolRecords(Alloc, File, Builder.getGsiBuilder(), IndexMap, | |
| 891 | IDTable, StringTableReferences, | |
| 892 | SS.getRecordData()); | |
| 893 | } | |
| 894 | break; | |
| 895 | default: | |
| 896 | // FIXME: Process the rest of the subsections. | |
| 897 | break; | |
| 898 | } | |
| 899 | 1332 | } |
| 900 | } | |
| 901 | 1333 | |
| 902 | // We should have seen all debug subsections across the entire object file now | |
| 903 | // which means that if a StringTable subsection and Checksums subsection were | |
| 904 | // present, now is the time to handle them. | |
| 905 | if (!CVStrTab.valid()) { | |
| 906 | if (Checksums.valid()) | |
| 907 | fatal(".debug$S sections with a checksums subsection must also contain a " | |
| 908 | "string table subsection"); | |
| 1334 | if (DebugChunk->getSectionName() == ".debug$F") { | |
| 1335 | ArrayRef<uint8_t> RelocatedDebugContents = | |
| 1336 | relocateDebugChunk(Alloc, *DebugChunk); | |
| 909 | 1337 | |
| 910 | if (!StringTableReferences.empty()) | |
| 911 | warn("No StringTable subsection was encountered, but there are string " | |
| 912 | "table references"); | |
| 913 | return; | |
| 914 | } | |
| 1338 | FixedStreamArray<object::FpoData> FpoRecords; | |
| 1339 | BinaryStreamReader Reader(RelocatedDebugContents, support::little); | |
| 1340 | uint32_t Count = RelocatedDebugContents.size() / sizeof(object::FpoData); | |
| 1341 | ExitOnErr(Reader.readArray(FpoRecords, Count)); | |
| 915 | 1342 | |
| 916 | // Rewrite each string table reference based on the value that the string | |
| 917 | // assumes in the final PDB. | |
| 918 | for (ulittle32_t *Ref : StringTableReferences) { | |
| 919 | auto ExpectedString = CVStrTab.getString(*Ref); | |
| 920 | if (!ExpectedString) { | |
| 921 | warn("Invalid string table reference"); | |
| 922 | consumeError(ExpectedString.takeError()); | |
| 1343 | // These are already relocated and don't refer to the string table, so we | |
| 1344 | // can just copy it. | |
| 1345 | for (const object::FpoData &FD : FpoRecords) | |
| 1346 | DbiBuilder.addOldFpoData(FD); | |
| 923 | 1347 | continue; |
| 924 | 1348 | } |
| 925 | ||
| 926 | *Ref = PDBStrTab.insert(*ExpectedString); | |
| 927 | 1349 | } |
| 928 | 1350 | |
| 929 | // Make a new file checksum table that refers to offsets in the PDB-wide | |
| 930 | // string table. Generally the string table subsection appears after the | |
| 931 | // checksum table, so we have to do this after looping over all the | |
| 932 | // subsections. | |
| 933 | auto NewChecksums = make_unique<DebugChecksumsSubsection>(PDBStrTab); | |
| 934 | for (FileChecksumEntry &FC : Checksums) { | |
| 935 | SmallString<128> FileName = ExitOnErr(CVStrTab.getString(FC.FileNameOffset)); | |
| 936 | if (!sys::path::is_absolute(FileName) && | |
| 937 | !Config->PDBSourcePath.empty()) { | |
| 938 | SmallString<128> AbsoluteFileName = Config->PDBSourcePath; | |
| 939 | sys::path::append(AbsoluteFileName, FileName); | |
| 940 | sys::path::native(AbsoluteFileName); | |
| 941 | sys::path::remove_dots(AbsoluteFileName, /*remove_dot_dots=*/true); | |
| 942 | FileName = std::move(AbsoluteFileName); | |
| 943 | } | |
| 944 | ExitOnErr(Builder.getDbiBuilder().addModuleSourceFile(*File->ModuleDBI, | |
| 945 | FileName)); | |
| 946 | NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum); | |
| 947 | } | |
| 948 | File->ModuleDBI->addDebugSubsection(std::move(NewChecksums)); | |
| 1351 | // Do any post-processing now that all .debug$S sections have been processed. | |
| 1352 | DSH.finish(); | |
| 949 | 1353 | } |
| 950 | 1354 | |
| 951 | 1355 | static PublicSym32 createPublic(Defined *Def) { |
| ... | ... | @@ -977,13 +1381,8 @@ void PDBLinker::addObjectsToPDB() { |
| 977 | 1381 | |
| 978 | 1382 | // Construct TPI and IPI stream contents. |
| 979 | 1383 | ScopedTimer T2(TpiStreamLayoutTimer); |
| 980 | if (Config->DebugGHashes) { | |
| 981 | addTypeInfo(Builder.getTpiBuilder(), GlobalTypeTable); | |
| 982 | addTypeInfo(Builder.getIpiBuilder(), GlobalIDTable); | |
| 983 | } else { | |
| 984 | addTypeInfo(Builder.getTpiBuilder(), TypeTable); | |
| 985 | addTypeInfo(Builder.getIpiBuilder(), IDTable); | |
| 986 | } | |
| 1384 | addTypeInfo(Builder.getTpiBuilder(), getTypeTable()); | |
| 1385 | addTypeInfo(Builder.getIpiBuilder(), getIDTable()); | |
| 987 | 1386 | T2.stop(); |
| 988 | 1387 | |
| 989 | 1388 | ScopedTimer T3(GlobalsLayoutTimer); |
| ... | ... | @@ -999,10 +1398,10 @@ void PDBLinker::addObjectsToPDB() { |
| 999 | 1398 | |
| 1000 | 1399 | if (!Publics.empty()) { |
| 1001 | 1400 | // Sort the public symbols and add them to the stream. |
| 1002 | std::sort(Publics.begin(), Publics.end(), | |
| 1003 | [](const PublicSym32 &L, const PublicSym32 &R) { | |
| 1004 | return L.Name < R.Name; | |
| 1005 | }); | |
| 1401 | sort(parallel::par, Publics.begin(), Publics.end(), | |
| 1402 | [](const PublicSym32 &L, const PublicSym32 &R) { | |
| 1403 | return L.Name < R.Name; | |
| 1404 | }); | |
| 1006 | 1405 | for (const PublicSym32 &Pub : Publics) |
| 1007 | 1406 | GsiBuilder.addPublicSymbol(Pub); |
| 1008 | 1407 | } |
| ... | ... | @@ -1037,6 +1436,32 @@ static codeview::CPUType toCodeViewMachine(COFF::MachineTypes Machine) { |
| 1037 | 1436 | } |
| 1038 | 1437 | } |
| 1039 | 1438 | |
| 1439 | // Mimic MSVC which surrounds arguments containing whitespace with quotes. | |
| 1440 | // Double double-quotes are handled, so that the resulting string can be | |
| 1441 | // executed again on the cmd-line. | |
| 1442 | static std::string quote(ArrayRef<StringRef> Args) { | |
| 1443 | std::string R; | |
| 1444 | R.reserve(256); | |
| 1445 | for (StringRef A : Args) { | |
| 1446 | if (!R.empty()) | |
| 1447 | R.push_back(' '); | |
| 1448 | bool HasWS = A.find(' ') != StringRef::npos; | |
| 1449 | bool HasQ = A.find('"') != StringRef::npos; | |
| 1450 | if (HasWS || HasQ) | |
| 1451 | R.push_back('"'); | |
| 1452 | if (HasQ) { | |
| 1453 | SmallVector<StringRef, 4> S; | |
| 1454 | A.split(S, '"'); | |
| 1455 | R.append(join(S, "\"\"")); | |
| 1456 | } else { | |
| 1457 | R.append(A); | |
| 1458 | } | |
| 1459 | if (HasWS || HasQ) | |
| 1460 | R.push_back('"'); | |
| 1461 | } | |
| 1462 | return R; | |
| 1463 | } | |
| 1464 | ||
| 1040 | 1465 | static void addCommonLinkerModuleSymbols(StringRef Path, |
| 1041 | 1466 | pdb::DbiModuleDescriptorBuilder &Mod, |
| 1042 | 1467 | BumpPtrAllocator &Allocator) { |
| ... | ... | @@ -1072,14 +1497,17 @@ static void addCommonLinkerModuleSymbols(StringRef Path, |
| 1072 | 1497 | CS.setLanguage(SourceLanguage::Link); |
| 1073 | 1498 | |
| 1074 | 1499 | ArrayRef<StringRef> Args = makeArrayRef(Config->Argv).drop_front(); |
| 1075 | std::string ArgStr = llvm::join(Args, " "); | |
| 1500 | std::string ArgStr = quote(Args); | |
| 1076 | 1501 | EBS.Fields.push_back("cwd"); |
| 1077 | 1502 | SmallString<64> cwd; |
| 1078 | sys::fs::current_path(cwd); | |
| 1503 | if (Config->PDBSourcePath.empty()) | |
| 1504 | sys::fs::current_path(cwd); | |
| 1505 | else | |
| 1506 | cwd = Config->PDBSourcePath; | |
| 1079 | 1507 | EBS.Fields.push_back(cwd); |
| 1080 | 1508 | EBS.Fields.push_back("exe"); |
| 1081 | 1509 | SmallString<64> exe = Config->Argv[0]; |
| 1082 | llvm::sys::fs::make_absolute(exe); | |
| 1510 | pdbMakeAbsolute(exe); | |
| 1083 | 1511 | EBS.Fields.push_back(exe); |
| 1084 | 1512 | EBS.Fields.push_back("pdb"); |
| 1085 | 1513 | EBS.Fields.push_back(Path); |
| ... | ... | @@ -1111,7 +1539,7 @@ static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod, |
| 1111 | 1539 | void coff::createPDB(SymbolTable *Symtab, |
| 1112 | 1540 | ArrayRef<OutputSection *> OutputSections, |
| 1113 | 1541 | ArrayRef<uint8_t> SectionTable, |
| 1114 | const llvm::codeview::DebugInfo &BuildId) { | |
| 1542 | llvm::codeview::DebugInfo *BuildId) { | |
| 1115 | 1543 | ScopedTimer T1(TotalPdbLinkTimer); |
| 1116 | 1544 | PDBLinker PDB(Symtab); |
| 1117 | 1545 | |
| ... | ... | @@ -1121,12 +1549,19 @@ void coff::createPDB(SymbolTable *Symtab, |
| 1121 | 1549 | PDB.addNatvisFiles(); |
| 1122 | 1550 | |
| 1123 | 1551 | ScopedTimer T2(DiskCommitTimer); |
| 1124 | PDB.commit(); | |
| 1552 | codeview::GUID Guid; | |
| 1553 | PDB.commit(&Guid); | |
| 1554 | memcpy(&BuildId->PDB70.Signature, &Guid, 16); | |
| 1125 | 1555 | } |
| 1126 | 1556 | |
| 1127 | void PDBLinker::initialize(const llvm::codeview::DebugInfo &BuildId) { | |
| 1557 | void PDBLinker::initialize(llvm::codeview::DebugInfo *BuildId) { | |
| 1128 | 1558 | ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize |
| 1129 | 1559 | |
| 1560 | BuildId->Signature.CVSignature = OMF::Signature::PDB70; | |
| 1561 | // Signature is set to a hash of the PDB contents when the PDB is done. | |
| 1562 | memset(BuildId->PDB70.Signature, 0, 16); | |
| 1563 | BuildId->PDB70.Age = 1; | |
| 1564 | ||
| 1130 | 1565 | // Create streams in MSF for predefined streams, namely |
| 1131 | 1566 | // PDB, TPI, DBI and IPI. |
| 1132 | 1567 | for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I) |
| ... | ... | @@ -1134,15 +1569,12 @@ void PDBLinker::initialize(const llvm::codeview::DebugInfo &BuildId) { |
| 1134 | 1569 | |
| 1135 | 1570 | // Add an Info stream. |
| 1136 | 1571 | auto &InfoBuilder = Builder.getInfoBuilder(); |
| 1137 | GUID uuid; | |
| 1138 | memcpy(&uuid, &BuildId.PDB70.Signature, sizeof(uuid)); | |
| 1139 | InfoBuilder.setAge(BuildId.PDB70.Age); | |
| 1140 | InfoBuilder.setGuid(uuid); | |
| 1141 | 1572 | InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70); |
| 1573 | InfoBuilder.setHashPDBContentsToGUID(true); | |
| 1142 | 1574 | |
| 1143 | 1575 | // Add an empty DBI stream. |
| 1144 | 1576 | pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); |
| 1145 | DbiBuilder.setAge(BuildId.PDB70.Age); | |
| 1577 | DbiBuilder.setAge(BuildId->PDB70.Age); | |
| 1146 | 1578 | DbiBuilder.setVersionHeader(pdb::PdbDbiV70); |
| 1147 | 1579 | DbiBuilder.setMachineType(Config->Machine); |
| 1148 | 1580 | // Technically we are not link.exe 14.11, but there are known cases where |
| ... | ... | @@ -1157,8 +1589,7 @@ void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections, |
| 1157 | 1589 | // It's not entirely clear what this is, but the * Linker * module uses it. |
| 1158 | 1590 | pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder(); |
| 1159 | 1591 | NativePath = Config->PDBPath; |
| 1160 | sys::fs::make_absolute(NativePath); | |
| 1161 | sys::path::native(NativePath, sys::path::Style::windows); | |
| 1592 | pdbMakeAbsolute(NativePath); | |
| 1162 | 1593 | uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath); |
| 1163 | 1594 | auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *")); |
| 1164 | 1595 | LinkerModule.setPdbFilePathNI(PdbFilePathNI); |
| ... | ... | @@ -1167,7 +1598,7 @@ void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections, |
| 1167 | 1598 | // Add section contributions. They must be ordered by ascending RVA. |
| 1168 | 1599 | for (OutputSection *OS : OutputSections) { |
| 1169 | 1600 | addLinkerModuleSectionSymbol(LinkerModule, *OS, Alloc); |
| 1170 | for (Chunk *C : OS->getChunks()) { | |
| 1601 | for (Chunk *C : OS->Chunks) { | |
| 1171 | 1602 | pdb::SectionContrib SC = |
| 1172 | 1603 | createSectionContrib(C, LinkerModule.getModuleIndex()); |
| 1173 | 1604 | Builder.getDbiBuilder().addSectionContrib(SC); |
| ... | ... | @@ -1186,9 +1617,9 @@ void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections, |
| 1186 | 1617 | DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable)); |
| 1187 | 1618 | } |
| 1188 | 1619 | |
| 1189 | void PDBLinker::commit() { | |
| 1620 | void PDBLinker::commit(codeview::GUID *Guid) { | |
| 1190 | 1621 | // Write to a file. |
| 1191 | ExitOnErr(Builder.commit(Config->PDBPath)); | |
| 1622 | ExitOnErr(Builder.commit(Config->PDBPath, Guid)); | |
| 1192 | 1623 | } |
| 1193 | 1624 | |
| 1194 | 1625 | static Expected<StringRef> |
| ... | ... | @@ -1315,20 +1746,26 @@ std::pair<StringRef, uint32_t> coff::getFileLine(const SectionChunk *C, |
| 1315 | 1746 | if (!findLineTable(C, Addr, CVStrTab, Checksums, Lines, OffsetInLinetable)) |
| 1316 | 1747 | return {"", 0}; |
| 1317 | 1748 | |
| 1318 | uint32_t NameIndex; | |
| 1319 | uint32_t LineNumber; | |
| 1749 | Optional<uint32_t> NameIndex; | |
| 1750 | Optional<uint32_t> LineNumber; | |
| 1320 | 1751 | for (LineColumnEntry &Entry : Lines) { |
| 1321 | 1752 | for (const LineNumberEntry &LN : Entry.LineNumbers) { |
| 1753 | LineInfo LI(LN.Flags); | |
| 1322 | 1754 | if (LN.Offset > OffsetInLinetable) { |
| 1755 | if (!NameIndex) { | |
| 1756 | NameIndex = Entry.NameIndex; | |
| 1757 | LineNumber = LI.getStartLine(); | |
| 1758 | } | |
| 1323 | 1759 | StringRef Filename = |
| 1324 | ExitOnErr(getFileName(CVStrTab, Checksums, NameIndex)); | |
| 1325 | return {Filename, LineNumber}; | |
| 1760 | ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex)); | |
| 1761 | return {Filename, *LineNumber}; | |
| 1326 | 1762 | } |
| 1327 | LineInfo LI(LN.Flags); | |
| 1328 | 1763 | NameIndex = Entry.NameIndex; |
| 1329 | 1764 | LineNumber = LI.getStartLine(); |
| 1330 | 1765 | } |
| 1331 | 1766 | } |
| 1332 | StringRef Filename = ExitOnErr(getFileName(CVStrTab, Checksums, NameIndex)); | |
| 1333 | return {Filename, LineNumber}; | |
| 1767 | if (!NameIndex) | |
| 1768 | return {"", 0}; | |
| 1769 | StringRef Filename = ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex)); | |
| 1770 | return {Filename, *LineNumber}; | |
| 1334 | 1771 | } |
deps/lld/COFF/PDB.h+1-1| ... | ... | @@ -28,7 +28,7 @@ class SymbolTable; |
| 28 | 28 | void createPDB(SymbolTable *Symtab, |
| 29 | 29 | llvm::ArrayRef<OutputSection *> OutputSections, |
| 30 | 30 | llvm::ArrayRef<uint8_t> SectionTable, |
| 31 | const llvm::codeview::DebugInfo &BuildId); | |
| 31 | llvm::codeview::DebugInfo *BuildId); | |
| 32 | 32 | |
| 33 | 33 | std::pair<llvm::StringRef, uint32_t> getFileLine(const SectionChunk *C, |
| 34 | 34 | uint32_t Addr); |
deps/lld/COFF/SymbolTable.cpp+136-49| ... | ... | @@ -60,16 +60,16 @@ void SymbolTable::addFile(InputFile *File) { |
| 60 | 60 | } |
| 61 | 61 | |
| 62 | 62 | static void errorOrWarn(const Twine &S) { |
| 63 | if (Config->Force) | |
| 63 | if (Config->ForceUnresolved) | |
| 64 | 64 | warn(S); |
| 65 | 65 | else |
| 66 | 66 | error(S); |
| 67 | 67 | } |
| 68 | 68 | |
| 69 | // Returns the name of the symbol in SC whose value is <= Addr that is closest | |
| 70 | // to Addr. This is generally the name of the global variable or function whose | |
| 71 | // definition contains Addr. | |
| 72 | static StringRef getSymbolName(SectionChunk *SC, uint32_t Addr) { | |
| 69 | // Returns the symbol in SC whose value is <= Addr that is closest to Addr. | |
| 70 | // This is generally the global variable or function whose definition contains | |
| 71 | // Addr. | |
| 72 | static Symbol *getSymbol(SectionChunk *SC, uint32_t Addr) { | |
| 73 | 73 | DefinedRegular *Candidate = nullptr; |
| 74 | 74 | |
| 75 | 75 | for (Symbol *S : SC->File->getSymbols()) { |
| ... | ... | @@ -81,14 +81,12 @@ static StringRef getSymbolName(SectionChunk *SC, uint32_t Addr) { |
| 81 | 81 | Candidate = D; |
| 82 | 82 | } |
| 83 | 83 | |
| 84 | if (!Candidate) | |
| 85 | return ""; | |
| 86 | return Candidate->getName(); | |
| 84 | return Candidate; | |
| 87 | 85 | } |
| 88 | 86 | |
| 89 | static std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex) { | |
| 87 | std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex) { | |
| 90 | 88 | struct Location { |
| 91 | StringRef SymName; | |
| 89 | Symbol *Sym; | |
| 92 | 90 | std::pair<StringRef, uint32_t> FileLine; |
| 93 | 91 | }; |
| 94 | 92 | std::vector<Location> Locations; |
| ... | ... | @@ -102,14 +100,14 @@ static std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex) { |
| 102 | 100 | continue; |
| 103 | 101 | std::pair<StringRef, uint32_t> FileLine = |
| 104 | 102 | getFileLine(SC, R.VirtualAddress); |
| 105 | StringRef SymName = getSymbolName(SC, R.VirtualAddress); | |
| 106 | if (!FileLine.first.empty() || !SymName.empty()) | |
| 107 | Locations.push_back({SymName, FileLine}); | |
| 103 | Symbol *Sym = getSymbol(SC, R.VirtualAddress); | |
| 104 | if (!FileLine.first.empty() || Sym) | |
| 105 | Locations.push_back({Sym, FileLine}); | |
| 108 | 106 | } |
| 109 | 107 | } |
| 110 | 108 | |
| 111 | 109 | if (Locations.empty()) |
| 112 | return "\n>>> referenced by " + toString(File) + "\n"; | |
| 110 | return "\n>>> referenced by " + toString(File); | |
| 113 | 111 | |
| 114 | 112 | std::string Out; |
| 115 | 113 | llvm::raw_string_ostream OS(Out); |
| ... | ... | @@ -119,13 +117,87 @@ static std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex) { |
| 119 | 117 | OS << Loc.FileLine.first << ":" << Loc.FileLine.second |
| 120 | 118 | << "\n>>> "; |
| 121 | 119 | OS << toString(File); |
| 122 | if (!Loc.SymName.empty()) | |
| 123 | OS << ":(" << Loc.SymName << ')'; | |
| 120 | if (Loc.Sym) | |
| 121 | OS << ":(" << toString(*Loc.Sym) << ')'; | |
| 124 | 122 | } |
| 125 | OS << '\n'; | |
| 126 | 123 | return OS.str(); |
| 127 | 124 | } |
| 128 | 125 | |
| 126 | void SymbolTable::loadMinGWAutomaticImports() { | |
| 127 | for (auto &I : SymMap) { | |
| 128 | Symbol *Sym = I.second; | |
| 129 | auto *Undef = dyn_cast<Undefined>(Sym); | |
| 130 | if (!Undef) | |
| 131 | continue; | |
| 132 | if (!Sym->IsUsedInRegularObj) | |
| 133 | continue; | |
| 134 | ||
| 135 | StringRef Name = Undef->getName(); | |
| 136 | ||
| 137 | if (Name.startswith("__imp_")) | |
| 138 | continue; | |
| 139 | // If we have an undefined symbol, but we have a Lazy representing a | |
| 140 | // symbol we could load from file, make sure to load that. | |
| 141 | Lazy *L = dyn_cast_or_null<Lazy>(find(("__imp_" + Name).str())); | |
| 142 | if (!L || L->PendingArchiveLoad) | |
| 143 | continue; | |
| 144 | ||
| 145 | log("Loading lazy " + L->getName() + " from " + L->File->getName() + | |
| 146 | " for automatic import"); | |
| 147 | L->PendingArchiveLoad = true; | |
| 148 | L->File->addMember(&L->Sym); | |
| 149 | } | |
| 150 | } | |
| 151 | ||
| 152 | bool SymbolTable::handleMinGWAutomaticImport(Symbol *Sym, StringRef Name) { | |
| 153 | if (Name.startswith("__imp_")) | |
| 154 | return false; | |
| 155 | Defined *Imp = dyn_cast_or_null<Defined>(find(("__imp_" + Name).str())); | |
| 156 | if (!Imp) | |
| 157 | return false; | |
| 158 | ||
| 159 | // Replace the reference directly to a variable with a reference | |
| 160 | // to the import address table instead. This obviously isn't right, | |
| 161 | // but we mark the symbol as IsRuntimePseudoReloc, and a later pass | |
| 162 | // will add runtime pseudo relocations for every relocation against | |
| 163 | // this Symbol. The runtime pseudo relocation framework expects the | |
| 164 | // reference itself to point at the IAT entry. | |
| 165 | size_t ImpSize = 0; | |
| 166 | if (isa<DefinedImportData>(Imp)) { | |
| 167 | log("Automatically importing " + Name + " from " + | |
| 168 | cast<DefinedImportData>(Imp)->getDLLName()); | |
| 169 | ImpSize = sizeof(DefinedImportData); | |
| 170 | } else if (isa<DefinedRegular>(Imp)) { | |
| 171 | log("Automatically importing " + Name + " from " + | |
| 172 | toString(cast<DefinedRegular>(Imp)->File)); | |
| 173 | ImpSize = sizeof(DefinedRegular); | |
| 174 | } else { | |
| 175 | warn("unable to automatically import " + Name + " from " + Imp->getName() + | |
| 176 | " from " + toString(cast<DefinedRegular>(Imp)->File) + | |
| 177 | "; unexpected symbol type"); | |
| 178 | return false; | |
| 179 | } | |
| 180 | Sym->replaceKeepingName(Imp, ImpSize); | |
| 181 | Sym->IsRuntimePseudoReloc = true; | |
| 182 | ||
| 183 | // There may exist symbols named .refptr.<name> which only consist | |
| 184 | // of a single pointer to <name>. If it turns out <name> is | |
| 185 | // automatically imported, we don't need to keep the .refptr.<name> | |
| 186 | // pointer at all, but redirect all accesses to it to the IAT entry | |
| 187 | // for __imp_<name> instead, and drop the whole .refptr.<name> chunk. | |
| 188 | DefinedRegular *Refptr = | |
| 189 | dyn_cast_or_null<DefinedRegular>(find((".refptr." + Name).str())); | |
| 190 | if (Refptr && Refptr->getChunk()->getSize() == Config->Wordsize) { | |
| 191 | SectionChunk *SC = dyn_cast_or_null<SectionChunk>(Refptr->getChunk()); | |
| 192 | if (SC && SC->Relocs.size() == 1 && *SC->symbols().begin() == Sym) { | |
| 193 | log("Replacing .refptr." + Name + " with " + Imp->getName()); | |
| 194 | Refptr->getChunk()->Live = false; | |
| 195 | Refptr->replaceKeepingName(Imp, ImpSize); | |
| 196 | } | |
| 197 | } | |
| 198 | return true; | |
| 199 | } | |
| 200 | ||
| 129 | 201 | void SymbolTable::reportRemainingUndefines() { |
| 130 | 202 | SmallPtrSet<Symbol *, 8> Undefs; |
| 131 | 203 | DenseMap<Symbol *, Symbol *> LocalImports; |
| ... | ... | @@ -169,9 +241,17 @@ void SymbolTable::reportRemainingUndefines() { |
| 169 | 241 | } |
| 170 | 242 | } |
| 171 | 243 | |
| 244 | // We don't want to report missing Microsoft precompiled headers symbols. | |
| 245 | // A proper message will be emitted instead in PDBLinker::aquirePrecompObj | |
| 246 | if (Name.contains("_PchSym_")) | |
| 247 | continue; | |
| 248 | ||
| 249 | if (Config->MinGW && handleMinGWAutomaticImport(Sym, Name)) | |
| 250 | continue; | |
| 251 | ||
| 172 | 252 | // Remaining undefined symbols are not fatal if /force is specified. |
| 173 | 253 | // They are replaced with dummy defined symbols. |
| 174 | if (Config->Force) | |
| 254 | if (Config->ForceUnresolved) | |
| 175 | 255 | replaceSymbol<DefinedAbsolute>(Sym, Name, 0); |
| 176 | 256 | Undefs.insert(Sym); |
| 177 | 257 | } |
| ... | ... | @@ -181,10 +261,10 @@ void SymbolTable::reportRemainingUndefines() { |
| 181 | 261 | |
| 182 | 262 | for (Symbol *B : Config->GCRoot) { |
| 183 | 263 | if (Undefs.count(B)) |
| 184 | errorOrWarn("<root>: undefined symbol: " + B->getName()); | |
| 264 | errorOrWarn("<root>: undefined symbol: " + toString(*B)); | |
| 185 | 265 | if (Config->WarnLocallyDefinedImported) |
| 186 | 266 | if (Symbol *Imp = LocalImports.lookup(B)) |
| 187 | warn("<root>: locally defined symbol imported: " + Imp->getName() + | |
| 267 | warn("<root>: locally defined symbol imported: " + toString(*Imp) + | |
| 188 | 268 | " (defined in " + toString(Imp->getFile()) + ") [LNK4217]"); |
| 189 | 269 | } |
| 190 | 270 | |
| ... | ... | @@ -195,34 +275,41 @@ void SymbolTable::reportRemainingUndefines() { |
| 195 | 275 | if (!Sym) |
| 196 | 276 | continue; |
| 197 | 277 | if (Undefs.count(Sym)) |
| 198 | errorOrWarn("undefined symbol: " + Sym->getName() + | |
| 278 | errorOrWarn("undefined symbol: " + toString(*Sym) + | |
| 199 | 279 | getSymbolLocations(File, SymIndex)); |
| 200 | 280 | if (Config->WarnLocallyDefinedImported) |
| 201 | 281 | if (Symbol *Imp = LocalImports.lookup(Sym)) |
| 202 | warn(toString(File) + ": locally defined symbol imported: " + | |
| 203 | Imp->getName() + " (defined in " + toString(Imp->getFile()) + | |
| 204 | ") [LNK4217]"); | |
| 282 | warn(toString(File) + | |
| 283 | ": locally defined symbol imported: " + toString(*Imp) + | |
| 284 | " (defined in " + toString(Imp->getFile()) + ") [LNK4217]"); | |
| 205 | 285 | } |
| 206 | 286 | } |
| 207 | 287 | } |
| 208 | 288 | |
| 209 | 289 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) { |
| 290 | bool Inserted = false; | |
| 210 | 291 | Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; |
| 211 | if (Sym) | |
| 212 | return {Sym, false}; | |
| 213 | Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); | |
| 214 | Sym->IsUsedInRegularObj = false; | |
| 215 | Sym->PendingArchiveLoad = false; | |
| 216 | return {Sym, true}; | |
| 292 | if (!Sym) { | |
| 293 | Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); | |
| 294 | Sym->IsUsedInRegularObj = false; | |
| 295 | Sym->PendingArchiveLoad = false; | |
| 296 | Inserted = true; | |
| 297 | } | |
| 298 | return {Sym, Inserted}; | |
| 299 | } | |
| 300 | ||
| 301 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) { | |
| 302 | std::pair<Symbol *, bool> Result = insert(Name); | |
| 303 | if (!File || !isa<BitcodeFile>(File)) | |
| 304 | Result.first->IsUsedInRegularObj = true; | |
| 305 | return Result; | |
| 217 | 306 | } |
| 218 | 307 | |
| 219 | 308 | Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F, |
| 220 | 309 | bool IsWeakAlias) { |
| 221 | 310 | Symbol *S; |
| 222 | 311 | bool WasInserted; |
| 223 | std::tie(S, WasInserted) = insert(Name); | |
| 224 | if (!F || !isa<BitcodeFile>(F)) | |
| 225 | S->IsUsedInRegularObj = true; | |
| 312 | std::tie(S, WasInserted) = insert(Name, F); | |
| 226 | 313 | if (WasInserted || (isa<Lazy>(S) && IsWeakAlias)) { |
| 227 | 314 | replaceSymbol<Undefined>(S, Name); |
| 228 | 315 | return S; |
| ... | ... | @@ -253,14 +340,20 @@ void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) { |
| 253 | 340 | } |
| 254 | 341 | |
| 255 | 342 | void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) { |
| 256 | error("duplicate symbol: " + toString(*Existing) + " in " + | |
| 257 | toString(Existing->getFile()) + " and in " + toString(NewFile)); | |
| 343 | std::string Msg = "duplicate symbol: " + toString(*Existing) + " in " + | |
| 344 | toString(Existing->getFile()) + " and in " + | |
| 345 | toString(NewFile); | |
| 346 | ||
| 347 | if (Config->ForceMultiple) | |
| 348 | warn(Msg); | |
| 349 | else | |
| 350 | error(Msg); | |
| 258 | 351 | } |
| 259 | 352 | |
| 260 | 353 | Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) { |
| 261 | 354 | Symbol *S; |
| 262 | 355 | bool WasInserted; |
| 263 | std::tie(S, WasInserted) = insert(N); | |
| 356 | std::tie(S, WasInserted) = insert(N, nullptr); | |
| 264 | 357 | S->IsUsedInRegularObj = true; |
| 265 | 358 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) |
| 266 | 359 | replaceSymbol<DefinedAbsolute>(S, N, Sym); |
| ... | ... | @@ -272,7 +365,7 @@ Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) { |
| 272 | 365 | Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) { |
| 273 | 366 | Symbol *S; |
| 274 | 367 | bool WasInserted; |
| 275 | std::tie(S, WasInserted) = insert(N); | |
| 368 | std::tie(S, WasInserted) = insert(N, nullptr); | |
| 276 | 369 | S->IsUsedInRegularObj = true; |
| 277 | 370 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) |
| 278 | 371 | replaceSymbol<DefinedAbsolute>(S, N, VA); |
| ... | ... | @@ -284,7 +377,7 @@ Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) { |
| 284 | 377 | Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) { |
| 285 | 378 | Symbol *S; |
| 286 | 379 | bool WasInserted; |
| 287 | std::tie(S, WasInserted) = insert(N); | |
| 380 | std::tie(S, WasInserted) = insert(N, nullptr); | |
| 288 | 381 | S->IsUsedInRegularObj = true; |
| 289 | 382 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) |
| 290 | 383 | replaceSymbol<DefinedSynthetic>(S, N, C); |
| ... | ... | @@ -298,9 +391,7 @@ Symbol *SymbolTable::addRegular(InputFile *F, StringRef N, |
| 298 | 391 | SectionChunk *C) { |
| 299 | 392 | Symbol *S; |
| 300 | 393 | bool WasInserted; |
| 301 | std::tie(S, WasInserted) = insert(N); | |
| 302 | if (!isa<BitcodeFile>(F)) | |
| 303 | S->IsUsedInRegularObj = true; | |
| 394 | std::tie(S, WasInserted) = insert(N, F); | |
| 304 | 395 | if (WasInserted || !isa<DefinedRegular>(S)) |
| 305 | 396 | replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ false, |
| 306 | 397 | /*IsExternal*/ true, Sym, C); |
| ... | ... | @@ -314,9 +405,7 @@ SymbolTable::addComdat(InputFile *F, StringRef N, |
| 314 | 405 | const coff_symbol_generic *Sym) { |
| 315 | 406 | Symbol *S; |
| 316 | 407 | bool WasInserted; |
| 317 | std::tie(S, WasInserted) = insert(N); | |
| 318 | if (!isa<BitcodeFile>(F)) | |
| 319 | S->IsUsedInRegularObj = true; | |
| 408 | std::tie(S, WasInserted) = insert(N, F); | |
| 320 | 409 | if (WasInserted || !isa<DefinedRegular>(S)) { |
| 321 | 410 | replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ true, |
| 322 | 411 | /*IsExternal*/ true, Sym, nullptr); |
| ... | ... | @@ -331,9 +420,7 @@ Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size, |
| 331 | 420 | const coff_symbol_generic *Sym, CommonChunk *C) { |
| 332 | 421 | Symbol *S; |
| 333 | 422 | bool WasInserted; |
| 334 | std::tie(S, WasInserted) = insert(N); | |
| 335 | if (!isa<BitcodeFile>(F)) | |
| 336 | S->IsUsedInRegularObj = true; | |
| 423 | std::tie(S, WasInserted) = insert(N, F); | |
| 337 | 424 | if (WasInserted || !isa<DefinedCOFF>(S)) |
| 338 | 425 | replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C); |
| 339 | 426 | else if (auto *DC = dyn_cast<DefinedCommon>(S)) |
| ... | ... | @@ -345,7 +432,7 @@ Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size, |
| 345 | 432 | Symbol *SymbolTable::addImportData(StringRef N, ImportFile *F) { |
| 346 | 433 | Symbol *S; |
| 347 | 434 | bool WasInserted; |
| 348 | std::tie(S, WasInserted) = insert(N); | |
| 435 | std::tie(S, WasInserted) = insert(N, nullptr); | |
| 349 | 436 | S->IsUsedInRegularObj = true; |
| 350 | 437 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) { |
| 351 | 438 | replaceSymbol<DefinedImportData>(S, N, F); |
| ... | ... | @@ -360,7 +447,7 @@ Symbol *SymbolTable::addImportThunk(StringRef Name, DefinedImportData *ID, |
| 360 | 447 | uint16_t Machine) { |
| 361 | 448 | Symbol *S; |
| 362 | 449 | bool WasInserted; |
| 363 | std::tie(S, WasInserted) = insert(Name); | |
| 450 | std::tie(S, WasInserted) = insert(Name, nullptr); | |
| 364 | 451 | S->IsUsedInRegularObj = true; |
| 365 | 452 | if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) { |
| 366 | 453 | replaceSymbol<DefinedImportThunk>(S, Name, ID, Machine); |
deps/lld/COFF/SymbolTable.h+8| ... | ... | @@ -54,6 +54,9 @@ public: |
| 54 | 54 | // symbols. |
| 55 | 55 | void reportRemainingUndefines(); |
| 56 | 56 | |
| 57 | void loadMinGWAutomaticImports(); | |
| 58 | bool handleMinGWAutomaticImport(Symbol *Sym, StringRef Name); | |
| 59 | ||
| 57 | 60 | // Returns a list of chunks of selected symbols. |
| 58 | 61 | std::vector<Chunk *> getChunks(); |
| 59 | 62 | |
| ... | ... | @@ -108,7 +111,10 @@ public: |
| 108 | 111 | } |
| 109 | 112 | |
| 110 | 113 | private: |
| 114 | /// Inserts symbol if not already present. | |
| 111 | 115 | std::pair<Symbol *, bool> insert(StringRef Name); |
| 116 | /// Same as insert(Name), but also sets IsUsedInRegularObj. | |
| 117 | std::pair<Symbol *, bool> insert(StringRef Name, InputFile *F); | |
| 112 | 118 | StringRef findByPrefix(StringRef Prefix); |
| 113 | 119 | |
| 114 | 120 | llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> SymMap; |
| ... | ... | @@ -117,6 +123,8 @@ private: |
| 117 | 123 | |
| 118 | 124 | extern SymbolTable *Symtab; |
| 119 | 125 | |
| 126 | std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex); | |
| 127 | ||
| 120 | 128 | } // namespace coff |
| 121 | 129 | } // namespace lld |
| 122 | 130 |
deps/lld/COFF/Symbols.cpp+8-1| ... | ... | @@ -54,7 +54,7 @@ InputFile *Symbol::getFile() { |
| 54 | 54 | |
| 55 | 55 | bool Symbol::isLive() const { |
| 56 | 56 | if (auto *R = dyn_cast<DefinedRegular>(this)) |
| 57 | return R->getChunk()->isLive(); | |
| 57 | return R->getChunk()->Live; | |
| 58 | 58 | if (auto *Imp = dyn_cast<DefinedImportData>(this)) |
| 59 | 59 | return Imp->File->Live; |
| 60 | 60 | if (auto *Imp = dyn_cast<DefinedImportThunk>(this)) |
| ... | ... | @@ -63,6 +63,13 @@ bool Symbol::isLive() const { |
| 63 | 63 | return true; |
| 64 | 64 | } |
| 65 | 65 | |
| 66 | // MinGW specific. | |
| 67 | void Symbol::replaceKeepingName(Symbol *Other, size_t Size) { | |
| 68 | StringRef OrigName = Name; | |
| 69 | memcpy(this, Other, Size); | |
| 70 | Name = OrigName; | |
| 71 | } | |
| 72 | ||
| 66 | 73 | COFFSymbolRef DefinedCOFF::getCOFFSymbol() { |
| 67 | 74 | size_t SymSize = cast<ObjFile>(File)->getCOFFObj()->getSymbolTableEntrySize(); |
| 68 | 75 | if (SymSize == sizeof(coff_symbol16)) |
deps/lld/COFF/Symbols.h+9-5| ... | ... | @@ -39,9 +39,9 @@ class Symbol { |
| 39 | 39 | public: |
| 40 | 40 | enum Kind { |
| 41 | 41 | // The order of these is significant. We start with the regular defined |
| 42 | // symbols as those are the most prevelant and the zero tag is the cheapest | |
| 42 | // symbols as those are the most prevalent and the zero tag is the cheapest | |
| 43 | 43 | // to set. Among the defined kinds, the lower the kind is preferred over |
| 44 | // the higher kind when testing wether one symbol should take precedence | |
| 44 | // the higher kind when testing whether one symbol should take precedence | |
| 45 | 45 | // over another. |
| 46 | 46 | DefinedRegularKind = 0, |
| 47 | 47 | DefinedCommonKind, |
| ... | ... | @@ -66,6 +66,8 @@ public: |
| 66 | 66 | // Returns the symbol name. |
| 67 | 67 | StringRef getName(); |
| 68 | 68 | |
| 69 | void replaceKeepingName(Symbol *Other, size_t Size); | |
| 70 | ||
| 69 | 71 | // Returns the file from which this symbol was created. |
| 70 | 72 | InputFile *getFile(); |
| 71 | 73 | |
| ... | ... | @@ -78,7 +80,7 @@ protected: |
| 78 | 80 | explicit Symbol(Kind K, StringRef N = "") |
| 79 | 81 | : SymbolKind(K), IsExternal(true), IsCOMDAT(false), |
| 80 | 82 | WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false), |
| 81 | Name(N) {} | |
| 83 | IsRuntimePseudoReloc(false), Name(N) {} | |
| 82 | 84 | |
| 83 | 85 | const unsigned SymbolKind : 8; |
| 84 | 86 | unsigned IsExternal : 1; |
| ... | ... | @@ -102,6 +104,8 @@ public: |
| 102 | 104 | /// True if we've already added this symbol to the list of GC roots. |
| 103 | 105 | unsigned IsGCRoot : 1; |
| 104 | 106 | |
| 107 | unsigned IsRuntimePseudoReloc : 1; | |
| 108 | ||
| 105 | 109 | protected: |
| 106 | 110 | StringRef Name; |
| 107 | 111 | }; |
| ... | ... | @@ -331,8 +335,8 @@ private: |
| 331 | 335 | Chunk *Data; |
| 332 | 336 | }; |
| 333 | 337 | |
| 334 | // If you have a symbol "__imp_foo" in your object file, a symbol name | |
| 335 | // "foo" becomes automatically available as a pointer to "__imp_foo". | |
| 338 | // If you have a symbol "foo" in your object file, a symbol name | |
| 339 | // "__imp_foo" becomes automatically available as a pointer to "foo". | |
| 336 | 340 | // This class is for such automatically-created symbols. |
| 337 | 341 | // Yes, this is an odd feature. We didn't intend to implement that. |
| 338 | 342 | // This is here just for compatibility with MSVC. |
deps/lld/COFF/Writer.cpp+601-148| ... | ... | @@ -77,36 +77,38 @@ static const int SectorSize = 512; |
| 77 | 77 | static const int DOSStubSize = sizeof(dos_header) + sizeof(DOSProgram); |
| 78 | 78 | static_assert(DOSStubSize % 8 == 0, "DOSStub size must be multiple of 8"); |
| 79 | 79 | |
| 80 | static const int NumberfOfDataDirectory = 16; | |
| 80 | static const int NumberOfDataDirectory = 16; | |
| 81 | 81 | |
| 82 | 82 | namespace { |
| 83 | 83 | |
| 84 | 84 | class DebugDirectoryChunk : public Chunk { |
| 85 | 85 | public: |
| 86 | DebugDirectoryChunk(const std::vector<Chunk *> &R) : Records(R) {} | |
| 86 | DebugDirectoryChunk(const std::vector<Chunk *> &R, bool WriteRepro) | |
| 87 | : Records(R), WriteRepro(WriteRepro) {} | |
| 87 | 88 | |
| 88 | 89 | size_t getSize() const override { |
| 89 | return Records.size() * sizeof(debug_directory); | |
| 90 | return (Records.size() + int(WriteRepro)) * sizeof(debug_directory); | |
| 90 | 91 | } |
| 91 | 92 | |
| 92 | 93 | void writeTo(uint8_t *B) const override { |
| 93 | 94 | auto *D = reinterpret_cast<debug_directory *>(B + OutputSectionOff); |
| 94 | 95 | |
| 95 | 96 | for (const Chunk *Record : Records) { |
| 96 | D->Characteristics = 0; | |
| 97 | D->TimeDateStamp = 0; | |
| 98 | D->MajorVersion = 0; | |
| 99 | D->MinorVersion = 0; | |
| 100 | D->Type = COFF::IMAGE_DEBUG_TYPE_CODEVIEW; | |
| 101 | D->SizeOfData = Record->getSize(); | |
| 102 | D->AddressOfRawData = Record->getRVA(); | |
| 103 | 97 | OutputSection *OS = Record->getOutputSection(); |
| 104 | 98 | uint64_t Offs = OS->getFileOff() + (Record->getRVA() - OS->getRVA()); |
| 105 | D->PointerToRawData = Offs; | |
| 106 | ||
| 107 | TimeDateStamps.push_back(&D->TimeDateStamp); | |
| 99 | fillEntry(D, COFF::IMAGE_DEBUG_TYPE_CODEVIEW, Record->getSize(), | |
| 100 | Record->getRVA(), Offs); | |
| 108 | 101 | ++D; |
| 109 | 102 | } |
| 103 | ||
| 104 | if (WriteRepro) { | |
| 105 | // FIXME: The COFF spec allows either a 0-sized entry to just say | |
| 106 | // "the timestamp field is really a hash", or a 4-byte size field | |
| 107 | // followed by that many bytes containing a longer hash (with the | |
| 108 | // lowest 4 bytes usually being the timestamp in little-endian order). | |
| 109 | // Consider storing the full 8 bytes computed by xxHash64 here. | |
| 110 | fillEntry(D, COFF::IMAGE_DEBUG_TYPE_REPRO, 0, 0, 0); | |
| 111 | } | |
| 110 | 112 | } |
| 111 | 113 | |
| 112 | 114 | void setTimeDateStamp(uint32_t TimeDateStamp) { |
| ... | ... | @@ -115,8 +117,23 @@ public: |
| 115 | 117 | } |
| 116 | 118 | |
| 117 | 119 | private: |
| 120 | void fillEntry(debug_directory *D, COFF::DebugType DebugType, size_t Size, | |
| 121 | uint64_t RVA, uint64_t Offs) const { | |
| 122 | D->Characteristics = 0; | |
| 123 | D->TimeDateStamp = 0; | |
| 124 | D->MajorVersion = 0; | |
| 125 | D->MinorVersion = 0; | |
| 126 | D->Type = DebugType; | |
| 127 | D->SizeOfData = Size; | |
| 128 | D->AddressOfRawData = RVA; | |
| 129 | D->PointerToRawData = Offs; | |
| 130 | ||
| 131 | TimeDateStamps.push_back(&D->TimeDateStamp); | |
| 132 | } | |
| 133 | ||
| 118 | 134 | mutable std::vector<support::ulittle32_t *> TimeDateStamps; |
| 119 | 135 | const std::vector<Chunk *> &Records; |
| 136 | bool WriteRepro; | |
| 120 | 137 | }; |
| 121 | 138 | |
| 122 | 139 | class CVDebugRecordChunk : public Chunk { |
| ... | ... | @@ -150,14 +167,22 @@ private: |
| 150 | 167 | void createSections(); |
| 151 | 168 | void createMiscChunks(); |
| 152 | 169 | void createImportTables(); |
| 170 | void appendImportThunks(); | |
| 171 | void locateImportTables( | |
| 172 | std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map); | |
| 153 | 173 | void createExportTable(); |
| 154 | 174 | void mergeSections(); |
| 175 | void readRelocTargets(); | |
| 176 | void removeUnusedSections(); | |
| 155 | 177 | void assignAddresses(); |
| 178 | void finalizeAddresses(); | |
| 156 | 179 | void removeEmptySections(); |
| 157 | 180 | void createSymbolAndStringTable(); |
| 158 | 181 | void openFile(StringRef OutputPath); |
| 159 | 182 | template <typename PEHeaderTy> void writeHeader(); |
| 160 | 183 | void createSEHTable(); |
| 184 | void createRuntimePseudoRelocs(); | |
| 185 | void insertCtorDtorSymbols(); | |
| 161 | 186 | void createGuardCFTables(); |
| 162 | 187 | void markSymbolsForRVATable(ObjFile *File, |
| 163 | 188 | ArrayRef<SectionChunk *> SymIdxChunks, |
| ... | ... | @@ -168,6 +193,7 @@ private: |
| 168 | 193 | void writeSections(); |
| 169 | 194 | void writeBuildId(); |
| 170 | 195 | void sortExceptionTable(); |
| 196 | void sortCRTSectionChunks(std::vector<Chunk *> &Chunks); | |
| 171 | 197 | |
| 172 | 198 | llvm::Optional<coff_symbol16> createSymbol(Defined *D); |
| 173 | 199 | size_t addEntryToStringTable(StringRef Str); |
| ... | ... | @@ -184,6 +210,10 @@ private: |
| 184 | 210 | std::vector<char> Strtab; |
| 185 | 211 | std::vector<llvm::object::coff_symbol16> OutputSymtab; |
| 186 | 212 | IdataContents Idata; |
| 213 | Chunk *ImportTableStart = nullptr; | |
| 214 | uint64_t ImportTableSize = 0; | |
| 215 | Chunk *IATStart = nullptr; | |
| 216 | uint64_t IATSize = 0; | |
| 187 | 217 | DelayLoadContents DelayIdata; |
| 188 | 218 | EdataContents Edata; |
| 189 | 219 | bool SetNoSEHCharacteristic = false; |
| ... | ... | @@ -191,7 +221,6 @@ private: |
| 191 | 221 | DebugDirectoryChunk *DebugDirectory = nullptr; |
| 192 | 222 | std::vector<Chunk *> DebugRecords; |
| 193 | 223 | CVDebugRecordChunk *BuildId = nullptr; |
| 194 | Optional<codeview::DebugInfo> PreviousBuildId; | |
| 195 | 224 | ArrayRef<uint8_t> SectionTable; |
| 196 | 225 | |
| 197 | 226 | uint64_t FileSize; |
| ... | ... | @@ -209,6 +238,8 @@ private: |
| 209 | 238 | OutputSection *DidatSec; |
| 210 | 239 | OutputSection *RsrcSec; |
| 211 | 240 | OutputSection *RelocSec; |
| 241 | OutputSection *CtorsSec; | |
| 242 | OutputSection *DtorsSec; | |
| 212 | 243 | |
| 213 | 244 | // The first and last .pdata sections in the output file. |
| 214 | 245 | // |
| ... | ... | @@ -237,6 +268,11 @@ void OutputSection::addChunk(Chunk *C) { |
| 237 | 268 | C->setOutputSection(this); |
| 238 | 269 | } |
| 239 | 270 | |
| 271 | void OutputSection::insertChunkAtStart(Chunk *C) { | |
| 272 | Chunks.insert(Chunks.begin(), C); | |
| 273 | C->setOutputSection(this); | |
| 274 | } | |
| 275 | ||
| 240 | 276 | void OutputSection::setPermissions(uint32_t C) { |
| 241 | 277 | Header.Characteristics &= ~PermMask; |
| 242 | 278 | Header.Characteristics |= C; |
| ... | ... | @@ -267,77 +303,232 @@ void OutputSection::writeHeaderTo(uint8_t *Buf) { |
| 267 | 303 | } // namespace coff |
| 268 | 304 | } // namespace lld |
| 269 | 305 | |
| 270 | // PDBs are matched against executables using a build id which consists of three | |
| 271 | // components: | |
| 272 | // 1. A 16-bit GUID | |
| 273 | // 2. An age | |
| 274 | // 3. A time stamp. | |
| 275 | // | |
| 276 | // Debuggers and symbol servers match executables against debug info by checking | |
| 277 | // each of these components of the EXE/DLL against the corresponding value in | |
| 278 | // the PDB and failing a match if any of the components differ. In the case of | |
| 279 | // symbol servers, symbols are cached in a folder that is a function of the | |
| 280 | // GUID. As a result, in order to avoid symbol cache pollution where every | |
| 281 | // incremental build copies a new PDB to the symbol cache, we must try to re-use | |
| 282 | // the existing GUID if one exists, but bump the age. This way the match will | |
| 283 | // fail, so the symbol cache knows to use the new PDB, but the GUID matches, so | |
| 284 | // it overwrites the existing item in the symbol cache rather than making a new | |
| 285 | // one. | |
| 286 | static Optional<codeview::DebugInfo> loadExistingBuildId(StringRef Path) { | |
| 287 | // We don't need to incrementally update a previous build id if we're not | |
| 288 | // writing codeview debug info. | |
| 289 | if (!Config->Debug) | |
| 290 | return None; | |
| 306 | // Check whether the target address S is in range from a relocation | |
| 307 | // of type RelType at address P. | |
| 308 | static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) { | |
| 309 | if (Config->Machine == ARMNT) { | |
| 310 | int64_t Diff = AbsoluteDifference(S, P + 4) + Margin; | |
| 311 | switch (RelType) { | |
| 312 | case IMAGE_REL_ARM_BRANCH20T: | |
| 313 | return isInt<21>(Diff); | |
| 314 | case IMAGE_REL_ARM_BRANCH24T: | |
| 315 | case IMAGE_REL_ARM_BLX23T: | |
| 316 | return isInt<25>(Diff); | |
| 317 | default: | |
| 318 | return true; | |
| 319 | } | |
| 320 | } else if (Config->Machine == ARM64) { | |
| 321 | int64_t Diff = AbsoluteDifference(S, P) + Margin; | |
| 322 | switch (RelType) { | |
| 323 | case IMAGE_REL_ARM64_BRANCH26: | |
| 324 | return isInt<28>(Diff); | |
| 325 | case IMAGE_REL_ARM64_BRANCH19: | |
| 326 | return isInt<21>(Diff); | |
| 327 | case IMAGE_REL_ARM64_BRANCH14: | |
| 328 | return isInt<16>(Diff); | |
| 329 | default: | |
| 330 | return true; | |
| 331 | } | |
| 332 | } else { | |
| 333 | llvm_unreachable("Unexpected architecture"); | |
| 334 | } | |
| 335 | } | |
| 291 | 336 | |
| 292 | auto ExpectedBinary = llvm::object::createBinary(Path); | |
| 293 | if (!ExpectedBinary) { | |
| 294 | consumeError(ExpectedBinary.takeError()); | |
| 295 | return None; | |
| 337 | // Return the last thunk for the given target if it is in range, | |
| 338 | // or create a new one. | |
| 339 | static std::pair<Defined *, bool> | |
| 340 | getThunk(DenseMap<uint64_t, Defined *> &LastThunks, Defined *Target, uint64_t P, | |
| 341 | uint16_t Type, int Margin) { | |
| 342 | Defined *&LastThunk = LastThunks[Target->getRVA()]; | |
| 343 | if (LastThunk && isInRange(Type, LastThunk->getRVA(), P, Margin)) | |
| 344 | return {LastThunk, false}; | |
| 345 | Chunk *C; | |
| 346 | switch (Config->Machine) { | |
| 347 | case ARMNT: | |
| 348 | C = make<RangeExtensionThunkARM>(Target); | |
| 349 | break; | |
| 350 | case ARM64: | |
| 351 | C = make<RangeExtensionThunkARM64>(Target); | |
| 352 | break; | |
| 353 | default: | |
| 354 | llvm_unreachable("Unexpected architecture"); | |
| 296 | 355 | } |
| 356 | Defined *D = make<DefinedSynthetic>("", C); | |
| 357 | LastThunk = D; | |
| 358 | return {D, true}; | |
| 359 | } | |
| 297 | 360 | |
| 298 | auto Binary = std::move(*ExpectedBinary); | |
| 299 | if (!Binary.getBinary()->isCOFF()) | |
| 300 | return None; | |
| 361 | // This checks all relocations, and for any relocation which isn't in range | |
| 362 | // it adds a thunk after the section chunk that contains the relocation. | |
| 363 | // If the latest thunk for the specific target is in range, that is used | |
| 364 | // instead of creating a new thunk. All range checks are done with the | |
| 365 | // specified margin, to make sure that relocations that originally are in | |
| 366 | // range, but only barely, also get thunks - in case other added thunks makes | |
| 367 | // the target go out of range. | |
| 368 | // | |
| 369 | // After adding thunks, we verify that all relocations are in range (with | |
| 370 | // no extra margin requirements). If this failed, we restart (throwing away | |
| 371 | // the previously created thunks) and retry with a wider margin. | |
| 372 | static bool createThunks(OutputSection *OS, int Margin) { | |
| 373 | bool AddressesChanged = false; | |
| 374 | DenseMap<uint64_t, Defined *> LastThunks; | |
| 375 | size_t ThunksSize = 0; | |
| 376 | // Recheck Chunks.size() each iteration, since we can insert more | |
| 377 | // elements into it. | |
| 378 | for (size_t I = 0; I != OS->Chunks.size(); ++I) { | |
| 379 | SectionChunk *SC = dyn_cast_or_null<SectionChunk>(OS->Chunks[I]); | |
| 380 | if (!SC) | |
| 381 | continue; | |
| 382 | size_t ThunkInsertionSpot = I + 1; | |
| 383 | ||
| 384 | // Try to get a good enough estimate of where new thunks will be placed. | |
| 385 | // Offset this by the size of the new thunks added so far, to make the | |
| 386 | // estimate slightly better. | |
| 387 | size_t ThunkInsertionRVA = SC->getRVA() + SC->getSize() + ThunksSize; | |
| 388 | for (size_t J = 0, E = SC->Relocs.size(); J < E; ++J) { | |
| 389 | const coff_relocation &Rel = SC->Relocs[J]; | |
| 390 | Symbol *&RelocTarget = SC->RelocTargets[J]; | |
| 391 | ||
| 392 | // The estimate of the source address P should be pretty accurate, | |
| 393 | // but we don't know whether the target Symbol address should be | |
| 394 | // offset by ThunkSize or not (or by some of ThunksSize but not all of | |
| 395 | // it), giving us some uncertainty once we have added one thunk. | |
| 396 | uint64_t P = SC->getRVA() + Rel.VirtualAddress + ThunksSize; | |
| 397 | ||
| 398 | Defined *Sym = dyn_cast_or_null<Defined>(RelocTarget); | |
| 399 | if (!Sym) | |
| 400 | continue; | |
| 301 | 401 | |
| 302 | std::error_code EC; | |
| 303 | COFFObjectFile File(Binary.getBinary()->getMemoryBufferRef(), EC); | |
| 304 | if (EC) | |
| 305 | return None; | |
| 402 | uint64_t S = Sym->getRVA(); | |
| 306 | 403 | |
| 307 | // If the machine of the binary we're outputting doesn't match the machine | |
| 308 | // of the existing binary, don't try to re-use the build id. | |
| 309 | if (File.is64() != Config->is64() || File.getMachine() != Config->Machine) | |
| 310 | return None; | |
| 404 | if (isInRange(Rel.Type, S, P, Margin)) | |
| 405 | continue; | |
| 406 | ||
| 407 | // If the target isn't in range, hook it up to an existing or new | |
| 408 | // thunk. | |
| 409 | Defined *Thunk; | |
| 410 | bool WasNew; | |
| 411 | std::tie(Thunk, WasNew) = getThunk(LastThunks, Sym, P, Rel.Type, Margin); | |
| 412 | if (WasNew) { | |
| 413 | Chunk *ThunkChunk = Thunk->getChunk(); | |
| 414 | ThunkChunk->setRVA( | |
| 415 | ThunkInsertionRVA); // Estimate of where it will be located. | |
| 416 | ThunkChunk->setOutputSection(OS); | |
| 417 | OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk); | |
| 418 | ThunkInsertionSpot++; | |
| 419 | ThunksSize += ThunkChunk->getSize(); | |
| 420 | ThunkInsertionRVA += ThunkChunk->getSize(); | |
| 421 | AddressesChanged = true; | |
| 422 | } | |
| 423 | RelocTarget = Thunk; | |
| 424 | } | |
| 425 | } | |
| 426 | return AddressesChanged; | |
| 427 | } | |
| 311 | 428 | |
| 312 | for (const auto &DebugDir : File.debug_directories()) { | |
| 313 | if (DebugDir.Type != IMAGE_DEBUG_TYPE_CODEVIEW) | |
| 429 | // Verify that all relocations are in range, with no extra margin requirements. | |
| 430 | static bool verifyRanges(const std::vector<Chunk *> Chunks) { | |
| 431 | for (Chunk *C : Chunks) { | |
| 432 | SectionChunk *SC = dyn_cast_or_null<SectionChunk>(C); | |
| 433 | if (!SC) | |
| 314 | 434 | continue; |
| 315 | 435 | |
| 316 | const codeview::DebugInfo *ExistingDI = nullptr; | |
| 317 | StringRef PDBFileName; | |
| 318 | if (auto EC = File.getDebugPDBInfo(ExistingDI, PDBFileName)) { | |
| 319 | (void)EC; | |
| 320 | return None; | |
| 436 | for (size_t J = 0, E = SC->Relocs.size(); J < E; ++J) { | |
| 437 | const coff_relocation &Rel = SC->Relocs[J]; | |
| 438 | Symbol *RelocTarget = SC->RelocTargets[J]; | |
| 439 | ||
| 440 | Defined *Sym = dyn_cast_or_null<Defined>(RelocTarget); | |
| 441 | if (!Sym) | |
| 442 | continue; | |
| 443 | ||
| 444 | uint64_t P = SC->getRVA() + Rel.VirtualAddress; | |
| 445 | uint64_t S = Sym->getRVA(); | |
| 446 | ||
| 447 | if (!isInRange(Rel.Type, S, P, 0)) | |
| 448 | return false; | |
| 321 | 449 | } |
| 322 | // We only support writing PDBs in v70 format. So if this is not a build | |
| 323 | // id that we recognize / support, ignore it. | |
| 324 | if (ExistingDI->Signature.CVSignature != OMF::Signature::PDB70) | |
| 325 | return None; | |
| 326 | return *ExistingDI; | |
| 327 | 450 | } |
| 328 | return None; | |
| 451 | return true; | |
| 452 | } | |
| 453 | ||
| 454 | // Assign addresses and add thunks if necessary. | |
| 455 | void Writer::finalizeAddresses() { | |
| 456 | assignAddresses(); | |
| 457 | if (Config->Machine != ARMNT && Config->Machine != ARM64) | |
| 458 | return; | |
| 459 | ||
| 460 | size_t OrigNumChunks = 0; | |
| 461 | for (OutputSection *Sec : OutputSections) { | |
| 462 | Sec->OrigChunks = Sec->Chunks; | |
| 463 | OrigNumChunks += Sec->Chunks.size(); | |
| 464 | } | |
| 465 | ||
| 466 | int Pass = 0; | |
| 467 | int Margin = 1024 * 100; | |
| 468 | while (true) { | |
| 469 | // First check whether we need thunks at all, or if the previous pass of | |
| 470 | // adding them turned out ok. | |
| 471 | bool RangesOk = true; | |
| 472 | size_t NumChunks = 0; | |
| 473 | for (OutputSection *Sec : OutputSections) { | |
| 474 | if (!verifyRanges(Sec->Chunks)) { | |
| 475 | RangesOk = false; | |
| 476 | break; | |
| 477 | } | |
| 478 | NumChunks += Sec->Chunks.size(); | |
| 479 | } | |
| 480 | if (RangesOk) { | |
| 481 | if (Pass > 0) | |
| 482 | log("Added " + Twine(NumChunks - OrigNumChunks) + " thunks with " + | |
| 483 | "margin " + Twine(Margin) + " in " + Twine(Pass) + " passes"); | |
| 484 | return; | |
| 485 | } | |
| 486 | ||
| 487 | if (Pass >= 10) | |
| 488 | fatal("adding thunks hasn't converged after " + Twine(Pass) + " passes"); | |
| 489 | ||
| 490 | if (Pass > 0) { | |
| 491 | // If the previous pass didn't work out, reset everything back to the | |
| 492 | // original conditions before retrying with a wider margin. This should | |
| 493 | // ideally never happen under real circumstances. | |
| 494 | for (OutputSection *Sec : OutputSections) { | |
| 495 | Sec->Chunks = Sec->OrigChunks; | |
| 496 | for (Chunk *C : Sec->Chunks) | |
| 497 | C->resetRelocTargets(); | |
| 498 | } | |
| 499 | Margin *= 2; | |
| 500 | } | |
| 501 | ||
| 502 | // Try adding thunks everywhere where it is needed, with a margin | |
| 503 | // to avoid things going out of range due to the added thunks. | |
| 504 | bool AddressesChanged = false; | |
| 505 | for (OutputSection *Sec : OutputSections) | |
| 506 | AddressesChanged |= createThunks(Sec, Margin); | |
| 507 | // If the verification above thought we needed thunks, we should have | |
| 508 | // added some. | |
| 509 | assert(AddressesChanged); | |
| 510 | ||
| 511 | // Recalculate the layout for the whole image (and verify the ranges at | |
| 512 | // the start of the next round). | |
| 513 | assignAddresses(); | |
| 514 | ||
| 515 | Pass++; | |
| 516 | } | |
| 329 | 517 | } |
| 330 | 518 | |
| 331 | 519 | // The main function of the writer. |
| 332 | 520 | void Writer::run() { |
| 333 | 521 | ScopedTimer T1(CodeLayoutTimer); |
| 334 | 522 | |
| 523 | createImportTables(); | |
| 335 | 524 | createSections(); |
| 336 | 525 | createMiscChunks(); |
| 337 | createImportTables(); | |
| 526 | appendImportThunks(); | |
| 338 | 527 | createExportTable(); |
| 339 | 528 | mergeSections(); |
| 340 | assignAddresses(); | |
| 529 | readRelocTargets(); | |
| 530 | removeUnusedSections(); | |
| 531 | finalizeAddresses(); | |
| 341 | 532 | removeEmptySections(); |
| 342 | 533 | setSectionPermissions(); |
| 343 | 534 | createSymbolAndStringTable(); |
| ... | ... | @@ -346,9 +537,6 @@ void Writer::run() { |
| 346 | 537 | fatal("image size (" + Twine(FileSize) + ") " + |
| 347 | 538 | "exceeds maximum allowable size (" + Twine(UINT32_MAX) + ")"); |
| 348 | 539 | |
| 349 | // We must do this before opening the output file, as it depends on being able | |
| 350 | // to read the contents of the existing output file. | |
| 351 | PreviousBuildId = loadExistingBuildId(Config->OutputFile); | |
| 352 | 540 | openFile(Config->OutputFile); |
| 353 | 541 | if (Config->is64()) { |
| 354 | 542 | writeHeader<pe32plus_header>(); |
| ... | ... | @@ -357,14 +545,14 @@ void Writer::run() { |
| 357 | 545 | } |
| 358 | 546 | writeSections(); |
| 359 | 547 | sortExceptionTable(); |
| 360 | writeBuildId(); | |
| 361 | 548 | |
| 362 | 549 | T1.stop(); |
| 363 | 550 | |
| 364 | 551 | if (!Config->PDBPath.empty() && Config->Debug) { |
| 365 | 552 | assert(BuildId); |
| 366 | createPDB(Symtab, OutputSections, SectionTable, *BuildId->BuildId); | |
| 553 | createPDB(Symtab, OutputSections, SectionTable, BuildId->BuildId); | |
| 367 | 554 | } |
| 555 | writeBuildId(); | |
| 368 | 556 | |
| 369 | 557 | writeMapFile(OutputSections); |
| 370 | 558 | |
| ... | ... | @@ -396,6 +584,110 @@ static void sortBySectionOrder(std::vector<Chunk *> &Chunks) { |
| 396 | 584 | }); |
| 397 | 585 | } |
| 398 | 586 | |
| 587 | // Sort concrete section chunks from GNU import libraries. | |
| 588 | // | |
| 589 | // GNU binutils doesn't use short import files, but instead produces import | |
| 590 | // libraries that consist of object files, with section chunks for the .idata$* | |
| 591 | // sections. These are linked just as regular static libraries. Each import | |
| 592 | // library consists of one header object, one object file for every imported | |
| 593 | // symbol, and one trailer object. In order for the .idata tables/lists to | |
| 594 | // be formed correctly, the section chunks within each .idata$* section need | |
| 595 | // to be grouped by library, and sorted alphabetically within each library | |
| 596 | // (which makes sure the header comes first and the trailer last). | |
| 597 | static bool fixGnuImportChunks( | |
| 598 | std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map) { | |
| 599 | uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; | |
| 600 | ||
| 601 | // Make sure all .idata$* section chunks are mapped as RDATA in order to | |
| 602 | // be sorted into the same sections as our own synthesized .idata chunks. | |
| 603 | for (auto &Pair : Map) { | |
| 604 | StringRef SectionName = Pair.first.first; | |
| 605 | uint32_t OutChars = Pair.first.second; | |
| 606 | if (!SectionName.startswith(".idata")) | |
| 607 | continue; | |
| 608 | if (OutChars == RDATA) | |
| 609 | continue; | |
| 610 | std::vector<Chunk *> &SrcVect = Pair.second; | |
| 611 | std::vector<Chunk *> &DestVect = Map[{SectionName, RDATA}]; | |
| 612 | DestVect.insert(DestVect.end(), SrcVect.begin(), SrcVect.end()); | |
| 613 | SrcVect.clear(); | |
| 614 | } | |
| 615 | ||
| 616 | bool HasIdata = false; | |
| 617 | // Sort all .idata$* chunks, grouping chunks from the same library, | |
| 618 | // with alphabetical ordering of the object fils within a library. | |
| 619 | for (auto &Pair : Map) { | |
| 620 | StringRef SectionName = Pair.first.first; | |
| 621 | if (!SectionName.startswith(".idata")) | |
| 622 | continue; | |
| 623 | ||
| 624 | std::vector<Chunk *> &Chunks = Pair.second; | |
| 625 | if (!Chunks.empty()) | |
| 626 | HasIdata = true; | |
| 627 | std::stable_sort(Chunks.begin(), Chunks.end(), [&](Chunk *S, Chunk *T) { | |
| 628 | SectionChunk *SC1 = dyn_cast_or_null<SectionChunk>(S); | |
| 629 | SectionChunk *SC2 = dyn_cast_or_null<SectionChunk>(T); | |
| 630 | if (!SC1 || !SC2) { | |
| 631 | // if SC1, order them ascending. If SC2 or both null, | |
| 632 | // S is not less than T. | |
| 633 | return SC1 != nullptr; | |
| 634 | } | |
| 635 | // Make a string with "libraryname/objectfile" for sorting, achieving | |
| 636 | // both grouping by library and sorting of objects within a library, | |
| 637 | // at once. | |
| 638 | std::string Key1 = | |
| 639 | (SC1->File->ParentName + "/" + SC1->File->getName()).str(); | |
| 640 | std::string Key2 = | |
| 641 | (SC2->File->ParentName + "/" + SC2->File->getName()).str(); | |
| 642 | return Key1 < Key2; | |
| 643 | }); | |
| 644 | } | |
| 645 | return HasIdata; | |
| 646 | } | |
| 647 | ||
| 648 | // Add generated idata chunks, for imported symbols and DLLs, and a | |
| 649 | // terminator in .idata$2. | |
| 650 | static void addSyntheticIdata( | |
| 651 | IdataContents &Idata, | |
| 652 | std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map) { | |
| 653 | uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; | |
| 654 | Idata.create(); | |
| 655 | ||
| 656 | // Add the .idata content in the right section groups, to allow | |
| 657 | // chunks from other linked in object files to be grouped together. | |
| 658 | // See Microsoft PE/COFF spec 5.4 for details. | |
| 659 | auto Add = [&](StringRef N, std::vector<Chunk *> &V) { | |
| 660 | std::vector<Chunk *> &DestVect = Map[{N, RDATA}]; | |
| 661 | DestVect.insert(DestVect.end(), V.begin(), V.end()); | |
| 662 | }; | |
| 663 | ||
| 664 | // The loader assumes a specific order of data. | |
| 665 | // Add each type in the correct order. | |
| 666 | Add(".idata$2", Idata.Dirs); | |
| 667 | Add(".idata$4", Idata.Lookups); | |
| 668 | Add(".idata$5", Idata.Addresses); | |
| 669 | Add(".idata$6", Idata.Hints); | |
| 670 | Add(".idata$7", Idata.DLLNames); | |
| 671 | } | |
| 672 | ||
| 673 | // Locate the first Chunk and size of the import directory list and the | |
| 674 | // IAT. | |
| 675 | void Writer::locateImportTables( | |
| 676 | std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map) { | |
| 677 | uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ; | |
| 678 | std::vector<Chunk *> &ImportTables = Map[{".idata$2", RDATA}]; | |
| 679 | if (!ImportTables.empty()) | |
| 680 | ImportTableStart = ImportTables.front(); | |
| 681 | for (Chunk *C : ImportTables) | |
| 682 | ImportTableSize += C->getSize(); | |
| 683 | ||
| 684 | std::vector<Chunk *> &IAT = Map[{".idata$5", RDATA}]; | |
| 685 | if (!IAT.empty()) | |
| 686 | IATStart = IAT.front(); | |
| 687 | for (Chunk *C : IAT) | |
| 688 | IATSize += C->getSize(); | |
| 689 | } | |
| 690 | ||
| 399 | 691 | // Create output section objects and add them to OutputSections. |
| 400 | 692 | void Writer::createSections() { |
| 401 | 693 | // First, create the builtin sections. |
| ... | ... | @@ -429,12 +721,14 @@ void Writer::createSections() { |
| 429 | 721 | DidatSec = CreateSection(".didat", DATA | R); |
| 430 | 722 | RsrcSec = CreateSection(".rsrc", DATA | R); |
| 431 | 723 | RelocSec = CreateSection(".reloc", DATA | DISCARDABLE | R); |
| 724 | CtorsSec = CreateSection(".ctors", DATA | R | W); | |
| 725 | DtorsSec = CreateSection(".dtors", DATA | R | W); | |
| 432 | 726 | |
| 433 | 727 | // Then bin chunks by name and output characteristics. |
| 434 | 728 | std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> Map; |
| 435 | 729 | for (Chunk *C : Symtab->getChunks()) { |
| 436 | 730 | auto *SC = dyn_cast<SectionChunk>(C); |
| 437 | if (SC && !SC->isLive()) { | |
| 731 | if (SC && !SC->Live) { | |
| 438 | 732 | if (Config->Verbose) |
| 439 | 733 | SC->printDiscardedMessage(); |
| 440 | 734 | continue; |
| ... | ... | @@ -442,26 +736,43 @@ void Writer::createSections() { |
| 442 | 736 | Map[{C->getSectionName(), C->getOutputCharacteristics()}].push_back(C); |
| 443 | 737 | } |
| 444 | 738 | |
| 739 | // Even in non MinGW cases, we might need to link against GNU import | |
| 740 | // libraries. | |
| 741 | bool HasIdata = fixGnuImportChunks(Map); | |
| 742 | if (!Idata.empty()) | |
| 743 | HasIdata = true; | |
| 744 | ||
| 745 | if (HasIdata) | |
| 746 | addSyntheticIdata(Idata, Map); | |
| 747 | ||
| 445 | 748 | // Process an /order option. |
| 446 | 749 | if (!Config->Order.empty()) |
| 447 | 750 | for (auto &Pair : Map) |
| 448 | 751 | sortBySectionOrder(Pair.second); |
| 449 | 752 | |
| 753 | if (HasIdata) | |
| 754 | locateImportTables(Map); | |
| 755 | ||
| 450 | 756 | // Then create an OutputSection for each section. |
| 451 | 757 | // '$' and all following characters in input section names are |
| 452 | 758 | // discarded when determining output section. So, .text$foo |
| 453 | 759 | // contributes to .text, for example. See PE/COFF spec 3.2. |
| 454 | for (auto Pair : Map) { | |
| 760 | for (auto &Pair : Map) { | |
| 455 | 761 | StringRef Name = getOutputSectionName(Pair.first.first); |
| 456 | 762 | uint32_t OutChars = Pair.first.second; |
| 457 | 763 | |
| 458 | // In link.exe, there is a special case for the I386 target where .CRT | |
| 459 | // sections are treated as if they have output characteristics DATA | R if | |
| 460 | // their characteristics are DATA | R | W. This implements the same special | |
| 461 | // case for all architectures. | |
| 462 | if (Name == ".CRT") | |
| 764 | if (Name == ".CRT") { | |
| 765 | // In link.exe, there is a special case for the I386 target where .CRT | |
| 766 | // sections are treated as if they have output characteristics DATA | R if | |
| 767 | // their characteristics are DATA | R | W. This implements the same | |
| 768 | // special case for all architectures. | |
| 463 | 769 | OutChars = DATA | R; |
| 464 | 770 | |
| 771 | log("Processing section " + Pair.first.first + " -> " + Name); | |
| 772 | ||
| 773 | sortCRTSectionChunks(Pair.second); | |
| 774 | } | |
| 775 | ||
| 465 | 776 | OutputSection *Sec = CreateSection(Name, OutChars); |
| 466 | 777 | std::vector<Chunk *> &Chunks = Pair.second; |
| 467 | 778 | for (Chunk *C : Chunks) |
| ... | ... | @@ -499,20 +810,20 @@ void Writer::createMiscChunks() { |
| 499 | 810 | } |
| 500 | 811 | |
| 501 | 812 | // Create Debug Information Chunks |
| 502 | if (Config->Debug) { | |
| 503 | DebugDirectory = make<DebugDirectoryChunk>(DebugRecords); | |
| 504 | ||
| 505 | OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec; | |
| 813 | OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec; | |
| 814 | if (Config->Debug || Config->Repro) { | |
| 815 | DebugDirectory = make<DebugDirectoryChunk>(DebugRecords, Config->Repro); | |
| 816 | DebugInfoSec->addChunk(DebugDirectory); | |
| 817 | } | |
| 506 | 818 | |
| 819 | if (Config->Debug) { | |
| 507 | 820 | // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified. We |
| 508 | 821 | // output a PDB no matter what, and this chunk provides the only means of |
| 509 | 822 | // allowing a debugger to match a PDB and an executable. So we need it even |
| 510 | 823 | // if we're ultimately not going to write CodeView data to the PDB. |
| 511 | auto *CVChunk = make<CVDebugRecordChunk>(); | |
| 512 | BuildId = CVChunk; | |
| 513 | DebugRecords.push_back(CVChunk); | |
| 824 | BuildId = make<CVDebugRecordChunk>(); | |
| 825 | DebugRecords.push_back(BuildId); | |
| 514 | 826 | |
| 515 | DebugInfoSec->addChunk(DebugDirectory); | |
| 516 | 827 | for (Chunk *C : DebugRecords) |
| 517 | 828 | DebugInfoSec->addChunk(C); |
| 518 | 829 | } |
| ... | ... | @@ -524,6 +835,12 @@ void Writer::createMiscChunks() { |
| 524 | 835 | // Create /guard:cf tables if requested. |
| 525 | 836 | if (Config->GuardCF != GuardCFLevel::Off) |
| 526 | 837 | createGuardCFTables(); |
| 838 | ||
| 839 | if (Config->MinGW) { | |
| 840 | createRuntimePseudoRelocs(); | |
| 841 | ||
| 842 | insertCtorDtorSymbols(); | |
| 843 | } | |
| 527 | 844 | } |
| 528 | 845 | |
| 529 | 846 | // Create .idata section for the DLL-imported symbol table. |
| ... | ... | @@ -531,9 +848,6 @@ void Writer::createMiscChunks() { |
| 531 | 848 | // IdataContents class abstracted away the details for us, |
| 532 | 849 | // so we just let it create chunks and add them to the section. |
| 533 | 850 | void Writer::createImportTables() { |
| 534 | if (ImportFile::Instances.empty()) | |
| 535 | return; | |
| 536 | ||
| 537 | 851 | // Initialize DLLOrder so that import entries are ordered in |
| 538 | 852 | // the same order as in the command line. (That affects DLL |
| 539 | 853 | // initialization order, and this ordering is MSVC-compatible.) |
| ... | ... | @@ -545,14 +859,6 @@ void Writer::createImportTables() { |
| 545 | 859 | if (Config->DLLOrder.count(DLL) == 0) |
| 546 | 860 | Config->DLLOrder[DLL] = Config->DLLOrder.size(); |
| 547 | 861 | |
| 548 | if (File->ThunkSym) { | |
| 549 | if (!isa<DefinedImportThunk>(File->ThunkSym)) | |
| 550 | fatal(toString(*File->ThunkSym) + " was replaced"); | |
| 551 | DefinedImportThunk *Thunk = cast<DefinedImportThunk>(File->ThunkSym); | |
| 552 | if (File->ThunkLive) | |
| 553 | TextSec->addChunk(Thunk->getChunk()); | |
| 554 | } | |
| 555 | ||
| 556 | 862 | if (File->ImpSym && !isa<DefinedImportData>(File->ImpSym)) |
| 557 | 863 | fatal(toString(*File->ImpSym) + " was replaced"); |
| 558 | 864 | DefinedImportData *ImpSym = cast_or_null<DefinedImportData>(File->ImpSym); |
| ... | ... | @@ -565,10 +871,25 @@ void Writer::createImportTables() { |
| 565 | 871 | Idata.add(ImpSym); |
| 566 | 872 | } |
| 567 | 873 | } |
| 874 | } | |
| 568 | 875 | |
| 569 | if (!Idata.empty()) | |
| 570 | for (Chunk *C : Idata.getChunks()) | |
| 571 | IdataSec->addChunk(C); | |
| 876 | void Writer::appendImportThunks() { | |
| 877 | if (ImportFile::Instances.empty()) | |
| 878 | return; | |
| 879 | ||
| 880 | for (ImportFile *File : ImportFile::Instances) { | |
| 881 | if (!File->Live) | |
| 882 | continue; | |
| 883 | ||
| 884 | if (!File->ThunkSym) | |
| 885 | continue; | |
| 886 | ||
| 887 | if (!isa<DefinedImportThunk>(File->ThunkSym)) | |
| 888 | fatal(toString(*File->ThunkSym) + " was replaced"); | |
| 889 | DefinedImportThunk *Thunk = cast<DefinedImportThunk>(File->ThunkSym); | |
| 890 | if (File->ThunkLive) | |
| 891 | TextSec->addChunk(Thunk->getChunk()); | |
| 892 | } | |
| 572 | 893 | |
| 573 | 894 | if (!DelayIdata.empty()) { |
| 574 | 895 | Defined *Helper = cast<Defined>(Config->DelayLoadHelper); |
| ... | ... | @@ -589,6 +910,21 @@ void Writer::createExportTable() { |
| 589 | 910 | EdataSec->addChunk(C); |
| 590 | 911 | } |
| 591 | 912 | |
| 913 | void Writer::removeUnusedSections() { | |
| 914 | // Remove sections that we can be sure won't get content, to avoid | |
| 915 | // allocating space for their section headers. | |
| 916 | auto IsUnused = [this](OutputSection *S) { | |
| 917 | if (S == RelocSec) | |
| 918 | return false; // This section is populated later. | |
| 919 | // MergeChunks have zero size at this point, as their size is finalized | |
| 920 | // later. Only remove sections that have no Chunks at all. | |
| 921 | return S->Chunks.empty(); | |
| 922 | }; | |
| 923 | OutputSections.erase( | |
| 924 | std::remove_if(OutputSections.begin(), OutputSections.end(), IsUnused), | |
| 925 | OutputSections.end()); | |
| 926 | } | |
| 927 | ||
| 592 | 928 | // The Windows loader doesn't seem to like empty sections, |
| 593 | 929 | // so we remove them if any. |
| 594 | 930 | void Writer::removeEmptySections() { |
| ... | ... | @@ -699,9 +1035,9 @@ void Writer::createSymbolAndStringTable() { |
| 699 | 1035 | } |
| 700 | 1036 | |
| 701 | 1037 | void Writer::mergeSections() { |
| 702 | if (!PdataSec->getChunks().empty()) { | |
| 703 | FirstPdata = PdataSec->getChunks().front(); | |
| 704 | LastPdata = PdataSec->getChunks().back(); | |
| 1038 | if (!PdataSec->Chunks.empty()) { | |
| 1039 | FirstPdata = PdataSec->Chunks.front(); | |
| 1040 | LastPdata = PdataSec->Chunks.back(); | |
| 705 | 1041 | } |
| 706 | 1042 | |
| 707 | 1043 | for (auto &P : Config->Merge) { |
| ... | ... | @@ -729,11 +1065,18 @@ void Writer::mergeSections() { |
| 729 | 1065 | } |
| 730 | 1066 | } |
| 731 | 1067 | |
| 1068 | // Visits all sections to initialize their relocation targets. | |
| 1069 | void Writer::readRelocTargets() { | |
| 1070 | for (OutputSection *Sec : OutputSections) | |
| 1071 | for_each(parallel::par, Sec->Chunks.begin(), Sec->Chunks.end(), | |
| 1072 | [&](Chunk *C) { C->readRelocTargets(); }); | |
| 1073 | } | |
| 1074 | ||
| 732 | 1075 | // Visits all sections to assign incremental, non-overlapping RVAs and |
| 733 | 1076 | // file offsets. |
| 734 | 1077 | void Writer::assignAddresses() { |
| 735 | 1078 | SizeOfHeaders = DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) + |
| 736 | sizeof(data_directory) * NumberfOfDataDirectory + | |
| 1079 | sizeof(data_directory) * NumberOfDataDirectory + | |
| 737 | 1080 | sizeof(coff_section) * OutputSections.size(); |
| 738 | 1081 | SizeOfHeaders += |
| 739 | 1082 | Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header); |
| ... | ... | @@ -746,7 +1089,7 @@ void Writer::assignAddresses() { |
| 746 | 1089 | addBaserels(); |
| 747 | 1090 | uint64_t RawSize = 0, VirtualSize = 0; |
| 748 | 1091 | Sec->Header.VirtualAddress = RVA; |
| 749 | for (Chunk *C : Sec->getChunks()) { | |
| 1092 | for (Chunk *C : Sec->Chunks) { | |
| 750 | 1093 | VirtualSize = alignTo(VirtualSize, C->Alignment); |
| 751 | 1094 | C->setRVA(RVA + VirtualSize); |
| 752 | 1095 | C->OutputSectionOff = VirtualSize; |
| ... | ... | @@ -808,7 +1151,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() { |
| 808 | 1151 | if (!Config->Relocatable) |
| 809 | 1152 | COFF->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED; |
| 810 | 1153 | COFF->SizeOfOptionalHeader = |
| 811 | sizeof(PEHeaderTy) + sizeof(data_directory) * NumberfOfDataDirectory; | |
| 1154 | sizeof(PEHeaderTy) + sizeof(data_directory) * NumberOfDataDirectory; | |
| 812 | 1155 | |
| 813 | 1156 | // Write PE header |
| 814 | 1157 | auto *PE = reinterpret_cast<PEHeaderTy *>(Buf); |
| ... | ... | @@ -866,7 +1209,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() { |
| 866 | 1209 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH; |
| 867 | 1210 | if (Config->TerminalServerAware) |
| 868 | 1211 | PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE; |
| 869 | PE->NumberOfRvaAndSize = NumberfOfDataDirectory; | |
| 1212 | PE->NumberOfRvaAndSize = NumberOfDataDirectory; | |
| 870 | 1213 | if (TextSec->getVirtualSize()) { |
| 871 | 1214 | PE->BaseOfCode = TextSec->getRVA(); |
| 872 | 1215 | PE->SizeOfCode = TextSec->getRawSize(); |
| ... | ... | @@ -875,16 +1218,18 @@ template <typename PEHeaderTy> void Writer::writeHeader() { |
| 875 | 1218 | |
| 876 | 1219 | // Write data directory |
| 877 | 1220 | auto *Dir = reinterpret_cast<data_directory *>(Buf); |
| 878 | Buf += sizeof(*Dir) * NumberfOfDataDirectory; | |
| 1221 | Buf += sizeof(*Dir) * NumberOfDataDirectory; | |
| 879 | 1222 | if (!Config->Exports.empty()) { |
| 880 | 1223 | Dir[EXPORT_TABLE].RelativeVirtualAddress = Edata.getRVA(); |
| 881 | 1224 | Dir[EXPORT_TABLE].Size = Edata.getSize(); |
| 882 | 1225 | } |
| 883 | if (!Idata.empty()) { | |
| 884 | Dir[IMPORT_TABLE].RelativeVirtualAddress = Idata.getDirRVA(); | |
| 885 | Dir[IMPORT_TABLE].Size = Idata.getDirSize(); | |
| 886 | Dir[IAT].RelativeVirtualAddress = Idata.getIATRVA(); | |
| 887 | Dir[IAT].Size = Idata.getIATSize(); | |
| 1226 | if (ImportTableStart) { | |
| 1227 | Dir[IMPORT_TABLE].RelativeVirtualAddress = ImportTableStart->getRVA(); | |
| 1228 | Dir[IMPORT_TABLE].Size = ImportTableSize; | |
| 1229 | } | |
| 1230 | if (IATStart) { | |
| 1231 | Dir[IAT].RelativeVirtualAddress = IATStart->getRVA(); | |
| 1232 | Dir[IAT].Size = IATSize; | |
| 888 | 1233 | } |
| 889 | 1234 | if (RsrcSec->getVirtualSize()) { |
| 890 | 1235 | Dir[RESOURCE_TABLE].RelativeVirtualAddress = RsrcSec->getRVA(); |
| ... | ... | @@ -907,7 +1252,7 @@ template <typename PEHeaderTy> void Writer::writeHeader() { |
| 907 | 1252 | : sizeof(object::coff_tls_directory32); |
| 908 | 1253 | } |
| 909 | 1254 | } |
| 910 | if (Config->Debug) { | |
| 1255 | if (DebugDirectory) { | |
| 911 | 1256 | Dir[DEBUG_DIRECTORY].RelativeVirtualAddress = DebugDirectory->getRVA(); |
| 912 | 1257 | Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize(); |
| 913 | 1258 | } |
| ... | ... | @@ -1002,6 +1347,25 @@ static void addSymbolToRVASet(SymbolRVASet &RVASet, Defined *S) { |
| 1002 | 1347 | RVASet.insert({C, Off}); |
| 1003 | 1348 | } |
| 1004 | 1349 | |
| 1350 | // Given a symbol, add it to the GFIDs table if it is a live, defined, function | |
| 1351 | // symbol in an executable section. | |
| 1352 | static void maybeAddAddressTakenFunction(SymbolRVASet &AddressTakenSyms, | |
| 1353 | Symbol *S) { | |
| 1354 | auto *D = dyn_cast_or_null<DefinedCOFF>(S); | |
| 1355 | ||
| 1356 | // Ignore undefined symbols and references to non-functions (e.g. globals and | |
| 1357 | // labels). | |
| 1358 | if (!D || | |
| 1359 | D->getCOFFSymbol().getComplexType() != COFF::IMAGE_SYM_DTYPE_FUNCTION) | |
| 1360 | return; | |
| 1361 | ||
| 1362 | // Mark the symbol as address taken if it's in an executable section. | |
| 1363 | Chunk *RefChunk = D->getChunk(); | |
| 1364 | OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr; | |
| 1365 | if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE) | |
| 1366 | addSymbolToRVASet(AddressTakenSyms, D); | |
| 1367 | } | |
| 1368 | ||
| 1005 | 1369 | // Visit all relocations from all section contributions of this object file and |
| 1006 | 1370 | // mark the relocation target as address-taken. |
| 1007 | 1371 | static void markSymbolsWithRelocations(ObjFile *File, |
| ... | ... | @@ -1010,21 +1374,17 @@ static void markSymbolsWithRelocations(ObjFile *File, |
| 1010 | 1374 | // We only care about live section chunks. Common chunks and other chunks |
| 1011 | 1375 | // don't generally contain relocations. |
| 1012 | 1376 | SectionChunk *SC = dyn_cast<SectionChunk>(C); |
| 1013 | if (!SC || !SC->isLive()) | |
| 1377 | if (!SC || !SC->Live) | |
| 1014 | 1378 | continue; |
| 1015 | 1379 | |
| 1016 | // Look for relocations in this section against symbols in executable output | |
| 1017 | // sections. | |
| 1018 | for (Symbol *Ref : SC->symbols()) { | |
| 1019 | // FIXME: Do further testing to see if the relocation type matters, | |
| 1020 | // especially for 32-bit where taking the address of something usually | |
| 1021 | // uses an absolute relocation instead of a relative one. | |
| 1022 | if (auto *D = dyn_cast_or_null<Defined>(Ref)) { | |
| 1023 | Chunk *RefChunk = D->getChunk(); | |
| 1024 | OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr; | |
| 1025 | if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE) | |
| 1026 | addSymbolToRVASet(UsedSymbols, D); | |
| 1027 | } | |
| 1380 | for (const coff_relocation &Reloc : SC->Relocs) { | |
| 1381 | if (Config->Machine == I386 && Reloc.Type == COFF::IMAGE_REL_I386_REL32) | |
| 1382 | // Ignore relative relocations on x86. On x86_64 they can't be ignored | |
| 1383 | // since they're also used to compute absolute addresses. | |
| 1384 | continue; | |
| 1385 | ||
| 1386 | Symbol *Ref = SC->File->getSymbol(Reloc.SymbolTableIndex); | |
| 1387 | maybeAddAddressTakenFunction(UsedSymbols, Ref); | |
| 1028 | 1388 | } |
| 1029 | 1389 | } |
| 1030 | 1390 | } |
| ... | ... | @@ -1051,7 +1411,11 @@ void Writer::createGuardCFTables() { |
| 1051 | 1411 | |
| 1052 | 1412 | // Mark the image entry as address-taken. |
| 1053 | 1413 | if (Config->Entry) |
| 1054 | addSymbolToRVASet(AddressTakenSyms, cast<Defined>(Config->Entry)); | |
| 1414 | maybeAddAddressTakenFunction(AddressTakenSyms, Config->Entry); | |
| 1415 | ||
| 1416 | // Mark exported symbols in executable sections as address-taken. | |
| 1417 | for (Export &E : Config->Exports) | |
| 1418 | maybeAddAddressTakenFunction(AddressTakenSyms, E.Sym); | |
| 1055 | 1419 | |
| 1056 | 1420 | // Ensure sections referenced in the gfid table are 16-byte aligned. |
| 1057 | 1421 | for (const ChunkAndOffset &C : AddressTakenSyms) |
| ... | ... | @@ -1087,7 +1451,7 @@ void Writer::markSymbolsForRVATable(ObjFile *File, |
| 1087 | 1451 | // is associated with something like a vtable and the vtable is discarded. |
| 1088 | 1452 | // In this case, the associated gfids section is discarded, and we don't |
| 1089 | 1453 | // mark the virtual member functions as address-taken by the vtable. |
| 1090 | if (!C->isLive()) | |
| 1454 | if (!C->Live) | |
| 1091 | 1455 | continue; |
| 1092 | 1456 | |
| 1093 | 1457 | // Validate that the contents look like symbol table indices. |
| ... | ... | @@ -1134,6 +1498,56 @@ void Writer::maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym, |
| 1134 | 1498 | cast<DefinedAbsolute>(C)->setVA(TableChunk->getSize() / 4); |
| 1135 | 1499 | } |
| 1136 | 1500 | |
| 1501 | // MinGW specific. Gather all relocations that are imported from a DLL even | |
| 1502 | // though the code didn't expect it to, produce the table that the runtime | |
| 1503 | // uses for fixing them up, and provide the synthetic symbols that the | |
| 1504 | // runtime uses for finding the table. | |
| 1505 | void Writer::createRuntimePseudoRelocs() { | |
| 1506 | std::vector<RuntimePseudoReloc> Rels; | |
| 1507 | ||
| 1508 | for (Chunk *C : Symtab->getChunks()) { | |
| 1509 | auto *SC = dyn_cast<SectionChunk>(C); | |
| 1510 | if (!SC || !SC->Live) | |
| 1511 | continue; | |
| 1512 | SC->getRuntimePseudoRelocs(Rels); | |
| 1513 | } | |
| 1514 | ||
| 1515 | if (!Rels.empty()) | |
| 1516 | log("Writing " + Twine(Rels.size()) + " runtime pseudo relocations"); | |
| 1517 | PseudoRelocTableChunk *Table = make<PseudoRelocTableChunk>(Rels); | |
| 1518 | RdataSec->addChunk(Table); | |
| 1519 | EmptyChunk *EndOfList = make<EmptyChunk>(); | |
| 1520 | RdataSec->addChunk(EndOfList); | |
| 1521 | ||
| 1522 | Symbol *HeadSym = Symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__"); | |
| 1523 | Symbol *EndSym = Symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__"); | |
| 1524 | replaceSymbol<DefinedSynthetic>(HeadSym, HeadSym->getName(), Table); | |
| 1525 | replaceSymbol<DefinedSynthetic>(EndSym, EndSym->getName(), EndOfList); | |
| 1526 | } | |
| 1527 | ||
| 1528 | // MinGW specific. | |
| 1529 | // The MinGW .ctors and .dtors lists have sentinels at each end; | |
| 1530 | // a (uintptr_t)-1 at the start and a (uintptr_t)0 at the end. | |
| 1531 | // There's a symbol pointing to the start sentinel pointer, __CTOR_LIST__ | |
| 1532 | // and __DTOR_LIST__ respectively. | |
| 1533 | void Writer::insertCtorDtorSymbols() { | |
| 1534 | AbsolutePointerChunk *CtorListHead = make<AbsolutePointerChunk>(-1); | |
| 1535 | AbsolutePointerChunk *CtorListEnd = make<AbsolutePointerChunk>(0); | |
| 1536 | AbsolutePointerChunk *DtorListHead = make<AbsolutePointerChunk>(-1); | |
| 1537 | AbsolutePointerChunk *DtorListEnd = make<AbsolutePointerChunk>(0); | |
| 1538 | CtorsSec->insertChunkAtStart(CtorListHead); | |
| 1539 | CtorsSec->addChunk(CtorListEnd); | |
| 1540 | DtorsSec->insertChunkAtStart(DtorListHead); | |
| 1541 | DtorsSec->addChunk(DtorListEnd); | |
| 1542 | ||
| 1543 | Symbol *CtorListSym = Symtab->findUnderscore("__CTOR_LIST__"); | |
| 1544 | Symbol *DtorListSym = Symtab->findUnderscore("__DTOR_LIST__"); | |
| 1545 | replaceSymbol<DefinedSynthetic>(CtorListSym, CtorListSym->getName(), | |
| 1546 | CtorListHead); | |
| 1547 | replaceSymbol<DefinedSynthetic>(DtorListSym, DtorListSym->getName(), | |
| 1548 | DtorListHead); | |
| 1549 | } | |
| 1550 | ||
| 1137 | 1551 | // Handles /section options to allow users to overwrite |
| 1138 | 1552 | // section attributes. |
| 1139 | 1553 | void Writer::setSectionPermissions() { |
| ... | ... | @@ -1160,7 +1574,7 @@ void Writer::writeSections() { |
| 1160 | 1574 | // ADD instructions). |
| 1161 | 1575 | if (Sec->Header.Characteristics & IMAGE_SCN_CNT_CODE) |
| 1162 | 1576 | memset(SecBuf, 0xCC, Sec->getRawSize()); |
| 1163 | for_each(parallel::par, Sec->getChunks().begin(), Sec->getChunks().end(), | |
| 1577 | for_each(parallel::par, Sec->Chunks.begin(), Sec->Chunks.end(), | |
| 1164 | 1578 | [&](Chunk *C) { C->writeTo(SecBuf); }); |
| 1165 | 1579 | } |
| 1166 | 1580 | } |
| ... | ... | @@ -1171,25 +1585,10 @@ void Writer::writeBuildId() { |
| 1171 | 1585 | // timestamp as well as a Guid and Age of the PDB. |
| 1172 | 1586 | // 2) In all cases, the PE COFF file header also contains a timestamp. |
| 1173 | 1587 | // For reproducibility, instead of a timestamp we want to use a hash of the |
| 1174 | // binary, however when building with debug info the hash needs to take into | |
| 1175 | // account the debug info, since it's possible to add blank lines to a file | |
| 1176 | // which causes the debug info to change but not the generated code. | |
| 1177 | // | |
| 1178 | // To handle this, we first set the Guid and Age in the debug directory (but | |
| 1179 | // only if we're doing a debug build). Then, we hash the binary (thus causing | |
| 1180 | // the hash to change if only the debug info changes, since the Age will be | |
| 1181 | // different). Finally, we write that hash into the debug directory (if | |
| 1182 | // present) as well as the COFF file header (always). | |
| 1588 | // PE contents. | |
| 1183 | 1589 | if (Config->Debug) { |
| 1184 | 1590 | assert(BuildId && "BuildId is not set!"); |
| 1185 | if (PreviousBuildId.hasValue()) { | |
| 1186 | *BuildId->BuildId = *PreviousBuildId; | |
| 1187 | BuildId->BuildId->PDB70.Age = BuildId->BuildId->PDB70.Age + 1; | |
| 1188 | } else { | |
| 1189 | BuildId->BuildId->Signature.CVSignature = OMF::Signature::PDB70; | |
| 1190 | BuildId->BuildId->PDB70.Age = 1; | |
| 1191 | llvm::getRandomBytes(BuildId->BuildId->PDB70.Signature, 16); | |
| 1192 | } | |
| 1591 | // BuildId->BuildId was filled in when the PDB was written. | |
| 1193 | 1592 | } |
| 1194 | 1593 | |
| 1195 | 1594 | // At this point the only fields in the COFF file which remain unset are the |
| ... | ... | @@ -1201,8 +1600,25 @@ void Writer::writeBuildId() { |
| 1201 | 1600 | Buffer->getBufferSize()); |
| 1202 | 1601 | |
| 1203 | 1602 | uint32_t Timestamp = Config->Timestamp; |
| 1603 | uint64_t Hash = 0; | |
| 1604 | bool GenerateSyntheticBuildId = | |
| 1605 | Config->MinGW && Config->Debug && Config->PDBPath.empty(); | |
| 1606 | ||
| 1607 | if (Config->Repro || GenerateSyntheticBuildId) | |
| 1608 | Hash = xxHash64(OutputFileData); | |
| 1609 | ||
| 1204 | 1610 | if (Config->Repro) |
| 1205 | Timestamp = static_cast<uint32_t>(xxHash64(OutputFileData)); | |
| 1611 | Timestamp = static_cast<uint32_t>(Hash); | |
| 1612 | ||
| 1613 | if (GenerateSyntheticBuildId) { | |
| 1614 | // For MinGW builds without a PDB file, we still generate a build id | |
| 1615 | // to allow associating a crash dump to the executable. | |
| 1616 | BuildId->BuildId->PDB70.CVSignature = OMF::Signature::PDB70; | |
| 1617 | BuildId->BuildId->PDB70.Age = 1; | |
| 1618 | memcpy(BuildId->BuildId->PDB70.Signature, &Hash, 8); | |
| 1619 | // xxhash only gives us 8 bytes, so put some fixed data in the other half. | |
| 1620 | memcpy(&BuildId->BuildId->PDB70.Signature[8], "LLD PDB.", 8); | |
| 1621 | } | |
| 1206 | 1622 | |
| 1207 | 1623 | if (DebugDirectory) |
| 1208 | 1624 | DebugDirectory->setTimeDateStamp(Timestamp); |
| ... | ... | @@ -1240,6 +1656,42 @@ void Writer::sortExceptionTable() { |
| 1240 | 1656 | errs() << "warning: don't know how to handle .pdata.\n"; |
| 1241 | 1657 | } |
| 1242 | 1658 | |
| 1659 | // The CRT section contains, among other things, the array of function | |
| 1660 | // pointers that initialize every global variable that is not trivially | |
| 1661 | // constructed. The CRT calls them one after the other prior to invoking | |
| 1662 | // main(). | |
| 1663 | // | |
| 1664 | // As per C++ spec, 3.6.2/2.3, | |
| 1665 | // "Variables with ordered initialization defined within a single | |
| 1666 | // translation unit shall be initialized in the order of their definitions | |
| 1667 | // in the translation unit" | |
| 1668 | // | |
| 1669 | // It is therefore critical to sort the chunks containing the function | |
| 1670 | // pointers in the order that they are listed in the object file (top to | |
| 1671 | // bottom), otherwise global objects might not be initialized in the | |
| 1672 | // correct order. | |
| 1673 | void Writer::sortCRTSectionChunks(std::vector<Chunk *> &Chunks) { | |
| 1674 | auto SectionChunkOrder = [](const Chunk *A, const Chunk *B) { | |
| 1675 | auto SA = dyn_cast<SectionChunk>(A); | |
| 1676 | auto SB = dyn_cast<SectionChunk>(B); | |
| 1677 | assert(SA && SB && "Non-section chunks in CRT section!"); | |
| 1678 | ||
| 1679 | StringRef SAObj = SA->File->MB.getBufferIdentifier(); | |
| 1680 | StringRef SBObj = SB->File->MB.getBufferIdentifier(); | |
| 1681 | ||
| 1682 | return SAObj == SBObj && SA->getSectionNumber() < SB->getSectionNumber(); | |
| 1683 | }; | |
| 1684 | std::stable_sort(Chunks.begin(), Chunks.end(), SectionChunkOrder); | |
| 1685 | ||
| 1686 | if (Config->Verbose) { | |
| 1687 | for (auto &C : Chunks) { | |
| 1688 | auto SC = dyn_cast<SectionChunk>(C); | |
| 1689 | log(" " + SC->File->MB.getBufferIdentifier().str() + | |
| 1690 | ", SectionID: " + Twine(SC->getSectionNumber())); | |
| 1691 | } | |
| 1692 | } | |
| 1693 | } | |
| 1694 | ||
| 1243 | 1695 | OutputSection *Writer::findSection(StringRef Name) { |
| 1244 | 1696 | for (OutputSection *Sec : OutputSections) |
| 1245 | 1697 | if (Sec->Name == Name) |
| ... | ... | @@ -1259,12 +1711,13 @@ uint32_t Writer::getSizeOfInitializedData() { |
| 1259 | 1711 | void Writer::addBaserels() { |
| 1260 | 1712 | if (!Config->Relocatable) |
| 1261 | 1713 | return; |
| 1714 | RelocSec->Chunks.clear(); | |
| 1262 | 1715 | std::vector<Baserel> V; |
| 1263 | 1716 | for (OutputSection *Sec : OutputSections) { |
| 1264 | 1717 | if (Sec->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) |
| 1265 | 1718 | continue; |
| 1266 | 1719 | // Collect all locations for base relocations. |
| 1267 | for (Chunk *C : Sec->getChunks()) | |
| 1720 | for (Chunk *C : Sec->Chunks) | |
| 1268 | 1721 | C->getBaserels(&V); |
| 1269 | 1722 | // Add the addresses to .reloc section. |
| 1270 | 1723 | if (!V.empty()) |
deps/lld/COFF/Writer.h+4-2| ... | ... | @@ -34,8 +34,8 @@ public: |
| 34 | 34 | Header.Characteristics = Chars; |
| 35 | 35 | } |
| 36 | 36 | void addChunk(Chunk *C); |
| 37 | void insertChunkAtStart(Chunk *C); | |
| 37 | 38 | void merge(OutputSection *Other); |
| 38 | ArrayRef<Chunk *> getChunks() { return Chunks; } | |
| 39 | 39 | void addPermissions(uint32_t C); |
| 40 | 40 | void setPermissions(uint32_t C); |
| 41 | 41 | uint64_t getRVA() { return Header.VirtualAddress; } |
| ... | ... | @@ -62,9 +62,11 @@ public: |
| 62 | 62 | llvm::StringRef Name; |
| 63 | 63 | llvm::object::coff_section Header = {}; |
| 64 | 64 | |
| 65 | std::vector<Chunk *> Chunks; | |
| 66 | std::vector<Chunk *> OrigChunks; | |
| 67 | ||
| 65 | 68 | private: |
| 66 | 69 | uint32_t StringTableOff = 0; |
| 67 | std::vector<Chunk *> Chunks; | |
| 68 | 70 | }; |
| 69 | 71 | |
| 70 | 72 | } |
deps/lld/Common/Args.cpp+8-1| ... | ... | @@ -13,6 +13,7 @@ |
| 13 | 13 | #include "llvm/ADT/StringExtras.h" |
| 14 | 14 | #include "llvm/ADT/StringRef.h" |
| 15 | 15 | #include "llvm/Option/ArgList.h" |
| 16 | #include "llvm/Support/Path.h" | |
| 16 | 17 | |
| 17 | 18 | using namespace llvm; |
| 18 | 19 | using namespace lld; |
| ... | ... | @@ -40,7 +41,7 @@ std::vector<StringRef> lld::args::getStrings(opt::InputArgList &Args, int Id) { |
| 40 | 41 | |
| 41 | 42 | uint64_t lld::args::getZOptionValue(opt::InputArgList &Args, int Id, |
| 42 | 43 | StringRef Key, uint64_t Default) { |
| 43 | for (auto *Arg : Args.filtered(Id)) { | |
| 44 | for (auto *Arg : Args.filtered_reverse(Id)) { | |
| 44 | 45 | std::pair<StringRef, StringRef> KV = StringRef(Arg->getValue()).split('='); |
| 45 | 46 | if (KV.first == Key) { |
| 46 | 47 | uint64_t Result = Default; |
| ... | ... | @@ -64,3 +65,9 @@ std::vector<StringRef> lld::args::getLines(MemoryBufferRef MB) { |
| 64 | 65 | } |
| 65 | 66 | return Ret; |
| 66 | 67 | } |
| 68 | ||
| 69 | StringRef lld::args::getFilenameWithoutExe(StringRef Path) { | |
| 70 | if (Path.endswith_lower(".exe")) | |
| 71 | return sys::path::stem(Path); | |
| 72 | return sys::path::filename(Path); | |
| 73 | } |
deps/lld/Common/ErrorHandler.cpp+3-2| ... | ... | @@ -47,8 +47,9 @@ ErrorHandler &lld::errorHandler() { |
| 47 | 47 | } |
| 48 | 48 | |
| 49 | 49 | void lld::exitLld(int Val) { |
| 50 | // Delete the output buffer so that any tempory file is deleted. | |
| 51 | errorHandler().OutputBuffer.reset(); | |
| 50 | // Delete any temporary file, while keeping the memory mapping open. | |
| 51 | if (errorHandler().OutputBuffer) | |
| 52 | errorHandler().OutputBuffer->discard(); | |
| 52 | 53 | |
| 53 | 54 | // Dealloc/destroy ManagedStatic variables before calling |
| 54 | 55 | // _exit(). In a non-LTO build, this is a nop. In an LTO |
deps/lld/Common/Strings.cpp+14-19| ... | ... | @@ -16,14 +16,6 @@ |
| 16 | 16 | #include <mutex> |
| 17 | 17 | #include <vector> |
| 18 | 18 | |
| 19 | #if defined(_MSC_VER) | |
| 20 | #include <Windows.h> | |
| 21 | ||
| 22 | // DbgHelp.h must be included after Windows.h. | |
| 23 | #include <DbgHelp.h> | |
| 24 | #pragma comment(lib, "dbghelp.lib") | |
| 25 | #endif | |
| 26 | ||
| 27 | 19 | using namespace llvm; |
| 28 | 20 | using namespace lld; |
| 29 | 21 | |
| ... | ... | @@ -45,18 +37,21 @@ Optional<std::string> lld::demangleItanium(StringRef Name) { |
| 45 | 37 | return S; |
| 46 | 38 | } |
| 47 | 39 | |
| 48 | Optional<std::string> lld::demangleMSVC(StringRef S) { | |
| 49 | #if defined(_MSC_VER) | |
| 50 | // UnDecorateSymbolName is not thread-safe, so we need a mutex. | |
| 51 | static std::mutex Mu; | |
| 52 | std::lock_guard<std::mutex> Lock(Mu); | |
| 40 | Optional<std::string> lld::demangleMSVC(StringRef Name) { | |
| 41 | std::string Prefix; | |
| 42 | if (Name.consume_front("__imp_")) | |
| 43 | Prefix = "__declspec(dllimport) "; | |
| 44 | ||
| 45 | // Demangle only C++ names. | |
| 46 | if (!Name.startswith("?")) | |
| 47 | return None; | |
| 53 | 48 | |
| 54 | char Buf[4096]; | |
| 55 | if (S.startswith("?")) | |
| 56 | if (size_t Len = UnDecorateSymbolName(S.str().c_str(), Buf, sizeof(Buf), 0)) | |
| 57 | return std::string(Buf, Len); | |
| 58 | #endif | |
| 59 | return None; | |
| 49 | char *Buf = microsoftDemangle(Name.str().c_str(), nullptr, nullptr, nullptr); | |
| 50 | if (!Buf) | |
| 51 | return None; | |
| 52 | std::string S(Buf); | |
| 53 | free(Buf); | |
| 54 | return Prefix + S; | |
| 60 | 55 | } |
| 61 | 56 | |
| 62 | 57 | StringMatcher::StringMatcher(ArrayRef<StringRef> Pat) { |
deps/lld/Common/TargetOptionsCommandFlags.cpp+1| ... | ... | @@ -32,3 +32,4 @@ llvm::Optional<llvm::CodeModel::Model> lld::GetCodeModelFromCMModel() { |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | 34 | std::string lld::GetCPUStr() { return ::getCPUStr(); } |
| 35 | std::vector<std::string> lld::GetMAttrs() { return ::MAttrs; } |
deps/lld/ELF/AArch64ErrataFix.cpp+16-11| ... | ... | @@ -356,7 +356,7 @@ static uint64_t scanCortexA53Errata843419(InputSection *IS, uint64_t &Off, |
| 356 | 356 | } |
| 357 | 357 | |
| 358 | 358 | uint64_t PatchOff = 0; |
| 359 | const uint8_t *Buf = IS->Data.begin(); | |
| 359 | const uint8_t *Buf = IS->data().begin(); | |
| 360 | 360 | const ulittle32_t *InstBuf = reinterpret_cast<const ulittle32_t *>(Buf + Off); |
| 361 | 361 | uint32_t Instr1 = *InstBuf++; |
| 362 | 362 | uint32_t Instr2 = *InstBuf++; |
| ... | ... | @@ -411,7 +411,7 @@ uint64_t lld::elf::Patch843419Section::getLDSTAddr() const { |
| 411 | 411 | void lld::elf::Patch843419Section::writeTo(uint8_t *Buf) { |
| 412 | 412 | // Copy the instruction that we will be replacing with a branch in the |
| 413 | 413 | // Patchee Section. |
| 414 | write32le(Buf, read32le(Patchee->Data.begin() + PatcheeOffset)); | |
| 414 | write32le(Buf, read32le(Patchee->data().begin() + PatcheeOffset)); | |
| 415 | 415 | |
| 416 | 416 | // Apply any relocation transferred from the original PatcheeSection. |
| 417 | 417 | // For a SyntheticSection Buf already has OutSecOff added, but relocateAlloc |
| ... | ... | @@ -451,7 +451,7 @@ void AArch64Err843419Patcher::init() { |
| 451 | 451 | continue; |
| 452 | 452 | if (!IsCodeMapSymbol(Def) && !IsDataMapSymbol(Def)) |
| 453 | 453 | continue; |
| 454 | if (auto *Sec = dyn_cast<InputSection>(Def->Section)) | |
| 454 | if (auto *Sec = dyn_cast_or_null<InputSection>(Def->Section)) | |
| 455 | 455 | if (Sec->Flags & SHF_EXECINSTR) |
| 456 | 456 | SectionMap[Sec].push_back(Def); |
| 457 | 457 | } |
| ... | ... | @@ -487,7 +487,8 @@ void AArch64Err843419Patcher::insertPatches( |
| 487 | 487 | InputSectionDescription &ISD, std::vector<Patch843419Section *> &Patches) { |
| 488 | 488 | uint64_t ISLimit; |
| 489 | 489 | uint64_t PrevISLimit = ISD.Sections.front()->OutSecOff; |
| 490 | uint64_t PatchUpperBound = PrevISLimit + Target->ThunkSectionSpacing; | |
| 490 | uint64_t PatchUpperBound = PrevISLimit + Target->getThunkSectionSpacing(); | |
| 491 | uint64_t OutSecAddr = ISD.Sections.front()->getParent()->Addr; | |
| 491 | 492 | |
| 492 | 493 | // Set the OutSecOff of patches to the place where we want to insert them. |
| 493 | 494 | // We use a similar strategy to Thunk placement. Place patches roughly |
| ... | ... | @@ -498,12 +499,12 @@ void AArch64Err843419Patcher::insertPatches( |
| 498 | 499 | ISLimit = IS->OutSecOff + IS->getSize(); |
| 499 | 500 | if (ISLimit > PatchUpperBound) { |
| 500 | 501 | while (PatchIt != PatchEnd) { |
| 501 | if ((*PatchIt)->getLDSTAddr() >= PrevISLimit) | |
| 502 | if ((*PatchIt)->getLDSTAddr() - OutSecAddr >= PrevISLimit) | |
| 502 | 503 | break; |
| 503 | 504 | (*PatchIt)->OutSecOff = PrevISLimit; |
| 504 | 505 | ++PatchIt; |
| 505 | 506 | } |
| 506 | PatchUpperBound = PrevISLimit + Target->ThunkSectionSpacing; | |
| 507 | PatchUpperBound = PrevISLimit + Target->getThunkSectionSpacing(); | |
| 507 | 508 | } |
| 508 | 509 | PrevISLimit = ISLimit; |
| 509 | 510 | } |
| ... | ... | @@ -538,20 +539,24 @@ static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset, |
| 538 | 539 | InputSection *IS, |
| 539 | 540 | std::vector<Patch843419Section *> &Patches) { |
| 540 | 541 | // There may be a relocation at the same offset that we are patching. There |
| 541 | // are three cases that we need to consider. | |
| 542 | // are four cases that we need to consider. | |
| 542 | 543 | // Case 1: R_AARCH64_JUMP26 branch relocation. We have already patched this |
| 543 | 544 | // instance of the erratum on a previous patch and altered the relocation. We |
| 544 | 545 | // have nothing more to do. |
| 545 | // Case 2: A load/store register (unsigned immediate) class relocation. There | |
| 546 | // Case 2: A TLS Relaxation R_RELAX_TLS_IE_TO_LE. In this case the ADRP that | |
| 547 | // we read will be transformed into a MOVZ later so we actually don't match | |
| 548 | // the sequence and have nothing more to do. | |
| 549 | // Case 3: A load/store register (unsigned immediate) class relocation. There | |
| 546 | 550 | // are two of these R_AARCH_LD64_ABS_LO12_NC and R_AARCH_LD64_GOT_LO12_NC and |
| 547 | 551 | // they are both absolute. We need to add the same relocation to the patch, |
| 548 | 552 | // and replace the relocation with a R_AARCH_JUMP26 branch relocation. |
| 549 | // Case 3: No relocation. We must create a new R_AARCH64_JUMP26 branch | |
| 553 | // Case 4: No relocation. We must create a new R_AARCH64_JUMP26 branch | |
| 550 | 554 | // relocation at the offset. |
| 551 | 555 | auto RelIt = std::find_if( |
| 552 | 556 | IS->Relocations.begin(), IS->Relocations.end(), |
| 553 | 557 | [=](const Relocation &R) { return R.Offset == PatcheeOffset; }); |
| 554 | if (RelIt != IS->Relocations.end() && RelIt->Type == R_AARCH64_JUMP26) | |
| 558 | if (RelIt != IS->Relocations.end() && | |
| 559 | (RelIt->Type == R_AARCH64_JUMP26 || RelIt->Expr == R_RELAX_TLS_IE_TO_LE)) | |
| 555 | 560 | return; |
| 556 | 561 | |
| 557 | 562 | log("detected cortex-a53-843419 erratum sequence starting at " + |
| ... | ... | @@ -598,7 +603,7 @@ AArch64Err843419Patcher::patchInputSectionDescription( |
| 598 | 603 | auto DataSym = std::next(CodeSym); |
| 599 | 604 | uint64_t Off = (*CodeSym)->Value; |
| 600 | 605 | uint64_t Limit = |
| 601 | (DataSym == MapSyms.end()) ? IS->Data.size() : (*DataSym)->Value; | |
| 606 | (DataSym == MapSyms.end()) ? IS->data().size() : (*DataSym)->Value; | |
| 602 | 607 | |
| 603 | 608 | while (Off < Limit) { |
| 604 | 609 | uint64_t StartAddr = IS->getVA(Off); |
deps/lld/ELF/Arch/AArch64.cpp+21-16| ... | ... | @@ -41,6 +41,7 @@ public: |
| 41 | 41 | int32_t Index, unsigned RelOff) const override; |
| 42 | 42 | bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 43 | 43 | uint64_t BranchAddr, const Symbol &S) const override; |
| 44 | uint32_t getThunkSectionSpacing() const override; | |
| 44 | 45 | bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; |
| 45 | 46 | bool usesOnlyLowPageBits(RelType Type) const override; |
| 46 | 47 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| ... | ... | @@ -57,6 +58,7 @@ AArch64::AArch64() { |
| 57 | 58 | RelativeRel = R_AARCH64_RELATIVE; |
| 58 | 59 | IRelativeRel = R_AARCH64_IRELATIVE; |
| 59 | 60 | GotRel = R_AARCH64_GLOB_DAT; |
| 61 | NoneRel = R_AARCH64_NONE; | |
| 60 | 62 | PltRel = R_AARCH64_JUMP_SLOT; |
| 61 | 63 | TlsDescRel = R_AARCH64_TLSDESC; |
| 62 | 64 | TlsGotRel = R_AARCH64_TLS_TPREL64; |
| ... | ... | @@ -66,22 +68,18 @@ AArch64::AArch64() { |
| 66 | 68 | PltHeaderSize = 32; |
| 67 | 69 | DefaultMaxPageSize = 65536; |
| 68 | 70 | |
| 69 | // It doesn't seem to be documented anywhere, but tls on aarch64 uses variant | |
| 70 | // 1 of the tls structures and the tcb size is 16. | |
| 71 | TcbSize = 16; | |
| 72 | NeedsThunks = true; | |
| 71 | // Align to the 2 MiB page size (known as a superpage or huge page). | |
| 72 | // FreeBSD automatically promotes 2 MiB-aligned allocations. | |
| 73 | DefaultImageBase = 0x200000; | |
| 73 | 74 | |
| 74 | // See comment in Arch/ARM.cpp for a more detailed explanation of | |
| 75 | // ThunkSectionSpacing. For AArch64 the only branches we are permitted to | |
| 76 | // Thunk have a range of +/- 128 MiB | |
| 77 | ThunkSectionSpacing = (128 * 1024 * 1024) - 0x30000; | |
| 75 | NeedsThunks = true; | |
| 78 | 76 | } |
| 79 | 77 | |
| 80 | 78 | RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S, |
| 81 | 79 | const uint8_t *Loc) const { |
| 82 | 80 | switch (Type) { |
| 83 | 81 | case R_AARCH64_TLSDESC_ADR_PAGE21: |
| 84 | return R_TLSDESC_PAGE; | |
| 82 | return R_AARCH64_TLSDESC_PAGE; | |
| 85 | 83 | case R_AARCH64_TLSDESC_LD64_LO12: |
| 86 | 84 | case R_AARCH64_TLSDESC_ADD_LO12: |
| 87 | 85 | return R_TLSDESC; |
| ... | ... | @@ -107,13 +105,13 @@ RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S, |
| 107 | 105 | case R_AARCH64_LD_PREL_LO19: |
| 108 | 106 | return R_PC; |
| 109 | 107 | case R_AARCH64_ADR_PREL_PG_HI21: |
| 110 | return R_PAGE_PC; | |
| 108 | return R_AARCH64_PAGE_PC; | |
| 111 | 109 | case R_AARCH64_LD64_GOT_LO12_NC: |
| 112 | 110 | case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC: |
| 113 | 111 | return R_GOT; |
| 114 | 112 | case R_AARCH64_ADR_GOT_PAGE: |
| 115 | 113 | case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21: |
| 116 | return R_GOT_PAGE_PC; | |
| 114 | return R_AARCH64_GOT_PAGE_PC; | |
| 117 | 115 | case R_AARCH64_NONE: |
| 118 | 116 | return R_NONE; |
| 119 | 117 | default: |
| ... | ... | @@ -125,7 +123,7 @@ RelExpr AArch64::adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 125 | 123 | RelExpr Expr) const { |
| 126 | 124 | if (Expr == R_RELAX_TLS_GD_TO_IE) { |
| 127 | 125 | if (Type == R_AARCH64_TLSDESC_ADR_PAGE21) |
| 128 | return R_RELAX_TLS_GD_TO_IE_PAGE_PC; | |
| 126 | return R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC; | |
| 129 | 127 | return R_RELAX_TLS_GD_TO_IE_ABS; |
| 130 | 128 | } |
| 131 | 129 | return Expr; |
| ... | ... | @@ -156,7 +154,7 @@ RelType AArch64::getDynRel(RelType Type) const { |
| 156 | 154 | } |
| 157 | 155 | |
| 158 | 156 | void AArch64::writeGotPlt(uint8_t *Buf, const Symbol &) const { |
| 159 | write64le(Buf, InX::Plt->getVA()); | |
| 157 | write64le(Buf, In.Plt->getVA()); | |
| 160 | 158 | } |
| 161 | 159 | |
| 162 | 160 | void AArch64::writePltHeader(uint8_t *Buf) const { |
| ... | ... | @@ -172,8 +170,8 @@ void AArch64::writePltHeader(uint8_t *Buf) const { |
| 172 | 170 | }; |
| 173 | 171 | memcpy(Buf, PltData, sizeof(PltData)); |
| 174 | 172 | |
| 175 | uint64_t Got = InX::GotPlt->getVA(); | |
| 176 | uint64_t Plt = InX::Plt->getVA(); | |
| 173 | uint64_t Got = In.GotPlt->getVA(); | |
| 174 | uint64_t Plt = In.Plt->getVA(); | |
| 177 | 175 | relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21, |
| 178 | 176 | getAArch64Page(Got + 16) - getAArch64Page(Plt + 4)); |
| 179 | 177 | relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16); |
| ... | ... | @@ -208,6 +206,13 @@ bool AArch64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 208 | 206 | return !inBranchRange(Type, BranchAddr, Dst); |
| 209 | 207 | } |
| 210 | 208 | |
| 209 | uint32_t AArch64::getThunkSectionSpacing() const { | |
| 210 | // See comment in Arch/ARM.cpp for a more detailed explanation of | |
| 211 | // getThunkSectionSpacing(). For AArch64 the only branches we are permitted to | |
| 212 | // Thunk have a range of +/- 128 MiB | |
| 213 | return (128 * 1024 * 1024) - 0x30000; | |
| 214 | } | |
| 215 | ||
| 211 | 216 | bool AArch64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { |
| 212 | 217 | if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) |
| 213 | 218 | return true; |
| ... | ... | @@ -338,7 +343,7 @@ void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 338 | 343 | or32le(Loc, (Val & 0xFFFC) << 3); |
| 339 | 344 | break; |
| 340 | 345 | case R_AARCH64_TLSLE_ADD_TPREL_HI12: |
| 341 | checkInt(Loc, Val, 24, Type); | |
| 346 | checkUInt(Loc, Val, 24, Type); | |
| 342 | 347 | or32AArch64Imm(Loc, Val >> 12); |
| 343 | 348 | break; |
| 344 | 349 | case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC: |
deps/lld/ELF/Arch/AMDGPU.cpp+1| ... | ... | @@ -35,6 +35,7 @@ public: |
| 35 | 35 | AMDGPU::AMDGPU() { |
| 36 | 36 | RelativeRel = R_AMDGPU_RELATIVE64; |
| 37 | 37 | GotRel = R_AMDGPU_ABS64; |
| 38 | NoneRel = R_AMDGPU_NONE; | |
| 38 | 39 | GotEntrySize = 8; |
| 39 | 40 | } |
| 40 | 41 |
deps/lld/ELF/Arch/ARM.cpp+76-48| ... | ... | @@ -40,6 +40,7 @@ public: |
| 40 | 40 | void addPltHeaderSymbols(InputSection &ISD) const override; |
| 41 | 41 | bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 42 | 42 | uint64_t BranchAddr, const Symbol &S) const override; |
| 43 | uint32_t getThunkSectionSpacing() const override; | |
| 43 | 44 | bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; |
| 44 | 45 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 45 | 46 | }; |
| ... | ... | @@ -50,6 +51,7 @@ ARM::ARM() { |
| 50 | 51 | RelativeRel = R_ARM_RELATIVE; |
| 51 | 52 | IRelativeRel = R_ARM_IRELATIVE; |
| 52 | 53 | GotRel = R_ARM_GLOB_DAT; |
| 54 | NoneRel = R_ARM_NONE; | |
| 53 | 55 | PltRel = R_ARM_JUMP_SLOT; |
| 54 | 56 | TlsGotRel = R_ARM_TLS_TPOFF32; |
| 55 | 57 | TlsModuleIndexRel = R_ARM_TLS_DTPMOD32; |
| ... | ... | @@ -59,41 +61,8 @@ ARM::ARM() { |
| 59 | 61 | GotPltEntrySize = 4; |
| 60 | 62 | PltEntrySize = 16; |
| 61 | 63 | PltHeaderSize = 32; |
| 62 | TrapInstr = 0xd4d4d4d4; | |
| 63 | // ARM uses Variant 1 TLS | |
| 64 | TcbSize = 8; | |
| 64 | TrapInstr = {0xd4, 0xd4, 0xd4, 0xd4}; | |
| 65 | 65 | NeedsThunks = true; |
| 66 | ||
| 67 | // The placing of pre-created ThunkSections is controlled by the | |
| 68 | // ThunkSectionSpacing parameter. The aim is to place the | |
| 69 | // ThunkSection such that all branches from the InputSections prior to the | |
| 70 | // ThunkSection can reach a Thunk placed at the end of the ThunkSection. | |
| 71 | // Graphically: | |
| 72 | // | up to ThunkSectionSpacing .text input sections | | |
| 73 | // | ThunkSection | | |
| 74 | // | up to ThunkSectionSpacing .text input sections | | |
| 75 | // | ThunkSection | | |
| 76 | ||
| 77 | // Pre-created ThunkSections are spaced roughly 16MiB apart on ARM. This is to | |
| 78 | // match the most common expected case of a Thumb 2 encoded BL, BLX or B.W | |
| 79 | // ARM B, BL, BLX range +/- 32MiB | |
| 80 | // Thumb B.W, BL, BLX range +/- 16MiB | |
| 81 | // Thumb B<cc>.W range +/- 1MiB | |
| 82 | // If a branch cannot reach a pre-created ThunkSection a new one will be | |
| 83 | // created so we can handle the rare cases of a Thumb 2 conditional branch. | |
| 84 | // We intentionally use a lower size for ThunkSectionSpacing than the maximum | |
| 85 | // branch range so the end of the ThunkSection is more likely to be within | |
| 86 | // range of the branch instruction that is furthest away. The value we shorten | |
| 87 | // ThunkSectionSpacing by is set conservatively to allow us to create 16,384 | |
| 88 | // 12 byte Thunks at any offset in a ThunkSection without risk of a branch to | |
| 89 | // one of the Thunks going out of range. | |
| 90 | ||
| 91 | // FIXME: lld assumes that the Thumb BL and BLX encoding permits the J1 and | |
| 92 | // J2 bits to be used to extend the branch range. On earlier Architectures | |
| 93 | // such as ARMv4, ARMv5 and ARMv6 (except ARMv6T2) the range is +/- 4MiB. If | |
| 94 | // support for the earlier encodings is added then when they are used the | |
| 95 | // ThunkSectionSpacing will need lowering. | |
| 96 | ThunkSectionSpacing = 0x1000000 - 0x30000; | |
| 97 | 66 | } |
| 98 | 67 | |
| 99 | 68 | uint32_t ARM::calcEFlags() const { |
| ... | ... | @@ -165,6 +134,12 @@ RelExpr ARM::getRelExpr(RelType Type, const Symbol &S, |
| 165 | 134 | return R_NONE; |
| 166 | 135 | case R_ARM_TLS_LE32: |
| 167 | 136 | return R_TLS; |
| 137 | case R_ARM_V4BX: | |
| 138 | // V4BX is just a marker to indicate there's a "bx rN" instruction at the | |
| 139 | // given address. It can be used to implement a special linker mode which | |
| 140 | // rewrites ARMv4T inputs to ARMv4. Since we support only ARMv4 input and | |
| 141 | // not ARMv4 output, we can just ignore it. | |
| 142 | return R_HINT; | |
| 168 | 143 | default: |
| 169 | 144 | return R_ABS; |
| 170 | 145 | } |
| ... | ... | @@ -177,7 +152,7 @@ RelType ARM::getDynRel(RelType Type) const { |
| 177 | 152 | } |
| 178 | 153 | |
| 179 | 154 | void ARM::writeGotPlt(uint8_t *Buf, const Symbol &) const { |
| 180 | write32le(Buf, InX::Plt->getVA()); | |
| 155 | write32le(Buf, In.Plt->getVA()); | |
| 181 | 156 | } |
| 182 | 157 | |
| 183 | 158 | void ARM::writeIgotPlt(uint8_t *Buf, const Symbol &S) const { |
| ... | ... | @@ -198,8 +173,8 @@ static void writePltHeaderLong(uint8_t *Buf) { |
| 198 | 173 | 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary |
| 199 | 174 | 0xd4, 0xd4, 0xd4, 0xd4}; |
| 200 | 175 | memcpy(Buf, PltData, sizeof(PltData)); |
| 201 | uint64_t GotPlt = InX::GotPlt->getVA(); | |
| 202 | uint64_t L1 = InX::Plt->getVA() + 8; | |
| 176 | uint64_t GotPlt = In.GotPlt->getVA(); | |
| 177 | uint64_t L1 = In.Plt->getVA() + 8; | |
| 203 | 178 | write32le(Buf + 16, GotPlt - L1 - 8); |
| 204 | 179 | } |
| 205 | 180 | |
| ... | ... | @@ -217,7 +192,7 @@ void ARM::writePltHeader(uint8_t *Buf) const { |
| 217 | 192 | 0xe5bef000, // ldr pc, [lr, #0x00000NNN] &(.got.plt -L1 - 4) |
| 218 | 193 | }; |
| 219 | 194 | |
| 220 | uint64_t Offset = InX::GotPlt->getVA() - InX::Plt->getVA() - 4; | |
| 195 | uint64_t Offset = In.GotPlt->getVA() - In.Plt->getVA() - 4; | |
| 221 | 196 | if (!llvm::isUInt<27>(Offset)) { |
| 222 | 197 | // We cannot encode the Offset, use the long form. |
| 223 | 198 | writePltHeaderLong(Buf); |
| ... | ... | @@ -227,10 +202,10 @@ void ARM::writePltHeader(uint8_t *Buf) const { |
| 227 | 202 | write32le(Buf + 4, PltData[1] | ((Offset >> 20) & 0xff)); |
| 228 | 203 | write32le(Buf + 8, PltData[2] | ((Offset >> 12) & 0xff)); |
| 229 | 204 | write32le(Buf + 12, PltData[3] | (Offset & 0xfff)); |
| 230 | write32le(Buf + 16, TrapInstr); // Pad to 32-byte boundary | |
| 231 | write32le(Buf + 20, TrapInstr); | |
| 232 | write32le(Buf + 24, TrapInstr); | |
| 233 | write32le(Buf + 28, TrapInstr); | |
| 205 | memcpy(Buf + 16, TrapInstr.data(), 4); // Pad to 32-byte boundary | |
| 206 | memcpy(Buf + 20, TrapInstr.data(), 4); | |
| 207 | memcpy(Buf + 24, TrapInstr.data(), 4); | |
| 208 | memcpy(Buf + 28, TrapInstr.data(), 4); | |
| 234 | 209 | } |
| 235 | 210 | |
| 236 | 211 | void ARM::addPltHeaderSymbols(InputSection &IS) const { |
| ... | ... | @@ -279,7 +254,7 @@ void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 279 | 254 | write32le(Buf + 0, PltData[0] | ((Offset >> 20) & 0xff)); |
| 280 | 255 | write32le(Buf + 4, PltData[1] | ((Offset >> 12) & 0xff)); |
| 281 | 256 | write32le(Buf + 8, PltData[2] | (Offset & 0xfff)); |
| 282 | write32le(Buf + 12, TrapInstr); // Pad to 16-byte boundary | |
| 257 | memcpy(Buf + 12, TrapInstr.data(), 4); // Pad to 16-byte boundary | |
| 283 | 258 | } |
| 284 | 259 | |
| 285 | 260 | void ARM::addPltSymbols(InputSection &IS, uint64_t Off) const { |
| ... | ... | @@ -324,6 +299,40 @@ bool ARM::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 324 | 299 | return false; |
| 325 | 300 | } |
| 326 | 301 | |
| 302 | uint32_t ARM::getThunkSectionSpacing() const { | |
| 303 | // The placing of pre-created ThunkSections is controlled by the value | |
| 304 | // ThunkSectionSpacing returned by getThunkSectionSpacing(). The aim is to | |
| 305 | // place the ThunkSection such that all branches from the InputSections | |
| 306 | // prior to the ThunkSection can reach a Thunk placed at the end of the | |
| 307 | // ThunkSection. Graphically: | |
| 308 | // | up to ThunkSectionSpacing .text input sections | | |
| 309 | // | ThunkSection | | |
| 310 | // | up to ThunkSectionSpacing .text input sections | | |
| 311 | // | ThunkSection | | |
| 312 | ||
| 313 | // Pre-created ThunkSections are spaced roughly 16MiB apart on ARMv7. This | |
| 314 | // is to match the most common expected case of a Thumb 2 encoded BL, BLX or | |
| 315 | // B.W: | |
| 316 | // ARM B, BL, BLX range +/- 32MiB | |
| 317 | // Thumb B.W, BL, BLX range +/- 16MiB | |
| 318 | // Thumb B<cc>.W range +/- 1MiB | |
| 319 | // If a branch cannot reach a pre-created ThunkSection a new one will be | |
| 320 | // created so we can handle the rare cases of a Thumb 2 conditional branch. | |
| 321 | // We intentionally use a lower size for ThunkSectionSpacing than the maximum | |
| 322 | // branch range so the end of the ThunkSection is more likely to be within | |
| 323 | // range of the branch instruction that is furthest away. The value we shorten | |
| 324 | // ThunkSectionSpacing by is set conservatively to allow us to create 16,384 | |
| 325 | // 12 byte Thunks at any offset in a ThunkSection without risk of a branch to | |
| 326 | // one of the Thunks going out of range. | |
| 327 | ||
| 328 | // On Arm the ThunkSectionSpacing depends on the range of the Thumb Branch | |
| 329 | // range. On earlier Architectures such as ARMv4, ARMv5 and ARMv6 (except | |
| 330 | // ARMv6T2) the range is +/- 4MiB. | |
| 331 | ||
| 332 | return (Config->ARMJ1J2BranchEncoding) ? 0x1000000 - 0x30000 | |
| 333 | : 0x400000 - 0x7500; | |
| 334 | } | |
| 335 | ||
| 327 | 336 | bool ARM::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { |
| 328 | 337 | uint64_t Range; |
| 329 | 338 | uint64_t InstrSize; |
| ... | ... | @@ -342,7 +351,7 @@ bool ARM::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { |
| 342 | 351 | break; |
| 343 | 352 | case R_ARM_THM_JUMP24: |
| 344 | 353 | case R_ARM_THM_CALL: |
| 345 | Range = 0x1000000; | |
| 354 | Range = Config->ARMJ1J2BranchEncoding ? 0x1000000 : 0x400000; | |
| 346 | 355 | InstrSize = 2; |
| 347 | 356 | break; |
| 348 | 357 | default: |
| ... | ... | @@ -447,11 +456,23 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 447 | 456 | } |
| 448 | 457 | // Bit 12 is 0 for BLX, 1 for BL |
| 449 | 458 | write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12); |
| 459 | if (!Config->ARMJ1J2BranchEncoding) { | |
| 460 | // Older Arm architectures do not support R_ARM_THM_JUMP24 and have | |
| 461 | // different encoding rules and range due to J1 and J2 always being 1. | |
| 462 | checkInt(Loc, Val, 23, Type); | |
| 463 | write16le(Loc, | |
| 464 | 0xf000 | // opcode | |
| 465 | ((Val >> 12) & 0x07ff)); // imm11 | |
| 466 | write16le(Loc + 2, | |
| 467 | (read16le(Loc + 2) & 0xd000) | // opcode | |
| 468 | 0x2800 | // J1 == J2 == 1 | |
| 469 | ((Val >> 1) & 0x07ff)); // imm11 | |
| 470 | break; | |
| 471 | } | |
| 450 | 472 | // Fall through as rest of encoding is the same as B.W |
| 451 | 473 | LLVM_FALLTHROUGH; |
| 452 | 474 | case R_ARM_THM_JUMP24: |
| 453 | 475 | // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0 |
| 454 | // FIXME: Use of I1 and I2 require v6T2ops | |
| 455 | 476 | checkInt(Loc, Val, 25, Type); |
| 456 | 477 | write16le(Loc, |
| 457 | 478 | 0xf000 | // opcode |
| ... | ... | @@ -470,14 +491,12 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 470 | 491 | break; |
| 471 | 492 | case R_ARM_MOVT_ABS: |
| 472 | 493 | case R_ARM_MOVT_PREL: |
| 473 | checkInt(Loc, Val, 32, Type); | |
| 474 | 494 | write32le(Loc, (read32le(Loc) & ~0x000f0fff) | |
| 475 | 495 | (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff)); |
| 476 | 496 | break; |
| 477 | 497 | case R_ARM_THM_MOVT_ABS: |
| 478 | 498 | case R_ARM_THM_MOVT_PREL: |
| 479 | 499 | // Encoding T1: A = imm4:i:imm3:imm8 |
| 480 | checkInt(Loc, Val, 32, Type); | |
| 481 | 500 | write16le(Loc, |
| 482 | 501 | 0xf2c0 | // opcode |
| 483 | 502 | ((Val >> 17) & 0x0400) | // i |
| ... | ... | @@ -542,10 +561,19 @@ int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const { |
| 542 | 561 | ((Lo & 0x07ff) << 1)); // imm11:0 |
| 543 | 562 | } |
| 544 | 563 | case R_ARM_THM_CALL: |
| 564 | if (!Config->ARMJ1J2BranchEncoding) { | |
| 565 | // Older Arm architectures do not support R_ARM_THM_JUMP24 and have | |
| 566 | // different encoding rules and range due to J1 and J2 always being 1. | |
| 567 | uint16_t Hi = read16le(Buf); | |
| 568 | uint16_t Lo = read16le(Buf + 2); | |
| 569 | return SignExtend64<22>(((Hi & 0x7ff) << 12) | // imm11 | |
| 570 | ((Lo & 0x7ff) << 1)); // imm11:0 | |
| 571 | break; | |
| 572 | } | |
| 573 | LLVM_FALLTHROUGH; | |
| 545 | 574 | case R_ARM_THM_JUMP24: { |
| 546 | 575 | // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0 |
| 547 | 576 | // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S) |
| 548 | // FIXME: I1 and I2 require v6T2ops | |
| 549 | 577 | uint16_t Hi = read16le(Buf); |
| 550 | 578 | uint16_t Lo = read16le(Buf + 2); |
| 551 | 579 | return SignExtend64<24>(((Hi & 0x0400) << 14) | // S |
deps/lld/ELF/Arch/AVR.cpp+3| ... | ... | @@ -43,12 +43,15 @@ using namespace lld::elf; |
| 43 | 43 | namespace { |
| 44 | 44 | class AVR final : public TargetInfo { |
| 45 | 45 | public: |
| 46 | AVR(); | |
| 46 | 47 | RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 47 | 48 | const uint8_t *Loc) const override; |
| 48 | 49 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 49 | 50 | }; |
| 50 | 51 | } // namespace |
| 51 | 52 | |
| 53 | AVR::AVR() { NoneRel = R_AVR_NONE; } | |
| 54 | ||
| 52 | 55 | RelExpr AVR::getRelExpr(RelType Type, const Symbol &S, |
| 53 | 56 | const uint8_t *Loc) const { |
| 54 | 57 | return R_ABS; |
deps/lld/ELF/Arch/Hexagon.cpp+192-3| ... | ... | @@ -9,6 +9,7 @@ |
| 9 | 9 | |
| 10 | 10 | #include "InputFiles.h" |
| 11 | 11 | #include "Symbols.h" |
| 12 | #include "SyntheticSections.h" | |
| 12 | 13 | #include "Target.h" |
| 13 | 14 | #include "lld/Common/ErrorHandler.h" |
| 14 | 15 | #include "llvm/BinaryFormat/ELF.h" |
| ... | ... | @@ -25,15 +26,48 @@ using namespace lld::elf; |
| 25 | 26 | namespace { |
| 26 | 27 | class Hexagon final : public TargetInfo { |
| 27 | 28 | public: |
| 29 | Hexagon(); | |
| 28 | 30 | uint32_t calcEFlags() const override; |
| 29 | 31 | RelExpr getRelExpr(RelType Type, const Symbol &S, |
| 30 | 32 | const uint8_t *Loc) const override; |
| 31 | 33 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 34 | void writePltHeader(uint8_t *Buf) const override; | |
| 35 | void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr, | |
| 36 | int32_t Index, unsigned RelOff) const override; | |
| 32 | 37 | }; |
| 33 | 38 | } // namespace |
| 34 | 39 | |
| 35 | // Support V60 only at the moment. | |
| 36 | uint32_t Hexagon::calcEFlags() const { return 0x60; } | |
| 40 | Hexagon::Hexagon() { | |
| 41 | PltRel = R_HEX_JMP_SLOT; | |
| 42 | RelativeRel = R_HEX_RELATIVE; | |
| 43 | GotRel = R_HEX_GLOB_DAT; | |
| 44 | GotEntrySize = 4; | |
| 45 | // The zero'th GOT entry is reserved for the address of _DYNAMIC. The | |
| 46 | // next 3 are reserved for the dynamic loader. | |
| 47 | GotPltHeaderEntriesNum = 4; | |
| 48 | GotPltEntrySize = 4; | |
| 49 | ||
| 50 | PltEntrySize = 16; | |
| 51 | PltHeaderSize = 32; | |
| 52 | ||
| 53 | // Hexagon Linux uses 64K pages by default. | |
| 54 | DefaultMaxPageSize = 0x10000; | |
| 55 | NoneRel = R_HEX_NONE; | |
| 56 | } | |
| 57 | ||
| 58 | uint32_t Hexagon::calcEFlags() const { | |
| 59 | assert(!ObjectFiles.empty()); | |
| 60 | ||
| 61 | // The architecture revision must always be equal to or greater than | |
| 62 | // greatest revision in the list of inputs. | |
| 63 | uint32_t Ret = 0; | |
| 64 | for (InputFile *F : ObjectFiles) { | |
| 65 | uint32_t EFlags = cast<ObjFile<ELF32LE>>(F)->getObj().getHeader()->e_flags; | |
| 66 | if (EFlags > Ret) | |
| 67 | Ret = EFlags; | |
| 68 | } | |
| 69 | return Ret; | |
| 70 | } | |
| 37 | 71 | |
| 38 | 72 | static uint32_t applyMask(uint32_t Mask, uint32_t Data) { |
| 39 | 73 | uint32_t Result = 0; |
| ... | ... | @@ -53,29 +87,143 @@ static uint32_t applyMask(uint32_t Mask, uint32_t Data) { |
| 53 | 87 | RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S, |
| 54 | 88 | const uint8_t *Loc) const { |
| 55 | 89 | switch (Type) { |
| 90 | case R_HEX_B9_PCREL: | |
| 91 | case R_HEX_B9_PCREL_X: | |
| 92 | case R_HEX_B13_PCREL: | |
| 56 | 93 | case R_HEX_B15_PCREL: |
| 57 | 94 | case R_HEX_B15_PCREL_X: |
| 95 | case R_HEX_6_PCREL_X: | |
| 96 | case R_HEX_32_PCREL: | |
| 97 | return R_PC; | |
| 58 | 98 | case R_HEX_B22_PCREL: |
| 99 | case R_HEX_PLT_B22_PCREL: | |
| 59 | 100 | case R_HEX_B22_PCREL_X: |
| 60 | 101 | case R_HEX_B32_PCREL_X: |
| 61 | return R_PC; | |
| 102 | return R_PLT_PC; | |
| 103 | case R_HEX_GOT_11_X: | |
| 104 | case R_HEX_GOT_16_X: | |
| 105 | case R_HEX_GOT_32_6_X: | |
| 106 | return R_HEXAGON_GOT; | |
| 62 | 107 | default: |
| 63 | 108 | return R_ABS; |
| 64 | 109 | } |
| 65 | 110 | } |
| 66 | 111 | |
| 112 | static uint32_t findMaskR6(uint32_t Insn) { | |
| 113 | // There are (arguably too) many relocation masks for the DSP's | |
| 114 | // R_HEX_6_X type. The table below is used to select the correct mask | |
| 115 | // for the given instruction. | |
| 116 | struct InstructionMask { | |
| 117 | uint32_t CmpMask; | |
| 118 | uint32_t RelocMask; | |
| 119 | }; | |
| 120 | ||
| 121 | static const InstructionMask R6[] = { | |
| 122 | {0x38000000, 0x0000201f}, {0x39000000, 0x0000201f}, | |
| 123 | {0x3e000000, 0x00001f80}, {0x3f000000, 0x00001f80}, | |
| 124 | {0x40000000, 0x000020f8}, {0x41000000, 0x000007e0}, | |
| 125 | {0x42000000, 0x000020f8}, {0x43000000, 0x000007e0}, | |
| 126 | {0x44000000, 0x000020f8}, {0x45000000, 0x000007e0}, | |
| 127 | {0x46000000, 0x000020f8}, {0x47000000, 0x000007e0}, | |
| 128 | {0x6a000000, 0x00001f80}, {0x7c000000, 0x001f2000}, | |
| 129 | {0x9a000000, 0x00000f60}, {0x9b000000, 0x00000f60}, | |
| 130 | {0x9c000000, 0x00000f60}, {0x9d000000, 0x00000f60}, | |
| 131 | {0x9f000000, 0x001f0100}, {0xab000000, 0x0000003f}, | |
| 132 | {0xad000000, 0x0000003f}, {0xaf000000, 0x00030078}, | |
| 133 | {0xd7000000, 0x006020e0}, {0xd8000000, 0x006020e0}, | |
| 134 | {0xdb000000, 0x006020e0}, {0xdf000000, 0x006020e0}}; | |
| 135 | ||
| 136 | // Duplex forms have a fixed mask and parse bits 15:14 are always | |
| 137 | // zero. Non-duplex insns will always have at least one bit set in the | |
| 138 | // parse field. | |
| 139 | if ((0xC000 & Insn) == 0x0) | |
| 140 | return 0x03f00000; | |
| 141 | ||
| 142 | for (InstructionMask I : R6) | |
| 143 | if ((0xff000000 & Insn) == I.CmpMask) | |
| 144 | return I.RelocMask; | |
| 145 | ||
| 146 | error("unrecognized instruction for R_HEX_6 relocation: 0x" + | |
| 147 | utohexstr(Insn)); | |
| 148 | return 0; | |
| 149 | } | |
| 150 | ||
| 151 | static uint32_t findMaskR8(uint32_t Insn) { | |
| 152 | if ((0xff000000 & Insn) == 0xde000000) | |
| 153 | return 0x00e020e8; | |
| 154 | if ((0xff000000 & Insn) == 0x3c000000) | |
| 155 | return 0x0000207f; | |
| 156 | return 0x00001fe0; | |
| 157 | } | |
| 158 | ||
| 159 | static uint32_t findMaskR11(uint32_t Insn) { | |
| 160 | if ((0xff000000 & Insn) == 0xa1000000) | |
| 161 | return 0x060020ff; | |
| 162 | return 0x06003fe0; | |
| 163 | } | |
| 164 | ||
| 165 | static uint32_t findMaskR16(uint32_t Insn) { | |
| 166 | if ((0xff000000 & Insn) == 0x48000000) | |
| 167 | return 0x061f20ff; | |
| 168 | if ((0xff000000 & Insn) == 0x49000000) | |
| 169 | return 0x061f3fe0; | |
| 170 | if ((0xff000000 & Insn) == 0x78000000) | |
| 171 | return 0x00df3fe0; | |
| 172 | if ((0xff000000 & Insn) == 0xb0000000) | |
| 173 | return 0x0fe03fe0; | |
| 174 | ||
| 175 | error("unrecognized instruction for R_HEX_16_X relocation: 0x" + | |
| 176 | utohexstr(Insn)); | |
| 177 | return 0; | |
| 178 | } | |
| 179 | ||
| 67 | 180 | static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); } |
| 68 | 181 | |
| 69 | 182 | void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 70 | 183 | switch (Type) { |
| 71 | 184 | case R_HEX_NONE: |
| 72 | 185 | break; |
| 186 | case R_HEX_6_PCREL_X: | |
| 187 | case R_HEX_6_X: | |
| 188 | or32le(Loc, applyMask(findMaskR6(read32le(Loc)), Val)); | |
| 189 | break; | |
| 190 | case R_HEX_8_X: | |
| 191 | or32le(Loc, applyMask(findMaskR8(read32le(Loc)), Val)); | |
| 192 | break; | |
| 193 | case R_HEX_9_X: | |
| 194 | or32le(Loc, applyMask(0x00003fe0, Val & 0x3f)); | |
| 195 | break; | |
| 196 | case R_HEX_10_X: | |
| 197 | or32le(Loc, applyMask(0x00203fe0, Val & 0x3f)); | |
| 198 | break; | |
| 199 | case R_HEX_11_X: | |
| 200 | case R_HEX_GOT_11_X: | |
| 201 | or32le(Loc, applyMask(findMaskR11(read32le(Loc)), Val & 0x3f)); | |
| 202 | break; | |
| 73 | 203 | case R_HEX_12_X: |
| 74 | 204 | or32le(Loc, applyMask(0x000007e0, Val)); |
| 75 | 205 | break; |
| 206 | case R_HEX_16_X: // These relocs only have 6 effective bits. | |
| 207 | case R_HEX_GOT_16_X: | |
| 208 | or32le(Loc, applyMask(findMaskR16(read32le(Loc)), Val & 0x3f)); | |
| 209 | break; | |
| 210 | case R_HEX_32: | |
| 211 | case R_HEX_32_PCREL: | |
| 212 | or32le(Loc, Val); | |
| 213 | break; | |
| 76 | 214 | case R_HEX_32_6_X: |
| 215 | case R_HEX_GOT_32_6_X: | |
| 77 | 216 | or32le(Loc, applyMask(0x0fff3fff, Val >> 6)); |
| 78 | 217 | break; |
| 218 | case R_HEX_B9_PCREL: | |
| 219 | or32le(Loc, applyMask(0x003000fe, Val >> 2)); | |
| 220 | break; | |
| 221 | case R_HEX_B9_PCREL_X: | |
| 222 | or32le(Loc, applyMask(0x003000fe, Val & 0x3f)); | |
| 223 | break; | |
| 224 | case R_HEX_B13_PCREL: | |
| 225 | or32le(Loc, applyMask(0x00202ffe, Val >> 2)); | |
| 226 | break; | |
| 79 | 227 | case R_HEX_B15_PCREL: |
| 80 | 228 | or32le(Loc, applyMask(0x00df20fe, Val >> 2)); |
| 81 | 229 | break; |
| ... | ... | @@ -83,6 +231,7 @@ void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 83 | 231 | or32le(Loc, applyMask(0x00df20fe, Val & 0x3f)); |
| 84 | 232 | break; |
| 85 | 233 | case R_HEX_B22_PCREL: |
| 234 | case R_HEX_PLT_B22_PCREL: | |
| 86 | 235 | or32le(Loc, applyMask(0x1ff3ffe, Val >> 2)); |
| 87 | 236 | break; |
| 88 | 237 | case R_HEX_B22_PCREL_X: |
| ... | ... | @@ -91,12 +240,52 @@ void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 91 | 240 | case R_HEX_B32_PCREL_X: |
| 92 | 241 | or32le(Loc, applyMask(0x0fff3fff, Val >> 6)); |
| 93 | 242 | break; |
| 243 | case R_HEX_HI16: | |
| 244 | or32le(Loc, applyMask(0x00c03fff, Val >> 16)); | |
| 245 | break; | |
| 246 | case R_HEX_LO16: | |
| 247 | or32le(Loc, applyMask(0x00c03fff, Val)); | |
| 248 | break; | |
| 94 | 249 | default: |
| 95 | 250 | error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type)); |
| 96 | 251 | break; |
| 97 | 252 | } |
| 98 | 253 | } |
| 99 | 254 | |
| 255 | void Hexagon::writePltHeader(uint8_t *Buf) const { | |
| 256 | const uint8_t PltData[] = { | |
| 257 | 0x00, 0x40, 0x00, 0x00, // { immext (#0) | |
| 258 | 0x1c, 0xc0, 0x49, 0x6a, // r28 = add (pc, ##GOT0@PCREL) } # @GOT0 | |
| 259 | 0x0e, 0x42, 0x9c, 0xe2, // { r14 -= add (r28, #16) # offset of GOTn | |
| 260 | 0x4f, 0x40, 0x9c, 0x91, // r15 = memw (r28 + #8) # object ID at GOT2 | |
| 261 | 0x3c, 0xc0, 0x9c, 0x91, // r28 = memw (r28 + #4) }# dynamic link at GOT1 | |
| 262 | 0x0e, 0x42, 0x0e, 0x8c, // { r14 = asr (r14, #2) # index of PLTn | |
| 263 | 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 } # call dynamic linker | |
| 264 | 0x0c, 0xdb, 0x00, 0x54, // trap0(#0xdb) # bring plt0 into 16byte alignment | |
| 265 | }; | |
| 266 | memcpy(Buf, PltData, sizeof(PltData)); | |
| 267 | ||
| 268 | // Offset from PLT0 to the GOT. | |
| 269 | uint64_t Off = In.GotPlt->getVA() - In.Plt->getVA(); | |
| 270 | relocateOne(Buf, R_HEX_B32_PCREL_X, Off); | |
| 271 | relocateOne(Buf + 4, R_HEX_6_PCREL_X, Off); | |
| 272 | } | |
| 273 | ||
| 274 | void Hexagon::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, | |
| 275 | uint64_t PltEntryAddr, int32_t Index, | |
| 276 | unsigned RelOff) const { | |
| 277 | const uint8_t Inst[] = { | |
| 278 | 0x00, 0x40, 0x00, 0x00, // { immext (#0) | |
| 279 | 0x0e, 0xc0, 0x49, 0x6a, // r14 = add (pc, ##GOTn@PCREL) } | |
| 280 | 0x1c, 0xc0, 0x8e, 0x91, // r28 = memw (r14) | |
| 281 | 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 | |
| 282 | }; | |
| 283 | memcpy(Buf, Inst, sizeof(Inst)); | |
| 284 | ||
| 285 | relocateOne(Buf, R_HEX_B32_PCREL_X, GotPltEntryAddr - PltEntryAddr); | |
| 286 | relocateOne(Buf + 4, R_HEX_6_PCREL_X, GotPltEntryAddr - PltEntryAddr); | |
| 287 | } | |
| 288 | ||
| 100 | 289 | TargetInfo *elf::getHexagonTargetInfo() { |
| 101 | 290 | static Hexagon Target; |
| 102 | 291 | return &Target; |
deps/lld/ELF/Arch/MSP430.cpp created+94| ... | ... | @@ -0,0 +1,94 @@ |
| 1 | //===- MSP430.cpp ---------------------------------------------------------===// | |
| 2 | // | |
| 3 | // The LLVM Linker | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | // | |
| 10 | // The MSP430 is a 16-bit microcontroller RISC architecture. The instruction set | |
| 11 | // has only 27 core instructions orthogonally augmented with a variety | |
| 12 | // of addressing modes for source and destination operands. Entire address space | |
| 13 | // of MSP430 is 64KB (the extended MSP430X architecture is not considered here). | |
| 14 | // A typical MSP430 MCU has several kilobytes of RAM and ROM, plenty | |
| 15 | // of peripherals and is generally optimized for a low power consumption. | |
| 16 | // | |
| 17 | //===----------------------------------------------------------------------===// | |
| 18 | ||
| 19 | #include "InputFiles.h" | |
| 20 | #include "Symbols.h" | |
| 21 | #include "Target.h" | |
| 22 | #include "lld/Common/ErrorHandler.h" | |
| 23 | #include "llvm/Object/ELF.h" | |
| 24 | #include "llvm/Support/Endian.h" | |
| 25 | ||
| 26 | using namespace llvm; | |
| 27 | using namespace llvm::object; | |
| 28 | using namespace llvm::support::endian; | |
| 29 | using namespace llvm::ELF; | |
| 30 | using namespace lld; | |
| 31 | using namespace lld::elf; | |
| 32 | ||
| 33 | namespace { | |
| 34 | class MSP430 final : public TargetInfo { | |
| 35 | public: | |
| 36 | MSP430(); | |
| 37 | RelExpr getRelExpr(RelType Type, const Symbol &S, | |
| 38 | const uint8_t *Loc) const override; | |
| 39 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; | |
| 40 | }; | |
| 41 | } // namespace | |
| 42 | ||
| 43 | MSP430::MSP430() { | |
| 44 | // mov.b #0, r3 | |
| 45 | TrapInstr = {0x43, 0x43, 0x43, 0x43}; | |
| 46 | } | |
| 47 | ||
| 48 | RelExpr MSP430::getRelExpr(RelType Type, const Symbol &S, | |
| 49 | const uint8_t *Loc) const { | |
| 50 | switch (Type) { | |
| 51 | case R_MSP430_10_PCREL: | |
| 52 | case R_MSP430_16_PCREL: | |
| 53 | case R_MSP430_16_PCREL_BYTE: | |
| 54 | case R_MSP430_2X_PCREL: | |
| 55 | case R_MSP430_RL_PCREL: | |
| 56 | case R_MSP430_SYM_DIFF: | |
| 57 | return R_PC; | |
| 58 | default: | |
| 59 | return R_ABS; | |
| 60 | } | |
| 61 | } | |
| 62 | ||
| 63 | void MSP430::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { | |
| 64 | switch (Type) { | |
| 65 | case R_MSP430_8: | |
| 66 | checkIntUInt(Loc, Val, 8, Type); | |
| 67 | *Loc = Val; | |
| 68 | break; | |
| 69 | case R_MSP430_16: | |
| 70 | case R_MSP430_16_PCREL: | |
| 71 | case R_MSP430_16_BYTE: | |
| 72 | case R_MSP430_16_PCREL_BYTE: | |
| 73 | checkIntUInt(Loc, Val, 16, Type); | |
| 74 | write16le(Loc, Val); | |
| 75 | break; | |
| 76 | case R_MSP430_32: | |
| 77 | checkIntUInt(Loc, Val, 32, Type); | |
| 78 | write32le(Loc, Val); | |
| 79 | break; | |
| 80 | case R_MSP430_10_PCREL: { | |
| 81 | int16_t Offset = ((int16_t)Val >> 1) - 1; | |
| 82 | checkInt(Loc, Offset, 10, Type); | |
| 83 | write16le(Loc, (read16le(Loc) & 0xFC00) | (Offset & 0x3FF)); | |
| 84 | break; | |
| 85 | } | |
| 86 | default: | |
| 87 | error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type)); | |
| 88 | } | |
| 89 | } | |
| 90 | ||
| 91 | TargetInfo *elf::getMSP430TargetInfo() { | |
| 92 | static MSP430 Target; | |
| 93 | return &Target; | |
| 94 | } |
deps/lld/ELF/Arch/Mips.cpp+8-5| ... | ... | @@ -53,9 +53,12 @@ template <class ELFT> MIPS<ELFT>::MIPS() { |
| 53 | 53 | PltEntrySize = 16; |
| 54 | 54 | PltHeaderSize = 32; |
| 55 | 55 | CopyRel = R_MIPS_COPY; |
| 56 | NoneRel = R_MIPS_NONE; | |
| 56 | 57 | PltRel = R_MIPS_JUMP_SLOT; |
| 57 | 58 | NeedsThunks = true; |
| 58 | TrapInstr = 0xefefefef; | |
| 59 | ||
| 60 | // Set `sigrie 1` as a trap instruction. | |
| 61 | write32(TrapInstr.data(), 0x04170001); | |
| 59 | 62 | |
| 60 | 63 | if (ELFT::Is64Bits) { |
| 61 | 64 | RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32; |
| ... | ... | @@ -185,7 +188,7 @@ template <class ELFT> RelType MIPS<ELFT>::getDynRel(RelType Type) const { |
| 185 | 188 | |
| 186 | 189 | template <class ELFT> |
| 187 | 190 | void MIPS<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &) const { |
| 188 | uint64_t VA = InX::Plt->getVA(); | |
| 191 | uint64_t VA = In.Plt->getVA(); | |
| 189 | 192 | if (isMicroMips()) |
| 190 | 193 | VA |= 1; |
| 191 | 194 | write32<ELFT::TargetEndianness>(Buf, VA); |
| ... | ... | @@ -239,8 +242,8 @@ static void writeMicroRelocation16(uint8_t *Loc, uint64_t V, uint8_t BitsSize, |
| 239 | 242 | template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *Buf) const { |
| 240 | 243 | const endianness E = ELFT::TargetEndianness; |
| 241 | 244 | if (isMicroMips()) { |
| 242 | uint64_t GotPlt = InX::GotPlt->getVA(); | |
| 243 | uint64_t Plt = InX::Plt->getVA(); | |
| 245 | uint64_t GotPlt = In.GotPlt->getVA(); | |
| 246 | uint64_t Plt = In.Plt->getVA(); | |
| 244 | 247 | // Overwrite trap instructions written by Writer::writeTrapInstr. |
| 245 | 248 | memset(Buf, 0, PltHeaderSize); |
| 246 | 249 | |
| ... | ... | @@ -292,7 +295,7 @@ template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *Buf) const { |
| 292 | 295 | write32<E>(Buf + 24, JalrInst); // jalr.hb $25 or jalr $25 |
| 293 | 296 | write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2 |
| 294 | 297 | |
| 295 | uint64_t GotPlt = InX::GotPlt->getVA(); | |
| 298 | uint64_t GotPlt = In.GotPlt->getVA(); | |
| 296 | 299 | writeValue<E>(Buf, GotPlt + 0x8000, 16, 16); |
| 297 | 300 | writeValue<E>(Buf + 4, GotPlt, 16, 0); |
| 298 | 301 | writeValue<E>(Buf + 8, GotPlt, 16, 0); |
deps/lld/ELF/Arch/PPC.cpp+5| ... | ... | @@ -29,6 +29,7 @@ public: |
| 29 | 29 | } // namespace |
| 30 | 30 | |
| 31 | 31 | PPC::PPC() { |
| 32 | NoneRel = R_PPC_NONE; | |
| 32 | 33 | GotBaseSymOff = 0x8000; |
| 33 | 34 | GotBaseSymInGotPlt = false; |
| 34 | 35 | } |
| ... | ... | @@ -36,6 +37,7 @@ PPC::PPC() { |
| 36 | 37 | RelExpr PPC::getRelExpr(RelType Type, const Symbol &S, |
| 37 | 38 | const uint8_t *Loc) const { |
| 38 | 39 | switch (Type) { |
| 40 | case R_PPC_REL14: | |
| 39 | 41 | case R_PPC_REL24: |
| 40 | 42 | case R_PPC_REL32: |
| 41 | 43 | return R_PC; |
| ... | ... | @@ -61,6 +63,9 @@ void PPC::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 61 | 63 | case R_PPC_REL32: |
| 62 | 64 | write32be(Loc, Val); |
| 63 | 65 | break; |
| 66 | case R_PPC_REL14: | |
| 67 | write32be(Loc, read32be(Loc) | (Val & 0xFFFC)); | |
| 68 | break; | |
| 64 | 69 | case R_PPC_PLTREL24: |
| 65 | 70 | case R_PPC_REL24: |
| 66 | 71 | write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC)); |
deps/lld/ELF/Arch/PPC64.cpp+436-37| ... | ... | @@ -23,12 +23,49 @@ using namespace lld::elf; |
| 23 | 23 | static uint64_t PPC64TocOffset = 0x8000; |
| 24 | 24 | static uint64_t DynamicThreadPointerOffset = 0x8000; |
| 25 | 25 | |
| 26 | // The instruction encoding of bits 21-30 from the ISA for the Xform and Dform | |
| 27 | // instructions that can be used as part of the initial exec TLS sequence. | |
| 28 | enum XFormOpcd { | |
| 29 | LBZX = 87, | |
| 30 | LHZX = 279, | |
| 31 | LWZX = 23, | |
| 32 | LDX = 21, | |
| 33 | STBX = 215, | |
| 34 | STHX = 407, | |
| 35 | STWX = 151, | |
| 36 | STDX = 149, | |
| 37 | ADD = 266, | |
| 38 | }; | |
| 39 | ||
| 40 | enum DFormOpcd { | |
| 41 | LBZ = 34, | |
| 42 | LBZU = 35, | |
| 43 | LHZ = 40, | |
| 44 | LHZU = 41, | |
| 45 | LHAU = 43, | |
| 46 | LWZ = 32, | |
| 47 | LWZU = 33, | |
| 48 | LFSU = 49, | |
| 49 | LD = 58, | |
| 50 | LFDU = 51, | |
| 51 | STB = 38, | |
| 52 | STBU = 39, | |
| 53 | STH = 44, | |
| 54 | STHU = 45, | |
| 55 | STW = 36, | |
| 56 | STWU = 37, | |
| 57 | STFSU = 53, | |
| 58 | STFDU = 55, | |
| 59 | STD = 62, | |
| 60 | ADDI = 14 | |
| 61 | }; | |
| 62 | ||
| 26 | 63 | uint64_t elf::getPPC64TocBase() { |
| 27 | 64 | // The TOC consists of sections .got, .toc, .tocbss, .plt in that order. The |
| 28 | 65 | // TOC starts where the first of these sections starts. We always create a |
| 29 | 66 | // .got when we see a relocation that uses it, so for us the start is always |
| 30 | 67 | // the .got. |
| 31 | uint64_t TocVA = InX::Got->getVA(); | |
| 68 | uint64_t TocVA = In.Got->getVA(); | |
| 32 | 69 | |
| 33 | 70 | // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000 |
| 34 | 71 | // thus permitting a full 64 Kbytes segment. Note that the glibc startup |
| ... | ... | @@ -37,6 +74,31 @@ uint64_t elf::getPPC64TocBase() { |
| 37 | 74 | return TocVA + PPC64TocOffset; |
| 38 | 75 | } |
| 39 | 76 | |
| 77 | unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther) { | |
| 78 | // The offset is encoded into the 3 most significant bits of the st_other | |
| 79 | // field, with some special values described in section 3.4.1 of the ABI: | |
| 80 | // 0 --> Zero offset between the GEP and LEP, and the function does NOT use | |
| 81 | // the TOC pointer (r2). r2 will hold the same value on returning from | |
| 82 | // the function as it did on entering the function. | |
| 83 | // 1 --> Zero offset between the GEP and LEP, and r2 should be treated as a | |
| 84 | // caller-saved register for all callers. | |
| 85 | // 2-6 --> The binary logarithm of the offset eg: | |
| 86 | // 2 --> 2^2 = 4 bytes --> 1 instruction. | |
| 87 | // 6 --> 2^6 = 64 bytes --> 16 instructions. | |
| 88 | // 7 --> Reserved. | |
| 89 | uint8_t GepToLep = (StOther >> 5) & 7; | |
| 90 | if (GepToLep < 2) | |
| 91 | return 0; | |
| 92 | ||
| 93 | // The value encoded in the st_other bits is the | |
| 94 | // log-base-2(offset). | |
| 95 | if (GepToLep < 7) | |
| 96 | return 1 << GepToLep; | |
| 97 | ||
| 98 | error("reserved value of 7 in the 3 most-significant-bits of st_other"); | |
| 99 | return 0; | |
| 100 | } | |
| 101 | ||
| 40 | 102 | namespace { |
| 41 | 103 | class PPC64 final : public TargetInfo { |
| 42 | 104 | public: |
| ... | ... | @@ -51,11 +113,16 @@ public: |
| 51 | 113 | void writeGotHeader(uint8_t *Buf) const override; |
| 52 | 114 | bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 53 | 115 | uint64_t BranchAddr, const Symbol &S) const override; |
| 116 | bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override; | |
| 54 | 117 | RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 55 | 118 | RelExpr Expr) const override; |
| 56 | 119 | void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 57 | 120 | void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 58 | 121 | void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 122 | void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; | |
| 123 | ||
| 124 | bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, | |
| 125 | uint8_t StOther) const override; | |
| 59 | 126 | }; |
| 60 | 127 | } // namespace |
| 61 | 128 | |
| ... | ... | @@ -71,8 +138,64 @@ static uint16_t highera(uint64_t V) { return (V + 0x8000) >> 32; } |
| 71 | 138 | static uint16_t highest(uint64_t V) { return V >> 48; } |
| 72 | 139 | static uint16_t highesta(uint64_t V) { return (V + 0x8000) >> 48; } |
| 73 | 140 | |
| 141 | // Extracts the 'PO' field of an instruction encoding. | |
| 142 | static uint8_t getPrimaryOpCode(uint32_t Encoding) { return (Encoding >> 26); } | |
| 143 | ||
| 144 | static bool isDQFormInstruction(uint32_t Encoding) { | |
| 145 | switch (getPrimaryOpCode(Encoding)) { | |
| 146 | default: | |
| 147 | return false; | |
| 148 | case 56: | |
| 149 | // The only instruction with a primary opcode of 56 is `lq`. | |
| 150 | return true; | |
| 151 | case 61: | |
| 152 | // There are both DS and DQ instruction forms with this primary opcode. | |
| 153 | // Namely `lxv` and `stxv` are the DQ-forms that use it. | |
| 154 | // The DS 'XO' bits being set to 01 is restricted to DQ form. | |
| 155 | return (Encoding & 3) == 0x1; | |
| 156 | } | |
| 157 | } | |
| 158 | ||
| 159 | static bool isInstructionUpdateForm(uint32_t Encoding) { | |
| 160 | switch (getPrimaryOpCode(Encoding)) { | |
| 161 | default: | |
| 162 | return false; | |
| 163 | case LBZU: | |
| 164 | case LHAU: | |
| 165 | case LHZU: | |
| 166 | case LWZU: | |
| 167 | case LFSU: | |
| 168 | case LFDU: | |
| 169 | case STBU: | |
| 170 | case STHU: | |
| 171 | case STWU: | |
| 172 | case STFSU: | |
| 173 | case STFDU: | |
| 174 | return true; | |
| 175 | // LWA has the same opcode as LD, and the DS bits is what differentiates | |
| 176 | // between LD/LDU/LWA | |
| 177 | case LD: | |
| 178 | case STD: | |
| 179 | return (Encoding & 3) == 1; | |
| 180 | } | |
| 181 | } | |
| 182 | ||
| 183 | // There are a number of places when we either want to read or write an | |
| 184 | // instruction when handling a half16 relocation type. On big-endian the buffer | |
| 185 | // pointer is pointing into the middle of the word we want to extract, and on | |
| 186 | // little-endian it is pointing to the start of the word. These 2 helpers are to | |
| 187 | // simplify reading and writing in that context. | |
| 188 | static void writeInstrFromHalf16(uint8_t *Loc, uint32_t Instr) { | |
| 189 | write32(Loc - (Config->EKind == ELF64BEKind ? 2 : 0), Instr); | |
| 190 | } | |
| 191 | ||
| 192 | static uint32_t readInstrFromHalf16(const uint8_t *Loc) { | |
| 193 | return read32(Loc - (Config->EKind == ELF64BEKind ? 2 : 0)); | |
| 194 | } | |
| 195 | ||
| 74 | 196 | PPC64::PPC64() { |
| 75 | 197 | GotRel = R_PPC64_GLOB_DAT; |
| 198 | NoneRel = R_PPC64_NONE; | |
| 76 | 199 | PltRel = R_PPC64_JMP_SLOT; |
| 77 | 200 | RelativeRel = R_PPC64_RELATIVE; |
| 78 | 201 | IRelativeRel = R_PPC64_IRELATIVE; |
| ... | ... | @@ -85,14 +208,14 @@ PPC64::PPC64() { |
| 85 | 208 | GotPltHeaderEntriesNum = 2; |
| 86 | 209 | PltHeaderSize = 60; |
| 87 | 210 | NeedsThunks = true; |
| 88 | TcbSize = 8; | |
| 89 | TlsTpOffset = 0x7000; | |
| 90 | 211 | |
| 91 | 212 | TlsModuleIndexRel = R_PPC64_DTPMOD64; |
| 92 | 213 | TlsOffsetRel = R_PPC64_DTPREL64; |
| 93 | 214 | |
| 94 | 215 | TlsGotRel = R_PPC64_TPREL64; |
| 95 | 216 | |
| 217 | NeedsMoreStackNonSplit = false; | |
| 218 | ||
| 96 | 219 | // We need 64K pages (at least under glibc/Linux, the loader won't |
| 97 | 220 | // set different permissions on a finer granularity than that). |
| 98 | 221 | DefaultMaxPageSize = 65536; |
| ... | ... | @@ -107,8 +230,7 @@ PPC64::PPC64() { |
| 107 | 230 | // use 0x10000000 as the starting address. |
| 108 | 231 | DefaultImageBase = 0x10000000; |
| 109 | 232 | |
| 110 | TrapInstr = | |
| 111 | (Config->IsLE == sys::IsLittleEndianHost) ? 0x7fe00008 : 0x0800e07f; | |
| 233 | write32(TrapInstr.data(), 0x7fe00008); | |
| 112 | 234 | } |
| 113 | 235 | |
| 114 | 236 | static uint32_t getEFlags(InputFile *File) { |
| ... | ... | @@ -146,27 +268,29 @@ void PPC64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 146 | 268 | // bl __tls_get_addr(x@tlsgd) into nop |
| 147 | 269 | // nop into addi r3, r3, x@tprel@l |
| 148 | 270 | |
| 149 | uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U; | |
| 150 | ||
| 151 | 271 | switch (Type) { |
| 152 | 272 | case R_PPC64_GOT_TLSGD16_HA: |
| 153 | write32(Loc - EndianOffset, 0x60000000); // nop | |
| 273 | writeInstrFromHalf16(Loc, 0x60000000); // nop | |
| 154 | 274 | break; |
| 275 | case R_PPC64_GOT_TLSGD16: | |
| 155 | 276 | case R_PPC64_GOT_TLSGD16_LO: |
| 156 | write32(Loc - EndianOffset, 0x3c6d0000); // addis r3, r13 | |
| 277 | writeInstrFromHalf16(Loc, 0x3c6d0000); // addis r3, r13 | |
| 157 | 278 | relocateOne(Loc, R_PPC64_TPREL16_HA, Val); |
| 158 | 279 | break; |
| 159 | 280 | case R_PPC64_TLSGD: |
| 160 | 281 | write32(Loc, 0x60000000); // nop |
| 161 | 282 | write32(Loc + 4, 0x38630000); // addi r3, r3 |
| 162 | relocateOne(Loc + 4 + EndianOffset, R_PPC64_TPREL16_LO, Val); | |
| 283 | // Since we are relocating a half16 type relocation and Loc + 4 points to | |
| 284 | // the start of an instruction we need to advance the buffer by an extra | |
| 285 | // 2 bytes on BE. | |
| 286 | relocateOne(Loc + 4 + (Config->EKind == ELF64BEKind ? 2 : 0), | |
| 287 | R_PPC64_TPREL16_LO, Val); | |
| 163 | 288 | break; |
| 164 | 289 | default: |
| 165 | 290 | llvm_unreachable("unsupported relocation for TLS GD to LE relaxation"); |
| 166 | 291 | } |
| 167 | 292 | } |
| 168 | 293 | |
| 169 | ||
| 170 | 294 | void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 171 | 295 | // Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement. |
| 172 | 296 | // The local dynamic code sequence for a global `x` will look like: |
| ... | ... | @@ -183,13 +307,12 @@ void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 183 | 307 | // bl __tls_get_addr(x@tlsgd) into nop |
| 184 | 308 | // nop into addi r3, r3, 4096 |
| 185 | 309 | |
| 186 | uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U; | |
| 187 | 310 | switch (Type) { |
| 188 | 311 | case R_PPC64_GOT_TLSLD16_HA: |
| 189 | write32(Loc - EndianOffset, 0x60000000); // nop | |
| 312 | writeInstrFromHalf16(Loc, 0x60000000); // nop | |
| 190 | 313 | break; |
| 191 | 314 | case R_PPC64_GOT_TLSLD16_LO: |
| 192 | write32(Loc - EndianOffset, 0x3c6d0000); // addis r3, r13, 0 | |
| 315 | writeInstrFromHalf16(Loc, 0x3c6d0000); // addis r3, r13, 0 | |
| 193 | 316 | break; |
| 194 | 317 | case R_PPC64_TLSLD: |
| 195 | 318 | write32(Loc, 0x60000000); // nop |
| ... | ... | @@ -212,9 +335,90 @@ void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 212 | 335 | } |
| 213 | 336 | } |
| 214 | 337 | |
| 338 | static unsigned getDFormOp(unsigned SecondaryOp) { | |
| 339 | switch (SecondaryOp) { | |
| 340 | case LBZX: | |
| 341 | return LBZ; | |
| 342 | case LHZX: | |
| 343 | return LHZ; | |
| 344 | case LWZX: | |
| 345 | return LWZ; | |
| 346 | case LDX: | |
| 347 | return LD; | |
| 348 | case STBX: | |
| 349 | return STB; | |
| 350 | case STHX: | |
| 351 | return STH; | |
| 352 | case STWX: | |
| 353 | return STW; | |
| 354 | case STDX: | |
| 355 | return STD; | |
| 356 | case ADD: | |
| 357 | return ADDI; | |
| 358 | default: | |
| 359 | error("unrecognized instruction for IE to LE R_PPC64_TLS"); | |
| 360 | return 0; | |
| 361 | } | |
| 362 | } | |
| 363 | ||
| 364 | void PPC64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const { | |
| 365 | // The initial exec code sequence for a global `x` will look like: | |
| 366 | // Instruction Relocation Symbol | |
| 367 | // addis r9, r2, x@got@tprel@ha R_PPC64_GOT_TPREL16_HA x | |
| 368 | // ld r9, x@got@tprel@l(r9) R_PPC64_GOT_TPREL16_LO_DS x | |
| 369 | // add r9, r9, x@tls R_PPC64_TLS x | |
| 370 | ||
| 371 | // Relaxing to local exec entails converting: | |
| 372 | // addis r9, r2, x@got@tprel@ha into nop | |
| 373 | // ld r9, x@got@tprel@l(r9) into addis r9, r13, x@tprel@ha | |
| 374 | // add r9, r9, x@tls into addi r9, r9, x@tprel@l | |
| 375 | ||
| 376 | // x@tls R_PPC64_TLS is a relocation which does not compute anything, | |
| 377 | // it is replaced with r13 (thread pointer). | |
| 378 | ||
| 379 | // The add instruction in the initial exec sequence has multiple variations | |
| 380 | // that need to be handled. If we are building an address it will use an add | |
| 381 | // instruction, if we are accessing memory it will use any of the X-form | |
| 382 | // indexed load or store instructions. | |
| 383 | ||
| 384 | unsigned Offset = (Config->EKind == ELF64BEKind) ? 2 : 0; | |
| 385 | switch (Type) { | |
| 386 | case R_PPC64_GOT_TPREL16_HA: | |
| 387 | write32(Loc - Offset, 0x60000000); // nop | |
| 388 | break; | |
| 389 | case R_PPC64_GOT_TPREL16_LO_DS: | |
| 390 | case R_PPC64_GOT_TPREL16_DS: { | |
| 391 | uint32_t RegNo = read32(Loc - Offset) & 0x03E00000; // bits 6-10 | |
| 392 | write32(Loc - Offset, 0x3C0D0000 | RegNo); // addis RegNo, r13 | |
| 393 | relocateOne(Loc, R_PPC64_TPREL16_HA, Val); | |
| 394 | break; | |
| 395 | } | |
| 396 | case R_PPC64_TLS: { | |
| 397 | uint32_t PrimaryOp = getPrimaryOpCode(read32(Loc)); | |
| 398 | if (PrimaryOp != 31) | |
| 399 | error("unrecognized instruction for IE to LE R_PPC64_TLS"); | |
| 400 | uint32_t SecondaryOp = (read32(Loc) & 0x000007FE) >> 1; // bits 21-30 | |
| 401 | uint32_t DFormOp = getDFormOp(SecondaryOp); | |
| 402 | write32(Loc, ((DFormOp << 26) | (read32(Loc) & 0x03FFFFFF))); | |
| 403 | relocateOne(Loc + Offset, R_PPC64_TPREL16_LO, Val); | |
| 404 | break; | |
| 405 | } | |
| 406 | default: | |
| 407 | llvm_unreachable("unknown relocation for IE to LE"); | |
| 408 | break; | |
| 409 | } | |
| 410 | } | |
| 411 | ||
| 215 | 412 | RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S, |
| 216 | 413 | const uint8_t *Loc) const { |
| 217 | 414 | switch (Type) { |
| 415 | case R_PPC64_GOT16: | |
| 416 | case R_PPC64_GOT16_DS: | |
| 417 | case R_PPC64_GOT16_HA: | |
| 418 | case R_PPC64_GOT16_HI: | |
| 419 | case R_PPC64_GOT16_LO: | |
| 420 | case R_PPC64_GOT16_LO_DS: | |
| 421 | return R_GOT_OFF; | |
| 218 | 422 | case R_PPC64_TOC16: |
| 219 | 423 | case R_PPC64_TOC16_DS: |
| 220 | 424 | case R_PPC64_TOC16_HA: |
| ... | ... | @@ -224,6 +428,7 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S, |
| 224 | 428 | return R_GOTREL; |
| 225 | 429 | case R_PPC64_TOC: |
| 226 | 430 | return R_PPC_TOC; |
| 431 | case R_PPC64_REL14: | |
| 227 | 432 | case R_PPC64_REL24: |
| 228 | 433 | return R_PPC_CALL_PLT; |
| 229 | 434 | case R_PPC64_REL16_LO: |
| ... | ... | @@ -279,7 +484,7 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S, |
| 279 | 484 | case R_PPC64_TLSLD: |
| 280 | 485 | return R_TLSLD_HINT; |
| 281 | 486 | case R_PPC64_TLS: |
| 282 | return R_HINT; | |
| 487 | return R_TLSIE_HINT; | |
| 283 | 488 | default: |
| 284 | 489 | return R_ABS; |
| 285 | 490 | } |
| ... | ... | @@ -308,16 +513,16 @@ void PPC64::writePltHeader(uint8_t *Buf) const { |
| 308 | 513 | // The 'bcl' instruction will set the link register to the address of the |
| 309 | 514 | // following instruction ('mflr r11'). Here we store the offset from that |
| 310 | 515 | // instruction to the first entry in the GotPlt section. |
| 311 | int64_t GotPltOffset = InX::GotPlt->getVA() - (InX::Plt->getVA() + 8); | |
| 516 | int64_t GotPltOffset = In.GotPlt->getVA() - (In.Plt->getVA() + 8); | |
| 312 | 517 | write64(Buf + 52, GotPltOffset); |
| 313 | 518 | } |
| 314 | 519 | |
| 315 | 520 | void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 316 | 521 | uint64_t PltEntryAddr, int32_t Index, |
| 317 | 522 | unsigned RelOff) const { |
| 318 | int32_t Offset = PltHeaderSize + Index * PltEntrySize; | |
| 319 | // bl __glink_PLTresolve | |
| 320 | write32(Buf, 0x48000000 | ((-Offset) & 0x03FFFFFc)); | |
| 523 | int32_t Offset = PltHeaderSize + Index * PltEntrySize; | |
| 524 | // bl __glink_PLTresolve | |
| 525 | write32(Buf, 0x48000000 | ((-Offset) & 0x03FFFFFc)); | |
| 321 | 526 | } |
| 322 | 527 | |
| 323 | 528 | static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) { |
| ... | ... | @@ -328,30 +533,36 @@ static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) { |
| 328 | 533 | |
| 329 | 534 | switch (Type) { |
| 330 | 535 | // TOC biased relocation. |
| 536 | case R_PPC64_GOT16: | |
| 331 | 537 | case R_PPC64_GOT_TLSGD16: |
| 332 | 538 | case R_PPC64_GOT_TLSLD16: |
| 333 | 539 | case R_PPC64_TOC16: |
| 334 | 540 | return {R_PPC64_ADDR16, TocBiasedVal}; |
| 541 | case R_PPC64_GOT16_DS: | |
| 335 | 542 | case R_PPC64_TOC16_DS: |
| 336 | 543 | case R_PPC64_GOT_TPREL16_DS: |
| 337 | 544 | case R_PPC64_GOT_DTPREL16_DS: |
| 338 | 545 | return {R_PPC64_ADDR16_DS, TocBiasedVal}; |
| 546 | case R_PPC64_GOT16_HA: | |
| 339 | 547 | case R_PPC64_GOT_TLSGD16_HA: |
| 340 | 548 | case R_PPC64_GOT_TLSLD16_HA: |
| 341 | 549 | case R_PPC64_GOT_TPREL16_HA: |
| 342 | 550 | case R_PPC64_GOT_DTPREL16_HA: |
| 343 | 551 | case R_PPC64_TOC16_HA: |
| 344 | 552 | return {R_PPC64_ADDR16_HA, TocBiasedVal}; |
| 553 | case R_PPC64_GOT16_HI: | |
| 345 | 554 | case R_PPC64_GOT_TLSGD16_HI: |
| 346 | 555 | case R_PPC64_GOT_TLSLD16_HI: |
| 347 | 556 | case R_PPC64_GOT_TPREL16_HI: |
| 348 | 557 | case R_PPC64_GOT_DTPREL16_HI: |
| 349 | 558 | case R_PPC64_TOC16_HI: |
| 350 | 559 | return {R_PPC64_ADDR16_HI, TocBiasedVal}; |
| 560 | case R_PPC64_GOT16_LO: | |
| 351 | 561 | case R_PPC64_GOT_TLSGD16_LO: |
| 352 | 562 | case R_PPC64_GOT_TLSLD16_LO: |
| 353 | 563 | case R_PPC64_TOC16_LO: |
| 354 | 564 | return {R_PPC64_ADDR16_LO, TocBiasedVal}; |
| 565 | case R_PPC64_GOT16_LO_DS: | |
| 355 | 566 | case R_PPC64_TOC16_LO_DS: |
| 356 | 567 | case R_PPC64_GOT_TPREL16_LO_DS: |
| 357 | 568 | case R_PPC64_GOT_DTPREL16_LO_DS: |
| ... | ... | @@ -386,9 +597,27 @@ static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) { |
| 386 | 597 | } |
| 387 | 598 | } |
| 388 | 599 | |
| 600 | static bool isTocOptType(RelType Type) { | |
| 601 | switch (Type) { | |
| 602 | case R_PPC64_GOT16_HA: | |
| 603 | case R_PPC64_GOT16_LO_DS: | |
| 604 | case R_PPC64_TOC16_HA: | |
| 605 | case R_PPC64_TOC16_LO_DS: | |
| 606 | case R_PPC64_TOC16_LO: | |
| 607 | return true; | |
| 608 | default: | |
| 609 | return false; | |
| 610 | } | |
| 611 | } | |
| 612 | ||
| 389 | 613 | void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 390 | // For a TOC-relative relocation, proceed in terms of the corresponding | |
| 391 | // ADDR16 relocation type. | |
| 614 | // We need to save the original relocation type to use in diagnostics, and | |
| 615 | // use the original type to determine if we should toc-optimize the | |
| 616 | // instructions being relocated. | |
| 617 | RelType OriginalType = Type; | |
| 618 | bool ShouldTocOptimize = isTocOptType(Type); | |
| 619 | // For dynamic thread pointer relative, toc-relative, and got-indirect | |
| 620 | // relocations, proceed in terms of the corresponding ADDR16 relocation type. | |
| 392 | 621 | std::tie(Type, Val) = toAddr16Rel(Type, Val); |
| 393 | 622 | |
| 394 | 623 | switch (Type) { |
| ... | ... | @@ -401,18 +630,25 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 401 | 630 | } |
| 402 | 631 | case R_PPC64_ADDR16: |
| 403 | 632 | case R_PPC64_TPREL16: |
| 404 | checkInt(Loc, Val, 16, Type); | |
| 633 | checkInt(Loc, Val, 16, OriginalType); | |
| 405 | 634 | write16(Loc, Val); |
| 406 | 635 | break; |
| 407 | 636 | case R_PPC64_ADDR16_DS: |
| 408 | case R_PPC64_TPREL16_DS: | |
| 409 | checkInt(Loc, Val, 16, Type); | |
| 410 | write16(Loc, (read16(Loc) & 3) | (Val & ~3)); | |
| 411 | break; | |
| 637 | case R_PPC64_TPREL16_DS: { | |
| 638 | checkInt(Loc, Val, 16, OriginalType); | |
| 639 | // DQ-form instructions use bits 28-31 as part of the instruction encoding | |
| 640 | // DS-form instructions only use bits 30-31. | |
| 641 | uint16_t Mask = isDQFormInstruction(readInstrFromHalf16(Loc)) ? 0xF : 0x3; | |
| 642 | checkAlignment(Loc, lo(Val), Mask + 1, OriginalType); | |
| 643 | write16(Loc, (read16(Loc) & Mask) | lo(Val)); | |
| 644 | } break; | |
| 412 | 645 | case R_PPC64_ADDR16_HA: |
| 413 | 646 | case R_PPC64_REL16_HA: |
| 414 | 647 | case R_PPC64_TPREL16_HA: |
| 415 | write16(Loc, ha(Val)); | |
| 648 | if (Config->TocOptimize && ShouldTocOptimize && ha(Val) == 0) | |
| 649 | writeInstrFromHalf16(Loc, 0x60000000); | |
| 650 | else | |
| 651 | write16(Loc, ha(Val)); | |
| 416 | 652 | break; |
| 417 | 653 | case R_PPC64_ADDR16_HI: |
| 418 | 654 | case R_PPC64_REL16_HI: |
| ... | ... | @@ -438,12 +674,40 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 438 | 674 | case R_PPC64_ADDR16_LO: |
| 439 | 675 | case R_PPC64_REL16_LO: |
| 440 | 676 | case R_PPC64_TPREL16_LO: |
| 677 | // When the high-adjusted part of a toc relocation evalutes to 0, it is | |
| 678 | // changed into a nop. The lo part then needs to be updated to use the | |
| 679 | // toc-pointer register r2, as the base register. | |
| 680 | if (Config->TocOptimize && ShouldTocOptimize && ha(Val) == 0) { | |
| 681 | uint32_t Instr = readInstrFromHalf16(Loc); | |
| 682 | if (isInstructionUpdateForm(Instr)) | |
| 683 | error(getErrorLocation(Loc) + | |
| 684 | "can't toc-optimize an update instruction: 0x" + | |
| 685 | utohexstr(Instr)); | |
| 686 | Instr = (Instr & 0xFFE00000) | 0x00020000; | |
| 687 | writeInstrFromHalf16(Loc, Instr); | |
| 688 | } | |
| 441 | 689 | write16(Loc, lo(Val)); |
| 442 | 690 | break; |
| 443 | 691 | case R_PPC64_ADDR16_LO_DS: |
| 444 | case R_PPC64_TPREL16_LO_DS: | |
| 445 | write16(Loc, (read16(Loc) & 3) | (lo(Val) & ~3)); | |
| 446 | break; | |
| 692 | case R_PPC64_TPREL16_LO_DS: { | |
| 693 | // DQ-form instructions use bits 28-31 as part of the instruction encoding | |
| 694 | // DS-form instructions only use bits 30-31. | |
| 695 | uint32_t Inst = readInstrFromHalf16(Loc); | |
| 696 | uint16_t Mask = isDQFormInstruction(Inst) ? 0xF : 0x3; | |
| 697 | checkAlignment(Loc, lo(Val), Mask + 1, OriginalType); | |
| 698 | if (Config->TocOptimize && ShouldTocOptimize && ha(Val) == 0) { | |
| 699 | // When the high-adjusted part of a toc relocation evalutes to 0, it is | |
| 700 | // changed into a nop. The lo part then needs to be updated to use the toc | |
| 701 | // pointer register r2, as the base register. | |
| 702 | if (isInstructionUpdateForm(Inst)) | |
| 703 | error(getErrorLocation(Loc) + | |
| 704 | "Can't toc-optimize an update instruction: 0x" + | |
| 705 | Twine::utohexstr(Inst)); | |
| 706 | Inst = (Inst & 0xFFE0000F) | 0x00020000; | |
| 707 | writeInstrFromHalf16(Loc, Inst); | |
| 708 | } | |
| 709 | write16(Loc, (read16(Loc) & Mask) | lo(Val)); | |
| 710 | } break; | |
| 447 | 711 | case R_PPC64_ADDR32: |
| 448 | 712 | case R_PPC64_REL32: |
| 449 | 713 | checkInt(Loc, Val, 32, Type); |
| ... | ... | @@ -454,9 +718,17 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 454 | 718 | case R_PPC64_TOC: |
| 455 | 719 | write64(Loc, Val); |
| 456 | 720 | break; |
| 721 | case R_PPC64_REL14: { | |
| 722 | uint32_t Mask = 0x0000FFFC; | |
| 723 | checkInt(Loc, Val, 16, Type); | |
| 724 | checkAlignment(Loc, Val, 4, Type); | |
| 725 | write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask)); | |
| 726 | break; | |
| 727 | } | |
| 457 | 728 | case R_PPC64_REL24: { |
| 458 | 729 | uint32_t Mask = 0x03FFFFFC; |
| 459 | checkInt(Loc, Val, 24, Type); | |
| 730 | checkInt(Loc, Val, 26, Type); | |
| 731 | checkAlignment(Loc, Val, 4, Type); | |
| 460 | 732 | write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask)); |
| 461 | 733 | break; |
| 462 | 734 | } |
| ... | ... | @@ -470,9 +742,30 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 470 | 742 | |
| 471 | 743 | bool PPC64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 472 | 744 | uint64_t BranchAddr, const Symbol &S) const { |
| 473 | // If a function is in the plt it needs to be called through | |
| 474 | // a call stub. | |
| 475 | return Type == R_PPC64_REL24 && S.isInPlt(); | |
| 745 | if (Type != R_PPC64_REL14 && Type != R_PPC64_REL24) | |
| 746 | return false; | |
| 747 | ||
| 748 | // If a function is in the Plt it needs to be called with a call-stub. | |
| 749 | if (S.isInPlt()) | |
| 750 | return true; | |
| 751 | ||
| 752 | // If a symbol is a weak undefined and we are compiling an executable | |
| 753 | // it doesn't need a range-extending thunk since it can't be called. | |
| 754 | if (S.isUndefWeak() && !Config->Shared) | |
| 755 | return false; | |
| 756 | ||
| 757 | // If the offset exceeds the range of the branch type then it will need | |
| 758 | // a range-extending thunk. | |
| 759 | return !inBranchRange(Type, BranchAddr, S.getVA()); | |
| 760 | } | |
| 761 | ||
| 762 | bool PPC64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { | |
| 763 | int64_t Offset = Dst - Src; | |
| 764 | if (Type == R_PPC64_REL14) | |
| 765 | return isInt<16>(Offset); | |
| 766 | if (Type == R_PPC64_REL24) | |
| 767 | return isInt<26>(Offset); | |
| 768 | llvm_unreachable("unsupported relocation type used in branch"); | |
| 476 | 769 | } |
| 477 | 770 | |
| 478 | 771 | RelExpr PPC64::adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| ... | ... | @@ -511,9 +804,8 @@ void PPC64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 511 | 804 | case R_PPC64_GOT_TLSGD16_LO: { |
| 512 | 805 | // Relax from addi r3, rA, sym@got@tlsgd@l to |
| 513 | 806 | // ld r3, sym@got@tprel@l(rA) |
| 514 | uint32_t EndianOffset = Config->EKind == ELF64BEKind ? 2U : 0U; | |
| 515 | uint32_t InputRegister = (read32(Loc - EndianOffset) & (0x1f << 16)); | |
| 516 | write32(Loc - EndianOffset, 0xE8600000 | InputRegister); | |
| 807 | uint32_t InputRegister = (readInstrFromHalf16(Loc) & (0x1f << 16)); | |
| 808 | writeInstrFromHalf16(Loc, 0xE8600000 | InputRegister); | |
| 517 | 809 | relocateOne(Loc, R_PPC64_GOT_TPREL16_LO_DS, Val); |
| 518 | 810 | return; |
| 519 | 811 | } |
| ... | ... | @@ -526,6 +818,113 @@ void PPC64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const { |
| 526 | 818 | } |
| 527 | 819 | } |
| 528 | 820 | |
| 821 | // The prologue for a split-stack function is expected to look roughly | |
| 822 | // like this: | |
| 823 | // .Lglobal_entry_point: | |
| 824 | // # TOC pointer initalization. | |
| 825 | // ... | |
| 826 | // .Llocal_entry_point: | |
| 827 | // # load the __private_ss member of the threads tcbhead. | |
| 828 | // ld r0,-0x7000-64(r13) | |
| 829 | // # subtract the functions stack size from the stack pointer. | |
| 830 | // addis r12, r1, ha(-stack-frame size) | |
| 831 | // addi r12, r12, l(-stack-frame size) | |
| 832 | // # compare needed to actual and branch to allocate_more_stack if more | |
| 833 | // # space is needed, otherwise fallthrough to 'normal' function body. | |
| 834 | // cmpld cr7,r12,r0 | |
| 835 | // blt- cr7, .Lallocate_more_stack | |
| 836 | // | |
| 837 | // -) The allocate_more_stack block might be placed after the split-stack | |
| 838 | // prologue and the `blt-` replaced with a `bge+ .Lnormal_func_body` | |
| 839 | // instead. | |
| 840 | // -) If either the addis or addi is not needed due to the stack size being | |
| 841 | // smaller then 32K or a multiple of 64K they will be replaced with a nop, | |
| 842 | // but there will always be 2 instructions the linker can overwrite for the | |
| 843 | // adjusted stack size. | |
| 844 | // | |
| 845 | // The linkers job here is to increase the stack size used in the addis/addi | |
| 846 | // pair by split-stack-size-adjust. | |
| 847 | // addis r12, r1, ha(-stack-frame size - split-stack-adjust-size) | |
| 848 | // addi r12, r12, l(-stack-frame size - split-stack-adjust-size) | |
| 849 | bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, | |
| 850 | uint8_t StOther) const { | |
| 851 | // If the caller has a global entry point adjust the buffer past it. The start | |
| 852 | // of the split-stack prologue will be at the local entry point. | |
| 853 | Loc += getPPC64GlobalEntryToLocalEntryOffset(StOther); | |
| 854 | ||
| 855 | // At the very least we expect to see a load of some split-stack data from the | |
| 856 | // tcb, and 2 instructions that calculate the ending stack address this | |
| 857 | // function will require. If there is not enough room for at least 3 | |
| 858 | // instructions it can't be a split-stack prologue. | |
| 859 | if (Loc + 12 >= End) | |
| 860 | return false; | |
| 861 | ||
| 862 | // First instruction must be `ld r0, -0x7000-64(r13)` | |
| 863 | if (read32(Loc) != 0xe80d8fc0) | |
| 864 | return false; | |
| 865 | ||
| 866 | int16_t HiImm = 0; | |
| 867 | int16_t LoImm = 0; | |
| 868 | // First instruction can be either an addis if the frame size is larger then | |
| 869 | // 32K, or an addi if the size is less then 32K. | |
| 870 | int32_t FirstInstr = read32(Loc + 4); | |
| 871 | if (getPrimaryOpCode(FirstInstr) == 15) { | |
| 872 | HiImm = FirstInstr & 0xFFFF; | |
| 873 | } else if (getPrimaryOpCode(FirstInstr) == 14) { | |
| 874 | LoImm = FirstInstr & 0xFFFF; | |
| 875 | } else { | |
| 876 | return false; | |
| 877 | } | |
| 878 | ||
| 879 | // Second instruction is either an addi or a nop. If the first instruction was | |
| 880 | // an addi then LoImm is set and the second instruction must be a nop. | |
| 881 | uint32_t SecondInstr = read32(Loc + 8); | |
| 882 | if (!LoImm && getPrimaryOpCode(SecondInstr) == 14) { | |
| 883 | LoImm = SecondInstr & 0xFFFF; | |
| 884 | } else if (SecondInstr != 0x60000000) { | |
| 885 | return false; | |
| 886 | } | |
| 887 | ||
| 888 | // The register operands of the first instruction should be the stack-pointer | |
| 889 | // (r1) as the input (RA) and r12 as the output (RT). If the second | |
| 890 | // instruction is not a nop, then it should use r12 as both input and output. | |
| 891 | auto CheckRegOperands = [](uint32_t Instr, uint8_t ExpectedRT, | |
| 892 | uint8_t ExpectedRA) { | |
| 893 | return ((Instr & 0x3E00000) >> 21 == ExpectedRT) && | |
| 894 | ((Instr & 0x1F0000) >> 16 == ExpectedRA); | |
| 895 | }; | |
| 896 | if (!CheckRegOperands(FirstInstr, 12, 1)) | |
| 897 | return false; | |
| 898 | if (SecondInstr != 0x60000000 && !CheckRegOperands(SecondInstr, 12, 12)) | |
| 899 | return false; | |
| 900 | ||
| 901 | int32_t StackFrameSize = (HiImm * 65536) + LoImm; | |
| 902 | // Check that the adjusted size doesn't overflow what we can represent with 2 | |
| 903 | // instructions. | |
| 904 | if (StackFrameSize < Config->SplitStackAdjustSize + INT32_MIN) { | |
| 905 | error(getErrorLocation(Loc) + "split-stack prologue adjustment overflows"); | |
| 906 | return false; | |
| 907 | } | |
| 908 | ||
| 909 | int32_t AdjustedStackFrameSize = | |
| 910 | StackFrameSize - Config->SplitStackAdjustSize; | |
| 911 | ||
| 912 | LoImm = AdjustedStackFrameSize & 0xFFFF; | |
| 913 | HiImm = (AdjustedStackFrameSize + 0x8000) >> 16; | |
| 914 | if (HiImm) { | |
| 915 | write32(Loc + 4, 0x3D810000 | (uint16_t)HiImm); | |
| 916 | // If the low immediate is zero the second instruction will be a nop. | |
| 917 | SecondInstr = LoImm ? 0x398C0000 | (uint16_t)LoImm : 0x60000000; | |
| 918 | write32(Loc + 8, SecondInstr); | |
| 919 | } else { | |
| 920 | // addi r12, r1, imm | |
| 921 | write32(Loc + 4, (0x39810000) | (uint16_t)LoImm); | |
| 922 | write32(Loc + 8, 0x60000000); | |
| 923 | } | |
| 924 | ||
| 925 | return true; | |
| 926 | } | |
| 927 | ||
| 529 | 928 | TargetInfo *elf::getPPC64TargetInfo() { |
| 530 | 929 | static PPC64 Target; |
| 531 | 930 | return &Target; |
deps/lld/ELF/Arch/RISCV.cpp created+279| ... | ... | @@ -0,0 +1,279 @@ |
| 1 | //===- RISCV.cpp ----------------------------------------------------------===// | |
| 2 | // | |
| 3 | // The LLVM Linker | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #include "InputFiles.h" | |
| 11 | #include "Target.h" | |
| 12 | ||
| 13 | using namespace llvm; | |
| 14 | using namespace llvm::object; | |
| 15 | using namespace llvm::support::endian; | |
| 16 | using namespace llvm::ELF; | |
| 17 | using namespace lld; | |
| 18 | using namespace lld::elf; | |
| 19 | ||
| 20 | namespace { | |
| 21 | ||
| 22 | class RISCV final : public TargetInfo { | |
| 23 | public: | |
| 24 | RISCV(); | |
| 25 | uint32_t calcEFlags() const override; | |
| 26 | RelExpr getRelExpr(RelType Type, const Symbol &S, | |
| 27 | const uint8_t *Loc) const override; | |
| 28 | void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override; | |
| 29 | }; | |
| 30 | ||
| 31 | } // end anonymous namespace | |
| 32 | ||
| 33 | RISCV::RISCV() { NoneRel = R_RISCV_NONE; } | |
| 34 | ||
| 35 | static uint32_t getEFlags(InputFile *F) { | |
| 36 | if (Config->Is64) | |
| 37 | return cast<ObjFile<ELF64LE>>(F)->getObj().getHeader()->e_flags; | |
| 38 | return cast<ObjFile<ELF32LE>>(F)->getObj().getHeader()->e_flags; | |
| 39 | } | |
| 40 | ||
| 41 | uint32_t RISCV::calcEFlags() const { | |
| 42 | assert(!ObjectFiles.empty()); | |
| 43 | ||
| 44 | uint32_t Target = getEFlags(ObjectFiles.front()); | |
| 45 | ||
| 46 | for (InputFile *F : ObjectFiles) { | |
| 47 | uint32_t EFlags = getEFlags(F); | |
| 48 | if (EFlags & EF_RISCV_RVC) | |
| 49 | Target |= EF_RISCV_RVC; | |
| 50 | ||
| 51 | if ((EFlags & EF_RISCV_FLOAT_ABI) != (Target & EF_RISCV_FLOAT_ABI)) | |
| 52 | error(toString(F) + | |
| 53 | ": cannot link object files with different floating-point ABI"); | |
| 54 | ||
| 55 | if ((EFlags & EF_RISCV_RVE) != (Target & EF_RISCV_RVE)) | |
| 56 | error(toString(F) + | |
| 57 | ": cannot link object files with different EF_RISCV_RVE"); | |
| 58 | } | |
| 59 | ||
| 60 | return Target; | |
| 61 | } | |
| 62 | ||
| 63 | RelExpr RISCV::getRelExpr(const RelType Type, const Symbol &S, | |
| 64 | const uint8_t *Loc) const { | |
| 65 | switch (Type) { | |
| 66 | case R_RISCV_JAL: | |
| 67 | case R_RISCV_BRANCH: | |
| 68 | case R_RISCV_CALL: | |
| 69 | case R_RISCV_PCREL_HI20: | |
| 70 | case R_RISCV_RVC_BRANCH: | |
| 71 | case R_RISCV_RVC_JUMP: | |
| 72 | case R_RISCV_32_PCREL: | |
| 73 | return R_PC; | |
| 74 | case R_RISCV_PCREL_LO12_I: | |
| 75 | case R_RISCV_PCREL_LO12_S: | |
| 76 | return R_RISCV_PC_INDIRECT; | |
| 77 | case R_RISCV_RELAX: | |
| 78 | case R_RISCV_ALIGN: | |
| 79 | return R_HINT; | |
| 80 | default: | |
| 81 | return R_ABS; | |
| 82 | } | |
| 83 | } | |
| 84 | ||
| 85 | // Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63. | |
| 86 | static uint32_t extractBits(uint64_t V, uint32_t Begin, uint32_t End) { | |
| 87 | return (V & ((1ULL << (Begin + 1)) - 1)) >> End; | |
| 88 | } | |
| 89 | ||
| 90 | void RISCV::relocateOne(uint8_t *Loc, const RelType Type, | |
| 91 | const uint64_t Val) const { | |
| 92 | switch (Type) { | |
| 93 | case R_RISCV_32: | |
| 94 | write32le(Loc, Val); | |
| 95 | return; | |
| 96 | case R_RISCV_64: | |
| 97 | write64le(Loc, Val); | |
| 98 | return; | |
| 99 | ||
| 100 | case R_RISCV_RVC_BRANCH: { | |
| 101 | checkInt(Loc, static_cast<int64_t>(Val) >> 1, 8, Type); | |
| 102 | checkAlignment(Loc, Val, 2, Type); | |
| 103 | uint16_t Insn = read16le(Loc) & 0xE383; | |
| 104 | uint16_t Imm8 = extractBits(Val, 8, 8) << 12; | |
| 105 | uint16_t Imm4_3 = extractBits(Val, 4, 3) << 10; | |
| 106 | uint16_t Imm7_6 = extractBits(Val, 7, 6) << 5; | |
| 107 | uint16_t Imm2_1 = extractBits(Val, 2, 1) << 3; | |
| 108 | uint16_t Imm5 = extractBits(Val, 5, 5) << 2; | |
| 109 | Insn |= Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5; | |
| 110 | ||
| 111 | write16le(Loc, Insn); | |
| 112 | return; | |
| 113 | } | |
| 114 | ||
| 115 | case R_RISCV_RVC_JUMP: { | |
| 116 | checkInt(Loc, static_cast<int64_t>(Val) >> 1, 11, Type); | |
| 117 | checkAlignment(Loc, Val, 2, Type); | |
| 118 | uint16_t Insn = read16le(Loc) & 0xE003; | |
| 119 | uint16_t Imm11 = extractBits(Val, 11, 11) << 12; | |
| 120 | uint16_t Imm4 = extractBits(Val, 4, 4) << 11; | |
| 121 | uint16_t Imm9_8 = extractBits(Val, 9, 8) << 9; | |
| 122 | uint16_t Imm10 = extractBits(Val, 10, 10) << 8; | |
| 123 | uint16_t Imm6 = extractBits(Val, 6, 6) << 7; | |
| 124 | uint16_t Imm7 = extractBits(Val, 7, 7) << 6; | |
| 125 | uint16_t Imm3_1 = extractBits(Val, 3, 1) << 3; | |
| 126 | uint16_t Imm5 = extractBits(Val, 5, 5) << 2; | |
| 127 | Insn |= Imm11 | Imm4 | Imm9_8 | Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5; | |
| 128 | ||
| 129 | write16le(Loc, Insn); | |
| 130 | return; | |
| 131 | } | |
| 132 | ||
| 133 | case R_RISCV_RVC_LUI: { | |
| 134 | int32_t Imm = ((Val + 0x800) >> 12); | |
| 135 | checkUInt(Loc, Imm, 6, Type); | |
| 136 | if (Imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0` | |
| 137 | write16le(Loc, (read16le(Loc) & 0x0F83) | 0x4000); | |
| 138 | } else { | |
| 139 | uint16_t Imm17 = extractBits(Val + 0x800, 17, 17) << 12; | |
| 140 | uint16_t Imm16_12 = extractBits(Val + 0x800, 16, 12) << 2; | |
| 141 | write16le(Loc, (read16le(Loc) & 0xEF83) | Imm17 | Imm16_12); | |
| 142 | } | |
| 143 | return; | |
| 144 | } | |
| 145 | ||
| 146 | case R_RISCV_JAL: { | |
| 147 | checkInt(Loc, static_cast<int64_t>(Val) >> 1, 20, Type); | |
| 148 | checkAlignment(Loc, Val, 2, Type); | |
| 149 | ||
| 150 | uint32_t Insn = read32le(Loc) & 0xFFF; | |
| 151 | uint32_t Imm20 = extractBits(Val, 20, 20) << 31; | |
| 152 | uint32_t Imm10_1 = extractBits(Val, 10, 1) << 21; | |
| 153 | uint32_t Imm11 = extractBits(Val, 11, 11) << 20; | |
| 154 | uint32_t Imm19_12 = extractBits(Val, 19, 12) << 12; | |
| 155 | Insn |= Imm20 | Imm10_1 | Imm11 | Imm19_12; | |
| 156 | ||
| 157 | write32le(Loc, Insn); | |
| 158 | return; | |
| 159 | } | |
| 160 | ||
| 161 | case R_RISCV_BRANCH: { | |
| 162 | checkInt(Loc, static_cast<int64_t>(Val) >> 1, 12, Type); | |
| 163 | checkAlignment(Loc, Val, 2, Type); | |
| 164 | ||
| 165 | uint32_t Insn = read32le(Loc) & 0x1FFF07F; | |
| 166 | uint32_t Imm12 = extractBits(Val, 12, 12) << 31; | |
| 167 | uint32_t Imm10_5 = extractBits(Val, 10, 5) << 25; | |
| 168 | uint32_t Imm4_1 = extractBits(Val, 4, 1) << 8; | |
| 169 | uint32_t Imm11 = extractBits(Val, 11, 11) << 7; | |
| 170 | Insn |= Imm12 | Imm10_5 | Imm4_1 | Imm11; | |
| 171 | ||
| 172 | write32le(Loc, Insn); | |
| 173 | return; | |
| 174 | } | |
| 175 | ||
| 176 | // auipc + jalr pair | |
| 177 | case R_RISCV_CALL: { | |
| 178 | checkInt(Loc, Val, 32, Type); | |
| 179 | if (isInt<32>(Val)) { | |
| 180 | relocateOne(Loc, R_RISCV_PCREL_HI20, Val); | |
| 181 | relocateOne(Loc + 4, R_RISCV_PCREL_LO12_I, Val); | |
| 182 | } | |
| 183 | return; | |
| 184 | } | |
| 185 | ||
| 186 | case R_RISCV_PCREL_HI20: | |
| 187 | case R_RISCV_HI20: { | |
| 188 | checkInt(Loc, Val, 32, Type); | |
| 189 | uint32_t Hi = Val + 0x800; | |
| 190 | write32le(Loc, (read32le(Loc) & 0xFFF) | (Hi & 0xFFFFF000)); | |
| 191 | return; | |
| 192 | } | |
| 193 | ||
| 194 | case R_RISCV_PCREL_LO12_I: | |
| 195 | case R_RISCV_LO12_I: { | |
| 196 | checkInt(Loc, Val, 32, Type); | |
| 197 | uint32_t Hi = Val + 0x800; | |
| 198 | uint32_t Lo = Val - (Hi & 0xFFFFF000); | |
| 199 | write32le(Loc, (read32le(Loc) & 0xFFFFF) | ((Lo & 0xFFF) << 20)); | |
| 200 | return; | |
| 201 | } | |
| 202 | ||
| 203 | case R_RISCV_PCREL_LO12_S: | |
| 204 | case R_RISCV_LO12_S: { | |
| 205 | checkInt(Loc, Val, 32, Type); | |
| 206 | uint32_t Hi = Val + 0x800; | |
| 207 | uint32_t Lo = Val - (Hi & 0xFFFFF000); | |
| 208 | uint32_t Imm11_5 = extractBits(Lo, 11, 5) << 25; | |
| 209 | uint32_t Imm4_0 = extractBits(Lo, 4, 0) << 7; | |
| 210 | write32le(Loc, (read32le(Loc) & 0x1FFF07F) | Imm11_5 | Imm4_0); | |
| 211 | return; | |
| 212 | } | |
| 213 | ||
| 214 | case R_RISCV_ADD8: | |
| 215 | *Loc += Val; | |
| 216 | return; | |
| 217 | case R_RISCV_ADD16: | |
| 218 | write16le(Loc, read16le(Loc) + Val); | |
| 219 | return; | |
| 220 | case R_RISCV_ADD32: | |
| 221 | write32le(Loc, read32le(Loc) + Val); | |
| 222 | return; | |
| 223 | case R_RISCV_ADD64: | |
| 224 | write64le(Loc, read64le(Loc) + Val); | |
| 225 | return; | |
| 226 | case R_RISCV_SUB6: | |
| 227 | *Loc = (*Loc & 0xc0) | (((*Loc & 0x3f) - Val) & 0x3f); | |
| 228 | return; | |
| 229 | case R_RISCV_SUB8: | |
| 230 | *Loc -= Val; | |
| 231 | return; | |
| 232 | case R_RISCV_SUB16: | |
| 233 | write16le(Loc, read16le(Loc) - Val); | |
| 234 | return; | |
| 235 | case R_RISCV_SUB32: | |
| 236 | write32le(Loc, read32le(Loc) - Val); | |
| 237 | return; | |
| 238 | case R_RISCV_SUB64: | |
| 239 | write64le(Loc, read64le(Loc) - Val); | |
| 240 | return; | |
| 241 | case R_RISCV_SET6: | |
| 242 | *Loc = (*Loc & 0xc0) | (Val & 0x3f); | |
| 243 | return; | |
| 244 | case R_RISCV_SET8: | |
| 245 | *Loc = Val; | |
| 246 | return; | |
| 247 | case R_RISCV_SET16: | |
| 248 | write16le(Loc, Val); | |
| 249 | return; | |
| 250 | case R_RISCV_SET32: | |
| 251 | case R_RISCV_32_PCREL: | |
| 252 | write32le(Loc, Val); | |
| 253 | return; | |
| 254 | ||
| 255 | case R_RISCV_ALIGN: | |
| 256 | case R_RISCV_RELAX: | |
| 257 | return; // Ignored (for now) | |
| 258 | case R_RISCV_NONE: | |
| 259 | return; // Do nothing | |
| 260 | ||
| 261 | // These are handled by the dynamic linker | |
| 262 | case R_RISCV_RELATIVE: | |
| 263 | case R_RISCV_COPY: | |
| 264 | case R_RISCV_JUMP_SLOT: | |
| 265 | // GP-relative relocations are only produced after relaxation, which | |
| 266 | // we don't support for now | |
| 267 | case R_RISCV_GPREL_I: | |
| 268 | case R_RISCV_GPREL_S: | |
| 269 | default: | |
| 270 | error(getErrorLocation(Loc) + | |
| 271 | "unimplemented relocation: " + toString(Type)); | |
| 272 | return; | |
| 273 | } | |
| 274 | } | |
| 275 | ||
| 276 | TargetInfo *elf::getRISCVTargetInfo() { | |
| 277 | static RISCV Target; | |
| 278 | return &Target; | |
| 279 | } |
deps/lld/ELF/Arch/SPARCV9.cpp+1| ... | ... | @@ -35,6 +35,7 @@ public: |
| 35 | 35 | SPARCV9::SPARCV9() { |
| 36 | 36 | CopyRel = R_SPARC_COPY; |
| 37 | 37 | GotRel = R_SPARC_GLOB_DAT; |
| 38 | NoneRel = R_SPARC_NONE; | |
| 38 | 39 | PltRel = R_SPARC_JMP_SLOT; |
| 39 | 40 | RelativeRel = R_SPARC_RELATIVE; |
| 40 | 41 | GotEntrySize = 8; |
deps/lld/ELF/Arch/X86.cpp+15-10| ... | ... | @@ -48,6 +48,7 @@ public: |
| 48 | 48 | X86::X86() { |
| 49 | 49 | CopyRel = R_386_COPY; |
| 50 | 50 | GotRel = R_386_GLOB_DAT; |
| 51 | NoneRel = R_386_NONE; | |
| 51 | 52 | PltRel = R_386_JUMP_SLOT; |
| 52 | 53 | IRelativeRel = R_386_IRELATIVE; |
| 53 | 54 | RelativeRel = R_386_RELATIVE; |
| ... | ... | @@ -59,7 +60,11 @@ X86::X86() { |
| 59 | 60 | PltEntrySize = 16; |
| 60 | 61 | PltHeaderSize = 16; |
| 61 | 62 | TlsGdRelaxSkip = 2; |
| 62 | TrapInstr = 0xcccccccc; // 0xcc = INT3 | |
| 63 | TrapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 | |
| 64 | ||
| 65 | // Align to the non-PAE large page size (known as a superpage or huge page). | |
| 66 | // FreeBSD automatically promotes large, superpage-aligned allocations. | |
| 67 | DefaultImageBase = 0x400000; | |
| 63 | 68 | } |
| 64 | 69 | |
| 65 | 70 | static bool hasBaseReg(uint8_t ModRM) { return (ModRM & 0xc7) != 0x5; } |
| ... | ... | @@ -152,7 +157,7 @@ RelExpr X86::adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 152 | 157 | } |
| 153 | 158 | |
| 154 | 159 | void X86::writeGotPltHeader(uint8_t *Buf) const { |
| 155 | write32le(Buf, InX::Dynamic->getVA()); | |
| 160 | write32le(Buf, In.Dynamic->getVA()); | |
| 156 | 161 | } |
| 157 | 162 | |
| 158 | 163 | void X86::writeGotPlt(uint8_t *Buf, const Symbol &S) const { |
| ... | ... | @@ -183,8 +188,8 @@ void X86::writePltHeader(uint8_t *Buf) const { |
| 183 | 188 | }; |
| 184 | 189 | memcpy(Buf, V, sizeof(V)); |
| 185 | 190 | |
| 186 | uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize(); | |
| 187 | uint32_t GotPlt = InX::GotPlt->getVA() - Ebx; | |
| 191 | uint32_t Ebx = In.Got->getVA() + In.Got->getSize(); | |
| 192 | uint32_t GotPlt = In.GotPlt->getVA() - Ebx; | |
| 188 | 193 | write32le(Buf + 2, GotPlt + 4); |
| 189 | 194 | write32le(Buf + 8, GotPlt + 8); |
| 190 | 195 | return; |
| ... | ... | @@ -196,7 +201,7 @@ void X86::writePltHeader(uint8_t *Buf) const { |
| 196 | 201 | 0x90, 0x90, 0x90, 0x90, // nop |
| 197 | 202 | }; |
| 198 | 203 | memcpy(Buf, PltData, sizeof(PltData)); |
| 199 | uint32_t GotPlt = InX::GotPlt->getVA(); | |
| 204 | uint32_t GotPlt = In.GotPlt->getVA(); | |
| 200 | 205 | write32le(Buf + 2, GotPlt + 4); |
| 201 | 206 | write32le(Buf + 8, GotPlt + 8); |
| 202 | 207 | } |
| ... | ... | @@ -213,7 +218,7 @@ void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 213 | 218 | |
| 214 | 219 | if (Config->Pic) { |
| 215 | 220 | // jmp *foo@GOT(%ebx) |
| 216 | uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize(); | |
| 221 | uint32_t Ebx = In.Got->getVA() + In.Got->getSize(); | |
| 217 | 222 | Buf[1] = 0xa3; |
| 218 | 223 | write32le(Buf + 2, GotPltEntryAddr - Ebx); |
| 219 | 224 | } else { |
| ... | ... | @@ -447,8 +452,8 @@ void RetpolinePic::writePltHeader(uint8_t *Buf) const { |
| 447 | 452 | }; |
| 448 | 453 | memcpy(Buf, Insn, sizeof(Insn)); |
| 449 | 454 | |
| 450 | uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize(); | |
| 451 | uint32_t GotPlt = InX::GotPlt->getVA() - Ebx; | |
| 455 | uint32_t Ebx = In.Got->getVA() + In.Got->getSize(); | |
| 456 | uint32_t GotPlt = In.GotPlt->getVA() - Ebx; | |
| 452 | 457 | write32le(Buf + 2, GotPlt + 4); |
| 453 | 458 | write32le(Buf + 9, GotPlt + 8); |
| 454 | 459 | } |
| ... | ... | @@ -467,7 +472,7 @@ void RetpolinePic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 467 | 472 | }; |
| 468 | 473 | memcpy(Buf, Insn, sizeof(Insn)); |
| 469 | 474 | |
| 470 | uint32_t Ebx = InX::Got->getVA() + InX::Got->getSize(); | |
| 475 | uint32_t Ebx = In.Got->getVA() + In.Got->getSize(); | |
| 471 | 476 | unsigned Off = getPltEntryOffset(Index); |
| 472 | 477 | write32le(Buf + 3, GotPltEntryAddr - Ebx); |
| 473 | 478 | write32le(Buf + 8, -Off - 12 + 32); |
| ... | ... | @@ -506,7 +511,7 @@ void RetpolineNoPic::writePltHeader(uint8_t *Buf) const { |
| 506 | 511 | }; |
| 507 | 512 | memcpy(Buf, Insn, sizeof(Insn)); |
| 508 | 513 | |
| 509 | uint32_t GotPlt = InX::GotPlt->getVA(); | |
| 514 | uint32_t GotPlt = In.GotPlt->getVA(); | |
| 510 | 515 | write32le(Buf + 2, GotPlt + 4); |
| 511 | 516 | write32le(Buf + 8, GotPlt + 8); |
| 512 | 517 | } |
deps/lld/ELF/Arch/X86_64.cpp+59-32| ... | ... | @@ -43,8 +43,8 @@ public: |
| 43 | 43 | void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 44 | 44 | void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 45 | 45 | void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override; |
| 46 | bool adjustPrologueForCrossSplitStack(uint8_t *Loc, | |
| 47 | uint8_t *End) const override; | |
| 46 | bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, | |
| 47 | uint8_t StOther) const override; | |
| 48 | 48 | |
| 49 | 49 | private: |
| 50 | 50 | void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op, |
| ... | ... | @@ -55,6 +55,7 @@ private: |
| 55 | 55 | template <class ELFT> X86_64<ELFT>::X86_64() { |
| 56 | 56 | CopyRel = R_X86_64_COPY; |
| 57 | 57 | GotRel = R_X86_64_GLOB_DAT; |
| 58 | NoneRel = R_X86_64_NONE; | |
| 58 | 59 | PltRel = R_X86_64_JUMP_SLOT; |
| 59 | 60 | RelativeRel = R_X86_64_RELATIVE; |
| 60 | 61 | IRelativeRel = R_X86_64_IRELATIVE; |
| ... | ... | @@ -66,7 +67,7 @@ template <class ELFT> X86_64<ELFT>::X86_64() { |
| 66 | 67 | PltEntrySize = 16; |
| 67 | 68 | PltHeaderSize = 16; |
| 68 | 69 | TlsGdRelaxSkip = 2; |
| 69 | TrapInstr = 0xcccccccc; // 0xcc = INT3 | |
| 70 | TrapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3 | |
| 70 | 71 | |
| 71 | 72 | // Align to the large page size (known as a superpage or huge page). |
| 72 | 73 | // FreeBSD automatically promotes large, superpage-aligned allocations. |
| ... | ... | @@ -124,7 +125,7 @@ template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const { |
| 124 | 125 | // required, but it is documented in the psabi and the glibc dynamic linker |
| 125 | 126 | // seems to use it (note that this is relevant for linking ld.so, not any |
| 126 | 127 | // other program). |
| 127 | write64le(Buf, InX::Dynamic->getVA()); | |
| 128 | write64le(Buf, In.Dynamic->getVA()); | |
| 128 | 129 | } |
| 129 | 130 | |
| 130 | 131 | template <class ELFT> |
| ... | ... | @@ -140,8 +141,8 @@ template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const { |
| 140 | 141 | 0x0f, 0x1f, 0x40, 0x00, // nop |
| 141 | 142 | }; |
| 142 | 143 | memcpy(Buf, PltData, sizeof(PltData)); |
| 143 | uint64_t GotPlt = InX::GotPlt->getVA(); | |
| 144 | uint64_t Plt = InX::Plt->getVA(); | |
| 144 | uint64_t GotPlt = In.GotPlt->getVA(); | |
| 145 | uint64_t Plt = In.Plt->getVA(); | |
| 145 | 146 | write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8 |
| 146 | 147 | write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16 |
| 147 | 148 | } |
| ... | ... | @@ -263,15 +264,6 @@ void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, RelType Type, |
| 263 | 264 | template <class ELFT> |
| 264 | 265 | void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type, |
| 265 | 266 | uint64_t Val) const { |
| 266 | // Convert | |
| 267 | // leaq bar@tlsld(%rip), %rdi | |
| 268 | // callq __tls_get_addr@PLT | |
| 269 | // leaq bar@dtpoff(%rax), %rcx | |
| 270 | // to | |
| 271 | // .word 0x6666 | |
| 272 | // .byte 0x66 | |
| 273 | // mov %fs:0,%rax | |
| 274 | // leaq bar@tpoff(%rax), %rcx | |
| 275 | 267 | if (Type == R_X86_64_DTPOFF64) { |
| 276 | 268 | write64le(Loc, Val); |
| 277 | 269 | return; |
| ... | ... | @@ -286,7 +278,37 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type, |
| 286 | 278 | 0x66, // .byte 0x66 |
| 287 | 279 | 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax |
| 288 | 280 | }; |
| 289 | memcpy(Loc - 3, Inst, sizeof(Inst)); | |
| 281 | ||
| 282 | if (Loc[4] == 0xe8) { | |
| 283 | // Convert | |
| 284 | // leaq bar@tlsld(%rip), %rdi # 48 8d 3d <Loc> | |
| 285 | // callq __tls_get_addr@PLT # e8 <disp32> | |
| 286 | // leaq bar@dtpoff(%rax), %rcx | |
| 287 | // to | |
| 288 | // .word 0x6666 | |
| 289 | // .byte 0x66 | |
| 290 | // mov %fs:0,%rax | |
| 291 | // leaq bar@tpoff(%rax), %rcx | |
| 292 | memcpy(Loc - 3, Inst, sizeof(Inst)); | |
| 293 | return; | |
| 294 | } | |
| 295 | ||
| 296 | if (Loc[4] == 0xff && Loc[5] == 0x15) { | |
| 297 | // Convert | |
| 298 | // leaq x@tlsld(%rip),%rdi # 48 8d 3d <Loc> | |
| 299 | // call *__tls_get_addr@GOTPCREL(%rip) # ff 15 <disp32> | |
| 300 | // to | |
| 301 | // .long 0x66666666 | |
| 302 | // movq %fs:0,%rax | |
| 303 | // See "Table 11.9: LD -> LE Code Transition (LP64)" in | |
| 304 | // https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf | |
| 305 | Loc[-3] = 0x66; | |
| 306 | memcpy(Loc - 2, Inst, sizeof(Inst)); | |
| 307 | return; | |
| 308 | } | |
| 309 | ||
| 310 | error(getErrorLocation(Loc - 3) + | |
| 311 | "expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD"); | |
| 290 | 312 | } |
| 291 | 313 | |
| 292 | 314 | template <class ELFT> |
| ... | ... | @@ -481,23 +503,27 @@ namespace { |
| 481 | 503 | // B) Or a load of a stack pointer offset with an lea to r10 or r11. |
| 482 | 504 | template <> |
| 483 | 505 | bool X86_64<ELF64LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc, |
| 484 | uint8_t *End) const { | |
| 506 | uint8_t *End, | |
| 507 | uint8_t StOther) const { | |
| 508 | if (Loc + 8 >= End) | |
| 509 | return false; | |
| 510 | ||
| 485 | 511 | // Replace "cmp %fs:0x70,%rsp" and subsequent branch |
| 486 | 512 | // with "stc, nopl 0x0(%rax,%rax,1)" |
| 487 | if (Loc + 8 < End && memcmp(Loc, "\x64\x48\x3b\x24\x25", 4) == 0) { | |
| 513 | if (memcmp(Loc, "\x64\x48\x3b\x24\x25", 5) == 0) { | |
| 488 | 514 | memcpy(Loc, "\xf9\x0f\x1f\x84\x00\x00\x00\x00", 8); |
| 489 | 515 | return true; |
| 490 | 516 | } |
| 491 | 517 | |
| 492 | // Adjust "lea -0x200(%rsp),%r10" to lea "-0x4200(%rsp),%r10" | |
| 493 | if (Loc + 7 < End && memcmp(Loc, "\x4c\x8d\x94\x24\x00\xfe\xff", 7) == 0) { | |
| 494 | memcpy(Loc, "\x4c\x8d\x94\x24\x00\xbe\xff", 7); | |
| 495 | return true; | |
| 496 | } | |
| 497 | ||
| 498 | // Adjust "lea -0x200(%rsp),%r11" to lea "-0x4200(%rsp),%r11" | |
| 499 | if (Loc + 7 < End && memcmp(Loc, "\x4c\x8d\x9c\x24\x00\xfe\xff", 7) == 0) { | |
| 500 | memcpy(Loc, "\x4c\x8d\x9c\x24\x00\xbe\xff", 7); | |
| 518 | // Adjust "lea X(%rsp),%rYY" to lea "(X - 0x4000)(%rsp),%rYY" where rYY could | |
| 519 | // be r10 or r11. The lea instruction feeds a subsequent compare which checks | |
| 520 | // if there is X available stack space. Making X larger effectively reserves | |
| 521 | // that much additional space. The stack grows downward so subtract the value. | |
| 522 | if (memcmp(Loc, "\x4c\x8d\x94\x24", 4) == 0 || | |
| 523 | memcmp(Loc, "\x4c\x8d\x9c\x24", 4) == 0) { | |
| 524 | // The offset bytes are encoded four bytes after the start of the | |
| 525 | // instruction. | |
| 526 | write32le(Loc + 4, read32le(Loc + 4) - 0x4000); | |
| 501 | 527 | return true; |
| 502 | 528 | } |
| 503 | 529 | return false; |
| ... | ... | @@ -505,7 +531,8 @@ bool X86_64<ELF64LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc, |
| 505 | 531 | |
| 506 | 532 | template <> |
| 507 | 533 | bool X86_64<ELF32LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc, |
| 508 | uint8_t *End) const { | |
| 534 | uint8_t *End, | |
| 535 | uint8_t StOther) const { | |
| 509 | 536 | llvm_unreachable("Target doesn't support split stacks."); |
| 510 | 537 | } |
| 511 | 538 | |
| ... | ... | @@ -566,8 +593,8 @@ template <class ELFT> void Retpoline<ELFT>::writePltHeader(uint8_t *Buf) const { |
| 566 | 593 | }; |
| 567 | 594 | memcpy(Buf, Insn, sizeof(Insn)); |
| 568 | 595 | |
| 569 | uint64_t GotPlt = InX::GotPlt->getVA(); | |
| 570 | uint64_t Plt = InX::Plt->getVA(); | |
| 596 | uint64_t GotPlt = In.GotPlt->getVA(); | |
| 597 | uint64_t Plt = In.Plt->getVA(); | |
| 571 | 598 | write32le(Buf + 2, GotPlt - Plt - 6 + 8); |
| 572 | 599 | write32le(Buf + 9, GotPlt - Plt - 13 + 16); |
| 573 | 600 | } |
| ... | ... | @@ -586,7 +613,7 @@ void Retpoline<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 586 | 613 | }; |
| 587 | 614 | memcpy(Buf, Insn, sizeof(Insn)); |
| 588 | 615 | |
| 589 | uint64_t Off = TargetInfo::getPltEntryOffset(Index); | |
| 616 | uint64_t Off = getPltEntryOffset(Index); | |
| 590 | 617 | |
| 591 | 618 | write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7); |
| 592 | 619 | write32le(Buf + 8, -Off - 12 + 32); |
| ... | ... | @@ -629,7 +656,7 @@ void RetpolineZNow<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, |
| 629 | 656 | memcpy(Buf, Insn, sizeof(Insn)); |
| 630 | 657 | |
| 631 | 658 | write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7); |
| 632 | write32le(Buf + 8, -TargetInfo::getPltEntryOffset(Index) - 12); | |
| 659 | write32le(Buf + 8, -getPltEntryOffset(Index) - 12); | |
| 633 | 660 | } |
| 634 | 661 | |
| 635 | 662 | template <class ELFT> static TargetInfo *getTargetInfo() { |
deps/lld/ELF/CMakeLists.txt+3-1| ... | ... | @@ -15,17 +15,19 @@ add_lld_library(lldELF |
| 15 | 15 | Arch/Hexagon.cpp |
| 16 | 16 | Arch/Mips.cpp |
| 17 | 17 | Arch/MipsArchTree.cpp |
| 18 | Arch/MSP430.cpp | |
| 18 | 19 | Arch/PPC.cpp |
| 19 | 20 | Arch/PPC64.cpp |
| 21 | Arch/RISCV.cpp | |
| 20 | 22 | Arch/SPARCV9.cpp |
| 21 | 23 | Arch/X86.cpp |
| 22 | 24 | Arch/X86_64.cpp |
| 23 | 25 | CallGraphSort.cpp |
| 26 | DWARF.cpp | |
| 24 | 27 | Driver.cpp |
| 25 | 28 | DriverUtils.cpp |
| 26 | 29 | EhFrame.cpp |
| 27 | 30 | Filesystem.cpp |
| 28 | GdbIndex.cpp | |
| 29 | 31 | ICF.cpp |
| 30 | 32 | InputFiles.cpp |
| 31 | 33 | InputSection.cpp |
deps/lld/ELF/CallGraphSort.cpp+21-30| ... | ... | @@ -57,10 +57,7 @@ struct Edge { |
| 57 | 57 | }; |
| 58 | 58 | |
| 59 | 59 | struct Cluster { |
| 60 | Cluster(int Sec, size_t S) { | |
| 61 | Sections.push_back(Sec); | |
| 62 | Size = S; | |
| 63 | } | |
| 60 | Cluster(int Sec, size_t S) : Sections{Sec}, Size(S) {} | |
| 64 | 61 | |
| 65 | 62 | double getDensity() const { |
| 66 | 63 | if (Size == 0) |
| ... | ... | @@ -72,7 +69,7 @@ struct Cluster { |
| 72 | 69 | size_t Size = 0; |
| 73 | 70 | uint64_t Weight = 0; |
| 74 | 71 | uint64_t InitialWeight = 0; |
| 75 | std::vector<Edge> Preds; | |
| 72 | Edge BestPred = {-1, 0}; | |
| 76 | 73 | }; |
| 77 | 74 | |
| 78 | 75 | class CallGraphSort { |
| ... | ... | @@ -96,12 +93,14 @@ constexpr int MAX_DENSITY_DEGRADATION = 8; |
| 96 | 93 | constexpr uint64_t MAX_CLUSTER_SIZE = 1024 * 1024; |
| 97 | 94 | } // end anonymous namespace |
| 98 | 95 | |
| 96 | typedef std::pair<const InputSectionBase *, const InputSectionBase *> | |
| 97 | SectionPair; | |
| 98 | ||
| 99 | 99 | // Take the edge list in Config->CallGraphProfile, resolve symbol names to |
| 100 | 100 | // Symbols, and generate a graph between InputSections with the provided |
| 101 | 101 | // weights. |
| 102 | 102 | CallGraphSort::CallGraphSort() { |
| 103 | llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>, | |
| 104 | uint64_t> &Profile = Config->CallGraphProfile; | |
| 103 | MapVector<SectionPair, uint64_t> &Profile = Config->CallGraphProfile; | |
| 105 | 104 | DenseMap<const InputSectionBase *, int> SecToCluster; |
| 106 | 105 | |
| 107 | 106 | auto GetOrCreateNode = [&](const InputSectionBase *IS) -> int { |
| ... | ... | @@ -114,7 +113,7 @@ CallGraphSort::CallGraphSort() { |
| 114 | 113 | }; |
| 115 | 114 | |
| 116 | 115 | // Create the graph. |
| 117 | for (const auto &C : Profile) { | |
| 116 | for (std::pair<SectionPair, uint64_t> &C : Profile) { | |
| 118 | 117 | const auto *FromSB = cast<InputSectionBase>(C.first.first->Repl); |
| 119 | 118 | const auto *ToSB = cast<InputSectionBase>(C.first.second->Repl); |
| 120 | 119 | uint64_t Weight = C.second; |
| ... | ... | @@ -136,8 +135,12 @@ CallGraphSort::CallGraphSort() { |
| 136 | 135 | if (From == To) |
| 137 | 136 | continue; |
| 138 | 137 | |
| 139 | // Add an edge | |
| 140 | Clusters[To].Preds.push_back({From, Weight}); | |
| 138 | // Remember the best edge. | |
| 139 | Cluster &ToC = Clusters[To]; | |
| 140 | if (ToC.BestPred.From == -1 || ToC.BestPred.Weight < Weight) { | |
| 141 | ToC.BestPred.From = From; | |
| 142 | ToC.BestPred.Weight = Weight; | |
| 143 | } | |
| 141 | 144 | } |
| 142 | 145 | for (Cluster &C : Clusters) |
| 143 | 146 | C.InitialWeight = C.Weight; |
| ... | ... | @@ -146,9 +149,7 @@ CallGraphSort::CallGraphSort() { |
| 146 | 149 | // It's bad to merge clusters which would degrade the density too much. |
| 147 | 150 | static bool isNewDensityBad(Cluster &A, Cluster &B) { |
| 148 | 151 | double NewDensity = double(A.Weight + B.Weight) / double(A.Size + B.Size); |
| 149 | if (NewDensity < A.getDensity() / MAX_DENSITY_DEGRADATION) | |
| 150 | return true; | |
| 151 | return false; | |
| 152 | return NewDensity < A.getDensity() / MAX_DENSITY_DEGRADATION; | |
| 152 | 153 | } |
| 153 | 154 | |
| 154 | 155 | static void mergeClusters(Cluster &Into, Cluster &From) { |
| ... | ... | @@ -167,9 +168,9 @@ void CallGraphSort::groupClusters() { |
| 167 | 168 | std::vector<int> SortedSecs(Clusters.size()); |
| 168 | 169 | std::vector<Cluster *> SecToCluster(Clusters.size()); |
| 169 | 170 | |
| 170 | for (int SI = 0, SE = Clusters.size(); SI != SE; ++SI) { | |
| 171 | SortedSecs[SI] = SI; | |
| 172 | SecToCluster[SI] = &Clusters[SI]; | |
| 171 | for (size_t I = 0; I < Clusters.size(); ++I) { | |
| 172 | SortedSecs[I] = I; | |
| 173 | SecToCluster[I] = &Clusters[I]; | |
| 173 | 174 | } |
| 174 | 175 | |
| 175 | 176 | std::stable_sort(SortedSecs.begin(), SortedSecs.end(), [&](int A, int B) { |
| ... | ... | @@ -181,21 +182,11 @@ void CallGraphSort::groupClusters() { |
| 181 | 182 | // been merged into another cluster yet. |
| 182 | 183 | Cluster &C = Clusters[SI]; |
| 183 | 184 | |
| 184 | int BestPred = -1; | |
| 185 | uint64_t BestWeight = 0; | |
| 186 | ||
| 187 | for (Edge &E : C.Preds) { | |
| 188 | if (BestPred == -1 || E.Weight > BestWeight) { | |
| 189 | BestPred = E.From; | |
| 190 | BestWeight = E.Weight; | |
| 191 | } | |
| 192 | } | |
| 193 | ||
| 194 | // don't consider merging if the edge is unlikely. | |
| 195 | if (BestWeight * 10 <= C.InitialWeight) | |
| 185 | // Don't consider merging if the edge is unlikely. | |
| 186 | if (C.BestPred.From == -1 || C.BestPred.Weight * 10 <= C.InitialWeight) | |
| 196 | 187 | continue; |
| 197 | 188 | |
| 198 | Cluster *PredC = SecToCluster[BestPred]; | |
| 189 | Cluster *PredC = SecToCluster[C.BestPred.From]; | |
| 199 | 190 | if (PredC == &C) |
| 200 | 191 | continue; |
| 201 | 192 | |
| ... | ... | @@ -229,7 +220,7 @@ DenseMap<const InputSectionBase *, int> CallGraphSort::run() { |
| 229 | 220 | groupClusters(); |
| 230 | 221 | |
| 231 | 222 | // Generate order. |
| 232 | llvm::DenseMap<const InputSectionBase *, int> OrderMap; | |
| 223 | DenseMap<const InputSectionBase *, int> OrderMap; | |
| 233 | 224 | ssize_t CurOrder = 1; |
| 234 | 225 | |
| 235 | 226 | for (const Cluster &C : Clusters) |
deps/lld/ELF/Config.h+11-1| ... | ... | @@ -47,7 +47,7 @@ enum class ICFLevel { None, Safe, All }; |
| 47 | 47 | enum class StripPolicy { None, All, Debug }; |
| 48 | 48 | |
| 49 | 49 | // For --unresolved-symbols. |
| 50 | enum class UnresolvedPolicy { ReportError, Warn, Ignore, IgnoreAll }; | |
| 50 | enum class UnresolvedPolicy { ReportError, Warn, Ignore }; | |
| 51 | 51 | |
| 52 | 52 | // For --orphan-handling. |
| 53 | 53 | enum class OrphanHandlingPolicy { Place, Warn, Error }; |
| ... | ... | @@ -127,6 +127,7 @@ struct Configuration { |
| 127 | 127 | bool AsNeeded = false; |
| 128 | 128 | bool Bsymbolic; |
| 129 | 129 | bool BsymbolicFunctions; |
| 130 | bool CallGraphProfileSort; | |
| 130 | 131 | bool CheckSections; |
| 131 | 132 | bool CompressDebugSections; |
| 132 | 133 | bool Cref; |
| ... | ... | @@ -134,11 +135,13 @@ struct Configuration { |
| 134 | 135 | bool Demangle = true; |
| 135 | 136 | bool DisableVerify; |
| 136 | 137 | bool EhFrameHdr; |
| 138 | bool EmitLLVM; | |
| 137 | 139 | bool EmitRelocs; |
| 138 | 140 | bool EnableNewDtags; |
| 139 | 141 | bool ExecuteOnly; |
| 140 | 142 | bool ExportDynamic; |
| 141 | 143 | bool FixCortexA53Errata843419; |
| 144 | bool FormatBinary = false; | |
| 142 | 145 | bool GcSections; |
| 143 | 146 | bool GdbIndex; |
| 144 | 147 | bool GnuHash = false; |
| ... | ... | @@ -156,6 +159,7 @@ struct Configuration { |
| 156 | 159 | bool OFormatBinary; |
| 157 | 160 | bool Omagic; |
| 158 | 161 | bool OptRemarksWithHotness; |
| 162 | bool PicThunk; | |
| 159 | 163 | bool Pie; |
| 160 | 164 | bool PrintGcSections; |
| 161 | 165 | bool PrintIcfSections; |
| ... | ... | @@ -170,19 +174,24 @@ struct Configuration { |
| 170 | 174 | bool Trace; |
| 171 | 175 | bool ThinLTOEmitImportsFiles; |
| 172 | 176 | bool ThinLTOIndexOnly; |
| 177 | bool TocOptimize; | |
| 173 | 178 | bool UndefinedVersion; |
| 174 | 179 | bool UseAndroidRelrTags = false; |
| 175 | 180 | bool WarnBackrefs; |
| 176 | 181 | bool WarnCommon; |
| 182 | bool WarnIfuncTextrel; | |
| 177 | 183 | bool WarnMissingEntry; |
| 178 | 184 | bool WarnSymbolOrdering; |
| 179 | 185 | bool WriteAddends; |
| 180 | 186 | bool ZCombreloc; |
| 181 | 187 | bool ZCopyreloc; |
| 182 | 188 | bool ZExecstack; |
| 189 | bool ZGlobal; | |
| 183 | 190 | bool ZHazardplt; |
| 184 | 191 | bool ZInitfirst; |
| 192 | bool ZInterpose; | |
| 185 | 193 | bool ZKeepTextSectionPrefix; |
| 194 | bool ZNodefaultlib; | |
| 186 | 195 | bool ZNodelete; |
| 187 | 196 | bool ZNodlopen; |
| 188 | 197 | bool ZNow; |
| ... | ... | @@ -212,6 +221,7 @@ struct Configuration { |
| 212 | 221 | unsigned LTOO; |
| 213 | 222 | unsigned Optimize; |
| 214 | 223 | unsigned ThinLTOJobs; |
| 224 | int32_t SplitStackAdjustSize; | |
| 215 | 225 | |
| 216 | 226 | // The following config options do not directly correspond to any |
| 217 | 227 | // particualr command line options. |
deps/lld/ELF/DWARF.cpp created+109| ... | ... | @@ -0,0 +1,109 @@ |
| 1 | //===- DWARF.cpp ----------------------------------------------------------===// | |
| 2 | // | |
| 3 | // The LLVM Linker | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | // | |
| 10 | // The -gdb-index option instructs the linker to emit a .gdb_index section. | |
| 11 | // The section contains information to make gdb startup faster. | |
| 12 | // The format of the section is described at | |
| 13 | // https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html. | |
| 14 | // | |
| 15 | //===----------------------------------------------------------------------===// | |
| 16 | ||
| 17 | #include "DWARF.h" | |
| 18 | #include "Symbols.h" | |
| 19 | #include "Target.h" | |
| 20 | #include "lld/Common/Memory.h" | |
| 21 | #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" | |
| 22 | #include "llvm/Object/ELFObjectFile.h" | |
| 23 | ||
| 24 | using namespace llvm; | |
| 25 | using namespace llvm::object; | |
| 26 | using namespace lld; | |
| 27 | using namespace lld::elf; | |
| 28 | ||
| 29 | template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *Obj) { | |
| 30 | for (InputSectionBase *Sec : Obj->getSections()) { | |
| 31 | if (!Sec) | |
| 32 | continue; | |
| 33 | ||
| 34 | if (LLDDWARFSection *M = | |
| 35 | StringSwitch<LLDDWARFSection *>(Sec->Name) | |
| 36 | .Case(".debug_addr", &AddrSection) | |
| 37 | .Case(".debug_gnu_pubnames", &GnuPubNamesSection) | |
| 38 | .Case(".debug_gnu_pubtypes", &GnuPubTypesSection) | |
| 39 | .Case(".debug_info", &InfoSection) | |
| 40 | .Case(".debug_ranges", &RangeSection) | |
| 41 | .Case(".debug_rnglists", &RngListsSection) | |
| 42 | .Case(".debug_line", &LineSection) | |
| 43 | .Default(nullptr)) { | |
| 44 | M->Data = toStringRef(Sec->data()); | |
| 45 | M->Sec = Sec; | |
| 46 | continue; | |
| 47 | } | |
| 48 | ||
| 49 | if (Sec->Name == ".debug_abbrev") | |
| 50 | AbbrevSection = toStringRef(Sec->data()); | |
| 51 | else if (Sec->Name == ".debug_str") | |
| 52 | StrSection = toStringRef(Sec->data()); | |
| 53 | else if (Sec->Name == ".debug_line_str") | |
| 54 | LineStringSection = toStringRef(Sec->data()); | |
| 55 | } | |
| 56 | } | |
| 57 | ||
| 58 | // Find if there is a relocation at Pos in Sec. The code is a bit | |
| 59 | // more complicated than usual because we need to pass a section index | |
| 60 | // to llvm since it has no idea about InputSection. | |
| 61 | template <class ELFT> | |
| 62 | template <class RelTy> | |
| 63 | Optional<RelocAddrEntry> | |
| 64 | LLDDwarfObj<ELFT>::findAux(const InputSectionBase &Sec, uint64_t Pos, | |
| 65 | ArrayRef<RelTy> Rels) const { | |
| 66 | auto It = std::lower_bound( | |
| 67 | Rels.begin(), Rels.end(), Pos, | |
| 68 | [](const RelTy &A, uint64_t B) { return A.r_offset < B; }); | |
| 69 | if (It == Rels.end() || It->r_offset != Pos) | |
| 70 | return None; | |
| 71 | const RelTy &Rel = *It; | |
| 72 | ||
| 73 | const ObjFile<ELFT> *File = Sec.getFile<ELFT>(); | |
| 74 | uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); | |
| 75 | const typename ELFT::Sym &Sym = File->getELFSyms()[SymIndex]; | |
| 76 | uint32_t SecIndex = File->getSectionIndex(Sym); | |
| 77 | ||
| 78 | // Broken debug info can point to a non-Defined symbol. | |
| 79 | auto *DR = dyn_cast<Defined>(&File->getRelocTargetSym(Rel)); | |
| 80 | if (!DR) { | |
| 81 | RelType Type = Rel.getType(Config->IsMips64EL); | |
| 82 | if (Type != Target->NoneRel) | |
| 83 | error(toString(File) + ": relocation " + lld::toString(Type) + " at 0x" + | |
| 84 | llvm::utohexstr(Rel.r_offset) + " has unsupported target"); | |
| 85 | return None; | |
| 86 | } | |
| 87 | uint64_t Val = DR->Value + getAddend<ELFT>(Rel); | |
| 88 | ||
| 89 | // FIXME: We should be consistent about always adding the file | |
| 90 | // offset or not. | |
| 91 | if (DR->Section->Flags & ELF::SHF_ALLOC) | |
| 92 | Val += cast<InputSection>(DR->Section)->getOffsetInFile(); | |
| 93 | ||
| 94 | return RelocAddrEntry{SecIndex, Val}; | |
| 95 | } | |
| 96 | ||
| 97 | template <class ELFT> | |
| 98 | Optional<RelocAddrEntry> LLDDwarfObj<ELFT>::find(const llvm::DWARFSection &S, | |
| 99 | uint64_t Pos) const { | |
| 100 | auto &Sec = static_cast<const LLDDWARFSection &>(S); | |
| 101 | if (Sec.Sec->AreRelocsRela) | |
| 102 | return findAux(*Sec.Sec, Pos, Sec.Sec->template relas<ELFT>()); | |
| 103 | return findAux(*Sec.Sec, Pos, Sec.Sec->template rels<ELFT>()); | |
| 104 | } | |
| 105 | ||
| 106 | template class elf::LLDDwarfObj<ELF32LE>; | |
| 107 | template class elf::LLDDwarfObj<ELF32BE>; | |
| 108 | template class elf::LLDDwarfObj<ELF64LE>; | |
| 109 | template class elf::LLDDwarfObj<ELF64BE>; |
deps/lld/ELF/DWARF.h created+93| ... | ... | @@ -0,0 +1,93 @@ |
| 1 | //===- DWARF.h -----------------------------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // The LLVM Linker | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===-------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef LLD_ELF_DWARF_H | |
| 11 | #define LLD_ELF_DWARF_H | |
| 12 | ||
| 13 | #include "InputFiles.h" | |
| 14 | #include "llvm/ADT/STLExtras.h" | |
| 15 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" | |
| 16 | #include "llvm/Object/ELF.h" | |
| 17 | ||
| 18 | namespace lld { | |
| 19 | namespace elf { | |
| 20 | ||
| 21 | class InputSection; | |
| 22 | ||
| 23 | struct LLDDWARFSection final : public llvm::DWARFSection { | |
| 24 | InputSectionBase *Sec = nullptr; | |
| 25 | }; | |
| 26 | ||
| 27 | template <class ELFT> class LLDDwarfObj final : public llvm::DWARFObject { | |
| 28 | public: | |
| 29 | explicit LLDDwarfObj(ObjFile<ELFT> *Obj); | |
| 30 | ||
| 31 | void forEachInfoSections( | |
| 32 | llvm::function_ref<void(const llvm::DWARFSection &)> F) const override { | |
| 33 | F(InfoSection); | |
| 34 | } | |
| 35 | ||
| 36 | const llvm::DWARFSection &getRangeSection() const override { | |
| 37 | return RangeSection; | |
| 38 | } | |
| 39 | ||
| 40 | const llvm::DWARFSection &getRnglistsSection() const override { | |
| 41 | return RngListsSection; | |
| 42 | } | |
| 43 | ||
| 44 | const llvm::DWARFSection &getLineSection() const override { | |
| 45 | return LineSection; | |
| 46 | } | |
| 47 | ||
| 48 | const llvm::DWARFSection &getAddrSection() const override { | |
| 49 | return AddrSection; | |
| 50 | } | |
| 51 | ||
| 52 | const llvm::DWARFSection &getGnuPubNamesSection() const override { | |
| 53 | return GnuPubNamesSection; | |
| 54 | } | |
| 55 | ||
| 56 | const llvm::DWARFSection &getGnuPubTypesSection() const override { | |
| 57 | return GnuPubTypesSection; | |
| 58 | } | |
| 59 | ||
| 60 | StringRef getFileName() const override { return ""; } | |
| 61 | StringRef getAbbrevSection() const override { return AbbrevSection; } | |
| 62 | StringRef getStringSection() const override { return StrSection; } | |
| 63 | StringRef getLineStringSection() const override { return LineStringSection; } | |
| 64 | ||
| 65 | bool isLittleEndian() const override { | |
| 66 | return ELFT::TargetEndianness == llvm::support::little; | |
| 67 | } | |
| 68 | ||
| 69 | llvm::Optional<llvm::RelocAddrEntry> find(const llvm::DWARFSection &Sec, | |
| 70 | uint64_t Pos) const override; | |
| 71 | ||
| 72 | private: | |
| 73 | template <class RelTy> | |
| 74 | llvm::Optional<llvm::RelocAddrEntry> findAux(const InputSectionBase &Sec, | |
| 75 | uint64_t Pos, | |
| 76 | ArrayRef<RelTy> Rels) const; | |
| 77 | ||
| 78 | LLDDWARFSection GnuPubNamesSection; | |
| 79 | LLDDWARFSection GnuPubTypesSection; | |
| 80 | LLDDWARFSection InfoSection; | |
| 81 | LLDDWARFSection RangeSection; | |
| 82 | LLDDWARFSection RngListsSection; | |
| 83 | LLDDWARFSection LineSection; | |
| 84 | LLDDWARFSection AddrSection; | |
| 85 | StringRef AbbrevSection; | |
| 86 | StringRef StrSection; | |
| 87 | StringRef LineStringSection; | |
| 88 | }; | |
| 89 | ||
| 90 | } // namespace elf | |
| 91 | } // namespace lld | |
| 92 | ||
| 93 | #endif |
deps/lld/ELF/Driver.cpp+255-124| ... | ... | @@ -63,6 +63,7 @@ using namespace llvm; |
| 63 | 63 | using namespace llvm::ELF; |
| 64 | 64 | using namespace llvm::object; |
| 65 | 65 | using namespace llvm::sys; |
| 66 | using namespace llvm::support; | |
| 66 | 67 | |
| 67 | 68 | using namespace lld; |
| 68 | 69 | using namespace lld::elf; |
| ... | ... | @@ -74,7 +75,7 @@ static void setConfigs(opt::InputArgList &Args); |
| 74 | 75 | |
| 75 | 76 | bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, |
| 76 | 77 | raw_ostream &Error) { |
| 77 | errorHandler().LogName = sys::path::filename(Args[0]); | |
| 78 | errorHandler().LogName = args::getFilenameWithoutExe(Args[0]); | |
| 78 | 79 | errorHandler().ErrorLimitExceededMsg = |
| 79 | 80 | "too many errors emitted, stopping now (use " |
| 80 | 81 | "-error-limit=0 to see all errors)"; |
| ... | ... | @@ -84,7 +85,6 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, |
| 84 | 85 | |
| 85 | 86 | InputSections.clear(); |
| 86 | 87 | OutputSections.clear(); |
| 87 | Tar = nullptr; | |
| 88 | 88 | BinaryFiles.clear(); |
| 89 | 89 | BitcodeFiles.clear(); |
| 90 | 90 | ObjectFiles.clear(); |
| ... | ... | @@ -94,6 +94,10 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly, |
| 94 | 94 | Driver = make<LinkerDriver>(); |
| 95 | 95 | Script = make<LinkerScript>(); |
| 96 | 96 | Symtab = make<SymbolTable>(); |
| 97 | ||
| 98 | Tar = nullptr; | |
| 99 | memset(&In, 0, sizeof(In)); | |
| 100 | ||
| 97 | 101 | Config->ProgName = Args[0]; |
| 98 | 102 | |
| 99 | 103 | Driver->main(Args); |
| ... | ... | @@ -125,9 +129,11 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) { |
| 125 | 129 | .Case("elf32_x86_64", {ELF32LEKind, EM_X86_64}) |
| 126 | 130 | .Cases("elf32btsmip", "elf32btsmipn32", {ELF32BEKind, EM_MIPS}) |
| 127 | 131 | .Cases("elf32ltsmip", "elf32ltsmipn32", {ELF32LEKind, EM_MIPS}) |
| 132 | .Case("elf32lriscv", {ELF32LEKind, EM_RISCV}) | |
| 128 | 133 | .Case("elf32ppc", {ELF32BEKind, EM_PPC}) |
| 129 | 134 | .Case("elf64btsmip", {ELF64BEKind, EM_MIPS}) |
| 130 | 135 | .Case("elf64ltsmip", {ELF64LEKind, EM_MIPS}) |
| 136 | .Case("elf64lriscv", {ELF64LEKind, EM_RISCV}) | |
| 131 | 137 | .Case("elf64ppc", {ELF64BEKind, EM_PPC64}) |
| 132 | 138 | .Case("elf64lppc", {ELF64LEKind, EM_PPC64}) |
| 133 | 139 | .Cases("elf_amd64", "elf_x86_64", {ELF64LEKind, EM_X86_64}) |
| ... | ... | @@ -183,7 +189,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { |
| 183 | 189 | return; |
| 184 | 190 | MemoryBufferRef MBRef = *Buffer; |
| 185 | 191 | |
| 186 | if (InBinary) { | |
| 192 | if (Config->FormatBinary) { | |
| 187 | 193 | Files.push_back(make<BinaryFile>(MBRef)); |
| 188 | 194 | return; |
| 189 | 195 | } |
| ... | ... | @@ -218,7 +224,7 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) { |
| 218 | 224 | return; |
| 219 | 225 | } |
| 220 | 226 | case file_magic::elf_shared_object: |
| 221 | if (Config->Relocatable) { | |
| 227 | if (Config->Static || Config->Relocatable) { | |
| 222 | 228 | error("attempted static link of dynamic object " + Path); |
| 223 | 229 | return; |
| 224 | 230 | } |
| ... | ... | @@ -269,14 +275,17 @@ static void initLLVM() { |
| 269 | 275 | |
| 270 | 276 | // Some command line options or some combinations of them are not allowed. |
| 271 | 277 | // This function checks for such errors. |
| 272 | static void checkOptions(opt::InputArgList &Args) { | |
| 278 | static void checkOptions() { | |
| 273 | 279 | // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup |
| 274 | 280 | // table which is a relatively new feature. |
| 275 | 281 | if (Config->EMachine == EM_MIPS && Config->GnuHash) |
| 276 | error("the .gnu.hash section is not compatible with the MIPS target."); | |
| 282 | error("the .gnu.hash section is not compatible with the MIPS target"); | |
| 277 | 283 | |
| 278 | 284 | if (Config->FixCortexA53Errata843419 && Config->EMachine != EM_AARCH64) |
| 279 | error("--fix-cortex-a53-843419 is only supported on AArch64 targets."); | |
| 285 | error("--fix-cortex-a53-843419 is only supported on AArch64 targets"); | |
| 286 | ||
| 287 | if (Config->TocOptimize && Config->EMachine != EM_PPC64) | |
| 288 | error("--toc-optimize is only supported on the PowerPC64 target"); | |
| 280 | 289 | |
| 281 | 290 | if (Config->Pie && Config->Shared) |
| 282 | 291 | error("-shared and -pie may not be used together"); |
| ... | ... | @@ -336,12 +345,13 @@ static bool getZFlag(opt::InputArgList &Args, StringRef K1, StringRef K2, |
| 336 | 345 | return Default; |
| 337 | 346 | } |
| 338 | 347 | |
| 339 | static bool isKnown(StringRef S) { | |
| 348 | static bool isKnownZFlag(StringRef S) { | |
| 340 | 349 | return S == "combreloc" || S == "copyreloc" || S == "defs" || |
| 341 | S == "execstack" || S == "hazardplt" || S == "initfirst" || | |
| 350 | S == "execstack" || S == "global" || S == "hazardplt" || | |
| 351 | S == "initfirst" || S == "interpose" || | |
| 342 | 352 | S == "keep-text-section-prefix" || S == "lazy" || S == "muldefs" || |
| 343 | S == "nocombreloc" || S == "nocopyreloc" || S == "nodelete" || | |
| 344 | S == "nodlopen" || S == "noexecstack" || | |
| 353 | S == "nocombreloc" || S == "nocopyreloc" || S == "nodefaultlib" || | |
| 354 | S == "nodelete" || S == "nodlopen" || S == "noexecstack" || | |
| 345 | 355 | S == "nokeep-text-section-prefix" || S == "norelro" || S == "notext" || |
| 346 | 356 | S == "now" || S == "origin" || S == "relro" || S == "retpolineplt" || |
| 347 | 357 | S == "rodynamic" || S == "text" || S == "wxneeded" || |
| ... | ... | @@ -351,7 +361,7 @@ static bool isKnown(StringRef S) { |
| 351 | 361 | // Report an error for an unknown -z option. |
| 352 | 362 | static void checkZOptions(opt::InputArgList &Args) { |
| 353 | 363 | for (auto *Arg : Args.filtered(OPT_z)) |
| 354 | if (!isKnown(Arg->getValue())) | |
| 364 | if (!isKnownZFlag(Arg->getValue())) | |
| 355 | 365 | error("unknown -z value: " + StringRef(Arg->getValue())); |
| 356 | 366 | } |
| 357 | 367 | |
| ... | ... | @@ -386,31 +396,30 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) { |
| 386 | 396 | if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version)) |
| 387 | 397 | message(getLLDVersion() + " (compatible with GNU linkers)"); |
| 388 | 398 | |
| 389 | // The behavior of -v or --version is a bit strange, but this is | |
| 390 | // needed for compatibility with GNU linkers. | |
| 391 | if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT)) | |
| 392 | return; | |
| 393 | if (Args.hasArg(OPT_version)) | |
| 394 | return; | |
| 395 | ||
| 396 | 399 | if (const char *Path = getReproduceOption(Args)) { |
| 397 | 400 | // Note that --reproduce is a debug option so you can ignore it |
| 398 | 401 | // if you are trying to understand the whole picture of the code. |
| 399 | 402 | Expected<std::unique_ptr<TarWriter>> ErrOrWriter = |
| 400 | 403 | TarWriter::create(Path, path::stem(Path)); |
| 401 | 404 | if (ErrOrWriter) { |
| 402 | Tar = ErrOrWriter->get(); | |
| 405 | Tar = std::move(*ErrOrWriter); | |
| 403 | 406 | Tar->append("response.txt", createResponseFile(Args)); |
| 404 | 407 | Tar->append("version.txt", getLLDVersion() + "\n"); |
| 405 | make<std::unique_ptr<TarWriter>>(std::move(*ErrOrWriter)); | |
| 406 | 408 | } else { |
| 407 | error(Twine("--reproduce: failed to open ") + Path + ": " + | |
| 408 | toString(ErrOrWriter.takeError())); | |
| 409 | error("--reproduce: " + toString(ErrOrWriter.takeError())); | |
| 409 | 410 | } |
| 410 | 411 | } |
| 411 | 412 | |
| 412 | 413 | readConfigs(Args); |
| 413 | 414 | checkZOptions(Args); |
| 415 | ||
| 416 | // The behavior of -v or --version is a bit strange, but this is | |
| 417 | // needed for compatibility with GNU linkers. | |
| 418 | if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT)) | |
| 419 | return; | |
| 420 | if (Args.hasArg(OPT_version)) | |
| 421 | return; | |
| 422 | ||
| 414 | 423 | initLLVM(); |
| 415 | 424 | createFiles(Args); |
| 416 | 425 | if (errorCount()) |
| ... | ... | @@ -418,7 +427,7 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) { |
| 418 | 427 | |
| 419 | 428 | inferMachineType(); |
| 420 | 429 | setConfigs(Args); |
| 421 | checkOptions(Args); | |
| 430 | checkOptions(); | |
| 422 | 431 | if (errorCount()) |
| 423 | 432 | return; |
| 424 | 433 | |
| ... | ... | @@ -448,9 +457,6 @@ static std::string getRpath(opt::InputArgList &Args) { |
| 448 | 457 | // Determines what we should do if there are remaining unresolved |
| 449 | 458 | // symbols after the name resolution. |
| 450 | 459 | static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) { |
| 451 | if (Args.hasArg(OPT_relocatable)) | |
| 452 | return UnresolvedPolicy::IgnoreAll; | |
| 453 | ||
| 454 | 460 | UnresolvedPolicy ErrorOrWarn = Args.hasFlag(OPT_error_unresolved_symbols, |
| 455 | 461 | OPT_warn_unresolved_symbols, true) |
| 456 | 462 | ? UnresolvedPolicy::ReportError |
| ... | ... | @@ -497,14 +503,11 @@ static Target2Policy getTarget2(opt::InputArgList &Args) { |
| 497 | 503 | } |
| 498 | 504 | |
| 499 | 505 | static bool isOutputFormatBinary(opt::InputArgList &Args) { |
| 500 | if (auto *Arg = Args.getLastArg(OPT_oformat)) { | |
| 501 | StringRef S = Arg->getValue(); | |
| 502 | if (S == "binary") | |
| 503 | return true; | |
| 504 | if (S.startswith("elf")) | |
| 505 | return false; | |
| 506 | StringRef S = Args.getLastArgValue(OPT_oformat, "elf"); | |
| 507 | if (S == "binary") | |
| 508 | return true; | |
| 509 | if (!S.startswith("elf")) | |
| 506 | 510 | error("unknown --oformat value: " + S); |
| 507 | } | |
| 508 | 511 | return false; |
| 509 | 512 | } |
| 510 | 513 | |
| ... | ... | @@ -645,38 +648,56 @@ static std::pair<bool, bool> getPackDynRelocs(opt::InputArgList &Args) { |
| 645 | 648 | |
| 646 | 649 | static void readCallGraph(MemoryBufferRef MB) { |
| 647 | 650 | // Build a map from symbol name to section |
| 648 | DenseMap<StringRef, const Symbol *> SymbolNameToSymbol; | |
| 651 | DenseMap<StringRef, Symbol *> Map; | |
| 649 | 652 | for (InputFile *File : ObjectFiles) |
| 650 | 653 | for (Symbol *Sym : File->getSymbols()) |
| 651 | SymbolNameToSymbol[Sym->getName()] = Sym; | |
| 654 | Map[Sym->getName()] = Sym; | |
| 655 | ||
| 656 | auto FindSection = [&](StringRef Name) -> InputSectionBase * { | |
| 657 | Symbol *Sym = Map.lookup(Name); | |
| 658 | if (!Sym) { | |
| 659 | if (Config->WarnSymbolOrdering) | |
| 660 | warn(MB.getBufferIdentifier() + ": no such symbol: " + Name); | |
| 661 | return nullptr; | |
| 662 | } | |
| 663 | maybeWarnUnorderableSymbol(Sym); | |
| 664 | ||
| 665 | if (Defined *DR = dyn_cast_or_null<Defined>(Sym)) | |
| 666 | return dyn_cast_or_null<InputSectionBase>(DR->Section); | |
| 667 | return nullptr; | |
| 668 | }; | |
| 652 | 669 | |
| 653 | for (StringRef L : args::getLines(MB)) { | |
| 670 | for (StringRef Line : args::getLines(MB)) { | |
| 654 | 671 | SmallVector<StringRef, 3> Fields; |
| 655 | L.split(Fields, ' '); | |
| 672 | Line.split(Fields, ' '); | |
| 656 | 673 | uint64_t Count; |
| 657 | if (Fields.size() != 3 || !to_integer(Fields[2], Count)) | |
| 658 | fatal(MB.getBufferIdentifier() + ": parse error"); | |
| 659 | const Symbol *FromSym = SymbolNameToSymbol.lookup(Fields[0]); | |
| 660 | const Symbol *ToSym = SymbolNameToSymbol.lookup(Fields[1]); | |
| 661 | if (Config->WarnSymbolOrdering) { | |
| 662 | if (!FromSym) | |
| 663 | warn(MB.getBufferIdentifier() + ": no such symbol: " + Fields[0]); | |
| 664 | if (!ToSym) | |
| 665 | warn(MB.getBufferIdentifier() + ": no such symbol: " + Fields[1]); | |
| 674 | ||
| 675 | if (Fields.size() != 3 || !to_integer(Fields[2], Count)) { | |
| 676 | error(MB.getBufferIdentifier() + ": parse error"); | |
| 677 | return; | |
| 678 | } | |
| 679 | ||
| 680 | if (InputSectionBase *From = FindSection(Fields[0])) | |
| 681 | if (InputSectionBase *To = FindSection(Fields[1])) | |
| 682 | Config->CallGraphProfile[std::make_pair(From, To)] += Count; | |
| 683 | } | |
| 684 | } | |
| 685 | ||
| 686 | template <class ELFT> static void readCallGraphsFromObjectFiles() { | |
| 687 | for (auto File : ObjectFiles) { | |
| 688 | auto *Obj = cast<ObjFile<ELFT>>(File); | |
| 689 | ||
| 690 | for (const Elf_CGProfile_Impl<ELFT> &CGPE : Obj->CGProfile) { | |
| 691 | auto *FromSym = dyn_cast<Defined>(&Obj->getSymbol(CGPE.cgp_from)); | |
| 692 | auto *ToSym = dyn_cast<Defined>(&Obj->getSymbol(CGPE.cgp_to)); | |
| 693 | if (!FromSym || !ToSym) | |
| 694 | continue; | |
| 695 | ||
| 696 | auto *From = dyn_cast_or_null<InputSectionBase>(FromSym->Section); | |
| 697 | auto *To = dyn_cast_or_null<InputSectionBase>(ToSym->Section); | |
| 698 | if (From && To) | |
| 699 | Config->CallGraphProfile[{From, To}] += CGPE.cgp_weight; | |
| 666 | 700 | } |
| 667 | if (!FromSym || !ToSym || Count == 0) | |
| 668 | continue; | |
| 669 | warnUnorderableSymbol(FromSym); | |
| 670 | warnUnorderableSymbol(ToSym); | |
| 671 | const Defined *FromSymD = dyn_cast<Defined>(FromSym); | |
| 672 | const Defined *ToSymD = dyn_cast<Defined>(ToSym); | |
| 673 | if (!FromSymD || !ToSymD) | |
| 674 | continue; | |
| 675 | const auto *FromSB = dyn_cast_or_null<InputSectionBase>(FromSymD->Section); | |
| 676 | const auto *ToSB = dyn_cast_or_null<InputSectionBase>(ToSymD->Section); | |
| 677 | if (!FromSB || !ToSB) | |
| 678 | continue; | |
| 679 | Config->CallGraphProfile[std::make_pair(FromSB, ToSB)] += Count; | |
| 680 | 701 | } |
| 681 | 702 | } |
| 682 | 703 | |
| ... | ... | @@ -753,7 +774,10 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 753 | 774 | Config->DynamicLinker = getDynamicLinker(Args); |
| 754 | 775 | Config->EhFrameHdr = |
| 755 | 776 | Args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false); |
| 777 | Config->EmitLLVM = Args.hasArg(OPT_plugin_opt_emit_llvm, false); | |
| 756 | 778 | Config->EmitRelocs = Args.hasArg(OPT_emit_relocs); |
| 779 | Config->CallGraphProfileSort = Args.hasFlag( | |
| 780 | OPT_call_graph_profile_sort, OPT_no_call_graph_profile_sort, true); | |
| 757 | 781 | Config->EnableNewDtags = |
| 758 | 782 | Args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true); |
| 759 | 783 | Config->Entry = Args.getLastArgValue(OPT_entry); |
| ... | ... | @@ -808,6 +832,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 808 | 832 | Config->SingleRoRx = Args.hasArg(OPT_no_rosegment); |
| 809 | 833 | Config->SoName = Args.getLastArgValue(OPT_soname); |
| 810 | 834 | Config->SortSection = getSortSection(Args); |
| 835 | Config->SplitStackAdjustSize = args::getInteger(Args, OPT_split_stack_adjust_size, 16384); | |
| 811 | 836 | Config->Strip = getStrip(Args); |
| 812 | 837 | Config->Sysroot = Args.getLastArgValue(OPT_sysroot); |
| 813 | 838 | Config->Target1Rel = Args.hasFlag(OPT_target1_rel, OPT_target1_abs, false); |
| ... | ... | @@ -837,15 +862,20 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 837 | 862 | Config->WarnBackrefs = |
| 838 | 863 | Args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false); |
| 839 | 864 | Config->WarnCommon = Args.hasFlag(OPT_warn_common, OPT_no_warn_common, false); |
| 865 | Config->WarnIfuncTextrel = | |
| 866 | Args.hasFlag(OPT_warn_ifunc_textrel, OPT_no_warn_ifunc_textrel, false); | |
| 840 | 867 | Config->WarnSymbolOrdering = |
| 841 | 868 | Args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true); |
| 842 | 869 | Config->ZCombreloc = getZFlag(Args, "combreloc", "nocombreloc", true); |
| 843 | 870 | Config->ZCopyreloc = getZFlag(Args, "copyreloc", "nocopyreloc", true); |
| 844 | 871 | Config->ZExecstack = getZFlag(Args, "execstack", "noexecstack", false); |
| 872 | Config->ZGlobal = hasZOption(Args, "global"); | |
| 845 | 873 | Config->ZHazardplt = hasZOption(Args, "hazardplt"); |
| 846 | 874 | Config->ZInitfirst = hasZOption(Args, "initfirst"); |
| 875 | Config->ZInterpose = hasZOption(Args, "interpose"); | |
| 847 | 876 | Config->ZKeepTextSectionPrefix = getZFlag( |
| 848 | 877 | Args, "keep-text-section-prefix", "nokeep-text-section-prefix", false); |
| 878 | Config->ZNodefaultlib = hasZOption(Args, "nodefaultlib"); | |
| 849 | 879 | Config->ZNodelete = hasZOption(Args, "nodelete"); |
| 850 | 880 | Config->ZNodlopen = hasZOption(Args, "nodlopen"); |
| 851 | 881 | Config->ZNow = getZFlag(Args, "now", "lazy", false); |
| ... | ... | @@ -876,6 +906,9 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 876 | 906 | if (Config->ThinLTOJobs == 0) |
| 877 | 907 | error("--thinlto-jobs: number of threads must be > 0"); |
| 878 | 908 | |
| 909 | if (Config->SplitStackAdjustSize < 0) | |
| 910 | error("--split-stack-adjust-size: size must be >= 0"); | |
| 911 | ||
| 879 | 912 | // Parse ELF{32,64}{LE,BE} and CPU type. |
| 880 | 913 | if (auto *Arg = Args.getLastArg(OPT_m)) { |
| 881 | 914 | StringRef S = Arg->getValue(); |
| ... | ... | @@ -964,22 +997,18 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { |
| 964 | 997 | // This function initialize such members. See Config.h for the details |
| 965 | 998 | // of these values. |
| 966 | 999 | static void setConfigs(opt::InputArgList &Args) { |
| 967 | ELFKind Kind = Config->EKind; | |
| 968 | uint16_t Machine = Config->EMachine; | |
| 1000 | ELFKind K = Config->EKind; | |
| 1001 | uint16_t M = Config->EMachine; | |
| 969 | 1002 | |
| 970 | 1003 | Config->CopyRelocs = (Config->Relocatable || Config->EmitRelocs); |
| 971 | Config->Is64 = (Kind == ELF64LEKind || Kind == ELF64BEKind); | |
| 972 | Config->IsLE = (Kind == ELF32LEKind || Kind == ELF64LEKind); | |
| 973 | Config->Endianness = | |
| 974 | Config->IsLE ? support::endianness::little : support::endianness::big; | |
| 975 | Config->IsMips64EL = (Kind == ELF64LEKind && Machine == EM_MIPS); | |
| 1004 | Config->Is64 = (K == ELF64LEKind || K == ELF64BEKind); | |
| 1005 | Config->IsLE = (K == ELF32LEKind || K == ELF64LEKind); | |
| 1006 | Config->Endianness = Config->IsLE ? endianness::little : endianness::big; | |
| 1007 | Config->IsMips64EL = (K == ELF64LEKind && M == EM_MIPS); | |
| 976 | 1008 | Config->Pic = Config->Pie || Config->Shared; |
| 1009 | Config->PicThunk = Args.hasArg(OPT_pic_veneer, Config->Pic); | |
| 977 | 1010 | Config->Wordsize = Config->Is64 ? 8 : 4; |
| 978 | 1011 | |
| 979 | // There is an ILP32 ABI for x86-64, although it's not very popular. | |
| 980 | // It is called the x32 ABI. | |
| 981 | bool IsX32 = (Kind == ELF32LEKind && Machine == EM_X86_64); | |
| 982 | ||
| 983 | 1012 | // ELF defines two different ways to store relocation addends as shown below: |
| 984 | 1013 | // |
| 985 | 1014 | // Rel: Addends are stored to the location where relocations are applied. |
| ... | ... | @@ -993,8 +1022,9 @@ static void setConfigs(opt::InputArgList &Args) { |
| 993 | 1022 | // You cannot choose which one, Rel or Rela, you want to use. Instead each |
| 994 | 1023 | // ABI defines which one you need to use. The following expression expresses |
| 995 | 1024 | // that. |
| 996 | Config->IsRela = | |
| 997 | (Config->Is64 || IsX32 || Machine == EM_PPC) && Machine != EM_MIPS; | |
| 1025 | Config->IsRela = M == EM_AARCH64 || M == EM_AMDGPU || M == EM_HEXAGON || | |
| 1026 | M == EM_PPC || M == EM_PPC64 || M == EM_RISCV || | |
| 1027 | M == EM_X86_64; | |
| 998 | 1028 | |
| 999 | 1029 | // If the output uses REL relocations we must store the dynamic relocation |
| 1000 | 1030 | // addends to the output sections. We also store addends for RELA relocations |
| ... | ... | @@ -1004,10 +1034,13 @@ static void setConfigs(opt::InputArgList &Args) { |
| 1004 | 1034 | Config->WriteAddends = Args.hasFlag(OPT_apply_dynamic_relocs, |
| 1005 | 1035 | OPT_no_apply_dynamic_relocs, false) || |
| 1006 | 1036 | !Config->IsRela; |
| 1037 | ||
| 1038 | Config->TocOptimize = | |
| 1039 | Args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, M == EM_PPC64); | |
| 1007 | 1040 | } |
| 1008 | 1041 | |
| 1009 | 1042 | // Returns a value of "-format" option. |
| 1010 | static bool getBinaryOption(StringRef S) { | |
| 1043 | static bool isFormatBinary(StringRef S) { | |
| 1011 | 1044 | if (S == "binary") |
| 1012 | 1045 | return true; |
| 1013 | 1046 | if (S == "elf" || S == "default") |
| ... | ... | @@ -1034,7 +1067,10 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) { |
| 1034 | 1067 | StringRef From; |
| 1035 | 1068 | StringRef To; |
| 1036 | 1069 | std::tie(From, To) = StringRef(Arg->getValue()).split('='); |
| 1037 | readDefsym(From, MemoryBufferRef(To, "-defsym")); | |
| 1070 | if (From.empty() || To.empty()) | |
| 1071 | error("-defsym: syntax error: " + StringRef(Arg->getValue())); | |
| 1072 | else | |
| 1073 | readDefsym(From, MemoryBufferRef(To, "-defsym")); | |
| 1038 | 1074 | break; |
| 1039 | 1075 | } |
| 1040 | 1076 | case OPT_script: |
| ... | ... | @@ -1049,7 +1085,7 @@ void LinkerDriver::createFiles(opt::InputArgList &Args) { |
| 1049 | 1085 | Config->AsNeeded = true; |
| 1050 | 1086 | break; |
| 1051 | 1087 | case OPT_format: |
| 1052 | InBinary = getBinaryOption(Arg->getValue()); | |
| 1088 | Config->FormatBinary = isFormatBinary(Arg->getValue()); | |
| 1053 | 1089 | break; |
| 1054 | 1090 | case OPT_no_as_needed: |
| 1055 | 1091 | Config->AsNeeded = false; |
| ... | ... | @@ -1220,33 +1256,34 @@ template <class ELFT> static void handleUndefined(StringRef Name) { |
| 1220 | 1256 | Symtab->fetchLazy<ELFT>(Sym); |
| 1221 | 1257 | } |
| 1222 | 1258 | |
| 1223 | template <class ELFT> static bool shouldDemote(Symbol &Sym) { | |
| 1224 | // If all references to a DSO happen to be weak, the DSO is not added to | |
| 1225 | // DT_NEEDED. If that happens, we need to eliminate shared symbols created | |
| 1226 | // from the DSO. Otherwise, they become dangling references that point to a | |
| 1227 | // non-existent DSO. | |
| 1228 | if (auto *S = dyn_cast<SharedSymbol>(&Sym)) | |
| 1229 | return !S->getFile<ELFT>().IsNeeded; | |
| 1230 | ||
| 1231 | // We are done processing archives, so lazy symbols that were used but not | |
| 1232 | // found can be converted to undefined. We could also just delete the other | |
| 1233 | // lazy symbols, but that seems to be more work than it is worth. | |
| 1234 | return Sym.isLazy() && Sym.IsUsedInRegularObj; | |
| 1259 | template <class ELFT> static void handleLibcall(StringRef Name) { | |
| 1260 | Symbol *Sym = Symtab->find(Name); | |
| 1261 | if (!Sym || !Sym->isLazy()) | |
| 1262 | return; | |
| 1263 | ||
| 1264 | MemoryBufferRef MB; | |
| 1265 | if (auto *LO = dyn_cast<LazyObject>(Sym)) | |
| 1266 | MB = LO->File->MB; | |
| 1267 | else | |
| 1268 | MB = cast<LazyArchive>(Sym)->getMemberBuffer(); | |
| 1269 | ||
| 1270 | if (isBitcode(MB)) | |
| 1271 | Symtab->fetchLazy<ELFT>(Sym); | |
| 1235 | 1272 | } |
| 1236 | 1273 | |
| 1237 | // Some files, such as .so or files between -{start,end}-lib may be removed | |
| 1238 | // after their symbols are added to the symbol table. If that happens, we | |
| 1239 | // need to remove symbols that refer files that no longer exist, so that | |
| 1240 | // they won't appear in the symbol table of the output file. | |
| 1241 | // | |
| 1242 | // We remove symbols by demoting them to undefined symbol. | |
| 1243 | template <class ELFT> static void demoteSymbols() { | |
| 1274 | // If all references to a DSO happen to be weak, the DSO is not added | |
| 1275 | // to DT_NEEDED. If that happens, we need to eliminate shared symbols | |
| 1276 | // created from the DSO. Otherwise, they become dangling references | |
| 1277 | // that point to a non-existent DSO. | |
| 1278 | template <class ELFT> static void demoteSharedSymbols() { | |
| 1244 | 1279 | for (Symbol *Sym : Symtab->getSymbols()) { |
| 1245 | if (shouldDemote<ELFT>(*Sym)) { | |
| 1246 | bool Used = Sym->Used; | |
| 1247 | replaceSymbol<Undefined>(Sym, nullptr, Sym->getName(), Sym->Binding, | |
| 1248 | Sym->StOther, Sym->Type); | |
| 1249 | Sym->Used = Used; | |
| 1280 | if (auto *S = dyn_cast<SharedSymbol>(Sym)) { | |
| 1281 | if (!S->getFile<ELFT>().IsNeeded) { | |
| 1282 | bool Used = S->Used; | |
| 1283 | replaceSymbol<Undefined>(S, nullptr, S->getName(), STB_WEAK, S->StOther, | |
| 1284 | S->Type); | |
| 1285 | S->Used = Used; | |
| 1286 | } | |
| 1250 | 1287 | } |
| 1251 | 1288 | } |
| 1252 | 1289 | } |
| ... | ... | @@ -1315,6 +1352,85 @@ static void findKeepUniqueSections(opt::InputArgList &Args) { |
| 1315 | 1352 | } |
| 1316 | 1353 | } |
| 1317 | 1354 | |
| 1355 | template <class ELFT> static Symbol *addUndefined(StringRef Name) { | |
| 1356 | return Symtab->addUndefined<ELFT>(Name, STB_GLOBAL, STV_DEFAULT, 0, false, | |
| 1357 | nullptr); | |
| 1358 | } | |
| 1359 | ||
| 1360 | // The --wrap option is a feature to rename symbols so that you can write | |
| 1361 | // wrappers for existing functions. If you pass `-wrap=foo`, all | |
| 1362 | // occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are | |
| 1363 | // expected to write `wrap_foo` function as a wrapper). The original | |
| 1364 | // symbol becomes accessible as `real_foo`, so you can call that from your | |
| 1365 | // wrapper. | |
| 1366 | // | |
| 1367 | // This data structure is instantiated for each -wrap option. | |
| 1368 | struct WrappedSymbol { | |
| 1369 | Symbol *Sym; | |
| 1370 | Symbol *Real; | |
| 1371 | Symbol *Wrap; | |
| 1372 | }; | |
| 1373 | ||
| 1374 | // Handles -wrap option. | |
| 1375 | // | |
| 1376 | // This function instantiates wrapper symbols. At this point, they seem | |
| 1377 | // like they are not being used at all, so we explicitly set some flags so | |
| 1378 | // that LTO won't eliminate them. | |
| 1379 | template <class ELFT> | |
| 1380 | static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &Args) { | |
| 1381 | std::vector<WrappedSymbol> V; | |
| 1382 | DenseSet<StringRef> Seen; | |
| 1383 | ||
| 1384 | for (auto *Arg : Args.filtered(OPT_wrap)) { | |
| 1385 | StringRef Name = Arg->getValue(); | |
| 1386 | if (!Seen.insert(Name).second) | |
| 1387 | continue; | |
| 1388 | ||
| 1389 | Symbol *Sym = Symtab->find(Name); | |
| 1390 | if (!Sym) | |
| 1391 | continue; | |
| 1392 | ||
| 1393 | Symbol *Real = addUndefined<ELFT>(Saver.save("__real_" + Name)); | |
| 1394 | Symbol *Wrap = addUndefined<ELFT>(Saver.save("__wrap_" + Name)); | |
| 1395 | V.push_back({Sym, Real, Wrap}); | |
| 1396 | ||
| 1397 | // We want to tell LTO not to inline symbols to be overwritten | |
| 1398 | // because LTO doesn't know the final symbol contents after renaming. | |
| 1399 | Real->CanInline = false; | |
| 1400 | Sym->CanInline = false; | |
| 1401 | ||
| 1402 | // Tell LTO not to eliminate these symbols. | |
| 1403 | Sym->IsUsedInRegularObj = true; | |
| 1404 | Wrap->IsUsedInRegularObj = true; | |
| 1405 | } | |
| 1406 | return V; | |
| 1407 | } | |
| 1408 | ||
| 1409 | // Do renaming for -wrap by updating pointers to symbols. | |
| 1410 | // | |
| 1411 | // When this function is executed, only InputFiles and symbol table | |
| 1412 | // contain pointers to symbol objects. We visit them to replace pointers, | |
| 1413 | // so that wrapped symbols are swapped as instructed by the command line. | |
| 1414 | template <class ELFT> static void wrapSymbols(ArrayRef<WrappedSymbol> Wrapped) { | |
| 1415 | DenseMap<Symbol *, Symbol *> Map; | |
| 1416 | for (const WrappedSymbol &W : Wrapped) { | |
| 1417 | Map[W.Sym] = W.Wrap; | |
| 1418 | Map[W.Real] = W.Sym; | |
| 1419 | } | |
| 1420 | ||
| 1421 | // Update pointers in input files. | |
| 1422 | parallelForEach(ObjectFiles, [&](InputFile *File) { | |
| 1423 | std::vector<Symbol *> &Syms = File->getMutableSymbols(); | |
| 1424 | for (size_t I = 0, E = Syms.size(); I != E; ++I) | |
| 1425 | if (Symbol *S = Map.lookup(Syms[I])) | |
| 1426 | Syms[I] = S; | |
| 1427 | }); | |
| 1428 | ||
| 1429 | // Update pointers in the symbol table. | |
| 1430 | for (const WrappedSymbol &W : Wrapped) | |
| 1431 | Symtab->wrap(W.Sym, W.Real, W.Wrap); | |
| 1432 | } | |
| 1433 | ||
| 1318 | 1434 | static const char *LibcallRoutineNames[] = { |
| 1319 | 1435 | #define HANDLE_LIBCALL(code, name) name, |
| 1320 | 1436 | #include "llvm/IR/RuntimeLibcalls.def" |
| ... | ... | @@ -1325,6 +1441,8 @@ static const char *LibcallRoutineNames[] = { |
| 1325 | 1441 | // all linker scripts have already been parsed. |
| 1326 | 1442 | template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 1327 | 1443 | Target = getTarget(); |
| 1444 | InX<ELFT>::VerSym = nullptr; | |
| 1445 | InX<ELFT>::VerNeed = nullptr; | |
| 1328 | 1446 | |
| 1329 | 1447 | Config->MaxPageSize = getMaxPageSize(Args); |
| 1330 | 1448 | Config->ImageBase = getImageBase(Args); |
| ... | ... | @@ -1380,8 +1498,8 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 1380 | 1498 | |
| 1381 | 1499 | // Some symbols (such as __ehdr_start) are defined lazily only when there |
| 1382 | 1500 | // are undefined symbols for them, so we add these to trigger that logic. |
| 1383 | for (StringRef Sym : Script->ReferencedSymbols) | |
| 1384 | Symtab->addUndefined<ELFT>(Sym); | |
| 1501 | for (StringRef Name : Script->ReferencedSymbols) | |
| 1502 | addUndefined<ELFT>(Name); | |
| 1385 | 1503 | |
| 1386 | 1504 | // Handle the `--undefined <sym>` options. |
| 1387 | 1505 | for (StringRef S : Config->Undefined) |
| ... | ... | @@ -1396,11 +1514,20 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 1396 | 1514 | // in a bitcode file in an archive member, we need to arrange to use LTO to |
| 1397 | 1515 | // compile those archive members by adding them to the link beforehand. |
| 1398 | 1516 | // |
| 1399 | // With this the symbol table should be complete. After this, no new names | |
| 1400 | // except a few linker-synthesized ones will be added to the symbol table. | |
| 1517 | // However, adding all libcall symbols to the link can have undesired | |
| 1518 | // consequences. For example, the libgcc implementation of | |
| 1519 | // __sync_val_compare_and_swap_8 on 32-bit ARM pulls in an .init_array entry | |
| 1520 | // that aborts the program if the Linux kernel does not support 64-bit | |
| 1521 | // atomics, which would prevent the program from running even if it does not | |
| 1522 | // use 64-bit atomics. | |
| 1523 | // | |
| 1524 | // Therefore, we only add libcall symbols to the link before LTO if we have | |
| 1525 | // to, i.e. if the symbol's definition is in bitcode. Any other required | |
| 1526 | // libcall symbols will be added to the link after LTO when we add the LTO | |
| 1527 | // object file to the link. | |
| 1401 | 1528 | if (!BitcodeFiles.empty()) |
| 1402 | 1529 | for (const char *S : LibcallRoutineNames) |
| 1403 | handleUndefined<ELFT>(S); | |
| 1530 | handleLibcall<ELFT>(S); | |
| 1404 | 1531 | |
| 1405 | 1532 | // Return if there were name resolution errors. |
| 1406 | 1533 | if (errorCount()) |
| ... | ... | @@ -1424,6 +1551,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 1424 | 1551 | Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC); |
| 1425 | 1552 | Out::ElfHeader->Size = sizeof(typename ELFT::Ehdr); |
| 1426 | 1553 | |
| 1554 | // Create wrapped symbols for -wrap option. | |
| 1555 | std::vector<WrappedSymbol> Wrapped = addWrappedSymbols<ELFT>(Args); | |
| 1556 | ||
| 1427 | 1557 | // We need to create some reserved symbols such as _end. Create them. |
| 1428 | 1558 | if (!Config->Relocatable) |
| 1429 | 1559 | addReservedSymbols(); |
| ... | ... | @@ -1436,12 +1566,11 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 1436 | 1566 | if (!Config->Relocatable) |
| 1437 | 1567 | Symtab->scanVersionScript(); |
| 1438 | 1568 | |
| 1439 | // Create wrapped symbols for -wrap option. | |
| 1440 | for (auto *Arg : Args.filtered(OPT_wrap)) | |
| 1441 | Symtab->addSymbolWrap<ELFT>(Arg->getValue()); | |
| 1442 | ||
| 1443 | 1569 | // Do link-time optimization if given files are LLVM bitcode files. |
| 1444 | 1570 | // This compiles bitcode files into real object files. |
| 1571 | // | |
| 1572 | // With this the symbol table should be complete. After this, no new names | |
| 1573 | // except a few linker-synthesized ones will be added to the symbol table. | |
| 1445 | 1574 | Symtab->addCombinedLTOObject<ELFT>(); |
| 1446 | 1575 | if (errorCount()) |
| 1447 | 1576 | return; |
| ... | ... | @@ -1452,8 +1581,15 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 1452 | 1581 | if (Config->ThinLTOIndexOnly) |
| 1453 | 1582 | return; |
| 1454 | 1583 | |
| 1584 | // Likewise, --plugin-opt=emit-llvm is an option to make LTO create | |
| 1585 | // an output file in bitcode and exit, so that you can just get a | |
| 1586 | // combined bitcode file. | |
| 1587 | if (Config->EmitLLVM) | |
| 1588 | return; | |
| 1589 | ||
| 1455 | 1590 | // Apply symbol renames for -wrap. |
| 1456 | Symtab->applySymbolWrap(); | |
| 1591 | if (!Wrapped.empty()) | |
| 1592 | wrapSymbols<ELFT>(Wrapped); | |
| 1457 | 1593 | |
| 1458 | 1594 | // Now that we have a complete list of input files. |
| 1459 | 1595 | // Beyond this point, no new files are added. |
| ... | ... | @@ -1481,27 +1617,19 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 1481 | 1617 | // supports them. |
| 1482 | 1618 | if (Config->ARMHasBlx == false) |
| 1483 | 1619 | warn("lld uses blx instruction, no object with architecture supporting " |
| 1484 | "feature detected."); | |
| 1485 | if (Config->ARMJ1J2BranchEncoding == false) | |
| 1486 | warn("lld uses extended branch encoding, no object with architecture " | |
| 1487 | "supporting feature detected."); | |
| 1488 | if (Config->ARMHasMovtMovw == false) | |
| 1489 | warn("lld may use movt/movw, no object with architecture supporting " | |
| 1490 | "feature detected."); | |
| 1620 | "feature detected"); | |
| 1491 | 1621 | } |
| 1492 | 1622 | |
| 1493 | 1623 | // This adds a .comment section containing a version string. We have to add it |
| 1494 | // before decompressAndMergeSections because the .comment section is a | |
| 1495 | // mergeable section. | |
| 1624 | // before mergeSections because the .comment section is a mergeable section. | |
| 1496 | 1625 | if (!Config->Relocatable) |
| 1497 | 1626 | InputSections.push_back(createCommentSection()); |
| 1498 | 1627 | |
| 1499 | 1628 | // Do size optimizations: garbage collection, merging of SHF_MERGE sections |
| 1500 | 1629 | // and identical code folding. |
| 1501 | decompressSections(); | |
| 1502 | 1630 | splitSections<ELFT>(); |
| 1503 | 1631 | markLive<ELFT>(); |
| 1504 | demoteSymbols<ELFT>(); | |
| 1632 | demoteSharedSymbols<ELFT>(); | |
| 1505 | 1633 | mergeSections(); |
| 1506 | 1634 | if (Config->ICF != ICFLevel::None) { |
| 1507 | 1635 | findKeepUniqueSections<ELFT>(Args); |
| ... | ... | @@ -1509,9 +1637,12 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) { |
| 1509 | 1637 | } |
| 1510 | 1638 | |
| 1511 | 1639 | // Read the callgraph now that we know what was gced or icfed |
| 1512 | if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file)) | |
| 1513 | if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) | |
| 1514 | readCallGraph(*Buffer); | |
| 1640 | if (Config->CallGraphProfileSort) { | |
| 1641 | if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file)) | |
| 1642 | if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue())) | |
| 1643 | readCallGraph(*Buffer); | |
| 1644 | readCallGraphsFromObjectFiles<ELFT>(); | |
| 1645 | } | |
| 1515 | 1646 | |
| 1516 | 1647 | // Write the result to the file. |
| 1517 | 1648 | writeResult<ELFT>(); |
deps/lld/ELF/Driver.h-3| ... | ... | @@ -42,9 +42,6 @@ private: |
| 42 | 42 | // True if we are in --start-lib and --end-lib. |
| 43 | 43 | bool InLib = false; |
| 44 | 44 | |
| 45 | // True if we are in -format=binary and -format=elf. | |
| 46 | bool InBinary = false; | |
| 47 | ||
| 48 | 45 | std::vector<InputFile *> Files; |
| 49 | 46 | }; |
| 50 | 47 |
deps/lld/ELF/DriverUtils.cpp+3-2| ... | ... | @@ -139,8 +139,9 @@ opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) { |
| 139 | 139 | } |
| 140 | 140 | |
| 141 | 141 | void elf::printHelp() { |
| 142 | ELFOptTable().PrintHelp(outs(), Config->ProgName.data(), "lld", | |
| 143 | false /*ShowHidden*/, true /*ShowAllAliases*/); | |
| 142 | ELFOptTable().PrintHelp( | |
| 143 | outs(), (Config->ProgName + " [options] file...").str().c_str(), "lld", | |
| 144 | false /*ShowHidden*/, true /*ShowAllAliases*/); | |
| 144 | 145 | outs() << "\n"; |
| 145 | 146 | |
| 146 | 147 | // Scripts generated by Libtool versions up to at least 2.4.6 (the most |
deps/lld/ELF/EhFrame.cpp+2-2| ... | ... | @@ -44,7 +44,7 @@ public: |
| 44 | 44 | private: |
| 45 | 45 | template <class P> void failOn(const P *Loc, const Twine &Msg) { |
| 46 | 46 | fatal("corrupted .eh_frame: " + Msg + "\n>>> defined in " + |
| 47 | IS->getObjMsg((const uint8_t *)Loc - IS->Data.data())); | |
| 47 | IS->getObjMsg((const uint8_t *)Loc - IS->data().data())); | |
| 48 | 48 | } |
| 49 | 49 | |
| 50 | 50 | uint8_t readByte(); |
| ... | ... | @@ -59,7 +59,7 @@ private: |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | 61 | size_t elf::readEhRecordSize(InputSectionBase *S, size_t Off) { |
| 62 | return EhReader(S, S->Data.slice(Off)).readEhRecordSize(); | |
| 62 | return EhReader(S, S->data().slice(Off)).readEhRecordSize(); | |
| 63 | 63 | } |
| 64 | 64 | |
| 65 | 65 | // .eh_frame section is a sequence of records. Each record starts with |
deps/lld/ELF/GdbIndex.cpp deleted-101| ... | ... | @@ -1,101 +0,0 @@ |
| 1 | //===- GdbIndex.cpp -------------------------------------------------------===// | |
| 2 | // | |
| 3 | // The LLVM Linker | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | // | |
| 10 | // The -gdb-index option instructs the linker to emit a .gdb_index section. | |
| 11 | // The section contains information to make gdb startup faster. | |
| 12 | // The format of the section is described at | |
| 13 | // https://sourceware.org/gdb/onlinedocs/gdb/Index-Section-Format.html. | |
| 14 | // | |
| 15 | //===----------------------------------------------------------------------===// | |
| 16 | ||
| 17 | #include "GdbIndex.h" | |
| 18 | #include "Symbols.h" | |
| 19 | #include "lld/Common/Memory.h" | |
| 20 | #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" | |
| 21 | #include "llvm/Object/ELFObjectFile.h" | |
| 22 | ||
| 23 | using namespace llvm; | |
| 24 | using namespace llvm::object; | |
| 25 | using namespace lld; | |
| 26 | using namespace lld::elf; | |
| 27 | ||
| 28 | template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *Obj) { | |
| 29 | for (InputSectionBase *Sec : Obj->getSections()) { | |
| 30 | if (!Sec) | |
| 31 | continue; | |
| 32 | if (LLDDWARFSection *M = StringSwitch<LLDDWARFSection *>(Sec->Name) | |
| 33 | .Case(".debug_info", &InfoSection) | |
| 34 | .Case(".debug_ranges", &RangeSection) | |
| 35 | .Case(".debug_line", &LineSection) | |
| 36 | .Default(nullptr)) { | |
| 37 | Sec->maybeDecompress(); | |
| 38 | M->Data = toStringRef(Sec->Data); | |
| 39 | M->Sec = Sec; | |
| 40 | continue; | |
| 41 | } | |
| 42 | if (Sec->Name == ".debug_abbrev") | |
| 43 | AbbrevSection = toStringRef(Sec->Data); | |
| 44 | else if (Sec->Name == ".debug_gnu_pubnames") | |
| 45 | GnuPubNamesSection = toStringRef(Sec->Data); | |
| 46 | else if (Sec->Name == ".debug_gnu_pubtypes") | |
| 47 | GnuPubTypesSection = toStringRef(Sec->Data); | |
| 48 | else if (Sec->Name == ".debug_str") | |
| 49 | StrSection = toStringRef(Sec->Data); | |
| 50 | } | |
| 51 | } | |
| 52 | ||
| 53 | // Find if there is a relocation at Pos in Sec. The code is a bit | |
| 54 | // more complicated than usual because we need to pass a section index | |
| 55 | // to llvm since it has no idea about InputSection. | |
| 56 | template <class ELFT> | |
| 57 | template <class RelTy> | |
| 58 | Optional<RelocAddrEntry> | |
| 59 | LLDDwarfObj<ELFT>::findAux(const InputSectionBase &Sec, uint64_t Pos, | |
| 60 | ArrayRef<RelTy> Rels) const { | |
| 61 | auto It = std::lower_bound( | |
| 62 | Rels.begin(), Rels.end(), Pos, | |
| 63 | [](const RelTy &A, uint64_t B) { return A.r_offset < B; }); | |
| 64 | if (It == Rels.end() || It->r_offset != Pos) | |
| 65 | return None; | |
| 66 | const RelTy &Rel = *It; | |
| 67 | ||
| 68 | const ObjFile<ELFT> *File = Sec.getFile<ELFT>(); | |
| 69 | uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); | |
| 70 | const typename ELFT::Sym &Sym = File->getELFSyms()[SymIndex]; | |
| 71 | uint32_t SecIndex = File->getSectionIndex(Sym); | |
| 72 | ||
| 73 | // Broken debug info can point to a non-Defined symbol. | |
| 74 | auto *DR = dyn_cast<Defined>(&File->getRelocTargetSym(Rel)); | |
| 75 | if (!DR) { | |
| 76 | error("unsupported relocation target while parsing debug info"); | |
| 77 | return None; | |
| 78 | } | |
| 79 | uint64_t Val = DR->Value + getAddend<ELFT>(Rel); | |
| 80 | ||
| 81 | // FIXME: We should be consistent about always adding the file | |
| 82 | // offset or not. | |
| 83 | if (DR->Section->Flags & ELF::SHF_ALLOC) | |
| 84 | Val += cast<InputSection>(DR->Section)->getOffsetInFile(); | |
| 85 | ||
| 86 | return RelocAddrEntry{SecIndex, Val}; | |
| 87 | } | |
| 88 | ||
| 89 | template <class ELFT> | |
| 90 | Optional<RelocAddrEntry> LLDDwarfObj<ELFT>::find(const llvm::DWARFSection &S, | |
| 91 | uint64_t Pos) const { | |
| 92 | auto &Sec = static_cast<const LLDDWARFSection &>(S); | |
| 93 | if (Sec.Sec->AreRelocsRela) | |
| 94 | return findAux(*Sec.Sec, Pos, Sec.Sec->template relas<ELFT>()); | |
| 95 | return findAux(*Sec.Sec, Pos, Sec.Sec->template rels<ELFT>()); | |
| 96 | } | |
| 97 | ||
| 98 | template class elf::LLDDwarfObj<ELF32LE>; | |
| 99 | template class elf::LLDDwarfObj<ELF32BE>; | |
| 100 | template class elf::LLDDwarfObj<ELF64LE>; | |
| 101 | template class elf::LLDDwarfObj<ELF64BE>; |
deps/lld/ELF/GdbIndex.h deleted-70| ... | ... | @@ -1,70 +0,0 @@ |
| 1 | //===- GdbIndex.h --------------------------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // The LLVM Linker | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===-------------------------------------------------------------------===// | |
| 9 | ||
| 10 | #ifndef LLD_ELF_GDB_INDEX_H | |
| 11 | #define LLD_ELF_GDB_INDEX_H | |
| 12 | ||
| 13 | #include "InputFiles.h" | |
| 14 | #include "llvm/DebugInfo/DWARF/DWARFContext.h" | |
| 15 | #include "llvm/Object/ELF.h" | |
| 16 | ||
| 17 | namespace lld { | |
| 18 | namespace elf { | |
| 19 | ||
| 20 | class InputSection; | |
| 21 | ||
| 22 | struct LLDDWARFSection final : public llvm::DWARFSection { | |
| 23 | InputSectionBase *Sec = nullptr; | |
| 24 | }; | |
| 25 | ||
| 26 | template <class ELFT> class LLDDwarfObj final : public llvm::DWARFObject { | |
| 27 | LLDDWARFSection InfoSection; | |
| 28 | LLDDWARFSection RangeSection; | |
| 29 | LLDDWARFSection LineSection; | |
| 30 | StringRef AbbrevSection; | |
| 31 | StringRef GnuPubNamesSection; | |
| 32 | StringRef GnuPubTypesSection; | |
| 33 | StringRef StrSection; | |
| 34 | ||
| 35 | template <class RelTy> | |
| 36 | llvm::Optional<llvm::RelocAddrEntry> findAux(const InputSectionBase &Sec, | |
| 37 | uint64_t Pos, | |
| 38 | ArrayRef<RelTy> Rels) const; | |
| 39 | ||
| 40 | public: | |
| 41 | explicit LLDDwarfObj(ObjFile<ELFT> *Obj); | |
| 42 | const llvm::DWARFSection &getInfoSection() const override { | |
| 43 | return InfoSection; | |
| 44 | } | |
| 45 | const llvm::DWARFSection &getRangeSection() const override { | |
| 46 | return RangeSection; | |
| 47 | } | |
| 48 | const llvm::DWARFSection &getLineSection() const override { | |
| 49 | return LineSection; | |
| 50 | } | |
| 51 | StringRef getFileName() const override { return ""; } | |
| 52 | StringRef getAbbrevSection() const override { return AbbrevSection; } | |
| 53 | StringRef getStringSection() const override { return StrSection; } | |
| 54 | StringRef getGnuPubNamesSection() const override { | |
| 55 | return GnuPubNamesSection; | |
| 56 | } | |
| 57 | StringRef getGnuPubTypesSection() const override { | |
| 58 | return GnuPubTypesSection; | |
| 59 | } | |
| 60 | bool isLittleEndian() const override { | |
| 61 | return ELFT::TargetEndianness == llvm::support::little; | |
| 62 | } | |
| 63 | llvm::Optional<llvm::RelocAddrEntry> find(const llvm::DWARFSection &Sec, | |
| 64 | uint64_t Pos) const override; | |
| 65 | }; | |
| 66 | ||
| 67 | } // namespace elf | |
| 68 | } // namespace lld | |
| 69 | ||
| 70 | #endif |
deps/lld/ELF/ICF.cpp+31-4| ... | ... | @@ -252,7 +252,10 @@ bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA, |
| 252 | 252 | |
| 253 | 253 | auto *DA = dyn_cast<Defined>(&SA); |
| 254 | 254 | auto *DB = dyn_cast<Defined>(&SB); |
| 255 | if (!DA || !DB) | |
| 255 | ||
| 256 | // Placeholder symbols generated by linker scripts look the same now but | |
| 257 | // may have different values later. | |
| 258 | if (!DA || !DB || DA->ScriptDefined || DB->ScriptDefined) | |
| 256 | 259 | return false; |
| 257 | 260 | |
| 258 | 261 | // Relocations referring to absolute symbols are constant-equal if their |
| ... | ... | @@ -298,7 +301,7 @@ bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA, |
| 298 | 301 | template <class ELFT> |
| 299 | 302 | bool ICF<ELFT>::equalsConstant(const InputSection *A, const InputSection *B) { |
| 300 | 303 | if (A->NumRelocations != B->NumRelocations || A->Flags != B->Flags || |
| 301 | A->getSize() != B->getSize() || A->Data != B->Data) | |
| 304 | A->getSize() != B->getSize() || A->data() != B->data()) | |
| 302 | 305 | return false; |
| 303 | 306 | |
| 304 | 307 | // If two sections have different output sections, we cannot merge them. |
| ... | ... | @@ -420,6 +423,22 @@ void ICF<ELFT>::forEachClass(llvm::function_ref<void(size_t, size_t)> Fn) { |
| 420 | 423 | ++Cnt; |
| 421 | 424 | } |
| 422 | 425 | |
| 426 | // Combine the hashes of the sections referenced by the given section into its | |
| 427 | // hash. | |
| 428 | template <class ELFT, class RelTy> | |
| 429 | static void combineRelocHashes(unsigned Cnt, InputSection *IS, | |
| 430 | ArrayRef<RelTy> Rels) { | |
| 431 | uint32_t Hash = IS->Class[Cnt % 2]; | |
| 432 | for (RelTy Rel : Rels) { | |
| 433 | Symbol &S = IS->template getFile<ELFT>()->getRelocTargetSym(Rel); | |
| 434 | if (auto *D = dyn_cast<Defined>(&S)) | |
| 435 | if (auto *RelSec = dyn_cast_or_null<InputSection>(D->Section)) | |
| 436 | Hash += RelSec->Class[Cnt % 2]; | |
| 437 | } | |
| 438 | // Set MSB to 1 to avoid collisions with non-hash IDs. | |
| 439 | IS->Class[(Cnt + 1) % 2] = Hash | (1U << 31); | |
| 440 | } | |
| 441 | ||
| 423 | 442 | static void print(const Twine &S) { |
| 424 | 443 | if (Config->PrintIcfSections) |
| 425 | 444 | message(S); |
| ... | ... | @@ -435,10 +454,18 @@ template <class ELFT> void ICF<ELFT>::run() { |
| 435 | 454 | |
| 436 | 455 | // Initially, we use hash values to partition sections. |
| 437 | 456 | parallelForEach(Sections, [&](InputSection *S) { |
| 438 | // Set MSB to 1 to avoid collisions with non-hash IDs. | |
| 439 | S->Class[0] = xxHash64(S->Data) | (1U << 31); | |
| 457 | S->Class[0] = xxHash64(S->data()); | |
| 440 | 458 | }); |
| 441 | 459 | |
| 460 | for (unsigned Cnt = 0; Cnt != 2; ++Cnt) { | |
| 461 | parallelForEach(Sections, [&](InputSection *S) { | |
| 462 | if (S->AreRelocsRela) | |
| 463 | combineRelocHashes<ELFT>(Cnt, S, S->template relas<ELFT>()); | |
| 464 | else | |
| 465 | combineRelocHashes<ELFT>(Cnt, S, S->template rels<ELFT>()); | |
| 466 | }); | |
| 467 | } | |
| 468 | ||
| 442 | 469 | // From now on, sections in Sections vector are ordered so that sections |
| 443 | 470 | // in the same equivalence class are consecutive in the vector. |
| 444 | 471 | std::stable_sort(Sections.begin(), Sections.end(), |
deps/lld/ELF/InputFiles.cpp+74-73| ... | ... | @@ -46,7 +46,7 @@ std::vector<LazyObjFile *> elf::LazyObjFiles; |
| 46 | 46 | std::vector<InputFile *> elf::ObjectFiles; |
| 47 | 47 | std::vector<InputFile *> elf::SharedFiles; |
| 48 | 48 | |
| 49 | TarWriter *elf::Tar; | |
| 49 | std::unique_ptr<TarWriter> elf::Tar; | |
| 50 | 50 | |
| 51 | 51 | InputFile::InputFile(Kind K, MemoryBufferRef M) |
| 52 | 52 | : MB(M), GroupId(NextGroupId), FileKind(K) { |
| ... | ... | @@ -125,11 +125,7 @@ std::string InputFile::getSrcMsg(const Symbol &Sym, InputSectionBase &Sec, |
| 125 | 125 | |
| 126 | 126 | template <class ELFT> void ObjFile<ELFT>::initializeDwarf() { |
| 127 | 127 | Dwarf = llvm::make_unique<DWARFContext>(make_unique<LLDDwarfObj<ELFT>>(this)); |
| 128 | const DWARFObject &Obj = Dwarf->getDWARFObj(); | |
| 129 | DWARFDataExtractor LineData(Obj, Obj.getLineSection(), Config->IsLE, | |
| 130 | Config->Wordsize); | |
| 131 | ||
| 132 | for (std::unique_ptr<DWARFCompileUnit> &CU : Dwarf->compile_units()) { | |
| 128 | for (std::unique_ptr<DWARFUnit> &CU : Dwarf->compile_units()) { | |
| 133 | 129 | auto Report = [](Error Err) { |
| 134 | 130 | handleAllErrors(std::move(Err), |
| 135 | 131 | [](ErrorInfoBase &Info) { warn(Info.message()); }); |
| ... | ... | @@ -324,17 +320,6 @@ StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections, |
| 324 | 320 | return Signature; |
| 325 | 321 | } |
| 326 | 322 | |
| 327 | template <class ELFT> | |
| 328 | ArrayRef<typename ObjFile<ELFT>::Elf_Word> | |
| 329 | ObjFile<ELFT>::getShtGroupEntries(const Elf_Shdr &Sec) { | |
| 330 | const ELFFile<ELFT> &Obj = this->getObj(); | |
| 331 | ArrayRef<Elf_Word> Entries = | |
| 332 | CHECK(Obj.template getSectionContentsAsArray<Elf_Word>(&Sec), this); | |
| 333 | if (Entries.empty() || Entries[0] != GRP_COMDAT) | |
| 334 | fatal(toString(this) + ": unsupported SHT_GROUP format"); | |
| 335 | return Entries.slice(1); | |
| 336 | } | |
| 337 | ||
| 338 | 323 | template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) { |
| 339 | 324 | // On a regular link we don't merge sections if -O0 (default is -O1). This |
| 340 | 325 | // sometimes makes the linker significantly faster, although the output will |
| ... | ... | @@ -416,6 +401,11 @@ void ObjFile<ELFT>::initializeSections( |
| 416 | 401 | continue; |
| 417 | 402 | const Elf_Shdr &Sec = ObjSections[I]; |
| 418 | 403 | |
| 404 | if (Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE) | |
| 405 | CGProfile = check( | |
| 406 | this->getObj().template getSectionContentsAsArray<Elf_CGProfile>( | |
| 407 | &Sec)); | |
| 408 | ||
| 419 | 409 | // SHF_EXCLUDE'ed sections are discarded by the linker. However, |
| 420 | 410 | // if -r is given, we'll let the final link discard such sections. |
| 421 | 411 | // This is compatible with GNU. |
| ... | ... | @@ -439,22 +429,34 @@ void ObjFile<ELFT>::initializeSections( |
| 439 | 429 | case SHT_GROUP: { |
| 440 | 430 | // De-duplicate section groups by their signatures. |
| 441 | 431 | StringRef Signature = getShtGroupSignature(ObjSections, Sec); |
| 442 | bool IsNew = ComdatGroups.insert(CachedHashStringRef(Signature)).second; | |
| 443 | 432 | this->Sections[I] = &InputSection::Discarded; |
| 444 | 433 | |
| 445 | // If it is a new section group, we want to keep group members. | |
| 446 | // Group leader sections, which contain indices of group members, are | |
| 447 | // discarded because they are useless beyond this point. The only | |
| 448 | // exception is the -r option because in order to produce re-linkable | |
| 449 | // object files, we want to pass through basically everything. | |
| 434 | ||
| 435 | ArrayRef<Elf_Word> Entries = | |
| 436 | CHECK(Obj.template getSectionContentsAsArray<Elf_Word>(&Sec), this); | |
| 437 | if (Entries.empty()) | |
| 438 | fatal(toString(this) + ": empty SHT_GROUP"); | |
| 439 | ||
| 440 | // The first word of a SHT_GROUP section contains flags. Currently, | |
| 441 | // the standard defines only "GRP_COMDAT" flag for the COMDAT group. | |
| 442 | // An group with the empty flag doesn't define anything; such sections | |
| 443 | // are just skipped. | |
| 444 | if (Entries[0] == 0) | |
| 445 | continue; | |
| 446 | ||
| 447 | if (Entries[0] != GRP_COMDAT) | |
| 448 | fatal(toString(this) + ": unsupported SHT_GROUP format"); | |
| 449 | ||
| 450 | bool IsNew = ComdatGroups.insert(CachedHashStringRef(Signature)).second; | |
| 450 | 451 | if (IsNew) { |
| 451 | 452 | if (Config->Relocatable) |
| 452 | 453 | this->Sections[I] = createInputSection(Sec); |
| 453 | continue; | |
| 454 | 	continue; | |
| 454 | 455 | } |
| 455 | 456 | |
| 457 | ||
| 456 | 458 | // Otherwise, discard group members. |
| 457 | for (uint32_t SecIndex : getShtGroupEntries(Sec)) { | |
| 459 | for (uint32_t SecIndex : Entries.slice(1)) { | |
| 458 | 460 | if (SecIndex >= Size) |
| 459 | 461 | fatal(toString(this) + |
| 460 | 462 | ": invalid section index in group: " + Twine(SecIndex)); |
| ... | ... | @@ -478,11 +480,13 @@ void ObjFile<ELFT>::initializeSections( |
| 478 | 480 | // .ARM.exidx sections have a reverse dependency on the InputSection they |
| 479 | 481 | // have a SHF_LINK_ORDER dependency, this is identified by the sh_link. |
| 480 | 482 | if (Sec.sh_flags & SHF_LINK_ORDER) { |
| 481 | if (Sec.sh_link >= this->Sections.size()) | |
| 483 | InputSectionBase *LinkSec = nullptr; | |
| 484 | if (Sec.sh_link < this->Sections.size()) | |
| 485 | LinkSec = this->Sections[Sec.sh_link]; | |
| 486 | if (!LinkSec) | |
| 482 | 487 | fatal(toString(this) + |
| 483 | 488 | ": invalid sh_link index: " + Twine(Sec.sh_link)); |
| 484 | 489 | |
| 485 | InputSectionBase *LinkSec = this->Sections[Sec.sh_link]; | |
| 486 | 490 | InputSection *IS = cast<InputSection>(this->Sections[I]); |
| 487 | 491 | LinkSec->DependentSections.push_back(IS); |
| 488 | 492 | if (!isa<InputSection>(LinkSec)) |
| ... | ... | @@ -598,7 +602,7 @@ InputSectionBase *ObjFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) { |
| 598 | 602 | // as a given section. |
| 599 | 603 | static InputSection *toRegularSection(MergeInputSection *Sec) { |
| 600 | 604 | return make<InputSection>(Sec->File, Sec->Flags, Sec->Type, Sec->Alignment, |
| 601 | Sec->Data, Sec->Name); | |
| 605 | Sec->data(), Sec->Name); | |
| 602 | 606 | } |
| 603 | 607 | |
| 604 | 608 | template <class ELFT> |
| ... | ... | @@ -618,9 +622,9 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 618 | 622 | // FIXME: Retain the first attribute section we see. The eglibc ARM |
| 619 | 623 | // dynamic loaders require the presence of an attribute section for dlopen |
| 620 | 624 | // to work. In a full implementation we would merge all attribute sections. |
| 621 | if (InX::ARMAttributes == nullptr) { | |
| 622 | InX::ARMAttributes = make<InputSection>(*this, Sec, Name); | |
| 623 | return InX::ARMAttributes; | |
| 625 | if (In.ARMAttributes == nullptr) { | |
| 626 | In.ARMAttributes = make<InputSection>(*this, Sec, Name); | |
| 627 | return In.ARMAttributes; | |
| 624 | 628 | } |
| 625 | 629 | return &InputSection::Discarded; |
| 626 | 630 | } |
| ... | ... | @@ -638,8 +642,16 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 638 | 642 | // This section contains relocation information. |
| 639 | 643 | // If -r is given, we do not interpret or apply relocation |
| 640 | 644 | // but just copy relocation sections to output. |
| 641 | if (Config->Relocatable) | |
| 642 | return make<InputSection>(*this, Sec, Name); | |
| 645 | if (Config->Relocatable) { | |
| 646 | InputSection *RelocSec = make<InputSection>(*this, Sec, Name); | |
| 647 | // We want to add a dependency to target, similar like we do for | |
| 648 | // -emit-relocs below. This is useful for the case when linker script | |
| 649 | // contains the "/DISCARD/". It is perhaps uncommon to use a script with | |
| 650 | // -r, but we faced it in the Linux kernel and have to handle such case | |
| 651 | // and not to crash. | |
| 652 | Target->DependentSections.push_back(RelocSec); | |
| 653 | return RelocSec; | |
| 654 | } | |
| 643 | 655 | |
| 644 | 656 | if (Target->FirstRelocation) |
| 645 | 657 | fatal(toString(this) + |
| ... | ... | @@ -704,7 +716,7 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 704 | 716 | // for split stack will include a .note.GNU-split-stack section. |
| 705 | 717 | if (Name == ".note.GNU-split-stack") { |
| 706 | 718 | if (Config->Relocatable) { |
| 707 | error("Cannot mix split-stack and non-split-stack in a relocatable link"); | |
| 719 | error("cannot mix split-stack and non-split-stack in a relocatable link"); | |
| 708 | 720 | return &InputSection::Discarded; |
| 709 | 721 | } |
| 710 | 722 | this->SplitStack = true; |
| ... | ... | @@ -724,7 +736,8 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) { |
| 724 | 736 | // sections. Drop those sections to avoid duplicate symbol errors. |
| 725 | 737 | // FIXME: This is glibc PR20543, we should remove this hack once that has been |
| 726 | 738 | // fixed for a while. |
| 727 | if (Name.startswith(".gnu.linkonce.")) | |
| 739 | if (Name == ".gnu.linkonce.t.__x86.get_pc_thunk.bx" || | |
| 740 | Name == ".gnu.linkonce.t.__i686.get_pc_thunk.bx") | |
| 728 | 741 | return &InputSection::Discarded; |
| 729 | 742 | |
| 730 | 743 | // If we are creating a new .build-id section, strip existing .build-id |
| ... | ... | @@ -806,7 +819,7 @@ template <class ELFT> Symbol *ObjFile<ELFT>::createSymbol(const Elf_Sym *Sym) { |
| 806 | 819 | if (Sec == &InputSection::Discarded) |
| 807 | 820 | return Symtab->addUndefined<ELFT>(Name, Binding, StOther, Type, |
| 808 | 821 | /*CanOmitFromDynSym=*/false, this); |
| 809 | return Symtab->addRegular(Name, StOther, Type, Value, Size, Binding, Sec, | |
| 822 | return Symtab->addDefined(Name, StOther, Type, Value, Size, Binding, Sec, | |
| 810 | 823 | this); |
| 811 | 824 | } |
| 812 | 825 | } |
| ... | ... | @@ -940,8 +953,7 @@ std::vector<const typename ELFT::Verdef *> SharedFile<ELFT>::parseVerdefs() { |
| 940 | 953 | auto *CurVerdef = reinterpret_cast<const Elf_Verdef *>(Verdef); |
| 941 | 954 | Verdef += CurVerdef->vd_next; |
| 942 | 955 | unsigned VerdefIndex = CurVerdef->vd_ndx; |
| 943 | if (Verdefs.size() <= VerdefIndex) | |
| 944 | Verdefs.resize(VerdefIndex + 1); | |
| 956 | Verdefs.resize(VerdefIndex + 1); | |
| 945 | 957 | Verdefs[VerdefIndex] = CurVerdef; |
| 946 | 958 | } |
| 947 | 959 | |
| ... | ... | @@ -993,25 +1005,25 @@ template <class ELFT> void SharedFile<ELFT>::parseRest() { |
| 993 | 1005 | for (size_t I = 0; I < Syms.size(); ++I) { |
| 994 | 1006 | const Elf_Sym &Sym = Syms[I]; |
| 995 | 1007 | |
| 996 | StringRef Name = CHECK(Sym.getName(this->StringTable), this); | |
| 997 | if (Sym.isUndefined()) { | |
| 998 | Symbol *S = Symtab->addUndefined<ELFT>(Name, Sym.getBinding(), | |
| 999 | Sym.st_other, Sym.getType(), | |
| 1000 | /*CanOmitFromDynSym=*/false, this); | |
| 1001 | S->ExportDynamic = true; | |
| 1002 | continue; | |
| 1003 | } | |
| 1004 | ||
| 1005 | 1008 | // ELF spec requires that all local symbols precede weak or global |
| 1006 | 1009 | // symbols in each symbol table, and the index of first non-local symbol |
| 1007 | 1010 | // is stored to sh_info. If a local symbol appears after some non-local |
| 1008 | 1011 | // symbol, that's a violation of the spec. |
| 1012 | StringRef Name = CHECK(Sym.getName(this->StringTable), this); | |
| 1009 | 1013 | if (Sym.getBinding() == STB_LOCAL) { |
| 1010 | 1014 | warn("found local symbol '" + Name + |
| 1011 | 1015 | "' in global part of symbol table in file " + toString(this)); |
| 1012 | 1016 | continue; |
| 1013 | 1017 | } |
| 1014 | 1018 | |
| 1019 | if (Sym.isUndefined()) { | |
| 1020 | Symbol *S = Symtab->addUndefined<ELFT>(Name, Sym.getBinding(), | |
| 1021 | Sym.st_other, Sym.getType(), | |
| 1022 | /*CanOmitFromDynSym=*/false, this); | |
| 1023 | S->ExportDynamic = true; | |
| 1024 | continue; | |
| 1025 | } | |
| 1026 | ||
| 1015 | 1027 | // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly |
| 1016 | 1028 | // assigns VER_NDX_LOCAL to this section global symbol. Here is a |
| 1017 | 1029 | // workaround for this bug. |
| ... | ... | @@ -1054,6 +1066,9 @@ static uint8_t getBitcodeMachineKind(StringRef Path, const Triple &T) { |
| 1054 | 1066 | switch (T.getArch()) { |
| 1055 | 1067 | case Triple::aarch64: |
| 1056 | 1068 | return EM_AARCH64; |
| 1069 | case Triple::amdgcn: | |
| 1070 | case Triple::r600: | |
| 1071 | return EM_AMDGPU; | |
| 1057 | 1072 | case Triple::arm: |
| 1058 | 1073 | case Triple::thumb: |
| 1059 | 1074 | return EM_ARM; |
| ... | ... | @@ -1064,9 +1079,12 @@ static uint8_t getBitcodeMachineKind(StringRef Path, const Triple &T) { |
| 1064 | 1079 | case Triple::mips64: |
| 1065 | 1080 | case Triple::mips64el: |
| 1066 | 1081 | return EM_MIPS; |
| 1082 | case Triple::msp430: | |
| 1083 | return EM_MSP430; | |
| 1067 | 1084 | case Triple::ppc: |
| 1068 | 1085 | return EM_PPC; |
| 1069 | 1086 | case Triple::ppc64: |
| 1087 | case Triple::ppc64le: | |
| 1070 | 1088 | return EM_PPC64; |
| 1071 | 1089 | case Triple::x86: |
| 1072 | 1090 | return T.isOSIAMCU() ? EM_IAMCU : EM_386; |
| ... | ... | @@ -1178,7 +1196,7 @@ static ELFKind getELFKind(MemoryBufferRef MB) { |
| 1178 | 1196 | } |
| 1179 | 1197 | |
| 1180 | 1198 | void BinaryFile::parse() { |
| 1181 | ArrayRef<uint8_t> Data = toArrayRef(MB.getBuffer()); | |
| 1199 | ArrayRef<uint8_t> Data = arrayRefFromStringRef(MB.getBuffer()); | |
| 1182 | 1200 | auto *Section = make<InputSection>(this, SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, |
| 1183 | 1201 | 8, Data, ".data"); |
| 1184 | 1202 | Sections.push_back(Section); |
| ... | ... | @@ -1192,11 +1210,11 @@ void BinaryFile::parse() { |
| 1192 | 1210 | if (!isAlnum(S[I])) |
| 1193 | 1211 | S[I] = '_'; |
| 1194 | 1212 | |
| 1195 | Symtab->addRegular(Saver.save(S + "_start"), STV_DEFAULT, STT_OBJECT, 0, 0, | |
| 1213 | Symtab->addDefined(Saver.save(S + "_start"), STV_DEFAULT, STT_OBJECT, 0, 0, | |
| 1196 | 1214 | STB_GLOBAL, Section, nullptr); |
| 1197 | Symtab->addRegular(Saver.save(S + "_end"), STV_DEFAULT, STT_OBJECT, | |
| 1215 | Symtab->addDefined(Saver.save(S + "_end"), STV_DEFAULT, STT_OBJECT, | |
| 1198 | 1216 | Data.size(), 0, STB_GLOBAL, Section, nullptr); |
| 1199 | Symtab->addRegular(Saver.save(S + "_size"), STV_DEFAULT, STT_OBJECT, | |
| 1217 | Symtab->addDefined(Saver.save(S + "_size"), STV_DEFAULT, STT_OBJECT, | |
| 1200 | 1218 | Data.size(), 0, STB_GLOBAL, nullptr, nullptr); |
| 1201 | 1219 | } |
| 1202 | 1220 | |
| ... | ... | @@ -1262,25 +1280,11 @@ template <class ELFT> void LazyObjFile::parse() { |
| 1262 | 1280 | return; |
| 1263 | 1281 | } |
| 1264 | 1282 | |
| 1265 | switch (getELFKind(this->MB)) { | |
| 1266 | case ELF32LEKind: | |
| 1267 | addElfSymbols<ELF32LE>(); | |
| 1268 | return; | |
| 1269 | case ELF32BEKind: | |
| 1270 | addElfSymbols<ELF32BE>(); | |
| 1271 | return; | |
| 1272 | case ELF64LEKind: | |
| 1273 | addElfSymbols<ELF64LE>(); | |
| 1274 | return; | |
| 1275 | case ELF64BEKind: | |
| 1276 | addElfSymbols<ELF64BE>(); | |
| 1283 | if (getELFKind(this->MB) != Config->EKind) { | |
| 1284 | error("incompatible file: " + this->MB.getBufferIdentifier()); | |
| 1277 | 1285 | return; |
| 1278 | default: | |
| 1279 | llvm_unreachable("getELFKind"); | |
| 1280 | 1286 | } |
| 1281 | } | |
| 1282 | 1287 | |
| 1283 | template <class ELFT> void LazyObjFile::addElfSymbols() { | |
| 1284 | 1288 | ELFFile<ELFT> Obj = check(ELFFile<ELFT>::create(MB.getBuffer())); |
| 1285 | 1289 | ArrayRef<typename ELFT::Shdr> Sections = CHECK(Obj.sections(), this); |
| 1286 | 1290 | |
| ... | ... | @@ -1305,12 +1309,9 @@ std::string elf::replaceThinLTOSuffix(StringRef Path) { |
| 1305 | 1309 | StringRef Suffix = Config->ThinLTOObjectSuffixReplace.first; |
| 1306 | 1310 | StringRef Repl = Config->ThinLTOObjectSuffixReplace.second; |
| 1307 | 1311 | |
| 1308 | if (!Path.endswith(Suffix)) { | |
| 1309 | error("-thinlto-object-suffix-replace=" + Suffix + ";" + Repl + | |
| 1310 | " was given, but " + Path + " does not end with the suffix"); | |
| 1311 | return ""; | |
| 1312 | } | |
| 1313 | return (Path.drop_back(Suffix.size()) + Repl).str(); | |
| 1312 | if (Path.consume_back(Suffix)) | |
| 1313 | return (Path + Repl).str(); | |
| 1314 | return Path; | |
| 1314 | 1315 | } |
| 1315 | 1316 | |
| 1316 | 1317 | template void ArchiveFile::parse<ELF32LE>(); |
deps/lld/ELF/InputFiles.h+8-5| ... | ... | @@ -50,7 +50,7 @@ class Symbol; |
| 50 | 50 | |
| 51 | 51 | // If -reproduce option is given, all input files are written |
| 52 | 52 | // to this tar archive. |
| 53 | extern llvm::TarWriter *Tar; | |
| 53 | extern std::unique_ptr<llvm::TarWriter> Tar; | |
| 54 | 54 | |
| 55 | 55 | // Opens a given file. |
| 56 | 56 | llvm::Optional<MemoryBufferRef> readFile(StringRef Path); |
| ... | ... | @@ -86,7 +86,9 @@ public: |
| 86 | 86 | |
| 87 | 87 | // Returns object file symbols. It is a runtime error to call this |
| 88 | 88 | // function on files of other types. |
| 89 | ArrayRef<Symbol *> getSymbols() { | |
| 89 | ArrayRef<Symbol *> getSymbols() { return getMutableSymbols(); } | |
| 90 | ||
| 91 | std::vector<Symbol *> &getMutableSymbols() { | |
| 90 | 92 | assert(FileKind == BinaryKind || FileKind == ObjKind || |
| 91 | 93 | FileKind == BitcodeKind); |
| 92 | 94 | return Symbols; |
| ... | ... | @@ -169,10 +171,10 @@ template <class ELFT> class ObjFile : public ELFFileBase<ELFT> { |
| 169 | 171 | typedef typename ELFT::Sym Elf_Sym; |
| 170 | 172 | typedef typename ELFT::Shdr Elf_Shdr; |
| 171 | 173 | typedef typename ELFT::Word Elf_Word; |
| 174 | typedef typename ELFT::CGProfile Elf_CGProfile; | |
| 172 | 175 | |
| 173 | 176 | StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> Sections, |
| 174 | 177 | const Elf_Shdr &Sec); |
| 175 | ArrayRef<Elf_Word> getShtGroupEntries(const Elf_Shdr &Sec); | |
| 176 | 178 | |
| 177 | 179 | public: |
| 178 | 180 | static bool classof(const InputFile *F) { return F->kind() == Base::ObjKind; } |
| ... | ... | @@ -218,6 +220,9 @@ public: |
| 218 | 220 | // Pointer to this input file's .llvm_addrsig section, if it has one. |
| 219 | 221 | const Elf_Shdr *AddrsigSec = nullptr; |
| 220 | 222 | |
| 223 | // SHT_LLVM_CALL_GRAPH_PROFILE table | |
| 224 | ArrayRef<Elf_CGProfile> CGProfile; | |
| 225 | ||
| 221 | 226 | private: |
| 222 | 227 | void |
| 223 | 228 | initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups); |
| ... | ... | @@ -272,8 +277,6 @@ public: |
| 272 | 277 | bool AddedToLink = false; |
| 273 | 278 | |
| 274 | 279 | private: |
| 275 | template <class ELFT> void addElfSymbols(); | |
| 276 | ||
| 277 | 280 | uint64_t OffsetInArchive; |
| 278 | 281 | }; |
| 279 | 282 |
deps/lld/ELF/InputSection.cpp+271-188| ... | ... | @@ -21,7 +21,6 @@ |
| 21 | 21 | #include "Thunks.h" |
| 22 | 22 | #include "lld/Common/ErrorHandler.h" |
| 23 | 23 | #include "lld/Common/Memory.h" |
| 24 | #include "llvm/Object/Decompressor.h" | |
| 25 | 24 | #include "llvm/Support/Compiler.h" |
| 26 | 25 | #include "llvm/Support/Compression.h" |
| 27 | 26 | #include "llvm/Support/Endian.h" |
| ... | ... | @@ -64,11 +63,11 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, |
| 64 | 63 | StringRef Name, Kind SectionKind) |
| 65 | 64 | : SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info, |
| 66 | 65 | Link), |
| 67 | File(File), Data(Data) { | |
| 66 | File(File), RawData(Data) { | |
| 68 | 67 | // In order to reduce memory allocation, we assume that mergeable |
| 69 | 68 | // sections are smaller than 4 GiB, which is not an unreasonable |
| 70 | 69 | // assumption as of 2017. |
| 71 | if (SectionKind == SectionBase::Merge && Data.size() > UINT32_MAX) | |
| 70 | if (SectionKind == SectionBase::Merge && RawData.size() > UINT32_MAX) | |
| 72 | 71 | error(toString(this) + ": section too large"); |
| 73 | 72 | |
| 74 | 73 | NumRelocations = 0; |
| ... | ... | @@ -80,6 +79,17 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags, |
| 80 | 79 | if (!isPowerOf2_64(V)) |
| 81 | 80 | fatal(toString(File) + ": section sh_addralign is not a power of 2"); |
| 82 | 81 | this->Alignment = V; |
| 82 | ||
| 83 | // In ELF, each section can be compressed by zlib, and if compressed, | |
| 84 | // section name may be mangled by appending "z" (e.g. ".zdebug_info"). | |
| 85 | // If that's the case, demangle section name so that we can handle a | |
| 86 | // section as if it weren't compressed. | |
| 87 | if ((Flags & SHF_COMPRESSED) || Name.startswith(".zdebug")) { | |
| 88 | if (!zlib::isAvailable()) | |
| 89 | error(toString(File) + ": contains a compressed section, " + | |
| 90 | "but zlib is not available"); | |
| 91 | parseCompressedHeader(); | |
| 92 | } | |
| 83 | 93 | } |
| 84 | 94 | |
| 85 | 95 | // Drop SHF_GROUP bit unless we are producing a re-linkable object file. |
| ... | ... | @@ -128,13 +138,25 @@ InputSectionBase::InputSectionBase(ObjFile<ELFT> &File, |
| 128 | 138 | size_t InputSectionBase::getSize() const { |
| 129 | 139 | if (auto *S = dyn_cast<SyntheticSection>(this)) |
| 130 | 140 | return S->getSize(); |
| 141 | if (UncompressedSize >= 0) | |
| 142 | return UncompressedSize; | |
| 143 | return RawData.size(); | |
| 144 | } | |
| 145 | ||
| 146 | void InputSectionBase::uncompress() const { | |
| 147 | size_t Size = UncompressedSize; | |
| 148 | UncompressedBuf.reset(new char[Size]); | |
| 131 | 149 | |
| 132 | return Data.size(); | |
| 150 | if (Error E = | |
| 151 | zlib::uncompress(toStringRef(RawData), UncompressedBuf.get(), Size)) | |
| 152 | fatal(toString(this) + | |
| 153 | ": uncompress failed: " + llvm::toString(std::move(E))); | |
| 154 | RawData = makeArrayRef((uint8_t *)UncompressedBuf.get(), Size); | |
| 133 | 155 | } |
| 134 | 156 | |
| 135 | 157 | uint64_t InputSectionBase::getOffsetInFile() const { |
| 136 | 158 | const uint8_t *FileStart = (const uint8_t *)File->MB.getBufferStart(); |
| 137 | const uint8_t *SecStart = Data.begin(); | |
| 159 | const uint8_t *SecStart = data().begin(); | |
| 138 | 160 | return SecStart - FileStart; |
| 139 | 161 | } |
| 140 | 162 | |
| ... | ... | @@ -180,34 +202,70 @@ OutputSection *SectionBase::getOutputSection() { |
| 180 | 202 | return Sec ? Sec->getParent() : nullptr; |
| 181 | 203 | } |
| 182 | 204 | |
| 183 | // Decompress section contents if required. Note that this function | |
| 184 | // is called from parallelForEach, so it must be thread-safe. | |
| 185 | void InputSectionBase::maybeDecompress() { | |
| 186 | if (DecompressBuf) | |
| 187 | return; | |
| 188 | if (!(Flags & SHF_COMPRESSED) && !Name.startswith(".zdebug")) | |
| 189 | return; | |
| 205 | // When a section is compressed, `RawData` consists with a header followed | |
| 206 | // by zlib-compressed data. This function parses a header to initialize | |
| 207 | // `UncompressedSize` member and remove the header from `RawData`. | |
| 208 | void InputSectionBase::parseCompressedHeader() { | |
| 209 | typedef typename ELF64LE::Chdr Chdr64; | |
| 210 | typedef typename ELF32LE::Chdr Chdr32; | |
| 190 | 211 | |
| 191 | // Decompress a section. | |
| 192 | Decompressor Dec = check(Decompressor::create(Name, toStringRef(Data), | |
| 193 | Config->IsLE, Config->Is64)); | |
| 212 | // Old-style header | |
| 213 | if (Name.startswith(".zdebug")) { | |
| 214 | if (!toStringRef(RawData).startswith("ZLIB")) { | |
| 215 | error(toString(this) + ": corrupted compressed section header"); | |
| 216 | return; | |
| 217 | } | |
| 218 | RawData = RawData.slice(4); | |
| 194 | 219 | |
| 195 | size_t Size = Dec.getDecompressedSize(); | |
| 196 | DecompressBuf.reset(new char[Size + Name.size()]()); | |
| 197 | if (Error E = Dec.decompress({DecompressBuf.get(), Size})) | |
| 198 | fatal(toString(this) + | |
| 199 | ": decompress failed: " + llvm::toString(std::move(E))); | |
| 220 | if (RawData.size() < 8) { | |
| 221 | error(toString(this) + ": corrupted compressed section header"); | |
| 222 | return; | |
| 223 | } | |
| 224 | ||
| 225 | UncompressedSize = read64be(RawData.data()); | |
| 226 | RawData = RawData.slice(8); | |
| 227 | ||
| 228 | // Restore the original section name. | |
| 229 | // (e.g. ".zdebug_info" -> ".debug_info") | |
| 230 | Name = Saver.save("." + Name.substr(2)); | |
| 231 | return; | |
| 232 | } | |
| 200 | 233 | |
| 201 | Data = makeArrayRef((uint8_t *)DecompressBuf.get(), Size); | |
| 234 | assert(Flags & SHF_COMPRESSED); | |
| 202 | 235 | Flags &= ~(uint64_t)SHF_COMPRESSED; |
| 203 | 236 | |
| 204 | // A section name may have been altered if compressed. If that's | |
| 205 | // the case, restore the original name. (i.e. ".zdebug_" -> ".debug_") | |
| 206 | if (Name.startswith(".zdebug")) { | |
| 207 | DecompressBuf[Size] = '.'; | |
| 208 | memcpy(&DecompressBuf[Size + 1], Name.data() + 2, Name.size() - 2); | |
| 209 | Name = StringRef(&DecompressBuf[Size], Name.size() - 1); | |
| 237 | // New-style 64-bit header | |
| 238 | if (Config->Is64) { | |
| 239 | if (RawData.size() < sizeof(Chdr64)) { | |
| 240 | error(toString(this) + ": corrupted compressed section"); | |
| 241 | return; | |
| 242 | } | |
| 243 | ||
| 244 | auto *Hdr = reinterpret_cast<const Chdr64 *>(RawData.data()); | |
| 245 | if (Hdr->ch_type != ELFCOMPRESS_ZLIB) { | |
| 246 | error(toString(this) + ": unsupported compression type"); | |
| 247 | return; | |
| 248 | } | |
| 249 | ||
| 250 | UncompressedSize = Hdr->ch_size; | |
| 251 | RawData = RawData.slice(sizeof(*Hdr)); | |
| 252 | return; | |
| 210 | 253 | } |
| 254 | ||
| 255 | // New-style 32-bit header | |
| 256 | if (RawData.size() < sizeof(Chdr32)) { | |
| 257 | error(toString(this) + ": corrupted compressed section"); | |
| 258 | return; | |
| 259 | } | |
| 260 | ||
| 261 | auto *Hdr = reinterpret_cast<const Chdr32 *>(RawData.data()); | |
| 262 | if (Hdr->ch_type != ELFCOMPRESS_ZLIB) { | |
| 263 | error(toString(this) + ": unsupported compression type"); | |
| 264 | return; | |
| 265 | } | |
| 266 | ||
| 267 | UncompressedSize = Hdr->ch_size; | |
| 268 | RawData = RawData.slice(sizeof(*Hdr)); | |
| 211 | 269 | } |
| 212 | 270 | |
| 213 | 271 | InputSection *InputSectionBase::getLinkOrderDep() const { |
| ... | ... | @@ -230,14 +288,17 @@ Defined *InputSectionBase::getEnclosingFunction(uint64_t Offset) { |
| 230 | 288 | // Returns a source location string. Used to construct an error message. |
| 231 | 289 | template <class ELFT> |
| 232 | 290 | std::string InputSectionBase::getLocation(uint64_t Offset) { |
| 291 | std::string SecAndOffset = (Name + "+0x" + utohexstr(Offset)).str(); | |
| 292 | ||
| 233 | 293 | // We don't have file for synthetic sections. |
| 234 | 294 | if (getFile<ELFT>() == nullptr) |
| 235 | return (Config->OutputFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")") | |
| 295 | return (Config->OutputFile + ":(" + SecAndOffset + ")") | |
| 236 | 296 | .str(); |
| 237 | 297 | |
| 238 | 298 | // First check if we can get desired values from debugging information. |
| 239 | 299 | if (Optional<DILineInfo> Info = getFile<ELFT>()->getDILineInfo(this, Offset)) |
| 240 | return Info->FileName + ":" + std::to_string(Info->Line); | |
| 300 | return Info->FileName + ":" + std::to_string(Info->Line) + ":(" + | |
| 301 | SecAndOffset + ")"; | |
| 241 | 302 | |
| 242 | 303 | // File->SourceFile contains STT_FILE symbol that contains a |
| 243 | 304 | // source file name. If it's missing, we use an object file name. |
| ... | ... | @@ -246,10 +307,10 @@ std::string InputSectionBase::getLocation(uint64_t Offset) { |
| 246 | 307 | SrcFile = toString(File); |
| 247 | 308 | |
| 248 | 309 | if (Defined *D = getEnclosingFunction<ELFT>(Offset)) |
| 249 | return SrcFile + ":(function " + toString(*D) + ")"; | |
| 310 | return SrcFile + ":(function " + toString(*D) + ": " + SecAndOffset + ")"; | |
| 250 | 311 | |
| 251 | 312 | // If there's no symbol, print out the offset in the section. |
| 252 | return (SrcFile + ":(" + Name + "+0x" + utohexstr(Offset) + ")").str(); | |
| 313 | return (SrcFile + ":(" + SecAndOffset + ")"); | |
| 253 | 314 | } |
| 254 | 315 | |
| 255 | 316 | // This function is intended to be used for constructing an error message. |
| ... | ... | @@ -259,9 +320,6 @@ std::string InputSectionBase::getLocation(uint64_t Offset) { |
| 259 | 320 | // |
| 260 | 321 | // Returns an empty string if there's no way to get line info. |
| 261 | 322 | std::string InputSectionBase::getSrcMsg(const Symbol &Sym, uint64_t Offset) { |
| 262 | // Synthetic sections don't have input files. | |
| 263 | if (!File) | |
| 264 | return ""; | |
| 265 | 323 | return File->getSrcMsg(Sym, *this, Offset); |
| 266 | 324 | } |
| 267 | 325 | |
| ... | ... | @@ -275,9 +333,6 @@ std::string InputSectionBase::getSrcMsg(const Symbol &Sym, uint64_t Offset) { |
| 275 | 333 | // |
| 276 | 334 | // path/to/foo.o:(function bar) in archive path/to/bar.a |
| 277 | 335 | std::string InputSectionBase::getObjMsg(uint64_t Off) { |
| 278 | // Synthetic sections don't have input files. | |
| 279 | if (!File) | |
| 280 | return ("<internal>:(" + Name + "+0x" + utohexstr(Off) + ")").str(); | |
| 281 | 336 | std::string Filename = File->getName(); |
| 282 | 337 | |
| 283 | 338 | std::string Archive; |
| ... | ... | @@ -362,7 +417,7 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
| 362 | 417 | // Output section VA is zero for -r, so r_offset is an offset within the |
| 363 | 418 | // section, but for --emit-relocs it is an virtual address. |
| 364 | 419 | P->r_offset = Sec->getVA(Rel.r_offset); |
| 365 | P->setSymbolAndType(InX::SymTab->getSymbolIndex(&Sym), Type, | |
| 420 | P->setSymbolAndType(In.SymTab->getSymbolIndex(&Sym), Type, | |
| 366 | 421 | Config->IsMips64EL); |
| 367 | 422 | |
| 368 | 423 | if (Sym.Type == STT_SECTION) { |
| ... | ... | @@ -380,14 +435,14 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) { |
| 380 | 435 | error("STT_SECTION symbol should be defined"); |
| 381 | 436 | continue; |
| 382 | 437 | } |
| 383 | SectionBase *Section = D->Section; | |
| 384 | if (Section == &InputSection::Discarded) { | |
| 438 | SectionBase *Section = D->Section->Repl; | |
| 439 | if (!Section->Live) { | |
| 385 | 440 | P->setSymbolAndType(0, 0, false); |
| 386 | 441 | continue; |
| 387 | 442 | } |
| 388 | 443 | |
| 389 | 444 | int64_t Addend = getAddend<ELFT>(Rel); |
| 390 | const uint8_t *BufLoc = Sec->Data.begin() + Rel.r_offset; | |
| 445 | const uint8_t *BufLoc = Sec->data().begin() + Rel.r_offset; | |
| 391 | 446 | if (!RelTy::IsRela) |
| 392 | 447 | Addend = Target->getImplicitAddend(BufLoc, Type); |
| 393 | 448 | |
| ... | ... | @@ -487,6 +542,62 @@ static uint64_t getARMStaticBase(const Symbol &Sym) { |
| 487 | 542 | return OS->PtLoad->FirstSec->Addr; |
| 488 | 543 | } |
| 489 | 544 | |
| 545 | // For R_RISCV_PC_INDIRECT (R_RISCV_PCREL_LO12_{I,S}), the symbol actually | |
| 546 | // points the corresponding R_RISCV_PCREL_HI20 relocation, and the target VA | |
| 547 | // is calculated using PCREL_HI20's symbol. | |
| 548 | // | |
| 549 | // This function returns the R_RISCV_PCREL_HI20 relocation from | |
| 550 | // R_RISCV_PCREL_LO12's symbol and addend. | |
| 551 | static Relocation *getRISCVPCRelHi20(const Symbol *Sym, uint64_t Addend) { | |
| 552 | const Defined *D = cast<Defined>(Sym); | |
| 553 | InputSection *IS = cast<InputSection>(D->Section); | |
| 554 | ||
| 555 | if (Addend != 0) | |
| 556 | warn("Non-zero addend in R_RISCV_PCREL_LO12 relocation to " + | |
| 557 | IS->getObjMsg(D->Value) + " is ignored"); | |
| 558 | ||
| 559 | // Relocations are sorted by offset, so we can use std::equal_range to do | |
| 560 | // binary search. | |
| 561 | auto Range = std::equal_range(IS->Relocations.begin(), IS->Relocations.end(), | |
| 562 | D->Value, RelocationOffsetComparator{}); | |
| 563 | for (auto It = std::get<0>(Range); It != std::get<1>(Range); ++It) | |
| 564 | if (isRelExprOneOf<R_PC>(It->Expr)) | |
| 565 | return &*It; | |
| 566 | ||
| 567 | error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) + | |
| 568 | " without an associated R_RISCV_PCREL_HI20 relocation"); | |
| 569 | return nullptr; | |
| 570 | } | |
| 571 | ||
| 572 | // A TLS symbol's virtual address is relative to the TLS segment. Add a | |
| 573 | // target-specific adjustment to produce a thread-pointer-relative offset. | |
| 574 | static int64_t getTlsTpOffset() { | |
| 575 | switch (Config->EMachine) { | |
| 576 | case EM_ARM: | |
| 577 | case EM_AARCH64: | |
| 578 | // Variant 1. The thread pointer points to a TCB with a fixed 2-word size, | |
| 579 | // followed by a variable amount of alignment padding, followed by the TLS | |
| 580 | // segment. | |
| 581 | // | |
| 582 | // NB: While the ARM/AArch64 ABI formally has a 2-word TCB size, lld | |
| 583 | // effectively increases the TCB size to 8 words for Android compatibility. | |
| 584 | // It accomplishes this by increasing the segment's alignment. | |
| 585 | return alignTo(Config->Wordsize * 2, Out::TlsPhdr->p_align); | |
| 586 | case EM_386: | |
| 587 | case EM_X86_64: | |
| 588 | // Variant 2. The TLS segment is located just before the thread pointer. | |
| 589 | return -Out::TlsPhdr->p_memsz; | |
| 590 | case EM_PPC64: | |
| 591 | // The thread pointer points to a fixed offset from the start of the | |
| 592 | // executable's TLS segment. An offset of 0x7000 allows a signed 16-bit | |
| 593 | // offset to reach 0x1000 of TCB/thread-library data and 0xf000 of the | |
| 594 | // program's TLS segment. | |
| 595 | return -0x7000; | |
| 596 | default: | |
| 597 | llvm_unreachable("unhandled Config->EMachine"); | |
| 598 | } | |
| 599 | } | |
| 600 | ||
| 490 | 601 | static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, |
| 491 | 602 | uint64_t P, const Symbol &Sym, RelExpr Expr) { |
| 492 | 603 | switch (Expr) { |
| ... | ... | @@ -501,38 +612,37 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, |
| 501 | 612 | case R_ARM_SBREL: |
| 502 | 613 | return Sym.getVA(A) - getARMStaticBase(Sym); |
| 503 | 614 | case R_GOT: |
| 615 | case R_GOT_PLT: | |
| 504 | 616 | case R_RELAX_TLS_GD_TO_IE_ABS: |
| 505 | 617 | return Sym.getGotVA() + A; |
| 506 | 618 | case R_GOTONLY_PC: |
| 507 | return InX::Got->getVA() + A - P; | |
| 619 | return In.Got->getVA() + A - P; | |
| 508 | 620 | case R_GOTONLY_PC_FROM_END: |
| 509 | return InX::Got->getVA() + A - P + InX::Got->getSize(); | |
| 621 | return In.Got->getVA() + A - P + In.Got->getSize(); | |
| 510 | 622 | case R_GOTREL: |
| 511 | return Sym.getVA(A) - InX::Got->getVA(); | |
| 623 | return Sym.getVA(A) - In.Got->getVA(); | |
| 512 | 624 | case R_GOTREL_FROM_END: |
| 513 | return Sym.getVA(A) - InX::Got->getVA() - InX::Got->getSize(); | |
| 625 | return Sym.getVA(A) - In.Got->getVA() - In.Got->getSize(); | |
| 514 | 626 | case R_GOT_FROM_END: |
| 515 | 627 | case R_RELAX_TLS_GD_TO_IE_END: |
| 516 | return Sym.getGotOffset() + A - InX::Got->getSize(); | |
| 628 | return Sym.getGotOffset() + A - In.Got->getSize(); | |
| 517 | 629 | case R_TLSLD_GOT_OFF: |
| 518 | 630 | case R_GOT_OFF: |
| 519 | 631 | case R_RELAX_TLS_GD_TO_IE_GOT_OFF: |
| 520 | 632 | return Sym.getGotOffset() + A; |
| 521 | case R_GOT_PAGE_PC: | |
| 522 | case R_RELAX_TLS_GD_TO_IE_PAGE_PC: | |
| 633 | case R_AARCH64_GOT_PAGE_PC: | |
| 634 | case R_AARCH64_GOT_PAGE_PC_PLT: | |
| 635 | case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC: | |
| 523 | 636 | return getAArch64Page(Sym.getGotVA() + A) - getAArch64Page(P); |
| 524 | 637 | case R_GOT_PC: |
| 525 | 638 | case R_RELAX_TLS_GD_TO_IE: |
| 526 | 639 | return Sym.getGotVA() + A - P; |
| 527 | case R_HINT: | |
| 528 | case R_NONE: | |
| 529 | case R_TLSDESC_CALL: | |
| 530 | case R_TLSLD_HINT: | |
| 531 | llvm_unreachable("cannot relocate hint relocs"); | |
| 640 | case R_HEXAGON_GOT: | |
| 641 | return Sym.getGotVA() - In.GotPlt->getVA(); | |
| 532 | 642 | case R_MIPS_GOTREL: |
| 533 | return Sym.getVA(A) - InX::MipsGot->getGp(File); | |
| 643 | return Sym.getVA(A) - In.MipsGot->getGp(File); | |
| 534 | 644 | case R_MIPS_GOT_GP: |
| 535 | return InX::MipsGot->getGp(File) + A; | |
| 645 | return In.MipsGot->getGp(File) + A; | |
| 536 | 646 | case R_MIPS_GOT_GP_PC: { |
| 537 | 647 | // R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target |
| 538 | 648 | // is _gp_disp symbol. In that case we should use the following |
| ... | ... | @@ -541,7 +651,7 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, |
| 541 | 651 | // microMIPS variants of these relocations use slightly different |
| 542 | 652 | // expressions: AHL + GP - P + 3 for %lo() and AHL + GP - P - 1 for %hi() |
| 543 | 653 | // to correctly handle less-sugnificant bit of the microMIPS symbol. |
| 544 | uint64_t V = InX::MipsGot->getGp(File) + A - P; | |
| 654 | uint64_t V = In.MipsGot->getGp(File) + A - P; | |
| 545 | 655 | if (Type == R_MIPS_LO16 || Type == R_MICROMIPS_LO16) |
| 546 | 656 | V += 4; |
| 547 | 657 | if (Type == R_MICROMIPS_LO16 || Type == R_MICROMIPS_HI16) |
| ... | ... | @@ -552,31 +662,34 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, |
| 552 | 662 | // If relocation against MIPS local symbol requires GOT entry, this entry |
| 553 | 663 | // should be initialized by 'page address'. This address is high 16-bits |
| 554 | 664 | // of sum the symbol's value and the addend. |
| 555 | return InX::MipsGot->getVA() + | |
| 556 | InX::MipsGot->getPageEntryOffset(File, Sym, A) - | |
| 557 | InX::MipsGot->getGp(File); | |
| 665 | return In.MipsGot->getVA() + In.MipsGot->getPageEntryOffset(File, Sym, A) - | |
| 666 | In.MipsGot->getGp(File); | |
| 558 | 667 | case R_MIPS_GOT_OFF: |
| 559 | 668 | case R_MIPS_GOT_OFF32: |
| 560 | 669 | // In case of MIPS if a GOT relocation has non-zero addend this addend |
| 561 | 670 | // should be applied to the GOT entry content not to the GOT entry offset. |
| 562 | 671 | // That is why we use separate expression type. |
| 563 | return InX::MipsGot->getVA() + | |
| 564 | InX::MipsGot->getSymEntryOffset(File, Sym, A) - | |
| 565 | InX::MipsGot->getGp(File); | |
| 672 | return In.MipsGot->getVA() + In.MipsGot->getSymEntryOffset(File, Sym, A) - | |
| 673 | In.MipsGot->getGp(File); | |
| 566 | 674 | case R_MIPS_TLSGD: |
| 567 | return InX::MipsGot->getVA() + InX::MipsGot->getGlobalDynOffset(File, Sym) - | |
| 568 | InX::MipsGot->getGp(File); | |
| 675 | return In.MipsGot->getVA() + In.MipsGot->getGlobalDynOffset(File, Sym) - | |
| 676 | In.MipsGot->getGp(File); | |
| 569 | 677 | case R_MIPS_TLSLD: |
| 570 | return InX::MipsGot->getVA() + InX::MipsGot->getTlsIndexOffset(File) - | |
| 571 | InX::MipsGot->getGp(File); | |
| 572 | case R_PAGE_PC: | |
| 573 | case R_PLT_PAGE_PC: { | |
| 574 | uint64_t Dest; | |
| 575 | if (Sym.isUndefWeak()) | |
| 576 | Dest = getAArch64Page(A); | |
| 577 | else | |
| 578 | Dest = getAArch64Page(Sym.getVA(A)); | |
| 579 | return Dest - getAArch64Page(P); | |
| 678 | return In.MipsGot->getVA() + In.MipsGot->getTlsIndexOffset(File) - | |
| 679 | In.MipsGot->getGp(File); | |
| 680 | case R_AARCH64_PAGE_PC: { | |
| 681 | uint64_t Val = Sym.isUndefWeak() ? P + A : Sym.getVA(A); | |
| 682 | return getAArch64Page(Val) - getAArch64Page(P); | |
| 683 | } | |
| 684 | case R_AARCH64_PLT_PAGE_PC: { | |
| 685 | uint64_t Val = Sym.isUndefWeak() ? P + A : Sym.getPltVA() + A; | |
| 686 | return getAArch64Page(Val) - getAArch64Page(P); | |
| 687 | } | |
| 688 | case R_RISCV_PC_INDIRECT: { | |
| 689 | if (const Relocation *HiRel = getRISCVPCRelHi20(&Sym, A)) | |
| 690 | return getRelocTargetVA(File, HiRel->Type, HiRel->Addend, Sym.getVA(), | |
| 691 | *HiRel->Sym, HiRel->Expr); | |
| 692 | return 0; | |
| 580 | 693 | } |
| 581 | 694 | case R_PC: { |
| 582 | 695 | uint64_t Dest; |
| ... | ... | @@ -608,16 +721,12 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, |
| 608 | 721 | return 0; |
| 609 | 722 | |
| 610 | 723 | // PPC64 V2 ABI describes two entry points to a function. The global entry |
| 611 | // point sets up the TOC base pointer. When calling a local function, the | |
| 612 | // call should branch to the local entry point rather than the global entry | |
| 613 | // point. Section 3.4.1 describes using the 3 most significant bits of the | |
| 614 | // st_other field to find out how many instructions there are between the | |
| 615 | // local and global entry point. | |
| 616 | uint8_t StOther = (Sym.StOther >> 5) & 7; | |
| 617 | if (StOther == 0 || StOther == 1) | |
| 618 | return SymVA - P; | |
| 619 | ||
| 620 | return SymVA - P + (1LL << StOther); | |
| 724 | // point is used for calls where the caller and callee (may) have different | |
| 725 | // TOC base pointers and r2 needs to be modified to hold the TOC base for | |
| 726 | // the callee. For local calls the caller and callee share the same | |
| 727 | // TOC base and so the TOC pointer initialization code should be skipped by | |
| 728 | // branching to the local entry point. | |
| 729 | return SymVA - P + getPPC64GlobalEntryToLocalEntryOffset(Sym.StOther); | |
| 621 | 730 | } |
| 622 | 731 | case R_PPC_TOC: |
| 623 | 732 | return getPPC64TocBase() + A; |
| ... | ... | @@ -634,48 +743,32 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A, |
| 634 | 743 | // statically to zero. |
| 635 | 744 | if (Sym.isTls() && Sym.isUndefWeak()) |
| 636 | 745 | return 0; |
| 637 | ||
| 638 | // For TLS variant 1 the TCB is a fixed size, whereas for TLS variant 2 the | |
| 639 | // TCB is on unspecified size and content. Targets that implement variant 1 | |
| 640 | // should set TcbSize. | |
| 641 | if (Target->TcbSize) { | |
| 642 | // PPC64 V2 ABI has the thread pointer offset into the middle of the TLS | |
| 643 | // storage area by TlsTpOffset for efficient addressing TCB and up to | |
| 644 | // 4KB – 8 B of other thread library information (placed before the TCB). | |
| 645 | // Subtracting this offset will get the address of the first TLS block. | |
| 646 | if (Target->TlsTpOffset) | |
| 647 | return Sym.getVA(A) - Target->TlsTpOffset; | |
| 648 | ||
| 649 | // If thread pointer is not offset into the middle, the first thing in the | |
| 650 | // TLS storage area is the TCB. Add the TcbSize to get the address of the | |
| 651 | // first TLS block. | |
| 652 | return Sym.getVA(A) + alignTo(Target->TcbSize, Out::TlsPhdr->p_align); | |
| 653 | } | |
| 654 | return Sym.getVA(A) - Out::TlsPhdr->p_memsz; | |
| 746 | return Sym.getVA(A) + getTlsTpOffset(); | |
| 655 | 747 | case R_RELAX_TLS_GD_TO_LE_NEG: |
| 656 | 748 | case R_NEG_TLS: |
| 657 | 749 | return Out::TlsPhdr->p_memsz - Sym.getVA(A); |
| 658 | 750 | case R_SIZE: |
| 659 | 751 | return Sym.getSize() + A; |
| 660 | 752 | case R_TLSDESC: |
| 661 | return InX::Got->getGlobalDynAddr(Sym) + A; | |
| 662 | case R_TLSDESC_PAGE: | |
| 663 | return getAArch64Page(InX::Got->getGlobalDynAddr(Sym) + A) - | |
| 753 | return In.Got->getGlobalDynAddr(Sym) + A; | |
| 754 | case R_AARCH64_TLSDESC_PAGE: | |
| 755 | return getAArch64Page(In.Got->getGlobalDynAddr(Sym) + A) - | |
| 664 | 756 | getAArch64Page(P); |
| 665 | 757 | case R_TLSGD_GOT: |
| 666 | return InX::Got->getGlobalDynOffset(Sym) + A; | |
| 758 | return In.Got->getGlobalDynOffset(Sym) + A; | |
| 667 | 759 | case R_TLSGD_GOT_FROM_END: |
| 668 | return InX::Got->getGlobalDynOffset(Sym) + A - InX::Got->getSize(); | |
| 760 | return In.Got->getGlobalDynOffset(Sym) + A - In.Got->getSize(); | |
| 669 | 761 | case R_TLSGD_PC: |
| 670 | return InX::Got->getGlobalDynAddr(Sym) + A - P; | |
| 762 | return In.Got->getGlobalDynAddr(Sym) + A - P; | |
| 671 | 763 | case R_TLSLD_GOT_FROM_END: |
| 672 | return InX::Got->getTlsIndexOff() + A - InX::Got->getSize(); | |
| 764 | return In.Got->getTlsIndexOff() + A - In.Got->getSize(); | |
| 673 | 765 | case R_TLSLD_GOT: |
| 674 | return InX::Got->getTlsIndexOff() + A; | |
| 766 | return In.Got->getTlsIndexOff() + A; | |
| 675 | 767 | case R_TLSLD_PC: |
| 676 | return InX::Got->getTlsIndexVA() + A - P; | |
| 768 | return In.Got->getTlsIndexVA() + A - P; | |
| 769 | default: | |
| 770 | llvm_unreachable("invalid expression"); | |
| 677 | 771 | } |
| 678 | llvm_unreachable("Invalid expression"); | |
| 679 | 772 | } |
| 680 | 773 | |
| 681 | 774 | // This function applies relocations to sections without SHF_ALLOC bit. |
| ... | ... | @@ -808,10 +901,10 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) { |
| 808 | 901 | case R_RELAX_TLS_GD_TO_LE_NEG: |
| 809 | 902 | Target->relaxTlsGdToLe(BufLoc, Type, TargetVA); |
| 810 | 903 | break; |
| 904 | case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC: | |
| 811 | 905 | case R_RELAX_TLS_GD_TO_IE: |
| 812 | 906 | case R_RELAX_TLS_GD_TO_IE_ABS: |
| 813 | 907 | case R_RELAX_TLS_GD_TO_IE_GOT_OFF: |
| 814 | case R_RELAX_TLS_GD_TO_IE_PAGE_PC: | |
| 815 | 908 | case R_RELAX_TLS_GD_TO_IE_END: |
| 816 | 909 | Target->relaxTlsGdToIe(BufLoc, Type, TargetVA); |
| 817 | 910 | break; |
| ... | ... | @@ -848,16 +941,20 @@ static void switchMorestackCallsToMorestackNonSplit( |
| 848 | 941 | // __morestack inside that function should be switched to |
| 849 | 942 | // __morestack_non_split. |
| 850 | 943 | Symbol *MoreStackNonSplit = Symtab->find("__morestack_non_split"); |
| 944 | if (!MoreStackNonSplit) { | |
| 945 | error("Mixing split-stack objects requires a definition of " | |
| 946 | "__morestack_non_split"); | |
| 947 | return; | |
| 948 | } | |
| 851 | 949 | |
| 852 | 950 | // Sort both collections to compare addresses efficiently. |
| 853 | llvm::sort(MorestackCalls.begin(), MorestackCalls.end(), | |
| 854 | [](const Relocation *L, const Relocation *R) { | |
| 855 | return L->Offset < R->Offset; | |
| 856 | }); | |
| 951 | llvm::sort(MorestackCalls, [](const Relocation *L, const Relocation *R) { | |
| 952 | return L->Offset < R->Offset; | |
| 953 | }); | |
| 857 | 954 | std::vector<Defined *> Functions(Prologues.begin(), Prologues.end()); |
| 858 | llvm::sort( | |
| 859 | Functions.begin(), Functions.end(), | |
| 860 | [](const Defined *L, const Defined *R) { return L->Value < R->Value; }); | |
| 955 | llvm::sort(Functions, [](const Defined *L, const Defined *R) { | |
| 956 | return L->Value < R->Value; | |
| 957 | }); | |
| 861 | 958 | |
| 862 | 959 | auto It = MorestackCalls.begin(); |
| 863 | 960 | for (Defined *F : Functions) { |
| ... | ... | @@ -872,8 +969,8 @@ static void switchMorestackCallsToMorestackNonSplit( |
| 872 | 969 | } |
| 873 | 970 | } |
| 874 | 971 | |
| 875 | static bool enclosingPrologueAdjusted(uint64_t Offset, | |
| 876 | const DenseSet<Defined *> &Prologues) { | |
| 972 | static bool enclosingPrologueAttempted(uint64_t Offset, | |
| 973 | const DenseSet<Defined *> &Prologues) { | |
| 877 | 974 | for (Defined *F : Prologues) |
| 878 | 975 | if (F->Value <= Offset && Offset < F->Value + F->Size) |
| 879 | 976 | return true; |
| ... | ... | @@ -889,7 +986,7 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf, |
| 889 | 986 | uint8_t *End) { |
| 890 | 987 | if (!getFile<ELFT>()->SplitStack) |
| 891 | 988 | return; |
| 892 | DenseSet<Defined *> AdjustedPrologues; | |
| 989 | DenseSet<Defined *> Prologues; | |
| 893 | 990 | std::vector<Relocation *> MorestackCalls; |
| 894 | 991 | |
| 895 | 992 | for (Relocation &Rel : Relocations) { |
| ... | ... | @@ -898,15 +995,9 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf, |
| 898 | 995 | if (Rel.Sym->isLocal()) |
| 899 | 996 | continue; |
| 900 | 997 | |
| 901 | Defined *D = dyn_cast<Defined>(Rel.Sym); | |
| 902 | // A reference to an undefined symbol was an error, and should not | |
| 903 | // have gotten to this point. | |
| 904 | if (!D) | |
| 905 | continue; | |
| 906 | ||
| 907 | 998 | // Ignore calls into the split-stack api. |
| 908 | if (D->getName().startswith("__morestack")) { | |
| 909 | if (D->getName().equals("__morestack")) | |
| 999 | if (Rel.Sym->getName().startswith("__morestack")) { | |
| 1000 | if (Rel.Sym->getName().equals("__morestack")) | |
| 910 | 1001 | MorestackCalls.push_back(&Rel); |
| 911 | 1002 | continue; |
| 912 | 1003 | } |
| ... | ... | @@ -914,24 +1005,36 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf, |
| 914 | 1005 | // A relocation to non-function isn't relevant. Sometimes |
| 915 | 1006 | // __morestack is not marked as a function, so this check comes |
| 916 | 1007 | // after the name check. |
| 917 | if (D->Type != STT_FUNC) | |
| 1008 | if (Rel.Sym->Type != STT_FUNC) | |
| 918 | 1009 | continue; |
| 919 | 1010 | |
| 920 | if (enclosingPrologueAdjusted(Rel.Offset, AdjustedPrologues)) | |
| 1011 | // If the callee's-file was compiled with split stack, nothing to do. In | |
| 1012 | // this context, a "Defined" symbol is one "defined by the binary currently | |
| 1013 | // being produced". So an "undefined" symbol might be provided by a shared | |
| 1014 | // library. It is not possible to tell how such symbols were compiled, so be | |
| 1015 | // conservative. | |
| 1016 | if (Defined *D = dyn_cast<Defined>(Rel.Sym)) | |
| 1017 | if (InputSection *IS = cast_or_null<InputSection>(D->Section)) | |
| 1018 | if (!IS || !IS->getFile<ELFT>() || IS->getFile<ELFT>()->SplitStack) | |
| 1019 | continue; | |
| 1020 | ||
| 1021 | if (enclosingPrologueAttempted(Rel.Offset, Prologues)) | |
| 921 | 1022 | continue; |
| 922 | 1023 | |
| 923 | 1024 | if (Defined *F = getEnclosingFunction<ELFT>(Rel.Offset)) { |
| 924 | if (Target->adjustPrologueForCrossSplitStack(Buf + F->Value, End)) { | |
| 925 | AdjustedPrologues.insert(F); | |
| 1025 | Prologues.insert(F); | |
| 1026 | if (Target->adjustPrologueForCrossSplitStack(Buf + getOffset(F->Value), | |
| 1027 | End, F->StOther)) | |
| 926 | 1028 | continue; |
| 927 | } | |
| 1029 | if (!getFile<ELFT>()->SomeNoSplitStack) | |
| 1030 | error(lld::toString(this) + ": " + F->getName() + | |
| 1031 | " (with -fsplit-stack) calls " + Rel.Sym->getName() + | |
| 1032 | " (without -fsplit-stack), but couldn't adjust its prologue"); | |
| 928 | 1033 | } |
| 929 | if (!getFile<ELFT>()->SomeNoSplitStack) | |
| 930 | error("function call at " + getErrorLocation(Buf + Rel.Offset) + | |
| 931 | "crosses a split-stack boundary, but unable " + | |
| 932 | "to adjust the enclosing function's prologue"); | |
| 933 | 1034 | } |
| 934 | switchMorestackCallsToMorestackNonSplit(AdjustedPrologues, MorestackCalls); | |
| 1035 | ||
| 1036 | if (Target->NeedsMoreStackNonSplit) | |
| 1037 | switchMorestackCallsToMorestackNonSplit(Prologues, MorestackCalls); | |
| 935 | 1038 | } |
| 936 | 1039 | |
| 937 | 1040 | template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { |
| ... | ... | @@ -960,10 +1063,23 @@ template <class ELFT> void InputSection::writeTo(uint8_t *Buf) { |
| 960 | 1063 | return; |
| 961 | 1064 | } |
| 962 | 1065 | |
| 1066 | // If this is a compressed section, uncompress section contents directly | |
| 1067 | // to the buffer. | |
| 1068 | if (UncompressedSize >= 0 && !UncompressedBuf) { | |
| 1069 | size_t Size = UncompressedSize; | |
| 1070 | if (Error E = zlib::uncompress(toStringRef(RawData), | |
| 1071 | (char *)(Buf + OutSecOff), Size)) | |
| 1072 | fatal(toString(this) + | |
| 1073 | ": uncompress failed: " + llvm::toString(std::move(E))); | |
| 1074 | uint8_t *BufEnd = Buf + OutSecOff + Size; | |
| 1075 | relocate<ELFT>(Buf, BufEnd); | |
| 1076 | return; | |
| 1077 | } | |
| 1078 | ||
| 963 | 1079 | // Copy section contents from source object file to output file |
| 964 | 1080 | // and then apply relocations. |
| 965 | memcpy(Buf + OutSecOff, Data.data(), Data.size()); | |
| 966 | uint8_t *BufEnd = Buf + OutSecOff + Data.size(); | |
| 1081 | memcpy(Buf + OutSecOff, data().data(), data().size()); | |
| 1082 | uint8_t *BufEnd = Buf + OutSecOff + data().size(); | |
| 967 | 1083 | relocate<ELFT>(Buf, BufEnd); |
| 968 | 1084 | } |
| 969 | 1085 | |
| ... | ... | @@ -1014,7 +1130,7 @@ template <class ELFT> void EhInputSection::split() { |
| 1014 | 1130 | template <class ELFT, class RelTy> |
| 1015 | 1131 | void EhInputSection::split(ArrayRef<RelTy> Rels) { |
| 1016 | 1132 | unsigned RelI = 0; |
| 1017 | for (size_t Off = 0, End = Data.size(); Off != End;) { | |
| 1133 | for (size_t Off = 0, End = data().size(); Off != End;) { | |
| 1018 | 1134 | size_t Size = readEhRecordSize(this, Off); |
| 1019 | 1135 | Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI)); |
| 1020 | 1136 | // The empty record is the end marker. |
| ... | ... | @@ -1094,65 +1210,32 @@ void MergeInputSection::splitIntoPieces() { |
| 1094 | 1210 | assert(Pieces.empty()); |
| 1095 | 1211 | |
| 1096 | 1212 | if (Flags & SHF_STRINGS) |
| 1097 | splitStrings(Data, Entsize); | |
| 1213 | splitStrings(data(), Entsize); | |
| 1098 | 1214 | else |
| 1099 | splitNonStrings(Data, Entsize); | |
| 1100 | ||
| 1101 | OffsetMap.reserve(Pieces.size()); | |
| 1102 | for (size_t I = 0, E = Pieces.size(); I != E; ++I) | |
| 1103 | OffsetMap[Pieces[I].InputOff] = I; | |
| 1104 | } | |
| 1105 | ||
| 1106 | template <class It, class T, class Compare> | |
| 1107 | static It fastUpperBound(It First, It Last, const T &Value, Compare Comp) { | |
| 1108 | size_t Size = std::distance(First, Last); | |
| 1109 | assert(Size != 0); | |
| 1110 | while (Size != 1) { | |
| 1111 | size_t H = Size / 2; | |
| 1112 | const It MI = First + H; | |
| 1113 | Size -= H; | |
| 1114 | First = Comp(Value, *MI) ? First : First + H; | |
| 1115 | } | |
| 1116 | return Comp(Value, *First) ? First : First + 1; | |
| 1117 | } | |
| 1118 | ||
| 1119 | // Do binary search to get a section piece at a given input offset. | |
| 1120 | static SectionPiece *findSectionPiece(MergeInputSection *Sec, uint64_t Offset) { | |
| 1121 | if (Sec->Data.size() <= Offset) | |
| 1122 | fatal(toString(Sec) + ": entry is past the end of the section"); | |
| 1123 | ||
| 1124 | // Find the element this offset points to. | |
| 1125 | auto I = fastUpperBound( | |
| 1126 | Sec->Pieces.begin(), Sec->Pieces.end(), Offset, | |
| 1127 | [](const uint64_t &A, const SectionPiece &B) { return A < B.InputOff; }); | |
| 1128 | --I; | |
| 1129 | return &*I; | |
| 1215 | splitNonStrings(data(), Entsize); | |
| 1130 | 1216 | } |
| 1131 | 1217 | |
| 1132 | 1218 | SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) { |
| 1133 | // Find a piece starting at a given offset. | |
| 1134 | auto It = OffsetMap.find(Offset); | |
| 1135 | if (It != OffsetMap.end()) | |
| 1136 | return &Pieces[It->second]; | |
| 1219 | if (this->data().size() <= Offset) | |
| 1220 | fatal(toString(this) + ": offset is outside the section"); | |
| 1137 | 1221 | |
| 1138 | 1222 | // If Offset is not at beginning of a section piece, it is not in the map. |
| 1139 | // In that case we need to search from the original section piece vector. | |
| 1140 | return findSectionPiece(this, Offset); | |
| 1223 | // In that case we need to do a binary search of the original section piece vector. | |
| 1224 | auto It2 = | |
| 1225 | llvm::upper_bound(Pieces, Offset, [](uint64_t Offset, SectionPiece P) { | |
| 1226 | return Offset < P.InputOff; | |
| 1227 | }); | |
| 1228 | return &It2[-1]; | |
| 1141 | 1229 | } |
| 1142 | 1230 | |
| 1143 | 1231 | // Returns the offset in an output section for a given input offset. |
| 1144 | 1232 | // Because contents of a mergeable section is not contiguous in output, |
| 1145 | 1233 | // it is not just an addition to a base output offset. |
| 1146 | 1234 | uint64_t MergeInputSection::getParentOffset(uint64_t Offset) const { |
| 1147 | // Find a string starting at a given offset. | |
| 1148 | auto It = OffsetMap.find(Offset); | |
| 1149 | if (It != OffsetMap.end()) | |
| 1150 | return Pieces[It->second].OutputOff; | |
| 1151 | ||
| 1152 | 1235 | // If Offset is not at beginning of a section piece, it is not in the map. |
| 1153 | 1236 | // In that case we need to search from the original section piece vector. |
| 1154 | 1237 | const SectionPiece &Piece = |
| 1155 | *findSectionPiece(const_cast<MergeInputSection *>(this), Offset); | |
| 1238 | *(const_cast<MergeInputSection *>(this)->getSectionPiece (Offset)); | |
| 1156 | 1239 | uint64_t Addend = Offset - Piece.InputOff; |
| 1157 | 1240 | return Piece.OutputOff + Addend; |
| 1158 | 1241 | } |
deps/lld/ELF/InputSection.h+23-15| ... | ... | @@ -115,7 +115,12 @@ public: |
| 115 | 115 | return cast_or_null<ObjFile<ELFT>>(File); |
| 116 | 116 | } |
| 117 | 117 | |
| 118 | ArrayRef<uint8_t> Data; | |
| 118 | ArrayRef<uint8_t> data() const { | |
| 119 | if (UncompressedSize >= 0 && !UncompressedBuf) | |
| 120 | uncompress(); | |
| 121 | return RawData; | |
| 122 | } | |
| 123 | ||
| 119 | 124 | uint64_t getOffsetInFile() const; |
| 120 | 125 | |
| 121 | 126 | // True if this section has already been placed to a linker script |
| ... | ... | @@ -169,11 +174,6 @@ public: |
| 169 | 174 | template <class ELFT> |
| 170 | 175 | Defined *getEnclosingFunction(uint64_t Offset); |
| 171 | 176 | |
| 172 | // Compilers emit zlib-compressed debug sections if the -gz option | |
| 173 | // is given. This function checks if this section is compressed, and | |
| 174 | // if so, decompress in memory. | |
| 175 | void maybeDecompress(); | |
| 176 | ||
| 177 | 177 | // Returns a source location string. Used to construct an error message. |
| 178 | 178 | template <class ELFT> std::string getLocation(uint64_t Offset); |
| 179 | 179 | std::string getSrcMsg(const Symbol &Sym, uint64_t Offset); |
| ... | ... | @@ -200,15 +200,21 @@ public: |
| 200 | 200 | |
| 201 | 201 | |
| 202 | 202 | template <typename T> llvm::ArrayRef<T> getDataAs() const { |
| 203 | size_t S = Data.size(); | |
| 203 | size_t S = data().size(); | |
| 204 | 204 | assert(S % sizeof(T) == 0); |
| 205 | return llvm::makeArrayRef<T>((const T *)Data.data(), S / sizeof(T)); | |
| 205 | return llvm::makeArrayRef<T>((const T *)data().data(), S / sizeof(T)); | |
| 206 | 206 | } |
| 207 | 207 | |
| 208 | private: | |
| 209 | // A pointer that owns decompressed data if a section is compressed by zlib. | |
| 208 | protected: | |
| 209 | void parseCompressedHeader(); | |
| 210 | void uncompress() const; | |
| 211 | ||
| 212 | mutable ArrayRef<uint8_t> RawData; | |
| 213 | ||
| 214 | // A pointer that owns uncompressed data if a section is compressed by zlib. | |
| 210 | 215 | // Since the feature is not used often, this is usually a nullptr. |
| 211 | std::unique_ptr<char[]> DecompressBuf; | |
| 216 | mutable std::unique_ptr<char[]> UncompressedBuf; | |
| 217 | int64_t UncompressedSize = -1; | |
| 212 | 218 | }; |
| 213 | 219 | |
| 214 | 220 | // SectionPiece represents a piece of splittable section contents. |
| ... | ... | @@ -247,7 +253,6 @@ public: |
| 247 | 253 | // Splittable sections are handled as a sequence of data |
| 248 | 254 | // rather than a single large blob of data. |
| 249 | 255 | std::vector<SectionPiece> Pieces; |
| 250 | llvm::DenseMap<uint32_t, uint32_t> OffsetMap; | |
| 251 | 256 | |
| 252 | 257 | // Returns I'th piece's data. This function is very hot when |
| 253 | 258 | // string merging is enabled, so we want to inline. |
| ... | ... | @@ -255,8 +260,8 @@ public: |
| 255 | 260 | llvm::CachedHashStringRef getData(size_t I) const { |
| 256 | 261 | size_t Begin = Pieces[I].InputOff; |
| 257 | 262 | size_t End = |
| 258 | (Pieces.size() - 1 == I) ? Data.size() : Pieces[I + 1].InputOff; | |
| 259 | return {toStringRef(Data.slice(Begin, End - Begin)), Pieces[I].Hash}; | |
| 263 | (Pieces.size() - 1 == I) ? data().size() : Pieces[I + 1].InputOff; | |
| 264 | return {toStringRef(data().slice(Begin, End - Begin)), Pieces[I].Hash}; | |
| 260 | 265 | } |
| 261 | 266 | |
| 262 | 267 | // Returns the SectionPiece at a given input section offset. |
| ... | ... | @@ -277,7 +282,9 @@ struct EhSectionPiece { |
| 277 | 282 | unsigned FirstRelocation) |
| 278 | 283 | : InputOff(Off), Sec(Sec), Size(Size), FirstRelocation(FirstRelocation) {} |
| 279 | 284 | |
| 280 | ArrayRef<uint8_t> data() { return {Sec->Data.data() + this->InputOff, Size}; } | |
| 285 | ArrayRef<uint8_t> data() { | |
| 286 | return {Sec->data().data() + this->InputOff, Size}; | |
| 287 | } | |
| 281 | 288 | |
| 282 | 289 | size_t InputOff; |
| 283 | 290 | ssize_t OutputOff = -1; |
| ... | ... | @@ -353,6 +360,7 @@ private: |
| 353 | 360 | |
| 354 | 361 | // The list of all input sections. |
| 355 | 362 | extern std::vector<InputSectionBase *> InputSections; |
| 363 | ||
| 356 | 364 | } // namespace elf |
| 357 | 365 | |
| 358 | 366 | std::string toString(const elf::InputSectionBase *); |
deps/lld/ELF/LTO.cpp+25-23| ... | ... | @@ -67,9 +67,10 @@ static std::string getThinLTOOutputFile(StringRef ModulePath) { |
| 67 | 67 | static lto::Config createConfig() { |
| 68 | 68 | lto::Config C; |
| 69 | 69 | |
| 70 | // LLD supports the new relocations. | |
| 70 | // LLD supports the new relocations and address-significance tables. | |
| 71 | 71 | C.Options = InitTargetOptionsFromCodeGenFlags(); |
| 72 | 72 | C.Options.RelaxELFRelocations = true; |
| 73 | C.Options.EmitAddrsig = true; | |
| 73 | 74 | |
| 74 | 75 | // Always emit a section per function/datum with LTO. |
| 75 | 76 | C.Options.FunctionSections = true; |
| ... | ... | @@ -87,6 +88,7 @@ static lto::Config createConfig() { |
| 87 | 88 | C.DiagHandler = diagnosticHandler; |
| 88 | 89 | C.OptLevel = Config->LTOO; |
| 89 | 90 | C.CPU = GetCPUStr(); |
| 91 | C.MAttrs = GetMAttrs(); | |
| 90 | 92 | |
| 91 | 93 | // Set up a custom pipeline if we've been asked to. |
| 92 | 94 | C.OptPipeline = Config->LTONewPmPasses; |
| ... | ... | @@ -101,6 +103,14 @@ static lto::Config createConfig() { |
| 101 | 103 | C.DebugPassManager = Config->LTODebugPassManager; |
| 102 | 104 | C.DwoDir = Config->DwoDir; |
| 103 | 105 | |
| 106 | if (Config->EmitLLVM) { | |
| 107 | C.PostInternalizeModuleHook = [](size_t Task, const Module &M) { | |
| 108 | if (std::unique_ptr<raw_fd_ostream> OS = openFile(Config->OutputFile)) | |
| 109 | WriteBitcodeToFile(M, *OS, false); | |
| 110 | return false; | |
| 111 | }; | |
| 112 | } | |
| 113 | ||
| 104 | 114 | if (Config->SaveTemps) |
| 105 | 115 | checkError(C.addSaveTemps(Config->OutputFile.str() + ".", |
| 106 | 116 | /*UseInputModulePath*/ true)); |
| ... | ... | @@ -108,18 +118,14 @@ static lto::Config createConfig() { |
| 108 | 118 | } |
| 109 | 119 | |
| 110 | 120 | BitcodeCompiler::BitcodeCompiler() { |
| 121 | // Initialize IndexFile. | |
| 122 | if (!Config->ThinLTOIndexOnlyArg.empty()) | |
| 123 | IndexFile = openFile(Config->ThinLTOIndexOnlyArg); | |
| 124 | ||
| 111 | 125 | // Initialize LTOObj. |
| 112 | 126 | lto::ThinBackend Backend; |
| 113 | ||
| 114 | 127 | if (Config->ThinLTOIndexOnly) { |
| 115 | StringRef Path = Config->ThinLTOIndexOnlyArg; | |
| 116 | if (!Path.empty()) | |
| 117 | IndexFile = openFile(Path); | |
| 118 | ||
| 119 | auto OnIndexWrite = [&](const std::string &Identifier) { | |
| 120 | ObjectToIndexFileState[Identifier] = true; | |
| 121 | }; | |
| 122 | ||
| 128 | auto OnIndexWrite = [&](StringRef S) { ThinIndices.erase(S); }; | |
| 123 | 129 | Backend = lto::createWriteIndexesThinBackend( |
| 124 | 130 | Config->ThinLTOPrefixReplace.first, Config->ThinLTOPrefixReplace.second, |
| 125 | 131 | Config->ThinLTOEmitImportsFiles, IndexFile.get(), OnIndexWrite); |
| ... | ... | @@ -132,10 +138,10 @@ BitcodeCompiler::BitcodeCompiler() { |
| 132 | 138 | |
| 133 | 139 | // Initialize UsedStartStop. |
| 134 | 140 | for (Symbol *Sym : Symtab->getSymbols()) { |
| 135 | StringRef Name = Sym->getName(); | |
| 141 | StringRef S = Sym->getName(); | |
| 136 | 142 | for (StringRef Prefix : {"__start_", "__stop_"}) |
| 137 | if (Name.startswith(Prefix)) | |
| 138 | UsedStartStop.insert(Name.substr(Prefix.size())); | |
| 143 | if (S.startswith(Prefix)) | |
| 144 | UsedStartStop.insert(S.substr(Prefix.size())); | |
| 139 | 145 | } |
| 140 | 146 | } |
| 141 | 147 | |
| ... | ... | @@ -151,7 +157,7 @@ void BitcodeCompiler::add(BitcodeFile &F) { |
| 151 | 157 | bool IsExec = !Config->Shared && !Config->Relocatable; |
| 152 | 158 | |
| 153 | 159 | if (Config->ThinLTOIndexOnly) |
| 154 | ObjectToIndexFileState.insert({Obj.getName(), false}); | |
| 160 | ThinIndices.insert(Obj.getName()); | |
| 155 | 161 | |
| 156 | 162 | ArrayRef<Symbol *> Syms = F.getSymbols(); |
| 157 | 163 | ArrayRef<lto::InputFile::Symbol> ObjSyms = Obj.symbols(); |
| ... | ... | @@ -240,15 +246,11 @@ std::vector<InputFile *> BitcodeCompiler::compile() { |
| 240 | 246 | Cache)); |
| 241 | 247 | |
| 242 | 248 | // Emit empty index files for non-indexed files |
| 243 | if (Config->ThinLTOIndexOnly) { | |
| 244 | for (auto &Identifier : ObjectToIndexFileState) | |
| 245 | if (!Identifier.getValue()) { | |
| 246 | std::string Path = getThinLTOOutputFile(Identifier.getKey()); | |
| 247 | openFile(Path + ".thinlto.bc"); | |
| 248 | ||
| 249 | if (Config->ThinLTOEmitImportsFiles) | |
| 250 | openFile(Path + ".imports"); | |
| 251 | } | |
| 249 | for (StringRef S : ThinIndices) { | |
| 250 | std::string Path = getThinLTOOutputFile(S); | |
| 251 | openFile(Path + ".thinlto.bc"); | |
| 252 | if (Config->ThinLTOEmitImportsFiles) | |
| 253 | openFile(Path + ".imports"); | |
| 252 | 254 | } |
| 253 | 255 | |
| 254 | 256 | // If LazyObjFile has not been added to link, emit empty index files. |
deps/lld/ELF/LTO.h+1-1| ... | ... | @@ -55,7 +55,7 @@ private: |
| 55 | 55 | std::vector<std::unique_ptr<MemoryBuffer>> Files; |
| 56 | 56 | llvm::DenseSet<StringRef> UsedStartStop; |
| 57 | 57 | std::unique_ptr<llvm::raw_fd_ostream> IndexFile; |
| 58 | llvm::StringMap<bool> ObjectToIndexFileState; | |
| 58 | llvm::DenseSet<StringRef> ThinIndices; | |
| 59 | 59 | }; |
| 60 | 60 | } // namespace elf |
| 61 | 61 | } // namespace lld |
deps/lld/ELF/LinkerScript.cpp+10-23| ... | ... | @@ -169,7 +169,7 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) { |
| 169 | 169 | // Define a symbol. |
| 170 | 170 | Symbol *Sym; |
| 171 | 171 | uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; |
| 172 | std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility, | |
| 172 | std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, Visibility, | |
| 173 | 173 | /*CanOmitFromDynSym*/ false, |
| 174 | 174 | /*File*/ nullptr); |
| 175 | 175 | ExprValue Value = Cmd->Expression(); |
| ... | ... | @@ -202,13 +202,14 @@ static void declareSymbol(SymbolAssignment *Cmd) { |
| 202 | 202 | // We can't calculate final value right now. |
| 203 | 203 | Symbol *Sym; |
| 204 | 204 | uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT; |
| 205 | std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, /*Type*/ 0, Visibility, | |
| 205 | std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, Visibility, | |
| 206 | 206 | /*CanOmitFromDynSym*/ false, |
| 207 | 207 | /*File*/ nullptr); |
| 208 | 208 | replaceSymbol<Defined>(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility, |
| 209 | 209 | STT_NOTYPE, 0, 0, nullptr); |
| 210 | 210 | Cmd->Sym = cast<Defined>(Sym); |
| 211 | 211 | Cmd->Provide = false; |
| 212 | Sym->ScriptDefined = true; | |
| 212 | 213 | } |
| 213 | 214 | |
| 214 | 215 | // This method is used to handle INSERT AFTER statement. Here we rebuild |
| ... | ... | @@ -414,18 +415,16 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) { |
| 414 | 415 | |
| 415 | 416 | void LinkerScript::discard(ArrayRef<InputSection *> V) { |
| 416 | 417 | for (InputSection *S : V) { |
| 417 | if (S == InX::ShStrTab || S == InX::Dynamic || S == InX::DynSymTab || | |
| 418 | S == InX::DynStrTab || S == InX::RelaPlt || S == InX::RelaDyn || | |
| 419 | S == InX::RelrDyn) | |
| 418 | if (S == In.ShStrTab || S == In.RelaDyn || S == In.RelrDyn) | |
| 420 | 419 | error("discarding " + S->Name + " section is not allowed"); |
| 421 | 420 | |
| 422 | 421 | // You can discard .hash and .gnu.hash sections by linker scripts. Since |
| 423 | 422 | // they are synthesized sections, we need to handle them differently than |
| 424 | 423 | // other regular sections. |
| 425 | if (S == InX::GnuHashTab) | |
| 426 | InX::GnuHashTab = nullptr; | |
| 427 | if (S == InX::HashTab) | |
| 428 | InX::HashTab = nullptr; | |
| 424 | if (S == In.GnuHashTab) | |
| 425 | In.GnuHashTab = nullptr; | |
| 426 | if (S == In.HashTab) | |
| 427 | In.HashTab = nullptr; | |
| 429 | 428 | |
| 430 | 429 | S->Assigned = false; |
| 431 | 430 | S->Live = false; |
| ... | ... | @@ -701,6 +700,7 @@ uint64_t LinkerScript::advance(uint64_t Size, unsigned Alignment) { |
| 701 | 700 | } |
| 702 | 701 | |
| 703 | 702 | void LinkerScript::output(InputSection *S) { |
| 703 | assert(Ctx->OutSec == S->getParent()); | |
| 704 | 704 | uint64_t Before = advance(0, 1); |
| 705 | 705 | uint64_t Pos = advance(S->getSize(), S->Alignment); |
| 706 | 706 | S->OutSecOff = Pos - S->getSize() - Ctx->OutSec->Addr; |
| ... | ... | @@ -816,21 +816,8 @@ void LinkerScript::assignOffsets(OutputSection *Sec) { |
| 816 | 816 | // Handle a single input section description command. |
| 817 | 817 | // It calculates and assigns the offsets for each section and also |
| 818 | 818 | // updates the output section size. |
| 819 | auto *Cmd = cast<InputSectionDescription>(Base); | |
| 820 | for (InputSection *Sec : Cmd->Sections) { | |
| 821 | // We tentatively added all synthetic sections at the beginning and | |
| 822 | // removed empty ones afterwards (because there is no way to know | |
| 823 | // whether they were going be empty or not other than actually running | |
| 824 | // linker scripts.) We need to ignore remains of empty sections. | |
| 825 | if (auto *S = dyn_cast<SyntheticSection>(Sec)) | |
| 826 | if (S->empty()) | |
| 827 | continue; | |
| 828 | ||
| 829 | if (!Sec->Live) | |
| 830 | continue; | |
| 831 | assert(Ctx->OutSec == Sec->getParent()); | |
| 819 | for (InputSection *Sec : cast<InputSectionDescription>(Base)->Sections) | |
| 832 | 820 | output(Sec); |
| 833 | } | |
| 834 | 821 | } |
| 835 | 822 | } |
| 836 | 823 |
deps/lld/ELF/LinkerScript.h+7-5| ... | ... | @@ -30,12 +30,13 @@ namespace lld { |
| 30 | 30 | namespace elf { |
| 31 | 31 | |
| 32 | 32 | class Defined; |
| 33 | class Symbol; | |
| 34 | class InputSectionBase; | |
| 35 | 33 | class InputSection; |
| 36 | class OutputSection; | |
| 37 | 34 | class InputSectionBase; |
| 35 | class InputSectionBase; | |
| 36 | class OutputSection; | |
| 38 | 37 | class SectionBase; |
| 38 | class Symbol; | |
| 39 | class ThunkSection; | |
| 39 | 40 | |
| 40 | 41 | // This represents an r-value in the linker script. |
| 41 | 42 | struct ExprValue { |
| ... | ... | @@ -145,7 +146,9 @@ struct MemoryRegion { |
| 145 | 146 | // Also it may be surrounded with SORT() command, so contains sorting rules. |
| 146 | 147 | struct SectionPattern { |
| 147 | 148 | SectionPattern(StringMatcher &&Pat1, StringMatcher &&Pat2) |
| 148 | : ExcludedFilePat(Pat1), SectionPat(Pat2) {} | |
| 149 | : ExcludedFilePat(Pat1), SectionPat(Pat2), | |
| 150 | SortOuter(SortSectionPolicy::Default), | |
| 151 | SortInner(SortSectionPolicy::Default) {} | |
| 149 | 152 | |
| 150 | 153 | StringMatcher ExcludedFilePat; |
| 151 | 154 | StringMatcher SectionPat; |
| ... | ... | @@ -153,7 +156,6 @@ struct SectionPattern { |
| 153 | 156 | SortSectionPolicy SortInner; |
| 154 | 157 | }; |
| 155 | 158 | |
| 156 | class ThunkSection; | |
| 157 | 159 | struct InputSectionDescription : BaseCommand { |
| 158 | 160 | InputSectionDescription(StringRef FilePattern) |
| 159 | 161 | : BaseCommand(InputSectionKind), FilePat(FilePattern) {} |
deps/lld/ELF/MapFile.cpp+6-5| ... | ... | @@ -126,7 +126,7 @@ static void printEhFrame(raw_ostream &OS, OutputSection *OSec) { |
| 126 | 126 | }; |
| 127 | 127 | |
| 128 | 128 | // Gather section pieces. |
| 129 | for (const CieRecord *Rec : InX::EhFrame->getCieRecords()) { | |
| 129 | for (const CieRecord *Rec : In.EhFrame->getCieRecords()) { | |
| 130 | 130 | Add(*Rec->Cie); |
| 131 | 131 | for (const EhSectionPiece *Fde : Rec->Fdes) |
| 132 | 132 | Add(*Fde); |
| ... | ... | @@ -163,17 +163,18 @@ void elf::writeMapFile() { |
| 163 | 163 | OS << right_justify("VMA", W) << ' ' << right_justify("LMA", W) |
| 164 | 164 | << " Size Align Out In Symbol\n"; |
| 165 | 165 | |
| 166 | OutputSection* OSec = nullptr; | |
| 166 | 167 | for (BaseCommand *Base : Script->SectionCommands) { |
| 167 | 168 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) { |
| 168 | 169 | if (Cmd->Provide && !Cmd->Sym) |
| 169 | 170 | continue; |
| 170 | //FIXME: calculate and print LMA. | |
| 171 | writeHeader(OS, Cmd->Addr, 0, Cmd->Size, 1); | |
| 171 | uint64_t LMA = OSec ? OSec->getLMA() + Cmd->Addr - OSec->getVA(0) : 0; | |
| 172 | writeHeader(OS, Cmd->Addr, LMA, Cmd->Size, 1); | |
| 172 | 173 | OS << Cmd->CommandString << '\n'; |
| 173 | 174 | continue; |
| 174 | 175 | } |
| 175 | 176 | |
| 176 | auto *OSec = cast<OutputSection>(Base); | |
| 177 | OSec = cast<OutputSection>(Base); | |
| 177 | 178 | writeHeader(OS, OSec->Addr, OSec->getLMA(), OSec->Size, OSec->Alignment); |
| 178 | 179 | OS << OSec->Name << '\n'; |
| 179 | 180 | |
| ... | ... | @@ -181,7 +182,7 @@ void elf::writeMapFile() { |
| 181 | 182 | for (BaseCommand *Base : OSec->SectionCommands) { |
| 182 | 183 | if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) { |
| 183 | 184 | for (InputSection *IS : ISD->Sections) { |
| 184 | if (IS == InX::EhFrame) { | |
| 185 | if (IS == In.EhFrame) { | |
| 185 | 186 | printEhFrame(OS, OSec); |
| 186 | 187 | continue; |
| 187 | 188 | } |
deps/lld/ELF/MarkLive.cpp+11-4| ... | ... | @@ -45,7 +45,7 @@ using namespace lld::elf; |
| 45 | 45 | template <class ELFT> |
| 46 | 46 | static typename ELFT::uint getAddend(InputSectionBase &Sec, |
| 47 | 47 | const typename ELFT::Rel &Rel) { |
| 48 | return Target->getImplicitAddend(Sec.Data.begin() + Rel.r_offset, | |
| 48 | return Target->getImplicitAddend(Sec.data().begin() + Rel.r_offset, | |
| 49 | 49 | Rel.getType(Config->IsMips64EL)); |
| 50 | 50 | } |
| 51 | 51 | |
| ... | ... | @@ -250,9 +250,10 @@ template <class ELFT> static void doGcSections() { |
| 250 | 250 | |
| 251 | 251 | if (Sec->Flags & SHF_LINK_ORDER) |
| 252 | 252 | continue; |
| 253 | if (isReserved<ELFT>(Sec) || Script->shouldKeep(Sec)) | |
| 253 | ||
| 254 | if (isReserved<ELFT>(Sec) || Script->shouldKeep(Sec)) { | |
| 254 | 255 | Enqueue(Sec, 0); |
| 255 | else if (isValidCIdentifier(Sec->Name)) { | |
| 256 | } else if (isValidCIdentifier(Sec->Name)) { | |
| 256 | 257 | CNamedSections[Saver.save("__start_" + Sec->Name)].push_back(Sec); |
| 257 | 258 | CNamedSections[Saver.save("__stop_" + Sec->Name)].push_back(Sec); |
| 258 | 259 | } |
| ... | ... | @@ -267,10 +268,16 @@ template <class ELFT> static void doGcSections() { |
| 267 | 268 | // input sections. This function make some or all of them on |
| 268 | 269 | // so that they are emitted to the output file. |
| 269 | 270 | template <class ELFT> void elf::markLive() { |
| 270 | // If -gc-sections is missing, no sections are removed. | |
| 271 | 271 | if (!Config->GcSections) { |
| 272 | // If -gc-sections is missing, no sections are removed. | |
| 272 | 273 | for (InputSectionBase *Sec : InputSections) |
| 273 | 274 | Sec->Live = true; |
| 275 | ||
| 276 | // If a DSO defines a symbol referenced in a regular object, it is needed. | |
| 277 | for (Symbol *Sym : Symtab->getSymbols()) | |
| 278 | if (auto *S = dyn_cast<SharedSymbol>(Sym)) | |
| 279 | if (S->IsUsedInRegularObj && !S->isWeak()) | |
| 280 | S->getFile<ELFT>().IsNeeded = true; | |
| 274 | 281 | return; |
| 275 | 282 | } |
| 276 | 283 |
deps/lld/ELF/Options.td+23-1| ... | ... | @@ -42,6 +42,12 @@ defm compress_debug_sections: |
| 42 | 42 | |
| 43 | 43 | defm defsym: Eq<"defsym", "Define a symbol alias">, MetaVarName<"<symbol>=<value>">; |
| 44 | 44 | |
| 45 | defm split_stack_adjust_size | |
| 46 | : Eq<"split-stack-adjust-size", | |
| 47 | "Specify adjustment to stack size when a split-stack function calls a " | |
| 48 | "non-split-stack function">, | |
| 49 | MetaVarName<"<value>">; | |
| 50 | ||
| 45 | 51 | defm library_path: |
| 46 | 52 | Eq<"library-path", "Add a directory to the library search path">, MetaVarName<"<dir>">; |
| 47 | 53 | |
| ... | ... | @@ -68,6 +74,10 @@ defm as_needed: B<"as-needed", |
| 68 | 74 | defm call_graph_ordering_file: |
| 69 | 75 | Eq<"call-graph-ordering-file", "Layout sections to optimize the given callgraph">; |
| 70 | 76 | |
| 77 | defm call_graph_profile_sort: B<"call-graph-profile-sort", | |
| 78 | "Reorder sections with call graph profile (default)", | |
| 79 | "Do not reorder sections with call graph profile">; | |
| 80 | ||
| 71 | 81 | // -chroot doesn't have a help text because it is an internal option. |
| 72 | 82 | def chroot: Separate<["--", "-"], "chroot">; |
| 73 | 83 | |
| ... | ... | @@ -132,7 +142,7 @@ def error_unresolved_symbols: F<"error-unresolved-symbols">, |
| 132 | 142 | defm exclude_libs: Eq<"exclude-libs", "Exclude static libraries from automatic export">; |
| 133 | 143 | |
| 134 | 144 | defm execute_only: B<"execute-only", |
| 135 | "Do not mark executable sections readable", | |
| 145 | "Mark executable sections unreadable", | |
| 136 | 146 | "Mark executable sections readable (default)">; |
| 137 | 147 | |
| 138 | 148 | defm export_dynamic: B<"export-dynamic", |
| ... | ... | @@ -245,6 +255,9 @@ defm use_android_relr_tags: B<"use-android-relr-tags", |
| 245 | 255 | "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*", |
| 246 | 256 | "Use SHT_RELR / DT_RELR* tags (default)">; |
| 247 | 257 | |
| 258 | def pic_veneer: F<"pic-veneer">, | |
| 259 | HelpText<"Always generate position independent thunks (veneers)">; | |
| 260 | ||
| 248 | 261 | defm pie: B<"pie", |
| 249 | 262 | "Create a position independent executable", |
| 250 | 263 | "Do not create a position independent executable (default)">; |
| ... | ... | @@ -315,6 +328,10 @@ defm threads: B<"threads", |
| 315 | 328 | "Run the linker multi-threaded (default)", |
| 316 | 329 | "Do not run the linker multi-threaded">; |
| 317 | 330 | |
| 331 | defm toc_optimize : B<"toc-optimize", | |
| 332 | "(PowerPC64) Enable TOC related optimizations (default)", | |
| 333 | "(PowerPC64) Disable TOC related optimizations">; | |
| 334 | ||
| 318 | 335 | def trace: F<"trace">, HelpText<"Print the names of the input files">; |
| 319 | 336 | |
| 320 | 337 | defm trace_symbol: Eq<"trace-symbol", "Trace references to symbols">; |
| ... | ... | @@ -348,6 +365,10 @@ defm warn_common: B<"warn-common", |
| 348 | 365 | "Warn about duplicate common symbols", |
| 349 | 366 | "Do not warn about duplicate common symbols (default)">; |
| 350 | 367 | |
| 368 | defm warn_ifunc_textrel: B<"warn-ifunc-textrel", | |
| 369 | "Warn about using ifunc symbols with text relocations", | |
| 370 | "Do not warn about using ifunc symbols with text relocations (default)">; | |
| 371 | ||
| 351 | 372 | defm warn_symbol_ordering: B<"warn-symbol-ordering", |
| 352 | 373 | "Warn about problems with the symbol ordering file (default)", |
| 353 | 374 | "Do not warn about problems with the symbol ordering file">; |
| ... | ... | @@ -440,6 +461,7 @@ def: F<"plugin-opt=debug-pass-manager">, |
| 440 | 461 | def: F<"plugin-opt=disable-verify">, Alias<disable_verify>, HelpText<"Alias for -disable-verify">; |
| 441 | 462 | def plugin_opt_dwo_dir_eq: J<"plugin-opt=dwo_dir=">, |
| 442 | 463 | HelpText<"Directory to store .dwo files when LTO and debug fission are used">; |
| 464 | def plugin_opt_emit_llvm: F<"plugin-opt=emit-llvm">; | |
| 443 | 465 | def: J<"plugin-opt=jobs=">, Alias<thinlto_jobs>, HelpText<"Alias for -thinlto-jobs">; |
| 444 | 466 | def: J<"plugin-opt=lto-partitions=">, Alias<lto_partitions>, HelpText<"Alias for -lto-partitions">; |
| 445 | 467 | def plugin_opt_mcpu_eq: J<"plugin-opt=mcpu=">; |
deps/lld/ELF/OutputSections.cpp+14-12| ... | ... | @@ -25,6 +25,7 @@ |
| 25 | 25 | using namespace llvm; |
| 26 | 26 | using namespace llvm::dwarf; |
| 27 | 27 | using namespace llvm::object; |
| 28 | using namespace llvm::support::endian; | |
| 28 | 29 | using namespace llvm::ELF; |
| 29 | 30 | |
| 30 | 31 | using namespace lld; |
| ... | ... | @@ -32,7 +33,6 @@ using namespace lld::elf; |
| 32 | 33 | |
| 33 | 34 | uint8_t Out::First; |
| 34 | 35 | PhdrEntry *Out::TlsPhdr; |
| 35 | OutputSection *Out::DebugInfo; | |
| 36 | 36 | OutputSection *Out::ElfHeader; |
| 37 | 37 | OutputSection *Out::ProgramHeaders; |
| 38 | 38 | OutputSection *Out::PreinitArray; |
| ... | ... | @@ -171,11 +171,12 @@ void OutputSection::sort(llvm::function_ref<int(InputSectionBase *S)> Order) { |
| 171 | 171 | |
| 172 | 172 | // Fill [Buf, Buf + Size) with Filler. |
| 173 | 173 | // This is used for linker script "=fillexp" command. |
| 174 | static void fill(uint8_t *Buf, size_t Size, uint32_t Filler) { | |
| 174 | static void fill(uint8_t *Buf, size_t Size, | |
| 175 | const std::array<uint8_t, 4> &Filler) { | |
| 175 | 176 | size_t I = 0; |
| 176 | 177 | for (; I + 4 < Size; I += 4) |
| 177 | memcpy(Buf + I, &Filler, 4); | |
| 178 | memcpy(Buf + I, &Filler, Size - I); | |
| 178 | memcpy(Buf + I, Filler.data(), 4); | |
| 179 | memcpy(Buf + I, Filler.data(), Size - I); | |
| 179 | 180 | } |
| 180 | 181 | |
| 181 | 182 | // Compress section contents if this section contains debug info. |
| ... | ... | @@ -236,8 +237,9 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) { |
| 236 | 237 | |
| 237 | 238 | // Write leading padding. |
| 238 | 239 | std::vector<InputSection *> Sections = getInputSections(this); |
| 239 | uint32_t Filler = getFiller(); | |
| 240 | if (Filler) | |
| 240 | std::array<uint8_t, 4> Filler = getFiller(); | |
| 241 | bool NonZeroFiller = read32(Filler.data()) != 0; | |
| 242 | if (NonZeroFiller) | |
| 241 | 243 | fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler); |
| 242 | 244 | |
| 243 | 245 | parallelForEachN(0, Sections.size(), [&](size_t I) { |
| ... | ... | @@ -245,7 +247,7 @@ template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) { |
| 245 | 247 | IS->writeTo<ELFT>(Buf); |
| 246 | 248 | |
| 247 | 249 | // Fill gaps between sections. |
| 248 | if (Filler) { | |
| 250 | if (NonZeroFiller) { | |
| 249 | 251 | uint8_t *Start = Buf + IS->OutSecOff + IS->getSize(); |
| 250 | 252 | uint8_t *End; |
| 251 | 253 | if (I + 1 == Sections.size()) |
| ... | ... | @@ -270,13 +272,13 @@ static void finalizeShtGroup(OutputSection *OS, |
| 270 | 272 | |
| 271 | 273 | // sh_link field for SHT_GROUP sections should contain the section index of |
| 272 | 274 | // the symbol table. |
| 273 | OS->Link = InX::SymTab->getParent()->SectionIndex; | |
| 275 | OS->Link = In.SymTab->getParent()->SectionIndex; | |
| 274 | 276 | |
| 275 | 277 | // sh_info then contain index of an entry in symbol table section which |
| 276 | 278 | // provides signature of the section group. |
| 277 | 279 | ObjFile<ELFT> *Obj = Section->getFile<ELFT>(); |
| 278 | 280 | ArrayRef<Symbol *> Symbols = Obj->getSymbols(); |
| 279 | OS->Info = InX::SymTab->getSymbolIndex(Symbols[Section->Info]); | |
| 281 | OS->Info = In.SymTab->getSymbolIndex(Symbols[Section->Info]); | |
| 280 | 282 | } |
| 281 | 283 | |
| 282 | 284 | template <class ELFT> void OutputSection::finalize() { |
| ... | ... | @@ -308,7 +310,7 @@ template <class ELFT> void OutputSection::finalize() { |
| 308 | 310 | if (isa<SyntheticSection>(First)) |
| 309 | 311 | return; |
| 310 | 312 | |
| 311 | Link = InX::SymTab->getParent()->SectionIndex; | |
| 313 | Link = In.SymTab->getParent()->SectionIndex; | |
| 312 | 314 | // sh_info for SHT_REL[A] sections should contain the section header index of |
| 313 | 315 | // the section to which the relocation applies. |
| 314 | 316 | InputSectionBase *S = First->getRelocatedSection(); |
| ... | ... | @@ -406,12 +408,12 @@ void OutputSection::sortInitFini() { |
| 406 | 408 | sort([](InputSectionBase *S) { return getPriority(S->Name); }); |
| 407 | 409 | } |
| 408 | 410 | |
| 409 | uint32_t OutputSection::getFiller() { | |
| 411 | std::array<uint8_t, 4> OutputSection::getFiller() { | |
| 410 | 412 | if (Filler) |
| 411 | 413 | return *Filler; |
| 412 | 414 | if (Flags & SHF_EXECINSTR) |
| 413 | 415 | return Target->TrapInstr; |
| 414 | return 0; | |
| 416 | return {0, 0, 0, 0}; | |
| 415 | 417 | } |
| 416 | 418 | |
| 417 | 419 | template void OutputSection::writeHeaderTo<ELF32LE>(ELF32LE::Shdr *Shdr); |
deps/lld/ELF/OutputSections.h+3-3| ... | ... | @@ -17,6 +17,7 @@ |
| 17 | 17 | #include "lld/Common/LLVM.h" |
| 18 | 18 | #include "llvm/MC/StringTableBuilder.h" |
| 19 | 19 | #include "llvm/Object/ELF.h" |
| 20 | #include <array> | |
| 20 | 21 | |
| 21 | 22 | namespace lld { |
| 22 | 23 | namespace elf { |
| ... | ... | @@ -94,7 +95,7 @@ public: |
| 94 | 95 | Expr SubalignExpr; |
| 95 | 96 | std::vector<BaseCommand *> SectionCommands; |
| 96 | 97 | std::vector<StringRef> Phdrs; |
| 97 | llvm::Optional<uint32_t> Filler; | |
| 98 | llvm::Optional<std::array<uint8_t, 4>> Filler; | |
| 98 | 99 | ConstraintKind Constraint = ConstraintKind::NoConstraint; |
| 99 | 100 | std::string Location; |
| 100 | 101 | std::string MemoryRegionName; |
| ... | ... | @@ -117,7 +118,7 @@ private: |
| 117 | 118 | std::vector<uint8_t> ZDebugHeader; |
| 118 | 119 | llvm::SmallVector<char, 1> CompressedData; |
| 119 | 120 | |
| 120 | uint32_t getFiller(); | |
| 121 | std::array<uint8_t, 4> getFiller(); | |
| 121 | 122 | }; |
| 122 | 123 | |
| 123 | 124 | int getPriority(StringRef S); |
| ... | ... | @@ -130,7 +131,6 @@ std::vector<InputSection *> getInputSections(OutputSection* OS); |
| 130 | 131 | struct Out { |
| 131 | 132 | static uint8_t First; |
| 132 | 133 | static PhdrEntry *TlsPhdr; |
| 133 | static OutputSection *DebugInfo; | |
| 134 | 134 | static OutputSection *ElfHeader; |
| 135 | 135 | static OutputSection *ProgramHeaders; |
| 136 | 136 | static OutputSection *PreinitArray; |
deps/lld/ELF/Relocations.cpp+215-150| ... | ... | @@ -50,6 +50,7 @@ |
| 50 | 50 | #include "SyntheticSections.h" |
| 51 | 51 | #include "Target.h" |
| 52 | 52 | #include "Thunks.h" |
| 53 | #include "lld/Common/ErrorHandler.h" | |
| 53 | 54 | #include "lld/Common/Memory.h" |
| 54 | 55 | #include "lld/Common/Strings.h" |
| 55 | 56 | #include "llvm/ADT/SmallSet.h" |
| ... | ... | @@ -65,6 +66,14 @@ using namespace llvm::support::endian; |
| 65 | 66 | using namespace lld; |
| 66 | 67 | using namespace lld::elf; |
| 67 | 68 | |
| 69 | static Optional<std::string> getLinkerScriptLocation(const Symbol &Sym) { | |
| 70 | for (BaseCommand *Base : Script->SectionCommands) | |
| 71 | if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) | |
| 72 | if (Cmd->Sym == &Sym) | |
| 73 | return Cmd->Location; | |
| 74 | return None; | |
| 75 | } | |
| 76 | ||
| 68 | 77 | // Construct a message in the following format. |
| 69 | 78 | // |
| 70 | 79 | // >>> defined in /home/alice/src/foo.o |
| ... | ... | @@ -72,8 +81,13 @@ using namespace lld::elf; |
| 72 | 81 | // >>> /home/alice/src/bar.o:(.text+0x1) |
| 73 | 82 | static std::string getLocation(InputSectionBase &S, const Symbol &Sym, |
| 74 | 83 | uint64_t Off) { |
| 75 | std::string Msg = | |
| 76 | "\n>>> defined in " + toString(Sym.File) + "\n>>> referenced by "; | |
| 84 | std::string Msg = "\n>>> defined in "; | |
| 85 | if (Sym.File) | |
| 86 | Msg += toString(Sym.File); | |
| 87 | else if (Optional<std::string> Loc = getLinkerScriptLocation(Sym)) | |
| 88 | Msg += *Loc; | |
| 89 | ||
| 90 | Msg += "\n>>> referenced by "; | |
| 77 | 91 | std::string Src = S.getSrcMsg(Sym, Off); |
| 78 | 92 | if (!Src.empty()) |
| 79 | 93 | Msg += Src + "\n>>> "; |
| ... | ... | @@ -90,12 +104,12 @@ static unsigned handleMipsTlsRelocation(RelType Type, Symbol &Sym, |
| 90 | 104 | InputSectionBase &C, uint64_t Offset, |
| 91 | 105 | int64_t Addend, RelExpr Expr) { |
| 92 | 106 | if (Expr == R_MIPS_TLSLD) { |
| 93 | InX::MipsGot->addTlsIndex(*C.File); | |
| 107 | In.MipsGot->addTlsIndex(*C.File); | |
| 94 | 108 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 95 | 109 | return 1; |
| 96 | 110 | } |
| 97 | 111 | if (Expr == R_MIPS_TLSGD) { |
| 98 | InX::MipsGot->addDynTlsEntry(*C.File, Sym); | |
| 112 | In.MipsGot->addDynTlsEntry(*C.File, Sym); | |
| 99 | 113 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 100 | 114 | return 1; |
| 101 | 115 | } |
| ... | ... | @@ -128,17 +142,17 @@ static unsigned handleARMTlsRelocation(RelType Type, Symbol &Sym, |
| 128 | 142 | |
| 129 | 143 | auto AddTlsReloc = [&](uint64_t Off, RelType Type, Symbol *Dest, bool Dyn) { |
| 130 | 144 | if (Dyn) |
| 131 | InX::RelaDyn->addReloc(Type, InX::Got, Off, Dest); | |
| 145 | In.RelaDyn->addReloc(Type, In.Got, Off, Dest); | |
| 132 | 146 | else |
| 133 | InX::Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest}); | |
| 147 | In.Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest}); | |
| 134 | 148 | }; |
| 135 | 149 | |
| 136 | 150 | // Local Dynamic is for access to module local TLS variables, while still |
| 137 | 151 | // being suitable for being dynamically loaded via dlopen. |
| 138 | 152 | // GOT[e0] is the module index, with a special value of 0 for the current |
| 139 | 153 | // module. GOT[e1] is unused. There only needs to be one module index entry. |
| 140 | if (Expr == R_TLSLD_PC && InX::Got->addTlsIndex()) { | |
| 141 | AddTlsReloc(InX::Got->getTlsIndexOff(), Target->TlsModuleIndexRel, | |
| 154 | if (Expr == R_TLSLD_PC && In.Got->addTlsIndex()) { | |
| 155 | AddTlsReloc(In.Got->getTlsIndexOff(), Target->TlsModuleIndexRel, | |
| 142 | 156 | NeedDynId ? nullptr : &Sym, NeedDynId); |
| 143 | 157 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 144 | 158 | return 1; |
| ... | ... | @@ -148,8 +162,8 @@ static unsigned handleARMTlsRelocation(RelType Type, Symbol &Sym, |
| 148 | 162 | // the module index and offset of symbol in TLS block we can fill these in |
| 149 | 163 | // using static GOT relocations. |
| 150 | 164 | if (Expr == R_TLSGD_PC) { |
| 151 | if (InX::Got->addDynTlsEntry(Sym)) { | |
| 152 | uint64_t Off = InX::Got->getGlobalDynOffset(Sym); | |
| 165 | if (In.Got->addDynTlsEntry(Sym)) { | |
| 166 | uint64_t Off = In.Got->getGlobalDynOffset(Sym); | |
| 153 | 167 | AddTlsReloc(Off, Target->TlsModuleIndexRel, &Sym, NeedDynId); |
| 154 | 168 | AddTlsReloc(Off + Config->Wordsize, Target->TlsOffsetRel, &Sym, |
| 155 | 169 | NeedDynOff); |
| ... | ... | @@ -165,9 +179,6 @@ template <class ELFT> |
| 165 | 179 | static unsigned |
| 166 | 180 | handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, |
| 167 | 181 | typename ELFT::uint Offset, int64_t Addend, RelExpr Expr) { |
| 168 | if (!(C.Flags & SHF_ALLOC)) | |
| 169 | return 0; | |
| 170 | ||
| 171 | 182 | if (!Sym.isTls()) |
| 172 | 183 | return 0; |
| 173 | 184 | |
| ... | ... | @@ -176,12 +187,12 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, |
| 176 | 187 | if (Config->EMachine == EM_MIPS) |
| 177 | 188 | return handleMipsTlsRelocation(Type, Sym, C, Offset, Addend, Expr); |
| 178 | 189 | |
| 179 | if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL>(Expr) && | |
| 190 | if (isRelExprOneOf<R_TLSDESC, R_AARCH64_TLSDESC_PAGE, R_TLSDESC_CALL>(Expr) && | |
| 180 | 191 | Config->Shared) { |
| 181 | if (InX::Got->addDynTlsEntry(Sym)) { | |
| 182 | uint64_t Off = InX::Got->getGlobalDynOffset(Sym); | |
| 183 | InX::RelaDyn->addReloc( | |
| 184 | {Target->TlsDescRel, InX::Got, Off, !Sym.IsPreemptible, &Sym, 0}); | |
| 192 | if (In.Got->addDynTlsEntry(Sym)) { | |
| 193 | uint64_t Off = In.Got->getGlobalDynOffset(Sym); | |
| 194 | In.RelaDyn->addReloc( | |
| 195 | {Target->TlsDescRel, In.Got, Off, !Sym.IsPreemptible, &Sym, 0}); | |
| 185 | 196 | } |
| 186 | 197 | if (Expr != R_TLSDESC_CALL) |
| 187 | 198 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| ... | ... | @@ -199,9 +210,9 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, |
| 199 | 210 | } |
| 200 | 211 | if (Expr == R_TLSLD_HINT) |
| 201 | 212 | return 1; |
| 202 | if (InX::Got->addTlsIndex()) | |
| 203 | InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, InX::Got, | |
| 204 | InX::Got->getTlsIndexOff(), nullptr); | |
| 213 | if (In.Got->addTlsIndex()) | |
| 214 | In.RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got, | |
| 215 | In.Got->getTlsIndexOff(), nullptr); | |
| 205 | 216 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 206 | 217 | return 1; |
| 207 | 218 | } |
| ... | ... | @@ -223,29 +234,29 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, |
| 223 | 234 | return 1; |
| 224 | 235 | } |
| 225 | 236 | if (!Sym.isInGot()) { |
| 226 | InX::Got->addEntry(Sym); | |
| 237 | In.Got->addEntry(Sym); | |
| 227 | 238 | uint64_t Off = Sym.getGotOffset(); |
| 228 | InX::Got->Relocations.push_back({R_ABS, Target->TlsOffsetRel, Off, 0, &Sym}); | |
| 239 | In.Got->Relocations.push_back( | |
| 240 | {R_ABS, Target->TlsOffsetRel, Off, 0, &Sym}); | |
| 229 | 241 | } |
| 230 | 242 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 231 | 243 | return 1; |
| 232 | 244 | } |
| 233 | 245 | |
| 234 | if (isRelExprOneOf<R_TLSDESC, R_TLSDESC_PAGE, R_TLSDESC_CALL, R_TLSGD_GOT, | |
| 235 | R_TLSGD_GOT_FROM_END, R_TLSGD_PC>(Expr)) { | |
| 246 | if (isRelExprOneOf<R_TLSDESC, R_AARCH64_TLSDESC_PAGE, R_TLSDESC_CALL, | |
| 247 | R_TLSGD_GOT, R_TLSGD_GOT_FROM_END, R_TLSGD_PC>(Expr)) { | |
| 236 | 248 | if (Config->Shared) { |
| 237 | if (InX::Got->addDynTlsEntry(Sym)) { | |
| 238 | uint64_t Off = InX::Got->getGlobalDynOffset(Sym); | |
| 239 | InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, InX::Got, Off, &Sym); | |
| 249 | if (In.Got->addDynTlsEntry(Sym)) { | |
| 250 | uint64_t Off = In.Got->getGlobalDynOffset(Sym); | |
| 251 | In.RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got, Off, &Sym); | |
| 240 | 252 | |
| 241 | 253 | // If the symbol is preemptible we need the dynamic linker to write |
| 242 | 254 | // the offset too. |
| 243 | 255 | uint64_t OffsetOff = Off + Config->Wordsize; |
| 244 | 256 | if (Sym.IsPreemptible) |
| 245 | InX::RelaDyn->addReloc(Target->TlsOffsetRel, InX::Got, OffsetOff, | |
| 246 | &Sym); | |
| 257 | In.RelaDyn->addReloc(Target->TlsOffsetRel, In.Got, OffsetOff, &Sym); | |
| 247 | 258 | else |
| 248 | InX::Got->Relocations.push_back( | |
| 259 | In.Got->Relocations.push_back( | |
| 249 | 260 | {R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Sym}); |
| 250 | 261 | } |
| 251 | 262 | C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| ... | ... | @@ -259,9 +270,9 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, |
| 259 | 270 | {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_IE), Type, |
| 260 | 271 | Offset, Addend, &Sym}); |
| 261 | 272 | if (!Sym.isInGot()) { |
| 262 | InX::Got->addEntry(Sym); | |
| 263 | InX::RelaDyn->addReloc(Target->TlsGotRel, InX::Got, Sym.getGotOffset(), | |
| 264 | &Sym); | |
| 273 | In.Got->addEntry(Sym); | |
| 274 | In.RelaDyn->addReloc(Target->TlsGotRel, In.Got, Sym.getGotOffset(), | |
| 275 | &Sym); | |
| 265 | 276 | } |
| 266 | 277 | } else { |
| 267 | 278 | C.Relocations.push_back( |
| ... | ... | @@ -273,13 +284,14 @@ handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C, |
| 273 | 284 | |
| 274 | 285 | // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally |
| 275 | 286 | // defined. |
| 276 | if (isRelExprOneOf<R_GOT, R_GOT_FROM_END, R_GOT_PC, R_GOT_PAGE_PC>(Expr) && | |
| 287 | if (isRelExprOneOf<R_GOT, R_GOT_FROM_END, R_GOT_PC, R_AARCH64_GOT_PAGE_PC, | |
| 288 | R_GOT_OFF, R_TLSIE_HINT>(Expr) && | |
| 277 | 289 | !Config->Shared && !Sym.IsPreemptible) { |
| 278 | 290 | C.Relocations.push_back({R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Sym}); |
| 279 | 291 | return 1; |
| 280 | 292 | } |
| 281 | 293 | |
| 282 | if (Expr == R_TLSDESC_CALL) | |
| 294 | if (Expr == R_TLSIE_HINT) | |
| 283 | 295 | return 1; |
| 284 | 296 | return 0; |
| 285 | 297 | } |
| ... | ... | @@ -325,24 +337,26 @@ static bool isAbsoluteValue(const Symbol &Sym) { |
| 325 | 337 | |
| 326 | 338 | // Returns true if Expr refers a PLT entry. |
| 327 | 339 | static bool needsPlt(RelExpr Expr) { |
| 328 | return isRelExprOneOf<R_PLT_PC, R_PPC_CALL_PLT, R_PLT, R_PLT_PAGE_PC>(Expr); | |
| 340 | return isRelExprOneOf<R_PLT_PC, R_PPC_CALL_PLT, R_PLT, R_AARCH64_PLT_PAGE_PC, | |
| 341 | R_GOT_PLT, R_AARCH64_GOT_PAGE_PC_PLT>(Expr); | |
| 329 | 342 | } |
| 330 | 343 | |
| 331 | 344 | // Returns true if Expr refers a GOT entry. Note that this function |
| 332 | 345 | // returns false for TLS variables even though they need GOT, because |
| 333 | 346 | // TLS variables uses GOT differently than the regular variables. |
| 334 | 347 | static bool needsGot(RelExpr Expr) { |
| 335 | return isRelExprOneOf<R_GOT, R_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOT_OFF, | |
| 336 | R_MIPS_GOT_OFF32, R_GOT_PAGE_PC, R_GOT_PC, | |
| 337 | R_GOT_FROM_END>(Expr); | |
| 348 | return isRelExprOneOf<R_GOT, R_GOT_OFF, R_HEXAGON_GOT, R_MIPS_GOT_LOCAL_PAGE, | |
| 349 | R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_AARCH64_GOT_PAGE_PC, | |
| 350 | R_AARCH64_GOT_PAGE_PC_PLT, R_GOT_PC, R_GOT_FROM_END, | |
| 351 | R_GOT_PLT>(Expr); | |
| 338 | 352 | } |
| 339 | 353 | |
| 340 | 354 | // True if this expression is of the form Sym - X, where X is a position in the |
| 341 | 355 | // file (PC, or GOT for example). |
| 342 | 356 | static bool isRelExpr(RelExpr Expr) { |
| 343 | 357 | return isRelExprOneOf<R_PC, R_GOTREL, R_GOTREL_FROM_END, R_MIPS_GOTREL, |
| 344 | R_PPC_CALL, R_PPC_CALL_PLT, R_PAGE_PC, | |
| 345 | R_RELAX_GOT_PC>(Expr); | |
| 358 | R_PPC_CALL, R_PPC_CALL_PLT, R_AARCH64_PAGE_PC, | |
| 359 | R_AARCH64_PLT_PAGE_PC, R_RELAX_GOT_PC>(Expr); | |
| 346 | 360 | } |
| 347 | 361 | |
| 348 | 362 | // Returns true if a given relocation can be computed at link-time. |
| ... | ... | @@ -357,18 +371,19 @@ static bool isRelExpr(RelExpr Expr) { |
| 357 | 371 | static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym, |
| 358 | 372 | InputSectionBase &S, uint64_t RelOff) { |
| 359 | 373 | // These expressions always compute a constant |
| 360 | if (isRelExprOneOf< | |
| 361 | R_GOT_FROM_END, R_GOT_OFF, R_TLSLD_GOT_OFF, R_MIPS_GOT_LOCAL_PAGE, | |
| 362 | R_MIPS_GOTREL, R_MIPS_GOT_OFF, R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, | |
| 363 | R_MIPS_TLSGD, R_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, | |
| 364 | R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOT_FROM_END, | |
| 365 | R_TLSGD_PC, R_PPC_CALL_PLT, R_TLSDESC_CALL, R_TLSDESC_PAGE, R_HINT, | |
| 366 | R_TLSLD_HINT>(E)) | |
| 374 | if (isRelExprOneOf<R_GOT_FROM_END, R_GOT_OFF, R_HEXAGON_GOT, R_TLSLD_GOT_OFF, | |
| 375 | R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOTREL, R_MIPS_GOT_OFF, | |
| 376 | R_MIPS_GOT_OFF32, R_MIPS_GOT_GP_PC, R_MIPS_TLSGD, | |
| 377 | R_AARCH64_GOT_PAGE_PC, R_AARCH64_GOT_PAGE_PC_PLT, R_GOT_PC, | |
| 378 | R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT, | |
| 379 | R_TLSGD_GOT_FROM_END, R_TLSGD_PC, R_PPC_CALL_PLT, | |
| 380 | R_TLSDESC_CALL, R_AARCH64_TLSDESC_PAGE, R_HINT, | |
| 381 | R_TLSLD_HINT, R_TLSIE_HINT>(E)) | |
| 367 | 382 | return true; |
| 368 | 383 | |
| 369 | 384 | // These never do, except if the entire file is position dependent or if |
| 370 | 385 | // only the low bits are used. |
| 371 | if (E == R_GOT || E == R_PLT || E == R_TLSDESC) | |
| 386 | if (E == R_GOT || E == R_GOT_PLT || E == R_PLT || E == R_TLSDESC) | |
| 372 | 387 | return Target->usesOnlyLowPageBits(Type) || !Config->Pic; |
| 373 | 388 | |
| 374 | 389 | if (Sym.IsPreemptible) |
| ... | ... | @@ -414,10 +429,14 @@ static RelExpr toPlt(RelExpr Expr) { |
| 414 | 429 | return R_PPC_CALL_PLT; |
| 415 | 430 | case R_PC: |
| 416 | 431 | return R_PLT_PC; |
| 417 | case R_PAGE_PC: | |
| 418 | return R_PLT_PAGE_PC; | |
| 432 | case R_AARCH64_PAGE_PC: | |
| 433 | return R_AARCH64_PLT_PAGE_PC; | |
| 434 | case R_AARCH64_GOT_PAGE_PC: | |
| 435 | return R_AARCH64_GOT_PAGE_PC_PLT; | |
| 419 | 436 | case R_ABS: |
| 420 | 437 | return R_PLT; |
| 438 | case R_GOT: | |
| 439 | return R_GOT_PLT; | |
| 421 | 440 | default: |
| 422 | 441 | return Expr; |
| 423 | 442 | } |
| ... | ... | @@ -466,7 +485,7 @@ static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &SS) { |
| 466 | 485 | SmallSet<SharedSymbol *, 4> Ret; |
| 467 | 486 | for (const Elf_Sym &S : File.getGlobalELFSyms()) { |
| 468 | 487 | if (S.st_shndx == SHN_UNDEF || S.st_shndx == SHN_ABS || |
| 469 | S.st_value != SS.Value) | |
| 488 | S.getType() == STT_TLS || S.st_value != SS.Value) | |
| 470 | 489 | continue; |
| 471 | 490 | StringRef Name = check(S.getName(File.getStringTable())); |
| 472 | 491 | Symbol *Sym = Symtab->find(Name); |
| ... | ... | @@ -489,6 +508,7 @@ static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value, |
| 489 | 508 | Sym.PltIndex = Old.PltIndex; |
| 490 | 509 | Sym.GotIndex = Old.GotIndex; |
| 491 | 510 | Sym.VerdefIndex = Old.VerdefIndex; |
| 511 | Sym.PPC64BranchltIndex = Old.PPC64BranchltIndex; | |
| 492 | 512 | Sym.IsPreemptible = true; |
| 493 | 513 | Sym.ExportDynamic = true; |
| 494 | 514 | Sym.IsUsedInRegularObj = true; |
| ... | ... | @@ -549,9 +569,9 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol &SS) { |
| 549 | 569 | BssSection *Sec = make<BssSection>(IsReadOnly ? ".bss.rel.ro" : ".bss", |
| 550 | 570 | SymSize, SS.Alignment); |
| 551 | 571 | if (IsReadOnly) |
| 552 | InX::BssRelRo->getParent()->addSection(Sec); | |
| 572 | In.BssRelRo->getParent()->addSection(Sec); | |
| 553 | 573 | else |
| 554 | InX::Bss->getParent()->addSection(Sec); | |
| 574 | In.Bss->getParent()->addSection(Sec); | |
| 555 | 575 | |
| 556 | 576 | // Look through the DSO's dynamic symbol table for aliases and create a |
| 557 | 577 | // dynamic symbol for each one. This causes the copy relocation to correctly |
| ... | ... | @@ -559,7 +579,7 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol &SS) { |
| 559 | 579 | for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS)) |
| 560 | 580 | replaceWithDefined(*Sym, Sec, 0, Sym->Size); |
| 561 | 581 | |
| 562 | InX::RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS); | |
| 582 | In.RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS); | |
| 563 | 583 | } |
| 564 | 584 | |
| 565 | 585 | // MIPS has an odd notion of "paired" relocations to calculate addends. |
| ... | ... | @@ -583,7 +603,7 @@ static int64_t computeMipsAddend(const RelTy &Rel, const RelTy *End, |
| 583 | 603 | if (PairTy == R_MIPS_NONE) |
| 584 | 604 | return 0; |
| 585 | 605 | |
| 586 | const uint8_t *Buf = Sec.Data.data(); | |
| 606 | const uint8_t *Buf = Sec.data().data(); | |
| 587 | 607 | uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL); |
| 588 | 608 | |
| 589 | 609 | // To make things worse, paired relocations might not be contiguous in |
| ... | ... | @@ -611,7 +631,7 @@ static int64_t computeAddend(const RelTy &Rel, const RelTy *End, |
| 611 | 631 | if (RelTy::IsRela) { |
| 612 | 632 | Addend = getAddend<ELFT>(Rel); |
| 613 | 633 | } else { |
| 614 | const uint8_t *Buf = Sec.Data.data(); | |
| 634 | const uint8_t *Buf = Sec.data().data(); | |
| 615 | 635 | Addend = Target->getImplicitAddend(Buf + Rel.r_offset, Type); |
| 616 | 636 | } |
| 617 | 637 | |
| ... | ... | @@ -627,9 +647,6 @@ static int64_t computeAddend(const RelTy &Rel, const RelTy *End, |
| 627 | 647 | // Returns true if this function printed out an error message. |
| 628 | 648 | static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec, |
| 629 | 649 | uint64_t Offset) { |
| 630 | if (Config->UnresolvedSymbols == UnresolvedPolicy::IgnoreAll) | |
| 631 | return false; | |
| 632 | ||
| 633 | 650 | if (Sym.isLocal() || !Sym.isUndefined() || Sym.isWeak()) |
| 634 | 651 | return false; |
| 635 | 652 | |
| ... | ... | @@ -646,6 +663,10 @@ static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec, |
| 646 | 663 | Msg += Src + "\n>>> "; |
| 647 | 664 | Msg += Sec.getObjMsg(Offset); |
| 648 | 665 | |
| 666 | if (Sym.getName().startswith("_ZTV")) | |
| 667 | Msg += "\nthe vtable symbol may be undefined because the class is missing " | |
| 668 | "its key function (see https://lld.llvm.org/missingkeyfunction)"; | |
| 669 | ||
| 649 | 670 | if ((Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal) || |
| 650 | 671 | Config->NoinhibitExec) { |
| 651 | 672 | warn(Msg); |
| ... | ... | @@ -700,7 +721,7 @@ public: |
| 700 | 721 | while (I != Pieces.size() && Pieces[I].InputOff + Pieces[I].Size <= Off) |
| 701 | 722 | ++I; |
| 702 | 723 | if (I == Pieces.size()) |
| 703 | return Off; | |
| 724 | fatal(".eh_frame: relocation is not in any piece"); | |
| 704 | 725 | |
| 705 | 726 | // Pieces must be contiguous, so there must be no holes in between. |
| 706 | 727 | assert(Pieces[I].InputOff <= Off && "Relocation not in any piece"); |
| ... | ... | @@ -726,13 +747,13 @@ static void addRelativeReloc(InputSectionBase *IS, uint64_t OffsetInSec, |
| 726 | 747 | // RelrDyn sections don't support odd offsets. Also, RelrDyn sections |
| 727 | 748 | // don't store the addend values, so we must write it to the relocated |
| 728 | 749 | // address. |
| 729 | if (InX::RelrDyn && IS->Alignment >= 2 && OffsetInSec % 2 == 0) { | |
| 750 | if (In.RelrDyn && IS->Alignment >= 2 && OffsetInSec % 2 == 0) { | |
| 730 | 751 | IS->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym}); |
| 731 | InX::RelrDyn->Relocs.push_back({IS, OffsetInSec}); | |
| 752 | In.RelrDyn->Relocs.push_back({IS, OffsetInSec}); | |
| 732 | 753 | return; |
| 733 | 754 | } |
| 734 | InX::RelaDyn->addReloc(Target->RelativeRel, IS, OffsetInSec, Sym, Addend, | |
| 735 | Expr, Type); | |
| 755 | In.RelaDyn->addReloc(Target->RelativeRel, IS, OffsetInSec, Sym, Addend, Expr, | |
| 756 | Type); | |
| 736 | 757 | } |
| 737 | 758 | |
| 738 | 759 | template <class ELFT, class GotPltSection> |
| ... | ... | @@ -745,9 +766,16 @@ static void addPltEntry(PltSection *Plt, GotPltSection *GotPlt, |
| 745 | 766 | } |
| 746 | 767 | |
| 747 | 768 | template <class ELFT> static void addGotEntry(Symbol &Sym) { |
| 748 | InX::Got->addEntry(Sym); | |
| 769 | In.Got->addEntry(Sym); | |
| 770 | ||
| 771 | RelExpr Expr; | |
| 772 | if (Sym.isTls()) | |
| 773 | Expr = R_TLS; | |
| 774 | else if (Sym.isGnuIFunc()) | |
| 775 | Expr = R_PLT; | |
| 776 | else | |
| 777 | Expr = R_ABS; | |
| 749 | 778 | |
| 750 | RelExpr Expr = Sym.isTls() ? R_TLS : R_ABS; | |
| 751 | 779 | uint64_t Off = Sym.getGotOffset(); |
| 752 | 780 | |
| 753 | 781 | // If a GOT slot value can be calculated at link-time, which is now, |
| ... | ... | @@ -760,19 +788,19 @@ template <class ELFT> static void addGotEntry(Symbol &Sym) { |
| 760 | 788 | bool IsLinkTimeConstant = |
| 761 | 789 | !Sym.IsPreemptible && (!Config->Pic || isAbsolute(Sym)); |
| 762 | 790 | if (IsLinkTimeConstant) { |
| 763 | InX::Got->Relocations.push_back({Expr, Target->GotRel, Off, 0, &Sym}); | |
| 791 | In.Got->Relocations.push_back({Expr, Target->GotRel, Off, 0, &Sym}); | |
| 764 | 792 | return; |
| 765 | 793 | } |
| 766 | 794 | |
| 767 | 795 | // Otherwise, we emit a dynamic relocation to .rel[a].dyn so that |
| 768 | 796 | // the GOT slot will be fixed at load-time. |
| 769 | 797 | if (!Sym.isTls() && !Sym.IsPreemptible && Config->Pic && !isAbsolute(Sym)) { |
| 770 | addRelativeReloc(InX::Got, Off, &Sym, 0, R_ABS, Target->GotRel); | |
| 798 | addRelativeReloc(In.Got, Off, &Sym, 0, R_ABS, Target->GotRel); | |
| 771 | 799 | return; |
| 772 | 800 | } |
| 773 | InX::RelaDyn->addReloc(Sym.isTls() ? Target->TlsGotRel : Target->GotRel, | |
| 774 | InX::Got, Off, &Sym, 0, | |
| 775 | Sym.IsPreemptible ? R_ADDEND : R_ABS, Target->GotRel); | |
| 801 | In.RelaDyn->addReloc(Sym.isTls() ? Target->TlsGotRel : Target->GotRel, In.Got, | |
| 802 | Off, &Sym, 0, Sym.IsPreemptible ? R_ADDEND : R_ABS, | |
| 803 | Target->GotRel); | |
| 776 | 804 | } |
| 777 | 805 | |
| 778 | 806 | // Return true if we can define a symbol in the executable that |
| ... | ... | @@ -825,7 +853,7 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type, |
| 825 | 853 | addRelativeReloc(&Sec, Offset, &Sym, Addend, Expr, Type); |
| 826 | 854 | return; |
| 827 | 855 | } else if (RelType Rel = Target->getDynRel(Type)) { |
| 828 | InX::RelaDyn->addReloc(Rel, &Sec, Offset, &Sym, Addend, R_ADDEND, Type); | |
| 856 | In.RelaDyn->addReloc(Rel, &Sec, Offset, &Sym, Addend, R_ADDEND, Type); | |
| 829 | 857 | |
| 830 | 858 | // MIPS ABI turns using of GOT and dynamic relocations inside out. |
| 831 | 859 | // While regular ABI uses dynamic relocations to fill up GOT entries |
| ... | ... | @@ -843,7 +871,7 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type, |
| 843 | 871 | // a dynamic relocation. |
| 844 | 872 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19 |
| 845 | 873 | if (Config->EMachine == EM_MIPS) |
| 846 | InX::MipsGot->addEntry(*Sec.File, Sym, Addend, Expr); | |
| 874 | In.MipsGot->addEntry(*Sec.File, Sym, Addend, Expr); | |
| 847 | 875 | return; |
| 848 | 876 | } |
| 849 | 877 | } |
| ... | ... | @@ -930,10 +958,9 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type, |
| 930 | 958 | "' cannot be preempted; recompile with -fPIE" + |
| 931 | 959 | getLocation(Sec, Sym, Offset)); |
| 932 | 960 | if (!Sym.isInPlt()) |
| 933 | addPltEntry<ELFT>(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel, | |
| 934 | Sym); | |
| 961 | addPltEntry<ELFT>(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym); | |
| 935 | 962 | if (!Sym.isDefined()) |
| 936 | replaceWithDefined(Sym, InX::Plt, Sym.getPltOffset(), 0); | |
| 963 | replaceWithDefined(Sym, In.Plt, getPltEntryOffset(Sym.PltIndex), 0); | |
| 937 | 964 | Sym.NeedsPltAddr = true; |
| 938 | 965 | Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym}); |
| 939 | 966 | return; |
| ... | ... | @@ -967,7 +994,7 @@ static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I, |
| 967 | 994 | if (maybeReportUndefined(Sym, Sec, Rel.r_offset)) |
| 968 | 995 | return; |
| 969 | 996 | |
| 970 | const uint8_t *RelocatedAddr = Sec.Data.begin() + Rel.r_offset; | |
| 997 | const uint8_t *RelocatedAddr = Sec.data().begin() + Rel.r_offset; | |
| 971 | 998 | RelExpr Expr = Target->getRelExpr(Type, Sym, RelocatedAddr); |
| 972 | 999 | |
| 973 | 1000 | // Ignore "hint" relocations because they are only markers for relaxation. |
| ... | ... | @@ -985,18 +1012,28 @@ static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I, |
| 985 | 1012 | // all dynamic symbols that can be resolved within the executable will |
| 986 | 1013 | // actually be resolved that way at runtime, because the main exectuable |
| 987 | 1014 | // is always at the beginning of a search list. We can leverage that fact. |
| 988 | if (Sym.isGnuIFunc()) | |
| 1015 | if (Sym.isGnuIFunc()) { | |
| 1016 | if (!Config->ZText && Config->WarnIfuncTextrel) { | |
| 1017 | warn("using ifunc symbols when text relocations are allowed may produce " | |
| 1018 | "a binary that will segfault, if the object file is linked with " | |
| 1019 | "old version of glibc (glibc 2.28 and earlier). If this applies to " | |
| 1020 | "you, consider recompiling the object files without -fPIC and " | |
| 1021 | "without -Wl,-z,notext option. Use -no-warn-ifunc-textrel to " | |
| 1022 | "turn off this warning." + | |
| 1023 | getLocation(Sec, Sym, Offset)); | |
| 1024 | } | |
| 989 | 1025 | Expr = toPlt(Expr); |
| 990 | else if (!Sym.IsPreemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym)) | |
| 1026 | } else if (!Sym.IsPreemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym)) { | |
| 991 | 1027 | Expr = Target->adjustRelaxExpr(Type, RelocatedAddr, Expr); |
| 992 | else if (!Sym.IsPreemptible) | |
| 1028 | } else if (!Sym.IsPreemptible) { | |
| 993 | 1029 | Expr = fromPlt(Expr); |
| 1030 | } | |
| 994 | 1031 | |
| 995 | 1032 | // This relocation does not require got entry, but it is relative to got and |
| 996 | 1033 | // needs it to be created. Here we request for that. |
| 997 | 1034 | if (isRelExprOneOf<R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_GOTREL, |
| 998 | 1035 | R_GOTREL_FROM_END, R_PPC_TOC>(Expr)) |
| 999 | InX::Got->HasGotOffRel = true; | |
| 1036 | In.Got->HasGotOffRel = true; | |
| 1000 | 1037 | |
| 1001 | 1038 | // Read an addend. |
| 1002 | 1039 | int64_t Addend = computeAddend<ELFT>(Rel, End, Sec, Expr, Sym.isLocal()); |
| ... | ... | @@ -1012,11 +1049,10 @@ static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I, |
| 1012 | 1049 | // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol. |
| 1013 | 1050 | if (needsPlt(Expr) && !Sym.isInPlt()) { |
| 1014 | 1051 | if (Sym.isGnuIFunc() && !Sym.IsPreemptible) |
| 1015 | addPltEntry<ELFT>(InX::Iplt, InX::IgotPlt, InX::RelaIplt, | |
| 1016 | Target->IRelativeRel, Sym); | |
| 1017 | else | |
| 1018 | addPltEntry<ELFT>(InX::Plt, InX::GotPlt, InX::RelaPlt, Target->PltRel, | |
| 1052 | addPltEntry<ELFT>(In.Iplt, In.IgotPlt, In.RelaIplt, Target->IRelativeRel, | |
| 1019 | 1053 | Sym); |
| 1054 | else | |
| 1055 | addPltEntry<ELFT>(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym); | |
| 1020 | 1056 | } |
| 1021 | 1057 | |
| 1022 | 1058 | // Create a GOT slot if a relocation needs GOT. |
| ... | ... | @@ -1029,7 +1065,7 @@ static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I, |
| 1029 | 1065 | // See "Global Offset Table" in Chapter 5 in the following document |
| 1030 | 1066 | // for detailed description: |
| 1031 | 1067 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
| 1032 | InX::MipsGot->addEntry(*Sec.File, Sym, Addend, Expr); | |
| 1068 | In.MipsGot->addEntry(*Sec.File, Sym, Addend, Expr); | |
| 1033 | 1069 | } else if (!Sym.isInGot()) { |
| 1034 | 1070 | addGotEntry<ELFT>(Sym); |
| 1035 | 1071 | } |
| ... | ... | @@ -1047,6 +1083,11 @@ static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) { |
| 1047 | 1083 | |
| 1048 | 1084 | for (auto I = Rels.begin(), End = Rels.end(); I != End;) |
| 1049 | 1085 | scanReloc<ELFT>(Sec, GetOffset, I, End); |
| 1086 | ||
| 1087 | // Sort relocations by offset to binary search for R_RISCV_PCREL_HI20 | |
| 1088 | if (Config->EMachine == EM_RISCV) | |
| 1089 | std::stable_sort(Sec.Relocations.begin(), Sec.Relocations.end(), | |
| 1090 | RelocationOffsetComparator{}); | |
| 1050 | 1091 | } |
| 1051 | 1092 | |
| 1052 | 1093 | template <class ELFT> void elf::scanRelocations(InputSectionBase &S) { |
| ... | ... | @@ -1056,6 +1097,43 @@ template <class ELFT> void elf::scanRelocations(InputSectionBase &S) { |
| 1056 | 1097 | scanRelocs<ELFT>(S, S.rels<ELFT>()); |
| 1057 | 1098 | } |
| 1058 | 1099 | |
| 1100 | static bool mergeCmp(const InputSection *A, const InputSection *B) { | |
| 1101 | // std::merge requires a strict weak ordering. | |
| 1102 | if (A->OutSecOff < B->OutSecOff) | |
| 1103 | return true; | |
| 1104 | ||
| 1105 | if (A->OutSecOff == B->OutSecOff) { | |
| 1106 | auto *TA = dyn_cast<ThunkSection>(A); | |
| 1107 | auto *TB = dyn_cast<ThunkSection>(B); | |
| 1108 | ||
| 1109 | // Check if Thunk is immediately before any specific Target | |
| 1110 | // InputSection for example Mips LA25 Thunks. | |
| 1111 | if (TA && TA->getTargetInputSection() == B) | |
| 1112 | return true; | |
| 1113 | ||
| 1114 | // Place Thunk Sections without specific targets before | |
| 1115 | // non-Thunk Sections. | |
| 1116 | if (TA && !TB && !TA->getTargetInputSection()) | |
| 1117 | return true; | |
| 1118 | } | |
| 1119 | ||
| 1120 | return false; | |
| 1121 | } | |
| 1122 | ||
| 1123 | // Call Fn on every executable InputSection accessed via the linker script | |
| 1124 | // InputSectionDescription::Sections. | |
| 1125 | static void forEachInputSectionDescription( | |
| 1126 | ArrayRef<OutputSection *> OutputSections, | |
| 1127 | llvm::function_ref<void(OutputSection *, InputSectionDescription *)> Fn) { | |
| 1128 | for (OutputSection *OS : OutputSections) { | |
| 1129 | if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) | |
| 1130 | continue; | |
| 1131 | for (BaseCommand *BC : OS->SectionCommands) | |
| 1132 | if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) | |
| 1133 | Fn(OS, ISD); | |
| 1134 | } | |
| 1135 | } | |
| 1136 | ||
| 1059 | 1137 | // Thunk Implementation |
| 1060 | 1138 | // |
| 1061 | 1139 | // Thunks (sometimes called stubs, veneers or branch islands) are small pieces |
| ... | ... | @@ -1158,6 +1236,7 @@ void ThunkCreator::mergeThunks(ArrayRef<OutputSection *> OutputSections) { |
| 1158 | 1236 | [](const std::pair<ThunkSection *, uint32_t> &TS) { |
| 1159 | 1237 | return TS.first->getSize() == 0; |
| 1160 | 1238 | }); |
| 1239 | ||
| 1161 | 1240 | // ISD->ThunkSections contains all created ThunkSections, including |
| 1162 | 1241 | // those inserted in previous passes. Extract the Thunks created this |
| 1163 | 1242 | // pass and order them in ascending OutSecOff. |
| ... | ... | @@ -1173,27 +1252,11 @@ void ThunkCreator::mergeThunks(ArrayRef<OutputSection *> OutputSections) { |
| 1173 | 1252 | // Merge sorted vectors of Thunks and InputSections by OutSecOff |
| 1174 | 1253 | std::vector<InputSection *> Tmp; |
| 1175 | 1254 | Tmp.reserve(ISD->Sections.size() + NewThunks.size()); |
| 1176 | auto MergeCmp = [](const InputSection *A, const InputSection *B) { | |
| 1177 | // std::merge requires a strict weak ordering. | |
| 1178 | if (A->OutSecOff < B->OutSecOff) | |
| 1179 | return true; | |
| 1180 | if (A->OutSecOff == B->OutSecOff) { | |
| 1181 | auto *TA = dyn_cast<ThunkSection>(A); | |
| 1182 | auto *TB = dyn_cast<ThunkSection>(B); | |
| 1183 | // Check if Thunk is immediately before any specific Target | |
| 1184 | // InputSection for example Mips LA25 Thunks. | |
| 1185 | if (TA && TA->getTargetInputSection() == B) | |
| 1186 | return true; | |
| 1187 | if (TA && !TB && !TA->getTargetInputSection()) | |
| 1188 | // Place Thunk Sections without specific targets before | |
| 1189 | // non-Thunk Sections. | |
| 1190 | return true; | |
| 1191 | } | |
| 1192 | return false; | |
| 1193 | }; | |
| 1255 | ||
| 1194 | 1256 | std::merge(ISD->Sections.begin(), ISD->Sections.end(), |
| 1195 | 1257 | NewThunks.begin(), NewThunks.end(), std::back_inserter(Tmp), |
| 1196 | MergeCmp); | |
| 1258 | mergeCmp); | |
| 1259 | ||
| 1197 | 1260 | ISD->Sections = std::move(Tmp); |
| 1198 | 1261 | }); |
| 1199 | 1262 | } |
| ... | ... | @@ -1237,20 +1300,23 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) { |
| 1237 | 1300 | // Find InputSectionRange within Target Output Section (TOS) that the |
| 1238 | 1301 | // InputSection (IS) that we need to precede is in. |
| 1239 | 1302 | OutputSection *TOS = IS->getParent(); |
| 1240 | for (BaseCommand *BC : TOS->SectionCommands) | |
| 1241 | if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) { | |
| 1242 | if (ISD->Sections.empty()) | |
| 1243 | continue; | |
| 1244 | InputSection *first = ISD->Sections.front(); | |
| 1245 | InputSection *last = ISD->Sections.back(); | |
| 1246 | if (IS->OutSecOff >= first->OutSecOff && | |
| 1247 | IS->OutSecOff <= last->OutSecOff) { | |
| 1248 | TS = addThunkSection(TOS, ISD, IS->OutSecOff); | |
| 1249 | ThunkedSections[IS] = TS; | |
| 1250 | break; | |
| 1251 | } | |
| 1252 | } | |
| 1253 | return TS; | |
| 1303 | for (BaseCommand *BC : TOS->SectionCommands) { | |
| 1304 | auto *ISD = dyn_cast<InputSectionDescription>(BC); | |
| 1305 | if (!ISD || ISD->Sections.empty()) | |
| 1306 | continue; | |
| 1307 | ||
| 1308 | InputSection *First = ISD->Sections.front(); | |
| 1309 | InputSection *Last = ISD->Sections.back(); | |
| 1310 | ||
| 1311 | if (IS->OutSecOff < First->OutSecOff || Last->OutSecOff < IS->OutSecOff) | |
| 1312 | continue; | |
| 1313 | ||
| 1314 | TS = addThunkSection(TOS, ISD, IS->OutSecOff); | |
| 1315 | ThunkedSections[IS] = TS; | |
| 1316 | return TS; | |
| 1317 | } | |
| 1318 | ||
| 1319 | return nullptr; | |
| 1254 | 1320 | } |
| 1255 | 1321 | |
| 1256 | 1322 | // Create one or more ThunkSections per OS that can be used to place Thunks. |
| ... | ... | @@ -1271,26 +1337,29 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) { |
| 1271 | 1337 | // allow for the creation of a short thunk. |
| 1272 | 1338 | void ThunkCreator::createInitialThunkSections( |
| 1273 | 1339 | ArrayRef<OutputSection *> OutputSections) { |
| 1340 | uint32_t ThunkSectionSpacing = Target->getThunkSectionSpacing(); | |
| 1341 | ||
| 1274 | 1342 | forEachInputSectionDescription( |
| 1275 | 1343 | OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) { |
| 1276 | 1344 | if (ISD->Sections.empty()) |
| 1277 | 1345 | return; |
| 1346 | ||
| 1278 | 1347 | uint32_t ISDBegin = ISD->Sections.front()->OutSecOff; |
| 1279 | 1348 | uint32_t ISDEnd = |
| 1280 | 1349 | ISD->Sections.back()->OutSecOff + ISD->Sections.back()->getSize(); |
| 1281 | 1350 | uint32_t LastThunkLowerBound = -1; |
| 1282 | if (ISDEnd - ISDBegin > Target->ThunkSectionSpacing * 2) | |
| 1283 | LastThunkLowerBound = ISDEnd - Target->ThunkSectionSpacing; | |
| 1351 | if (ISDEnd - ISDBegin > ThunkSectionSpacing * 2) | |
| 1352 | LastThunkLowerBound = ISDEnd - ThunkSectionSpacing; | |
| 1284 | 1353 | |
| 1285 | 1354 | uint32_t ISLimit; |
| 1286 | 1355 | uint32_t PrevISLimit = ISDBegin; |
| 1287 | uint32_t ThunkUpperBound = ISDBegin + Target->ThunkSectionSpacing; | |
| 1356 | uint32_t ThunkUpperBound = ISDBegin + ThunkSectionSpacing; | |
| 1288 | 1357 | |
| 1289 | 1358 | for (const InputSection *IS : ISD->Sections) { |
| 1290 | 1359 | ISLimit = IS->OutSecOff + IS->getSize(); |
| 1291 | 1360 | if (ISLimit > ThunkUpperBound) { |
| 1292 | 1361 | addThunkSection(OS, ISD, PrevISLimit); |
| 1293 | ThunkUpperBound = PrevISLimit + Target->ThunkSectionSpacing; | |
| 1362 | ThunkUpperBound = PrevISLimit + ThunkSectionSpacing; | |
| 1294 | 1363 | } |
| 1295 | 1364 | if (ISLimit > LastThunkLowerBound) |
| 1296 | 1365 | break; |
| ... | ... | @@ -1304,13 +1373,14 @@ ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS, |
| 1304 | 1373 | InputSectionDescription *ISD, |
| 1305 | 1374 | uint64_t Off) { |
| 1306 | 1375 | auto *TS = make<ThunkSection>(OS, Off); |
| 1307 | ISD->ThunkSections.push_back(std::make_pair(TS, Pass)); | |
| 1376 | ISD->ThunkSections.push_back({TS, Pass}); | |
| 1308 | 1377 | return TS; |
| 1309 | 1378 | } |
| 1310 | 1379 | |
| 1311 | 1380 | std::pair<Thunk *, bool> ThunkCreator::getThunk(Symbol &Sym, RelType Type, |
| 1312 | 1381 | uint64_t Src) { |
| 1313 | 1382 | std::vector<Thunk *> *ThunkVec = nullptr; |
| 1383 | ||
| 1314 | 1384 | // We use (section, offset) pair to find the thunk position if possible so |
| 1315 | 1385 | // that we create only one thunk for aliased symbols or ICFed sections. |
| 1316 | 1386 | if (auto *D = dyn_cast<Defined>(&Sym)) |
| ... | ... | @@ -1318,40 +1388,28 @@ std::pair<Thunk *, bool> ThunkCreator::getThunk(Symbol &Sym, RelType Type, |
| 1318 | 1388 | ThunkVec = &ThunkedSymbolsBySection[{D->Section->Repl, D->Value}]; |
| 1319 | 1389 | if (!ThunkVec) |
| 1320 | 1390 | ThunkVec = &ThunkedSymbols[&Sym]; |
| 1391 | ||
| 1321 | 1392 | // Check existing Thunks for Sym to see if they can be reused |
| 1322 | for (Thunk *ET : *ThunkVec) | |
| 1323 | if (ET->isCompatibleWith(Type) && | |
| 1324 | Target->inBranchRange(Type, Src, ET->getThunkTargetSym()->getVA())) | |
| 1325 | return std::make_pair(ET, false); | |
| 1393 | for (Thunk *T : *ThunkVec) | |
| 1394 | if (T->isCompatibleWith(Type) && | |
| 1395 | Target->inBranchRange(Type, Src, T->getThunkTargetSym()->getVA())) | |
| 1396 | return std::make_pair(T, false); | |
| 1397 | ||
| 1326 | 1398 | // No existing compatible Thunk in range, create a new one |
| 1327 | 1399 | Thunk *T = addThunk(Type, Sym); |
| 1328 | 1400 | ThunkVec->push_back(T); |
| 1329 | 1401 | return std::make_pair(T, true); |
| 1330 | 1402 | } |
| 1331 | 1403 | |
| 1332 | // Call Fn on every executable InputSection accessed via the linker script | |
| 1333 | // InputSectionDescription::Sections. | |
| 1334 | void ThunkCreator::forEachInputSectionDescription( | |
| 1335 | ArrayRef<OutputSection *> OutputSections, | |
| 1336 | llvm::function_ref<void(OutputSection *, InputSectionDescription *)> Fn) { | |
| 1337 | for (OutputSection *OS : OutputSections) { | |
| 1338 | if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR)) | |
| 1339 | continue; | |
| 1340 | for (BaseCommand *BC : OS->SectionCommands) | |
| 1341 | if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) | |
| 1342 | Fn(OS, ISD); | |
| 1343 | } | |
| 1344 | } | |
| 1345 | ||
| 1346 | 1404 | // Return true if the relocation target is an in range Thunk. |
| 1347 | 1405 | // Return false if the relocation is not to a Thunk. If the relocation target |
| 1348 | 1406 | // was originally to a Thunk, but is no longer in range we revert the |
| 1349 | 1407 | // relocation back to its original non-Thunk target. |
| 1350 | 1408 | bool ThunkCreator::normalizeExistingThunk(Relocation &Rel, uint64_t Src) { |
| 1351 | if (Thunk *ET = Thunks.lookup(Rel.Sym)) { | |
| 1409 | if (Thunk *T = Thunks.lookup(Rel.Sym)) { | |
| 1352 | 1410 | if (Target->inBranchRange(Rel.Type, Src, Rel.Sym->getVA())) |
| 1353 | 1411 | return true; |
| 1354 | Rel.Sym = &ET->Destination; | |
| 1412 | Rel.Sym = &T->Destination; | |
| 1355 | 1413 | if (Rel.Sym->isInPlt()) |
| 1356 | 1414 | Rel.Expr = toPlt(Rel.Expr); |
| 1357 | 1415 | } |
| ... | ... | @@ -1385,11 +1443,13 @@ bool ThunkCreator::normalizeExistingThunk(Relocation &Rel, uint64_t Src) { |
| 1385 | 1443 | // relocation out of range error. |
| 1386 | 1444 | bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) { |
| 1387 | 1445 | bool AddressesChanged = false; |
| 1388 | if (Pass == 0 && Target->ThunkSectionSpacing) | |
| 1446 | ||
| 1447 | if (Pass == 0 && Target->getThunkSectionSpacing()) | |
| 1389 | 1448 | createInitialThunkSections(OutputSections); |
| 1390 | else if (Pass == 10) | |
| 1391 | // With Thunk Size much smaller than branch range we expect to | |
| 1392 | // converge quickly; if we get to 10 something has gone wrong. | |
| 1449 | ||
| 1450 | // With Thunk Size much smaller than branch range we expect to | |
| 1451 | // converge quickly; if we get to 10 something has gone wrong. | |
| 1452 | if (Pass == 10) | |
| 1393 | 1453 | fatal("thunk creation not converged"); |
| 1394 | 1454 | |
| 1395 | 1455 | // Create all the Thunks and insert them into synthetic ThunkSections. The |
| ... | ... | @@ -1412,9 +1472,11 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) { |
| 1412 | 1472 | if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Src, |
| 1413 | 1473 | *Rel.Sym)) |
| 1414 | 1474 | continue; |
| 1475 | ||
| 1415 | 1476 | Thunk *T; |
| 1416 | 1477 | bool IsNew; |
| 1417 | 1478 | std::tie(T, IsNew) = getThunk(*Rel.Sym, Rel.Type, Src); |
| 1479 | ||
| 1418 | 1480 | if (IsNew) { |
| 1419 | 1481 | // Find or create a ThunkSection for the new Thunk |
| 1420 | 1482 | ThunkSection *TS; |
| ... | ... | @@ -1425,13 +1487,16 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) { |
| 1425 | 1487 | TS->addThunk(T); |
| 1426 | 1488 | Thunks[T->getThunkTargetSym()] = T; |
| 1427 | 1489 | } |
| 1490 | ||
| 1428 | 1491 | // Redirect relocation to Thunk, we never go via the PLT to a Thunk |
| 1429 | 1492 | Rel.Sym = T->getThunkTargetSym(); |
| 1430 | 1493 | Rel.Expr = fromPlt(Rel.Expr); |
| 1431 | 1494 | } |
| 1495 | ||
| 1432 | 1496 | for (auto &P : ISD->ThunkSections) |
| 1433 | 1497 | AddressesChanged |= P.first->assignOffsets(); |
| 1434 | 1498 | }); |
| 1499 | ||
| 1435 | 1500 | for (auto &P : ThunkedSections) |
| 1436 | 1501 | AddressesChanged |= P.second->assignOffsets(); |
| 1437 | 1502 |
deps/lld/ELF/Relocations.h+30-9| ... | ... | @@ -33,16 +33,28 @@ enum RelExpr { |
| 33 | 33 | R_INVALID, |
| 34 | 34 | R_ABS, |
| 35 | 35 | R_ADDEND, |
| 36 | R_AARCH64_GOT_PAGE_PC, | |
| 37 | // The expression is used for IFUNC support. Describes PC-relative | |
| 38 | // address of the memory page of GOT entry. This entry is used for | |
| 39 | // a redirection to IPLT. | |
| 40 | R_AARCH64_GOT_PAGE_PC_PLT, | |
| 41 | R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC, | |
| 42 | R_AARCH64_PAGE_PC, | |
| 43 | R_AARCH64_PLT_PAGE_PC, | |
| 44 | R_AARCH64_TLSDESC_PAGE, | |
| 36 | 45 | R_ARM_SBREL, |
| 37 | 46 | R_GOT, |
| 47 | // The expression is used for IFUNC support. Evaluates to GOT entry, | |
| 48 | // containing redirection to the IPLT. | |
| 49 | R_GOT_PLT, | |
| 38 | 50 | R_GOTONLY_PC, |
| 39 | 51 | R_GOTONLY_PC_FROM_END, |
| 40 | 52 | R_GOTREL, |
| 41 | 53 | R_GOTREL_FROM_END, |
| 42 | 54 | R_GOT_FROM_END, |
| 43 | 55 | R_GOT_OFF, |
| 44 | R_GOT_PAGE_PC, | |
| 45 | 56 | R_GOT_PC, |
| 57 | R_HEXAGON_GOT, | |
| 46 | 58 | R_HINT, |
| 47 | 59 | R_MIPS_GOTREL, |
| 48 | 60 | R_MIPS_GOT_GP, |
| ... | ... | @@ -54,10 +66,8 @@ enum RelExpr { |
| 54 | 66 | R_MIPS_TLSLD, |
| 55 | 67 | R_NEG_TLS, |
| 56 | 68 | R_NONE, |
| 57 | R_PAGE_PC, | |
| 58 | 69 | R_PC, |
| 59 | 70 | R_PLT, |
| 60 | R_PLT_PAGE_PC, | |
| 61 | 71 | R_PLT_PC, |
| 62 | 72 | R_PPC_CALL, |
| 63 | 73 | R_PPC_CALL_PLT, |
| ... | ... | @@ -68,20 +78,20 @@ enum RelExpr { |
| 68 | 78 | R_RELAX_TLS_GD_TO_IE_ABS, |
| 69 | 79 | R_RELAX_TLS_GD_TO_IE_END, |
| 70 | 80 | R_RELAX_TLS_GD_TO_IE_GOT_OFF, |
| 71 | R_RELAX_TLS_GD_TO_IE_PAGE_PC, | |
| 72 | 81 | R_RELAX_TLS_GD_TO_LE, |
| 73 | 82 | R_RELAX_TLS_GD_TO_LE_NEG, |
| 74 | 83 | R_RELAX_TLS_IE_TO_LE, |
| 75 | 84 | R_RELAX_TLS_LD_TO_LE, |
| 76 | 85 | R_RELAX_TLS_LD_TO_LE_ABS, |
| 86 | R_RISCV_PC_INDIRECT, | |
| 77 | 87 | R_SIZE, |
| 78 | 88 | R_TLS, |
| 79 | 89 | R_TLSDESC, |
| 80 | 90 | R_TLSDESC_CALL, |
| 81 | R_TLSDESC_PAGE, | |
| 82 | 91 | R_TLSGD_GOT, |
| 83 | 92 | R_TLSGD_GOT_FROM_END, |
| 84 | 93 | R_TLSGD_PC, |
| 94 | R_TLSIE_HINT, | |
| 85 | 95 | R_TLSLD_GOT, |
| 86 | 96 | R_TLSLD_GOT_FROM_END, |
| 87 | 97 | R_TLSLD_GOT_OFF, |
| ... | ... | @@ -128,6 +138,21 @@ struct Relocation { |
| 128 | 138 | Symbol *Sym; |
| 129 | 139 | }; |
| 130 | 140 | |
| 141 | struct RelocationOffsetComparator { | |
| 142 | bool operator()(const Relocation &Lhs, const Relocation &Rhs) { | |
| 143 | return Lhs.Offset < Rhs.Offset; | |
| 144 | } | |
| 145 | ||
| 146 | // For std::lower_bound, std::upper_bound, std::equal_range. | |
| 147 | bool operator()(const Relocation &Rel, uint64_t Val) { | |
| 148 | return Rel.Offset < Val; | |
| 149 | } | |
| 150 | ||
| 151 | bool operator()(uint64_t Val, const Relocation &Rel) { | |
| 152 | return Val < Rel.Offset; | |
| 153 | } | |
| 154 | }; | |
| 155 | ||
| 131 | 156 | template <class ELFT> void scanRelocations(InputSectionBase &); |
| 132 | 157 | |
| 133 | 158 | class ThunkSection; |
| ... | ... | @@ -155,10 +180,6 @@ private: |
| 155 | 180 | |
| 156 | 181 | void createInitialThunkSections(ArrayRef<OutputSection *> OutputSections); |
| 157 | 182 | |
| 158 | void forEachInputSectionDescription( | |
| 159 | ArrayRef<OutputSection *> OutputSections, | |
| 160 | llvm::function_ref<void(OutputSection *, InputSectionDescription *)> Fn); | |
| 161 | ||
| 162 | 183 | std::pair<Thunk *, bool> getThunk(Symbol &Sym, RelType Type, uint64_t Src); |
| 163 | 184 | |
| 164 | 185 | ThunkSection *addThunkSection(OutputSection *OS, InputSectionDescription *, |
deps/lld/ELF/ScriptLexer.cpp+9| ... | ... | @@ -244,6 +244,15 @@ StringRef ScriptLexer::peek() { |
| 244 | 244 | return Tok; |
| 245 | 245 | } |
| 246 | 246 | |
| 247 | StringRef ScriptLexer::peek2() { | |
| 248 | skip(); | |
| 249 | StringRef Tok = next(); | |
| 250 | if (errorCount()) | |
| 251 | return ""; | |
| 252 | Pos = Pos - 2; | |
| 253 | return Tok; | |
| 254 | } | |
| 255 | ||
| 247 | 256 | bool ScriptLexer::consume(StringRef Tok) { |
| 248 | 257 | if (peek() == Tok) { |
| 249 | 258 | skip(); |
deps/lld/ELF/ScriptLexer.h+1| ... | ... | @@ -29,6 +29,7 @@ public: |
| 29 | 29 | bool atEOF(); |
| 30 | 30 | StringRef next(); |
| 31 | 31 | StringRef peek(); |
| 32 | StringRef peek2(); | |
| 32 | 33 | void skip(); |
| 33 | 34 | bool consume(StringRef Tok); |
| 34 | 35 | void expect(StringRef Expect); |
deps/lld/ELF/ScriptParser.cpp+108-36| ... | ... | @@ -72,13 +72,15 @@ private: |
| 72 | 72 | void readRegionAlias(); |
| 73 | 73 | void readSearchDir(); |
| 74 | 74 | void readSections(); |
| 75 | void readTarget(); | |
| 75 | 76 | void readVersion(); |
| 76 | 77 | void readVersionScriptCommand(); |
| 77 | 78 | |
| 78 | 79 | SymbolAssignment *readSymbolAssignment(StringRef Name); |
| 79 | 80 | ByteCommand *readByteCommand(StringRef Tok); |
| 80 | uint32_t readFill(); | |
| 81 | uint32_t parseFill(StringRef Tok); | |
| 81 | std::array<uint8_t, 4> readFill(); | |
| 82 | std::array<uint8_t, 4> parseFill(StringRef Tok); | |
| 83 | bool readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2); | |
| 82 | 84 | void readSectionAddressType(OutputSection *Cmd); |
| 83 | 85 | OutputSection *readOverlaySectionDescription(); |
| 84 | 86 | OutputSection *readOutputSectionDescription(StringRef OutSec); |
| ... | ... | @@ -255,6 +257,8 @@ void ScriptParser::readLinkerScript() { |
| 255 | 257 | readSearchDir(); |
| 256 | 258 | } else if (Tok == "SECTIONS") { |
| 257 | 259 | readSections(); |
| 260 | } else if (Tok == "TARGET") { | |
| 261 | readTarget(); | |
| 258 | 262 | } else if (Tok == "VERSION") { |
| 259 | 263 | readVersion(); |
| 260 | 264 | } else if (SymbolAssignment *Cmd = readAssignment(Tok)) { |
| ... | ... | @@ -266,6 +270,8 @@ void ScriptParser::readLinkerScript() { |
| 266 | 270 | } |
| 267 | 271 | |
| 268 | 272 | void ScriptParser::readDefsym(StringRef Name) { |
| 273 | if (errorCount()) | |
| 274 | return; | |
| 269 | 275 | Expr E = readExpr(); |
| 270 | 276 | if (!atEOF()) |
| 271 | 277 | setError("EOF expected, but got " + next()); |
| ... | ... | @@ -378,10 +384,42 @@ void ScriptParser::readOutputArch() { |
| 378 | 384 | skip(); |
| 379 | 385 | } |
| 380 | 386 | |
| 387 | static std::pair<ELFKind, uint16_t> parseBfdName(StringRef S) { | |
| 388 | return StringSwitch<std::pair<ELFKind, uint16_t>>(S) | |
| 389 | .Case("elf32-i386", {ELF32LEKind, EM_386}) | |
| 390 | .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU}) | |
| 391 | .Case("elf32-littlearm", {ELF32LEKind, EM_ARM}) | |
| 392 | .Case("elf32-x86-64", {ELF32LEKind, EM_X86_64}) | |
| 393 | .Case("elf64-aarch64", {ELF64LEKind, EM_AARCH64}) | |
| 394 | .Case("elf64-littleaarch64", {ELF64LEKind, EM_AARCH64}) | |
| 395 | .Case("elf64-powerpc", {ELF64BEKind, EM_PPC64}) | |
| 396 | .Case("elf64-powerpcle", {ELF64LEKind, EM_PPC64}) | |
| 397 | .Case("elf64-x86-64", {ELF64LEKind, EM_X86_64}) | |
| 398 | .Case("elf32-tradbigmips", {ELF32BEKind, EM_MIPS}) | |
| 399 | .Case("elf32-ntradbigmips", {ELF32BEKind, EM_MIPS}) | |
| 400 | .Case("elf32-tradlittlemips", {ELF32LEKind, EM_MIPS}) | |
| 401 | .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS}) | |
| 402 | .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS}) | |
| 403 | .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS}) | |
| 404 | .Default({ELFNoneKind, EM_NONE}); | |
| 405 | } | |
| 406 | ||
| 407 | // Parse OUTPUT_FORMAT(bfdname) or OUTPUT_FORMAT(bfdname, big, little). | |
| 408 | // Currently we ignore big and little parameters. | |
| 381 | 409 | void ScriptParser::readOutputFormat() { |
| 382 | // Error checking only for now. | |
| 383 | 410 | expect("("); |
| 384 | skip(); | |
| 411 | ||
| 412 | StringRef Name = unquote(next()); | |
| 413 | StringRef S = Name; | |
| 414 | if (S.consume_back("-freebsd")) | |
| 415 | Config->OSABI = ELFOSABI_FREEBSD; | |
| 416 | ||
| 417 | std::tie(Config->EKind, Config->EMachine) = parseBfdName(S); | |
| 418 | if (Config->EMachine == EM_NONE) | |
| 419 | setError("unknown output format name: " + Name); | |
| 420 | if (S == "elf32-ntradlittlemips" || S == "elf32-ntradbigmips") | |
| 421 | Config->MipsN32Abi = true; | |
| 422 | ||
| 385 | 423 | if (consume(")")) |
| 386 | 424 | return; |
| 387 | 425 | expect(","); |
| ... | ... | @@ -497,6 +535,9 @@ void ScriptParser::readSections() { |
| 497 | 535 | for (BaseCommand *Cmd : readOverlay()) |
| 498 | 536 | V.push_back(Cmd); |
| 499 | 537 | continue; |
| 538 | } else if (Tok == "INCLUDE") { | |
| 539 | readInclude(); | |
| 540 | continue; | |
| 500 | 541 | } |
| 501 | 542 | |
| 502 | 543 | if (BaseCommand *Cmd = readAssignment(Tok)) |
| ... | ... | @@ -522,6 +563,23 @@ void ScriptParser::readSections() { |
| 522 | 563 | V.end()); |
| 523 | 564 | } |
| 524 | 565 | |
| 566 | void ScriptParser::readTarget() { | |
| 567 | // TARGET(foo) is an alias for "--format foo". Unlike GNU linkers, | |
| 568 | // we accept only a limited set of BFD names (i.e. "elf" or "binary") | |
| 569 | // for --format. We recognize only /^elf/ and "binary" in the linker | |
| 570 | // script as well. | |
| 571 | expect("("); | |
| 572 | StringRef Tok = next(); | |
| 573 | expect(")"); | |
| 574 | ||
| 575 | if (Tok.startswith("elf")) | |
| 576 | Config->FormatBinary = false; | |
| 577 | else if (Tok == "binary") | |
| 578 | Config->FormatBinary = true; | |
| 579 | else | |
| 580 | setError("unknown target: " + Tok); | |
| 581 | } | |
| 582 | ||
| 525 | 583 | static int precedence(StringRef Op) { |
| 526 | 584 | return StringSwitch<int>(Op) |
| 527 | 585 | .Cases("*", "/", "%", 8) |
| ... | ... | @@ -672,13 +730,33 @@ Expr ScriptParser::readAssert() { |
| 672 | 730 | // alias for =fillexp section attribute, which is different from |
| 673 | 731 | // what GNU linkers do. |
| 674 | 732 | // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html |
| 675 | uint32_t ScriptParser::readFill() { | |
| 733 | std::array<uint8_t, 4> ScriptParser::readFill() { | |
| 676 | 734 | expect("("); |
| 677 | uint32_t V = parseFill(next()); | |
| 735 | std::array<uint8_t, 4> V = parseFill(next()); | |
| 678 | 736 | expect(")"); |
| 679 | 737 | return V; |
| 680 | 738 | } |
| 681 | 739 | |
| 740 | // Tries to read the special directive for an output section definition which | |
| 741 | // can be one of following: "(NOLOAD)", "(COPY)", "(INFO)" or "(OVERLAY)". | |
| 742 | // Tok1 and Tok2 are next 2 tokens peeked. See comment for readSectionAddressType below. | |
| 743 | bool ScriptParser::readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2) { | |
| 744 | if (Tok1 != "(") | |
| 745 | return false; | |
| 746 | if (Tok2 != "NOLOAD" && Tok2 != "COPY" && Tok2 != "INFO" && Tok2 != "OVERLAY") | |
| 747 | return false; | |
| 748 | ||
| 749 | expect("("); | |
| 750 | if (consume("NOLOAD")) { | |
| 751 | Cmd->Noload = true; | |
| 752 | } else { | |
| 753 | skip(); // This is "COPY", "INFO" or "OVERLAY". | |
| 754 | Cmd->NonAlloc = true; | |
| 755 | } | |
| 756 | expect(")"); | |
| 757 | return true; | |
| 758 | } | |
| 759 | ||
| 682 | 760 | // Reads an expression and/or the special directive for an output |
| 683 | 761 | // section definition. Directive is one of following: "(NOLOAD)", |
| 684 | 762 | // "(COPY)", "(INFO)" or "(OVERLAY)". |
| ... | ... | @@ -691,28 +769,12 @@ uint32_t ScriptParser::readFill() { |
| 691 | 769 | // https://sourceware.org/binutils/docs/ld/Output-Section-Address.html |
| 692 | 770 | // https://sourceware.org/binutils/docs/ld/Output-Section-Type.html |
| 693 | 771 | void ScriptParser::readSectionAddressType(OutputSection *Cmd) { |
| 694 | if (consume("(")) { | |
| 695 | if (consume("NOLOAD")) { | |
| 696 | expect(")"); | |
| 697 | Cmd->Noload = true; | |
| 698 | return; | |
| 699 | } | |
| 700 | if (consume("COPY") || consume("INFO") || consume("OVERLAY")) { | |
| 701 | expect(")"); | |
| 702 | Cmd->NonAlloc = true; | |
| 703 | return; | |
| 704 | } | |
| 705 | Cmd->AddrExpr = readExpr(); | |
| 706 | expect(")"); | |
| 707 | } else { | |
| 708 | Cmd->AddrExpr = readExpr(); | |
| 709 | } | |
| 772 | if (readSectionDirective(Cmd, peek(), peek2())) | |
| 773 | return; | |
| 710 | 774 | |
| 711 | if (consume("(")) { | |
| 712 | expect("NOLOAD"); | |
| 713 | expect(")"); | |
| 714 | Cmd->Noload = true; | |
| 715 | } | |
| 775 | Cmd->AddrExpr = readExpr(); | |
| 776 | if (peek() == "(" && !readSectionDirective(Cmd, "(", peek2())) | |
| 777 | setError("unknown section directive: " + peek2()); | |
| 716 | 778 | } |
| 717 | 779 | |
| 718 | 780 | static Expr checkAlignment(Expr E, std::string &Loc) { |
| ... | ... | @@ -778,10 +840,17 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) { |
| 778 | 840 | Cmd->Filler = readFill(); |
| 779 | 841 | } else if (Tok == "SORT") { |
| 780 | 842 | readSort(); |
| 843 | } else if (Tok == "INCLUDE") { | |
| 844 | readInclude(); | |
| 781 | 845 | } else if (peek() == "(") { |
| 782 | 846 | Cmd->SectionCommands.push_back(readInputSectionDescription(Tok)); |
| 783 | 847 | } else { |
| 784 | setError("unknown command " + Tok); | |
| 848 | // We have a file name and no input sections description. It is not a | |
| 849 | // commonly used syntax, but still acceptable. In that case, all sections | |
| 850 | // from the file will be included. | |
| 851 | auto *ISD = make<InputSectionDescription>(Tok); | |
| 852 | ISD->SectionPatterns.push_back({{}, StringMatcher({"*"})}); | |
| 853 | Cmd->SectionCommands.push_back(ISD); | |
| 785 | 854 | } |
| 786 | 855 | } |
| 787 | 856 | |
| ... | ... | @@ -818,13 +887,13 @@ OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) { |
| 818 | 887 | // When reading a hexstring, ld.bfd handles it as a blob of arbitrary |
| 819 | 888 | // size, while ld.gold always handles it as a 32-bit big-endian number. |
| 820 | 889 | // We are compatible with ld.gold because it's easier to implement. |
| 821 | uint32_t ScriptParser::parseFill(StringRef Tok) { | |
| 890 | std::array<uint8_t, 4> ScriptParser::parseFill(StringRef Tok) { | |
| 822 | 891 | uint32_t V = 0; |
| 823 | 892 | if (!to_integer(Tok, V)) |
| 824 | 893 | setError("invalid filler expression: " + Tok); |
| 825 | 894 | |
| 826 | uint32_t Buf; | |
| 827 | write32be(&Buf, V); | |
| 895 | std::array<uint8_t, 4> Buf; | |
| 896 | write32be(Buf.data(), V); | |
| 828 | 897 | return Buf; |
| 829 | 898 | } |
| 830 | 899 | |
| ... | ... | @@ -1404,7 +1473,11 @@ uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2, |
| 1404 | 1473 | void ScriptParser::readMemory() { |
| 1405 | 1474 | expect("{"); |
| 1406 | 1475 | while (!errorCount() && !consume("}")) { |
| 1407 | StringRef Name = next(); | |
| 1476 | StringRef Tok = next(); | |
| 1477 | if (Tok == "INCLUDE") { | |
| 1478 | readInclude(); | |
| 1479 | continue; | |
| 1480 | } | |
| 1408 | 1481 | |
| 1409 | 1482 | uint32_t Flags = 0; |
| 1410 | 1483 | uint32_t NegFlags = 0; |
| ... | ... | @@ -1419,10 +1492,9 @@ void ScriptParser::readMemory() { |
| 1419 | 1492 | uint64_t Length = readMemoryAssignment("LENGTH", "len", "l"); |
| 1420 | 1493 | |
| 1421 | 1494 | // Add the memory region to the region map. |
| 1422 | MemoryRegion *MR = | |
| 1423 | make<MemoryRegion>(Name, Origin, Length, Flags, NegFlags); | |
| 1424 | if (!Script->MemoryRegions.insert({Name, MR}).second) | |
| 1425 | setError("region '" + Name + "' already defined"); | |
| 1495 | MemoryRegion *MR = make<MemoryRegion>(Tok, Origin, Length, Flags, NegFlags); | |
| 1496 | if (!Script->MemoryRegions.insert({Tok, MR}).second) | |
| 1497 | setError("region '" + Tok + "' already defined"); | |
| 1426 | 1498 | } |
| 1427 | 1499 | } |
| 1428 | 1500 |
deps/lld/ELF/SymbolTable.cpp+92-158| ... | ... | @@ -94,8 +94,20 @@ template <class ELFT> void SymbolTable::addFile(InputFile *File) { |
| 94 | 94 | if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) { |
| 95 | 95 | // DSOs are uniquified not by filename but by soname. |
| 96 | 96 | F->parseSoName(); |
| 97 | if (errorCount() || !SoNames.insert(F->SoName).second) | |
| 97 | if (errorCount()) | |
| 98 | 98 | return; |
| 99 | ||
| 100 | // If a DSO appears more than once on the command line with and without | |
| 101 | // --as-needed, --no-as-needed takes precedence over --as-needed because a | |
| 102 | // user can add an extra DSO with --no-as-needed to force it to be added to | |
| 103 | // the dependency list. | |
| 104 | DenseMap<StringRef, InputFile *>::iterator It; | |
| 105 | bool WasInserted; | |
| 106 | std::tie(It, WasInserted) = SoNames.try_emplace(F->SoName, F); | |
| 107 | cast<SharedFile<ELFT>>(It->second)->IsNeeded |= F->IsNeeded; | |
| 108 | if (!WasInserted) | |
| 109 | return; | |
| 110 | ||
| 99 | 111 | SharedFiles.push_back(F); |
| 100 | 112 | F->parseRest(); |
| 101 | 113 | return; |
| ... | ... | @@ -139,77 +151,27 @@ template <class ELFT> void SymbolTable::addCombinedLTOObject() { |
| 139 | 151 | } |
| 140 | 152 | } |
| 141 | 153 | |
| 142 | Defined *SymbolTable::addAbsolute(StringRef Name, uint8_t Visibility, | |
| 143 | uint8_t Binding) { | |
| 144 | Symbol *Sym = | |
| 145 | addRegular(Name, Visibility, STT_NOTYPE, 0, 0, Binding, nullptr, nullptr); | |
| 146 | return cast<Defined>(Sym); | |
| 147 | } | |
| 148 | ||
| 149 | 154 | // Set a flag for --trace-symbol so that we can print out a log message |
| 150 | 155 | // if a new symbol with the same name is inserted into the symbol table. |
| 151 | 156 | void SymbolTable::trace(StringRef Name) { |
| 152 | 157 | SymMap.insert({CachedHashStringRef(Name), -1}); |
| 153 | 158 | } |
| 154 | 159 | |
| 155 | // Rename SYM as __wrap_SYM. The original symbol is preserved as __real_SYM. | |
| 156 | // Used to implement --wrap. | |
| 157 | template <class ELFT> void SymbolTable::addSymbolWrap(StringRef Name) { | |
| 158 | Symbol *Sym = find(Name); | |
| 159 | if (!Sym) | |
| 160 | return; | |
| 161 | ||
| 162 | // Do not wrap the same symbol twice. | |
| 163 | for (const WrappedSymbol &S : WrappedSymbols) | |
| 164 | if (S.Sym == Sym) | |
| 165 | return; | |
| 160 | void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) { | |
| 161 | // Swap symbols as instructed by -wrap. | |
| 162 | int &Idx1 = SymMap[CachedHashStringRef(Sym->getName())]; | |
| 163 | int &Idx2 = SymMap[CachedHashStringRef(Real->getName())]; | |
| 164 | int &Idx3 = SymMap[CachedHashStringRef(Wrap->getName())]; | |
| 166 | 165 | |
| 167 | Symbol *Real = addUndefined<ELFT>(Saver.save("__real_" + Name)); | |
| 168 | Symbol *Wrap = addUndefined<ELFT>(Saver.save("__wrap_" + Name)); | |
| 169 | WrappedSymbols.push_back({Sym, Real, Wrap}); | |
| 166 | Idx2 = Idx1; | |
| 167 | Idx1 = Idx3; | |
| 170 | 168 | |
| 171 | // We want to tell LTO not to inline symbols to be overwritten | |
| 172 | // because LTO doesn't know the final symbol contents after renaming. | |
| 173 | Real->CanInline = false; | |
| 174 | Sym->CanInline = false; | |
| 175 | ||
| 176 | // Tell LTO not to eliminate these symbols. | |
| 177 | Sym->IsUsedInRegularObj = true; | |
| 178 | Wrap->IsUsedInRegularObj = true; | |
| 179 | } | |
| 180 | ||
| 181 | // Apply symbol renames created by -wrap. The renames are created | |
| 182 | // before LTO in addSymbolWrap() to have a chance to inform LTO (if | |
| 183 | // LTO is running) not to include these symbols in IPO. Now that the | |
| 184 | // symbols are finalized, we can perform the replacement. | |
| 185 | void SymbolTable::applySymbolWrap() { | |
| 186 | // This function rotates 3 symbols: | |
| 187 | // | |
| 188 | // __real_sym becomes sym | |
| 189 | // sym becomes __wrap_sym | |
| 190 | // __wrap_sym becomes __real_sym | |
| 191 | // | |
| 192 | // The last part is special in that we don't want to change what references to | |
| 193 | // __wrap_sym point to, we just want have __real_sym in the symbol table. | |
| 194 | ||
| 195 | for (WrappedSymbol &W : WrappedSymbols) { | |
| 196 | // First, make a copy of __real_sym. | |
| 197 | Symbol *Real = nullptr; | |
| 198 | if (W.Real->isDefined()) { | |
| 199 | Real = reinterpret_cast<Symbol *>(make<SymbolUnion>()); | |
| 200 | memcpy(Real, W.Real, sizeof(SymbolUnion)); | |
| 201 | } | |
| 202 | ||
| 203 | // Replace __real_sym with sym and sym with __wrap_sym. | |
| 204 | memcpy(W.Real, W.Sym, sizeof(SymbolUnion)); | |
| 205 | memcpy(W.Sym, W.Wrap, sizeof(SymbolUnion)); | |
| 206 | ||
| 207 | // We now have two copies of __wrap_sym. Drop one. | |
| 208 | W.Wrap->IsUsedInRegularObj = false; | |
| 209 | ||
| 210 | if (Real) | |
| 211 | SymVector.push_back(Real); | |
| 212 | } | |
| 169 | // Now renaming is complete. No one refers Real symbol. We could leave | |
| 170 | // Real as-is, but if Real is written to the symbol table, that may | |
| 171 | // contain irrelevant values. So, we copy all values from Sym to Real. | |
| 172 | StringRef S = Real->getName(); | |
| 173 | memcpy(Real, Sym, sizeof(SymbolUnion)); | |
| 174 | Real->setName(S); | |
| 213 | 175 | } |
| 214 | 176 | |
| 215 | 177 | static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { |
| ... | ... | @@ -221,7 +183,7 @@ static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) { |
| 221 | 183 | } |
| 222 | 184 | |
| 223 | 185 | // Find an existing symbol or create and insert a new one. |
| 224 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) { | |
| 186 | std::pair<Symbol *, bool> SymbolTable::insertName(StringRef Name) { | |
| 225 | 187 | // <name>@@<version> means the symbol is the default version. In that |
| 226 | 188 | // case <name>@@<version> will be used to resolve references to <name>. |
| 227 | 189 | // |
| ... | ... | @@ -239,34 +201,34 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) { |
| 239 | 201 | |
| 240 | 202 | if (SymIndex == -1) { |
| 241 | 203 | SymIndex = SymVector.size(); |
| 242 | IsNew = Traced = true; | |
| 204 | IsNew = true; | |
| 205 | Traced = true; | |
| 243 | 206 | } |
| 244 | 207 | |
| 245 | Symbol *Sym; | |
| 246 | if (IsNew) { | |
| 247 | Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); | |
| 248 | Sym->Visibility = STV_DEFAULT; | |
| 249 | Sym->IsUsedInRegularObj = false; | |
| 250 | Sym->ExportDynamic = false; | |
| 251 | Sym->CanInline = true; | |
| 252 | Sym->Traced = Traced; | |
| 253 | Sym->VersionId = Config->DefaultSymbolVersion; | |
| 254 | SymVector.push_back(Sym); | |
| 255 | } else { | |
| 256 | Sym = SymVector[SymIndex]; | |
| 257 | } | |
| 258 | return {Sym, IsNew}; | |
| 208 | if (!IsNew) | |
| 209 | return {SymVector[SymIndex], false}; | |
| 210 | ||
| 211 | auto *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); | |
| 212 | Sym->SymbolKind = Symbol::PlaceholderKind; | |
| 213 | Sym->Visibility = STV_DEFAULT; | |
| 214 | Sym->IsUsedInRegularObj = false; | |
| 215 | Sym->ExportDynamic = false; | |
| 216 | Sym->CanInline = true; | |
| 217 | Sym->Traced = Traced; | |
| 218 | Sym->VersionId = Config->DefaultSymbolVersion; | |
| 219 | SymVector.push_back(Sym); | |
| 220 | return {Sym, true}; | |
| 259 | 221 | } |
| 260 | 222 | |
| 261 | 223 | // Find an existing symbol or create and insert a new one, then apply the given |
| 262 | 224 | // attributes. |
| 263 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, uint8_t Type, | |
| 225 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, | |
| 264 | 226 | uint8_t Visibility, |
| 265 | 227 | bool CanOmitFromDynSym, |
| 266 | 228 | InputFile *File) { |
| 267 | 229 | Symbol *S; |
| 268 | 230 | bool WasInserted; |
| 269 | std::tie(S, WasInserted) = insert(Name); | |
| 231 | std::tie(S, WasInserted) = insertName(Name); | |
| 270 | 232 | |
| 271 | 233 | // Merge in the new symbol's visibility. |
| 272 | 234 | S->Visibility = getMinVisibility(S->Visibility, Visibility); |
| ... | ... | @@ -277,21 +239,9 @@ std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, uint8_t Type, |
| 277 | 239 | if (!File || File->kind() == InputFile::ObjKind) |
| 278 | 240 | S->IsUsedInRegularObj = true; |
| 279 | 241 | |
| 280 | if (!WasInserted && S->Type != Symbol::UnknownType && | |
| 281 | ((Type == STT_TLS) != S->isTls())) { | |
| 282 | error("TLS attribute mismatch: " + toString(*S) + "\n>>> defined in " + | |
| 283 | toString(S->File) + "\n>>> defined in " + toString(File)); | |
| 284 | } | |
| 285 | ||
| 286 | 242 | return {S, WasInserted}; |
| 287 | 243 | } |
| 288 | 244 | |
| 289 | template <class ELFT> Symbol *SymbolTable::addUndefined(StringRef Name) { | |
| 290 | return addUndefined<ELFT>(Name, STB_GLOBAL, STV_DEFAULT, | |
| 291 | /*Type*/ 0, | |
| 292 | /*CanOmitFromDynSym*/ false, /*File*/ nullptr); | |
| 293 | } | |
| 294 | ||
| 295 | 245 | static uint8_t getVisibility(uint8_t StOther) { return StOther & 3; } |
| 296 | 246 | |
| 297 | 247 | template <class ELFT> |
| ... | ... | @@ -301,8 +251,7 @@ Symbol *SymbolTable::addUndefined(StringRef Name, uint8_t Binding, |
| 301 | 251 | Symbol *S; |
| 302 | 252 | bool WasInserted; |
| 303 | 253 | uint8_t Visibility = getVisibility(StOther); |
| 304 | std::tie(S, WasInserted) = | |
| 305 | insert(Name, Type, Visibility, CanOmitFromDynSym, File); | |
| 254 | std::tie(S, WasInserted) = insert(Name, Visibility, CanOmitFromDynSym, File); | |
| 306 | 255 | |
| 307 | 256 | // An undefined symbol with non default visibility must be satisfied |
| 308 | 257 | // in the same DSO. |
| ... | ... | @@ -314,10 +263,6 @@ Symbol *SymbolTable::addUndefined(StringRef Name, uint8_t Binding, |
| 314 | 263 | if (S->isShared() || S->isLazy() || (S->isUndefined() && Binding != STB_WEAK)) |
| 315 | 264 | S->Binding = Binding; |
| 316 | 265 | |
| 317 | if (!Config->GcSections && Binding != STB_WEAK) | |
| 318 | if (auto *SS = dyn_cast<SharedSymbol>(S)) | |
| 319 | SS->getFile<ELFT>().IsNeeded = true; | |
| 320 | ||
| 321 | 266 | if (S->isLazy()) { |
| 322 | 267 | // An undefined weak will not fetch archive members. See comment on Lazy in |
| 323 | 268 | // Symbols.h for the details. |
| ... | ... | @@ -450,7 +395,7 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment, |
| 450 | 395 | InputFile &File) { |
| 451 | 396 | Symbol *S; |
| 452 | 397 | bool WasInserted; |
| 453 | std::tie(S, WasInserted) = insert(N, Type, getVisibility(StOther), | |
| 398 | std::tie(S, WasInserted) = insert(N, getVisibility(StOther), | |
| 454 | 399 | /*CanOmitFromDynSym*/ false, &File); |
| 455 | 400 | |
| 456 | 401 | int Cmp = compareDefined(S, WasInserted, Binding, N); |
| ... | ... | @@ -487,12 +432,6 @@ Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment, |
| 487 | 432 | return S; |
| 488 | 433 | } |
| 489 | 434 | |
| 490 | static void reportDuplicate(Symbol *Sym, InputFile *NewFile) { | |
| 491 | if (!Config->AllowMultipleDefinition) | |
| 492 | error("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " + | |
| 493 | toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); | |
| 494 | } | |
| 495 | ||
| 496 | 435 | static void reportDuplicate(Symbol *Sym, InputFile *NewFile, |
| 497 | 436 | InputSectionBase *ErrSec, uint64_t ErrOffset) { |
| 498 | 437 | if (Config->AllowMultipleDefinition) |
| ... | ... | @@ -500,7 +439,8 @@ static void reportDuplicate(Symbol *Sym, InputFile *NewFile, |
| 500 | 439 | |
| 501 | 440 | Defined *D = cast<Defined>(Sym); |
| 502 | 441 | if (!D->Section || !ErrSec) { |
| 503 | reportDuplicate(Sym, NewFile); | |
| 442 | error("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " + | |
| 443 | toString(Sym->File) + "\n>>> defined in " + toString(NewFile)); | |
| 504 | 444 | return; |
| 505 | 445 | } |
| 506 | 446 | |
| ... | ... | @@ -527,12 +467,12 @@ static void reportDuplicate(Symbol *Sym, InputFile *NewFile, |
| 527 | 467 | error(Msg); |
| 528 | 468 | } |
| 529 | 469 | |
| 530 | Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, | |
| 531 | uint64_t Value, uint64_t Size, uint8_t Binding, | |
| 532 | SectionBase *Section, InputFile *File) { | |
| 470 | Defined *SymbolTable::addDefined(StringRef Name, uint8_t StOther, uint8_t Type, | |
| 471 | uint64_t Value, uint64_t Size, uint8_t Binding, | |
| 472 | SectionBase *Section, InputFile *File) { | |
| 533 | 473 | Symbol *S; |
| 534 | 474 | bool WasInserted; |
| 535 | std::tie(S, WasInserted) = insert(Name, Type, getVisibility(StOther), | |
| 475 | std::tie(S, WasInserted) = insert(Name, getVisibility(StOther), | |
| 536 | 476 | /*CanOmitFromDynSym*/ false, File); |
| 537 | 477 | int Cmp = compareDefinedNonCommon(S, WasInserted, Binding, Section == nullptr, |
| 538 | 478 | Value, Name); |
| ... | ... | @@ -542,7 +482,7 @@ Symbol *SymbolTable::addRegular(StringRef Name, uint8_t StOther, uint8_t Type, |
| 542 | 482 | else if (Cmp == 0) |
| 543 | 483 | reportDuplicate(S, File, dyn_cast_or_null<InputSectionBase>(Section), |
| 544 | 484 | Value); |
| 545 | return S; | |
| 485 | return cast<Defined>(S); | |
| 546 | 486 | } |
| 547 | 487 | |
| 548 | 488 | template <typename ELFT> |
| ... | ... | @@ -554,7 +494,7 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> &File, |
| 554 | 494 | // unchanged. |
| 555 | 495 | Symbol *S; |
| 556 | 496 | bool WasInserted; |
| 557 | std::tie(S, WasInserted) = insert(Name, Sym.getType(), STV_DEFAULT, | |
| 497 | std::tie(S, WasInserted) = insert(Name, STV_DEFAULT, | |
| 558 | 498 | /*CanOmitFromDynSym*/ true, &File); |
| 559 | 499 | // Make sure we preempt DSO symbols with default visibility. |
| 560 | 500 | if (Sym.getVisibility() == STV_DEFAULT) |
| ... | ... | @@ -562,19 +502,16 @@ void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> &File, |
| 562 | 502 | |
| 563 | 503 | // An undefined symbol with non default visibility must be satisfied |
| 564 | 504 | // in the same DSO. |
| 565 | if (WasInserted || | |
| 566 | ((S->isUndefined() || S->isLazy()) && S->Visibility == STV_DEFAULT)) { | |
| 567 | uint8_t Binding = S->Binding; | |
| 568 | bool WasUndefined = S->isUndefined(); | |
| 569 | replaceSymbol<SharedSymbol>(S, File, Name, Sym.getBinding(), Sym.st_other, | |
| 505 | auto Replace = [&](uint8_t Binding) { | |
| 506 | replaceSymbol<SharedSymbol>(S, File, Name, Binding, Sym.st_other, | |
| 570 | 507 | Sym.getType(), Sym.st_value, Sym.st_size, |
| 571 | 508 | Alignment, VerdefIndex); |
| 572 | if (!WasInserted) { | |
| 573 | S->Binding = Binding; | |
| 574 | if (!S->isWeak() && !Config->GcSections && WasUndefined) | |
| 575 | File.IsNeeded = true; | |
| 576 | } | |
| 577 | } | |
| 509 | }; | |
| 510 | ||
| 511 | if (WasInserted) | |
| 512 | Replace(Sym.getBinding()); | |
| 513 | else if (S->Visibility == STV_DEFAULT && (S->isUndefined() || S->isLazy())) | |
| 514 | Replace(S->Binding); | |
| 578 | 515 | } |
| 579 | 516 | |
| 580 | 517 | Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding, |
| ... | ... | @@ -583,13 +520,13 @@ Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding, |
| 583 | 520 | Symbol *S; |
| 584 | 521 | bool WasInserted; |
| 585 | 522 | std::tie(S, WasInserted) = |
| 586 | insert(Name, Type, getVisibility(StOther), CanOmitFromDynSym, &F); | |
| 523 | insert(Name, getVisibility(StOther), CanOmitFromDynSym, &F); | |
| 587 | 524 | int Cmp = compareDefinedNonCommon(S, WasInserted, Binding, |
| 588 | 525 | /*IsAbs*/ false, /*Value*/ 0, Name); |
| 589 | 526 | if (Cmp > 0) |
| 590 | 527 | replaceSymbol<Defined>(S, &F, Name, Binding, StOther, Type, 0, 0, nullptr); |
| 591 | 528 | else if (Cmp == 0) |
| 592 | reportDuplicate(S, &F); | |
| 529 | reportDuplicate(S, &F, nullptr, 0); | |
| 593 | 530 | return S; |
| 594 | 531 | } |
| 595 | 532 | |
| ... | ... | @@ -602,18 +539,14 @@ Symbol *SymbolTable::find(StringRef Name) { |
| 602 | 539 | return SymVector[It->second]; |
| 603 | 540 | } |
| 604 | 541 | |
| 605 | // This is used to handle lazy symbols. May replace existent | |
| 606 | // symbol with lazy version or request to Fetch it. | |
| 607 | template <class ELFT, typename LazyT, typename... ArgT> | |
| 608 | static void replaceOrFetchLazy(StringRef Name, InputFile &File, | |
| 609 | llvm::function_ref<InputFile *()> Fetch, | |
| 610 | ArgT &&... Arg) { | |
| 542 | template <class ELFT> | |
| 543 | void SymbolTable::addLazyArchive(StringRef Name, ArchiveFile &File, | |
| 544 | const object::Archive::Symbol Sym) { | |
| 611 | 545 | Symbol *S; |
| 612 | 546 | bool WasInserted; |
| 613 | std::tie(S, WasInserted) = Symtab->insert(Name); | |
| 547 | std::tie(S, WasInserted) = insertName(Name); | |
| 614 | 548 | if (WasInserted) { |
| 615 | replaceSymbol<LazyT>(S, File, Symbol::UnknownType, | |
| 616 | std::forward<ArgT>(Arg)...); | |
| 549 | replaceSymbol<LazyArchive>(S, File, STT_NOTYPE, Sym); | |
| 617 | 550 | return; |
| 618 | 551 | } |
| 619 | 552 | if (!S->isUndefined()) |
| ... | ... | @@ -622,26 +555,37 @@ static void replaceOrFetchLazy(StringRef Name, InputFile &File, |
| 622 | 555 | // An undefined weak will not fetch archive members. See comment on Lazy in |
| 623 | 556 | // Symbols.h for the details. |
| 624 | 557 | if (S->isWeak()) { |
| 625 | replaceSymbol<LazyT>(S, File, S->Type, std::forward<ArgT>(Arg)...); | |
| 558 | replaceSymbol<LazyArchive>(S, File, S->Type, Sym); | |
| 626 | 559 | S->Binding = STB_WEAK; |
| 627 | 560 | return; |
| 628 | 561 | } |
| 629 | 562 | |
| 630 | if (InputFile *F = Fetch()) | |
| 631 | Symtab->addFile<ELFT>(F); | |
| 563 | if (InputFile *F = File.fetch(Sym)) | |
| 564 | addFile<ELFT>(F); | |
| 632 | 565 | } |
| 633 | 566 | |
| 634 | 567 | template <class ELFT> |
| 635 | void SymbolTable::addLazyArchive(StringRef Name, ArchiveFile &F, | |
| 636 | const object::Archive::Symbol Sym) { | |
| 637 | replaceOrFetchLazy<ELFT, LazyArchive>(Name, F, [&]() { return F.fetch(Sym); }, | |
| 638 | Sym); | |
| 639 | } | |
| 568 | void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &File) { | |
| 569 | Symbol *S; | |
| 570 | bool WasInserted; | |
| 571 | std::tie(S, WasInserted) = insertName(Name); | |
| 572 | if (WasInserted) { | |
| 573 | replaceSymbol<LazyObject>(S, File, STT_NOTYPE, Name); | |
| 574 | return; | |
| 575 | } | |
| 576 | if (!S->isUndefined()) | |
| 577 | return; | |
| 640 | 578 | |
| 641 | template <class ELFT> | |
| 642 | void SymbolTable::addLazyObject(StringRef Name, LazyObjFile &Obj) { | |
| 643 | replaceOrFetchLazy<ELFT, LazyObject>(Name, Obj, [&]() { return Obj.fetch(); }, | |
| 644 | Name); | |
| 579 | // An undefined weak will not fetch archive members. See comment on Lazy in | |
| 580 | // Symbols.h for the details. | |
| 581 | if (S->isWeak()) { | |
| 582 | replaceSymbol<LazyObject>(S, File, S->Type, Name); | |
| 583 | S->Binding = STB_WEAK; | |
| 584 | return; | |
| 585 | } | |
| 586 | ||
| 587 | if (InputFile *F = File.fetch()) | |
| 588 | addFile<ELFT>(F); | |
| 645 | 589 | } |
| 646 | 590 | |
| 647 | 591 | template <class ELFT> void SymbolTable::fetchLazy(Symbol *Sym) { |
| ... | ... | @@ -822,16 +766,6 @@ template void SymbolTable::addFile<ELF32BE>(InputFile *); |
| 822 | 766 | template void SymbolTable::addFile<ELF64LE>(InputFile *); |
| 823 | 767 | template void SymbolTable::addFile<ELF64BE>(InputFile *); |
| 824 | 768 | |
| 825 | template void SymbolTable::addSymbolWrap<ELF32LE>(StringRef); | |
| 826 | template void SymbolTable::addSymbolWrap<ELF32BE>(StringRef); | |
| 827 | template void SymbolTable::addSymbolWrap<ELF64LE>(StringRef); | |
| 828 | template void SymbolTable::addSymbolWrap<ELF64BE>(StringRef); | |
| 829 | ||
| 830 | template Symbol *SymbolTable::addUndefined<ELF32LE>(StringRef); | |
| 831 | template Symbol *SymbolTable::addUndefined<ELF32BE>(StringRef); | |
| 832 | template Symbol *SymbolTable::addUndefined<ELF64LE>(StringRef); | |
| 833 | template Symbol *SymbolTable::addUndefined<ELF64BE>(StringRef); | |
| 834 | ||
| 835 | 769 | template Symbol *SymbolTable::addUndefined<ELF32LE>(StringRef, uint8_t, uint8_t, |
| 836 | 770 | uint8_t, bool, InputFile *); |
| 837 | 771 | template Symbol *SymbolTable::addUndefined<ELF32BE>(StringRef, uint8_t, uint8_t, |
deps/lld/ELF/SymbolTable.h+10-24| ... | ... | @@ -37,22 +37,17 @@ class SymbolTable { |
| 37 | 37 | public: |
| 38 | 38 | template <class ELFT> void addFile(InputFile *File); |
| 39 | 39 | template <class ELFT> void addCombinedLTOObject(); |
| 40 | template <class ELFT> void addSymbolWrap(StringRef Name); | |
| 41 | void applySymbolWrap(); | |
| 40 | void wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap); | |
| 42 | 41 | |
| 43 | 42 | ArrayRef<Symbol *> getSymbols() const { return SymVector; } |
| 44 | 43 | |
| 45 | Defined *addAbsolute(StringRef Name, | |
| 46 | uint8_t Visibility = llvm::ELF::STV_HIDDEN, | |
| 47 | uint8_t Binding = llvm::ELF::STB_GLOBAL); | |
| 48 | ||
| 49 | template <class ELFT> Symbol *addUndefined(StringRef Name); | |
| 50 | 44 | template <class ELFT> |
| 51 | 45 | Symbol *addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther, |
| 52 | 46 | uint8_t Type, bool CanOmitFromDynSym, InputFile *File); |
| 53 | Symbol *addRegular(StringRef Name, uint8_t StOther, uint8_t Type, | |
| 54 | uint64_t Value, uint64_t Size, uint8_t Binding, | |
| 55 | SectionBase *Section, InputFile *File); | |
| 47 | ||
| 48 | Defined *addDefined(StringRef Name, uint8_t StOther, uint8_t Type, | |
| 49 | uint64_t Value, uint64_t Size, uint8_t Binding, | |
| 50 | SectionBase *Section, InputFile *File); | |
| 56 | 51 | |
| 57 | 52 | template <class ELFT> |
| 58 | 53 | void addShared(StringRef Name, SharedFile<ELFT> &F, |
| ... | ... | @@ -72,10 +67,8 @@ public: |
| 72 | 67 | uint8_t Binding, uint8_t StOther, uint8_t Type, |
| 73 | 68 | InputFile &File); |
| 74 | 69 | |
| 75 | std::pair<Symbol *, bool> insert(StringRef Name); | |
| 76 | std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Type, | |
| 77 | uint8_t Visibility, bool CanOmitFromDynSym, | |
| 78 | InputFile *File); | |
| 70 | std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Visibility, | |
| 71 | bool CanOmitFromDynSym, InputFile *File); | |
| 79 | 72 | |
| 80 | 73 | template <class ELFT> void fetchLazy(Symbol *Sym); |
| 81 | 74 | |
| ... | ... | @@ -88,6 +81,8 @@ public: |
| 88 | 81 | void handleDynamicList(); |
| 89 | 82 | |
| 90 | 83 | private: |
| 84 | std::pair<Symbol *, bool> insertName(StringRef Name); | |
| 85 | ||
| 91 | 86 | std::vector<Symbol *> findByVersion(SymbolVersion Ver); |
| 92 | 87 | std::vector<Symbol *> findAllByVersion(SymbolVersion Ver); |
| 93 | 88 | |
| ... | ... | @@ -113,7 +108,7 @@ private: |
| 113 | 108 | llvm::DenseSet<llvm::CachedHashStringRef> ComdatGroups; |
| 114 | 109 | |
| 115 | 110 | // Set of .so files to not link the same shared object file more than once. |
| 116 | llvm::DenseSet<StringRef> SoNames; | |
| 111 | llvm::DenseMap<StringRef, InputFile *> SoNames; | |
| 117 | 112 | |
| 118 | 113 | // A map from demangled symbol names to their symbol objects. |
| 119 | 114 | // This mapping is 1:N because two symbols with different versions |
| ... | ... | @@ -121,15 +116,6 @@ private: |
| 121 | 116 | // directive in version scripts. |
| 122 | 117 | llvm::Optional<llvm::StringMap<std::vector<Symbol *>>> DemangledSyms; |
| 123 | 118 | |
| 124 | struct WrappedSymbol { | |
| 125 | Symbol *Sym; | |
| 126 | Symbol *Real; | |
| 127 | Symbol *Wrap; | |
| 128 | }; | |
| 129 | ||
| 130 | // For -wrap. | |
| 131 | std::vector<WrappedSymbol> WrappedSymbols; | |
| 132 | ||
| 133 | 119 | // For LTO. |
| 134 | 120 | std::unique_ptr<BitcodeCompiler> LTO; |
| 135 | 121 | }; |
deps/lld/ELF/Symbols.cpp+46-14| ... | ... | @@ -38,6 +38,7 @@ Defined *ElfSym::GlobalOffsetTable; |
| 38 | 38 | Defined *ElfSym::MipsGp; |
| 39 | 39 | Defined *ElfSym::MipsGpDisp; |
| 40 | 40 | Defined *ElfSym::MipsLocalGp; |
| 41 | Defined *ElfSym::RelaIpltStart; | |
| 41 | 42 | Defined *ElfSym::RelaIpltEnd; |
| 42 | 43 | |
| 43 | 44 | static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) { |
| ... | ... | @@ -90,10 +91,15 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) { |
| 90 | 91 | uint64_t VA = IS->getVA(Offset); |
| 91 | 92 | |
| 92 | 93 | if (D.isTls() && !Config->Relocatable) { |
| 93 | if (!Out::TlsPhdr) | |
| 94 | // Use the address of the TLS segment's first section rather than the | |
| 95 | // segment's address, because segment addresses aren't initialized until | |
| 96 | // after sections are finalized. (e.g. Measuring the size of .rela.dyn | |
| 97 | // for Android relocation packing requires knowing TLS symbol addresses | |
| 98 | // during section finalization.) | |
| 99 | if (!Out::TlsPhdr || !Out::TlsPhdr->FirstSec) | |
| 94 | 100 | fatal(toString(D.File) + |
| 95 | 101 | " has an STT_TLS symbol but doesn't have an SHF_TLS section"); |
| 96 | return VA - Out::TlsPhdr->p_vaddr; | |
| 102 | return VA - Out::TlsPhdr->FirstSec->Addr; | |
| 97 | 103 | } |
| 98 | 104 | return VA; |
| 99 | 105 | } |
| ... | ... | @@ -102,7 +108,10 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) { |
| 102 | 108 | return 0; |
| 103 | 109 | case Symbol::LazyArchiveKind: |
| 104 | 110 | case Symbol::LazyObjectKind: |
| 105 | llvm_unreachable("lazy symbol reached writer"); | |
| 111 | assert(Sym.IsUsedInRegularObj && "lazy symbol reached writer"); | |
| 112 | return 0; | |
| 113 | case Symbol::PlaceholderKind: | |
| 114 | llvm_unreachable("placeholder symbol reached writer"); | |
| 106 | 115 | } |
| 107 | 116 | llvm_unreachable("invalid symbol kind"); |
| 108 | 117 | } |
| ... | ... | @@ -112,7 +121,7 @@ uint64_t Symbol::getVA(int64_t Addend) const { |
| 112 | 121 | return OutVA + Addend; |
| 113 | 122 | } |
| 114 | 123 | |
| 115 | uint64_t Symbol::getGotVA() const { return InX::Got->getVA() + getGotOffset(); } | |
| 124 | uint64_t Symbol::getGotVA() const { return In.Got->getVA() + getGotOffset(); } | |
| 116 | 125 | |
| 117 | 126 | uint64_t Symbol::getGotOffset() const { |
| 118 | 127 | return GotIndex * Target->GotEntrySize; |
| ... | ... | @@ -120,8 +129,8 @@ uint64_t Symbol::getGotOffset() const { |
| 120 | 129 | |
| 121 | 130 | uint64_t Symbol::getGotPltVA() const { |
| 122 | 131 | if (this->IsInIgot) |
| 123 | return InX::IgotPlt->getVA() + getGotPltOffset(); | |
| 124 | return InX::GotPlt->getVA() + getGotPltOffset(); | |
| 132 | return In.IgotPlt->getVA() + getGotPltOffset(); | |
| 133 | return In.GotPlt->getVA() + getGotPltOffset(); | |
| 125 | 134 | } |
| 126 | 135 | |
| 127 | 136 | uint64_t Symbol::getGotPltOffset() const { |
| ... | ... | @@ -130,15 +139,20 @@ uint64_t Symbol::getGotPltOffset() const { |
| 130 | 139 | return (PltIndex + Target->GotPltHeaderEntriesNum) * Target->GotPltEntrySize; |
| 131 | 140 | } |
| 132 | 141 | |
| 142 | uint64_t Symbol::getPPC64LongBranchOffset() const { | |
| 143 | assert(PPC64BranchltIndex != 0xffff); | |
| 144 | return PPC64BranchltIndex * Target->GotPltEntrySize; | |
| 145 | } | |
| 146 | ||
| 133 | 147 | uint64_t Symbol::getPltVA() const { |
| 134 | if (this->IsInIplt) | |
| 135 | return InX::Iplt->getVA() + PltIndex * Target->PltEntrySize; | |
| 136 | return InX::Plt->getVA() + Target->getPltEntryOffset(PltIndex); | |
| 148 | PltSection *Plt = IsInIplt ? In.Iplt : In.Plt; | |
| 149 | return Plt->getVA() + Plt->HeaderSize + PltIndex * Target->PltEntrySize; | |
| 137 | 150 | } |
| 138 | 151 | |
| 139 | uint64_t Symbol::getPltOffset() const { | |
| 140 | assert(!this->IsInIplt); | |
| 141 | return Target->getPltEntryOffset(PltIndex); | |
| 152 | uint64_t Symbol::getPPC64LongBranchTableVA() const { | |
| 153 | assert(PPC64BranchltIndex != 0xffff); | |
| 154 | return In.PPC64LongBranchTarget->getVA() + | |
| 155 | PPC64BranchltIndex * Target->GotPltEntrySize; | |
| 142 | 156 | } |
| 143 | 157 | |
| 144 | 158 | uint64_t Symbol::getSize() const { |
| ... | ... | @@ -204,12 +218,21 @@ void Symbol::parseSymbolVersion() { |
| 204 | 218 | |
| 205 | 219 | InputFile *LazyArchive::fetch() { return cast<ArchiveFile>(File)->fetch(Sym); } |
| 206 | 220 | |
| 221 | MemoryBufferRef LazyArchive::getMemberBuffer() { | |
| 222 | Archive::Child C = CHECK( | |
| 223 | Sym.getMember(), "could not get the member for symbol " + Sym.getName()); | |
| 224 | ||
| 225 | return CHECK(C.getMemoryBufferRef(), | |
| 226 | "could not get the buffer for the member defining symbol " + | |
| 227 | Sym.getName()); | |
| 228 | } | |
| 229 | ||
| 207 | 230 | uint8_t Symbol::computeBinding() const { |
| 208 | 231 | if (Config->Relocatable) |
| 209 | 232 | return Binding; |
| 210 | 233 | if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED) |
| 211 | 234 | return STB_LOCAL; |
| 212 | if (VersionId == VER_NDX_LOCAL && isDefined()) | |
| 235 | if (VersionId == VER_NDX_LOCAL && isDefined() && !IsPreemptible) | |
| 213 | 236 | return STB_LOCAL; |
| 214 | 237 | if (!Config->GnuUnique && Binding == STB_GNU_UNIQUE) |
| 215 | 238 | return STB_GLOBAL; |
| ... | ... | @@ -243,10 +266,19 @@ void elf::printTraceSymbol(Symbol *Sym) { |
| 243 | 266 | message(toString(Sym->File) + S + Sym->getName()); |
| 244 | 267 | } |
| 245 | 268 | |
| 246 | void elf::warnUnorderableSymbol(const Symbol *Sym) { | |
| 269 | void elf::maybeWarnUnorderableSymbol(const Symbol *Sym) { | |
| 247 | 270 | if (!Config->WarnSymbolOrdering) |
| 248 | 271 | return; |
| 249 | 272 | |
| 273 | // If UnresolvedPolicy::Ignore is used, no "undefined symbol" error/warning | |
| 274 | // is emitted. It makes sense to not warn on undefined symbols. | |
| 275 | // | |
| 276 | // Note, ld.bfd --symbol-ordering-file= does not warn on undefined symbols, | |
| 277 | // but we don't have to be compatible here. | |
| 278 | if (Sym->isUndefined() && | |
| 279 | Config->UnresolvedSymbols == UnresolvedPolicy::Ignore) | |
| 280 | return; | |
| 281 | ||
| 250 | 282 | const InputFile *File = Sym->File; |
| 251 | 283 | auto *D = dyn_cast<Defined>(Sym); |
| 252 | 284 |
deps/lld/ELF/Symbols.h+51-15| ... | ... | @@ -21,6 +21,14 @@ |
| 21 | 21 | #include "llvm/Object/ELF.h" |
| 22 | 22 | |
| 23 | 23 | namespace lld { |
| 24 | namespace elf { | |
| 25 | class Symbol; | |
| 26 | class InputFile; | |
| 27 | } // namespace elf | |
| 28 | ||
| 29 | std::string toString(const elf::Symbol &); | |
| 30 | std::string toString(const elf::InputFile *); | |
| 31 | ||
| 24 | 32 | namespace elf { |
| 25 | 33 | |
| 26 | 34 | class ArchiveFile; |
| ... | ... | @@ -50,6 +58,7 @@ struct StringRefZ { |
| 50 | 58 | class Symbol { |
| 51 | 59 | public: |
| 52 | 60 | enum Kind { |
| 61 | PlaceholderKind, | |
| 53 | 62 | DefinedKind, |
| 54 | 63 | SharedKind, |
| 55 | 64 | UndefinedKind, |
| ... | ... | @@ -70,6 +79,7 @@ public: |
| 70 | 79 | uint32_t DynsymIndex = 0; |
| 71 | 80 | uint32_t GotIndex = -1; |
| 72 | 81 | uint32_t PltIndex = -1; |
| 82 | ||
| 73 | 83 | uint32_t GlobalDynIndex = -1; |
| 74 | 84 | |
| 75 | 85 | // This field is a index to the symbol's version definition. |
| ... | ... | @@ -78,6 +88,9 @@ public: |
| 78 | 88 | // Version definition index. |
| 79 | 89 | uint16_t VersionId; |
| 80 | 90 | |
| 91 | // An index into the .branch_lt section on PPC64. | |
| 92 | uint16_t PPC64BranchltIndex = -1; | |
| 93 | ||
| 81 | 94 | // Symbol binding. This is not overwritten by replaceSymbol to track |
| 82 | 95 | // changes during resolution. In particular: |
| 83 | 96 | // - An undefined weak is still weak when it resolves to a shared library. |
| ... | ... | @@ -89,7 +102,7 @@ public: |
| 89 | 102 | uint8_t Type; // symbol type |
| 90 | 103 | uint8_t StOther; // st_other field value |
| 91 | 104 | |
| 92 | const uint8_t SymbolKind; | |
| 105 | uint8_t SymbolKind; | |
| 93 | 106 | |
| 94 | 107 | // Symbol visibility. This is the computed minimum visibility of all |
| 95 | 108 | // observed non-DSO symbols. |
| ... | ... | @@ -128,8 +141,12 @@ public: |
| 128 | 141 | return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind; |
| 129 | 142 | } |
| 130 | 143 | |
| 131 | // True if this is an undefined weak symbol. | |
| 132 | bool isUndefWeak() const { return isWeak() && isUndefined(); } | |
| 144 | // True if this is an undefined weak symbol. This only works once | |
| 145 | // all input files have been added. | |
| 146 | bool isUndefWeak() const { | |
| 147 | // See comment on lazy symbols for details. | |
| 148 | return isWeak() && (isUndefined() || isLazy()); | |
| 149 | } | |
| 133 | 150 | |
| 134 | 151 | StringRef getName() const { |
| 135 | 152 | if (NameSize == (uint32_t)-1) |
| ... | ... | @@ -137,10 +154,16 @@ public: |
| 137 | 154 | return {NameData, NameSize}; |
| 138 | 155 | } |
| 139 | 156 | |
| 157 | void setName(StringRef S) { | |
| 158 | NameData = S.data(); | |
| 159 | NameSize = S.size(); | |
| 160 | } | |
| 161 | ||
| 140 | 162 | void parseSymbolVersion(); |
| 141 | 163 | |
| 142 | 164 | bool isInGot() const { return GotIndex != -1U; } |
| 143 | 165 | bool isInPlt() const { return PltIndex != -1U; } |
| 166 | bool isInPPC64Branchlt() const { return PPC64BranchltIndex != 0xffff; } | |
| 144 | 167 | |
| 145 | 168 | uint64_t getVA(int64_t Addend = 0) const; |
| 146 | 169 | |
| ... | ... | @@ -149,7 +172,8 @@ public: |
| 149 | 172 | uint64_t getGotPltOffset() const; |
| 150 | 173 | uint64_t getGotPltVA() const; |
| 151 | 174 | uint64_t getPltVA() const; |
| 152 | uint64_t getPltOffset() const; | |
| 175 | uint64_t getPPC64LongBranchTableVA() const; | |
| 176 | uint64_t getPPC64LongBranchOffset() const; | |
| 153 | 177 | uint64_t getSize() const; |
| 154 | 178 | OutputSection *getOutputSection() const; |
| 155 | 179 | |
| ... | ... | @@ -159,7 +183,8 @@ protected: |
| 159 | 183 | : File(File), NameData(Name.Data), NameSize(Name.Size), Binding(Binding), |
| 160 | 184 | Type(Type), StOther(StOther), SymbolKind(K), NeedsPltAddr(false), |
| 161 | 185 | IsInIplt(false), IsInIgot(false), IsPreemptible(false), |
| 162 | Used(!Config->GcSections), NeedsTocRestore(false) {} | |
| 186 | Used(!Config->GcSections), NeedsTocRestore(false), | |
| 187 | ScriptDefined(false) {} | |
| 163 | 188 | |
| 164 | 189 | public: |
| 165 | 190 | // True the symbol should point to its PLT entry. |
| ... | ... | @@ -182,12 +207,8 @@ public: |
| 182 | 207 | // PPC64 toc pointer. |
| 183 | 208 | unsigned NeedsTocRestore : 1; |
| 184 | 209 | |
| 185 | // The Type field may also have this value. It means that we have not yet seen | |
| 186 | // a non-Lazy symbol with this name, so we don't know what its type is. The | |
| 187 | // Type field is normally set to this value for Lazy symbols unless we saw a | |
| 188 | // weak undefined symbol first, in which case we need to remember the original | |
| 189 | // symbol's type in order to check for TLS mismatches. | |
| 190 | enum { UnknownType = 255 }; | |
| 210 | // True if this symbol is defined by a linker script. | |
| 211 | unsigned ScriptDefined : 1; | |
| 191 | 212 | |
| 192 | 213 | bool isSection() const { return Type == llvm::ELF::STT_SECTION; } |
| 193 | 214 | bool isTls() const { return Type == llvm::ELF::STT_TLS; } |
| ... | ... | @@ -286,6 +307,7 @@ public: |
| 286 | 307 | static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; } |
| 287 | 308 | |
| 288 | 309 | InputFile *fetch(); |
| 310 | MemoryBufferRef getMemberBuffer(); | |
| 289 | 311 | |
| 290 | 312 | private: |
| 291 | 313 | const llvm::object::Archive::Symbol Sym; |
| ... | ... | @@ -330,7 +352,8 @@ struct ElfSym { |
| 330 | 352 | static Defined *MipsGpDisp; |
| 331 | 353 | static Defined *MipsLocalGp; |
| 332 | 354 | |
| 333 | // __rela_iplt_end or __rel_iplt_end | |
| 355 | // __rel{,a}_iplt_{start,end} symbols. | |
| 356 | static Defined *RelaIpltStart; | |
| 334 | 357 | static Defined *RelaIpltEnd; |
| 335 | 358 | }; |
| 336 | 359 | |
| ... | ... | @@ -349,6 +372,8 @@ void printTraceSymbol(Symbol *Sym); |
| 349 | 372 | |
| 350 | 373 | template <typename T, typename... ArgT> |
| 351 | 374 | void replaceSymbol(Symbol *S, ArgT &&... Arg) { |
| 375 | using llvm::ELF::STT_TLS; | |
| 376 | ||
| 352 | 377 | static_assert(std::is_trivially_destructible<T>(), |
| 353 | 378 | "Symbol types must be trivially destructible"); |
| 354 | 379 | static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small"); |
| ... | ... | @@ -367,6 +392,19 @@ void replaceSymbol(Symbol *S, ArgT &&... Arg) { |
| 367 | 392 | S->ExportDynamic = Sym.ExportDynamic; |
| 368 | 393 | S->CanInline = Sym.CanInline; |
| 369 | 394 | S->Traced = Sym.Traced; |
| 395 | S->ScriptDefined = Sym.ScriptDefined; | |
| 396 | ||
| 397 | // Symbols representing thread-local variables must be referenced by | |
| 398 | // TLS-aware relocations, and non-TLS symbols must be reference by | |
| 399 | // non-TLS relocations, so there's a clear distinction between TLS | |
| 400 | // and non-TLS symbols. It is an error if the same symbol is defined | |
| 401 | // as a TLS symbol in one file and as a non-TLS symbol in other file. | |
| 402 | bool TlsMismatch = (Sym.Type == STT_TLS && S->Type != STT_TLS) || | |
| 403 | (Sym.Type != STT_TLS && S->Type == STT_TLS); | |
| 404 | ||
| 405 | if (Sym.SymbolKind != Symbol::PlaceholderKind && TlsMismatch && !Sym.isLazy()) | |
| 406 | error("TLS attribute mismatch: " + toString(Sym) + "\n>>> defined in " + | |
| 407 | toString(Sym.File) + "\n>>> defined in " + toString(S->File)); | |
| 370 | 408 | |
| 371 | 409 | // Print out a log message if --trace-symbol was specified. |
| 372 | 410 | // This is for debugging. |
| ... | ... | @@ -374,10 +412,8 @@ void replaceSymbol(Symbol *S, ArgT &&... Arg) { |
| 374 | 412 | printTraceSymbol(S); |
| 375 | 413 | } |
| 376 | 414 | |
| 377 | void warnUnorderableSymbol(const Symbol *Sym); | |
| 415 | void maybeWarnUnorderableSymbol(const Symbol *Sym); | |
| 378 | 416 | } // namespace elf |
| 379 | ||
| 380 | std::string toString(const elf::Symbol &B); | |
| 381 | 417 | } // namespace lld |
| 382 | 418 | |
| 383 | 419 | #endif |
deps/lld/ELF/SyntheticSections.cpp+290-214| ... | ... | @@ -30,10 +30,11 @@ |
| 30 | 30 | #include "lld/Common/Threads.h" |
| 31 | 31 | #include "lld/Common/Version.h" |
| 32 | 32 | #include "llvm/ADT/SetOperations.h" |
| 33 | #include "llvm/ADT/StringExtras.h" | |
| 33 | 34 | #include "llvm/BinaryFormat/Dwarf.h" |
| 34 | 35 | #include "llvm/DebugInfo/DWARF/DWARFDebugPubTable.h" |
| 35 | #include "llvm/Object/Decompressor.h" | |
| 36 | 36 | #include "llvm/Object/ELFObjectFile.h" |
| 37 | #include "llvm/Support/Compression.h" | |
| 37 | 38 | #include "llvm/Support/Endian.h" |
| 38 | 39 | #include "llvm/Support/LEB128.h" |
| 39 | 40 | #include "llvm/Support/MD5.h" |
| ... | ... | @@ -104,7 +105,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { |
| 104 | 105 | Create = true; |
| 105 | 106 | |
| 106 | 107 | std::string Filename = toString(Sec->File); |
| 107 | const size_t Size = Sec->Data.size(); | |
| 108 | const size_t Size = Sec->data().size(); | |
| 108 | 109 | // Older version of BFD (such as the default FreeBSD linker) concatenate |
| 109 | 110 | // .MIPS.abiflags instead of merging. To allow for this case (or potential |
| 110 | 111 | // zero padding) we ignore everything after the first Elf_Mips_ABIFlags |
| ... | ... | @@ -113,7 +114,7 @@ MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() { |
| 113 | 114 | Twine(Size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags))); |
| 114 | 115 | return nullptr; |
| 115 | 116 | } |
| 116 | auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(Sec->Data.data()); | |
| 117 | auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(Sec->data().data()); | |
| 117 | 118 | if (S->version != 0) { |
| 118 | 119 | error(Filename + ": unexpected .MIPS.abiflags version " + |
| 119 | 120 | Twine(S->version)); |
| ... | ... | @@ -153,7 +154,7 @@ template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *Buf) { |
| 153 | 154 | Options->size = getSize(); |
| 154 | 155 | |
| 155 | 156 | if (!Config->Relocatable) |
| 156 | Reginfo.ri_gp_value = InX::MipsGot->getGp(); | |
| 157 | Reginfo.ri_gp_value = In.MipsGot->getGp(); | |
| 157 | 158 | memcpy(Buf + sizeof(Elf_Mips_Options), &Reginfo, sizeof(Reginfo)); |
| 158 | 159 | } |
| 159 | 160 | |
| ... | ... | @@ -176,7 +177,7 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() { |
| 176 | 177 | Sec->Live = false; |
| 177 | 178 | |
| 178 | 179 | std::string Filename = toString(Sec->File); |
| 179 | ArrayRef<uint8_t> D = Sec->Data; | |
| 180 | ArrayRef<uint8_t> D = Sec->data(); | |
| 180 | 181 | |
| 181 | 182 | while (!D.empty()) { |
| 182 | 183 | if (D.size() < sizeof(Elf_Mips_Options)) { |
| ... | ... | @@ -210,7 +211,7 @@ MipsReginfoSection<ELFT>::MipsReginfoSection(Elf_Mips_RegInfo Reginfo) |
| 210 | 211 | |
| 211 | 212 | template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *Buf) { |
| 212 | 213 | if (!Config->Relocatable) |
| 213 | Reginfo.ri_gp_value = InX::MipsGot->getGp(); | |
| 214 | Reginfo.ri_gp_value = In.MipsGot->getGp(); | |
| 214 | 215 | memcpy(Buf, &Reginfo, sizeof(Reginfo)); |
| 215 | 216 | } |
| 216 | 217 | |
| ... | ... | @@ -232,12 +233,12 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() { |
| 232 | 233 | for (InputSectionBase *Sec : Sections) { |
| 233 | 234 | Sec->Live = false; |
| 234 | 235 | |
| 235 | if (Sec->Data.size() != sizeof(Elf_Mips_RegInfo)) { | |
| 236 | if (Sec->data().size() != sizeof(Elf_Mips_RegInfo)) { | |
| 236 | 237 | error(toString(Sec->File) + ": invalid size of .reginfo section"); |
| 237 | 238 | return nullptr; |
| 238 | 239 | } |
| 239 | 240 | |
| 240 | auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->Data.data()); | |
| 241 | auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->data().data()); | |
| 241 | 242 | Reginfo.ri_gprmask |= R->ri_gprmask; |
| 242 | 243 | Sec->getFile<ELFT>()->MipsGp0 = R->ri_gp_value; |
| 243 | 244 | }; |
| ... | ... | @@ -260,8 +261,8 @@ Defined *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, |
| 260 | 261 | uint64_t Size, InputSectionBase &Section) { |
| 261 | 262 | auto *S = make<Defined>(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type, |
| 262 | 263 | Value, Size, &Section); |
| 263 | if (InX::SymTab) | |
| 264 | InX::SymTab->addSymbol(S); | |
| 264 | if (In.SymTab) | |
| 265 | In.SymTab->addSymbol(S); | |
| 265 | 266 | return S; |
| 266 | 267 | } |
| 267 | 268 | |
| ... | ... | @@ -502,7 +503,7 @@ std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const { |
| 502 | 503 | uint8_t *Buf = getParent()->Loc + OutSecOff; |
| 503 | 504 | std::vector<FdeData> Ret; |
| 504 | 505 | |
| 505 | uint64_t VA = InX::EhFrameHdr->getVA(); | |
| 506 | uint64_t VA = In.EhFrameHdr->getVA(); | |
| 506 | 507 | for (CieRecord *Rec : CieRecords) { |
| 507 | 508 | uint8_t Enc = getFdeEncoding(Rec->Cie); |
| 508 | 509 | for (EhSectionPiece *Fde : Rec->Fdes) { |
| ... | ... | @@ -937,7 +938,7 @@ template <class ELFT> void MipsGotSection::build() { |
| 937 | 938 | Symbol *S = P.first; |
| 938 | 939 | uint64_t Offset = P.second * Config->Wordsize; |
| 939 | 940 | if (S->IsPreemptible) |
| 940 | InX::RelaDyn->addReloc(Target->TlsGotRel, this, Offset, S); | |
| 941 | In.RelaDyn->addReloc(Target->TlsGotRel, this, Offset, S); | |
| 941 | 942 | } |
| 942 | 943 | for (std::pair<Symbol *, size_t> &P : Got.DynTlsSymbols) { |
| 943 | 944 | Symbol *S = P.first; |
| ... | ... | @@ -945,7 +946,7 @@ template <class ELFT> void MipsGotSection::build() { |
| 945 | 946 | if (S == nullptr) { |
| 946 | 947 | if (!Config->Pic) |
| 947 | 948 | continue; |
| 948 | InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S); | |
| 949 | In.RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S); | |
| 949 | 950 | } else { |
| 950 | 951 | // When building a shared library we still need a dynamic relocation |
| 951 | 952 | // for the module index. Therefore only checking for |
| ... | ... | @@ -953,13 +954,13 @@ template <class ELFT> void MipsGotSection::build() { |
| 953 | 954 | // thread-locals that have been marked as local through a linker script) |
| 954 | 955 | if (!S->IsPreemptible && !Config->Pic) |
| 955 | 956 | continue; |
| 956 | InX::RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S); | |
| 957 | In.RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S); | |
| 957 | 958 | // However, we can skip writing the TLS offset reloc for non-preemptible |
| 958 | 959 | // symbols since it is known even in shared libraries |
| 959 | 960 | if (!S->IsPreemptible) |
| 960 | 961 | continue; |
| 961 | 962 | Offset += Config->Wordsize; |
| 962 | InX::RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S); | |
| 963 | In.RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S); | |
| 963 | 964 | } |
| 964 | 965 | } |
| 965 | 966 | |
| ... | ... | @@ -971,7 +972,7 @@ template <class ELFT> void MipsGotSection::build() { |
| 971 | 972 | // Dynamic relocations for "global" entries. |
| 972 | 973 | for (const std::pair<Symbol *, size_t> &P : Got.Global) { |
| 973 | 974 | uint64_t Offset = P.second * Config->Wordsize; |
| 974 | InX::RelaDyn->addReloc(Target->RelativeRel, this, Offset, P.first); | |
| 975 | In.RelaDyn->addReloc(Target->RelativeRel, this, Offset, P.first); | |
| 975 | 976 | } |
| 976 | 977 | if (!Config->Pic) |
| 977 | 978 | continue; |
| ... | ... | @@ -981,14 +982,14 @@ template <class ELFT> void MipsGotSection::build() { |
| 981 | 982 | size_t PageCount = L.second.Count; |
| 982 | 983 | for (size_t PI = 0; PI < PageCount; ++PI) { |
| 983 | 984 | uint64_t Offset = (L.second.FirstIndex + PI) * Config->Wordsize; |
| 984 | InX::RelaDyn->addReloc({Target->RelativeRel, this, Offset, L.first, | |
| 985 | int64_t(PI * 0x10000)}); | |
| 985 | In.RelaDyn->addReloc({Target->RelativeRel, this, Offset, L.first, | |
| 986 | int64_t(PI * 0x10000)}); | |
| 986 | 987 | } |
| 987 | 988 | } |
| 988 | 989 | for (const std::pair<GotEntry, size_t> &P : Got.Local16) { |
| 989 | 990 | uint64_t Offset = P.second * Config->Wordsize; |
| 990 | InX::RelaDyn->addReloc({Target->RelativeRel, this, Offset, true, | |
| 991 | P.first.first, P.first.second}); | |
| 991 | In.RelaDyn->addReloc({Target->RelativeRel, this, Offset, true, | |
| 992 | P.first.first, P.first.second}); | |
| 992 | 993 | } |
| 993 | 994 | } |
| 994 | 995 | } |
| ... | ... | @@ -1200,21 +1201,21 @@ DynamicSection<ELFT>::DynamicSection() |
| 1200 | 1201 | // Add strings to .dynstr early so that .dynstr's size will be |
| 1201 | 1202 | // fixed early. |
| 1202 | 1203 | for (StringRef S : Config->FilterList) |
| 1203 | addInt(DT_FILTER, InX::DynStrTab->addString(S)); | |
| 1204 | addInt(DT_FILTER, In.DynStrTab->addString(S)); | |
| 1204 | 1205 | for (StringRef S : Config->AuxiliaryList) |
| 1205 | addInt(DT_AUXILIARY, InX::DynStrTab->addString(S)); | |
| 1206 | addInt(DT_AUXILIARY, In.DynStrTab->addString(S)); | |
| 1206 | 1207 | |
| 1207 | 1208 | if (!Config->Rpath.empty()) |
| 1208 | 1209 | addInt(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH, |
| 1209 | InX::DynStrTab->addString(Config->Rpath)); | |
| 1210 | In.DynStrTab->addString(Config->Rpath)); | |
| 1210 | 1211 | |
| 1211 | 1212 | for (InputFile *File : SharedFiles) { |
| 1212 | 1213 | SharedFile<ELFT> *F = cast<SharedFile<ELFT>>(File); |
| 1213 | 1214 | if (F->IsNeeded) |
| 1214 | addInt(DT_NEEDED, InX::DynStrTab->addString(F->SoName)); | |
| 1215 | addInt(DT_NEEDED, In.DynStrTab->addString(F->SoName)); | |
| 1215 | 1216 | } |
| 1216 | 1217 | if (!Config->SoName.empty()) |
| 1217 | addInt(DT_SONAME, InX::DynStrTab->addString(Config->SoName)); | |
| 1218 | addInt(DT_SONAME, In.DynStrTab->addString(Config->SoName)); | |
| 1218 | 1219 | } |
| 1219 | 1220 | |
| 1220 | 1221 | template <class ELFT> |
| ... | ... | @@ -1254,18 +1255,33 @@ void DynamicSection<ELFT>::addSym(int32_t Tag, Symbol *Sym) { |
| 1254 | 1255 | Entries.push_back({Tag, [=] { return Sym->getVA(); }}); |
| 1255 | 1256 | } |
| 1256 | 1257 | |
| 1258 | // A Linker script may assign the RELA relocation sections to the same | |
| 1259 | // output section. When this occurs we cannot just use the OutputSection | |
| 1260 | // Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to | |
| 1261 | // overlap with the [DT_RELA, DT_RELA + DT_RELASZ). | |
| 1262 | static uint64_t addPltRelSz() { | |
| 1263 | size_t Size = In.RelaPlt->getSize(); | |
| 1264 | if (In.RelaIplt->getParent() == In.RelaPlt->getParent() && | |
| 1265 | In.RelaIplt->Name == In.RelaPlt->Name) | |
| 1266 | Size += In.RelaIplt->getSize(); | |
| 1267 | return Size; | |
| 1268 | } | |
| 1269 | ||
| 1257 | 1270 | // Add remaining entries to complete .dynamic contents. |
| 1258 | 1271 | template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { |
| 1259 | if (this->Size) | |
| 1260 | return; // Already finalized. | |
| 1261 | ||
| 1262 | 1272 | // Set DT_FLAGS and DT_FLAGS_1. |
| 1263 | 1273 | uint32_t DtFlags = 0; |
| 1264 | 1274 | uint32_t DtFlags1 = 0; |
| 1265 | 1275 | if (Config->Bsymbolic) |
| 1266 | 1276 | DtFlags |= DF_SYMBOLIC; |
| 1277 | if (Config->ZGlobal) | |
| 1278 | DtFlags1 |= DF_1_GLOBAL; | |
| 1267 | 1279 | if (Config->ZInitfirst) |
| 1268 | 1280 | DtFlags1 |= DF_1_INITFIRST; |
| 1281 | if (Config->ZInterpose) | |
| 1282 | DtFlags1 |= DF_1_INTERPOSE; | |
| 1283 | if (Config->ZNodefaultlib) | |
| 1284 | DtFlags1 |= DF_1_NODEFLIB; | |
| 1269 | 1285 | if (Config->ZNodelete) |
| 1270 | 1286 | DtFlags1 |= DF_1_NODELETE; |
| 1271 | 1287 | if (Config->ZNodlopen) |
| ... | ... | @@ -1297,10 +1313,12 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { |
| 1297 | 1313 | if (!Config->Shared && !Config->Relocatable && !Config->ZRodynamic) |
| 1298 | 1314 | addInt(DT_DEBUG, 0); |
| 1299 | 1315 | |
| 1300 | this->Link = InX::DynStrTab->getParent()->SectionIndex; | |
| 1301 | if (!InX::RelaDyn->empty()) { | |
| 1302 | addInSec(InX::RelaDyn->DynamicTag, InX::RelaDyn); | |
| 1303 | addSize(InX::RelaDyn->SizeDynamicTag, InX::RelaDyn->getParent()); | |
| 1316 | if (OutputSection *Sec = In.DynStrTab->getParent()) | |
| 1317 | this->Link = Sec->SectionIndex; | |
| 1318 | ||
| 1319 | if (!In.RelaDyn->empty()) { | |
| 1320 | addInSec(In.RelaDyn->DynamicTag, In.RelaDyn); | |
| 1321 | addSize(In.RelaDyn->SizeDynamicTag, In.RelaDyn->getParent()); | |
| 1304 | 1322 | |
| 1305 | 1323 | bool IsRela = Config->IsRela; |
| 1306 | 1324 | addInt(IsRela ? DT_RELAENT : DT_RELENT, |
| ... | ... | @@ -1310,16 +1328,16 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { |
| 1310 | 1328 | // The problem is in the tight relation between dynamic |
| 1311 | 1329 | // relocations and GOT. So do not emit this tag on MIPS. |
| 1312 | 1330 | if (Config->EMachine != EM_MIPS) { |
| 1313 | size_t NumRelativeRels = InX::RelaDyn->getRelativeRelocCount(); | |
| 1331 | size_t NumRelativeRels = In.RelaDyn->getRelativeRelocCount(); | |
| 1314 | 1332 | if (Config->ZCombreloc && NumRelativeRels) |
| 1315 | 1333 | addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels); |
| 1316 | 1334 | } |
| 1317 | 1335 | } |
| 1318 | if (InX::RelrDyn && !InX::RelrDyn->Relocs.empty()) { | |
| 1336 | if (In.RelrDyn && !In.RelrDyn->Relocs.empty()) { | |
| 1319 | 1337 | addInSec(Config->UseAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR, |
| 1320 | InX::RelrDyn); | |
| 1338 | In.RelrDyn); | |
| 1321 | 1339 | addSize(Config->UseAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ, |
| 1322 | InX::RelrDyn->getParent()); | |
| 1340 | In.RelrDyn->getParent()); | |
| 1323 | 1341 | addInt(Config->UseAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT, |
| 1324 | 1342 | sizeof(Elf_Relr)); |
| 1325 | 1343 | } |
| ... | ... | @@ -1329,33 +1347,33 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { |
| 1329 | 1347 | // as RelaIplt have. And we still want to emit proper dynamic tags for that |
| 1330 | 1348 | // case, so here we always use RelaPlt as marker for the begining of |
| 1331 | 1349 | // .rel[a].plt section. |
| 1332 | if (InX::RelaPlt->getParent()->Live) { | |
| 1333 | addInSec(DT_JMPREL, InX::RelaPlt); | |
| 1334 | addSize(DT_PLTRELSZ, InX::RelaPlt->getParent()); | |
| 1350 | if (In.RelaPlt->getParent()->Live) { | |
| 1351 | addInSec(DT_JMPREL, In.RelaPlt); | |
| 1352 | Entries.push_back({DT_PLTRELSZ, addPltRelSz}); | |
| 1335 | 1353 | switch (Config->EMachine) { |
| 1336 | 1354 | case EM_MIPS: |
| 1337 | addInSec(DT_MIPS_PLTGOT, InX::GotPlt); | |
| 1355 | addInSec(DT_MIPS_PLTGOT, In.GotPlt); | |
| 1338 | 1356 | break; |
| 1339 | 1357 | case EM_SPARCV9: |
| 1340 | addInSec(DT_PLTGOT, InX::Plt); | |
| 1358 | addInSec(DT_PLTGOT, In.Plt); | |
| 1341 | 1359 | break; |
| 1342 | 1360 | default: |
| 1343 | addInSec(DT_PLTGOT, InX::GotPlt); | |
| 1361 | addInSec(DT_PLTGOT, In.GotPlt); | |
| 1344 | 1362 | break; |
| 1345 | 1363 | } |
| 1346 | 1364 | addInt(DT_PLTREL, Config->IsRela ? DT_RELA : DT_REL); |
| 1347 | 1365 | } |
| 1348 | 1366 | |
| 1349 | addInSec(DT_SYMTAB, InX::DynSymTab); | |
| 1367 | addInSec(DT_SYMTAB, In.DynSymTab); | |
| 1350 | 1368 | addInt(DT_SYMENT, sizeof(Elf_Sym)); |
| 1351 | addInSec(DT_STRTAB, InX::DynStrTab); | |
| 1352 | addInt(DT_STRSZ, InX::DynStrTab->getSize()); | |
| 1369 | addInSec(DT_STRTAB, In.DynStrTab); | |
| 1370 | addInt(DT_STRSZ, In.DynStrTab->getSize()); | |
| 1353 | 1371 | if (!Config->ZText) |
| 1354 | 1372 | addInt(DT_TEXTREL, 0); |
| 1355 | if (InX::GnuHashTab) | |
| 1356 | addInSec(DT_GNU_HASH, InX::GnuHashTab); | |
| 1357 | if (InX::HashTab) | |
| 1358 | addInSec(DT_HASH, InX::HashTab); | |
| 1373 | if (In.GnuHashTab) | |
| 1374 | addInSec(DT_GNU_HASH, In.GnuHashTab); | |
| 1375 | if (In.HashTab) | |
| 1376 | addInSec(DT_HASH, In.HashTab); | |
| 1359 | 1377 | |
| 1360 | 1378 | if (Out::PreinitArray) { |
| 1361 | 1379 | addOutSec(DT_PREINIT_ARRAY, Out::PreinitArray); |
| ... | ... | @@ -1377,47 +1395,47 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() { |
| 1377 | 1395 | if (B->isDefined()) |
| 1378 | 1396 | addSym(DT_FINI, B); |
| 1379 | 1397 | |
| 1380 | bool HasVerNeed = In<ELFT>::VerNeed->getNeedNum() != 0; | |
| 1381 | if (HasVerNeed || In<ELFT>::VerDef) | |
| 1382 | addInSec(DT_VERSYM, In<ELFT>::VerSym); | |
| 1383 | if (In<ELFT>::VerDef) { | |
| 1384 | addInSec(DT_VERDEF, In<ELFT>::VerDef); | |
| 1398 | bool HasVerNeed = InX<ELFT>::VerNeed->getNeedNum() != 0; | |
| 1399 | if (HasVerNeed || In.VerDef) | |
| 1400 | addInSec(DT_VERSYM, InX<ELFT>::VerSym); | |
| 1401 | if (In.VerDef) { | |
| 1402 | addInSec(DT_VERDEF, In.VerDef); | |
| 1385 | 1403 | addInt(DT_VERDEFNUM, getVerDefNum()); |
| 1386 | 1404 | } |
| 1387 | 1405 | if (HasVerNeed) { |
| 1388 | addInSec(DT_VERNEED, In<ELFT>::VerNeed); | |
| 1389 | addInt(DT_VERNEEDNUM, In<ELFT>::VerNeed->getNeedNum()); | |
| 1406 | addInSec(DT_VERNEED, InX<ELFT>::VerNeed); | |
| 1407 | addInt(DT_VERNEEDNUM, InX<ELFT>::VerNeed->getNeedNum()); | |
| 1390 | 1408 | } |
| 1391 | 1409 | |
| 1392 | 1410 | if (Config->EMachine == EM_MIPS) { |
| 1393 | 1411 | addInt(DT_MIPS_RLD_VERSION, 1); |
| 1394 | 1412 | addInt(DT_MIPS_FLAGS, RHF_NOTPOT); |
| 1395 | 1413 | addInt(DT_MIPS_BASE_ADDRESS, Target->getImageBase()); |
| 1396 | addInt(DT_MIPS_SYMTABNO, InX::DynSymTab->getNumSymbols()); | |
| 1414 | addInt(DT_MIPS_SYMTABNO, In.DynSymTab->getNumSymbols()); | |
| 1397 | 1415 | |
| 1398 | add(DT_MIPS_LOCAL_GOTNO, [] { return InX::MipsGot->getLocalEntriesNum(); }); | |
| 1416 | add(DT_MIPS_LOCAL_GOTNO, [] { return In.MipsGot->getLocalEntriesNum(); }); | |
| 1399 | 1417 | |
| 1400 | if (const Symbol *B = InX::MipsGot->getFirstGlobalEntry()) | |
| 1418 | if (const Symbol *B = In.MipsGot->getFirstGlobalEntry()) | |
| 1401 | 1419 | addInt(DT_MIPS_GOTSYM, B->DynsymIndex); |
| 1402 | 1420 | else |
| 1403 | addInt(DT_MIPS_GOTSYM, InX::DynSymTab->getNumSymbols()); | |
| 1404 | addInSec(DT_PLTGOT, InX::MipsGot); | |
| 1405 | if (InX::MipsRldMap) { | |
| 1421 | addInt(DT_MIPS_GOTSYM, In.DynSymTab->getNumSymbols()); | |
| 1422 | addInSec(DT_PLTGOT, In.MipsGot); | |
| 1423 | if (In.MipsRldMap) { | |
| 1406 | 1424 | if (!Config->Pie) |
| 1407 | addInSec(DT_MIPS_RLD_MAP, InX::MipsRldMap); | |
| 1425 | addInSec(DT_MIPS_RLD_MAP, In.MipsRldMap); | |
| 1408 | 1426 | // Store the offset to the .rld_map section |
| 1409 | 1427 | // relative to the address of the tag. |
| 1410 | addInSecRelative(DT_MIPS_RLD_MAP_REL, InX::MipsRldMap); | |
| 1428 | addInSecRelative(DT_MIPS_RLD_MAP_REL, In.MipsRldMap); | |
| 1411 | 1429 | } |
| 1412 | 1430 | } |
| 1413 | 1431 | |
| 1414 | 1432 | // Glink dynamic tag is required by the V2 abi if the plt section isn't empty. |
| 1415 | if (Config->EMachine == EM_PPC64 && !InX::Plt->empty()) { | |
| 1433 | if (Config->EMachine == EM_PPC64 && !In.Plt->empty()) { | |
| 1416 | 1434 | // The Glink tag points to 32 bytes before the first lazy symbol resolution |
| 1417 | 1435 | // stub, which starts directly after the header. |
| 1418 | 1436 | Entries.push_back({DT_PPC64_GLINK, [=] { |
| 1419 | 1437 | unsigned Offset = Target->PltHeaderSize - 32; |
| 1420 | return InX::Plt->getVA(0) + Offset; | |
| 1438 | return In.Plt->getVA(0) + Offset; | |
| 1421 | 1439 | }}); |
| 1422 | 1440 | } |
| 1423 | 1441 | |
| ... | ... | @@ -1486,13 +1504,19 @@ void RelocationBaseSection::addReloc(const DynamicReloc &Reloc) { |
| 1486 | 1504 | } |
| 1487 | 1505 | |
| 1488 | 1506 | void RelocationBaseSection::finalizeContents() { |
| 1489 | // If all relocations are R_*_RELATIVE they don't refer to any | |
| 1490 | // dynamic symbol and we don't need a dynamic symbol table. If that | |
| 1491 | // is the case, just use 0 as the link. | |
| 1492 | Link = InX::DynSymTab ? InX::DynSymTab->getParent()->SectionIndex : 0; | |
| 1507 | // When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE | |
| 1508 | // relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that | |
| 1509 | // case. | |
| 1510 | InputSection *SymTab = Config->Relocatable ? In.SymTab : In.DynSymTab; | |
| 1511 | if (SymTab && SymTab->getParent()) | |
| 1512 | getParent()->Link = SymTab->getParent()->SectionIndex; | |
| 1513 | else | |
| 1514 | getParent()->Link = 0; | |
| 1493 | 1515 | |
| 1494 | // Set required output section properties. | |
| 1495 | getParent()->Link = Link; | |
| 1516 | if (In.RelaPlt == this) | |
| 1517 | getParent()->Info = In.GotPlt->getParent()->SectionIndex; | |
| 1518 | if (In.RelaIplt == this) | |
| 1519 | getParent()->Info = In.IgotPlt->getParent()->SectionIndex; | |
| 1496 | 1520 | } |
| 1497 | 1521 | |
| 1498 | 1522 | RelrBaseSection::RelrBaseSection() |
| ... | ... | @@ -1621,10 +1645,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() { |
| 1621 | 1645 | NonRelatives.push_back(R); |
| 1622 | 1646 | } |
| 1623 | 1647 | |
| 1624 | llvm::sort(Relatives.begin(), Relatives.end(), | |
| 1625 | [](const Elf_Rel &A, const Elf_Rel &B) { | |
| 1626 | return A.r_offset < B.r_offset; | |
| 1627 | }); | |
| 1648 | llvm::sort(Relatives, [](const Elf_Rel &A, const Elf_Rel &B) { | |
| 1649 | return A.r_offset < B.r_offset; | |
| 1650 | }); | |
| 1628 | 1651 | |
| 1629 | 1652 | // Try to find groups of relative relocations which are spaced one word |
| 1630 | 1653 | // apart from one another. These generally correspond to vtable entries. The |
| ... | ... | @@ -1702,10 +1725,9 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() { |
| 1702 | 1725 | } |
| 1703 | 1726 | |
| 1704 | 1727 | // Finally the non-relative relocations. |
| 1705 | llvm::sort(NonRelatives.begin(), NonRelatives.end(), | |
| 1706 | [](const Elf_Rela &A, const Elf_Rela &B) { | |
| 1707 | return A.r_offset < B.r_offset; | |
| 1708 | }); | |
| 1728 | llvm::sort(NonRelatives, [](const Elf_Rela &A, const Elf_Rela &B) { | |
| 1729 | return A.r_offset < B.r_offset; | |
| 1730 | }); | |
| 1709 | 1731 | if (!NonRelatives.empty()) { |
| 1710 | 1732 | Add(NonRelatives.size()); |
| 1711 | 1733 | Add(HasAddendIfRela); |
| ... | ... | @@ -1720,6 +1742,11 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() { |
| 1720 | 1742 | } |
| 1721 | 1743 | } |
| 1722 | 1744 | |
| 1745 | // Don't allow the section to shrink; otherwise the size of the section can | |
| 1746 | // oscillate infinitely. | |
| 1747 | if (RelocData.size() < OldSize) | |
| 1748 | RelocData.append(OldSize - RelocData.size(), 0); | |
| 1749 | ||
| 1723 | 1750 | // Returns whether the section size changed. We need to keep recomputing both |
| 1724 | 1751 | // section layout and the contents of this section until the size converges |
| 1725 | 1752 | // because changing this section's size can affect section layout, which in |
| ... | ... | @@ -1843,10 +1870,13 @@ static bool sortMipsSymbols(const SymbolTableEntry &L, |
| 1843 | 1870 | } |
| 1844 | 1871 | |
| 1845 | 1872 | void SymbolTableBaseSection::finalizeContents() { |
| 1846 | getParent()->Link = StrTabSec.getParent()->SectionIndex; | |
| 1873 | if (OutputSection *Sec = StrTabSec.getParent()) | |
| 1874 | getParent()->Link = Sec->SectionIndex; | |
| 1847 | 1875 | |
| 1848 | if (this->Type != SHT_DYNSYM) | |
| 1876 | if (this->Type != SHT_DYNSYM) { | |
| 1877 | sortSymTabSymbols(); | |
| 1849 | 1878 | return; |
| 1879 | } | |
| 1850 | 1880 | |
| 1851 | 1881 | // If it is a .dynsym, there should be no local symbols, but we need |
| 1852 | 1882 | // to do a few things for the dynamic linker. |
| ... | ... | @@ -1855,9 +1885,9 @@ void SymbolTableBaseSection::finalizeContents() { |
| 1855 | 1885 | // Because the first symbol entry is a null entry, 1 is the first. |
| 1856 | 1886 | getParent()->Info = 1; |
| 1857 | 1887 | |
| 1858 | if (InX::GnuHashTab) { | |
| 1888 | if (In.GnuHashTab) { | |
| 1859 | 1889 | // NB: It also sorts Symbols to meet the GNU hash table requirements. |
| 1860 | InX::GnuHashTab->addSymbols(Symbols); | |
| 1890 | In.GnuHashTab->addSymbols(Symbols); | |
| 1861 | 1891 | } else if (Config->EMachine == EM_MIPS) { |
| 1862 | 1892 | std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols); |
| 1863 | 1893 | } |
| ... | ... | @@ -1874,9 +1904,7 @@ void SymbolTableBaseSection::finalizeContents() { |
| 1874 | 1904 | // Aside from above, we put local symbols in groups starting with the STT_FILE |
| 1875 | 1905 | // symbol. That is convenient for purpose of identifying where are local symbols |
| 1876 | 1906 | // coming from. |
| 1877 | void SymbolTableBaseSection::postThunkContents() { | |
| 1878 | assert(this->Type == SHT_SYMTAB); | |
| 1879 | ||
| 1907 | void SymbolTableBaseSection::sortSymTabSymbols() { | |
| 1880 | 1908 | // Move all local symbols before global symbols. |
| 1881 | 1909 | auto E = std::stable_partition( |
| 1882 | 1910 | Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) { |
| ... | ... | @@ -1948,7 +1976,8 @@ static uint32_t getSymSectionIndex(Symbol *Sym) { |
| 1948 | 1976 | if (!isa<Defined>(Sym) || Sym->NeedsPltAddr) |
| 1949 | 1977 | return SHN_UNDEF; |
| 1950 | 1978 | if (const OutputSection *OS = Sym->getOutputSection()) |
| 1951 | return OS->SectionIndex >= SHN_LORESERVE ? SHN_XINDEX : OS->SectionIndex; | |
| 1979 | return OS->SectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX | |
| 1980 | : OS->SectionIndex; | |
| 1952 | 1981 | return SHN_ABS; |
| 1953 | 1982 | } |
| 1954 | 1983 | |
| ... | ... | @@ -2038,7 +2067,7 @@ void SymtabShndxSection::writeTo(uint8_t *Buf) { |
| 2038 | 2067 | // with an entry in .symtab. If the corresponding entry contains SHN_XINDEX, |
| 2039 | 2068 | // we need to write actual index, otherwise, we must write SHN_UNDEF(0). |
| 2040 | 2069 | Buf += 4; // Ignore .symtab[0] entry. |
| 2041 | for (const SymbolTableEntry &Entry : InX::SymTab->getSymbols()) { | |
| 2070 | for (const SymbolTableEntry &Entry : In.SymTab->getSymbols()) { | |
| 2042 | 2071 | if (getSymSectionIndex(Entry.Sym) == SHN_XINDEX) |
| 2043 | 2072 | write32(Buf, Entry.Sym->getOutputSection()->SectionIndex); |
| 2044 | 2073 | Buf += 4; |
| ... | ... | @@ -2059,11 +2088,11 @@ bool SymtabShndxSection::empty() const { |
| 2059 | 2088 | } |
| 2060 | 2089 | |
| 2061 | 2090 | void SymtabShndxSection::finalizeContents() { |
| 2062 | getParent()->Link = InX::SymTab->getParent()->SectionIndex; | |
| 2091 | getParent()->Link = In.SymTab->getParent()->SectionIndex; | |
| 2063 | 2092 | } |
| 2064 | 2093 | |
| 2065 | 2094 | size_t SymtabShndxSection::getSize() const { |
| 2066 | return InX::SymTab->getNumSymbols() * 4; | |
| 2095 | return In.SymTab->getNumSymbols() * 4; | |
| 2067 | 2096 | } |
| 2068 | 2097 | |
| 2069 | 2098 | // .hash and .gnu.hash sections contain on-disk hash tables that map |
| ... | ... | @@ -2102,7 +2131,8 @@ GnuHashTableSection::GnuHashTableSection() |
| 2102 | 2131 | } |
| 2103 | 2132 | |
| 2104 | 2133 | void GnuHashTableSection::finalizeContents() { |
| 2105 | getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; | |
| 2134 | if (OutputSection *Sec = In.DynSymTab->getParent()) | |
| 2135 | getParent()->Link = Sec->SectionIndex; | |
| 2106 | 2136 | |
| 2107 | 2137 | // Computes bloom filter size in word size. We want to allocate 12 |
| 2108 | 2138 | // bits for each symbol. It must be a power of two. |
| ... | ... | @@ -2127,7 +2157,7 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) { |
| 2127 | 2157 | |
| 2128 | 2158 | // Write a header. |
| 2129 | 2159 | write32(Buf, NBuckets); |
| 2130 | write32(Buf + 4, InX::DynSymTab->getNumSymbols() - Symbols.size()); | |
| 2160 | write32(Buf + 4, In.DynSymTab->getNumSymbols() - Symbols.size()); | |
| 2131 | 2161 | write32(Buf + 8, MaskWords); |
| 2132 | 2162 | write32(Buf + 12, Shift2); |
| 2133 | 2163 | Buf += 16; |
| ... | ... | @@ -2148,6 +2178,8 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) { |
| 2148 | 2178 | void GnuHashTableSection::writeBloomFilter(uint8_t *Buf) { |
| 2149 | 2179 | unsigned C = Config->Is64 ? 64 : 32; |
| 2150 | 2180 | for (const Entry &Sym : Symbols) { |
| 2181 | // When C = 64, we choose a word with bits [6:...] and set 1 to two bits in | |
| 2182 | // the word using bits [0:5] and [26:31]. | |
| 2151 | 2183 | size_t I = (Sym.Hash / C) & (MaskWords - 1); |
| 2152 | 2184 | uint64_t Val = readUint(Buf + I * Config->Wordsize); |
| 2153 | 2185 | Val |= uint64_t(1) << (Sym.Hash % C); |
| ... | ... | @@ -2232,13 +2264,14 @@ HashTableSection::HashTableSection() |
| 2232 | 2264 | } |
| 2233 | 2265 | |
| 2234 | 2266 | void HashTableSection::finalizeContents() { |
| 2235 | getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; | |
| 2267 | if (OutputSection *Sec = In.DynSymTab->getParent()) | |
| 2268 | getParent()->Link = Sec->SectionIndex; | |
| 2236 | 2269 | |
| 2237 | 2270 | unsigned NumEntries = 2; // nbucket and nchain. |
| 2238 | NumEntries += InX::DynSymTab->getNumSymbols(); // The chain entries. | |
| 2271 | NumEntries += In.DynSymTab->getNumSymbols(); // The chain entries. | |
| 2239 | 2272 | |
| 2240 | 2273 | // Create as many buckets as there are symbols. |
| 2241 | NumEntries += InX::DynSymTab->getNumSymbols(); | |
| 2274 | NumEntries += In.DynSymTab->getNumSymbols(); | |
| 2242 | 2275 | this->Size = NumEntries * 4; |
| 2243 | 2276 | } |
| 2244 | 2277 | |
| ... | ... | @@ -2246,7 +2279,7 @@ void HashTableSection::writeTo(uint8_t *Buf) { |
| 2246 | 2279 | // See comment in GnuHashTableSection::writeTo. |
| 2247 | 2280 | memset(Buf, 0, Size); |
| 2248 | 2281 | |
| 2249 | unsigned NumSymbols = InX::DynSymTab->getNumSymbols(); | |
| 2282 | unsigned NumSymbols = In.DynSymTab->getNumSymbols(); | |
| 2250 | 2283 | |
| 2251 | 2284 | uint32_t *P = reinterpret_cast<uint32_t *>(Buf); |
| 2252 | 2285 | write32(P++, NumSymbols); // nbucket |
| ... | ... | @@ -2255,7 +2288,7 @@ void HashTableSection::writeTo(uint8_t *Buf) { |
| 2255 | 2288 | uint32_t *Buckets = P; |
| 2256 | 2289 | uint32_t *Chains = P + NumSymbols; |
| 2257 | 2290 | |
| 2258 | for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { | |
| 2291 | for (const SymbolTableEntry &S : In.DynSymTab->getSymbols()) { | |
| 2259 | 2292 | Symbol *Sym = S.Sym; |
| 2260 | 2293 | StringRef Name = Sym->getName(); |
| 2261 | 2294 | unsigned I = Sym->DynsymIndex; |
| ... | ... | @@ -2270,7 +2303,8 @@ void HashTableSection::writeTo(uint8_t *Buf) { |
| 2270 | 2303 | PltSection::PltSection(bool IsIplt) |
| 2271 | 2304 | : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16, |
| 2272 | 2305 | Config->EMachine == EM_PPC64 ? ".glink" : ".plt"), |
| 2273 | HeaderSize(IsIplt ? 0 : Target->PltHeaderSize), IsIplt(IsIplt) { | |
| 2306 | HeaderSize(!IsIplt || Config->ZRetpolineplt ? Target->PltHeaderSize : 0), | |
| 2307 | IsIplt(IsIplt) { | |
| 2274 | 2308 | // The PLT needs to be writable on SPARC as the dynamic linker will |
| 2275 | 2309 | // modify the instructions in the PLT entries. |
| 2276 | 2310 | if (Config->EMachine == EM_SPARCV9) |
| ... | ... | @@ -2278,9 +2312,9 @@ PltSection::PltSection(bool IsIplt) |
| 2278 | 2312 | } |
| 2279 | 2313 | |
| 2280 | 2314 | void PltSection::writeTo(uint8_t *Buf) { |
| 2281 | // At beginning of PLT but not the IPLT, we have code to call the dynamic | |
| 2315 | // At beginning of PLT or retpoline IPLT, we have code to call the dynamic | |
| 2282 | 2316 | // linker to resolve dynsyms at runtime. Write such code. |
| 2283 | if (!IsIplt) | |
| 2317 | if (HeaderSize > 0) | |
| 2284 | 2318 | Target->writePltHeader(Buf); |
| 2285 | 2319 | size_t Off = HeaderSize; |
| 2286 | 2320 | // The IPlt is immediately after the Plt, account for this in RelOff |
| ... | ... | @@ -2298,9 +2332,9 @@ void PltSection::writeTo(uint8_t *Buf) { |
| 2298 | 2332 | |
| 2299 | 2333 | template <class ELFT> void PltSection::addEntry(Symbol &Sym) { |
| 2300 | 2334 | Sym.PltIndex = Entries.size(); |
| 2301 | RelocationBaseSection *PltRelocSection = InX::RelaPlt; | |
| 2335 | RelocationBaseSection *PltRelocSection = In.RelaPlt; | |
| 2302 | 2336 | if (IsIplt) { |
| 2303 | PltRelocSection = InX::RelaIplt; | |
| 2337 | PltRelocSection = In.RelaIplt; | |
| 2304 | 2338 | Sym.IsInIplt = true; |
| 2305 | 2339 | } |
| 2306 | 2340 | unsigned RelOff = |
| ... | ... | @@ -2326,14 +2360,14 @@ void PltSection::addSymbols() { |
| 2326 | 2360 | } |
| 2327 | 2361 | |
| 2328 | 2362 | unsigned PltSection::getPltRelocOff() const { |
| 2329 | return IsIplt ? InX::Plt->getSize() : 0; | |
| 2363 | return IsIplt ? In.Plt->getSize() : 0; | |
| 2330 | 2364 | } |
| 2331 | 2365 | |
| 2332 | 2366 | // The string hash function for .gdb_index. |
| 2333 | 2367 | static uint32_t computeGdbHash(StringRef S) { |
| 2334 | 2368 | uint32_t H = 0; |
| 2335 | 2369 | for (uint8_t C : S) |
| 2336 | H = H * 67 + tolower(C) - 113; | |
| 2370 | H = H * 67 + toLower(C) - 113; | |
| 2337 | 2371 | return H; |
| 2338 | 2372 | } |
| 2339 | 2373 | |
| ... | ... | @@ -2371,7 +2405,7 @@ static std::vector<InputSection *> getDebugInfoSections() { |
| 2371 | 2405 | |
| 2372 | 2406 | static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &Dwarf) { |
| 2373 | 2407 | std::vector<GdbIndexSection::CuEntry> Ret; |
| 2374 | for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units()) | |
| 2408 | for (std::unique_ptr<DWARFUnit> &Cu : Dwarf.compile_units()) | |
| 2375 | 2409 | Ret.push_back({Cu->getOffset(), Cu->getLength() + 4}); |
| 2376 | 2410 | return Ret; |
| 2377 | 2411 | } |
| ... | ... | @@ -2381,12 +2415,15 @@ readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) { |
| 2381 | 2415 | std::vector<GdbIndexSection::AddressEntry> Ret; |
| 2382 | 2416 | |
| 2383 | 2417 | uint32_t CuIdx = 0; |
| 2384 | for (std::unique_ptr<DWARFCompileUnit> &Cu : Dwarf.compile_units()) { | |
| 2385 | DWARFAddressRangesVector Ranges; | |
| 2386 | Cu->collectAddressRanges(Ranges); | |
| 2418 | for (std::unique_ptr<DWARFUnit> &Cu : Dwarf.compile_units()) { | |
| 2419 | Expected<DWARFAddressRangesVector> Ranges = Cu->collectAddressRanges(); | |
| 2420 | if (!Ranges) { | |
| 2421 | error(toString(Sec) + ": " + toString(Ranges.takeError())); | |
| 2422 | return {}; | |
| 2423 | } | |
| 2387 | 2424 | |
| 2388 | 2425 | ArrayRef<InputSectionBase *> Sections = Sec->File->getSections(); |
| 2389 | for (DWARFAddressRange &R : Ranges) { | |
| 2426 | for (DWARFAddressRange &R : *Ranges) { | |
| 2390 | 2427 | InputSectionBase *S = Sections[R.SectionIndex]; |
| 2391 | 2428 | if (!S || S == &InputSection::Discarded || !S->Live) |
| 2392 | 2429 | continue; |
| ... | ... | @@ -2399,21 +2436,35 @@ readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) { |
| 2399 | 2436 | } |
| 2400 | 2437 | ++CuIdx; |
| 2401 | 2438 | } |
| 2439 | ||
| 2402 | 2440 | return Ret; |
| 2403 | 2441 | } |
| 2404 | 2442 | |
| 2405 | static std::vector<GdbIndexSection::NameTypeEntry> | |
| 2406 | readPubNamesAndTypes(DWARFContext &Dwarf, uint32_t Idx) { | |
| 2407 | StringRef Sec1 = Dwarf.getDWARFObj().getGnuPubNamesSection(); | |
| 2408 | StringRef Sec2 = Dwarf.getDWARFObj().getGnuPubTypesSection(); | |
| 2409 | ||
| 2410 | std::vector<GdbIndexSection::NameTypeEntry> Ret; | |
| 2411 | for (StringRef Sec : {Sec1, Sec2}) { | |
| 2412 | DWARFDebugPubTable Table(Sec, Config->IsLE, true); | |
| 2413 | for (const DWARFDebugPubTable::Set &Set : Table.getData()) | |
| 2443 | template <class ELFT> | |
| 2444 | static std::vector<GdbIndexSection::NameAttrEntry> | |
| 2445 | readPubNamesAndTypes(const LLDDwarfObj<ELFT> &Obj, | |
| 2446 | const std::vector<GdbIndexSection::CuEntry> &CUs) { | |
| 2447 | const DWARFSection &PubNames = Obj.getGnuPubNamesSection(); | |
| 2448 | const DWARFSection &PubTypes = Obj.getGnuPubTypesSection(); | |
| 2449 | ||
| 2450 | std::vector<GdbIndexSection::NameAttrEntry> Ret; | |
| 2451 | for (const DWARFSection *Pub : {&PubNames, &PubTypes}) { | |
| 2452 | DWARFDebugPubTable Table(Obj, *Pub, Config->IsLE, true); | |
| 2453 | for (const DWARFDebugPubTable::Set &Set : Table.getData()) { | |
| 2454 | // The value written into the constant pool is Kind << 24 | CuIndex. As we | |
| 2455 | // don't know how many compilation units precede this object to compute | |
| 2456 | // CuIndex, we compute (Kind << 24 | CuIndexInThisObject) instead, and add | |
| 2457 | // the number of preceding compilation units later. | |
| 2458 | uint32_t I = | |
| 2459 | lower_bound(CUs, Set.Offset, | |
| 2460 | [](GdbIndexSection::CuEntry CU, uint32_t Offset) { | |
| 2461 | return CU.CuOffset < Offset; | |
| 2462 | }) - | |
| 2463 | CUs.begin(); | |
| 2414 | 2464 | for (const DWARFDebugPubTable::Entry &Ent : Set.Entries) |
| 2415 | 2465 | Ret.push_back({{Ent.Name, computeGdbHash(Ent.Name)}, |
| 2416 | (Ent.Descriptor.toBits() << 24) | Idx}); | |
| 2466 | (Ent.Descriptor.toBits() << 24) | I}); | |
| 2467 | } | |
| 2417 | 2468 | } |
| 2418 | 2469 | return Ret; |
| 2419 | 2470 | } |
| ... | ... | @@ -2421,9 +2472,18 @@ readPubNamesAndTypes(DWARFContext &Dwarf, uint32_t Idx) { |
| 2421 | 2472 | // Create a list of symbols from a given list of symbol names and types |
| 2422 | 2473 | // by uniquifying them by name. |
| 2423 | 2474 | static std::vector<GdbIndexSection::GdbSymbol> |
| 2424 | createSymbols(ArrayRef<std::vector<GdbIndexSection::NameTypeEntry>> NameTypes) { | |
| 2475 | createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> NameAttrs, | |
| 2476 | const std::vector<GdbIndexSection::GdbChunk> &Chunks) { | |
| 2425 | 2477 | typedef GdbIndexSection::GdbSymbol GdbSymbol; |
| 2426 | typedef GdbIndexSection::NameTypeEntry NameTypeEntry; | |
| 2478 | typedef GdbIndexSection::NameAttrEntry NameAttrEntry; | |
| 2479 | ||
| 2480 | // For each chunk, compute the number of compilation units preceding it. | |
| 2481 | uint32_t CuIdx = 0; | |
| 2482 | std::vector<uint32_t> CuIdxs(Chunks.size()); | |
| 2483 | for (uint32_t I = 0, E = Chunks.size(); I != E; ++I) { | |
| 2484 | CuIdxs[I] = CuIdx; | |
| 2485 | CuIdx += Chunks[I].CompilationUnits.size(); | |
| 2486 | } | |
| 2427 | 2487 | |
| 2428 | 2488 | // The number of symbols we will handle in this function is of the order |
| 2429 | 2489 | // of millions for very large executables, so we use multi-threading to |
| ... | ... | @@ -2441,21 +2501,24 @@ createSymbols(ArrayRef<std::vector<GdbIndexSection::NameTypeEntry>> NameTypes) { |
| 2441 | 2501 | // Instantiate GdbSymbols while uniqufying them by name. |
| 2442 | 2502 | std::vector<std::vector<GdbSymbol>> Symbols(NumShards); |
| 2443 | 2503 | parallelForEachN(0, Concurrency, [&](size_t ThreadId) { |
| 2444 | for (ArrayRef<NameTypeEntry> Entries : NameTypes) { | |
| 2445 | for (const NameTypeEntry &Ent : Entries) { | |
| 2504 | uint32_t I = 0; | |
| 2505 | for (ArrayRef<NameAttrEntry> Entries : NameAttrs) { | |
| 2506 | for (const NameAttrEntry &Ent : Entries) { | |
| 2446 | 2507 | size_t ShardId = Ent.Name.hash() >> Shift; |
| 2447 | 2508 | if ((ShardId & (Concurrency - 1)) != ThreadId) |
| 2448 | 2509 | continue; |
| 2449 | 2510 | |
| 2511 | uint32_t V = Ent.CuIndexAndAttrs + CuIdxs[I]; | |
| 2450 | 2512 | size_t &Idx = Map[ShardId][Ent.Name]; |
| 2451 | 2513 | if (Idx) { |
| 2452 | Symbols[ShardId][Idx - 1].CuVector.push_back(Ent.Type); | |
| 2514 | Symbols[ShardId][Idx - 1].CuVector.push_back(V); | |
| 2453 | 2515 | continue; |
| 2454 | 2516 | } |
| 2455 | 2517 | |
| 2456 | 2518 | Idx = Symbols[ShardId].size() + 1; |
| 2457 | Symbols[ShardId].push_back({Ent.Name, {Ent.Type}, 0, 0}); | |
| 2519 | Symbols[ShardId].push_back({Ent.Name, {V}, 0, 0}); | |
| 2458 | 2520 | } |
| 2521 | ++I; | |
| 2459 | 2522 | } |
| 2460 | 2523 | }); |
| 2461 | 2524 | |
| ... | ... | @@ -2498,7 +2561,7 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() { |
| 2498 | 2561 | S->Live = false; |
| 2499 | 2562 | |
| 2500 | 2563 | std::vector<GdbChunk> Chunks(Sections.size()); |
| 2501 | std::vector<std::vector<NameTypeEntry>> NameTypes(Sections.size()); | |
| 2564 | std::vector<std::vector<NameAttrEntry>> NameAttrs(Sections.size()); | |
| 2502 | 2565 | |
| 2503 | 2566 | parallelForEachN(0, Sections.size(), [&](size_t I) { |
| 2504 | 2567 | ObjFile<ELFT> *File = Sections[I]->getFile<ELFT>(); |
| ... | ... | @@ -2507,12 +2570,14 @@ template <class ELFT> GdbIndexSection *GdbIndexSection::create() { |
| 2507 | 2570 | Chunks[I].Sec = Sections[I]; |
| 2508 | 2571 | Chunks[I].CompilationUnits = readCuList(Dwarf); |
| 2509 | 2572 | Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]); |
| 2510 | NameTypes[I] = readPubNamesAndTypes(Dwarf, I); | |
| 2573 | NameAttrs[I] = readPubNamesAndTypes<ELFT>( | |
| 2574 | static_cast<const LLDDwarfObj<ELFT> &>(Dwarf.getDWARFObj()), | |
| 2575 | Chunks[I].CompilationUnits); | |
| 2511 | 2576 | }); |
| 2512 | 2577 | |
| 2513 | 2578 | auto *Ret = make<GdbIndexSection>(); |
| 2514 | 2579 | Ret->Chunks = std::move(Chunks); |
| 2515 | Ret->Symbols = createSymbols(NameTypes); | |
| 2580 | Ret->Symbols = createSymbols(NameAttrs, Ret->Chunks); | |
| 2516 | 2581 | Ret->initOutputSize(); |
| 2517 | 2582 | return Ret; |
| 2518 | 2583 | } |
| ... | ... | @@ -2570,8 +2635,9 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { |
| 2570 | 2635 | |
| 2571 | 2636 | // Write the string pool. |
| 2572 | 2637 | Hdr->ConstantPoolOff = Buf - Start; |
| 2573 | for (GdbSymbol &Sym : Symbols) | |
| 2638 | parallelForEach(Symbols, [&](GdbSymbol &Sym) { | |
| 2574 | 2639 | memcpy(Buf + Sym.NameOff, Sym.Name.data(), Sym.Name.size()); |
| 2640 | }); | |
| 2575 | 2641 | |
| 2576 | 2642 | // Write the CU vectors. |
| 2577 | 2643 | for (GdbSymbol &Sym : Symbols) { |
| ... | ... | @@ -2584,7 +2650,7 @@ void GdbIndexSection::writeTo(uint8_t *Buf) { |
| 2584 | 2650 | } |
| 2585 | 2651 | } |
| 2586 | 2652 | |
| 2587 | bool GdbIndexSection::empty() const { return !Out::DebugInfo; } | |
| 2653 | bool GdbIndexSection::empty() const { return Chunks.empty(); } | |
| 2588 | 2654 | |
| 2589 | 2655 | EhFrameHeader::EhFrameHeader() |
| 2590 | 2656 | : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".eh_frame_hdr") {} |
| ... | ... | @@ -2596,13 +2662,13 @@ EhFrameHeader::EhFrameHeader() |
| 2596 | 2662 | void EhFrameHeader::writeTo(uint8_t *Buf) { |
| 2597 | 2663 | typedef EhFrameSection::FdeData FdeData; |
| 2598 | 2664 | |
| 2599 | std::vector<FdeData> Fdes = InX::EhFrame->getFdeData(); | |
| 2665 | std::vector<FdeData> Fdes = In.EhFrame->getFdeData(); | |
| 2600 | 2666 | |
| 2601 | 2667 | Buf[0] = 1; |
| 2602 | 2668 | Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4; |
| 2603 | 2669 | Buf[2] = DW_EH_PE_udata4; |
| 2604 | 2670 | Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4; |
| 2605 | write32(Buf + 4, InX::EhFrame->getParent()->Addr - this->getVA() - 4); | |
| 2671 | write32(Buf + 4, In.EhFrame->getParent()->Addr - this->getVA() - 4); | |
| 2606 | 2672 | write32(Buf + 8, Fdes.size()); |
| 2607 | 2673 | Buf += 12; |
| 2608 | 2674 | |
| ... | ... | @@ -2615,13 +2681,12 @@ void EhFrameHeader::writeTo(uint8_t *Buf) { |
| 2615 | 2681 | |
| 2616 | 2682 | size_t EhFrameHeader::getSize() const { |
| 2617 | 2683 | // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs. |
| 2618 | return 12 + InX::EhFrame->NumFdes * 8; | |
| 2684 | return 12 + In.EhFrame->NumFdes * 8; | |
| 2619 | 2685 | } |
| 2620 | 2686 | |
| 2621 | bool EhFrameHeader::empty() const { return InX::EhFrame->empty(); } | |
| 2687 | bool EhFrameHeader::empty() const { return In.EhFrame->empty(); } | |
| 2622 | 2688 | |
| 2623 | template <class ELFT> | |
| 2624 | VersionDefinitionSection<ELFT>::VersionDefinitionSection() | |
| 2689 | VersionDefinitionSection::VersionDefinitionSection() | |
| 2625 | 2690 | : SyntheticSection(SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t), |
| 2626 | 2691 | ".gnu.version_d") {} |
| 2627 | 2692 | |
| ... | ... | @@ -2631,12 +2696,13 @@ static StringRef getFileDefName() { |
| 2631 | 2696 | return Config->OutputFile; |
| 2632 | 2697 | } |
| 2633 | 2698 | |
| 2634 | template <class ELFT> void VersionDefinitionSection<ELFT>::finalizeContents() { | |
| 2635 | FileDefNameOff = InX::DynStrTab->addString(getFileDefName()); | |
| 2699 | void VersionDefinitionSection::finalizeContents() { | |
| 2700 | FileDefNameOff = In.DynStrTab->addString(getFileDefName()); | |
| 2636 | 2701 | for (VersionDefinition &V : Config->VersionDefinitions) |
| 2637 | V.NameOff = InX::DynStrTab->addString(V.Name); | |
| 2702 | V.NameOff = In.DynStrTab->addString(V.Name); | |
| 2638 | 2703 | |
| 2639 | getParent()->Link = InX::DynStrTab->getParent()->SectionIndex; | |
| 2704 | if (OutputSection *Sec = In.DynStrTab->getParent()) | |
| 2705 | getParent()->Link = Sec->SectionIndex; | |
| 2640 | 2706 | |
| 2641 | 2707 | // sh_info should be set to the number of definitions. This fact is missed in |
| 2642 | 2708 | // documentation, but confirmed by binutils community: |
| ... | ... | @@ -2644,68 +2710,68 @@ template <class ELFT> void VersionDefinitionSection<ELFT>::finalizeContents() { |
| 2644 | 2710 | getParent()->Info = getVerDefNum(); |
| 2645 | 2711 | } |
| 2646 | 2712 | |
| 2647 | template <class ELFT> | |
| 2648 | void VersionDefinitionSection<ELFT>::writeOne(uint8_t *Buf, uint32_t Index, | |
| 2649 | StringRef Name, size_t NameOff) { | |
| 2650 | auto *Verdef = reinterpret_cast<Elf_Verdef *>(Buf); | |
| 2651 | Verdef->vd_version = 1; | |
| 2652 | Verdef->vd_cnt = 1; | |
| 2653 | Verdef->vd_aux = sizeof(Elf_Verdef); | |
| 2654 | Verdef->vd_next = sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); | |
| 2655 | Verdef->vd_flags = (Index == 1 ? VER_FLG_BASE : 0); | |
| 2656 | Verdef->vd_ndx = Index; | |
| 2657 | Verdef->vd_hash = hashSysV(Name); | |
| 2658 | ||
| 2659 | auto *Verdaux = reinterpret_cast<Elf_Verdaux *>(Buf + sizeof(Elf_Verdef)); | |
| 2660 | Verdaux->vda_name = NameOff; | |
| 2661 | Verdaux->vda_next = 0; | |
| 2713 | void VersionDefinitionSection::writeOne(uint8_t *Buf, uint32_t Index, | |
| 2714 | StringRef Name, size_t NameOff) { | |
| 2715 | uint16_t Flags = Index == 1 ? VER_FLG_BASE : 0; | |
| 2716 | ||
| 2717 | // Write a verdef. | |
| 2718 | write16(Buf, 1); // vd_version | |
| 2719 | write16(Buf + 2, Flags); // vd_flags | |
| 2720 | write16(Buf + 4, Index); // vd_ndx | |
| 2721 | write16(Buf + 6, 1); // vd_cnt | |
| 2722 | write32(Buf + 8, hashSysV(Name)); // vd_hash | |
| 2723 | write32(Buf + 12, 20); // vd_aux | |
| 2724 | write32(Buf + 16, 28); // vd_next | |
| 2725 | ||
| 2726 | // Write a veraux. | |
| 2727 | write32(Buf + 20, NameOff); // vda_name | |
| 2728 | write32(Buf + 24, 0); // vda_next | |
| 2662 | 2729 | } |
| 2663 | 2730 | |
| 2664 | template <class ELFT> | |
| 2665 | void VersionDefinitionSection<ELFT>::writeTo(uint8_t *Buf) { | |
| 2731 | void VersionDefinitionSection::writeTo(uint8_t *Buf) { | |
| 2666 | 2732 | writeOne(Buf, 1, getFileDefName(), FileDefNameOff); |
| 2667 | 2733 | |
| 2668 | 2734 | for (VersionDefinition &V : Config->VersionDefinitions) { |
| 2669 | Buf += sizeof(Elf_Verdef) + sizeof(Elf_Verdaux); | |
| 2735 | Buf += EntrySize; | |
| 2670 | 2736 | writeOne(Buf, V.Id, V.Name, V.NameOff); |
| 2671 | 2737 | } |
| 2672 | 2738 | |
| 2673 | 2739 | // Need to terminate the last version definition. |
| 2674 | Elf_Verdef *Verdef = reinterpret_cast<Elf_Verdef *>(Buf); | |
| 2675 | Verdef->vd_next = 0; | |
| 2740 | write32(Buf + 16, 0); // vd_next | |
| 2676 | 2741 | } |
| 2677 | 2742 | |
| 2678 | template <class ELFT> size_t VersionDefinitionSection<ELFT>::getSize() const { | |
| 2679 | return (sizeof(Elf_Verdef) + sizeof(Elf_Verdaux)) * getVerDefNum(); | |
| 2743 | size_t VersionDefinitionSection::getSize() const { | |
| 2744 | return EntrySize * getVerDefNum(); | |
| 2680 | 2745 | } |
| 2681 | 2746 | |
| 2747 | // .gnu.version is a table where each entry is 2 byte long. | |
| 2682 | 2748 | template <class ELFT> |
| 2683 | 2749 | VersionTableSection<ELFT>::VersionTableSection() |
| 2684 | 2750 | : SyntheticSection(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t), |
| 2685 | 2751 | ".gnu.version") { |
| 2686 | this->Entsize = sizeof(Elf_Versym); | |
| 2752 | this->Entsize = 2; | |
| 2687 | 2753 | } |
| 2688 | 2754 | |
| 2689 | 2755 | template <class ELFT> void VersionTableSection<ELFT>::finalizeContents() { |
| 2690 | 2756 | // At the moment of june 2016 GNU docs does not mention that sh_link field |
| 2691 | 2757 | // should be set, but Sun docs do. Also readelf relies on this field. |
| 2692 | getParent()->Link = InX::DynSymTab->getParent()->SectionIndex; | |
| 2758 | getParent()->Link = In.DynSymTab->getParent()->SectionIndex; | |
| 2693 | 2759 | } |
| 2694 | 2760 | |
| 2695 | 2761 | template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const { |
| 2696 | return sizeof(Elf_Versym) * (InX::DynSymTab->getSymbols().size() + 1); | |
| 2762 | return (In.DynSymTab->getSymbols().size() + 1) * 2; | |
| 2697 | 2763 | } |
| 2698 | 2764 | |
| 2699 | 2765 | template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) { |
| 2700 | auto *OutVersym = reinterpret_cast<Elf_Versym *>(Buf) + 1; | |
| 2701 | for (const SymbolTableEntry &S : InX::DynSymTab->getSymbols()) { | |
| 2702 | OutVersym->vs_index = S.Sym->VersionId; | |
| 2703 | ++OutVersym; | |
| 2766 | Buf += 2; | |
| 2767 | for (const SymbolTableEntry &S : In.DynSymTab->getSymbols()) { | |
| 2768 | write16(Buf, S.Sym->VersionId); | |
| 2769 | Buf += 2; | |
| 2704 | 2770 | } |
| 2705 | 2771 | } |
| 2706 | 2772 | |
| 2707 | 2773 | template <class ELFT> bool VersionTableSection<ELFT>::empty() const { |
| 2708 | return !In<ELFT>::VerDef && In<ELFT>::VerNeed->empty(); | |
| 2774 | return !In.VerDef && InX<ELFT>::VerNeed->empty(); | |
| 2709 | 2775 | } |
| 2710 | 2776 | |
| 2711 | 2777 | template <class ELFT> |
| ... | ... | @@ -2729,7 +2795,7 @@ template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) { |
| 2729 | 2795 | // to create one by adding it to our needed list and creating a dynstr entry |
| 2730 | 2796 | // for the soname. |
| 2731 | 2797 | if (File.VerdefMap.empty()) |
| 2732 | Needed.push_back({&File, InX::DynStrTab->addString(File.SoName)}); | |
| 2798 | Needed.push_back({&File, In.DynStrTab->addString(File.SoName)}); | |
| 2733 | 2799 | const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex]; |
| 2734 | 2800 | typename SharedFile<ELFT>::NeededVer &NV = File.VerdefMap[Ver]; |
| 2735 | 2801 | |
| ... | ... | @@ -2737,8 +2803,8 @@ template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) { |
| 2737 | 2803 | // prepare to create one by allocating a version identifier and creating a |
| 2738 | 2804 | // dynstr entry for the version name. |
| 2739 | 2805 | if (NV.Index == 0) { |
| 2740 | NV.StrTab = InX::DynStrTab->addString(File.getStringTable().data() + | |
| 2741 | Ver->getAux()->vda_name); | |
| 2806 | NV.StrTab = In.DynStrTab->addString(File.getStringTable().data() + | |
| 2807 | Ver->getAux()->vda_name); | |
| 2742 | 2808 | NV.Index = NextIndex++; |
| 2743 | 2809 | } |
| 2744 | 2810 | SS->VersionId = NV.Index; |
| ... | ... | @@ -2780,7 +2846,8 @@ template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) { |
| 2780 | 2846 | } |
| 2781 | 2847 | |
| 2782 | 2848 | template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() { |
| 2783 | getParent()->Link = InX::DynStrTab->getParent()->SectionIndex; | |
| 2849 | if (OutputSection *Sec = In.DynStrTab->getParent()) | |
| 2850 | getParent()->Link = Sec->SectionIndex; | |
| 2784 | 2851 | getParent()->Info = Needed.size(); |
| 2785 | 2852 | } |
| 2786 | 2853 | |
| ... | ... | @@ -2896,12 +2963,6 @@ static MergeSyntheticSection *createMergeSynthetic(StringRef Name, |
| 2896 | 2963 | return make<MergeNoTailSection>(Name, Type, Flags, Alignment); |
| 2897 | 2964 | } |
| 2898 | 2965 | |
| 2899 | // Debug sections may be compressed by zlib. Decompress if exists. | |
| 2900 | void elf::decompressSections() { | |
| 2901 | parallelForEach(InputSections, | |
| 2902 | [](InputSectionBase *Sec) { Sec->maybeDecompress(); }); | |
| 2903 | } | |
| 2904 | ||
| 2905 | 2966 | template <class ELFT> void elf::splitSections() { |
| 2906 | 2967 | // splitIntoPieces needs to be called on each MergeInputSection |
| 2907 | 2968 | // before calling finalizeContents(). |
| ... | ... | @@ -3040,34 +3101,54 @@ bool ThunkSection::assignOffsets() { |
| 3040 | 3101 | return Changed; |
| 3041 | 3102 | } |
| 3042 | 3103 | |
| 3043 | InputSection *InX::ARMAttributes; | |
| 3044 | BssSection *InX::Bss; | |
| 3045 | BssSection *InX::BssRelRo; | |
| 3046 | BuildIdSection *InX::BuildId; | |
| 3047 | EhFrameHeader *InX::EhFrameHdr; | |
| 3048 | EhFrameSection *InX::EhFrame; | |
| 3049 | SyntheticSection *InX::Dynamic; | |
| 3050 | StringTableSection *InX::DynStrTab; | |
| 3051 | SymbolTableBaseSection *InX::DynSymTab; | |
| 3052 | InputSection *InX::Interp; | |
| 3053 | GdbIndexSection *InX::GdbIndex; | |
| 3054 | GotSection *InX::Got; | |
| 3055 | GotPltSection *InX::GotPlt; | |
| 3056 | GnuHashTableSection *InX::GnuHashTab; | |
| 3057 | HashTableSection *InX::HashTab; | |
| 3058 | IgotPltSection *InX::IgotPlt; | |
| 3059 | MipsGotSection *InX::MipsGot; | |
| 3060 | MipsRldMapSection *InX::MipsRldMap; | |
| 3061 | PltSection *InX::Plt; | |
| 3062 | PltSection *InX::Iplt; | |
| 3063 | RelocationBaseSection *InX::RelaDyn; | |
| 3064 | RelrBaseSection *InX::RelrDyn; | |
| 3065 | RelocationBaseSection *InX::RelaPlt; | |
| 3066 | RelocationBaseSection *InX::RelaIplt; | |
| 3067 | StringTableSection *InX::ShStrTab; | |
| 3068 | StringTableSection *InX::StrTab; | |
| 3069 | SymbolTableBaseSection *InX::SymTab; | |
| 3070 | SymtabShndxSection *InX::SymTabShndx; | |
| 3104 | // If linking position-dependent code then the table will store the addresses | |
| 3105 | // directly in the binary so the section has type SHT_PROGBITS. If linking | |
| 3106 | // position-independent code the section has type SHT_NOBITS since it will be | |
| 3107 | // allocated and filled in by the dynamic linker. | |
| 3108 | PPC64LongBranchTargetSection::PPC64LongBranchTargetSection() | |
| 3109 | : SyntheticSection(SHF_ALLOC | SHF_WRITE, | |
| 3110 | Config->Pic ? SHT_NOBITS : SHT_PROGBITS, 8, | |
| 3111 | ".branch_lt") {} | |
| 3112 | ||
| 3113 | void PPC64LongBranchTargetSection::addEntry(Symbol &Sym) { | |
| 3114 | assert(Sym.PPC64BranchltIndex == 0xffff); | |
| 3115 | Sym.PPC64BranchltIndex = Entries.size(); | |
| 3116 | Entries.push_back(&Sym); | |
| 3117 | } | |
| 3118 | ||
| 3119 | size_t PPC64LongBranchTargetSection::getSize() const { | |
| 3120 | return Entries.size() * 8; | |
| 3121 | } | |
| 3122 | ||
| 3123 | void PPC64LongBranchTargetSection::writeTo(uint8_t *Buf) { | |
| 3124 | assert(Target->GotPltEntrySize == 8); | |
| 3125 | // If linking non-pic we have the final addresses of the targets and they get | |
| 3126 | // written to the table directly. For pic the dynamic linker will allocate | |
| 3127 | // the section and fill it it. | |
| 3128 | if (Config->Pic) | |
| 3129 | return; | |
| 3130 | ||
| 3131 | for (const Symbol *Sym : Entries) { | |
| 3132 | assert(Sym->getVA()); | |
| 3133 | // Need calls to branch to the local entry-point since a long-branch | |
| 3134 | // must be a local-call. | |
| 3135 | write64(Buf, | |
| 3136 | Sym->getVA() + getPPC64GlobalEntryToLocalEntryOffset(Sym->StOther)); | |
| 3137 | Buf += Target->GotPltEntrySize; | |
| 3138 | } | |
| 3139 | } | |
| 3140 | ||
| 3141 | bool PPC64LongBranchTargetSection::empty() const { | |
| 3142 | // `removeUnusedSyntheticSections()` is called before thunk allocation which | |
| 3143 | // is too early to determine if this section will be empty or not. We need | |
| 3144 | // Finalized to keep the section alive until after thunk creation. Finalized | |
| 3145 | // only gets set to true once `finalizeSections()` is called after thunk | |
| 3146 | // creation. Becuase of this, if we don't create any long-branch thunks we end | |
| 3147 | // up with an empty .branch_lt section in the binary. | |
| 3148 | return Finalized && Entries.empty(); | |
| 3149 | } | |
| 3150 | ||
| 3151 | InStruct elf::In; | |
| 3071 | 3152 | |
| 3072 | 3153 | template GdbIndexSection *GdbIndexSection::create<ELF32LE>(); |
| 3073 | 3154 | template GdbIndexSection *GdbIndexSection::create<ELF32BE>(); |
| ... | ... | @@ -3143,8 +3224,3 @@ template class elf::VersionNeedSection<ELF32LE>; |
| 3143 | 3224 | template class elf::VersionNeedSection<ELF32BE>; |
| 3144 | 3225 | template class elf::VersionNeedSection<ELF64LE>; |
| 3145 | 3226 | template class elf::VersionNeedSection<ELF64BE>; |
| 3146 | ||
| 3147 | template class elf::VersionDefinitionSection<ELF32LE>; | |
| 3148 | template class elf::VersionDefinitionSection<ELF32BE>; | |
| 3149 | template class elf::VersionDefinitionSection<ELF64LE>; | |
| 3150 | template class elf::VersionDefinitionSection<ELF64BE>; |
deps/lld/ELF/SyntheticSections.h+80-57| ... | ... | @@ -21,8 +21,8 @@ |
| 21 | 21 | #ifndef LLD_ELF_SYNTHETIC_SECTION_H |
| 22 | 22 | #define LLD_ELF_SYNTHETIC_SECTION_H |
| 23 | 23 | |
| 24 | #include "DWARF.h" | |
| 24 | 25 | #include "EhFrame.h" |
| 25 | #include "GdbIndex.h" | |
| 26 | 26 | #include "InputSection.h" |
| 27 | 27 | #include "llvm/ADT/MapVector.h" |
| 28 | 28 | #include "llvm/MC/StringTableBuilder.h" |
| ... | ... | @@ -50,8 +50,6 @@ public: |
| 50 | 50 | // If the section has the SHF_ALLOC flag and the size may be changed if |
| 51 | 51 | // thunks are added, update the section size. |
| 52 | 52 | virtual bool updateAllocSize() { return false; } |
| 53 | // If any additional finalization of contents are needed post thunk creation. | |
| 54 | virtual void postThunkContents() {} | |
| 55 | 53 | virtual bool empty() const { return false; } |
| 56 | 54 | |
| 57 | 55 | static bool classof(const SectionBase *D) { |
| ... | ... | @@ -137,6 +135,15 @@ protected: |
| 137 | 135 | uint64_t Size = 0; |
| 138 | 136 | }; |
| 139 | 137 | |
| 138 | // .note.GNU-stack section. | |
| 139 | class GnuStackSection : public SyntheticSection { | |
| 140 | public: | |
| 141 | GnuStackSection() | |
| 142 | : SyntheticSection(0, llvm::ELF::SHT_PROGBITS, 1, ".note.GNU-stack") {} | |
| 143 | void writeTo(uint8_t *Buf) override {} | |
| 144 | size_t getSize() const override { return 0; } | |
| 145 | }; | |
| 146 | ||
| 140 | 147 | // .note.gnu.build-id section. |
| 141 | 148 | class BuildIdSection : public SyntheticSection { |
| 142 | 149 | // First 16 bytes are a header. |
| ... | ... | @@ -163,7 +170,9 @@ private: |
| 163 | 170 | class BssSection final : public SyntheticSection { |
| 164 | 171 | public: |
| 165 | 172 | BssSection(StringRef Name, uint64_t Size, uint32_t Alignment); |
| 166 | void writeTo(uint8_t *) override {} | |
| 173 | void writeTo(uint8_t *) override { | |
| 174 | llvm_unreachable("unexpected writeTo() call for SHT_NOBITS section"); | |
| 175 | } | |
| 167 | 176 | bool empty() const override { return getSize() == 0; } |
| 168 | 177 | size_t getSize() const override { return Size; } |
| 169 | 178 | |
| ... | ... | @@ -300,8 +309,6 @@ private: |
| 300 | 309 | |
| 301 | 310 | uint64_t Size = 0; |
| 302 | 311 | |
| 303 | size_t LocalEntriesNum = 0; | |
| 304 | ||
| 305 | 312 | // Symbol and addend. |
| 306 | 313 | typedef std::pair<Symbol *, int64_t> GotEntry; |
| 307 | 314 | |
| ... | ... | @@ -333,8 +340,6 @@ private: |
| 333 | 340 | size_t getPageEntriesNum() const; |
| 334 | 341 | // Number of entries require 16-bit index to access. |
| 335 | 342 | size_t getIndexedEntriesNum() const; |
| 336 | ||
| 337 | bool isOverflow() const; | |
| 338 | 343 | }; |
| 339 | 344 | |
| 340 | 345 | // Container of GOT created for each input file. |
| ... | ... | @@ -529,6 +534,7 @@ struct RelativeReloc { |
| 529 | 534 | class RelrBaseSection : public SyntheticSection { |
| 530 | 535 | public: |
| 531 | 536 | RelrBaseSection(); |
| 537 | bool empty() const override { return Relocs.empty(); } | |
| 532 | 538 | std::vector<RelativeReloc> Relocs; |
| 533 | 539 | }; |
| 534 | 540 | |
| ... | ... | @@ -561,7 +567,6 @@ class SymbolTableBaseSection : public SyntheticSection { |
| 561 | 567 | public: |
| 562 | 568 | SymbolTableBaseSection(StringTableSection &StrTabSec); |
| 563 | 569 | void finalizeContents() override; |
| 564 | void postThunkContents() override; | |
| 565 | 570 | size_t getSize() const override { return getNumSymbols() * Entsize; } |
| 566 | 571 | void addSymbol(Symbol *Sym); |
| 567 | 572 | unsigned getNumSymbols() const { return Symbols.size() + 1; } |
| ... | ... | @@ -569,6 +574,8 @@ public: |
| 569 | 574 | ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; } |
| 570 | 575 | |
| 571 | 576 | protected: |
| 577 | void sortSymTabSymbols(); | |
| 578 | ||
| 572 | 579 | // A vector of symbols and their string table offsets. |
| 573 | 580 | std::vector<SymbolTableEntry> Symbols; |
| 574 | 581 | |
| ... | ... | @@ -612,7 +619,8 @@ public: |
| 612 | 619 | void addSymbols(std::vector<SymbolTableEntry> &Symbols); |
| 613 | 620 | |
| 614 | 621 | private: |
| 615 | enum { Shift2 = 6 }; | |
| 622 | // See the comment in writeBloomFilter. | |
| 623 | enum { Shift2 = 26 }; | |
| 616 | 624 | |
| 617 | 625 | void writeBloomFilter(uint8_t *Buf); |
| 618 | 626 | void writeHashTable(uint8_t *Buf); |
| ... | ... | @@ -652,13 +660,13 @@ public: |
| 652 | 660 | size_t getSize() const override; |
| 653 | 661 | bool empty() const override { return Entries.empty(); } |
| 654 | 662 | void addSymbols(); |
| 655 | ||
| 656 | 663 | template <class ELFT> void addEntry(Symbol &Sym); |
| 657 | 664 | |
| 665 | size_t HeaderSize; | |
| 666 | ||
| 658 | 667 | private: |
| 659 | 668 | unsigned getPltRelocOff() const; |
| 660 | 669 | std::vector<std::pair<const Symbol *, unsigned>> Entries; |
| 661 | size_t HeaderSize; | |
| 662 | 670 | bool IsIplt; |
| 663 | 671 | }; |
| 664 | 672 | |
| ... | ... | @@ -676,9 +684,9 @@ public: |
| 676 | 684 | uint64_t CuLength; |
| 677 | 685 | }; |
| 678 | 686 | |
| 679 | struct NameTypeEntry { | |
| 687 | struct NameAttrEntry { | |
| 680 | 688 | llvm::CachedHashStringRef Name; |
| 681 | uint32_t Type; | |
| 689 | uint32_t CuIndexAndAttrs; | |
| 682 | 690 | }; |
| 683 | 691 | |
| 684 | 692 | struct GdbChunk { |
| ... | ... | @@ -748,11 +756,7 @@ public: |
| 748 | 756 | // shall be contained in the DT_VERDEFNUM entry of the .dynamic section. |
| 749 | 757 | // The section shall contain an array of Elf_Verdef structures, optionally |
| 750 | 758 | // followed by an array of Elf_Verdaux structures. |
| 751 | template <class ELFT> | |
| 752 | 759 | class VersionDefinitionSection final : public SyntheticSection { |
| 753 | typedef typename ELFT::Verdef Elf_Verdef; | |
| 754 | typedef typename ELFT::Verdaux Elf_Verdaux; | |
| 755 | ||
| 756 | 760 | public: |
| 757 | 761 | VersionDefinitionSection(); |
| 758 | 762 | void finalizeContents() override; |
| ... | ... | @@ -760,6 +764,7 @@ public: |
| 760 | 764 | void writeTo(uint8_t *Buf) override; |
| 761 | 765 | |
| 762 | 766 | private: |
| 767 | enum { EntrySize = 28 }; | |
| 763 | 768 | void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff); |
| 764 | 769 | |
| 765 | 770 | unsigned FileDefNameOff; |
| ... | ... | @@ -773,8 +778,6 @@ private: |
| 773 | 778 | // the own object or in any of the dependencies. |
| 774 | 779 | template <class ELFT> |
| 775 | 780 | class VersionTableSection final : public SyntheticSection { |
| 776 | typedef typename ELFT::Versym Elf_Versym; | |
| 777 | ||
| 778 | 781 | public: |
| 779 | 782 | VersionTableSection(); |
| 780 | 783 | void finalizeContents() override; |
| ... | ... | @@ -964,9 +967,27 @@ private: |
| 964 | 967 | size_t Size = 0; |
| 965 | 968 | }; |
| 966 | 969 | |
| 970 | // This section is used to store the addresses of functions that are called | |
| 971 | // in range-extending thunks on PowerPC64. When producing position dependant | |
| 972 | // code the addresses are link-time constants and the table is written out to | |
| 973 | // the binary. When producing position-dependant code the table is allocated and | |
| 974 | // filled in by the dynamic linker. | |
| 975 | class PPC64LongBranchTargetSection final : public SyntheticSection { | |
| 976 | public: | |
| 977 | PPC64LongBranchTargetSection(); | |
| 978 | void addEntry(Symbol &Sym); | |
| 979 | size_t getSize() const override; | |
| 980 | void writeTo(uint8_t *Buf) override; | |
| 981 | bool empty() const override; | |
| 982 | void finalizeContents() override { Finalized = true; } | |
| 983 | ||
| 984 | private: | |
| 985 | std::vector<const Symbol *> Entries; | |
| 986 | bool Finalized = false; | |
| 987 | }; | |
| 988 | ||
| 967 | 989 | InputSection *createInterpSection(); |
| 968 | 990 | MergeInputSection *createCommentSection(); |
| 969 | void decompressSections(); | |
| 970 | 991 | template <class ELFT> void splitSections(); |
| 971 | 992 | void mergeSections(); |
| 972 | 993 | |
| ... | ... | @@ -974,46 +995,48 @@ Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value, |
| 974 | 995 | uint64_t Size, InputSectionBase &Section); |
| 975 | 996 | |
| 976 | 997 | // Linker generated sections which can be used as inputs. |
| 977 | struct InX { | |
| 978 | static InputSection *ARMAttributes; | |
| 979 | static BssSection *Bss; | |
| 980 | static BssSection *BssRelRo; | |
| 981 | static BuildIdSection *BuildId; | |
| 982 | static EhFrameHeader *EhFrameHdr; | |
| 983 | static EhFrameSection *EhFrame; | |
| 984 | static SyntheticSection *Dynamic; | |
| 985 | static StringTableSection *DynStrTab; | |
| 986 | static SymbolTableBaseSection *DynSymTab; | |
| 987 | static GnuHashTableSection *GnuHashTab; | |
| 988 | static HashTableSection *HashTab; | |
| 989 | static InputSection *Interp; | |
| 990 | static GdbIndexSection *GdbIndex; | |
| 991 | static GotSection *Got; | |
| 992 | static GotPltSection *GotPlt; | |
| 993 | static IgotPltSection *IgotPlt; | |
| 994 | static MipsGotSection *MipsGot; | |
| 995 | static MipsRldMapSection *MipsRldMap; | |
| 996 | static PltSection *Plt; | |
| 997 | static PltSection *Iplt; | |
| 998 | static RelocationBaseSection *RelaDyn; | |
| 999 | static RelrBaseSection *RelrDyn; | |
| 1000 | static RelocationBaseSection *RelaPlt; | |
| 1001 | static RelocationBaseSection *RelaIplt; | |
| 1002 | static StringTableSection *ShStrTab; | |
| 1003 | static StringTableSection *StrTab; | |
| 1004 | static SymbolTableBaseSection *SymTab; | |
| 1005 | static SymtabShndxSection* SymTabShndx; | |
| 1006 | }; | |
| 1007 | ||
| 1008 | template <class ELFT> struct In { | |
| 1009 | static VersionDefinitionSection<ELFT> *VerDef; | |
| 998 | struct InStruct { | |
| 999 | InputSection *ARMAttributes; | |
| 1000 | BssSection *Bss; | |
| 1001 | BssSection *BssRelRo; | |
| 1002 | BuildIdSection *BuildId; | |
| 1003 | EhFrameHeader *EhFrameHdr; | |
| 1004 | EhFrameSection *EhFrame; | |
| 1005 | SyntheticSection *Dynamic; | |
| 1006 | StringTableSection *DynStrTab; | |
| 1007 | SymbolTableBaseSection *DynSymTab; | |
| 1008 | GnuHashTableSection *GnuHashTab; | |
| 1009 | HashTableSection *HashTab; | |
| 1010 | InputSection *Interp; | |
| 1011 | GdbIndexSection *GdbIndex; | |
| 1012 | GotSection *Got; | |
| 1013 | GotPltSection *GotPlt; | |
| 1014 | IgotPltSection *IgotPlt; | |
| 1015 | PPC64LongBranchTargetSection *PPC64LongBranchTarget; | |
| 1016 | MipsGotSection *MipsGot; | |
| 1017 | MipsRldMapSection *MipsRldMap; | |
| 1018 | PltSection *Plt; | |
| 1019 | PltSection *Iplt; | |
| 1020 | RelocationBaseSection *RelaDyn; | |
| 1021 | RelrBaseSection *RelrDyn; | |
| 1022 | RelocationBaseSection *RelaPlt; | |
| 1023 | RelocationBaseSection *RelaIplt; | |
| 1024 | StringTableSection *ShStrTab; | |
| 1025 | StringTableSection *StrTab; | |
| 1026 | SymbolTableBaseSection *SymTab; | |
| 1027 | SymtabShndxSection *SymTabShndx; | |
| 1028 | VersionDefinitionSection *VerDef; | |
| 1029 | }; | |
| 1030 | ||
| 1031 | extern InStruct In; | |
| 1032 | ||
| 1033 | template <class ELFT> struct InX { | |
| 1010 | 1034 | static VersionTableSection<ELFT> *VerSym; |
| 1011 | 1035 | static VersionNeedSection<ELFT> *VerNeed; |
| 1012 | 1036 | }; |
| 1013 | 1037 | |
| 1014 | template <class ELFT> VersionDefinitionSection<ELFT> *In<ELFT>::VerDef; | |
| 1015 | template <class ELFT> VersionTableSection<ELFT> *In<ELFT>::VerSym; | |
| 1016 | template <class ELFT> VersionNeedSection<ELFT> *In<ELFT>::VerNeed; | |
| 1038 | template <class ELFT> VersionTableSection<ELFT> *InX<ELFT>::VerSym; | |
| 1039 | template <class ELFT> VersionNeedSection<ELFT> *InX<ELFT>::VerNeed; | |
| 1017 | 1040 | } // namespace elf |
| 1018 | 1041 | } // namespace lld |
| 1019 | 1042 |
deps/lld/ELF/Target.cpp+8-5| ... | ... | @@ -73,12 +73,16 @@ TargetInfo *elf::getTarget() { |
| 73 | 73 | case ELF64BEKind: |
| 74 | 74 | return getMipsTargetInfo<ELF64BE>(); |
| 75 | 75 | default: |
| 76 | fatal("unsupported MIPS target"); | |
| 76 | llvm_unreachable("unsupported MIPS target"); | |
| 77 | 77 | } |
| 78 | case EM_MSP430: | |
| 79 | return getMSP430TargetInfo(); | |
| 78 | 80 | case EM_PPC: |
| 79 | 81 | return getPPCTargetInfo(); |
| 80 | 82 | case EM_PPC64: |
| 81 | 83 | return getPPC64TargetInfo(); |
| 84 | case EM_RISCV: | |
| 85 | return getRISCVTargetInfo(); | |
| 82 | 86 | case EM_SPARCV9: |
| 83 | 87 | return getSPARCV9TargetInfo(); |
| 84 | 88 | case EM_X86_64: |
| ... | ... | @@ -86,7 +90,7 @@ TargetInfo *elf::getTarget() { |
| 86 | 90 | return getX32TargetInfo(); |
| 87 | 91 | return getX86_64TargetInfo(); |
| 88 | 92 | } |
| 89 | fatal("unknown target machine"); | |
| 93 | llvm_unreachable("unknown target machine"); | |
| 90 | 94 | } |
| 91 | 95 | |
| 92 | 96 | template <class ELFT> static ErrorPlace getErrPlace(const uint8_t *Loc) { |
| ... | ... | @@ -130,12 +134,11 @@ bool TargetInfo::needsThunk(RelExpr Expr, RelType Type, const InputFile *File, |
| 130 | 134 | return false; |
| 131 | 135 | } |
| 132 | 136 | |
| 133 | bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *Loc, | |
| 134 | uint8_t *End) const { | |
| 137 | bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, | |
| 138 | uint8_t StOther) const { | |
| 135 | 139 | llvm_unreachable("Target doesn't support split stacks."); |
| 136 | 140 | } |
| 137 | 141 | |
| 138 | ||
| 139 | 142 | bool TargetInfo::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const { |
| 140 | 143 | return true; |
| 141 | 144 | } |
deps/lld/ELF/Target.h+36-28| ... | ... | @@ -13,6 +13,8 @@ |
| 13 | 13 | #include "InputSection.h" |
| 14 | 14 | #include "lld/Common/ErrorHandler.h" |
| 15 | 15 | #include "llvm/Object/ELF.h" |
| 16 | #include "llvm/Support/MathExtras.h" | |
| 17 | #include <array> | |
| 16 | 18 | |
| 17 | 19 | namespace lld { |
| 18 | 20 | std::string toString(elf::RelType Type); |
| ... | ... | @@ -43,10 +45,6 @@ public: |
| 43 | 45 | virtual void addPltHeaderSymbols(InputSection &IS) const {} |
| 44 | 46 | virtual void addPltSymbols(InputSection &IS, uint64_t Off) const {} |
| 45 | 47 | |
| 46 | unsigned getPltEntryOffset(unsigned Index) const { | |
| 47 | return Index * PltEntrySize + PltHeaderSize; | |
| 48 | } | |
| 49 | ||
| 50 | 48 | // Returns true if a relocation only uses the low bits of a value such that |
| 51 | 49 | // all those bits are in the same page. For example, if the relocation |
| 52 | 50 | // only uses the low 12 bits in a system with 4k pages. If this is true, the |
| ... | ... | @@ -60,11 +58,18 @@ public: |
| 60 | 58 | const InputFile *File, uint64_t BranchAddr, |
| 61 | 59 | const Symbol &S) const; |
| 62 | 60 | |
| 61 | // On systems with range extensions we place collections of Thunks at | |
| 62 | // regular spacings that enable the majority of branches reach the Thunks. | |
| 63 | // a value of 0 means range extension thunks are not supported. | |
| 64 | virtual uint32_t getThunkSectionSpacing() const { return 0; } | |
| 65 | ||
| 63 | 66 | // The function with a prologue starting at Loc was compiled with |
| 64 | 67 | // -fsplit-stack and it calls a function compiled without. Adjust the prologue |
| 65 | 68 | // to do the right thing. See https://gcc.gnu.org/wiki/SplitStacks. |
| 66 | virtual bool adjustPrologueForCrossSplitStack(uint8_t *Loc, | |
| 67 | uint8_t *End) const; | |
| 69 | // The symbols st_other flags are needed on PowerPC64 for determining the | |
| 70 | // offset to the split-stack prologue. | |
| 71 | virtual bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End, | |
| 72 | uint8_t StOther) const; | |
| 68 | 73 | |
| 69 | 74 | // Return true if we can reach Dst from Src with Relocation RelocType |
| 70 | 75 | virtual bool inBranchRange(RelType Type, uint64_t Src, |
| ... | ... | @@ -87,12 +92,9 @@ public: |
| 87 | 92 | // True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got. |
| 88 | 93 | bool GotBaseSymInGotPlt = true; |
| 89 | 94 | |
| 90 | // On systems with range extensions we place collections of Thunks at | |
| 91 | // regular spacings that enable the majority of branches reach the Thunks. | |
| 92 | uint32_t ThunkSectionSpacing = 0; | |
| 93 | ||
| 94 | 95 | RelType CopyRel; |
| 95 | 96 | RelType GotRel; |
| 97 | RelType NoneRel; | |
| 96 | 98 | RelType PltRel; |
| 97 | 99 | RelType RelativeRel; |
| 98 | 100 | RelType IRelativeRel; |
| ... | ... | @@ -112,20 +114,16 @@ public: |
| 112 | 114 | // On PPC ELF V2 abi, the first entry in the .got is the .TOC. |
| 113 | 115 | unsigned GotHeaderEntriesNum = 0; |
| 114 | 116 | |
| 115 | // For TLS variant 1, the TCB is a fixed size specified by the Target. | |
| 116 | // For variant 2, the TCB is an unspecified size. | |
| 117 | // Set to 0 for variant 2. | |
| 118 | unsigned TcbSize = 0; | |
| 119 | ||
| 120 | // Set to the offset (in bytes) that the thread pointer is initialized to | |
| 121 | // point to, relative to the start of the thread local storage. | |
| 122 | unsigned TlsTpOffset = 0; | |
| 123 | ||
| 124 | 117 | bool NeedsThunks = false; |
| 125 | 118 | |
| 126 | 119 | // A 4-byte field corresponding to one or more trap instructions, used to pad |
| 127 | 120 | // executable OutputSections. |
| 128 | uint32_t TrapInstr = 0; | |
| 121 | std::array<uint8_t, 4> TrapInstr; | |
| 122 | ||
| 123 | // If a target needs to rewrite calls to __morestack to instead call | |
| 124 | // __morestack_non_split when a split-stack enabled caller calls a | |
| 125 | // non-split-stack callee this will return true. Otherwise returns false. | |
| 126 | bool NeedsMoreStackNonSplit = true; | |
| 129 | 127 | |
| 130 | 128 | virtual RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data, |
| 131 | 129 | RelExpr Expr) const; |
| ... | ... | @@ -148,8 +146,10 @@ TargetInfo *getAMDGPUTargetInfo(); |
| 148 | 146 | TargetInfo *getARMTargetInfo(); |
| 149 | 147 | TargetInfo *getAVRTargetInfo(); |
| 150 | 148 | TargetInfo *getHexagonTargetInfo(); |
| 149 | TargetInfo *getMSP430TargetInfo(); | |
| 151 | 150 | TargetInfo *getPPC64TargetInfo(); |
| 152 | 151 | TargetInfo *getPPCTargetInfo(); |
| 152 | TargetInfo *getRISCVTargetInfo(); | |
| 153 | 153 | TargetInfo *getSPARCV9TargetInfo(); |
| 154 | 154 | TargetInfo *getX32TargetInfo(); |
| 155 | 155 | TargetInfo *getX86TargetInfo(); |
| ... | ... | @@ -168,6 +168,15 @@ static inline std::string getErrorLocation(const uint8_t *Loc) { |
| 168 | 168 | return getErrorPlace(Loc).Loc; |
| 169 | 169 | } |
| 170 | 170 | |
| 171 | // In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first is | |
| 172 | // a global entry point (GEP) which typically is used to intiailzie the TOC | |
| 173 | // pointer in general purpose register 2. The second is a local entry | |
| 174 | // point (LEP) which bypasses the TOC pointer initialization code. The | |
| 175 | // offset between GEP and LEP is encoded in a function's st_other flags. | |
| 176 | // This function will return the offset (in bytes) from the global entry-point | |
| 177 | // to the local entry-point. | |
| 178 | unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther); | |
| 179 | ||
| 171 | 180 | uint64_t getPPC64TocBase(); |
| 172 | 181 | uint64_t getAArch64Page(uint64_t Expr); |
| 173 | 182 | |
| ... | ... | @@ -184,19 +193,18 @@ static inline void reportRangeError(uint8_t *Loc, RelType Type, const Twine &V, |
| 184 | 193 | Hint = "; consider recompiling with -fdebug-types-section to reduce size " |
| 185 | 194 | "of debug sections"; |
| 186 | 195 | |
| 187 | error(ErrPlace.Loc + "relocation " + lld::toString(Type) + | |
| 188 | " out of range: " + V.str() + " is not in [" + Twine(Min).str() + ", " + | |
| 189 | Twine(Max).str() + "]" + Hint); | |
| 196 | errorOrWarn(ErrPlace.Loc + "relocation " + lld::toString(Type) + | |
| 197 | " out of range: " + V.str() + " is not in [" + Twine(Min).str() + | |
| 198 | ", " + Twine(Max).str() + "]" + Hint); | |
| 190 | 199 | } |
| 191 | 200 | |
| 192 | // Sign-extend Nth bit all the way to MSB. | |
| 193 | inline int64_t signExtend(uint64_t V, int N) { | |
| 194 | return int64_t(V << (64 - N)) >> (64 - N); | |
| 201 | inline unsigned getPltEntryOffset(unsigned Idx) { | |
| 202 | return Target->PltHeaderSize + Target->PltEntrySize * Idx; | |
| 195 | 203 | } |
| 196 | 204 | |
| 197 | 205 | // Make sure that V can be represented as an N bit signed integer. |
| 198 | 206 | inline void checkInt(uint8_t *Loc, int64_t V, int N, RelType Type) { |
| 199 | if (V != signExtend(V, N)) | |
| 207 | if (V != llvm::SignExtend64(V, N)) | |
| 200 | 208 | reportRangeError(Loc, Type, Twine(V), llvm::minIntN(N), llvm::maxIntN(N)); |
| 201 | 209 | } |
| 202 | 210 | |
| ... | ... | @@ -210,7 +218,7 @@ inline void checkUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) { |
| 210 | 218 | inline void checkIntUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) { |
| 211 | 219 | // For the error message we should cast V to a signed integer so that error |
| 212 | 220 | // messages show a small negative value rather than an extremely large one |
| 213 | if (V != (uint64_t)signExtend(V, N) && (V >> N) != 0) | |
| 221 | if (V != (uint64_t)llvm::SignExtend64(V, N) && (V >> N) != 0) | |
| 214 | 222 | reportRangeError(Loc, Type, Twine((int64_t)V), llvm::minIntN(N), |
| 215 | 223 | llvm::maxIntN(N)); |
| 216 | 224 | } |
deps/lld/ELF/Thunks.cpp+280-24| ... | ... | @@ -159,6 +159,50 @@ public: |
| 159 | 159 | void addSymbols(ThunkSection &IS) override; |
| 160 | 160 | }; |
| 161 | 161 | |
| 162 | // Implementations of Thunks for older Arm architectures that do not support | |
| 163 | // the movt/movw instructions. These thunks require at least Architecture v5 | |
| 164 | // as used on processors such as the Arm926ej-s. There are no Thumb entry | |
| 165 | // points as there is no Thumb branch instruction on these architecture that | |
| 166 | // can result in a thunk | |
| 167 | class ARMV5ABSLongThunk final : public ARMThunk { | |
| 168 | public: | |
| 169 | ARMV5ABSLongThunk(Symbol &Dest) : ARMThunk(Dest) {} | |
| 170 | ||
| 171 | uint32_t sizeLong() override { return 8; } | |
| 172 | void writeLong(uint8_t *Buf) override; | |
| 173 | void addSymbols(ThunkSection &IS) override; | |
| 174 | bool isCompatibleWith(uint32_t RelocType) const override; | |
| 175 | }; | |
| 176 | ||
| 177 | class ARMV5PILongThunk final : public ARMThunk { | |
| 178 | public: | |
| 179 | ARMV5PILongThunk(Symbol &Dest) : ARMThunk(Dest) {} | |
| 180 | ||
| 181 | uint32_t sizeLong() override { return 16; } | |
| 182 | void writeLong(uint8_t *Buf) override; | |
| 183 | void addSymbols(ThunkSection &IS) override; | |
| 184 | bool isCompatibleWith(uint32_t RelocType) const override; | |
| 185 | }; | |
| 186 | ||
| 187 | // Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted | |
| 188 | class ThumbV6MABSLongThunk final : public ThumbThunk { | |
| 189 | public: | |
| 190 | ThumbV6MABSLongThunk(Symbol &Dest) : ThumbThunk(Dest) {} | |
| 191 | ||
| 192 | uint32_t sizeLong() override { return 12; } | |
| 193 | void writeLong(uint8_t *Buf) override; | |
| 194 | void addSymbols(ThunkSection &IS) override; | |
| 195 | }; | |
| 196 | ||
| 197 | class ThumbV6MPILongThunk final : public ThumbThunk { | |
| 198 | public: | |
| 199 | ThumbV6MPILongThunk(Symbol &Dest) : ThumbThunk(Dest) {} | |
| 200 | ||
| 201 | uint32_t sizeLong() override { return 16; } | |
| 202 | void writeLong(uint8_t *Buf) override; | |
| 203 | void addSymbols(ThunkSection &IS) override; | |
| 204 | }; | |
| 205 | ||
| 162 | 206 | // MIPS LA25 thunk |
| 163 | 207 | class MipsThunk final : public Thunk { |
| 164 | 208 | public: |
| ... | ... | @@ -209,6 +253,46 @@ public: |
| 209 | 253 | void addSymbols(ThunkSection &IS) override; |
| 210 | 254 | }; |
| 211 | 255 | |
| 256 | // A bl instruction uses a signed 24 bit offset, with an implicit 4 byte | |
| 257 | // alignment. This gives a possible 26 bits of 'reach'. If the call offset is | |
| 258 | // larger then that we need to emit a long-branch thunk. The target address | |
| 259 | // of the callee is stored in a table to be accessed TOC-relative. Since the | |
| 260 | // call must be local (a non-local call will have a PltCallStub instead) the | |
| 261 | // table stores the address of the callee's local entry point. For | |
| 262 | // position-independent code a corresponding relative dynamic relocation is | |
| 263 | // used. | |
| 264 | class PPC64LongBranchThunk : public Thunk { | |
| 265 | public: | |
| 266 | uint32_t size() override { return 16; } | |
| 267 | void writeTo(uint8_t *Buf) override; | |
| 268 | void addSymbols(ThunkSection &IS) override; | |
| 269 | ||
| 270 | protected: | |
| 271 | PPC64LongBranchThunk(Symbol &Dest) : Thunk(Dest) {} | |
| 272 | }; | |
| 273 | ||
| 274 | class PPC64PILongBranchThunk final : public PPC64LongBranchThunk { | |
| 275 | public: | |
| 276 | PPC64PILongBranchThunk(Symbol &Dest) : PPC64LongBranchThunk(Dest) { | |
| 277 | assert(!Dest.IsPreemptible); | |
| 278 | if (Dest.isInPPC64Branchlt()) | |
| 279 | return; | |
| 280 | ||
| 281 | In.PPC64LongBranchTarget->addEntry(Dest); | |
| 282 | In.RelaDyn->addReloc({Target->RelativeRel, In.PPC64LongBranchTarget, | |
| 283 | Dest.getPPC64LongBranchOffset(), true, &Dest, | |
| 284 | getPPC64GlobalEntryToLocalEntryOffset(Dest.StOther)}); | |
| 285 | } | |
| 286 | }; | |
| 287 | ||
| 288 | class PPC64PDLongBranchThunk final : public PPC64LongBranchThunk { | |
| 289 | public: | |
| 290 | PPC64PDLongBranchThunk(Symbol &Dest) : PPC64LongBranchThunk(Dest) { | |
| 291 | if (!Dest.isInPPC64Branchlt()) | |
| 292 | In.PPC64LongBranchTarget->addEntry(Dest); | |
| 293 | } | |
| 294 | }; | |
| 295 | ||
| 212 | 296 | } // end anonymous namespace |
| 213 | 297 | |
| 214 | 298 | Defined *Thunk::addSymbol(StringRef Name, uint8_t Type, uint64_t Value, |
| ... | ... | @@ -395,12 +479,12 @@ void ARMV7PILongThunk::writeLong(uint8_t *Buf) { |
| 395 | 479 | const uint8_t Data[] = { |
| 396 | 480 | 0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) + 8) |
| 397 | 481 | 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P) + 8) |
| 398 | 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc | |
| 399 | 0x1c, 0xff, 0x2f, 0xe1, // bx r12 | |
| 482 | 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc | |
| 483 | 0x1c, 0xff, 0x2f, 0xe1, // bx ip | |
| 400 | 484 | }; |
| 401 | 485 | uint64_t S = getARMThunkDestVA(Destination); |
| 402 | 486 | uint64_t P = getThunkTargetSym()->getVA(); |
| 403 | uint64_t Offset = S - P - 16; | |
| 487 | int64_t Offset = S - P - 16; | |
| 404 | 488 | memcpy(Buf, Data, sizeof(Data)); |
| 405 | 489 | Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, Offset); |
| 406 | 490 | Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, Offset); |
| ... | ... | @@ -416,12 +500,12 @@ void ThumbV7PILongThunk::writeLong(uint8_t *Buf) { |
| 416 | 500 | const uint8_t Data[] = { |
| 417 | 501 | 0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4) |
| 418 | 502 | 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4) |
| 419 | 0xfc, 0x44, // L1: add r12, pc | |
| 420 | 0x60, 0x47, // bx r12 | |
| 503 | 0xfc, 0x44, // L1: add ip, pc | |
| 504 | 0x60, 0x47, // bx ip | |
| 421 | 505 | }; |
| 422 | 506 | uint64_t S = getARMThunkDestVA(Destination); |
| 423 | 507 | uint64_t P = getThunkTargetSym()->getVA() & ~0x1; |
| 424 | uint64_t Offset = S - P - 12; | |
| 508 | int64_t Offset = S - P - 12; | |
| 425 | 509 | memcpy(Buf, Data, sizeof(Data)); |
| 426 | 510 | Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, Offset); |
| 427 | 511 | Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, Offset); |
| ... | ... | @@ -433,6 +517,102 @@ void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) { |
| 433 | 517 | addSymbol("$t", STT_NOTYPE, 0, IS); |
| 434 | 518 | } |
| 435 | 519 | |
| 520 | void ARMV5ABSLongThunk::writeLong(uint8_t *Buf) { | |
| 521 | const uint8_t Data[] = { | |
| 522 | 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc,#-4] ; L1 | |
| 523 | 0x00, 0x00, 0x00, 0x00, // L1: .word S | |
| 524 | }; | |
| 525 | memcpy(Buf, Data, sizeof(Data)); | |
| 526 | Target->relocateOne(Buf + 4, R_ARM_ABS32, getARMThunkDestVA(Destination)); | |
| 527 | } | |
| 528 | ||
| 529 | void ARMV5ABSLongThunk::addSymbols(ThunkSection &IS) { | |
| 530 | addSymbol(Saver.save("__ARMv5ABSLongThunk_" + Destination.getName()), | |
| 531 | STT_FUNC, 0, IS); | |
| 532 | addSymbol("$a", STT_NOTYPE, 0, IS); | |
| 533 | addSymbol("$d", STT_NOTYPE, 4, IS); | |
| 534 | } | |
| 535 | ||
| 536 | bool ARMV5ABSLongThunk::isCompatibleWith(uint32_t RelocType) const { | |
| 537 | // Thumb branch relocations can't use BLX | |
| 538 | return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24; | |
| 539 | } | |
| 540 | ||
| 541 | void ARMV5PILongThunk::writeLong(uint8_t *Buf) { | |
| 542 | const uint8_t Data[] = { | |
| 543 | 0x04, 0xc0, 0x9f, 0xe5, // P: ldr ip, [pc,#4] ; L2 | |
| 544 | 0x0c, 0xc0, 0x8f, 0xe0, // L1: add ip, pc, ip | |
| 545 | 0x1c, 0xff, 0x2f, 0xe1, // bx ip | |
| 546 | 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 8) | |
| 547 | }; | |
| 548 | uint64_t S = getARMThunkDestVA(Destination); | |
| 549 | uint64_t P = getThunkTargetSym()->getVA() & ~0x1; | |
| 550 | memcpy(Buf, Data, sizeof(Data)); | |
| 551 | Target->relocateOne(Buf + 12, R_ARM_REL32, S - P - 12); | |
| 552 | } | |
| 553 | ||
| 554 | void ARMV5PILongThunk::addSymbols(ThunkSection &IS) { | |
| 555 | addSymbol(Saver.save("__ARMV5PILongThunk_" + Destination.getName()), STT_FUNC, | |
| 556 | 0, IS); | |
| 557 | addSymbol("$a", STT_NOTYPE, 0, IS); | |
| 558 | addSymbol("$d", STT_NOTYPE, 12, IS); | |
| 559 | } | |
| 560 | ||
| 561 | bool ARMV5PILongThunk::isCompatibleWith(uint32_t RelocType) const { | |
| 562 | // Thumb branch relocations can't use BLX | |
| 563 | return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24; | |
| 564 | } | |
| 565 | ||
| 566 | void ThumbV6MABSLongThunk::writeLong(uint8_t *Buf) { | |
| 567 | // Most Thumb instructions cannot access the high registers r8 - r15. As the | |
| 568 | // only register we can corrupt is r12 we must instead spill a low register | |
| 569 | // to the stack to use as a scratch register. We push r1 even though we | |
| 570 | // don't need to get some space to use for the return address. | |
| 571 | const uint8_t Data[] = { | |
| 572 | 0x03, 0xb4, // push {r0, r1} ; Obtain scratch registers | |
| 573 | 0x01, 0x48, // ldr r0, [pc, #4] ; L1 | |
| 574 | 0x01, 0x90, // str r0, [sp, #4] ; SP + 4 = S | |
| 575 | 0x01, 0xbd, // pop {r0, pc} ; restore r0 and branch to dest | |
| 576 | 0x00, 0x00, 0x00, 0x00 // L1: .word S | |
| 577 | }; | |
| 578 | uint64_t S = getARMThunkDestVA(Destination); | |
| 579 | memcpy(Buf, Data, sizeof(Data)); | |
| 580 | Target->relocateOne(Buf + 8, R_ARM_ABS32, S); | |
| 581 | } | |
| 582 | ||
| 583 | void ThumbV6MABSLongThunk::addSymbols(ThunkSection &IS) { | |
| 584 | addSymbol(Saver.save("__Thumbv6MABSLongThunk_" + Destination.getName()), | |
| 585 | STT_FUNC, 1, IS); | |
| 586 | addSymbol("$t", STT_NOTYPE, 0, IS); | |
| 587 | addSymbol("$d", STT_NOTYPE, 8, IS); | |
| 588 | } | |
| 589 | ||
| 590 | void ThumbV6MPILongThunk::writeLong(uint8_t *Buf) { | |
| 591 | // Most Thumb instructions cannot access the high registers r8 - r15. As the | |
| 592 | // only register we can corrupt is ip (r12) we must instead spill a low | |
| 593 | // register to the stack to use as a scratch register. | |
| 594 | const uint8_t Data[] = { | |
| 595 | 0x01, 0xb4, // P: push {r0} ; Obtain scratch register | |
| 596 | 0x02, 0x48, // ldr r0, [pc, #8] ; L2 | |
| 597 | 0x84, 0x46, // mov ip, r0 ; high to low register | |
| 598 | 0x01, 0xbc, // pop {r0} ; restore scratch register | |
| 599 | 0xe7, 0x44, // L1: add pc, ip ; transfer control | |
| 600 | 0xc0, 0x46, // nop ; pad to 4-byte boundary | |
| 601 | 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 4) | |
| 602 | }; | |
| 603 | uint64_t S = getARMThunkDestVA(Destination); | |
| 604 | uint64_t P = getThunkTargetSym()->getVA() & ~0x1; | |
| 605 | memcpy(Buf, Data, sizeof(Data)); | |
| 606 | Target->relocateOne(Buf + 12, R_ARM_REL32, S - P - 12); | |
| 607 | } | |
| 608 | ||
| 609 | void ThumbV6MPILongThunk::addSymbols(ThunkSection &IS) { | |
| 610 | addSymbol(Saver.save("__Thumbv6MPILongThunk_" + Destination.getName()), | |
| 611 | STT_FUNC, 1, IS); | |
| 612 | addSymbol("$t", STT_NOTYPE, 0, IS); | |
| 613 | addSymbol("$d", STT_NOTYPE, 12, IS); | |
| 614 | } | |
| 615 | ||
| 436 | 616 | // Write MIPS LA25 thunk code to call PIC function from the non-PIC one. |
| 437 | 617 | void MipsThunk::writeTo(uint8_t *Buf) { |
| 438 | 618 | uint64_t S = Destination.getVA(); |
| ... | ... | @@ -502,17 +682,21 @@ InputSection *MicroMipsR6Thunk::getTargetInputSection() const { |
| 502 | 682 | return dyn_cast<InputSection>(DR.Section); |
| 503 | 683 | } |
| 504 | 684 | |
| 505 | void PPC64PltCallStub::writeTo(uint8_t *Buf) { | |
| 506 | int64_t Off = Destination.getGotPltVA() - getPPC64TocBase(); | |
| 507 | // Need to add 0x8000 to offset to account for the low bits being signed. | |
| 508 | uint16_t OffHa = (Off + 0x8000) >> 16; | |
| 509 | uint16_t OffLo = Off; | |
| 685 | static void writePPCLoadAndBranch(uint8_t *Buf, int64_t Offset) { | |
| 686 | uint16_t OffHa = (Offset + 0x8000) >> 16; | |
| 687 | uint16_t OffLo = Offset & 0xffff; | |
| 510 | 688 | |
| 511 | write32(Buf + 0, 0xf8410018); // std r2,24(r1) | |
| 512 | write32(Buf + 4, 0x3d820000 | OffHa); // addis r12,r2, X@plt@to@ha | |
| 513 | write32(Buf + 8, 0xe98c0000 | OffLo); // ld r12,X@plt@toc@l(r12) | |
| 514 | write32(Buf + 12, 0x7d8903a6); // mtctr r12 | |
| 515 | write32(Buf + 16, 0x4e800420); // bctr | |
| 689 | write32(Buf + 0, 0x3d820000 | OffHa); // addis r12, r2, OffHa | |
| 690 | write32(Buf + 4, 0xe98c0000 | OffLo); // ld r12, OffLo(r12) | |
| 691 | write32(Buf + 8, 0x7d8903a6); // mtctr r12 | |
| 692 | write32(Buf + 12, 0x4e800420); // bctr | |
| 693 | } | |
| 694 | ||
| 695 | void PPC64PltCallStub::writeTo(uint8_t *Buf) { | |
| 696 | int64_t Offset = Destination.getGotPltVA() - getPPC64TocBase(); | |
| 697 | // Save the TOC pointer to the save-slot reserved in the call frame. | |
| 698 | write32(Buf + 0, 0xf8410018); // std r2,24(r1) | |
| 699 | writePPCLoadAndBranch(Buf + 4, Offset); | |
| 516 | 700 | } |
| 517 | 701 | |
| 518 | 702 | void PPC64PltCallStub::addSymbols(ThunkSection &IS) { |
| ... | ... | @@ -521,6 +705,16 @@ void PPC64PltCallStub::addSymbols(ThunkSection &IS) { |
| 521 | 705 | S->NeedsTocRestore = true; |
| 522 | 706 | } |
| 523 | 707 | |
| 708 | void PPC64LongBranchThunk::writeTo(uint8_t *Buf) { | |
| 709 | int64_t Offset = Destination.getPPC64LongBranchTableVA() - getPPC64TocBase(); | |
| 710 | writePPCLoadAndBranch(Buf, Offset); | |
| 711 | } | |
| 712 | ||
| 713 | void PPC64LongBranchThunk::addSymbols(ThunkSection &IS) { | |
| 714 | addSymbol(Saver.save("__long_branch_" + Destination.getName()), STT_FUNC, 0, | |
| 715 | IS); | |
| 716 | } | |
| 717 | ||
| 524 | 718 | Thunk::Thunk(Symbol &D) : Destination(D), Offset(0) {} |
| 525 | 719 | |
| 526 | 720 | Thunk::~Thunk() = default; |
| ... | ... | @@ -528,28 +722,85 @@ Thunk::~Thunk() = default; |
| 528 | 722 | static Thunk *addThunkAArch64(RelType Type, Symbol &S) { |
| 529 | 723 | if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26) |
| 530 | 724 | fatal("unrecognized relocation type"); |
| 531 | if (Config->Pic) | |
| 725 | if (Config->PicThunk) | |
| 532 | 726 | return make<AArch64ADRPThunk>(S); |
| 533 | 727 | return make<AArch64ABSLongThunk>(S); |
| 534 | 728 | } |
| 535 | 729 | |
| 536 | 730 | // Creates a thunk for Thumb-ARM interworking. |
| 537 | static Thunk *addThunkArm(RelType Reloc, Symbol &S) { | |
| 538 | // ARM relocations need ARM to Thumb interworking Thunks. | |
| 539 | // Thumb relocations need Thumb to ARM relocations. | |
| 540 | // Use position independent Thunks if we require position independent code. | |
| 731 | // Arm Architectures v5 and v6 do not support Thumb2 technology. This means | |
| 732 | // - MOVT and MOVW instructions cannot be used | |
| 733 | // - Only Thumb relocation that can generate a Thunk is a BL, this can always | |
| 734 | // be transformed into a BLX | |
| 735 | static Thunk *addThunkPreArmv7(RelType Reloc, Symbol &S) { | |
| 541 | 736 | switch (Reloc) { |
| 542 | 737 | case R_ARM_PC24: |
| 543 | 738 | case R_ARM_PLT32: |
| 544 | 739 | case R_ARM_JUMP24: |
| 545 | 740 | case R_ARM_CALL: |
| 741 | case R_ARM_THM_CALL: | |
| 742 | if (Config->PicThunk) | |
| 743 | return make<ARMV5PILongThunk>(S); | |
| 744 | return make<ARMV5ABSLongThunk>(S); | |
| 745 | } | |
| 746 | fatal("relocation " + toString(Reloc) + " to " + toString(S) + | |
| 747 | " not supported for Armv5 or Armv6 targets"); | |
| 748 | } | |
| 749 | ||
| 750 | // Create a thunk for Thumb long branch on V6-M. | |
| 751 | // Arm Architecture v6-M only supports Thumb instructions. This means | |
| 752 | // - MOVT and MOVW instructions cannot be used. | |
| 753 | // - Only a limited number of instructions can access registers r8 and above | |
| 754 | // - No interworking support is needed (all Thumb). | |
| 755 | static Thunk *addThunkV6M(RelType Reloc, Symbol &S) { | |
| 756 | switch (Reloc) { | |
| 757 | case R_ARM_THM_JUMP19: | |
| 758 | case R_ARM_THM_JUMP24: | |
| 759 | case R_ARM_THM_CALL: | |
| 546 | 760 | if (Config->Pic) |
| 761 | return make<ThumbV6MPILongThunk>(S); | |
| 762 | return make<ThumbV6MABSLongThunk>(S); | |
| 763 | } | |
| 764 | fatal("relocation " + toString(Reloc) + " to " + toString(S) + | |
| 765 | " not supported for Armv6-M targets"); | |
| 766 | } | |
| 767 | ||
| 768 | // Creates a thunk for Thumb-ARM interworking or branch range extension. | |
| 769 | static Thunk *addThunkArm(RelType Reloc, Symbol &S) { | |
| 770 | // Decide which Thunk is needed based on: | |
| 771 | // Available instruction set | |
| 772 | // - An Arm Thunk can only be used if Arm state is available. | |
| 773 | // - A Thumb Thunk can only be used if Thumb state is available. | |
| 774 | // - Can only use a Thunk if it uses instructions that the Target supports. | |
| 775 | // Relocation is branch or branch and link | |
| 776 | // - Branch instructions cannot change state, can only select Thunk that | |
| 777 | // starts in the same state as the caller. | |
| 778 | // - Branch and link relocations can change state, can select Thunks from | |
| 779 | // either Arm or Thumb. | |
| 780 | // Position independent Thunks if we require position independent code. | |
| 781 | ||
| 782 | // Handle architectures that have restrictions on the instructions that they | |
| 783 | // can use in Thunks. The flags below are set by reading the BuildAttributes | |
| 784 | // of the input objects. InputFiles.cpp contains the mapping from ARM | |
| 785 | // architecture to flag. | |
| 786 | if (!Config->ARMHasMovtMovw) { | |
| 787 | if (!Config->ARMJ1J2BranchEncoding) | |
| 788 | return addThunkPreArmv7(Reloc, S); | |
| 789 | return addThunkV6M(Reloc, S); | |
| 790 | } | |
| 791 | ||
| 792 | switch (Reloc) { | |
| 793 | case R_ARM_PC24: | |
| 794 | case R_ARM_PLT32: | |
| 795 | case R_ARM_JUMP24: | |
| 796 | case R_ARM_CALL: | |
| 797 | if (Config->PicThunk) | |
| 547 | 798 | return make<ARMV7PILongThunk>(S); |
| 548 | 799 | return make<ARMV7ABSLongThunk>(S); |
| 549 | 800 | case R_ARM_THM_JUMP19: |
| 550 | 801 | case R_ARM_THM_JUMP24: |
| 551 | 802 | case R_ARM_THM_CALL: |
| 552 | if (Config->Pic) | |
| 803 | if (Config->PicThunk) | |
| 553 | 804 | return make<ThumbV7PILongThunk>(S); |
| 554 | 805 | return make<ThumbV7ABSLongThunk>(S); |
| 555 | 806 | } |
| ... | ... | @@ -565,9 +816,14 @@ static Thunk *addThunkMips(RelType Type, Symbol &S) { |
| 565 | 816 | } |
| 566 | 817 | |
| 567 | 818 | static Thunk *addThunkPPC64(RelType Type, Symbol &S) { |
| 568 | if (Type == R_PPC64_REL24) | |
| 819 | assert(Type == R_PPC64_REL24 && "unexpected relocation type for thunk"); | |
| 820 | if (S.isInPlt()) | |
| 569 | 821 | return make<PPC64PltCallStub>(S); |
| 570 | fatal("unexpected relocation type"); | |
| 822 | ||
| 823 | if (Config->PicThunk) | |
| 824 | return make<PPC64PILongBranchThunk>(S); | |
| 825 | ||
| 826 | return make<PPC64PDLongBranchThunk>(S); | |
| 571 | 827 | } |
| 572 | 828 | |
| 573 | 829 | Thunk *addThunk(RelType Type, Symbol &S) { |
deps/lld/ELF/Writer.cpp+403-282| ... | ... | @@ -53,8 +53,10 @@ private: |
| 53 | 53 | void forEachRelSec(llvm::function_ref<void(InputSectionBase &)> Fn); |
| 54 | 54 | void sortSections(); |
| 55 | 55 | void resolveShfLinkOrder(); |
| 56 | void maybeAddThunks(); | |
| 56 | 57 | void sortInputSections(); |
| 57 | 58 | void finalizeSections(); |
| 59 | void checkExecuteOnly(); | |
| 58 | 60 | void setReservedSymbolSections(); |
| 59 | 61 | |
| 60 | 62 | std::vector<PhdrEntry *> createPhdrs(); |
| ... | ... | @@ -77,7 +79,6 @@ private: |
| 77 | 79 | void addRelIpltSymbols(); |
| 78 | 80 | void addStartEndSymbols(); |
| 79 | 81 | void addStartStopSymbols(OutputSection *Sec); |
| 80 | uint64_t getEntryAddr(); | |
| 81 | 82 | |
| 82 | 83 | std::vector<PhdrEntry *> Phdrs; |
| 83 | 84 | |
| ... | ... | @@ -114,18 +115,16 @@ StringRef elf::getOutputSectionName(const InputSectionBase *S) { |
| 114 | 115 | // for instance. |
| 115 | 116 | if (Config->ZKeepTextSectionPrefix) |
| 116 | 117 | for (StringRef V : |
| 117 | {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."}) { | |
| 118 | {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."}) | |
| 118 | 119 | if (isSectionPrefix(V, S->Name)) |
| 119 | 120 | return V.drop_back(); |
| 120 | } | |
| 121 | 121 | |
| 122 | 122 | for (StringRef V : |
| 123 | 123 | {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.", |
| 124 | 124 | ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.", |
| 125 | ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) { | |
| 125 | ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."}) | |
| 126 | 126 | if (isSectionPrefix(V, S->Name)) |
| 127 | 127 | return V.drop_back(); |
| 128 | } | |
| 129 | 128 | |
| 130 | 129 | // CommonSection is identified as "COMMON" in linker scripts. |
| 131 | 130 | // By default, it should go to .bss section. |
| ... | ... | @@ -159,7 +158,7 @@ template <class ELFT> static void combineEhFrameSections() { |
| 159 | 158 | if (!ES || !ES->Live) |
| 160 | 159 | continue; |
| 161 | 160 | |
| 162 | InX::EhFrame->addSection<ELFT>(ES); | |
| 161 | In.EhFrame->addSection<ELFT>(ES); | |
| 163 | 162 | S = nullptr; |
| 164 | 163 | } |
| 165 | 164 | |
| ... | ... | @@ -173,10 +172,14 @@ static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec, |
| 173 | 172 | Symbol *S = Symtab->find(Name); |
| 174 | 173 | if (!S || S->isDefined()) |
| 175 | 174 | return nullptr; |
| 176 | Symbol *Sym = Symtab->addRegular(Name, StOther, STT_NOTYPE, Val, | |
| 177 | /*Size=*/0, Binding, Sec, | |
| 178 | /*File=*/nullptr); | |
| 179 | return cast<Defined>(Sym); | |
| 175 | return Symtab->addDefined(Name, StOther, STT_NOTYPE, Val, | |
| 176 | /*Size=*/0, Binding, Sec, | |
| 177 | /*File=*/nullptr); | |
| 178 | } | |
| 179 | ||
| 180 | static Defined *addAbsolute(StringRef Name) { | |
| 181 | return Symtab->addDefined(Name, STV_HIDDEN, STT_NOTYPE, 0, 0, STB_GLOBAL, | |
| 182 | nullptr, nullptr); | |
| 180 | 183 | } |
| 181 | 184 | |
| 182 | 185 | // The linker is expected to define some symbols depending on |
| ... | ... | @@ -188,21 +191,19 @@ void elf::addReservedSymbols() { |
| 188 | 191 | // to GOT. Default offset is 0x7ff0. |
| 189 | 192 | // See "Global Data Symbols" in Chapter 6 in the following document: |
| 190 | 193 | // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf |
| 191 | ElfSym::MipsGp = Symtab->addAbsolute("_gp", STV_HIDDEN, STB_GLOBAL); | |
| 194 | ElfSym::MipsGp = addAbsolute("_gp"); | |
| 192 | 195 | |
| 193 | 196 | // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between |
| 194 | 197 | // start of function and 'gp' pointer into GOT. |
| 195 | 198 | if (Symtab->find("_gp_disp")) |
| 196 | ElfSym::MipsGpDisp = | |
| 197 | Symtab->addAbsolute("_gp_disp", STV_HIDDEN, STB_GLOBAL); | |
| 199 | ElfSym::MipsGpDisp = addAbsolute("_gp_disp"); | |
| 198 | 200 | |
| 199 | 201 | // The __gnu_local_gp is a magic symbol equal to the current value of 'gp' |
| 200 | 202 | // pointer. This symbol is used in the code generated by .cpload pseudo-op |
| 201 | 203 | // in case of using -mno-shared option. |
| 202 | 204 | // https://sourceware.org/ml/binutils/2004-12/msg00094.html |
| 203 | 205 | if (Symtab->find("__gnu_local_gp")) |
| 204 | ElfSym::MipsLocalGp = | |
| 205 | Symtab->addAbsolute("__gnu_local_gp", STV_HIDDEN, STB_GLOBAL); | |
| 206 | ElfSym::MipsLocalGp = addAbsolute("__gnu_local_gp"); | |
| 206 | 207 | } |
| 207 | 208 | |
| 208 | 209 | // The Power Architecture 64-bit v2 ABI defines a TableOfContents (TOC) which |
| ... | ... | @@ -211,9 +212,20 @@ void elf::addReservedSymbols() { |
| 211 | 212 | // _GLOBAL_OFFSET_TABLE_ and _SDA_BASE_ from the 32-bit ABI. It is used to |
| 212 | 213 | // represent the TOC base which is offset by 0x8000 bytes from the start of |
| 213 | 214 | // the .got section. |
| 214 | ElfSym::GlobalOffsetTable = addOptionalRegular( | |
| 215 | (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_", | |
| 216 | Out::ElfHeader, Target->GotBaseSymOff); | |
| 215 | // We do not allow _GLOBAL_OFFSET_TABLE_ to be defined by input objects as the | |
| 216 | // correctness of some relocations depends on its value. | |
| 217 | StringRef GotTableSymName = | |
| 218 | (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_"; | |
| 219 | if (Symbol *S = Symtab->find(GotTableSymName)) { | |
| 220 | if (S->isDefined()) | |
| 221 | error(toString(S->File) + " cannot redefine linker defined symbol '" + | |
| 222 | GotTableSymName + "'"); | |
| 223 | else | |
| 224 | ElfSym::GlobalOffsetTable = Symtab->addDefined( | |
| 225 | GotTableSymName, STV_HIDDEN, STT_NOTYPE, Target->GotBaseSymOff, | |
| 226 | /*Size=*/0, STB_GLOBAL, Out::ElfHeader, | |
| 227 | /*File=*/nullptr); | |
| 228 | } | |
| 217 | 229 | |
| 218 | 230 | // __ehdr_start is the location of ELF file headers. Note that we define |
| 219 | 231 | // this symbol unconditionally even when using a linker script, which |
| ... | ... | @@ -263,54 +275,52 @@ template <class ELFT> static void createSyntheticSections() { |
| 263 | 275 | |
| 264 | 276 | auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); }; |
| 265 | 277 | |
| 266 | InX::DynStrTab = make<StringTableSection>(".dynstr", true); | |
| 267 | InX::Dynamic = make<DynamicSection<ELFT>>(); | |
| 278 | In.DynStrTab = make<StringTableSection>(".dynstr", true); | |
| 279 | In.Dynamic = make<DynamicSection<ELFT>>(); | |
| 268 | 280 | if (Config->AndroidPackDynRelocs) { |
| 269 | InX::RelaDyn = make<AndroidPackedRelocationSection<ELFT>>( | |
| 281 | In.RelaDyn = make<AndroidPackedRelocationSection<ELFT>>( | |
| 270 | 282 | Config->IsRela ? ".rela.dyn" : ".rel.dyn"); |
| 271 | 283 | } else { |
| 272 | InX::RelaDyn = make<RelocationSection<ELFT>>( | |
| 284 | In.RelaDyn = make<RelocationSection<ELFT>>( | |
| 273 | 285 | Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc); |
| 274 | 286 | } |
| 275 | InX::ShStrTab = make<StringTableSection>(".shstrtab", false); | |
| 287 | In.ShStrTab = make<StringTableSection>(".shstrtab", false); | |
| 276 | 288 | |
| 277 | 289 | Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC); |
| 278 | 290 | Out::ProgramHeaders->Alignment = Config->Wordsize; |
| 279 | 291 | |
| 280 | 292 | if (needsInterpSection()) { |
| 281 | InX::Interp = createInterpSection(); | |
| 282 | Add(InX::Interp); | |
| 283 | } else { | |
| 284 | InX::Interp = nullptr; | |
| 293 | In.Interp = createInterpSection(); | |
| 294 | Add(In.Interp); | |
| 285 | 295 | } |
| 286 | 296 | |
| 287 | 297 | if (Config->Strip != StripPolicy::All) { |
| 288 | InX::StrTab = make<StringTableSection>(".strtab", false); | |
| 289 | InX::SymTab = make<SymbolTableSection<ELFT>>(*InX::StrTab); | |
| 290 | InX::SymTabShndx = make<SymtabShndxSection>(); | |
| 298 | In.StrTab = make<StringTableSection>(".strtab", false); | |
| 299 | In.SymTab = make<SymbolTableSection<ELFT>>(*In.StrTab); | |
| 300 | In.SymTabShndx = make<SymtabShndxSection>(); | |
| 291 | 301 | } |
| 292 | 302 | |
| 293 | 303 | if (Config->BuildId != BuildIdKind::None) { |
| 294 | InX::BuildId = make<BuildIdSection>(); | |
| 295 | Add(InX::BuildId); | |
| 304 | In.BuildId = make<BuildIdSection>(); | |
| 305 | Add(In.BuildId); | |
| 296 | 306 | } |
| 297 | 307 | |
| 298 | InX::Bss = make<BssSection>(".bss", 0, 1); | |
| 299 | Add(InX::Bss); | |
| 308 | In.Bss = make<BssSection>(".bss", 0, 1); | |
| 309 | Add(In.Bss); | |
| 300 | 310 | |
| 301 | 311 | // If there is a SECTIONS command and a .data.rel.ro section name use name |
| 302 | 312 | // .data.rel.ro.bss so that we match in the .data.rel.ro output section. |
| 303 | 313 | // This makes sure our relro is contiguous. |
| 304 | 314 | bool HasDataRelRo = Script->HasSectionsCommand && findSection(".data.rel.ro"); |
| 305 | InX::BssRelRo = | |
| 315 | In.BssRelRo = | |
| 306 | 316 | make<BssSection>(HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1); |
| 307 | Add(InX::BssRelRo); | |
| 317 | Add(In.BssRelRo); | |
| 308 | 318 | |
| 309 | 319 | // Add MIPS-specific sections. |
| 310 | 320 | if (Config->EMachine == EM_MIPS) { |
| 311 | 321 | if (!Config->Shared && Config->HasDynSymTab) { |
| 312 | InX::MipsRldMap = make<MipsRldMapSection>(); | |
| 313 | Add(InX::MipsRldMap); | |
| 322 | In.MipsRldMap = make<MipsRldMapSection>(); | |
| 323 | Add(In.MipsRldMap); | |
| 314 | 324 | } |
| 315 | 325 | if (auto *Sec = MipsAbiFlagsSection<ELFT>::create()) |
| 316 | 326 | Add(Sec); |
| ... | ... | @@ -321,65 +331,70 @@ template <class ELFT> static void createSyntheticSections() { |
| 321 | 331 | } |
| 322 | 332 | |
| 323 | 333 | if (Config->HasDynSymTab) { |
| 324 | InX::DynSymTab = make<SymbolTableSection<ELFT>>(*InX::DynStrTab); | |
| 325 | Add(InX::DynSymTab); | |
| 334 | In.DynSymTab = make<SymbolTableSection<ELFT>>(*In.DynStrTab); | |
| 335 | Add(In.DynSymTab); | |
| 326 | 336 | |
| 327 | In<ELFT>::VerSym = make<VersionTableSection<ELFT>>(); | |
| 328 | Add(In<ELFT>::VerSym); | |
| 337 | InX<ELFT>::VerSym = make<VersionTableSection<ELFT>>(); | |
| 338 | Add(InX<ELFT>::VerSym); | |
| 329 | 339 | |
| 330 | 340 | if (!Config->VersionDefinitions.empty()) { |
| 331 | In<ELFT>::VerDef = make<VersionDefinitionSection<ELFT>>(); | |
| 332 | Add(In<ELFT>::VerDef); | |
| 341 | In.VerDef = make<VersionDefinitionSection>(); | |
| 342 | Add(In.VerDef); | |
| 333 | 343 | } |
| 334 | 344 | |
| 335 | In<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>(); | |
| 336 | Add(In<ELFT>::VerNeed); | |
| 345 | InX<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>(); | |
| 346 | Add(InX<ELFT>::VerNeed); | |
| 337 | 347 | |
| 338 | 348 | if (Config->GnuHash) { |
| 339 | InX::GnuHashTab = make<GnuHashTableSection>(); | |
| 340 | Add(InX::GnuHashTab); | |
| 349 | In.GnuHashTab = make<GnuHashTableSection>(); | |
| 350 | Add(In.GnuHashTab); | |
| 341 | 351 | } |
| 342 | 352 | |
| 343 | 353 | if (Config->SysvHash) { |
| 344 | InX::HashTab = make<HashTableSection>(); | |
| 345 | Add(InX::HashTab); | |
| 354 | In.HashTab = make<HashTableSection>(); | |
| 355 | Add(In.HashTab); | |
| 346 | 356 | } |
| 347 | 357 | |
| 348 | Add(InX::Dynamic); | |
| 349 | Add(InX::DynStrTab); | |
| 350 | Add(InX::RelaDyn); | |
| 358 | Add(In.Dynamic); | |
| 359 | Add(In.DynStrTab); | |
| 360 | Add(In.RelaDyn); | |
| 351 | 361 | } |
| 352 | 362 | |
| 353 | 363 | if (Config->RelrPackDynRelocs) { |
| 354 | InX::RelrDyn = make<RelrSection<ELFT>>(); | |
| 355 | Add(InX::RelrDyn); | |
| 364 | In.RelrDyn = make<RelrSection<ELFT>>(); | |
| 365 | Add(In.RelrDyn); | |
| 356 | 366 | } |
| 357 | 367 | |
| 358 | 368 | // Add .got. MIPS' .got is so different from the other archs, |
| 359 | 369 | // it has its own class. |
| 360 | 370 | if (Config->EMachine == EM_MIPS) { |
| 361 | InX::MipsGot = make<MipsGotSection>(); | |
| 362 | Add(InX::MipsGot); | |
| 371 | In.MipsGot = make<MipsGotSection>(); | |
| 372 | Add(In.MipsGot); | |
| 363 | 373 | } else { |
| 364 | InX::Got = make<GotSection>(); | |
| 365 | Add(InX::Got); | |
| 374 | In.Got = make<GotSection>(); | |
| 375 | Add(In.Got); | |
| 366 | 376 | } |
| 367 | 377 | |
| 368 | InX::GotPlt = make<GotPltSection>(); | |
| 369 | Add(InX::GotPlt); | |
| 370 | InX::IgotPlt = make<IgotPltSection>(); | |
| 371 | Add(InX::IgotPlt); | |
| 378 | if (Config->EMachine == EM_PPC64) { | |
| 379 | In.PPC64LongBranchTarget = make<PPC64LongBranchTargetSection>(); | |
| 380 | Add(In.PPC64LongBranchTarget); | |
| 381 | } | |
| 382 | ||
| 383 | In.GotPlt = make<GotPltSection>(); | |
| 384 | Add(In.GotPlt); | |
| 385 | In.IgotPlt = make<IgotPltSection>(); | |
| 386 | Add(In.IgotPlt); | |
| 372 | 387 | |
| 373 | 388 | if (Config->GdbIndex) { |
| 374 | InX::GdbIndex = GdbIndexSection::create<ELFT>(); | |
| 375 | Add(InX::GdbIndex); | |
| 389 | In.GdbIndex = GdbIndexSection::create<ELFT>(); | |
| 390 | Add(In.GdbIndex); | |
| 376 | 391 | } |
| 377 | 392 | |
| 378 | 393 | // We always need to add rel[a].plt to output if it has entries. |
| 379 | 394 | // Even for static linking it can contain R_[*]_IRELATIVE relocations. |
| 380 | InX::RelaPlt = make<RelocationSection<ELFT>>( | |
| 395 | In.RelaPlt = make<RelocationSection<ELFT>>( | |
| 381 | 396 | Config->IsRela ? ".rela.plt" : ".rel.plt", false /*Sort*/); |
| 382 | Add(InX::RelaPlt); | |
| 397 | Add(In.RelaPlt); | |
| 383 | 398 | |
| 384 | 399 | // The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure |
| 385 | 400 | // that the IRelative relocations are processed last by the dynamic loader. |
| ... | ... | @@ -387,34 +402,42 @@ template <class ELFT> static void createSyntheticSections() { |
| 387 | 402 | // packing is enabled because that would cause a section type mismatch. |
| 388 | 403 | // However, because the Android dynamic loader reads .rel.plt after .rel.dyn, |
| 389 | 404 | // we can get the desired behaviour by placing the iplt section in .rel.plt. |
| 390 | InX::RelaIplt = make<RelocationSection<ELFT>>( | |
| 405 | In.RelaIplt = make<RelocationSection<ELFT>>( | |
| 391 | 406 | (Config->EMachine == EM_ARM && !Config->AndroidPackDynRelocs) |
| 392 | 407 | ? ".rel.dyn" |
| 393 | : InX::RelaPlt->Name, | |
| 408 | : In.RelaPlt->Name, | |
| 394 | 409 | false /*Sort*/); |
| 395 | Add(InX::RelaIplt); | |
| 396 | ||
| 397 | InX::Plt = make<PltSection>(false); | |
| 398 | Add(InX::Plt); | |
| 399 | InX::Iplt = make<PltSection>(true); | |
| 400 | Add(InX::Iplt); | |
| 410 | Add(In.RelaIplt); | |
| 411 | ||
| 412 | In.Plt = make<PltSection>(false); | |
| 413 | Add(In.Plt); | |
| 414 | In.Iplt = make<PltSection>(true); | |
| 415 | Add(In.Iplt); | |
| 416 | ||
| 417 | // .note.GNU-stack is always added when we are creating a re-linkable | |
| 418 | // object file. Other linkers are using the presence of this marker | |
| 419 | // section to control the executable-ness of the stack area, but that | |
| 420 | // is irrelevant these days. Stack area should always be non-executable | |
| 421 | // by default. So we emit this section unconditionally. | |
| 422 | if (Config->Relocatable) | |
| 423 | Add(make<GnuStackSection>()); | |
| 401 | 424 | |
| 402 | 425 | if (!Config->Relocatable) { |
| 403 | 426 | if (Config->EhFrameHdr) { |
| 404 | InX::EhFrameHdr = make<EhFrameHeader>(); | |
| 405 | Add(InX::EhFrameHdr); | |
| 427 | In.EhFrameHdr = make<EhFrameHeader>(); | |
| 428 | Add(In.EhFrameHdr); | |
| 406 | 429 | } |
| 407 | InX::EhFrame = make<EhFrameSection>(); | |
| 408 | Add(InX::EhFrame); | |
| 430 | In.EhFrame = make<EhFrameSection>(); | |
| 431 | Add(In.EhFrame); | |
| 409 | 432 | } |
| 410 | 433 | |
| 411 | if (InX::SymTab) | |
| 412 | Add(InX::SymTab); | |
| 413 | if (InX::SymTabShndx) | |
| 414 | Add(InX::SymTabShndx); | |
| 415 | Add(InX::ShStrTab); | |
| 416 | if (InX::StrTab) | |
| 417 | Add(InX::StrTab); | |
| 434 | if (In.SymTab) | |
| 435 | Add(In.SymTab); | |
| 436 | if (In.SymTabShndx) | |
| 437 | Add(In.SymTabShndx); | |
| 438 | Add(In.ShStrTab); | |
| 439 | if (In.StrTab) | |
| 440 | Add(In.StrTab); | |
| 418 | 441 | |
| 419 | 442 | if (Config->EMachine == EM_ARM && !Config->Relocatable) |
| 420 | 443 | // Add a sentinel to terminate .ARM.exidx. It helps an unwinder |
| ... | ... | @@ -451,6 +474,7 @@ template <class ELFT> void Writer<ELFT>::run() { |
| 451 | 474 | // to the string table, and add entries to .got and .plt. |
| 452 | 475 | // finalizeSections does that. |
| 453 | 476 | finalizeSections(); |
| 477 | checkExecuteOnly(); | |
| 454 | 478 | if (errorCount()) |
| 455 | 479 | return; |
| 456 | 480 | |
| ... | ... | @@ -476,10 +500,9 @@ template <class ELFT> void Writer<ELFT>::run() { |
| 476 | 500 | |
| 477 | 501 | setPhdrs(); |
| 478 | 502 | |
| 479 | if (Config->Relocatable) { | |
| 503 | if (Config->Relocatable) | |
| 480 | 504 | for (OutputSection *Sec : OutputSections) |
| 481 | 505 | Sec->Addr = 0; |
| 482 | } | |
| 483 | 506 | |
| 484 | 507 | if (Config->CheckSections) |
| 485 | 508 | checkSections(); |
| ... | ... | @@ -548,9 +571,11 @@ static bool includeInSymtab(const Symbol &B) { |
| 548 | 571 | if (!Sec) |
| 549 | 572 | return true; |
| 550 | 573 | Sec = Sec->Repl; |
| 574 | ||
| 551 | 575 | // Exclude symbols pointing to garbage-collected sections. |
| 552 | 576 | if (isa<InputSectionBase>(Sec) && !Sec->Live) |
| 553 | 577 | return false; |
| 578 | ||
| 554 | 579 | if (auto *S = dyn_cast<MergeInputSection>(Sec)) |
| 555 | 580 | if (!S->getSectionPiece(D->Value)->Live) |
| 556 | 581 | return false; |
| ... | ... | @@ -562,7 +587,7 @@ static bool includeInSymtab(const Symbol &B) { |
| 562 | 587 | // Local symbols are not in the linker's symbol table. This function scans |
| 563 | 588 | // each object file's symbol table to copy local symbols to the output. |
| 564 | 589 | template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { |
| 565 | if (!InX::SymTab) | |
| 590 | if (!In.SymTab) | |
| 566 | 591 | return; |
| 567 | 592 | for (InputFile *File : ObjectFiles) { |
| 568 | 593 | ObjFile<ELFT> *F = cast<ObjFile<ELFT>>(File); |
| ... | ... | @@ -581,16 +606,16 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() { |
| 581 | 606 | SectionBase *Sec = DR->Section; |
| 582 | 607 | if (!shouldKeepInSymtab(Sec, B->getName(), *B)) |
| 583 | 608 | continue; |
| 584 | InX::SymTab->addSymbol(B); | |
| 609 | In.SymTab->addSymbol(B); | |
| 585 | 610 | } |
| 586 | 611 | } |
| 587 | 612 | } |
| 588 | 613 | |
| 614 | // Create a section symbol for each output section so that we can represent | |
| 615 | // relocations that point to the section. If we know that no relocation is | |
| 616 | // referring to a section (that happens if the section is a synthetic one), we | |
| 617 | // don't create a section symbol for that section. | |
| 589 | 618 | template <class ELFT> void Writer<ELFT>::addSectionSymbols() { |
| 590 | // Create a section symbol for each output section so that we can represent | |
| 591 | // relocations that point to the section. If we know that no relocation is | |
| 592 | // referring to a section (that happens if the section is a synthetic one), we | |
| 593 | // don't create a section symbol for that section. | |
| 594 | 619 | for (BaseCommand *Base : Script->SectionCommands) { |
| 595 | 620 | auto *Sec = dyn_cast<OutputSection>(Base); |
| 596 | 621 | if (!Sec) |
| ... | ... | @@ -617,7 +642,7 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() { |
| 617 | 642 | auto *Sym = |
| 618 | 643 | make<Defined>(IS->File, "", STB_LOCAL, /*StOther=*/0, STT_SECTION, |
| 619 | 644 | /*Value=*/0, /*Size=*/0, IS); |
| 620 | InX::SymTab->addSymbol(Sym); | |
| 645 | In.SymTab->addSymbol(Sym); | |
| 621 | 646 | } |
| 622 | 647 | } |
| 623 | 648 | |
| ... | ... | @@ -662,9 +687,14 @@ static bool isRelroSection(const OutputSection *Sec) { |
| 662 | 687 | // .got contains pointers to external symbols. They are resolved by |
| 663 | 688 | // the dynamic linker when a module is loaded into memory, and after |
| 664 | 689 | // that they are not expected to change. So, it can be in RELRO. |
| 665 | if (InX::Got && Sec == InX::Got->getParent()) | |
| 690 | if (In.Got && Sec == In.Got->getParent()) | |
| 666 | 691 | return true; |
| 667 | 692 | |
| 693 | // .toc is a GOT-ish section for PowerPC64. Their contents are accessed | |
| 694 | // through r2 register, which is reserved for that purpose. Since r2 is used | |
| 695 | // for accessing .got as well, .got and .toc need to be close enough in the | |
| 696 | // virtual address space. Usually, .toc comes just after .got. Since we place | |
| 697 | // .got into RELRO, .toc needs to be placed into RELRO too. | |
| 668 | 698 | if (Sec->Name.equals(".toc")) |
| 669 | 699 | return true; |
| 670 | 700 | |
| ... | ... | @@ -672,13 +702,13 @@ static bool isRelroSection(const OutputSection *Sec) { |
| 672 | 702 | // by default resolved lazily, so we usually cannot put it into RELRO. |
| 673 | 703 | // However, if "-z now" is given, the lazy symbol resolution is |
| 674 | 704 | // disabled, which enables us to put it into RELRO. |
| 675 | if (Sec == InX::GotPlt->getParent()) | |
| 705 | if (Sec == In.GotPlt->getParent()) | |
| 676 | 706 | return Config->ZNow; |
| 677 | 707 | |
| 678 | 708 | // .dynamic section contains data for the dynamic linker, and |
| 679 | 709 | // there's no need to write to it at runtime, so it's better to put |
| 680 | 710 | // it into RELRO. |
| 681 | if (Sec == InX::Dynamic->getParent()) | |
| 711 | if (Sec == In.Dynamic->getParent()) | |
| 682 | 712 | return true; |
| 683 | 713 | |
| 684 | 714 | // Sections with some special names are put into RELRO. This is a |
| ... | ... | @@ -700,17 +730,17 @@ static bool isRelroSection(const OutputSection *Sec) { |
| 700 | 730 | // * It is easy two see how similar two ranks are (see getRankProximity). |
| 701 | 731 | enum RankFlags { |
| 702 | 732 | RF_NOT_ADDR_SET = 1 << 18, |
| 703 | RF_NOT_INTERP = 1 << 17, | |
| 704 | RF_NOT_ALLOC = 1 << 16, | |
| 705 | RF_WRITE = 1 << 15, | |
| 706 | RF_EXEC_WRITE = 1 << 14, | |
| 707 | RF_EXEC = 1 << 13, | |
| 708 | RF_RODATA = 1 << 12, | |
| 709 | RF_NON_TLS_BSS = 1 << 11, | |
| 710 | RF_NON_TLS_BSS_RO = 1 << 10, | |
| 711 | RF_NOT_TLS = 1 << 9, | |
| 712 | RF_BSS = 1 << 8, | |
| 713 | RF_NOTE = 1 << 7, | |
| 733 | RF_NOT_ALLOC = 1 << 17, | |
| 734 | RF_NOT_INTERP = 1 << 16, | |
| 735 | RF_NOT_NOTE = 1 << 15, | |
| 736 | RF_WRITE = 1 << 14, | |
| 737 | RF_EXEC_WRITE = 1 << 13, | |
| 738 | RF_EXEC = 1 << 12, | |
| 739 | RF_RODATA = 1 << 11, | |
| 740 | RF_NON_TLS_BSS = 1 << 10, | |
| 741 | RF_NON_TLS_BSS_RO = 1 << 9, | |
| 742 | RF_NOT_TLS = 1 << 8, | |
| 743 | RF_BSS = 1 << 7, | |
| 714 | 744 | RF_PPC_NOT_TOCBSS = 1 << 6, |
| 715 | 745 | RF_PPC_TOCL = 1 << 5, |
| 716 | 746 | RF_PPC_TOC = 1 << 4, |
| ... | ... | @@ -729,16 +759,24 @@ static unsigned getSectionRank(const OutputSection *Sec) { |
| 729 | 759 | return Rank; |
| 730 | 760 | Rank |= RF_NOT_ADDR_SET; |
| 731 | 761 | |
| 762 | // Allocatable sections go first to reduce the total PT_LOAD size and | |
| 763 | // so debug info doesn't change addresses in actual code. | |
| 764 | if (!(Sec->Flags & SHF_ALLOC)) | |
| 765 | return Rank | RF_NOT_ALLOC; | |
| 766 | ||
| 732 | 767 | // Put .interp first because some loaders want to see that section |
| 733 | 768 | // on the first page of the executable file when loaded into memory. |
| 734 | 769 | if (Sec->Name == ".interp") |
| 735 | 770 | return Rank; |
| 736 | 771 | Rank |= RF_NOT_INTERP; |
| 737 | 772 | |
| 738 | // Allocatable sections go first to reduce the total PT_LOAD size and | |
| 739 | // so debug info doesn't change addresses in actual code. | |
| 740 | if (!(Sec->Flags & SHF_ALLOC)) | |
| 741 | return Rank | RF_NOT_ALLOC; | |
| 773 | // Put .note sections (which make up one PT_NOTE) at the beginning so that | |
| 774 | // they are likely to be included in a core file even if core file size is | |
| 775 | // limited. In particular, we want a .note.gnu.build-id and a .note.tag to be | |
| 776 | // included in a core to match core files with executables. | |
| 777 | if (Sec->Type == SHT_NOTE) | |
| 778 | return Rank; | |
| 779 | Rank |= RF_NOT_NOTE; | |
| 742 | 780 | |
| 743 | 781 | // Sort sections based on their access permission in the following |
| 744 | 782 | // order: R, RX, RWX, RW. This order is based on the following |
| ... | ... | @@ -802,12 +840,6 @@ static unsigned getSectionRank(const OutputSection *Sec) { |
| 802 | 840 | if (IsNoBits) |
| 803 | 841 | Rank |= RF_BSS; |
| 804 | 842 | |
| 805 | // We create a NOTE segment for contiguous .note sections, so make | |
| 806 | // them contigous if there are more than one .note section with the | |
| 807 | // same attributes. | |
| 808 | if (Sec->Type == SHT_NOTE) | |
| 809 | Rank |= RF_NOTE; | |
| 810 | ||
| 811 | 843 | // Some architectures have additional ordering restrictions for sections |
| 812 | 844 | // within the same PT_LOAD. |
| 813 | 845 | if (Config->EMachine == EM_PPC64) { |
| ... | ... | @@ -850,8 +882,10 @@ static unsigned getSectionRank(const OutputSection *Sec) { |
| 850 | 882 | static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) { |
| 851 | 883 | const OutputSection *A = cast<OutputSection>(ACmd); |
| 852 | 884 | const OutputSection *B = cast<OutputSection>(BCmd); |
| 885 | ||
| 853 | 886 | if (A->SortRank != B->SortRank) |
| 854 | 887 | return A->SortRank < B->SortRank; |
| 888 | ||
| 855 | 889 | if (!(A->SortRank & RF_NOT_ADDR_SET)) |
| 856 | 890 | return Config->SectionStartMap.lookup(A->Name) < |
| 857 | 891 | Config->SectionStartMap.lookup(B->Name); |
| ... | ... | @@ -874,14 +908,20 @@ void PhdrEntry::add(OutputSection *Sec) { |
| 874 | 908 | // need these symbols, since IRELATIVE relocs are resolved through GOT |
| 875 | 909 | // and PLT. For details, see http://www.airs.com/blog/archives/403. |
| 876 | 910 | template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() { |
| 877 | if (needsInterpSection()) | |
| 911 | if (Config->Relocatable || needsInterpSection()) | |
| 878 | 912 | return; |
| 879 | StringRef S = Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start"; | |
| 880 | addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK); | |
| 881 | 913 | |
| 882 | S = Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end"; | |
| 883 | ElfSym::RelaIpltEnd = | |
| 884 | addOptionalRegular(S, InX::RelaIplt, 0, STV_HIDDEN, STB_WEAK); | |
| 914 | // By default, __rela_iplt_{start,end} belong to a dummy section 0 | |
| 915 | // because .rela.plt might be empty and thus removed from output. | |
| 916 | // We'll override Out::ElfHeader with In.RelaIplt later when we are | |
| 917 | // sure that .rela.plt exists in output. | |
| 918 | ElfSym::RelaIpltStart = addOptionalRegular( | |
| 919 | Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start", | |
| 920 | Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK); | |
| 921 | ||
| 922 | ElfSym::RelaIpltEnd = addOptionalRegular( | |
| 923 | Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end", | |
| 924 | Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK); | |
| 885 | 925 | } |
| 886 | 926 | |
| 887 | 927 | template <class ELFT> |
| ... | ... | @@ -895,7 +935,7 @@ void Writer<ELFT>::forEachRelSec( |
| 895 | 935 | for (InputSectionBase *IS : InputSections) |
| 896 | 936 | if (IS->Live && isa<InputSection>(IS) && (IS->Flags & SHF_ALLOC)) |
| 897 | 937 | Fn(*IS); |
| 898 | for (EhInputSection *ES : InX::EhFrame->Sections) | |
| 938 | for (EhInputSection *ES : In.EhFrame->Sections) | |
| 899 | 939 | Fn(*ES); |
| 900 | 940 | } |
| 901 | 941 | |
| ... | ... | @@ -908,15 +948,19 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() { |
| 908 | 948 | if (ElfSym::GlobalOffsetTable) { |
| 909 | 949 | // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually |
| 910 | 950 | // to the start of the .got or .got.plt section. |
| 911 | InputSection *GotSection = InX::GotPlt; | |
| 951 | InputSection *GotSection = In.GotPlt; | |
| 912 | 952 | if (!Target->GotBaseSymInGotPlt) |
| 913 | GotSection = InX::MipsGot ? cast<InputSection>(InX::MipsGot) | |
| 914 | : cast<InputSection>(InX::Got); | |
| 953 | GotSection = In.MipsGot ? cast<InputSection>(In.MipsGot) | |
| 954 | : cast<InputSection>(In.Got); | |
| 915 | 955 | ElfSym::GlobalOffsetTable->Section = GotSection; |
| 916 | 956 | } |
| 917 | 957 | |
| 918 | if (ElfSym::RelaIpltEnd) | |
| 919 | ElfSym::RelaIpltEnd->Value = InX::RelaIplt->getSize(); | |
| 958 | // .rela_iplt_{start,end} mark the start and the end of .rela.plt section. | |
| 959 | if (ElfSym::RelaIpltStart && !In.RelaIplt->empty()) { | |
| 960 | ElfSym::RelaIpltStart->Section = In.RelaIplt; | |
| 961 | ElfSym::RelaIpltEnd->Section = In.RelaIplt; | |
| 962 | ElfSym::RelaIpltEnd->Value = In.RelaIplt->getSize(); | |
| 963 | } | |
| 920 | 964 | |
| 921 | 965 | PhdrEntry *Last = nullptr; |
| 922 | 966 | PhdrEntry *LastRO = nullptr; |
| ... | ... | @@ -1088,7 +1132,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() { |
| 1088 | 1132 | SymbolOrderEntry &Ent = It->second; |
| 1089 | 1133 | Ent.Present = true; |
| 1090 | 1134 | |
| 1091 | warnUnorderableSymbol(&Sym); | |
| 1135 | maybeWarnUnorderableSymbol(&Sym); | |
| 1092 | 1136 | |
| 1093 | 1137 | if (auto *D = dyn_cast<Defined>(&Sym)) { |
| 1094 | 1138 | if (auto *Sec = dyn_cast_or_null<InputSectionBase>(D->Section)) { |
| ... | ... | @@ -1097,6 +1141,7 @@ static DenseMap<const InputSectionBase *, int> buildSectionOrder() { |
| 1097 | 1141 | } |
| 1098 | 1142 | } |
| 1099 | 1143 | }; |
| 1144 | ||
| 1100 | 1145 | // We want both global and local symbols. We get the global ones from the |
| 1101 | 1146 | // symbol table and iterate the object files for the local ones. |
| 1102 | 1147 | for (Symbol *Sym : Symtab->getSymbols()) |
| ... | ... | @@ -1132,11 +1177,10 @@ sortISDBySectionOrder(InputSectionDescription *ISD, |
| 1132 | 1177 | } |
| 1133 | 1178 | OrderedSections.push_back({IS, I->second}); |
| 1134 | 1179 | } |
| 1135 | llvm::sort( | |
| 1136 | OrderedSections.begin(), OrderedSections.end(), | |
| 1137 | [&](std::pair<InputSection *, int> A, std::pair<InputSection *, int> B) { | |
| 1138 | return A.second < B.second; | |
| 1139 | }); | |
| 1180 | llvm::sort(OrderedSections, [&](std::pair<InputSection *, int> A, | |
| 1181 | std::pair<InputSection *, int> B) { | |
| 1182 | return A.second < B.second; | |
| 1183 | }); | |
| 1140 | 1184 | |
| 1141 | 1185 | // Find an insertion point for the ordered section list in the unordered |
| 1142 | 1186 | // section list. On targets with limited-range branches, this is the mid-point |
| ... | ... | @@ -1166,7 +1210,7 @@ sortISDBySectionOrder(InputSectionDescription *ISD, |
| 1166 | 1210 | // we effectively double the amount of code that could potentially call into |
| 1167 | 1211 | // the hot code without a thunk. |
| 1168 | 1212 | size_t InsPt = 0; |
| 1169 | if (Target->ThunkSectionSpacing && !OrderedSections.empty()) { | |
| 1213 | if (Target->getThunkSectionSpacing() && !OrderedSections.empty()) { | |
| 1170 | 1214 | uint64_t UnorderedPos = 0; |
| 1171 | 1215 | for (; InsPt != UnorderedSections.size(); ++InsPt) { |
| 1172 | 1216 | UnorderedPos += UnorderedSections[InsPt]->getSize(); |
| ... | ... | @@ -1342,10 +1386,12 @@ static bool compareByFilePosition(InputSection *A, InputSection *B) { |
| 1342 | 1386 | if (A->kind() == InputSectionBase::Synthetic || |
| 1343 | 1387 | B->kind() == InputSectionBase::Synthetic) |
| 1344 | 1388 | return A->kind() != InputSectionBase::Synthetic; |
| 1389 | ||
| 1345 | 1390 | InputSection *LA = A->getLinkOrderDep(); |
| 1346 | 1391 | InputSection *LB = B->getLinkOrderDep(); |
| 1347 | 1392 | OutputSection *AOut = LA->getParent(); |
| 1348 | 1393 | OutputSection *BOut = LB->getParent(); |
| 1394 | ||
| 1349 | 1395 | if (AOut != BOut) |
| 1350 | 1396 | return AOut->SectionIndex < BOut->SectionIndex; |
| 1351 | 1397 | return LA->OutSecOff < LB->OutSecOff; |
| ... | ... | @@ -1392,6 +1438,7 @@ static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) { |
| 1392 | 1438 | for (const ExidxEntry Entry : Cur->getDataAs<ExidxEntry>()) |
| 1393 | 1439 | if (IsExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind) |
| 1394 | 1440 | return false; |
| 1441 | ||
| 1395 | 1442 | // All table entries in this .ARM.exidx Section can be merged into the |
| 1396 | 1443 | // previous Section. |
| 1397 | 1444 | return true; |
| ... | ... | @@ -1423,18 +1470,19 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { |
| 1423 | 1470 | assert(Sections.size() >= 2 && |
| 1424 | 1471 | "We should create a sentinel section only if there are " |
| 1425 | 1472 | "alive regular exidx sections."); |
| 1473 | ||
| 1426 | 1474 | // The last executable section is required to fill the sentinel. |
| 1427 | 1475 | // Remember it here so that we don't have to find it again. |
| 1428 | 1476 | Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep(); |
| 1429 | 1477 | } |
| 1430 | 1478 | |
| 1479 | // The EHABI for the Arm Architecture permits consecutive identical | |
| 1480 | // table entries to be merged. We use a simple implementation that | |
| 1481 | // removes a .ARM.exidx Input Section if it can be merged into the | |
| 1482 | // previous one. This does not require any rewriting of InputSection | |
| 1483 | // contents but misses opportunities for fine grained deduplication | |
| 1484 | // where only a subset of the InputSection contents can be merged. | |
| 1431 | 1485 | if (Config->MergeArmExidx) { |
| 1432 | // The EHABI for the Arm Architecture permits consecutive identical | |
| 1433 | // table entries to be merged. We use a simple implementation that | |
| 1434 | // removes a .ARM.exidx Input Section if it can be merged into the | |
| 1435 | // previous one. This does not require any rewriting of InputSection | |
| 1436 | // contents but misses opportunities for fine grained deduplication | |
| 1437 | // where only a subset of the InputSection contents can be merged. | |
| 1438 | 1486 | size_t Prev = 0; |
| 1439 | 1487 | // The last one is a sentinel entry which should not be removed. |
| 1440 | 1488 | for (size_t I = 1; I < Sections.size() - 1; ++I) { |
| ... | ... | @@ -1456,11 +1504,49 @@ template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() { |
| 1456 | 1504 | } |
| 1457 | 1505 | } |
| 1458 | 1506 | |
| 1459 | static void applySynthetic(const std::vector<SyntheticSection *> &Sections, | |
| 1460 | llvm::function_ref<void(SyntheticSection *)> Fn) { | |
| 1461 | for (SyntheticSection *SS : Sections) | |
| 1462 | if (SS && SS->getParent() && !SS->empty()) | |
| 1463 | Fn(SS); | |
| 1507 | // For most RISC ISAs, we need to generate content that depends on the address | |
| 1508 | // of InputSections. For example some architectures such as AArch64 use small | |
| 1509 | // displacements for jump instructions that is the linker's responsibility for | |
| 1510 | // creating range extension thunks for. As the generation of the content may | |
| 1511 | // also alter InputSection addresses we must converge to a fixed point. | |
| 1512 | template <class ELFT> void Writer<ELFT>::maybeAddThunks() { | |
| 1513 | if (!Target->NeedsThunks && !Config->AndroidPackDynRelocs && | |
| 1514 | !Config->RelrPackDynRelocs) | |
| 1515 | return; | |
| 1516 | ||
| 1517 | ThunkCreator TC; | |
| 1518 | AArch64Err843419Patcher A64P; | |
| 1519 | ||
| 1520 | for (;;) { | |
| 1521 | bool Changed = false; | |
| 1522 | ||
| 1523 | Script->assignAddresses(); | |
| 1524 | ||
| 1525 | if (Target->NeedsThunks) | |
| 1526 | Changed |= TC.createThunks(OutputSections); | |
| 1527 | ||
| 1528 | if (Config->FixCortexA53Errata843419) { | |
| 1529 | if (Changed) | |
| 1530 | Script->assignAddresses(); | |
| 1531 | Changed |= A64P.createFixes(); | |
| 1532 | } | |
| 1533 | ||
| 1534 | if (In.MipsGot) | |
| 1535 | In.MipsGot->updateAllocSize(); | |
| 1536 | ||
| 1537 | Changed |= In.RelaDyn->updateAllocSize(); | |
| 1538 | ||
| 1539 | if (In.RelrDyn) | |
| 1540 | Changed |= In.RelrDyn->updateAllocSize(); | |
| 1541 | ||
| 1542 | if (!Changed) | |
| 1543 | return; | |
| 1544 | } | |
| 1545 | } | |
| 1546 | ||
| 1547 | static void finalizeSynthetic(SyntheticSection *Sec) { | |
| 1548 | if (Sec && !Sec->empty() && Sec->getParent()) | |
| 1549 | Sec->finalizeContents(); | |
| 1464 | 1550 | } |
| 1465 | 1551 | |
| 1466 | 1552 | // In order to allow users to manipulate linker-synthesized sections, |
| ... | ... | @@ -1500,6 +1586,7 @@ static void removeUnusedSyntheticSections() { |
| 1500 | 1586 | // with the same name defined in other ELF executable or DSO. |
| 1501 | 1587 | static bool computeIsPreemptible(const Symbol &B) { |
| 1502 | 1588 | assert(!B.isLocal()); |
| 1589 | ||
| 1503 | 1590 | // Only symbols that appear in dynsym can be preempted. |
| 1504 | 1591 | if (!B.includeInDynsym()) |
| 1505 | 1592 | return false; |
| ... | ... | @@ -1528,7 +1615,6 @@ static bool computeIsPreemptible(const Symbol &B) { |
| 1528 | 1615 | |
| 1529 | 1616 | // Create output section objects and add them to OutputSections. |
| 1530 | 1617 | template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1531 | Out::DebugInfo = findSection(".debug_info"); | |
| 1532 | 1618 | Out::PreinitArray = findSection(".preinit_array"); |
| 1533 | 1619 | Out::InitArray = findSection(".init_array"); |
| 1534 | 1620 | Out::FiniArray = findSection(".fini_array"); |
| ... | ... | @@ -1547,46 +1633,51 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1547 | 1633 | // It should be okay as no one seems to care about the type. |
| 1548 | 1634 | // Even the author of gold doesn't remember why gold behaves that way. |
| 1549 | 1635 | // https://sourceware.org/ml/binutils/2002-03/msg00360.html |
| 1550 | if (InX::DynSymTab) | |
| 1551 | Symtab->addRegular("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, | |
| 1552 | /*Size=*/0, STB_WEAK, InX::Dynamic, | |
| 1636 | if (In.Dynamic->Parent) | |
| 1637 | Symtab->addDefined("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/, | |
| 1638 | /*Size=*/0, STB_WEAK, In.Dynamic, | |
| 1553 | 1639 | /*File=*/nullptr); |
| 1554 | 1640 | |
| 1555 | 1641 | // Define __rel[a]_iplt_{start,end} symbols if needed. |
| 1556 | 1642 | addRelIpltSymbols(); |
| 1557 | 1643 | |
| 1644 | // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800 if not defined. | |
| 1645 | if (Config->EMachine == EM_RISCV) | |
| 1646 | if (!dyn_cast_or_null<Defined>(Symtab->find("__global_pointer$"))) | |
| 1647 | addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800); | |
| 1648 | ||
| 1558 | 1649 | // This responsible for splitting up .eh_frame section into |
| 1559 | 1650 | // pieces. The relocation scan uses those pieces, so this has to be |
| 1560 | 1651 | // earlier. |
| 1561 | applySynthetic({InX::EhFrame}, | |
| 1562 | [](SyntheticSection *SS) { SS->finalizeContents(); }); | |
| 1652 | finalizeSynthetic(In.EhFrame); | |
| 1563 | 1653 | |
| 1564 | 1654 | for (Symbol *S : Symtab->getSymbols()) |
| 1565 | S->IsPreemptible |= computeIsPreemptible(*S); | |
| 1655 | if (!S->IsPreemptible) | |
| 1656 | S->IsPreemptible = computeIsPreemptible(*S); | |
| 1566 | 1657 | |
| 1567 | 1658 | // Scan relocations. This must be done after every symbol is declared so that |
| 1568 | 1659 | // we can correctly decide if a dynamic relocation is needed. |
| 1569 | 1660 | if (!Config->Relocatable) |
| 1570 | 1661 | forEachRelSec(scanRelocations<ELFT>); |
| 1571 | 1662 | |
| 1572 | if (InX::Plt && !InX::Plt->empty()) | |
| 1573 | InX::Plt->addSymbols(); | |
| 1574 | if (InX::Iplt && !InX::Iplt->empty()) | |
| 1575 | InX::Iplt->addSymbols(); | |
| 1663 | if (In.Plt && !In.Plt->empty()) | |
| 1664 | In.Plt->addSymbols(); | |
| 1665 | if (In.Iplt && !In.Iplt->empty()) | |
| 1666 | In.Iplt->addSymbols(); | |
| 1576 | 1667 | |
| 1577 | 1668 | // Now that we have defined all possible global symbols including linker- |
| 1578 | 1669 | // synthesized ones. Visit all symbols to give the finishing touches. |
| 1579 | 1670 | for (Symbol *Sym : Symtab->getSymbols()) { |
| 1580 | 1671 | if (!includeInSymtab(*Sym)) |
| 1581 | 1672 | continue; |
| 1582 | if (InX::SymTab) | |
| 1583 | InX::SymTab->addSymbol(Sym); | |
| 1673 | if (In.SymTab) | |
| 1674 | In.SymTab->addSymbol(Sym); | |
| 1584 | 1675 | |
| 1585 | if (InX::DynSymTab && Sym->includeInDynsym()) { | |
| 1586 | InX::DynSymTab->addSymbol(Sym); | |
| 1676 | if (Sym->includeInDynsym()) { | |
| 1677 | In.DynSymTab->addSymbol(Sym); | |
| 1587 | 1678 | if (auto *File = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File)) |
| 1588 | 1679 | if (File->IsNeeded && !Sym->isUndefined()) |
| 1589 | In<ELFT>::VerNeed->addSymbol(Sym); | |
| 1680 | InX<ELFT>::VerNeed->addSymbol(Sym); | |
| 1590 | 1681 | } |
| 1591 | 1682 | } |
| 1592 | 1683 | |
| ... | ... | @@ -1594,8 +1685,8 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1594 | 1685 | if (errorCount()) |
| 1595 | 1686 | return; |
| 1596 | 1687 | |
| 1597 | if (InX::MipsGot) | |
| 1598 | InX::MipsGot->build<ELFT>(); | |
| 1688 | if (In.MipsGot) | |
| 1689 | In.MipsGot->build<ELFT>(); | |
| 1599 | 1690 | |
| 1600 | 1691 | removeUnusedSyntheticSections(); |
| 1601 | 1692 | |
| ... | ... | @@ -1607,15 +1698,6 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1607 | 1698 | if (auto *Sec = dyn_cast<OutputSection>(Base)) |
| 1608 | 1699 | OutputSections.push_back(Sec); |
| 1609 | 1700 | |
| 1610 | // Ensure data sections are not mixed with executable sections when | |
| 1611 | // -execute-only is used. | |
| 1612 | if (Config->ExecuteOnly) | |
| 1613 | for (OutputSection *OS : OutputSections) | |
| 1614 | if (OS->Flags & SHF_EXECINSTR) | |
| 1615 | for (InputSection *IS : getInputSections(OS)) | |
| 1616 | if (!(IS->Flags & SHF_EXECINSTR)) | |
| 1617 | error("-execute-only does not support intermingling data and code"); | |
| 1618 | ||
| 1619 | 1701 | // Prefer command line supplied address over other constraints. |
| 1620 | 1702 | for (OutputSection *Sec : OutputSections) { |
| 1621 | 1703 | auto I = Config->SectionStartMap.find(Sec->Name); |
| ... | ... | @@ -1628,10 +1710,10 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1628 | 1710 | // particularly relevant. |
| 1629 | 1711 | Out::ElfHeader->SectionIndex = 1; |
| 1630 | 1712 | |
| 1631 | unsigned I = 1; | |
| 1632 | for (OutputSection *Sec : OutputSections) { | |
| 1633 | Sec->SectionIndex = I++; | |
| 1634 | Sec->ShName = InX::ShStrTab->addString(Sec->Name); | |
| 1713 | for (size_t I = 0, E = OutputSections.size(); I != E; ++I) { | |
| 1714 | OutputSection *Sec = OutputSections[I]; | |
| 1715 | Sec->SectionIndex = I + 1; | |
| 1716 | Sec->ShName = In.ShStrTab->addString(Sec->Name); | |
| 1635 | 1717 | } |
| 1636 | 1718 | |
| 1637 | 1719 | // Binary and relocatable output does not have PHDRS. |
| ... | ... | @@ -1641,6 +1723,12 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1641 | 1723 | Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() : createPhdrs(); |
| 1642 | 1724 | addPtArmExid(Phdrs); |
| 1643 | 1725 | Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size(); |
| 1726 | ||
| 1727 | // Find the TLS segment. This happens before the section layout loop so that | |
| 1728 | // Android relocation packing can look up TLS symbol addresses. | |
| 1729 | for (PhdrEntry *P : Phdrs) | |
| 1730 | if (P->p_type == PT_TLS) | |
| 1731 | Out::TlsPhdr = P; | |
| 1644 | 1732 | } |
| 1645 | 1733 | |
| 1646 | 1734 | // Some symbols are defined in term of program headers. Now that we |
| ... | ... | @@ -1649,15 +1737,30 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1649 | 1737 | |
| 1650 | 1738 | // Dynamic section must be the last one in this list and dynamic |
| 1651 | 1739 | // symbol table section (DynSymTab) must be the first one. |
| 1652 | applySynthetic( | |
| 1653 | {InX::DynSymTab, InX::Bss, InX::BssRelRo, InX::GnuHashTab, | |
| 1654 | InX::HashTab, InX::SymTab, InX::SymTabShndx, InX::ShStrTab, | |
| 1655 | InX::StrTab, In<ELFT>::VerDef, InX::DynStrTab, InX::Got, | |
| 1656 | InX::MipsGot, InX::IgotPlt, InX::GotPlt, InX::RelaDyn, | |
| 1657 | InX::RelrDyn, InX::RelaIplt, InX::RelaPlt, InX::Plt, | |
| 1658 | InX::Iplt, InX::EhFrameHdr, In<ELFT>::VerSym, In<ELFT>::VerNeed, | |
| 1659 | InX::Dynamic}, | |
| 1660 | [](SyntheticSection *SS) { SS->finalizeContents(); }); | |
| 1740 | finalizeSynthetic(In.DynSymTab); | |
| 1741 | finalizeSynthetic(In.Bss); | |
| 1742 | finalizeSynthetic(In.BssRelRo); | |
| 1743 | finalizeSynthetic(In.GnuHashTab); | |
| 1744 | finalizeSynthetic(In.HashTab); | |
| 1745 | finalizeSynthetic(In.SymTabShndx); | |
| 1746 | finalizeSynthetic(In.ShStrTab); | |
| 1747 | finalizeSynthetic(In.StrTab); | |
| 1748 | finalizeSynthetic(In.VerDef); | |
| 1749 | finalizeSynthetic(In.DynStrTab); | |
| 1750 | finalizeSynthetic(In.Got); | |
| 1751 | finalizeSynthetic(In.MipsGot); | |
| 1752 | finalizeSynthetic(In.IgotPlt); | |
| 1753 | finalizeSynthetic(In.GotPlt); | |
| 1754 | finalizeSynthetic(In.RelaDyn); | |
| 1755 | finalizeSynthetic(In.RelrDyn); | |
| 1756 | finalizeSynthetic(In.RelaIplt); | |
| 1757 | finalizeSynthetic(In.RelaPlt); | |
| 1758 | finalizeSynthetic(In.Plt); | |
| 1759 | finalizeSynthetic(In.Iplt); | |
| 1760 | finalizeSynthetic(In.EhFrameHdr); | |
| 1761 | finalizeSynthetic(InX<ELFT>::VerSym); | |
| 1762 | finalizeSynthetic(InX<ELFT>::VerNeed); | |
| 1763 | finalizeSynthetic(In.Dynamic); | |
| 1661 | 1764 | |
| 1662 | 1765 | if (!Script->HasSectionsCommand && !Config->Relocatable) |
| 1663 | 1766 | fixSectionAlignments(); |
| ... | ... | @@ -1666,37 +1769,21 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1666 | 1769 | // needs to be resolved before any other address dependent operation. |
| 1667 | 1770 | resolveShfLinkOrder(); |
| 1668 | 1771 | |
| 1669 | // Some architectures need to generate content that depends on the address | |
| 1670 | // of InputSections. For example some architectures use small displacements | |
| 1671 | // for jump instructions that is the linker's responsibility for creating | |
| 1672 | // range extension thunks for. As the generation of the content may also | |
| 1673 | // alter InputSection addresses we must converge to a fixed point. | |
| 1674 | if (Target->NeedsThunks || Config->AndroidPackDynRelocs || | |
| 1675 | Config->RelrPackDynRelocs) { | |
| 1676 | ThunkCreator TC; | |
| 1677 | AArch64Err843419Patcher A64P; | |
| 1678 | bool Changed; | |
| 1679 | do { | |
| 1680 | Script->assignAddresses(); | |
| 1681 | Changed = false; | |
| 1682 | if (Target->NeedsThunks) | |
| 1683 | Changed |= TC.createThunks(OutputSections); | |
| 1684 | if (Config->FixCortexA53Errata843419) { | |
| 1685 | if (Changed) | |
| 1686 | Script->assignAddresses(); | |
| 1687 | Changed |= A64P.createFixes(); | |
| 1688 | } | |
| 1689 | if (InX::MipsGot) | |
| 1690 | InX::MipsGot->updateAllocSize(); | |
| 1691 | Changed |= InX::RelaDyn->updateAllocSize(); | |
| 1692 | if (InX::RelrDyn) | |
| 1693 | Changed |= InX::RelrDyn->updateAllocSize(); | |
| 1694 | } while (Changed); | |
| 1695 | } | |
| 1772 | // Jump instructions in many ISAs have small displacements, and therefore they | |
| 1773 | // cannot jump to arbitrary addresses in memory. For example, RISC-V JAL | |
| 1774 | // instruction can target only +-1 MiB from PC. It is a linker's | |
| 1775 | // responsibility to create and insert small pieces of code between sections | |
| 1776 | // to extend the ranges if jump targets are out of range. Such code pieces are | |
| 1777 | // called "thunks". | |
| 1778 | // | |
| 1779 | // We add thunks at this stage. We couldn't do this before this point because | |
| 1780 | // this is the earliest point where we know sizes of sections and their | |
| 1781 | // layouts (that are needed to determine if jump targets are in range). | |
| 1782 | maybeAddThunks(); | |
| 1696 | 1783 | |
| 1697 | // createThunks may have added local symbols to the static symbol table | |
| 1698 | applySynthetic({InX::SymTab}, | |
| 1699 | [](SyntheticSection *SS) { SS->postThunkContents(); }); | |
| 1784 | // maybeAddThunks may have added local symbols to the static symbol table. | |
| 1785 | finalizeSynthetic(In.SymTab); | |
| 1786 | finalizeSynthetic(In.PPC64LongBranchTarget); | |
| 1700 | 1787 | |
| 1701 | 1788 | // Fill other section headers. The dynamic table is finalized |
| 1702 | 1789 | // at the end because some tags like RELSZ depend on result |
| ... | ... | @@ -1705,6 +1792,21 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() { |
| 1705 | 1792 | Sec->finalize<ELFT>(); |
| 1706 | 1793 | } |
| 1707 | 1794 | |
| 1795 | // Ensure data sections are not mixed with executable sections when | |
| 1796 | // -execute-only is used. -execute-only is a feature to make pages executable | |
| 1797 | // but not readable, and the feature is currently supported only on AArch64. | |
| 1798 | template <class ELFT> void Writer<ELFT>::checkExecuteOnly() { | |
| 1799 | if (!Config->ExecuteOnly) | |
| 1800 | return; | |
| 1801 | ||
| 1802 | for (OutputSection *OS : OutputSections) | |
| 1803 | if (OS->Flags & SHF_EXECINSTR) | |
| 1804 | for (InputSection *IS : getInputSections(OS)) | |
| 1805 | if (!(IS->Flags & SHF_EXECINSTR)) | |
| 1806 | error("cannot place " + toString(IS) + " into " + toString(OS->Name) + | |
| 1807 | ": -execute-only does not support intermingling data and code"); | |
| 1808 | } | |
| 1809 | ||
| 1708 | 1810 | // The linker is expected to define SECNAME_start and SECNAME_end |
| 1709 | 1811 | // symbols for a few sections. This function defines them. |
| 1710 | 1812 | template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { |
| ... | ... | @@ -1721,9 +1823,13 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() { |
| 1721 | 1823 | // program to fail to link due to relocation overflow, if their |
| 1722 | 1824 | // program text is above 2 GiB. We use the address of the .text |
| 1723 | 1825 | // section instead to prevent that failure. |
| 1826 | // | |
| 1827 | // In a rare sitaution, .text section may not exist. If that's the | |
| 1828 | // case, use the image base address as a last resort. | |
| 1724 | 1829 | OutputSection *Default = findSection(".text"); |
| 1725 | 1830 | if (!Default) |
| 1726 | 1831 | Default = Out::ElfHeader; |
| 1832 | ||
| 1727 | 1833 | auto Define = [=](StringRef Start, StringRef End, OutputSection *OS) { |
| 1728 | 1834 | if (OS) { |
| 1729 | 1835 | addOptionalRegular(Start, OS, 0); |
| ... | ... | @@ -1763,7 +1869,7 @@ static bool needsPtLoad(OutputSection *Sec) { |
| 1763 | 1869 | // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is |
| 1764 | 1870 | // responsible for allocating space for them, not the PT_LOAD that |
| 1765 | 1871 | // contains the TLS initialization image. |
| 1766 | if (Sec->Flags & SHF_TLS && Sec->Type == SHT_NOBITS) | |
| 1872 | if ((Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS) | |
| 1767 | 1873 | return false; |
| 1768 | 1874 | return true; |
| 1769 | 1875 | } |
| ... | ... | @@ -1841,9 +1947,8 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() { |
| 1841 | 1947 | Ret.push_back(TlsHdr); |
| 1842 | 1948 | |
| 1843 | 1949 | // Add an entry for .dynamic. |
| 1844 | if (InX::DynSymTab) | |
| 1845 | AddHdr(PT_DYNAMIC, InX::Dynamic->getParent()->getPhdrFlags()) | |
| 1846 | ->add(InX::Dynamic->getParent()); | |
| 1950 | if (OutputSection *Sec = In.Dynamic->getParent()) | |
| 1951 | AddHdr(PT_DYNAMIC, Sec->getPhdrFlags())->add(Sec); | |
| 1847 | 1952 | |
| 1848 | 1953 | // PT_GNU_RELRO includes all sections that should be marked as |
| 1849 | 1954 | // read-only by dynamic linker after proccessing relocations. |
| ... | ... | @@ -1871,10 +1976,10 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() { |
| 1871 | 1976 | Ret.push_back(RelRo); |
| 1872 | 1977 | |
| 1873 | 1978 | // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr. |
| 1874 | if (!InX::EhFrame->empty() && InX::EhFrameHdr && InX::EhFrame->getParent() && | |
| 1875 | InX::EhFrameHdr->getParent()) | |
| 1876 | AddHdr(PT_GNU_EH_FRAME, InX::EhFrameHdr->getParent()->getPhdrFlags()) | |
| 1877 | ->add(InX::EhFrameHdr->getParent()); | |
| 1979 | if (!In.EhFrame->empty() && In.EhFrameHdr && In.EhFrame->getParent() && | |
| 1980 | In.EhFrameHdr->getParent()) | |
| 1981 | AddHdr(PT_GNU_EH_FRAME, In.EhFrameHdr->getParent()->getPhdrFlags()) | |
| 1982 | ->add(In.EhFrameHdr->getParent()); | |
| 1878 | 1983 | |
| 1879 | 1984 | // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes |
| 1880 | 1985 | // the dynamic linker fill the segment with random data. |
| ... | ... | @@ -1945,77 +2050,77 @@ template <class ELFT> void Writer<ELFT>::fixSectionAlignments() { |
| 1945 | 2050 | for (const PhdrEntry *P : Phdrs) { |
| 1946 | 2051 | if (P->p_type != PT_GNU_RELRO) |
| 1947 | 2052 | continue; |
| 2053 | ||
| 1948 | 2054 | if (P->FirstSec) |
| 1949 | 2055 | PageAlign(P->FirstSec); |
| 2056 | ||
| 1950 | 2057 | // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we |
| 1951 | 2058 | // have to align it to a page. |
| 1952 | 2059 | auto End = OutputSections.end(); |
| 1953 | 2060 | auto I = std::find(OutputSections.begin(), End, P->LastSec); |
| 1954 | 2061 | if (I == End || (I + 1) == End) |
| 1955 | 2062 | continue; |
| 2063 | ||
| 1956 | 2064 | OutputSection *Cmd = (*(I + 1)); |
| 1957 | 2065 | if (needsPtLoad(Cmd)) |
| 1958 | 2066 | PageAlign(Cmd); |
| 1959 | 2067 | } |
| 1960 | 2068 | } |
| 1961 | 2069 | |
| 1962 | // Adjusts the file alignment for a given output section and returns | |
| 1963 | // its new file offset. The file offset must be the same with its | |
| 1964 | // virtual address (modulo the page size) so that the loader can load | |
| 1965 | // executables without any address adjustment. | |
| 1966 | static uint64_t getFileAlignment(uint64_t Off, OutputSection *Cmd) { | |
| 1967 | OutputSection *First = Cmd->PtLoad ? Cmd->PtLoad->FirstSec : nullptr; | |
| 1968 | // The first section in a PT_LOAD has to have congruent offset and address | |
| 1969 | // module the page size. | |
| 1970 | if (Cmd == First) | |
| 1971 | return alignTo(Off, std::max<uint64_t>(Cmd->Alignment, Config->MaxPageSize), | |
| 1972 | Cmd->Addr); | |
| 1973 | ||
| 1974 | // For SHT_NOBITS we don't want the alignment of the section to impact the | |
| 1975 | // offset of the sections that follow. Since nothing seems to care about the | |
| 1976 | // sh_offset of the SHT_NOBITS section itself, just ignore it. | |
| 1977 | if (Cmd->Type == SHT_NOBITS) | |
| 2070 | // Compute an in-file position for a given section. The file offset must be the | |
| 2071 | // same with its virtual address modulo the page size, so that the loader can | |
| 2072 | // load executables without any address adjustment. | |
| 2073 | static uint64_t computeFileOffset(OutputSection *OS, uint64_t Off) { | |
| 2074 | // File offsets are not significant for .bss sections. By convention, we keep | |
| 2075 | // section offsets monotonically increasing rather than setting to zero. | |
| 2076 | if (OS->Type == SHT_NOBITS) | |
| 1978 | 2077 | return Off; |
| 1979 | 2078 | |
| 1980 | 2079 | // If the section is not in a PT_LOAD, we just have to align it. |
| 1981 | if (!Cmd->PtLoad) | |
| 1982 | return alignTo(Off, Cmd->Alignment); | |
| 2080 | if (!OS->PtLoad) | |
| 2081 | return alignTo(Off, OS->Alignment); | |
| 2082 | ||
| 2083 | // The first section in a PT_LOAD has to have congruent offset and address | |
| 2084 | // module the page size. | |
| 2085 | OutputSection *First = OS->PtLoad->FirstSec; | |
| 2086 | if (OS == First) { | |
| 2087 | uint64_t Alignment = std::max<uint64_t>(OS->Alignment, Config->MaxPageSize); | |
| 2088 | return alignTo(Off, Alignment, OS->Addr); | |
| 2089 | } | |
| 1983 | 2090 | |
| 1984 | 2091 | // If two sections share the same PT_LOAD the file offset is calculated |
| 1985 | 2092 | // using this formula: Off2 = Off1 + (VA2 - VA1). |
| 1986 | return First->Offset + Cmd->Addr - First->Addr; | |
| 2093 | return First->Offset + OS->Addr - First->Addr; | |
| 1987 | 2094 | } |
| 1988 | 2095 | |
| 1989 | static uint64_t setOffset(OutputSection *Cmd, uint64_t Off) { | |
| 1990 | Off = getFileAlignment(Off, Cmd); | |
| 1991 | Cmd->Offset = Off; | |
| 2096 | // Set an in-file position to a given section and returns the end position of | |
| 2097 | // the section. | |
| 2098 | static uint64_t setFileOffset(OutputSection *OS, uint64_t Off) { | |
| 2099 | Off = computeFileOffset(OS, Off); | |
| 2100 | OS->Offset = Off; | |
| 1992 | 2101 | |
| 1993 | // For SHT_NOBITS we should not count the size. | |
| 1994 | if (Cmd->Type == SHT_NOBITS) | |
| 2102 | if (OS->Type == SHT_NOBITS) | |
| 1995 | 2103 | return Off; |
| 1996 | ||
| 1997 | return Off + Cmd->Size; | |
| 2104 | return Off + OS->Size; | |
| 1998 | 2105 | } |
| 1999 | 2106 | |
| 2000 | 2107 | template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() { |
| 2001 | 2108 | uint64_t Off = 0; |
| 2002 | 2109 | for (OutputSection *Sec : OutputSections) |
| 2003 | 2110 | if (Sec->Flags & SHF_ALLOC) |
| 2004 | Off = setOffset(Sec, Off); | |
| 2111 | Off = setFileOffset(Sec, Off); | |
| 2005 | 2112 | FileSize = alignTo(Off, Config->Wordsize); |
| 2006 | 2113 | } |
| 2007 | 2114 | |
| 2008 | 2115 | static std::string rangeToString(uint64_t Addr, uint64_t Len) { |
| 2009 | if (Len == 0) | |
| 2010 | return "<empty range at 0x" + utohexstr(Addr) + ">"; | |
| 2011 | 2116 | return "[0x" + utohexstr(Addr) + ", 0x" + utohexstr(Addr + Len - 1) + "]"; |
| 2012 | 2117 | } |
| 2013 | 2118 | |
| 2014 | 2119 | // Assign file offsets to output sections. |
| 2015 | 2120 | template <class ELFT> void Writer<ELFT>::assignFileOffsets() { |
| 2016 | 2121 | uint64_t Off = 0; |
| 2017 | Off = setOffset(Out::ElfHeader, Off); | |
| 2018 | Off = setOffset(Out::ProgramHeaders, Off); | |
| 2122 | Off = setFileOffset(Out::ElfHeader, Off); | |
| 2123 | Off = setFileOffset(Out::ProgramHeaders, Off); | |
| 2019 | 2124 | |
| 2020 | 2125 | PhdrEntry *LastRX = nullptr; |
| 2021 | 2126 | for (PhdrEntry *P : Phdrs) |
| ... | ... | @@ -2023,9 +2128,10 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() { |
| 2023 | 2128 | LastRX = P; |
| 2024 | 2129 | |
| 2025 | 2130 | for (OutputSection *Sec : OutputSections) { |
| 2026 | Off = setOffset(Sec, Off); | |
| 2131 | Off = setFileOffset(Sec, Off); | |
| 2027 | 2132 | if (Script->HasSectionsCommand) |
| 2028 | 2133 | continue; |
| 2134 | ||
| 2029 | 2135 | // If this is a last section of the last executable segment and that |
| 2030 | 2136 | // segment is the last loadable segment, align the offset of the |
| 2031 | 2137 | // following section to avoid loading non-segments parts of the file. |
| ... | ... | @@ -2050,7 +2156,7 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() { |
| 2050 | 2156 | continue; |
| 2051 | 2157 | if ((Sec->Offset > FileSize) || (Sec->Offset + Sec->Size > FileSize)) |
| 2052 | 2158 | error("unable to place section " + Sec->Name + " at file offset " + |
| 2053 | rangeToString(Sec->Offset, Sec->Offset + Sec->Size) + | |
| 2159 | rangeToString(Sec->Offset, Sec->Size) + | |
| 2054 | 2160 | "; check your linker script for overflows"); |
| 2055 | 2161 | } |
| 2056 | 2162 | } |
| ... | ... | @@ -2061,19 +2167,23 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() { |
| 2061 | 2167 | for (PhdrEntry *P : Phdrs) { |
| 2062 | 2168 | OutputSection *First = P->FirstSec; |
| 2063 | 2169 | OutputSection *Last = P->LastSec; |
| 2170 | ||
| 2064 | 2171 | if (First) { |
| 2065 | 2172 | P->p_filesz = Last->Offset - First->Offset; |
| 2066 | 2173 | if (Last->Type != SHT_NOBITS) |
| 2067 | 2174 | P->p_filesz += Last->Size; |
| 2175 | ||
| 2068 | 2176 | P->p_memsz = Last->Addr + Last->Size - First->Addr; |
| 2069 | 2177 | P->p_offset = First->Offset; |
| 2070 | 2178 | P->p_vaddr = First->Addr; |
| 2179 | ||
| 2071 | 2180 | if (!P->HasLMA) |
| 2072 | 2181 | P->p_paddr = First->getLMA(); |
| 2073 | 2182 | } |
| 2074 | if (P->p_type == PT_LOAD) | |
| 2183 | ||
| 2184 | if (P->p_type == PT_LOAD) { | |
| 2075 | 2185 | P->p_align = std::max<uint64_t>(P->p_align, Config->MaxPageSize); |
| 2076 | else if (P->p_type == PT_GNU_RELRO) { | |
| 2186 | } else if (P->p_type == PT_GNU_RELRO) { | |
| 2077 | 2187 | P->p_align = 1; |
| 2078 | 2188 | // The glibc dynamic loader rounds the size down, so we need to round up |
| 2079 | 2189 | // to protect the last page. This is a no-op on FreeBSD which always |
| ... | ... | @@ -2081,12 +2191,22 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() { |
| 2081 | 2191 | P->p_memsz = alignTo(P->p_memsz, Target->PageSize); |
| 2082 | 2192 | } |
| 2083 | 2193 | |
| 2084 | // The TLS pointer goes after PT_TLS. At least glibc will align it, | |
| 2085 | // so round up the size to make sure the offsets are correct. | |
| 2086 | if (P->p_type == PT_TLS) { | |
| 2087 | Out::TlsPhdr = P; | |
| 2088 | if (P->p_memsz) | |
| 2089 | P->p_memsz = alignTo(P->p_memsz, P->p_align); | |
| 2194 | if (P->p_type == PT_TLS && P->p_memsz) { | |
| 2195 | if (!Config->Shared && | |
| 2196 | (Config->EMachine == EM_ARM || Config->EMachine == EM_AARCH64)) { | |
| 2197 | // On ARM/AArch64, reserve extra space (8 words) between the thread | |
| 2198 | // pointer and an executable's TLS segment by overaligning the segment. | |
| 2199 | // This reservation is needed for backwards compatibility with Android's | |
| 2200 | // TCB, which allocates several slots after the thread pointer (e.g. | |
| 2201 | // TLS_SLOT_STACK_GUARD==5). For simplicity, this overalignment is also | |
| 2202 | // done on other operating systems. | |
| 2203 | P->p_align = std::max<uint64_t>(P->p_align, Config->Wordsize * 8); | |
| 2204 | } | |
| 2205 | ||
| 2206 | // The TLS pointer goes after PT_TLS for variant 2 targets. At least glibc | |
| 2207 | // will align it, so round up the size to make sure the offsets are | |
| 2208 | // correct. | |
| 2209 | P->p_memsz = alignTo(P->p_memsz, P->p_align); | |
| 2090 | 2210 | } |
| 2091 | 2211 | } |
| 2092 | 2212 | } |
| ... | ... | @@ -2103,10 +2223,9 @@ struct SectionOffset { |
| 2103 | 2223 | // load and virtual adresses). |
| 2104 | 2224 | static void checkOverlap(StringRef Name, std::vector<SectionOffset> &Sections, |
| 2105 | 2225 | bool IsVirtualAddr) { |
| 2106 | llvm::sort(Sections.begin(), Sections.end(), | |
| 2107 | [=](const SectionOffset &A, const SectionOffset &B) { | |
| 2108 | return A.Offset < B.Offset; | |
| 2109 | }); | |
| 2226 | llvm::sort(Sections, [=](const SectionOffset &A, const SectionOffset &B) { | |
| 2227 | return A.Offset < B.Offset; | |
| 2228 | }); | |
| 2110 | 2229 | |
| 2111 | 2230 | // Finding overlap is easy given a vector is sorted by start position. |
| 2112 | 2231 | // If an element starts before the end of the previous element, they overlap. |
| ... | ... | @@ -2150,7 +2269,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() { |
| 2150 | 2269 | // file so we skip any non-allocated sections in that case. |
| 2151 | 2270 | std::vector<SectionOffset> FileOffs; |
| 2152 | 2271 | for (OutputSection *Sec : OutputSections) |
| 2153 | if (0 < Sec->Size && Sec->Type != SHT_NOBITS && | |
| 2272 | if (Sec->Size > 0 && Sec->Type != SHT_NOBITS && | |
| 2154 | 2273 | (!Config->OFormatBinary || (Sec->Flags & SHF_ALLOC))) |
| 2155 | 2274 | FileOffs.push_back({Sec, Sec->Offset}); |
| 2156 | 2275 | checkOverlap("file", FileOffs, false); |
| ... | ... | @@ -2168,7 +2287,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() { |
| 2168 | 2287 | // ranges in the file. |
| 2169 | 2288 | std::vector<SectionOffset> VMAs; |
| 2170 | 2289 | for (OutputSection *Sec : OutputSections) |
| 2171 | if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) | |
| 2290 | if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) | |
| 2172 | 2291 | VMAs.push_back({Sec, Sec->Addr}); |
| 2173 | 2292 | checkOverlap("virtual address", VMAs, true); |
| 2174 | 2293 | |
| ... | ... | @@ -2177,7 +2296,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() { |
| 2177 | 2296 | // script with AT(). |
| 2178 | 2297 | std::vector<SectionOffset> LMAs; |
| 2179 | 2298 | for (OutputSection *Sec : OutputSections) |
| 2180 | if (0 < Sec->Size && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) | |
| 2299 | if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS)) | |
| 2181 | 2300 | LMAs.push_back({Sec, Sec->getLMA()}); |
| 2182 | 2301 | checkOverlap("load address", LMAs, false); |
| 2183 | 2302 | } |
| ... | ... | @@ -2190,7 +2309,7 @@ template <class ELFT> void Writer<ELFT>::checkSections() { |
| 2190 | 2309 | // 4. the number represented by the entry symbol, if it is a number; |
| 2191 | 2310 | // 5. the address of the first byte of the .text section, if present; |
| 2192 | 2311 | // 6. the address 0. |
| 2193 | template <class ELFT> uint64_t Writer<ELFT>::getEntryAddr() { | |
| 2312 | static uint64_t getEntryAddr() { | |
| 2194 | 2313 | // Case 1, 2 or 3 |
| 2195 | 2314 | if (Symbol *B = Symtab->find(Config->Entry)) |
| 2196 | 2315 | return B->getVA(); |
| ... | ... | @@ -2233,6 +2352,7 @@ static uint8_t getAbiVersion() { |
| 2233 | 2352 | |
| 2234 | 2353 | template <class ELFT> void Writer<ELFT>::writeHeader() { |
| 2235 | 2354 | uint8_t *Buf = Buffer->getBufferStart(); |
| 2355 | ||
| 2236 | 2356 | // For executable segments, the trap instructions are written before writing |
| 2237 | 2357 | // the header. Setting Elf header bytes to zero ensures that any unused bytes |
| 2238 | 2358 | // in header are zero-cleared, instead of having trap instructions. |
| ... | ... | @@ -2291,7 +2411,7 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { |
| 2291 | 2411 | else |
| 2292 | 2412 | EHdr->e_shnum = Num; |
| 2293 | 2413 | |
| 2294 | uint32_t StrTabIndex = InX::ShStrTab->getParent()->SectionIndex; | |
| 2414 | uint32_t StrTabIndex = In.ShStrTab->getParent()->SectionIndex; | |
| 2295 | 2415 | if (StrTabIndex >= SHN_LORESERVE) { |
| 2296 | 2416 | SHdrs->sh_link = StrTabIndex; |
| 2297 | 2417 | EHdr->e_shstrndx = SHN_XINDEX; |
| ... | ... | @@ -2305,7 +2425,8 @@ template <class ELFT> void Writer<ELFT>::writeHeader() { |
| 2305 | 2425 | |
| 2306 | 2426 | // Open a result file. |
| 2307 | 2427 | template <class ELFT> void Writer<ELFT>::openFile() { |
| 2308 | if (!Config->Is64 && FileSize > UINT32_MAX) { | |
| 2428 | uint64_t MaxSize = Config->Is64 ? INT64_MAX : UINT32_MAX; | |
| 2429 | if (MaxSize < FileSize) { | |
| 2309 | 2430 | error("output file too large: " + Twine(FileSize) + " bytes"); |
| 2310 | 2431 | return; |
| 2311 | 2432 | } |
| ... | ... | @@ -2370,8 +2491,8 @@ template <class ELFT> void Writer<ELFT>::writeSections() { |
| 2370 | 2491 | uint8_t *Buf = Buffer->getBufferStart(); |
| 2371 | 2492 | |
| 2372 | 2493 | OutputSection *EhFrameHdr = nullptr; |
| 2373 | if (InX::EhFrameHdr && !InX::EhFrameHdr->empty()) | |
| 2374 | EhFrameHdr = InX::EhFrameHdr->getParent(); | |
| 2494 | if (In.EhFrameHdr && !In.EhFrameHdr->empty()) | |
| 2495 | EhFrameHdr = In.EhFrameHdr->getParent(); | |
| 2375 | 2496 | |
| 2376 | 2497 | // In -r or -emit-relocs mode, write the relocation sections first as in |
| 2377 | 2498 | // ELf_Rel targets we might find out that we need to modify the relocated |
| ... | ... | @@ -2391,13 +2512,13 @@ template <class ELFT> void Writer<ELFT>::writeSections() { |
| 2391 | 2512 | } |
| 2392 | 2513 | |
| 2393 | 2514 | template <class ELFT> void Writer<ELFT>::writeBuildId() { |
| 2394 | if (!InX::BuildId || !InX::BuildId->getParent()) | |
| 2515 | if (!In.BuildId || !In.BuildId->getParent()) | |
| 2395 | 2516 | return; |
| 2396 | 2517 | |
| 2397 | 2518 | // Compute a hash of all sections of the output file. |
| 2398 | 2519 | uint8_t *Start = Buffer->getBufferStart(); |
| 2399 | 2520 | uint8_t *End = Start + FileSize; |
| 2400 | InX::BuildId->writeBuildId({Start, End}); | |
| 2521 | In.BuildId->writeBuildId({Start, End}); | |
| 2401 | 2522 | } |
| 2402 | 2523 | |
| 2403 | 2524 | template void elf::writeResult<ELF32LE>(); |
deps/lld/LICENSE.TXT+1-1| ... | ... | @@ -4,7 +4,7 @@ lld License |
| 4 | 4 | University of Illinois/NCSA |
| 5 | 5 | Open Source License |
| 6 | 6 | |
| 7 | Copyright (c) 2011-2018 by the contributors listed in CREDITS.TXT | |
| 7 | Copyright (c) 2011-2019 by the contributors listed in CREDITS.TXT | |
| 8 | 8 | All rights reserved. |
| 9 | 9 | |
| 10 | 10 | Developed by: |
deps/lld/MinGW/Driver.cpp+27-4| ... | ... | @@ -6,9 +6,27 @@ |
| 6 | 6 | // License. See LICENSE.TXT for details. |
| 7 | 7 | // |
| 8 | 8 | //===----------------------------------------------------------------------===// |
| 9 | /// | |
| 10 | /// GNU ld style linker driver for COFF currently supporting mingw-w64. | |
| 11 | /// | |
| 9 | // | |
| 10 | // MinGW is a GNU development environment for Windows. It consists of GNU | |
| 11 | // tools such as GCC and GNU ld. Unlike Cygwin, there's no POSIX-compatible | |
| 12 | // layer, as it aims to be a native development toolchain. | |
| 13 | // | |
| 14 | // lld/MinGW is a drop-in replacement for GNU ld/MinGW. | |
| 15 | // | |
| 16 | // Being a native development tool, a MinGW linker is not very different from | |
| 17 | // Microsoft link.exe, so a MinGW linker can be implemented as a thin wrapper | |
| 18 | // for lld/COFF. This driver takes Unix-ish command line options, translates | |
| 19 | // them to Windows-ish ones, and then passes them to lld/COFF. | |
| 20 | // | |
| 21 | // When this driver calls the lld/COFF driver, it passes a hidden option | |
| 22 | // "-lldmingw" along with other user-supplied options, to run the lld/COFF | |
| 23 | // linker in "MinGW mode". | |
| 24 | // | |
| 25 | // There are subtle differences between MS link.exe and GNU ld/MinGW, and GNU | |
| 26 | // ld/MinGW implements a few GNU-specific features. Such features are directly | |
| 27 | // implemented in lld/COFF and enabled only when the linker is running in MinGW | |
| 28 | // mode. | |
| 29 | // | |
| 12 | 30 | //===----------------------------------------------------------------------===// |
| 13 | 31 | |
| 14 | 32 | #include "lld/Common/Driver.h" |
| ... | ... | @@ -212,9 +230,14 @@ bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) { |
| 212 | 230 | else |
| 213 | 231 | Add("-alternatename:__image_base__=__ImageBase"); |
| 214 | 232 | |
| 233 | for (auto *A : Args.filtered(OPT_require_defined)) | |
| 234 | Add("-include:" + StringRef(A->getValue())); | |
| 235 | ||
| 215 | 236 | std::vector<StringRef> SearchPaths; |
| 216 | for (auto *A : Args.filtered(OPT_L)) | |
| 237 | for (auto *A : Args.filtered(OPT_L)) { | |
| 217 | 238 | SearchPaths.push_back(A->getValue()); |
| 239 | Add("-libpath:" + StringRef(A->getValue())); | |
| 240 | } | |
| 218 | 241 | |
| 219 | 242 | StringRef Prefix = ""; |
| 220 | 243 | bool Static = false; |
deps/lld/MinGW/Options.td+9| ... | ... | @@ -40,6 +40,9 @@ def strip_debug: F<"strip-debug">, |
| 40 | 40 | def whole_archive: F<"whole-archive">, |
| 41 | 41 | HelpText<"Include all object files for following archives">; |
| 42 | 42 | def verbose: F<"verbose">, HelpText<"Verbose mode">; |
| 43 | def require_defined: S<"require-defined">, | |
| 44 | HelpText<"Force symbol to be added to symbol table as an undefined one">; | |
| 45 | def require_defined_eq: J<"require-defined=">, Alias<require_defined>; | |
| 43 | 46 | |
| 44 | 47 | // LLD specific options |
| 45 | 48 | def _HASH_HASH_HASH : Flag<["-"], "###">, |
| ... | ... | @@ -75,3 +78,9 @@ def version: F<"version">, HelpText<"Display the version number and exit">; |
| 75 | 78 | def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>; |
| 76 | 79 | def alias_strip_s: Flag<["-"], "s">, Alias<strip_all>; |
| 77 | 80 | def alias_strip_S: Flag<["-"], "S">, Alias<strip_debug>; |
| 81 | ||
| 82 | // Ignored options | |
| 83 | def: S<"plugin">; | |
| 84 | def: J<"plugin=">; | |
| 85 | def: S<"plugin-opt">; | |
| 86 | def: J<"plugin-opt=">; |
deps/lld/docs/NewLLD.rst+7-7| ... | ... | @@ -53,7 +53,7 @@ between speed, simplicity and extensibility. |
| 53 | 53 | until we need them to continue linking. |
| 54 | 54 | When we need to do some costly operation (such as looking up |
| 55 | 55 | a hash table for each symbol), we do it only once. |
| 56 | We obtain a handler (which is typically just a pointer to actual data) | |
| 56 | We obtain a handle (which is typically just a pointer to actual data) | |
| 57 | 57 | on the first operation and use it throughout the process. |
| 58 | 58 | |
| 59 | 59 | * Efficient archive file handling |
| ... | ... | @@ -90,18 +90,18 @@ between speed, simplicity and extensibility. |
| 90 | 90 | `--end-group`, to let the linker loop over the files between the options until |
| 91 | 91 | no new symbols are added to the set. |
| 92 | 92 | |
| 93 | Visiting the same archive files multiple makes the linker slower. | |
| 93 | Visiting the same archive files multiple times makes the linker slower. | |
| 94 | 94 | |
| 95 | 95 | Here is how LLD approaches the problem. Instead of memorizing only undefined |
| 96 | 96 | symbols, we program LLD so that it memorizes all symbols. When it sees an |
| 97 | 97 | undefined symbol that can be resolved by extracting an object file from an |
| 98 | archive file it previously visited, it immediately extracts the file and link | |
| 99 | it. It is doable because LLD does not forget symbols it have seen in archive | |
| 98 | archive file it previously visited, it immediately extracts the file and links | |
| 99 | it. It is doable because LLD does not forget symbols it has seen in archive | |
| 100 | 100 | files. |
| 101 | 101 | |
| 102 | We believe that the LLD's way is efficient and easy to justify. | |
| 102 | We believe that LLD's way is efficient and easy to justify. | |
| 103 | 103 | |
| 104 | The semantics of LLD's archive handling is different from the traditional | |
| 104 | The semantics of LLD's archive handling are different from the traditional | |
| 105 | 105 | Unix's. You can observe it if you carefully craft archive files to exploit |
| 106 | 106 | it. However, in reality, we don't know any program that cannot link with our |
| 107 | 107 | algorithm so far, so it's not going to cause trouble. |
| ... | ... | @@ -157,7 +157,7 @@ functions, the code of the linker should look obvious to you. |
| 157 | 157 | - Undefined symbols represent undefined symbols, which need to be replaced by |
| 158 | 158 | Defined symbols by the resolver until the link is complete. |
| 159 | 159 | - Lazy symbols represent symbols we found in archive file headers |
| 160 | which can turn into Defined if we read archieve members. | |
| 160 | which can turn into Defined if we read archive members. | |
| 161 | 161 | |
| 162 | 162 | There's only one Symbol instance for each unique symbol name. This uniqueness |
| 163 | 163 | is guaranteed by the symbol table. As the resolver reads symbols from input |
deps/lld/docs/README.txt+1-4| ... | ... | @@ -6,7 +6,4 @@ currently tested with Sphinx 1.1.3. |
| 6 | 6 | |
| 7 | 7 | We currently use the 'nature' theme and a Beaker inspired structure. |
| 8 | 8 | |
| 9 | To rebuild documents into html: | |
| 10 | ||
| 11 | [/lld/docs]> make html | |
| 12 | ||
| 9 | See sphinx_intro.rst for more details. |
deps/lld/docs/Readers.rst+1-1| ... | ... | @@ -74,7 +74,7 @@ files in parallel. Therefore, there should be no parsing state in you Reader |
| 74 | 74 | object. Any parsing state should be in ivars of your File subclass or in |
| 75 | 75 | some temporary object. |
| 76 | 76 | |
| 77 | The key method to implement in a reader is:: | |
| 77 | The key function to implement in a reader is:: | |
| 78 | 78 | |
| 79 | 79 | virtual error_code loadFile(LinkerInput &input, |
| 80 | 80 | std::vector<std::unique_ptr<File>> &result); |
deps/lld/docs/ReleaseNotes.rst+80-12| ... | ... | @@ -1,14 +1,19 @@ |
| 1 | 1 | ======================= |
| 2 | LLD 7.0.0 Release Notes | |
| 2 | lld 8.0.0 Release Notes | |
| 3 | 3 | ======================= |
| 4 | 4 | |
| 5 | 5 | .. contents:: |
| 6 | 6 | :local: |
| 7 | 7 | |
| 8 | .. warning:: | |
| 9 | These are in-progress notes for the upcoming LLVM 8.0.0 release. | |
| 10 | Release notes for previous releases can be found on | |
| 11 | `the Download Page <https://releases.llvm.org/download.html>`_. | |
| 12 | ||
| 8 | 13 | Introduction |
| 9 | 14 | ============ |
| 10 | 15 | |
| 11 | This document contains the release notes for the lld linker, release 7.0.0. | |
| 16 | This document contains the release notes for the lld linker, release 8.0.0. | |
| 12 | 17 | Here we describe the status of lld, including major improvements |
| 13 | 18 | from the previous release. All lld releases may be downloaded |
| 14 | 19 | from the `LLVM releases web site <https://llvm.org/releases/>`_. |
| ... | ... | @@ -19,23 +24,86 @@ Non-comprehensive list of changes in this release |
| 19 | 24 | ELF Improvements |
| 20 | 25 | ---------------- |
| 21 | 26 | |
| 22 | * lld is now able to overcome MIPS GOT entries number limitation | |
| 23 | and generate multi-GOT if necessary. | |
| 27 | * lld now supports RISC-V. (`r339364 | |
| 28 | <https://reviews.llvm.org/rL339364>`_) | |
| 29 | ||
| 30 | * Default image base address has changed from 65536 to 2 MiB for i386 | |
| 31 | and 4 MiB for AArch64 to make lld-generated executables work better | |
| 32 | with automatic superpage promotion. FreeBSD can promote contiguous | |
| 33 | non-superpages to a superpage if they are aligned to the superpage | |
| 34 | size. (`r342746 <https://reviews.llvm.org/rL342746>`_) | |
| 35 | ||
| 36 | * lld/Hexagon can now link Linux kernel and musl libc for Qualcomm | |
| 37 | Hexagon ISA. | |
| 24 | 38 | |
| 25 | * lld is now able to produce MIPS position-independent executable (PIE). | |
| 39 | * Initial MSP430 ISA support has landed. | |
| 26 | 40 | |
| 27 | * Fixed MIPS TLS GOT entries for local symbols in shared libraries. | |
| 41 | * The following flags have been added: ``-z interpose``, ``-z global`` | |
| 28 | 42 | |
| 29 | * Fixed calculation of MIPS GP relative relocations | |
| 30 | in case of relocatable output. | |
| 43 | * lld now uses the ``sigrie`` instruction as a trap instruction for | |
| 44 | MIPS targets. | |
| 31 | 45 | |
| 32 | 46 | COFF Improvements |
| 33 | 47 | ----------------- |
| 34 | 48 | |
| 35 | * Improved correctness of exporting mangled stdcall symbols. | |
| 49 | * PDB GUID is set to hash of PDB contents instead to a random byte | |
| 50 | sequence for build reproducibility. | |
| 51 | ||
| 52 | * ``/pdbsourcepath:`` is now also used to make ``"cwd"``, ``"exe"``, ``"pdb"`` | |
| 53 | in the env block of PDB outputs absolute if they are relative, and to make | |
| 54 | paths to obj files referenced in PDB outputs absolute if they are relative. | |
| 55 | Together with the previous item, this makes it possible to generate | |
| 56 | executables and PDBs that are fully deterministic and independent of the | |
| 57 | absolute path to the build directory, so that different machines building | |
| 58 | the same code in different directories can produce exactly the same output. | |
| 59 | ||
| 60 | * The following flags have been added: ``/force:multiple`` | |
| 61 | ||
| 62 | * lld now can link against import libraries produced by GNU tools. | |
| 63 | ||
| 64 | * lld can create thunks for ARM and ARM64, to allow linking larger images | |
| 65 | (over 16 MB for ARM and over 128 MB for ARM64) | |
| 66 | ||
| 67 | * Several speed and memory usage improvements. | |
| 68 | ||
| 69 | * lld now creates debug info for typedefs. | |
| 70 | ||
| 71 | * lld can now link obj files produced by ``cl.exe /Z7 /Yc``. | |
| 72 | ||
| 73 | * lld now understands ``%_PDB%`` and ``%_EXT%`` in ``/pdbaltpath:``. | |
| 74 | ||
| 75 | * Undefined symbols are now printed in demangled form in addition to raw form. | |
| 76 | ||
| 77 | MinGW Improvements | |
| 78 | ------------------ | |
| 79 | ||
| 80 | * lld can now automatically import data variables from DLLs without the | |
| 81 | use of the dllimport attribute. | |
| 82 | ||
| 83 | * lld can now use existing normal MinGW sysroots with import libraries and | |
| 84 | CRT startup object files for GNU binutils. lld can handle most object | |
| 85 | files produced by GCC, and thus works as a drop-in replacement for | |
| 86 | ld.bfd in such environments. (There are known issues with linking crtend.o | |
| 87 | from GCC in setups with DWARF exceptions though, where object files are | |
| 88 | linked in a different order than with GNU ld, inserting a DWARF exception | |
| 89 | table terminator too early.) | |
| 90 | ||
| 91 | * lld now supports COFF embedded directives for linking to nondefault | |
| 92 | libraries, just like for the normal COFF target. | |
| 93 | ||
| 94 | * Actually generate a codeview build id signature, even if not creating a PDB. | |
| 95 | Previously, the ``--build-id`` option did not actually generate a build id | |
| 96 | unless ``--pdb`` was specified. | |
| 97 | ||
| 98 | MachO Improvements | |
| 99 | ------------------ | |
| 36 | 100 | |
| 37 | * Completed support for ARM64 relocations. | |
| 101 | * Item 1. | |
| 38 | 102 | |
| 39 | * Added support for outputting PDB debug info for MinGW targets. | |
| 103 | WebAssembly Improvements | |
| 104 | ------------------------ | |
| 40 | 105 | |
| 41 | * Improved compatibility of output binaries with GNU binutils objcopy/strip. | |
| 106 | * Add initial support for creating shared libraries (-shared). | |
| 107 | Note: The shared library format is still under active development and may | |
| 108 | undergo significant changes in future versions. | |
| 109 | See: https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md |
deps/lld/docs/WebAssembly.rst+92-14| ... | ... | @@ -1,13 +1,10 @@ |
| 1 | 1 | WebAssembly lld port |
| 2 | 2 | ==================== |
| 3 | 3 | |
| 4 | Note: The WebAssembly port is still a work in progress and is be lacking | |
| 5 | certain features. | |
| 6 | ||
| 7 | 4 | The WebAssembly version of lld takes WebAssembly binaries as inputs and produces |
| 8 | a WebAssembly binary as its output. For the most part this port tried to mimic | |
| 9 | the behaviour of traditional ELF linkers and specifically the ELF lld port. | |
| 10 | Where possible that command line flags and the semantics should be the same. | |
| 5 | a WebAssembly binary as its output. For the most part it tries to mimic the | |
| 6 | behaviour of traditional ELF linkers and specifically the ELF lld port. Where | |
| 7 | possible that command line flags and the semantics should be the same. | |
| 11 | 8 | |
| 12 | 9 | |
| 13 | 10 | Object file format |
| ... | ... | @@ -23,14 +20,95 @@ currently requires enabling the experimental backed using |
| 23 | 20 | ``-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly``. |
| 24 | 21 | |
| 25 | 22 | |
| 23 | Usage | |
| 24 | ----- | |
| 25 | ||
| 26 | The WebAssembly version of lld is installed as **wasm-ld**. It shared many | |
| 27 | common linker flags with **ld.lld** but also includes several | |
| 28 | WebAssembly-specific options: | |
| 29 | ||
| 30 | .. option:: --no-entry | |
| 31 | ||
| 32 | Don't search for the entry point symbol (by default ``_start``). | |
| 33 | ||
| 34 | .. option:: --export-table | |
| 35 | ||
| 36 | Export the function table to the environment. | |
| 37 | ||
| 38 | .. option:: --import-table | |
| 39 | ||
| 40 | Import the function table from the environment. | |
| 41 | ||
| 42 | .. option:: --export-all | |
| 43 | ||
| 44 | Export all symbols (normally combined with --no-gc-sections) | |
| 45 | ||
| 46 | .. option:: --export-dynamic | |
| 47 | ||
| 48 | When building an executable, export any non-hidden symbols. By default only | |
| 49 | the entry point and any symbols marked with --export/--export-all are | |
| 50 | exported. | |
| 51 | ||
| 52 | .. option:: --global-base=<value> | |
| 53 | ||
| 54 | Address at which to place global data. | |
| 55 | ||
| 56 | .. option:: --no-merge-data-segments | |
| 57 | ||
| 58 | Disable merging of data segments. | |
| 59 | ||
| 60 | .. option:: --stack-first | |
| 61 | ||
| 62 | Place stack at start of linear memory rather than after data. | |
| 63 | ||
| 64 | .. option:: --compress-relocations | |
| 65 | ||
| 66 | Relocation targets in the code section 5-bytes wide in order to potentially | |
| 67 | occomate the largest LEB128 value. This option will cause the linker to | |
| 68 | shirnk the code section to remove any padding from the final output. However | |
| 69 | because it effects code offset, this option is not comatible with outputing | |
| 70 | debug information. | |
| 71 | ||
| 72 | .. option:: --allow-undefined | |
| 73 | ||
| 74 | Allow undefined symbols in linked binary. | |
| 75 | ||
| 76 | .. option:: --import-memory | |
| 77 | ||
| 78 | Import memory from the environment. | |
| 79 | ||
| 80 | .. option:: --initial-memory=<value> | |
| 81 | ||
| 82 | Initial size of the linear memory. Default: static data size. | |
| 83 | ||
| 84 | .. option:: --max-memory=<value> | |
| 85 | ||
| 86 | Maximum size of the linear memory. Default: unlimited. | |
| 87 | ||
| 88 | By default the function table is neither imported nor exported, but defined | |
| 89 | for internal use only. | |
| 90 | ||
| 91 | When building shared libraries symbols are exported if they are marked | |
| 92 | as ``visibility=default``. When building executables only the entry point is | |
| 93 | exported by default. In addition any symbol included on the command line via | |
| 94 | ``--export`` is also exported. | |
| 95 | ||
| 96 | Since WebAssembly is designed with size in mind the linker defaults to | |
| 97 | ``--gc-sections`` which means that all unused functions and data segments will | |
| 98 | be stripped from the binary. | |
| 99 | ||
| 100 | The symbols which are preserved by default are: | |
| 101 | ||
| 102 | - The entry point (by default ``_start``). | |
| 103 | - Any symbol which is to be exported. | |
| 104 | - Any symbol transitively referenced by the above. | |
| 105 | ||
| 106 | ||
| 26 | 107 | Missing features |
| 27 | 108 | ---------------- |
| 28 | 109 | |
| 29 | There are several key features that are not yet implement in the WebAssembly | |
| 30 | ports: | |
| 31 | ||
| 32 | - COMDAT support. This means that support for C++ is still very limited. | |
| 33 | - Function stripping. Currently there is no support for ``--gc-sections`` so | |
| 34 | functions and data from a given object will linked as a unit. | |
| 35 | - Section start/end symbols. The synthetic symbols that mark the start and | |
| 36 | of data regions are not yet created in the output file. | |
| 110 | - Merging of data section similar to ``SHF_MERGE`` in the ELF world is not | |
| 111 | supported. | |
| 112 | - No support for creating shared libraries. The spec for shared libraries in | |
| 113 | WebAssembly is still in flux: | |
| 114 | https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md |
deps/lld/docs/conf.py+2-2| ... | ... | @@ -48,9 +48,9 @@ copyright = u'2011-%d, LLVM Project' % date.today().year |
| 48 | 48 | # built documents. |
| 49 | 49 | # |
| 50 | 50 | # The short version. |
| 51 | version = '7' | |
| 51 | version = '8' | |
| 52 | 52 | # The full version, including alpha/beta/rc tags. |
| 53 | release = '7' | |
| 53 | release = '8' | |
| 54 | 54 | |
| 55 | 55 | # The language for content autogenerated by Sphinx. Refer to documentation |
| 56 | 56 | # for a list of supported languages. |
deps/lld/docs/index.rst+10-11| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | LLD - The LLVM Linker |
| 2 | 2 | ===================== |
| 3 | 3 | |
| 4 | LLD is a linker from the LLVM project. That is a drop-in replacement | |
| 4 | LLD is a linker from the LLVM project that is a drop-in replacement | |
| 5 | 5 | for system linkers and runs much faster than them. It also provides |
| 6 | 6 | features that are useful for toolchain developers. |
| 7 | 7 | |
| ... | ... | @@ -17,7 +17,7 @@ read :doc:`AtomLLD`. |
| 17 | 17 | Features |
| 18 | 18 | -------- |
| 19 | 19 | |
| 20 | - LLD is a drop-in replacement for the GNU linkers. That accepts the | |
| 20 | - LLD is a drop-in replacement for the GNU linkers that accepts the | |
| 21 | 21 | same command line arguments and linker scripts as GNU. |
| 22 | 22 | |
| 23 | 23 | We are currently working closely with the FreeBSD project to make |
| ... | ... | @@ -30,29 +30,27 @@ Features |
| 30 | 30 | <https://www.freebsd.org/news/status/report-2016-10-2016-12.html#Using-LLVM%27s-LLD-Linker-as-FreeBSD%27s-System-Linker>`_. |
| 31 | 31 | |
| 32 | 32 | - LLD is very fast. When you link a large program on a multicore |
| 33 | machine, you can expect that LLD runs more than twice as fast as GNU | |
| 33 | machine, you can expect that LLD runs more than twice as fast as the GNU | |
| 34 | 34 | gold linker. Your milage may vary, though. |
| 35 | 35 | |
| 36 | 36 | - It supports various CPUs/ABIs including x86-64, x86, x32, AArch64, |
| 37 | 37 | ARM, MIPS 32/64 big/little-endian, PowerPC, PowerPC 64 and AMDGPU. |
| 38 | Among these, x86-64 is the most well-supported target and have | |
| 39 | reached production quality. AArch64 and MIPS seem decent too. x86 | |
| 40 | should be OK but not well tested yet. ARM support is being developed | |
| 41 | actively. | |
| 38 | Among these, x86-64, AArch64, and ARM (>= v6) are production quality. | |
| 39 | MIPS seems decent too. x86 should be OK but is not well tested yet. | |
| 42 | 40 | |
| 43 | 41 | - It is always a cross-linker, meaning that it always supports all the |
| 44 | 42 | above targets however it was built. In fact, we don't provide a |
| 45 | 43 | build-time option to enable/disable each target. This should make it |
| 46 | 44 | easy to use our linker as part of a cross-compile toolchain. |
| 47 | 45 | |
| 48 | - You can embed LLD to your program to eliminate dependency to | |
| 46 | - You can embed LLD in your program to eliminate dependencies on | |
| 49 | 47 | external linkers. All you have to do is to construct object files |
| 50 | 48 | and command line arguments just like you would do to invoke an |
| 51 | 49 | external linker and then call the linker's main function, |
| 52 | 50 | ``lld::elf::link``, from your code. |
| 53 | 51 | |
| 54 | 52 | - It is small. We are using LLVM libObject library to read from object |
| 55 | files, so it is not completely a fair comparison, but as of February | |
| 53 | files, so it is not a completely fair comparison, but as of February | |
| 56 | 54 | 2017, LLD/ELF consists only of 21k lines of C++ code while GNU gold |
| 57 | 55 | consists of 198k lines of C++ code. |
| 58 | 56 | |
| ... | ... | @@ -102,8 +100,8 @@ under ``tools`` directory just like you probably did for clang. For the |
| 102 | 100 | details, see `Getting Started with the LLVM System |
| 103 | 101 | <http://llvm.org/docs/GettingStarted.html>`_. |
| 104 | 102 | |
| 105 | If you haven't checkout out LLVM, the easiest way to build LLD is to | |
| 106 | checkout the entire LLVM projects/sub-projects from a git mirror and | |
| 103 | If you haven't checked out LLVM, the easiest way to build LLD is to | |
| 104 | check out the entire LLVM projects/sub-projects from a git mirror and | |
| 107 | 105 | build that tree. You need `cmake` and of course a C++ compiler. |
| 108 | 106 | |
| 109 | 107 | .. code-block:: console |
| ... | ... | @@ -175,4 +173,5 @@ document soon. |
| 175 | 173 | AtomLLD |
| 176 | 174 | WebAssembly |
| 177 | 175 | windows_support |
| 176 | missingkeyfunction | |
| 178 | 177 | ReleaseNotes |
deps/lld/docs/ld.lld.1+53-4| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | .\" |
| 4 | 4 | .\" This man page documents only lld's ELF linking support, obtained originally |
| 5 | 5 | .\" from FreeBSD. |
| 6 | .Dd July 30, 2018 | |
| 6 | .Dd September 26, 2018 | |
| 7 | 7 | .Dt LD.LLD 1 |
| 8 | 8 | .Os |
| 9 | 9 | .Sh NAME |
| ... | ... | @@ -13,6 +13,7 @@ |
| 13 | 13 | .Nm ld.lld |
| 14 | 14 | .Op Ar options |
| 15 | 15 | .Ar objfile ... |
| 16 | ||
| 16 | 17 | .Sh DESCRIPTION |
| 17 | 18 | A linker takes one or more object, archive, and library files, and combines |
| 18 | 19 | them into an output file (an executable, a shared library, or another object |
| ... | ... | @@ -25,7 +26,21 @@ is a drop-in replacement for the GNU BFD and gold linkers. |
| 25 | 26 | It accepts most of the same command line arguments and linker scripts |
| 26 | 27 | as GNU linkers. |
| 27 | 28 | .Pp |
| 28 | These options are available: | |
| 29 | .Nm | |
| 30 | currently supports i386, x86-64, ARM, AArch64, PowerPC32, PowerPC64, | |
| 31 | MIPS32, MIPS64, RISC-V, AMDGPU, Hexagon and SPARC V9 targets. | |
| 32 | .Nm | |
| 33 | acts as a Microsoft link.exe-compatible linker if invoked as | |
| 34 | .Nm lld-link | |
| 35 | and as macOS's ld if invoked as | |
| 36 | .Nm ld.ld64. | |
| 37 | All these targets are always supported however | |
| 38 | .Nm | |
| 39 | was built, so you can always use | |
| 40 | .Nm | |
| 41 | as a native linker as well as a cross linker. | |
| 42 | ||
| 43 | .Sh OPTIONS | |
| 29 | 44 | .Bl -tag -width indent |
| 30 | 45 | .It Fl -allow-multiple-definition |
| 31 | 46 | Do not error if a symbol is defined multiple times. |
| ... | ... | @@ -144,6 +159,9 @@ Maximum number of errors to emit before stopping. |
| 144 | 159 | A value of zero indicates that there is no limit. |
| 145 | 160 | .It Fl -error-unresolved-symbols |
| 146 | 161 | Report unresolved symbols as errors. |
| 162 | .It Fl -execute-only | |
| 163 | Mark executable sections unreadable. This option is currently only | |
| 164 | supported on AArch64. | |
| 147 | 165 | .It Fl -exclude-libs Ns = Ns Ar value |
| 148 | 166 | Exclude static libraries from automatic export. |
| 149 | 167 | .It Fl -export-dynamic , Fl E |
| ... | ... | @@ -293,10 +311,14 @@ Write optimization remarks in YAML format to |
| 293 | 311 | .Ar file . |
| 294 | 312 | .It Fl -opt-remarks-with-hotness |
| 295 | 313 | Include hotness information in the optimization remarks file. |
| 314 | .It Fl -pic-veneer | |
| 315 | Always generate position independent thunks. | |
| 296 | 316 | .It Fl -pie |
| 297 | 317 | Create a position independent executable. |
| 298 | 318 | .It Fl -print-gc-sections |
| 299 | 319 | List removed unused sections. |
| 320 | .It Fl -print-icf-sections | |
| 321 | List identical folded sections. | |
| 300 | 322 | .It Fl -print-map |
| 301 | 323 | Print a link map to the standard output. |
| 302 | 324 | .It Fl -push-state |
| ... | ... | @@ -304,7 +326,7 @@ Save the current state of |
| 304 | 326 | .Fl -as-needed , |
| 305 | 327 | .Fl -static , |
| 306 | 328 | and |
| 307 | .Fl -while-archive. | |
| 329 | .Fl -whole-archive. | |
| 308 | 330 | .It Fl -pop-state |
| 309 | 331 | Undo the effect of |
| 310 | 332 | .Fl -push-state. |
| ... | ... | @@ -426,6 +448,17 @@ This can be used to ensure linker invocation remains compatible with |
| 426 | 448 | traditional Unix-like linkers. |
| 427 | 449 | .It Fl -warn-common |
| 428 | 450 | Warn about duplicate common symbols. |
| 451 | .It Fl -warn-ifunc-textrel | |
| 452 | Warn about using ifunc symbols in conjunction with text relocations. | |
| 453 | Older versions of glibc library (2.28 and earlier) has a bug that causes | |
| 454 | the segment that includes ifunc symbols to be marked as not executable when | |
| 455 | they are relocated. As a result, although the program compiles and links | |
| 456 | successfully, it gives segmentation fault when the instruction pointer reaches | |
| 457 | an ifunc symbol. Use -warn-ifunc-textrel to let lld give a warning, if the | |
| 458 | code may include ifunc symbols, may do text relocations and be linked with | |
| 459 | an older glibc version. Otherwise, there is no need to use it, as the default | |
| 460 | value does not give a warning. This flag has been introduced in late 2018, | |
| 461 | has no counter part in ld and gold linkers, and may be removed in the future. | |
| 429 | 462 | .It Fl -warn-unresolved-symbols |
| 430 | 463 | Report unresolved symbols as warnings. |
| 431 | 464 | .It Fl -whole-archive |
| ... | ... | @@ -440,10 +473,22 @@ Make the main stack executable. |
| 440 | 473 | Stack permissions are recorded in the |
| 441 | 474 | .Dv PT_GNU_STACK |
| 442 | 475 | segment. |
| 476 | .It Cm global | |
| 477 | Sets the | |
| 478 | .Dv DF_1_GLOBAL flag in the | |
| 479 | .Dv DYNAMIC | |
| 480 | section. | |
| 481 | Different loaders can decide how to handle this flag on their own. | |
| 443 | 482 | .It Cm initfirst |
| 444 | 483 | Sets the |
| 445 | 484 | .Dv DF_1_INITFIRST |
| 446 | 485 | flag to indicate the module should be initialized first. |
| 486 | .It Cm interpose | |
| 487 | Set the | |
| 488 | .Dv DF_1_INTERPOSE | |
| 489 | flag to indicate to the runtime linker that the object is an interposer. | |
| 490 | During symbol resolution interposers are searched after the application | |
| 491 | but before other dependencies. | |
| 447 | 492 | .It Cm muldefs |
| 448 | 493 | Do not error if a symbol is defined multiple times. |
| 449 | 494 | The first definition will be used. |
| ... | ... | @@ -453,6 +498,10 @@ This is a synonym for |
| 453 | 498 | Disable combining and sorting multiple relocation sections. |
| 454 | 499 | .It Cm nocopyreloc |
| 455 | 500 | Disable the creation of copy relocations. |
| 501 | .It Cm nodefaultlib | |
| 502 | Set the | |
| 503 | .Dv DF_1_NODEFLIB | |
| 504 | flag to indicate that default library search paths should be ignored. | |
| 456 | 505 | .It Cm nodelete |
| 457 | 506 | Set the |
| 458 | 507 | .Dv DF_1_NODELETE |
| ... | ... | @@ -460,7 +509,7 @@ flag to indicate that the object cannot be unloaded from a process. |
| 460 | 509 | .It Cm nodlopen |
| 461 | 510 | Set the |
| 462 | 511 | .Dv DF_1_NOOPEN |
| 463 | flag to indcate that the object may not be opened by | |
| 512 | flag to indicate that the object may not be opened by | |
| 464 | 513 | .Xr dlopen 3 . |
| 465 | 514 | .It Cm norelro |
| 466 | 515 | Do not indicate that portions of the object shold be mapped read-only |
deps/lld/docs/missingkeyfunction.rst created+84| ... | ... | @@ -0,0 +1,84 @@ |
| 1 | Missing Key Function | |
| 2 | ==================== | |
| 3 | ||
| 4 | If your build failed with a linker error something like this:: | |
| 5 | ||
| 6 | foo.cc:28: error: undefined reference to 'vtable for C' | |
| 7 | the vtable symbol may be undefined because the class is missing its key function (see https://lld.llvm.org/missingkeyfunction) | |
| 8 | ||
| 9 | it's likely that your class C has a key function (defined by the ABI as the first | |
| 10 | non-pure, non-inline, virtual method), but you haven't actually defined it. | |
| 11 | ||
| 12 | When a class has a key function, the compiler emits the vtable (and some other | |
| 13 | things as well) only in the translation unit that defines that key function. Thus, | |
| 14 | if you're missing the key function, you'll also be missing the vtable. If no other | |
| 15 | function calls your missing method, you won't see any undefined reference errors | |
| 16 | for it, but you will see undefined references to the vtable symbol. | |
| 17 | ||
| 18 | When a class has no non-pure, non-inline, virtual methods, there is no key | |
| 19 | method, and the compiler is forced to emit the vtable in every translation unit | |
| 20 | that references the class. In this case, it is emitted in a COMDAT section, | |
| 21 | which allows the linker to eliminate all duplicate copies. This is still | |
| 22 | wasteful in terms of object file size and link time, so it's always advisable to | |
| 23 | ensure there is at least one eligible method that can serve as the key function. | |
| 24 | ||
| 25 | Here are the most common mistakes that lead to this error: | |
| 26 | ||
| 27 | Failing to define a virtual destructor | |
| 28 | -------------------------------------- | |
| 29 | ||
| 30 | Say you have a base class declared in a header file:: | |
| 31 | ||
| 32 | class B { | |
| 33 | public: | |
| 34 | B(); | |
| 35 | virtual ~B(); | |
| 36 | ... | |
| 37 | }; | |
| 38 | ||
| 39 | Here, ``~B`` is the first non-pure, non-inline, virtual method, so it is the key | |
| 40 | method. If you forget to define ``B::~B`` in your source file, the compiler will | |
| 41 | not emit the vtable for ``B``, and you'll get an undefined reference to "vtable | |
| 42 | for B". | |
| 43 | ||
| 44 | This is just an example of the more general mistake of forgetting to define the | |
| 45 | key function, but it's quite common because virtual destructors are likely to be | |
| 46 | the first eligible key function and it's easy to forget to implement them. It's | |
| 47 | also more likely that you won't have any direct references to the destructor, so | |
| 48 | you won't see any undefined reference errors that point directly to the problem. | |
| 49 | ||
| 50 | The solution in this case is to implement the missing method. | |
| 51 | ||
| 52 | Forgetting to declare a virtual method in an abstract class as pure | |
| 53 | ------------------------------------------------------------------- | |
| 54 | ||
| 55 | Say you have an abstract base class declared in a header file:: | |
| 56 | ||
| 57 | class A { | |
| 58 | public: | |
| 59 | A(); | |
| 60 | virtual ~A() {} | |
| 61 | virtual int foo() = 0; | |
| 62 | ... | |
| 63 | virtual int bar(); | |
| 64 | ... | |
| 65 | }; | |
| 66 | ||
| 67 | This base class is intended to be abstract, but you forgot to mark one of the | |
| 68 | methods pure. Here, ``A::bar``, being non-pure, is nominated as the key function, | |
| 69 | and as a result, the vtable for ``A`` is not emitted, because the compiler is | |
| 70 | waiting for a translation unit that defines ``A::bar``. | |
| 71 | ||
| 72 | The solution in this case is to add the missing ``= 0`` to the declaration of | |
| 73 | ``A::bar``. | |
| 74 | ||
| 75 | Key method is defined, but the linker doesn't see it | |
| 76 | ---------------------------------------------------- | |
| 77 | ||
| 78 | It's also possible that you have defined the key function somewhere, but the | |
| 79 | object file containing the definition of that method isn't being linked into | |
| 80 | your application. | |
| 81 | ||
| 82 | The solution in this case is to check your dependencies to make sure that | |
| 83 | the object file or the library file containing the key function is given to | |
| 84 | the linker. |
deps/lld/docs/open_projects.rst-2| ... | ... | @@ -3,8 +3,6 @@ |
| 3 | 3 | Open Projects |
| 4 | 4 | ============= |
| 5 | 5 | |
| 6 | .. include:: ../include/lld/Core/TODO.txt | |
| 7 | ||
| 8 | 6 | Documentation TODOs |
| 9 | 7 | ~~~~~~~~~~~~~~~~~~~ |
| 10 | 8 |
deps/lld/docs/windows_support.rst+2-2| ... | ... | @@ -20,8 +20,8 @@ command line options, and it drives further linking processes. LLD accepts |
| 20 | 20 | almost all command line options that the linker shipped with Microsoft Visual |
| 21 | 21 | C++ (link.exe) supports. |
| 22 | 22 | |
| 23 | The current status is that LLD can link itself on Windows x86/x64 | |
| 24 | using Visual C++ 2013 as the compiler. | |
| 23 | The current status is that LLD is used to link production builds of large | |
| 24 | real-world binaries such as Firefox and Chromium. | |
| 25 | 25 | |
| 26 | 26 | Development status |
| 27 | 27 | ================== |
deps/lld/include/lld/Common/Args.h+3| ... | ... | @@ -29,6 +29,9 @@ uint64_t getZOptionValue(llvm::opt::InputArgList &Args, int Id, StringRef Key, |
| 29 | 29 | uint64_t Default); |
| 30 | 30 | |
| 31 | 31 | std::vector<StringRef> getLines(MemoryBufferRef MB); |
| 32 | ||
| 33 | StringRef getFilenameWithoutExe(StringRef Path); | |
| 34 | ||
| 32 | 35 | } // namespace args |
| 33 | 36 | } // namespace lld |
| 34 | 37 |
deps/lld/include/lld/Common/ErrorHandler.h+1-1| ... | ... | @@ -153,7 +153,7 @@ T check2(Expected<T> E, llvm::function_ref<std::string()> Prefix) { |
| 153 | 153 | inline std::string toString(const Twine &S) { return S.str(); } |
| 154 | 154 | |
| 155 | 155 | // To evaluate the second argument lazily, we use C macro. |
| 156 | #define CHECK(E, S) check2(E, [&] { return toString(S); }) | |
| 156 | #define CHECK(E, S) check2((E), [&] { return toString(S); }) | |
| 157 | 157 | |
| 158 | 158 | } // namespace lld |
| 159 | 159 |
deps/lld/include/lld/Common/LLVM.h+58-42| ... | ... | @@ -22,53 +22,69 @@ |
| 22 | 22 | #include <utility> |
| 23 | 23 | |
| 24 | 24 | namespace llvm { |
| 25 | // ADT's. | |
| 26 | class Error; | |
| 27 | class StringRef; | |
| 28 | class Twine; | |
| 29 | class MemoryBuffer; | |
| 30 | class MemoryBufferRef; | |
| 31 | template<typename T> class ArrayRef; | |
| 32 | template<unsigned InternalLen> class SmallString; | |
| 33 | template<typename T, unsigned N> class SmallVector; | |
| 34 | template<typename T> class SmallVectorImpl; | |
| 25 | // ADT's. | |
| 26 | class raw_ostream; | |
| 27 | class Error; | |
| 28 | class StringRef; | |
| 29 | class Twine; | |
| 30 | class MemoryBuffer; | |
| 31 | class MemoryBufferRef; | |
| 32 | template <typename T> class ArrayRef; | |
| 33 | template <unsigned InternalLen> class SmallString; | |
| 34 | template <typename T, unsigned N> class SmallVector; | |
| 35 | template <typename T> class ErrorOr; | |
| 36 | template <typename T> class Expected; | |
| 35 | 37 | |
| 36 | template<typename T> | |
| 37 | struct SaveAndRestore; | |
| 38 | namespace object { | |
| 39 | class WasmObjectFile; | |
| 40 | struct WasmSection; | |
| 41 | struct WasmSegment; | |
| 42 | class WasmSymbol; | |
| 43 | } // namespace object | |
| 38 | 44 | |
| 39 | template<typename T> | |
| 40 | class ErrorOr; | |
| 41 | ||
| 42 | template<typename T> | |
| 43 | class Expected; | |
| 44 | ||
| 45 | class raw_ostream; | |
| 46 | // TODO: DenseMap, ... | |
| 47 | } | |
| 45 | namespace wasm { | |
| 46 | struct WasmEvent; | |
| 47 | struct WasmEventType; | |
| 48 | struct WasmFunction; | |
| 49 | struct WasmGlobal; | |
| 50 | struct WasmGlobalType; | |
| 51 | struct WasmRelocation; | |
| 52 | struct WasmSignature; | |
| 53 | } // namespace wasm | |
| 54 | } // namespace llvm | |
| 48 | 55 | |
| 49 | 56 | namespace lld { |
| 50 | // Casting operators. | |
| 51 | using llvm::isa; | |
| 52 | using llvm::cast; | |
| 53 | using llvm::dyn_cast; | |
| 54 | using llvm::dyn_cast_or_null; | |
| 55 | using llvm::cast_or_null; | |
| 57 | // Casting operators. | |
| 58 | using llvm::cast; | |
| 59 | using llvm::cast_or_null; | |
| 60 | using llvm::dyn_cast; | |
| 61 | using llvm::dyn_cast_or_null; | |
| 62 | using llvm::isa; | |
| 56 | 63 | |
| 57 | // ADT's. | |
| 58 | using llvm::Error; | |
| 59 | using llvm::StringRef; | |
| 60 | using llvm::Twine; | |
| 61 | using llvm::MemoryBuffer; | |
| 62 | using llvm::MemoryBufferRef; | |
| 63 | using llvm::ArrayRef; | |
| 64 | using llvm::SmallString; | |
| 65 | using llvm::SmallVector; | |
| 66 | using llvm::SmallVectorImpl; | |
| 67 | using llvm::SaveAndRestore; | |
| 68 | using llvm::ErrorOr; | |
| 69 | using llvm::Expected; | |
| 64 | // ADT's. | |
| 65 | using llvm::ArrayRef; | |
| 66 | using llvm::Error; | |
| 67 | using llvm::ErrorOr; | |
| 68 | using llvm::Expected; | |
| 69 | using llvm::MemoryBuffer; | |
| 70 | using llvm::MemoryBufferRef; | |
| 71 | using llvm::raw_ostream; | |
| 72 | using llvm::SmallString; | |
| 73 | using llvm::SmallVector; | |
| 74 | using llvm::StringRef; | |
| 75 | using llvm::Twine; | |
| 70 | 76 | |
| 71 | using llvm::raw_ostream; | |
| 77 | using llvm::object::WasmObjectFile; | |
| 78 | using llvm::object::WasmSection; | |
| 79 | using llvm::object::WasmSegment; | |
| 80 | using llvm::object::WasmSymbol; | |
| 81 | using llvm::wasm::WasmEvent; | |
| 82 | using llvm::wasm::WasmEventType; | |
| 83 | using llvm::wasm::WasmFunction; | |
| 84 | using llvm::wasm::WasmGlobal; | |
| 85 | using llvm::wasm::WasmGlobalType; | |
| 86 | using llvm::wasm::WasmRelocation; | |
| 87 | using llvm::wasm::WasmSignature; | |
| 72 | 88 | } // end namespace lld. |
| 73 | 89 | |
| 74 | 90 | namespace std { |
| ... | ... | @@ -78,6 +94,6 @@ public: |
| 78 | 94 | return llvm::hash_value(s); |
| 79 | 95 | } |
| 80 | 96 | }; |
| 81 | } | |
| 97 | } // namespace std | |
| 82 | 98 | |
| 83 | 99 | #endif |
deps/lld/include/lld/Common/Strings.h-3| ... | ... | @@ -41,9 +41,6 @@ private: |
| 41 | 41 | std::vector<llvm::GlobPattern> Patterns; |
| 42 | 42 | }; |
| 43 | 43 | |
| 44 | inline llvm::ArrayRef<uint8_t> toArrayRef(llvm::StringRef S) { | |
| 45 | return {reinterpret_cast<const uint8_t *>(S.data()), S.size()}; | |
| 46 | } | |
| 47 | 44 | } // namespace lld |
| 48 | 45 | |
| 49 | 46 | #endif |
deps/lld/include/lld/Common/TargetOptionsCommandFlags.h+1| ... | ... | @@ -19,4 +19,5 @@ namespace lld { |
| 19 | 19 | llvm::TargetOptions InitTargetOptionsFromCodeGenFlags(); |
| 20 | 20 | llvm::Optional<llvm::CodeModel::Model> GetCodeModelFromCMModel(); |
| 21 | 21 | std::string GetCPUStr(); |
| 22 | std::vector<std::string> GetMAttrs(); | |
| 22 | 23 | } |
deps/lld/include/lld/Common/Threads.h+1-1| ... | ... | @@ -74,7 +74,7 @@ template <typename R, class FuncTy> void parallelForEach(R &&Range, FuncTy Fn) { |
| 74 | 74 | } |
| 75 | 75 | |
| 76 | 76 | inline void parallelForEachN(size_t Begin, size_t End, |
| 77 | std::function<void(size_t)> Fn) { | |
| 77 | llvm::function_ref<void(size_t)> Fn) { | |
| 78 | 78 | if (ThreadsEnabled) |
| 79 | 79 | for_each_n(llvm::parallel::par, Begin, End, Fn); |
| 80 | 80 | else |
deps/lld/include/lld/Core/TODO.txt deleted-14| ... | ... | @@ -1,14 +0,0 @@ |
| 1 | include/lld/Core | |
| 2 | ~~~~~~~~~~~~~~~~ | |
| 3 | ||
| 4 | * The yaml reader/writer interfaces should be changed to return | |
| 5 | an explanatory string if there is an error. The existing error_code | |
| 6 | abstraction only works for returning low level OS errors. It does not | |
| 7 | work for describing formatting issues. | |
| 8 | ||
| 9 | * We need to add more attributes to File. In particular, we need cpu | |
| 10 | and OS information (like target triples). We should also provide explicit | |
| 11 | support for `LLVM IR module flags metadata`__. | |
| 12 | ||
| 13 | .. __: http://llvm.org/docs/LangRef.html#module_flags | |
| 14 | .. _Clang: http://clang.llvm.org/docs/InternalsManual.html#Diagnostics |
deps/lld/lib/Driver/DarwinLdDriver.cpp+7-4| ... | ... | @@ -382,10 +382,13 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) { |
| 382 | 382 | if (arch == MachOLinkingContext::arch_unknown && |
| 383 | 383 | !parsedArgs.getLastArg(OPT_test_file_usage)) { |
| 384 | 384 | // If no -arch and no options at all, print usage message. |
| 385 | if (parsedArgs.size() == 0) | |
| 386 | table.PrintHelp(llvm::outs(), args[0], "LLVM Linker", false); | |
| 387 | else | |
| 385 | if (parsedArgs.size() == 0) { | |
| 386 | table.PrintHelp(llvm::outs(), | |
| 387 | (std::string(args[0]) + " [options] file...").c_str(), | |
| 388 | "LLVM Linker", false); | |
| 389 | } else { | |
| 388 | 390 | error("-arch not specified and could not be inferred"); |
| 391 | } | |
| 389 | 392 | return false; |
| 390 | 393 | } |
| 391 | 394 | } |
| ... | ... | @@ -1143,7 +1146,7 @@ static void createFiles(MachOLinkingContext &ctx, bool Implicit) { |
| 1143 | 1146 | /// This is where the link is actually performed. |
| 1144 | 1147 | bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly, |
| 1145 | 1148 | raw_ostream &Error) { |
| 1146 | errorHandler().LogName = llvm::sys::path::filename(args[0]); | |
| 1149 | errorHandler().LogName = args::getFilenameWithoutExe(args[0]); | |
| 1147 | 1150 | errorHandler().ErrorLimitExceededMsg = |
| 1148 | 1151 | "too many errors emitted, stopping now (use " |
| 1149 | 1152 | "'-error-limit 0' to see all errors)"; |
deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp+2| ... | ... | @@ -80,6 +80,7 @@ public: |
| 80 | 80 | switch (ref->kindValue()) { |
| 81 | 81 | case ripRel32Got: |
| 82 | 82 | assert(targetNowGOT && "target must be GOT"); |
| 83 | LLVM_FALLTHROUGH; | |
| 83 | 84 | case ripRel32GotLoad: |
| 84 | 85 | const_cast<Reference *>(ref) |
| 85 | 86 | ->setKindValue(targetNowGOT ? ripRel32 : ripRel32GotLoadNowLea); |
| ... | ... | @@ -621,6 +622,7 @@ void ArchHandler_x86_64::applyFixupFinal( |
| 621 | 622 | // Fall into llvm_unreachable(). |
| 622 | 623 | break; |
| 623 | 624 | } |
| 625 | llvm_unreachable("invalid x86_64 Reference Kind"); | |
| 624 | 626 | } |
| 625 | 627 | |
| 626 | 628 | void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref, |
deps/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp+1| ... | ... | @@ -262,6 +262,7 @@ void MachOLinkingContext::configure(HeaderFileType type, Arch arch, OS os, |
| 262 | 262 | case llvm::MachO::MH_OBJECT: |
| 263 | 263 | _printRemainingUndefines = false; |
| 264 | 264 | _allowRemainingUndefines = true; |
| 265 | break; | |
| 265 | 266 | default: |
| 266 | 267 | break; |
| 267 | 268 | } |
deps/lld/test/CMakeLists.txt+3| ... | ... | @@ -53,6 +53,9 @@ add_lit_testsuite(check-lld "Running lld test suite" |
| 53 | 53 | DEPENDS ${LLD_TEST_DEPS} |
| 54 | 54 | ) |
| 55 | 55 | |
| 56 | add_custom_target(lld-test-depends DEPENDS ${LLD_TEST_DEPS}) | |
| 57 | set_target_properties(lld-test-depends PROPERTIES FOLDER "lld tests") | |
| 58 | ||
| 56 | 59 | add_lit_testsuites(LLD ${CMAKE_CURRENT_SOURCE_DIR} |
| 57 | 60 | PARAMS lld_site_config=${CMAKE_CURRENT_BINARY_DIR}/lit.site.cfg |
| 58 | 61 | lld_unit_site_config=${CMAKE_CURRENT_BINARY_DIR}/Unit/lit.site.cfg |
deps/lld/test/COFF/Inputs/bad-block-size.pdb created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | Microsoft C/C++ MSF 7.00 | |
| 2 | DS | |
| \ No newline at end of file |
deps/lld/test/COFF/Inputs/comdat-jumptable2.s created+35| ... | ... | @@ -0,0 +1,35 @@ |
| 1 | .section .text@comdatfunc, "x" | |
| 2 | .linkonce discard | |
| 3 | .globl comdatfunc | |
| 4 | comdatfunc: | |
| 5 | leaq .Ljumptable(%rip), %rax | |
| 6 | movslq (%rax, %rcx, 4), %rcx | |
| 7 | addq %rcx, %rax | |
| 8 | jmp *%rax | |
| 9 | ||
| 10 | .section .rdata, "dr" | |
| 11 | .long 0xcccccccc | |
| 12 | .Ljumptable: | |
| 13 | .long .Ltail1-.Ljumptable | |
| 14 | .long .Ltail2-.Ljumptable | |
| 15 | .long .Ltail3-.Ljumptable | |
| 16 | .long 0xdddddddd | |
| 17 | ||
| 18 | .section .text@comdatfunc, "x" | |
| 19 | # If assembled with binutils, the following line can be kept in: | |
| 20 | # .linkonce discard | |
| 21 | .Ltail1: | |
| 22 | movl $1, %eax | |
| 23 | ret | |
| 24 | .Ltail2: | |
| 25 | movl $2, %eax | |
| 26 | ret | |
| 27 | .Ltail3: | |
| 28 | movl $3, %eax | |
| 29 | ret | |
| 30 | ||
| 31 | .text | |
| 32 | .globl otherfunc | |
| 33 | otherfunc: | |
| 34 | call comdatfunc | |
| 35 | ret |
deps/lld/test/COFF/Inputs/crt-dyn-initializer-order_1.yaml created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | --- !COFF | |
| 2 | header: | |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 4 | Characteristics: [ ] | |
| 5 | sections: | |
| 6 | - Name: '.CRT$XCU' | |
| 7 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | |
| 8 | Alignment: 1 | |
| 9 | SectionData: 55 | |
| 10 | - Name: '.CRT$XCU' | |
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | |
| 12 | Alignment: 1 | |
| 13 | SectionData: 70 | |
| 14 | symbols: | |
| 15 | ... |
deps/lld/test/COFF/Inputs/crt-dyn-initializer-order_2.yaml created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | --- !COFF | |
| 2 | header: | |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 4 | Characteristics: [ ] | |
| 5 | sections: | |
| 6 | - Name: '.CRT$XCU' | |
| 7 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | |
| 8 | Alignment: 1 | |
| 9 | SectionData: 10 | |
| 10 | - Name: '.CRT$XCU' | |
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | |
| 12 | Alignment: 1 | |
| 13 | SectionData: 11 | |
| 14 | - Name: '.CRT$XCU' | |
| 15 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | |
| 16 | Alignment: 1 | |
| 17 | SectionData: 12 | |
| 18 | symbols: | |
| 19 | ... |
deps/lld/test/COFF/Inputs/empty.yaml created+67| ... | ... | @@ -0,0 +1,67 @@ |
| 1 | --- !COFF | |
| 2 | header: | |
| 3 | Machine: IMAGE_FILE_MACHINE_I386 | |
| 4 | Characteristics: [ ] | |
| 5 | sections: | |
| 6 | - Name: .text | |
| 7 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 8 | Alignment: 4 | |
| 9 | SectionData: 31C0C3 | |
| 10 | - Name: .data | |
| 11 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | |
| 12 | Alignment: 4 | |
| 13 | SectionData: '' | |
| 14 | - Name: .bss | |
| 15 | Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | |
| 16 | Alignment: 4 | |
| 17 | SectionData: '' | |
| 18 | symbols: | |
| 19 | - Name: .text | |
| 20 | Value: 0 | |
| 21 | SectionNumber: 1 | |
| 22 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 23 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 24 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 25 | SectionDefinition: | |
| 26 | Length: 3 | |
| 27 | NumberOfRelocations: 0 | |
| 28 | NumberOfLinenumbers: 0 | |
| 29 | CheckSum: 3963538403 | |
| 30 | Number: 1 | |
| 31 | - Name: .data | |
| 32 | Value: 0 | |
| 33 | SectionNumber: 2 | |
| 34 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 35 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 36 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 37 | SectionDefinition: | |
| 38 | Length: 0 | |
| 39 | NumberOfRelocations: 0 | |
| 40 | NumberOfLinenumbers: 0 | |
| 41 | CheckSum: 0 | |
| 42 | Number: 2 | |
| 43 | - Name: .bss | |
| 44 | Value: 0 | |
| 45 | SectionNumber: 3 | |
| 46 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 47 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 48 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 49 | SectionDefinition: | |
| 50 | Length: 0 | |
| 51 | NumberOfRelocations: 0 | |
| 52 | NumberOfLinenumbers: 0 | |
| 53 | CheckSum: 0 | |
| 54 | Number: 3 | |
| 55 | - Name: '@feat.00' | |
| 56 | Value: 1 | |
| 57 | SectionNumber: -1 | |
| 58 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 59 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 60 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 61 | - Name: _main | |
| 62 | Value: 0 | |
| 63 | SectionNumber: 1 | |
| 64 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 65 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | |
| 66 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 67 | ... |
deps/lld/test/COFF/Inputs/far-arm-thumb-abs.s deleted-2| ... | ... | @@ -1,2 +0,0 @@ |
| 1 | .global too_far1 | |
| 2 | too_far1 = 0x1401004 |
deps/lld/test/COFF/Inputs/far-arm-thumb-abs20.s deleted-2| ... | ... | @@ -1,2 +0,0 @@ |
| 1 | .global too_far20 | |
| 2 | too_far20 = 0x501004 |
deps/lld/test/COFF/Inputs/gnu-implib-data.s created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | .global __imp_data | |
| 2 | ||
| 3 | # The data that is emitted into .idata$7 here is isn't needed for | |
| 4 | # the import data structures, but we need to emit something which | |
| 5 | # produces a relocation against _head_test_lib, to pull in the | |
| 6 | # header and trailer objects. | |
| 7 | ||
| 8 | .section .idata$7 | |
| 9 | .rva _head_test_lib | |
| 10 | ||
| 11 | .section .idata$5 | |
| 12 | __imp_data: | |
| 13 | .rva .Lhint_name | |
| 14 | .long 0 | |
| 15 | ||
| 16 | .section .idata$4 | |
| 17 | .rva .Lhint_name | |
| 18 | .long 0 | |
| 19 | ||
| 20 | .section .idata$6 | |
| 21 | .Lhint_name: | |
| 22 | .short 0 | |
| 23 | .asciz "data" |
deps/lld/test/COFF/Inputs/gnu-implib-func.s created+27| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | .text | |
| 2 | .global func | |
| 3 | .global __imp_func | |
| 4 | func: | |
| 5 | jmp *__imp_func | |
| 6 | ||
| 7 | # The data that is emitted into .idata$7 here is isn't needed for | |
| 8 | # the import data structures, but we need to emit something which | |
| 9 | # produces a relocation against _head_test_lib, to pull in the | |
| 10 | # header and trailer objects. | |
| 11 | ||
| 12 | .section .idata$7 | |
| 13 | .rva _head_test_lib | |
| 14 | ||
| 15 | .section .idata$5 | |
| 16 | __imp_func: | |
| 17 | .rva .Lhint_name | |
| 18 | .long 0 | |
| 19 | ||
| 20 | .section .idata$4 | |
| 21 | .rva .Lhint_name | |
| 22 | .long 0 | |
| 23 | ||
| 24 | .section .idata$6 | |
| 25 | .Lhint_name: | |
| 26 | .short 0 | |
| 27 | .asciz "func" |
deps/lld/test/COFF/Inputs/gnu-implib-head.s created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | .section .idata$2 | |
| 2 | .global _head_test_lib | |
| 3 | _head_test_lib: | |
| 4 | .rva hname | |
| 5 | .long 0 | |
| 6 | .long 0 | |
| 7 | .rva __test_lib_iname | |
| 8 | .rva fthunk | |
| 9 | ||
| 10 | .section .idata$5 | |
| 11 | fthunk: | |
| 12 | .section .idata$4 | |
| 13 | hname: |
deps/lld/test/COFF/Inputs/gnu-implib-tail.s created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | .section .idata$4 | |
| 2 | .long 0 | |
| 3 | .long 0 | |
| 4 | .section .idata$5 | |
| 5 | .long 0 | |
| 6 | .long 0 | |
| 7 | ||
| 8 | .section .idata$7 | |
| 9 | .global __test_lib_iname | |
| 10 | __test_lib_iname: | |
| 11 | .asciz "foo.dll" |
deps/lld/test/COFF/Inputs/gnu-weak.o created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/gnu-weak.o differ |
deps/lld/test/COFF/Inputs/gnu-weak2.o created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/gnu-weak2.o differ |
deps/lld/test/COFF/Inputs/icf-safe.s created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | .section .rdata,"dr",one_only,non_addrsig1 | |
| 2 | .globl non_addrsig1 | |
| 3 | non_addrsig1: | |
| 4 | .byte 3 | |
| 5 | ||
| 6 | .section .rdata,"dr",one_only,non_addrsig2 | |
| 7 | .globl non_addrsig2 | |
| 8 | non_addrsig2: | |
| 9 | .byte 3 |
deps/lld/test/COFF/Inputs/inline-weak.o created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/inline-weak.o differ |
deps/lld/test/COFF/Inputs/inline-weak2.o created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/inline-weak2.o differ |
deps/lld/test/COFF/Inputs/pdb-file-statics-a.yaml+3-3| ... | ... | @@ -1353,7 +1353,7 @@ sections: |
| 1353 | 1353 | RegRelativeSym: |
| 1354 | 1354 | Offset: 48 |
| 1355 | 1355 | Type: 116 |
| 1356 | Register: CVRegRSP | |
| 1356 | Register: RSP | |
| 1357 | 1357 | VarName: __formal |
| 1358 | 1358 | - Kind: S_PROC_ID_END |
| 1359 | 1359 | ScopeEndSym: |
| ... | ... | @@ -1528,13 +1528,13 @@ sections: |
| 1528 | 1528 | RegRelativeSym: |
| 1529 | 1529 | Offset: 48 |
| 1530 | 1530 | Type: 116 |
| 1531 | Register: CVRegRSP | |
| 1531 | Register: RSP | |
| 1532 | 1532 | VarName: argc |
| 1533 | 1533 | - Kind: S_REGREL32 |
| 1534 | 1534 | RegRelativeSym: |
| 1535 | 1535 | Offset: 56 |
| 1536 | 1536 | Type: 4098 |
| 1537 | Register: CVRegRSP | |
| 1537 | Register: RSP | |
| 1538 | 1538 | VarName: argv |
| 1539 | 1539 | - Kind: S_PROC_ID_END |
| 1540 | 1540 | ScopeEndSym: |
deps/lld/test/COFF/Inputs/pdb-file-statics-b.yaml+1-1| ... | ... | @@ -1328,7 +1328,7 @@ sections: |
| 1328 | 1328 | RegRelativeSym: |
| 1329 | 1329 | Offset: 48 |
| 1330 | 1330 | Type: 116 |
| 1331 | Register: CVRegRSP | |
| 1331 | Register: RSP | |
| 1332 | 1332 | VarName: __formal |
| 1333 | 1333 | - Kind: S_PROC_ID_END |
| 1334 | 1334 | ScopeEndSym: |
deps/lld/test/COFF/Inputs/pdb-scopes-a.yaml+4-4| ... | ... | @@ -53,7 +53,7 @@ sections: |
| 53 | 53 | RegRelativeSym: |
| 54 | 54 | Offset: 8 |
| 55 | 55 | Type: 116 |
| 56 | Register: CVRegRSP | |
| 56 | Register: RSP | |
| 57 | 57 | VarName: x |
| 58 | 58 | - Kind: S_PROC_ID_END |
| 59 | 59 | ScopeEndSym: |
| ... | ... | @@ -93,7 +93,7 @@ sections: |
| 93 | 93 | RegRelativeSym: |
| 94 | 94 | Offset: 64 |
| 95 | 95 | Type: 116 |
| 96 | Register: CVRegRSP | |
| 96 | Register: RSP | |
| 97 | 97 | VarName: argc |
| 98 | 98 | - Kind: S_BLOCK32 |
| 99 | 99 | BlockSym: |
| ... | ... | @@ -104,7 +104,7 @@ sections: |
| 104 | 104 | RegRelativeSym: |
| 105 | 105 | Offset: 32 |
| 106 | 106 | Type: 116 |
| 107 | Register: CVRegRSP | |
| 107 | Register: RSP | |
| 108 | 108 | VarName: x |
| 109 | 109 | - Kind: S_END |
| 110 | 110 | ScopeEndSym: |
| ... | ... | @@ -117,7 +117,7 @@ sections: |
| 117 | 117 | RegRelativeSym: |
| 118 | 118 | Offset: 36 |
| 119 | 119 | Type: 116 |
| 120 | Register: CVRegRSP | |
| 120 | Register: RSP | |
| 121 | 121 | VarName: y |
| 122 | 122 | - Kind: S_END |
| 123 | 123 | ScopeEndSym: |
deps/lld/test/COFF/Inputs/pdb-scopes-b.yaml+3-3| ... | ... | @@ -53,7 +53,7 @@ sections: |
| 53 | 53 | RegRelativeSym: |
| 54 | 54 | Offset: 64 |
| 55 | 55 | Type: 116 |
| 56 | Register: CVRegRSP | |
| 56 | Register: RSP | |
| 57 | 57 | VarName: x |
| 58 | 58 | - Kind: S_BLOCK32 |
| 59 | 59 | BlockSym: |
| ... | ... | @@ -64,7 +64,7 @@ sections: |
| 64 | 64 | RegRelativeSym: |
| 65 | 65 | Offset: 32 |
| 66 | 66 | Type: 116 |
| 67 | Register: CVRegRSP | |
| 67 | Register: RSP | |
| 68 | 68 | VarName: y |
| 69 | 69 | - Kind: S_END |
| 70 | 70 | ScopeEndSym: |
| ... | ... | @@ -77,7 +77,7 @@ sections: |
| 77 | 77 | RegRelativeSym: |
| 78 | 78 | Offset: 36 |
| 79 | 79 | Type: 116 |
| 80 | Register: CVRegRSP | |
| 80 | Register: RSP | |
| 81 | 81 | VarName: w |
| 82 | 82 | - Kind: S_END |
| 83 | 83 | ScopeEndSym: |
deps/lld/test/COFF/Inputs/pdb-type-server-missing-2.yaml created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | --- !COFF | |
| 2 | header: | |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 4 | Characteristics: [ ] | |
| 5 | sections: | |
| 6 | - Name: '.debug$T' | |
| 7 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 8 | Alignment: 1 | |
| 9 | Types: | |
| 10 | - Kind: LF_TYPESERVER2 | |
| 11 | TypeServer2: | |
| 12 | Guid: '{01DF191B-22BF-6B42-96CE-5258B8329FE5}' | |
| 13 | Age: 18 | |
| 14 | Name: 'C:\src\llvm-project\build\definitely_not_found_for_sure.pdb' | |
| 15 | - Name: '.text$mn' | |
| 16 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 17 | Alignment: 16 | |
| 18 | SectionData: 33C0C3 | |
| 19 | symbols: | |
| 20 | - Name: '.debug$T' | |
| 21 | Value: 0 | |
| 22 | SectionNumber: 2 | |
| 23 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 24 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 25 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 26 | SectionDefinition: | |
| 27 | Length: 564 | |
| 28 | NumberOfRelocations: 0 | |
| 29 | NumberOfLinenumbers: 0 | |
| 30 | CheckSum: 0 | |
| 31 | Number: 0 | |
| 32 | ... |
deps/lld/test/COFF/Inputs/pdb-type-server-simple-a.yaml+1-1| ... | ... | @@ -53,7 +53,7 @@ sections: |
| 53 | 53 | RegRelativeSym: |
| 54 | 54 | Offset: 32 |
| 55 | 55 | Type: 4102 |
| 56 | Register: CVRegRSP | |
| 56 | Register: RSP | |
| 57 | 57 | VarName: f |
| 58 | 58 | - Kind: S_PROC_ID_END |
| 59 | 59 | ScopeEndSym: |
deps/lld/test/COFF/Inputs/pdb-type-server-simple-b.yaml+1-1| ... | ... | @@ -53,7 +53,7 @@ sections: |
| 53 | 53 | RegRelativeSym: |
| 54 | 54 | Offset: 8 |
| 55 | 55 | Type: 4097 |
| 56 | Register: CVRegRSP | |
| 56 | Register: RSP | |
| 57 | 57 | VarName: p |
| 58 | 58 | - Kind: S_PROC_ID_END |
| 59 | 59 | ScopeEndSym: |
deps/lld/test/COFF/Inputs/pdb-type-server-valid-signature.yaml created+121| ... | ... | @@ -0,0 +1,121 @@ |
| 1 | --- !COFF | |
| 2 | header: | |
| 3 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 4 | Characteristics: [ ] | |
| 5 | sections: | |
| 6 | - Name: '.debug$S' | |
| 7 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 8 | Alignment: 1 | |
| 9 | Subsections: | |
| 10 | - !Symbols | |
| 11 | Records: | |
| 12 | - Kind: S_GPROC32_ID | |
| 13 | ProcSym: | |
| 14 | CodeSize: 3 | |
| 15 | DbgStart: 0 | |
| 16 | DbgEnd: 2 | |
| 17 | FunctionType: 4199 | |
| 18 | Flags: [ ] | |
| 19 | DisplayName: main | |
| 20 | - Kind: S_FRAMEPROC | |
| 21 | FrameProcSym: | |
| 22 | TotalFrameBytes: 0 | |
| 23 | PaddingFrameBytes: 0 | |
| 24 | OffsetToPadding: 0 | |
| 25 | BytesOfCalleeSavedRegisters: 0 | |
| 26 | OffsetOfExceptionHandler: 0 | |
| 27 | SectionIdOfExceptionHandler: 0 | |
| 28 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | |
| 29 | - Kind: S_PROC_ID_END | |
| 30 | ScopeEndSym: | |
| 31 | - !Lines | |
| 32 | CodeSize: 3 | |
| 33 | Flags: [ ] | |
| 34 | RelocOffset: 0 | |
| 35 | RelocSegment: 0 | |
| 36 | Blocks: | |
| 37 | - FileName: 'c:\src\llvm-project\build\t.c' | |
| 38 | Lines: | |
| 39 | - Offset: 0 | |
| 40 | LineStart: 1 | |
| 41 | IsStatement: true | |
| 42 | EndDelta: 0 | |
| 43 | Columns: | |
| 44 | - !FileChecksums | |
| 45 | Checksums: | |
| 46 | - FileName: 'c:\src\llvm-project\build\t.c' | |
| 47 | Kind: MD5 | |
| 48 | Checksum: 270A878DCC1B845655B162F56C4F5020 | |
| 49 | - !StringTable | |
| 50 | Strings: | |
| 51 | - 'c:\src\llvm-project\build\t.c' | |
| 52 | Relocations: | |
| 53 | - VirtualAddress: 44 | |
| 54 | SymbolName: main | |
| 55 | Type: IMAGE_REL_AMD64_SECREL | |
| 56 | - VirtualAddress: 48 | |
| 57 | SymbolName: main | |
| 58 | Type: IMAGE_REL_AMD64_SECTION | |
| 59 | - VirtualAddress: 100 | |
| 60 | SymbolName: main | |
| 61 | Type: IMAGE_REL_AMD64_SECREL | |
| 62 | - VirtualAddress: 104 | |
| 63 | SymbolName: main | |
| 64 | Type: IMAGE_REL_AMD64_SECTION | |
| 65 | - Name: '.debug$T' | |
| 66 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 67 | Alignment: 1 | |
| 68 | Types: | |
| 69 | - Kind: LF_TYPESERVER2 | |
| 70 | TypeServer2: | |
| 71 | Guid: '{8DABD2A0-28FF-CB43-9BAF-175B77B76414}' | |
| 72 | Age: 18 | |
| 73 | Name: 'pdb-diff-cl.pdb' | |
| 74 | - Name: '.text$mn' | |
| 75 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 76 | Alignment: 16 | |
| 77 | SectionData: 33C0C3 | |
| 78 | symbols: | |
| 79 | - Name: '.debug$S' | |
| 80 | Value: 0 | |
| 81 | SectionNumber: 1 | |
| 82 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 83 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 84 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 85 | SectionDefinition: | |
| 86 | Length: 328 | |
| 87 | NumberOfRelocations: 4 | |
| 88 | NumberOfLinenumbers: 0 | |
| 89 | CheckSum: 0 | |
| 90 | Number: 0 | |
| 91 | - Name: '.debug$T' | |
| 92 | Value: 0 | |
| 93 | SectionNumber: 2 | |
| 94 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 95 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 96 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 97 | SectionDefinition: | |
| 98 | Length: 564 | |
| 99 | NumberOfRelocations: 0 | |
| 100 | NumberOfLinenumbers: 0 | |
| 101 | CheckSum: 0 | |
| 102 | Number: 0 | |
| 103 | - Name: '.text$mn' | |
| 104 | Value: 0 | |
| 105 | SectionNumber: 3 | |
| 106 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 107 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 108 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 109 | SectionDefinition: | |
| 110 | Length: 3 | |
| 111 | NumberOfRelocations: 0 | |
| 112 | NumberOfLinenumbers: 0 | |
| 113 | CheckSum: 4021952397 | |
| 114 | Number: 0 | |
| 115 | - Name: main | |
| 116 | Value: 0 | |
| 117 | SectionNumber: 3 | |
| 118 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 119 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | |
| 120 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 121 | ... |
deps/lld/test/COFF/Inputs/precomp-a.obj created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/precomp-a.obj differ |
deps/lld/test/COFF/Inputs/precomp-b.obj created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/precomp-b.obj differ |
deps/lld/test/COFF/Inputs/precomp-invalid.obj created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/precomp-invalid.obj differ |
deps/lld/test/COFF/Inputs/precomp.obj created| Binary files /dev/null and b/deps/lld/test/COFF/Inputs/precomp.obj differ |
deps/lld/test/COFF/arm-thumb-branch-error.s deleted-10| ... | ... | @@ -1,10 +0,0 @@ |
| 1 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-windows-gnu %s -o %t | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-windows-gnu %S/Inputs/far-arm-thumb-abs.s -o %tfar | |
| 3 | // RUN: not lld-link -entry:_start -subsystem:console %t %tfar -out:%t2 2>&1 | FileCheck %s | |
| 4 | // REQUIRES: arm | |
| 5 | .syntax unified | |
| 6 | .globl _start | |
| 7 | _start: | |
| 8 | bl too_far1 | |
| 9 | ||
| 10 | // CHECK: relocation out of range |
deps/lld/test/COFF/arm-thumb-branch20-error.s+9-3| ... | ... | @@ -1,10 +1,16 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-windows-gnu %s -o %t.obj |
| 3 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-windows-gnu %S/Inputs/far-arm-thumb-abs20.s -o %t.far.obj | |
| 4 | // RUN: not lld-link -entry:_start -subsystem:console %t.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s | |
| 3 | // RUN: not lld-link -entry:_start -subsystem:console %t.obj -out:%t.exe 2>&1 | FileCheck %s | |
| 5 | 4 | .syntax unified |
| 6 | 5 | .globl _start |
| 7 | 6 | _start: |
| 8 | 7 | bne too_far20 |
| 8 | .space 0x100000 | |
| 9 | .section .text$a, "xr" | |
| 10 | too_far20: | |
| 11 | bx lr | |
| 9 | 12 | |
| 10 | // CHECK: relocation out of range | |
| 13 | // When trying to add a thunk at the end of the section, the thunk itself | |
| 14 | // will be too far away, so this won't converge. | |
| 15 | ||
| 16 | // CHECK: adding thunks hasn't converged |
deps/lld/test/COFF/arm-thumb-thunks-multipass.s created+70| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7-windows %s -o %t.obj | |
| 3 | // RUN: lld-link -entry:main -subsystem:console %t.obj -out:%t.exe -verbose 2>&1 | FileCheck -check-prefix=VERBOSE %s | |
| 4 | // RUN: llvm-objdump -d %t.exe -start-address=0x403000 -stop-address=0x403008 | FileCheck -check-prefix=FUNC01 %s | |
| 5 | // RUN: llvm-objdump -d %t.exe -start-address=0x404ffa -stop-address=0x405012 | FileCheck -check-prefix=FUNC01-THUNKS %s | |
| 6 | ||
| 7 | // VERBOSE: Added {{.*}} thunks with margin 204800 in 2 passes | |
| 8 | ||
| 9 | .syntax unified | |
| 10 | .globl main | |
| 11 | .text | |
| 12 | main: | |
| 13 | b func01 | |
| 14 | bx lr | |
| 15 | ||
| 16 | .irp i, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18 | |
| 17 | .section .text$\i\()a, "xr" | |
| 18 | .balign 8192 | |
| 19 | func\i: | |
| 20 | bne far_func\i | |
| 21 | bne func_within_margin\i | |
| 22 | // Originally, the first section is less than 8192 bytes large, and the | |
| 23 | // second one follows almost directly. After adding one thunk after | |
| 24 | // the first section, the second one will move forward by 8192 bytes | |
| 25 | // due to the alignment. | |
| 26 | .space 8192 - 8 - 4 | |
| 27 | ||
| 28 | .section .text$\i\()b, "xr" | |
| 29 | .balign 8192 | |
| 30 | align\i: | |
| 31 | nop | |
| 32 | .endr | |
| 33 | ||
| 34 | .section .text$999, "xr" | |
| 35 | tail: | |
| 36 | .space 0x100000 - 100*1024 - 18*8192*2 | |
| 37 | // Initially, these symbols are within range from all the sections above, | |
| 38 | // even when taking the initial margin into account. After adding thunks | |
| 39 | // to all the sections above, some of these are also out of range, forcing | |
| 40 | // running a second pass. | |
| 41 | .irp i, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18 | |
| 42 | func_within_margin\i: | |
| 43 | nop | |
| 44 | .endr | |
| 45 | .space 0x100000 | |
| 46 | ||
| 47 | // These are always out of range. | |
| 48 | .irp i, 01, 02, 03, 04, 05, 06, 07, 08, 09, 10, 11, 12, 13, 14, 15, 16, 17, 18 | |
| 49 | far_func\i: | |
| 50 | nop | |
| 51 | .endr | |
| 52 | bx lr | |
| 53 | ||
| 54 | // FUNC01: 403000: 41 f0 fc 87 bne.w #8184 <.text+0x3ffc> | |
| 55 | // FUNC01: 403004: 41 f0 ff 87 bne.w #8190 <.text+0x4006> | |
| 56 | ||
| 57 | // Check that we only have two thunks here, even if we created the first | |
| 58 | // thunk twice (once in the first pass, then thrown away and recreated | |
| 59 | // in the second pass). | |
| 60 | ||
| 61 | // FUNC01-THUNKS: 404ffa: 00 00 movs r0, r0 | |
| 62 | // The instruction above is padding from the .space | |
| 63 | // FUNC01-THUNKS: 404ffc: 47 f2 1e 0c movw r12, #28702 | |
| 64 | // FUNC01-THUNKS: 405000: c0 f2 20 0c movt r12, #32 | |
| 65 | // FUNC01-THUNKS: 405004: e7 44 add pc, r12 | |
| 66 | // FUNC01-THUNKS: 405006: 46 f6 f0 7c movw r12, #28656 | |
| 67 | // FUNC01-THUNKS: 40500a: c0 f2 10 0c movt r12, #16 | |
| 68 | // FUNC01-THUNKS: 40500e: e7 44 add pc, r12 | |
| 69 | // The instruction below is padding from the .balign | |
| 70 | // FUNC01-THUNKS: 405010: cc cc ldm r4!, {r2, r3, r6, r7} |
deps/lld/test/COFF/arm-thumb-thunks-pdb.s created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7-windows %s -o %t.obj | |
| 3 | // RUN: lld-link -entry:main -subsystem:console %t.obj -out:%t.exe -debug -pdb:%t.pdb -verbose 2>&1 | FileCheck %s --check-prefix=VERBOSE | |
| 4 | ||
| 5 | // VERBOSE: Added 1 thunks with margin {{.*}} in {{.*}} passes | |
| 6 | ||
| 7 | .syntax unified | |
| 8 | .globl main | |
| 9 | .globl func1 | |
| 10 | .text | |
| 11 | main: | |
| 12 | bne func1 | |
| 13 | bx lr | |
| 14 | .section .text$a, "xr" | |
| 15 | .space 0x100000 | |
| 16 | .section .text$b, "xr" | |
| 17 | func1: | |
| 18 | bx lr |
deps/lld/test/COFF/arm-thumb-thunks.s created+75| ... | ... | @@ -0,0 +1,75 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7-windows %s -o %t.obj | |
| 3 | // RUN: lld-link -entry:main -subsystem:console %t.obj -out:%t.exe -verbose 2>&1 | FileCheck -check-prefix=VERBOSE %s | |
| 4 | // RUN: llvm-objdump -d %t.exe -start-address=0x401000 -stop-address=0x401022 | FileCheck -check-prefix=MAIN %s | |
| 5 | // RUN: llvm-objdump -d %t.exe -start-address=0x501022 -stop-address=0x501032 | FileCheck -check-prefix=FUNC1 %s | |
| 6 | // RUN: llvm-objdump -d %t.exe -start-address=0x601032 | FileCheck -check-prefix=FUNC2 %s | |
| 7 | ||
| 8 | // VERBOSE: Added 3 thunks with margin {{.*}} in 1 passes | |
| 9 | ||
| 10 | .syntax unified | |
| 11 | .globl main | |
| 12 | .globl func1 | |
| 13 | .text | |
| 14 | main: | |
| 15 | bne func1 | |
| 16 | bne func2 | |
| 17 | // This should reuse the same thunk as func1 above | |
| 18 | bne func1_alias | |
| 19 | bx lr | |
| 20 | .section .text$a, "xr" | |
| 21 | .space 0x100000 | |
| 22 | .section .text$b, "xr" | |
| 23 | func1: | |
| 24 | func1_alias: | |
| 25 | // This shouldn't reuse the func2 thunk from above, since it is out | |
| 26 | // of range. | |
| 27 | bne func2 | |
| 28 | bx lr | |
| 29 | .section .text$c, "xr" | |
| 30 | .space 0x100000 | |
| 31 | .section .text$d, "xr" | |
| 32 | func2: | |
| 33 | // Test using string tail merging. This is irrelevant to the thunking itself, | |
| 34 | // but running multiple passes of assignAddresses() calls finalizeAddresses() | |
| 35 | // multiple times; check that MergeChunk handles this correctly. | |
| 36 | movw r0, :lower16:"??_C@string1" | |
| 37 | movt r0, :upper16:"??_C@string1" | |
| 38 | movw r1, :lower16:"??_C@string2" | |
| 39 | movt r1, :upper16:"??_C@string2" | |
| 40 | bx lr | |
| 41 | ||
| 42 | .section .rdata,"dr",discard,"??_C@string1" | |
| 43 | .globl "??_C@string1" | |
| 44 | "??_C@string1": | |
| 45 | .asciz "foobar" | |
| 46 | .section .rdata,"dr",discard,"??_C@string2" | |
| 47 | .globl "??_C@string2" | |
| 48 | "??_C@string2": | |
| 49 | .asciz "bar" | |
| 50 | ||
| 51 | // MAIN: 401000: 40 f0 05 80 bne.w #10 <.text+0xe> | |
| 52 | // MAIN: 401004: 40 f0 08 80 bne.w #16 <.text+0x18> | |
| 53 | // MAIN: 401008: 40 f0 01 80 bne.w #2 <.text+0xe> | |
| 54 | // MAIN: 40100c: 70 47 bx lr | |
| 55 | // func1 thunk | |
| 56 | // MAIN: 40100e: 40 f2 08 0c movw r12, #8 | |
| 57 | // MAIN: 401012: c0 f2 10 0c movt r12, #16 | |
| 58 | // MAIN: 401016: e7 44 add pc, r12 | |
| 59 | // func2 thunk | |
| 60 | // MAIN: 401018: 40 f2 0e 0c movw r12, #14 | |
| 61 | // MAIN: 40101c: c0 f2 20 0c movt r12, #32 | |
| 62 | // MAIN: 401020: e7 44 add pc, r12 | |
| 63 | ||
| 64 | // FUNC1: 501022: 40 f0 01 80 bne.w #2 <.text+0x100028> | |
| 65 | // FUNC1: 501026: 70 47 bx lr | |
| 66 | // func2 thunk | |
| 67 | // FUNC1: 501028: 4f f6 fe 7c movw r12, #65534 | |
| 68 | // FUNC1: 50102c: c0 f2 0f 0c movt r12, #15 | |
| 69 | // FUNC1: 501030: e7 44 add pc, r12 | |
| 70 | ||
| 71 | // FUNC2: 601032: 42 f2 00 00 movw r0, #8192 | |
| 72 | // FUNC2: 601036: c0 f2 60 00 movt r0, #96 | |
| 73 | // FUNC2: 60103a: 42 f2 03 01 movw r1, #8195 | |
| 74 | // FUNC2: 60103e: c0 f2 60 01 movt r1, #96 | |
| 75 | // FUNC2: 601042: 70 47 bx lr |
deps/lld/test/COFF/arm64-branch-range.test deleted-16| ... | ... | @@ -1,16 +0,0 @@ |
| 1 | // REQUIRES: aarch64 | |
| 2 | ||
| 3 | // RUN: echo -e '.globl _start\n _start:\n bl too_far26\n' > %t.main26.s | |
| 4 | // RUN: echo -e '.globl _start\n _start:\n b.ne too_far19\n' > %t.main19.s | |
| 5 | // RUN: echo -e '.globl _start\n _start:\n tbz x0, #0, too_far14\n' > %t.main14.s | |
| 6 | ||
| 7 | // RUN: llvm-mc -filetype=obj -triple=aarch64-windows %t.main26.s -o %t.main26.obj | |
| 8 | // RUN: llvm-mc -filetype=obj -triple=aarch64-windows %t.main19.s -o %t.main19.obj | |
| 9 | // RUN: llvm-mc -filetype=obj -triple=aarch64-windows %t.main14.s -o %t.main14.obj | |
| 10 | // RUN: llvm-mc -filetype=obj -triple=aarch64-windows %S/Inputs/far-arm64-abs.s -o %t.far.obj | |
| 11 | ||
| 12 | // RUN: not lld-link -base:0x10000 -entry:_start -subsystem:console %t.main26.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s | |
| 13 | // RUN: not lld-link -base:0x10000 -entry:_start -subsystem:console %t.main19.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s | |
| 14 | // RUN: not lld-link -base:0x10000 -entry:_start -subsystem:console %t.main14.obj %t.far.obj -out:%t.exe 2>&1 | FileCheck %s | |
| 15 | ||
| 16 | // CHECK: relocation out of range |
deps/lld/test/COFF/arm64-delayimport.yaml created+91| ... | ... | @@ -0,0 +1,91 @@ |
| 1 | # REQUIRES: aarch64 | |
| 2 | ||
| 3 | # RUN: yaml2obj < %s > %t.obj | |
| 4 | # RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t.obj %p/Inputs/library-arm64.lib /alternatename:__delayLoadHelper2=main /delayload:library.dll | |
| 5 | # RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix DISASM | |
| 6 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s -check-prefix IMPORTS | |
| 7 | ||
| 8 | # DISASM: 140001014: 11 00 00 d0 adrp x17, #8192 | |
| 9 | # DISASM: 140001018: 31 22 00 91 add x17, x17, #8 | |
| 10 | # DISASM: 14000101c: fd 7b b3 a9 stp x29, x30, [sp, #-208]! | |
| 11 | # DISASM: 140001020: fd 03 00 91 mov x29, sp | |
| 12 | # DISASM: 140001024: e0 07 01 a9 stp x0, x1, [sp, #16] | |
| 13 | # DISASM: 140001028: e2 0f 02 a9 stp x2, x3, [sp, #32] | |
| 14 | # DISASM: 14000102c: e4 17 03 a9 stp x4, x5, [sp, #48] | |
| 15 | # DISASM: 140001030: e6 1f 04 a9 stp x6, x7, [sp, #64] | |
| 16 | # DISASM: 140001034: e0 87 02 ad stp q0, q1, [sp, #80] | |
| 17 | # DISASM: 140001038: e2 8f 03 ad stp q2, q3, [sp, #112] | |
| 18 | # DISASM: 14000103c: e4 97 04 ad stp q4, q5, [sp, #144] | |
| 19 | # DISASM: 140001040: e6 9f 05 ad stp q6, q7, [sp, #176] | |
| 20 | # DISASM: 140001044: e1 03 11 aa mov x1, x17 | |
| 21 | # DISASM: 140001048: 00 00 00 b0 adrp x0, #4096 | |
| 22 | # DISASM: 14000104c: 00 00 00 91 add x0, x0, #0 | |
| 23 | # DISASM: 140001050: ec ff ff 97 bl #-80 <.text> | |
| 24 | # DISASM: 140001054: f0 03 00 aa mov x16, x0 | |
| 25 | # DISASM: 140001058: e6 9f 45 ad ldp q6, q7, [sp, #176] | |
| 26 | # DISASM: 14000105c: e4 97 44 ad ldp q4, q5, [sp, #144] | |
| 27 | # DISASM: 140001060: e2 8f 43 ad ldp q2, q3, [sp, #112] | |
| 28 | # DISASM: 140001064: e0 87 42 ad ldp q0, q1, [sp, #80] | |
| 29 | # DISASM: 140001068: e6 1f 44 a9 ldp x6, x7, [sp, #64] | |
| 30 | # DISASM: 14000106c: e4 17 43 a9 ldp x4, x5, [sp, #48] | |
| 31 | # DISASM: 140001070: e2 0f 42 a9 ldp x2, x3, [sp, #32] | |
| 32 | # DISASM: 140001074: e0 07 41 a9 ldp x0, x1, [sp, #16] | |
| 33 | # DISASM: 140001078: fd 7b cd a8 ldp x29, x30, [sp], #208 | |
| 34 | # DISASM: 14000107c: 00 02 1f d6 br x16 | |
| 35 | ||
| 36 | # IMPORTS: Format: COFF-ARM64 | |
| 37 | # IMPORTS: Arch: aarch64 | |
| 38 | # IMPORTS: AddressSize: 64bit | |
| 39 | # IMPORTS: DelayImport { | |
| 40 | # IMPORTS: Name: library.dll | |
| 41 | # IMPORTS: Attributes: 0x1 | |
| 42 | # IMPORTS: ModuleHandle: 0x3000 | |
| 43 | # IMPORTS: ImportAddressTable: 0x3008 | |
| 44 | # IMPORTS: ImportNameTable: 0x2040 | |
| 45 | # IMPORTS: BoundDelayImportTable: 0x0 | |
| 46 | # IMPORTS: UnloadDelayImportTable: 0x0 | |
| 47 | # IMPORTS: Import { | |
| 48 | # IMPORTS: Symbol: function (0) | |
| 49 | # IMPORTS: Address: 0x140001014 | |
| 50 | # IMPORTS: } | |
| 51 | # IMPORTS: } | |
| 52 | ||
| 53 | --- !COFF | |
| 54 | header: | |
| 55 | Machine: IMAGE_FILE_MACHINE_ARM64 | |
| 56 | Characteristics: [ ] | |
| 57 | sections: | |
| 58 | - Name: .text | |
| 59 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 60 | Alignment: 4 | |
| 61 | SectionData: 00000094C0035FD6 | |
| 62 | Relocations: | |
| 63 | - VirtualAddress: 0 | |
| 64 | SymbolName: function | |
| 65 | Type: IMAGE_REL_ARM64_BRANCH26 | |
| 66 | symbols: | |
| 67 | - Name: .text | |
| 68 | Value: 0 | |
| 69 | SectionNumber: 1 | |
| 70 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 71 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 72 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 73 | SectionDefinition: | |
| 74 | Length: 8 | |
| 75 | NumberOfRelocations: 1 | |
| 76 | NumberOfLinenumbers: 0 | |
| 77 | CheckSum: 0 | |
| 78 | Number: 1 | |
| 79 | - Name: main | |
| 80 | Value: 0 | |
| 81 | SectionNumber: 1 | |
| 82 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 83 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 84 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 85 | - Name: function | |
| 86 | Value: 0 | |
| 87 | SectionNumber: 0 | |
| 88 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 89 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 90 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 91 | ... |
deps/lld/test/COFF/arm64-localimport-align.s created+24| ... | ... | @@ -0,0 +1,24 @@ |
| 1 | // REQUIRES: aarch64 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-windows %s -o %t.obj | |
| 3 | // RUN: lld-link -entry:main -subsystem:console %t.obj -out:%t.exe | |
| 4 | // Don't check the output, just make sure it links fine and doesn't | |
| 5 | // error out due to a misaligned load. | |
| 6 | .text | |
| 7 | .globl main | |
| 8 | .globl myfunc | |
| 9 | main: | |
| 10 | adrp x8, __imp_myfunc | |
| 11 | ldr x0, [x8, :lo12:__imp_myfunc] | |
| 12 | br x0 | |
| 13 | ret | |
| 14 | myfunc: | |
| 15 | ret | |
| 16 | ||
| 17 | .section .rdata, "dr" | |
| 18 | // Start the .rdata section with a 4 byte chunk, to expose the alignment | |
| 19 | // of the next chunk in the section. | |
| 20 | mydata: | |
| 21 | .byte 42 | |
| 22 | // The synthesized LocalImportChunk gets stored here in the .rdata | |
| 23 | // section, but needs to get proper 8 byte alignment since it is a | |
| 24 | // pointer, just like regular LookupChunks in the IAT. |
deps/lld/test/COFF/arm64-relocs-imports.test+9-9| ... | ... | @@ -34,14 +34,14 @@ |
| 34 | 34 | # BEFORE: 64: e0 03 1f 2a mov w0, wzr |
| 35 | 35 | # BEFORE: 68: fe 07 41 f8 ldr x30, [sp], #16 |
| 36 | 36 | # BEFORE: 6c: c0 03 5f d6 ret |
| 37 | # BEFORE: 70: 08 00 00 00 <unknown> | |
| 38 | # BEFORE: 74: 00 00 00 00 <unknown> | |
| 39 | # BEFORE: 78: 01 00 00 00 <unknown> | |
| 40 | # BEFORE: 7c: 01 00 00 00 <unknown> | |
| 37 | # BEFORE: 70: 08 00 00 00 udf #8 | |
| 38 | # BEFORE: 74: 00 00 00 00 udf #0 | |
| 39 | # BEFORE: 78: 01 00 00 00 udf #1 | |
| 40 | # BEFORE: 7c: 01 00 00 00 udf #1 | |
| 41 | 41 | # BEFORE: 80: 00 00 00 91 add x0, x0, #0 |
| 42 | 42 | # BEFORE: 84: 00 00 40 91 add x0, x0, #0, lsl #12 |
| 43 | 43 | # BEFORE: 88: 00 00 40 f9 ldr x0, [x0] |
| 44 | # BEFORE: 8c: 01 00 00 00 <unknown> | |
| 44 | # BEFORE: 8c: 01 00 00 00 udf #1 | |
| 45 | 45 | # BEFORE: 90: 20 1a 09 30 adr x0, #74565 |
| 46 | 46 | # BEFORE: 94: 01 00 00 54 b.ne #0 |
| 47 | 47 | # BEFORE: 98: 00 00 00 36 tbz w0, #0, #0 |
| ... | ... | @@ -76,13 +76,13 @@ |
| 76 | 76 | # AFTER: 140001068: fe 07 41 f8 ldr x30, [sp], #16 |
| 77 | 77 | # AFTER: 14000106c: c0 03 5f d6 ret |
| 78 | 78 | # AFTER: 140001070: 10 20 00 40 <unknown> |
| 79 | # AFTER: 140001074: 01 00 00 00 <unknown> | |
| 80 | # AFTER: 140001078: 09 20 00 00 <unknown> | |
| 81 | # AFTER: 14000107c: 09 00 00 00 <unknown> | |
| 79 | # AFTER: 140001074: 01 00 00 00 udf #1 | |
| 80 | # AFTER: 140001078: 09 20 00 00 udf #8201 | |
| 81 | # AFTER: 14000107c: 09 00 00 00 udf #9 | |
| 82 | 82 | # AFTER: 140001080: 00 20 0e 91 add x0, x0, #904 |
| 83 | 83 | # AFTER: 140001084: 00 04 40 91 add x0, x0, #1, lsl #12 |
| 84 | 84 | # AFTER: 140001088: 00 c4 41 f9 ldr x0, [x0, #904] |
| 85 | # AFTER: 14000108c: 03 00 00 00 <unknown> | |
| 85 | # AFTER: 14000108c: 03 00 00 00 udf #3 | |
| 86 | 86 | # AFTER: 140001090: e0 95 09 30 adr x0, #78525 |
| 87 | 87 | # AFTER: 140001094: 41 00 00 54 b.ne #8 |
| 88 | 88 | # AFTER: 140001098: 20 00 00 36 tbz w0, #0, #4 |
deps/lld/test/COFF/arm64-thunks.s created+27| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | // REQUIRES: aarch64 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-windows %s -o %t.obj | |
| 3 | // RUN: lld-link -entry:main -subsystem:console %t.obj -out:%t.exe -verbose 2>&1 | FileCheck -check-prefix=VERBOSE %s | |
| 4 | // RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s | |
| 5 | ||
| 6 | // VERBOSE: Added 1 thunks with margin {{.*}} in 1 passes | |
| 7 | ||
| 8 | .globl main | |
| 9 | .globl func1 | |
| 10 | .text | |
| 11 | main: | |
| 12 | tbz w0, #0, func1 | |
| 13 | ret | |
| 14 | .section .text$a, "xr" | |
| 15 | .space 0x8000 | |
| 16 | .section .text$b, "xr" | |
| 17 | func1: | |
| 18 | ret | |
| 19 | ||
| 20 | // DISASM: 0000000140001000 .text: | |
| 21 | // DISASM: 140001000: 40 00 00 36 tbz w0, #0, #8 <.text+0x8> | |
| 22 | // DISASM: 140001004: c0 03 5f d6 ret | |
| 23 | // DISASM: 140001008: 50 00 00 90 adrp x16, #32768 | |
| 24 | // DISASM: 14000100c: 10 52 00 91 add x16, x16, #20 | |
| 25 | // DISASM: 140001010: 00 02 1f d6 br x16 | |
| 26 | ||
| 27 | // DISASM: 140009014: c0 03 5f d6 ret |
deps/lld/test/COFF/associative-comdat-mingw.s+3-2| ... | ... | @@ -11,10 +11,11 @@ |
| 11 | 11 | # CHECK: Number: 2 |
| 12 | 12 | # CHECK-LABEL: Name: .rdata (2E 72 64 61 74 61 00 00) |
| 13 | 13 | # This is the critical check to show that only *one* definition of |
| 14 | # .xdata$foo was retained. This *must* be 4. | |
| 14 | # .xdata$foo was retained. This *must* be 0x24 (0x4 for the .xdata | |
| 15 | # section and 0x20 for the .ctors/.dtors headers/ends). | |
| 15 | 16 | # Make sure that no other .xdata sections get included, which would |
| 16 | 17 | # increase the size here. |
| 17 | # CHECK-NEXT: VirtualSize: 0x4 | |
| 18 | # CHECK-NEXT: VirtualSize: 0x24 | |
| 18 | 19 | |
| 19 | 20 | .text |
| 20 | 21 | .def main; |
deps/lld/test/COFF/autoimport-arm-code.s created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | # REQUIRES: arm | |
| 2 | ||
| 3 | # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.thumb\n.text\nDllMainCRTStartup:\nbx lr\n.data\nvariable:\n.long 42" > %t-lib.s | |
| 4 | # RUN: llvm-mc -triple=armv7-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj | |
| 5 | # RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib | |
| 6 | ||
| 7 | # RUN: llvm-mc -triple=armv7-windows-gnu %s -filetype=obj -o %t.obj | |
| 8 | # RUN: not lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib 2>&1 | FileCheck %s | |
| 9 | ||
| 10 | # CHECK: error: unable to automatically import from variable with relocation type IMAGE_REL_ARM_MOV32T | |
| 11 | ||
| 12 | .global main | |
| 13 | .text | |
| 14 | .thumb | |
| 15 | main: | |
| 16 | movw r0, :lower16:variable | |
| 17 | movt r0, :upper16:variable | |
| 18 | ldr r0, [r0] | |
| 19 | bx lr |
deps/lld/test/COFF/autoimport-arm-data.s created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | # REQUIRES: arm | |
| 2 | ||
| 3 | # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.thumb\n.text\nDllMainCRTStartup:\nbx lr\n.data\nvariable:\n.long 42" > %t-lib.s | |
| 4 | # RUN: llvm-mc -triple=armv7-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj | |
| 5 | # RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib | |
| 6 | ||
| 7 | # RUN: llvm-mc -triple=armv7-windows-gnu %s -filetype=obj -o %t.obj | |
| 8 | # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose | |
| 9 | ||
| 10 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s | |
| 11 | # RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s | |
| 12 | ||
| 13 | # IMPORTS: Import { | |
| 14 | # IMPORTS-NEXT: Name: autoimport-arm-data.s.tmp-lib.dll | |
| 15 | # IMPORTS-NEXT: ImportLookupTableRVA: 0x2050 | |
| 16 | # IMPORTS-NEXT: ImportAddressTableRVA: 0x2058 | |
| 17 | # IMPORTS-NEXT: Symbol: variable (0) | |
| 18 | # IMPORTS-NEXT: } | |
| 19 | ||
| 20 | # Runtime pseudo reloc list header consisting of 0x0, 0x0, 0x1. | |
| 21 | # First runtime pseudo reloc, with import from 0x2058, | |
| 22 | # applied at 0x3000, with a size of 32 bits. | |
| 23 | # CONTENTS: Contents of section .rdata: | |
| 24 | # CONTENTS: 402000 00000000 00000000 01000000 58200000 | |
| 25 | # CONTENTS: 402010 00300000 20000000 | |
| 26 | # ptr: pointing at the IAT RVA at 0x2058 | |
| 27 | # relocs: pointing at the runtime pseudo reloc list at | |
| 28 | # 0x2000 - 0x2018. | |
| 29 | # CONTENTS: Contents of section .data: | |
| 30 | # CONTENTS: 403000 58204000 00204000 18204000 | |
| 31 | ||
| 32 | .global main | |
| 33 | .text | |
| 34 | .thumb | |
| 35 | main: | |
| 36 | bx lr | |
| 37 | .data | |
| 38 | ptr: | |
| 39 | .long variable | |
| 40 | relocs: | |
| 41 | .long __RUNTIME_PSEUDO_RELOC_LIST__ | |
| 42 | .long __RUNTIME_PSEUDO_RELOC_LIST_END__ |
deps/lld/test/COFF/autoimport-arm64-code.s created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | # REQUIRES: aarch64 | |
| 2 | ||
| 3 | # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s | |
| 4 | # RUN: llvm-mc -triple=aarch64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj | |
| 5 | # RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib | |
| 6 | ||
| 7 | # RUN: llvm-mc -triple=aarch64-windows-gnu %s -filetype=obj -o %t.obj | |
| 8 | # RUN: not lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib 2>&1 | FileCheck %s | |
| 9 | ||
| 10 | # CHECK: error: unable to automatically import from variable with relocation type IMAGE_REL_ARM64_PAGEBASE_REL21 | |
| 11 | # CHECK: error: unable to automatically import from variable with relocation type IMAGE_REL_ARM64_PAGEOFFSET_12L | |
| 12 | ||
| 13 | .global main | |
| 14 | .text | |
| 15 | main: | |
| 16 | adrp x0, variable | |
| 17 | ldr w0, [x0, :lo12:variable] | |
| 18 | ret |
deps/lld/test/COFF/autoimport-arm64-data.s created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | # REQUIRES: aarch64 | |
| 2 | ||
| 3 | # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s | |
| 4 | # RUN: llvm-mc -triple=aarch64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj | |
| 5 | # RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib | |
| 6 | ||
| 7 | # RUN: llvm-mc -triple=aarch64-windows-gnu %s -filetype=obj -o %t.obj | |
| 8 | # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose | |
| 9 | ||
| 10 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s | |
| 11 | # RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s | |
| 12 | ||
| 13 | # IMPORTS: Import { | |
| 14 | # IMPORTS-NEXT: Name: autoimport-arm64-data.s.tmp-lib.dll | |
| 15 | # IMPORTS-NEXT: ImportLookupTableRVA: 0x2060 | |
| 16 | # IMPORTS-NEXT: ImportAddressTableRVA: 0x2070 | |
| 17 | # IMPORTS-NEXT: Symbol: variable (0) | |
| 18 | # IMPORTS-NEXT: } | |
| 19 | ||
| 20 | # Runtime pseudo reloc list header consisting of 0x0, 0x0, 0x1. | |
| 21 | # First runtime pseudo reloc, with import from 0x2070, | |
| 22 | # applied at 0x3000, with a size of 32 bits. | |
| 23 | # CONTENTS: Contents of section .rdata: | |
| 24 | # CONTENTS: 140002000 00000000 00000000 01000000 70200000 | |
| 25 | # CONTENTS: 140002010 00300000 40000000 | |
| 26 | # ptr: pointing at the IAT RVA at 0x2070 | |
| 27 | # relocs: pointing at the runtime pseudo reloc list at | |
| 28 | # 0x2000 - 0x2018. | |
| 29 | # CONTENTS: Contents of section .data: | |
| 30 | # CONTENTS: 140003000 70200040 01000000 00200040 01000000 | |
| 31 | # CONTENTS: 140003010 18200040 01000000 | |
| 32 | ||
| 33 | .global main | |
| 34 | .text | |
| 35 | main: | |
| 36 | ret | |
| 37 | .data | |
| 38 | ptr: | |
| 39 | .quad variable | |
| 40 | relocs: | |
| 41 | .quad __RUNTIME_PSEUDO_RELOC_LIST__ | |
| 42 | .quad __RUNTIME_PSEUDO_RELOC_LIST_END__ |
deps/lld/test/COFF/autoimport-gnu-implib.s created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-head.s -filetype=obj -o %t-dabcdh.o | |
| 4 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-data.s -filetype=obj -o %t-dabcds00000.o | |
| 5 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-tail.s -filetype=obj -o %t-dabcdt.o | |
| 6 | # RUN: rm -f %t-implib.a | |
| 7 | # RUN: llvm-ar rcs %t-implib.a %t-dabcdh.o %t-dabcds00000.o %t-dabcdt.o | |
| 8 | ||
| 9 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj | |
| 10 | # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-implib.a -verbose | |
| 11 | ||
| 12 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s | |
| 13 | ||
| 14 | # IMPORTS: Import { | |
| 15 | # IMPORTS-NEXT: Name: foo.dll | |
| 16 | # IMPORTS-NEXT: ImportLookupTableRVA: | |
| 17 | # IMPORTS-NEXT: ImportAddressTableRVA: | |
| 18 | # IMPORTS-NEXT: Symbol: data (0) | |
| 19 | # IMPORTS-NEXT: } | |
| 20 | ||
| 21 | .global main | |
| 22 | .text | |
| 23 | main: | |
| 24 | movl data(%rip), %eax | |
| 25 | ret | |
| 26 | .data |
deps/lld/test/COFF/autoimport-list-ptrs.s created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj | |
| 4 | # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj -verbose | |
| 5 | ||
| 6 | # RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s | |
| 7 | ||
| 8 | # Even if we didn't actually write any pseudo relocations, | |
| 9 | # check that the synthetic pointers still are set to a non-null value | |
| 10 | # CONTENTS: Contents of section .data: | |
| 11 | # CONTENTS: 140003000 00200040 01000000 00200040 01000000 | |
| 12 | ||
| 13 | .global main | |
| 14 | .text | |
| 15 | main: | |
| 16 | retq | |
| 17 | .data | |
| 18 | relocs: | |
| 19 | .quad __RUNTIME_PSEUDO_RELOC_LIST__ | |
| 20 | .quad __RUNTIME_PSEUDO_RELOC_LIST_END__ |
deps/lld/test/COFF/autoimport-refptr.s created+65| ... | ... | @@ -0,0 +1,65 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s | |
| 4 | # RUN: llvm-mc -triple=x86_64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj | |
| 5 | # RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib | |
| 6 | ||
| 7 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj | |
| 8 | # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose | |
| 9 | ||
| 10 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s | |
| 11 | # RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s | |
| 12 | # RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s | |
| 13 | ||
| 14 | # IMPORTS: Import { | |
| 15 | # IMPORTS-NEXT: Name: autoimport-refptr.s.tmp-lib.dll | |
| 16 | # IMPORTS-NEXT: ImportLookupTableRVA: 0x2050 | |
| 17 | # IMPORTS-NEXT: ImportAddressTableRVA: 0x2060 | |
| 18 | # IMPORTS-NEXT: Symbol: variable (0) | |
| 19 | # IMPORTS-NEXT: } | |
| 20 | ||
| 21 | # DISASM: Disassembly of section .text: | |
| 22 | # DISASM: .text: | |
| 23 | # Relative offset at 0x1002 pointing at the IAT at 0x2060 | |
| 24 | # DISASM: 140001000: 48 8b 05 59 10 00 00 movq 4185(%rip), %rax | |
| 25 | # DISASM: 140001007: 8b 00 movl (%rax), %eax | |
| 26 | # Relative offset at 0x100b pointing at the .refptr.localvar stub at | |
| 27 | # 0x2000 | |
| 28 | # DISASM: 140001009: 48 8b 0d f0 0f 00 00 movq 4080(%rip), %rcx | |
| 29 | # DISASM: 140001010: 03 01 addl (%rcx), %eax | |
| 30 | # DISASM: 140001012: c3 retq | |
| 31 | ||
| 32 | # relocs: pointing at an empty list of runtime pseudo relocs. | |
| 33 | # localvar: 42 | |
| 34 | # CONTENTS: Contents of section .data: | |
| 35 | # CONTENTS: 140003000 08200040 01000000 08200040 01000000 | |
| 36 | # CONTENTS: 140003010 2a000000 | |
| 37 | ||
| 38 | .global main | |
| 39 | .global localvar | |
| 40 | .text | |
| 41 | main: | |
| 42 | movq .refptr.variable(%rip), %rax | |
| 43 | movl (%rax), %eax | |
| 44 | movq .refptr.localvar(%rip), %rcx | |
| 45 | addl (%rcx), %eax | |
| 46 | ret | |
| 47 | ||
| 48 | .data | |
| 49 | relocs: | |
| 50 | .quad __RUNTIME_PSEUDO_RELOC_LIST__ | |
| 51 | .quad __RUNTIME_PSEUDO_RELOC_LIST_END__ | |
| 52 | localvar: | |
| 53 | .int 42 | |
| 54 | ||
| 55 | # Normally the compiler wouldn't emit a stub for a variable that is | |
| 56 | # emitted in the same translation unit. | |
| 57 | .section .rdata$.refptr.localvar,"dr",discard,.refptr.localvar | |
| 58 | .global .refptr.localvar | |
| 59 | .refptr.localvar: | |
| 60 | .quad localvar | |
| 61 | ||
| 62 | .section .rdata$.refptr.variable,"dr",discard,.refptr.variable | |
| 63 | .global .refptr.variable | |
| 64 | .refptr.variable: | |
| 65 | .quad variable |
deps/lld/test/COFF/autoimport-x86.s created+53| ... | ... | @@ -0,0 +1,53 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo -e ".global variable\n.global DllMainCRTStartup\n.text\nDllMainCRTStartup:\nret\n.data\nvariable:\n.long 42" > %t-lib.s | |
| 4 | # RUN: llvm-mc -triple=x86_64-windows-gnu %t-lib.s -filetype=obj -o %t-lib.obj | |
| 5 | # RUN: lld-link -out:%t-lib.dll -dll -entry:DllMainCRTStartup %t-lib.obj -lldmingw -implib:%t-lib.lib | |
| 6 | ||
| 7 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj | |
| 8 | # RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose | |
| 9 | ||
| 10 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s | |
| 11 | # RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s | |
| 12 | # RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s | |
| 13 | ||
| 14 | # IMPORTS: Import { | |
| 15 | # IMPORTS-NEXT: Name: autoimport-x86.s.tmp-lib.dll | |
| 16 | # IMPORTS-NEXT: ImportLookupTableRVA: 0x2070 | |
| 17 | # IMPORTS-NEXT: ImportAddressTableRVA: 0x2080 | |
| 18 | # IMPORTS-NEXT: Symbol: variable (0) | |
| 19 | # IMPORTS-NEXT: } | |
| 20 | ||
| 21 | # DISASM: Disassembly of section .text: | |
| 22 | # DISASM: .text: | |
| 23 | # Relative offset at 0x1002 pointing at the IAT at 0x2080. | |
| 24 | # DISASM: 140001000: 8b 05 7a 10 00 00 movl 4218(%rip), %eax | |
| 25 | # DISASM: 140001006: c3 retq | |
| 26 | ||
| 27 | # Runtime pseudo reloc list header consisting of 0x0, 0x0, 0x1. | |
| 28 | # First runtime pseudo reloc, with import from 0x2080, | |
| 29 | # applied at 0x1002, with a size of 32 bits. | |
| 30 | # Second runtime pseudo reloc, with import from 0x2080, | |
| 31 | # applied at 0x3000, with a size of 64 bits. | |
| 32 | # CONTENTS: Contents of section .rdata: | |
| 33 | # CONTENTS: 140002000 00000000 00000000 01000000 80200000 | |
| 34 | # CONTENTS: 140002010 02100000 20000000 80200000 00300000 | |
| 35 | # CONTENTS: 140002020 40000000 | |
| 36 | # ptr: pointing at the IAT RVA at 0x2080 | |
| 37 | # relocs: pointing at the runtime pseudo reloc list at | |
| 38 | # 0x2000 - 0x2024. | |
| 39 | # CONTENTS: Contents of section .data: | |
| 40 | # CONTENTS: 140003000 80200040 01000000 00200040 01000000 | |
| 41 | # CONTENTS: 140003010 24200040 01000000 | |
| 42 | ||
| 43 | .global main | |
| 44 | .text | |
| 45 | main: | |
| 46 | movl variable(%rip), %eax | |
| 47 | ret | |
| 48 | .data | |
| 49 | ptr: | |
| 50 | .quad variable | |
| 51 | relocs: | |
| 52 | .quad __RUNTIME_PSEUDO_RELOC_LIST__ | |
| 53 | .quad __RUNTIME_PSEUDO_RELOC_LIST_END__ |
deps/lld/test/COFF/baserel.test+3-3| ... | ... | @@ -47,9 +47,9 @@ |
| 47 | 47 | # RUN: llvm-readobj -file-headers -sections %t.exe | FileCheck %s \ |
| 48 | 48 | # RUN: --check-prefix=BASEREL-HEADER |
| 49 | 49 | # |
| 50 | # RN: lld-link /out:%t.exe /entry:main /fixed %t.obj %p/Inputs/std64.lib | |
| 51 | # RN: llvm-readobj -file-headers %t.exe | FileCheck %s \ | |
| 52 | # RN: --check-prefix=NOBASEREL-HEADER | |
| 50 | # RUN: lld-link /out:%t.exe /entry:main /fixed %t.obj %p/Inputs/std64.lib | |
| 51 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck %s \ | |
| 52 | # RUN: --check-prefix=NOBASEREL-HEADER | |
| 53 | 53 | # |
| 54 | 54 | # BASEREL-HEADER-NOT: IMAGE_FILE_RELOCS_STRIPPED |
| 55 | 55 | # |
deps/lld/test/COFF/broken-arm-reloc.yaml created+92| ... | ... | @@ -0,0 +1,92 @@ |
| 1 | # REQUIRES: arm | |
| 2 | ||
| 3 | # .global main | |
| 4 | # .global variable | |
| 5 | # .text | |
| 6 | # .thumb | |
| 7 | #main: | |
| 8 | # movw r0, :lower16:variable | |
| 9 | # nop | |
| 10 | # movt r0, :upper16:variable | |
| 11 | # ldr r0, [r0] | |
| 12 | # bx lr | |
| 13 | # .data | |
| 14 | #variable: | |
| 15 | # .long 42 | |
| 16 | ||
| 17 | # RUN: yaml2obj %s > %t.obj | |
| 18 | # RUN: not lld-link -out:%t.exe -entry:main %t.obj 2>&1 | FileCheck %s | |
| 19 | ||
| 20 | # CHECK: error: unexpected instruction in MOVT instruction in MOV32T relocation | |
| 21 | ||
| 22 | --- !COFF | |
| 23 | header: | |
| 24 | Machine: IMAGE_FILE_MACHINE_ARMNT | |
| 25 | Characteristics: [ ] | |
| 26 | sections: | |
| 27 | - Name: .text | |
| 28 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 29 | Alignment: 4 | |
| 30 | SectionData: 40F2000000BFC0F2000000687047 | |
| 31 | Relocations: | |
| 32 | - VirtualAddress: 0 | |
| 33 | SymbolName: variable | |
| 34 | Type: IMAGE_REL_ARM_MOV32T | |
| 35 | - Name: .data | |
| 36 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | |
| 37 | Alignment: 4 | |
| 38 | SectionData: 2A000000 | |
| 39 | - Name: .bss | |
| 40 | Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | |
| 41 | Alignment: 4 | |
| 42 | SectionData: '' | |
| 43 | symbols: | |
| 44 | - Name: .text | |
| 45 | Value: 0 | |
| 46 | SectionNumber: 1 | |
| 47 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 48 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 49 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 50 | SectionDefinition: | |
| 51 | Length: 14 | |
| 52 | NumberOfRelocations: 1 | |
| 53 | NumberOfLinenumbers: 0 | |
| 54 | CheckSum: 2762100735 | |
| 55 | Number: 1 | |
| 56 | - Name: .data | |
| 57 | Value: 0 | |
| 58 | SectionNumber: 2 | |
| 59 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 60 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 61 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 62 | SectionDefinition: | |
| 63 | Length: 4 | |
| 64 | NumberOfRelocations: 0 | |
| 65 | NumberOfLinenumbers: 0 | |
| 66 | CheckSum: 3482275674 | |
| 67 | Number: 2 | |
| 68 | - Name: .bss | |
| 69 | Value: 0 | |
| 70 | SectionNumber: 3 | |
| 71 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 72 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 73 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 74 | SectionDefinition: | |
| 75 | Length: 0 | |
| 76 | NumberOfRelocations: 0 | |
| 77 | NumberOfLinenumbers: 0 | |
| 78 | CheckSum: 0 | |
| 79 | Number: 3 | |
| 80 | - Name: main | |
| 81 | Value: 0 | |
| 82 | SectionNumber: 1 | |
| 83 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 84 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 85 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 86 | - Name: variable | |
| 87 | Value: 0 | |
| 88 | SectionNumber: 2 | |
| 89 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 90 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 91 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 92 | ... |
deps/lld/test/COFF/comdat-jumptable.s created+70| ... | ... | @@ -0,0 +1,70 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t1.obj | |
| 3 | # RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/comdat-jumptable2.s -filetype=obj -o %t2.obj | |
| 4 | ||
| 5 | # RUN: llvm-objdump -s %t1.obj | FileCheck --check-prefix=OBJ1 %s | |
| 6 | # RUN: llvm-objdump -s %t2.obj | FileCheck --check-prefix=OBJ2 %s | |
| 7 | ||
| 8 | # RUN: lld-link -lldmingw -entry:main %t1.obj %t2.obj -out:%t.exe | |
| 9 | # RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=EXE %s | |
| 10 | ||
| 11 | # Test linking cases where comdat functions have an associated jump table | |
| 12 | # in a non-comdat rdata (which GCC produces for functions with jump tables). | |
| 13 | # In these cases, ld.bfd keeps all rdata sections, but the relocations that | |
| 14 | # refer to discarded comdat sections just are emitted as they were originally. | |
| 15 | ||
| 16 | # In real scenarios, the jump table .rdata section should be identical across | |
| 17 | # all object files; here it is different to illustrate more clearly what | |
| 18 | # the linker actually does. | |
| 19 | ||
| 20 | # OBJ1: Contents of section .rdata: | |
| 21 | # OBJ1: 0000 aaaaaaaa 14000000 1e000000 28000000 | |
| 22 | # OBJ1: 0010 bbbbbbbb | |
| 23 | ||
| 24 | # OBJ2: Contents of section .rdata: | |
| 25 | # OBJ2: 0000 cccccccc 14000000 1e000000 28000000 | |
| 26 | # OBJ2: 0010 dddddddd | |
| 27 | ||
| 28 | # EXE: Contents of section .rdata: | |
| 29 | # EXE: 140002000 aaaaaaaa 0c100000 12100000 18100000 | |
| 30 | # EXE: 140002010 bbbbbbbb cccccccc 14000000 1e000000 | |
| 31 | # EXE: 140002020 28000000 dddddddd | |
| 32 | ||
| 33 | ||
| 34 | .section .text@comdatfunc, "x" | |
| 35 | .linkonce discard | |
| 36 | .globl comdatfunc | |
| 37 | comdatfunc: | |
| 38 | leaq .Ljumptable(%rip), %rax | |
| 39 | movslq (%rax, %rcx, 4), %rcx | |
| 40 | addq %rcx, %rax | |
| 41 | jmp *%rax | |
| 42 | ||
| 43 | .section .rdata, "dr" | |
| 44 | .long 0xaaaaaaaa | |
| 45 | .Ljumptable: | |
| 46 | .long .Ltail1-.Ljumptable | |
| 47 | .long .Ltail2-.Ljumptable | |
| 48 | .long .Ltail3-.Ljumptable | |
| 49 | .long 0xbbbbbbbb | |
| 50 | ||
| 51 | .section .text@comdatfunc, "x" | |
| 52 | # If assembled with binutils, the following line can be kept in: | |
| 53 | # .linkonce discard | |
| 54 | .Ltail1: | |
| 55 | movl $1, %eax | |
| 56 | ret | |
| 57 | .Ltail2: | |
| 58 | movl $2, %eax | |
| 59 | ret | |
| 60 | .Ltail3: | |
| 61 | movl $3, %eax | |
| 62 | ret | |
| 63 | ||
| 64 | ||
| 65 | .text | |
| 66 | .globl main | |
| 67 | main: | |
| 68 | call comdatfunc | |
| 69 | call otherfunc | |
| 70 | ret |
deps/lld/test/COFF/comdat-weak.test created+82| ... | ... | @@ -0,0 +1,82 @@ |
| 1 | RUN: lld-link -lldmingw %S/Inputs/inline-weak.o %S/Inputs/inline-weak2.o -out:%t.exe | |
| 2 | ||
| 3 | When compiling certain forms of templated inline functions, some | |
| 4 | versions of GCC (tested with 5.4) produces a weak symbol for the function. | |
| 5 | Newer versions of GCC don't do this though. | |
| 6 | ||
| 7 | The bundled object files are an example of that, they can be produced | |
| 8 | with test code like this: | |
| 9 | ||
| 10 | $ cat inline-weak.h | |
| 11 | class MyClass { | |
| 12 | public: | |
| 13 | template<typename... _Args> int get(_Args&&... args) { | |
| 14 | return a; | |
| 15 | } | |
| 16 | private: | |
| 17 | int a; | |
| 18 | }; | |
| 19 | ||
| 20 | $ cat inline-weak.cpp | |
| 21 | #include "inline-weak.h" | |
| 22 | ||
| 23 | int get(MyClass& a); | |
| 24 | ||
| 25 | int main(int argc, char* argv[]) { | |
| 26 | MyClass a; | |
| 27 | int ret = a.get(); | |
| 28 | ret += get(a); | |
| 29 | return ret; | |
| 30 | } | |
| 31 | extern "C" void mainCRTStartup(void) { | |
| 32 | main(0, (char**)0); | |
| 33 | } | |
| 34 | extern "C" void __main(void) { | |
| 35 | } | |
| 36 | ||
| 37 | $ cat inline-weak2.cpp | |
| 38 | #include "inline-weak.h" | |
| 39 | ||
| 40 | int get(MyClass& a) { | |
| 41 | return a.get(); | |
| 42 | } | |
| 43 | ||
| 44 | $ x86_64-w64-mingw32-g++ -std=c++11 -c inline-weak.cpp | |
| 45 | $ x86_64-w64-mingw32-g++ -std=c++11 -c inline-weak2.cpp | |
| 46 | ||
| 47 | $ x86_64-w64-mingw32-nm inline-weak.o | grep MyClass3get | |
| 48 | 0000000000000000 p .pdata$_ZN7MyClass3getIJEEEiDpOT_ | |
| 49 | 0000000000000000 t .text$_ZN7MyClass3getIJEEEiDpOT_ | |
| 50 | 0000000000000000 T .weak._ZN7MyClass3getIIEEEiDpOT_.main | |
| 51 | 0000000000000000 r .xdata$_ZN7MyClass3getIJEEEiDpOT_ | |
| 52 | w _ZN7MyClass3getIIEEEiDpOT_ | |
| 53 | 0000000000000000 T _ZN7MyClass3getIJEEEiDpOT_ | |
| 54 | ||
| 55 | $ x86_64-w64-mingw32-nm inline-weak2.o | grep MyClass3get | |
| 56 | 0000000000000000 p .pdata$_ZN7MyClass3getIJEEEiDpOT_ | |
| 57 | 0000000000000000 t .text$_ZN7MyClass3getIJEEEiDpOT_ | |
| 58 | 0000000000000000 T .weak._ZN7MyClass3getIIEEEiDpOT_._Z3getR7MyClass | |
| 59 | 0000000000000000 r .xdata$_ZN7MyClass3getIJEEEiDpOT_ | |
| 60 | w _ZN7MyClass3getIIEEEiDpOT_ | |
| 61 | 0000000000000000 T _ZN7MyClass3getIJEEEiDpOT_ | |
| 62 | ||
| 63 | This can't be reproduced by assembling .s files with llvm-mc, since that | |
| 64 | always produces a symbol named .weak.<weaksymbol>.default, therefore | |
| 65 | the test uses prebuilt object files instead. | |
| 66 | ||
| 67 | In these cases, the undefined weak symbol points to the regular symbol | |
| 68 | .weak._ZN7MyClass3getIIEEEiDpOT_.<othersymbol>, where <othersymbol> | |
| 69 | varies among the object files that emit the same function. This regular | |
| 70 | symbol points to the same location as the comdat function | |
| 71 | _ZN7MyClass3getIJEEEiDpOT_. | |
| 72 | ||
| 73 | When linking, the comdat section from the second object file gets | |
| 74 | discarded, as it matches the one that already exists. This means that | |
| 75 | the uniquely named symbol .weak.<weakname>.<othername> points to a | |
| 76 | discarded section chunk. | |
| 77 | ||
| 78 | Previously, this would have triggered adding an Undefined symbol for | |
| 79 | this case, which would later break linking. However, also previously, | |
| 80 | if the second object file is linked in via a static library, this | |
| 81 | leftover symbol is retained as a Lazy symbol, which would make the link | |
| 82 | succeed. |
deps/lld/test/COFF/common-replacement.s+1-1| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | |
| 15 | 15 | # SECTIONS: Name: .data (2E 64 61 74 61 00 00 00) |
| 16 | 16 | # SECTIONS-NEXT: VirtualSize: 0x8 |
| 17 | # SECTIONS-NEXT: VirtualAddress: 0x2000 | |
| 17 | # SECTIONS-NEXT: VirtualAddress: 0x3000 | |
| 18 | 18 | # SECTIONS-NEXT: RawDataSize: 512 |
| 19 | 19 | |
| 20 | 20 |
deps/lld/test/COFF/could-not-open.test created+5| ... | ... | @@ -0,0 +1,5 @@ |
| 1 | RUN: not lld-link 01 2>&1 | FileCheck %s | |
| 2 | ||
| 3 | CHECK: could not open 01 | |
| 4 | CHECK-NOT: /machine is not specified | |
| 5 | CHECK-NOT: subsystem must be defined |
deps/lld/test/COFF/crt-dyn-initializer-order.test created+100| ... | ... | @@ -0,0 +1,100 @@ |
| 1 | # // a.cpp | |
| 2 | # #include <iostream> | |
| 3 | # #include <vector> | |
| 4 | # | |
| 5 | # template <int Magic> struct TemplatedObject { | |
| 6 | # static std::vector<TemplatedObject<Magic> *> Instances; | |
| 7 | # TemplatedObject() { Instances.push_back(this); } | |
| 8 | # }; | |
| 9 | # | |
| 10 | # using Object = TemplatedObject<0>; | |
| 11 | # template <> std::vector<Object *> Object::Instances{}; | |
| 12 | # Object idle{}; | |
| 13 | # | |
| 14 | # int main() { | |
| 15 | # if (Object::Instances.size() == 0) | |
| 16 | # std::cout << "It's broken" << std::endl; | |
| 17 | # else | |
| 18 | # std::cout << "It works!" << std::endl; | |
| 19 | # return 0; | |
| 20 | # } | |
| 21 | # // using `clang-cl /c a.cpp | lld-link a.obj` works | |
| 22 | # // using `cl /c a.cpp | lld-link a.obj` fails without lld/COFF/Writer.cpp/Writer::sortSectionChunks() | |
| 23 | ||
| 24 | # RUN: yaml2obj %s > %t.obj | |
| 25 | # RUN: yaml2obj %S/Inputs/crt-dyn-initializer-order_1.yaml > %t1.obj | |
| 26 | # RUN: yaml2obj %S/Inputs/crt-dyn-initializer-order_2.yaml > %t2.obj | |
| 27 | ||
| 28 | # CHECK: Name: .CRT | |
| 29 | # CHECK: Characteristics [ | |
| 30 | # CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | |
| 31 | # CHECK-NEXT: IMAGE_SCN_MEM_READ | |
| 32 | # CHECK-NEXT: ] | |
| 33 | # CHECK-NEXT: SectionData ( | |
| 34 | ||
| 35 | # RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj %t1.obj %t2.obj | |
| 36 | # RUN: llvm-readobj -sections -section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE1 | |
| 37 | # CASE1-NEXT: 01020304 55701011 1205 | |
| 38 | ||
| 39 | # RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj %t2.obj %t1.obj | |
| 40 | # RUN: llvm-readobj -sections -section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE2 | |
| 41 | # CASE2-NEXT: 01020304 10111255 7005 | |
| 42 | ||
| 43 | # RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t1.obj %t2.obj %t.obj | |
| 44 | # RUN: llvm-readobj -sections -section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE3 | |
| 45 | # CASE3-NEXT: 01557010 11120203 0405 | |
| 46 | ||
| 47 | # RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t1.obj %t.obj %t2.obj | |
| 48 | # RUN: llvm-readobj -sections -section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE4 | |
| 49 | # CASE4-NEXT: 01557002 03041011 1205 | |
| 50 | ||
| 51 | # RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t2.obj %t1.obj %t.obj | |
| 52 | # RUN: llvm-readobj -sections -section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE5 | |
| 53 | # CASE5-NEXT: 01101112 55700203 0405 | |
| 54 | ||
| 55 | # RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t2.obj %t.obj %t1.obj | |
| 56 | # RUN: llvm-readobj -sections -section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE6 | |
| 57 | # CASE6-NEXT: 01101112 02030455 7005 | |
| 58 | ||
| 59 | # CHECK-NEXT: ) | |
| 60 | ||
| 61 | --- !COFF | |
| 62 | header: | |
| 63 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 64 | Characteristics: [ ] | |
| 65 | sections: | |
| 66 | - Name: '.CRT$XCA' | |
| 67 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | |
| 68 | Alignment: 1 | |
| 69 | SectionData: 01 | |
| 70 | - Name: '.CRT$XCU' | |
| 71 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | |
| 72 | Alignment: 1 | |
| 73 | SectionData: 02 | |
| 74 | - Name: '.CRT$XCU' | |
| 75 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_LNK_COMDAT ] | |
| 76 | Alignment: 1 | |
| 77 | SectionData: 03 | |
| 78 | - Name: '.CRT$XCU' | |
| 79 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | |
| 80 | Alignment: 1 | |
| 81 | SectionData: 04 | |
| 82 | - Name: '.CRT$XCZ' | |
| 83 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] | |
| 84 | Alignment: 1 | |
| 85 | SectionData: 05 | |
| 86 | symbols: | |
| 87 | - Name: '.CRT$XCU' | |
| 88 | Value: 0 | |
| 89 | SectionNumber: 3 | |
| 90 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 91 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 92 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 93 | SectionDefinition: | |
| 94 | Length: 1 | |
| 95 | NumberOfRelocations: 0 | |
| 96 | NumberOfLinenumbers: 0 | |
| 97 | CheckSum: 1 | |
| 98 | Number: 2 | |
| 99 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | |
| 100 | ... |
deps/lld/test/COFF/ctors_dtors_priority.s+25-10| ... | ... | @@ -1,12 +1,17 @@ |
| 1 | 1 | # REQUIRES: x86 |
| 2 | 2 | # RUN: llvm-mc -triple=x86_64-windows-gnu -filetype=obj -o %t.obj %s |
| 3 | # RUN: lld-link -entry:main %t.obj -out:%t.exe | |
| 3 | # RUN: lld-link -lldmingw -entry:main %t.obj -out:%t.exe | |
| 4 | 4 | # RUN: llvm-objdump -s %t.exe | FileCheck %s |
| 5 | 5 | |
| 6 | 6 | .globl main |
| 7 | 7 | main: |
| 8 | 8 | nop |
| 9 | 9 | |
| 10 | # Check that these symbols point at the right spots. | |
| 11 | .data | |
| 12 | .quad __CTOR_LIST__ | |
| 13 | .quad __DTOR_LIST__ | |
| 14 | ||
| 10 | 15 | .section .ctors.00005, "w" |
| 11 | 16 | .quad 2 |
| 12 | 17 | .section .ctors, "w" |
| ... | ... | @@ -15,16 +20,26 @@ main: |
| 15 | 20 | .quad 3 |
| 16 | 21 | |
| 17 | 22 | .section .dtors, "w" |
| 18 | .quad 1 | |
| 23 | .quad 4 | |
| 19 | 24 | .section .dtors.00100, "w" |
| 20 | .quad 3 | |
| 25 | .quad 6 | |
| 21 | 26 | .section .dtors.00005, "w" |
| 22 | .quad 2 | |
| 27 | .quad 5 | |
| 28 | ||
| 29 | # Also test that the .CRT section is merged into .rdata | |
| 23 | 30 | |
| 24 | # CHECK: Contents of section .ctors: | |
| 25 | # CHECK-NEXT: 140002000 01000000 00000000 02000000 00000000 | |
| 26 | # CHECK-NEXT: 140002010 03000000 00000000 | |
| 31 | .section .CRT$XCA, "dw" | |
| 32 | .quad 7 | |
| 33 | .quad 8 | |
| 27 | 34 | |
| 28 | # CHECK: Contents of section .dtors: | |
| 29 | # CHECK-NEXT: 140003000 01000000 00000000 02000000 00000000 | |
| 30 | # CHECK-NEXT: 140003010 03000000 00000000 | |
| 35 | # CHECK: Contents of section .rdata: | |
| 36 | # CHECK-NEXT: 140002000 07000000 00000000 08000000 00000000 | |
| 37 | # CHECK-NEXT: 140002010 ffffffff ffffffff 01000000 00000000 | |
| 38 | # CHECK-NEXT: 140002020 02000000 00000000 03000000 00000000 | |
| 39 | # CHECK-NEXT: 140002030 00000000 00000000 ffffffff ffffffff | |
| 40 | # CHECK-NEXT: 140002040 04000000 00000000 05000000 00000000 | |
| 41 | # CHECK-NEXT: 140002050 06000000 00000000 00000000 00000000 | |
| 42 | # __CTOR_LIST__ pointing at 0x140002010 and | |
| 43 | # __DTOR_LIST__ pointing at 0x140002038. | |
| 44 | # CHECK-NEXT: Contents of section .data: | |
| 45 | # CHECK-NEXT: 140003000 10200040 01000000 38200040 01000000 |
deps/lld/test/COFF/debug-fastlink.test created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj | |
| 2 | # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj | |
| 3 | ||
| 4 | ; If /DEBUG:FASTLINK is specified, /DEBUG:FULL is used instead | |
| 5 | # RUN: rm -f %t.pdb | |
| 6 | # RUN: lld-link /DEBUG /pdb:%t.pdb /DEBUG:FASTLINK /entry:main /nodefaultlib %t1.obj %t2.obj \ | |
| 7 | # RUN: 2>&1 | FileCheck %s | |
| 8 | ||
| 9 | # CHECK: /debug:fastlink unsupported; using /debug:full | |
| 10 | ||
| 11 | # RUN: ls %t.pdb | |
| 12 |
deps/lld/test/COFF/debug-reloc.s+9-9| ... | ... | @@ -8,35 +8,35 @@ |
| 8 | 8 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck %s -check-prefix HEADERS |
| 9 | 9 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck %s -check-prefix DEBUG |
| 10 | 10 | |
| 11 | # SECTIONS: Number: 2 | |
| 11 | # SECTIONS: Number: 3 | |
| 12 | 12 | # SECTIONS-NEXT: Name: .buildid (2E 62 75 69 6C 64 69 64) |
| 13 | 13 | # SECTIONS-NEXT: VirtualSize: 0x35 |
| 14 | # SECTIONS-NEXT: VirtualAddress: 0x2000 | |
| 15 | # SECTIONS: Number: 3 | |
| 14 | # SECTIONS-NEXT: VirtualAddress: 0x3000 | |
| 15 | # SECTIONS: Number: 4 | |
| 16 | 16 | # SECTIONS-NEXT: Name: .data (2E 64 61 74 61 00 00 00) |
| 17 | 17 | # SECTIONS-NEXT: VirtualSize: 0x8 |
| 18 | # SECTIONS-NEXT: VirtualAddress: 0x3000 | |
| 18 | # SECTIONS-NEXT: VirtualAddress: 0x4000 | |
| 19 | 19 | |
| 20 | 20 | # RELOCS: BaseReloc [ |
| 21 | 21 | # RELOCS-NEXT: Entry { |
| 22 | 22 | # RELOCS-NEXT: Type: DIR64 |
| 23 | # RELOCS-NEXT: Address: 0x3000 | |
| 23 | # RELOCS-NEXT: Address: 0x4000 | |
| 24 | 24 | # RELOCS-NEXT: } |
| 25 | 25 | # RELOCS-NEXT: Entry { |
| 26 | 26 | # RELOCS-NEXT: Type: ABSOLUTE |
| 27 | # RELOCS-NEXT: Address: 0x3000 | |
| 27 | # RELOCS-NEXT: Address: 0x4000 | |
| 28 | 28 | # RELOCS-NEXT: } |
| 29 | 29 | # RELOCS-NEXT: ] |
| 30 | 30 | |
| 31 | # HEADERS: DebugRVA: 0x2000 | |
| 31 | # HEADERS: DebugRVA: 0x3000 | |
| 32 | 32 | # HEADERS: DebugSize: 0x1C |
| 33 | 33 | |
| 34 | 34 | # DEBUG: DebugDirectory [ |
| 35 | 35 | # DEBUG: DebugEntry { |
| 36 | 36 | # DEBUG: Type: CodeView (0x2) |
| 37 | 37 | # DEBUG: SizeOfData: 0x19 |
| 38 | # DEBUG: AddressOfRawData: 0x201C | |
| 39 | # DEBUG: PointerToRawData: 0x61C | |
| 38 | # DEBUG: AddressOfRawData: 0x301C | |
| 39 | # DEBUG: PointerToRawData: 0x81C | |
| 40 | 40 | |
| 41 | 41 | 	.text |
| 42 | 42 | 	.def	 mainfunc; |
deps/lld/test/COFF/directives.s created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -triple=x86_64-windows %s -filetype=obj -o %t.obj | |
| 4 | ||
| 5 | # RUN: lld-link -dll -out:%t.dll -entry:entry %t.obj -subsystem:console | |
| 6 | # RUN: llvm-objdump -p %t.dll | FileCheck %s | |
| 7 | ||
| 8 | # CHECK: Export Table: | |
| 9 | # CHECK: DLL name: directives.s.tmp.dll | |
| 10 | # CHECK: Ordinal RVA Name | |
| 11 | # CHECK-NEXT: 0 0 | |
| 12 | # CHECK-NEXT: 1 0x1000 exportfn1 | |
| 13 | # CHECK-NEXT: 2 0x1000 exportfn2 | |
| 14 | # CHECK-NEXT: 3 0x1000 exportfn3 | |
| 15 | # CHECK-NEXT: 4 0x1000 exportfn4 | |
| 16 | # CHECK-NEXT: 5 0x1000 exportfn5 | |
| 17 | # CHECK-NEXT: 6 0x1000 exportfn6 | |
| 18 | ||
| 19 | .global entry | |
| 20 | .global exportfn1 | |
| 21 | .global exportfn2 | |
| 22 | .global exportfn3 | |
| 23 | .global exportfn4 | |
| 24 | .global exportfn5 | |
| 25 | .global exportfn6 | |
| 26 | .text | |
| 27 | entry: | |
| 28 | exportfn1: | |
| 29 | exportfn2: | |
| 30 | exportfn3: | |
| 31 | exportfn4: | |
| 32 | exportfn5: | |
| 33 | exportfn6: | |
| 34 | ret | |
| 35 | .section .drectve | |
| 36 | # Test that directive strings can be separated by any combination of | |
| 37 | # spaces and null bytes. | |
| 38 | .ascii "-export:exportfn1 " | |
| 39 | .asciz "-export:exportfn2" | |
| 40 | .asciz "-export:exportfn3" | |
| 41 | .asciz "-export:exportfn4 " | |
| 42 | .byte 0 | |
| 43 | .ascii " " | |
| 44 | .byte 0 | |
| 45 | .asciz "-export:exportfn5" | |
| 46 | .asciz " -export:exportfn6" |
deps/lld/test/COFF/duplicate-imp-func.s created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo -e ".globl libfunc\n.text\nlibfunc:\nret" > %t.lib.s | |
| 4 | # RUN: llvm-mc -triple=x86_64-windows-gnu %t.lib.s -filetype=obj -o %t.lib.o | |
| 5 | # RUN: lld-link -lldmingw -dll -out:%t.lib.dll -entry:libfunc %t.lib.o -implib:%t.lib.dll.a | |
| 6 | ||
| 7 | # RUN: echo -e ".globl helper1\n.text\nhelper1:\ncall libfunc\nret" > %t.helper1.s | |
| 8 | # RUN: echo -e ".globl helper2\n.text\nhelper2:\nret\n.globl libfunc\n.globl __imp_libfunc\nlibfunc:\nret\n.data\n__imp_libfunc:\n.quad libfunc" > %t.helper2.s | |
| 9 | # RUN: llvm-mc -triple=x86_64-windows-gnu %t.helper1.s -filetype=obj -o %t.helper1.o | |
| 10 | # RUN: llvm-mc -triple=x86_64-windows-gnu %t.helper2.s -filetype=obj -o %t.helper2.o | |
| 11 | ||
| 12 | # RUN: llvm-ar rcs %t.helper.a %t.helper1.o %t.helper2.o | |
| 13 | ||
| 14 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.main.o | |
| 15 | ||
| 16 | # Simulate a setup, where two libraries provide the same import function; | |
| 17 | # %t.lib.dll.a is a pure import library which provides "libfunc". | |
| 18 | # %t.helper.a is a static library which contains "helper1" and "helper2". | |
| 19 | # | |
| 20 | # helper1 contains an undefined reference to libfunc. helper2 contains a | |
| 21 | # fake local implementation of libfunc, together with the __imp_libfunc | |
| 22 | # stub. | |
| 23 | # | |
| 24 | # %t.lib.dll.a is listed before %t.helper.a on the command line. After | |
| 25 | # including helper1, the library member that first declared the Lazy libfunc | |
| 26 | # (%t.lib.dll.a) gets enqueued to be loaded. Before that gets done, helper2 | |
| 27 | # gets loaded, which also turns out to provide a definition of libfunc. | |
| 28 | # Once the import library member from %t.lib.dll.a gets loaded, libfunc | |
| 29 | # and __imp_libfunc already are defined. | |
| 30 | ||
| 31 | # Just check that this fails cleanly (doesn't crash). | |
| 32 | # RUN: not lld-link -lldmingw -out:%t.main.exe -entry:main %t.main.o %t.lib.dll.a %t.helper.a | |
| 33 | ||
| 34 | # Test with %t.helper.a on the command line; in this case we won't try to | |
| 35 | # include libfunc from %t.lib.dll.a and everything works fine. | |
| 36 | # RUN: lld-link -lldmingw -out:%t.main.exe -entry:main %t.main.o %t.helper.a %t.lib.dll.a | |
| 37 | ||
| 38 | .globl main | |
| 39 | .text | |
| 40 | main: | |
| 41 | call helper1 | |
| 42 | call helper2 | |
| 43 | ret |
deps/lld/test/COFF/entry-inference-mingw.s created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.o | |
| 3 | ||
| 4 | # RUN: lld-link -lldmingw %t.o -out:%t-default.exe 2>&1 | FileCheck -allow-empty -check-prefix=LINK %s | |
| 5 | # RUN: lld-link -lldmingw %t.o -out:%t-cui.exe -subsystem:console 2>&1 | FileCheck -allow-empty -check-prefix=LINK %s | |
| 6 | # RUN: lld-link -lldmingw %t.o -out:%t-gui.exe -subsystem:windows 2>&1 | FileCheck -allow-empty -check-prefix=LINK %s | |
| 7 | ||
| 8 | # RUN: llvm-readobj -file-headers %t-default.exe | FileCheck -check-prefix=CUI %s | |
| 9 | # RUN: llvm-readobj -file-headers %t-cui.exe | FileCheck -check-prefix=CUI %s | |
| 10 | # RUN: llvm-readobj -file-headers %t-gui.exe | FileCheck -check-prefix=GUI %s | |
| 11 | ||
| 12 | # Check that this doesn't print any warnings. | |
| 13 | # LINK-NOT: found both wmain and main | |
| 14 | ||
| 15 | # CUI: AddressOfEntryPoint: 0x1001 | |
| 16 | # CUI: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3) | |
| 17 | ||
| 18 | # GUI: AddressOfEntryPoint: 0x1002 | |
| 19 | # GUI: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI (0x2) | |
| 20 | ||
| 21 | ||
| 22 | .text | |
| 23 | .globl mainCRTStartup | |
| 24 | .globl WinMainCRTStartup | |
| 25 | # MinGW only uses the entry points above, these other ones aren't | |
| 26 | # used as entry. | |
| 27 | .globl main | |
| 28 | .globl wmain | |
| 29 | .globl wmainCRTStartup | |
| 30 | .globl wWinMainCRTStartup | |
| 31 | foo: | |
| 32 | ret | |
| 33 | mainCRTStartup: | |
| 34 | ret | |
| 35 | WinMainCRTStartup: | |
| 36 | ret | |
| 37 | main: | |
| 38 | ret | |
| 39 | wmain: | |
| 40 | ret | |
| 41 | wmainCRTStartup: | |
| 42 | ret | |
| 43 | wWinMainCRTStartup: | |
| 44 | ret |
deps/lld/test/COFF/entry-inference.test+8| ... | ... | @@ -1,18 +1,26 @@ |
| 1 | 1 | # RUN: sed -e s/ENTRYNAME/main/ %s | yaml2obj > %t.obj |
| 2 | 2 | # RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1 |
| 3 | 3 | # RUN: FileCheck -check-prefix=MAIN %s < %t.log |
| 4 | # RUN: not lld-link /nodefaultlib /out:%t.exe %t.obj > %t.log 2>&1 | |
| 5 | # RUN: FileCheck -check-prefix=MAIN %s < %t.log | |
| 4 | 6 | |
| 5 | 7 | # RUN: sed s/ENTRYNAME/wmain/ %s | yaml2obj > %t.obj |
| 6 | 8 | # RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1 |
| 7 | 9 | # RUN: FileCheck -check-prefix=WMAIN %s < %t.log |
| 10 | # RUN: not lld-link /nodefaultlib /out:%t.exe %t.obj > %t.log 2>&1 | |
| 11 | # RUN: FileCheck -check-prefix=WMAIN %s < %t.log | |
| 8 | 12 | |
| 9 | 13 | # RUN: sed s/ENTRYNAME/WinMain/ %s | yaml2obj > %t.obj |
| 10 | 14 | # RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1 |
| 11 | 15 | # RUN: FileCheck -check-prefix=WINMAIN %s < %t.log |
| 16 | # RUN: not lld-link /nodefaultlib /out:%t.exe %t.obj > %t.log 2>&1 | |
| 17 | # RUN: FileCheck -check-prefix=WINMAIN %s < %t.log | |
| 12 | 18 | |
| 13 | 19 | # RUN: sed s/ENTRYNAME/wWinMain/ %s | yaml2obj > %t.obj |
| 14 | 20 | # RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1 |
| 15 | 21 | # RUN: FileCheck -check-prefix=WWINMAIN %s < %t.log |
| 22 | # RUN: not lld-link /nodefaultlib /out:%t.exe %t.obj > %t.log 2>&1 | |
| 23 | # RUN: FileCheck -check-prefix=WWINMAIN %s < %t.log | |
| 16 | 24 | |
| 17 | 25 | # MAIN: error: <root>: undefined symbol: mainCRTStartup |
| 18 | 26 | # WMAIN: error: <root>: undefined symbol: wmainCRTStartup |
deps/lld/test/COFF/entry-inference4.test+16-4| ... | ... | @@ -14,10 +14,22 @@ |
| 14 | 14 | # RUN: not lld-link /subsystem:console /out:%t.exe %t.obj > %t.log 2>&1 |
| 15 | 15 | # RUN: FileCheck -check-prefix=WMAIN %s < %t.log |
| 16 | 16 | |
| 17 | # MAIN: error: <root>: undefined symbol: mainCRTStartup | |
| 18 | # WMAIN: error: <root>: undefined symbol: wmainCRTStartup | |
| 19 | # WINMAIN: error: <root>: undefined symbol: WinMainCRTStartup | |
| 20 | # WWINMAIN: error: <root>: undefined symbol: wWinMainCRTStartup | |
| 17 | # RUN: sed 's/ENTRY1/wmain/;s/ENTRY2/main/' %s | yaml2obj > %t.obj | |
| 18 | # RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1 | |
| 19 | # RUN: FileCheck -check-prefix=MAINWMAIN %s < %t.log | |
| 20 | ||
| 21 | # RUN: sed 's/ENTRY1/wWinMain/;s/ENTRY2/WinMain/' %s | yaml2obj > %t.obj | |
| 22 | # RUN: not lld-link /out:%t.exe %t.obj > %t.log 2>&1 | |
| 23 | # RUN: FileCheck -check-prefix=WINMAINWWINMAIN %s < %t.log | |
| 24 | ||
| 25 | # MAIN: error: <root>: undefined symbol: mainCRTStartup | |
| 26 | # WMAIN: error: <root>: undefined symbol: wmainCRTStartup | |
| 27 | # MAINWMAIN: warning: found both wmain and main; using latter | |
| 28 | # MAINWMAIN: error: <root>: undefined symbol: mainCRTStartup | |
| 29 | # WINMAIN: error: <root>: undefined symbol: WinMainCRTStartup | |
| 30 | # WWINMAIN: error: <root>: undefined symbol: wWinMainCRTStartup | |
| 31 | # WINMAINWWINMAIN: warning: found both wWinMain and WinMain; using latter | |
| 32 | # WINMAINWWINMAIN: error: <root>: undefined symbol: WinMainCRTStartup | |
| 21 | 33 | |
| 22 | 34 | --- !COFF |
| 23 | 35 | header: |
deps/lld/test/COFF/export-all.s+21-6| ... | ... | @@ -3,14 +3,13 @@ |
| 3 | 3 | # RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj |
| 4 | 4 | |
| 5 | 5 | # RUN: lld-link -lldmingw -dll -out:%t.dll -entry:DllMainCRTStartup@12 %t.obj -implib:%t.lib |
| 6 | # RUN: llvm-readobj -coff-exports %t.dll | FileCheck %s | |
| 6 | # RUN: llvm-readobj -coff-exports %t.dll | grep Name: | FileCheck %s | |
| 7 | 7 | # RUN: llvm-readobj %t.lib | FileCheck -check-prefix=IMPLIB %s |
| 8 | 8 | |
| 9 | # CHECK-NOT: Name: DllMainCRTStartup | |
| 10 | # CHECK-NOT: Name: _imp__unexported | |
| 11 | # CHECK: Name: dataSym | |
| 12 | # CHECK: Name: foobar | |
| 13 | # CHECK-NOT: Name: unexported | |
| 9 | # CHECK: Name: | |
| 10 | # CHECK-NEXT: Name: dataSym | |
| 11 | # CHECK-NEXT: Name: foobar | |
| 12 | # CHECK-EMPTY: | |
| 14 | 13 | |
| 15 | 14 | # IMPLIB: Symbol: __imp__dataSym |
| 16 | 15 | # IMPLIB-NOT: Symbol: _dataSym |
| ... | ... | @@ -22,6 +21,7 @@ |
| 22 | 21 | .global _dataSym |
| 23 | 22 | .global _unexported |
| 24 | 23 | .global __imp__unexported |
| 24 | .global .refptr._foobar | |
| 25 | 25 | .text |
| 26 | 26 | _DllMainCRTStartup@12: |
| 27 | 27 | ret |
| ... | ... | @@ -34,6 +34,8 @@ _dataSym: |
| 34 | 34 | .int 4 |
| 35 | 35 | __imp__unexported: |
| 36 | 36 | .int _unexported |
| 37 | .refptr._foobar: | |
| 38 | .int _foobar | |
| 37 | 39 | |
| 38 | 40 | # Test specifying -export-all-symbols, on an object file that contains |
| 39 | 41 | # dllexport directive for some of the symbols. |
| ... | ... | @@ -63,6 +65,7 @@ __imp__unexported: |
| 63 | 65 | # RUN: mkdir -p %T/libs |
| 64 | 66 | # RUN: echo -e ".global mingwfunc\n.text\nmingwfunc:\nret\n" > %T/libs/mingwfunc.s |
| 65 | 67 | # RUN: llvm-mc -triple=x86_64-windows-gnu %T/libs/mingwfunc.s -filetype=obj -o %T/libs/mingwfunc.o |
| 68 | # RUN: rm -f %T/libs/libmingwex.a | |
| 66 | 69 | # RUN: llvm-ar rcs %T/libs/libmingwex.a %T/libs/mingwfunc.o |
| 67 | 70 | # RUN: echo -e ".global crtfunc\n.text\ncrtfunc:\nret\n" > %T/libs/crtfunc.s |
| 68 | 71 | # RUN: llvm-mc -triple=x86_64-windows-gnu %T/libs/crtfunc.s -filetype=obj -o %T/libs/crt2.o |
| ... | ... | @@ -74,6 +77,18 @@ __imp__unexported: |
| 74 | 77 | # CHECK-EXCLUDE-NEXT: foobar @1 |
| 75 | 78 | # CHECK-EXCLUDE-NEXT: EOF |
| 76 | 79 | |
| 80 | # Test that libraries included with -wholearchive: are autoexported, even if | |
| 81 | # they are in a library that otherwise normally would be excluded. | |
| 82 | ||
| 83 | # RUN: lld-link -out:%t.dll -dll -entry:DllMainCRTStartup %t.main.obj -lldmingw %T/libs/crt2.o -wholearchive:%T/libs/libmingwex.a -output-def:%t.def | |
| 84 | # RUN: echo "EOF" >> %t.def | |
| 85 | # RUN: cat %t.def | FileCheck -check-prefix=CHECK-WHOLEARCHIVE %s | |
| 86 | ||
| 87 | # CHECK-WHOLEARCHIVE: EXPORTS | |
| 88 | # CHECK-WHOLEARCHIVE-NEXT: foobar @1 | |
| 89 | # CHECK-WHOLEARCHIVE-NEXT: mingwfunc @2 | |
| 90 | # CHECK-WHOLEARCHIVE-NEXT: EOF | |
| 91 | ||
| 77 | 92 | # Test that we handle import libraries together with -opt:noref. |
| 78 | 93 | |
| 79 | 94 | # RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj |
deps/lld/test/COFF/export.test+9| ... | ... | @@ -97,3 +97,12 @@ FORWARDER: Ordinal RVA Name |
| 97 | 97 | FORWARDER: 0 0 |
| 98 | 98 | FORWARDER: 1 0x1010 exportfn |
| 99 | 99 | FORWARDER: 2 foo (forwarded to kernel32.foobar) |
| 100 | ||
| 101 | # RUN: lld-link /out:%t.dll /dll %t.obj /merge:.rdata=.text /export:exportfn1 /export:exportfn2 | |
| 102 | # RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=MERGE -match-full-lines %s | |
| 103 | ||
| 104 | MERGE: DLL name: export.test.tmp.dll | |
| 105 | MERGE: Ordinal RVA Name | |
| 106 | MERGE-NEXT: 0 0 | |
| 107 | MERGE-NEXT: 1 0x1008 exportfn1 | |
| 108 | MERGE-NEXT: 2 0x1010 exportfn2 |
deps/lld/test/COFF/force-multiple.test created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | # RUN: yaml2obj < %s > %t1.obj | |
| 2 | # RUN: yaml2obj < %s > %t2.obj | |
| 3 | ||
| 4 | # RUN: not lld-link /out:%t.exe /entry:main %t1.obj %t2.obj >& %t.log | |
| 5 | # RUN: FileCheck -check-prefix=ERROR %s < %t.log | |
| 6 | ||
| 7 | # RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.obj /force >& %t.log | |
| 8 | # RUN: FileCheck -check-prefix=WARN %s < %t.log | |
| 9 | ||
| 10 | # RUN: lld-link /out:%t.exe /entry:main %t1.obj %t2.obj /force:multiple >& %t.log | |
| 11 | # RUN: FileCheck -check-prefix=WARN %s < %t.log | |
| 12 | ||
| 13 | # ERROR: error: duplicate symbol: main | |
| 14 | ||
| 15 | # WARN: warning: duplicate symbol: main | |
| 16 | ||
| 17 | --- !COFF | |
| 18 | header: | |
| 19 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 20 | Characteristics: [] | |
| 21 | sections: | |
| 22 | - Name: .text | |
| 23 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 24 | Alignment: 4 | |
| 25 | SectionData: 000000000000 | |
| 26 | symbols: | |
| 27 | - Name: .text | |
| 28 | Value: 0 | |
| 29 | SectionNumber: 1 | |
| 30 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 31 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 32 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 33 | SectionDefinition: | |
| 34 | Length: 6 | |
| 35 | NumberOfRelocations: 0 | |
| 36 | NumberOfLinenumbers: 0 | |
| 37 | CheckSum: 0 | |
| 38 | Number: 0 | |
| 39 | - Name: main | |
| 40 | Value: 0 | |
| 41 | SectionNumber: 1 | |
| 42 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 43 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 44 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 45 | ... |
deps/lld/test/COFF/gfids-export.s created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -triple x86_64-pc-win32 %s -filetype=obj -o %t.obj | |
| 3 | # RUN: lld-link %t.obj -guard:cf -dll -out:%t.dll -noentry | |
| 4 | # RUN: llvm-readobj -coff-load-config %t.dll | FileCheck %s --check-prefix=CHECK | |
| 5 | ||
| 6 | # There should be a single entry in the table for the exported symbol. | |
| 7 | # | |
| 8 | # CHECK: GuardFidTable [ | |
| 9 | # CHECK-NEXT: 0x180001000 | |
| 10 | # CHECK-NEXT: ] | |
| 11 | ||
| 12 | .def func_export; .scl 2; .type 32; .endef | |
| 13 | .globl func_export | |
| 14 | .section .text,"xr",one_only,func_export | |
| 15 | .p2align 4 | |
| 16 | func_export: | |
| 17 | movl $1, %eax | |
| 18 | .globl label_export | |
| 19 | label_export: | |
| 20 | movl $2, %eax | |
| 21 | ret | |
| 22 | ||
| 23 | .data | |
| 24 | .globl data_export | |
| 25 | data_export: | |
| 26 | .long 42 | |
| 27 | ||
| 28 | .section .drectve,"dr" | |
| 29 | .ascii " /EXPORT:func_export" | |
| 30 | .ascii " /EXPORT:label_export" | |
| 31 | .ascii " /EXPORT:data_export" | |
| 32 | ||
| 33 | ||
| 34 | # Load configuration directory entry (winnt.h _IMAGE_LOAD_CONFIG_DIRECTORY64). | |
| 35 | # The linker will define the __guard_* symbols. | |
| 36 | .section .rdata,"dr" | |
| 37 | .globl _load_config_used | |
| 38 | _load_config_used: | |
| 39 | .long 256 | |
| 40 | .fill 124, 1, 0 | |
| 41 | .quad __guard_fids_table | |
| 42 | .quad __guard_fids_count | |
| 43 | .long __guard_flags | |
| 44 | .fill 128, 1, 0 |
deps/lld/test/COFF/gfids-relocations32.s created+87| ... | ... | @@ -0,0 +1,87 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -triple i686-pc-win32 %s -filetype=obj -o %t.obj | |
| 3 | # RUN: lld-link %t.obj -guard:cf -out:%t.exe -entry:main | |
| 4 | # RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK | |
| 5 | ||
| 6 | # Only f and _main should go in the table. | |
| 7 | # (use /lldmap:map.txt to check their addresses). | |
| 8 | # | |
| 9 | # CHECK: GuardFidTable [ | |
| 10 | # CHECK-NEXT: 0x401000 | |
| 11 | # CHECK-NEXT: 0x401030 | |
| 12 | # CHECK-NEXT: ] | |
| 13 | ||
| 14 | # The input was loosly based on studying this program: | |
| 15 | # | |
| 16 | # void foo() { return; } | |
| 17 | # void bar() { return; } | |
| 18 | # int main() { | |
| 19 | # foo(); | |
| 20 | # void (*arr[])() = { &bar }; | |
| 21 | # (*arr[0])(); | |
| 22 | # return 0; | |
| 23 | # } | |
| 24 | # cl /c a.cc && dumpbin /disasm a.obj > a.txt && | |
| 25 | # link a.obj /guard:cf /map:map.txt && dumpbin /loadconfig a.exe | |
| 26 | ||
| 27 | ||
| 28 | ||
| 29 | .def f; | |
| 30 | .scl 3; | |
| 31 | .type 32; | |
| 32 | .endef | |
| 33 | .section .text,"xr",one_only,f | |
| 34 | .p2align 4 | |
| 35 | f: movl $1, %eax | |
| 36 | ret | |
| 37 | ||
| 38 | ||
| 39 | .def g; | |
| 40 | .scl 3; | |
| 41 | .type 32; | |
| 42 | .endef | |
| 43 | .section .text,"xr",one_only,g | |
| 44 | .p2align 4 | |
| 45 | g: movl $2, %eax | |
| 46 | ret | |
| 47 | ||
| 48 | ||
| 49 | .def label; | |
| 50 | .scl 6; # StorageClass: Label | |
| 51 | .type 0; # Type: Not a function. | |
| 52 | .endef | |
| 53 | .section .text,"xr",one_only,label | |
| 54 | .p2align 4 | |
| 55 | label: ret | |
| 56 | ||
| 57 | ||
| 58 | .data | |
| 59 | .globl fp | |
| 60 | .p2align 4 | |
| 61 | fp: .long f # DIR32 relocation to function | |
| 62 | .long label # DIR32 relocation to label | |
| 63 | ||
| 64 | ||
| 65 | .def _main; | |
| 66 | .scl 2; | |
| 67 | .type 32; | |
| 68 | .endef | |
| 69 | .section .text,"xr",one_only,_main | |
| 70 | .globl _main | |
| 71 | .p2align 4 | |
| 72 | _main: call *fp # DIR32 relocation to data | |
| 73 | call g # REL32 relocation to function | |
| 74 | ret | |
| 75 | ||
| 76 | ||
| 77 | # Load configuration directory entry (winnt.h _IMAGE_LOAD_CONFIG_DIRECTORY32). | |
| 78 | # The linker will define the ___guard_* symbols. | |
| 79 | .section .rdata,"dr" | |
| 80 | .globl __load_config_used | |
| 81 | __load_config_used: | |
| 82 | .long 104 # Size. | |
| 83 | .fill 76, 1, 0 | |
| 84 | .long ___guard_fids_table | |
| 85 | .long ___guard_fids_count | |
| 86 | .long ___guard_flags | |
| 87 | .fill 12, 1, 0 |
deps/lld/test/COFF/gfids-relocations64.s created+76| ... | ... | @@ -0,0 +1,76 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -triple x86_64-pc-win32 %s -filetype=obj -o %t.obj | |
| 3 | # RUN: lld-link %t.obj -guard:cf -out:%t.exe -entry:main | |
| 4 | # RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK | |
| 5 | ||
| 6 | # f, g, and main go in the table. | |
| 7 | # Including g isn't strictly necessary since it's not an indirect call target, | |
| 8 | # however the linker can't know that because relative relocations are used both | |
| 9 | # for direct calls and for getting the absolute address of a function. | |
| 10 | # (use /lldmap:map.txt to check their addresses). | |
| 11 | # | |
| 12 | # CHECK: GuardFidTable [ | |
| 13 | # CHECK-NEXT: 0x140001000 | |
| 14 | # CHECK-NEXT: 0x140001010 | |
| 15 | # CHECK-NEXT: 0x140001030 | |
| 16 | # CHECK-NEXT: ] | |
| 17 | ||
| 18 | .def f; | |
| 19 | .scl 3; | |
| 20 | .type 32; | |
| 21 | .endef | |
| 22 | .section .text,"xr",one_only,f | |
| 23 | .p2align 4 | |
| 24 | f: movl $1, %eax | |
| 25 | ret | |
| 26 | ||
| 27 | ||
| 28 | .def g; | |
| 29 | .scl 3; | |
| 30 | .type 32; | |
| 31 | .endef | |
| 32 | .section .text,"xr",one_only,g | |
| 33 | .p2align 4 | |
| 34 | g: movl $2, %eax | |
| 35 | ret | |
| 36 | ||
| 37 | ||
| 38 | .def label; | |
| 39 | .scl 6; # StorageClass: Label | |
| 40 | .type 0; # Type: Not a function. | |
| 41 | .endef | |
| 42 | .section .text,"xr",one_only,label | |
| 43 | .p2align 4 | |
| 44 | label: ret | |
| 45 | ||
| 46 | ||
| 47 | .data | |
| 48 | .globl fp | |
| 49 | .p2align 4 | |
| 50 | fp: .quad f # DIR32 relocation to function | |
| 51 | .quad label # DIR32 relocation to label | |
| 52 | ||
| 53 | ||
| 54 | .def main; | |
| 55 | .scl 2; | |
| 56 | .type 32; | |
| 57 | .endef | |
| 58 | .section .text,"xr",one_only,main | |
| 59 | .globl main | |
| 60 | .p2align 4 | |
| 61 | main: call *fp # DIR32 relocation to data | |
| 62 | call g # REL32 relocation to function | |
| 63 | ret | |
| 64 | ||
| 65 | ||
| 66 | # Load configuration directory entry (winnt.h _IMAGE_LOAD_CONFIG_DIRECTORY64). | |
| 67 | # The linker will define the __guard_* symbols. | |
| 68 | .section .rdata,"dr" | |
| 69 | .globl _load_config_used | |
| 70 | _load_config_used: | |
| 71 | .long 256 | |
| 72 | .fill 124, 1, 0 | |
| 73 | .quad __guard_fids_table | |
| 74 | .quad __guard_fids_count | |
| 75 | .long __guard_flags | |
| 76 | .fill 128, 1, 0 |
deps/lld/test/COFF/gnu-weak.test created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | RUN: lld-link -lldmingw %S/Inputs/gnu-weak.o %S/Inputs/gnu-weak2.o -out:%t.exe | |
| 2 | ||
| 3 | GNU ld can handle several definitions of the same weak symbol, and | |
| 4 | unless there is a strong definition of it, it just picks the first | |
| 5 | weak definition encountered. | |
| 6 | ||
| 7 | For each of the weak definitions, GNU tools produce a regular symbol | |
| 8 | named .weak.<weaksymbol>.<othersymbol>, where the other symbol name is | |
| 9 | another symbol defined close by. | |
| 10 | ||
| 11 | This can't be reproduced by assembling with llvm-mc, as llvm-mc always | |
| 12 | produces similar regular symbols named .weak.<weaksymbol>.default. | |
| 13 | ||
| 14 | The bundled object files can be produced from test code that looks like | |
| 15 | this: | |
| 16 | ||
| 17 | $ cat gnu-weak.c | |
| 18 | void weakfunc(void) __attribute__((weak)); | |
| 19 | void otherfunc(void); | |
| 20 | ||
| 21 | __attribute__((weak)) void weakfunc() { | |
| 22 | } | |
| 23 | ||
| 24 | int main(int argc, char* argv[]) { | |
| 25 | otherfunc(); | |
| 26 | weakfunc(); | |
| 27 | return 0; | |
| 28 | } | |
| 29 | void mainCRTStartup(void) { | |
| 30 | main(0, (char**)0); | |
| 31 | } | |
| 32 | void __main(void) { | |
| 33 | } | |
| 34 | ||
| 35 | $ cat gnu-weak2.c | |
| 36 | void weakfunc(void) __attribute__((weak)); | |
| 37 | ||
| 38 | __attribute__((weak)) void weakfunc() { | |
| 39 | } | |
| 40 | ||
| 41 | void otherfunc(void) { | |
| 42 | } | |
| 43 | ||
| 44 | $ x86_64-w64-mingw32-gcc -c -O2 gnu-weak.c | |
| 45 | $ x86_64-w64-mingw32-gcc -c -O2 gnu-weak2.c | |
| 46 | ||
| 47 | $ x86_64-w64-mingw32-nm gnu-weak.o | grep weakfunc | |
| 48 | 0000000000000000 T .weak.weakfunc.main | |
| 49 | w weakfunc | |
| 50 | $ x86_64-w64-mingw32-nm gnu-weak2.o | grep weakfunc | |
| 51 | 0000000000000000 T .weak.weakfunc.otherfunc | |
| 52 | w weakfunc |
deps/lld/test/COFF/header-size.s created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-windows %s -o %t.obj | |
| 3 | // RUN: lld-link -entry:main -subsystem:console %t.obj -out:%t.exe | |
| 4 | // RUN: llvm-readobj -sections %t.exe | FileCheck %s | |
| 5 | .globl main | |
| 6 | main: | |
| 7 | ret | |
| 8 | ||
| 9 | // Check that the first section data comes at 512 bytes in the file. | |
| 10 | // If the size allocated for headers would include size for section | |
| 11 | // headers which aren't written, PointerToRawData would be 0x400 instead. | |
| 12 | // CHECK: PointerToRawData: 0x200 |
deps/lld/test/COFF/icf-safe.s created+37| ... | ... | @@ -0,0 +1,37 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-win32 %s -o %t1.obj | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-win32 %S/Inputs/icf-safe.s -o %t2.obj | |
| 4 | # RUN: lld-link /dll /noentry /out:%t.dll /verbose /opt:noref,icf %t1.obj %t2.obj 2>&1 | FileCheck %s | |
| 5 | # RUN: lld-link /dll /noentry /out:%t.dll /verbose /opt:noref,icf /export:g3 /export:g4 %t1.obj %t2.obj 2>&1 | FileCheck --check-prefix=EXPORT %s | |
| 6 | ||
| 7 | # CHECK-NOT: Selected | |
| 8 | # CHECK: Selected g3 | |
| 9 | # CHECK-NEXT: Removed g4 | |
| 10 | # CHECK-NOT: Removed | |
| 11 | # CHECK-NOT: Selected | |
| 12 | ||
| 13 | # EXPORT-NOT: Selected | |
| 14 | ||
| 15 | .section .rdata,"dr",one_only,g1 | |
| 16 | .globl g1 | |
| 17 | g1: | |
| 18 | .byte 1 | |
| 19 | ||
| 20 | .section .rdata,"dr",one_only,g2 | |
| 21 | .globl g2 | |
| 22 | g2: | |
| 23 | .byte 1 | |
| 24 | ||
| 25 | .section .rdata,"dr",one_only,g3 | |
| 26 | .globl g3 | |
| 27 | g3: | |
| 28 | .byte 2 | |
| 29 | ||
| 30 | .section .rdata,"dr",one_only,g4 | |
| 31 | .globl g4 | |
| 32 | g4: | |
| 33 | .byte 2 | |
| 34 | ||
| 35 | .addrsig | |
| 36 | .addrsig_sym g1 | |
| 37 | .addrsig_sym g2 |
deps/lld/test/COFF/ignore-many.test created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | Tests /ignore with more than one argument. | |
| 2 | ||
| 3 | RUN: yaml2obj %S/ignore4217.yaml > %t1.obj | |
| 4 | RUN: yaml2obj %S/Inputs/pdb-type-server-missing-2.yaml > %t2.obj | |
| 5 | RUN: echo foo > %t3.order | |
| 6 | ||
| 7 | RUN: lld-link /entry:main /out:%t.exe %t1.obj %t2.obj /order:@%t3.order /debug 2>&1 | FileCheck -check-prefix=WARNINGS %s | |
| 8 | RUN: lld-link /entry:main /out:%t.exe %t1.obj %t2.obj /order:@%t3.order /debug /ignore:4217,4099,4037 2>&1 | FileCheck -allow-empty -check-prefix=SUPPRESSED %s | |
| 9 | ||
| 10 | WARNINGS: locally defined symbol imported | |
| 11 | WARNINGS: missing symbol: foo | |
| 12 | WARNINGS: warning: Cannot use debug info for | |
| 13 | ||
| 14 | SUPPRESSED-NOT: locally defined symbol imported | |
| 15 | SUPPRESSED-NOT: missing symbol: foo | |
| 16 | SUPPRESSED-NOT: warning: Cannot use debug info for |
deps/lld/test/COFF/imports-gnu-autoexport.s created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # | |
| 3 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-head.s -filetype=obj -o %t-dabcdh.o | |
| 4 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-func.s -filetype=obj -o %t-dabcds00000.o | |
| 5 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-tail.s -filetype=obj -o %t-dabcdt.o | |
| 6 | # RUN: rm -f %t-implib.a | |
| 7 | # RUN: llvm-ar rcs %t-implib.a %t-dabcdh.o %t-dabcds00000.o %t-dabcdt.o | |
| 8 | # RUN: lld-link -lldmingw -dll -out:%t.dll -entry:main -subsystem:console \ | |
| 9 | # RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib %t-implib.a -include:func | |
| 10 | # RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix=EXPORT %s | |
| 11 | ||
| 12 | # Check that only the single normal symbol was exported, none of the symbols | |
| 13 | # from the import library. | |
| 14 | ||
| 15 | EXPORT: Export { | |
| 16 | EXPORT-NEXT: Ordinal: 0 | |
| 17 | EXPORT-NEXT: Name: | |
| 18 | EXPORT-NEXT: RVA: 0x0 | |
| 19 | EXPORT-NEXT: } | |
| 20 | EXPORT-NEXT: Export { | |
| 21 | EXPORT-NEXT: Ordinal: 1 | |
| 22 | EXPORT-NEXT: Name: main | |
| 23 | EXPORT-NEXT: RVA: 0x1010 | |
| 24 | EXPORT-NEXT: } | |
| 25 | EXPORT-NEXT-EMPTY: |
deps/lld/test/COFF/imports-gnu-only.s created+28| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # | |
| 3 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-head.s -filetype=obj -o %t-dabcdh.o | |
| 4 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-func.s -filetype=obj -o %t-dabcds00000.o | |
| 5 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-tail.s -filetype=obj -o %t-dabcdt.o | |
| 6 | # RUN: rm -f %t-implib.a | |
| 7 | # RUN: llvm-ar rcs %t-implib.a %t-dabcdh.o %t-dabcds00000.o %t-dabcdt.o | |
| 8 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj | |
| 9 | # RUN: lld-link -out:%t.exe -entry:main -subsystem:console \ | |
| 10 | # RUN: %t.obj %t-implib.a | |
| 11 | # RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=DATA %s | |
| 12 | ||
| 13 | .text | |
| 14 | .global main | |
| 15 | main: | |
| 16 | call func | |
| 17 | ret | |
| 18 | ||
| 19 | # Check that the linker inserted the null terminating import descriptor, | |
| 20 | # even if there were no normal import libraries, only gnu ones. | |
| 21 | ||
| 22 | # DATA: Contents of section .rdata: | |
| 23 | # First import descriptor | |
| 24 | # DATA: 140002000 28200000 00000000 00000000 53200000 | |
| 25 | # Last word from first import descriptor, null terminator descriptor | |
| 26 | # DATA: 140002010 38200000 00000000 00000000 00000000 | |
| 27 | # Null terminator descriptor and import lookup table. | |
| 28 | # DATA: 140002020 00000000 00000000 48200000 00000000 |
deps/lld/test/COFF/imports-gnu.test created+29| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # Verify that the lld can link to GNU import libs. | |
| 3 | # | |
| 4 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-head.s -filetype=obj -o %t-dabcdh.o | |
| 5 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-func.s -filetype=obj -o %t-dabcds00000.o | |
| 6 | # RUN: llvm-mc -triple=x86_64-windows-gnu %p/Inputs/gnu-implib-tail.s -filetype=obj -o %t-dabcdt.o | |
| 7 | # RUN: rm -f %t-implib.a | |
| 8 | # RUN: llvm-ar rcs %t-implib.a %t-dabcdh.o %t-dabcds00000.o %t-dabcdt.o | |
| 9 | # Not linking with -lldmingw; one can link to GNU import libs even if not targeting MinGW. | |
| 10 | # RUN: lld-link -out:%t.exe -entry:main -subsystem:console \ | |
| 11 | # RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib %t-implib.a -include:func | |
| 12 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s | |
| 13 | ||
| 14 | # Check that import entries from both libraries show up. | |
| 15 | ||
| 16 | IMPORT: Import { | |
| 17 | IMPORT-NEXT: Name: foo.dll | |
| 18 | IMPORT-NEXT: ImportLookupTableRVA: | |
| 19 | IMPORT-NEXT: ImportAddressTableRVA: | |
| 20 | IMPORT-NEXT: Symbol: func (0) | |
| 21 | IMPORT-NEXT: } | |
| 22 | IMPORT-NEXT: Import { | |
| 23 | IMPORT-NEXT: Name: std64.dll | |
| 24 | IMPORT-NEXT: ImportLookupTableRVA: | |
| 25 | IMPORT-NEXT: ImportAddressTableRVA: | |
| 26 | IMPORT-NEXT: Symbol: ExitProcess (0) | |
| 27 | IMPORT-NEXT: Symbol: (50) | |
| 28 | IMPORT-NEXT: Symbol: MessageBoxA (1) | |
| 29 | IMPORT-NEXT: } |
deps/lld/test/COFF/imports.test+13| ... | ... | @@ -34,3 +34,16 @@ IMPORT-NEXT: Symbol: ExitProcess (0) |
| 34 | 34 | IMPORT-NEXT: Symbol: (50) |
| 35 | 35 | IMPORT-NEXT: Symbol: MessageBoxA (1) |
| 36 | 36 | IMPORT-NEXT: } |
| 37 | ||
| 38 | # RUN: lld-link /out:%t.exe /entry:main /subsystem:console /merge:.rdata=.text \ | |
| 39 | # RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /include:ExitProcess | |
| 40 | # RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=MERGE %s | |
| 41 | ||
| 42 | MERGE: Import { | |
| 43 | MERGE-NEXT: Name: std64.dll | |
| 44 | MERGE-NEXT: ImportLookupTableRVA: 0x1090 | |
| 45 | MERGE-NEXT: ImportAddressTableRVA: 0x10B0 | |
| 46 | MERGE-NEXT: Symbol: ExitProcess (0) | |
| 47 | MERGE-NEXT: Symbol: (50) | |
| 48 | MERGE-NEXT: Symbol: MessageBoxA (1) | |
| 49 | MERGE-NEXT: } |
deps/lld/test/COFF/invalid-debug-type.test+2-1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj |
| 2 | 2 | # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj |
| 3 | 3 | # RUN: lld-link /debug /debugtype:invalid /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ |
| 4 | # RUN: %t1.obj %t2.obj | |
| 4 | # RUN: %t1.obj %t2.obj 2>&1 | FileCheck %s | |
| 5 | 5 | |
| 6 | # CHECK: /debugtype: unknown option: invalid | |
| \ No newline at end of file |
deps/lld/test/COFF/invalid-debug.test created+6| ... | ... | @@ -0,0 +1,6 @@ |
| 1 | # RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj | |
| 2 | # RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj | |
| 3 | # RUN: not lld-link /debug /debug:invalid /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \ | |
| 4 | # RUN: %t1.obj %t2.obj 2>&1 | FileCheck %s | |
| 5 | ||
| 6 | # CHECK: /debug: unknown option: invalid |
deps/lld/test/COFF/libname-mingw.test created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | # RUN: mkdir -p %t/a | |
| 2 | # RUN: cp %p/Inputs/std64.lib %t/a/libstd64.a | |
| 3 | ||
| 4 | # RUN: lld-link /lldmingw /out:%t.exe /entry:main /verbose \ | |
| 5 | # RUN: /defaultlib:std64.lib /subsystem:console %p/Inputs/hello64.obj \ | |
| 6 | # RUN: /libpath:%t/a 2>&1 | FileCheck %s | |
| 7 | ||
| 8 | CHECK: a{{[/\\]}}libstd64.a |
deps/lld/test/COFF/line-error.yaml created+160| ... | ... | @@ -0,0 +1,160 @@ |
| 1 | # RUN: yaml2obj %s -o %t.obj | |
| 2 | # RUN: not lld-link %t.obj /subsystem:console 2>&1 | FileCheck %s | |
| 3 | ||
| 4 | # CHECK: lld-link: error: undefined symbol: function | |
| 5 | # CHECK-NEXT: >>> referenced by {{.*}}line-error.yaml.tmp.obj:(caller1) | |
| 6 | # CHECK-NEXT: >>> referenced by E:\file.cpp:1935 | |
| 7 | # CHECK-NEXT: >>> {{.*}}line-error.yaml.tmp.obj:(caller22) | |
| 8 | ||
| 9 | --- !COFF | |
| 10 | header: | |
| 11 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 12 | Characteristics: [ ] | |
| 13 | sections: | |
| 14 | - Name: .text | |
| 15 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 16 | Alignment: 16 | |
| 17 | SectionData: 488B0500000000488B51284881C2D80000004889C148FF2500000000 | |
| 18 | Relocations: | |
| 19 | - VirtualAddress: 3 | |
| 20 | SymbolName: function | |
| 21 | Type: IMAGE_REL_AMD64_REL32 | |
| 22 | - Name: .text | |
| 23 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 24 | Alignment: 16 | |
| 25 | SectionData: 488B0500000000488B51084881C2D80000004889C148FF2500000000 | |
| 26 | Relocations: | |
| 27 | - VirtualAddress: 3 | |
| 28 | SymbolName: function | |
| 29 | Type: IMAGE_REL_AMD64_REL32 | |
| 30 | - Name: '.debug$S' | |
| 31 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 32 | Alignment: 4 | |
| 33 | Subsections: | |
| 34 | - !FileChecksums | |
| 35 | Checksums: | |
| 36 | - FileName: 'E:\file.cpp' | |
| 37 | Kind: MD5 | |
| 38 | Checksum: D72EDEF8B8E50C364A330F9CB3CD904B | |
| 39 | - !StringTable | |
| 40 | Strings: | |
| 41 | - 'E:\file.cpp' | |
| 42 | - Name: '.debug$S' | |
| 43 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 44 | Alignment: 4 | |
| 45 | Subsections: | |
| 46 | - !Lines | |
| 47 | CodeSize: 28 | |
| 48 | Flags: [ ] | |
| 49 | RelocOffset: 0 | |
| 50 | RelocSegment: 0 | |
| 51 | Blocks: [] | |
| 52 | Relocations: | |
| 53 | - VirtualAddress: 12 | |
| 54 | SymbolName: caller1 | |
| 55 | Type: IMAGE_REL_AMD64_SECREL | |
| 56 | - Name: '.debug$S' | |
| 57 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 58 | Alignment: 4 | |
| 59 | Subsections: | |
| 60 | - !Lines | |
| 61 | CodeSize: 28 | |
| 62 | Flags: [ ] | |
| 63 | RelocOffset: 0 | |
| 64 | RelocSegment: 0 | |
| 65 | Blocks: | |
| 66 | - FileName: 'E:\file.cpp' | |
| 67 | Lines: | |
| 68 | - Offset: 11 | |
| 69 | LineStart: 1935 | |
| 70 | IsStatement: false | |
| 71 | EndDelta: 0 | |
| 72 | Columns: [] | |
| 73 | Relocations: | |
| 74 | - VirtualAddress: 12 | |
| 75 | SymbolName: caller22 | |
| 76 | Type: IMAGE_REL_AMD64_SECREL | |
| 77 | symbols: | |
| 78 | - Name: .text | |
| 79 | Value: 0 | |
| 80 | SectionNumber: 1 | |
| 81 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 82 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 83 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 84 | SectionDefinition: | |
| 85 | Length: 28 | |
| 86 | NumberOfRelocations: 2 | |
| 87 | NumberOfLinenumbers: 0 | |
| 88 | CheckSum: 2430089736 | |
| 89 | Number: 1 | |
| 90 | Selection: IMAGE_COMDAT_SELECT_NODUPLICATES | |
| 91 | - Name: caller1 | |
| 92 | Value: 0 | |
| 93 | SectionNumber: 1 | |
| 94 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 95 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | |
| 96 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 97 | - Name: .text | |
| 98 | Value: 0 | |
| 99 | SectionNumber: 2 | |
| 100 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 101 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 102 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 103 | SectionDefinition: | |
| 104 | Length: 28 | |
| 105 | NumberOfRelocations: 2 | |
| 106 | NumberOfLinenumbers: 0 | |
| 107 | CheckSum: 3449717304 | |
| 108 | Number: 2 | |
| 109 | Selection: IMAGE_COMDAT_SELECT_NODUPLICATES | |
| 110 | - Name: caller22 | |
| 111 | Value: 0 | |
| 112 | SectionNumber: 2 | |
| 113 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 114 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | |
| 115 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 116 | - Name: '.debug$S' | |
| 117 | Value: 0 | |
| 118 | SectionNumber: 3 | |
| 119 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 120 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 121 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 122 | SectionDefinition: | |
| 123 | Length: 767204 | |
| 124 | NumberOfRelocations: 0 | |
| 125 | NumberOfLinenumbers: 0 | |
| 126 | CheckSum: 4280093374 | |
| 127 | Number: 3 | |
| 128 | - Name: '.debug$S' | |
| 129 | Value: 0 | |
| 130 | SectionNumber: 4 | |
| 131 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 132 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 133 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 134 | SectionDefinition: | |
| 135 | Length: 296 | |
| 136 | NumberOfRelocations: 1 | |
| 137 | NumberOfLinenumbers: 0 | |
| 138 | CheckSum: 1957793731 | |
| 139 | Number: 1 | |
| 140 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | |
| 141 | - Name: '.debug$S' | |
| 142 | Value: 0 | |
| 143 | SectionNumber: 5 | |
| 144 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 145 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 146 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 147 | SectionDefinition: | |
| 148 | Length: 276 | |
| 149 | NumberOfRelocations: 1 | |
| 150 | NumberOfLinenumbers: 0 | |
| 151 | CheckSum: 1957793731 | |
| 152 | Number: 2 | |
| 153 | Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE | |
| 154 | - Name: function | |
| 155 | Value: 0 | |
| 156 | SectionNumber: 0 | |
| 157 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 158 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 159 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 160 | ... |
deps/lld/test/COFF/lto-cache.ll+2| ... | ... | @@ -1,4 +1,6 @@ |
| 1 | 1 | ; REQUIRES: x86 |
| 2 | ; NetBSD: noatime mounts currently inhibit 'touch' from updating atime | |
| 3 | ; UNSUPPORTED: system-netbsd | |
| 2 | 4 | |
| 3 | 5 | ; RUN: opt -module-hash -module-summary %s -o %t.o |
| 4 | 6 | ; RUN: opt -module-hash -module-summary %p/Inputs/lto-cache.ll -o %t2.o |
deps/lld/test/COFF/lto-chkstk.ll+1| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | ; RUN: llvm-as -o %t.obj %s |
| 3 | 3 | ; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %T/lto-chkstk-foo.obj %S/Inputs/lto-chkstk-foo.s |
| 4 | 4 | ; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %T/lto-chkstk-chkstk.obj %S/Inputs/lto-chkstk-chkstk.s |
| 5 | ; RUN: rm -f %t.lib | |
| 5 | 6 | ; RUN: llvm-ar cru %t.lib %T/lto-chkstk-chkstk.obj |
| 6 | 7 | ; RUN: lld-link /out:%t.exe /entry:main /subsystem:console %t.obj %T/lto-chkstk-foo.obj %t.lib |
| 7 | 8 |
deps/lld/test/COFF/lto-cpu-string.ll created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | ; REQUIRES: x86 | |
| 2 | ; RUN: llvm-as %s -o %t.obj | |
| 3 | ||
| 4 | ; RUN: lld-link %t.obj -noentry -nodefaultlib -out:%t.dll -dll | |
| 5 | ; RUN: llvm-objdump -d -section=".text" -no-leading-addr -no-show-raw-insn %t.dll | FileCheck %s | |
| 6 | ; CHECK: nop{{$}} | |
| 7 | ||
| 8 | ; RUN: lld-link -mllvm:-mcpu=znver1 -noentry -nodefaultlib %t.obj -out:%t.znver1.dll -dll | |
| 9 | ; RUN: llvm-objdump -d -section=".text" -no-leading-addr -no-show-raw-insn %t.znver1.dll | FileCheck -check-prefix=ZNVER1 %s | |
| 10 | ; ZNVER1: nopw | |
| 11 | ||
| 12 | target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" | |
| 13 | target triple = "x86_64-pc-windows-msvc19.14.26433" | |
| 14 | ||
| 15 | define dllexport void @foo() #0 { | |
| 16 | entry: | |
| 17 | call void asm sideeffect ".p2align 4, 0x90", "~{dirflag},~{fpsr},~{flags}"() | |
| 18 | ret void | |
| 19 | } | |
| 20 | ||
| 21 | attributes #0 = { "no-frame-pointer-elim"="true" } |
deps/lld/test/COFF/msvclto-archive.ll deleted-40| ... | ... | @@ -1,40 +0,0 @@ |
| 1 | ; REQUIRES: x86 | |
| 2 | ;; Make sure we re-create archive files to strip bitcode files. | |
| 3 | ||
| 4 | ;; Do not create empty archives because the MSVC linker | |
| 5 | ;; doesn't support them. | |
| 6 | ; RUN: llvm-as -o %t.obj %s | |
| 7 | ; RUN: rm -f %t-main1.a | |
| 8 | ; RUN: llvm-ar cru %t-main1.a %t.obj | |
| 9 | ; RUN: mkdir -p %t.dir | |
| 10 | ; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t.dir/bitcode.obj %p/Inputs/msvclto.s | |
| 11 | ; RUN: lld-link %t-main1.a %t.dir/bitcode.obj /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ | |
| 12 | ; RUN: /entry:main /verbose 2> %t.log || true | |
| 13 | ; RUN: FileCheck -check-prefix=BC %s < %t.log | |
| 14 | ; BC-NOT: Creating a temporary archive for | |
| 15 | ||
| 16 | ; RUN: rm -f %t-main2.a | |
| 17 | ; RUN: llvm-ar cru %t-main2.a %t.dir/bitcode.obj | |
| 18 | ; RUN: lld-link %t.obj %t-main2.a /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ | |
| 19 | ; RUN: /entry:main /verbose 2> %t.log || true | |
| 20 | ; RUN: FileCheck -check-prefix=OBJ %s < %t.log | |
| 21 | ; OBJ-NOT: Creating a temporary archive | |
| 22 | ||
| 23 | ;; Make sure that we always rebuild thin archives because | |
| 24 | ;; the MSVC linker doesn't support thin archives. | |
| 25 | ; RUN: rm -f %t-main3.a | |
| 26 | ; RUN: llvm-ar cruT %t-main3.a %t.dir/bitcode.obj | |
| 27 | ; RUN: lld-link %t.obj %t-main3.a /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ | |
| 28 | ; RUN: /entry:main /verbose 2> %t.log || true | |
| 29 | ; RUN: FileCheck -check-prefix=THIN %s < %t.log | |
| 30 | ; THIN: Creating a temporary archive | |
| 31 | ||
| 32 | target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" | |
| 33 | target triple = "x86_64-pc-windows-msvc" | |
| 34 | ||
| 35 | declare void @foo() | |
| 36 | ||
| 37 | define i32 @main() { | |
| 38 | call void @foo() | |
| 39 | ret i32 0 | |
| 40 | } |
deps/lld/test/COFF/msvclto-order.ll deleted-25| ... | ... | @@ -1,25 +0,0 @@ |
| 1 | ; REQUIRES: x86 | |
| 2 | ; RUN: opt -thinlto-bc %s -o %t.obj | |
| 3 | ; RUN: llc -filetype=obj %S/Inputs/msvclto-order-a.ll -o %T/msvclto-order-a.obj | |
| 4 | ; RUN: llvm-ar crs %T/msvclto-order-a.lib %T/msvclto-order-a.obj | |
| 5 | ; RUN: llc -filetype=obj %S/Inputs/msvclto-order-b.ll -o %T/msvclto-order-b.obj | |
| 6 | ; RUN: llvm-ar crs %T/msvclto-order-b.lib %T/msvclto-order-b.obj | |
| 7 | ; RUN: lld-link /verbose /msvclto /out:%t.exe /entry:main %t.obj \ | |
| 8 | ; RUN: %T/msvclto-order-a.lib %T/msvclto-order-b.lib 2> %t.log || true | |
| 9 | ; RUN: FileCheck %s < %t.log | |
| 10 | ||
| 11 | ; CHECK: : link.exe | |
| 12 | ; CHECK-NOT: .lib{{$}} | |
| 13 | ; CHECK: lld-msvclto-order-a{{.*}}.obj | |
| 14 | ; CHECK-NOT: lld-msvclto-order-b{{.*}}.obj | |
| 15 | ; CHECK: .lib{{$}} | |
| 16 | ||
| 17 | target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" | |
| 18 | target triple = "x86_64-pc-windows-msvc" | |
| 19 | ||
| 20 | declare void @foo() | |
| 21 | ||
| 22 | define i32 @main() { | |
| 23 | call void @foo() | |
| 24 | ret i32 0 | |
| 25 | } |
deps/lld/test/COFF/msvclto.ll deleted-20| ... | ... | @@ -1,20 +0,0 @@ |
| 1 | ; REQUIRES: x86 | |
| 2 | ; RUN: llvm-as -o %t.obj %s | |
| 3 | ; RUN: mkdir -p %t.dir | |
| 4 | ; RUN: llvm-mc -triple=x86_64-pc-windows-msvc -filetype=obj -o %t.dir/bitcode.obj %p/Inputs/msvclto.s | |
| 5 | ; RUN: lld-link %t.obj %t.dir/bitcode.obj /msvclto /out:%t.exe /opt:lldlto=1 /opt:icf \ | |
| 6 | ; RUN: /entry:main /verbose 2> %t.log || true | |
| 7 | ; RUN: FileCheck %s < %t.log | |
| 8 | ||
| 9 | ; CHECK: /opt:icf /entry:main | |
| 10 | ; CHECK: /verbose | |
| 11 | ||
| 12 | target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" | |
| 13 | target triple = "x86_64-pc-windows-msvc" | |
| 14 | ||
| 15 | declare void @foo() | |
| 16 | ||
| 17 | define i32 @main() { | |
| 18 | call void @foo() | |
| 19 | ret i32 0 | |
| 20 | } |
deps/lld/test/COFF/no-idata.s created+20| ... | ... | @@ -0,0 +1,20 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # | |
| 3 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj | |
| 4 | # RUN: lld-link -out:%t.exe -entry:main -subsystem:console %t.obj | |
| 5 | # RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=DUMP %s | |
| 6 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DIRECTORY %s | |
| 7 | ||
| 8 | .text | |
| 9 | .global main | |
| 10 | main: | |
| 11 | ret | |
| 12 | ||
| 13 | # Check that no .idata (.rdata) entries were added, no null terminator | |
| 14 | # for the import descriptor table. | |
| 15 | # DUMP: Contents of section .text: | |
| 16 | # DUMP-NEXT: 140001000 c3 | |
| 17 | # DUMP-NEXT-EMPTY: | |
| 18 | ||
| 19 | # DIRECTORY: ImportTableRVA: 0x0 | |
| 20 | # DIRECTORY: ImportTableSize: 0x0 |
deps/lld/test/COFF/pdb-debug-f.s created+28| ... | ... | @@ -0,0 +1,28 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -triple=i386-pc-win32 -filetype=obj -o %t.obj %s | |
| 3 | # RUN: lld-link /subsystem:console /debug /nodefaultlib /entry:foo /out:%t.exe /pdb:%t.pdb %t.obj | |
| 4 | # RUN: llvm-pdbutil dump -fpo %t.pdb | FileCheck %s | |
| 5 | ||
| 6 | # CHECK: Old FPO Data | |
| 7 | # CHECK-NEXT: ============================================================ | |
| 8 | # CHECK-NEXT: RVA | Code | Locals | Params | Prolog | Saved Regs | Use BP | Has SEH | Frame Type | |
| 9 | # CHECK-NEXT: 00001002 | 1 | 2 | 3 | 4 | 0 | false | false | FPO | |
| 10 | ||
| 11 | .text | |
| 12 | _foo: | |
| 13 | ret | |
| 14 | ||
| 15 | .global _foo | |
| 16 | ||
| 17 | .section .debug$F,"dr" | |
| 18 | 	.long _foo@IMGREL+2 | |
| 19 | 	.long 1 # cbProc | |
| 20 | 	.long 2 # cdwLocals; | |
| 21 | 	.short 3 # cdwParams; | |
| 22 | 	.short 4 # flags | |
| 23 | # cbProlog : 8; | |
| 24 | # cbRegs : 3; | |
| 25 | # fHasSEH : 1; | |
| 26 | # fUseBP : 1; | |
| 27 | # reserved : 1; | |
| 28 | # cbFrame : 2; | |
| \ No newline at end of file |
deps/lld/test/COFF/pdb-framedata.yaml created+462| ... | ... | @@ -0,0 +1,462 @@ |
| 1 | # // Compile with clang-cl -m32 /Z7 /GS- /c t.obj pdb-framedata.cpp | |
| 2 | # | |
| 3 | # int func(int x, int y) { | |
| 4 | # return x + y; | |
| 5 | # } | |
| 6 | # | |
| 7 | # int main(int argc, char **argv) { | |
| 8 | # return func(argc, argc+1); | |
| 9 | # } | |
| 10 | ||
| 11 | # RUN: yaml2obj %s -o %t.obj | |
| 12 | # RUN: lld-link %t.obj -debug -entry:main -nodefaultlib -debug -out:%t.exe -pdb:%t.pdb | |
| 13 | # RUN: llvm-pdbutil dump -fpo %t.pdb | FileCheck %s | |
| 14 | ||
| 15 | # CHECK: New FPO Data | |
| 16 | # CHECK-NEXT: ============================================================ | |
| 17 | # CHECK-NEXT: RVA | Code | Locals | Params | Stack | Prolog | Saved Regs | Has SEH | Has C++EH | Start | Program | |
| 18 | # CHECK-NEXT: 00001000 | 31 | 0 | 8 | 0 | 6 | 0 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = | |
| 19 | # CHECK-NEXT: 00001001 | 30 | 0 | 8 | 0 | 5 | 4 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = | |
| 20 | # CHECK-NEXT: 00001003 | 28 | 0 | 8 | 0 | 3 | 4 | false | false | false | $T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = | |
| 21 | # CHECK-NEXT: 00001020 | 53 | 0 | 8 | 0 | 7 | 0 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = | |
| 22 | # CHECK-NEXT: 00001021 | 52 | 0 | 8 | 0 | 6 | 4 | false | false | false | $T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = | |
| 23 | # CHECK-NEXT: 00001023 | 50 | 0 | 8 | 0 | 4 | 4 | false | false | false | $T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = | |
| 24 | # CHECK-NEXT: 00001024 | 49 | 0 | 8 | 0 | 3 | 8 | false | false | false | $T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $esi $T0 8 - ^ = | |
| 25 | ||
| 26 | ||
| 27 | --- !COFF | |
| 28 | header: | |
| 29 | Machine: IMAGE_FILE_MACHINE_I386 | |
| 30 | Characteristics: [ ] | |
| 31 | sections: | |
| 32 | - Name: .text | |
| 33 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 34 | Alignment: 16 | |
| 35 | SectionData: 5589E583EC088B450C8B4D088B550803550C8945FC89D0894DF883C4085DC3905589E55683EC148B450C8B4D08C745F8000000008B550883C2018B7508893424895424048945F4894DF0E80000000083C4145E5DC3 | |
| 36 | Relocations: | |
| 37 | - VirtualAddress: 75 | |
| 38 | SymbolName: '?func@@YAHHH@Z' | |
| 39 | Type: IMAGE_REL_I386_REL32 | |
| 40 | - Name: .data | |
| 41 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | |
| 42 | Alignment: 4 | |
| 43 | SectionData: '' | |
| 44 | - Name: .bss | |
| 45 | Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ] | |
| 46 | Alignment: 4 | |
| 47 | SectionData: '' | |
| 48 | - Name: .drectve | |
| 49 | Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ] | |
| 50 | Alignment: 1 | |
| 51 | SectionData: 202F44454641554C544C49423A6C6962636D742E6C6962202F44454641554C544C49423A6F6C646E616D65732E6C6962 | |
| 52 | - Name: '.debug$S' | |
| 53 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 54 | Alignment: 4 | |
| 55 | Subsections: | |
| 56 | - !Symbols | |
| 57 | Records: | |
| 58 | - Kind: S_COMPILE3 | |
| 59 | Compile3Sym: | |
| 60 | Flags: [ ] | |
| 61 | Machine: Pentium3 | |
| 62 | FrontendMajor: 8 | |
| 63 | FrontendMinor: 0 | |
| 64 | FrontendBuild: 0 | |
| 65 | FrontendQFE: 0 | |
| 66 | BackendMajor: 8000 | |
| 67 | BackendMinor: 0 | |
| 68 | BackendBuild: 0 | |
| 69 | BackendQFE: 0 | |
| 70 | Version: 'clang version 8.0.0 ' | |
| 71 | - !FrameData | |
| 72 | Frames: | |
| 73 | - CodeSize: 31 | |
| 74 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | |
| 75 | LocalSize: 0 | |
| 76 | MaxStackSize: 0 | |
| 77 | ParamsSize: 8 | |
| 78 | PrologSize: 6 | |
| 79 | RvaStart: 0 | |
| 80 | SavedRegsSize: 0 | |
| 81 | - CodeSize: 30 | |
| 82 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | |
| 83 | LocalSize: 0 | |
| 84 | MaxStackSize: 0 | |
| 85 | ParamsSize: 8 | |
| 86 | PrologSize: 5 | |
| 87 | RvaStart: 1 | |
| 88 | SavedRegsSize: 4 | |
| 89 | - CodeSize: 28 | |
| 90 | FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | |
| 91 | LocalSize: 0 | |
| 92 | MaxStackSize: 0 | |
| 93 | ParamsSize: 8 | |
| 94 | PrologSize: 3 | |
| 95 | RvaStart: 3 | |
| 96 | SavedRegsSize: 4 | |
| 97 | - !Symbols | |
| 98 | Records: | |
| 99 | - Kind: S_GPROC32_ID | |
| 100 | ProcSym: | |
| 101 | CodeSize: 31 | |
| 102 | DbgStart: 0 | |
| 103 | DbgEnd: 0 | |
| 104 | FunctionType: 4098 | |
| 105 | Flags: [ ] | |
| 106 | DisplayName: func | |
| 107 | - Kind: S_LOCAL | |
| 108 | LocalSym: | |
| 109 | Type: 116 | |
| 110 | Flags: [ IsParameter ] | |
| 111 | VarName: x | |
| 112 | - Kind: S_DEFRANGE_REGISTER_REL | |
| 113 | DefRangeRegisterRelSym: | |
| 114 | Register: 22 | |
| 115 | Flags: 0 | |
| 116 | BasePointerOffset: 8 | |
| 117 | Range: | |
| 118 | OffsetStart: 12 | |
| 119 | ISectStart: 0 | |
| 120 | Range: 19 | |
| 121 | Gaps: | |
| 122 | - Kind: S_LOCAL | |
| 123 | LocalSym: | |
| 124 | Type: 116 | |
| 125 | Flags: [ IsParameter ] | |
| 126 | VarName: y | |
| 127 | - Kind: S_DEFRANGE_REGISTER_REL | |
| 128 | DefRangeRegisterRelSym: | |
| 129 | Register: 22 | |
| 130 | Flags: 0 | |
| 131 | BasePointerOffset: 12 | |
| 132 | Range: | |
| 133 | OffsetStart: 12 | |
| 134 | ISectStart: 0 | |
| 135 | Range: 19 | |
| 136 | Gaps: | |
| 137 | - Kind: S_PROC_ID_END | |
| 138 | ScopeEndSym: | |
| 139 | - !Lines | |
| 140 | CodeSize: 31 | |
| 141 | Flags: [ ] | |
| 142 | RelocOffset: 0 | |
| 143 | RelocSegment: 0 | |
| 144 | Blocks: | |
| 145 | - FileName: 'D:\src\llvmbuild\cl\Debug\x64\pdb-framedata.cpp' | |
| 146 | Lines: | |
| 147 | - Offset: 0 | |
| 148 | LineStart: 3 | |
| 149 | IsStatement: false | |
| 150 | EndDelta: 0 | |
| 151 | - Offset: 12 | |
| 152 | LineStart: 4 | |
| 153 | IsStatement: false | |
| 154 | EndDelta: 0 | |
| 155 | Columns: | |
| 156 | - !FrameData | |
| 157 | Frames: | |
| 158 | - CodeSize: 53 | |
| 159 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | |
| 160 | LocalSize: 0 | |
| 161 | MaxStackSize: 0 | |
| 162 | ParamsSize: 8 | |
| 163 | PrologSize: 7 | |
| 164 | RvaStart: 0 | |
| 165 | SavedRegsSize: 0 | |
| 166 | - CodeSize: 52 | |
| 167 | FrameFunc: '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | |
| 168 | LocalSize: 0 | |
| 169 | MaxStackSize: 0 | |
| 170 | ParamsSize: 8 | |
| 171 | PrologSize: 6 | |
| 172 | RvaStart: 1 | |
| 173 | SavedRegsSize: 4 | |
| 174 | - CodeSize: 50 | |
| 175 | FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | |
| 176 | LocalSize: 0 | |
| 177 | MaxStackSize: 0 | |
| 178 | ParamsSize: 8 | |
| 179 | PrologSize: 4 | |
| 180 | RvaStart: 3 | |
| 181 | SavedRegsSize: 4 | |
| 182 | - CodeSize: 49 | |
| 183 | FrameFunc: '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $esi $T0 8 - ^ = ' | |
| 184 | LocalSize: 0 | |
| 185 | MaxStackSize: 0 | |
| 186 | ParamsSize: 8 | |
| 187 | PrologSize: 3 | |
| 188 | RvaStart: 4 | |
| 189 | SavedRegsSize: 8 | |
| 190 | - !Symbols | |
| 191 | Records: | |
| 192 | - Kind: S_GPROC32_ID | |
| 193 | ProcSym: | |
| 194 | CodeSize: 53 | |
| 195 | DbgStart: 0 | |
| 196 | DbgEnd: 0 | |
| 197 | FunctionType: 4102 | |
| 198 | Flags: [ ] | |
| 199 | DisplayName: main | |
| 200 | - Kind: S_LOCAL | |
| 201 | LocalSym: | |
| 202 | Type: 116 | |
| 203 | Flags: [ IsParameter ] | |
| 204 | VarName: argc | |
| 205 | - Kind: S_DEFRANGE_REGISTER_REL | |
| 206 | DefRangeRegisterRelSym: | |
| 207 | Register: 22 | |
| 208 | Flags: 0 | |
| 209 | BasePointerOffset: 8 | |
| 210 | Range: | |
| 211 | OffsetStart: 52 | |
| 212 | ISectStart: 0 | |
| 213 | Range: 33 | |
| 214 | Gaps: | |
| 215 | - Kind: S_LOCAL | |
| 216 | LocalSym: | |
| 217 | Type: 4099 | |
| 218 | Flags: [ IsParameter ] | |
| 219 | VarName: argv | |
| 220 | - Kind: S_DEFRANGE_REGISTER_REL | |
| 221 | DefRangeRegisterRelSym: | |
| 222 | Register: 22 | |
| 223 | Flags: 0 | |
| 224 | BasePointerOffset: 12 | |
| 225 | Range: | |
| 226 | OffsetStart: 52 | |
| 227 | ISectStart: 0 | |
| 228 | Range: 33 | |
| 229 | Gaps: | |
| 230 | - Kind: S_PROC_ID_END | |
| 231 | ScopeEndSym: | |
| 232 | - !Lines | |
| 233 | CodeSize: 53 | |
| 234 | Flags: [ ] | |
| 235 | RelocOffset: 0 | |
| 236 | RelocSegment: 0 | |
| 237 | Blocks: | |
| 238 | - FileName: 'D:\src\llvmbuild\cl\Debug\x64\pdb-framedata.cpp' | |
| 239 | Lines: | |
| 240 | - Offset: 0 | |
| 241 | LineStart: 7 | |
| 242 | IsStatement: false | |
| 243 | EndDelta: 0 | |
| 244 | - Offset: 20 | |
| 245 | LineStart: 8 | |
| 246 | IsStatement: false | |
| 247 | EndDelta: 0 | |
| 248 | Columns: | |
| 249 | - !FileChecksums | |
| 250 | Checksums: | |
| 251 | - FileName: 'D:\src\llvmbuild\cl\Debug\x64\pdb-framedata.cpp' | |
| 252 | Kind: MD5 | |
| 253 | Checksum: A611B73E19B77B02646FAAF7CAEB025D | |
| 254 | - !StringTable | |
| 255 | Strings: | |
| 256 | - 'D:\src\llvmbuild\cl\Debug\x64\pdb-framedata.cpp' | |
| 257 | - '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = ' | |
| 258 | - '$T0 .raSearch = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | |
| 259 | - '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = ' | |
| 260 | - '$T0 $ebp 4 + = $eip $T0 ^ = $esp $T0 4 + = $ebp $T0 4 - ^ = $esi $T0 8 - ^ = ' | |
| 261 | - '' | |
| 262 | Relocations: | |
| 263 | - VirtualAddress: 68 | |
| 264 | SymbolName: '?func@@YAHHH@Z' | |
| 265 | Type: IMAGE_REL_I386_DIR32NB | |
| 266 | - VirtualAddress: 208 | |
| 267 | SymbolName: '?func@@YAHHH@Z' | |
| 268 | Type: IMAGE_REL_I386_SECREL | |
| 269 | - VirtualAddress: 212 | |
| 270 | SymbolName: '?func@@YAHHH@Z' | |
| 271 | Type: IMAGE_REL_I386_SECTION | |
| 272 | - VirtualAddress: 244 | |
| 273 | SymbolName: .text | |
| 274 | Type: IMAGE_REL_I386_SECREL | |
| 275 | - VirtualAddress: 248 | |
| 276 | SymbolName: .text | |
| 277 | Type: IMAGE_REL_I386_SECTION | |
| 278 | - VirtualAddress: 276 | |
| 279 | SymbolName: .text | |
| 280 | Type: IMAGE_REL_I386_SECREL | |
| 281 | - VirtualAddress: 280 | |
| 282 | SymbolName: .text | |
| 283 | Type: IMAGE_REL_I386_SECTION | |
| 284 | - VirtualAddress: 296 | |
| 285 | SymbolName: '?func@@YAHHH@Z' | |
| 286 | Type: IMAGE_REL_I386_SECREL | |
| 287 | - VirtualAddress: 300 | |
| 288 | SymbolName: '?func@@YAHHH@Z' | |
| 289 | Type: IMAGE_REL_I386_SECTION | |
| 290 | - VirtualAddress: 344 | |
| 291 | SymbolName: _main | |
| 292 | Type: IMAGE_REL_I386_DIR32NB | |
| 293 | - VirtualAddress: 516 | |
| 294 | SymbolName: _main | |
| 295 | Type: IMAGE_REL_I386_SECREL | |
| 296 | - VirtualAddress: 520 | |
| 297 | SymbolName: _main | |
| 298 | Type: IMAGE_REL_I386_SECTION | |
| 299 | - VirtualAddress: 555 | |
| 300 | SymbolName: .text | |
| 301 | Type: IMAGE_REL_I386_SECREL | |
| 302 | - VirtualAddress: 559 | |
| 303 | SymbolName: .text | |
| 304 | Type: IMAGE_REL_I386_SECTION | |
| 305 | - VirtualAddress: 590 | |
| 306 | SymbolName: .text | |
| 307 | Type: IMAGE_REL_I386_SECREL | |
| 308 | - VirtualAddress: 594 | |
| 309 | SymbolName: .text | |
| 310 | Type: IMAGE_REL_I386_SECTION | |
| 311 | - VirtualAddress: 612 | |
| 312 | SymbolName: _main | |
| 313 | Type: IMAGE_REL_I386_SECREL | |
| 314 | - VirtualAddress: 616 | |
| 315 | SymbolName: _main | |
| 316 | Type: IMAGE_REL_I386_SECTION | |
| 317 | - Name: '.debug$T' | |
| 318 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 319 | Alignment: 4 | |
| 320 | Types: | |
| 321 | - Kind: LF_ARGLIST | |
| 322 | ArgList: | |
| 323 | ArgIndices: [ 116, 116 ] | |
| 324 | - Kind: LF_PROCEDURE | |
| 325 | Procedure: | |
| 326 | ReturnType: 116 | |
| 327 | CallConv: NearC | |
| 328 | Options: [ None ] | |
| 329 | ParameterCount: 2 | |
| 330 | ArgumentList: 4096 | |
| 331 | - Kind: LF_FUNC_ID | |
| 332 | FuncId: | |
| 333 | ParentScope: 0 | |
| 334 | FunctionType: 4097 | |
| 335 | Name: func | |
| 336 | - Kind: LF_POINTER | |
| 337 | Pointer: | |
| 338 | ReferentType: 1136 | |
| 339 | Attrs: 32778 | |
| 340 | - Kind: LF_ARGLIST | |
| 341 | ArgList: | |
| 342 | ArgIndices: [ 116, 4099 ] | |
| 343 | - Kind: LF_PROCEDURE | |
| 344 | Procedure: | |
| 345 | ReturnType: 116 | |
| 346 | CallConv: NearC | |
| 347 | Options: [ None ] | |
| 348 | ParameterCount: 2 | |
| 349 | ArgumentList: 4100 | |
| 350 | - Kind: LF_FUNC_ID | |
| 351 | FuncId: | |
| 352 | ParentScope: 0 | |
| 353 | FunctionType: 4101 | |
| 354 | Name: main | |
| 355 | - Name: .llvm_addrsig | |
| 356 | Characteristics: [ IMAGE_SCN_LNK_REMOVE ] | |
| 357 | Alignment: 1 | |
| 358 | SectionData: 0F | |
| 359 | symbols: | |
| 360 | - Name: .text | |
| 361 | Value: 0 | |
| 362 | SectionNumber: 1 | |
| 363 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 364 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 365 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 366 | SectionDefinition: | |
| 367 | Length: 85 | |
| 368 | NumberOfRelocations: 1 | |
| 369 | NumberOfLinenumbers: 0 | |
| 370 | CheckSum: 1989857796 | |
| 371 | Number: 1 | |
| 372 | - Name: .data | |
| 373 | Value: 0 | |
| 374 | SectionNumber: 2 | |
| 375 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 376 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 377 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 378 | SectionDefinition: | |
| 379 | Length: 0 | |
| 380 | NumberOfRelocations: 0 | |
| 381 | NumberOfLinenumbers: 0 | |
| 382 | CheckSum: 0 | |
| 383 | Number: 2 | |
| 384 | - Name: .bss | |
| 385 | Value: 0 | |
| 386 | SectionNumber: 3 | |
| 387 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 388 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 389 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 390 | SectionDefinition: | |
| 391 | Length: 0 | |
| 392 | NumberOfRelocations: 0 | |
| 393 | NumberOfLinenumbers: 0 | |
| 394 | CheckSum: 0 | |
| 395 | Number: 3 | |
| 396 | - Name: .drectve | |
| 397 | Value: 0 | |
| 398 | SectionNumber: 4 | |
| 399 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 400 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 401 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 402 | SectionDefinition: | |
| 403 | Length: 48 | |
| 404 | NumberOfRelocations: 0 | |
| 405 | NumberOfLinenumbers: 0 | |
| 406 | CheckSum: 149686238 | |
| 407 | Number: 4 | |
| 408 | - Name: '.debug$S' | |
| 409 | Value: 0 | |
| 410 | SectionNumber: 5 | |
| 411 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 412 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 413 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 414 | SectionDefinition: | |
| 415 | Length: 988 | |
| 416 | NumberOfRelocations: 18 | |
| 417 | NumberOfLinenumbers: 0 | |
| 418 | CheckSum: 2571438511 | |
| 419 | Number: 5 | |
| 420 | - Name: '.debug$T' | |
| 421 | Value: 0 | |
| 422 | SectionNumber: 6 | |
| 423 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 424 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 425 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 426 | SectionDefinition: | |
| 427 | Length: 120 | |
| 428 | NumberOfRelocations: 0 | |
| 429 | NumberOfLinenumbers: 0 | |
| 430 | CheckSum: 3148269371 | |
| 431 | Number: 6 | |
| 432 | - Name: .llvm_addrsig | |
| 433 | Value: 0 | |
| 434 | SectionNumber: 7 | |
| 435 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 436 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 437 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 438 | SectionDefinition: | |
| 439 | Length: 1 | |
| 440 | NumberOfRelocations: 0 | |
| 441 | NumberOfLinenumbers: 0 | |
| 442 | CheckSum: 2428444049 | |
| 443 | Number: 7 | |
| 444 | - Name: '@feat.00' | |
| 445 | Value: 1 | |
| 446 | SectionNumber: -1 | |
| 447 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 448 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 449 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 450 | - Name: '?func@@YAHHH@Z' | |
| 451 | Value: 0 | |
| 452 | SectionNumber: 1 | |
| 453 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 454 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | |
| 455 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 456 | - Name: _main | |
| 457 | Value: 32 | |
| 458 | SectionNumber: 1 | |
| 459 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 460 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | |
| 461 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 462 | ... |
deps/lld/test/COFF/pdb-global-hashes.test+3-3| ... | ... | @@ -4,9 +4,9 @@ RUN: yaml2obj %p/Inputs/pdb-hashes-2-missing.yaml > %t.2.missing.obj |
| 4 | 4 | RUN: lld-link /debug %t.1.obj %t.2.obj /entry:main /nodefaultlib /PDB:%t.nohash.pdb |
| 5 | 5 | RUN: lld-link /debug:ghash %t.1.obj %t.2.obj /entry:main /nodefaultlib /PDB:%t.hash.pdb |
| 6 | 6 | RUN: lld-link /debug:ghash %t.1.obj %t.2.missing.obj /entry:main /nodefaultlib /PDB:%t.mixed.pdb |
| 7 | RUN: llvm-pdbutil dump -types -ids %t.nohash.pdb | FileCheck %s | |
| 8 | RUN: llvm-pdbutil dump -types -ids %t.hash.pdb | FileCheck %s | |
| 9 | RUN: llvm-pdbutil dump -types -ids %t.mixed.pdb | FileCheck %s | |
| 7 | RUN: llvm-pdbutil dump -types -ids -dont-resolve-forward-refs %t.nohash.pdb | FileCheck %s | |
| 8 | RUN: llvm-pdbutil dump -types -ids -dont-resolve-forward-refs %t.hash.pdb | FileCheck %s | |
| 9 | RUN: llvm-pdbutil dump -types -ids -dont-resolve-forward-refs %t.mixed.pdb | FileCheck %s | |
| 10 | 10 | |
| 11 | 11 | ; These object files were generated via the following inputs and commands: |
| 12 | 12 | ; ---------------------------------------------- |
deps/lld/test/COFF/pdb-globals.test+5-1| ... | ... | @@ -15,6 +15,8 @@ RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s |
| 15 | 15 | CHECK-LABEL: Global Symbols |
| 16 | 16 | CHECK-NEXT: ============================================================ |
| 17 | 17 | CHECK-NEXT: Records |
| 18 | CHECK-NEXT: 340 | S_UDT [size = 20] `HelloPoint` | |
| 19 | CHECK-NEXT: original type = 0x1007 | |
| 18 | 20 | CHECK-NEXT: 208 | S_LPROCREF [size = 24] `LocalFunc` |
| 19 | 21 | CHECK-NEXT: module = 1, sum name = 0, offset = 292 |
| 20 | 22 | CHECK-NEXT: 160 | S_PROCREF [size = 28] `GlobalFunc` |
| ... | ... | @@ -25,9 +27,11 @@ CHECK-NEXT: 232 | S_GDATA32 [size = 28] `__purecall` |
| 25 | 27 | CHECK-NEXT: type = 0x0403 (void*), addr = 0003:0004 |
| 26 | 28 | CHECK-NEXT: 260 | S_GDATA32 [size = 24] `GlobalVar` |
| 27 | 29 | CHECK-NEXT: type = 0x100B (const int*), addr = 0003:0000 |
| 30 | CHECK-NEXT: 312 | S_UDT [size = 28] `HelloPointTypedef` | |
| 31 | CHECK-NEXT: original type = 0x1005 | |
| 28 | 32 | CHECK-NEXT: 284 | S_LDATA32 [size = 28] `ConstantVar` |
| 29 | 33 | CHECK-NEXT: type = 0x100A (const int), addr = 0002:0000 |
| 30 | CHECK-NEXT: 312 | S_PROCREF [size = 40] `HelloPoint::HelloPoint` | |
| 34 | CHECK-NEXT: 360 | S_PROCREF [size = 40] `HelloPoint::HelloPoint` | |
| 31 | 35 | CHECK-NEXT: module = 1, sum name = 0, offset = 376 |
| 32 | 36 | |
| 33 | 37 | CHECK-LABEL: Symbols |
deps/lld/test/COFF/pdb-heapsite.yaml+1-1| ... | ... | @@ -69,7 +69,7 @@ sections: |
| 69 | 69 | RegRelativeSym: |
| 70 | 70 | Offset: 8 |
| 71 | 71 | Type: 35 |
| 72 | Register: CVRegRSP | |
| 72 | Register: RSP | |
| 73 | 73 | VarName: __formal |
| 74 | 74 | - Kind: S_PROC_ID_END |
| 75 | 75 | ScopeEndSym: |
deps/lld/test/COFF/pdb-linker-module.test+3-3| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | RUN: echo "/nodefaultlib" > %t.rsp |
| 2 | RUN: lld-link /debug /pdb:%t.pdb @%t.rsp /entry:main %S/Inputs/pdb-diff.obj | |
| 2 | RUN: lld-link /debug /pdb:%t.pdb @%t.rsp /entry:"1 "'"'hello'"'" 2" /manifestuac:"level='asInvoker' uiAccess='false'" %S/Inputs/pdb-diff.obj /force | |
| 3 | 3 | RUN: llvm-pdbutil dump -modules %t.pdb | FileCheck --check-prefix=MODS %s |
| 4 | 4 | RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck --check-prefix=SYMS %s |
| 5 | 5 | |
| 6 | 6 | MODS: Mod 0001 | `* Linker *` |
| 7 | 7 | MODS-NEXT: Obj: ``: |
| 8 | MODS-NEXT: debug stream: 12, # files: 0, has ec info: false | |
| 8 | MODS-NEXT: debug stream: 13, # files: 0, has ec info: false | |
| 9 | 9 | MODS-NEXT: pdb file ni: 1 `{{.*}}pdb-linker-module.test.tmp.pdb`, src file ni: 0 `` |
| 10 | 10 | |
| 11 | 11 | SYMS: Mod 0001 | `* Linker *` |
| ... | ... | @@ -22,4 +22,4 @@ SYMS-NEXT: - {{.*}}lld-link |
| 22 | 22 | SYMS-NEXT: - pdb |
| 23 | 23 | SYMS-NEXT: - {{.*}}pdb-linker-module{{.*}}pdb |
| 24 | 24 | SYMS-NEXT: - cmd |
| 25 | SYMS-NEXT: - /debug /pdb:{{.*}}pdb-linker-module{{.*}}pdb /nodefaultlib /entry:main {{.*}}pdb-diff.obj | |
| 25 | SYMS-NEXT: - /debug /pdb:{{.*}}pdb-linker-module{{.*}}pdb /nodefaultlib "/entry:1 ""hello"" 2" "/manifestuac:level='asInvoker' uiAccess='false'" {{.*}}pdb-diff.obj |
deps/lld/test/COFF/pdb-options.test+5| ... | ... | @@ -6,6 +6,11 @@ |
| 6 | 6 | # RUN: lld-link /pdb:%t.pdb /entry:main /nodefaultlib %t1.obj %t2.obj |
| 7 | 7 | # RUN: not ls %t.pdb |
| 8 | 8 | |
| 9 | ; If /DEBUG:NONE is specified after /DEBUG, /pdb is ignored. | |
| 10 | # RUN: rm -f %t.pdb | |
| 11 | # RUN: lld-link /DEBUG /pdb:%t.pdb /DEBUG:NONE /entry:main /nodefaultlib %t1.obj %t2.obj | |
| 12 | # RUN: not ls %t.pdb | |
| 13 | ||
| 9 | 14 | ; If /DEBUG and /pdb are specified, it uses the specified name. |
| 10 | 15 | # RUN: lld-link /DEBUG /pdb:%t.pdb /entry:main /nodefaultlib %t1.obj %t2.obj |
| 11 | 16 | # RUN: ls %t.pdb |
deps/lld/test/COFF/pdb-procid-remapping.test+2| ... | ... | @@ -14,6 +14,7 @@ CHECK-NEXT: type = `0x1004 (int (<no type>))`, debug start = 4, d |
| 14 | 14 | CHECK-NEXT: 136 | S_FRAMEPROC [size = 32] |
| 15 | 15 | CHECK-NEXT: size = 40, padding size = 0, offset to padding = 0 |
| 16 | 16 | CHECK-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000 |
| 17 | CHECK-NEXT: local fp reg = NONE, param fp reg = NONE | |
| 17 | 18 | CHECK-NEXT: flags = has async eh | opt speed |
| 18 | 19 | CHECK-NEXT: 168 | S_END [size = 4] |
| 19 | 20 | CHECK-LABEL: Mod 0001 | |
| ... | ... | @@ -23,6 +24,7 @@ CHECK-NEXT: type = `0x1001 (int ())`, debug start = 0, debug end |
| 23 | 24 | CHECK-NEXT: 136 | S_FRAMEPROC [size = 32] |
| 24 | 25 | CHECK-NEXT: size = 0, padding size = 0, offset to padding = 0 |
| 25 | 26 | CHECK-NEXT: bytes of callee saved registers = 0, exception handler addr = 0000:0000 |
| 27 | CHECK-NEXT: local fp reg = NONE, param fp reg = NONE | |
| 26 | 28 | CHECK-NEXT: flags = has async eh | opt speed |
| 27 | 29 | CHECK-NEXT: 168 | S_END [size = 4] |
| 28 | 30 | CHECK-LABEL: Mod 0002 | |
deps/lld/test/COFF/pdb-relative-source-lines.test+79-19| ... | ... | @@ -17,29 +17,89 @@ void bar(void) { |
| 17 | 17 | |
| 18 | 18 | $ clang-cl -Xclang -fdebug-compilation-dir -Xclang . -c -Z7 pdb_lines*.c |
| 19 | 19 | |
| 20 | RUN: yaml2obj %S/Inputs/pdb_lines_1_relative.yaml -o %t.pdb_lines_1_relative.obj | |
| 21 | RUN: yaml2obj %S/Inputs/pdb_lines_2_relative.yaml -o %t.pdb_lines_2_relative.obj | |
| 22 | RUN: rm -f %t.exe %t.pdb | |
| 23 | RUN: lld-link -debug -pdbsourcepath:c:\\src -entry:main -nodefaultlib -out:%t.exe -pdb:%t.pdb %t.pdb_lines_1_relative.obj %t.pdb_lines_2_relative.obj | |
| 24 | RUN: llvm-pdbutil pdb2yaml -modules -module-files -subsections=lines,fc %t.pdb | FileCheck %s | |
| 25 | ||
| 26 | CHECK-LABEL: - Module: {{.*}}pdb_lines_1_relative.obj | |
| 27 | CHECK-NEXT: ObjFile: {{.*}}pdb_lines_1_relative.obj | |
| 20 | /pdbsourcepath: only sets the directory that relative paths are considered | |
| 21 | relative to, so this test needs to pass relative paths to lld-link for: | |
| 22 | 1. The input obj files | |
| 23 | 2. The /pdb: switch | |
| 24 | 3. The lld-link invocation itself | |
| 25 | To achieve this, put all inputs of the lld-link invocation (including lld-link | |
| 26 | itself) in a temp directory that's cwd and then make sure to only use relative | |
| 27 | arguments when calling ./lld-link below. | |
| 28 | RUN: rm -rf %t | |
| 29 | RUN: mkdir %t | |
| 30 | RUN: cp lld-link %t/lld-link | |
| 31 | RUN: cd %t | |
| 32 | ||
| 33 | RUN: yaml2obj %S/Inputs/pdb_lines_1_relative.yaml -o %t/pdb_lines_1_relative.obj | |
| 34 | RUN: yaml2obj %S/Inputs/pdb_lines_2_relative.yaml -o %t/pdb_lines_2_relative.obj | |
| 35 | RUN: ./lld-link -debug "-pdbsourcepath:c:\src" -entry:main -nodefaultlib -out:out.exe -pdb:out.pdb pdb_lines_1_relative.obj pdb_lines_2_relative.obj | |
| 36 | RUN: llvm-pdbutil pdb2yaml -modules -module-files -module-syms -subsections=lines,fc %t/out.pdb | FileCheck %s | |
| 37 | RUN: ./lld-link -debug "-pdbsourcepath:/usr/src" -entry:main -nodefaultlib -out:out.exe -pdb:out.pdb pdb_lines_1_relative.obj pdb_lines_2_relative.obj | |
| 38 | RUN: llvm-pdbutil pdb2yaml -modules -module-files -module-syms -subsections=lines,fc %t/out.pdb | FileCheck --check-prefix=POSIX %s | |
| 39 | ||
| 40 | CHECK-LABEL: - Module: 'c:\src\pdb_lines_1_relative.obj' | |
| 41 | CHECK-NEXT: ObjFile: 'c:\src\pdb_lines_1_relative.obj' | |
| 28 | 42 | CHECK: SourceFiles: |
| 29 | CHECK-NEXT: - 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_1.c' | |
| 30 | CHECK-NEXT: - 'c:{{[\\/]}}src{{[\\/]}}foo.h' | |
| 43 | CHECK-NEXT: - 'c:\src\pdb_lines_1.c' | |
| 44 | CHECK-NEXT: - 'c:\src\foo.h' | |
| 31 | 45 | CHECK: Subsections: |
| 32 | CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_1.c' | |
| 33 | CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}foo.h' | |
| 46 | CHECK: - FileName: 'c:\src\pdb_lines_1.c' | |
| 47 | CHECK: - FileName: 'c:\src\foo.h' | |
| 34 | 48 | CHECK: - !FileChecksums |
| 35 | CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_1.c' | |
| 36 | CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}foo.h' | |
| 49 | CHECK: - FileName: 'c:\src\pdb_lines_1.c' | |
| 50 | CHECK: - FileName: 'c:\src\foo.h' | |
| 37 | 51 | |
| 38 | CHECK-LABEL: - Module: {{.*}}pdb_lines_2_relative.obj | |
| 39 | CHECK-NEXT: ObjFile: {{.*}}pdb_lines_2_relative.obj | |
| 52 | CHECK-LABEL: - Module: 'c:\src\pdb_lines_2_relative.obj' | |
| 53 | CHECK-NEXT: ObjFile: 'c:\src\pdb_lines_2_relative.obj' | |
| 40 | 54 | CHECK: SourceFiles: |
| 41 | CHECK-NEXT: - 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_2.c' | |
| 55 | CHECK-NEXT: - 'c:\src\pdb_lines_2.c' | |
| 42 | 56 | CHECK: Subsections: |
| 43 | CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_2.c' | |
| 57 | CHECK: - FileName: 'c:\src\pdb_lines_2.c' | |
| 44 | 58 | CHECK: - !FileChecksums |
| 45 | CHECK: - FileName: 'c:{{[\\/]}}src{{[\\/]}}pdb_lines_2.c' | |
| 59 | CHECK: - FileName: 'c:\src\pdb_lines_2.c' | |
| 60 | ||
| 61 | CHECK-LABEL: - Kind: S_ENVBLOCK | |
| 62 | CHECK-NEXT: EnvBlockSym: | |
| 63 | CHECK-NEXT: Entries: | |
| 64 | CHECK-NEXT: - cwd | |
| 65 | CHECK-NEXT: - 'c:\src' | |
| 66 | CHECK-NEXT: - exe | |
| 67 | CHECK-NEXT: - 'c:\src\lld-link' | |
| 68 | CHECK-NEXT: - pdb | |
| 69 | CHECK-NEXT: - 'c:\src\out.pdb' | |
| 70 | CHECK-NEXT: - cmd | |
| 71 | CHECK-NEXT: - '-debug -pdbsourcepath:c:\src -entry:main -nodefaultlib -out:out.exe -pdb:out.pdb pdb_lines_1_relative.obj pdb_lines_2_relative.obj' | |
| 72 | ||
| 73 | ||
| 74 | POSIX-LABEL: - Module: '/usr/src/pdb_lines_1_relative.obj' | |
| 75 | POSIX-NEXT: ObjFile: '/usr/src/pdb_lines_1_relative.obj' | |
| 76 | POSIX: SourceFiles: | |
| 77 | POSIX-NEXT: - '/usr/src/pdb_lines_1.c' | |
| 78 | POSIX-NEXT: - '/usr/src/foo.h' | |
| 79 | POSIX: Subsections: | |
| 80 | POSIX: - FileName: '/usr/src/pdb_lines_1.c' | |
| 81 | POSIX: - FileName: '/usr/src/foo.h' | |
| 82 | POSIX: - !FileChecksums | |
| 83 | POSIX: - FileName: '/usr/src/pdb_lines_1.c' | |
| 84 | POSIX: - FileName: '/usr/src/foo.h' | |
| 85 | ||
| 86 | POSIX-LABEL: - Module: '/usr/src/pdb_lines_2_relative.obj' | |
| 87 | POSIX-NEXT: ObjFile: '/usr/src/pdb_lines_2_relative.obj' | |
| 88 | POSIX: SourceFiles: | |
| 89 | POSIX-NEXT: - '/usr/src/pdb_lines_2.c' | |
| 90 | POSIX: Subsections: | |
| 91 | POSIX: - FileName: '/usr/src/pdb_lines_2.c' | |
| 92 | POSIX: - !FileChecksums | |
| 93 | POSIX: - FileName: '/usr/src/pdb_lines_2.c' | |
| 94 | ||
| 95 | POSIX-LABEL: - Kind: S_ENVBLOCK | |
| 96 | POSIX-NEXT: EnvBlockSym: | |
| 97 | POSIX-NEXT: Entries: | |
| 98 | POSIX-NEXT: - cwd | |
| 99 | POSIX-NEXT: - '/usr/src' | |
| 100 | POSIX-NEXT: - exe | |
| 101 | POSIX-NEXT: - '/usr/src/lld-link' | |
| 102 | POSIX-NEXT: - pdb | |
| 103 | POSIX-NEXT: - '/usr/src/out.pdb' | |
| 104 | POSIX-NEXT: - cmd | |
| 105 | POSIX-NEXT: - '-debug -pdbsourcepath:/usr/src -entry:main -nodefaultlib -out:out.exe -pdb:out.pdb pdb_lines_1_relative.obj pdb_lines_2_relative.obj' |
deps/lld/test/COFF/pdb-same-name.test+2-2| ... | ... | @@ -14,10 +14,10 @@ |
| 14 | 14 | RAW: Modules |
| 15 | 15 | RAW-NEXT: ============================================================ |
| 16 | 16 | RAW-NEXT: Mod 0000 | `foo.obj`: |
| 17 | RAW-NEXT: Obj: `{{.*}}1\foo.lib`: | |
| 17 | RAW-NEXT: Obj: `{{.*}}1{{[\\/]}}foo.lib`: | |
| 18 | 18 | RAW-NEXT: debug stream: 11, # files: 1, has ec info: false |
| 19 | 19 | RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` |
| 20 | 20 | RAW-NEXT: Mod 0001 | `foo.obj`: |
| 21 | RAW-NEXT: Obj: `{{.*}}2\foo.lib`: | |
| 21 | RAW-NEXT: Obj: `{{.*}}2{{[\\/]}}foo.lib`: | |
| 22 | 22 | RAW-NEXT: debug stream: 12, # files: 1, has ec info: false |
| 23 | 23 | RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 `` |
deps/lld/test/COFF/pdb-symbol-types.yaml+6-2| ... | ... | @@ -17,9 +17,13 @@ |
| 17 | 17 | # CHECK-NEXT: ============================================================ |
| 18 | 18 | # CHECK-NEXT: Records |
| 19 | 19 | # CHECK-NEXT: 48 | S_PROCREF [size = 20] `main` |
| 20 | # CHECK-NEXT: module = 1, sum name = 0, offset = 116 | |
| 20 | # CHECK-NEXT: module = 1, sum name = 0, offset = 116 | |
| 21 | # CHECK-NEXT: 96 | S_UDT [size = 16] `UDT_Foo` | |
| 22 | # CHECK-NEXT: original type = 0x1004 | |
| 23 | # CHECK-NEXT: 112 | S_UDT [size = 12] `Foo` | |
| 24 | # CHECK-NEXT: original type = 0x1004 | |
| 21 | 25 | # CHECK-NEXT: 68 | S_GDATA32 [size = 28] `global_foo` |
| 22 | # CHECK-NEXT: type = 0x1004 (Foo), addr = 0003:0000 | |
| 26 | # CHECK-NEXT: type = 0x1004 (Foo), addr = 0003:0000 | |
| 23 | 27 | |
| 24 | 28 | # CHECK: Symbols |
| 25 | 29 | # CHECK: ============================================================ |
deps/lld/test/COFF/pdb-thunk.yaml+6-6| ... | ... | @@ -84,7 +84,7 @@ sections: |
| 84 | 84 | RegRelativeSym: |
| 85 | 85 | Offset: 8 |
| 86 | 86 | Type: 4097 |
| 87 | Register: CVRegRSP | |
| 87 | Register: RSP | |
| 88 | 88 | VarName: this |
| 89 | 89 | - Kind: S_PROC_ID_END |
| 90 | 90 | ScopeEndSym: |
| ... | ... | @@ -124,7 +124,7 @@ sections: |
| 124 | 124 | RegRelativeSym: |
| 125 | 125 | Offset: 8 |
| 126 | 126 | Type: 4121 |
| 127 | Register: CVRegRSP | |
| 127 | Register: RSP | |
| 128 | 128 | VarName: this |
| 129 | 129 | - Kind: S_PROC_ID_END |
| 130 | 130 | ScopeEndSym: |
| ... | ... | @@ -164,7 +164,7 @@ sections: |
| 164 | 164 | RegRelativeSym: |
| 165 | 165 | Offset: 48 |
| 166 | 166 | Type: 4143 |
| 167 | Register: CVRegRSP | |
| 167 | Register: RSP | |
| 168 | 168 | VarName: this |
| 169 | 169 | - Kind: S_PROC_ID_END |
| 170 | 170 | ScopeEndSym: |
| ... | ... | @@ -208,7 +208,7 @@ sections: |
| 208 | 208 | RegRelativeSym: |
| 209 | 209 | Offset: 8 |
| 210 | 210 | Type: 4143 |
| 211 | Register: CVRegRSP | |
| 211 | Register: RSP | |
| 212 | 212 | VarName: this |
| 213 | 213 | - Kind: S_PROC_ID_END |
| 214 | 214 | ScopeEndSym: |
| ... | ... | @@ -2176,7 +2176,7 @@ sections: |
| 2176 | 2176 | RegRelativeSym: |
| 2177 | 2177 | Offset: 8 |
| 2178 | 2178 | Type: 4097 |
| 2179 | Register: CVRegRSP | |
| 2179 | Register: RSP | |
| 2180 | 2180 | VarName: this |
| 2181 | 2181 | - Kind: S_PROC_ID_END |
| 2182 | 2182 | ScopeEndSym: |
| ... | ... | @@ -2222,7 +2222,7 @@ sections: |
| 2222 | 2222 | RegRelativeSym: |
| 2223 | 2223 | Offset: 8 |
| 2224 | 2224 | Type: 4121 |
| 2225 | Register: CVRegRSP | |
| 2225 | Register: RSP | |
| 2226 | 2226 | VarName: this |
| 2227 | 2227 | - Kind: S_PROC_ID_END |
| 2228 | 2228 | ScopeEndSym: |
deps/lld/test/COFF/pdb-type-server-invalid-signature.yaml created+140| ... | ... | @@ -0,0 +1,140 @@ |
| 1 | ||
| 2 | # RUN: cd %S/Inputs | |
| 3 | # RUN: yaml2obj %s -o %t.obj | |
| 4 | # RUN: lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s | |
| 5 | # RUN: cd %S | |
| 6 | ||
| 7 | # CHECK: warning: Cannot use debug info for {{.*}}.obj | |
| 8 | # CHECK-NEXT: The signature does not match; the file(s) might be out of date | |
| 9 | ||
| 10 | # Also test a valid match | |
| 11 | ||
| 12 | # RUN: cd %S/Inputs | |
| 13 | # RUN: yaml2obj %S/Inputs/pdb-type-server-valid-signature.yaml -o %t2.obj | |
| 14 | # RUN: lld-link %t2.obj -out:%t2.exe -debug -pdb:%t2.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s -check-prefix=VALID-SIGNATURE -allow-empty | |
| 15 | # RUN: cd %S | |
| 16 | ||
| 17 | # VALID-SIGNATURE-NOT: warning: Cannot use debug info for {{.*}}.obj | |
| 18 | # VALID-SIGNATURE-NOT: The signature does not match; the file(s) might be out of date | |
| 19 | ||
| 20 | --- !COFF | |
| 21 | header: | |
| 22 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 23 | Characteristics: [ ] | |
| 24 | sections: | |
| 25 | - Name: '.debug$S' | |
| 26 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 27 | Alignment: 1 | |
| 28 | Subsections: | |
| 29 | - !Symbols | |
| 30 | Records: | |
| 31 | - Kind: S_GPROC32_ID | |
| 32 | ProcSym: | |
| 33 | CodeSize: 3 | |
| 34 | DbgStart: 0 | |
| 35 | DbgEnd: 2 | |
| 36 | FunctionType: 4199 | |
| 37 | Flags: [ ] | |
| 38 | DisplayName: main | |
| 39 | - Kind: S_FRAMEPROC | |
| 40 | FrameProcSym: | |
| 41 | TotalFrameBytes: 0 | |
| 42 | PaddingFrameBytes: 0 | |
| 43 | OffsetToPadding: 0 | |
| 44 | BytesOfCalleeSavedRegisters: 0 | |
| 45 | OffsetOfExceptionHandler: 0 | |
| 46 | SectionIdOfExceptionHandler: 0 | |
| 47 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | |
| 48 | - Kind: S_PROC_ID_END | |
| 49 | ScopeEndSym: | |
| 50 | - !Lines | |
| 51 | CodeSize: 3 | |
| 52 | Flags: [ ] | |
| 53 | RelocOffset: 0 | |
| 54 | RelocSegment: 0 | |
| 55 | Blocks: | |
| 56 | - FileName: 'c:\src\llvm-project\build\t.c' | |
| 57 | Lines: | |
| 58 | - Offset: 0 | |
| 59 | LineStart: 1 | |
| 60 | IsStatement: true | |
| 61 | EndDelta: 0 | |
| 62 | Columns: | |
| 63 | - !FileChecksums | |
| 64 | Checksums: | |
| 65 | - FileName: 'c:\src\llvm-project\build\t.c' | |
| 66 | Kind: MD5 | |
| 67 | Checksum: 270A878DCC1B845655B162F56C4F5020 | |
| 68 | - !StringTable | |
| 69 | Strings: | |
| 70 | - 'c:\src\llvm-project\build\t.c' | |
| 71 | Relocations: | |
| 72 | - VirtualAddress: 44 | |
| 73 | SymbolName: main | |
| 74 | Type: IMAGE_REL_AMD64_SECREL | |
| 75 | - VirtualAddress: 48 | |
| 76 | SymbolName: main | |
| 77 | Type: IMAGE_REL_AMD64_SECTION | |
| 78 | - VirtualAddress: 100 | |
| 79 | SymbolName: main | |
| 80 | Type: IMAGE_REL_AMD64_SECREL | |
| 81 | - VirtualAddress: 104 | |
| 82 | SymbolName: main | |
| 83 | Type: IMAGE_REL_AMD64_SECTION | |
| 84 | - Name: '.debug$T' | |
| 85 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 86 | Alignment: 1 | |
| 87 | Types: | |
| 88 | - Kind: LF_TYPESERVER2 | |
| 89 | TypeServer2: | |
| 90 | Guid: '{01DF191B-22BF-6B42-96CE-5258B8329FE5}' | |
| 91 | Age: 18 | |
| 92 | Name: 'pdb-diff-cl.pdb' | |
| 93 | - Name: '.text$mn' | |
| 94 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 95 | Alignment: 16 | |
| 96 | SectionData: 33C0C3 | |
| 97 | symbols: | |
| 98 | - Name: '.debug$S' | |
| 99 | Value: 0 | |
| 100 | SectionNumber: 1 | |
| 101 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 102 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 103 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 104 | SectionDefinition: | |
| 105 | Length: 328 | |
| 106 | NumberOfRelocations: 4 | |
| 107 | NumberOfLinenumbers: 0 | |
| 108 | CheckSum: 0 | |
| 109 | Number: 0 | |
| 110 | - Name: '.debug$T' | |
| 111 | Value: 0 | |
| 112 | SectionNumber: 2 | |
| 113 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 114 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 115 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 116 | SectionDefinition: | |
| 117 | Length: 564 | |
| 118 | NumberOfRelocations: 0 | |
| 119 | NumberOfLinenumbers: 0 | |
| 120 | CheckSum: 0 | |
| 121 | Number: 0 | |
| 122 | - Name: '.text$mn' | |
| 123 | Value: 0 | |
| 124 | SectionNumber: 3 | |
| 125 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 126 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 127 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 128 | SectionDefinition: | |
| 129 | Length: 3 | |
| 130 | NumberOfRelocations: 0 | |
| 131 | NumberOfLinenumbers: 0 | |
| 132 | CheckSum: 4021952397 | |
| 133 | Number: 0 | |
| 134 | - Name: main | |
| 135 | Value: 0 | |
| 136 | SectionNumber: 3 | |
| 137 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 138 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | |
| 139 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 140 | ... |
deps/lld/test/COFF/pdb-type-server-missing.yaml+18-3| ... | ... | @@ -1,10 +1,25 @@ |
| 1 | 1 | # This is an object compiled with /Zi (see the LF_TYPESERVER2 record) without an |
| 2 | 2 | # adjacent type server PDB. Test that LLD fails gracefully on it. |
| 3 | # Also try linking another OBJ with a reference to the same PDB | |
| 3 | 4 | |
| 4 | # RUN: yaml2obj %s -o %t.obj | |
| 5 | # RUN: lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s | |
| 5 | # RUN: yaml2obj %s -o %t1.obj | |
| 6 | # RUN: yaml2obj %p/Inputs/pdb-type-server-missing-2.yaml -o %t2.obj | |
| 7 | # RUN: lld-link %t1.obj %t2.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s -check-prefix=WARN | |
| 8 | # RUN: lld-link %t1.obj %t2.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main /ignore:4099 2>&1 | FileCheck %s -check-prefix=IGNORE -allow-empty | |
| 9 | # RUN: not lld-link %t1.obj %t2.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main /WX 2>&1 | FileCheck %s -check-prefix=ERR | |
| 10 | # RUN: lld-link %t1.obj %t2.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main /ignore:4099 /WX 2>&1 | FileCheck %s -check-prefix=IGNORE-ERR -allow-empty | |
| 6 | 11 | |
| 7 | # CHECK: warning: Type server PDB for {{.*}}.obj is invalid, ignoring debug info. | |
| 12 | # WARN: warning: Cannot use debug info for '{{.*}}.obj' [LNK4099] | |
| 13 | # WARN-NEXT: {{N|n}}o such file or directory | |
| 14 | ||
| 15 | # IGNORE-NOT: warning: Cannot use debug info for '{{.*}}.obj' [LNK4099] | |
| 16 | # IGNORE-NOT: {{N|n}}o such file or directory | |
| 17 | ||
| 18 | # ERR: error: Cannot use debug info for '{{.*}}.obj' [LNK4099] | |
| 19 | # ERR-NEXT: {{N|n}}o such file or directory | |
| 20 | ||
| 21 | # IGNORE-ERR-NOT: error: Cannot use debug info for '{{.*}}.obj' [LNK4099] | |
| 22 | # IGNORE-ERR-NOT: {{N|n}}o such file or directory | |
| 8 | 23 | |
| 9 | 24 | --- !COFF |
| 10 | 25 | header: |
deps/lld/test/COFF/pdb-type-server-native-errors.yaml created+130| ... | ... | @@ -0,0 +1,130 @@ |
| 1 | ||
| 2 | # RUN: cd %S/Inputs | |
| 3 | # RUN: yaml2obj %s -o %t.obj | |
| 4 | # RUN: lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s | |
| 5 | # RUN: cd %S | |
| 6 | ||
| 7 | # CHECK: warning: Cannot use debug info for {{.*}}.obj | |
| 8 | # CHECK-NEXT: The PDB file is corrupt. MSF superblock is missing | |
| 9 | ||
| 10 | --- !COFF | |
| 11 | header: | |
| 12 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 13 | Characteristics: [ ] | |
| 14 | sections: | |
| 15 | - Name: '.debug$S' | |
| 16 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 17 | Alignment: 1 | |
| 18 | Subsections: | |
| 19 | - !Symbols | |
| 20 | Records: | |
| 21 | - Kind: S_GPROC32_ID | |
| 22 | ProcSym: | |
| 23 | CodeSize: 3 | |
| 24 | DbgStart: 0 | |
| 25 | DbgEnd: 2 | |
| 26 | FunctionType: 4199 | |
| 27 | Flags: [ ] | |
| 28 | DisplayName: main | |
| 29 | - Kind: S_FRAMEPROC | |
| 30 | FrameProcSym: | |
| 31 | TotalFrameBytes: 0 | |
| 32 | PaddingFrameBytes: 0 | |
| 33 | OffsetToPadding: 0 | |
| 34 | BytesOfCalleeSavedRegisters: 0 | |
| 35 | OffsetOfExceptionHandler: 0 | |
| 36 | SectionIdOfExceptionHandler: 0 | |
| 37 | Flags: [ AsynchronousExceptionHandling, OptimizedForSpeed ] | |
| 38 | - Kind: S_PROC_ID_END | |
| 39 | ScopeEndSym: | |
| 40 | - !Lines | |
| 41 | CodeSize: 3 | |
| 42 | Flags: [ ] | |
| 43 | RelocOffset: 0 | |
| 44 | RelocSegment: 0 | |
| 45 | Blocks: | |
| 46 | - FileName: 'c:\src\llvm-project\build\t.c' | |
| 47 | Lines: | |
| 48 | - Offset: 0 | |
| 49 | LineStart: 1 | |
| 50 | IsStatement: true | |
| 51 | EndDelta: 0 | |
| 52 | Columns: | |
| 53 | - !FileChecksums | |
| 54 | Checksums: | |
| 55 | - FileName: 'c:\src\llvm-project\build\t.c' | |
| 56 | Kind: MD5 | |
| 57 | Checksum: 270A878DCC1B845655B162F56C4F5020 | |
| 58 | - !StringTable | |
| 59 | Strings: | |
| 60 | - 'c:\src\llvm-project\build\t.c' | |
| 61 | Relocations: | |
| 62 | - VirtualAddress: 44 | |
| 63 | SymbolName: main | |
| 64 | Type: IMAGE_REL_AMD64_SECREL | |
| 65 | - VirtualAddress: 48 | |
| 66 | SymbolName: main | |
| 67 | Type: IMAGE_REL_AMD64_SECTION | |
| 68 | - VirtualAddress: 100 | |
| 69 | SymbolName: main | |
| 70 | Type: IMAGE_REL_AMD64_SECREL | |
| 71 | - VirtualAddress: 104 | |
| 72 | SymbolName: main | |
| 73 | Type: IMAGE_REL_AMD64_SECTION | |
| 74 | - Name: '.debug$T' | |
| 75 | Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] | |
| 76 | Alignment: 1 | |
| 77 | Types: | |
| 78 | - Kind: LF_TYPESERVER2 | |
| 79 | TypeServer2: | |
| 80 | Guid: '{01DF191B-22BF-6B42-96CE-5258B8329FE5}' | |
| 81 | Age: 18 | |
| 82 | Name: 'bad-block-size.pdb' | |
| 83 | - Name: '.text$mn' | |
| 84 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 85 | Alignment: 16 | |
| 86 | SectionData: 33C0C3 | |
| 87 | symbols: | |
| 88 | - Name: '.debug$S' | |
| 89 | Value: 0 | |
| 90 | SectionNumber: 1 | |
| 91 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 92 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 93 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 94 | SectionDefinition: | |
| 95 | Length: 328 | |
| 96 | NumberOfRelocations: 4 | |
| 97 | NumberOfLinenumbers: 0 | |
| 98 | CheckSum: 0 | |
| 99 | Number: 0 | |
| 100 | - Name: '.debug$T' | |
| 101 | Value: 0 | |
| 102 | SectionNumber: 2 | |
| 103 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 104 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 105 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 106 | SectionDefinition: | |
| 107 | Length: 564 | |
| 108 | NumberOfRelocations: 0 | |
| 109 | NumberOfLinenumbers: 0 | |
| 110 | CheckSum: 0 | |
| 111 | Number: 0 | |
| 112 | - Name: '.text$mn' | |
| 113 | Value: 0 | |
| 114 | SectionNumber: 3 | |
| 115 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 116 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 117 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 118 | SectionDefinition: | |
| 119 | Length: 3 | |
| 120 | NumberOfRelocations: 0 | |
| 121 | NumberOfLinenumbers: 0 | |
| 122 | CheckSum: 4021952397 | |
| 123 | Number: 0 | |
| 124 | - Name: main | |
| 125 | Value: 0 | |
| 126 | SectionNumber: 3 | |
| 127 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 128 | ComplexType: IMAGE_SYM_DTYPE_FUNCTION | |
| 129 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 130 | ... |
deps/lld/test/COFF/pdb-type-server-simple.test+7-5| ... | ... | @@ -62,10 +62,12 @@ CHECK: {{.*}}: `b.c` |
| 62 | 62 | CHECK-LABEL: Global Symbols |
| 63 | 63 | CHECK: ============================================================ |
| 64 | 64 | CHECK-NEXT: Records |
| 65 | CHECK-NEXT: 36 | S_PROCREF [size = 20] `main` | |
| 66 | CHECK-NEXT: module = 1, sum name = 0, offset = 104 | |
| 67 | CHECK-NEXT: 56 | S_PROCREF [size = 16] `g` | |
| 68 | CHECK-NEXT: module = 2, sum name = 0, offset = 104 | |
| 65 | CHECK-NEXT: 36 | S_PROCREF [size = 20] `main` | |
| 66 | CHECK-NEXT: module = 1, sum name = 0, offset = 104 | |
| 67 | CHECK-NEXT: 68 | S_PROCREF [size = 16] `g` | |
| 68 | CHECK-NEXT: module = 2, sum name = 0, offset = 104 | |
| 69 | CHECK-NEXT: 56 | S_UDT [size = 12] `Foo` | |
| 70 | CHECK-NEXT: original type = 0x1006 | |
| 69 | 71 | |
| 70 | 72 | CHECK-LABEL: Symbols |
| 71 | 73 | CHECK: ============================================================ |
| ... | ... | @@ -89,7 +91,7 @@ CHECK: size = 0, padding size = 0, offset to padding = 0 |
| 89 | 91 | CHECK: bytes of callee saved registers = 0, exception handler addr = 0000:0000 |
| 90 | 92 | CHECK: flags = has async eh | opt speed |
| 91 | 93 | CHECK: 180 | S_REGREL32 [size = 16] `p` |
| 92 | CHECK: type = [[FOO_PTR]] (Foo*), register = CVRegRSP, offset = 8 | |
| 94 | CHECK: type = [[FOO_PTR]] (Foo*), register = RSP, offset = 8 | |
| 93 | 95 | CHECK: 196 | S_END [size = 4] |
| 94 | 96 | CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]` |
| 95 | 97 | CHECK-LABEL: Mod 0002 | `* Linker *`: |
deps/lld/test/COFF/pdb.test-19| ... | ... | @@ -193,25 +193,6 @@ RAW-NEXT: flags = function, addr = 0001:0000 |
| 193 | 193 | RAW-NEXT: 0 | S_PUB32 [size = 20] `foo` |
| 194 | 194 | RAW-NEXT: flags = function, addr = 0001:0016 |
| 195 | 195 | RAW-NOT: S_PUB32 |
| 196 | RAW-NEXT: Hash Bitmap ( | |
| 197 | RAW-NEXT: 0000: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 198 | RAW-NEXT: 0020: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 199 | RAW-NEXT: 0040: 00000000 20000000 00000000 00000000 00000000 00000000 00000000 00000000 |.... ...........................| | |
| 200 | RAW-NEXT: 0060: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 201 | RAW-NEXT: 0080: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 202 | RAW-NEXT: 00A0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 203 | RAW-NEXT: 00C0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 204 | RAW-NEXT: 00E0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 205 | RAW-NEXT: 0100: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 206 | RAW-NEXT: 0120: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 207 | RAW-NEXT: 0140: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 208 | RAW-NEXT: 0160: 01000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 209 | RAW-NEXT: 0180: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 210 | RAW-NEXT: 01A0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 211 | RAW-NEXT: 01C0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 212 | RAW-NEXT: 01E0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 |................................| | |
| 213 | RAW-NEXT: 0200: 00000000 |....| | |
| 214 | RAW-NEXT: ) | |
| 215 | 196 | RAW-NEXT: Hash Entries |
| 216 | 197 | RAW-NEXT: off = 21, refcnt = 1 |
| 217 | 198 | RAW-NEXT: off = 1, refcnt = 1 |
deps/lld/test/COFF/pdbaltpath.test created+39| ... | ... | @@ -0,0 +1,39 @@ |
| 1 | # RUN: yaml2obj %p/Inputs/empty.yaml > %t.obj | |
| 2 | ||
| 3 | # RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:hello.pdb | |
| 4 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix HELLO %s | |
| 5 | # HELLO: PDBFileName: hello.pdb | |
| 6 | ||
| 7 | # RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:%_Pdb% | |
| 8 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix PDBVAR %s | |
| 9 | # PDBVAR: PDBFileName: pdbaltpath.test.tmp.pdb | |
| 10 | ||
| 11 | # RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_ExT%.pdb | |
| 12 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix EXTVAR %s | |
| 13 | # EXTVAR: PDBFileName: fooexe.pdb | |
| 14 | ||
| 15 | # RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:%_PDB | |
| 16 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix NOCLOSE %s | |
| 17 | # NOCLOSE: PDBFileName: %_PDB | |
| 18 | ||
| 19 | # RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB | |
| 20 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix NOCLOSE2 %s | |
| 21 | # NOCLOSE2: PDBFileName: foo%_PDB | |
| 22 | ||
| 23 | # RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB%bar%_EXT | |
| 24 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix CLOSEONE %s | |
| 25 | # CLOSEONE: PDBFileName: foopdbaltpath.test.tmp.pdbbar%_EXT | |
| 26 | ||
| 27 | # RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB%bar%_EXT% | |
| 28 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix CLOSETWO %s | |
| 29 | # CLOSETWO: PDBFileName: foopdbaltpath.test.tmp.pdbbarexe | |
| 30 | ||
| 31 | # RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB%bar%_EXT%a | |
| 32 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix CLOSETWO2 %s | |
| 33 | # CLOSETWO2: PDBFileName: foopdbaltpath.test.tmp.pdbbarexea | |
| 34 | ||
| 35 | # RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%FoO%bar%r%a 2>&1 | FileCheck --check-prefix UNKNOWN-WARN %s | |
| 36 | # RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck --check-prefix ENVVARS %s | |
| 37 | # UNKNOWN-WARN: only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping %FoO% as literal | |
| 38 | # UNKNOWN-WARN: only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping %r% as literal | |
| 39 | # ENVVARS: PDBFileName: foo%FoO%bar%r%a |
deps/lld/test/COFF/precomp-link.test created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf | |
| 2 | RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s | |
| 3 | ||
| 4 | RUN: lld-link %S/Inputs/precomp.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf | |
| 5 | RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s | |
| 6 | ||
| 7 | RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-invalid.obj %S/Inputs/precomp.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf 2>&1 | FileCheck %s -check-prefix FAILURE | |
| 8 | ||
| 9 | RUN: not lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf 2>&1 | FileCheck %s -check-prefix FAILURE-MISSING-PRECOMPOBJ | |
| 10 | ||
| 11 | FAILURE: warning: Cannot use debug info for 'precomp-invalid.obj' [LNK4099] | |
| 12 | FAILURE-NEXT: failed to load reference '{{.*}}precomp.obj': The signature does not match; the file(s) might be out of date. | |
| 13 | ||
| 14 | FAILURE-MISSING-PRECOMPOBJ: warning: Cannot use debug info for 'precomp-a.obj' [LNK4099] | |
| 15 | FAILURE-MISSING-PRECOMPOBJ-NEXT: failed to load reference '{{.*}}precomp.obj': The path to this file must be provided on the command-line | |
| 16 | ||
| 17 | CHECK: Types (TPI Stream) | |
| 18 | CHECK-NOT: LF_PRECOMP | |
| 19 | CHECK-NOT: LF_ENDPRECOMP | |
| 20 | ||
| 21 | // precomp.h | |
| 22 | #pragma once | |
| 23 | int Function(char A); | |
| 24 | ||
| 25 | // precomp.cpp | |
| 26 | #include "precomp.h" | |
| 27 | ||
| 28 | // a.cpp | |
| 29 | #include "precomp.h" | |
| 30 | int main(void) { | |
| 31 | Function('a'); | |
| 32 | return 0; | |
| 33 | } | |
| 34 | ||
| 35 | // b.cpp | |
| 36 | #include "precomp.h" | |
| 37 | int Function(char a) { | |
| 38 | return (int)a; | |
| 39 | } | |
| 40 | ||
| 41 | // cl.exe precomp.cpp /Z7 /Ycprecomp.h /c | |
| 42 | // cl.exe a.cpp b.cpp /Z7 /Yuprecomp.h /c |
deps/lld/test/COFF/reloc-discarded.s+1| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | # RUN: not lld-link -entry:main -nodefaultlib %t1.obj %t2.obj -out:%t.exe -opt:noref 2>&1 | FileCheck %s |
| 11 | 11 | |
| 12 | 12 | # CHECK: error: relocation against symbol in discarded section: assoc_global |
| 13 | # CHECK: >>> referenced by {{.*}}reloc-discarded{{.*}}.obj:(main) | |
| 13 | 14 | |
| 14 | 15 | 	.section	.bss,"bw",discard,main_global |
| 15 | 16 | 	.globl	main_global |
deps/lld/test/COFF/rsds.test+120-6| ... | ... | @@ -1,9 +1,9 @@ |
| 1 | 1 | # RUN: yaml2obj %s > %t.obj |
| 2 | 2 | |
| 3 | 3 | # RUN: rm -f %t.dll %t.pdb |
| 4 | # RUN: lld-link /debug /pdbaltpath:test1.pdb /dll /out:%t.dll /entry:DllMain %t.obj | |
| 4 | # RUN: lld-link /debug /pdbaltpath:test.pdb /dll /out:%t.dll /entry:DllMain %t.obj | |
| 5 | 5 | # RUN: llvm-readobj -coff-debug-directory %t.dll > %t.1.txt |
| 6 | # RUN: lld-link /debug /pdbaltpath:test2.pdb /dll /out:%t.dll /entry:DllMain %t.obj | |
| 6 | # RUN: lld-link /debug /pdbaltpath:test.pdb /dll /out:%t.dll /entry:DllMain %t.obj | |
| 7 | 7 | # RUN: llvm-readobj -coff-debug-directory %t.dll > %t.2.txt |
| 8 | 8 | # RUN: cat %t.1.txt %t.2.txt | FileCheck %s |
| 9 | 9 | |
| ... | ... | @@ -12,7 +12,19 @@ |
| 12 | 12 | # RUN: llvm-readobj -coff-debug-directory %t.dll > %t.3.txt |
| 13 | 13 | # RUN: lld-link /debug /pdb:%t2.pdb /dll /out:%t.dll /entry:DllMain %t.obj |
| 14 | 14 | # RUN: llvm-readobj -coff-debug-directory %t.dll > %t.4.txt |
| 15 | # RUN: cat %t.3.txt %t.4.txt | FileCheck %s | |
| 15 | # RUN: cat %t.3.txt %t.4.txt | FileCheck --check-prefix TWOPDBS %s | |
| 16 | ||
| 17 | # RUN: rm -f %t.dll %t.pdb | |
| 18 | # RUN: lld-link /Brepro /dll /out:%t.dll /entry:DllMain %t.obj | |
| 19 | # RUN: llvm-readobj -coff-debug-directory %t.dll | FileCheck --check-prefix REPRO %s | |
| 20 | ||
| 21 | # RUN: rm -f %t.dll %t.pdb | |
| 22 | # RUN: lld-link /Brepro /debug /dll /out:%t.dll /entry:DllMain %t.obj | |
| 23 | # RUN: llvm-readobj -coff-debug-directory %t.dll | FileCheck --check-prefix REPRODEBUG %s | |
| 24 | ||
| 25 | # RUN: rm -f %t.dll %t.pdb | |
| 26 | # RUN: lld-link /lldmingw /debug:dwarf /dll /out:%t.dll /entry:DllMain %t.obj | |
| 27 | # RUN: llvm-readobj -coff-debug-directory %t.dll | FileCheck --check-prefix MINGW %s | |
| 16 | 28 | |
| 17 | 29 | # CHECK: File: [[FILE:.*]].dll |
| 18 | 30 | # CHECK: DebugDirectory [ |
| ... | ... | @@ -29,7 +41,7 @@ |
| 29 | 41 | # CHECK: PDBSignature: 0x53445352 |
| 30 | 42 | # CHECK: PDBGUID: [[GUID:\(([A-Za-z0-9]{2} ?){16}\)]] |
| 31 | 43 | # CHECK: PDBAge: 1 |
| 32 | # CHECK: PDBFileName: {{.*}}1.pdb | |
| 44 | # CHECK: PDBFileName: {{.*}}.pdb | |
| 33 | 45 | # CHECK: } |
| 34 | 46 | # CHECK: } |
| 35 | 47 | # CHECK: ] |
| ... | ... | @@ -47,12 +59,114 @@ |
| 47 | 59 | # CHECK: PDBInfo { |
| 48 | 60 | # CHECK: PDBSignature: 0x53445352 |
| 49 | 61 | # CHECK: PDBGUID: [[GUID]] |
| 50 | # CHECK: PDBAge: 2 | |
| 51 | # CHECK: PDBFileName: {{.*}}2.pdb | |
| 62 | # CHECK: PDBAge: 1 | |
| 63 | # CHECK: PDBFileName: {{.*}}.pdb | |
| 52 | 64 | # CHECK: } |
| 53 | 65 | # CHECK: } |
| 54 | 66 | # CHECK: ] |
| 55 | 67 | |
| 68 | # TWOPDBS: File: [[FILE:.*]].dll | |
| 69 | # TWOPDBS: DebugDirectory [ | |
| 70 | # TWOPDBS: DebugEntry { | |
| 71 | # TWOPDBS: Characteristics: 0x0 | |
| 72 | # TWOPDBS: TimeDateStamp: | |
| 73 | # TWOPDBS: MajorVersion: 0x0 | |
| 74 | # TWOPDBS: MinorVersion: 0x0 | |
| 75 | # TWOPDBS: Type: CodeView (0x2) | |
| 76 | # TWOPDBS: SizeOfData: 0x{{[^0]}} | |
| 77 | # TWOPDBS: AddressOfRawData: 0x{{[^0]}} | |
| 78 | # TWOPDBS: PointerToRawData: 0x{{[^0]}} | |
| 79 | # TWOPDBS: PDBInfo { | |
| 80 | # TWOPDBS: PDBSignature: 0x53445352 | |
| 81 | # TWOPDBS: PDBGUID: [[GUID:\(([A-Za-z0-9]{2} ?){16}\)]] | |
| 82 | # TWOPDBS: PDBAge: 1 | |
| 83 | # TWOPDBS: PDBFileName: {{.*}}.pdb | |
| 84 | # TWOPDBS: } | |
| 85 | # TWOPDBS: } | |
| 86 | # TWOPDBS: ] | |
| 87 | # TWOPDBS: File: [[FILE]].dll | |
| 88 | # TWOPDBS: DebugDirectory [ | |
| 89 | # TWOPDBS: DebugEntry { | |
| 90 | # TWOPDBS: Characteristics: 0x0 | |
| 91 | # TWOPDBS: TimeDateStamp: | |
| 92 | # TWOPDBS: MajorVersion: 0x0 | |
| 93 | # TWOPDBS: MinorVersion: 0x0 | |
| 94 | # TWOPDBS: Type: CodeView (0x2) | |
| 95 | # TWOPDBS: SizeOfData: 0x{{[^0]}} | |
| 96 | # TWOPDBS: AddressOfRawData: 0x{{[^0]}} | |
| 97 | # TWOPDBS: PointerToRawData: 0x{{[^0]}} | |
| 98 | # TWOPDBS: PDBInfo { | |
| 99 | # TWOPDBS: PDBSignature: 0x53445352 | |
| 100 | # TWOPDBS-NOT: PDBGUID: [[GUID]] | |
| 101 | # TWOPDBS: PDBAge: 1 | |
| 102 | # TWOPDBS: PDBFileName: {{.*}}.pdb | |
| 103 | # TWOPDBS: } | |
| 104 | # TWOPDBS: } | |
| 105 | # TWOPDBS: ] | |
| 106 | ||
| 107 | # REPRO: File: {{.*}}.dll | |
| 108 | # REPRO: DebugDirectory [ | |
| 109 | # REPRO: DebugEntry { | |
| 110 | # REPRO: Characteristics: 0x0 | |
| 111 | # REPRO: TimeDateStamp: | |
| 112 | # REPRO: MajorVersion: 0x0 | |
| 113 | # REPRO: MinorVersion: 0x0 | |
| 114 | # REPRO: Type: Repro (0x10) | |
| 115 | # REPRO: SizeOfData: 0x0 | |
| 116 | # REPRO: AddressOfRawData: 0x0 | |
| 117 | # REPRO: PointerToRawData: 0x0 | |
| 118 | # REPRO: } | |
| 119 | # REPRO: ] | |
| 120 | ||
| 121 | # REPRODEBUG: File: {{.*}}.dll | |
| 122 | # REPRODEBUG: DebugDirectory [ | |
| 123 | # REPRODEBUG: DebugEntry { | |
| 124 | # REPRODEBUG: Characteristics: 0x0 | |
| 125 | # REPRODEBUG: TimeDateStamp: | |
| 126 | # REPRODEBUG: MajorVersion: 0x0 | |
| 127 | # REPRODEBUG: MinorVersion: 0x0 | |
| 128 | # REPRODEBUG: Type: CodeView (0x2) | |
| 129 | # REPRODEBUG: SizeOfData: 0x{{[^0]}} | |
| 130 | # REPRODEBUG: AddressOfRawData: 0x{{[^0]}} | |
| 131 | # REPRODEBUG: PointerToRawData: 0x{{[^0]}} | |
| 132 | # REPRODEBUG: PDBInfo { | |
| 133 | # REPRODEBUG: PDBSignature: 0x53445352 | |
| 134 | # REPRODEBUG: PDBGUID: | |
| 135 | # REPRODEBUG: PDBAge: 1 | |
| 136 | # REPRODEBUG: PDBFileName: | |
| 137 | # REPRODEBUG: } | |
| 138 | # REPRODEBUG: } | |
| 139 | # REPRODEBUG: DebugEntry { | |
| 140 | # REPRODEBUG: Characteristics: 0x0 | |
| 141 | # REPRODEBUG: TimeDateStamp: | |
| 142 | # REPRODEBUG: MajorVersion: 0x0 | |
| 143 | # REPRODEBUG: MinorVersion: 0x0 | |
| 144 | # REPRODEBUG: Type: Repro (0x10) | |
| 145 | # REPRODEBUG: SizeOfData: 0x0 | |
| 146 | # REPRODEBUG: AddressOfRawData: 0x0 | |
| 147 | # REPRODEBUG: PointerToRawData: 0x0 | |
| 148 | # REPRODEBUG: } | |
| 149 | # REPRODEBUG: ] | |
| 150 | ||
| 151 | # MINGW: File: {{.*}}.dll | |
| 152 | # MINGW: DebugDirectory [ | |
| 153 | # MINGW: DebugEntry { | |
| 154 | # MINGW: Characteristics: 0x0 | |
| 155 | # MINGW: TimeDateStamp: | |
| 156 | # MINGW: MajorVersion: 0x0 | |
| 157 | # MINGW: MinorVersion: 0x0 | |
| 158 | # MINGW: Type: CodeView (0x2) | |
| 159 | # MINGW: SizeOfData: 0x{{[^0]}} | |
| 160 | # MINGW: AddressOfRawData: 0x{{[^0]}} | |
| 161 | # MINGW: PointerToRawData: 0x{{[^0]}} | |
| 162 | # MINGW: PDBInfo { | |
| 163 | # MINGW: PDBSignature: 0x53445352 | |
| 164 | # MINGW: PDBGUID: [[GUID:\(([A-Za-z0-9]{2} ?){16}\)]] | |
| 165 | # MINGW: PDBAge: 1 | |
| 166 | # MINGW: PDBFileName: | |
| 167 | # MINGW: } | |
| 168 | # MINGW: } | |
| 169 | # MINGW: ] | |
| 56 | 170 | --- !COFF |
| 57 | 171 | header: |
| 58 | 172 | Machine: IMAGE_FILE_MACHINE_I386 |
deps/lld/test/COFF/s_udt.s created+476| ... | ... | @@ -0,0 +1,476 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-windows-msvc < %s > %t.obj | |
| 3 | # RUN: lld-link /DEBUG:FULL /nodefaultlib /entry:main %t.obj /PDB:%t.pdb /OUT:%t.exe | |
| 4 | # RUN: llvm-pdbutil dump -types -globals -symbols -modi=0 %t.pdb | FileCheck %s | |
| 5 | ||
| 6 | # CHECK: Types (TPI Stream) | |
| 7 | # CHECK-NEXT: ============================================================ | |
| 8 | # CHECK: 0x1003 | LF_STRUCTURE [size = 44] `Struct` | |
| 9 | # CHECK-NEXT: unique name: `.?AUStruct@@` | |
| 10 | # CHECK-NEXT: vtable: <no type>, base list: <no type>, field list: <no type> | |
| 11 | # CHECK-NEXT: options: forward ref (-> 0x1006) | has unique name, sizeof 0 | |
| 12 | # CHECK-NEXT: 0x1004 | LF_POINTER [size = 12] | |
| 13 | # CHECK-NEXT: referent = 0x1003, mode = pointer, opts = None, kind = ptr64 | |
| 14 | # CHECK: 0x1006 | LF_STRUCTURE [size = 44] `Struct` | |
| 15 | # CHECK-NEXT: unique name: `.?AUStruct@@` | |
| 16 | # CHECK-NEXT: vtable: <no type>, base list: <no type>, field list: 0x1005 | |
| 17 | # CHECK-NEXT: options: has unique name, sizeof 4 | |
| 18 | # CHECK: Global Symbols | |
| 19 | # CHECK-NEXT: ============================================================ | |
| 20 | # CHECK: {{.*}} | S_UDT [size = 24] `StructTypedef` | |
| 21 | # CHECK: original type = 0x1003 | |
| 22 | # CHECK: {{.*}} | S_UDT [size = 16] `Struct` | |
| 23 | # CHECK: original type = 0x1006 | |
| 24 | # CHECK: {{.*}} | S_UDT [size = 20] `IntTypedef` | |
| 25 | # CHECK: original type = 0x0074 (int) | |
| 26 | # CHECK: Symbols | |
| 27 | # CHECK-NEXT: ============================================================ | |
| 28 | # CHECK: {{.*}} | S_GPROC32 [size = 44] `main` | |
| 29 | # CHECK-NEXT: parent = 0, end = 252, addr = 0001:0000, code size = 52 | |
| 30 | # CHECK-NEXT: type = `0x1002 (int (int, char**))`, debug start = 0, debug end = 0, flags = none | |
| 31 | # CHECK-NOT: {{.*}} | S_END | |
| 32 | # CHECK: {{.*}} | S_UDT [size = 28] `main::LocalTypedef` | |
| 33 | # CHECK-NEXT: original type = 0x1004 | |
| 34 | # CHECK: {{.*}} | S_END [size = 4] | |
| 35 | ||
| 36 | # source code to re-generate: | |
| 37 | # clang-cl /Z7 /GS- /GR- /c foo.cpp | |
| 38 | # | |
| 39 | # struct Struct { | |
| 40 | # int x; | |
| 41 | # }; | |
| 42 | # | |
| 43 | # using IntTypedef = int; | |
| 44 | # using StructTypedef = Struct; | |
| 45 | # Struct S; | |
| 46 | # StructTypedef SS; | |
| 47 | # IntTypedef I; | |
| 48 | # | |
| 49 | # int main(int argc, char **argv) { | |
| 50 | # using LocalTypedef = Struct*; | |
| 51 | # LocalTypedef SPtr; | |
| 52 | # return I + S.x + SS.x + SPtr->x; | |
| 53 | # } | |
| 54 | ||
| 55 | 	.text | |
| 56 | 	.def	 @feat.00; | |
| 57 | 	.scl	3; | |
| 58 | 	.type	0; | |
| 59 | 	.endef | |
| 60 | 	.globl	@feat.00 | |
| 61 | .set @feat.00, 0 | |
| 62 | 	.intel_syntax noprefix | |
| 63 | 	.def	 main; | |
| 64 | 	.scl	2; | |
| 65 | 	.type	32; | |
| 66 | 	.endef | |
| 67 | 	.globl	main # -- Begin function main | |
| 68 | 	.p2align	4, 0x90 | |
| 69 | main: # @main | |
| 70 | .Lfunc_begin0: | |
| 71 | 	.cv_func_id 0 | |
| 72 | 	.cv_file	1 "D:\\src\\llvmbuild\\cl\\Debug\\x64\\foo.cpp" "2B62298EE3EEF94E1D81FDFE18BD46A6" 1 | |
| 73 | 	.cv_loc	0 1 12 0 # foo.cpp:12:0 | |
| 74 | .seh_proc main | |
| 75 | # %bb.0: # %entry | |
| 76 | 	sub	rsp, 32 | |
| 77 | 	.seh_stackalloc 32 | |
| 78 | 	.seh_endprologue | |
| 79 | 	mov	dword ptr [rsp + 28], 0 | |
| 80 | 	mov	qword ptr [rsp + 16], rdx | |
| 81 | 	mov	dword ptr [rsp + 12], ecx | |
| 82 | .Ltmp0: | |
| 83 | 	.cv_loc	0 1 15 0 # foo.cpp:15:0 | |
| 84 | 	mov	ecx, dword ptr [rip + "?I@@3HA"] | |
| 85 | 	add	ecx, dword ptr [rip + "?S@@3UStruct@@A"] | |
| 86 | 	add	ecx, dword ptr [rip + "?SS@@3UStruct@@A"] | |
| 87 | 	mov	rdx, qword ptr [rsp] | |
| 88 | 	add	ecx, dword ptr [rdx] | |
| 89 | 	mov	eax, ecx | |
| 90 | 	add	rsp, 32 | |
| 91 | 	ret | |
| 92 | .Ltmp1: | |
| 93 | .Lfunc_end0: | |
| 94 | 	.seh_handlerdata | |
| 95 | 	.text | |
| 96 | 	.seh_endproc | |
| 97 | # -- End function | |
| 98 | 	.bss | |
| 99 | 	.globl	"?S@@3UStruct@@A" # @"?S@@3UStruct@@A" | |
| 100 | 	.p2align	2 | |
| 101 | "?S@@3UStruct@@A": | |
| 102 | 	.zero	4 | |
| 103 | ||
| 104 | 	.globl	"?SS@@3UStruct@@A" # @"?SS@@3UStruct@@A" | |
| 105 | 	.p2align	2 | |
| 106 | "?SS@@3UStruct@@A": | |
| 107 | 	.zero	4 | |
| 108 | ||
| 109 | 	.globl	"?I@@3HA" # @"?I@@3HA" | |
| 110 | 	.p2align	2 | |
| 111 | "?I@@3HA": | |
| 112 | 	.long	0 # 0x0 | |
| 113 | ||
| 114 | 	.section	.drectve,"yn" | |
| 115 | 	.ascii	" /DEFAULTLIB:libcmt.lib" | |
| 116 | 	.ascii	" /DEFAULTLIB:oldnames.lib" | |
| 117 | 	.section	.debug$S,"dr" | |
| 118 | 	.p2align	2 | |
| 119 | 	.long	4 # Debug section magic | |
| 120 | 	.long	241 | |
| 121 | 	.long	.Ltmp3-.Ltmp2 # Subsection size | |
| 122 | .Ltmp2: | |
| 123 | 	.short	.Ltmp5-.Ltmp4 # Record length | |
| 124 | .Ltmp4: | |
| 125 | 	.short	4412 # Record kind: S_COMPILE3 | |
| 126 | 	.long	1 # Flags and language | |
| 127 | 	.short	208 # CPUType | |
| 128 | 	.short	8 # Frontend version | |
| 129 | 	.short	0 | |
| 130 | 	.short	0 | |
| 131 | 	.short	0 | |
| 132 | 	.short	8000 # Backend version | |
| 133 | 	.short	0 | |
| 134 | 	.short	0 | |
| 135 | 	.short	0 | |
| 136 | 	.asciz	"clang version 8.0.0 " # Null-terminated compiler version string | |
| 137 | .Ltmp5: | |
| 138 | .Ltmp3: | |
| 139 | 	.p2align	2 | |
| 140 | 	.long	241 # Symbol subsection for main | |
| 141 | 	.long	.Ltmp7-.Ltmp6 # Subsection size | |
| 142 | .Ltmp6: | |
| 143 | 	.short	.Ltmp9-.Ltmp8 # Record length | |
| 144 | .Ltmp8: | |
| 145 | 	.short	4423 # Record kind: S_GPROC32_ID | |
| 146 | 	.long	0 # PtrParent | |
| 147 | 	.long	0 # PtrEnd | |
| 148 | 	.long	0 # PtrNext | |
| 149 | 	.long	.Lfunc_end0-main # Code size | |
| 150 | 	.long	0 # Offset after prologue | |
| 151 | 	.long	0 # Offset before epilogue | |
| 152 | 	.long	4099 # Function type index | |
| 153 | 	.secrel32	main # Function section relative address | |
| 154 | 	.secidx	main # Function section index | |
| 155 | 	.byte	0 # Flags | |
| 156 | 	.asciz	"main" # Function name | |
| 157 | .Ltmp9: | |
| 158 | 	.short	.Ltmp11-.Ltmp10 # Record length | |
| 159 | .Ltmp10: | |
| 160 | 	.short	4114 # Record kind: S_FRAMEPROC | |
| 161 | 	.long	32 # FrameSize | |
| 162 | 	.long	0 # Padding | |
| 163 | 	.long	0 # Offset of padding | |
| 164 | 	.long	0 # Bytes of callee saved registers | |
| 165 | 	.long	0 # Exception handler offset | |
| 166 | 	.short	0 # Exception handler section | |
| 167 | 	.long	81920 # Flags (defines frame register) | |
| 168 | .Ltmp11: | |
| 169 | 	.short	.Ltmp13-.Ltmp12 # Record length | |
| 170 | .Ltmp12: | |
| 171 | 	.short	4414 # Record kind: S_LOCAL | |
| 172 | 	.long	116 # TypeIndex | |
| 173 | 	.short	1 # Flags | |
| 174 | 	.asciz	"argc" | |
| 175 | .Ltmp13: | |
| 176 | 	.cv_def_range	 .Ltmp0 .Ltmp1, "B\021\f\000\000\000" | |
| 177 | 	.short	.Ltmp15-.Ltmp14 # Record length | |
| 178 | .Ltmp14: | |
| 179 | 	.short	4414 # Record kind: S_LOCAL | |
| 180 | 	.long	4096 # TypeIndex | |
| 181 | 	.short	1 # Flags | |
| 182 | 	.asciz	"argv" | |
| 183 | .Ltmp15: | |
| 184 | 	.cv_def_range	 .Ltmp0 .Ltmp1, "B\021\020\000\000\000" | |
| 185 | 	.short	.Ltmp17-.Ltmp16 # Record length | |
| 186 | .Ltmp16: | |
| 187 | 	.short	4414 # Record kind: S_LOCAL | |
| 188 | 	.long	4101 # TypeIndex | |
| 189 | 	.short	0 # Flags | |
| 190 | 	.asciz	"SPtr" | |
| 191 | .Ltmp17: | |
| 192 | 	.cv_def_range	 .Ltmp0 .Ltmp1, "B\021\000\000\000\000" | |
| 193 | 	.short	.Ltmp19-.Ltmp18 # Record length | |
| 194 | .Ltmp18: | |
| 195 | 	.short	4360 # Record kind: S_UDT | |
| 196 | 	.long	4101 # Type | |
| 197 | 	.asciz	"main::LocalTypedef" | |
| 198 | .Ltmp19: | |
| 199 | 	.short	2 # Record length | |
| 200 | 	.short	4431 # Record kind: S_PROC_ID_END | |
| 201 | .Ltmp7: | |
| 202 | 	.p2align	2 | |
| 203 | 	.cv_linetable	0, main, .Lfunc_end0 | |
| 204 | 	.long	241 # Symbol subsection for globals | |
| 205 | 	.long	.Ltmp21-.Ltmp20 # Subsection size | |
| 206 | .Ltmp20: | |
| 207 | 	.short	.Ltmp23-.Ltmp22 # Record length | |
| 208 | .Ltmp22: | |
| 209 | 	.short	4365 # Record kind: S_GDATA32 | |
| 210 | 	.long	4103 # Type | |
| 211 | 	.secrel32	"?S@@3UStruct@@A" # DataOffset | |
| 212 | 	.secidx	"?S@@3UStruct@@A" # Segment | |
| 213 | 	.asciz	"S" # Name | |
| 214 | .Ltmp23: | |
| 215 | 	.short	.Ltmp25-.Ltmp24 # Record length | |
| 216 | .Ltmp24: | |
| 217 | 	.short	4365 # Record kind: S_GDATA32 | |
| 218 | 	.long	4100 # Type | |
| 219 | 	.secrel32	"?SS@@3UStruct@@A" # DataOffset | |
| 220 | 	.secidx	"?SS@@3UStruct@@A" # Segment | |
| 221 | 	.asciz	"SS" # Name | |
| 222 | .Ltmp25: | |
| 223 | 	.short	.Ltmp27-.Ltmp26 # Record length | |
| 224 | .Ltmp26: | |
| 225 | 	.short	4365 # Record kind: S_GDATA32 | |
| 226 | 	.long	116 # Type | |
| 227 | 	.secrel32	"?I@@3HA" # DataOffset | |
| 228 | 	.secidx	"?I@@3HA" # Segment | |
| 229 | 	.asciz	"I" # Name | |
| 230 | .Ltmp27: | |
| 231 | .Ltmp21: | |
| 232 | 	.p2align	2 | |
| 233 | 	.long	241 | |
| 234 | 	.long	.Ltmp29-.Ltmp28 # Subsection size | |
| 235 | .Ltmp28: | |
| 236 | 	.short	.Ltmp31-.Ltmp30 # Record length | |
| 237 | .Ltmp30: | |
| 238 | 	.short	4360 # Record kind: S_UDT | |
| 239 | 	.long	4103 # Type | |
| 240 | 	.asciz	"Struct" | |
| 241 | .Ltmp31: | |
| 242 | 	.short	.Ltmp33-.Ltmp32 # Record length | |
| 243 | .Ltmp32: | |
| 244 | 	.short	4360 # Record kind: S_UDT | |
| 245 | 	.long	4100 # Type | |
| 246 | 	.asciz	"StructTypedef" | |
| 247 | .Ltmp33: | |
| 248 | 	.short	.Ltmp35-.Ltmp34 # Record length | |
| 249 | .Ltmp34: | |
| 250 | 	.short	4360 # Record kind: S_UDT | |
| 251 | 	.long	116 # Type | |
| 252 | 	.asciz	"IntTypedef" | |
| 253 | .Ltmp35: | |
| 254 | .Ltmp29: | |
| 255 | 	.p2align	2 | |
| 256 | 	.cv_filechecksums # File index to string table offset subsection | |
| 257 | 	.cv_stringtable # String table | |
| 258 | 	.long	241 | |
| 259 | 	.long	.Ltmp37-.Ltmp36 # Subsection size | |
| 260 | .Ltmp36: | |
| 261 | 	.short	6 # Record length | |
| 262 | 	.short	4428 # Record kind: S_BUILDINFO | |
| 263 | 	.long	4108 # LF_BUILDINFO index | |
| 264 | .Ltmp37: | |
| 265 | 	.p2align	2 | |
| 266 | 	.section	.debug$T,"dr" | |
| 267 | 	.p2align	2 | |
| 268 | 	.long	4 # Debug section magic | |
| 269 | 	# Pointer (0x1000) { | |
| 270 | 	# TypeLeafKind: LF_POINTER (0x1002) | |
| 271 | 	# PointeeType: char* (0x670) | |
| 272 | 	# PtrType: Near64 (0xC) | |
| 273 | 	# PtrMode: Pointer (0x0) | |
| 274 | 	# IsFlat: 0 | |
| 275 | 	# IsConst: 0 | |
| 276 | 	# IsVolatile: 0 | |
| 277 | 	# IsUnaligned: 0 | |
| 278 | 	# IsRestrict: 0 | |
| 279 | 	# IsThisPtr&: 0 | |
| 280 | 	# IsThisPtr&&: 0 | |
| 281 | 	# SizeOf: 8 | |
| 282 | 	# } | |
| 283 | 	.byte	0x0a, 0x00, 0x02, 0x10 | |
| 284 | 	.byte	0x70, 0x06, 0x00, 0x00 | |
| 285 | 	.byte	0x0c, 0x00, 0x01, 0x00 | |
| 286 | 	# ArgList (0x1001) { | |
| 287 | 	# TypeLeafKind: LF_ARGLIST (0x1201) | |
| 288 | 	# NumArgs: 2 | |
| 289 | 	# Arguments [ | |
| 290 | 	# ArgType: int (0x74) | |
| 291 | 	# ArgType: char** (0x1000) | |
| 292 | 	# ] | |
| 293 | 	# } | |
| 294 | 	.byte	0x0e, 0x00, 0x01, 0x12 | |
| 295 | 	.byte	0x02, 0x00, 0x00, 0x00 | |
| 296 | 	.byte	0x74, 0x00, 0x00, 0x00 | |
| 297 | 	.byte	0x00, 0x10, 0x00, 0x00 | |
| 298 | 	# Procedure (0x1002) { | |
| 299 | 	# TypeLeafKind: LF_PROCEDURE (0x1008) | |
| 300 | 	# ReturnType: int (0x74) | |
| 301 | 	# CallingConvention: NearC (0x0) | |
| 302 | 	# FunctionOptions [ (0x0) | |
| 303 | 	# ] | |
| 304 | 	# NumParameters: 2 | |
| 305 | 	# ArgListType: (int, char**) (0x1001) | |
| 306 | 	# } | |
| 307 | 	.byte	0x0e, 0x00, 0x08, 0x10 | |
| 308 | 	.byte	0x74, 0x00, 0x00, 0x00 | |
| 309 | 	.byte	0x00, 0x00, 0x02, 0x00 | |
| 310 | 	.byte	0x01, 0x10, 0x00, 0x00 | |
| 311 | 	# FuncId (0x1003) { | |
| 312 | 	# TypeLeafKind: LF_FUNC_ID (0x1601) | |
| 313 | 	# ParentScope: 0x0 | |
| 314 | 	# FunctionType: int (int, char**) (0x1002) | |
| 315 | 	# Name: main | |
| 316 | 	# } | |
| 317 | 	.byte	0x12, 0x00, 0x01, 0x16 | |
| 318 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 319 | 	.byte	0x02, 0x10, 0x00, 0x00 | |
| 320 | 	.byte	0x6d, 0x61, 0x69, 0x6e | |
| 321 | 	.byte	0x00, 0xf3, 0xf2, 0xf1 | |
| 322 | 	# Struct (0x1004) { | |
| 323 | 	# TypeLeafKind: LF_STRUCTURE (0x1505) | |
| 324 | 	# MemberCount: 0 | |
| 325 | 	# Properties [ (0x280) | |
| 326 | 	# ForwardReference (0x80) | |
| 327 | 	# HasUniqueName (0x200) | |
| 328 | 	# ] | |
| 329 | 	# FieldList: 0x0 | |
| 330 | 	# DerivedFrom: 0x0 | |
| 331 | 	# VShape: 0x0 | |
| 332 | 	# SizeOf: 0 | |
| 333 | 	# Name: Struct | |
| 334 | 	# LinkageName: .?AUStruct@@ | |
| 335 | 	# } | |
| 336 | 	.byte	0x2a, 0x00, 0x05, 0x15 | |
| 337 | 	.byte	0x00, 0x00, 0x80, 0x02 | |
| 338 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 339 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 340 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 341 | 	.byte	0x00, 0x00, 0x53, 0x74 | |
| 342 | 	.byte	0x72, 0x75, 0x63, 0x74 | |
| 343 | 	.byte	0x00, 0x2e, 0x3f, 0x41 | |
| 344 | 	.byte	0x55, 0x53, 0x74, 0x72 | |
| 345 | 	.byte	0x75, 0x63, 0x74, 0x40 | |
| 346 | 	.byte	0x40, 0x00, 0xf2, 0xf1 | |
| 347 | 	# Pointer (0x1005) { | |
| 348 | 	# TypeLeafKind: LF_POINTER (0x1002) | |
| 349 | 	# PointeeType: Struct (0x1004) | |
| 350 | 	# PtrType: Near64 (0xC) | |
| 351 | 	# PtrMode: Pointer (0x0) | |
| 352 | 	# IsFlat: 0 | |
| 353 | 	# IsConst: 0 | |
| 354 | 	# IsVolatile: 0 | |
| 355 | 	# IsUnaligned: 0 | |
| 356 | 	# IsRestrict: 0 | |
| 357 | 	# IsThisPtr&: 0 | |
| 358 | 	# IsThisPtr&&: 0 | |
| 359 | 	# SizeOf: 8 | |
| 360 | 	# } | |
| 361 | 	.byte	0x0a, 0x00, 0x02, 0x10 | |
| 362 | 	.byte	0x04, 0x10, 0x00, 0x00 | |
| 363 | 	.byte	0x0c, 0x00, 0x01, 0x00 | |
| 364 | 	# FieldList (0x1006) { | |
| 365 | 	# TypeLeafKind: LF_FIELDLIST (0x1203) | |
| 366 | 	# DataMember { | |
| 367 | 	# TypeLeafKind: LF_MEMBER (0x150D) | |
| 368 | 	# AccessSpecifier: Public (0x3) | |
| 369 | 	# Type: int (0x74) | |
| 370 | 	# FieldOffset: 0x0 | |
| 371 | 	# Name: x | |
| 372 | 	# } | |
| 373 | 	# } | |
| 374 | 	.byte	0x0e, 0x00, 0x03, 0x12 | |
| 375 | 	.byte	0x0d, 0x15, 0x03, 0x00 | |
| 376 | 	.byte	0x74, 0x00, 0x00, 0x00 | |
| 377 | 	.byte	0x00, 0x00, 0x78, 0x00 | |
| 378 | 	# Struct (0x1007) { | |
| 379 | 	# TypeLeafKind: LF_STRUCTURE (0x1505) | |
| 380 | 	# MemberCount: 1 | |
| 381 | 	# Properties [ (0x200) | |
| 382 | 	# HasUniqueName (0x200) | |
| 383 | 	# ] | |
| 384 | 	# FieldList: <field list> (0x1006) | |
| 385 | 	# DerivedFrom: 0x0 | |
| 386 | 	# VShape: 0x0 | |
| 387 | 	# SizeOf: 4 | |
| 388 | 	# Name: Struct | |
| 389 | 	# LinkageName: .?AUStruct@@ | |
| 390 | 	# } | |
| 391 | 	.byte	0x2a, 0x00, 0x05, 0x15 | |
| 392 | 	.byte	0x01, 0x00, 0x00, 0x02 | |
| 393 | 	.byte	0x06, 0x10, 0x00, 0x00 | |
| 394 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 395 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 396 | 	.byte	0x04, 0x00, 0x53, 0x74 | |
| 397 | 	.byte	0x72, 0x75, 0x63, 0x74 | |
| 398 | 	.byte	0x00, 0x2e, 0x3f, 0x41 | |
| 399 | 	.byte	0x55, 0x53, 0x74, 0x72 | |
| 400 | 	.byte	0x75, 0x63, 0x74, 0x40 | |
| 401 | 	.byte	0x40, 0x00, 0xf2, 0xf1 | |
| 402 | 	# StringId (0x1008) { | |
| 403 | 	# TypeLeafKind: LF_STRING_ID (0x1605) | |
| 404 | 	# Id: 0x0 | |
| 405 | 	# StringData: D:\src\llvmbuild\cl\Debug\x64\foo.cpp | |
| 406 | 	# } | |
| 407 | 	.byte	0x2e, 0x00, 0x05, 0x16 | |
| 408 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 409 | 	.byte	0x44, 0x3a, 0x5c, 0x73 | |
| 410 | 	.byte	0x72, 0x63, 0x5c, 0x6c | |
| 411 | 	.byte	0x6c, 0x76, 0x6d, 0x62 | |
| 412 | 	.byte	0x75, 0x69, 0x6c, 0x64 | |
| 413 | 	.byte	0x5c, 0x63, 0x6c, 0x5c | |
| 414 | 	.byte	0x44, 0x65, 0x62, 0x75 | |
| 415 | 	.byte	0x67, 0x5c, 0x78, 0x36 | |
| 416 | 	.byte	0x34, 0x5c, 0x66, 0x6f | |
| 417 | 	.byte	0x6f, 0x2e, 0x63, 0x70 | |
| 418 | 	.byte	0x70, 0x00, 0xf2, 0xf1 | |
| 419 | 	# UdtSourceLine (0x1009) { | |
| 420 | 	# TypeLeafKind: LF_UDT_SRC_LINE (0x1606) | |
| 421 | 	# UDT: Struct (0x1007) | |
| 422 | 	# SourceFile: D:\src\llvmbuild\cl\Debug\x64\foo.cpp (0x1008) | |
| 423 | 	# LineNumber: 1 | |
| 424 | 	# } | |
| 425 | 	.byte	0x0e, 0x00, 0x06, 0x16 | |
| 426 | 	.byte	0x07, 0x10, 0x00, 0x00 | |
| 427 | 	.byte	0x08, 0x10, 0x00, 0x00 | |
| 428 | 	.byte	0x01, 0x00, 0x00, 0x00 | |
| 429 | 	# StringId (0x100A) { | |
| 430 | 	# TypeLeafKind: LF_STRING_ID (0x1605) | |
| 431 | 	# Id: 0x0 | |
| 432 | 	# StringData: D:\\src\\llvmbuild\\cl\\Debug\\x64 | |
| 433 | 	# } | |
| 434 | 	.byte	0x2a, 0x00, 0x05, 0x16 | |
| 435 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 436 | 	.byte	0x44, 0x3a, 0x5c, 0x5c | |
| 437 | 	.byte	0x73, 0x72, 0x63, 0x5c | |
| 438 | 	.byte	0x5c, 0x6c, 0x6c, 0x76 | |
| 439 | 	.byte	0x6d, 0x62, 0x75, 0x69 | |
| 440 | 	.byte	0x6c, 0x64, 0x5c, 0x5c | |
| 441 | 	.byte	0x63, 0x6c, 0x5c, 0x5c | |
| 442 | 	.byte	0x44, 0x65, 0x62, 0x75 | |
| 443 | 	.byte	0x67, 0x5c, 0x5c, 0x78 | |
| 444 | 	.byte	0x36, 0x34, 0x00, 0xf1 | |
| 445 | 	# StringId (0x100B) { | |
| 446 | 	# TypeLeafKind: LF_STRING_ID (0x1605) | |
| 447 | 	# Id: 0x0 | |
| 448 | 	# StringData: foo.cpp | |
| 449 | 	# } | |
| 450 | 	.byte	0x0e, 0x00, 0x05, 0x16 | |
| 451 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 452 | 	.byte	0x66, 0x6f, 0x6f, 0x2e | |
| 453 | 	.byte	0x63, 0x70, 0x70, 0x00 | |
| 454 | 	# BuildInfo (0x100C) { | |
| 455 | 	# TypeLeafKind: LF_BUILDINFO (0x1603) | |
| 456 | 	# NumArgs: 5 | |
| 457 | 	# Arguments [ | |
| 458 | 	# ArgType: D:\\src\\llvmbuild\\cl\\Debug\\x64 (0x100A) | |
| 459 | 	# ArgType: 0x0 | |
| 460 | 	# ArgType: foo.cpp (0x100B) | |
| 461 | 	# ArgType: 0x0 | |
| 462 | 	# ArgType: 0x0 | |
| 463 | 	# ] | |
| 464 | 	# } | |
| 465 | 	.byte	0x1a, 0x00, 0x03, 0x16 | |
| 466 | 	.byte	0x05, 0x00, 0x0a, 0x10 | |
| 467 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 468 | 	.byte	0x00, 0x00, 0x0b, 0x10 | |
| 469 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 470 | 	.byte	0x00, 0x00, 0x00, 0x00 | |
| 471 | 	.byte	0x00, 0x00, 0xf2, 0xf1 | |
| 472 | ||
| 473 | 	.addrsig | |
| 474 | 	.addrsig_sym "?S@@3UStruct@@A" | |
| 475 | 	.addrsig_sym "?SS@@3UStruct@@A" | |
| 476 | 	.addrsig_sym "?I@@3HA" |
deps/lld/test/COFF/subsystem-inference-mingw.s created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.o | |
| 3 | ||
| 4 | # RUN: lld-link -lldmingw %t.o -out:%t.exe | |
| 5 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck %s | |
| 6 | ||
| 7 | # CHECK: AddressOfEntryPoint: 0x1001 | |
| 8 | # CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3) | |
| 9 | ||
| 10 | .text | |
| 11 | .globl foo | |
| 12 | .globl mainCRTStartup | |
| 13 | foo: | |
| 14 | ret | |
| 15 | mainCRTStartup: | |
| 16 | call foo | |
| 17 | ret |
deps/lld/test/COFF/subsystem-inference2.test created+54| ... | ... | @@ -0,0 +1,54 @@ |
| 1 | # RUN: yaml2obj %s > %t.obj | |
| 2 | # RUN: lld-link /out:%t.exe %t.obj 2>&1 | FileCheck -check-prefix=WARN %s | |
| 3 | # RUN: llvm-readobj -file-headers %t.exe | FileCheck %s | |
| 4 | ||
| 5 | # WARN: warning: found main and WinMain; defaulting to /subsystem:console | |
| 6 | # CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI | |
| 7 | ||
| 8 | --- !COFF | |
| 9 | header: | |
| 10 | Machine: IMAGE_FILE_MACHINE_AMD64 | |
| 11 | Characteristics: [] | |
| 12 | sections: | |
| 13 | - Name: .text | |
| 14 | Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] | |
| 15 | Alignment: 4 | |
| 16 | SectionData: B82A000000C3 | |
| 17 | symbols: | |
| 18 | - Name: .text | |
| 19 | Value: 0 | |
| 20 | SectionNumber: 1 | |
| 21 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 22 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 23 | StorageClass: IMAGE_SYM_CLASS_STATIC | |
| 24 | SectionDefinition: | |
| 25 | Length: 6 | |
| 26 | NumberOfRelocations: 0 | |
| 27 | NumberOfLinenumbers: 0 | |
| 28 | CheckSum: 0 | |
| 29 | Number: 0 | |
| 30 | - Name: main | |
| 31 | Value: 0 | |
| 32 | SectionNumber: 1 | |
| 33 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 34 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 35 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 36 | - Name: WinMain | |
| 37 | Value: 0 | |
| 38 | SectionNumber: 1 | |
| 39 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 40 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 41 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 42 | - Name: mainCRTStartup | |
| 43 | Value: 0 | |
| 44 | SectionNumber: 1 | |
| 45 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 46 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 47 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 48 | - Name: WinMainCRTStartup | |
| 49 | Value: 0 | |
| 50 | SectionNumber: 1 | |
| 51 | SimpleType: IMAGE_SYM_TYPE_NULL | |
| 52 | ComplexType: IMAGE_SYM_DTYPE_NULL | |
| 53 | StorageClass: IMAGE_SYM_CLASS_EXTERNAL | |
| 54 | ... |
deps/lld/test/COFF/thinlto-archives.ll+10-2| ... | ... | @@ -6,9 +6,17 @@ |
| 6 | 6 | ; RUN: opt -thinlto-bc -o %T/thinlto-archives/b/bar.obj %S/Inputs/bar.ll |
| 7 | 7 | ; RUN: llvm-ar crs %T/thinlto-archives/a.lib %T/thinlto-archives/a/bar.obj |
| 8 | 8 | ; RUN: llvm-ar crs %T/thinlto-archives/b.lib %T/thinlto-archives/b/bar.obj |
| 9 | ; RUN: lld-link /out:%T/thinlto-archives/main.exe -entry:main \ | |
| 10 | ; RUN: -subsystem:console %T/thinlto-archives/main.obj \ | |
| 9 | ; RUN: lld-link -out:%T/thinlto-archives/main.exe -entry:main \ | |
| 10 | ; RUN: -lldsavetemps -subsystem:console %T/thinlto-archives/main.obj \ | |
| 11 | 11 | ; RUN: %T/thinlto-archives/a.lib %T/thinlto-archives/b.lib |
| 12 | ; RUN: FileCheck %s < %T/thinlto-archives/main.exe.resolution.txt | |
| 13 | ||
| 14 | ; CHECK: {{/thinlto-archives/main.obj$}} | |
| 15 | ; CHECK: {{^-r=.*/thinlto-archives/main.obj,main,px$}} | |
| 16 | ; CHECK: {{/thinlto-archives/a.libbar.obj$}} | |
| 17 | ; CHECK-NEXT: {{^-r=.*/thinlto-archives/a.libbar.obj,foo,p$}} | |
| 18 | ; CHECK-NEXT: {{/thinlto-archives/b.libbar.obj$}} | |
| 19 | ; CHECK-NEXT: {{^-r=.*/thinlto-archives/b.libbar.obj,bar,p$}} | |
| 12 | 20 | |
| 13 | 21 | target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128" |
| 14 | 22 | target triple = "x86_64-pc-windows-msvc" |
deps/lld/test/COFF/undefined-symbol-cv.s+5-5| ... | ... | @@ -2,19 +2,19 @@ |
| 2 | 2 | # RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s |
| 3 | 3 | # RUN: not lld-link /out:%t.exe %t.obj 2>&1 | FileCheck %s |
| 4 | 4 | |
| 5 | # CHECK: error: undefined symbol: ?foo@@YAHXZ | |
| 5 | # CHECK: error: undefined symbol: "int __cdecl foo(void)" (?foo@@YAHXZ) | |
| 6 | 6 | # CHECK-NEXT: >>> referenced by file1.cpp:1 |
| 7 | 7 | # CHECK-NEXT: >>> {{.*}}.obj:(main) |
| 8 | 8 | # CHECK-NEXT: >>> referenced by file1.cpp:2 |
| 9 | 9 | # CHECK-NEXT: >>> {{.*}}.obj:(main) |
| 10 | ||
| 11 | # CHECK: error: undefined symbol: ?bar@@YAHXZ | |
| 10 | # CHECK-EMPTY: | |
| 11 | # CHECK-NEXT: error: undefined symbol: "int __cdecl bar(void)" (?bar@@YAHXZ) | |
| 12 | 12 | # CHECK-NEXT: >>> referenced by file2.cpp:3 |
| 13 | 13 | # CHECK-NEXT: >>> {{.*}}.obj:(main) |
| 14 | 14 | # CHECK-NEXT: >>> referenced by file1.cpp:4 |
| 15 | 15 | # CHECK-NEXT: >>> {{.*}}.obj:(f1) |
| 16 | ||
| 17 | # CHECK: error: undefined symbol: ?baz@@YAHXZ | |
| 16 | # CHECK-EMPTY: | |
| 17 | # CHECK-NEXT: error: undefined symbol: "int __cdecl baz(void)" (?baz@@YAHXZ) | |
| 18 | 18 | # CHECK-NEXT: >>> referenced by file1.cpp:5 |
| 19 | 19 | # CHECK-NEXT: >>> {{.*}}.obj:(f2) |
| 20 | 20 |
deps/lld/test/COFF/undefined-symbol.s+6-6| ... | ... | @@ -2,15 +2,15 @@ |
| 2 | 2 | # RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s |
| 3 | 3 | # RUN: not lld-link /out:%t.exe %t.obj 2>&1 | FileCheck %s |
| 4 | 4 | |
| 5 | # CHECK: error: undefined symbol: ?foo@@YAHXZ | |
| 5 | # CHECK: error: undefined symbol: "int __cdecl foo(void)" (?foo@@YAHXZ) | |
| 6 | 6 | # CHECK-NEXT: >>> referenced by {{.*}}.obj:(main) |
| 7 | 7 | # CHECK-NEXT: >>> referenced by {{.*}}.obj:(main) |
| 8 | ||
| 9 | # CHECK: error: undefined symbol: ?bar@@YAHXZ | |
| 8 | # CHECK-EMPTY: | |
| 9 | # CHECK-NEXT: error: undefined symbol: "int __cdecl bar(void)" (?bar@@YAHXZ) | |
| 10 | 10 | # CHECK-NEXT: >>> referenced by {{.*}}.obj:(main) |
| 11 | 11 | # CHECK-NEXT: >>> referenced by {{.*}}.obj:(f1) |
| 12 | ||
| 13 | # CHECK: error: undefined symbol: ?baz@@YAHXZ | |
| 12 | # CHECK-EMPTY: | |
| 13 | # CHECK-NEXT: error: undefined symbol: "__declspec(dllimport) int __cdecl baz(void)" (__imp_?baz@@YAHXZ) | |
| 14 | 14 | # CHECK-NEXT: >>> referenced by {{.*}}.obj:(f2) |
| 15 | 15 | |
| 16 | 16 | .section .text,"xr",one_only,main |
| ... | ... | @@ -27,4 +27,4 @@ f1: |
| 27 | 27 | .section .text,"xr",one_only,f2 |
| 28 | 28 | .globl f2 |
| 29 | 29 | f2: |
| 30 | 	call	"?baz@@YAHXZ" | |
| 30 | 	callq	*"__imp_?baz@@YAHXZ"(%rip) |
deps/lld/test/COFF/wholearchive.s+1| ... | ... | @@ -1,6 +1,7 @@ |
| 1 | 1 | # REQUIRES: x86 |
| 2 | 2 | |
| 3 | 3 | # RUN: yaml2obj < %p/Inputs/export.yaml > %t.archive.obj |
| 4 | # RUN: rm -f %t.archive.lib | |
| 4 | 5 | # RUN: llvm-ar rcs %t.archive.lib %t.archive.obj |
| 5 | 6 | # RUN: llvm-mc -triple=x86_64-windows-msvc %s -filetype=obj -o %t.main.obj |
| 6 | 7 |
deps/lld/test/ELF/Inputs/bad-reloc-target.test created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | --- !ELF | |
| 2 | FileHeader: | |
| 3 | Class: ELFCLASS64 | |
| 4 | Data: ELFDATA2LSB | |
| 5 | Type: ET_REL | |
| 6 | Machine: EM_X86_64 | |
| 7 | Sections: | |
| 8 | - Name: .text | |
| 9 | Type: SHT_PROGBITS | |
| 10 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 11 | - Name: .rela.text | |
| 12 | Type: SHT_RELA | |
| 13 | Link: .symtab | |
| 14 | Info: 99 | |
| 15 | Relocations: | |
| 16 | - Offset: 0x0000000000000000 | |
| 17 | Symbol: foo | |
| 18 | Type: R_X86_64_64 | |
| 19 | Symbols: | |
| 20 | Global: | |
| 21 | - Name: foo | |
| \ No newline at end of file |
deps/lld/test/ELF/Inputs/copy-rel-tls.s created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | .bss | |
| 2 | .global foo | |
| 3 | .type foo, @object | |
| 4 | .size foo, 4 | |
| 5 | foo: | |
| 6 | ||
| 7 | .section .tbss,"awT",@nobits | |
| 8 | .global tfoo | |
| 9 | .skip 0x2000 | |
| 10 | .type tfoo,@object | |
| 11 | .size tfoo, 4 | |
| 12 | tfoo: |
deps/lld/test/ELF/Inputs/gdb-index-invalid-ranges.obj.s created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | main: | |
| 2 | callq f1 |
deps/lld/test/ELF/Inputs/gdb-index-multiple-cu-2.s created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | .globl _start | |
| 2 | _start: | |
| 3 | ||
| 4 | .section .debug_abbrev,"",@progbits | |
| 5 | 	.byte	1 # Abbreviation Code | |
| 6 | 	.byte	17 # DW_TAG_compile_unit | |
| 7 | 	.byte	1 # DW_CHILDREN_yes | |
| 8 | 	.ascii	"\264B" # DW_AT_GNU_pubnames | |
| 9 | 	.byte	25 # DW_FORM_flag_present | |
| 10 | 	.byte	0 # EOM(1) | |
| 11 | 	.byte	0 # EOM(2) | |
| 12 | 	.byte	2 # Abbreviation Code | |
| 13 | 	.byte	46 # DW_TAG_subprogram | |
| 14 | 	.byte	0 # DW_CHILDREN_no | |
| 15 | 	.byte	3 # DW_AT_name | |
| 16 | 	.byte	8 # DW_FORM_string | |
| 17 | 	.byte	0 # EOM(1) | |
| 18 | 	.byte	0 # EOM(2) | |
| 19 | 	.byte	0 | |
| 20 | ||
| 21 | .section .debug_info,"",@progbits | |
| 22 | .Lcu_begin0: | |
| 23 | 	.long	.Lcu_end0 - .Lcu_begin0 - 4 | |
| 24 | 	.short	4 # DWARF version number | |
| 25 | 	.long	0 # Offset Into Abbrev. Section | |
| 26 | 	.byte	4 # Address Size | |
| 27 | .Ldie: | |
| 28 | 	.byte	1 # Abbrev [1] DW_TAG_compile_unit | |
| 29 | 	.byte	2 # Abbrev [2] DW_TAG_subprogram | |
| 30 | 	.asciz	"_start" # DW_AT_name | |
| 31 | 	.byte	0 | |
| 32 | .Lcu_end0: | |
| 33 | ||
| 34 | # .debug_gnu_pubnames has just one set, associated with .Lcu_begin1 (CuIndex: 1) | |
| 35 | .section .debug_gnu_pubnames,"",@progbits | |
| 36 | 	.long	.LpubNames_end0 - .LpubNames_begin0 | |
| 37 | .LpubNames_begin0: | |
| 38 | 	.short	2 # Version | |
| 39 | 	.long	.Lcu_begin0 # CU Offset | |
| 40 | 	.long	.Lcu_end0 - .Lcu_begin0 | |
| 41 | 	.long	.Ldie - .Lcu_begin0 | |
| 42 | 	.byte	48 # Attributes: FUNCTION, EXTERNAL | |
| 43 | 	.asciz	"_start" # External Name | |
| 44 | 	.long	0 | |
| 45 | .LpubNames_end0: |
deps/lld/test/ELF/Inputs/hexagon-shared.s created+3| ... | ... | @@ -0,0 +1,3 @@ |
| 1 | .global bar | |
| 2 | bar: | |
| 3 | jumpr lr |
deps/lld/test/ELF/Inputs/i386-linkonce.s created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | .section .gnu.linkonce.t.__i686.get_pc_thunk.bx | |
| 2 | .global __i686.get_pc_thunk.bx | |
| 3 | __i686.get_pc_thunk.bx: | |
| 4 | mov (%esp),%ebx | |
| 5 | ret | |
| 6 | ||
| 7 | .section .text | |
| 8 | .global _strchr1 | |
| 9 | _strchr1: | |
| 10 | call __i686.get_pc_thunk.bx | |
| 11 | ret |
deps/lld/test/ELF/Inputs/ppc64-bsymbolic-local-def.s created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | .abiversion 2 | |
| 2 | .section ".text" | |
| 3 | ||
| 4 | .p2align 2 | |
| 5 | .global def | |
| 6 | .type def, @function | |
| 7 | def: | |
| 8 | .Ldef_gep: | |
| 9 | addis 2, 12, .TOC.-.Ldef_gep@ha | |
| 10 | addi 2, 2, .TOC.-.Ldef_gep@l | |
| 11 | .Ldef_lep: | |
| 12 | .localentry def, .-def | |
| 13 | li 3, 55 | |
| 14 | blr |
deps/lld/test/ELF/Inputs/ppc64-no-split-stack.s created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | 	.abiversion 2 | |
| 2 | .p2align 2 | |
| 3 | .global nss_callee | |
| 4 | .type nss_callee, @function | |
| 5 | nss_callee: | |
| 6 | li 3, 1 | |
| 7 | blr | |
| 8 |
deps/lld/test/ELF/Inputs/ppc64-tls-ie-le.s created+29| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | 	.text | |
| 2 | 	.abiversion 2 | |
| 3 | 	.type	c,@object # @c | |
| 4 | 	.section	.tdata,"awT",@progbits | |
| 5 | 	.globl	c | |
| 6 | c: | |
| 7 | 	.byte	97 # 0x61 | |
| 8 | 	.size	c, 1 | |
| 9 | ||
| 10 | 	.type	s,@object # @s | |
| 11 | 	.globl	s | |
| 12 | 	.p2align	1 | |
| 13 | s: | |
| 14 | 	.short	55 # 0x37 | |
| 15 | 	.size	s, 2 | |
| 16 | ||
| 17 | 	.type	i,@object # @i | |
| 18 | 	.globl	i | |
| 19 | 	.p2align	2 | |
| 20 | i: | |
| 21 | 	.long	55 # 0x37 | |
| 22 | 	.size	i, 4 | |
| 23 | ||
| 24 | 	.type	l,@object # @l | |
| 25 | 	.globl	l | |
| 26 | 	.p2align	3 | |
| 27 | l: | |
| 28 | 	.quad	55 # 0x37 | |
| 29 | 	.size	l, 8 |
deps/lld/test/ELF/Inputs/ppc64le-quadword-ldst.o created| Binary files /dev/null and b/deps/lld/test/ELF/Inputs/ppc64le-quadword-ldst.o differ |
deps/lld/test/ELF/Inputs/wrap-with-archive.s created+5| ... | ... | @@ -0,0 +1,5 @@ |
| 1 | .global __executable_start | |
| 2 | .global __wrap_get_executable_start | |
| 3 | ||
| 4 | __wrap_get_executable_start:	 | |
| 5 | 	movabs $__executable_start,%rdx |
deps/lld/test/ELF/Inputs/x86-64-split-stack-extra.s created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | # This file is split out to provide better code coverage. | |
| 2 | 	.global	split | |
| 3 | 	.type	split,@function | |
| 4 | split: | |
| 5 | 	retq | |
| 6 | ||
| 7 | 	.size	split,. - split | |
| 8 | ||
| 9 | 	.section	.note.GNU-stack,"",@progbits | |
| 10 | 	.section	.note.GNU-split-stack,"",@progbits |
deps/lld/test/ELF/aarch64-abs16.s+10-10| ... | ... | @@ -14,14 +14,14 @@ _start: |
| 14 | 14 | // RUN: llvm-objdump -s -section=.data %t2 | FileCheck %s |
| 15 | 15 | |
| 16 | 16 | // CHECK: Contents of section .data: |
| 17 | // 11000: S = 0x100, A = 0xfeff | |
| 18 | // S + A = 0xffff | |
| 19 | // 11002: S = 0x100, A = -0x8100 | |
| 20 | // S + A = 0x8000 | |
| 21 | // CHECK-NEXT: 20000 ffff0080 | |
| 17 | // 210000: S = 0x100, A = 0xfeff | |
| 18 | // S + A = 0xffff | |
| 19 | // 210002: S = 0x100, A = -0x8100 | |
| 20 | // S + A = 0x8000 | |
| 21 | // CHECK-NEXT: 210000 ffff0080 | |
| 22 | 22 | |
| 23 | // RUN: not ld.lld %t.o %t255.o -o %t2 | |
| 24 | // | FileCheck %s --check-prefix=OVERFLOW | |
| 25 | // RUN: not ld.lld %t.o %t257.o -o %t2 | |
| 26 | // | FileCheck %s --check-prefix=OVERFLOW | |
| 27 | // OVERFLOW: Relocation R_AARCH64_ABS16 out of range: 65536 is not in [-32768, 65535] | |
| 23 | // RUN: not ld.lld %t.o %t255.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW1 | |
| 24 | // OVERFLOW1: relocation R_AARCH64_ABS16 out of range: -32769 is not in [-32768, 32767] | |
| 25 | ||
| 26 | // RUN: not ld.lld %t.o %t257.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW2 | |
| 27 | // OVERFLOW2: relocation R_AARCH64_ABS16 out of range: 65536 is not in [-32768, 32767] |
deps/lld/test/ELF/aarch64-abs32.s+10-10| ... | ... | @@ -14,14 +14,14 @@ _start: |
| 14 | 14 | // RUN: llvm-objdump -s -section=.data %t2 | FileCheck %s |
| 15 | 15 | |
| 16 | 16 | // CHECK: Contents of section .data: |
| 17 | // 20000: S = 0x100, A = 0xfffffeff | |
| 18 | // S + A = 0xffffffff | |
| 19 | // 20004: S = 0x100, A = -0x80000100 | |
| 20 | // S + A = 0x80000000 | |
| 21 | // CHECK-NEXT: 20000 ffffffff 00000080 | |
| 17 | // 210000: S = 0x100, A = 0xfffffeff | |
| 18 | // S + A = 0xffffffff | |
| 19 | // 210004: S = 0x100, A = -0x80000100 | |
| 20 | // S + A = 0x80000000 | |
| 21 | // CHECK-NEXT: 210000 ffffffff 00000080 | |
| 22 | 22 | |
| 23 | // RUN: not ld.lld %t.o %t255.o -o %t2 | |
| 24 | // | FileCheck %s --check-prefix=OVERFLOW | |
| 25 | // RUN: not ld.lld %t.o %t257.o -o %t2 | |
| 26 | // | FileCheck %s --check-prefix=OVERFLOW | |
| 27 | // OVERFLOW: Relocation R_AARCH64_ABS32 out of range: 4294967296 is not in [-2147483648, 4294967295] | |
| 23 | // RUN: not ld.lld %t.o %t255.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW1 | |
| 24 | // OVERFLOW1: relocation R_AARCH64_ABS32 out of range: -2147483649 is not in [-2147483648, 2147483647] | |
| 25 | ||
| 26 | // RUN: not ld.lld %t.o %t257.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW2 | |
| 27 | // OVERFLOW2: relocation R_AARCH64_ABS32 out of range: 4294967296 is not in [-2147483648, 2147483647] |
deps/lld/test/ELF/aarch64-call26-thunk.s+5-5| ... | ... | @@ -11,11 +11,11 @@ _start: |
| 11 | 11 | |
| 12 | 12 | // CHECK: Disassembly of section .text: |
| 13 | 13 | // CHECK-NEXT: _start: |
| 14 | // CHECK-NEXT: 20000: 02 00 00 94 bl #8 | |
| 14 | // CHECK-NEXT: 210000: 02 00 00 94 bl #8 | |
| 15 | 15 | // CHECK: __AArch64AbsLongThunk_big: |
| 16 | // CHECK-NEXT: 20008: 50 00 00 58 ldr x16, #8 | |
| 17 | // CHECK-NEXT: 2000c: 00 02 1f d6 br x16 | |
| 16 | // CHECK-NEXT: 210008: 50 00 00 58 ldr x16, #8 | |
| 17 | // CHECK-NEXT: 21000c: 00 02 1f d6 br x16 | |
| 18 | 18 | // CHECK: $d: |
| 19 | // CHECK-NEXT: 20010: 00 00 00 00 .word 0x00000000 | |
| 20 | // CHECK-NEXT: 20014: 10 00 00 00 .word 0x00000010 | |
| 19 | // CHECK-NEXT: 210010: 00 00 00 00 .word 0x00000000 | |
| 20 | // CHECK-NEXT: 210014: 10 00 00 00 .word 0x00000010 | |
| 21 | 21 |
deps/lld/test/ELF/aarch64-combined-dynrel-ifunc.s created+51| ... | ... | @@ -0,0 +1,51 @@ |
| 1 | // REQUIRES: AArch64 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/shared.s -o %t-lib.o | |
| 3 | // RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o | |
| 4 | // RUN: ld.lld %t-lib.o --shared -o %t.so | |
| 5 | // RUN: echo "SECTIONS { \ | |
| 6 | // RUN: .text : { *(.text) } \ | |
| 7 | // RUN: .rela.dyn : { *(.rela.dyn) *(.rela.plt) } \ | |
| 8 | // RUN: } " > %t.script | |
| 9 | // RUN: ld.lld %t.o -o %t.axf %t.so --script %t.script | |
| 10 | // RUN: llvm-readobj --section-headers --dynamic-table %t.axf | FileCheck %s | |
| 11 | ||
| 12 | // The linker script above combines the .rela.dyn and .rela.plt into a single | |
| 13 | // table. ELF is clear that the DT_PLTRELSZ should match the subset of | |
| 14 | // relocations that is associated with the PLT. It is less clear about what | |
| 15 | // the value of DT_RELASZ should be. ELF implies that it should be the size | |
| 16 | // of the single table so that DT_RELASZ includes DT_PLTRELSZ. The loader in | |
| 17 | // glibc permits this as long as .rela.plt comes after .rela.dyn in the | |
| 18 | // combined table. In the ARM case irelative relocations do not count as PLT | |
| 19 | // relocs. In the AArch64 case irelative relocations count as PLT relocs. | |
| 20 | ||
| 21 | .text | |
| 22 | .globl indirect | |
| 23 | .type indirect,@gnu_indirect_function | |
| 24 | indirect: | |
| 25 | ret | |
| 26 | ||
| 27 | .globl bar // from Inputs/shared.s | |
| 28 | ||
| 29 | .text | |
| 30 | .globl _start | |
| 31 | .type _start,@function | |
| 32 | main: | |
| 33 | bl indirect | |
| 34 | bl bar | |
| 35 | adrp x8, :got:indirect | |
| 36 | ldr x8, [x8, :got_lo12:indirect] | |
| 37 | adrp x8, :got:bar | |
| 38 | ldr x8, [x8, :got_lo12:bar] | |
| 39 | ret | |
| 40 | ||
| 41 | // CHECK: Name: .rela.dyn | |
| 42 | // CHECK-NEXT: Type: SHT_RELA | |
| 43 | // CHECK-NEXT: Flags [ | |
| 44 | // CHECK-NEXT: SHF_ALLOC | |
| 45 | // CHECK-NEXT: ] | |
| 46 | // CHECK-NEXT: Address: | |
| 47 | // CHECK-NEXT: Offset: | |
| 48 | // CHECK-NEXT: Size: 72 | |
| 49 | ||
| 50 | // CHECK: 0x0000000000000008 RELASZ 72 | |
| 51 | // CHECK: 0x0000000000000002 PLTRELSZ 48 |
deps/lld/test/ELF/aarch64-combined-dynrel.s created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | // REQUIRES: AArch64 | |
| 2 | // RUN: llvm-mc --triple=aarch64-linux-gnu -filetype=obj -o %t.o %s | |
| 3 | // RUN: echo "SECTIONS { \ | |
| 4 | // RUN: .text : { *(.text) } \ | |
| 5 | // RUN: .rela.dyn : { *(.rela.dyn) *(.rela.plt) } \ | |
| 6 | // RUN: } " > %t.script | |
| 7 | // RUN: ld.lld %t.o -o %t.so --shared --script %t.script | |
| 8 | // RUN: llvm-readobj --section-headers --dynamic-table %t.so | FileCheck %s | |
| 9 | ||
| 10 | // The linker script above combines the .rela.dyn and .rela.plt into a single | |
| 11 | // table. ELF is clear that the DT_PLTRELSZ should match the subset of | |
| 12 | // relocations that is associated with the PLT. It is less clear about what | |
| 13 | // the value of DT_RELASZ should be. ELF implies that it should be the size | |
| 14 | // of the single table so that DT_RELASZ includes DT_PLTRELSZ. The loader in | |
| 15 | // glibc permits this as long as .rela.plt comes after .rela.dyn in the | |
| 16 | // combined table. | |
| 17 | .text | |
| 18 | .globl func | |
| 19 | .type func, %function | |
| 20 | .globl foo | |
| 21 | .type foo, %object | |
| 22 | ||
| 23 | .globl _start | |
| 24 | .type _start, %function | |
| 25 | _start: | |
| 26 | bl func | |
| 27 | adrp x8, :got:foo | |
| 28 | ldr x8, [x8, :got_lo12:foo] | |
| 29 | ret | |
| 30 | ||
| 31 | // CHECK: Name: .rela.dyn | |
| 32 | // CHECK-NEXT: Type: SHT_RELA | |
| 33 | // CHECK-NEXT: Flags [ | |
| 34 | // CHECK-NEXT: SHF_ALLOC | |
| 35 | // CHECK-NEXT: ] | |
| 36 | // CHECK-NEXT: Address: | |
| 37 | // CHECK-NEXT: Offset: | |
| 38 | // CHECK-NEXT: Size: 48 | |
| 39 | ||
| 40 | // CHECK: 0x0000000000000008 RELASZ 48 | |
| 41 | // CHECK: 0x0000000000000002 PLTRELSZ 24 |
deps/lld/test/ELF/aarch64-condb-reloc.s+18-12| ... | ... | @@ -12,21 +12,21 @@ |
| 12 | 12 | # 0x1102c - 16 = 0x1101c |
| 13 | 13 | # CHECK: Disassembly of section .text: |
| 14 | 14 | # CHECK-NEXT: _foo: |
| 15 | # CHECK-NEXT: 20000: {{.*}} nop | |
| 16 | # CHECK-NEXT: 20004: {{.*}} nop | |
| 17 | # CHECK-NEXT: 20008: {{.*}} nop | |
| 18 | # CHECK-NEXT: 2000c: {{.*}} nop | |
| 15 | # CHECK-NEXT: 210000: {{.*}} nop | |
| 16 | # CHECK-NEXT: 210004: {{.*}} nop | |
| 17 | # CHECK-NEXT: 210008: {{.*}} nop | |
| 18 | # CHECK-NEXT: 21000c: {{.*}} nop | |
| 19 | 19 | # CHECK: _bar: |
| 20 | # CHECK-NEXT: 20010: {{.*}} nop | |
| 21 | # CHECK-NEXT: 20014: {{.*}} nop | |
| 22 | # CHECK-NEXT: 20018: {{.*}} nop | |
| 20 | # CHECK-NEXT: 210010: {{.*}} nop | |
| 21 | # CHECK-NEXT: 210014: {{.*}} nop | |
| 22 | # CHECK-NEXT: 210018: {{.*}} nop | |
| 23 | 23 | # CHECK: _dah: |
| 24 | # CHECK-NEXT: 2001c: {{.*}} nop | |
| 25 | # CHECK-NEXT: 20020: {{.*}} nop | |
| 24 | # CHECK-NEXT: 21001c: {{.*}} nop | |
| 25 | # CHECK-NEXT: 210020: {{.*}} nop | |
| 26 | 26 | # CHECK: _start: |
| 27 | # CHECK-NEXT: 20024: {{.*}} b.eq #-36 | |
| 28 | # CHECK-NEXT: 20028: {{.*}} b.eq #-24 | |
| 29 | # CHECK-NEXT: 2002c: {{.*}} b.eq #-16 | |
| 27 | # CHECK-NEXT: 210024: {{.*}} b.eq #-36 | |
| 28 | # CHECK-NEXT: 210028: {{.*}} b.eq #-24 | |
| 29 | # CHECK-NEXT: 21002c: {{.*}} b.eq #-16 | |
| 30 | 30 | |
| 31 | 31 | #DSOREL: Section { |
| 32 | 32 | #DSOREL: Index: |
| ... | ... | @@ -79,14 +79,20 @@ |
| 79 | 79 | #DSO-NEXT: 10044: {{.*}} nop |
| 80 | 80 | #DSO-NEXT: 10048: {{.*}} nop |
| 81 | 81 | #DSO-NEXT: 1004c: {{.*}} nop |
| 82 | #DSO-EMPTY: | |
| 83 | #DSO-NEXT: _foo@plt: | |
| 82 | 84 | #DSO-NEXT: 10050: {{.*}} adrp x16, #65536 |
| 83 | 85 | #DSO-NEXT: 10054: {{.*}} ldr x17, [x16, #24] |
| 84 | 86 | #DSO-NEXT: 10058: {{.*}} add x16, x16, #24 |
| 85 | 87 | #DSO-NEXT: 1005c: {{.*}} br x17 |
| 88 | #DSO-EMPTY: | |
| 89 | #DSO-NEXT: _bar@plt: | |
| 86 | 90 | #DSO-NEXT: 10060: {{.*}} adrp x16, #65536 |
| 87 | 91 | #DSO-NEXT: 10064: {{.*}} ldr x17, [x16, #32] |
| 88 | 92 | #DSO-NEXT: 10068: {{.*}} add x16, x16, #32 |
| 89 | 93 | #DSO-NEXT: 1006c: {{.*}} br x17 |
| 94 | #DSO-EMPTY: | |
| 95 | #DSO-NEXT: _dah@plt: | |
| 90 | 96 | #DSO-NEXT: 10070: {{.*}} adrp x16, #65536 |
| 91 | 97 | #DSO-NEXT: 10074: {{.*}} ldr x17, [x16, #40] |
| 92 | 98 | #DSO-NEXT: 10078: {{.*}} add x16, x16, #40 |
deps/lld/test/ELF/aarch64-copy.s+16-16| ... | ... | @@ -22,7 +22,7 @@ _start: |
| 22 | 22 | // CHECK-NEXT: SHF_ALLOC |
| 23 | 23 | // CHECK-NEXT: SHF_WRITE |
| 24 | 24 | // CHECK-NEXT: ] |
| 25 | // CHECK-NEXT: Address: 0x40000 | |
| 25 | // CHECK-NEXT: Address: 0x230000 | |
| 26 | 26 | // CHECK-NEXT: Offset: |
| 27 | 27 | // CHECK-NEXT: Size: 24 |
| 28 | 28 | // CHECK-NEXT: Link: |
| ... | ... | @@ -32,19 +32,19 @@ _start: |
| 32 | 32 | // CHECK: Relocations [ |
| 33 | 33 | // CHECK-NEXT: Section ({{.*}}) .rela.dyn { |
| 34 | 34 | // CHECK-NEXT: Relocation { |
| 35 | // CHECK-NEXT: Offset: 0x40000 | |
| 35 | // CHECK-NEXT: Offset: 0x230000 | |
| 36 | 36 | // CHECK-NEXT: Type: R_AARCH64_COPY |
| 37 | 37 | // CHECK-NEXT: Symbol: x |
| 38 | 38 | // CHECK-NEXT: Addend: 0x0 |
| 39 | 39 | // CHECK-NEXT: } |
| 40 | 40 | // CHECK-NEXT: Relocation { |
| 41 | // CHECK-NEXT: Offset: 0x40010 | |
| 41 | // CHECK-NEXT: Offset: 0x230010 | |
| 42 | 42 | // CHECK-NEXT: Type: R_AARCH64_COPY |
| 43 | 43 | // CHECK-NEXT: Symbol: y |
| 44 | 44 | // CHECK-NEXT: Addend: 0x0 |
| 45 | 45 | // CHECK-NEXT: } |
| 46 | 46 | // CHECK-NEXT: Relocation { |
| 47 | // CHECK-NEXT: Offset: 0x40014 | |
| 47 | // CHECK-NEXT: Offset: 0x230014 | |
| 48 | 48 | // CHECK-NEXT: Type: R_AARCH64_COPY |
| 49 | 49 | // CHECK-NEXT: Symbol: z |
| 50 | 50 | // CHECK-NEXT: Addend: 0x0 |
| ... | ... | @@ -54,21 +54,21 @@ _start: |
| 54 | 54 | |
| 55 | 55 | // CHECK: Symbols [ |
| 56 | 56 | // CHECK: Name: x |
| 57 | // CHECK-NEXT: Value: 0x40000 | |
| 57 | // CHECK-NEXT: Value: 0x230000 | |
| 58 | 58 | // CHECK-NEXT: Size: 4 |
| 59 | 59 | // CHECK-NEXT: Binding: Global |
| 60 | 60 | // CHECK-NEXT: Type: Object |
| 61 | 61 | // CHECK-NEXT: Other: |
| 62 | 62 | // CHECK-NEXT: Section: .bss |
| 63 | 63 | // CHECK: Name: y |
| 64 | // CHECK-NEXT: Value: 0x40010 | |
| 64 | // CHECK-NEXT: Value: 0x230010 | |
| 65 | 65 | // CHECK-NEXT: Size: 4 |
| 66 | 66 | // CHECK-NEXT: Binding: Global |
| 67 | 67 | // CHECK-NEXT: Type: Object |
| 68 | 68 | // CHECK-NEXT: Other: |
| 69 | 69 | // CHECK-NEXT: Section: .bss |
| 70 | 70 | // CHECK: Name: z |
| 71 | // CHECK-NEXT: Value: 0x40014 | |
| 71 | // CHECK-NEXT: Value: 0x230014 | |
| 72 | 72 | // CHECK-NEXT: Size: 4 |
| 73 | 73 | // CHECK-NEXT: Binding: Global |
| 74 | 74 | // CHECK-NEXT: Type: Object |
| ... | ... | @@ -78,16 +78,16 @@ _start: |
| 78 | 78 | |
| 79 | 79 | // CODE: Disassembly of section .text: |
| 80 | 80 | // CODE-NEXT: _start: |
| 81 | // S(x) = 0x40000, A = 0, P = 0x20000 | |
| 81 | // S(x) = 0x230000, A = 0, P = 0x210000 | |
| 82 | 82 | // S + A - P = 0x20000 = 131072 |
| 83 | // CODE-NEXT: 20000: {{.*}} adr x1, #131072 | |
| 84 | // S(y) = 0x40010, A = 0, P = 0x20004 | |
| 85 | // Page(S + A) - Page(P) = 0x40000 - 0x20000 = 0x20000 = 131072 | |
| 86 | // CODE-NEXT: 20004: {{.*}} adrp x2, #131072 | |
| 87 | // S(y) = 0x40010, A = 0 | |
| 83 | // CODE-NEXT: 210000: {{.*}} adr x1, #131072 | |
| 84 | // S(y) = 0x230010, A = 0, P = 0x210004 | |
| 85 | // Page(S + A) - Page(P) = 0x230000 - 0x210000 = 0x20000 = 131072 | |
| 86 | // CODE-NEXT: 210004: {{.*}} adrp x2, #131072 | |
| 87 | // S(y) = 0x230010, A = 0 | |
| 88 | 88 | // (S + A) & 0xFFF = 0x10 = 16 |
| 89 | // CODE-NEXT: 20008: {{.*}} add x2, x2, #16 | |
| 89 | // CODE-NEXT: 210008: {{.*}} add x2, x2, #16 | |
| 90 | 90 | |
| 91 | 91 | // RODATA: Contents of section .rodata: |
| 92 | // S(z) = 0x40014 | |
| 93 | // RODATA-NEXT: 102e0 14000400 | |
| 92 | // S(z) = 0x230014 | |
| 93 | // RODATA-NEXT: 2002e0 14002300 |
deps/lld/test/ELF/aarch64-copy2.s+1-1| ... | ... | @@ -19,7 +19,7 @@ _start: |
| 19 | 19 | // CHECK-NEXT: Section: Undefined |
| 20 | 20 | |
| 21 | 21 | // CHECK: Name: foo |
| 22 | // CHECK-NEXT: Value: 0x20030 | |
| 22 | // CHECK-NEXT: Value: 0x210030 | |
| 23 | 23 | // CHECK-NEXT: Size: 0 |
| 24 | 24 | // CHECK-NEXT: Binding: Global |
| 25 | 25 | // CHECK-NEXT: Type: Function |
deps/lld/test/ELF/aarch64-cortex-a53-843419-abs-mapsyms.s created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | // REQUIRES: aarch64 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t | |
| 3 | // RUN: ld.lld --just-symbols %t -fix-cortex-a53-843419 -o %t.axf | |
| 4 | // RUN: llvm-readobj --symbols %t.axf | FileCheck %s | |
| 5 | ||
| 6 | // Check that we can gracefully handle --just-symbols, which gives a local | |
| 7 | // absolute mapping symbol (with no Section). Previously we assumed that all | |
| 8 | // mapping symbols were defined relative to a section and assert failed. | |
| 9 | ||
| 10 | .text | |
| 11 | .global _start | |
| 12 | .type _start, %function | |
| 13 | _start: ret | |
| 14 | ||
| 15 | // CHECK: Name: $x.0 | |
| 16 | // CHECK-NEXT: Value: 0x0 | |
| 17 | // CHECK-NEXT: Size: 0 | |
| 18 | // CHECK-NEXT: Binding: Local (0x0) | |
| 19 | // CHECK-NEXT: Type: None (0x0) | |
| 20 | // CHECK-NEXT: Other: 0 | |
| 21 | // CHECK-NEXT: Section: Absolute (0xFFF1) | |
| 22 | // CHECK-NEXT: } |
deps/lld/test/ELF/aarch64-cortex-a53-843419-cli.s+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 3 | 3 | // RUN: not ld.lld %t -fix-cortex-a53-843419 -o /dev/null 2>&1 | FileCheck %s |
| 4 | 4 | |
| 5 | // CHECK: --fix-cortex-a53-843419 is only supported on AArch64 targets. | |
| 5 | // CHECK: --fix-cortex-a53-843419 is only supported on AArch64 targets | |
| 6 | 6 | .globl entry |
| 7 | 7 | .text |
| 8 | 8 | .quad 0 |
deps/lld/test/ELF/aarch64-cortex-a53-843419-large.s+37-37| ... | ... | @@ -1,23 +1,23 @@ |
| 1 | 1 | // REQUIRES: aarch64 |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o |
| 3 | 3 | // RUN: ld.lld --fix-cortex-a53-843419 %t.o -o %t2 |
| 4 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=131072 -stop-address=131084 | FileCheck --check-prefix=CHECK1 %s | |
| 5 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=135168 -stop-address=135172 | FileCheck --check-prefix=CHECK2 %s | |
| 6 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=139256 -stop-address=139272 | FileCheck --check-prefix=CHECK3 %s | |
| 7 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=67256312 -stop-address=67256328 | FileCheck --check-prefix=CHECK4 %s | |
| 8 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=100810760 -stop-address=100810776 | FileCheck --check-prefix=CHECK5 %s | |
| 9 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=134352908 -stop-address=134352912 | FileCheck --check-prefix=CHECK6 %s | |
| 10 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=134356988 -stop-address=134357012 | FileCheck --check-prefix=CHECK7 %s | |
| 4 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=2162688 -stop-address=2162700 | FileCheck --check-prefix=CHECK1 %s | |
| 5 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=2166784 -stop-address=2166788 | FileCheck --check-prefix=CHECK2 %s | |
| 6 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=2170872 -stop-address=2170888 | FileCheck --check-prefix=CHECK3 %s | |
| 7 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=69287928 -stop-address=69287944 | FileCheck --check-prefix=CHECK4 %s | |
| 8 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=102842376 -stop-address=102842392 | FileCheck --check-prefix=CHECK5 %s | |
| 9 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=136384524 -stop-address=136384528 | FileCheck --check-prefix=CHECK6 %s | |
| 10 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 -start-address=136388604 -stop-address=136388628 | FileCheck --check-prefix=CHECK7 %s | |
| 11 | 11 | // Test case for Cortex-A53 Erratum 843419 in an OutputSection exceeding |
| 12 | 12 | // the maximum branch range. Both range extension thunks and patches are |
| 13 | // required. | |
| 14 | ||
| 13 | // required.					 | |
| 14 | 						 | |
| 15 | 15 | // CHECK1: __AArch64AbsLongThunk_need_thunk_after_patch: |
| 16 | // CHECK1-NEXT: 20000: 50 00 00 58 ldr x16, #8 | |
| 17 | // CHECK1-NEXT: 20004: 00 02 1f d6 br x16 | |
| 18 | // CHECK1: $d: | |
| 19 | // CHECK1-NEXT: 20008: 0c 10 02 08 .word 0x0802100c | |
| 20 | ||
| 16 | // CHECK1-NEXT: 210000: 50 00 00 58 ldr x16, #8 | |
| 17 | // CHECK1-NEXT: 210004: 00 02 1f d6 br x16 | |
| 18 | // CHECK1: $d:					 | |
| 19 | // CHECK1-NEXT: 210008: 0c 10 21 08 .word 0x0821100c | |
| 20 | 						 | |
| 21 | 21 | .section .text.01, "ax", %progbits |
| 22 | 22 | .balign 4096 |
| 23 | 23 | .globl _start |
| ... | ... | @@ -29,7 +29,7 @@ _start: |
| 29 | 29 | .space 4096 - 12 |
| 30 | 30 | |
| 31 | 31 | // CHECK2: _start: |
| 32 | // CHECK2-NEXT: 21000: 00 fc ff 97 bl #-4096 | |
| 32 | // CHECK2-NEXT: 211000: 00 fc ff 97 bl #-4096 | |
| 33 | 33 | |
| 34 | 34 | // Expect patch on pass 1 |
| 35 | 35 | .section .text.03, "ax", %progbits |
| ... | ... | @@ -42,10 +42,10 @@ t3_ff8_ldr: |
| 42 | 42 | ret |
| 43 | 43 | |
| 44 | 44 | // CHECK3: t3_ff8_ldr: |
| 45 | // CHECK3-NEXT: 21ff8: 60 00 04 f0 adrp x0, #134279168 | |
| 46 | // CHECK3-NEXT: 21ffc: 21 00 40 f9 ldr x1, [x1] | |
| 47 | // CHECK3-NEXT: 22000: 02 08 80 15 b #100671496 | |
| 48 | // CHECK3-NEXT: 22004: c0 03 5f d6 ret | |
| 45 | // CHECK3-NEXT: 211ff8: 60 00 04 f0 adrp x0, #134279168 | |
| 46 | // CHECK3-NEXT: 211ffc: 21 00 40 f9 ldr x1, [x1] | |
| 47 | // CHECK3-NEXT: 212000: 02 08 80 15 b #100671496 | |
| 48 | // CHECK3-NEXT: 212004: c0 03 5f d6 ret | |
| 49 | 49 | |
| 50 | 50 | .section .text.04, "ax", %progbits |
| 51 | 51 | .space 64 * 1024 * 1024 |
| ... | ... | @@ -63,20 +63,20 @@ t3_ff8_str: |
| 63 | 63 | ret |
| 64 | 64 | |
| 65 | 65 | // CHECK4: t3_ff8_str: |
| 66 | // CHECK4-NEXT: 4023ff8: 60 00 02 b0 adrp x0, #67162112 | |
| 67 | // CHECK4-NEXT: 4023ffc: 21 00 40 f9 ldr x1, [x1] | |
| 68 | // CHECK4-NEXT: 4024000: 04 00 80 14 b #33554448 | |
| 69 | // CHECK4-NEXT: 4024004: c0 03 5f d6 ret | |
| 66 | // CHECK4-NEXT: 4213ff8: 60 00 02 b0 adrp x0, #67162112 | |
| 67 | // CHECK4-NEXT: 4213ffc: 21 00 40 f9 ldr x1, [x1] | |
| 68 | // CHECK4-NEXT: 4214000: 04 00 80 14 b #33554448 | |
| 69 | // CHECK4-NEXT: 4214004: c0 03 5f d6 ret | |
| 70 | 70 | |
| 71 | 71 | .section .text.06, "ax", %progbits |
| 72 | 72 | .space 32 * 1024 * 1024 |
| 73 | 73 | |
| 74 | // CHECK5: __CortexA53843419_21000: | |
| 75 | // CHECK5-NEXT: 6024008: 00 00 40 f9 ldr x0, [x0] | |
| 76 | // CHECK5-NEXT: 602400c: fe f7 7f 16 b #-100671496 | |
| 77 | // CHECK5: __CortexA53843419_4023000: | |
| 78 | // CHECK5-NEXT: 6024010: 00 00 00 f9 str x0, [x0] | |
| 79 | // CHECK5-NEXT: 6024014: fc ff 7f 17 b #-33554448 | |
| 74 | // CHECK5: __CortexA53843419_211000: | |
| 75 | // CHECK5-NEXT: 6214008: 00 00 40 f9 ldr x0, [x0] | |
| 76 | // CHECK5-NEXT: 621400c: fe f7 7f 16 b #-100671496 | |
| 77 | // CHECK5: __CortexA53843419_4213000: | |
| 78 | // CHECK5-NEXT: 6214010: 00 00 00 f9 str x0, [x0] | |
| 79 | // CHECK5-NEXT: 6214014: fc ff 7f 17 b #-33554448 | |
| 80 | 80 | |
| 81 | 81 | .section .text.07, "ax", %progbits |
| 82 | 82 | .space (32 * 1024 * 1024) - 12300 |
| ... | ... | @@ -88,7 +88,7 @@ need_thunk_after_patch: |
| 88 | 88 | ret |
| 89 | 89 | |
| 90 | 90 | // CHECK6: need_thunk_after_patch: |
| 91 | // CHECK6-NEXT: 802100c: c0 03 5f d6 ret | |
| 91 | // CHECK6-NEXT: 821100c: c0 03 5f d6 ret | |
| 92 | 92 | |
| 93 | 93 | // Will need a patch on pass 2 |
| 94 | 94 | .section .text.09, "ax", %progbits |
| ... | ... | @@ -102,13 +102,13 @@ t3_ffc_ldr: |
| 102 | 102 | ret |
| 103 | 103 | |
| 104 | 104 | // CHECK7: t3_ffc_ldr: |
| 105 | // CHECK7-NEXT: 8021ffc: 60 00 00 f0 adrp x0, #61440 | |
| 106 | // CHECK7-NEXT: 8022000: 21 00 40 f9 ldr x1, [x1] | |
| 107 | // CHECK7-NEXT: 8022004: 02 00 00 14 b #8 | |
| 108 | // CHECK7-NEXT: 8022008: c0 03 5f d6 ret | |
| 109 | // CHECK7: __CortexA53843419_8022004: | |
| 110 | // CHECK7-NEXT: 802200c: 00 00 40 f9 ldr x0, [x0] | |
| 111 | // CHECK7-NEXT: 8022010: fe ff ff 17 b #-8 | |
| 105 | // CHECK7-NEXT: 8211ffc: 60 00 00 f0 adrp x0, #61440 | |
| 106 | // CHECK7-NEXT: 8212000: 21 00 40 f9 ldr x1, [x1] | |
| 107 | // CHECK7-NEXT: 8212004: 02 00 00 14 b #8 | |
| 108 | // CHECK7-NEXT: 8212008: c0 03 5f d6 ret | |
| 109 | // CHECK7: __CortexA53843419_8212004: | |
| 110 | // CHECK7-NEXT: 821200c: 00 00 40 f9 ldr x0, [x0] | |
| 111 | // CHECK7-NEXT: 8212010: fe ff ff 17 b #-8 | |
| 112 | 112 | |
| 113 | 113 | .section .data |
| 114 | 114 | .globl dat |
deps/lld/test/ELF/aarch64-cortex-a53-843419-large2.s created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | // REQUIRES: aarch64 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o | |
| 3 | // RUN: ld.lld --fix-cortex-a53-843419 -Ttext=0x8000000 %t.o -o %t2 | |
| 4 | // RUN: llvm-objdump -d --start-address=0x8001000 --stop-address=0x8001004 %t2 | FileCheck %s | |
| 5 | ||
| 6 | .section .text.01, "ax", %progbits | |
| 7 | .balign 4096 | |
| 8 | .space 4096 - 8 | |
| 9 | adrp x0, thunk | |
| 10 | ldr x1, [x1, #0] | |
| 11 | // CHECK: thunk: | |
| 12 | // CHECK-NEXT: b #67108872 <__CortexA53843419_8001000> | |
| 13 | thunk: | |
| 14 | ldr x0, [x0, :got_lo12:thunk] | |
| 15 | ret | |
| 16 | .space 64 * 1024 * 1024 | |
| 17 | ||
| 18 | .section .text.02, "ax", %progbits | |
| 19 | .space 64 * 1024 * 1024 |
deps/lld/test/ELF/aarch64-cortex-a53-843419-recognize.s+245-245| ... | ... | @@ -26,13 +26,13 @@ |
| 26 | 26 | // - Optional instruction 3 present or not. |
| 27 | 27 | // - Load or store for instruction 4. |
| 28 | 28 | |
| 29 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21FF8 in unpatched output. | |
| 29 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 211FF8 in unpatched output. | |
| 30 | 30 | // CHECK: t3_ff8_ldr: |
| 31 | // CHECK-NEXT: 21ff8: e0 01 00 f0 adrp x0, #258048 | |
| 32 | // CHECK-NEXT: 21ffc: 21 00 40 f9 ldr x1, [x1] | |
| 33 | // CHECK-FIX: 22000: 03 c8 00 14 b #204812 | |
| 34 | // CHECK-NOFIX: 22000: 00 00 40 f9 ldr x0, [x0] | |
| 35 | // CHECK-NEXT: 22004: c0 03 5f d6 ret | |
| 31 | // CHECK-NEXT: 211ff8: e0 01 00 f0 adrp x0, #258048 | |
| 32 | // CHECK-NEXT: 211ffc: 21 00 40 f9 ldr x1, [x1] | |
| 33 | // CHECK-FIX: 212000: 03 c8 00 14 b #204812 | |
| 34 | // CHECK-NOFIX: 212000: 00 00 40 f9 ldr x0, [x0] | |
| 35 | // CHECK-NEXT: 212004: c0 03 5f d6 ret | |
| 36 | 36 | .section .text.01, "ax", %progbits |
| 37 | 37 | .balign 4096 |
| 38 | 38 | .globl t3_ff8_ldr |
| ... | ... | @@ -44,13 +44,13 @@ t3_ff8_ldr: |
| 44 | 44 | ldr x0, [x0, :got_lo12:dat1] |
| 45 | 45 | ret |
| 46 | 46 | |
| 47 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23FF8 in unpatched output. | |
| 47 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 213FF8 in unpatched output. | |
| 48 | 48 | // CHECK: t3_ff8_ldrsimd: |
| 49 | // CHECK-NEXT: 23ff8: e0 01 00 b0 adrp x0, #249856 | |
| 50 | // CHECK-NEXT: 23ffc: 21 00 40 bd ldr s1, [x1] | |
| 51 | // CHECK-FIX: 24000: 05 c0 00 14 b #196628 | |
| 52 | // CHECK-NOFIX: 24000: 02 04 40 f9 ldr x2, [x0, #8] | |
| 53 | // CHECK-NEXT: 24004: c0 03 5f d6 ret | |
| 49 | // CHECK-NEXT: 213ff8: e0 01 00 b0 adrp x0, #249856 | |
| 50 | // CHECK-NEXT: 213ffc: 21 00 40 bd ldr s1, [x1] | |
| 51 | // CHECK-FIX: 214000: 05 c0 00 14 b #196628 | |
| 52 | // CHECK-NOFIX: 214000: 02 04 40 f9 ldr x2, [x0, #8] | |
| 53 | // CHECK-NEXT: 214004: c0 03 5f d6 ret | |
| 54 | 54 | .section .text.02, "ax", %progbits |
| 55 | 55 | .balign 4096 |
| 56 | 56 | .globl t3_ff8_ldrsimd |
| ... | ... | @@ -62,13 +62,13 @@ t3_ff8_ldrsimd: |
| 62 | 62 | ldr x2, [x0, :got_lo12:dat2] |
| 63 | 63 | ret |
| 64 | 64 | |
| 65 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 25FFC in unpatched output. | |
| 65 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 215FFC in unpatched output. | |
| 66 | 66 | // CHECK: t3_ffc_ldrpost: |
| 67 | // CHECK-NEXT: 25ffc: c0 01 00 f0 adrp x0, #241664 | |
| 68 | // CHECK-NEXT: 26000: 21 84 40 bc ldr s1, [x1], #8 | |
| 69 | // CHECK-FIX: 26004: 06 b8 00 14 b #188440 | |
| 70 | // CHECK-NOFIX: 26004: 03 08 40 f9 ldr x3, [x0, #16] | |
| 71 | // CHECK-NEXT: 26008: c0 03 5f d6 ret | |
| 67 | // CHECK-NEXT: 215ffc: c0 01 00 f0 adrp x0, #241664 | |
| 68 | // CHECK-NEXT: 216000: 21 84 40 bc ldr s1, [x1], #8 | |
| 69 | // CHECK-FIX: 216004: 06 b8 00 14 b #188440 | |
| 70 | // CHECK-NOFIX: 216004: 03 08 40 f9 ldr x3, [x0, #16] | |
| 71 | // CHECK-NEXT: 216008: c0 03 5f d6 ret | |
| 72 | 72 | .section .text.03, "ax", %progbits |
| 73 | 73 | .balign 4096 |
| 74 | 74 | .globl t3_ffc_ldrpost |
| ... | ... | @@ -80,13 +80,13 @@ t3_ffc_ldrpost: |
| 80 | 80 | ldr x3, [x0, :got_lo12:dat3] |
| 81 | 81 | ret |
| 82 | 82 | |
| 83 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 27FF8 in unpatched output. | |
| 83 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 217FF8 in unpatched output. | |
| 84 | 84 | // CHECK: t3_ff8_strpre: |
| 85 | // CHECK-NEXT: 27ff8: c0 01 00 b0 adrp x0, #233472 | |
| 86 | // CHECK-NEXT: 27ffc: 21 8c 00 bc str s1, [x1, #8]! | |
| 87 | // CHECK-FIX: 28000: 09 b0 00 14 b #180260 | |
| 88 | // CHECK-NOFIX: 28000: 02 00 40 f9 ldr x2, [x0] | |
| 89 | // CHECK-NEXT: 28004: c0 03 5f d6 ret | |
| 85 | // CHECK-NEXT: 217ff8: c0 01 00 b0 adrp x0, #233472 | |
| 86 | // CHECK-NEXT: 217ffc: 21 8c 00 bc str s1, [x1, #8]! | |
| 87 | // CHECK-FIX: 218000: 09 b0 00 14 b #180260 | |
| 88 | // CHECK-NOFIX: 218000: 02 00 40 f9 ldr x2, [x0] | |
| 89 | // CHECK-NEXT: 218004: c0 03 5f d6 ret | |
| 90 | 90 | .section .text.04, "ax", %progbits |
| 91 | 91 | .balign 4096 |
| 92 | 92 | .globl t3_ff8_strpre |
| ... | ... | @@ -98,13 +98,13 @@ t3_ff8_strpre: |
| 98 | 98 | ldr x2, [x0, :lo12:dat1] |
| 99 | 99 | ret |
| 100 | 100 | |
| 101 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 29FFC in unpatched output. | |
| 101 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 219FFC in unpatched output. | |
| 102 | 102 | // CHECK: t3_ffc_str: |
| 103 | // CHECK-NEXT: 29ffc: bc 01 00 f0 adrp x28, #225280 | |
| 104 | // CHECK-NEXT: 2a000: 42 00 00 f9 str x2, [x2] | |
| 105 | // CHECK-FIX: 2a004: 0a a8 00 14 b #172072 | |
| 106 | // CHECK-NOFIX: 2a004: 9c 07 00 f9 str x28, [x28, #8] | |
| 107 | // CHECK-NEXT: 2a008: c0 03 5f d6 ret | |
| 103 | // CHECK-NEXT: 219ffc: bc 01 00 f0 adrp x28, #225280 | |
| 104 | // CHECK-NEXT: 21a000: 42 00 00 f9 str x2, [x2] | |
| 105 | // CHECK-FIX: 21a004: 0a a8 00 14 b #172072 | |
| 106 | // CHECK-NOFIX: 21a004: 9c 07 00 f9 str x28, [x28, #8] | |
| 107 | // CHECK-NEXT: 21a008: c0 03 5f d6 ret | |
| 108 | 108 | .section .text.05, "ax", %progbits |
| 109 | 109 | .balign 4096 |
| 110 | 110 | .globl t3_ffc_str |
| ... | ... | @@ -116,13 +116,13 @@ t3_ffc_str: |
| 116 | 116 | str x28, [x28, :lo12:dat2] |
| 117 | 117 | ret |
| 118 | 118 | |
| 119 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 2BFFC in unpatched output. | |
| 119 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21BFFC in unpatched output. | |
| 120 | 120 | // CHECK: t3_ffc_strsimd: |
| 121 | // CHECK-NEXT: 2bffc: bc 01 00 b0 adrp x28, #217088 | |
| 122 | // CHECK-NEXT: 2c000: 44 00 00 b9 str w4, [x2] | |
| 123 | // CHECK-FIX: 2c004: 0c a0 00 14 b #163888 | |
| 124 | // CHECK-NOFIX: 2c004: 84 0b 00 f9 str x4, [x28, #16] | |
| 125 | // CHECK-NEXT: 2c008: c0 03 5f d6 ret | |
| 121 | // CHECK-NEXT: 21bffc: bc 01 00 b0 adrp x28, #217088 | |
| 122 | // CHECK-NEXT: 21c000: 44 00 00 b9 str w4, [x2] | |
| 123 | // CHECK-FIX: 21c004: 0c a0 00 14 b #163888 | |
| 124 | // CHECK-NOFIX: 21c004: 84 0b 00 f9 str x4, [x28, #16] | |
| 125 | // CHECK-NEXT: 21c008: c0 03 5f d6 ret | |
| 126 | 126 | .section .text.06, "ax", %progbits |
| 127 | 127 | .balign 4096 |
| 128 | 128 | .globl t3_ffc_strsimd |
| ... | ... | @@ -134,13 +134,13 @@ t3_ffc_strsimd: |
| 134 | 134 | str x4, [x28, :lo12:dat3] |
| 135 | 135 | ret |
| 136 | 136 | |
| 137 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 2DFF8 in unpatched output. | |
| 137 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21DFF8 in unpatched output. | |
| 138 | 138 | // CHECK: t3_ff8_ldrunpriv: |
| 139 | // CHECK-NEXT: 2dff8: 9d 01 00 f0 adrp x29, #208896 | |
| 140 | // CHECK-NEXT: 2dffc: 41 08 40 38 ldtrb w1, [x2] | |
| 141 | // CHECK-FIX: 2e000: 0f 98 00 14 b #155708 | |
| 142 | // CHECK-NOFIX: 2e000: bd 03 40 f9 ldr x29, [x29] | |
| 143 | // CHECK-NEXT: 2e004: c0 03 5f d6 ret | |
| 139 | // CHECK-NEXT: 21dff8: 9d 01 00 f0 adrp x29, #208896 | |
| 140 | // CHECK-NEXT: 21dffc: 41 08 40 38 ldtrb w1, [x2] | |
| 141 | // CHECK-FIX: 21e000: 0f 98 00 14 b #155708 | |
| 142 | // CHECK-NOFIX: 21e000: bd 03 40 f9 ldr x29, [x29] | |
| 143 | // CHECK-NEXT: 21e004: c0 03 5f d6 ret | |
| 144 | 144 | .section .text.07, "ax", %progbits |
| 145 | 145 | .balign 4096 |
| 146 | 146 | .globl t3_ff8_ldrunpriv |
| ... | ... | @@ -152,13 +152,13 @@ t3_ff8_ldrunpriv: |
| 152 | 152 | ldr x29, [x29, :got_lo12:dat1] |
| 153 | 153 | ret |
| 154 | 154 | |
| 155 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 2FFFC in unpatched output. | |
| 155 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21FFFC in unpatched output. | |
| 156 | 156 | // CHECK: t3_ffc_ldur: |
| 157 | // CHECK-NEXT: 2fffc: 9d 01 00 b0 adrp x29, #200704 | |
| 158 | // CHECK-NEXT: 30000: 42 40 40 b8 ldur w2, [x2, #4] | |
| 159 | // CHECK-FIX: 30004: 10 90 00 14 b #147520 | |
| 160 | // CHECK-NOFIX: 30004: bd 07 40 f9 ldr x29, [x29, #8] | |
| 161 | // CHECK-NEXT: 30008: c0 03 5f d6 ret | |
| 157 | // CHECK-NEXT: 21fffc: 9d 01 00 b0 adrp x29, #200704 | |
| 158 | // CHECK-NEXT: 220000: 42 40 40 b8 ldur w2, [x2, #4] | |
| 159 | // CHECK-FIX: 220004: 10 90 00 14 b #147520 | |
| 160 | // CHECK-NOFIX: 220004: bd 07 40 f9 ldr x29, [x29, #8] | |
| 161 | // CHECK-NEXT: 220008: c0 03 5f d6 ret | |
| 162 | 162 | .balign 4096 |
| 163 | 163 | .globl t3_ffc_ldur |
| 164 | 164 | .type t3_ffc_ldur, %function |
| ... | ... | @@ -169,13 +169,13 @@ t3_ffc_ldur: |
| 169 | 169 | ldr x29, [x29, :got_lo12:dat2] |
| 170 | 170 | ret |
| 171 | 171 | |
| 172 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 31FFC in unpatched output. | |
| 172 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 221FFC in unpatched output. | |
| 173 | 173 | // CHECK: t3_ffc_sturh: |
| 174 | // CHECK-NEXT: 31ffc: 72 01 00 f0 adrp x18, #192512 | |
| 175 | // CHECK-NEXT: 32000: 43 40 00 78 sturh w3, [x2, #4] | |
| 176 | // CHECK-FIX: 32004: 12 88 00 14 b #139336 | |
| 177 | // CHECK-NOFIX: 32004: 41 0a 40 f9 ldr x1, [x18, #16] | |
| 178 | // CHECK-NEXT: 32008: c0 03 5f d6 ret | |
| 174 | // CHECK-NEXT: 221ffc: 72 01 00 f0 adrp x18, #192512 | |
| 175 | // CHECK-NEXT: 222000: 43 40 00 78 sturh w3, [x2, #4] | |
| 176 | // CHECK-FIX: 222004: 12 88 00 14 b #139336 | |
| 177 | // CHECK-NOFIX: 222004: 41 0a 40 f9 ldr x1, [x18, #16] | |
| 178 | // CHECK-NEXT: 222008: c0 03 5f d6 ret | |
| 179 | 179 | .section .text.09, "ax", %progbits |
| 180 | 180 | .balign 4096 |
| 181 | 181 | .globl t3_ffc_sturh |
| ... | ... | @@ -187,13 +187,13 @@ t3_ffc_sturh: |
| 187 | 187 | ldr x1, [x18, :got_lo12:dat3] |
| 188 | 188 | ret |
| 189 | 189 | |
| 190 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 33FF8 in unpatched output. | |
| 190 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 223FF8 in unpatched output. | |
| 191 | 191 | // CHECK: t3_ff8_literal: |
| 192 | // CHECK-NEXT: 33ff8: 72 01 00 b0 adrp x18, #184320 | |
| 193 | // CHECK-NEXT: 33ffc: e3 ff ff 58 ldr x3, #-4 | |
| 194 | // CHECK-FIX: 34000: 15 80 00 14 b #131156 | |
| 195 | // CHECK-NOFIX: 34000: 52 02 40 f9 ldr x18, [x18] | |
| 196 | // CHECK-NEXT: 34004: c0 03 5f d6 ret | |
| 192 | // CHECK-NEXT: 223ff8: 72 01 00 b0 adrp x18, #184320 | |
| 193 | // CHECK-NEXT: 223ffc: e3 ff ff 58 ldr x3, #-4 | |
| 194 | // CHECK-FIX: 224000: 15 80 00 14 b #131156 | |
| 195 | // CHECK-NOFIX: 224000: 52 02 40 f9 ldr x18, [x18] | |
| 196 | // CHECK-NEXT: 224004: c0 03 5f d6 ret | |
| 197 | 197 | .section .text.10, "ax", %progbits |
| 198 | 198 | .balign 4096 |
| 199 | 199 | .globl t3_ff8_literal |
| ... | ... | @@ -205,13 +205,13 @@ t3_ff8_literal: |
| 205 | 205 | ldr x18, [x18, :lo12:dat1] |
| 206 | 206 | ret |
| 207 | 207 | |
| 208 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 35FFC in unpatched output. | |
| 208 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 225FFC in unpatched output. | |
| 209 | 209 | // CHECK: t3_ffc_register: |
| 210 | // CHECK-NEXT: 35ffc: 4f 01 00 f0 adrp x15, #176128 | |
| 211 | // CHECK-NEXT: 36000: 43 68 61 f8 ldr x3, [x2, x1] | |
| 212 | // CHECK-FIX: 36004: 16 78 00 14 b #122968 | |
| 213 | // CHECK-NOFIX: 36004: ea 05 40 f9 ldr x10, [x15, #8] | |
| 214 | // CHECK-NEXT: 36008: c0 03 5f d6 ret | |
| 210 | // CHECK-NEXT: 225ffc: 4f 01 00 f0 adrp x15, #176128 | |
| 211 | // CHECK-NEXT: 226000: 43 68 61 f8 ldr x3, [x2, x1] | |
| 212 | // CHECK-FIX: 226004: 16 78 00 14 b #122968 | |
| 213 | // CHECK-NOFIX: 226004: ea 05 40 f9 ldr x10, [x15, #8] | |
| 214 | // CHECK-NEXT: 226008: c0 03 5f d6 ret | |
| 215 | 215 | .section .text.11, "ax", %progbits |
| 216 | 216 | .balign 4096 |
| 217 | 217 | .globl t3_ffc_register |
| ... | ... | @@ -223,13 +223,13 @@ t3_ffc_register: |
| 223 | 223 | ldr x10, [x15, :lo12:dat2] |
| 224 | 224 | ret |
| 225 | 225 | |
| 226 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 37FF8 in unpatched output. | |
| 226 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 227FF8 in unpatched output. | |
| 227 | 227 | // CHECK: t3_ff8_stp: |
| 228 | // CHECK-NEXT: 37ff8: 50 01 00 b0 adrp x16, #167936 | |
| 229 | // CHECK-NEXT: 37ffc: 61 08 00 a9 stp x1, x2, [x3] | |
| 230 | // CHECK-FIX: 38000: 19 70 00 14 b #114788 | |
| 231 | // CHECK-NOFIX: 38000: 0d 0a 40 f9 ldr x13, [x16, #16] | |
| 232 | // CHECK-NEXT: 38004: c0 03 5f d6 ret | |
| 228 | // CHECK-NEXT: 227ff8: 50 01 00 b0 adrp x16, #167936 | |
| 229 | // CHECK-NEXT: 227ffc: 61 08 00 a9 stp x1, x2, [x3] | |
| 230 | // CHECK-FIX: 228000: 19 70 00 14 b #114788 | |
| 231 | // CHECK-NOFIX: 228000: 0d 0a 40 f9 ldr x13, [x16, #16] | |
| 232 | // CHECK-NEXT: 228004: c0 03 5f d6 ret | |
| 233 | 233 | .section .text.12, "ax", %progbits |
| 234 | 234 | .balign 4096 |
| 235 | 235 | .globl t3_ff8_stp |
| ... | ... | @@ -241,13 +241,13 @@ t3_ff8_stp: |
| 241 | 241 | ldr x13, [x16, :lo12:dat3] |
| 242 | 242 | ret |
| 243 | 243 | |
| 244 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 39FFC in unpatched output. | |
| 244 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 229FFC in unpatched output. | |
| 245 | 245 | // CHECK: t3_ffc_stnp: |
| 246 | // CHECK-NEXT: 39ffc: 27 01 00 f0 adrp x7, #159744 | |
| 247 | // CHECK-NEXT: 3a000: 61 08 00 a8 stnp x1, x2, [x3] | |
| 248 | // CHECK-FIX: 3a004: 1a 68 00 14 b #106600 | |
| 249 | // CHECK-NOFIX: 3a004: e9 00 40 f9 ldr x9, [x7] | |
| 250 | // CHECK-NEXT: 3a008: c0 03 5f d6 ret | |
| 246 | // CHECK-NEXT: 229ffc: 27 01 00 f0 adrp x7, #159744 | |
| 247 | // CHECK-NEXT: 22a000: 61 08 00 a8 stnp x1, x2, [x3] | |
| 248 | // CHECK-FIX: 22a004: 1a 68 00 14 b #106600 | |
| 249 | // CHECK-NOFIX: 22a004: e9 00 40 f9 ldr x9, [x7] | |
| 250 | // CHECK-NEXT: 22a008: c0 03 5f d6 ret | |
| 251 | 251 | .section .text.13, "ax", %progbits |
| 252 | 252 | .balign 4096 |
| 253 | 253 | .globl t3_ffc_stnp |
| ... | ... | @@ -259,13 +259,13 @@ t3_ffc_stnp: |
| 259 | 259 | ldr x9, [x7, :lo12:dat1] |
| 260 | 260 | ret |
| 261 | 261 | |
| 262 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 3BFFC in unpatched output. | |
| 262 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 22BFFC in unpatched output. | |
| 263 | 263 | // CHECK: t3_ffc_st1singlepost: |
| 264 | // CHECK-NEXT: 3bffc: 37 01 00 b0 adrp x23, #151552 | |
| 265 | // CHECK-NEXT: 3c000: 20 04 82 0d st1 { v0.b }[1], [x1], x2 | |
| 266 | // CHECK-FIX: 3c004: 1c 60 00 14 b #98416 | |
| 267 | // CHECK-NOFIX: 3c004: f6 06 40 f9 ldr x22, [x23, #8] | |
| 268 | // CHECK-NEXT: 3c008: c0 03 5f d6 ret | |
| 264 | // CHECK-NEXT: 22bffc: 37 01 00 b0 adrp x23, #151552 | |
| 265 | // CHECK-NEXT: 22c000: 20 04 82 0d st1 { v0.b }[1], [x1], x2 | |
| 266 | // CHECK-FIX: 22c004: 1c 60 00 14 b #98416 | |
| 267 | // CHECK-NOFIX: 22c004: f6 06 40 f9 ldr x22, [x23, #8] | |
| 268 | // CHECK-NEXT: 22c008: c0 03 5f d6 ret | |
| 269 | 269 | .section .text.14, "ax", %progbits |
| 270 | 270 | .balign 4096 |
| 271 | 271 | .globl t3_ffc_st1singlepost |
| ... | ... | @@ -277,13 +277,13 @@ t3_ffc_st1singlepost: |
| 277 | 277 | ldr x22, [x23, :lo12:dat2] |
| 278 | 278 | ret |
| 279 | 279 | |
| 280 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 3DFF8 in unpatched output. | |
| 280 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 22DFF8 in unpatched output. | |
| 281 | 281 | // CHECK: t3_ff8_st1multiple: |
| 282 | // CHECK-NEXT: 3dff8: 17 01 00 f0 adrp x23, #143360 | |
| 283 | // CHECK-NEXT: 3dffc: 20 a0 00 4c st1 { v0.16b, v1.16b }, [x1] | |
| 284 | // CHECK-FIX: 3e000: 1f 58 00 14 b #90236 | |
| 285 | // CHECK-NOFIX: 3e000: f8 0a 40 f9 ldr x24, [x23, #16] | |
| 286 | // CHECK-NEXT: 3e004: c0 03 5f d6 ret | |
| 282 | // CHECK-NEXT: 22dff8: 17 01 00 f0 adrp x23, #143360 | |
| 283 | // CHECK-NEXT: 22dffc: 20 a0 00 4c st1 { v0.16b, v1.16b }, [x1] | |
| 284 | // CHECK-FIX: 22e000: 1f 58 00 14 b #90236 | |
| 285 | // CHECK-NOFIX: 22e000: f8 0a 40 f9 ldr x24, [x23, #16] | |
| 286 | // CHECK-NEXT: 22e004: c0 03 5f d6 ret | |
| 287 | 287 | .section .text.15, "ax", %progbits |
| 288 | 288 | .balign 4096 |
| 289 | 289 | .globl t3_ff8_st1multiple |
| ... | ... | @@ -295,14 +295,14 @@ t3_ff8_st1multiple: |
| 295 | 295 | ldr x24, [x23, :lo12:dat3] |
| 296 | 296 | ret |
| 297 | 297 | |
| 298 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 3FFF8 in unpatched output. | |
| 298 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 22FFF8 in unpatched output. | |
| 299 | 299 | // CHECK: t4_ff8_ldr: |
| 300 | // CHECK-NEXT: 3fff8: 00 01 00 b0 adrp x0, #135168 | |
| 301 | // CHECK-NEXT: 3fffc: 21 00 40 f9 ldr x1, [x1] | |
| 302 | // CHECK-NEXT: 40000: 42 00 00 8b add x2, x2, x0 | |
| 303 | // CHECK-FIX: 40004: 20 50 00 14 b #82048 | |
| 304 | // CHECK-NOFIX: 40004: 02 00 40 f9 ldr x2, [x0] | |
| 305 | // CHECK-NEXT: 40008: c0 03 5f d6 ret | |
| 300 | // CHECK-NEXT: 22fff8: 00 01 00 b0 adrp x0, #135168 | |
| 301 | // CHECK-NEXT: 22fffc: 21 00 40 f9 ldr x1, [x1] | |
| 302 | // CHECK-NEXT: 230000: 42 00 00 8b add x2, x2, x0 | |
| 303 | // CHECK-FIX: 230004: 20 50 00 14 b #82048 | |
| 304 | // CHECK-NOFIX: 230004: 02 00 40 f9 ldr x2, [x0] | |
| 305 | // CHECK-NEXT: 230008: c0 03 5f d6 ret | |
| 306 | 306 | .section .text.16, "ax", %progbits |
| 307 | 307 | .balign 4096 |
| 308 | 308 | .globl t4_ff8_ldr |
| ... | ... | @@ -315,14 +315,14 @@ t4_ff8_ldr: |
| 315 | 315 | ldr x2, [x0, :got_lo12:dat1] |
| 316 | 316 | ret |
| 317 | 317 | |
| 318 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 41FFC in unpatched output. | |
| 318 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 231FFC in unpatched output. | |
| 319 | 319 | // CHECK: t4_ffc_str: |
| 320 | // CHECK-NEXT: 41ffc: fc 00 00 f0 adrp x28, #126976 | |
| 321 | // CHECK-NEXT: 42000: 42 00 00 f9 str x2, [x2] | |
| 322 | // CHECK-NEXT: 42004: 20 00 02 cb sub x0, x1, x2 | |
| 323 | // CHECK-FIX: 42008: 21 48 00 14 b #73860 | |
| 324 | // CHECK-NOFIX: 42008: 9b 07 00 f9 str x27, [x28, #8] | |
| 325 | // CHECK-NEXT: 4200c: c0 03 5f d6 ret | |
| 320 | // CHECK-NEXT: 231ffc: fc 00 00 f0 adrp x28, #126976 | |
| 321 | // CHECK-NEXT: 232000: 42 00 00 f9 str x2, [x2] | |
| 322 | // CHECK-NEXT: 232004: 20 00 02 cb sub x0, x1, x2 | |
| 323 | // CHECK-FIX: 232008: 21 48 00 14 b #73860 | |
| 324 | // CHECK-NOFIX: 232008: 9b 07 00 f9 str x27, [x28, #8] | |
| 325 | // CHECK-NEXT: 23200c: c0 03 5f d6 ret | |
| 326 | 326 | .section .text.17, "ax", %progbits |
| 327 | 327 | .balign 4096 |
| 328 | 328 | .globl t4_ffc_str |
| ... | ... | @@ -335,14 +335,14 @@ t4_ffc_str: |
| 335 | 335 | str x27, [x28, :got_lo12:dat2] |
| 336 | 336 | ret |
| 337 | 337 | |
| 338 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 43FF8 in unpatched output. | |
| 338 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 233FF8 in unpatched output. | |
| 339 | 339 | // CHECK: t4_ff8_stp: |
| 340 | // CHECK-NEXT: 43ff8: f0 00 00 b0 adrp x16, #118784 | |
| 341 | // CHECK-NEXT: 43ffc: 61 08 00 a9 stp x1, x2, [x3] | |
| 342 | // CHECK-NEXT: 44000: 03 7e 10 9b mul x3, x16, x16 | |
| 343 | // CHECK-FIX: 44004: 24 40 00 14 b #65680 | |
| 344 | // CHECK-NOFIX: 44004: 0e 0a 40 f9 ldr x14, [x16, #16] | |
| 345 | // CHECK-NEXT: 44008: c0 03 5f d6 ret | |
| 340 | // CHECK-NEXT: 233ff8: f0 00 00 b0 adrp x16, #118784 | |
| 341 | // CHECK-NEXT: 233ffc: 61 08 00 a9 stp x1, x2, [x3] | |
| 342 | // CHECK-NEXT: 234000: 03 7e 10 9b mul x3, x16, x16 | |
| 343 | // CHECK-FIX: 234004: 24 40 00 14 b #65680 | |
| 344 | // CHECK-NOFIX: 234004: 0e 0a 40 f9 ldr x14, [x16, #16] | |
| 345 | // CHECK-NEXT: 234008: c0 03 5f d6 ret | |
| 346 | 346 | .section .text.18, "ax", %progbits |
| 347 | 347 | .balign 4096 |
| 348 | 348 | .globl t4_ff8_stp |
| ... | ... | @@ -355,14 +355,14 @@ t4_ff8_stp: |
| 355 | 355 | ldr x14, [x16, :got_lo12:dat3] |
| 356 | 356 | ret |
| 357 | 357 | |
| 358 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 45FF8 in unpatched output. | |
| 358 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 235FF8 in unpatched output. | |
| 359 | 359 | // CHECK: t4_ff8_stppre: |
| 360 | // CHECK-NEXT: 45ff8: d0 00 00 f0 adrp x16, #110592 | |
| 361 | // CHECK-NEXT: 45ffc: 61 08 81 a9 stp x1, x2, [x3, #16]! | |
| 362 | // CHECK-NEXT: 46000: 03 7e 10 9b mul x3, x16, x16 | |
| 363 | // CHECK-FIX: 46004: 26 38 00 14 b #57496 | |
| 364 | // CHECK-NOFIX: 46004: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 365 | // CHECK-NEXT: 46008: c0 03 5f d6 ret | |
| 360 | // CHECK-NEXT: 235ff8: d0 00 00 f0 adrp x16, #110592 | |
| 361 | // CHECK-NEXT: 235ffc: 61 08 81 a9 stp x1, x2, [x3, #16]! | |
| 362 | // CHECK-NEXT: 236000: 03 7e 10 9b mul x3, x16, x16 | |
| 363 | // CHECK-FIX: 236004: 26 38 00 14 b #57496 | |
| 364 | // CHECK-NOFIX: 236004: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 365 | // CHECK-NEXT: 236008: c0 03 5f d6 ret | |
| 366 | 366 | .section .text.19, "ax", %progbits |
| 367 | 367 | .balign 4096 |
| 368 | 368 | .globl t4_ff8_stppre |
| ... | ... | @@ -375,14 +375,14 @@ t4_ff8_stppre: |
| 375 | 375 | ldr x14, [x16, #8] |
| 376 | 376 | ret |
| 377 | 377 | |
| 378 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 47FF8 in unpatched output. | |
| 378 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 237FF8 in unpatched output. | |
| 379 | 379 | // CHECK: t4_ff8_stppost: |
| 380 | // CHECK-NEXT: 47ff8: d0 00 00 b0 adrp x16, #102400 | |
| 381 | // CHECK-NEXT: 47ffc: 61 08 81 a8 stp x1, x2, [x3], #16 | |
| 382 | // CHECK-NEXT: 48000: 03 7e 10 9b mul x3, x16, x16 | |
| 383 | // CHECK-FIX: 48004: 28 30 00 14 b #49312 | |
| 384 | // CHECK-NOFIX: 48004: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 385 | // CHECK-NEXT: 48008: c0 03 5f d6 ret | |
| 380 | // CHECK-NEXT: 237ff8: d0 00 00 b0 adrp x16, #102400 | |
| 381 | // CHECK-NEXT: 237ffc: 61 08 81 a8 stp x1, x2, [x3], #16 | |
| 382 | // CHECK-NEXT: 238000: 03 7e 10 9b mul x3, x16, x16 | |
| 383 | // CHECK-FIX: 238004: 28 30 00 14 b #49312 | |
| 384 | // CHECK-NOFIX: 238004: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 385 | // CHECK-NEXT: 238008: c0 03 5f d6 ret | |
| 386 | 386 | .section .text.20, "ax", %progbits |
| 387 | 387 | .balign 4096 |
| 388 | 388 | .globl t4_ff8_stppost |
| ... | ... | @@ -395,14 +395,14 @@ t4_ff8_stppost: |
| 395 | 395 | ldr x14, [x16, #8] |
| 396 | 396 | ret |
| 397 | 397 | |
| 398 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 49FFC in unpatched output. | |
| 398 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 239FFC in unpatched output. | |
| 399 | 399 | // CHECK: t4_ffc_stpsimd: |
| 400 | // CHECK-NEXT: 49ffc: b0 00 00 f0 adrp x16, #94208 | |
| 401 | // CHECK-NEXT: 4a000: 61 08 00 ad stp q1, q2, [x3] | |
| 402 | // CHECK-NEXT: 4a004: 03 7e 10 9b mul x3, x16, x16 | |
| 403 | // CHECK-FIX: 4a008: 29 28 00 14 b #41124 | |
| 404 | // CHECK-NOFIX: 4a008: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 405 | // CHECK-NEXT: 4a00c: c0 03 5f d6 ret | |
| 400 | // CHECK-NEXT: 239ffc: b0 00 00 f0 adrp x16, #94208 | |
| 401 | // CHECK-NEXT: 23a000: 61 08 00 ad stp q1, q2, [x3] | |
| 402 | // CHECK-NEXT: 23a004: 03 7e 10 9b mul x3, x16, x16 | |
| 403 | // CHECK-FIX: 23a008: 29 28 00 14 b #41124 | |
| 404 | // CHECK-NOFIX: 23a008: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 405 | // CHECK-NEXT: 23a00c: c0 03 5f d6 ret | |
| 406 | 406 | .section .text.21, "ax", %progbits |
| 407 | 407 | .balign 4096 |
| 408 | 408 | .globl t4_ffc_stpsimd |
| ... | ... | @@ -415,14 +415,14 @@ t4_ffc_stpsimd: |
| 415 | 415 | ldr x14, [x16, #8] |
| 416 | 416 | ret |
| 417 | 417 | |
| 418 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 4BFFC in unpatched output. | |
| 418 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23BFFC in unpatched output. | |
| 419 | 419 | // CHECK: t4_ffc_stnp: |
| 420 | // CHECK-NEXT: 4bffc: a7 00 00 b0 adrp x7, #86016 | |
| 421 | // CHECK-NEXT: 4c000: 61 08 00 a8 stnp x1, x2, [x3] | |
| 422 | // CHECK-NEXT: 4c004: 1f 20 03 d5 nop | |
| 423 | // CHECK-FIX: 4c008: 2b 20 00 14 b #32940 | |
| 424 | // CHECK-NOFIX: 4c008: ea 00 40 f9 ldr x10, [x7] | |
| 425 | // CHECK-NEXT: 4c00c: c0 03 5f d6 ret | |
| 420 | // CHECK-NEXT: 23bffc: a7 00 00 b0 adrp x7, #86016 | |
| 421 | // CHECK-NEXT: 23c000: 61 08 00 a8 stnp x1, x2, [x3] | |
| 422 | // CHECK-NEXT: 23c004: 1f 20 03 d5 nop | |
| 423 | // CHECK-FIX: 23c008: 2b 20 00 14 b #32940 | |
| 424 | // CHECK-NOFIX: 23c008: ea 00 40 f9 ldr x10, [x7] | |
| 425 | // CHECK-NEXT: 23c00c: c0 03 5f d6 ret | |
| 426 | 426 | .section .text.22, "ax", %progbits |
| 427 | 427 | .balign 4096 |
| 428 | 428 | .globl t4_ffc_stnp |
| ... | ... | @@ -435,14 +435,14 @@ t4_ffc_stnp: |
| 435 | 435 | ldr x10, [x7, :got_lo12:dat1] |
| 436 | 436 | ret |
| 437 | 437 | |
| 438 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 4DFFC in unpatched output. | |
| 438 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23DFFC in unpatched output. | |
| 439 | 439 | // CHECK: t4_ffc_st1: |
| 440 | // CHECK-NEXT: 4dffc: 98 00 00 f0 adrp x24, #77824 | |
| 441 | // CHECK-NEXT: 4e000: 20 80 00 4d st1 { v0.s }[2], [x1] | |
| 442 | // CHECK-NEXT: 4e004: f6 06 40 f9 ldr x22, [x23, #8] | |
| 443 | // CHECK-FIX: 4e008: 2d 18 00 14 b #24756 | |
| 444 | // CHECK-NOFIX: 4e008: 18 ff 3f f9 str x24, [x24, #32760] | |
| 445 | // CHECK-NEXT: 4e00c: c0 03 5f d6 ret | |
| 440 | // CHECK-NEXT: 23dffc: 98 00 00 f0 adrp x24, #77824 | |
| 441 | // CHECK-NEXT: 23e000: 20 80 00 4d st1 { v0.s }[2], [x1] | |
| 442 | // CHECK-NEXT: 23e004: f6 06 40 f9 ldr x22, [x23, #8] | |
| 443 | // CHECK-FIX: 23e008: 2d 18 00 14 b #24756 | |
| 444 | // CHECK-NOFIX: 23e008: 18 ff 3f f9 str x24, [x24, #32760] | |
| 445 | // CHECK-NEXT: 23e00c: c0 03 5f d6 ret | |
| 446 | 446 | .section .text.23, "ax", %progbits |
| 447 | 447 | .balign 4096 |
| 448 | 448 | .globl t4_ffc_st1 |
| ... | ... | @@ -455,14 +455,14 @@ t4_ffc_st1: |
| 455 | 455 | str x24, [x24, #32760] |
| 456 | 456 | ret |
| 457 | 457 | |
| 458 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 4FFF8 in unpatched output. | |
| 458 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23FFF8 in unpatched output. | |
| 459 | 459 | // CHECK: t3_ff8_ldr_once: |
| 460 | // CHECK-NEXT: 4fff8: 80 00 00 b0 adrp x0, #69632 | |
| 461 | // CHECK-NEXT: 4fffc: 20 70 82 4c st1 { v0.16b }, [x1], x2 | |
| 462 | // CHECK-FIX: 50000: 31 10 00 14 b #16580 | |
| 463 | // CHECK-NOFIX: 50000: 01 08 40 f9 ldr x1, [x0, #16] | |
| 464 | // CHECK-NEXT: 50004: 02 08 40 f9 ldr x2, [x0, #16] | |
| 465 | // CHECK-NEXT: 50008: c0 03 5f d6 ret | |
| 460 | // CHECK-NEXT: 23fff8: 80 00 00 b0 adrp x0, #69632 | |
| 461 | // CHECK-NEXT: 23fffc: 20 70 82 4c st1 { v0.16b }, [x1], x2 | |
| 462 | // CHECK-FIX: 240000: 31 10 00 14 b #16580 | |
| 463 | // CHECK-NOFIX: 240000: 01 08 40 f9 ldr x1, [x0, #16] | |
| 464 | // CHECK-NEXT: 240004: 02 08 40 f9 ldr x2, [x0, #16] | |
| 465 | // CHECK-NEXT: 240008: c0 03 5f d6 ret | |
| 466 | 466 | .section .text.24, "ax", %progbits |
| 467 | 467 | .balign 4096 |
| 468 | 468 | .globl t3_ff8_ldr_once |
| ... | ... | @@ -475,14 +475,14 @@ t3_ff8_ldr_once: |
| 475 | 475 | ldr x2, [x0, #16] |
| 476 | 476 | ret |
| 477 | 477 | |
| 478 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 51FF8 in unpatched output. | |
| 478 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 241FF8 in unpatched output. | |
| 479 | 479 | // CHECK: t3_ff8_ldxr: |
| 480 | // CHECK-NEXT: 51ff8: 60 00 00 f0 adrp x0, #61440 | |
| 481 | // CHECK-NEXT: 51ffc: 03 7c 5f c8 ldxr x3, [x0] | |
| 482 | // CHECK-FIX: 52000: 33 08 00 14 b #8396 | |
| 483 | // CHECK-NOFIX: 52000: 01 08 40 f9 ldr x1, [x0, #16] | |
| 484 | // CHECK: 52004: 02 08 40 f9 ldr x2, [x0, #16] | |
| 485 | // CHECK-NEXT: 52008: c0 03 5f d6 ret | |
| 480 | // CHECK-NEXT: 241ff8: 60 00 00 f0 adrp x0, #61440 | |
| 481 | // CHECK-NEXT: 241ffc: 03 7c 5f c8 ldxr x3, [x0] | |
| 482 | // CHECK-FIX: 242000: 33 08 00 14 b #8396 | |
| 483 | // CHECK-NOFIX: 242000: 01 08 40 f9 ldr x1, [x0, #16] | |
| 484 | // CHECK: 242004: 02 08 40 f9 ldr x2, [x0, #16] | |
| 485 | // CHECK-NEXT: 242008: c0 03 5f d6 ret | |
| 486 | 486 | .section .text.25, "ax", %progbits |
| 487 | 487 | .balign 4096 |
| 488 | 488 | .globl t3_ff8_ldxr |
| ... | ... | @@ -495,14 +495,14 @@ t3_ff8_ldxr: |
| 495 | 495 | ldr x2, [x0, #16] |
| 496 | 496 | ret |
| 497 | 497 | |
| 498 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 53FF8 in unpatched output. | |
| 498 | // CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 243FF8 in unpatched output. | |
| 499 | 499 | // CHECK: t3_ff8_stxr: |
| 500 | // CHECK-NEXT: 53ff8: 60 00 00 b0 adrp x0, #53248 | |
| 501 | // CHECK-NEXT: 53ffc: 03 7c 04 c8 stxr w4, x3, [x0] | |
| 502 | // CHECK-FIX: 54000: 35 00 00 14 b #212 | |
| 503 | // CHECK-NOFIX: 54000: 01 08 40 f9 ldr x1, [x0, #16] | |
| 504 | // CHECK: 54004: 02 08 40 f9 ldr x2, [x0, #16] | |
| 505 | // CHECK-NEXT: 54008: c0 03 5f d6 ret | |
| 500 | // CHECK-NEXT: 243ff8: 60 00 00 b0 adrp x0, #53248 | |
| 501 | // CHECK-NEXT: 243ffc: 03 7c 04 c8 stxr w4, x3, [x0] | |
| 502 | // CHECK-FIX: 244000: 35 00 00 14 b #212 | |
| 503 | // CHECK-NOFIX: 244000: 01 08 40 f9 ldr x1, [x0, #16] | |
| 504 | // CHECK: 244004: 02 08 40 f9 ldr x2, [x0, #16] | |
| 505 | // CHECK-NEXT: 244008: c0 03 5f d6 ret | |
| 506 | 506 | .section .text.26, "ax", %progbits |
| 507 | 507 | .balign 4096 |
| 508 | 508 | .globl t3_ff8_stxr |
| ... | ... | @@ -521,84 +521,84 @@ t3_ff8_stxr: |
| 521 | 521 | _start: |
| 522 | 522 | ret |
| 523 | 523 | |
| 524 | // CHECK-FIX: __CortexA53843419_22000: | |
| 525 | // CHECK-FIX-NEXT: 5400c: 00 00 40 f9 ldr x0, [x0] | |
| 526 | // CHECK-FIX-NEXT: 54010: fd 37 ff 17 b #-204812 | |
| 527 | // CHECK-FIX: __CortexA53843419_24000: | |
| 528 | // CHECK-FIX-NEXT: 54014: 02 04 40 f9 ldr x2, [x0, #8] | |
| 529 | // CHECK-FIX-NEXT: 54018: fb 3f ff 17 b #-196628 | |
| 530 | // CHECK-FIX: __CortexA53843419_26004: | |
| 531 | // CHECK-FIX-NEXT: 5401c: 03 08 40 f9 ldr x3, [x0, #16] | |
| 532 | // CHECK-FIX-NEXT: 54020: fa 47 ff 17 b #-188440 | |
| 533 | // CHECK-FIX: __CortexA53843419_28000: | |
| 534 | // CHECK-FIX-NEXT: 54024: 02 00 40 f9 ldr x2, [x0] | |
| 535 | // CHECK-FIX-NEXT: 54028: f7 4f ff 17 b #-180260 | |
| 536 | // CHECK-FIX: __CortexA53843419_2A004: | |
| 537 | // CHECK-FIX-NEXT: 5402c: 9c 07 00 f9 str x28, [x28, #8] | |
| 538 | // CHECK-FIX-NEXT: 54030: f6 57 ff 17 b #-172072 | |
| 539 | // CHECK-FIX: __CortexA53843419_2C004: | |
| 540 | // CHECK-FIX-NEXT: 54034: 84 0b 00 f9 str x4, [x28, #16] | |
| 541 | // CHECK-FIX-NEXT: 54038: f4 5f ff 17 b #-163888 | |
| 542 | // CHECK-FIX: __CortexA53843419_2E000: | |
| 543 | // CHECK-FIX-NEXT: 5403c: bd 03 40 f9 ldr x29, [x29] | |
| 544 | // CHECK-FIX-NEXT: 54040: f1 67 ff 17 b #-155708 | |
| 545 | // CHECK-FIX: __CortexA53843419_30004: | |
| 546 | // CHECK-FIX-NEXT: 54044: bd 07 40 f9 ldr x29, [x29, #8] | |
| 547 | // CHECK-FIX-NEXT: 54048: f0 6f ff 17 b #-147520 | |
| 548 | // CHECK-FIX: __CortexA53843419_32004: | |
| 549 | // CHECK-FIX-NEXT: 5404c: 41 0a 40 f9 ldr x1, [x18, #16] | |
| 550 | // CHECK-FIX-NEXT: 54050: ee 77 ff 17 b #-139336 | |
| 551 | // CHECK-FIX: __CortexA53843419_34000: | |
| 552 | // CHECK-FIX-NEXT: 54054: 52 02 40 f9 ldr x18, [x18] | |
| 553 | // CHECK-FIX-NEXT: 54058: eb 7f ff 17 b #-131156 | |
| 554 | // CHECK-FIX: __CortexA53843419_36004: | |
| 555 | // CHECK-FIX-NEXT: 5405c: ea 05 40 f9 ldr x10, [x15, #8] | |
| 556 | // CHECK-FIX-NEXT: 54060: ea 87 ff 17 b #-122968 | |
| 557 | // CHECK-FIX: __CortexA53843419_38000: | |
| 558 | // CHECK-FIX-NEXT: 54064: 0d 0a 40 f9 ldr x13, [x16, #16] | |
| 559 | // CHECK-FIX-NEXT: 54068: e7 8f ff 17 b #-114788 | |
| 560 | // CHECK-FIX: __CortexA53843419_3A004: | |
| 561 | // CHECK-FIX-NEXT: 5406c: e9 00 40 f9 ldr x9, [x7] | |
| 562 | // CHECK-FIX-NEXT: 54070: e6 97 ff 17 b #-106600 | |
| 563 | // CHECK-FIX: __CortexA53843419_3C004: | |
| 564 | // CHECK-FIX-NEXT: 54074: f6 06 40 f9 ldr x22, [x23, #8] | |
| 565 | // CHECK-FIX-NEXT: 54078: e4 9f ff 17 b #-98416 | |
| 566 | // CHECK-FIX: __CortexA53843419_3E000: | |
| 567 | // CHECK-FIX-NEXT: 5407c: f8 0a 40 f9 ldr x24, [x23, #16] | |
| 568 | // CHECK-FIX-NEXT: 54080: e1 a7 ff 17 b #-90236 | |
| 569 | // CHECK-FIX: __CortexA53843419_40004: | |
| 570 | // CHECK-FIX-NEXT: 54084: 02 00 40 f9 ldr x2, [x0] | |
| 571 | // CHECK-FIX-NEXT: 54088: e0 af ff 17 b #-82048 | |
| 572 | // CHECK-FIX: __CortexA53843419_42008: | |
| 573 | // CHECK-FIX-NEXT: 5408c: 9b 07 00 f9 str x27, [x28, #8] | |
| 574 | // CHECK-FIX-NEXT: 54090: df b7 ff 17 b #-73860 | |
| 575 | // CHECK-FIX: __CortexA53843419_44004: | |
| 576 | // CHECK-FIX-NEXT: 54094: 0e 0a 40 f9 ldr x14, [x16, #16] | |
| 577 | // CHECK-FIX-NEXT: 54098: dc bf ff 17 b #-65680 | |
| 578 | // CHECK-FIX: __CortexA53843419_46004: | |
| 579 | // CHECK-FIX-NEXT: 5409c: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 580 | // CHECK-FIX-NEXT: 540a0: da c7 ff 17 b #-57496 | |
| 581 | // CHECK-FIX: __CortexA53843419_48004: | |
| 582 | // CHECK-FIX-NEXT: 540a4: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 583 | // CHECK-FIX-NEXT: 540a8: d8 cf ff 17 b #-49312 | |
| 584 | // CHECK-FIX: __CortexA53843419_4A008: | |
| 585 | // CHECK-FIX-NEXT: 540ac: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 586 | // CHECK-FIX-NEXT: 540b0: d7 d7 ff 17 b #-41124 | |
| 587 | // CHECK-FIX: __CortexA53843419_4C008: | |
| 588 | // CHECK-FIX-NEXT: 540b4: ea 00 40 f9 ldr x10, [x7] | |
| 589 | // CHECK-FIX-NEXT: 540b8: d5 df ff 17 b #-32940 | |
| 590 | // CHECK-FIX: __CortexA53843419_4E008: | |
| 591 | // CHECK-FIX-NEXT: 540bc: 18 ff 3f f9 str x24, [x24, #32760] | |
| 592 | // CHECK-FIX-NEXT: 540c0: d3 e7 ff 17 b #-24756 | |
| 593 | // CHECK-FIX: __CortexA53843419_50000: | |
| 594 | // CHECK-FIX-NEXT: 540c4: 01 08 40 f9 ldr x1, [x0, #16] | |
| 595 | // CHECK-FIX-NEXT: 540c8: cf ef ff 17 b #-16580 | |
| 596 | // CHECK-FIX: __CortexA53843419_52000: | |
| 597 | // CHECK-FIX-NEXT: 540cc: 01 08 40 f9 ldr x1, [x0, #16] | |
| 598 | // CHECK-FIX-NEXT: 540d0: cd f7 ff 17 b #-8396 | |
| 599 | // CHECK-FIX: __CortexA53843419_54000: | |
| 600 | // CHECK-FIX-NEXT: 540d4: 01 08 40 f9 ldr x1, [x0, #16] | |
| 601 | // CHECK-FIX-NEXT: 540d8: cb ff ff 17 b #-212 | |
| 524 | // CHECK-FIX: __CortexA53843419_212000: | |
| 525 | // CHECK-FIX-NEXT: 24400c: 00 00 40 f9 ldr x0, [x0] | |
| 526 | // CHECK-FIX-NEXT: 244010: fd 37 ff 17 b #-204812 | |
| 527 | // CHECK-FIX: __CortexA53843419_214000: | |
| 528 | // CHECK-FIX-NEXT: 244014: 02 04 40 f9 ldr x2, [x0, #8] | |
| 529 | // CHECK-FIX-NEXT: 244018: fb 3f ff 17 b #-196628 | |
| 530 | // CHECK-FIX: __CortexA53843419_216004: | |
| 531 | // CHECK-FIX-NEXT: 24401c: 03 08 40 f9 ldr x3, [x0, #16] | |
| 532 | // CHECK-FIX-NEXT: 244020: fa 47 ff 17 b #-188440 | |
| 533 | // CHECK-FIX: __CortexA53843419_218000: | |
| 534 | // CHECK-FIX-NEXT: 244024: 02 00 40 f9 ldr x2, [x0] | |
| 535 | // CHECK-FIX-NEXT: 244028: f7 4f ff 17 b #-180260 | |
| 536 | // CHECK-FIX: __CortexA53843419_21A004: | |
| 537 | // CHECK-FIX-NEXT: 24402c: 9c 07 00 f9 str x28, [x28, #8] | |
| 538 | // CHECK-FIX-NEXT: 244030: f6 57 ff 17 b #-172072 | |
| 539 | // CHECK-FIX: __CortexA53843419_21C004: | |
| 540 | // CHECK-FIX-NEXT: 244034: 84 0b 00 f9 str x4, [x28, #16] | |
| 541 | // CHECK-FIX-NEXT: 244038: f4 5f ff 17 b #-163888 | |
| 542 | // CHECK-FIX: __CortexA53843419_21E000: | |
| 543 | // CHECK-FIX-NEXT: 24403c: bd 03 40 f9 ldr x29, [x29] | |
| 544 | // CHECK-FIX-NEXT: 244040: f1 67 ff 17 b #-155708 | |
| 545 | // CHECK-FIX: __CortexA53843419_220004: | |
| 546 | // CHECK-FIX-NEXT: 244044: bd 07 40 f9 ldr x29, [x29, #8] | |
| 547 | // CHECK-FIX-NEXT: 244048: f0 6f ff 17 b #-147520 | |
| 548 | // CHECK-FIX: __CortexA53843419_222004: | |
| 549 | // CHECK-FIX-NEXT: 24404c: 41 0a 40 f9 ldr x1, [x18, #16] | |
| 550 | // CHECK-FIX-NEXT: 244050: ee 77 ff 17 b #-139336 | |
| 551 | // CHECK-FIX: __CortexA53843419_224000: | |
| 552 | // CHECK-FIX-NEXT: 244054: 52 02 40 f9 ldr x18, [x18] | |
| 553 | // CHECK-FIX-NEXT: 244058: eb 7f ff 17 b #-131156 | |
| 554 | // CHECK-FIX: __CortexA53843419_226004: | |
| 555 | // CHECK-FIX-NEXT: 24405c: ea 05 40 f9 ldr x10, [x15, #8] | |
| 556 | // CHECK-FIX-NEXT: 244060: ea 87 ff 17 b #-122968 | |
| 557 | // CHECK-FIX: __CortexA53843419_228000: | |
| 558 | // CHECK-FIX-NEXT: 244064: 0d 0a 40 f9 ldr x13, [x16, #16] | |
| 559 | // CHECK-FIX-NEXT: 244068: e7 8f ff 17 b #-114788 | |
| 560 | // CHECK-FIX: __CortexA53843419_22A004: | |
| 561 | // CHECK-FIX-NEXT: 24406c: e9 00 40 f9 ldr x9, [x7] | |
| 562 | // CHECK-FIX-NEXT: 244070: e6 97 ff 17 b #-106600 | |
| 563 | // CHECK-FIX: __CortexA53843419_22C004: | |
| 564 | // CHECK-FIX-NEXT: 244074: f6 06 40 f9 ldr x22, [x23, #8] | |
| 565 | // CHECK-FIX-NEXT: 244078: e4 9f ff 17 b #-98416 | |
| 566 | // CHECK-FIX: __CortexA53843419_22E000: | |
| 567 | // CHECK-FIX-NEXT: 24407c: f8 0a 40 f9 ldr x24, [x23, #16] | |
| 568 | // CHECK-FIX-NEXT: 244080: e1 a7 ff 17 b #-90236 | |
| 569 | // CHECK-FIX: __CortexA53843419_230004: | |
| 570 | // CHECK-FIX-NEXT: 244084: 02 00 40 f9 ldr x2, [x0] | |
| 571 | // CHECK-FIX-NEXT: 244088: e0 af ff 17 b #-82048 | |
| 572 | // CHECK-FIX: __CortexA53843419_232008: | |
| 573 | // CHECK-FIX-NEXT: 24408c: 9b 07 00 f9 str x27, [x28, #8] | |
| 574 | // CHECK-FIX-NEXT: 244090: df b7 ff 17 b #-73860 | |
| 575 | // CHECK-FIX: __CortexA53843419_234004: | |
| 576 | // CHECK-FIX-NEXT: 244094: 0e 0a 40 f9 ldr x14, [x16, #16] | |
| 577 | // CHECK-FIX-NEXT: 244098: dc bf ff 17 b #-65680 | |
| 578 | // CHECK-FIX: __CortexA53843419_236004: | |
| 579 | // CHECK-FIX-NEXT: 24409c: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 580 | // CHECK-FIX-NEXT: 2440a0: da c7 ff 17 b #-57496 | |
| 581 | // CHECK-FIX: __CortexA53843419_238004: | |
| 582 | // CHECK-FIX-NEXT: 2440a4: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 583 | // CHECK-FIX-NEXT: 2440a8: d8 cf ff 17 b #-49312 | |
| 584 | // CHECK-FIX: __CortexA53843419_23A008: | |
| 585 | // CHECK-FIX-NEXT: 2440ac: 0e 06 40 f9 ldr x14, [x16, #8] | |
| 586 | // CHECK-FIX-NEXT: 2440b0: d7 d7 ff 17 b #-41124 | |
| 587 | // CHECK-FIX: __CortexA53843419_23C008: | |
| 588 | // CHECK-FIX-NEXT: 2440b4: ea 00 40 f9 ldr x10, [x7] | |
| 589 | // CHECK-FIX-NEXT: 2440b8: d5 df ff 17 b #-32940 | |
| 590 | // CHECK-FIX: __CortexA53843419_23E008: | |
| 591 | // CHECK-FIX-NEXT: 2440bc: 18 ff 3f f9 str x24, [x24, #32760] | |
| 592 | // CHECK-FIX-NEXT: 2440c0: d3 e7 ff 17 b #-24756 | |
| 593 | // CHECK-FIX: __CortexA53843419_240000: | |
| 594 | // CHECK-FIX-NEXT: 2440c4: 01 08 40 f9 ldr x1, [x0, #16] | |
| 595 | // CHECK-FIX-NEXT: 2440c8: cf ef ff 17 b #-16580 | |
| 596 | // CHECK-FIX: __CortexA53843419_242000: | |
| 597 | // CHECK-FIX-NEXT: 2440cc: 01 08 40 f9 ldr x1, [x0, #16] | |
| 598 | // CHECK-FIX-NEXT: 2440d0: cd f7 ff 17 b #-8396 | |
| 599 | // CHECK-FIX: __CortexA53843419_244000: | |
| 600 | // CHECK-FIX-NEXT: 2440d4: 01 08 40 f9 ldr x1, [x0, #16] | |
| 601 | // CHECK-FIX-NEXT: 2440d8: cb ff ff 17 b #-212 | |
| 602 | 602 | .data |
| 603 | 603 | .globl dat |
| 604 | 604 | .globl dat2 |
deps/lld/test/ELF/aarch64-cortex-a53-843419-tlsrelax.s created+38| ... | ... | @@ -0,0 +1,38 @@ |
| 1 | // REQUIRES: aarch64 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o | |
| 3 | // RUN: ld.lld -fix-cortex-a53-843419 %t.o -o %t2 | |
| 4 | // RUN: llvm-objdump -triple=aarch64-linux-gnu -d %t2 | FileCheck %s | |
| 5 | ||
| 6 | // The following code sequence is covered by the TLS IE to LE relaxation. It | |
| 7 | // transforms the ADRP, LDR to MOVZ, MOVK. The former can trigger a | |
| 8 | // cortex-a53-843419 patch, whereas the latter can not. As both | |
| 9 | // relaxation and patching transform instructions very late in the | |
| 10 | // link there is a possibility of them both being simultaneously | |
| 11 | // applied. In this case the relaxed sequence is immune from the erratum so we | |
| 12 | // prefer to keep it. | |
| 13 | .text | |
| 14 | .balign 4096 | |
| 15 | .space 4096 - 8 | |
| 16 | .globl _start | |
| 17 | .type _start,@function | |
| 18 | _start: | |
| 19 | mrs x1, tpidr_el0 | |
| 20 | adrp x0, :gottprel:v | |
| 21 | ldr x1, [x0, #:gottprel_lo12:v] | |
| 22 | adrp x0, :gottprel:v | |
| 23 | ldr x1, [x0, #:gottprel_lo12:v] | |
| 24 | ret | |
| 25 | ||
| 26 | // CHECK: _start: | |
| 27 | // CHECK-NEXT: 210ff8: 41 d0 3b d5 mrs x1, TPIDR_EL0 | |
| 28 | // CHECK-NEXT: 210ffc: 00 00 a0 d2 movz x0, #0, lsl #16 | |
| 29 | // CHECK-NEXT: 211000: 01 08 80 f2 movk x1, #64 | |
| 30 | // CHECK-NEXT: 211004: 00 00 a0 d2 movz x0, #0, lsl #16 | |
| 31 | // CHECK-NEXT: 211008: 01 08 80 f2 movk x1, #64 | |
| 32 | // CHECK-NEXT: 21100c: c0 03 5f d6 ret | |
| 33 | ||
| 34 | .type v,@object | |
| 35 | .section .tbss,"awT",@nobits | |
| 36 | .globl v | |
| 37 | v: | |
| 38 | .word 0 |
deps/lld/test/ELF/aarch64-data-relocs.s+2-2| ... | ... | @@ -12,7 +12,7 @@ _start: |
| 12 | 12 | // S = 0x100, A = 0x24 |
| 13 | 13 | // S + A = 0x124 |
| 14 | 14 | // CHECK: Contents of section .R_AARCH64_ABS64: |
| 15 | // CHECK-NEXT: 20000 24010000 00000000 | |
| 15 | // CHECK-NEXT: 210000 24010000 00000000 | |
| 16 | 16 | |
| 17 | 17 | .section .R_AARCH64_PREL64, "ax",@progbits |
| 18 | 18 | .xword foo - . + 0x24 |
| ... | ... | @@ -20,4 +20,4 @@ _start: |
| 20 | 20 | // S = 0x100, A = 0x24, P = 0x20008 |
| 21 | 21 | // S + A - P = 0xfffffffffffe011c |
| 22 | 22 | // CHECK: Contents of section .R_AARCH64_PREL64: |
| 23 | // CHECK-NEXT: 20008 1c01feff ffffffff | |
| 23 | // CHECK-NEXT: 210008 1c01dfff ffffffff |
deps/lld/test/ELF/aarch64-gnu-ifunc-address-pie.s created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | # REQUIRES: aarch64 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o | |
| 3 | # RUN: ld.lld -pie %t.o -o %tout | |
| 4 | # RUN: llvm-objdump -D %tout | FileCheck %s | |
| 5 | # RUN: llvm-readobj -r %tout | FileCheck %s -check-prefix=CHECK-RELOCS | |
| 6 | ||
| 7 | # Test that when we take the address of a preemptible ifunc using -fpie, we can | |
| 8 | # handle the case when the ifunc is in the same translation unit as the address | |
| 9 | # taker. In this case the compiler knows that ifunc is not defined in a shared | |
| 10 | # library so it can use a non got generating relative reference. | |
| 11 | .text | |
| 12 | .globl myfunc | |
| 13 | .type myfunc,@gnu_indirect_function | |
| 14 | myfunc: | |
| 15 | ret | |
| 16 | ||
| 17 | .text | |
| 18 | .globl main | |
| 19 | .type main,@function | |
| 20 | main: | |
| 21 | adrp x8, myfunc | |
| 22 | add x8, x8, :lo12: myfunc | |
| 23 | ret | |
| 24 | ||
| 25 | # CHECK: 0000000000010000 myfunc: | |
| 26 | # CHECK-NEXT: 10000:	c0 03 5f d6 	ret | |
| 27 | # CHECK: 0000000000010004 main: | |
| 28 | # CHECK-NEXT: 10004:	08 00 00 90 	adrp	x8, #0 | |
| 29 | # x8 = 0x10000 | |
| 30 | # CHECK-NEXT: 10008:	08 41 00 91 	add	x8, x8, #16 | |
| 31 | # x8 = 0x10010 = .plt for myfunc | |
| 32 | # CHECK-NEXT: 1000c:	c0 03 5f d6 	ret | |
| 33 | # CHECK-NEXT: Disassembly of section .plt: | |
| 34 | # CHECK-NEXT: 0000000000010010 .plt: | |
| 35 | # CHECK-NEXT: 10010:	90 00 00 90 	adrp	x16, #65536 | |
| 36 | # CHECK-NEXT: 10014:	11 02 40 f9 	ldr	x17, [x16] | |
| 37 | # CHECK-NEXT: 10018:	10 02 00 91 	add	x16, x16, #0 | |
| 38 | # CHECK-NEXT: 1001c:	20 02 1f d6 	br	x17 | |
| 39 | ||
| 40 | # CHECK-RELOCS: Relocations [ | |
| 41 | # CHECK-RELOCS-NEXT: Section {{.*}} .rela.plt { | |
| 42 | # CHECK-RELOCS-NEXT: 0x20000 R_AARCH64_IRELATIVE - 0x10000 | |
| 43 | # CHECK-RELOCS-NEXT: } | |
| 44 | # CHECK-RELOCS-NEXT: ] |
deps/lld/test/ELF/aarch64-gnu-ifunc-address.s created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | # REQUIRES: aarch64 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o | |
| 3 | # RUN: ld.lld -shared %t.o -o %tout | |
| 4 | # RUN: llvm-objdump -D %tout | FileCheck %s | |
| 5 | # RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=CHECK-RELOCS | |
| 6 | ||
| 7 | # Test that when we take the address of a preemptible ifunc in a shared object | |
| 8 | # we get R_AARCH64_GLOB_DAT to the symbol as it could be defined in another | |
| 9 | # link unit and preempt our definition. | |
| 10 | .text | |
| 11 | .globl myfunc | |
| 12 | .type myfunc,@gnu_indirect_function | |
| 13 | myfunc: | |
| 14 | ret | |
| 15 | ||
| 16 | .text | |
| 17 | .globl main | |
| 18 | .type main,@function | |
| 19 | main: | |
| 20 | adrp x8, :got:myfunc | |
| 21 | ldr x8, [x8, :got_lo12:myfunc] | |
| 22 | ret | |
| 23 | # CHECK: 0000000000010004 main: | |
| 24 | # x8 = 0x30000 | |
| 25 | # CHECK-NEXT: 10004: 08 01 00 90 adrp x8, #131072 | |
| 26 | # x8 = 0x300e0 = .got entry for myfunc with R_AARCH64_GLOB_DAT | |
| 27 | # CHECK-NEXT: 10008: 08 71 40 f9 ldr x8, [x8, #224] | |
| 28 | # CHECK-NEXT: 1000c: c0 03 5f d6 ret | |
| 29 | ||
| 30 | # CHECK: Disassembly of section .got: | |
| 31 | # CHECK-NEXT: 00000000000300e0 .got: | |
| 32 | ||
| 33 | # CHECK-RELOCS: Relocations [ | |
| 34 | # CHECK-RELOCS-NEXT: Section {{.*}} .rela.dyn { | |
| 35 | # CHECK-RELOCS-NEXT: 0x300E0 R_AARCH64_GLOB_DAT myfunc 0x0 | |
| 36 | # CHECK-RELOCS-NEXT: } | |
| 37 | # CHECK-RELOCS-NEXT: Section {{.*}} .rela.plt { | |
| 38 | # CHECK-RELOCS-NEXT: 0x20018 R_AARCH64_JUMP_SLOT myfunc 0x0 | |
| 39 | # CHECK-RELOCS-NEXT: } | |
| 40 | # CHECK-RELOCS-NEXT: ] |
deps/lld/test/ELF/aarch64-gnu-ifunc-plt.s+42-38| ... | ... | @@ -10,19 +10,19 @@ |
| 10 | 10 | // Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt |
| 11 | 11 | // CHECK: Relocations [ |
| 12 | 12 | // CHECK-NEXT: Section (4) .rela.plt { |
| 13 | // CHECK: 0x30018 R_AARCH64_JUMP_SLOT bar2 0x0 | |
| 14 | // CHECK-NEXT: 0x30020 R_AARCH64_JUMP_SLOT zed2 0x0 | |
| 15 | // CHECK-NEXT: 0x30028 R_AARCH64_IRELATIVE - 0x20000 | |
| 16 | // CHECK-NEXT: 0x30030 R_AARCH64_IRELATIVE - 0x20004 | |
| 13 | // CHECK: 0x220018 R_AARCH64_JUMP_SLOT bar2 0x0 | |
| 14 | // CHECK-NEXT: 0x220020 R_AARCH64_JUMP_SLOT zed2 0x0 | |
| 15 | // CHECK-NEXT: 0x220028 R_AARCH64_IRELATIVE - 0x210000 | |
| 16 | // CHECK-NEXT: 0x220030 R_AARCH64_IRELATIVE - 0x210004 | |
| 17 | 17 | // CHECK-NEXT: } |
| 18 | 18 | // CHECK-NEXT: ] |
| 19 | 19 | |
| 20 | 20 | // Check that .got.plt entries point back to PLT header |
| 21 | 21 | // GOTPLT: Contents of section .got.plt: |
| 22 | // GOTPLT-NEXT: 30000 00000000 00000000 00000000 00000000 | |
| 23 | // GOTPLT-NEXT: 30010 00000000 00000000 20000200 00000000 | |
| 24 | // GOTPLT-NEXT: 30020 20000200 00000000 20000200 00000000 | |
| 25 | // GOTPLT-NEXT: 30030 20000200 00000000 | |
| 22 | // GOTPLT-NEXT: 220000 00000000 00000000 00000000 00000000 | |
| 23 | // GOTPLT-NEXT: 220010 00000000 00000000 20002100 00000000 | |
| 24 | // GOTPLT-NEXT: 220020 20002100 00000000 20002100 00000000 | |
| 25 | // GOTPLT-NEXT: 220030 20002100 00000000 | |
| 26 | 26 | |
| 27 | 27 | // Check that the PLTRELSZ tag includes the IRELATIVE relocations |
| 28 | 28 | // CHECK: DynamicSection [ |
| ... | ... | @@ -31,40 +31,44 @@ |
| 31 | 31 | // Check that a PLT header is written and the ifunc entries appear last |
| 32 | 32 | // DISASM: Disassembly of section .text: |
| 33 | 33 | // DISASM-NEXT: foo: |
| 34 | // DISASM-NEXT: 20000: {{.*}} ret | |
| 34 | // DISASM-NEXT: 210000: {{.*}} ret | |
| 35 | 35 | // DISASM: bar: |
| 36 | // DISASM-NEXT: 20004: {{.*}} ret | |
| 36 | // DISASM-NEXT: 210004: {{.*}} ret | |
| 37 | 37 | // DISASM: _start: |
| 38 | // DISASM-NEXT: 20008: {{.*}} bl #88 | |
| 39 | // DISASM-NEXT: 2000c: {{.*}} bl #100 | |
| 40 | // DISASM-NEXT: 20010: {{.*}} bl #48 | |
| 41 | // DISASM-NEXT: 20014: {{.*}} bl #60 | |
| 38 | // DISASM-NEXT: 210008: {{.*}} bl #88 | |
| 39 | // DISASM-NEXT: 21000c: {{.*}} bl #100 | |
| 40 | // DISASM-NEXT: 210010: {{.*}} bl #48 | |
| 41 | // DISASM-NEXT: 210014: {{.*}} bl #60 | |
| 42 | 42 | // DISASM-NEXT: Disassembly of section .plt: |
| 43 | 43 | // DISASM-NEXT: .plt: |
| 44 | // DISASM-NEXT: 20020: {{.*}} stp x16, x30, [sp, #-16]! | |
| 45 | // DISASM-NEXT: 20024: {{.*}} adrp x16, #65536 | |
| 46 | // DISASM-NEXT: 20028: {{.*}} ldr x17, [x16, #16] | |
| 47 | // DISASM-NEXT: 2002c: {{.*}} add x16, x16, #16 | |
| 48 | // DISASM-NEXT: 20030: {{.*}} br x17 | |
| 49 | // DISASM-NEXT: 20034: {{.*}} nop | |
| 50 | // DISASM-NEXT: 20038: {{.*}} nop | |
| 51 | // DISASM-NEXT: 2003c: {{.*}} nop | |
| 52 | // DISASM-NEXT: 20040: {{.*}} adrp x16, #65536 | |
| 53 | // DISASM-NEXT: 20044: {{.*}} ldr x17, [x16, #24] | |
| 54 | // DISASM-NEXT: 20048: {{.*}} add x16, x16, #24 | |
| 55 | // DISASM-NEXT: 2004c: {{.*}} br x17 | |
| 56 | // DISASM-NEXT: 20050: {{.*}} adrp x16, #65536 | |
| 57 | // DISASM-NEXT: 20054: {{.*}} ldr x17, [x16, #32] | |
| 58 | // DISASM-NEXT: 20058: {{.*}} add x16, x16, #32 | |
| 59 | // DISASM-NEXT: 2005c: {{.*}} br x17 | |
| 60 | // DISASM-NEXT: 20060: {{.*}} adrp x16, #65536 | |
| 61 | // DISASM-NEXT: 20064: {{.*}} ldr x17, [x16, #40] | |
| 62 | // DISASM-NEXT: 20068: {{.*}} add x16, x16, #40 | |
| 63 | // DISASM-NEXT: 2006c: {{.*}} br x17 | |
| 64 | // DISASM-NEXT: 20070: {{.*}} adrp x16, #65536 | |
| 65 | // DISASM-NEXT: 20074: {{.*}} ldr x17, [x16, #48] | |
| 66 | // DISASM-NEXT: 20078: {{.*}} add x16, x16, #48 | |
| 67 | // DISASM-NEXT: 2007c: {{.*}} br x17 | |
| 44 | // DISASM-NEXT: 210020: {{.*}} stp x16, x30, [sp, #-16]! | |
| 45 | // DISASM-NEXT: 210024: {{.*}} adrp x16, #65536 | |
| 46 | // DISASM-NEXT: 210028: {{.*}} ldr x17, [x16, #16] | |
| 47 | // DISASM-NEXT: 21002c: {{.*}} add x16, x16, #16 | |
| 48 | // DISASM-NEXT: 210030: {{.*}} br x17 | |
| 49 | // DISASM-NEXT: 210034: {{.*}} nop | |
| 50 | // DISASM-NEXT: 210038: {{.*}} nop | |
| 51 | // DISASM-NEXT: 21003c: {{.*}} nop | |
| 52 | // DISASM-EMPTY: | |
| 53 | // DISASM-NEXT: bar2@plt: | |
| 54 | // DISASM-NEXT: 210040: {{.*}} adrp x16, #65536 | |
| 55 | // DISASM-NEXT: 210044: {{.*}} ldr x17, [x16, #24] | |
| 56 | // DISASM-NEXT: 210048: {{.*}} add x16, x16, #24 | |
| 57 | // DISASM-NEXT: 21004c: {{.*}} br x17 | |
| 58 | // DISASM-EMPTY: | |
| 59 | // DISASM-NEXT: zed2@plt: | |
| 60 | // DISASM-NEXT: 210050: {{.*}} adrp x16, #65536 | |
| 61 | // DISASM-NEXT: 210054: {{.*}} ldr x17, [x16, #32] | |
| 62 | // DISASM-NEXT: 210058: {{.*}} add x16, x16, #32 | |
| 63 | // DISASM-NEXT: 21005c: {{.*}} br x17 | |
| 64 | // DISASM-NEXT: 210060: {{.*}} adrp x16, #65536 | |
| 65 | // DISASM-NEXT: 210064: {{.*}} ldr x17, [x16, #40] | |
| 66 | // DISASM-NEXT: 210068: {{.*}} add x16, x16, #40 | |
| 67 | // DISASM-NEXT: 21006c: {{.*}} br x17 | |
| 68 | // DISASM-NEXT: 210070: {{.*}} adrp x16, #65536 | |
| 69 | // DISASM-NEXT: 210074: {{.*}} ldr x17, [x16, #48] | |
| 70 | // DISASM-NEXT: 210078: {{.*}} add x16, x16, #48 | |
| 71 | // DISASM-NEXT: 21007c: {{.*}} br x17 | |
| 68 | 72 | |
| 69 | 73 | .text |
| 70 | 74 | .type foo STT_GNU_IFUNC |
deps/lld/test/ELF/aarch64-gnu-ifunc.s+23-23| ... | ... | @@ -16,14 +16,14 @@ |
| 16 | 16 | // CHECK-NEXT: Offset: 0x158 |
| 17 | 17 | // CHECK-NEXT: Size: 48 |
| 18 | 18 | // CHECK-NEXT: Link: 0 |
| 19 | // CHECK-NEXT: Info: 0 | |
| 19 | // CHECK-NEXT: Info: 4 | |
| 20 | 20 | // CHECK-NEXT: AddressAlignment: 8 |
| 21 | 21 | // CHECK-NEXT: EntrySize: 24 |
| 22 | 22 | // CHECK-NEXT: } |
| 23 | 23 | // CHECK: Relocations [ |
| 24 | 24 | // CHECK-NEXT: Section ({{.*}}) .rela.plt { |
| 25 | // CHECK-NEXT: 0x30000 R_AARCH64_IRELATIVE | |
| 26 | // CHECK-NEXT: 0x30008 R_AARCH64_IRELATIVE | |
| 25 | // CHECK-NEXT: 0x220000 R_AARCH64_IRELATIVE | |
| 26 | // CHECK-NEXT: 0x220008 R_AARCH64_IRELATIVE | |
| 27 | 27 | // CHECK-NEXT: } |
| 28 | 28 | // CHECK-NEXT: ] |
| 29 | 29 | // CHECK: Symbols [ |
| ... | ... | @@ -38,7 +38,7 @@ |
| 38 | 38 | // CHECK-NEXT: } |
| 39 | 39 | // CHECK-NEXT: Symbol { |
| 40 | 40 | // CHECK-NEXT: Name: $x.0 |
| 41 | // CHECK-NEXT: Value: 0x20000 | |
| 41 | // CHECK-NEXT: Value: 0x210000 | |
| 42 | 42 | // CHECK-NEXT: Size: 0 |
| 43 | 43 | // CHECK-NEXT: Binding: Local |
| 44 | 44 | // CHECK-NEXT: Type: None |
| ... | ... | @@ -47,7 +47,7 @@ |
| 47 | 47 | // CHECK-NEXT: } |
| 48 | 48 | // CHECK-NEXT: Symbol { |
| 49 | 49 | // CHECK-NEXT: Name: __rela_iplt_end |
| 50 | // CHECK-NEXT: Value: 0x10188 | |
| 50 | // CHECK-NEXT: Value: 0x200188 | |
| 51 | 51 | // CHECK-NEXT: Size: 0 |
| 52 | 52 | // CHECK-NEXT: Binding: Local |
| 53 | 53 | // CHECK-NEXT: Type: None |
| ... | ... | @@ -58,7 +58,7 @@ |
| 58 | 58 | // CHECK-NEXT: } |
| 59 | 59 | // CHECK-NEXT: Symbol { |
| 60 | 60 | // CHECK-NEXT: Name: __rela_iplt_start |
| 61 | // CHECK-NEXT: Value: 0x10158 | |
| 61 | // CHECK-NEXT: Value: 0x200158 | |
| 62 | 62 | // CHECK-NEXT: Size: 0 |
| 63 | 63 | // CHECK-NEXT: Binding: Local |
| 64 | 64 | // CHECK-NEXT: Type: None |
| ... | ... | @@ -69,7 +69,7 @@ |
| 69 | 69 | // CHECK-NEXT: } |
| 70 | 70 | // CHECK-NEXT: Symbol { |
| 71 | 71 | // CHECK-NEXT: Name: _start |
| 72 | // CHECK-NEXT: Value: 0x20008 | |
| 72 | // CHECK-NEXT: Value: 0x210008 | |
| 73 | 73 | // CHECK-NEXT: Size: 0 |
| 74 | 74 | // CHECK-NEXT: Binding: Global |
| 75 | 75 | // CHECK-NEXT: Type: None |
| ... | ... | @@ -78,7 +78,7 @@ |
| 78 | 78 | // CHECK-NEXT: } |
| 79 | 79 | // CHECK-NEXT: Symbol { |
| 80 | 80 | // CHECK-NEXT: Name: bar |
| 81 | // CHECK-NEXT: Value: 0x20004 | |
| 81 | // CHECK-NEXT: Value: 0x210004 | |
| 82 | 82 | // CHECK-NEXT: Size: 0 |
| 83 | 83 | // CHECK-NEXT: Binding: Global |
| 84 | 84 | // CHECK-NEXT: Type: GNU_IFunc |
| ... | ... | @@ -87,7 +87,7 @@ |
| 87 | 87 | // CHECK-NEXT: } |
| 88 | 88 | // CHECK-NEXT: Symbol { |
| 89 | 89 | // CHECK-NEXT: Name: foo |
| 90 | // CHECK-NEXT: Value: 0x20000 | |
| 90 | // CHECK-NEXT: Value: 0x210000 | |
| 91 | 91 | // CHECK-NEXT: Size: 0 |
| 92 | 92 | // CHECK-NEXT: Binding: Global |
| 93 | 93 | // CHECK-NEXT: Type: GNU_IFunc |
| ... | ... | @@ -101,24 +101,24 @@ |
| 101 | 101 | |
| 102 | 102 | // DISASM: Disassembly of section .text: |
| 103 | 103 | // DISASM-NEXT: foo: |
| 104 | // DISASM-NEXT: 20000: c0 03 5f d6 ret | |
| 104 | // DISASM-NEXT: 210000: c0 03 5f d6 ret | |
| 105 | 105 | // DISASM: bar: |
| 106 | // DISASM-NEXT: 20004: c0 03 5f d6 ret | |
| 106 | // DISASM-NEXT: 210004: c0 03 5f d6 ret | |
| 107 | 107 | // DISASM: _start: |
| 108 | // DISASM-NEXT: 20008: 06 00 00 94 bl #24 | |
| 109 | // DISASM-NEXT: 2000c: 09 00 00 94 bl #36 | |
| 110 | // DISASM-NEXT: 20010: 42 60 05 91 add x2, x2, #344 | |
| 111 | // DISASM-NEXT: 20014: 42 20 06 91 add x2, x2, #392 | |
| 108 | // DISASM-NEXT: 210008: 06 00 00 94 bl #24 | |
| 109 | // DISASM-NEXT: 21000c: 09 00 00 94 bl #36 | |
| 110 | // DISASM-NEXT: 210010: 42 60 05 91 add x2, x2, #344 | |
| 111 | // DISASM-NEXT: 210014: 42 20 06 91 add x2, x2, #392 | |
| 112 | 112 | // DISASM-NEXT: Disassembly of section .plt: |
| 113 | 113 | // DISASM-NEXT: .plt: |
| 114 | // DISASM-NEXT: 20020: 90 00 00 90 adrp x16, #65536 | |
| 115 | // DISASM-NEXT: 20024: 11 02 40 f9 ldr x17, [x16] | |
| 116 | // DISASM-NEXT: 20028: 10 02 00 91 add x16, x16, #0 | |
| 117 | // DISASM-NEXT: 2002c: 20 02 1f d6 br x17 | |
| 118 | // DISASM-NEXT: 20030: 90 00 00 90 adrp x16, #65536 | |
| 119 | // DISASM-NEXT: 20034: 11 06 40 f9 ldr x17, [x16, #8] | |
| 120 | // DISASM-NEXT: 20038: 10 22 00 91 add x16, x16, #8 | |
| 121 | // DISASM-NEXT: 2003c: 20 02 1f d6 br x17 | |
| 114 | // DISASM-NEXT: 210020: 90 00 00 90 adrp x16, #65536 | |
| 115 | // DISASM-NEXT: 210024: 11 02 40 f9 ldr x17, [x16] | |
| 116 | // DISASM-NEXT: 210028: 10 02 00 91 add x16, x16, #0 | |
| 117 | // DISASM-NEXT: 21002c: 20 02 1f d6 br x17 | |
| 118 | // DISASM-NEXT: 210030: 90 00 00 90 adrp x16, #65536 | |
| 119 | // DISASM-NEXT: 210034: 11 06 40 f9 ldr x17, [x16, #8] | |
| 120 | // DISASM-NEXT: 210038: 10 22 00 91 add x16, x16, #8 | |
| 121 | // DISASM-NEXT: 21003c: 20 02 1f d6 br x17 | |
| 122 | 122 | |
| 123 | 123 | .text |
| 124 | 124 | .type foo STT_GNU_IFUNC |
deps/lld/test/ELF/aarch64-gnu-ifunc2.s created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | # REQUIRES: aarch64 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o | |
| 3 | # RUN: ld.lld -static %t.o -o %tout | |
| 4 | # RUN: llvm-objdump -D %tout | FileCheck %s | |
| 5 | # RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=RELOC | |
| 6 | ||
| 7 | # CHECK: Disassembly of section .text: | |
| 8 | # CHECK-NEXT: myfunc: | |
| 9 | # CHECK-NEXT: 210000: | |
| 10 | ||
| 11 | # CHECK: main: | |
| 12 | # adrp x8, 0x230000, 0x230000 == address in .got | |
| 13 | # CHECK-NEXT: 210004: {{.*}} adrp x8, #131072 | |
| 14 | # CHECK-NEXT: 210008: {{.*}} ldr x8, [x8] | |
| 15 | # CHECK-NEXT: 21000c: {{.*}} ret | |
| 16 | ||
| 17 | # CHECK: Disassembly of section .plt: | |
| 18 | # CHECK-NEXT: .plt: | |
| 19 | # adrp x16, 0x220000, 0x220000 == address in .got.plt | |
| 20 | # CHECK-NEXT: 210010: {{.*}} adrp x16, #65536 | |
| 21 | # CHECK-NEXT: 210014: {{.*}} ldr x17, [x16] | |
| 22 | # CHECK-NEXT: 210018: {{.*}} add x16, x16, #0 | |
| 23 | # CHECK-NEXT: 21001c: {{.*}} br x17 | |
| 24 | ||
| 25 | # CHECK: Disassembly of section .got.plt: | |
| 26 | # CHECK-NEXT: .got.plt: | |
| 27 | # CHECK-NEXT: 220000: | |
| 28 | ||
| 29 | # CHECK: Disassembly of section .got: | |
| 30 | # CHECK-NEXT: .got: | |
| 31 | # 0x210010 == address in .plt | |
| 32 | # CHECK-NEXT: 230000: 10 00 21 00 | |
| 33 | ||
| 34 | # RELOC: Relocations [ | |
| 35 | # RELOC-NEXT: Section {{.*}} .rela.plt { | |
| 36 | # RELOC-NEXT: 0x220000 R_AARCH64_IRELATIVE - 0x210000 | |
| 37 | # RELOC-NEXT: } | |
| 38 | # RELOC-NEXT: ] | |
| 39 | ||
| 40 | .text | |
| 41 | .globl myfunc | |
| 42 | .type myfunc,@gnu_indirect_function | |
| 43 | myfunc: | |
| 44 | ret | |
| 45 | ||
| 46 | .text | |
| 47 | .globl main | |
| 48 | .type main,@function | |
| 49 | main: | |
| 50 | adrp x8, :got:myfunc | |
| 51 | ldr x8, [x8, :got_lo12:myfunc] | |
| 52 | ret |
deps/lld/test/ELF/aarch64-gnu-ifunc3.s created+49| ... | ... | @@ -0,0 +1,49 @@ |
| 1 | # REQUIRES: aarch64 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o | |
| 3 | # RUN: ld.lld -static %t.o -o %tout | |
| 4 | # RUN: llvm-objdump -D %tout | FileCheck %s | |
| 5 | # RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=RELOC | |
| 6 | ||
| 7 | # The address of myfunc is the address of the PLT entry for myfunc. | |
| 8 | # The adrp to myfunc should generate a PLT entry and a got entry with an | |
| 9 | # irelative relocation. | |
| 10 | .text | |
| 11 | .globl myfunc | |
| 12 | .type myfunc,@gnu_indirect_function | |
| 13 | myfunc: | |
| 14 | ret | |
| 15 | ||
| 16 | .text | |
| 17 | .globl _start | |
| 18 | .type _start,@function | |
| 19 | _start: | |
| 20 | adrp x8, myfunc | |
| 21 | add x8, x8, :lo12:myfunc | |
| 22 | ret | |
| 23 | ||
| 24 | # CHECK: Disassembly of section .text: | |
| 25 | # CHECK-NEXT: myfunc: | |
| 26 | # CHECK-NEXT: 210000:	c0 03 5f d6 	ret | |
| 27 | # CHECK: _start: | |
| 28 | # adrp x8, 0x210000 + 0x10 from add == .plt entry | |
| 29 | # CHECK-NEXT: 210004:	08 00 00 90 	adrp	x8, #0 | |
| 30 | # CHECK-NEXT: 210008:	08 41 00 91 	add	x8, x8, #16 | |
| 31 | # CHECK-NEXT: 21000c:	c0 03 5f d6 	ret | |
| 32 | # CHECK-NEXT: Disassembly of section .plt: | |
| 33 | # CHECK-NEXT: .plt: | |
| 34 | # adrp x16, 0x220000, 0x220000 == address in .got.plt | |
| 35 | # CHECK-NEXT: 210010:	90 00 00 90 	adrp	x16, #65536 | |
| 36 | # CHECK-NEXT: 210014:	11 02 40 f9 	ldr	x17, [x16] | |
| 37 | # CHECK-NEXT: 210018:	10 02 00 91 	add	x16, x16, #0 | |
| 38 | # CHECK-NEXT: 21001c:	20 02 1f d6 	br	x17 | |
| 39 | # CHECK-NEXT: Disassembly of section .got.plt: | |
| 40 | # CHECK-NEXT: .got.plt: | |
| 41 | # 0x210010 == address in .plt | |
| 42 | # CHECK-NEXT: 220000:	10 00 21 00 | |
| 43 | # CHECK-NEXT: 220004:	00 00 00 00 | |
| 44 | ||
| 45 | # RELOC: Relocations [ | |
| 46 | # RELOC-NEXT: Section (1) .rela.plt { | |
| 47 | # RELOC-NEXT: 0x220000 R_AARCH64_IRELATIVE - 0x210000 | |
| 48 | # RELOC-NEXT: } | |
| 49 | # RELOC-NEXT: ] |
deps/lld/test/ELF/aarch64-jump26-thunk.s+5-5| ... | ... | @@ -11,10 +11,10 @@ _start: |
| 11 | 11 | |
| 12 | 12 | // CHECK: Disassembly of section .text: |
| 13 | 13 | // CHECK-NEXT: _start: |
| 14 | // CHECK-NEXT: 20000: 02 00 00 14 b #8 | |
| 14 | // CHECK-NEXT: 210000: 02 00 00 14 b #8 | |
| 15 | 15 | // CHECK: __AArch64AbsLongThunk_big: |
| 16 | // CHECK-NEXT: 20008: 50 00 00 58 ldr x16, #8 | |
| 17 | // CHECK-NEXT: 2000c: 00 02 1f d6 br x16 | |
| 16 | // CHECK-NEXT: 210008: 50 00 00 58 ldr x16, #8 | |
| 17 | // CHECK-NEXT: 21000c: 00 02 1f d6 br x16 | |
| 18 | 18 | // CHECK: $d: |
| 19 | // CHECK-NEXT: 20010: 00 00 00 00 .word 0x00000000 | |
| 20 | // CHECK-NEXT: 20014: 10 00 00 00 .word 0x00000010 | |
| 19 | // CHECK-NEXT: 210010: 00 00 00 00 .word 0x00000000 | |
| 20 | // CHECK-NEXT: 210014: 10 00 00 00 .word 0x00000010 |
deps/lld/test/ELF/aarch64-lo12-alignment.s+4-4| ... | ... | @@ -39,7 +39,7 @@ foo4: |
| 39 | 39 | foo8: |
| 40 | 40 | .space 8 |
| 41 | 41 | |
| 42 | // CHECK: improper alignment for relocation R_AARCH64_LDST16_ABS_LO12_NC: 0x30001 is not aligned to 2 bytes | |
| 43 | // CHECK-NEXT: improper alignment for relocation R_AARCH64_LDST32_ABS_LO12_NC: 0x30002 is not aligned to 4 bytes | |
| 44 | // CHECK-NEXT: improper alignment for relocation R_AARCH64_LDST64_ABS_LO12_NC: 0x30004 is not aligned to 8 bytes | |
| 45 | // CHECK-NEXT: improper alignment for relocation R_AARCH64_LDST128_ABS_LO12_NC: 0x30008 is not aligned to 16 bytes | |
| 42 | // CHECK: improper alignment for relocation R_AARCH64_LDST16_ABS_LO12_NC: 0x220001 is not aligned to 2 bytes | |
| 43 | // CHECK-NEXT: improper alignment for relocation R_AARCH64_LDST32_ABS_LO12_NC: 0x220002 is not aligned to 4 bytes | |
| 44 | // CHECK-NEXT: improper alignment for relocation R_AARCH64_LDST64_ABS_LO12_NC: 0x220004 is not aligned to 8 bytes | |
| 45 | // CHECK-NEXT: improper alignment for relocation R_AARCH64_LDST128_ABS_LO12_NC: 0x220008 is not aligned to 16 bytes |
deps/lld/test/ELF/aarch64-prel16.s+12-12| ... | ... | @@ -7,8 +7,8 @@ |
| 7 | 7 | .globl _start |
| 8 | 8 | _start: |
| 9 | 9 | .data |
| 10 | .hword foo - . + 0x20eff | |
| 11 | .hword foo - . + 0x8f02 | |
| 10 | .hword foo - . + 0x210eff | |
| 11 | .hword foo - . + 0x1f8f02 | |
| 12 | 12 | |
| 13 | 13 | // Note: If this test fails, it probably happens because of |
| 14 | 14 | // the change of the address of the .data section. |
| ... | ... | @@ -18,14 +18,14 @@ _start: |
| 18 | 18 | // RUN: llvm-objdump -s -section=.data %t2 | FileCheck %s |
| 19 | 19 | |
| 20 | 20 | // CHECK: Contents of section .data: |
| 21 | // 11000: S = 0x100, A = 0x20eff, P = 0x11000 | |
| 22 | // S + A - P = 0xffff | |
| 23 | // 11002: S = 0x100, A = 0x8f02, P = 0x11002 | |
| 24 | // S + A - P = 0x8000 | |
| 25 | // CHECK-NEXT: 11000 ffff0080 | |
| 21 | // 201000: S = 0x100, A = 0x210eff, P = 0x201000 | |
| 22 | // S + A - P = 0xffff | |
| 23 | // 201002: S = 0x100, A = 0x1f8f02, P = 0x201002 | |
| 24 | // S + A - P = 0x8000 | |
| 25 | // CHECK-NEXT: 201000 ffff0080 | |
| 26 | 26 | |
| 27 | // RUN: not ld.lld %t.o %t255.o -o %t2 | |
| 28 | // | FileCheck %s --check-prefix=OVERFLOW | |
| 29 | // RUN: not ld.lld %t.o %t257.o -o %t2 | |
| 30 | // | FileCheck %s --check-prefix=OVERFLOW | |
| 31 | // OVERFLOW: Relocation R_AARCH64_PREL16 out of range: -94209 is not in [-32768, 65535] | |
| 27 | // RUN: not ld.lld -z max-page-size=4096 %t.o %t255.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW1 | |
| 28 | // OVERFLOW1: relocation R_AARCH64_PREL16 out of range: -32769 is not in [-32768, 32767] | |
| 29 | ||
| 30 | // RUN: not ld.lld -z max-page-size=4096 %t.o %t257.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW2 | |
| 31 | // OVERFLOW2: relocation R_AARCH64_PREL16 out of range: 65536 is not in [-32768, 32767] |
deps/lld/test/ELF/aarch64-prel32.s+12-12| ... | ... | @@ -7,8 +7,8 @@ |
| 7 | 7 | .globl _start |
| 8 | 8 | _start: |
| 9 | 9 | .data |
| 10 | .word foo - . + 0x100010eff | |
| 11 | .word foo - . - 0x7ffef0fc | |
| 10 | .word foo - . + 0x100200eff | |
| 11 | .word foo - . - 0x7fdff0fc | |
| 12 | 12 | |
| 13 | 13 | // Note: If this test fails, it probably happens because of |
| 14 | 14 | // the change of the address of the .data section. |
| ... | ... | @@ -18,14 +18,14 @@ _start: |
| 18 | 18 | // RUN: llvm-objdump -s -section=.data %t2 | FileCheck %s |
| 19 | 19 | |
| 20 | 20 | // CHECK: Contents of section .data: |
| 21 | // 11000: S = 0x100, A = 0x100010eff, P = 0x11000 | |
| 22 | // S + A - P = 0xffffffff | |
| 23 | // 11004: S = 0x100, A = -0x7ffef0fc, P = 0x11004 | |
| 24 | // S + A - P = 0x80000000 | |
| 25 | // CHECK-NEXT: 11000 ffffffff 00000080 | |
| 21 | // 201000: S = 0x100, A = 0x100200eff, P = 0x201000 | |
| 22 | // S + A - P = 0xffffffff | |
| 23 | // 201004: S = 0x100, A = -0x7fdff0fc, P = 0x201004 | |
| 24 | // S + A - P = 0x80000000 | |
| 25 | // CHECK-NEXT: 201000 ffffffff 00000080 | |
| 26 | 26 | |
| 27 | // RUN: not ld.lld %t.o %t255.o -o %t2 | |
| 28 | // | FileCheck %s --check-prefix=OVERFLOW | |
| 29 | // RUN: not ld.lld %t.o %t257.o -o %t2 | |
| 30 | // | FileCheck %s --check-prefix=OVERFLOW | |
| 31 | // OVERFLOW: Relocation R_AARCH64_PREL32 out of range: 18446744071562006527 is not in [-2147483648, 4294967295] | |
| 27 | // RUN: not ld.lld -z max-page-size=4096 %t.o %t255.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW1 | |
| 28 | // OVERFLOW1: relocation R_AARCH64_PREL32 out of range: -2147483649 is not in [-2147483648, 2147483647] | |
| 29 | ||
| 30 | // RUN: not ld.lld -z max-page-size=4096 %t.o %t257.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW2 | |
| 31 | // OVERFLOW2: relocation R_AARCH64_PREL32 out of range: 4294967296 is not in [-2147483648, 2147483647] |
deps/lld/test/ELF/aarch64-relocs.s+25-25| ... | ... | @@ -24,13 +24,13 @@ mystr: |
| 24 | 24 | .asciz "blah" |
| 25 | 25 | .size mystr, 4 |
| 26 | 26 | |
| 27 | # S = 0x20012, A = 0x4, P = 0x20012 | |
| 28 | # PAGE(S + A) = 0x11000 | |
| 29 | # PAGE(P) = 0x11000 | |
| 27 | # S = 0x210012, A = 0x4, P = 0x210012 | |
| 28 | # PAGE(S + A) = 0x210000 | |
| 29 | # PAGE(P) = 0x210000 | |
| 30 | 30 | # |
| 31 | 31 | # CHECK: Disassembly of section .R_AARCH64_ADR_PREL_PG_H121: |
| 32 | 32 | # CHECK-NEXT: $x.2: |
| 33 | # CHECK-NEXT: 20012: 01 00 00 90 adrp x1, #0 | |
| 33 | # CHECK-NEXT: 210012: 01 00 00 90 adrp x1, #0 | |
| 34 | 34 | |
| 35 | 35 | .section .R_AARCH64_ADD_ABS_LO12_NC,"ax",@progbits |
| 36 | 36 | add x0, x0, :lo12:.L.str |
| ... | ... | @@ -38,13 +38,13 @@ mystr: |
| 38 | 38 | .asciz "blah" |
| 39 | 39 | .size mystr, 4 |
| 40 | 40 | |
| 41 | # S = 0x2001b, A = 0x4 | |
| 41 | # S = 0x21001b, A = 0x4 | |
| 42 | 42 | # R = (S + A) & 0xFFF = 0x1f |
| 43 | 43 | # R << 10 = 0x7c00 |
| 44 | 44 | # |
| 45 | 45 | # CHECK: Disassembly of section .R_AARCH64_ADD_ABS_LO12_NC: |
| 46 | 46 | # CHECK-NEXT: $x.4: |
| 47 | # CHECK-NEXT: 2001b: 00 7c 00 91 add x0, x0, #31 | |
| 47 | # CHECK-NEXT: 21001b: 00 7c 00 91 add x0, x0, #31 | |
| 48 | 48 | |
| 49 | 49 | .section .R_AARCH64_LDST64_ABS_LO12_NC,"ax",@progbits |
| 50 | 50 | ldr x28, [x27, :lo12:foo] |
| ... | ... | @@ -52,12 +52,12 @@ foo: |
| 52 | 52 | .asciz "foo" |
| 53 | 53 | .size mystr, 3 |
| 54 | 54 | |
| 55 | # S = 0x20024, A = 0x4 | |
| 55 | # S = 0x210024, A = 0x4 | |
| 56 | 56 | # R = ((S + A) & 0xFFF) << 7 = 0x00001400 |
| 57 | 57 | # 0x00001400 | 0xf940177c = 0xf940177c |
| 58 | 58 | # CHECK: Disassembly of section .R_AARCH64_LDST64_ABS_LO12_NC: |
| 59 | 59 | # CHECK-NEXT: $x.6: |
| 60 | # CHECK-NEXT: 20024: 7c 17 40 f9 ldr x28, [x27, #40] | |
| 60 | # CHECK-NEXT: 210024: 7c 17 40 f9 ldr x28, [x27, #40] | |
| 61 | 61 | |
| 62 | 62 | .section .SUB,"ax",@progbits |
| 63 | 63 | nop |
| ... | ... | @@ -66,33 +66,33 @@ sub: |
| 66 | 66 | |
| 67 | 67 | # CHECK: Disassembly of section .SUB: |
| 68 | 68 | # CHECK-NEXT: $x.8: |
| 69 | # CHECK-NEXT: 2002c: 1f 20 03 d5 nop | |
| 69 | # CHECK-NEXT: 21002c: 1f 20 03 d5 nop | |
| 70 | 70 | # CHECK: sub: |
| 71 | # CHECK-NEXT: 20030: 1f 20 03 d5 nop | |
| 71 | # CHECK-NEXT: 210030: 1f 20 03 d5 nop | |
| 72 | 72 | |
| 73 | 73 | .section .R_AARCH64_CALL26,"ax",@progbits |
| 74 | 74 | call26: |
| 75 | 75 | bl sub |
| 76 | 76 | |
| 77 | # S = 0x2002c, A = 0x4, P = 0x20034 | |
| 77 | # S = 0x21002c, A = 0x4, P = 0x210034 | |
| 78 | 78 | # R = S + A - P = -0x4 = 0xfffffffc |
| 79 | 79 | # (R & 0x0ffffffc) >> 2 = 0x03ffffff |
| 80 | 80 | # 0x94000000 | 0x03ffffff = 0x97ffffff |
| 81 | 81 | # CHECK: Disassembly of section .R_AARCH64_CALL26: |
| 82 | 82 | # CHECK-NEXT: call26: |
| 83 | # CHECK-NEXT: 20034: ff ff ff 97 bl #-4 | |
| 83 | # CHECK-NEXT: 210034: ff ff ff 97 bl #-4 | |
| 84 | 84 | |
| 85 | 85 | .section .R_AARCH64_JUMP26,"ax",@progbits |
| 86 | 86 | jump26: |
| 87 | 87 | b sub |
| 88 | 88 | |
| 89 | # S = 0x2002c, A = 0x4, P = 0x20038 | |
| 89 | # S = 0x21002c, A = 0x4, P = 0x210038 | |
| 90 | 90 | # R = S + A - P = -0x8 = 0xfffffff8 |
| 91 | 91 | # (R & 0x0ffffffc) >> 2 = 0x03fffffe |
| 92 | 92 | # 0x14000000 | 0x03fffffe = 0x17fffffe |
| 93 | 93 | # CHECK: Disassembly of section .R_AARCH64_JUMP26: |
| 94 | 94 | # CHECK-NEXT: jump26: |
| 95 | # CHECK-NEXT: 20038: fe ff ff 17 b #-8 | |
| 95 | # CHECK-NEXT: 210038: fe ff ff 17 b #-8 | |
| 96 | 96 | |
| 97 | 97 | .section .R_AARCH64_LDST32_ABS_LO12_NC,"ax",@progbits |
| 98 | 98 | ldst32: |
| ... | ... | @@ -101,12 +101,12 @@ foo32: |
| 101 | 101 | .asciz "foo" |
| 102 | 102 | .size mystr, 3 |
| 103 | 103 | |
| 104 | # S = 0x2003c, A = 0x4 | |
| 104 | # S = 0x21003c, A = 0x4 | |
| 105 | 105 | # R = ((S + A) & 0xFFC) << 8 = 0x00004000 |
| 106 | 106 | # 0x00004000 | 0xbd4000a4 = 0xbd4040a4 |
| 107 | 107 | # CHECK: Disassembly of section .R_AARCH64_LDST32_ABS_LO12_NC: |
| 108 | 108 | # CHECK-NEXT: ldst32: |
| 109 | # CHECK-NEXT: 2003c: a4 40 40 bd ldr s4, [x5, #64] | |
| 109 | # CHECK-NEXT: 21003c: a4 40 40 bd ldr s4, [x5, #64] | |
| 110 | 110 | |
| 111 | 111 | .section .R_AARCH64_LDST8_ABS_LO12_NC,"ax",@progbits |
| 112 | 112 | ldst8: |
| ... | ... | @@ -115,12 +115,12 @@ foo8: |
| 115 | 115 | .asciz "foo" |
| 116 | 116 | .size mystr, 3 |
| 117 | 117 | |
| 118 | # S = 0x20044, A = 0x4 | |
| 118 | # S = 0x210044, A = 0x4 | |
| 119 | 119 | # R = ((S + A) & 0xFFF) << 10 = 0x00012000 |
| 120 | 120 | # 0x00012000 | 0x398001ab = 0x398121ab |
| 121 | 121 | # CHECK: Disassembly of section .R_AARCH64_LDST8_ABS_LO12_NC: |
| 122 | 122 | # CHECK-NEXT: ldst8: |
| 123 | # CHECK-NEXT: 20044: ab 21 81 39 ldrsb x11, [x13, #72] | |
| 123 | # CHECK-NEXT: 210044: ab 21 81 39 ldrsb x11, [x13, #72] | |
| 124 | 124 | |
| 125 | 125 | .section .R_AARCH64_LDST128_ABS_LO12_NC,"ax",@progbits |
| 126 | 126 | ldst128: |
| ... | ... | @@ -129,14 +129,14 @@ foo128: |
| 129 | 129 | .asciz "foo" |
| 130 | 130 | .size mystr, 3 |
| 131 | 131 | |
| 132 | # S = 0x2004c, A = 0x4 | |
| 132 | # S = 0x21004c, A = 0x4 | |
| 133 | 133 | # R = ((S + A) & 0xFF8) << 6 = 0x00001400 |
| 134 | 134 | # 0x00001400 | 0x3dc00274 = 0x3dc01674 |
| 135 | 135 | # CHECK: Disassembly of section .R_AARCH64_LDST128_ABS_LO12_NC: |
| 136 | 136 | # CHECK: ldst128: |
| 137 | # CHECK: 2004c: 74 16 c0 3d ldr q20, [x19, #80] | |
| 137 | # CHECK: 21004c: 74 16 c0 3d ldr q20, [x19, #80] | |
| 138 | 138 | #foo128: |
| 139 | # 20050: 66 6f 6f 00 .word | |
| 139 | # 210050: 66 6f 6f 00 .word | |
| 140 | 140 | |
| 141 | 141 | .section .R_AARCH64_LDST16_ABS_LO12_NC,"ax",@progbits |
| 142 | 142 | ldst16: |
| ... | ... | @@ -147,14 +147,14 @@ foo16: |
| 147 | 147 | .asciz "foo" |
| 148 | 148 | .size mystr, 4 |
| 149 | 149 | |
| 150 | # S = 0x20054, A = 0x4 | |
| 150 | # S = 0x210054, A = 0x4 | |
| 151 | 151 | # R = ((S + A) & 0x0FFC) << 9 = 0xb000 |
| 152 | 152 | # 0xb000 | 0x7d400271 = 0x7d40b271 |
| 153 | 153 | # CHECK: Disassembly of section .R_AARCH64_LDST16_ABS_LO12_NC: |
| 154 | 154 | # CHECK-NEXT: ldst16: |
| 155 | # CHECK-NEXT: 20054: 71 c2 40 7d ldr h17, [x19, #96] | |
| 156 | # CHECK-NEXT: 20058: 61 c2 40 79 ldrh w1, [x19, #96] | |
| 157 | # CHECK-NEXT: 2005c: 62 c6 40 79 ldrh w2, [x19, #98] | |
| 155 | # CHECK-NEXT: 210054: 71 c2 40 7d ldr h17, [x19, #96] | |
| 156 | # CHECK-NEXT: 210058: 61 c2 40 79 ldrh w1, [x19, #96] | |
| 157 | # CHECK-NEXT: 21005c: 62 c6 40 79 ldrh w2, [x19, #98] | |
| 158 | 158 | |
| 159 | 159 | .section .R_AARCH64_MOVW_UABS,"ax",@progbits |
| 160 | 160 | movz1: |
deps/lld/test/ELF/aarch64-thunk-pi.s+4| ... | ... | @@ -81,10 +81,14 @@ high_target2: |
| 81 | 81 | // CHECK-NEXT: 10000034: 1f 20 03 d5 nop |
| 82 | 82 | // CHECK-NEXT: 10000038: 1f 20 03 d5 nop |
| 83 | 83 | // CHECK-NEXT: 1000003c: 1f 20 03 d5 nop |
| 84 | // CHECK-EMPTY: | |
| 85 | // CHECK-NEXT: high_target@plt: | |
| 84 | 86 | // CHECK-NEXT: 10000040: 10 00 00 90 adrp x16, #0 |
| 85 | 87 | // CHECK-NEXT: 10000044: 11 3e 40 f9 ldr x17, [x16, #120] |
| 86 | 88 | // CHECK-NEXT: 10000048: 10 e2 01 91 add x16, x16, #120 |
| 87 | 89 | // CHECK-NEXT: 1000004c: 20 02 1f d6 br x17 |
| 90 | // CHECK-EMPTY: | |
| 91 | // CHECK-NEXT: low_target@plt: | |
| 88 | 92 | // CHECK-NEXT: 10000050: 10 00 00 90 adrp x16, #0 |
| 89 | 93 | // CHECK-NEXT: 10000054: 11 42 40 f9 ldr x17, [x16, #128] |
| 90 | 94 | // CHECK-NEXT: 10000058: 10 02 02 91 add x16, x16, #128 |
deps/lld/test/ELF/aarch64-thunk-section-location.s+4-4| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | // REQUIRES: aarch64 |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t |
| 3 | 3 | // RUN: ld.lld %t -o %t2 2>&1 |
| 4 | // RUN: llvm-objdump -d -start-address=134086664 -stop-address=134086676 -triple=aarch64-linux-gnu %t2 | FileCheck %s | |
| 4 | // RUN: llvm-objdump -d -start-address=136118280 -stop-address=136118292 -triple=aarch64-linux-gnu %t2 | FileCheck %s | |
| 5 | 5 | // Check that the range extension thunks are dumped close to the aarch64 branch |
| 6 | 6 | // range of 128 MiB |
| 7 | 7 | .section .text.1, "ax", %progbits |
| ... | ... | @@ -35,7 +35,7 @@ high_target: |
| 35 | 35 | ret |
| 36 | 36 | |
| 37 | 37 | // CHECK: __AArch64AbsLongThunk_high_target: |
| 38 | // CHECK-NEXT: 7fe0008: 50 00 00 58 ldr x16, #8 | |
| 39 | // CHECK-NEXT: 7fe000c: 00 02 1f d6 br x16 | |
| 38 | // CHECK-NEXT: 81d0008: 50 00 00 58 ldr x16, #8 | |
| 39 | // CHECK-NEXT: 81d000c: 00 02 1f d6 br x16 | |
| 40 | 40 | // CHECK: $d: |
| 41 | // CHECK-NEXT: 7fe0010: 00 10 02 08 .word 0x08021000 | |
| 41 | // CHECK-NEXT: 81d0010: 00 10 21 08 .word 0x08211000 |
deps/lld/test/ELF/aarch64-tls-gdie.s+7-7| ... | ... | @@ -21,14 +21,14 @@ _start: |
| 21 | 21 | // SEC-NEXT: SHF_ALLOC |
| 22 | 22 | // SEC-NEXT: SHF_WRITE |
| 23 | 23 | // SEC-NEXT: ] |
| 24 | // SEC-NEXT: Address: 0x300B0 | |
| 24 | // SEC-NEXT: Address: 0x2200B0 | |
| 25 | 25 | |
| 26 | // page(0x300B0) - page(0x20004) = 65536 | |
| 26 | // page(0x2200B0) - page(0x20004) = 65536 | |
| 27 | 27 | // 0x0B0 = 176 |
| 28 | 28 | |
| 29 | 29 | // CHECK: _start: |
| 30 | // CHECK-NEXT: 20000: {{.*}} nop | |
| 31 | // CHECK-NEXT: 20004: {{.*}} adrp x0, #65536 | |
| 32 | // CHECK-NEXT: 20008: {{.*}} ldr x0, [x0, #176] | |
| 33 | // CHECK-NEXT: 2000c: {{.*}} nop | |
| 34 | // CHECK-NEXT: 20010: {{.*}} nop | |
| 30 | // CHECK-NEXT: 210000: {{.*}} nop | |
| 31 | // CHECK-NEXT: 210004: {{.*}} adrp x0, #65536 | |
| 32 | // CHECK-NEXT: 210008: {{.*}} ldr x0, [x0, #176] | |
| 33 | // CHECK-NEXT: 21000c: {{.*}} nop | |
| 34 | // CHECK-NEXT: 210010: {{.*}} nop |
deps/lld/test/ELF/aarch64-tls-gdle.s+6-6| ... | ... | @@ -5,17 +5,17 @@ |
| 5 | 5 | # RUN: llvm-objdump -d %tout | FileCheck %s |
| 6 | 6 | # RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s |
| 7 | 7 | |
| 8 | #Local-Dynamic to Initial-Exec relax creates no | |
| 8 | #Local-Dynamic to Local-Exec relax creates no | |
| 9 | 9 | #RELOC: Relocations [ |
| 10 | 10 | #RELOC-NEXT: ] |
| 11 | 11 | |
| 12 | # TCB size = 0x16 and foo is first element from TLS register. | |
| 12 | # TCB size = 64 and foo is first element from TLS register. | |
| 13 | 13 | # CHECK: Disassembly of section .text: |
| 14 | 14 | # CHECK: _start: |
| 15 | # CHECK: 20000:	00 00 a0 d2	movz	x0, #0, lsl #16 | |
| 16 | # CHECK: 20004:	00 02 80 f2 	movk	x0, #16 | |
| 17 | # CHECK: 20008:	1f 20 03 d5 	nop | |
| 18 | # CHECK: 2000c:	1f 20 03 d5 	nop | |
| 15 | # CHECK: 210000:	00 00 a0 d2	movz	x0, #0, lsl #16 | |
| 16 | # CHECK: 210004:	00 08 80 f2 	movk	x0, #64 | |
| 17 | # CHECK: 210008:	1f 20 03 d5 	nop | |
| 18 | # CHECK: 21000c:	1f 20 03 d5 	nop | |
| 19 | 19 | |
| 20 | 20 | .globl _start |
| 21 | 21 | _start: |
deps/lld/test/ELF/aarch64-tls-ie.s+11-11| ... | ... | @@ -15,7 +15,7 @@ |
| 15 | 15 | #RELOC-NEXT: SHF_ALLOC |
| 16 | 16 | #RELOC-NEXT: SHF_WRITE |
| 17 | 17 | #RELOC-NEXT: ] |
| 18 | #RELOC-NEXT: Address: 0x300B0 | |
| 18 | #RELOC-NEXT: Address: 0x2200B0 | |
| 19 | 19 | #RELOC-NEXT: Offset: 0x200B0 |
| 20 | 20 | #RELOC-NEXT: Size: 16 |
| 21 | 21 | #RELOC-NEXT: Link: 0 |
| ... | ... | @@ -25,21 +25,21 @@ |
| 25 | 25 | #RELOC-NEXT: } |
| 26 | 26 | #RELOC: Relocations [ |
| 27 | 27 | #RELOC-NEXT: Section ({{.*}}) .rela.dyn { |
| 28 | #RELOC-NEXT: 0x300B8 R_AARCH64_TLS_TPREL64 bar 0x0 | |
| 29 | #RELOC-NEXT: 0x300B0 R_AARCH64_TLS_TPREL64 foo 0x0 | |
| 28 | #RELOC-NEXT: 0x2200B8 R_AARCH64_TLS_TPREL64 bar 0x0 | |
| 29 | #RELOC-NEXT: 0x2200B0 R_AARCH64_TLS_TPREL64 foo 0x0 | |
| 30 | 30 | #RELOC-NEXT: } |
| 31 | 31 | #RELOC-NEXT:] |
| 32 | 32 | |
| 33 | # Page(0x300B0) - Page(0x20000) = 0x10000 = 65536 | |
| 34 | # 0x300B0 & 0xff8 = 0xB0 = 176 | |
| 35 | # Page(0x300B8) - Page(0x20000) = 0x10000 = 65536 | |
| 36 | # 0x300B8 & 0xff8 = 0xB8 = 184 | |
| 33 | # Page(0x2200B0) - Page(0x210000) = 0x10000 = 65536 | |
| 34 | # 0x2200B0 & 0xff8 = 0xB0 = 176 | |
| 35 | # Page(0x2200B8) - Page(0x210000) = 0x10000 = 65536 | |
| 36 | # 0x2200B8 & 0xff8 = 0xB8 = 184 | |
| 37 | 37 | #CHECK: Disassembly of section .text: |
| 38 | 38 | #CHECK: _start: |
| 39 | #CHECK: 20000: 80 00 00 90 adrp x0, #65536 | |
| 40 | #CHECK: 20004: 00 58 40 f9 ldr x0, [x0, #176] | |
| 41 | #CHECK: 20008: 80 00 00 90 adrp x0, #65536 | |
| 42 | #CHECK: 2000c: 00 5c 40 f9 ldr x0, [x0, #184] | |
| 39 | #CHECK: 210000: 80 00 00 90 adrp x0, #65536 | |
| 40 | #CHECK: 210004: 00 58 40 f9 ldr x0, [x0, #176] | |
| 41 | #CHECK: 210008: 80 00 00 90 adrp x0, #65536 | |
| 42 | #CHECK: 21000c: 00 5c 40 f9 ldr x0, [x0, #184] | |
| 43 | 43 | |
| 44 | 44 | .globl _start |
| 45 | 45 | _start: |
deps/lld/test/ELF/aarch64-tls-iele.s+5-5| ... | ... | @@ -9,13 +9,13 @@ |
| 9 | 9 | # RELOC: Relocations [ |
| 10 | 10 | # RELOC-NEXT: ] |
| 11 | 11 | |
| 12 | # TCB size = 0x16 and foo is first element from TLS register. | |
| 12 | # TCB size = 64 and foo is first element from TLS register. | |
| 13 | 13 | # CHECK: Disassembly of section .text: |
| 14 | 14 | # CHECK: _start: |
| 15 | # CHECK-NEXT: 20000: 00 00 a0 d2 movz x0, #0, lsl #16 | |
| 16 | # CHECK-NEXT: 20004: 80 02 80 f2 movk x0, #20 | |
| 17 | # CHECK-NEXT: 20008: 00 00 a0 d2 movz x0, #0, lsl #16 | |
| 18 | # CHECK-NEXT: 2000c: 00 02 80 f2 movk x0, #16 | |
| 15 | # CHECK-NEXT: 210000: 00 00 a0 d2 movz x0, #0, lsl #16 | |
| 16 | # CHECK-NEXT: 210004: 80 08 80 f2 movk x0, #68 | |
| 17 | # CHECK-NEXT: 210008: 00 00 a0 d2 movz x0, #0, lsl #16 | |
| 18 | # CHECK-NEXT: 21000c: 00 08 80 f2 movk x0, #64 | |
| 19 | 19 | |
| 20 | 20 | .section .tdata |
| 21 | 21 | .align 2 |
deps/lld/test/ELF/aarch64-tls-le.s+23-6| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | # RUN: llvm-objdump -d %tout | FileCheck %s |
| 5 | 5 | # RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s |
| 6 | 6 | |
| 7 | #Local-Dynamic to Initial-Exec relax creates no | |
| 7 | #Local-Dynamic to Local-Exec relax creates no | |
| 8 | 8 | #RELOC: Relocations [ |
| 9 | 9 | #RELOC-NEXT: ] |
| 10 | 10 | |
| ... | ... | @@ -13,19 +13,36 @@ _start: |
| 13 | 13 | mrs x0, TPIDR_EL0 |
| 14 | 14 | add x0, x0, :tprel_hi12:v1 |
| 15 | 15 | add x0, x0, :tprel_lo12_nc:v1 |
| 16 | mrs x0, TPIDR_EL0 | |
| 17 | add x0, x0, :tprel_hi12:v2 | |
| 18 | add x0, x0, :tprel_lo12_nc:v2 | |
| 16 | 19 | |
| 17 | # TCB size = 0x16 and foo is first element from TLS register. | |
| 20 | # TCB size = 64 and foo is first element from TLS register. | |
| 18 | 21 | #CHECK: Disassembly of section .text: |
| 19 | 22 | #CHECK: _start: |
| 20 | #CHECK: 20000: 40 d0 3b d5 mrs x0, TPIDR_EL0 | |
| 21 | #CHECK: 20004: 00 00 40 91 add x0, x0, #0, lsl #12 | |
| 22 | #CHECK: 20008: 00 40 00 91 add x0, x0, #16 | |
| 23 | #CHECK: 210000: 40 d0 3b d5 mrs x0, TPIDR_EL0 | |
| 24 | #CHECK: 210004: 00 00 40 91 add x0, x0, #0, lsl #12 | |
| 25 | #CHECK: 210008: 00 00 01 91 add x0, x0, #64 | |
| 26 | #CHECK: 21000c: 40 d0 3b d5 mrs x0, TPIDR_EL0 | |
| 27 | #CHECK: 210010: 00 fc 7f 91 add x0, x0, #4095, lsl #12 | |
| 28 | #CHECK: 210014: 00 e0 3f 91 add x0, x0, #4088 | |
| 23 | 29 | |
| 24 | .type v1,@object | |
| 25 | 30 | .section .tbss,"awT",@nobits |
| 31 | ||
| 32 | .type v1,@object | |
| 26 | 33 | .globl v1 |
| 27 | 34 | .p2align 2 |
| 28 | 35 | v1: |
| 29 | 36 | .word 0 |
| 30 | 37 | .size v1, 4 |
| 31 | 38 | |
| 39 | # The current offset from the thread pointer is 68. Raise it to just below the | |
| 40 | # 24-bit limit. | |
| 41 | .space (0xfffff8 - 68) | |
| 42 | ||
| 43 | .type v2,@object | |
| 44 | .globl v2 | |
| 45 | .p2align 2 | |
| 46 | v2: | |
| 47 | .word 0 | |
| 48 | .size v2, 4 |
deps/lld/test/ELF/aarch64-tlsld-ldst.s+26-26| ... | ... | @@ -25,28 +25,28 @@ _start: mrs x8, TPIDR_EL0 |
| 25 | 25 | ldrb w0, [x8, :tprel_lo12_nc:var4] |
| 26 | 26 | |
| 27 | 27 | // CHECK: _start: |
| 28 | // CHECK-NEXT: 20000: 48 d0 3b d5 mrs x8, TPIDR_EL0 | |
| 29 | // 0x0 + c10 = 0xc10 = tcb (16-bytes) + var0 | |
| 30 | // CHECK-NEXT: 20004: 08 01 40 91 add x8, x8, #0, lsl #12 | |
| 31 | // CHECK-NEXT: 20008: 14 05 c3 3d ldr q20, [x8, #3088] | |
| 32 | // 0x1000 + 0x820 = 0x1820 = tcb + var1 | |
| 33 | // CHECK-NEXT: 2000c: 08 05 40 91 add x8, x8, #1, lsl #12 | |
| 34 | // CHECK-NEXT: 20010: 00 11 44 f9 ldr x0, [x8, #2080] | |
| 35 | // 0x2000 + 0x428 = 0x2428 = tcb + var2 | |
| 36 | // CHECK-NEXT: 20014: 08 09 40 91 add x8, x8, #2, lsl #12 | |
| 37 | // CHECK-NEXT: 20018: 00 29 44 b9 ldr w0, [x8, #1064] | |
| 38 | // 0x3000 + 0x2c = 0x302c = tcb + var3 | |
| 39 | // CHECK-NEXT: 2001c: 08 0d 40 91 add x8, x8, #3, lsl #12 | |
| 40 | // CHECK-NEXT: 20020: 00 59 40 79 ldrh w0, [x8, #44] | |
| 41 | // 0x3000 + 0xc2e = 0x32ce = tcb + var4 | |
| 42 | // CHECK-NEXT: 20024: 08 0d 40 91 add x8, x8, #3, lsl #12 | |
| 43 | // CHECK-NEXT: 20028: 00 b9 70 39 ldrb w0, [x8, #3118] | |
| 28 | // CHECK-NEXT: 210000: 48 d0 3b d5 mrs x8, TPIDR_EL0 | |
| 29 | // 0x0 + c40 = 0xc40 = tcb (64-bytes) + var0 | |
| 30 | // CHECK-NEXT: 210004: 08 01 40 91 add x8, x8, #0, lsl #12 | |
| 31 | // CHECK-NEXT: 210008: 14 11 c3 3d ldr q20, [x8, #3136] | |
| 32 | // 0x1000 + 0x850 = 0x1850 = tcb + var1 | |
| 33 | // CHECK-NEXT: 21000c: 08 05 40 91 add x8, x8, #1, lsl #12 | |
| 34 | // CHECK-NEXT: 210010: 00 29 44 f9 ldr x0, [x8, #2128] | |
| 35 | // 0x2000 + 0x458 = 0x2458 = tcb + var2 | |
| 36 | // CHECK-NEXT: 210014: 08 09 40 91 add x8, x8, #2, lsl #12 | |
| 37 | // CHECK-NEXT: 210018: 00 59 44 b9 ldr w0, [x8, #1112] | |
| 38 | // 0x3000 + 0x5c = 0x305c = tcb + var3 | |
| 39 | // CHECK-NEXT: 21001c: 08 0d 40 91 add x8, x8, #3, lsl #12 | |
| 40 | // CHECK-NEXT: 210020: 00 b9 40 79 ldrh w0, [x8, #92] | |
| 41 | // 0x3000 + 0xc5e = 0x3c5e = tcb + var4 | |
| 42 | // CHECK-NEXT: 210024: 08 0d 40 91 add x8, x8, #3, lsl #12 | |
| 43 | // CHECK-NEXT: 210028: 00 79 71 39 ldrb w0, [x8, #3166] | |
| 44 | 44 | |
| 45 | // CHECK-SYMS: 0000000000000c00 0 TLS GLOBAL DEFAULT 2 var0 | |
| 46 | // CHECK-SYMS-NEXT: 0000000000001810 4 TLS GLOBAL DEFAULT 2 var1 | |
| 47 | // CHECK-SYMS-NEXT: 0000000000002418 2 TLS GLOBAL DEFAULT 2 var2 | |
| 48 | // CHECK-SYMS-NEXT: 000000000000301c 1 TLS GLOBAL DEFAULT 2 var3 | |
| 49 | // CHECK-SYMS-NEXT: 0000000000003c1e 0 TLS GLOBAL DEFAULT 2 var4 | |
| 45 | // CHECK-SYMS: 0000000000000c00 16 TLS GLOBAL DEFAULT 2 var0 | |
| 46 | // CHECK-SYMS-NEXT: 0000000000001810 8 TLS GLOBAL DEFAULT 2 var1 | |
| 47 | // CHECK-SYMS-NEXT: 0000000000002418 4 TLS GLOBAL DEFAULT 2 var2 | |
| 48 | // CHECK-SYMS-NEXT: 000000000000301c 2 TLS GLOBAL DEFAULT 2 var3 | |
| 49 | // CHECK-SYMS-NEXT: 0000000000003c1e 1 TLS GLOBAL DEFAULT 2 var4 | |
| 50 | 50 | |
| 51 | 51 | .globl var0 |
| 52 | 52 | .globl var1 |
| ... | ... | @@ -59,12 +59,12 @@ _start: mrs x8, TPIDR_EL0 |
| 59 | 59 | .type var3,@object |
| 60 | 60 | |
| 61 | 61 | .section .tbss,"awT",@nobits |
| 62 | .balign 16 | |
| 62 | .balign 64 | |
| 63 | 63 | .space 1024 * 3 |
| 64 | 64 | var0: |
| 65 | 65 | .quad 0 |
| 66 | 66 | .quad 0 |
| 67 | .size var1, 16 | |
| 67 | .size var0, 16 | |
| 68 | 68 | .space 1024 * 3 |
| 69 | 69 | var1: |
| 70 | 70 | .quad 0 |
| ... | ... | @@ -72,14 +72,14 @@ var1: |
| 72 | 72 | .space 1024 * 3 |
| 73 | 73 | var2: |
| 74 | 74 | .word 0 |
| 75 | .size var1, 4 | |
| 75 | .size var2, 4 | |
| 76 | 76 | |
| 77 | 77 | .space 1024 * 3 |
| 78 | 78 | var3: |
| 79 | 79 | .hword 0 |
| 80 | .size var2, 2 | |
| 80 | .size var3, 2 | |
| 81 | 81 | .space 1024 * 3 |
| 82 | 82 | var4: |
| 83 | 83 | .byte 0 |
| 84 | .size var3, 1 | |
| 84 | .size var4, 1 | |
| 85 | 85 | .space 1024 * 3 |
deps/lld/test/ELF/aarch64-tstbr14-reloc.s+15-11| ... | ... | @@ -13,19 +13,19 @@ |
| 13 | 13 | # 0x11028 - 24 = 0x20010 |
| 14 | 14 | # CHECK: Disassembly of section .text: |
| 15 | 15 | # CHECK-NEXT: _foo: |
| 16 | # CHECK-NEXT: 20000: {{.*}} nop | |
| 17 | # CHECK-NEXT: 20004: {{.*}} nop | |
| 18 | # CHECK-NEXT: 20008: {{.*}} nop | |
| 19 | # CHECK-NEXT: 2000c: {{.*}} nop | |
| 16 | # CHECK-NEXT: 210000: {{.*}} nop | |
| 17 | # CHECK-NEXT: 210004: {{.*}} nop | |
| 18 | # CHECK-NEXT: 210008: {{.*}} nop | |
| 19 | # CHECK-NEXT: 21000c: {{.*}} nop | |
| 20 | 20 | # CHECK: _bar: |
| 21 | # CHECK-NEXT: 20010: {{.*}} nop | |
| 22 | # CHECK-NEXT: 20014: {{.*}} nop | |
| 23 | # CHECK-NEXT: 20018: {{.*}} nop | |
| 21 | # CHECK-NEXT: 210010: {{.*}} nop | |
| 22 | # CHECK-NEXT: 210014: {{.*}} nop | |
| 23 | # CHECK-NEXT: 210018: {{.*}} nop | |
| 24 | 24 | # CHECK: _start: |
| 25 | # CHECK-NEXT: 2001c: {{.*}} tbnz w3, #15, #-28 | |
| 26 | # CHECK-NEXT: 20020: {{.*}} tbnz w3, #15, #-16 | |
| 27 | # CHECK-NEXT: 20024: {{.*}} tbz x6, #45, #-36 | |
| 28 | # CHECK-NEXT: 20028: {{.*}} tbz x6, #45, #-24 | |
| 25 | # CHECK-NEXT: 21001c: {{.*}} tbnz w3, #15, #-28 | |
| 26 | # CHECK-NEXT: 210020: {{.*}} tbnz w3, #15, #-16 | |
| 27 | # CHECK-NEXT: 210024: {{.*}} tbz x6, #45, #-36 | |
| 28 | # CHECK-NEXT: 210028: {{.*}} tbz x6, #45, #-24 | |
| 29 | 29 | |
| 30 | 30 | #DSOREL: Section { |
| 31 | 31 | #DSOREL: Index: |
| ... | ... | @@ -79,10 +79,14 @@ |
| 79 | 79 | #DSO-NEXT: 10044: {{.*}} nop |
| 80 | 80 | #DSO-NEXT: 10048: {{.*}} nop |
| 81 | 81 | #DSO-NEXT: 1004c: {{.*}} nop |
| 82 | #DSO-EMPTY: | |
| 83 | #DSO-NEXT: _foo@plt: | |
| 82 | 84 | #DSO-NEXT: 10050: {{.*}} adrp x16, #65536 |
| 83 | 85 | #DSO-NEXT: 10054: {{.*}} ldr x17, [x16, #24] |
| 84 | 86 | #DSO-NEXT: 10058: {{.*}} add x16, x16, #24 |
| 85 | 87 | #DSO-NEXT: 1005c: {{.*}} br x17 |
| 88 | #DSO-EMPTY: | |
| 89 | #DSO-NEXT: _bar@plt: | |
| 86 | 90 | #DSO-NEXT: 10060: {{.*}} adrp x16, #65536 |
| 87 | 91 | #DSO-NEXT: 10064: {{.*}} ldr x17, [x16, #32] |
| 88 | 92 | #DSO-NEXT: 10068: {{.*}} add x16, x16, #32 |
deps/lld/test/ELF/aarch64-undefined-weak.s+12-12| ... | ... | @@ -34,16 +34,16 @@ _start: |
| 34 | 34 | ldr x8, target |
| 35 | 35 | |
| 36 | 36 | // CHECK: Disassembly of section .text: |
| 37 | // 131072 = 0x20000 | |
| 38 | // CHECK: 20000: {{.*}} b #4 | |
| 39 | // CHECK-NEXT: 20004: {{.*}} bl #4 | |
| 40 | // CHECK-NEXT: 20008: {{.*}} b.eq #4 | |
| 41 | // CHECK-NEXT: 2000c: {{.*}} cbz x1, #4 | |
| 42 | // CHECK-NEXT: 20010: {{.*}} adr x0, #0 | |
| 43 | // CHECK-NEXT: 20014: {{.*}} adrp x0, #-131072 | |
| 44 | // CHECK: 20018: {{.*}} .word 0x00000000 | |
| 45 | // CHECK-NEXT: 2001c: {{.*}} .word 0x00000000 | |
| 46 | // CHECK-NEXT: 20020: {{.*}} .word 0x00000000 | |
| 47 | // CHECK-NEXT: 20024: {{.*}} .short 0x0000 | |
| 37 | // 2162688 = 0x210000 | |
| 38 | // CHECK: 210000: {{.*}} b #4 | |
| 39 | // CHECK-NEXT: 210004: {{.*}} bl #4 | |
| 40 | // CHECK-NEXT: 210008: {{.*}} b.eq #4 | |
| 41 | // CHECK-NEXT: 21000c: {{.*}} cbz x1, #4 | |
| 42 | // CHECK-NEXT: 210010: {{.*}} adr x0, #0 | |
| 43 | // CHECK-NEXT: 210014: {{.*}} adrp x0, #0 | |
| 44 | // CHECK: 210018: {{.*}} .word 0x00000000 | |
| 45 | // CHECK-NEXT: 21001c: {{.*}} .word 0x00000000 | |
| 46 | // CHECK-NEXT: 210020: {{.*}} .word 0x00000000 | |
| 47 | // CHECK-NEXT: 210024: {{.*}} .short 0x0000 | |
| 48 | 48 | // CHECK: $x.2: |
| 49 | // CHECK-NEXT: 20026: {{.*}} ldr x8, #0 | |
| 49 | // CHECK-NEXT: 210026: {{.*}} ldr x8, #0 |
deps/lld/test/ELF/amdgpu-elf-flags-err.s+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | # REQUIRES: amdgpu |
| 2 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx802 -filetype=obj %S/Inputs/amdgpu-kernel-0.s -o %t-0.o | |
| 3 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -filetype=obj %S/Inputs/amdgpu-kernel-1.s -o %t-1.o | |
| 2 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx802 -mattr=-code-object-v3 -filetype=obj %S/Inputs/amdgpu-kernel-0.s -o %t-0.o | |
| 3 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -mattr=-code-object-v3 -filetype=obj %S/Inputs/amdgpu-kernel-1.s -o %t-1.o | |
| 4 | 4 | # RUN: not ld.lld -shared %t-0.o %t-1.o -o /dev/null 2>&1 | FileCheck %s |
| 5 | 5 | |
| 6 | 6 | # CHECK: error: incompatible e_flags: {{.*}}-1.o |
deps/lld/test/ELF/amdgpu-elf-flags.s+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | # REQUIRES: amdgpu |
| 2 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -filetype=obj %S/Inputs/amdgpu-kernel-0.s -o %t-0.o | |
| 3 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -filetype=obj %S/Inputs/amdgpu-kernel-1.s -o %t-1.o | |
| 2 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -mattr=-code-object-v3 -filetype=obj %S/Inputs/amdgpu-kernel-0.s -o %t-0.o | |
| 3 | # RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 -mattr=-code-object-v3 -filetype=obj %S/Inputs/amdgpu-kernel-1.s -o %t-1.o | |
| 4 | 4 | # RUN: ld.lld -shared %t-0.o %t-1.o -o %t.so |
| 5 | 5 | # RUN: llvm-readobj -file-headers %t.so | FileCheck %s |
| 6 | 6 |
deps/lld/test/ELF/amdgpu-kernels.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | # REQUIRES: amdgpu |
| 2 | # RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o | |
| 2 | # RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri -mattr=-code-object-v3 %s -o %t.o | |
| 3 | 3 | # RUN: ld.lld -shared %t.o -o %t |
| 4 | 4 | # RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s |
| 5 | 5 |
deps/lld/test/ELF/archive-fetch.s created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # We have a code in LLD that prevents fetching the same object from archive file twice. | |
| 4 | # This test triggers that code, without it we would fail to link output. | |
| 5 | ||
| 6 | # RUN: echo '.globl foo, bar; foo:' | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %tfoo.o | |
| 7 | # RUN: echo '.globl foo, bar; bar:' | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %tbar.o | |
| 8 | # RUN: rm -f %t.a | |
| 9 | # RUN: llvm-ar rcs %t.a %tfoo.o %tbar.o | |
| 10 | ||
| 11 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 12 | # RUN: ld.lld %t.a %t.o -o /dev/null | |
| 13 | ||
| 14 | _start: | |
| 15 | callq foo |
deps/lld/test/ELF/arm-bl-v6-inrange.s created+47| ... | ... | @@ -0,0 +1,47 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv6-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: echo "SECTIONS { \ | |
| 4 | // RUN: .callee1 0x100004 : { *(.callee_low) } \ | |
| 5 | // RUN: .caller 0x500000 : { *(.text) } \ | |
| 6 | // RUN: .callee2 0x900004 : { *(.callee_high) } } " > %t.script | |
| 7 | // RUN: ld.lld %t --script %t.script -o %t2 2>&1 | |
| 8 | // RUN: llvm-objdump -d -triple=thumbv6-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-THUMB %s | |
| 9 | // RUN: llvm-objdump -d -triple=armv6-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-ARM %s | |
| 10 | ||
| 11 | // On older Arm Architectures such as v5 and v6 the Thumb BL and BLX relocation | |
| 12 | // uses a slightly different encoding that has a lower range. These relocations | |
| 13 | // are at the extreme range of what is permitted. | |
| 14 | .thumb | |
| 15 | .text | |
| 16 | .syntax unified | |
| 17 | .cpu arm1176jzf-s | |
| 18 | .globl _start | |
| 19 | .type _start,%function | |
| 20 | _start: | |
| 21 | bl thumbfunc | |
| 22 | bl armfunc | |
| 23 | bx lr | |
| 24 | ||
| 25 | .section .callee_low, "ax", %progbits | |
| 26 | .globl thumbfunc | |
| 27 | .type thumbfunc, %function | |
| 28 | thumbfunc: | |
| 29 | bx lr | |
| 30 | // CHECK-THUMB: Disassembly of section .callee1: | |
| 31 | // CHECK-THUMB-NEXT: thumbfunc: | |
| 32 | // CHECK-THUMB-NEXT: 100004: 70 47 bx lr | |
| 33 | // CHECK-THUMB-NEXT: Disassembly of section .caller: | |
| 34 | // CHECK-THUMB-NEXT: _start: | |
| 35 | // CHECK-THUMB-NEXT: 500000: 00 f4 00 f8 bl #-4194304 | |
| 36 | // CHECK-THUMB-NEXT: 500004: ff f3 fe ef blx #4194300 | |
| 37 | // CHECK-THUMB-NEXT: 500008: 70 47 bx lr | |
| 38 | ||
| 39 | .arm | |
| 40 | .section .callee_high, "ax", %progbits | |
| 41 | .globl armfunc | |
| 42 | .type armfunc, %function | |
| 43 | armfunc: | |
| 44 | bx lr | |
| 45 | // CHECK-ARM: Disassembly of section .callee2: | |
| 46 | // CHECK-ARM-NEXT: armfunc: | |
| 47 | // CHECK-ARM-NEXT: 900004: 1e ff 2f e1 bx lr |
deps/lld/test/ELF/arm-bl-v6.s+23-10| ... | ... | @@ -1,22 +1,23 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: ld.lld %t -o /dev/null 2>&1 | FileCheck %s | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv6-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: ld.lld %t -o %t2 2>&1 | |
| 4 | // RUN: llvm-objdump -d -triple=armv6-none-linux-gnueabi -start-address=69632 -stop-address=69640 %t2 | FileCheck -check-prefix=CHECK-ARM1 %s | |
| 5 | // RUN: llvm-objdump -d -triple=thumbv6-none-linux-gnueabi %t2 -start-address=69640 -stop-address=69644 | FileCheck -check-prefix=CHECK-THUMB1 %s | |
| 6 | // RUN: llvm-objdump -d -triple=armv6-none-linux-gnueabi -start-address=2166796 -stop-address=2166804 %t2 | FileCheck -check-prefix=CHECK-ARM2 %s | |
| 7 | // RUN: llvm-objdump -d -triple=thumbv6-none-linux-gnueabi %t2 -start-address=6365184 -stop-address=6365186 | FileCheck -check-prefix=CHECK-THUMB2 %s | |
| 4 | 8 | |
| 5 | 9 | // On Arm v6 the range of a Thumb BL instruction is only 4 megabytes as the |
| 6 | 10 | // extended range encoding is not supported. The following example has a Thumb |
| 7 | 11 | // BL that is out of range on ARM v6 and requires a range extension thunk. |
| 8 | 12 | // As v6 does not support MOVT or MOVW instructions the Thunk must not |
| 9 | // use these instructions either. At present we don't support v6 so we give a | |
| 10 | // warning for unsupported features. | |
| 13 | // use these instructions either. | |
| 14 | ||
| 11 | 15 | |
| 12 | // CHECK: warning: lld uses extended branch encoding, no object with architecture supporting feature detected. | |
| 13 | // CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected. | |
| 14 | 16 | // ARM v6 supports blx so we shouldn't see the blx not supported warning. |
| 15 | 17 | // CHECK-NOT: warning: lld uses blx instruction, no object with architecture supporting feature detected. |
| 16 | 18 | .text |
| 17 | 19 | .syntax unified |
| 18 | 20 | .cpu arm1176jzf-s |
| 19 | .eabi_attribute 6, 6 @ Tag_CPU_arch | |
| 20 | 21 | .globl _start |
| 21 | 22 | .type _start,%function |
| 22 | 23 | .balign 0x1000 |
| ... | ... | @@ -24,6 +25,10 @@ _start: |
| 24 | 25 | bl thumbfunc |
| 25 | 26 | bx lr |
| 26 | 27 | |
| 28 | // CHECK-ARM1: Disassembly of section .text: | |
| 29 | // CHECK-ARM1-NEXT: _start: | |
| 30 | // CHECK-ARM1-NEXT: 11000: 00 00 00 fa blx #0 <thumbfunc> | |
| 31 | // CHECK-ARM1-NEXT: 11004: 1e ff 2f e1 bx lr | |
| 27 | 32 | .thumb |
| 28 | 33 | .section .text.2, "ax", %progbits |
| 29 | 34 | .globl thumbfunc |
| ... | ... | @@ -31,11 +36,17 @@ _start: |
| 31 | 36 | thumbfunc: |
| 32 | 37 | bl farthumbfunc |
| 33 | 38 | |
| 34 | // 6 Megabytes, enough to make farthumbfunc out of range of caller on a v6 | |
| 35 | // Arm, but not on a v7 Arm. | |
| 39 | // CHECK-THUMB1: thumbfunc: | |
| 40 | // CHECK-THUMB1-NEXT: 11008:	00 f2 00 e8 	blx	#2097152 | |
| 41 | // 6 Megabytes, enough to make farthumbfunc out of range of caller | |
| 42 | // on a v6 Arm, but not on a v7 Arm. | |
| 43 | ||
| 36 | 44 | .section .text.3, "ax", %progbits |
| 37 | 45 | .space 0x200000 |
| 38 | ||
| 46 | // CHECK-ARM2: __ARMv5ABSLongThunk_farthumbfunc: | |
| 47 | // CHECK-ARM2-NEXT: 21100c: 04 f0 1f e5 ldr pc, [pc, #-4] | |
| 48 | // CHECK-ARM2: $d: | |
| 49 | // CHECK-ARM2-NEXT: 211010: 01 20 61 00 .word 0x00612001 | |
| 39 | 50 | .section .text.4, "ax", %progbits |
| 40 | 51 | .space 0x200000 |
| 41 | 52 | |
| ... | ... | @@ -49,3 +60,5 @@ thumbfunc: |
| 49 | 60 | .type farthumbfunc,%function |
| 50 | 61 | farthumbfunc: |
| 51 | 62 | bx lr |
| 63 | // CHECK-THUMB2: farthumbfunc: | |
| 64 | // CHECK-THUMB2-NEXT: 612000: 70 47 bx lr |
deps/lld/test/ELF/arm-blx-v4t.s+2-5| ... | ... | @@ -1,19 +1,16 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=arm-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t -o /dev/null 2>&1 | FileCheck %s |
| 4 | 4 | |
| 5 | 5 | // On Arm v4t there is no blx instruction so all interworking must go via |
| 6 | 6 | // a thunk. At present we don't support v4t so we give a warning for unsupported |
| 7 | 7 | // features. |
| 8 | 8 | |
| 9 | // CHECK: warning: lld uses blx instruction, no object with architecture supporting feature detected. | |
| 10 | // CHECK-NEXT: warning: lld uses extended branch encoding, no object with architecture supporting feature detected. | |
| 11 | // CHECK-NEXT: warning: lld may use movt/movw, no object with architecture supporting feature detected. | |
| 9 | // CHECK: warning: lld uses blx instruction, no object with architecture supporting feature detected | |
| 12 | 10 | |
| 13 | 11 | .text |
| 14 | 12 | .syntax unified |
| 15 | 13 | .cpu arm7tdmi |
| 16 | .eabi_attribute 6, 2 @ Tag_CPU_arch | |
| 17 | 14 | .arm |
| 18 | 15 | .globl _start |
| 19 | 16 | .type _start,%function |
deps/lld/test/ELF/arm-branch-rangethunk.s+3-3| ... | ... | @@ -1,9 +1,9 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-arm-abs.s -o %tfar | |
| 4 | 4 | // RUN: ld.lld %t %tfar -o %t2 2>&1 |
| 5 | 5 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=SHORT %s |
| 6 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-long-arm-abs.s -o %tfarlong | |
| 6 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/far-long-arm-abs.s -o %tfarlong | |
| 7 | 7 | // RUN: ld.lld %t %tfarlong -o %t3 2>&1 |
| 8 | 8 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck --check-prefix=LONG %s |
| 9 | 9 | .syntax unified |
deps/lld/test/ELF/arm-branch-undef-weak-plt-thunk.s+2-2| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-shared.s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-shared.s -o %t | |
| 3 | 3 | // RUN: ld.lld %t --shared -o %t.so |
| 4 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2 | |
| 4 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2 | |
| 5 | 5 | // RUN: ld.lld %t2 %t.so -o %t3 |
| 6 | 6 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi -start-address=69632 -stop-address=69664 %t3 | FileCheck %s |
| 7 | 7 |
deps/lld/test/ELF/arm-combined-dynrel-ifunc.s created+49| ... | ... | @@ -0,0 +1,49 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-linux-gnueabihf %p/Inputs/arm-shared.s -o %t-lib.o | |
| 3 | // RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-linux-gnueabihf %s -o %t.o | |
| 4 | // RUN: ld.lld %t-lib.o --shared -o %t.so | |
| 5 | // RUN: echo "SECTIONS { \ | |
| 6 | // RUN: .text : { *(.text) } \ | |
| 7 | // RUN: .rela.dyn : { *(.rel.dyn) *(.rel.plt) } \ | |
| 8 | // RUN: } " > %t.script | |
| 9 | // RUN: ld.lld %t.o -o %t.axf %t.so --script %t.script | |
| 10 | // RUN: llvm-readobj --section-headers --dynamic-table %t.axf | FileCheck %s | |
| 11 | ||
| 12 | // The linker script above combines the .rela.dyn and .rela.plt into a single | |
| 13 | // table. ELF is clear that the DT_PLTRELSZ should match the subset of | |
| 14 | // relocations that is associated with the PLT. It is less clear about what | |
| 15 | // the value of DT_RELASZ should be. ELF implies that it should be the size | |
| 16 | // of the single table so that DT_RELASZ includes DT_PLTRELSZ. The loader in | |
| 17 | // glibc permits this as long as .rela.plt comes after .rela.dyn in the | |
| 18 | // combined table. In the ARM case irelative relocations do not count as PLT | |
| 19 | // relocs. | |
| 20 | ||
| 21 | .text | |
| 22 | .globl indirect | |
| 23 | .type indirect,%gnu_indirect_function | |
| 24 | indirect: | |
| 25 | bx lr | |
| 26 | ||
| 27 | .globl bar2 // from Inputs/arm-shared.s | |
| 28 | ||
| 29 | .text | |
| 30 | .globl _start | |
| 31 | .type _start,%function | |
| 32 | main: | |
| 33 | bl indirect | |
| 34 | bl bar2 | |
| 35 | .word indirect(got) | |
| 36 | .word bar2(got) | |
| 37 | bx lr | |
| 38 | ||
| 39 | // CHECK: Name: .rela.dyn | |
| 40 | // CHECK-NEXT: Type: SHT_REL | |
| 41 | // CHECK-NEXT: Flags [ | |
| 42 | // CHECK-NEXT: SHF_ALLOC | |
| 43 | // CHECK-NEXT: ] | |
| 44 | // CHECK-NEXT: Address: | |
| 45 | // CHECK-NEXT: Offset: | |
| 46 | // CHECK-NEXT: Size: 24 | |
| 47 | ||
| 48 | // CHECK: 0x00000012 RELSZ 24 (bytes) | |
| 49 | // CHECK: 0x00000002 PLTRELSZ 8 (bytes) |
deps/lld/test/ELF/arm-extreme-range-pi-thunk.s created+82| ... | ... | @@ -0,0 +1,82 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: echo "SECTIONS {" > %t.script | |
| 4 | // RUN: echo " .text_low 0x130 : { *(.text) }" >> %t.script | |
| 5 | // RUN: echo " .text_high 0xf0000000 : AT(0x1000) { *(.text_high) }" >> %t.script | |
| 6 | // RUN: echo " } " >> %t.script | |
| 7 | // RUN: ld.lld --script %t.script --pie --static %t -o %t2 2>&1 | |
| 8 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s | |
| 9 | ||
| 10 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t3 | |
| 11 | // RUN: ld.lld --script %t.script --pie %t3 -o %t4 2>&1 | |
| 12 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t4 | FileCheck -check-prefix=CHECK-THUMB %s | |
| 13 | ||
| 14 | // Check that we can create Arm and Thumb v7a Position Independent Thunks that | |
| 15 | // can span the address space without triggering overflow errors. We use an | |
| 16 | // AT(0x1000) for .text_high to avoid creating an almost 4Gb size file. | |
| 17 | .syntax unified | |
| 18 | .text | |
| 19 | .global _start | |
| 20 | .type _start, %function | |
| 21 | _start: | |
| 22 | bl high | |
| 23 | bx lr | |
| 24 | ||
| 25 | .section .text_high, "ax", %progbits | |
| 26 | .global high | |
| 27 | .type high, %function | |
| 28 | high: | |
| 29 | bl _start | |
| 30 | bx lr | |
| 31 | ||
| 32 | // ARMv7a instructions and relocations. | |
| 33 | ||
| 34 | // CHECK: Disassembly of section .text_low: | |
| 35 | // CHECK-NEXT: _start: | |
| 36 | // CHECK-NEXT: 130: 00 00 00 eb bl #0 <__ARMV7PILongThunk_high> | |
| 37 | // CHECK-NEXT: 134: 1e ff 2f e1 bx lr | |
| 38 | ||
| 39 | // CHECK: __ARMV7PILongThunk_high: | |
| 40 | // CHECK-NEXT: 138: b8 ce 0f e3 movw r12, #65208 | |
| 41 | // CHECK-NEXT: 13c: ff cf 4e e3 movt r12, #61439 | |
| 42 | // 0x140 + 0xEFFF0000 + 0x0000FEB8 + 8 = 0xf0000000 = high | |
| 43 | // CHECK-NEXT: 140: 0f c0 8c e0 add r12, r12, pc | |
| 44 | // CHECK-NEXT: 144: 1c ff 2f e1 bx r12 | |
| 45 | ||
| 46 | // CHECK: Disassembly of section .text_high: | |
| 47 | // CHECK-NEXT: high: | |
| 48 | // CHECK-NEXT: f0000000: 00 00 00 eb bl #0 <__ARMV7PILongThunk__start> | |
| 49 | // CHECK-NEXT: f0000004: 1e ff 2f e1 bx lr | |
| 50 | ||
| 51 | // CHECK: __ARMV7PILongThunk__start: | |
| 52 | // CHECK-NEXT: f0000008: 18 c1 00 e3 movw r12, #280 | |
| 53 | // CHECK-NEXT: f000000c: 00 c0 41 e3 movt r12, #4096 | |
| 54 | // 0xf0000010 + 0x10000000 + 0x0000118 + 8 = bits32(0x100000130),0x130 = _start | |
| 55 | // CHECK-NEXT: f0000010: 0f c0 8c e0 add r12, r12, pc | |
| 56 | // CHECK-NEXT: f0000014: 1c ff 2f e1 bx r12 | |
| 57 | ||
| 58 | // Thumbv7a instructions and relocations | |
| 59 | // CHECK-THUMB: Disassembly of section .text_low: | |
| 60 | // CHECK-THUMB-NEXT: _start: | |
| 61 | // CHECK-THUMB-NEXT: 130: 00 f0 02 f8 bl #4 | |
| 62 | // CHECK-THUMB-NEXT: 134: 70 47 bx lr | |
| 63 | // CHECK-THUMB-NEXT: 136: d4 d4 bmi #-88 | |
| 64 | ||
| 65 | // CHECK-THUMB: __ThumbV7PILongThunk_high: | |
| 66 | // CHECK-THUMB-NEXT: 138: 4f f6 bd 6c movw r12, #65213 | |
| 67 | // CHECK-THUMB-NEXT: 13c: ce f6 ff 7c movt r12, #61439 | |
| 68 | // 0x140 + 0xEFFF0000 + 0x0000FEBD + 4 = 0xf0000001 = high | |
| 69 | // CHECK-THUMB-NEXT: 140: fc 44 add r12, pc | |
| 70 | // CHECK-THUMB-NEXT: 142: 60 47 bx r12 | |
| 71 | ||
| 72 | // CHECK-THUMB: Disassembly of section .text_high: | |
| 73 | // CHECK-THUMB-NEXT: high: | |
| 74 | // CHECK-THUMB-NEXT: f0000000: 00 f0 02 f8 bl #4 | |
| 75 | // CHECK-THUMB-NEXT: f0000004: 70 47 bx lr | |
| 76 | ||
| 77 | // CHECK-THUMB: __ThumbV7PILongThunk__start: | |
| 78 | // CHECK-THUMB-NEXT: f0000008: 40 f2 1d 1c movw r12, #285 | |
| 79 | // CHECK-THUMB-NEXT: f000000c: c1 f2 00 0c movt r12, #4096 | |
| 80 | // 0xf0000010 + 0x10000000 + 0x000011d +4 = bits32(0x100000131),0x131 = _start | |
| 81 | // CHECK-THUMB-NEXT: f0000010: fc 44 add r12, pc | |
| 82 | // CHECK-THUMB-NEXT: f0000012: 60 47 bx r12 |
deps/lld/test/ELF/arm-force-pi-thunk.s created+87| ... | ... | @@ -0,0 +1,87 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: echo "SECTIONS { \ | |
| 4 | // RUN: . = SIZEOF_HEADERS; \ | |
| 5 | // RUN: .text_low : { *(.text_low) *(.text_low2) } \ | |
| 6 | // RUN: .text_high 0x2000000 : { *(.text_high) *(.text_high2) } \ | |
| 7 | // RUN: } " > %t.script | |
| 8 | // RUN: ld.lld --pic-veneer --script %t.script %t -o %t2 2>&1 | |
| 9 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 | FileCheck %s | |
| 10 | ||
| 11 | // Test that we can force generation of position independent thunks even when | |
| 12 | // inputs are not pic. | |
| 13 | ||
| 14 | .syntax unified | |
| 15 | .section .text_low, "ax", %progbits | |
| 16 | .thumb | |
| 17 | .globl _start | |
| 18 | _start: bx lr | |
| 19 | .globl low_target | |
| 20 | .type low_target, %function | |
| 21 | low_target: | |
| 22 | bl high_target | |
| 23 | bl high_target2 | |
| 24 | ||
| 25 | .section .text_low2, "ax", %progbits | |
| 26 | .thumb | |
| 27 | .globl low_target2 | |
| 28 | .type low_target2, %function | |
| 29 | low_target2: | |
| 30 | bl high_target | |
| 31 | bl high_target2 | |
| 32 | ||
| 33 | // CHECK: Disassembly of section .text_low: | |
| 34 | // CHECK-NEXT: _start: | |
| 35 | // CHECK-NEXT: 94: 70 47 bx lr | |
| 36 | // CHECK: low_target: | |
| 37 | // CHECK-NEXT: 96: 00 f0 03 f8 bl #6 | |
| 38 | // CHECK-NEXT: 9a: 00 f0 07 f8 bl #14 | |
| 39 | // CHECK-NEXT: 9e: d4 d4 bmi #-88 | |
| 40 | // CHECK: __ThumbV7PILongThunk_high_target: | |
| 41 | // CHECK-NEXT: a0: 4f f6 55 7c movw r12, #65365 | |
| 42 | // CHECK-NEXT: a4: c0 f2 ff 1c movt r12, #511 | |
| 43 | // CHECK-NEXT: a8: fc 44 add r12, pc | |
| 44 | // CHECK-NEXT: aa: 60 47 bx r12 | |
| 45 | // CHECK: __ThumbV7PILongThunk_high_target2: | |
| 46 | // CHECK-NEXT: ac: 4f f6 69 7c movw r12, #65385 | |
| 47 | // CHECK-NEXT: b0: c0 f2 ff 1c movt r12, #511 | |
| 48 | // CHECK-NEXT: b4: fc 44 add r12, pc | |
| 49 | // CHECK-NEXT: b6: 60 47 bx r12 | |
| 50 | // CHECK: low_target2: | |
| 51 | // CHECK-NEXT: b8: ff f7 f2 ff bl #-28 | |
| 52 | // CHECK-NEXT: bc: ff f7 f6 ff bl #-20 | |
| 53 | ||
| 54 | ||
| 55 | .section .text_high, "ax", %progbits | |
| 56 | .thumb | |
| 57 | .globl high_target | |
| 58 | .type high_target, %function | |
| 59 | high_target: | |
| 60 | bl low_target | |
| 61 | bl low_target2 | |
| 62 | ||
| 63 | .section .text_high2, "ax", %progbits | |
| 64 | .thumb | |
| 65 | .globl high_target2 | |
| 66 | .type high_target2, %function | |
| 67 | high_target2: | |
| 68 | bl low_target | |
| 69 | bl low_target2 | |
| 70 | ||
| 71 | // CHECK: Disassembly of section .text_high: | |
| 72 | // CHECK-NEXT: high_target: | |
| 73 | // CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4 | |
| 74 | // CHECK-NEXT: 2000004: 00 f0 06 f8 bl #12 | |
| 75 | // CHECK: __ThumbV7PILongThunk_low_target: | |
| 76 | // CHECK-NEXT: 2000008: 40 f2 83 0c movw r12, #131 | |
| 77 | // CHECK-NEXT: 200000c: cf f6 00 6c movt r12, #65024 | |
| 78 | // CHECK-NEXT: 2000010: fc 44 add r12, pc | |
| 79 | // CHECK-NEXT: 2000012: 60 47 bx r12 | |
| 80 | // CHECK: __ThumbV7PILongThunk_low_target2: | |
| 81 | // CHECK-NEXT: 2000014: 40 f2 99 0c movw r12, #153 | |
| 82 | // CHECK-NEXT: 2000018: cf f6 00 6c movt r12, #65024 | |
| 83 | // CHECK-NEXT: 200001c: fc 44 add r12, pc | |
| 84 | // CHECK-NEXT: 200001e: 60 47 bx r12 | |
| 85 | // CHECK: high_target2: | |
| 86 | // CHECK-NEXT: 2000020: ff f7 f2 ff bl #-28 | |
| 87 | // CHECK-NEXT: 2000024: ff f7 f6 ff bl #-20 |
deps/lld/test/ELF/arm-gnu-ifunc.s+4-1| ... | ... | @@ -35,6 +35,8 @@ _start: |
| 35 | 35 | // CHECK-NEXT: Address: 0x100F4 |
| 36 | 36 | // CHECK-NEXT: Offset: 0xF4 |
| 37 | 37 | // CHECK-NEXT: Size: 16 |
| 38 | // CHECK-NEXT: Link: | |
| 39 | // CHECK-NEXT: Info: 4 | |
| 38 | 40 | // CHECK: Name: .plt |
| 39 | 41 | // CHECK-NEXT: Type: SHT_PROGBITS |
| 40 | 42 | // CHECK-NEXT: Flags [ |
| ... | ... | @@ -44,7 +46,8 @@ _start: |
| 44 | 46 | // CHECK-NEXT: Address: 0x11020 |
| 45 | 47 | // CHECK-NEXT: Offset: 0x1020 |
| 46 | 48 | // CHECK-NEXT: Size: 32 |
| 47 | // CHECK: Name: .got | |
| 49 | // CHECK: Index: 4 | |
| 50 | // CHECK-NEXT: Name: .got | |
| 48 | 51 | // CHECK-NEXT: Type: SHT_PROGBITS |
| 49 | 52 | // CHECK-NEXT: Flags [ |
| 50 | 53 | // CHECK-NEXT: SHF_ALLOC |
deps/lld/test/ELF/arm-long-thunk-converge.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -triple armv7-unknown-gnu -filetype=obj -o %t %s | |
| 2 | // RUN: llvm-mc -triple armv7-unknown-gnu -arm-add-build-attributes -filetype=obj -o %t %s | |
| 3 | 3 | // RUN: ld.lld %t %S/Inputs/arm-long-thunk-converge.lds -o %t2 |
| 4 | 4 | // RUN: llvm-objdump -d -start-address=0x00000000 -stop-address=0x00000010 -triple=armv7a-linux-gnueabihf %t2 | FileCheck --check-prefix=CHECK1 %s |
| 5 | 5 | // RUN: llvm-objdump -d -start-address=0x02000000 -stop-address=0x02000010 -triple=armv7a-linux-gnueabihf %t2 | FileCheck --check-prefix=CHECK2 %s |
deps/lld/test/ELF/arm-thumb-branch-rangethunk.s+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar | |
| 4 | 4 | // RUN: ld.lld %t %tfar -o %t2 2>&1 |
| 5 | 5 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t2 |
| 6 | 6 | .syntax unified |
deps/lld/test/ELF/arm-thumb-branch.s+2-2| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %S/Inputs/far-arm-thumb-abs.s -o %tfar | |
| 4 | 4 | // RUN: echo "SECTIONS { \ |
| 5 | 5 | // RUN: . = 0xb4; \ |
| 6 | 6 | // RUN: .callee1 : { *(.callee_low) } \ |
deps/lld/test/ELF/arm-thumb-condbranch-thunk.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t -o %t2 2>&1 |
| 4 | 4 | // The output file is large, most of it zeroes. We dissassemble only the |
| 5 | 5 | // parts we need to speed up the test and avoid a large output file |
deps/lld/test/ELF/arm-thumb-interwork-shared.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t --shared -o %t.so |
| 4 | 4 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t.so | FileCheck %s |
| 5 | 5 | // RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s -check-prefix=PLT |
deps/lld/test/ELF/arm-thumb-interwork-thunk-range.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | |
| 3 | 3 | // RUN: ld.lld %t.o -o /dev/null -image-base=0x80000000 |
| 4 | 4 | |
| 5 | 5 | // Test that when the thunk is at a high address we don't get confused with it |
deps/lld/test/ELF/arm-thumb-interwork-thunk-v5.s created+66| ... | ... | @@ -0,0 +1,66 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv5-none-linux-gnueabi %s -o %t | |
| 3 | // RUN: ld.lld %t -o %t2 | |
| 4 | // RUN: llvm-objdump -d %t2 -triple=armv5-none-linux-gnueabi | FileCheck -check-prefix=CHECK-ARM %s | |
| 5 | // RUN: llvm-objdump -d %t2 -triple=thumbv5-none-linux-gnueabi | FileCheck -check-prefix=CHECK-THUMB %s | |
| 6 | // RUN: ld.lld %t -o %t3 --shared | |
| 7 | // RUN: llvm-objdump -d %t3 -triple=armv5-none-linux-gnueabi | FileCheck -check-prefix=CHECK-ARM-PI %s | |
| 8 | // RUN: llvm-objdump -d %t3 -triple=thumbv5-none-linux-gnueabi | FileCheck -check-prefix=CHECK-THUMB-PI %s | |
| 9 | ||
| 10 | // Test ARM Thumb Interworking on older Arm architectures using Thunks that do | |
| 11 | // not use MOVT/MOVW instructions. | |
| 12 | // For pure interworking (not considering range extension) there is only the | |
| 13 | // case of an Arm B to a Thumb Symbol to consider as in older Arm architectures | |
| 14 | // there is no Thumb B.w that we can intercept with a Thunk and we still assume | |
| 15 | // support for the blx instruction for Thumb BL and BLX to an Arm symbol. | |
| 16 | .arm | |
| 17 | .text | |
| 18 | .syntax unified | |
| 19 | .cpu arm10tdmi | |
| 20 | ||
| 21 | .text | |
| 22 | .globl _start | |
| 23 | .type _start, %function | |
| 24 | .balign 0x1000 | |
| 25 | _start: | |
| 26 | b thumb_func | |
| 27 | bl thumb_func | |
| 28 | blx thumb_func | |
| 29 | bx lr | |
| 30 | ||
| 31 | // CHECK-ARM: _start: | |
| 32 | // CHECK-ARM-NEXT: 11000: 03 00 00 ea b #12 <__ARMv5ABSLongThunk_thumb_func> | |
| 33 | // CHECK-ARM-NEXT: 11004: 01 00 00 fa blx #4 <thumb_func> | |
| 34 | // CHECK-ARM-NEXT: 11008: 00 00 00 fa blx #0 <thumb_func> | |
| 35 | // CHECK-ARM-NEXT: 1100c: 1e ff 2f e1 bx lr | |
| 36 | ||
| 37 | // CHECK-THUMB: thumb_func: | |
| 38 | // CHECK-THUMB-NEXT: 11010: 70 47 bx lr | |
| 39 | ||
| 40 | // CHECK-ARM: __ARMv5ABSLongThunk_thumb_func: | |
| 41 | // CHECK-ARM-NEXT: 11014: 04 f0 1f e5 ldr pc, [pc, #-4] | |
| 42 | // CHECK-ARM: $d: | |
| 43 | // CHECK-ARM-NEXT: 11018: 11 10 01 00 .word 0x00011011 | |
| 44 | ||
| 45 | // CHECK-ARM-PI: _start: | |
| 46 | // CHECK-ARM-PI-NEXT: 1000: 03 00 00 ea b #12 <__ARMV5PILongThunk_thumb_func> | |
| 47 | // CHECK-ARM-PI-NEXT: 1004: 01 00 00 fa blx #4 <thumb_func> | |
| 48 | // CHECK-ARM-PI-NEXT: 1008: 00 00 00 fa blx #0 <thumb_func> | |
| 49 | // CHECK-ARM-PI-NEXT: 100c: 1e ff 2f e1 bx lr | |
| 50 | ||
| 51 | // CHECK-THUMB-PI: thumb_func: | |
| 52 | // CHECK-THUMB-PI-NEXT: 1010: 70 47 bx lr | |
| 53 | ||
| 54 | // CHECK-ARM-PI: __ARMV5PILongThunk_thumb_func: | |
| 55 | // CHECK-ARM-PI-NEXT: 1014: 04 c0 9f e5 ldr r12, [pc, #4] | |
| 56 | // CHECK-ARM-PI-NEXT: 1018: 0c c0 8f e0 add r12, pc, r12 | |
| 57 | // CHECK-ARM-PI-NEXT: 101c: 1c ff 2f e1 bx r12 | |
| 58 | // CHECK-ARM-PI: $d: | |
| 59 | // CHECK-ARM-PI-NEXT: 1020: f1 ff ff ff .word 0xfffffff1 | |
| 60 | ||
| 61 | .section .text.1, "ax", %progbits | |
| 62 | .thumb | |
| 63 | .hidden thumb_func | |
| 64 | .type thumb_func, %function | |
| 65 | thumb_func: | |
| 66 | bx lr |
deps/lld/test/ELF/arm-thumb-interwork-thunk.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: echo "SECTIONS { \ |
| 4 | 4 | // RUN: . = SIZEOF_HEADERS; \ |
| 5 | 5 | // RUN: .R_ARM_JUMP24_callee_1 : { *(.R_ARM_JUMP24_callee_low) } \ |
deps/lld/test/ELF/arm-thumb-mix-range-thunk-os.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t -o %t2 2>&1 |
| 4 | 4 | // The output file is large, most of it zeroes. We dissassemble only the |
| 5 | 5 | // parts we need to speed up the test and avoid a large output file |
deps/lld/test/ELF/arm-thumb-plt-range-thunk-os.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t --shared --icf=all -o %t.so |
| 4 | 4 | // The output file is large, most of it zeroes. We dissassemble only the |
| 5 | 5 | // parts we need to speed up the test and avoid a large output file |
deps/lld/test/ELF/arm-thumb-range-thunk-os.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t -o %t2 2>&1 |
| 4 | 4 | // The output file is large, most of it zeroes. We dissassemble only the |
| 5 | 5 | // parts we need to speed up the test and avoid a large output file |
deps/lld/test/ELF/arm-thumb-thunk-empty-pass.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t -o %t2 2>&1 |
| 4 | 4 | // RUN: llvm-objdump -d %t2 -start-address=69632 -stop-address=69646 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK1 %s |
| 5 | 5 | // RUN: llvm-objdump -d %t2 -start-address=16846856 -stop-address=16846874 -triple=thumbv7a-linux-gnueabihf | FileCheck -check-prefix=CHECK2 %s |
deps/lld/test/ELF/arm-thumb-thunk-symbols.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t -o %t2 2>&1 |
| 4 | 4 | // RUN: llvm-readobj --symbols %t2 | FileCheck %s |
| 5 | 5 | // RUN: ld.lld --shared %t -o %t3 2>&1 |
deps/lld/test/ELF/arm-thumb-thunk-v6m.s created+61| ... | ... | @@ -0,0 +1,61 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv6m-none-eabi %s -o %t | |
| 3 | // RUN: echo "SECTIONS { \ | |
| 4 | // RUN: . = SIZEOF_HEADERS; \ | |
| 5 | // RUN: .text_low : { *(.text_low) *(.text_low2) } \ | |
| 6 | // RUN: .text_high 0x2000000 : { *(.text_high) *(.text_high2) } \ | |
| 7 | // RUN: } " > %t.script | |
| 8 | // RUN: ld.lld --script %t.script %t -o %t2 | |
| 9 | // RUN: llvm-objdump -d %t2 -triple=armv6m-none-eabi | FileCheck %s | |
| 10 | // RUN: ld.lld --script %t.script %t -o %t3 --pie | |
| 11 | // RUN: llvm-objdump -d %t3 -triple=armv6m-none-eabi | FileCheck -check-prefix=CHECK-PI %s | |
| 12 | ||
| 13 | // Range extension thunks for Arm Architecture v6m. Only Thumb instructions | |
| 14 | // are permitted which limits the access to instructions that can access the | |
| 15 | // high registers (r8 - r15), this means that the thunks have to spill | |
| 16 | // low registers (r0 - r7) in order to perform the transfer of control. | |
| 17 | ||
| 18 | .syntax unified | |
| 19 | .section .text_low, "ax", %progbits | |
| 20 | .thumb | |
| 21 | .type _start, %function | |
| 22 | .balign 4 | |
| 23 | .globl _start | |
| 24 | _start: | |
| 25 | bl far | |
| 26 | ||
| 27 | .section .text_high, "ax", %progbits | |
| 28 | .globl far | |
| 29 | .type far, %function | |
| 30 | far: | |
| 31 | bx lr | |
| 32 | ||
| 33 | // CHECK: Disassembly of section .text_low: | |
| 34 | // CHECK-NEXT: _start: | |
| 35 | // CHECK-NEXT: 94: 00 f0 00 f8 bl #0 | |
| 36 | // CHECK: __Thumbv6MABSLongThunk_far: | |
| 37 | // CHECK-NEXT: 98: 03 b4 push {r0, r1} | |
| 38 | // CHECK-NEXT: 9a: 01 48 ldr r0, [pc, #4] | |
| 39 | // CHECK-NEXT: 9c: 01 90 str r0, [sp, #4] | |
| 40 | // CHECK-NEXT: 9e: 01 bd pop {r0, pc} | |
| 41 | // CHECK: a0: 01 00 00 02 .word 0x02000001 | |
| 42 | // CHECK: Disassembly of section .text_high: | |
| 43 | // CHECK-NEXT: far: | |
| 44 | // CHECK-NEXT: 2000000: 70 47 bx lr | |
| 45 | ||
| 46 | // CHECK-PI: Disassembly of section .text_low: | |
| 47 | // CHECK-PI-NEXT: _start: | |
| 48 | // CHECK-PI-NEXT: 130: 00 f0 00 f8 bl #0 | |
| 49 | // CHECK-PI: __Thumbv6MPILongThunk_far: | |
| 50 | // CHECK-PI-NEXT: 134: 01 b4 push {r0} | |
| 51 | // CHECK-PI-NEXT: 136: 02 48 ldr r0, [pc, #8] | |
| 52 | // CHECK-PI-NEXT: 138: 84 46 mov r12, r0 | |
| 53 | // CHECK-PI-NEXT: 13a: 01 bc pop {r0} | |
| 54 | // pc = pc (0x13c + 4) + r12 (1fffec1) = 0x2000001 = .far | |
| 55 | // CHECK-PI-NEXT: 13c: e7 44 add pc, r12 | |
| 56 | // CHECK-PI-NEXT: 13e: c0 46 mov r8, r8 | |
| 57 | // CHECK-PI: 140: c1 fe ff 01 .word 0x01fffec1 | |
| 58 | ||
| 59 | // CHECK-PI: Disassembly of section .text_high: | |
| 60 | // CHECK-PI-NEXT: far: | |
| 61 | // CHECK-PI-NEXT: 2000000: 70 47 bx lr |
deps/lld/test/ELF/arm-thumb-undefined-weak-narrow.test created+50| ... | ... | @@ -0,0 +1,50 @@ |
| 1 | # REQUIRES: arm | |
| 2 | # RUN: yaml2obj %s -o %t.o | |
| 3 | # RUN: ld.lld %t.o -o %t | |
| 4 | # RUN: llvm-objdump -triple=thumbv7a-linux-gnueabi -d %t | FileCheck %s | |
| 5 | ||
| 6 | # CHECK: Disassembly of section .text: | |
| 7 | # CHECK-NEXT:_start: | |
| 8 | # CHECK-NEXT: 11000: ff e7 b #-2 | |
| 9 | ||
| 10 | # Test the R_ARM_THM_JUMP11 relocation (102) to an undefined weak reference | |
| 11 | # It should resolve to the next instruction, which is an offset of -2 which | |
| 12 | # when added to the Thumb PC-bias of 4 is +2. We can't use llvm-mc to construct | |
| 13 | # the object as it relaxes b.n to b.w (R_ARM_JUMP24). | |
| 14 | ||
| 15 | !ELF | |
| 16 | FileHeader: | |
| 17 | Class: ELFCLASS32 | |
| 18 | Data: ELFDATA2LSB | |
| 19 | Type: ET_REL | |
| 20 | Machine: EM_ARM | |
| 21 | Sections: | |
| 22 | - Type: SHT_PROGBITS | |
| 23 | Name: .text | |
| 24 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 25 | Content: "fee7" | |
| 26 | - Type: SHT_REL | |
| 27 | Name: .rel.text | |
| 28 | Link: .symtab | |
| 29 | Info: .text | |
| 30 | Relocations: | |
| 31 | - Offset: 0 | |
| 32 | Symbol: undefined_weak | |
| 33 | Type: R_ARM_THM_JUMP11 | |
| 34 | ||
| 35 | Symbols: | |
| 36 | Global: | |
| 37 | - Type: STT_FUNC | |
| 38 | Name: _start | |
| 39 | Value: 1 | |
| 40 | Section: .text | |
| 41 | Local: | |
| 42 | - Type: STT_NOTYPE | |
| 43 | Name: "$t" | |
| 44 | Section: .text | |
| 45 | Value: 0 | |
| 46 | Weak: | |
| 47 | - Type: STT_NOTYPE | |
| 48 | Name: undefined_weak | |
| 49 | Value: 0 | |
| 50 |
deps/lld/test/ELF/arm-thunk-edgecase.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o | |
| 3 | 3 | // RUN: echo "SECTIONS { \ |
| 4 | 4 | // RUN: .text_armfunc 0x1000 : { *(.text_armfunc) } \ |
| 5 | 5 | // RUN: .text_thumbfunc 0x11010 : { *(.text_thumbfunc) } \ |
deps/lld/test/ELF/arm-thunk-largesection.s+7-4| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t -o %t2 2>&1 |
| 4 | 4 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=69632 -stop-address=69636 %t2 | FileCheck -check-prefix=CHECK1 %s |
| 5 | 5 | // RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi -start-address=73732 -stop-address=73742 %t2 | FileCheck -check-prefix=CHECK2 %s |
| ... | ... | @@ -16,9 +16,12 @@ _start: |
| 16 | 16 | bx lr |
| 17 | 17 | .space 0x1000 |
| 18 | 18 | // CHECK1: Disassembly of section .text: |
| 19 | // CHECK1-NEXT: _start: | |
| 20 | // CHECK1-NEXT: 11000: 70 47 bx lr | |
| 21 | // CHECK1-NEXT: 11002: 00 00 movs r0, r0 | |
| 19 | // CHECK1-NEXT:_start: | |
| 20 | // CHECK1-NEXT: 11000: 70 47 bx lr | |
| 21 | // CHECK1-EMPTY: | |
| 22 | // CHECK-NEXT:$d.1: | |
| 23 | // CHECK-NEXT: 11002: 00 00 .short 0x0000 | |
| 24 | ||
| 22 | 25 | |
| 23 | 26 | // CHECK2: __Thumbv7ABSLongThunk__start: |
| 24 | 27 | // CHECK2-NEXT: 12004: fe f7 fc bf b.w #-4104 <_start> |
deps/lld/test/ELF/arm-thunk-linkerscript-dotexpr.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: echo "SECTIONS { \ |
| 4 | 4 | // RUN: . = SIZEOF_HEADERS; \ |
| 5 | 5 | // RUN: .text_low : { *(.text_low) *(.text_low2) . = . + 0x2000000 ; *(.text_high) *(.text_high2) } \ |
deps/lld/test/ELF/arm-thunk-linkerscript-large.s+3-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: echo "SECTIONS { \ |
| 4 | 4 | // RUN: .text 0x100000 : { *(.text) } \ |
| 5 | 5 | // RUN: .textl : { *(.text_l0*) *(.text_l1*) *(.text_l2*) *(.text_l3*) } \ |
| ... | ... | @@ -21,7 +21,8 @@ |
| 21 | 21 | // per OutputSection basis |
| 22 | 22 | .syntax unified |
| 23 | 23 | |
| 24 | // Define a function that we can match with .text_l* aligned on a megabyte // boundary | |
| 24 | // Define a function that we can match with .text_l* aligned on a megabyte | |
| 25 | // boundary | |
| 25 | 26 | .macro FUNCTIONL suff |
| 26 | 27 | .section .text_l\suff\(), "ax", %progbits |
| 27 | 28 | .thumb |
deps/lld/test/ELF/arm-thunk-linkerscript-orphan.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: echo "SECTIONS { \ |
| 4 | 4 | // RUN: .text_low 0x100000 : { *(.text_low) } \ |
| 5 | 5 | // RUN: .text_high 0x2000000 : { *(.text_high) } \ |
deps/lld/test/ELF/arm-thunk-linkerscript-sort.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: echo "SECTIONS { \ |
| 4 | 4 | // RUN: .text 0x100000 : { *(SORT_BY_NAME(.text.*)) } \ |
| 5 | 5 | // RUN: }" > %t.script |
deps/lld/test/ELF/arm-thunk-linkerscript.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: echo "SECTIONS { \ |
| 4 | 4 | // RUN: . = SIZEOF_HEADERS; \ |
| 5 | 5 | // RUN: .text_low : { *(.text_low) *(.text_low2) } \ |
deps/lld/test/ELF/arm-thunk-multipass.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t -o %t2 2>&1 |
| 4 | 4 | // The output file is large, most of it zeroes. We dissassemble only the |
| 5 | 5 | // parts we need to speed up the test and avoid a large output file |
deps/lld/test/ELF/arm-thunk-nosuitable.s+2-3| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | // REQUIRES: ARM | |
| 1 | // REQUIRES: arm | |
| 2 | 2 | // RUN: llvm-mc %s --arm-add-build-attributes --triple=armv7a-linux-gnueabihf --filetype=obj -o %t.o |
| 3 | 3 | // RUN: ld.lld %t.o -o %t |
| 4 | 4 | // RUN: llvm-objdump -triple=thumbv7a-linux-gnueabihf -d -start-address=2166784 -stop-address=2166794 %t | FileCheck %s |
| ... | ... | @@ -23,8 +23,7 @@ _start: |
| 23 | 23 | // CHECK-NEXT: 211000: 00 f0 00 80 beq.w #0 |
| 24 | 24 | // CHECK: __Thumbv7ABSLongThunk_target: |
| 25 | 25 | // CHECK-NEXT: 211004: 00 f0 01 90 b.w #12582914 |
| 26 | // CHECK: $t.1: | |
| 27 | // CHECK-NEXT: 211008: 70 47 bx lr | |
| 26 | // CHECK: 211008: 70 47 bx lr | |
| 28 | 27 | |
| 29 | 28 | .section .text.2, "ax", %progbits |
| 30 | 29 | .space 12 * 1024 * 1024 |
deps/lld/test/ELF/arm-thunk-re-add.s+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | // REQUIRES: arm |
| 2 | // RUN: llvm-mc -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 2 | // RUN: llvm-mc -arm-add-build-attributes -filetype=obj -triple=thumbv7a-none-linux-gnueabi %s -o %t | |
| 3 | 3 | // RUN: ld.lld %t --shared -o %t.so |
| 4 | 4 | // The output file is large, most of it zeroes. We dissassemble only the |
| 5 | 5 | // parts we need to speed up the test and avoid a large output file |
deps/lld/test/ELF/arm-thunk-section-too-large.s+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | // REQUIRES: ARM | |
| 1 | // REQUIRES: arm | |
| 2 | 2 | // RUN: llvm-mc %s -triple=armv7a-linux-gnueabihf -arm-add-build-attributes -filetype=obj -o %t.o |
| 3 | 3 | // RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s |
| 4 | 4 |
deps/lld/test/ELF/arm-tls-le32.s+6-6| ... | ... | @@ -69,9 +69,9 @@ x: |
| 69 | 69 | |
| 70 | 70 | // CHECK: Disassembly of section .text: |
| 71 | 71 | // CHECK-NEXT: _start: |
| 72 | // offset of x from Thread pointer = (TcbSize + 0x0 = 0x8) | |
| 73 | // CHECK-NEXT: 11000: 08 00 00 00 | |
| 74 | // offset of z from Thread pointer = (TcbSize + 0x8 = 0x10) | |
| 75 | // CHECK-NEXT: 11004: 10 00 00 00 | |
| 76 | // offset of y from Thread pointer = (TcbSize + 0x4 = 0xc) | |
| 77 | // CHECK-NEXT: 11008: 0c 00 00 00 | |
| 72 | // offset of x from Thread pointer = (TcbSize + 0x0 = 0x20) | |
| 73 | // CHECK-NEXT: 11000: 20 00 00 00 | |
| 74 | // offset of z from Thread pointer = (TcbSize + 0x8 = 0x28) | |
| 75 | // CHECK-NEXT: 11004: 28 00 00 00 | |
| 76 | // offset of y from Thread pointer = (TcbSize + 0x4 = 0x24) | |
| 77 | // CHECK-NEXT: 11008: 24 00 00 00 |
deps/lld/test/ELF/arm-tls-norelax-ie-le.s+2-2| ... | ... | @@ -37,5 +37,5 @@ x2: |
| 37 | 37 | .type x2, %object |
| 38 | 38 | |
| 39 | 39 | // CHECK: Contents of section .got: |
| 40 | // x1 at offset 8 from TP, x2 at offset c from TP. Offsets include TCB size of 8 | |
| 41 | // CHECK-NEXT: 13064 08000000 0c000000 | |
| 40 | // x1 at offset 0x20 from TP, x2 at offset 0x24 from TP. Offsets include TCB size of 0x20 | |
| 41 | // CHECK-NEXT: 13064 20000000 24000000 |
deps/lld/test/ELF/arm-v4bx.test created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | # REQUIRES: arm | |
| 2 | # RUN: yaml2obj %s -o %t.o | |
| 3 | # RUN: ld.lld %t.o -o %t | |
| 4 | # RUN: llvm-readelf -sections %t | FileCheck %s | |
| 5 | # RUN: ld.lld -shared %t.o -o %t | |
| 6 | # RUN: llvm-readelf -sections %t | FileCheck %s | |
| 7 | ||
| 8 | # CHECK: .text | |
| 9 | ||
| 10 | --- !ELF | |
| 11 | FileHeader: | |
| 12 | Class: ELFCLASS32 | |
| 13 | Data: ELFDATA2LSB | |
| 14 | Type: ET_REL | |
| 15 | Machine: EM_ARM | |
| 16 | Flags: [ EF_ARM_EABI_VER5 ] | |
| 17 | Sections: | |
| 18 | - Name: .text | |
| 19 | Type: SHT_PROGBITS | |
| 20 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 21 | AddressAlign: 0x0000000000000004 | |
| 22 | Content: 1EFF2F01 | |
| 23 | - Name: .rel.text | |
| 24 | Type: SHT_REL | |
| 25 | Link: .symtab | |
| 26 | AddressAlign: 0x0000000000000004 | |
| 27 | Info: .text | |
| 28 | Relocations: | |
| 29 | - Offset: 0x0000000000000000 | |
| 30 | Symbol: '' | |
| 31 | Type: R_ARM_V4BX | |
| 32 | Symbols: | |
| 33 | Global: | |
| 34 | - Name: _start | |
| 35 | Section: .text | |
| 36 | Local: | |
| 37 | - Name: .text | |
| 38 | Type: STT_SECTION | |
| 39 | Section: .text | |
| 40 | DynamicSymbols: |
deps/lld/test/ELF/arm-v5-reloc-error.s created+31| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | // REQUIRES: arm | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabi %s -o %t | |
| 3 | // RUN: echo "SECTIONS { \ | |
| 4 | // RUN: . = SIZEOF_HEADERS; \ | |
| 5 | // RUN: .text_low : { *(.text_low) *(.text_low2) } \ | |
| 6 | // RUN: .text_high 0x2000000 : { *(.text_high) *(.text_high2) } \ | |
| 7 | // RUN: } " > %t.script | |
| 8 | // RUN: not ld.lld --script %t.script %t -o %t2 2>&1 | FileCheck %s | |
| 9 | ||
| 10 | // CHECK: error: relocation R_ARM_THM_JUMP24 to far not supported for Armv5 or Armv6 targets | |
| 11 | ||
| 12 | // Lie about our build attributes. Our triple is armv7a-linux-gnueabi but | |
| 13 | // we are claiming to be Armv5. This can also happen with llvm-mc when we | |
| 14 | // don't have any .eabi_attribute directives in the file or the | |
| 15 | // --arm-add-build-attributes command line isn't used to add them from the | |
| 16 | // triple. | |
| 17 | .eabi_attribute 6, 5 // Tag_cpu_arch 5 = v5TEJ | |
| 18 | .thumb | |
| 19 | .syntax unified | |
| 20 | .section .text_low, "ax", %progbits | |
| 21 | .thumb | |
| 22 | .globl _start | |
| 23 | .type _start, %function | |
| 24 | _start: | |
| 25 | b.w far // Will produce relocation not supported in Armv5. | |
| 26 | ||
| 27 | .section .text_high, "ax", %progbits | |
| 28 | .globl far | |
| 29 | .type far, %function | |
| 30 | far: | |
| 31 | bx lr |
deps/lld/test/ELF/as-needed-in-regular.s created+24| ... | ... | @@ -0,0 +1,24 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo '.globl a; .type a, @function; .type a, @function; a: ret' | \ | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %ta.o | |
| 5 | # RUN: ld.lld %ta.o --shared --soname=a.so -o %ta.so | |
| 6 | ||
| 7 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 8 | # RUN: ld.lld %t.o --as-needed %ta.so -o %t | |
| 9 | # RUN: llvm-readelf -d %t | FileCheck %s | |
| 10 | # RUN: ld.lld %t.o --as-needed %ta.so --gc-sections -o %t | |
| 11 | # RUN: llvm-readelf -d %t | FileCheck %s | |
| 12 | ||
| 13 | # The order of %ta.so and %t.o does not matter. | |
| 14 | ||
| 15 | # RUN: ld.lld --as-needed %ta.so %t.o -o %t | |
| 16 | # RUN: llvm-readelf -d %t | FileCheck %s | |
| 17 | # RUN: ld.lld --as-needed %ta.so %t.o --gc-sections -o %t | |
| 18 | # RUN: llvm-readelf -d %t | FileCheck %s | |
| 19 | ||
| 20 | # CHECK: a.so | |
| 21 | ||
| 22 | .global _start | |
| 23 | _start: | |
| 24 | jmp a@PLT |
deps/lld/test/ELF/as-needed-not-in-regular.s created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo '.globl a1, a2; .type a1, @function; .type a2, @function; a1: a2: ret' | \ | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %ta.o | |
| 5 | # RUN: ld.lld %ta.o --shared --soname=a.so -o %ta.so | |
| 6 | ||
| 7 | # RUN: echo '.globl b; .type b, @function; b: jmp a1@PLT' | \ | |
| 8 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %tb.o | |
| 9 | # RUN: ld.lld %tb.o %ta.so --shared --soname=b.so -o %tb.so | |
| 10 | ||
| 11 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 12 | # RUN: ld.lld %t.o %tb.so --as-needed %ta.so -o %t | |
| 13 | # RUN: llvm-readelf -d %t | FileCheck %s | |
| 14 | ||
| 15 | # RUN: ld.lld %t.o %tb.so --as-needed %ta.so --gc-sections -o %t | |
| 16 | # RUN: llvm-readelf -d %t | FileCheck %s | |
| 17 | ||
| 18 | # The symbol a1 (defined in a.so) is not referenced by a regular object, | |
| 19 | # the reference to a2 is weak, don't add a DT_NEEDED entry for a.so. | |
| 20 | # CHECK-NOT: a.so | |
| 21 | ||
| 22 | # RUN: ld.lld %t.o %tb.so --as-needed %ta.so --no-as-needed %ta.so -o %t | |
| 23 | # RUN: llvm-readelf -d %t | FileCheck %s -check-prefix=NEEDED | |
| 24 | ||
| 25 | # a.so is needed because one of its occurrences is needed. | |
| 26 | # NEEDED: a.so | |
| 27 | ||
| 28 | .global _start | |
| 29 | .weak a2 | |
| 30 | _start: | |
| 31 | jmp b@PLT | |
| 32 | jmp a2 |
deps/lld/test/ELF/as-needed-weak.s+1-1| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | |
| 13 | 13 | # CHECK: Symbol table of .hash for image: |
| 14 | 14 | # CHECK-NEXT: Num Buc: Value Size Type Bind Vis Ndx Name |
| 15 | # CHECK-NEXT: 1 1: 0000000000000000 0 FUNC WEAK DEFAULT UND foo@ | |
| 15 | # CHECK-NEXT: 1 1: 0000000000000000 0 FUNC WEAK DEFAULT UND foo | |
| 16 | 16 | |
| 17 | 17 | .globl _start |
| 18 | 18 | .weak foo |
deps/lld/test/ELF/bad-reloc-target.test created+29| ... | ... | @@ -0,0 +1,29 @@ |
| 1 | # RUN: yaml2obj %s -o %t1.o | |
| 2 | # RUN: not ld.lld %t1.o -o %t1 2>&1 | FileCheck %s | |
| 3 | # CHECK: error: {{.*}}.o: unsupported relocation reference | |
| 4 | ||
| 5 | # RUN: yaml2obj %S/Inputs/bad-reloc-target.test -o %t2.o | |
| 6 | # RUN: not ld.lld %t2.o -o %t2 2>&1 | FileCheck %s --check-prefix=ERR2 | |
| 7 | # ERR2: error: {{.*}}.o: invalid relocated section index: 99 | |
| 8 | ||
| 9 | --- !ELF | |
| 10 | FileHeader: | |
| 11 | Class: ELFCLASS64 | |
| 12 | Data: ELFDATA2LSB | |
| 13 | Type: ET_REL | |
| 14 | Machine: EM_X86_64 | |
| 15 | Sections: | |
| 16 | - Name: .text | |
| 17 | Type: SHT_PROGBITS | |
| 18 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 19 | - Name: .rela.text | |
| 20 | Type: SHT_RELA | |
| 21 | Link: .symtab | |
| 22 | Info: 0 | |
| 23 | Relocations: | |
| 24 | - Offset: 0x0000000000000000 | |
| 25 | Symbol: foo | |
| 26 | Type: R_X86_64_64 | |
| 27 | Symbols: | |
| 28 | Global: | |
| 29 | - Name: foo | |
| \ No newline at end of file |
deps/lld/test/ELF/basic-aarch64.s+8-8| ... | ... | @@ -59,7 +59,7 @@ _start: |
| 59 | 59 | # CHECK-NEXT: SHF_ALLOC (0x2) |
| 60 | 60 | # CHECK-NEXT: SHF_EXECINSTR (0x4) |
| 61 | 61 | # CHECK-NEXT: ] |
| 62 | # CHECK-NEXT: Address: 0x20000 | |
| 62 | # CHECK-NEXT: Address: 0x210000 | |
| 63 | 63 | # CHECK-NEXT: Offset: 0x10000 |
| 64 | 64 | # CHECK-NEXT: Size: 12 |
| 65 | 65 | # CHECK-NEXT: Link: 0 |
| ... | ... | @@ -138,7 +138,7 @@ _start: |
| 138 | 138 | # CHECK-NEXT: } |
| 139 | 139 | # CHECK-NEXT: Symbol { |
| 140 | 140 | # CHECK-NEXT: Name: $x.0 |
| 141 | # CHECK-NEXT: Value: 0x20000 | |
| 141 | # CHECK-NEXT: Value: 0x210000 | |
| 142 | 142 | # CHECK-NEXT: Size: 0 |
| 143 | 143 | # CHECK-NEXT: Binding: Local (0x0) |
| 144 | 144 | # CHECK-NEXT: Type: None (0x0) |
| ... | ... | @@ -159,8 +159,8 @@ _start: |
| 159 | 159 | # CHECK-NEXT: ProgramHeader { |
| 160 | 160 | # CHECK-NEXT: Type: PT_PHDR (0x6) |
| 161 | 161 | # CHECK-NEXT: Offset: 0x40 |
| 162 | # CHECK-NEXT: VirtualAddress: 0x10040 | |
| 163 | # CHECK-NEXT: PhysicalAddress: 0x10040 | |
| 162 | # CHECK-NEXT: VirtualAddress: 0x200040 | |
| 163 | # CHECK-NEXT: PhysicalAddress: 0x200040 | |
| 164 | 164 | # CHECK-NEXT: FileSize: 224 |
| 165 | 165 | # CHECK-NEXT: MemSize: 224 |
| 166 | 166 | # CHECK-NEXT: Flags [ (0x4) |
| ... | ... | @@ -171,8 +171,8 @@ _start: |
| 171 | 171 | # CHECK-NEXT: ProgramHeader { |
| 172 | 172 | # CHECK-NEXT: Type: PT_LOAD (0x1) |
| 173 | 173 | # CHECK-NEXT: Offset: 0x0 |
| 174 | # CHECK-NEXT: VirtualAddress: 0x10000 | |
| 175 | # CHECK-NEXT: PhysicalAddress: 0x10000 | |
| 174 | # CHECK-NEXT: VirtualAddress: 0x200000 | |
| 175 | # CHECK-NEXT: PhysicalAddress: 0x200000 | |
| 176 | 176 | # CHECK-NEXT: FileSize: 288 |
| 177 | 177 | # CHECK-NEXT: MemSize: 288 |
| 178 | 178 | # CHECK-NEXT: Flags [ |
| ... | ... | @@ -183,8 +183,8 @@ _start: |
| 183 | 183 | # CHECK-NEXT: ProgramHeader { |
| 184 | 184 | # CHECK-NEXT: Type: PT_LOAD (0x1) |
| 185 | 185 | # CHECK-NEXT: Offset: 0x1000 |
| 186 | # CHECK-NEXT: VirtualAddress: 0x20000 | |
| 187 | # CHECK-NEXT: PhysicalAddress: 0x20000 | |
| 186 | # CHECK-NEXT: VirtualAddress: 0x210000 | |
| 187 | # CHECK-NEXT: PhysicalAddress: 0x210000 | |
| 188 | 188 | # CHECK-NEXT: FileSize: 4096 |
| 189 | 189 | # CHECK-NEXT: MemSize: 4096 |
| 190 | 190 | # CHECK-NEXT: Flags [ (0x5) |
deps/lld/test/ELF/basic-ppc64.s+34-17| ... | ... | @@ -28,7 +28,7 @@ |
| 28 | 28 | // CHECK-NEXT: Version: 1 |
| 29 | 29 | // CHECK-NEXT: Entry: 0x10000 |
| 30 | 30 | // CHECK-NEXT: ProgramHeaderOffset: 0x40 |
| 31 | // CHECK-NEXT: SectionHeaderOffset: | |
| 31 | // CHECK-NEXT: SectionHeaderOffset: 0x200F8 | |
| 32 | 32 | // CHECK-NEXT: Flags [ (0x2) |
| 33 | 33 | // CHECK-NEXT: 0x2 |
| 34 | 34 | // CHECK-NEXT: ] |
| ... | ... | @@ -36,8 +36,8 @@ |
| 36 | 36 | // CHECK-NEXT: ProgramHeaderEntrySize: 56 |
| 37 | 37 | // CHECK-NEXT: ProgramHeaderCount: 7 |
| 38 | 38 | // CHECK-NEXT: SectionHeaderEntrySize: 64 |
| 39 | // CHECK-NEXT: SectionHeaderCount: 10 | |
| 40 | // CHECK-NEXT: StringTableSectionIndex: 8 | |
| 39 | // CHECK-NEXT: SectionHeaderCount: 11 | |
| 40 | // CHECK-NEXT: StringTableSectionIndex: 9 | |
| 41 | 41 | // CHECK-NEXT:} |
| 42 | 42 | // CHECK-NEXT:Sections [ |
| 43 | 43 | // CHECK-NEXT: Section { |
| ... | ... | @@ -156,7 +156,23 @@ |
| 156 | 156 | // CHECK-NEXT: } |
| 157 | 157 | // CHECK-NEXT: Section { |
| 158 | 158 | // CHECK-NEXT: Index: 6 |
| 159 | // CHECK-NEXT: Name: .comment (38) | |
| 159 | // CHECK-NEXT: Name: .branch_lt (38) | |
| 160 | // CHECK-NEXT: Type: SHT_NOBITS (0x8) | |
| 161 | // CHECK-NEXT: Flags [ (0x3) | |
| 162 | // CHECK-NEXT: SHF_ALLOC (0x2) | |
| 163 | // CHECK-NEXT: SHF_WRITE (0x1) | |
| 164 | // CHECK-NEXT: ] | |
| 165 | // CHECK-NEXT: Address: 0x30000 | |
| 166 | // CHECK-NEXT: Offset: 0x20060 | |
| 167 | // CHECK-NEXT: Size: 0 | |
| 168 | // CHECK-NEXT: Link: 0 | |
| 169 | // CHECK-NEXT: Info: 0 | |
| 170 | // CHECK-NEXT: AddressAlignment: 8 | |
| 171 | // CHECK-NEXT: EntrySize: 0 | |
| 172 | // CHECK-NEXT: } | |
| 173 | // CHECK-NEXT: Section { | |
| 174 | // CHECK-NEXT: Index: 7 | |
| 175 | // CHECK-NEXT: Name: .comment (49) | |
| 160 | 176 | // CHECK-NEXT: Type: SHT_PROGBITS (0x1) |
| 161 | 177 | // CHECK-NEXT: Flags [ (0x30) |
| 162 | 178 | // CHECK-NEXT: SHF_MERGE (0x10) |
| ... | ... | @@ -174,15 +190,15 @@ |
| 174 | 190 | // CHECK-NEXT: ) |
| 175 | 191 | // CHECK-NEXT: } |
| 176 | 192 | // CHECK-NEXT: Section { |
| 177 | // CHECK-NEXT: Index: 7 | |
| 178 | // CHECK-NEXT: Name: .symtab (47) | |
| 193 | // CHECK-NEXT: Index: 8 | |
| 194 | // CHECK-NEXT: Name: .symtab (58) | |
| 179 | 195 | // CHECK-NEXT: Type: SHT_SYMTAB (0x2) |
| 180 | 196 | // CHECK-NEXT: Flags [ (0x0) |
| 181 | 197 | // CHECK-NEXT: ] |
| 182 | 198 | // CHECK-NEXT: Address: 0x0 |
| 183 | 199 | // CHECK-NEXT: Offset: 0x20068 |
| 184 | 200 | // CHECK-NEXT: Size: 48 |
| 185 | // CHECK-NEXT: Link: 9 | |
| 201 | // CHECK-NEXT: Link: 10 | |
| 186 | 202 | // CHECK-NEXT: Info: 2 |
| 187 | 203 | // CHECK-NEXT: AddressAlignment: 8 |
| 188 | 204 | // CHECK-NEXT: EntrySize: 24 |
| ... | ... | @@ -193,14 +209,14 @@ |
| 193 | 209 | // CHECK-NEXT: ) |
| 194 | 210 | // CHECK-NEXT: } |
| 195 | 211 | // CHECK-NEXT: Section { |
| 196 | // CHECK-NEXT: Index: 8 | |
| 197 | // CHECK-NEXT: Name: .shstrtab (55) | |
| 212 | // CHECK-NEXT: Index: 9 | |
| 213 | // CHECK-NEXT: Name: .shstrtab (66) | |
| 198 | 214 | // CHECK-NEXT: Type: SHT_STRTAB (0x3) |
| 199 | 215 | // CHECK-NEXT: Flags [ (0x0) |
| 200 | 216 | // CHECK-NEXT: ] |
| 201 | 217 | // CHECK-NEXT: Address: 0x0 |
| 202 | 218 | // CHECK-NEXT: Offset: 0x20098 |
| 203 | // CHECK-NEXT: Size: 73 | |
| 219 | // CHECK-NEXT: Size: 84 | |
| 204 | 220 | // CHECK-NEXT: Link: 0 |
| 205 | 221 | // CHECK-NEXT: Info: 0 |
| 206 | 222 | // CHECK-NEXT: AddressAlignment: 1 |
| ... | ... | @@ -208,19 +224,20 @@ |
| 208 | 224 | // CHECK-NEXT: SectionData ( |
| 209 | 225 | // CHECK-NEXT: 0000: 002E6479 6E73796D 002E6861 7368002E |..dynsym..hash..| |
| 210 | 226 | // CHECK-NEXT: 0010: 64796E73 7472002E 74657874 002E6479 |dynstr..text..dy| |
| 211 | // CHECK-NEXT: 0020: 6E616D69 63002E63 6F6D6D65 6E74002E |namic..comment..| | |
| 212 | // CHECK-NEXT: 0030: 73796D74 6162002E 73687374 72746162 |symtab..shstrtab| | |
| 213 | // CHECK-NEXT: 0040: 002E7374 72746162 00 |..strtab.| | |
| 227 | // CHECK-NEXT: 0020: 6E616D69 63002E62 72616E63 685F6C74 |namic..branch_lt| | |
| 228 | // CHECK-NEXT: 0030: 002E636F 6D6D656E 74002E73 796D7461 |..comment..symta| | |
| 229 | // CHECK-NEXT: 0040: 62002E73 68737472 74616200 2E737472 |b..shstrtab..str| | |
| 230 | // CHECK-NEXT: 0050: 74616200 |tab.| | |
| 214 | 231 | // CHECK-NEXT: ) |
| 215 | 232 | // CHECK-NEXT: } |
| 216 | 233 | // CHECK-NEXT: Section { |
| 217 | // CHECK-NEXT: Index: 9 | |
| 218 | // CHECK-NEXT: Name: .strtab (65) | |
| 234 | // CHECK-NEXT: Index: 10 | |
| 235 | // CHECK-NEXT: Name: .strtab (76) | |
| 219 | 236 | // CHECK-NEXT: Type: SHT_STRTAB (0x3) |
| 220 | 237 | // CHECK-NEXT: Flags [ (0x0) |
| 221 | 238 | // CHECK-NEXT: ] |
| 222 | 239 | // CHECK-NEXT: Address: 0x0 |
| 223 | // CHECK-NEXT: Offset: 0x200E1 | |
| 240 | // CHECK-NEXT: Offset: 0x200EC | |
| 224 | 241 | // CHECK-NEXT: Size: 10 |
| 225 | 242 | // CHECK-NEXT: Link: 0 |
| 226 | 243 | // CHECK-NEXT: Info: 0 |
| ... | ... | @@ -275,7 +292,7 @@ |
| 275 | 292 | // CHECK-NEXT: VirtualAddress: 0x20000 |
| 276 | 293 | // CHECK-NEXT: PhysicalAddress: 0x20000 |
| 277 | 294 | // CHECK-NEXT: FileSize: 96 |
| 278 | // CHECK-NEXT: MemSize: 96 | |
| 295 | // CHECK-NEXT: MemSize: 65536 | |
| 279 | 296 | // CHECK-NEXT: Flags [ (0x6) |
| 280 | 297 | // CHECK-NEXT: PF_R (0x4) |
| 281 | 298 | // CHECK-NEXT: PF_W (0x2) |
deps/lld/test/ELF/basic32.s+8-8| ... | ... | @@ -23,7 +23,7 @@ _start: |
| 23 | 23 | # CHECK-NEXT: Type: Executable (0x2) |
| 24 | 24 | # CHECK-NEXT: Machine: EM_386 (0x3) |
| 25 | 25 | # CHECK-NEXT: Version: 1 |
| 26 | # CHECK-NEXT: Entry: 0x11000 | |
| 26 | # CHECK-NEXT: Entry: 0x401000 | |
| 27 | 27 | # CHECK-NEXT: ProgramHeaderOffset: 0x34 |
| 28 | 28 | # CHECK-NEXT: SectionHeaderOffset: 0x205C |
| 29 | 29 | # CHECK-NEXT: Flags [ (0x0) |
| ... | ... | @@ -58,7 +58,7 @@ _start: |
| 58 | 58 | # CHECK-NEXT: SHF_ALLOC (0x2) |
| 59 | 59 | # CHECK-NEXT: SHF_EXECINSTR (0x4) |
| 60 | 60 | # CHECK-NEXT: ] |
| 61 | # CHECK-NEXT: Address: 0x11000 | |
| 61 | # CHECK-NEXT: Address: 0x401000 | |
| 62 | 62 | # CHECK-NEXT: Offset: 0x1000 |
| 63 | 63 | # CHECK-NEXT: Size: 12 |
| 64 | 64 | # CHECK-NEXT: Link: 0 |
| ... | ... | @@ -129,8 +129,8 @@ _start: |
| 129 | 129 | # CHECK-NEXT: ProgramHeader { |
| 130 | 130 | # CHECK-NEXT: Type: PT_PHDR (0x6) |
| 131 | 131 | # CHECK-NEXT: Offset: 0x34 |
| 132 | # CHECK-NEXT: VirtualAddress: 0x10034 | |
| 133 | # CHECK-NEXT: PhysicalAddress: 0x10034 | |
| 132 | # CHECK-NEXT: VirtualAddress: 0x400034 | |
| 133 | # CHECK-NEXT: PhysicalAddress: 0x400034 | |
| 134 | 134 | # CHECK-NEXT: FileSize: 128 |
| 135 | 135 | # CHECK-NEXT: MemSize: 128 |
| 136 | 136 | # CHECK-NEXT: Flags [ (0x4) |
| ... | ... | @@ -141,8 +141,8 @@ _start: |
| 141 | 141 | # CHECK-NEXT: ProgramHeader { |
| 142 | 142 | # CHECK-NEXT: Type: PT_LOAD (0x1) |
| 143 | 143 | # CHECK-NEXT: Offset: 0x0 |
| 144 | # CHECK-NEXT: VirtualAddress: 0x10000 | |
| 145 | # CHECK-NEXT: PhysicalAddress: 0x10000 | |
| 144 | # CHECK-NEXT: VirtualAddress: 0x400000 | |
| 145 | # CHECK-NEXT: PhysicalAddress: 0x400000 | |
| 146 | 146 | # CHECK-NEXT: FileSize: 180 |
| 147 | 147 | # CHECK-NEXT: MemSize: 180 |
| 148 | 148 | # CHECK-NEXT: Flags [ |
| ... | ... | @@ -153,8 +153,8 @@ _start: |
| 153 | 153 | # CHECK-NEXT: ProgramHeader { |
| 154 | 154 | # CHECK-NEXT: Type: PT_LOAD (0x1) |
| 155 | 155 | # CHECK-NEXT: Offset: 0x1000 |
| 156 | # CHECK-NEXT: VirtualAddress: 0x11000 | |
| 157 | # CHECK-NEXT: PhysicalAddress: 0x11000 | |
| 156 | # CHECK-NEXT: VirtualAddress: 0x401000 | |
| 157 | # CHECK-NEXT: PhysicalAddress: 0x401000 | |
| 158 | 158 | # CHECK-NEXT: FileSize: 4096 |
| 159 | 159 | # CHECK-NEXT: MemSize: 4096 |
| 160 | 160 | # CHECK-NEXT: Flags [ (0x5) |
deps/lld/test/ELF/basic64be.s+42-23| ... | ... | @@ -23,7 +23,7 @@ |
| 23 | 23 | # CHECK-NEXT: Version: 1 |
| 24 | 24 | # CHECK-NEXT: Entry: 0x10010000 |
| 25 | 25 | # CHECK-NEXT: ProgramHeaderOffset: 0x40 |
| 26 | # CHECK-NEXT: SectionHeaderOffset: 0x11050 | |
| 26 | # CHECK-NEXT: SectionHeaderOffset: 0x20058 | |
| 27 | 27 | # CHECK-NEXT: Flags [ (0x2) |
| 28 | 28 | # CHECK-NEXT: 0x2 |
| 29 | 29 | # CHECK-NEXT: ] |
| ... | ... | @@ -31,8 +31,8 @@ |
| 31 | 31 | # CHECK-NEXT: ProgramHeaderEntrySize: 56 |
| 32 | 32 | # CHECK-NEXT: ProgramHeaderCount: 4 |
| 33 | 33 | # CHECK-NEXT: SectionHeaderEntrySize: 64 |
| 34 | # CHECK-NEXT: SectionHeaderCount: 6 | |
| 35 | # CHECK-NEXT: StringTableSectionIndex: 4 | |
| 34 | # CHECK-NEXT: SectionHeaderCount: 7 | |
| 35 | # CHECK-NEXT: StringTableSectionIndex: 5 | |
| 36 | 36 | # CHECK-NEXT: } |
| 37 | 37 | # CHECK-NEXT: Sections [ |
| 38 | 38 | # CHECK-NEXT: Section { |
| ... | ... | @@ -72,14 +72,32 @@ |
| 72 | 72 | # CHECK-NEXT: } |
| 73 | 73 | # CHECK-NEXT: Section { |
| 74 | 74 | # CHECK-NEXT: Index: 2 |
| 75 | # CHECK-NEXT: Name: .comment (7) | |
| 75 | # CHECK-NEXT: Name: .branch_lt (7) | |
| 76 | # CHECK-NEXT: Type: SHT_PROGBITS (0x1) | |
| 77 | # CHECK-NEXT: Flags [ (0x3) | |
| 78 | # CHECK-NEXT: SHF_ALLOC (0x2) | |
| 79 | # CHECK-NEXT: SHF_WRITE (0x1) | |
| 80 | # CHECK-NEXT: ] | |
| 81 | # CHECK-NEXT: Address: 0x10020000 | |
| 82 | # CHECK-NEXT: Offset: 0x20000 | |
| 83 | # CHECK-NEXT: Size: 0 | |
| 84 | # CHECK-NEXT: Link: 0 | |
| 85 | # CHECK-NEXT: Info: 0 | |
| 86 | # CHECK-NEXT: AddressAlignment: 8 | |
| 87 | # CHECK-NEXT: EntrySize: 0 | |
| 88 | # CHECK-NEXT: SectionData ( | |
| 89 | # CHECK-NEXT: ) | |
| 90 | # CHECK-NEXT: } | |
| 91 | # CHECK-NEXT: Section { | |
| 92 | # CHECK-NEXT: Index: 3 | |
| 93 | # CHECK-NEXT: Name: .comment (18) | |
| 76 | 94 | # CHECK-NEXT: Type: SHT_PROGBITS (0x1) |
| 77 | 95 | # CHECK-NEXT: Flags [ (0x30) |
| 78 | 96 | # CHECK-NEXT: SHF_MERGE (0x10) |
| 79 | 97 | # CHECK-NEXT: SHF_STRINGS (0x20) |
| 80 | 98 | # CHECK-NEXT: ] |
| 81 | 99 | # CHECK-NEXT: Address: 0x0 |
| 82 | # CHECK-NEXT: Offset: 0x11000 | |
| 100 | # CHECK-NEXT: Offset: 0x20000 | |
| 83 | 101 | # CHECK-NEXT: Size: 8 |
| 84 | 102 | # CHECK-NEXT: Link: 0 |
| 85 | 103 | # CHECK-NEXT: Info: 0 |
| ... | ... | @@ -90,15 +108,15 @@ |
| 90 | 108 | # CHECK-NEXT: ) |
| 91 | 109 | # CHECK-NEXT: } |
| 92 | 110 | # CHECK-NEXT: Section { |
| 93 | # CHECK-NEXT: Index: 3 | |
| 94 | # CHECK-NEXT: Name: .symtab (16) | |
| 111 | # CHECK-NEXT: Index: 4 | |
| 112 | # CHECK-NEXT: Name: .symtab (27) | |
| 95 | 113 | # CHECK-NEXT: Type: SHT_SYMTAB (0x2) |
| 96 | 114 | # CHECK-NEXT: Flags [ (0x0) |
| 97 | 115 | # CHECK-NEXT: ] |
| 98 | 116 | # CHECK-NEXT: Address: 0x0 |
| 99 | # CHECK-NEXT: Offset: 0x11008 | |
| 117 | # CHECK-NEXT: Offset: 0x20008 | |
| 100 | 118 | # CHECK-NEXT: Size: 24 |
| 101 | # CHECK-NEXT: Link: 5 | |
| 119 | # CHECK-NEXT: Link: 6 | |
| 102 | 120 | # CHECK-NEXT: Info: 1 |
| 103 | 121 | # CHECK-NEXT: AddressAlignment: 8 |
| 104 | 122 | # CHECK-NEXT: EntrySize: 24 |
| ... | ... | @@ -108,32 +126,33 @@ |
| 108 | 126 | # CHECK-NEXT: ) |
| 109 | 127 | # CHECK-NEXT: } |
| 110 | 128 | # CHECK-NEXT: Section { |
| 111 | # CHECK-NEXT: Index: 4 | |
| 112 | # CHECK-NEXT: Name: .shstrtab (24) | |
| 129 | # CHECK-NEXT: Index: 5 | |
| 130 | # CHECK-NEXT: Name: .shstrtab (35) | |
| 113 | 131 | # CHECK-NEXT: Type: SHT_STRTAB (0x3) |
| 114 | 132 | # CHECK-NEXT: Flags [ (0x0) |
| 115 | 133 | # CHECK-NEXT: ] |
| 116 | 134 | # CHECK-NEXT: Address: 0x0 |
| 117 | # CHECK-NEXT: Offset: 0x11020 | |
| 118 | # CHECK-NEXT: Size: 42 | |
| 135 | # CHECK-NEXT: Offset: 0x20020 | |
| 136 | # CHECK-NEXT: Size: 53 | |
| 119 | 137 | # CHECK-NEXT: Link: 0 |
| 120 | 138 | # CHECK-NEXT: Info: 0 |
| 121 | 139 | # CHECK-NEXT: AddressAlignment: 1 |
| 122 | 140 | # CHECK-NEXT: EntrySize: 0 |
| 123 | 141 | # CHECK-NEXT: SectionData ( |
| 124 | # CHECK-NEXT: 0000: 002E7465 7874002E 636F6D6D 656E7400 |..text..comment.| | |
| 125 | # CHECK-NEXT: 0010: 2E73796D 74616200 2E736873 74727461 |.symtab..shstrta| | |
| 126 | # CHECK-NEXT: 0020: 62002E73 74727461 6200 |b..strtab.| | |
| 142 | # CHECK-NEXT: 0000: 002E7465 7874002E 6272616E 63685F6C |..text..branch_l| | |
| 143 | # CHECK-NEXT: 0010: 74002E63 6F6D6D65 6E74002E 73796D74 |t..comment..symt| | |
| 144 | # CHECK-NEXT: 0020: 6162002E 73687374 72746162 002E7374 |ab..shstrtab..st| | |
| 145 | # CHECK-NEXT: 0030: 72746162 00 |rtab.| | |
| 127 | 146 | # CHECK-NEXT: ) |
| 128 | 147 | # CHECK-NEXT: } |
| 129 | 148 | # CHECK-NEXT: Section { |
| 130 | # CHECK-NEXT: Index: 5 | |
| 131 | # CHECK-NEXT: Name: .strtab (34) | |
| 149 | # CHECK-NEXT: Index: 6 | |
| 150 | # CHECK-NEXT: Name: .strtab (45) | |
| 132 | 151 | # CHECK-NEXT: Type: SHT_STRTAB (0x3) |
| 133 | 152 | # CHECK-NEXT: Flags [ (0x0) |
| 134 | 153 | # CHECK-NEXT: ] |
| 135 | 154 | # CHECK-NEXT: Address: 0x0 |
| 136 | # CHECK-NEXT: Offset: 0x1104A | |
| 155 | # CHECK-NEXT: Offset: 0x20055 | |
| 137 | 156 | # CHECK-NEXT: Size: 1 |
| 138 | 157 | # CHECK-NEXT: Link: 0 |
| 139 | 158 | # CHECK-NEXT: Info: 0 |
| ... | ... | @@ -150,8 +169,8 @@ |
| 150 | 169 | # CHECK-NEXT: Offset: 0x40 |
| 151 | 170 | # CHECK-NEXT: VirtualAddress: 0x10000040 |
| 152 | 171 | # CHECK-NEXT: PhysicalAddress: 0x10000040 |
| 153 | # CHECK-NEXT: FileSize: 224 | |
| 154 | # CHECK-NEXT: MemSize: 224 | |
| 172 | # CHECK-NEXT: FileSize: 280 | |
| 173 | # CHECK-NEXT: MemSize: 280 | |
| 155 | 174 | # CHECK-NEXT: Flags [ (0x4) |
| 156 | 175 | # CHECK-NEXT: PF_R (0x4) |
| 157 | 176 | # CHECK-NEXT: ] |
| ... | ... | @@ -162,8 +181,8 @@ |
| 162 | 181 | # CHECK-NEXT: Offset: 0x0 |
| 163 | 182 | # CHECK-NEXT: VirtualAddress: 0x10000000 |
| 164 | 183 | # CHECK-NEXT: PhysicalAddress: 0x10000000 |
| 165 | # CHECK-NEXT: FileSize: 288 | |
| 166 | # CHECK-NEXT: MemSize: 288 | |
| 184 | # CHECK-NEXT: FileSize: 344 | |
| 185 | # CHECK-NEXT: MemSize: 344 | |
| 167 | 186 | # CHECK-NEXT: Flags [ (0x4) |
| 168 | 187 | # CHECK-NEXT: PF_R (0x4) |
| 169 | 188 | # CHECK-NEXT: ] |
deps/lld/test/ELF/bsymbolic-undef.s+2-2| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | # CHECK: DynamicSymbols [ |
| 7 | 7 | # CHECK-NEXT: Symbol { |
| 8 | # CHECK-NEXT: Name: @ | |
| 8 | # CHECK-NEXT: Name: | |
| 9 | 9 | # CHECK-NEXT: Value: 0x0 |
| 10 | 10 | # CHECK-NEXT: Size: 0 |
| 11 | 11 | # CHECK-NEXT: Binding: Local (0x0) |
| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | # CHECK-NEXT: Section: Undefined (0x0) |
| 15 | 15 | # CHECK-NEXT: } |
| 16 | 16 | # CHECK-NEXT: Symbol { |
| 17 | # CHECK-NEXT: Name: undef@ | |
| 17 | # CHECK-NEXT: Name: undef | |
| 18 | 18 | # CHECK-NEXT: Value: 0x0 |
| 19 | 19 | # CHECK-NEXT: Size: 0 |
| 20 | 20 | # CHECK-NEXT: Binding: Global (0x1) |
deps/lld/test/ELF/cgprofile-obj.s created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 4 | # RUN: ld.lld -e A %t.o -o %t | |
| 5 | # RUN: llvm-nm --no-sort %t | FileCheck %s | |
| 6 | # RUN: ld.lld --no-call-graph-profile-sort -e A %t.o -o %t | |
| 7 | # RUN: llvm-nm --no-sort %t | FileCheck %s --check-prefix=NO-CG | |
| 8 | ||
| 9 | .section .text.D,"ax",@progbits | |
| 10 | D: | |
| 11 | retq | |
| 12 | ||
| 13 | .section .text.C,"ax",@progbits | |
| 14 | .globl C | |
| 15 | C: | |
| 16 | retq | |
| 17 | ||
| 18 | .section .text.B,"ax",@progbits | |
| 19 | .globl B | |
| 20 | B: | |
| 21 | retq | |
| 22 | ||
| 23 | .section .text.A,"ax",@progbits | |
| 24 | .globl A | |
| 25 | A: | |
| 26 | Aa: | |
| 27 | retq | |
| 28 | ||
| 29 | .cg_profile A, B, 10 | |
| 30 | .cg_profile A, B, 10 | |
| 31 | .cg_profile Aa, B, 80 | |
| 32 | .cg_profile A, C, 40 | |
| 33 | .cg_profile B, C, 30 | |
| 34 | .cg_profile C, D, 90 | |
| 35 | ||
| 36 | # CHECK: 0000000000201003 t D | |
| 37 | # CHECK: 0000000000201000 T A | |
| 38 | # CHECK: 0000000000201001 T B | |
| 39 | # CHECK: 0000000000201002 T C | |
| 40 | ||
| 41 | # NO-CG: 0000000000201000 t D | |
| 42 | # NO-CG: 0000000000201003 T A | |
| 43 | # NO-CG: 0000000000201002 T B | |
| 44 | # NO-CG: 0000000000201001 T C |
deps/lld/test/ELF/cgprofile-shared-warn.s created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 4 | # RUN: ld.lld --shared %t.o -o /dev/null 2>&1 | count 0 | |
| 5 | # RUN: ld.lld -e A --unresolved-symbols=ignore-all %t.o -o /dev/null 2>&1 | count 0 | |
| 6 | ||
| 7 | # RUN: echo '.globl B; B: ret' | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t1.o | |
| 8 | # RUN: ld.lld --shared %t1.o -o %t1.so | |
| 9 | # RUN: ld.lld -e A %t.o %t1.so -o /dev/null 2>&1 | count 0 | |
| 10 | ||
| 11 | # RUN: ld.lld --gc-sections %t.o %t1.so -o /dev/null 2>&1 | count 0 | |
| 12 | .globl _start | |
| 13 | _start: | |
| 14 | ret | |
| 15 | ||
| 16 | .section .text.A,"ax",@progbits | |
| 17 | .globl A | |
| 18 | A: | |
| 19 | callq B | |
| 20 | ||
| 21 | .cg_profile A, B, 10 |
deps/lld/test/ELF/cgprofile-txt2.s created+38| ... | ... | @@ -0,0 +1,38 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | |
| 4 | # RUN: echo "A B 5" > %t.call_graph | |
| 5 | # RUN: echo "B C 50" >> %t.call_graph | |
| 6 | # RUN: echo "C D 40" >> %t.call_graph | |
| 7 | # RUN: echo "D B 10" >> %t.call_graph | |
| 8 | # RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t2 | |
| 9 | # RUN: llvm-readobj -symbols %t2 | FileCheck %s | |
| 10 | ||
| 11 | # CHECK: Name: A | |
| 12 | # CHECK-NEXT: Value: 0x201003 | |
| 13 | # CHECK: Name: B | |
| 14 | # CHECK-NEXT: Value: 0x201000 | |
| 15 | # CHECK: Name: C | |
| 16 | # CHECK-NEXT: Value: 0x201001 | |
| 17 | # CHECK: Name: D | |
| 18 | # CHECK-NEXT: Value: 0x201002 | |
| 19 | ||
| 20 | .section .text.A,"ax",@progbits | |
| 21 | .globl A | |
| 22 | A: | |
| 23 | nop | |
| 24 | ||
| 25 | .section .text.B,"ax",@progbits | |
| 26 | .globl B | |
| 27 | B: | |
| 28 | nop | |
| 29 | ||
| 30 | .section .text.C,"ax",@progbits | |
| 31 | .globl C | |
| 32 | C: | |
| 33 | nop | |
| 34 | ||
| 35 | .section .text.D,"ax",@progbits | |
| 36 | .globl D | |
| 37 | D: | |
| 38 | nop |
deps/lld/test/ELF/comdat-linkonce.s+6-1| ... | ... | @@ -4,7 +4,12 @@ |
| 4 | 4 | // RUN: ld.lld -shared %t.o %t2.o -o %t |
| 5 | 5 | // RUN: ld.lld -shared %t2.o %t.o -o %t |
| 6 | 6 | |
| 7 | .section .gnu.linkonce.t.zed | |
| 7 | .section .gnu.linkonce.t.__x86.get_pc_thunk.bx | |
| 8 | 8 | .globl abc |
| 9 | 9 | abc: |
| 10 | 10 | nop |
| 11 | ||
| 12 | .section .gnu.linkonce.t.__i686.get_pc_thunk.bx | |
| 13 | .globl def | |
| 14 | def: | |
| 15 | nop |
deps/lld/test/ELF/common-gc2.s+2-2| ... | ... | @@ -3,8 +3,8 @@ |
| 3 | 3 | # RUN: ld.lld -gc-sections -export-dynamic %t -o %t1 |
| 4 | 4 | # RUN: llvm-readobj --dyn-symbols %t1 | FileCheck %s |
| 5 | 5 | |
| 6 | # CHECK: Name: bar@ | |
| 7 | # CHECK: Name: foo@ | |
| 6 | # CHECK: Name: bar | |
| 7 | # CHECK: Name: foo | |
| 8 | 8 | |
| 9 | 9 | .comm foo,4,4 |
| 10 | 10 | .comm bar,4,4 |
deps/lld/test/ELF/compressed-debug-input-err.s+2-2| ... | ... | @@ -3,8 +3,8 @@ |
| 3 | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
| 4 | 4 | # RUN: not ld.lld %t.o -o %t.so -shared 2>&1 | FileCheck %s |
| 5 | 5 | |
| 6 | ## Check we are able to report zlib decompressor errors. | |
| 7 | # CHECK: error: {{.*}}.o:(.zdebug_str): decompress failed: zlib error: Z_DATA_ERROR | |
| 6 | ## Check we are able to report zlib uncompress errors. | |
| 7 | # CHECK: error: {{.*}}.o:(.debug_str): uncompress failed: zlib error: Z_DATA_ERROR | |
| 8 | 8 | |
| 9 | 9 | .section .zdebug_str,"MS",@progbits,1 |
| 10 | 10 | .ascii "ZLIB" |
deps/lld/test/ELF/conflict.s+1| ... | ... | @@ -26,6 +26,7 @@ |
| 26 | 26 | # RUN: FileCheck -check-prefix=DEMANGLE %s |
| 27 | 27 | |
| 28 | 28 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/conflict.s -o %t2.o |
| 29 | # RUN: rm -f %t3.a | |
| 29 | 30 | # RUN: llvm-ar rcs %t3.a %t2.o |
| 30 | 31 | # RUN: not ld.lld %t1.o %t3.a -u baz -o %t2 2>&1 | FileCheck -check-prefix=ARCHIVE %s |
| 31 | 32 |
deps/lld/test/ELF/copy-rel-tls.s created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/copy-rel-tls.s -o %t1.o | |
| 4 | // RUN: ld.lld %t1.o -shared -soname t1.so -o %t1.so | |
| 5 | // RUN: ld.lld %t.o %t1.so -o %t | |
| 6 | // RUN: llvm-nm %t1.so | FileCheck %s | |
| 7 | // RUN: llvm-nm %t | FileCheck --check-prefix=TLS %s | |
| 8 | // foo and tfoo have the same st_value but we should not copy tfoo. | |
| 9 | // CHECK: 2000 B foo | |
| 10 | // CHECK: 2000 B tfoo | |
| 11 | // TLS-NOT: tfoo | |
| 12 | ||
| 13 | .global _start | |
| 14 | _start: | |
| 15 | leaq foo, %rax |
deps/lld/test/ELF/debug-line-str.s created+136| ... | ... | @@ -0,0 +1,136 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -dwarf-version=5 %s -o %t.o | |
| 3 | # RUN: not ld.lld %t.o -o %t1 2>&1 | FileCheck %s | |
| 4 | ||
| 5 | # Check we do not crash and able to report the source location. | |
| 6 | ||
| 7 | # CHECK: error: undefined symbol: foo() | |
| 8 | # CHECK-NEXT: >>> referenced by test.cpp:3 | |
| 9 | # CHECK-NEXT: >>> {{.*}}.o:(.text+0x1) | |
| 10 | ||
| 11 | # The code below is the reduced version of the output | |
| 12 | # from the following invocation and source: | |
| 13 | # | |
| 14 | # // test.cpp: | |
| 15 | # int foo(); | |
| 16 | # int main() { | |
| 17 | # return foo(); | |
| 18 | # } | |
| 19 | # | |
| 20 | # clang -gdwarf-5 test.cpp -o test.s -S | |
| 21 | # clang version 8.0.0 (trunk 343487) | |
| 22 | ||
| 23 | .text | |
| 24 | .file "test.cpp" | |
| 25 | .globl main | |
| 26 | .type main,@function | |
| 27 | main: | |
| 28 | .Lfunc_begin0: | |
| 29 | .file 0 "/home/path" "test.cpp" md5 0x8ed32099ab837bd13543fd3e8102739f | |
| 30 | .file 1 "test.cpp" md5 0x8ed32099ab837bd13543fd3e8102739f | |
| 31 | .loc 1 3 10 prologue_end | |
| 32 | jmp _Z3foov | |
| 33 | .Lfunc_end0: | |
| 34 | ||
| 35 | .Lstr_offsets_base0: | |
| 36 | .section .debug_str,"MS",@progbits,1 | |
| 37 | .asciz "stub" | |
| 38 | ||
| 39 | .section .debug_str_offsets,"",@progbits | |
| 40 | .long 0 | |
| 41 | ||
| 42 | .section .debug_abbrev,"",@progbits | |
| 43 | .byte 1 # Abbreviation Code | |
| 44 | .byte 17 # DW_TAG_compile_unit | |
| 45 | .byte 0 # DW_CHILDREN_yes | |
| 46 | .byte 37 # DW_AT_producer | |
| 47 | .byte 37 # DW_FORM_strx1 | |
| 48 | .byte 19 # DW_AT_language | |
| 49 | .byte 5 # DW_FORM_data2 | |
| 50 | .byte 3 # DW_AT_name | |
| 51 | .byte 37 # DW_FORM_strx1 | |
| 52 | .byte 114 # DW_AT_str_offsets_base | |
| 53 | .byte 23 # DW_FORM_sec_offset | |
| 54 | .byte 16 # DW_AT_stmt_list | |
| 55 | .byte 23 # DW_FORM_sec_offset | |
| 56 | .byte 27 # DW_AT_comp_dir | |
| 57 | .byte 37 # DW_FORM_strx1 | |
| 58 | .byte 17 # DW_AT_low_pc | |
| 59 | .byte 1 # DW_FORM_addr | |
| 60 | .byte 18 # DW_AT_high_pc | |
| 61 | .byte 6 # DW_FORM_data4 | |
| 62 | .byte 0 # EOM(1) | |
| 63 | .byte 0 # EOM(2) | |
| 64 | ||
| 65 | .byte 2 # Abbreviation Code | |
| 66 | .byte 46 # DW_TAG_subprogram | |
| 67 | .byte 0 # DW_CHILDREN_no | |
| 68 | .byte 17 # DW_AT_low_pc | |
| 69 | .byte 1 # DW_FORM_addr | |
| 70 | .byte 18 # DW_AT_high_pc | |
| 71 | .byte 6 # DW_FORM_data4 | |
| 72 | .byte 64 # DW_AT_frame_base | |
| 73 | .byte 24 # DW_FORM_exprloc | |
| 74 | .byte 3 # DW_AT_name | |
| 75 | .byte 37 # DW_FORM_strx1 | |
| 76 | .byte 58 # DW_AT_decl_file | |
| 77 | .byte 11 # DW_FORM_data1 | |
| 78 | .byte 59 # DW_AT_decl_line | |
| 79 | .byte 11 # DW_FORM_data1 | |
| 80 | .byte 73 # DW_AT_type | |
| 81 | .byte 19 # DW_FORM_ref4 | |
| 82 | .byte 63 # DW_AT_external | |
| 83 | .byte 25 # DW_FORM_flag_present | |
| 84 | .byte 0 # EOM(1) | |
| 85 | .byte 0 # EOM(2) | |
| 86 | ||
| 87 | .byte 3 # Abbreviation Code | |
| 88 | .byte 36 # DW_TAG_base_type | |
| 89 | .byte 0 # DW_CHILDREN_no | |
| 90 | .byte 3 # DW_AT_name | |
| 91 | .byte 37 # DW_FORM_strx1 | |
| 92 | .byte 62 # DW_AT_encoding | |
| 93 | .byte 11 # DW_FORM_data1 | |
| 94 | .byte 11 # DW_AT_byte_size | |
| 95 | .byte 11 # DW_FORM_data1 | |
| 96 | .byte 0 # EOM(1) | |
| 97 | .byte 0 # EOM(2) | |
| 98 | .byte 0 # EOM(3) | |
| 99 | ||
| 100 | .section .debug_info,"",@progbits | |
| 101 | .Lcu_begin0: | |
| 102 | .long 61 # Length of Unit | |
| 103 | .short 5 # DWARF version number | |
| 104 | .byte 1 # DWARF Unit Type | |
| 105 | .byte 8 # Address Size (in bytes) | |
| 106 | .long .debug_abbrev # Offset Into Abbrev. Section | |
| 107 | ||
| 108 | .byte 1 # Abbrev [1] 0xc:0x35 DW_TAG_compile_unit | |
| 109 | .byte 0 # DW_AT_producer | |
| 110 | .short 0 # DW_AT_language | |
| 111 | .byte 0 # DW_AT_name | |
| 112 | .long .Lstr_offsets_base0 # DW_AT_str_offsets_base | |
| 113 | .long .Lline_table_start0 # DW_AT_stmt_list | |
| 114 | .byte 0 # DW_AT_comp_dir | |
| 115 | .quad .Lfunc_begin0 # DW_AT_low_pc | |
| 116 | .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc | |
| 117 | ||
| 118 | .byte 2 # Abbrev [2] 0x26:0x16 DW_TAG_subprogram | |
| 119 | .quad .Lfunc_begin0 # DW_AT_low_pc | |
| 120 | .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc | |
| 121 | .byte 1 # DW_AT_frame_base | |
| 122 | .byte 87 | |
| 123 | .byte 0 # DW_AT_name | |
| 124 | .byte 1 # DW_AT_decl_file | |
| 125 | .byte 2 # DW_AT_decl_line | |
| 126 | .long 60 # DW_AT_type | |
| 127 | # DW_AT_external | |
| 128 | ||
| 129 | .byte 3 # Abbrev [3] 0x3c:0x4 DW_TAG_base_type | |
| 130 | .byte 0 # DW_AT_name | |
| 131 | .byte 5 # DW_AT_encoding | |
| 132 | .byte 4 # DW_AT_byte_size | |
| 133 | .byte 0 # End Of Children Mark | |
| 134 | ||
| 135 | .section .debug_line,"",@progbits | |
| 136 | .Lline_table_start0: |
deps/lld/test/ELF/debug-relocation-none.test created+58| ... | ... | @@ -0,0 +1,58 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: yaml2obj %s -o %t.o | |
| 3 | # RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s | |
| 4 | ||
| 5 | ## Previously we would report an error saying the relocation in .debug_info | |
| 6 | ## has an unsupported target. | |
| 7 | ## Check we do not report debug information parsing errors when relocation | |
| 8 | ## used is of type R_*_NONE, what actually means it should be ignored. | |
| 9 | ||
| 10 | # CHECK-NOT: error | |
| 11 | # CHECK: error: undefined symbol: bar | |
| 12 | # CHECK-NOT: error | |
| 13 | ||
| 14 | --- !ELF | |
| 15 | FileHeader: | |
| 16 | Class: ELFCLASS64 | |
| 17 | Data: ELFDATA2LSB | |
| 18 | Type: ET_REL | |
| 19 | Machine: EM_X86_64 | |
| 20 | Sections: | |
| 21 | - Name: .text | |
| 22 | Type: SHT_PROGBITS | |
| 23 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 24 | Content: '0000000000000000' | |
| 25 | - Name: .rela.text | |
| 26 | Type: SHT_RELA | |
| 27 | AddressAlign: 8 | |
| 28 | Link: .symtab | |
| 29 | Info: .text | |
| 30 | Relocations: | |
| 31 | - Offset: 0x0000000000000000 | |
| 32 | Symbol: bar | |
| 33 | Type: R_X86_64_64 | |
| 34 | - Name: .debug_line | |
| 35 | Type: SHT_PROGBITS | |
| 36 | Content: 3300000002001C0000000101FB0E0D000101010100000001000001006162632E7300000000000009020000000000000000140208000101 | |
| 37 | - Name: .rela.debug_line | |
| 38 | AddressAlign: 8 | |
| 39 | Type: SHT_RELA | |
| 40 | Link: .symtab | |
| 41 | Info: .debug_line | |
| 42 | Relocations: | |
| 43 | - Offset: 0x0000000000000029 | |
| 44 | Type: R_X86_64_NONE | |
| 45 | - Name: .debug_info | |
| 46 | Type: SHT_PROGBITS | |
| 47 | AddressAlign: 0x0000000000000001 | |
| 48 | Content: 0C000000040000000000080100000000 | |
| 49 | - Name: .debug_abbrev | |
| 50 | Type: SHT_PROGBITS | |
| 51 | AddressAlign: 0x0000000000000001 | |
| 52 | Content: '0111001017000000' | |
| 53 | ||
| 54 | Symbols: | |
| 55 | Global: | |
| 56 | - Name: _start | |
| 57 | Section: .text | |
| 58 | - Name: bar |
deps/lld/test/ELF/defsym.s+17-2| ... | ... | @@ -9,6 +9,12 @@ |
| 9 | 9 | # RUN: llvm-readobj -t -s %t2 | FileCheck %s |
| 10 | 10 | # RUN: llvm-objdump -d -print-imm-hex %t2 | FileCheck %s --check-prefix=USE |
| 11 | 11 | |
| 12 | ## Check we are reporting the error correctly and don't crash | |
| 13 | ## when handling the second --defsym. | |
| 14 | # RUN: not ld.lld -o %t2 %t.o --defsym ERR+ \ | |
| 15 | # --defsym foo2=foo1 2>&1 | FileCheck %s --check-prefix=ERR | |
| 16 | # ERR: error: -defsym: syntax error: ERR+ | |
| 17 | ||
| 12 | 18 | # CHECK: Symbol { |
| 13 | 19 | # CHECK: Name: foo1 |
| 14 | 20 | # CHECK-NEXT: Value: 0x123 |
| ... | ... | @@ -68,8 +74,17 @@ |
| 68 | 74 | # EXPR-NEXT: Section: Absolute |
| 69 | 75 | # EXPR-NEXT: } |
| 70 | 76 | |
| 71 | # RUN: not ld.lld -o %t %t.o --defsym=foo2=und 2>&1 | FileCheck %s -check-prefix=ERR | |
| 72 | # ERR: error: -defsym:1: symbol not found: und | |
| 77 | # RUN: not ld.lld -o %t %t.o --defsym=foo2=und 2>&1 | FileCheck %s -check-prefix=ERR1 | |
| 78 | # ERR1: error: -defsym:1: symbol not found: und | |
| 79 | ||
| 80 | # RUN: not ld.lld -o %t %t.o --defsym=xxx=yyy,zzz 2>&1 | FileCheck %s -check-prefix=ERR2 | |
| 81 | # ERR2: -defsym:1: EOF expected, but got , | |
| 82 | ||
| 83 | # RUN: not ld.lld -o %t %t.o --defsym=foo 2>&1 | FileCheck %s -check-prefix=ERR3 | |
| 84 | # ERR3: error: -defsym: syntax error: foo | |
| 85 | ||
| 86 | # RUN: not ld.lld -o %t %t.o --defsym= 2>&1 | FileCheck %s -check-prefix=ERR4 | |
| 87 | # ERR4: error: -defsym: syntax error: | |
| 73 | 88 | |
| 74 | 89 | .globl foo1 |
| 75 | 90 | foo1 = 0x123 |
deps/lld/test/ELF/dont-export-hidden.s+1-1| ... | ... | @@ -19,7 +19,7 @@ foo: |
| 19 | 19 | |
| 20 | 20 | // CHECK: DynamicSymbols [ |
| 21 | 21 | // CHECK-NEXT: Symbol { |
| 22 | // CHECK-NEXT: Name: @ | |
| 22 | // CHECK-NEXT: Name: | |
| 23 | 23 | // CHECK-NEXT: Value: 0x0 |
| 24 | 24 | // CHECK-NEXT: Size: 0 |
| 25 | 25 | // CHECK-NEXT: Binding: Local |
deps/lld/test/ELF/driver-access.test+1-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | # REQUIRES: x86, shell | |
| 1 | # REQUIRES: x86 | |
| 2 | 2 | # Make sure that LLD works even if the current directory is not writable. |
| 3 | 3 | |
| 4 | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o |
deps/lld/test/ELF/driver.test+3| ... | ... | @@ -62,6 +62,9 @@ |
| 62 | 62 | # RUN: not ld.lld %t -z foo 2>&1 | FileCheck -check-prefix=ERR10 %s |
| 63 | 63 | # ERR10: unknown -z value: foo |
| 64 | 64 | |
| 65 | ## Check we report "unknown -z value" error even with -v. | |
| 66 | # RUN: not ld.lld %t -z foo -v 2>&1 | FileCheck -check-prefix=ERR10 %s | |
| 67 | ||
| 65 | 68 | # RUN: not ld.lld %t -z max-page-size 2>&1 | FileCheck -check-prefix=ERR11 %s |
| 66 | 69 | # ERR11: unknown -z value: max-page-size |
| 67 | 70 |
deps/lld/test/ELF/dt_flags.s+3-2| ... | ... | @@ -3,7 +3,8 @@ |
| 3 | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 4 | 4 | # RUN: ld.lld -shared %t -o %t.so |
| 5 | 5 | |
| 6 | # RUN: ld.lld -z initfirst -z now -z nodelete -z nodlopen -z origin -Bsymbolic %t %t.so -o %t1 | |
| 6 | # RUN: ld.lld -z global -z initfirst -z interpose -z now -z nodefaultlib \ | |
| 7 | # RUN: -z nodelete -z nodlopen -z origin -Bsymbolic %t %t.so -o %t1 | |
| 7 | 8 | # RUN: llvm-readobj -dynamic-table %t1 | FileCheck -check-prefix=FLAGS %s |
| 8 | 9 | |
| 9 | 10 | # RUN: ld.lld %t %t.so -o %t2 |
| ... | ... | @@ -14,7 +15,7 @@ |
| 14 | 15 | |
| 15 | 16 | # FLAGS: DynamicSection [ |
| 16 | 17 | # FLAGS: 0x000000000000001E FLAGS ORIGIN SYMBOLIC BIND_NOW |
| 17 | # FLAGS: 0x000000006FFFFFFB FLAGS_1 NOW NODELETE INITFIRST NOOPEN ORIGIN | |
| 18 | # FLAGS: 0x000000006FFFFFFB FLAGS_1 NOW GLOBAL NODELETE INITFIRST NOOPEN ORIGIN INTERPOSE NODEFLIB | |
| 18 | 19 | # FLAGS: ] |
| 19 | 20 | |
| 20 | 21 | # CHECK: DynamicSection [ |
deps/lld/test/ELF/dynamic-list-locals.s created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 4 | # RUN: echo "{ local: *; };" > %t.list | |
| 5 | # RUN: not ld.lld -dynamic-list %t.list -shared %t.o -o %t.so 2>&1 | FileCheck %s | |
| 6 | ||
| 7 | # CHECK: error: {{.*}}:1: "local:" scope not supported in --dynamic-list |
deps/lld/test/ELF/dynamic-list-preempt.s+4-4| ... | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | |
| 17 | 17 | # DYNSYMS: DynamicSymbols [ |
| 18 | 18 | # DYNSYMS-NEXT: Symbol { |
| 19 | # DYNSYMS-NEXT: Name: @ (0) | |
| 19 | # DYNSYMS-NEXT: Name: | |
| 20 | 20 | # DYNSYMS-NEXT: Value: 0x0 |
| 21 | 21 | # DYNSYMS-NEXT: Size: 0 |
| 22 | 22 | # DYNSYMS-NEXT: Binding: Local |
| ... | ... | @@ -25,7 +25,7 @@ |
| 25 | 25 | # DYNSYMS-NEXT: Section: Undefined |
| 26 | 26 | # DYNSYMS-NEXT: } |
| 27 | 27 | # DYNSYMS-NEXT: Symbol { |
| 28 | # DYNSYMS-NEXT: Name: bar@ | |
| 28 | # DYNSYMS-NEXT: Name: bar | |
| 29 | 29 | # DYNSYMS-NEXT: Value: |
| 30 | 30 | # DYNSYMS-NEXT: Size: |
| 31 | 31 | # DYNSYMS-NEXT: Binding: Global |
| ... | ... | @@ -34,7 +34,7 @@ |
| 34 | 34 | # DYNSYMS-NEXT: Section: |
| 35 | 35 | # DYNSYMS-NEXT: } |
| 36 | 36 | # DYNSYMS-NEXT: Symbol { |
| 37 | # DYNSYMS-NEXT: Name: ext@ | |
| 37 | # DYNSYMS-NEXT: Name: ext | |
| 38 | 38 | # DYNSYMS-NEXT: Value: |
| 39 | 39 | # DYNSYMS-NEXT: Size: |
| 40 | 40 | # DYNSYMS-NEXT: Binding: Global |
| ... | ... | @@ -43,7 +43,7 @@ |
| 43 | 43 | # DYNSYMS-NEXT: Section: |
| 44 | 44 | # DYNSYMS-NEXT: } |
| 45 | 45 | # DYNSYMS-NEXT: Symbol { |
| 46 | # DYNSYMS-NEXT: Name: foo@ | |
| 46 | # DYNSYMS-NEXT: Name: foo | |
| 47 | 47 | # DYNSYMS-NEXT: Value: |
| 48 | 48 | # DYNSYMS-NEXT: Size: |
| 49 | 49 | # DYNSYMS-NEXT: Binding: Global |
deps/lld/test/ELF/dynamic-list-unexpected-end.s created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 4 | # RUN: echo "{ }; foo;" > %t.list | |
| 5 | # RUN: not ld.lld -dynamic-list %t.list -shared %t.o -o %t.so 2>&1 | FileCheck %s | |
| 6 | ||
| 7 | # CHECK: error: {{.*}}:1: EOF expected, but got foo |
deps/lld/test/ELF/dynamic-list-wildcard.s+3-3| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | |
| 9 | 9 | # CHECK: DynamicSymbols [ |
| 10 | 10 | # CHECK-NEXT: Symbol { |
| 11 | # CHECK-NEXT: Name:	 @ (0) | |
| 11 | # CHECK-NEXT: Name: | |
| 12 | 12 | # CHECK-NEXT: Value:	 0x0 |
| 13 | 13 | # CHECK-NEXT: Size:	 0 |
| 14 | 14 | # CHECK-NEXT: Binding:	 Local (0x0) |
| ... | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | # CHECK-NEXT: Section:	 Undefined (0x0) |
| 18 | 18 | # CHECK-NEXT: } |
| 19 | 19 | # CHECK-NEXT: Symbol { |
| 20 | # CHECK-NEXT: Name:	 foo1@ (1) | |
| 20 | # CHECK-NEXT: Name:	 foo1 | |
| 21 | 21 | # CHECK-NEXT: Value:	 0x1000 |
| 22 | 22 | # CHECK-NEXT: Size:	 0 |
| 23 | 23 | # CHECK-NEXT: Binding:	 Global (0x1) |
| ... | ... | @@ -26,7 +26,7 @@ |
| 26 | 26 | # CHECK-NEXT: Section:	 .text (0x4) |
| 27 | 27 | # CHECK-NEXT: } |
| 28 | 28 | # CHECK-NEXT: Symbol { |
| 29 | # CHECK-NEXT: Name:	 foo11@ (6) | |
| 29 | # CHECK-NEXT: Name:	 foo11 | |
| 30 | 30 | # CHECK-NEXT: Value:	 0x1001 |
| 31 | 31 | # CHECK-NEXT: Size:	 0 |
| 32 | 32 | # CHECK-NEXT: Binding:	 Global (0x1) |
deps/lld/test/ELF/dynamic-list.s+11-11| ... | ... | @@ -23,7 +23,7 @@ |
| 23 | 23 | |
| 24 | 24 | # CHECK: DynamicSymbols [ |
| 25 | 25 | # CHECK-NEXT: Symbol { |
| 26 | # CHECK-NEXT: Name: @ | |
| 26 | # CHECK-NEXT: Name: | |
| 27 | 27 | # CHECK-NEXT: Value: 0x0 |
| 28 | 28 | # CHECK-NEXT: Size: 0 |
| 29 | 29 | # CHECK-NEXT: Binding: Local |
| ... | ... | @@ -32,7 +32,7 @@ |
| 32 | 32 | # CHECK-NEXT: Section: Undefined |
| 33 | 33 | # CHECK-NEXT: } |
| 34 | 34 | # CHECK-NEXT: Symbol { |
| 35 | # CHECK-NEXT: Name: foo1@ | |
| 35 | # CHECK-NEXT: Name: foo1 | |
| 36 | 36 | # CHECK-NEXT: Value: 0x201000 |
| 37 | 37 | # CHECK-NEXT: Size: 0 |
| 38 | 38 | # CHECK-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -54,7 +54,7 @@ |
| 54 | 54 | |
| 55 | 55 | # CHECK2: DynamicSymbols [ |
| 56 | 56 | # CHECK2-NEXT: Symbol { |
| 57 | # CHECK2-NEXT: Name: @ | |
| 57 | # CHECK2-NEXT: Name: | |
| 58 | 58 | # CHECK2-NEXT: Value: 0x0 |
| 59 | 59 | # CHECK2-NEXT: Size: 0 |
| 60 | 60 | # CHECK2-NEXT: Binding: Local |
| ... | ... | @@ -63,7 +63,7 @@ |
| 63 | 63 | # CHECK2-NEXT: Section: Undefined |
| 64 | 64 | # CHECK2-NEXT: } |
| 65 | 65 | # CHECK2-NEXT: Symbol { |
| 66 | # CHECK2-NEXT: Name: foo1@ | |
| 66 | # CHECK2-NEXT: Name: foo1 | |
| 67 | 67 | # CHECK2-NEXT: Value: 0x201000 |
| 68 | 68 | # CHECK2-NEXT: Size: 0 |
| 69 | 69 | # CHECK2-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -72,7 +72,7 @@ |
| 72 | 72 | # CHECK2-NEXT: Section: .text (0x4) |
| 73 | 73 | # CHECK2-NEXT: } |
| 74 | 74 | # CHECK2-NEXT: Symbol { |
| 75 | # CHECK2-NEXT: Name: foo2@ | |
| 75 | # CHECK2-NEXT: Name: foo2 | |
| 76 | 76 | # CHECK2-NEXT: Value: 0x201001 |
| 77 | 77 | # CHECK2-NEXT: Size: 0 |
| 78 | 78 | # CHECK2-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -81,7 +81,7 @@ |
| 81 | 81 | # CHECK2-NEXT: Section: .text (0x4) |
| 82 | 82 | # CHECK2-NEXT: } |
| 83 | 83 | # CHECK2-NEXT: Symbol { |
| 84 | # CHECK2-NEXT: Name: foo31@ | |
| 84 | # CHECK2-NEXT: Name: foo31 | |
| 85 | 85 | # CHECK2-NEXT: Value: 0x201002 |
| 86 | 86 | # CHECK2-NEXT: Size: 0 |
| 87 | 87 | # CHECK2-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -104,7 +104,7 @@ |
| 104 | 104 | |
| 105 | 105 | # CHECK3: DynamicSymbols [ |
| 106 | 106 | # CHECK3-NEXT: Symbol { |
| 107 | # CHECK3-NEXT: Name: @ | |
| 107 | # CHECK3-NEXT: Name: | |
| 108 | 108 | # CHECK3-NEXT: Value: 0x0 |
| 109 | 109 | # CHECK3-NEXT: Size: 0 |
| 110 | 110 | # CHECK3-NEXT: Binding: Local |
| ... | ... | @@ -113,7 +113,7 @@ |
| 113 | 113 | # CHECK3-NEXT: Section: Undefined |
| 114 | 114 | # CHECK3-NEXT: } |
| 115 | 115 | # CHECK3-NEXT: Symbol { |
| 116 | # CHECK3-NEXT: Name: _start@ | |
| 116 | # CHECK3-NEXT: Name: _start | |
| 117 | 117 | # CHECK3-NEXT: Value: 0x201003 |
| 118 | 118 | # CHECK3-NEXT: Size: 0 |
| 119 | 119 | # CHECK3-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -122,7 +122,7 @@ |
| 122 | 122 | # CHECK3-NEXT: Section: .text (0x4) |
| 123 | 123 | # CHECK3-NEXT: } |
| 124 | 124 | # CHECK3-NEXT: Symbol { |
| 125 | # CHECK3-NEXT: Name: foo1@ | |
| 125 | # CHECK3-NEXT: Name: foo1 | |
| 126 | 126 | # CHECK3-NEXT: Value: 0x201000 |
| 127 | 127 | # CHECK3-NEXT: Size: 0 |
| 128 | 128 | # CHECK3-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -131,7 +131,7 @@ |
| 131 | 131 | # CHECK3-NEXT: Section: .text (0x4) |
| 132 | 132 | # CHECK3-NEXT: } |
| 133 | 133 | # CHECK3-NEXT: Symbol { |
| 134 | # CHECK3-NEXT: Name: foo2@ | |
| 134 | # CHECK3-NEXT: Name: foo2 | |
| 135 | 135 | # CHECK3-NEXT: Value: 0x201001 |
| 136 | 136 | # CHECK3-NEXT: Size: 0 |
| 137 | 137 | # CHECK3-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -140,7 +140,7 @@ |
| 140 | 140 | # CHECK3-NEXT: Section: .text (0x4) |
| 141 | 141 | # CHECK3-NEXT: } |
| 142 | 142 | # CHECK3-NEXT: Symbol { |
| 143 | # CHECK3-NEXT: Name: foo31@ | |
| 143 | # CHECK3-NEXT: Name: foo31 | |
| 144 | 144 | # CHECK3-NEXT: Value: 0x201002 |
| 145 | 145 | # CHECK3-NEXT: Size: 0 |
| 146 | 146 | # CHECK3-NEXT: Binding: Global (0x1) |
deps/lld/test/ELF/dynamic-reloc.s+1-1| ... | ... | @@ -18,7 +18,7 @@ |
| 18 | 18 | // CHECK-NEXT: Offset: |
| 19 | 19 | // CHECK-NEXT: Size: [[RELASIZE:.*]] |
| 20 | 20 | // CHECK-NEXT: Link: 1 |
| 21 | // CHECK-NEXT: Info: 0 | |
| 21 | // CHECK-NEXT: Info: 7 | |
| 22 | 22 | // CHECK-NEXT: AddressAlignment: 8 |
| 23 | 23 | // CHECK-NEXT: EntrySize: 24 |
| 24 | 24 |
deps/lld/test/ELF/dynsym-no-rosegment.s+2-2| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | # CHECK: DynamicSymbols [ |
| 7 | 7 | # CHECK-NEXT: Symbol { |
| 8 | # CHECK-NEXT: Name: @ (0) | |
| 8 | # CHECK-NEXT: Name: | |
| 9 | 9 | # CHECK-NEXT: Value: 0x0 |
| 10 | 10 | # CHECK-NEXT: Size: 0 |
| 11 | 11 | # CHECK-NEXT: Binding: Local |
| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | # CHECK-NEXT: Section: Undefined |
| 15 | 15 | # CHECK-NEXT: } |
| 16 | 16 | # CHECK-NEXT: Symbol { |
| 17 | # CHECK-NEXT: Name: undef@ | |
| 17 | # CHECK-NEXT: Name: undef | |
| 18 | 18 | # CHECK-NEXT: Value: 0x0 |
| 19 | 19 | # CHECK-NEXT: Size: 0 |
| 20 | 20 | # CHECK-NEXT: Binding: Global |
deps/lld/test/ELF/dynsym-pie.s+1-1| ... | ... | @@ -50,7 +50,7 @@ |
| 50 | 50 | |
| 51 | 51 | # CHECK: DynamicSymbols [ |
| 52 | 52 | # CHECK-NEXT: Symbol { |
| 53 | # CHECK-NEXT: Name: @ | |
| 53 | # CHECK-NEXT: Name: | |
| 54 | 54 | # CHECK-NEXT: Value: 0x0 |
| 55 | 55 | # CHECK-NEXT: Size: 0 |
| 56 | 56 | # CHECK-NEXT: Binding: Local |
deps/lld/test/ELF/edata-etext.s-1| ... | ... | @@ -18,7 +18,6 @@ |
| 18 | 18 | # CHECK-NEXT: 2 .data 00000002 0000000000202000 DATA |
| 19 | 19 | # CHECK-NEXT: 3 .bss 00000006 0000000000202004 BSS |
| 20 | 20 | # CHECK: SYMBOL TABLE: |
| 21 | # CHECK-NEXT: 0000000000000000 *UND* 00000000 | |
| 22 | 21 | # CHECK-NEXT: 0000000000202002 .data 00000000 _edata |
| 23 | 22 | # CHECK-NEXT: 000000000020200a .bss 00000000 _end |
| 24 | 23 | # CHECK-NEXT: 0000000000201001 .text 00000000 _etext |
deps/lld/test/ELF/emit-relocs-icf1.s created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: ld.lld --emit-relocs --icf=all %t.o -o %t | |
| 4 | # RUN: llvm-readobj -r %t | FileCheck %s | |
| 5 | ||
| 6 | # CHECK: Relocations [ | |
| 7 | # CHECK-NEXT: Section (3) .rela.text { | |
| 8 | # CHECK-NEXT: 0x201000 R_X86_64_64 .text 0x11 | |
| 9 | # CHECK-NEXT: 0x201008 R_X86_64_64 .text 0x11 | |
| 10 | # CHECK-NEXT: 0x201011 R_X86_64_64 .rodata 0x0 | |
| 11 | # CHECK-NEXT: } | |
| 12 | # CHECK-NEXT: ] | |
| 13 | ||
| 14 | .rodata | |
| 15 | quux: | |
| 16 | .quad 0xfe | |
| 17 | ||
| 18 | .section .text.foo,"ax" | |
| 19 | foo: | |
| 20 | .quad quux | |
| 21 | ||
| 22 | .section .text.bar,"ax" | |
| 23 | bar: | |
| 24 | .quad quux | |
| 25 | ||
| 26 | .text | |
| 27 | .quad foo | |
| 28 | .quad bar | |
| 29 | ||
| 30 | .global _start | |
| 31 | _start: | |
| 32 | nop |
deps/lld/test/ELF/emit-relocs-icf2.s created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: ld.lld --gc-sections --emit-relocs --icf=all %t.o -o %t | |
| 4 | # RUN: llvm-readobj -r %t | FileCheck %s | |
| 5 | ||
| 6 | # CHECK: Relocations [ | |
| 7 | # CHECK-NEXT: Section (3) .rela.text { | |
| 8 | # CHECK-NEXT: 0x201000 R_X86_64_64 .text 0x11 | |
| 9 | # CHECK-NEXT: 0x201008 R_X86_64_64 .text 0x11 | |
| 10 | # CHECK-NEXT: 0x201011 R_X86_64_64 .rodata 0x0 | |
| 11 | # CHECK-NEXT: } | |
| 12 | # CHECK-NEXT: ] | |
| 13 | ||
| 14 | .rodata | |
| 15 | quux: | |
| 16 | .quad 0xfe | |
| 17 | ||
| 18 | .section .text.foo,"ax" | |
| 19 | foo: | |
| 20 | .quad quux | |
| 21 | ||
| 22 | .section .text.bar,"ax" | |
| 23 | bar: | |
| 24 | .quad quux | |
| 25 | ||
| 26 | .section .text.baz,"ax" | |
| 27 | baz: | |
| 28 | .quad quux | |
| 29 | ||
| 30 | .text | |
| 31 | .quad foo | |
| 32 | .quad bar | |
| 33 | ||
| 34 | .global _start | |
| 35 | _start: | |
| 36 | nop |
deps/lld/test/ELF/empty-pack-dyn-relocs.s created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | ||
| 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 4 | // RUN: ld.lld -pie --pack-dyn-relocs=relr %t.o -o %t | |
| 5 | // RUN: llvm-readobj -sections %t | FileCheck %s | |
| 6 | ||
| 7 | .global _start | |
| 8 | _start: | |
| 9 | nop | |
| 10 | ||
| 11 | # CHECK-NOT: Name: .relr.dyn |
deps/lld/test/ELF/empty-ver.s+1-1| ... | ... | @@ -29,7 +29,7 @@ |
| 29 | 29 | // CHECK-NEXT: Symbols [ |
| 30 | 30 | // CHECK-NEXT: Symbol { |
| 31 | 31 | // CHECK-NEXT: Version: 0 |
| 32 | // CHECK-NEXT: Name: @ | |
| 32 | // CHECK-NEXT: Name: | |
| 33 | 33 | // CHECK-NEXT: } |
| 34 | 34 | // CHECK-NEXT: Symbol { |
| 35 | 35 | // CHECK-NEXT: Version: 2 |
deps/lld/test/ELF/empty-ver2.s+2-2| ... | ... | @@ -8,11 +8,11 @@ |
| 8 | 8 | # CHECK: Symbols [ |
| 9 | 9 | # CHECK-NEXT: Symbol { |
| 10 | 10 | # CHECK-NEXT: Version: 0 |
| 11 | # CHECK-NEXT: Name: @ | |
| 11 | # CHECK-NEXT: Name: | |
| 12 | 12 | # CHECK-NEXT: } |
| 13 | 13 | # CHECK-NEXT: Symbol { |
| 14 | 14 | # CHECK-NEXT: Version: 1 |
| 15 | # CHECK-NEXT: Name: bar@@ | |
| 15 | # CHECK-NEXT: Name: bar@ | |
| 16 | 16 | # CHECK-NEXT: } |
| 17 | 17 | # CHECK-NEXT: ] |
| 18 | 18 |
deps/lld/test/ELF/emulation-aarch64.s created+57| ... | ... | @@ -0,0 +1,57 @@ |
| 1 | # REQUIRES: aarch64 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %taarch64 | |
| 3 | # RUN: ld.lld -m aarch64linux %taarch64 -o %t2aarch64 | |
| 4 | # RUN: llvm-readobj -file-headers %t2aarch64 | FileCheck --check-prefix=AARCH64 %s | |
| 5 | # RUN: ld.lld -m aarch64elf %taarch64 -o %t3aarch64 | |
| 6 | # RUN: llvm-readobj -file-headers %t3aarch64 | FileCheck --check-prefix=AARCH64 %s | |
| 7 | # RUN: ld.lld -m aarch64_elf64_le_vec %taarch64 -o %t4aarch64 | |
| 8 | # RUN: llvm-readobj -file-headers %t4aarch64 | FileCheck --check-prefix=AARCH64 %s | |
| 9 | # RUN: ld.lld %taarch64 -o %t5aarch64 | |
| 10 | # RUN: llvm-readobj -file-headers %t5aarch64 | FileCheck --check-prefix=AARCH64 %s | |
| 11 | # RUN: echo 'OUTPUT_FORMAT(elf64-littleaarch64)' > %t4aarch64.script | |
| 12 | # RUN: ld.lld %t4aarch64.script %taarch64 -o %t4aarch64 | |
| 13 | # RUN: llvm-readobj -file-headers %t4aarch64 | FileCheck --check-prefix=AARCH64 %s | |
| 14 | # AARCH64: ElfHeader { | |
| 15 | # AARCH64-NEXT: Ident { | |
| 16 | # AARCH64-NEXT: Magic: (7F 45 4C 46) | |
| 17 | # AARCH64-NEXT: Class: 64-bit (0x2) | |
| 18 | # AARCH64-NEXT: DataEncoding: LittleEndian (0x1) | |
| 19 | # AARCH64-NEXT: FileVersion: 1 | |
| 20 | # AARCH64-NEXT: OS/ABI: SystemV (0x0) | |
| 21 | # AARCH64-NEXT: ABIVersion: 0 | |
| 22 | # AARCH64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 23 | # AARCH64-NEXT: } | |
| 24 | # AARCH64-NEXT: Type: Executable (0x2) | |
| 25 | # AARCH64-NEXT: Machine: EM_AARCH64 (0xB7) | |
| 26 | # AARCH64-NEXT: Version: 1 | |
| 27 | # AARCH64-NEXT: Entry: | |
| 28 | # AARCH64-NEXT: ProgramHeaderOffset: 0x40 | |
| 29 | # AARCH64-NEXT: SectionHeaderOffset: | |
| 30 | # AARCH64-NEXT: Flags [ (0x0) | |
| 31 | # AARCH64-NEXT: ] | |
| 32 | ||
| 33 | # RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %taarch64fbsd | |
| 34 | # RUN: echo 'OUTPUT_FORMAT(elf64-aarch64-freebsd)' > %taarch64fbsd.script | |
| 35 | # RUN: ld.lld %taarch64fbsd.script %taarch64fbsd -o %t2aarch64fbsd | |
| 36 | # RUN: llvm-readobj -file-headers %t2aarch64fbsd | FileCheck --check-prefix=AARCH64-FBSD %s | |
| 37 | # AARCH64-FBSD: ElfHeader { | |
| 38 | # AARCH64-FBSD-NEXT: Ident { | |
| 39 | # AARCH64-FBSD-NEXT: Magic: (7F 45 4C 46) | |
| 40 | # AARCH64-FBSD-NEXT: Class: 64-bit (0x2) | |
| 41 | # AARCH64-FBSD-NEXT: DataEncoding: LittleEndian (0x1) | |
| 42 | # AARCH64-FBSD-NEXT: FileVersion: 1 | |
| 43 | # AARCH64-FBSD-NEXT: OS/ABI: FreeBSD (0x9) | |
| 44 | # AARCH64-FBSD-NEXT: ABIVersion: 0 | |
| 45 | # AARCH64-FBSD-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 46 | # AARCH64-FBSD-NEXT: } | |
| 47 | # AARCH64-FBSD-NEXT: Type: Executable (0x2) | |
| 48 | # AARCH64-FBSD-NEXT: Machine: EM_AARCH64 (0xB7) | |
| 49 | # AARCH64-FBSD-NEXT: Version: 1 | |
| 50 | # AARCH64-FBSD-NEXT: Entry: | |
| 51 | # AARCH64-FBSD-NEXT: ProgramHeaderOffset: 0x40 | |
| 52 | # AARCH64-FBSD-NEXT: SectionHeaderOffset: | |
| 53 | # AARCH64-FBSD-NEXT: Flags [ (0x0) | |
| 54 | # AARCH64-FBSD-NEXT: ] | |
| 55 | ||
| 56 | .globl _start | |
| 57 | _start: |
deps/lld/test/ELF/emulation-arm.s created+27| ... | ... | @@ -0,0 +1,27 @@ |
| 1 | # REQUIRES: arm | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=armv7-unknown-linux %s -o %tarm | |
| 3 | # RUN: ld.lld -m armelf %tarm -o %t2arm | |
| 4 | # RUN: llvm-readobj -file-headers %t2arm | FileCheck --check-prefix=ARM %s | |
| 5 | # RUN: ld.lld -m armelf_linux_eabi %tarm -o %t3arm | |
| 6 | # RUN: llvm-readobj -file-headers %t3arm | FileCheck --check-prefix=ARM %s | |
| 7 | # RUN: ld.lld %tarm -o %t4arm | |
| 8 | # RUN: llvm-readobj -file-headers %t4arm | FileCheck --check-prefix=ARM %s | |
| 9 | # RUN: echo 'OUTPUT_FORMAT(elf32-littlearm)' > %t5arm.script | |
| 10 | # RUN: ld.lld %t5arm.script %tarm -o %t5arm | |
| 11 | # RUN: llvm-readobj -file-headers %t5arm | FileCheck --check-prefix=ARM %s | |
| 12 | # ARM: ElfHeader { | |
| 13 | # ARM-NEXT: Ident { | |
| 14 | # ARM-NEXT: Magic: (7F 45 4C 46) | |
| 15 | # ARM-NEXT: Class: 32-bit (0x1) | |
| 16 | # ARM-NEXT: DataEncoding: LittleEndian (0x1) | |
| 17 | # ARM-NEXT: FileVersion: 1 | |
| 18 | # ARM-NEXT: OS/ABI: SystemV (0x0) | |
| 19 | # ARM-NEXT: ABIVersion: 0 | |
| 20 | # ARM-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 21 | # ARM-NEXT: } | |
| 22 | # ARM-NEXT: Type: Executable (0x2) | |
| 23 | # ARM-NEXT: Machine: EM_ARM (0x28) | |
| 24 | # ARM-NEXT: Version: 1 | |
| 25 | ||
| 26 | .globl _start | |
| 27 | _start: |
deps/lld/test/ELF/emulation-mips.s created+189| ... | ... | @@ -0,0 +1,189 @@ |
| 1 | # REQUIRES: mips | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %tmips | |
| 3 | # RUN: ld.lld -m elf32btsmip -e _start %tmips -o %t2mips | |
| 4 | # RUN: llvm-readobj -file-headers %t2mips | FileCheck --check-prefix=MIPS %s | |
| 5 | # RUN: ld.lld %tmips -e _start -o %t3mips | |
| 6 | # RUN: llvm-readobj -file-headers %t3mips | FileCheck --check-prefix=MIPS %s | |
| 7 | # RUN: echo 'OUTPUT_FORMAT(elf32-tradbigmips)' > %tmips.script | |
| 8 | # RUN: ld.lld %tmips.script -e _start %tmips -o %t4mips | |
| 9 | # RUN: llvm-readobj -file-headers %t4mips | FileCheck --check-prefix=MIPS %s | |
| 10 | # MIPS: ElfHeader { | |
| 11 | # MIPS-NEXT: Ident { | |
| 12 | # MIPS-NEXT: Magic: (7F 45 4C 46) | |
| 13 | # MIPS-NEXT: Class: 32-bit (0x1) | |
| 14 | # MIPS-NEXT: DataEncoding: BigEndian (0x2) | |
| 15 | # MIPS-NEXT: FileVersion: 1 | |
| 16 | # MIPS-NEXT: OS/ABI: SystemV (0x0) | |
| 17 | # MIPS-NEXT: ABIVersion: 1 | |
| 18 | # MIPS-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 19 | # MIPS-NEXT: } | |
| 20 | # MIPS-NEXT: Type: Executable (0x2) | |
| 21 | # MIPS-NEXT: Machine: EM_MIPS (0x8) | |
| 22 | # MIPS-NEXT: Version: 1 | |
| 23 | # MIPS-NEXT: Entry: | |
| 24 | # MIPS-NEXT: ProgramHeaderOffset: 0x34 | |
| 25 | # MIPS-NEXT: SectionHeaderOffset: | |
| 26 | # MIPS-NEXT: Flags [ | |
| 27 | # MIPS-NEXT: EF_MIPS_ABI_O32 | |
| 28 | # MIPS-NEXT: EF_MIPS_ARCH_32 | |
| 29 | # MIPS-NEXT: EF_MIPS_CPIC | |
| 30 | # MIPS-NEXT: ] | |
| 31 | ||
| 32 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %tmipsel | |
| 33 | # RUN: ld.lld -m elf32ltsmip -e _start %tmipsel -o %t2mipsel | |
| 34 | # RUN: llvm-readobj -file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s | |
| 35 | # RUN: ld.lld -melf32ltsmip -e _start %tmipsel -o %t2mipsel | |
| 36 | # RUN: llvm-readobj -file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s | |
| 37 | # RUN: ld.lld %tmipsel -e _start -o %t3mipsel | |
| 38 | # RUN: llvm-readobj -file-headers %t3mipsel | FileCheck --check-prefix=MIPSEL %s | |
| 39 | # RUN: echo 'OUTPUT_FORMAT(elf32-tradlittlemips)' > %tmipsel.script | |
| 40 | # RUN: ld.lld %tmipsel.script -e _start %tmipsel -o %t4mipsel | |
| 41 | # RUN: llvm-readobj -file-headers %t4mipsel | FileCheck --check-prefix=MIPSEL %s | |
| 42 | # MIPSEL: ElfHeader { | |
| 43 | # MIPSEL-NEXT: Ident { | |
| 44 | # MIPSEL-NEXT: Magic: (7F 45 4C 46) | |
| 45 | # MIPSEL-NEXT: Class: 32-bit (0x1) | |
| 46 | # MIPSEL-NEXT: DataEncoding: LittleEndian (0x1) | |
| 47 | # MIPSEL-NEXT: FileVersion: 1 | |
| 48 | # MIPSEL-NEXT: OS/ABI: SystemV (0x0) | |
| 49 | # MIPSEL-NEXT: ABIVersion: 1 | |
| 50 | # MIPSEL-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 51 | # MIPSEL-NEXT: } | |
| 52 | # MIPSEL-NEXT: Type: Executable (0x2) | |
| 53 | # MIPSEL-NEXT: Machine: EM_MIPS (0x8) | |
| 54 | # MIPSEL-NEXT: Version: 1 | |
| 55 | # MIPSEL-NEXT: Entry: | |
| 56 | # MIPSEL-NEXT: ProgramHeaderOffset: 0x34 | |
| 57 | # MIPSEL-NEXT: SectionHeaderOffset: | |
| 58 | # MIPSEL-NEXT: Flags [ | |
| 59 | # MIPSEL-NEXT: EF_MIPS_ABI_O32 | |
| 60 | # MIPSEL-NEXT: EF_MIPS_ARCH_32 | |
| 61 | # MIPSEL-NEXT: EF_MIPS_CPIC | |
| 62 | # MIPSEL-NEXT: ] | |
| 63 | ||
| 64 | # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux-gnuabin32 %s -o %tmipsn32 | |
| 65 | # RUN: ld.lld -m elf32btsmipn32 -e _start %tmipsn32 -o %t2mipsn32 | |
| 66 | # RUN: llvm-readobj -file-headers %t2mipsn32 | FileCheck --check-prefix=MIPSN32 %s | |
| 67 | # RUN: ld.lld %tmipsn32 -e _start -o %t3mipsn32 | |
| 68 | # RUN: llvm-readobj -file-headers %t3mipsn32 | FileCheck --check-prefix=MIPSN32 %s | |
| 69 | # RUN: echo 'OUTPUT_FORMAT(elf32-ntradbigmips)' > %tmipsn32.script | |
| 70 | # RUN: ld.lld %tmipsn32.script -e _start %tmipsn32 -o %t4mipsn32 | |
| 71 | # RUN: llvm-readobj -file-headers %t4mipsn32 | FileCheck --check-prefix=MIPSN32 %s | |
| 72 | # MIPSN32: ElfHeader { | |
| 73 | # MIPSN32-NEXT: Ident { | |
| 74 | # MIPSN32-NEXT: Magic: (7F 45 4C 46) | |
| 75 | # MIPSN32-NEXT: Class: 32-bit (0x1) | |
| 76 | # MIPSN32-NEXT: DataEncoding: BigEndian (0x2) | |
| 77 | # MIPSN32-NEXT: FileVersion: 1 | |
| 78 | # MIPSN32-NEXT: OS/ABI: SystemV (0x0) | |
| 79 | # MIPSN32-NEXT: ABIVersion: 1 | |
| 80 | # MIPSN32-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 81 | # MIPSN32-NEXT: } | |
| 82 | # MIPSN32-NEXT: Type: Executable (0x2) | |
| 83 | # MIPSN32-NEXT: Machine: EM_MIPS (0x8) | |
| 84 | # MIPSN32-NEXT: Version: 1 | |
| 85 | # MIPSN32-NEXT: Entry: | |
| 86 | # MIPSN32-NEXT: ProgramHeaderOffset: 0x34 | |
| 87 | # MIPSN32-NEXT: SectionHeaderOffset: | |
| 88 | # MIPSN32-NEXT: Flags [ | |
| 89 | # MIPSN32-NEXT: EF_MIPS_ABI2 | |
| 90 | # MIPSN32-NEXT: EF_MIPS_ARCH_64 | |
| 91 | # MIPSN32-NEXT: EF_MIPS_CPIC | |
| 92 | # MIPSN32-NEXT: ] | |
| 93 | ||
| 94 | # RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux-gnuabin32 %s -o %tmipsn32el | |
| 95 | # RUN: ld.lld -m elf32ltsmipn32 -e _start %tmipsn32el -o %t2mipsn32el | |
| 96 | # RUN: llvm-readobj -file-headers %t2mipsn32el | FileCheck --check-prefix=MIPSN32EL %s | |
| 97 | # RUN: ld.lld -melf32ltsmipn32 -e _start %tmipsn32el -o %t2mipsn32el | |
| 98 | # RUN: llvm-readobj -file-headers %t2mipsn32el | FileCheck --check-prefix=MIPSN32EL %s | |
| 99 | # RUN: ld.lld %tmipsn32el -e _start -o %t3mipsn32el | |
| 100 | # RUN: llvm-readobj -file-headers %t3mipsn32el | FileCheck --check-prefix=MIPSN32EL %s | |
| 101 | # RUN: echo 'OUTPUT_FORMAT(elf32-ntradlittlemips)' > %tmipsn32el.script | |
| 102 | # RUN: ld.lld %tmipsn32el.script -e _start %tmipsn32el -o %t4mipsn32el | |
| 103 | # RUN: llvm-readobj -file-headers %t4mipsn32el | FileCheck --check-prefix=MIPSN32EL %s | |
| 104 | # MIPSN32EL: ElfHeader { | |
| 105 | # MIPSN32EL-NEXT: Ident { | |
| 106 | # MIPSN32EL-NEXT: Magic: (7F 45 4C 46) | |
| 107 | # MIPSN32EL-NEXT: Class: 32-bit (0x1) | |
| 108 | # MIPSN32EL-NEXT: DataEncoding: LittleEndian (0x1) | |
| 109 | # MIPSN32EL-NEXT: FileVersion: 1 | |
| 110 | # MIPSN32EL-NEXT: OS/ABI: SystemV (0x0) | |
| 111 | # MIPSN32EL-NEXT: ABIVersion: 1 | |
| 112 | # MIPSN32EL-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 113 | # MIPSN32EL-NEXT: } | |
| 114 | # MIPSN32EL-NEXT: Type: Executable (0x2) | |
| 115 | # MIPSN32EL-NEXT: Machine: EM_MIPS (0x8) | |
| 116 | # MIPSN32EL-NEXT: Version: 1 | |
| 117 | # MIPSN32EL-NEXT: Entry: | |
| 118 | # MIPSN32EL-NEXT: ProgramHeaderOffset: 0x34 | |
| 119 | # MIPSN32EL-NEXT: SectionHeaderOffset: | |
| 120 | # MIPSN32EL-NEXT: Flags [ | |
| 121 | # MIPSN32EL-NEXT: EF_MIPS_ABI2 | |
| 122 | # MIPSN32EL-NEXT: EF_MIPS_ARCH_64 | |
| 123 | # MIPSN32EL-NEXT: EF_MIPS_CPIC | |
| 124 | # MIPSN32EL-NEXT: ] | |
| 125 | ||
| 126 | # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -position-independent \ | |
| 127 | # RUN: %s -o %tmips64 | |
| 128 | # RUN: ld.lld -m elf64btsmip -e _start %tmips64 -o %t2mips64 | |
| 129 | # RUN: llvm-readobj -file-headers %t2mips64 | FileCheck --check-prefix=MIPS64 %s | |
| 130 | # RUN: ld.lld %tmips64 -e _start -o %t3mips64 | |
| 131 | # RUN: llvm-readobj -file-headers %t3mips64 | FileCheck --check-prefix=MIPS64 %s | |
| 132 | # RUN: echo 'OUTPUT_FORMAT(elf64-tradbigmips)' > %tmips64.script | |
| 133 | # RUN: ld.lld %tmips64.script -e _start %tmips64 -o %t4mips64 | |
| 134 | # RUN: llvm-readobj -file-headers %t4mips64 | FileCheck --check-prefix=MIPS64 %s | |
| 135 | # MIPS64: ElfHeader { | |
| 136 | # MIPS64-NEXT: Ident { | |
| 137 | # MIPS64-NEXT: Magic: (7F 45 4C 46) | |
| 138 | # MIPS64-NEXT: Class: 64-bit (0x2) | |
| 139 | # MIPS64-NEXT: DataEncoding: BigEndian (0x2) | |
| 140 | # MIPS64-NEXT: FileVersion: 1 | |
| 141 | # MIPS64-NEXT: OS/ABI: SystemV (0x0) | |
| 142 | # MIPS64-NEXT: ABIVersion: 0 | |
| 143 | # MIPS64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 144 | # MIPS64-NEXT: } | |
| 145 | # MIPS64-NEXT: Type: Executable (0x2) | |
| 146 | # MIPS64-NEXT: Machine: EM_MIPS (0x8) | |
| 147 | # MIPS64-NEXT: Version: 1 | |
| 148 | # MIPS64-NEXT: Entry: | |
| 149 | # MIPS64-NEXT: ProgramHeaderOffset: 0x40 | |
| 150 | # MIPS64-NEXT: SectionHeaderOffset: | |
| 151 | # MIPS64-NEXT: Flags [ | |
| 152 | # MIPS64-NEXT: EF_MIPS_ARCH_64 | |
| 153 | # MIPS64-NEXT: EF_MIPS_CPIC | |
| 154 | # MIPS64-NEXT: EF_MIPS_PIC | |
| 155 | # MIPS64-NEXT: ] | |
| 156 | ||
| 157 | # RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux \ | |
| 158 | # RUN: -position-independent %s -o %tmips64el | |
| 159 | # RUN: ld.lld -m elf64ltsmip -e _start %tmips64el -o %t2mips64el | |
| 160 | # RUN: llvm-readobj -file-headers %t2mips64el | FileCheck --check-prefix=MIPS64EL %s | |
| 161 | # RUN: ld.lld %tmips64el -e _start -o %t3mips64el | |
| 162 | # RUN: llvm-readobj -file-headers %t3mips64el | FileCheck --check-prefix=MIPS64EL %s | |
| 163 | # RUN: echo 'OUTPUT_FORMAT(elf64-tradlittlemips)' > %tmips64el.script | |
| 164 | # RUN: ld.lld %tmips64el.script -e _start %tmips64el -o %t4mips64el | |
| 165 | # RUN: llvm-readobj -file-headers %t4mips64el | FileCheck --check-prefix=MIPS64EL %s | |
| 166 | # MIPS64EL: ElfHeader { | |
| 167 | # MIPS64EL-NEXT: Ident { | |
| 168 | # MIPS64EL-NEXT: Magic: (7F 45 4C 46) | |
| 169 | # MIPS64EL-NEXT: Class: 64-bit (0x2) | |
| 170 | # MIPS64EL-NEXT: DataEncoding: LittleEndian (0x1) | |
| 171 | # MIPS64EL-NEXT: FileVersion: 1 | |
| 172 | # MIPS64EL-NEXT: OS/ABI: SystemV (0x0) | |
| 173 | # MIPS64EL-NEXT: ABIVersion: 0 | |
| 174 | # MIPS64EL-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 175 | # MIPS64EL-NEXT: } | |
| 176 | # MIPS64EL-NEXT: Type: Executable (0x2) | |
| 177 | # MIPS64EL-NEXT: Machine: EM_MIPS (0x8) | |
| 178 | # MIPS64EL-NEXT: Version: 1 | |
| 179 | # MIPS64EL-NEXT: Entry: | |
| 180 | # MIPS64EL-NEXT: ProgramHeaderOffset: 0x40 | |
| 181 | # MIPS64EL-NEXT: SectionHeaderOffset: | |
| 182 | # MIPS64EL-NEXT: Flags [ | |
| 183 | # MIPS64EL-NEXT: EF_MIPS_ARCH_64 | |
| 184 | # MIPS64EL-NEXT: EF_MIPS_CPIC | |
| 185 | # MIPS64EL-NEXT: EF_MIPS_PIC | |
| 186 | # MIPS64EL-NEXT: ] | |
| 187 | ||
| 188 | .globl _start | |
| 189 | _start: |
deps/lld/test/ELF/emulation-ppc.s created+107| ... | ... | @@ -0,0 +1,107 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %tppc64 | |
| 3 | # RUN: ld.lld -m elf64ppc %tppc64 -o %t2ppc64 | |
| 4 | # RUN: llvm-readobj -file-headers %t2ppc64 | FileCheck --check-prefix=PPC64 %s | |
| 5 | # RUN: ld.lld %tppc64 -o %t3ppc64 | |
| 6 | # RUN: llvm-readobj -file-headers %t3ppc64 | FileCheck --check-prefix=PPC64 %s | |
| 7 | # RUN: echo 'OUTPUT_FORMAT(elf64-powerpc)' > %tppc64.script | |
| 8 | # RUN: ld.lld %tppc64.script %tppc64 -o %t4ppc64 | |
| 9 | # RUN: llvm-readobj -file-headers %t4ppc64 | FileCheck --check-prefix=PPC64 %s | |
| 10 | ||
| 11 | # PPC64: ElfHeader { | |
| 12 | # PPC64-NEXT: Ident { | |
| 13 | # PPC64-NEXT: Magic: (7F 45 4C 46) | |
| 14 | # PPC64-NEXT: Class: 64-bit (0x2) | |
| 15 | # PPC64-NEXT: DataEncoding: BigEndian (0x2) | |
| 16 | # PPC64-NEXT: FileVersion: 1 | |
| 17 | # PPC64-NEXT: OS/ABI: SystemV (0x0) | |
| 18 | # PPC64-NEXT: ABIVersion: 0 | |
| 19 | # PPC64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 20 | # PPC64-NEXT: } | |
| 21 | # PPC64-NEXT: Type: Executable (0x2) | |
| 22 | # PPC64-NEXT: Machine: EM_PPC64 (0x15) | |
| 23 | # PPC64-NEXT: Version: 1 | |
| 24 | # PPC64-NEXT: Entry: | |
| 25 | # PPC64-NEXT: ProgramHeaderOffset: 0x40 | |
| 26 | # PPC64-NEXT: SectionHeaderOffset: | |
| 27 | # PPC64-NEXT: Flags [ (0x2) | |
| 28 | # PPC64-NEXT: 0x2 | |
| 29 | # PPC64-NEXT: ] | |
| 30 | # PPC64-NEXT: HeaderSize: 64 | |
| 31 | # PPC64-NEXT: ProgramHeaderEntrySize: 56 | |
| 32 | # PPC64-NEXT: ProgramHeaderCount: | |
| 33 | # PPC64-NEXT: SectionHeaderEntrySize: 64 | |
| 34 | # PPC64-NEXT: SectionHeaderCount: | |
| 35 | # PPC64-NEXT: StringTableSectionIndex: | |
| 36 | # PPC64-NEXT: } | |
| 37 | ||
| 38 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-freebsd %s -o %tppc64fbsd | |
| 39 | # RUN: echo 'OUTPUT_FORMAT(elf64-powerpc-freebsd)' > %tppc64fbsd.script | |
| 40 | # RUN: ld.lld %tppc64fbsd.script %tppc64fbsd -o %t2ppc64fbsd | |
| 41 | # RUN: llvm-readobj -file-headers %t2ppc64fbsd | FileCheck --check-prefix=PPC64-FBSD %s | |
| 42 | ||
| 43 | # PPC64-FBSD: ElfHeader { | |
| 44 | # PPC64-FBSD-NEXT: Ident { | |
| 45 | # PPC64-FBSD-NEXT: Magic: (7F 45 4C 46) | |
| 46 | # PPC64-FBSD-NEXT: Class: 64-bit (0x2) | |
| 47 | # PPC64-FBSD-NEXT: DataEncoding: BigEndian (0x2) | |
| 48 | # PPC64-FBSD-NEXT: FileVersion: 1 | |
| 49 | # PPC64-FBSD-NEXT: OS/ABI: FreeBSD (0x9) | |
| 50 | # PPC64-FBSD-NEXT: ABIVersion: 0 | |
| 51 | # PPC64-FBSD-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 52 | # PPC64-FBSD-NEXT: } | |
| 53 | # PPC64-FBSD-NEXT: Type: Executable (0x2) | |
| 54 | # PPC64-FBSD-NEXT: Machine: EM_PPC64 (0x15) | |
| 55 | # PPC64-FBSD-NEXT: Version: 1 | |
| 56 | # PPC64-FBSD-NEXT: Entry: | |
| 57 | # PPC64-FBSD-NEXT: ProgramHeaderOffset: 0x40 | |
| 58 | # PPC64-FBSD-NEXT: SectionHeaderOffset: | |
| 59 | # PPC64-FBSD-NEXT: Flags [ (0x2) | |
| 60 | # PPC64-FBSD-NEXT: 0x2 | |
| 61 | # PPC64-FBSD-NEXT: ] | |
| 62 | # PPC64-FBSD-NEXT: HeaderSize: 64 | |
| 63 | # PPC64-FBSD-NEXT: ProgramHeaderEntrySize: 56 | |
| 64 | # PPC64-FBSD-NEXT: ProgramHeaderCount: | |
| 65 | # PPC64-FBSD-NEXT: SectionHeaderEntrySize: 64 | |
| 66 | # PPC64-FBSD-NEXT: SectionHeaderCount: | |
| 67 | # PPC64-FBSD-NEXT: StringTableSectionIndex: | |
| 68 | # PPC64-FBSD-NEXT: } | |
| 69 | ||
| 70 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %tppc64le | |
| 71 | # RUN: ld.lld -m elf64lppc %tppc64le -o %t2ppc64le | |
| 72 | # RUN: llvm-readobj -file-headers %t2ppc64le | FileCheck --check-prefix=PPC64LE %s | |
| 73 | # RUN: ld.lld %tppc64le -o %t3ppc64le | |
| 74 | # RUN: llvm-readobj -file-headers %t3ppc64le | FileCheck --check-prefix=PPC64LE %s | |
| 75 | # RUN: echo 'OUTPUT_FORMAT(elf64-powerpcle)' > %tppc64le.script | |
| 76 | # RUN: ld.lld %tppc64le.script %tppc64le -o %t4ppc64le | |
| 77 | # RUN: llvm-readobj -file-headers %t4ppc64le | FileCheck --check-prefix=PPC64LE %s | |
| 78 | ||
| 79 | # PPC64LE: ElfHeader { | |
| 80 | # PPC64LE-NEXT: Ident { | |
| 81 | # PPC64LE-NEXT: Magic: (7F 45 4C 46) | |
| 82 | # PPC64LE-NEXT: Class: 64-bit (0x2) | |
| 83 | # PPC64LE-NEXT: DataEncoding: LittleEndian (0x1) | |
| 84 | # PPC64LE-NEXT: FileVersion: 1 | |
| 85 | # PPC64LE-NEXT: OS/ABI: SystemV (0x0) | |
| 86 | # PPC64LE-NEXT: ABIVersion: 0 | |
| 87 | # PPC64LE-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 88 | # PPC64LE-NEXT: } | |
| 89 | # PPC64LE-NEXT: Type: Executable (0x2) | |
| 90 | # PPC64LE-NEXT: Machine: EM_PPC64 (0x15) | |
| 91 | # PPC64LE-NEXT: Version: 1 | |
| 92 | # PPC64LE-NEXT: Entry: | |
| 93 | # PPC64LE-NEXT: ProgramHeaderOffset: 0x40 | |
| 94 | # PPC64LE-NEXT: SectionHeaderOffset: | |
| 95 | # PPC64LE-NEXT: Flags [ (0x2) | |
| 96 | # PPC64LE-NEXT: 0x2 | |
| 97 | # PPC64LE-NEXT: ] | |
| 98 | # PPC64LE-NEXT: HeaderSize: 64 | |
| 99 | # PPC64LE-NEXT: ProgramHeaderEntrySize: 56 | |
| 100 | # PPC64LE-NEXT: ProgramHeaderCount: | |
| 101 | # PPC64LE-NEXT: SectionHeaderEntrySize: 64 | |
| 102 | # PPC64LE-NEXT: SectionHeaderCount: | |
| 103 | # PPC64LE-NEXT: StringTableSectionIndex: | |
| 104 | # PPC64LE-NEXT: } | |
| 105 | ||
| 106 | .globl _start | |
| 107 | _start: |
deps/lld/test/ELF/emulation-x86.s created+211| ... | ... | @@ -0,0 +1,211 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %tx64 | |
| 3 | # RUN: ld.lld -m elf_amd64_fbsd %tx64 -o %t2x64 | |
| 4 | # RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=AMD64 %s | |
| 5 | # RUN: ld.lld %tx64 -o %t3x64 | |
| 6 | # RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=AMD64 %s | |
| 7 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.sysv | |
| 8 | # RUN: ld.lld -m elf_amd64_fbsd %t.sysv -o %t.freebsd | |
| 9 | # RUN: llvm-readobj -file-headers %t.freebsd | FileCheck --check-prefix=AMD64 %s | |
| 10 | # RUN: echo 'OUTPUT_FORMAT(elf64-x86-64-freebsd)' > %t4x64.script | |
| 11 | # RUN: ld.lld %t4x64.script %tx64 -o %t4x64 | |
| 12 | # RUN: llvm-readobj -file-headers %t4x64 | FileCheck --check-prefix=AMD64 %s | |
| 13 | # AMD64: ElfHeader { | |
| 14 | # AMD64-NEXT: Ident { | |
| 15 | # AMD64-NEXT: Magic: (7F 45 4C 46) | |
| 16 | # AMD64-NEXT: Class: 64-bit (0x2) | |
| 17 | # AMD64-NEXT: DataEncoding: LittleEndian (0x1) | |
| 18 | # AMD64-NEXT: FileVersion: 1 | |
| 19 | # AMD64-NEXT: OS/ABI: FreeBSD (0x9) | |
| 20 | # AMD64-NEXT: ABIVersion: 0 | |
| 21 | # AMD64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 22 | # AMD64-NEXT: } | |
| 23 | # AMD64-NEXT: Type: Executable (0x2) | |
| 24 | # AMD64-NEXT: Machine: EM_X86_64 (0x3E) | |
| 25 | # AMD64-NEXT: Version: 1 | |
| 26 | # AMD64-NEXT: Entry: | |
| 27 | # AMD64-NEXT: ProgramHeaderOffset: 0x40 | |
| 28 | # AMD64-NEXT: SectionHeaderOffset: | |
| 29 | # AMD64-NEXT: Flags [ (0x0) | |
| 30 | # AMD64-NEXT: ] | |
| 31 | # AMD64-NEXT: HeaderSize: 64 | |
| 32 | # AMD64-NEXT: ProgramHeaderEntrySize: 56 | |
| 33 | # AMD64-NEXT: ProgramHeaderCount: | |
| 34 | # AMD64-NEXT: SectionHeaderEntrySize: 64 | |
| 35 | # AMD64-NEXT: SectionHeaderCount: | |
| 36 | # AMD64-NEXT: StringTableSectionIndex: | |
| 37 | # AMD64-NEXT: } | |
| 38 | ||
| 39 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tx64 | |
| 40 | # RUN: ld.lld -m elf_x86_64 %tx64 -o %t2x64 | |
| 41 | # RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=X86-64 %s | |
| 42 | # RUN: ld.lld %tx64 -o %t3x64 | |
| 43 | # RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=X86-64 %s | |
| 44 | # RUN: echo 'OUTPUT_FORMAT(elf64-x86-64)' > %t4x64.script | |
| 45 | # RUN: ld.lld %t4x64.script %tx64 -o %t4x64 | |
| 46 | # RUN: ld.lld %tx64 -o %t4x64 %t4x64.script | |
| 47 | # RUN: llvm-readobj -file-headers %t4x64 | FileCheck --check-prefix=X86-64 %s | |
| 48 | # X86-64: ElfHeader { | |
| 49 | # X86-64-NEXT: Ident { | |
| 50 | # X86-64-NEXT: Magic: (7F 45 4C 46) | |
| 51 | # X86-64-NEXT: Class: 64-bit (0x2) | |
| 52 | # X86-64-NEXT: DataEncoding: LittleEndian (0x1) | |
| 53 | # X86-64-NEXT: FileVersion: 1 | |
| 54 | # X86-64-NEXT: OS/ABI: SystemV (0x0) | |
| 55 | # X86-64-NEXT: ABIVersion: 0 | |
| 56 | # X86-64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 57 | # X86-64-NEXT: } | |
| 58 | # X86-64-NEXT: Type: Executable (0x2) | |
| 59 | # X86-64-NEXT: Machine: EM_X86_64 (0x3E) | |
| 60 | # X86-64-NEXT: Version: 1 | |
| 61 | # X86-64-NEXT: Entry: | |
| 62 | # X86-64-NEXT: ProgramHeaderOffset: 0x40 | |
| 63 | # X86-64-NEXT: SectionHeaderOffset: | |
| 64 | # X86-64-NEXT: Flags [ (0x0) | |
| 65 | # X86-64-NEXT: ] | |
| 66 | # X86-64-NEXT: HeaderSize: 64 | |
| 67 | # X86-64-NEXT: ProgramHeaderEntrySize: 56 | |
| 68 | # X86-64-NEXT: ProgramHeaderCount: | |
| 69 | # X86-64-NEXT: SectionHeaderEntrySize: 64 | |
| 70 | # X86-64-NEXT: SectionHeaderCount: | |
| 71 | # X86-64-NEXT: StringTableSectionIndex: | |
| 72 | # X86-64-NEXT: } | |
| 73 | ||
| 74 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnux32 %s -o %tx32 | |
| 75 | # RUN: ld.lld -m elf32_x86_64 %tx32 -o %t2x32 | |
| 76 | # RUN: llvm-readobj -file-headers %t2x32 | FileCheck --check-prefix=X32 %s | |
| 77 | # RUN: ld.lld %tx32 -o %t3x32 | |
| 78 | # RUN: llvm-readobj -file-headers %t3x32 | FileCheck --check-prefix=X32 %s | |
| 79 | # RUN: echo 'OUTPUT_FORMAT(elf32-x86-64)' > %t4x32.script | |
| 80 | # RUN: ld.lld %t4x32.script %tx32 -o %t4x32 | |
| 81 | # RUN: llvm-readobj -file-headers %t4x32 | FileCheck --check-prefix=X32 %s | |
| 82 | # X32: ElfHeader { | |
| 83 | # X32-NEXT: Ident { | |
| 84 | # X32-NEXT: Magic: (7F 45 4C 46) | |
| 85 | # X32-NEXT: Class: 32-bit (0x1) | |
| 86 | # X32-NEXT: DataEncoding: LittleEndian (0x1) | |
| 87 | # X32-NEXT: FileVersion: 1 | |
| 88 | # X32-NEXT: OS/ABI: SystemV (0x0) | |
| 89 | # X32-NEXT: ABIVersion: 0 | |
| 90 | # X32-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 91 | # X32-NEXT: } | |
| 92 | # X32-NEXT: Type: Executable (0x2) | |
| 93 | # X32-NEXT: Machine: EM_X86_64 (0x3E) | |
| 94 | # X32-NEXT: Version: 1 | |
| 95 | # X32-NEXT: Entry: | |
| 96 | # X32-NEXT: ProgramHeaderOffset: 0x34 | |
| 97 | # X32-NEXT: SectionHeaderOffset: | |
| 98 | # X32-NEXT: Flags [ (0x0) | |
| 99 | # X32-NEXT: ] | |
| 100 | # X32-NEXT: HeaderSize: 52 | |
| 101 | # X32-NEXT: ProgramHeaderEntrySize: 32 | |
| 102 | # X32-NEXT: ProgramHeaderCount: | |
| 103 | # X32-NEXT: SectionHeaderEntrySize: 40 | |
| 104 | # X32-NEXT: SectionHeaderCount: | |
| 105 | # X32-NEXT: StringTableSectionIndex: | |
| 106 | # X32-NEXT: } | |
| 107 | ||
| 108 | # RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tx86 | |
| 109 | # RUN: ld.lld -m elf_i386 %tx86 -o %t2x86 | |
| 110 | # RUN: llvm-readobj -file-headers %t2x86 | FileCheck --check-prefix=X86 %s | |
| 111 | # RUN: ld.lld %tx86 -o %t3x86 | |
| 112 | # RUN: llvm-readobj -file-headers %t3x86 | FileCheck --check-prefix=X86 %s | |
| 113 | # RUN: echo 'OUTPUT_FORMAT(elf32-i386)' > %t4x86.script | |
| 114 | # RUN: ld.lld %t4x86.script %tx86 -o %t4x86 | |
| 115 | # RUN: llvm-readobj -file-headers %t4x86 | FileCheck --check-prefix=X86 %s | |
| 116 | # X86: ElfHeader { | |
| 117 | # X86-NEXT: Ident { | |
| 118 | # X86-NEXT: Magic: (7F 45 4C 46) | |
| 119 | # X86-NEXT: Class: 32-bit (0x1) | |
| 120 | # X86-NEXT: DataEncoding: LittleEndian (0x1) | |
| 121 | # X86-NEXT: FileVersion: 1 | |
| 122 | # X86-NEXT: OS/ABI: SystemV (0x0) | |
| 123 | # X86-NEXT: ABIVersion: 0 | |
| 124 | # X86-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 125 | # X86-NEXT: } | |
| 126 | # X86-NEXT: Type: Executable (0x2) | |
| 127 | # X86-NEXT: Machine: EM_386 (0x3) | |
| 128 | # X86-NEXT: Version: 1 | |
| 129 | # X86-NEXT: Entry: | |
| 130 | # X86-NEXT: ProgramHeaderOffset: 0x34 | |
| 131 | # X86-NEXT: SectionHeaderOffset: | |
| 132 | # X86-NEXT: Flags [ (0x0) | |
| 133 | # X86-NEXT: ] | |
| 134 | # X86-NEXT: HeaderSize: 52 | |
| 135 | # X86-NEXT: ProgramHeaderEntrySize: 32 | |
| 136 | # X86-NEXT: ProgramHeaderCount: | |
| 137 | # X86-NEXT: SectionHeaderEntrySize: 40 | |
| 138 | # X86-NEXT: SectionHeaderCount: | |
| 139 | # X86-NEXT: StringTableSectionIndex: | |
| 140 | # X86-NEXT: } | |
| 141 | ||
| 142 | # RUN: llvm-mc -filetype=obj -triple=i686-unknown-freebsd %s -o %tx86fbsd | |
| 143 | # RUN: ld.lld -m elf_i386_fbsd %tx86fbsd -o %t2x86fbsd | |
| 144 | # RUN: llvm-readobj -file-headers %t2x86fbsd | FileCheck --check-prefix=X86FBSD %s | |
| 145 | # RUN: ld.lld %tx86fbsd -o %t3x86fbsd | |
| 146 | # RUN: llvm-readobj -file-headers %t3x86fbsd | FileCheck --check-prefix=X86FBSD %s | |
| 147 | # RUN: echo 'OUTPUT_FORMAT(elf32-i386-freebsd)' > %t4x86fbsd.script | |
| 148 | # RUN: ld.lld %t4x86fbsd.script %tx86fbsd -o %t4x86fbsd | |
| 149 | # RUN: llvm-readobj -file-headers %t4x86fbsd | FileCheck --check-prefix=X86FBSD %s | |
| 150 | # X86FBSD: ElfHeader { | |
| 151 | # X86FBSD-NEXT: Ident { | |
| 152 | # X86FBSD-NEXT: Magic: (7F 45 4C 46) | |
| 153 | # X86FBSD-NEXT: Class: 32-bit (0x1) | |
| 154 | # X86FBSD-NEXT: DataEncoding: LittleEndian (0x1) | |
| 155 | # X86FBSD-NEXT: FileVersion: 1 | |
| 156 | # X86FBSD-NEXT: OS/ABI: FreeBSD (0x9) | |
| 157 | # X86FBSD-NEXT: ABIVersion: 0 | |
| 158 | # X86FBSD-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 159 | # X86FBSD-NEXT: } | |
| 160 | # X86FBSD-NEXT: Type: Executable (0x2) | |
| 161 | # X86FBSD-NEXT: Machine: EM_386 (0x3) | |
| 162 | # X86FBSD-NEXT: Version: 1 | |
| 163 | # X86FBSD-NEXT: Entry: | |
| 164 | # X86FBSD-NEXT: ProgramHeaderOffset: 0x34 | |
| 165 | # X86FBSD-NEXT: SectionHeaderOffset: | |
| 166 | # X86FBSD-NEXT: Flags [ (0x0) | |
| 167 | # X86FBSD-NEXT: ] | |
| 168 | # X86FBSD-NEXT: HeaderSize: 52 | |
| 169 | # X86FBSD-NEXT: ProgramHeaderEntrySize: 32 | |
| 170 | # X86FBSD-NEXT: ProgramHeaderCount: | |
| 171 | # X86FBSD-NEXT: SectionHeaderEntrySize: 40 | |
| 172 | # X86FBSD-NEXT: SectionHeaderCount: | |
| 173 | # X86FBSD-NEXT: StringTableSectionIndex: | |
| 174 | # X86FBSD-NEXT: } | |
| 175 | ||
| 176 | # RUN: llvm-mc -filetype=obj -triple=i586-intel-elfiamcu %s -o %tiamcu | |
| 177 | # RUN: ld.lld -m elf_iamcu %tiamcu -o %t2iamcu | |
| 178 | # RUN: llvm-readobj -file-headers %t2iamcu | FileCheck --check-prefix=IAMCU %s | |
| 179 | # RUN: ld.lld %tiamcu -o %t3iamcu | |
| 180 | # RUN: llvm-readobj -file-headers %t3iamcu | FileCheck --check-prefix=IAMCU %s | |
| 181 | # RUN: echo 'OUTPUT_FORMAT(elf32-iamcu)' > %t4iamcu.script | |
| 182 | # RUN: ld.lld %t4iamcu.script %tiamcu -o %t4iamcu | |
| 183 | # RUN: llvm-readobj -file-headers %t4iamcu | FileCheck --check-prefix=IAMCU %s | |
| 184 | # IAMCU: ElfHeader { | |
| 185 | # IAMCU-NEXT: Ident { | |
| 186 | # IAMCU-NEXT: Magic: (7F 45 4C 46) | |
| 187 | # IAMCU-NEXT: Class: 32-bit (0x1) | |
| 188 | # IAMCU-NEXT: DataEncoding: LittleEndian (0x1) | |
| 189 | # IAMCU-NEXT: FileVersion: 1 | |
| 190 | # IAMCU-NEXT: OS/ABI: SystemV (0x0) | |
| 191 | # IAMCU-NEXT: ABIVersion: 0 | |
| 192 | # IAMCU-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 193 | # IAMCU-NEXT: } | |
| 194 | # IAMCU-NEXT: Type: Executable (0x2) | |
| 195 | # IAMCU-NEXT: Machine: EM_IAMCU (0x6) | |
| 196 | # IAMCU-NEXT: Version: 1 | |
| 197 | # IAMCU-NEXT: Entry: | |
| 198 | # IAMCU-NEXT: ProgramHeaderOffset: 0x34 | |
| 199 | # IAMCU-NEXT: SectionHeaderOffset: | |
| 200 | # IAMCU-NEXT: Flags [ (0x0) | |
| 201 | # IAMCU-NEXT: ] | |
| 202 | # IAMCU-NEXT: HeaderSize: 52 | |
| 203 | # IAMCU-NEXT: ProgramHeaderEntrySize: 32 | |
| 204 | # IAMCU-NEXT: ProgramHeaderCount: | |
| 205 | # IAMCU-NEXT: SectionHeaderEntrySize: 40 | |
| 206 | # IAMCU-NEXT: SectionHeaderCount: | |
| 207 | # IAMCU-NEXT: StringTableSectionIndex: | |
| 208 | # IAMCU-NEXT: } | |
| 209 | ||
| 210 | .globl _start | |
| 211 | _start: |
deps/lld/test/ELF/emulation.s deleted-396| ... | ... | @@ -1,396 +0,0 @@ |
| 1 | # REQUIRES: x86,ppc,mips,aarch64 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %tx64 | |
| 3 | # RUN: ld.lld -m elf_amd64_fbsd %tx64 -o %t2x64 | |
| 4 | # RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=AMD64 %s | |
| 5 | # RUN: ld.lld %tx64 -o %t3x64 | |
| 6 | # RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=AMD64 %s | |
| 7 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.sysv | |
| 8 | # RUN: ld.lld -m elf_amd64_fbsd %t.sysv -o %t.freebsd | |
| 9 | # RUN: llvm-readobj -file-headers %t.freebsd | FileCheck --check-prefix=AMD64 %s | |
| 10 | # AMD64: ElfHeader { | |
| 11 | # AMD64-NEXT: Ident { | |
| 12 | # AMD64-NEXT: Magic: (7F 45 4C 46) | |
| 13 | # AMD64-NEXT: Class: 64-bit (0x2) | |
| 14 | # AMD64-NEXT: DataEncoding: LittleEndian (0x1) | |
| 15 | # AMD64-NEXT: FileVersion: 1 | |
| 16 | # AMD64-NEXT: OS/ABI: FreeBSD (0x9) | |
| 17 | # AMD64-NEXT: ABIVersion: 0 | |
| 18 | # AMD64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 19 | # AMD64-NEXT: } | |
| 20 | # AMD64-NEXT: Type: Executable (0x2) | |
| 21 | # AMD64-NEXT: Machine: EM_X86_64 (0x3E) | |
| 22 | # AMD64-NEXT: Version: 1 | |
| 23 | # AMD64-NEXT: Entry: | |
| 24 | # AMD64-NEXT: ProgramHeaderOffset: 0x40 | |
| 25 | # AMD64-NEXT: SectionHeaderOffset: | |
| 26 | # AMD64-NEXT: Flags [ (0x0) | |
| 27 | # AMD64-NEXT: ] | |
| 28 | # AMD64-NEXT: HeaderSize: 64 | |
| 29 | # AMD64-NEXT: ProgramHeaderEntrySize: 56 | |
| 30 | # AMD64-NEXT: ProgramHeaderCount: | |
| 31 | # AMD64-NEXT: SectionHeaderEntrySize: 64 | |
| 32 | # AMD64-NEXT: SectionHeaderCount: | |
| 33 | # AMD64-NEXT: StringTableSectionIndex: | |
| 34 | # AMD64-NEXT: } | |
| 35 | ||
| 36 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tx64 | |
| 37 | # RUN: ld.lld -m elf_x86_64 %tx64 -o %t2x64 | |
| 38 | # RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=X86-64 %s | |
| 39 | # RUN: ld.lld %tx64 -o %t3x64 | |
| 40 | # RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=X86-64 %s | |
| 41 | # X86-64: ElfHeader { | |
| 42 | # X86-64-NEXT: Ident { | |
| 43 | # X86-64-NEXT: Magic: (7F 45 4C 46) | |
| 44 | # X86-64-NEXT: Class: 64-bit (0x2) | |
| 45 | # X86-64-NEXT: DataEncoding: LittleEndian (0x1) | |
| 46 | # X86-64-NEXT: FileVersion: 1 | |
| 47 | # X86-64-NEXT: OS/ABI: SystemV (0x0) | |
| 48 | # X86-64-NEXT: ABIVersion: 0 | |
| 49 | # X86-64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 50 | # X86-64-NEXT: } | |
| 51 | # X86-64-NEXT: Type: Executable (0x2) | |
| 52 | # X86-64-NEXT: Machine: EM_X86_64 (0x3E) | |
| 53 | # X86-64-NEXT: Version: 1 | |
| 54 | # X86-64-NEXT: Entry: | |
| 55 | # X86-64-NEXT: ProgramHeaderOffset: 0x40 | |
| 56 | # X86-64-NEXT: SectionHeaderOffset: | |
| 57 | # X86-64-NEXT: Flags [ (0x0) | |
| 58 | # X86-64-NEXT: ] | |
| 59 | # X86-64-NEXT: HeaderSize: 64 | |
| 60 | # X86-64-NEXT: ProgramHeaderEntrySize: 56 | |
| 61 | # X86-64-NEXT: ProgramHeaderCount: | |
| 62 | # X86-64-NEXT: SectionHeaderEntrySize: 64 | |
| 63 | # X86-64-NEXT: SectionHeaderCount: | |
| 64 | # X86-64-NEXT: StringTableSectionIndex: | |
| 65 | # X86-64-NEXT: } | |
| 66 | ||
| 67 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnux32 %s -o %tx32 | |
| 68 | # RUN: ld.lld -m elf32_x86_64 %tx32 -o %t2x32 | |
| 69 | # RUN: llvm-readobj -file-headers %t2x32 | FileCheck --check-prefix=X32 %s | |
| 70 | # RUN: ld.lld %tx32 -o %t3x32 | |
| 71 | # RUN: llvm-readobj -file-headers %t3x32 | FileCheck --check-prefix=X32 %s | |
| 72 | # X32: ElfHeader { | |
| 73 | # X32-NEXT: Ident { | |
| 74 | # X32-NEXT: Magic: (7F 45 4C 46) | |
| 75 | # X32-NEXT: Class: 32-bit (0x1) | |
| 76 | # X32-NEXT: DataEncoding: LittleEndian (0x1) | |
| 77 | # X32-NEXT: FileVersion: 1 | |
| 78 | # X32-NEXT: OS/ABI: SystemV (0x0) | |
| 79 | # X32-NEXT: ABIVersion: 0 | |
| 80 | # X32-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 81 | # X32-NEXT: } | |
| 82 | # X32-NEXT: Type: Executable (0x2) | |
| 83 | # X32-NEXT: Machine: EM_X86_64 (0x3E) | |
| 84 | # X32-NEXT: Version: 1 | |
| 85 | # X32-NEXT: Entry: | |
| 86 | # X32-NEXT: ProgramHeaderOffset: 0x34 | |
| 87 | # X32-NEXT: SectionHeaderOffset: | |
| 88 | # X32-NEXT: Flags [ (0x0) | |
| 89 | # X32-NEXT: ] | |
| 90 | # X32-NEXT: HeaderSize: 52 | |
| 91 | # X32-NEXT: ProgramHeaderEntrySize: 32 | |
| 92 | # X32-NEXT: ProgramHeaderCount: | |
| 93 | # X32-NEXT: SectionHeaderEntrySize: 40 | |
| 94 | # X32-NEXT: SectionHeaderCount: | |
| 95 | # X32-NEXT: StringTableSectionIndex: | |
| 96 | # X32-NEXT: } | |
| 97 | ||
| 98 | # RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tx86 | |
| 99 | # RUN: ld.lld -m elf_i386 %tx86 -o %t2x86 | |
| 100 | # RUN: llvm-readobj -file-headers %t2x86 | FileCheck --check-prefix=X86 %s | |
| 101 | # RUN: ld.lld %tx86 -o %t3x86 | |
| 102 | # RUN: llvm-readobj -file-headers %t3x86 | FileCheck --check-prefix=X86 %s | |
| 103 | # X86: ElfHeader { | |
| 104 | # X86-NEXT: Ident { | |
| 105 | # X86-NEXT: Magic: (7F 45 4C 46) | |
| 106 | # X86-NEXT: Class: 32-bit (0x1) | |
| 107 | # X86-NEXT: DataEncoding: LittleEndian (0x1) | |
| 108 | # X86-NEXT: FileVersion: 1 | |
| 109 | # X86-NEXT: OS/ABI: SystemV (0x0) | |
| 110 | # X86-NEXT: ABIVersion: 0 | |
| 111 | # X86-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 112 | # X86-NEXT: } | |
| 113 | # X86-NEXT: Type: Executable (0x2) | |
| 114 | # X86-NEXT: Machine: EM_386 (0x3) | |
| 115 | # X86-NEXT: Version: 1 | |
| 116 | # X86-NEXT: Entry: | |
| 117 | # X86-NEXT: ProgramHeaderOffset: 0x34 | |
| 118 | # X86-NEXT: SectionHeaderOffset: | |
| 119 | # X86-NEXT: Flags [ (0x0) | |
| 120 | # X86-NEXT: ] | |
| 121 | # X86-NEXT: HeaderSize: 52 | |
| 122 | # X86-NEXT: ProgramHeaderEntrySize: 32 | |
| 123 | # X86-NEXT: ProgramHeaderCount: | |
| 124 | # X86-NEXT: SectionHeaderEntrySize: 40 | |
| 125 | # X86-NEXT: SectionHeaderCount: | |
| 126 | # X86-NEXT: StringTableSectionIndex: | |
| 127 | # X86-NEXT: } | |
| 128 | ||
| 129 | # RUN: llvm-mc -filetype=obj -triple=i686-unknown-freebsd %s -o %tx86fbsd | |
| 130 | # RUN: ld.lld -m elf_i386_fbsd %tx86fbsd -o %t2x86_fbsd | |
| 131 | # RUN: llvm-readobj -file-headers %t2x86_fbsd | FileCheck --check-prefix=X86FBSD %s | |
| 132 | # RUN: ld.lld %tx86fbsd -o %t3x86fbsd | |
| 133 | # RUN: llvm-readobj -file-headers %t3x86fbsd | FileCheck --check-prefix=X86FBSD %s | |
| 134 | # X86FBSD: ElfHeader { | |
| 135 | # X86FBSD-NEXT: Ident { | |
| 136 | # X86FBSD-NEXT: Magic: (7F 45 4C 46) | |
| 137 | # X86FBSD-NEXT: Class: 32-bit (0x1) | |
| 138 | # X86FBSD-NEXT: DataEncoding: LittleEndian (0x1) | |
| 139 | # X86FBSD-NEXT: FileVersion: 1 | |
| 140 | # X86FBSD-NEXT: OS/ABI: FreeBSD (0x9) | |
| 141 | # X86FBSD-NEXT: ABIVersion: 0 | |
| 142 | # X86FBSD-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 143 | # X86FBSD-NEXT: } | |
| 144 | # X86FBSD-NEXT: Type: Executable (0x2) | |
| 145 | # X86FBSD-NEXT: Machine: EM_386 (0x3) | |
| 146 | # X86FBSD-NEXT: Version: 1 | |
| 147 | # X86FBSD-NEXT: Entry: | |
| 148 | # X86FBSD-NEXT: ProgramHeaderOffset: 0x34 | |
| 149 | # X86FBSD-NEXT: SectionHeaderOffset: | |
| 150 | # X86FBSD-NEXT: Flags [ (0x0) | |
| 151 | # X86FBSD-NEXT: ] | |
| 152 | # X86FBSD-NEXT: HeaderSize: 52 | |
| 153 | # X86FBSD-NEXT: ProgramHeaderEntrySize: 32 | |
| 154 | # X86FBSD-NEXT: ProgramHeaderCount: | |
| 155 | # X86FBSD-NEXT: SectionHeaderEntrySize: 40 | |
| 156 | # X86FBSD-NEXT: SectionHeaderCount: | |
| 157 | # X86FBSD-NEXT: StringTableSectionIndex: | |
| 158 | # X86FBSD-NEXT: } | |
| 159 | ||
| 160 | # RUN: llvm-mc -filetype=obj -triple=i586-intel-elfiamcu %s -o %tiamcu | |
| 161 | # RUN: ld.lld -m elf_iamcu %tiamcu -o %t2iamcu | |
| 162 | # RUN: llvm-readobj -file-headers %t2iamcu | FileCheck --check-prefix=IAMCU %s | |
| 163 | # RUN: ld.lld %tiamcu -o %t3iamcu | |
| 164 | # RUN: llvm-readobj -file-headers %t3iamcu | FileCheck --check-prefix=IAMCU %s | |
| 165 | # IAMCU: ElfHeader { | |
| 166 | # IAMCU-NEXT: Ident { | |
| 167 | # IAMCU-NEXT: Magic: (7F 45 4C 46) | |
| 168 | # IAMCU-NEXT: Class: 32-bit (0x1) | |
| 169 | # IAMCU-NEXT: DataEncoding: LittleEndian (0x1) | |
| 170 | # IAMCU-NEXT: FileVersion: 1 | |
| 171 | # IAMCU-NEXT: OS/ABI: SystemV (0x0) | |
| 172 | # IAMCU-NEXT: ABIVersion: 0 | |
| 173 | # IAMCU-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 174 | # IAMCU-NEXT: } | |
| 175 | # IAMCU-NEXT: Type: Executable (0x2) | |
| 176 | # IAMCU-NEXT: Machine: EM_IAMCU (0x6) | |
| 177 | # IAMCU-NEXT: Version: 1 | |
| 178 | # IAMCU-NEXT: Entry: | |
| 179 | # IAMCU-NEXT: ProgramHeaderOffset: 0x34 | |
| 180 | # IAMCU-NEXT: SectionHeaderOffset: | |
| 181 | # IAMCU-NEXT: Flags [ (0x0) | |
| 182 | # IAMCU-NEXT: ] | |
| 183 | # IAMCU-NEXT: HeaderSize: 52 | |
| 184 | # IAMCU-NEXT: ProgramHeaderEntrySize: 32 | |
| 185 | # IAMCU-NEXT: ProgramHeaderCount: | |
| 186 | # IAMCU-NEXT: SectionHeaderEntrySize: 40 | |
| 187 | # IAMCU-NEXT: SectionHeaderCount: | |
| 188 | # IAMCU-NEXT: StringTableSectionIndex: | |
| 189 | # IAMCU-NEXT: } | |
| 190 | ||
| 191 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %tppc64 | |
| 192 | # RUN: ld.lld -m elf64ppc %tppc64 -o %t2ppc64 | |
| 193 | # RUN: llvm-readobj -file-headers %t2ppc64 | FileCheck --check-prefix=PPC64 %s | |
| 194 | # RUN: ld.lld %tppc64 -o %t3ppc64 | |
| 195 | # RUN: llvm-readobj -file-headers %t3ppc64 | FileCheck --check-prefix=PPC64 %s | |
| 196 | # PPC64: ElfHeader { | |
| 197 | # PPC64-NEXT: Ident { | |
| 198 | # PPC64-NEXT: Magic: (7F 45 4C 46) | |
| 199 | # PPC64-NEXT: Class: 64-bit (0x2) | |
| 200 | # PPC64-NEXT: DataEncoding: BigEndian (0x2) | |
| 201 | # PPC64-NEXT: FileVersion: 1 | |
| 202 | # PPC64-NEXT: OS/ABI: SystemV (0x0) | |
| 203 | # PPC64-NEXT: ABIVersion: 0 | |
| 204 | # PPC64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 205 | # PPC64-NEXT: } | |
| 206 | # PPC64-NEXT: Type: Executable (0x2) | |
| 207 | # PPC64-NEXT: Machine: EM_PPC64 (0x15) | |
| 208 | # PPC64-NEXT: Version: 1 | |
| 209 | # PPC64-NEXT: Entry: | |
| 210 | # PPC64-NEXT: ProgramHeaderOffset: 0x40 | |
| 211 | # PPC64-NEXT: SectionHeaderOffset: | |
| 212 | # PPC64-NEXT: Flags [ (0x2) | |
| 213 | # PPC64-NEXT: 0x2 | |
| 214 | # PPC64-NEXT: ] | |
| 215 | # PPC64-NEXT: HeaderSize: 64 | |
| 216 | # PPC64-NEXT: ProgramHeaderEntrySize: 56 | |
| 217 | # PPC64-NEXT: ProgramHeaderCount: | |
| 218 | # PPC64-NEXT: SectionHeaderEntrySize: 64 | |
| 219 | # PPC64-NEXT: SectionHeaderCount: | |
| 220 | # PPC64-NEXT: StringTableSectionIndex: | |
| 221 | # PPC64-NEXT: } | |
| 222 | ||
| 223 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %tppc64le | |
| 224 | # RUN: ld.lld -m elf64lppc %tppc64le -o %t2ppc64le | |
| 225 | # RUN: llvm-readobj -file-headers %t2ppc64le | FileCheck --check-prefix=PPC64LE %s | |
| 226 | # RUN: ld.lld %tppc64le -o %t3ppc64le | |
| 227 | # RUN: llvm-readobj -file-headers %t3ppc64le | FileCheck --check-prefix=PPC64LE %s | |
| 228 | # PPC64LE: ElfHeader { | |
| 229 | # PPC64LE-NEXT: Ident { | |
| 230 | # PPC64LE-NEXT: Magic: (7F 45 4C 46) | |
| 231 | # PPC64LE-NEXT: Class: 64-bit (0x2) | |
| 232 | # PPC64LE-NEXT: DataEncoding: LittleEndian (0x1) | |
| 233 | # PPC64LE-NEXT: FileVersion: 1 | |
| 234 | # PPC64LE-NEXT: OS/ABI: SystemV (0x0) | |
| 235 | # PPC64LE-NEXT: ABIVersion: 0 | |
| 236 | # PPC64LE-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 237 | # PPC64LE-NEXT: } | |
| 238 | # PPC64LE-NEXT: Type: Executable (0x2) | |
| 239 | # PPC64LE-NEXT: Machine: EM_PPC64 (0x15) | |
| 240 | # PPC64LE-NEXT: Version: 1 | |
| 241 | # PPC64LE-NEXT: Entry: | |
| 242 | # PPC64LE-NEXT: ProgramHeaderOffset: 0x40 | |
| 243 | # PPC64LE-NEXT: SectionHeaderOffset: | |
| 244 | # PPC64LE-NEXT: Flags [ (0x2) | |
| 245 | # PPC64LE-NEXT: 0x2 | |
| 246 | # PPC64LE-NEXT: ] | |
| 247 | # PPC64LE-NEXT: HeaderSize: 64 | |
| 248 | # PPC64LE-NEXT: ProgramHeaderEntrySize: 56 | |
| 249 | # PPC64LE-NEXT: ProgramHeaderCount: | |
| 250 | # PPC64LE-NEXT: SectionHeaderEntrySize: 64 | |
| 251 | # PPC64LE-NEXT: SectionHeaderCount: | |
| 252 | # PPC64LE-NEXT: StringTableSectionIndex: | |
| 253 | # PPC64LE-NEXT: } | |
| 254 | ||
| 255 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %tmips | |
| 256 | # RUN: ld.lld -m elf32btsmip -e _start %tmips -o %t2mips | |
| 257 | # RUN: llvm-readobj -file-headers %t2mips | FileCheck --check-prefix=MIPS %s | |
| 258 | # RUN: ld.lld %tmips -e _start -o %t3mips | |
| 259 | # RUN: llvm-readobj -file-headers %t3mips | FileCheck --check-prefix=MIPS %s | |
| 260 | # MIPS: ElfHeader { | |
| 261 | # MIPS-NEXT: Ident { | |
| 262 | # MIPS-NEXT: Magic: (7F 45 4C 46) | |
| 263 | # MIPS-NEXT: Class: 32-bit (0x1) | |
| 264 | # MIPS-NEXT: DataEncoding: BigEndian (0x2) | |
| 265 | # MIPS-NEXT: FileVersion: 1 | |
| 266 | # MIPS-NEXT: OS/ABI: SystemV (0x0) | |
| 267 | # MIPS-NEXT: ABIVersion: 1 | |
| 268 | # MIPS-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 269 | # MIPS-NEXT: } | |
| 270 | # MIPS-NEXT: Type: Executable (0x2) | |
| 271 | # MIPS-NEXT: Machine: EM_MIPS (0x8) | |
| 272 | # MIPS-NEXT: Version: 1 | |
| 273 | # MIPS-NEXT: Entry: | |
| 274 | # MIPS-NEXT: ProgramHeaderOffset: 0x34 | |
| 275 | # MIPS-NEXT: SectionHeaderOffset: | |
| 276 | # MIPS-NEXT: Flags [ | |
| 277 | # MIPS-NEXT: EF_MIPS_ABI_O32 | |
| 278 | # MIPS-NEXT: EF_MIPS_ARCH_32 | |
| 279 | # MIPS-NEXT: EF_MIPS_CPIC | |
| 280 | # MIPS-NEXT: ] | |
| 281 | ||
| 282 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %tmipsel | |
| 283 | # RUN: ld.lld -m elf32ltsmip -e _start %tmipsel -o %t2mipsel | |
| 284 | # RUN: llvm-readobj -file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s | |
| 285 | # RUN: ld.lld -melf32ltsmip -e _start %tmipsel -o %t2mipsel | |
| 286 | # RUN: llvm-readobj -file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s | |
| 287 | # RUN: ld.lld %tmipsel -e _start -o %t3mipsel | |
| 288 | # RUN: llvm-readobj -file-headers %t3mipsel | FileCheck --check-prefix=MIPSEL %s | |
| 289 | # MIPSEL: ElfHeader { | |
| 290 | # MIPSEL-NEXT: Ident { | |
| 291 | # MIPSEL-NEXT: Magic: (7F 45 4C 46) | |
| 292 | # MIPSEL-NEXT: Class: 32-bit (0x1) | |
| 293 | # MIPSEL-NEXT: DataEncoding: LittleEndian (0x1) | |
| 294 | # MIPSEL-NEXT: FileVersion: 1 | |
| 295 | # MIPSEL-NEXT: OS/ABI: SystemV (0x0) | |
| 296 | # MIPSEL-NEXT: ABIVersion: 1 | |
| 297 | # MIPSEL-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 298 | # MIPSEL-NEXT: } | |
| 299 | # MIPSEL-NEXT: Type: Executable (0x2) | |
| 300 | # MIPSEL-NEXT: Machine: EM_MIPS (0x8) | |
| 301 | # MIPSEL-NEXT: Version: 1 | |
| 302 | # MIPSEL-NEXT: Entry: | |
| 303 | # MIPSEL-NEXT: ProgramHeaderOffset: 0x34 | |
| 304 | # MIPSEL-NEXT: SectionHeaderOffset: | |
| 305 | # MIPSEL-NEXT: Flags [ | |
| 306 | # MIPSEL-NEXT: EF_MIPS_ABI_O32 | |
| 307 | # MIPSEL-NEXT: EF_MIPS_ARCH_32 | |
| 308 | # MIPSEL-NEXT: EF_MIPS_CPIC | |
| 309 | # MIPSEL-NEXT: ] | |
| 310 | ||
| 311 | # RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -position-independent \ | |
| 312 | # RUN: %s -o %tmips64 | |
| 313 | # RUN: ld.lld -m elf64btsmip -e _start %tmips64 -o %t2mips64 | |
| 314 | # RUN: llvm-readobj -file-headers %t2mips64 | FileCheck --check-prefix=MIPS64 %s | |
| 315 | # RUN: ld.lld %tmips64 -e _start -o %t3mips64 | |
| 316 | # RUN: llvm-readobj -file-headers %t3mips64 | FileCheck --check-prefix=MIPS64 %s | |
| 317 | # MIPS64: ElfHeader { | |
| 318 | # MIPS64-NEXT: Ident { | |
| 319 | # MIPS64-NEXT: Magic: (7F 45 4C 46) | |
| 320 | # MIPS64-NEXT: Class: 64-bit (0x2) | |
| 321 | # MIPS64-NEXT: DataEncoding: BigEndian (0x2) | |
| 322 | # MIPS64-NEXT: FileVersion: 1 | |
| 323 | # MIPS64-NEXT: OS/ABI: SystemV (0x0) | |
| 324 | # MIPS64-NEXT: ABIVersion: 0 | |
| 325 | # MIPS64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 326 | # MIPS64-NEXT: } | |
| 327 | # MIPS64-NEXT: Type: Executable (0x2) | |
| 328 | # MIPS64-NEXT: Machine: EM_MIPS (0x8) | |
| 329 | # MIPS64-NEXT: Version: 1 | |
| 330 | # MIPS64-NEXT: Entry: | |
| 331 | # MIPS64-NEXT: ProgramHeaderOffset: 0x40 | |
| 332 | # MIPS64-NEXT: SectionHeaderOffset: | |
| 333 | # MIPS64-NEXT: Flags [ | |
| 334 | # MIPS64-NEXT: EF_MIPS_ARCH_64 | |
| 335 | # MIPS64-NEXT: EF_MIPS_CPIC | |
| 336 | # MIPS64-NEXT: EF_MIPS_PIC | |
| 337 | # MIPS64-NEXT: ] | |
| 338 | ||
| 339 | # RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux \ | |
| 340 | # RUN: -position-independent %s -o %tmips64el | |
| 341 | # RUN: ld.lld -m elf64ltsmip -e _start %tmips64el -o %t2mips64el | |
| 342 | # RUN: llvm-readobj -file-headers %t2mips64el | FileCheck --check-prefix=MIPS64EL %s | |
| 343 | # RUN: ld.lld %tmips64el -e _start -o %t3mips64el | |
| 344 | # RUN: llvm-readobj -file-headers %t3mips64el | FileCheck --check-prefix=MIPS64EL %s | |
| 345 | # MIPS64EL: ElfHeader { | |
| 346 | # MIPS64EL-NEXT: Ident { | |
| 347 | # MIPS64EL-NEXT: Magic: (7F 45 4C 46) | |
| 348 | # MIPS64EL-NEXT: Class: 64-bit (0x2) | |
| 349 | # MIPS64EL-NEXT: DataEncoding: LittleEndian (0x1) | |
| 350 | # MIPS64EL-NEXT: FileVersion: 1 | |
| 351 | # MIPS64EL-NEXT: OS/ABI: SystemV (0x0) | |
| 352 | # MIPS64EL-NEXT: ABIVersion: 0 | |
| 353 | # MIPS64EL-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 354 | # MIPS64EL-NEXT: } | |
| 355 | # MIPS64EL-NEXT: Type: Executable (0x2) | |
| 356 | # MIPS64EL-NEXT: Machine: EM_MIPS (0x8) | |
| 357 | # MIPS64EL-NEXT: Version: 1 | |
| 358 | # MIPS64EL-NEXT: Entry: | |
| 359 | # MIPS64EL-NEXT: ProgramHeaderOffset: 0x40 | |
| 360 | # MIPS64EL-NEXT: SectionHeaderOffset: | |
| 361 | # MIPS64EL-NEXT: Flags [ | |
| 362 | # MIPS64EL-NEXT: EF_MIPS_ARCH_64 | |
| 363 | # MIPS64EL-NEXT: EF_MIPS_CPIC | |
| 364 | # MIPS64EL-NEXT: EF_MIPS_PIC | |
| 365 | # MIPS64EL-NEXT: ] | |
| 366 | ||
| 367 | # RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %taarch64 | |
| 368 | # RUN: ld.lld -m aarch64linux %taarch64 -o %t2aarch64 | |
| 369 | # RUN: llvm-readobj -file-headers %t2aarch64 | FileCheck --check-prefix=AARCH64 %s | |
| 370 | # RUN: ld.lld -m aarch64elf %taarch64 -o %t3aarch64 | |
| 371 | # RUN: llvm-readobj -file-headers %t3aarch64 | FileCheck --check-prefix=AARCH64 %s | |
| 372 | # RUN: ld.lld -m aarch64_elf64_le_vec %taarch64 -o %t4aarch64 | |
| 373 | # RUN: llvm-readobj -file-headers %t4aarch64 | FileCheck --check-prefix=AARCH64 %s | |
| 374 | # RUN: ld.lld %taarch64 -o %t5aarch64 | |
| 375 | # RUN: llvm-readobj -file-headers %t5aarch64 | FileCheck --check-prefix=AARCH64 %s | |
| 376 | # AARCH64: ElfHeader { | |
| 377 | # AARCH64-NEXT: Ident { | |
| 378 | # AARCH64-NEXT: Magic: (7F 45 4C 46) | |
| 379 | # AARCH64-NEXT: Class: 64-bit (0x2) | |
| 380 | # AARCH64-NEXT: DataEncoding: LittleEndian (0x1) | |
| 381 | # AARCH64-NEXT: FileVersion: 1 | |
| 382 | # AARCH64-NEXT: OS/ABI: SystemV (0x0) | |
| 383 | # AARCH64-NEXT: ABIVersion: 0 | |
| 384 | # AARCH64-NEXT: Unused: (00 00 00 00 00 00 00) | |
| 385 | # AARCH64-NEXT: } | |
| 386 | # AARCH64-NEXT: Type: Executable (0x2) | |
| 387 | # AARCH64-NEXT: Machine: EM_AARCH64 (0xB7) | |
| 388 | # AARCH64-NEXT: Version: 1 | |
| 389 | # AARCH64-NEXT: Entry: | |
| 390 | # AARCH64-NEXT: ProgramHeaderOffset: 0x40 | |
| 391 | # AARCH64-NEXT: SectionHeaderOffset: | |
| 392 | # AARCH64-NEXT: Flags [ (0x0) | |
| 393 | # AARCH64-NEXT: ] | |
| 394 | ||
| 395 | .globl _start | |
| 396 | _start: |
deps/lld/test/ELF/execute-only-mixed-data.s+1-1| ... | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | // RUN: }" > %t.lds |
| 17 | 17 | // RUN: ld.lld -T%t.lds %t.o -o %t -execute-only 2>&1 |
| 18 | 18 | |
| 19 | // CHECK: -execute-only does not support intermingling data and code | |
| 19 | // CHECK: cannot place {{.*}}:(.rodata.foo) into .text: -execute-only does not support intermingling data and code | |
| 20 | 20 | |
| 21 | 21 | br lr |
| 22 | 22 |
deps/lld/test/ELF/format-binary.test+12| ... | ... | @@ -55,3 +55,15 @@ |
| 55 | 55 | # CHECK-NEXT: Other: 0 |
| 56 | 56 | # CHECK-NEXT: Section: Absolute |
| 57 | 57 | # CHECK-NEXT: } |
| 58 | ||
| 59 | # RUN: echo 'OUTPUT_FORMAT(elf64-x86-64)' > %t.script | |
| 60 | # RUN: ld.lld -b binary %t.binary -T %t.script -o %t.out | |
| 61 | # RUN: llvm-readobj %t.out -sections -section-data -symbols | FileCheck -check-prefix=X86-64 %s | |
| 62 | ||
| 63 | # X86-64: Format: ELF64-x86-64 | |
| 64 | ||
| 65 | # RUN: echo 'OUTPUT_FORMAT("elf64-x86-64")' > %t.script | |
| 66 | # RUN: ld.lld -b binary %t.binary -T %t.script -o %t.out | |
| 67 | # RUN: llvm-readobj %t.out -sections -section-data -symbols | FileCheck -check-prefix=X86-64-in-quotes %s | |
| 68 | ||
| 69 | # X86-64-in-quotes: Format: ELF64-x86-64 |
deps/lld/test/ELF/gc-sections-implicit-addend.s+3-3| ... | ... | @@ -12,10 +12,10 @@ |
| 12 | 12 | # CHECK-NEXT: SHF_MERGE |
| 13 | 13 | # CHECK-NEXT: SHF_STRINGS |
| 14 | 14 | # CHECK-NEXT: ] |
| 15 | # CHECK-NEXT: Address: 0x100B4 | |
| 15 | # CHECK-NEXT: Address: 0x4000B4 | |
| 16 | 16 | |
| 17 | # 0x100B4 == 65716 | |
| 18 | # DISASM: leal 65716, %eax | |
| 17 | # 0x4000B4 == 4194484 | |
| 18 | # DISASM: leal 4194484, %eax | |
| 19 | 19 | |
| 20 | 20 | .section .foo,"aMS",@progbits,1 |
| 21 | 21 | .byte 0 |
deps/lld/test/ELF/gc-sections-linker-defined-symbol.s+1-1| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | # RUN: ld.lld %t.o -o %t.so --gc-sections -shared |
| 5 | 5 | # RUN: llvm-readobj --dyn-symbols %t.so | FileCheck %s |
| 6 | 6 | |
| 7 | # CHECK: Name: _end@ | |
| 7 | # CHECK: Name: _end | |
| 8 | 8 | # CHECK-NEXT: Value: |
| 9 | 9 | # CHECK-NEXT: Size: |
| 10 | 10 | # CHECK-NEXT: Binding: Global |
deps/lld/test/ELF/gdb-index-base-addr.s+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | # RUN: ld.lld --gdb-index %t1.o -o %t |
| 4 | 4 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s |
| 5 | 5 | |
| 6 | # CHECK: .gnu_index contents: | |
| 6 | # CHECK: .gdb_index contents: | |
| 7 | 7 | # CHECK: Address area offset = 0x28, has 2 entries: |
| 8 | 8 | # CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 |
| 9 | 9 | # CHECK-NEXT: Low/High address = [0x201003, 0x201006) (Size: 0x3), CU id = 0 |
deps/lld/test/ELF/gdb-index-dwarf5-low-high.s created+49| ... | ... | @@ -0,0 +1,49 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 3 | # RUN: ld.lld --gdb-index %t.o -o %t | |
| 4 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s | |
| 5 | ||
| 6 | # CHECK: Address area offset = 0x28, has 1 entries: | |
| 7 | # CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 | |
| 8 | ||
| 9 | .text | |
| 10 | .globl main | |
| 11 | main: # @main | |
| 12 | .Lfunc_begin0: | |
| 13 | retq | |
| 14 | .Lfunc_end0: | |
| 15 | .section .debug_abbrev,"",@progbits | |
| 16 | .byte 1 # Abbreviation Code | |
| 17 | .byte 17 # DW_TAG_compile_unit | |
| 18 | .byte 0 # DW_CHILDREN_no | |
| 19 | .byte 115 # DW_AT_addr_base | |
| 20 | .byte 23 # DW_FORM_sec_offset | |
| 21 | .byte 17 # DW_AT_low_pc | |
| 22 | .byte 27 # DW_FORM_addrx | |
| 23 | .byte 18 # DW_AT_high_pc | |
| 24 | .byte 6 # DW_FORM_data4 | |
| 25 | .byte 0 # EOM(1) | |
| 26 | .byte 0 # EOM(2) | |
| 27 | .byte 0 # EOM(3) | |
| 28 | ||
| 29 | .section .debug_info,"",@progbits | |
| 30 | .Lcu_begin0: | |
| 31 | .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit | |
| 32 | .Ldebug_info_start0: | |
| 33 | .short 5 # DWARF version number | |
| 34 | .byte 1 # DWARF Unit Type | |
| 35 | .byte 8 # Address Size (in bytes) | |
| 36 | .long .debug_abbrev # Offset Into Abbrev. Section | |
| 37 | .byte 1 # Abbrev [1] 0xc:0x2b DW_TAG_compile_unit | |
| 38 | .long .Laddr_table_base0 # DW_AT_addr_base | |
| 39 | .byte 0 # DW_AT_low_pc | |
| 40 | .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc | |
| 41 | .Ldebug_info_end0: | |
| 42 | ||
| 43 | .section .debug_addr,"",@progbits | |
| 44 | .long 12 | |
| 45 | .short 5 | |
| 46 | .byte 8 | |
| 47 | .byte 0 | |
| 48 | .Laddr_table_base0: | |
| 49 | .quad .Lfunc_begin0 |
deps/lld/test/ELF/gdb-index-invalid-ranges.s created+42| ... | ... | @@ -0,0 +1,42 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: not ld.lld --gdb-index -e main %t.o -o %t 2>&1 | FileCheck %s | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/gdb-index-invalid-ranges.obj.s -o %t2.o | |
| 5 | # RUN: llvm-ar rc %t.a %t.o | |
| 6 | # RUN: not ld.lld --gdb-index -e main %t2.o %t.a -o %t 2>&1 | FileCheck --check-prefix=ARCHIVE %s | |
| 7 | ||
| 8 | # CHECK: ld.lld: error: {{.*}}gdb-index-invalid-ranges.s.tmp.o:(.debug_info): decoding address ranges: invalid range list entry at offset 0x10 | |
| 9 | # ARCHIVE: ld.lld: error: {{.*}}gdb-index-invalid-ranges.s.tmp.a(gdb-index-invalid-ranges.s.tmp.o):(.debug_info): decoding address ranges: invalid range list entry at offset 0x10 | |
| 10 | ||
| 11 | .section .text.foo1,"ax",@progbits | |
| 12 | .globl f1 | |
| 13 | .Lfunc_begin0: | |
| 14 | f1: | |
| 15 | nop | |
| 16 | .Lfunc_end0: | |
| 17 | ||
| 18 | .section .debug_abbrev,"",@progbits | |
| 19 | .byte 1 # Abbreviation Code | |
| 20 | .byte 17 # DW_TAG_compile_unit | |
| 21 | .byte 0 # DW_CHILDREN_no | |
| 22 | .byte 85 # DW_AT_ranges | |
| 23 | .byte 23 # DW_FORM_sec_offset | |
| 24 | .byte 0 # EOM(1) | |
| 25 | .byte 0 # EOM(2) | |
| 26 | .byte 0 # EOM(3) | |
| 27 | ||
| 28 | .section .debug_info,"",@progbits | |
| 29 | .Lcu_begin0: | |
| 30 | .long .Lunit_end0-.Lunit_begin0 # Length of Unit | |
| 31 | .Lunit_begin0: | |
| 32 | .short 4 # DWARF version number | |
| 33 | .long .debug_abbrev # Offset Into Abbrev. Section | |
| 34 | .byte 8 # Address Size (in bytes) | |
| 35 | .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit | |
| 36 | .long .Ldebug_ranges0 # DW_AT_ranges | |
| 37 | .Lunit_end0: | |
| 38 | ||
| 39 | .section .debug_ranges,"",@progbits | |
| 40 | .Ldebug_ranges0: | |
| 41 | .quad .Lfunc_begin0 | |
| 42 | .quad .Lfunc_end0 |
deps/lld/test/ELF/gdb-index-multiple-cu-2.s created+36| ... | ... | @@ -0,0 +1,36 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/gdb-index-multiple-cu-2.s -o %t1.o | |
| 4 | # RUN: ld.lld --gdb-index %t.o %t1.o -o %t | |
| 5 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s | |
| 6 | ||
| 7 | # %t.o has 2 CUs while %t1 has 1, thus _start in %t1.o should have CuIndex 2. | |
| 8 | # Attributes << 24 | CuIndex = 48 << 24 | 2 = 0x30000002 | |
| 9 | # CHECK: Constant pool | |
| 10 | # CHECK-NEXT: 0(0x0): 0x30000002 | |
| 11 | ||
| 12 | .section .debug_abbrev,"",@progbits | |
| 13 | 	.byte	1 # Abbreviation Code | |
| 14 | 	.byte	17 # DW_TAG_compile_unit | |
| 15 | 	.byte	0 # DW_CHILDREN_yes | |
| 16 | 	.byte	0 # EOM(1) | |
| 17 | 	.byte	0 # EOM(2) | |
| 18 | 	.byte	0 | |
| 19 | ||
| 20 | .section .debug_info,"",@progbits | |
| 21 | .Lcu_begin0: | |
| 22 | 	.long	.Lcu_end0 - .Lcu_begin0 - 4 | |
| 23 | 	.short	4 # DWARF version number | |
| 24 | 	.long	0 # Offset Into Abbrev. Section | |
| 25 | 	.byte	4 # Address Size | |
| 26 | 	.byte	1 # Abbrev [1] DW_TAG_compile_unit | |
| 27 | 	.byte	0 | |
| 28 | .Lcu_end0: | |
| 29 | .Lcu_begin1: | |
| 30 | 	.long	.Lcu_end1 - .Lcu_begin1 - 4 | |
| 31 | 	.short	4 # DWARF version number | |
| 32 | 	.long	0 # Offset Into Abbrev. Section | |
| 33 | 	.byte	4 # Address Size | |
| 34 | 	.byte	1 # Abbrev [1] DW_TAG_compile_unit | |
| 35 | 	.byte	0 | |
| 36 | .Lcu_end1: |
deps/lld/test/ELF/gdb-index-multiple-cu.s created+88| ... | ... | @@ -0,0 +1,88 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: ld.lld --gdb-index %t.o -o %t | |
| 4 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s | |
| 5 | ||
| 6 | # CuIndexAndAttrs of _start: | |
| 7 | # Attributes << 24 | CuIndex = 48 << 24 | 0 = 0x30000000 | |
| 8 | # CuIndexAndAttrs of foo: | |
| 9 | # Attributes << 24 | CuIndex = 48 << 24 | 1 = 0x30000001 | |
| 10 | # CHECK: Symbol table | |
| 11 | # CHECK-DAG: String name: _start, CU vector index: 0 | |
| 12 | # CHECK-DAG: String name: foo, CU vector index: 1 | |
| 13 | # CHECK: Constant pool | |
| 14 | # CHECK-NEXT: 0(0x0): 0x30000000 | |
| 15 | # CHECK-NEXT: 1(0x8): 0x30000001 | |
| 16 | ||
| 17 | .globl _start, foo | |
| 18 | _start: | |
| 19 | foo: | |
| 20 | ||
| 21 | .section .debug_abbrev,"",@progbits | |
| 22 | 	.byte	1 # Abbreviation Code | |
| 23 | 	.byte	17 # DW_TAG_compile_unit | |
| 24 | 	.byte	1 # DW_CHILDREN_yes | |
| 25 | 	.ascii	"\264B" # DW_AT_GNU_pubnames | |
| 26 | 	.byte	25 # DW_FORM_flag_present | |
| 27 | 	.byte	0 # EOM(1) | |
| 28 | 	.byte	0 # EOM(2) | |
| 29 | 	.byte	2 # Abbreviation Code | |
| 30 | 	.byte	46 # DW_TAG_subprogram | |
| 31 | 	.byte	0 # DW_CHILDREN_no | |
| 32 | 	.byte	3 # DW_AT_name | |
| 33 | 	.byte	8 # DW_FORM_string | |
| 34 | 	.byte	0 # EOM(1) | |
| 35 | 	.byte	0 # EOM(2) | |
| 36 | 	.byte	0 | |
| 37 | ||
| 38 | .section .debug_info,"",@progbits | |
| 39 | .Lcu_begin0: | |
| 40 | 	.long	.Lcu_end0 - .Lcu_begin0 - 4 | |
| 41 | 	.short	4 # DWARF version number | |
| 42 | 	.long	0 # Offset Into Abbrev. Section | |
| 43 | 	.byte	4 # Address Size | |
| 44 | .Ldie0: | |
| 45 | 	.byte	1 # Abbrev [1] DW_TAG_compile_unit | |
| 46 | 	.byte	2 # Abbrev [2] DW_TAG_subprogram | |
| 47 | 	.asciz	"_start" # DW_AT_name | |
| 48 | 	.byte	0 | |
| 49 | 	.byte	0 | |
| 50 | .Lcu_end0: | |
| 51 | .Lcu_begin1: | |
| 52 | 	.long	.Lcu_end1 - .Lcu_begin1 - 4 | |
| 53 | 	.short	4 # DWARF version number | |
| 54 | 	.long	0 # Offset Into Abbrev. Section | |
| 55 | 	.byte	4 # Address Size | |
| 56 | .Ldie1: | |
| 57 | 	.byte	1 # Abbrev [1] DW_TAG_compile_unit | |
| 58 | 	.byte	2 # Abbrev [2] DW_TAG_subprogram | |
| 59 | 	.asciz	"foo" # DW_AT_name | |
| 60 | 	.byte	0 | |
| 61 | .Lcu_end1: | |
| 62 | ||
| 63 | # Swap sets to test the case where pubnames are in a | |
| 64 | # different order than the CUs they refer to. | |
| 65 | .section .debug_gnu_pubnames,"",@progbits | |
| 66 | 	# CuIndex: 1 | |
| 67 | 	.long	.LpubNames_end1 - .LpubNames_begin1 | |
| 68 | .LpubNames_begin1: | |
| 69 | 	.short	2 # Version | |
| 70 | 	.long	.Lcu_begin1 # CU Offset | |
| 71 | 	.long	.Lcu_end1 - .Lcu_begin1 | |
| 72 | 	.long	.Ldie1 - .Lcu_begin1 | |
| 73 | 	.byte	48 # Attributes: FUNCTION, EXTERNAL | |
| 74 | 	.asciz	"foo" # External Name | |
| 75 | 	.long	0 | |
| 76 | .LpubNames_end1: | |
| 77 | ||
| 78 | 	# CuIndex: 0 | |
| 79 | 	.long	.LpubNames_end0 - .LpubNames_begin0 | |
| 80 | .LpubNames_begin0: | |
| 81 | 	.short	2 # Version | |
| 82 | 	.long	.Lcu_begin0 # CU Offset | |
| 83 | 	.long	.Lcu_end0 - .Lcu_begin0 | |
| 84 | 	.long	.Ldie0 - .Lcu_begin0 | |
| 85 | 	.byte	48 # Attributes: FUNCTION, EXTERNAL | |
| 86 | 	.asciz	"_start" # External Name | |
| 87 | 	.long	0 | |
| 88 | .LpubNames_end0: |
deps/lld/test/ELF/gdb-index-no-debug.s created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 3 | # RUN: ld.lld -o %t.exe -gdb-index %t.o | |
| 4 | # RUN: llvm-objdump --section-headers %t.exe | FileCheck %s | |
| 5 | # CHECK-NOT: .gdb_index | |
| 6 | ||
| 7 | .global _start | |
| 8 | _start: |
deps/lld/test/ELF/gdb-index-ranges.s+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | # RUN: ld.lld --gdb-index -e main %t.o -o %t |
| 4 | 4 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s |
| 5 | 5 | |
| 6 | # CHECK: .gnu_index contents: | |
| 6 | # CHECK: .gdb_index contents: | |
| 7 | 7 | # CHECK: Address area offset = 0x28, has 2 entries: |
| 8 | 8 | # CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 |
| 9 | 9 | # CHECK-NEXT: Low/High address = [0x201001, 0x201003) (Size: 0x2), CU id = 0 |
deps/lld/test/ELF/gdb-index-rng-lists.s created+202| ... | ... | @@ -0,0 +1,202 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o | |
| 3 | # RUN: ld.lld --gdb-index %t1.o -o %t | |
| 4 | # RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s | |
| 5 | ||
| 6 | ## The code contains DWARF v5 sections .debug_rnglists and .debug_addr. | |
| 7 | ## Check we are able to build the correct address | |
| 8 | ## area using address range lists. | |
| 9 | ||
| 10 | # CHECK: .gdb_index contents: | |
| 11 | # CHECK: Address area offset = 0x28, has 2 entries: | |
| 12 | # CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0 | |
| 13 | # CHECK-NEXT: Low/High address = [0x201001, 0x201003) (Size: 0x2), CU id = 0 | |
| 14 | ||
| 15 | .text | |
| 16 | .section .text._Z3zedv,"ax",@progbits | |
| 17 | .Lfunc_begin0: | |
| 18 | retq | |
| 19 | .Lfunc_end0: | |
| 20 | ||
| 21 | .section .text.main,"ax",@progbits | |
| 22 | .Lfunc_begin1: | |
| 23 | retq | |
| 24 | retq | |
| 25 | .Lfunc_end1: | |
| 26 | ||
| 27 | .section .debug_str_offsets,"",@progbits | |
| 28 | .long 32 | |
| 29 | .short 5 | |
| 30 | .short 0 | |
| 31 | .Lstr_offsets_base0: | |
| 32 | .long .Linfo_string0 | |
| 33 | .long .Linfo_string0 | |
| 34 | .long .Linfo_string0 | |
| 35 | .long .Linfo_string0 | |
| 36 | .long .Linfo_string0 | |
| 37 | .long .Linfo_string0 | |
| 38 | .long .Linfo_string0 | |
| 39 | ||
| 40 | .section .debug_str,"MS",@progbits,1 | |
| 41 | .Linfo_string0: | |
| 42 | .asciz "stub" | |
| 43 | ||
| 44 | .section .debug_abbrev,"",@progbits | |
| 45 | .byte 1 # Abbreviation Code | |
| 46 | .byte 17 # DW_TAG_compile_unit | |
| 47 | .byte 1 # DW_CHILDREN_yes | |
| 48 | .byte 37 # DW_AT_producer | |
| 49 | .byte 37 # DW_FORM_strx1 | |
| 50 | .byte 19 # DW_AT_language | |
| 51 | .byte 5 # DW_FORM_data2 | |
| 52 | .byte 3 # DW_AT_name | |
| 53 | .byte 37 # DW_FORM_strx1 | |
| 54 | .byte 114 # DW_AT_str_offsets_base | |
| 55 | .byte 23 # DW_FORM_sec_offset | |
| 56 | .byte 16 # DW_AT_stmt_list | |
| 57 | .byte 23 # DW_FORM_sec_offset | |
| 58 | .byte 27 # DW_AT_comp_dir | |
| 59 | .byte 37 # DW_FORM_strx1 | |
| 60 | .byte 115 # DW_AT_addr_base | |
| 61 | .byte 23 # DW_FORM_sec_offset | |
| 62 | .byte 17 # DW_AT_low_pc | |
| 63 | .byte 1 # DW_FORM_addr | |
| 64 | .byte 85 # DW_AT_ranges | |
| 65 | .byte 35 # DW_FORM_rnglistx | |
| 66 | .byte 116 # DW_AT_rnglists_base | |
| 67 | .byte 23 # DW_FORM_sec_offset | |
| 68 | .byte 0 # EOM(1) | |
| 69 | .byte 0 # EOM(2) | |
| 70 | .byte 2 # Abbreviation Code | |
| 71 | .byte 46 # DW_TAG_subprogram | |
| 72 | .byte 0 # DW_CHILDREN_no | |
| 73 | .byte 17 # DW_AT_low_pc | |
| 74 | .byte 27 # DW_FORM_addrx | |
| 75 | .byte 18 # DW_AT_high_pc | |
| 76 | .byte 6 # DW_FORM_data4 | |
| 77 | .byte 64 # DW_AT_frame_base | |
| 78 | .byte 24 # DW_FORM_exprloc | |
| 79 | .byte 110 # DW_AT_linkage_name | |
| 80 | .byte 37 # DW_FORM_strx1 | |
| 81 | .byte 3 # DW_AT_name | |
| 82 | .byte 37 # DW_FORM_strx1 | |
| 83 | .byte 58 # DW_AT_decl_file | |
| 84 | .byte 11 # DW_FORM_data1 | |
| 85 | .byte 59 # DW_AT_decl_line | |
| 86 | .byte 11 # DW_FORM_data1 | |
| 87 | .byte 73 # DW_AT_type | |
| 88 | .byte 19 # DW_FORM_ref4 | |
| 89 | .byte 63 # DW_AT_external | |
| 90 | .byte 25 # DW_FORM_flag_present | |
| 91 | .byte 0 # EOM(1) | |
| 92 | .byte 0 # EOM(2) | |
| 93 | .byte 3 # Abbreviation Code | |
| 94 | .byte 46 # DW_TAG_subprogram | |
| 95 | .byte 0 # DW_CHILDREN_no | |
| 96 | .byte 17 # DW_AT_low_pc | |
| 97 | .byte 27 # DW_FORM_addrx | |
| 98 | .byte 18 # DW_AT_high_pc | |
| 99 | .byte 6 # DW_FORM_data4 | |
| 100 | .byte 64 # DW_AT_frame_base | |
| 101 | .byte 24 # DW_FORM_exprloc | |
| 102 | .byte 3 # DW_AT_name | |
| 103 | .byte 37 # DW_FORM_strx1 | |
| 104 | .byte 58 # DW_AT_decl_file | |
| 105 | .byte 11 # DW_FORM_data1 | |
| 106 | .byte 59 # DW_AT_decl_line | |
| 107 | .byte 11 # DW_FORM_data1 | |
| 108 | .byte 73 # DW_AT_type | |
| 109 | .byte 19 # DW_FORM_ref4 | |
| 110 | .byte 63 # DW_AT_external | |
| 111 | .byte 25 # DW_FORM_flag_present | |
| 112 | .byte 0 # EOM(1) | |
| 113 | .byte 0 # EOM(2) | |
| 114 | .byte 4 # Abbreviation Code | |
| 115 | .byte 36 # DW_TAG_base_type | |
| 116 | .byte 0 # DW_CHILDREN_no | |
| 117 | .byte 3 # DW_AT_name | |
| 118 | .byte 37 # DW_FORM_strx1 | |
| 119 | .byte 62 # DW_AT_encoding | |
| 120 | .byte 11 # DW_FORM_data1 | |
| 121 | .byte 11 # DW_AT_byte_size | |
| 122 | .byte 11 # DW_FORM_data1 | |
| 123 | .byte 0 # EOM(1) | |
| 124 | .byte 0 # EOM(2) | |
| 125 | .byte 0 # EOM(3) | |
| 126 | ||
| 127 | .section .debug_info,"",@progbits | |
| 128 | .Lcu_begin0: | |
| 129 | .long 75 # Length of Unit | |
| 130 | .short 5 # DWARF version number | |
| 131 | .byte 1 # DWARF Unit Type | |
| 132 | .byte 8 # Address Size (in bytes) | |
| 133 | .long .debug_abbrev # Offset Into Abbrev. Section | |
| 134 | ||
| 135 | .byte 1 # Abbrev [1] 0xc:0x43 DW_TAG_compile_unit | |
| 136 | .byte 0 # DW_AT_producer | |
| 137 | .short 4 # DW_AT_language | |
| 138 | .byte 1 # DW_AT_name | |
| 139 | .long .Lstr_offsets_base0 # DW_AT_str_offsets_base | |
| 140 | .long 0 # DW_AT_stmt_list | |
| 141 | .byte 2 # DW_AT_comp_dir | |
| 142 | .long .Laddr_table_base0 # DW_AT_addr_base | |
| 143 | .quad 0 # DW_AT_low_pc | |
| 144 | .byte 0 # DW_AT_ranges | |
| 145 | .long .Lrnglists_table_base0 # DW_AT_rnglists_base | |
| 146 | ||
| 147 | .byte 2 # Abbrev [2] 0x2b:0x10 DW_TAG_subprogram | |
| 148 | .byte 0 # DW_AT_low_pc | |
| 149 | .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc | |
| 150 | .byte 1 # DW_AT_frame_base | |
| 151 | .byte 86 | |
| 152 | .byte 3 # DW_AT_linkage_name | |
| 153 | .byte 4 # DW_AT_name | |
| 154 | .byte 1 # DW_AT_decl_file | |
| 155 | .byte 1 # DW_AT_decl_line | |
| 156 | .long 74 # DW_AT_type | |
| 157 | # DW_AT_external | |
| 158 | ||
| 159 | .byte 3 # Abbrev [3] 0x3b:0xf DW_TAG_subprogram | |
| 160 | .byte 1 # DW_AT_low_pc | |
| 161 | .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc | |
| 162 | .byte 1 # DW_AT_frame_base | |
| 163 | .byte 86 | |
| 164 | .byte 6 # DW_AT_name | |
| 165 | .byte 1 # DW_AT_decl_file | |
| 166 | .byte 5 # DW_AT_decl_line | |
| 167 | .long 74 # DW_AT_type | |
| 168 | # DW_AT_external | |
| 169 | ||
| 170 | .byte 4 # Abbrev [4] 0x4a:0x4 DW_TAG_base_type | |
| 171 | .byte 5 # DW_AT_name | |
| 172 | .byte 5 # DW_AT_encoding | |
| 173 | .byte 4 # DW_AT_byte_size | |
| 174 | .byte 0 # End Of Children Mark | |
| 175 | ||
| 176 | .section .debug_rnglists,"",@progbits | |
| 177 | .long .Ldebug_rnglist_table_end0-.Ldebug_rnglist_table_start0 # Length | |
| 178 | .Ldebug_rnglist_table_start0: | |
| 179 | .short 5 # Version | |
| 180 | .byte 8 # Address size | |
| 181 | .byte 0 # Segment selector size | |
| 182 | .long 1 # Offset entry count | |
| 183 | .Lrnglists_table_base0: | |
| 184 | .long .Ldebug_ranges0-.Lrnglists_table_base0 | |
| 185 | .Ldebug_ranges0: | |
| 186 | .byte 3 # DW_RLE_startx_length | |
| 187 | .byte 0 # start index | |
| 188 | .uleb128 .Lfunc_end0-.Lfunc_begin0 # length | |
| 189 | .byte 3 # DW_RLE_startx_length | |
| 190 | .byte 1 # start index | |
| 191 | .uleb128 .Lfunc_end1-.Lfunc_begin1 # length | |
| 192 | .byte 0 # DW_RLE_end_of_list | |
| 193 | .Ldebug_rnglist_table_end0: | |
| 194 | ||
| 195 | .section .debug_addr,"",@progbits | |
| 196 | .long 20 | |
| 197 | .short 5 | |
| 198 | .byte 8 | |
| 199 | .byte 0 | |
| 200 | .Laddr_table_base0: | |
| 201 | .quad .Lfunc_begin0 | |
| 202 | .quad .Lfunc_begin1 |
deps/lld/test/ELF/gdb-index.s+1-1| ... | ... | @@ -25,7 +25,7 @@ |
| 25 | 25 | # DISASM-CHECK: 201004: 90 nop |
| 26 | 26 | # DISASM-CHECK: 201005: 90 nop |
| 27 | 27 | |
| 28 | # DWARF: .gnu_index contents: | |
| 28 | # DWARF: .gdb_index contents: | |
| 29 | 29 | # DWARF-NEXT: Version = 7 |
| 30 | 30 | # DWARF: CU list offset = 0x18, has 2 entries: |
| 31 | 31 | # DWARF-NEXT: 0: Offset = 0x0, Length = 0x34 |
deps/lld/test/ELF/global-offset-table-position-redef-err.s created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 3 | # RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s | |
| 4 | ||
| 5 | # On some targets the location of the _GLOBAL_OFFSET_TABLE_ symbol table can | |
| 6 | # matter for the correctness of some relocations. Follow the example of ld.gold | |
| 7 | # and give a multiple definition error if input objects attempt to redefine it. | |
| 8 | ||
| 9 | # CHECK: ld.lld: error: {{.*o}} cannot redefine linker defined symbol '_GLOBAL_OFFSET_TABLE_' | |
| 10 | ||
| 11 | .data | |
| 12 | .global _GLOBAL_OFFSET_TABLE_ | |
| 13 | _GLOBAL_OFFSET_TABLE_: | |
| 14 | .word 0 |
deps/lld/test/ELF/gnu-hash-table-copy.s+4-4| ... | ... | @@ -13,10 +13,10 @@ |
| 13 | 13 | |
| 14 | 14 | # CHECK: Symbol table '.dynsym' contains 4 entries: |
| 15 | 15 | # CHECK-NEXT: Num: Value Size Type Bind Vis Ndx Name |
| 16 | # CHECK-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND @ | |
| 17 | # CHECK-NEXT: 1: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND foo@ | |
| 18 | # CHECK-DAG: : {{.*}} 4 OBJECT GLOBAL DEFAULT {{.*}} bar@ | |
| 19 | # CHECK-DAG: : {{.*}} 0 FUNC GLOBAL DEFAULT UND zed@ | |
| 16 | # CHECK-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND | |
| 17 | # CHECK-NEXT: 1: 0000000000000000 0 OBJECT GLOBAL DEFAULT UND foo | |
| 18 | # CHECK-DAG: : {{.*}} 4 OBJECT GLOBAL DEFAULT {{.*}} bar | |
| 19 | # CHECK-DAG: : {{.*}} 0 FUNC GLOBAL DEFAULT UND zed | |
| 20 | 20 | |
| 21 | 21 | # CHECK: First Hashed Symbol Index: 2 |
| 22 | 22 |
deps/lld/test/ELF/gnu-hash-table-rwsegment.s+2-2| ... | ... | @@ -8,8 +8,8 @@ |
| 8 | 8 | # CHECK-NEXT: Num Buckets: 1 |
| 9 | 9 | # CHECK-NEXT: First Hashed Symbol Index: 1 |
| 10 | 10 | # CHECK-NEXT: Num Mask Words: 1 |
| 11 | # CHECK-NEXT: Shift Count: 6 | |
| 12 | # CHECK-NEXT: Bloom Filter: [0x400000000004204] | |
| 11 | # CHECK-NEXT: Shift Count: 26 | |
| 12 | # CHECK-NEXT: Bloom Filter: [0x400000000000204] | |
| 13 | 13 | # CHECK-NEXT: Buckets: [1] |
| 14 | 14 | # CHECK-NEXT: Values: [0xB8860BA, 0xB887389] |
| 15 | 15 | # CHECK-NEXT: } |
deps/lld/test/ELF/gnu-hash-table.s+27-27| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %t2.s -o %t2-ppc64le.o |
| 14 | 14 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %t2.s -o %t2-ppc64.o |
| 15 | 15 | |
| 16 | # RUN: rm -f %t2-i386.a %t2-x86_64.a %t2-ppc64.a | |
| 16 | # RUN: rm -f %t2-i386.a %t2-x86_64.a %t2-ppc64.a %t2-ppc64le.a | |
| 17 | 17 | # RUN: llvm-ar rc %t2-i386.a %t2-i386.o |
| 18 | 18 | # RUN: llvm-ar rc %t2-x86_64.a %t2-x86_64.o |
| 19 | 19 | # RUN: llvm-ar rc %t2-ppc64le.a %t2-ppc64le.o |
| ... | ... | @@ -49,7 +49,7 @@ |
| 49 | 49 | |
| 50 | 50 | # EMPTY: DynamicSymbols [ |
| 51 | 51 | # EMPTY: Symbol { |
| 52 | # EMPTY: Name: foo@ | |
| 52 | # EMPTY: Name: foo | |
| 53 | 53 | # EMPTY-NEXT: Value: 0x0 |
| 54 | 54 | # EMPTY-NEXT: Size: 0 |
| 55 | 55 | # EMPTY-NEXT: Binding: Global |
| ... | ... | @@ -62,7 +62,7 @@ |
| 62 | 62 | # EMPTY-NEXT: Num Buckets: 1 |
| 63 | 63 | # EMPTY-NEXT: First Hashed Symbol Index: 2 |
| 64 | 64 | # EMPTY-NEXT: Num Mask Words: 1 |
| 65 | # EMPTY-NEXT: Shift Count: 6 | |
| 65 | # EMPTY-NEXT: Shift Count: 26 | |
| 66 | 66 | # EMPTY-NEXT: Bloom Filter: [0x0] |
| 67 | 67 | # EMPTY-NEXT: Buckets: [0] |
| 68 | 68 | # EMPTY-NEXT: Values: [] |
| ... | ... | @@ -87,32 +87,32 @@ |
| 87 | 87 | # I386: ] |
| 88 | 88 | # I386: DynamicSymbols [ |
| 89 | 89 | # I386: Symbol { |
| 90 | # I386: Name: @ | |
| 90 | # I386: Name: | |
| 91 | 91 | # I386: Binding: Local |
| 92 | 92 | # I386: Section: Undefined |
| 93 | 93 | # I386: } |
| 94 | 94 | # I386: Symbol { |
| 95 | # I386: Name: baz@ | |
| 95 | # I386: Name: baz | |
| 96 | 96 | # I386: Binding: Global |
| 97 | 97 | # I386: Section: Undefined |
| 98 | 98 | # I386: } |
| 99 | 99 | # I386: Symbol { |
| 100 | # I386: Name: xyz@ | |
| 100 | # I386: Name: xyz | |
| 101 | 101 | # I386: Binding: Global |
| 102 | 102 | # I386: Section: Undefined |
| 103 | 103 | # I386: } |
| 104 | 104 | # I386: Symbol { |
| 105 | # I386: Name: zed@ | |
| 105 | # I386: Name: zed | |
| 106 | 106 | # I386: Binding: Weak |
| 107 | 107 | # I386: Section: Undefined |
| 108 | 108 | # I386: } |
| 109 | 109 | # I386: Symbol { |
| 110 | # I386: Name: bar@ | |
| 110 | # I386: Name: bar | |
| 111 | 111 | # I386: Binding: Global |
| 112 | 112 | # I386: Section: .text |
| 113 | 113 | # I386: } |
| 114 | 114 | # I386: Symbol { |
| 115 | # I386: Name: foo@ | |
| 115 | # I386: Name: foo | |
| 116 | 116 | # I386: Binding: Global |
| 117 | 117 | # I386: Section: .text |
| 118 | 118 | # I386: } |
| ... | ... | @@ -121,8 +121,8 @@ |
| 121 | 121 | # I386-NEXT: Num Buckets: 1 |
| 122 | 122 | # I386-NEXT: First Hashed Symbol Index: 4 |
| 123 | 123 | # I386-NEXT: Num Mask Words: 1 |
| 124 | # I386-NEXT: Shift Count: 6 | |
| 125 | # I386-NEXT: Bloom Filter: [0x4004204] | |
| 124 | # I386-NEXT: Shift Count: 26 | |
| 125 | # I386-NEXT: Bloom Filter: [0x4000204] | |
| 126 | 126 | # I386-NEXT: Buckets: [4] |
| 127 | 127 | # I386-NEXT: Values: [0xB8860BA, 0xB887389] |
| 128 | 128 | # I386-NEXT: } |
| ... | ... | @@ -147,32 +147,32 @@ |
| 147 | 147 | # X86_64: ] |
| 148 | 148 | # X86_64: DynamicSymbols [ |
| 149 | 149 | # X86_64: Symbol { |
| 150 | # X86_64: Name: @ | |
| 150 | # X86_64: Name: | |
| 151 | 151 | # X86_64: Binding: Local |
| 152 | 152 | # X86_64: Section: Undefined |
| 153 | 153 | # X86_64: } |
| 154 | 154 | # X86_64: Symbol { |
| 155 | # X86_64: Name: baz@ | |
| 155 | # X86_64: Name: baz | |
| 156 | 156 | # X86_64: Binding: Global |
| 157 | 157 | # X86_64: Section: Undefined |
| 158 | 158 | # X86_64: } |
| 159 | 159 | # X86_64: Symbol { |
| 160 | # X86_64: Name: xyz@ | |
| 160 | # X86_64: Name: xyz | |
| 161 | 161 | # X86_64: Binding: Global |
| 162 | 162 | # X86_64: Section: Undefined |
| 163 | 163 | # X86_64: } |
| 164 | 164 | # X86_64: Symbol { |
| 165 | # X86_64: Name: zed@ | |
| 165 | # X86_64: Name: zed | |
| 166 | 166 | # X86_64: Binding: Weak |
| 167 | 167 | # X86_64: Section: Undefined |
| 168 | 168 | # X86_64: } |
| 169 | 169 | # X86_64: Symbol { |
| 170 | # X86_64: Name: bar@ | |
| 170 | # X86_64: Name: bar | |
| 171 | 171 | # X86_64: Binding: Global |
| 172 | 172 | # X86_64: Section: .text |
| 173 | 173 | # X86_64: } |
| 174 | 174 | # X86_64: Symbol { |
| 175 | # X86_64: Name: foo@ | |
| 175 | # X86_64: Name: foo | |
| 176 | 176 | # X86_64: Binding: Global |
| 177 | 177 | # X86_64: Section: .text |
| 178 | 178 | # X86_64: } |
| ... | ... | @@ -181,8 +181,8 @@ |
| 181 | 181 | # X86_64-NEXT: Num Buckets: 1 |
| 182 | 182 | # X86_64-NEXT: First Hashed Symbol Index: 4 |
| 183 | 183 | # X86_64-NEXT: Num Mask Words: 1 |
| 184 | # X86_64-NEXT: Shift Count: 6 | |
| 185 | # X86_64-NEXT: Bloom Filter: [0x400000000004204] | |
| 184 | # X86_64-NEXT: Shift Count: 26 | |
| 185 | # X86_64-NEXT: Bloom Filter: [0x400000000000204] | |
| 186 | 186 | # X86_64-NEXT: Buckets: [4] |
| 187 | 187 | # X86_64-NEXT: Values: [0xB8860BA, 0xB887389] |
| 188 | 188 | # X86_64-NEXT: } |
| ... | ... | @@ -207,32 +207,32 @@ |
| 207 | 207 | # PPC64: ] |
| 208 | 208 | # PPC64: DynamicSymbols [ |
| 209 | 209 | # PPC64: Symbol { |
| 210 | # PPC64: Name: @ | |
| 210 | # PPC64: Name: | |
| 211 | 211 | # PPC64: Binding: Local |
| 212 | 212 | # PPC64: Section: Undefined |
| 213 | 213 | # PPC64: } |
| 214 | 214 | # PPC64: Symbol { |
| 215 | # PPC64: Name: baz@ | |
| 215 | # PPC64: Name: baz | |
| 216 | 216 | # PPC64: Binding: Global |
| 217 | 217 | # PPC64: Section: Undefined |
| 218 | 218 | # PPC64: } |
| 219 | 219 | # PPC64: Symbol { |
| 220 | # PPC64: Name: xyz@ | |
| 220 | # PPC64: Name: xyz | |
| 221 | 221 | # PPC64: Binding: Global |
| 222 | 222 | # PPC64: Section: Undefined |
| 223 | 223 | # PPC64: } |
| 224 | 224 | # PPC64: Symbol { |
| 225 | # PPC64: Name: zed@ | |
| 225 | # PPC64: Name: zed | |
| 226 | 226 | # PPC64: Binding: Weak |
| 227 | 227 | # PPC64: Section: Undefined |
| 228 | 228 | # PPC64: } |
| 229 | 229 | # PPC64: Symbol { |
| 230 | # PPC64: Name: bar@ | |
| 230 | # PPC64: Name: bar | |
| 231 | 231 | # PPC64: Binding: Global |
| 232 | 232 | # PPC64: Section: .text |
| 233 | 233 | # PPC64: } |
| 234 | 234 | # PPC64: Symbol { |
| 235 | # PPC64: Name: foo@ | |
| 235 | # PPC64: Name: foo | |
| 236 | 236 | # PPC64: Binding: Global |
| 237 | 237 | # PPC64: Section: .text |
| 238 | 238 | # PPC64: } |
| ... | ... | @@ -241,8 +241,8 @@ |
| 241 | 241 | # PPC64-NEXT: Num Buckets: 1 |
| 242 | 242 | # PPC64-NEXT: First Hashed Symbol Index: 4 |
| 243 | 243 | # PPC64-NEXT: Num Mask Words: 1 |
| 244 | # PPC64-NEXT: Shift Count: 6 | |
| 245 | # PPC64-NEXT: Bloom Filter: [0x400000000004204] | |
| 244 | # PPC64-NEXT: Shift Count: 26 | |
| 245 | # PPC64-NEXT: Bloom Filter: [0x400000000000204] | |
| 246 | 246 | # PPC64-NEXT: Buckets: [4] |
| 247 | 247 | # PPC64-NEXT: Values: [0xB8860BA, 0xB887389] |
| 248 | 248 | # PPC64-NEXT: } |
deps/lld/test/ELF/gnu-ifunc-empty.s created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | ||
| 3 | // Verifies that .rela_iplt_{start,end} point to a dummy section | |
| 4 | // if .rela.iplt does not exist. | |
| 5 | ||
| 6 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 7 | // RUN: ld.lld -static %t.o -o %t.exe | |
| 8 | // RUN: llvm-objdump -syms %t.exe | FileCheck %s | |
| 9 | ||
| 10 | // CHECK: 0000000000200000 .text 00000000 .hidden __rela_iplt_end | |
| 11 | // CHECK: 0000000000200000 .text 00000000 .hidden __rela_iplt_start | |
| 12 | ||
| 13 | .globl _start | |
| 14 | _start: | |
| 15 | movl $__rela_iplt_start, %edx | |
| 16 | movl $__rela_iplt_end, %edx |
deps/lld/test/ELF/gnu-ifunc-i386.s+19-19| ... | ... | @@ -16,14 +16,14 @@ |
| 16 | 16 | // CHECK-NEXT: Offset: 0xD4 |
| 17 | 17 | // CHECK-NEXT: Size: 16 |
| 18 | 18 | // CHECK-NEXT: Link: 0 |
| 19 | // CHECK-NEXT: Info: 0 | |
| 19 | // CHECK-NEXT: Info: 4 | |
| 20 | 20 | // CHECK-NEXT: AddressAlignment: 4 |
| 21 | 21 | // CHECK-NEXT: EntrySize: 8 |
| 22 | 22 | // CHECK-NEXT: } |
| 23 | 23 | // CHECK: Relocations [ |
| 24 | 24 | // CHECK-NEXT: Section ({{.*}}) .rel.plt { |
| 25 | // CHECK-NEXT: 0x12000 R_386_IRELATIVE | |
| 26 | // CHECK-NEXT: 0x12004 R_386_IRELATIVE | |
| 25 | // CHECK-NEXT: 0x402000 R_386_IRELATIVE | |
| 26 | // CHECK-NEXT: 0x402004 R_386_IRELATIVE | |
| 27 | 27 | // CHECK-NEXT: } |
| 28 | 28 | // CHECK-NEXT: ] |
| 29 | 29 | |
| ... | ... | @@ -39,7 +39,7 @@ |
| 39 | 39 | // CHECK-NEXT: } |
| 40 | 40 | // CHECK-NEXT: Symbol { |
| 41 | 41 | // CHECK-NEXT: Name: __rel_iplt_end |
| 42 | // CHECK-NEXT: Value: 0x100E4 | |
| 42 | // CHECK-NEXT: Value: 0x4000E4 | |
| 43 | 43 | // CHECK-NEXT: Size: 0 |
| 44 | 44 | // CHECK-NEXT: Binding: Local |
| 45 | 45 | // CHECK-NEXT: Type: None |
| ... | ... | @@ -61,7 +61,7 @@ |
| 61 | 61 | // CHECK-NEXT: } |
| 62 | 62 | // CHECK-NEXT: Symbol { |
| 63 | 63 | // CHECK-NEXT: Name: _start |
| 64 | // CHECK-NEXT: Value: 0x11002 | |
| 64 | // CHECK-NEXT: Value: 0x401002 | |
| 65 | 65 | // CHECK-NEXT: Size: 0 |
| 66 | 66 | // CHECK-NEXT: Binding: Global |
| 67 | 67 | // CHECK-NEXT: Type: None |
| ... | ... | @@ -70,7 +70,7 @@ |
| 70 | 70 | // CHECK-NEXT: } |
| 71 | 71 | // CHECK-NEXT: Symbol { |
| 72 | 72 | // CHECK-NEXT: Name: bar |
| 73 | // CHECK-NEXT: Value: 0x11001 | |
| 73 | // CHECK-NEXT: Value: 0x401001 | |
| 74 | 74 | // CHECK-NEXT: Size: 0 |
| 75 | 75 | // CHECK-NEXT: Binding: Global |
| 76 | 76 | // CHECK-NEXT: Type: GNU_IFunc |
| ... | ... | @@ -79,7 +79,7 @@ |
| 79 | 79 | // CHECK-NEXT: } |
| 80 | 80 | // CHECK-NEXT: Symbol { |
| 81 | 81 | // CHECK-NEXT: Name: foo |
| 82 | // CHECK-NEXT: Value: 0x11000 | |
| 82 | // CHECK-NEXT: Value: 0x401000 | |
| 83 | 83 | // CHECK-NEXT: Size: 0 |
| 84 | 84 | // CHECK-NEXT: Binding: Global |
| 85 | 85 | // CHECK-NEXT: Type: GNU_IFunc |
| ... | ... | @@ -90,22 +90,22 @@ |
| 90 | 90 | |
| 91 | 91 | // DISASM: Disassembly of section .text: |
| 92 | 92 | // DISASM-NEXT: foo: |
| 93 | // DISASM-NEXT: 11000: c3 retl | |
| 93 | // DISASM-NEXT: 401000: c3 retl | |
| 94 | 94 | // DISASM: bar: |
| 95 | // DISASM-NEXT: 11001: c3 retl | |
| 95 | // DISASM-NEXT: 401001: c3 retl | |
| 96 | 96 | // DISASM: _start: |
| 97 | // DISASM-NEXT: 11002: e8 19 00 00 00 calll 25 | |
| 98 | // DISASM-NEXT: 11007: e8 24 00 00 00 calll 36 | |
| 99 | // DISASM-NEXT: 1100c: ba d4 00 01 00 movl $65748, %edx | |
| 100 | // DISASM-NEXT: 11011: ba e4 00 01 00 movl $65764, %edx | |
| 97 | // DISASM-NEXT: 401002: e8 19 00 00 00 calll 25 | |
| 98 | // DISASM-NEXT: 401007: e8 24 00 00 00 calll 36 | |
| 99 | // DISASM-NEXT: 40100c: ba d4 00 40 00 movl $4194516, %edx | |
| 100 | // DISASM-NEXT: 401011: ba e4 00 40 00 movl $4194532, %edx | |
| 101 | 101 | // DISASM-NEXT: Disassembly of section .plt: |
| 102 | 102 | // DISASM-NEXT: .plt: |
| 103 | // DISASM-NEXT: 11020: ff 25 00 20 01 00 jmpl *73728 | |
| 104 | // DISASM-NEXT: 11026: 68 10 00 00 00 pushl $16 | |
| 105 | // DISASM-NEXT: 1102b: e9 e0 ff ff ff jmp -32 <_start+0xe> | |
| 106 | // DISASM-NEXT: 11030: ff 25 04 20 01 00 jmpl *73732 | |
| 107 | // DISASM-NEXT: 11036: 68 18 00 00 00 pushl $24 | |
| 108 | // DISASM-NEXT: 1103b: e9 d0 ff ff ff jmp -48 <_start+0xe> | |
| 103 | // DISASM-NEXT: 401020: ff 25 00 20 40 00 jmpl *4202496 | |
| 104 | // DISASM-NEXT: 401026: 68 10 00 00 00 pushl $16 | |
| 105 | // DISASM-NEXT: 40102b: e9 e0 ff ff ff jmp -32 <_start+0xe> | |
| 106 | // DISASM-NEXT: 401030: ff 25 04 20 40 00 jmpl *4202500 | |
| 107 | // DISASM-NEXT: 401036: 68 18 00 00 00 pushl $24 | |
| 108 | // DISASM-NEXT: 40103b: e9 d0 ff ff ff jmp -48 <_start+0xe> | |
| 109 | 109 | |
| 110 | 110 | .text |
| 111 | 111 | .type foo STT_GNU_IFUNC |
deps/lld/test/ELF/gnu-ifunc-plt-i386.s+34-30| ... | ... | @@ -10,16 +10,16 @@ |
| 10 | 10 | // Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt |
| 11 | 11 | // CHECK: Relocations [ |
| 12 | 12 | // CHECK-NEXT: Section (4) .rel.plt { |
| 13 | // CHECK-NEXT: 0x1200C R_386_JUMP_SLOT bar2 | |
| 14 | // CHECK-NEXT: 0x12010 R_386_JUMP_SLOT zed2 | |
| 15 | // CHECK-NEXT: 0x12014 R_386_IRELATIVE | |
| 16 | // CHECK-NEXT: 0x12018 R_386_IRELATIVE | |
| 13 | // CHECK-NEXT: 0x40200C R_386_JUMP_SLOT bar2 | |
| 14 | // CHECK-NEXT: 0x402010 R_386_JUMP_SLOT zed2 | |
| 15 | // CHECK-NEXT: 0x402014 R_386_IRELATIVE | |
| 16 | // CHECK-NEXT: 0x402018 R_386_IRELATIVE | |
| 17 | 17 | |
| 18 | 18 | // Check that IRELATIVE .got.plt entries point to ifunc resolver and not |
| 19 | 19 | // back to the plt entry + 6. |
| 20 | 20 | // GOTPLT: Contents of section .got.plt: |
| 21 | // GOTPLT: 12000 00300100 00000000 00000000 36100100 | |
| 22 | // GOTPLT-NEXT: 12010 46100100 00100100 01100100 | |
| 21 | // GOTPLT: 402000 00304000 00000000 00000000 36104000 | |
| 22 | // GOTPLT-NEXT: 402010 46104000 00104000 01104000 | |
| 23 | 23 | |
| 24 | 24 | // Check that the PLTRELSZ tag includes the IRELATIVE relocations |
| 25 | 25 | // CHECK: DynamicSection [ |
| ... | ... | @@ -28,34 +28,38 @@ |
| 28 | 28 | // Check that a PLT header is written and the ifunc entries appear last |
| 29 | 29 | // DISASM: Disassembly of section .text: |
| 30 | 30 | // DISASM-NEXT: foo: |
| 31 | // DISASM-NEXT: 11000: c3 retl | |
| 31 | // DISASM-NEXT: 401000: c3 retl | |
| 32 | 32 | // DISASM: bar: |
| 33 | // DISASM-NEXT: 11001: c3 retl | |
| 33 | // DISASM-NEXT: 401001: c3 retl | |
| 34 | 34 | // DISASM: _start: |
| 35 | // DISASM-NEXT: 11002: e8 49 00 00 00 calll 73 | |
| 36 | // DISASM-NEXT: 11007: e8 54 00 00 00 calll 84 | |
| 37 | // DISASM-NEXT: 1100c: e8 1f 00 00 00 calll 31 | |
| 38 | // DISASM-NEXT: 11011: e8 2a 00 00 00 calll 42 | |
| 35 | // DISASM-NEXT: 401002: e8 49 00 00 00 calll 73 | |
| 36 | // DISASM-NEXT: 401007: e8 54 00 00 00 calll 84 | |
| 37 | // DISASM-NEXT: 40100c: e8 1f 00 00 00 calll 31 | |
| 38 | // DISASM-NEXT: 401011: e8 2a 00 00 00 calll 42 | |
| 39 | 39 | // DISASM-NEXT: Disassembly of section .plt: |
| 40 | 40 | // DISASM-NEXT: .plt: |
| 41 | // DISASM-NEXT: 11020: ff 35 04 20 01 00 pushl 73732 | |
| 42 | // DISASM-NEXT: 11026: ff 25 08 20 01 00 jmpl *73736 | |
| 43 | // DISASM-NEXT: 1102c: 90 nop | |
| 44 | // DISASM-NEXT: 1102d: 90 nop | |
| 45 | // DISASM-NEXT: 1102e: 90 nop | |
| 46 | // DISASM-NEXT: 1102f: 90 nop | |
| 47 | // DISASM-NEXT: 11030: ff 25 0c 20 01 00 jmpl *73740 | |
| 48 | // DISASM-NEXT: 11036: 68 00 00 00 00 pushl $0 | |
| 49 | // DISASM-NEXT: 1103b: e9 e0 ff ff ff jmp -32 <.plt> | |
| 50 | // DISASM-NEXT: 11040: ff 25 10 20 01 00 jmpl *73744 | |
| 51 | // DISASM-NEXT: 11046: 68 08 00 00 00 pushl $8 | |
| 52 | // DISASM-NEXT: 1104b: e9 d0 ff ff ff jmp -48 <.plt> | |
| 53 | // DISASM-NEXT: 11050: ff 25 14 20 01 00 jmpl *73748 | |
| 54 | // DISASM-NEXT: 11056: 68 30 00 00 00 pushl $48 | |
| 55 | // DISASM-NEXT: 1105b: e9 e0 ff ff ff jmp -32 <.plt+0x20> | |
| 56 | // DISASM-NEXT: 11060: ff 25 18 20 01 00 jmpl *73752 | |
| 57 | // DISASM-NEXT: 11066: 68 38 00 00 00 pushl $56 | |
| 58 | // DISASM-NEXT: 1106b: e9 d0 ff ff ff jmp -48 <.plt+0x20> | |
| 41 | // DISASM-NEXT: 401020: ff 35 04 20 40 00 pushl 4202500 | |
| 42 | // DISASM-NEXT: 401026: ff 25 08 20 40 00 jmpl *4202504 | |
| 43 | // DISASM-NEXT: 40102c: 90 nop | |
| 44 | // DISASM-NEXT: 40102d: 90 nop | |
| 45 | // DISASM-NEXT: 40102e: 90 nop | |
| 46 | // DISASM-NEXT: 40102f: 90 nop | |
| 47 | // DISASM-EMPTY: | |
| 48 | // DISASM-NEXT: bar2@plt: | |
| 49 | // DISASM-NEXT: 401030: ff 25 0c 20 40 00 jmpl *4202508 | |
| 50 | // DISASM-NEXT: 401036: 68 00 00 00 00 pushl $0 | |
| 51 | // DISASM-NEXT: 40103b: e9 e0 ff ff ff jmp -32 <.plt> | |
| 52 | // DISASM-EMPTY: | |
| 53 | // DISASM-NEXT: zed2@plt: | |
| 54 | // DISASM-NEXT: 401040: ff 25 10 20 40 00 jmpl *4202512 | |
| 55 | // DISASM-NEXT: 401046: 68 08 00 00 00 pushl $8 | |
| 56 | // DISASM-NEXT: 40104b: e9 d0 ff ff ff jmp -48 <.plt> | |
| 57 | // DISASM-NEXT: 401050: ff 25 14 20 40 00 jmpl *4202516 | |
| 58 | // DISASM-NEXT: 401056: 68 30 00 00 00 pushl $48 | |
| 59 | // DISASM-NEXT: 40105b: e9 e0 ff ff ff jmp -32 <zed2@plt> | |
| 60 | // DISASM-NEXT: 401060: ff 25 18 20 40 00 jmpl *4202520 | |
| 61 | // DISASM-NEXT: 401066: 68 38 00 00 00 pushl $56 | |
| 62 | // DISASM-NEXT: 40106b: e9 d0 ff ff ff jmp -48 <zed2@plt> | |
| 59 | 63 | |
| 60 | 64 | .text |
| 61 | 65 | .type foo STT_GNU_IFUNC |
deps/lld/test/ELF/gnu-ifunc-plt.s+6-2| ... | ... | @@ -42,18 +42,22 @@ |
| 42 | 42 | // DISASM-NEXT: 201020: ff 35 e2 0f 00 00 pushq 4066(%rip) |
| 43 | 43 | // DISASM-NEXT: 201026: ff 25 e4 0f 00 00 jmpq *4068(%rip) |
| 44 | 44 | // DISASM-NEXT: 20102c: 0f 1f 40 00 nopl (%rax) |
| 45 | // DISASM-EMPTY: | |
| 46 | // DISASM-NEXT: bar2@plt: | |
| 45 | 47 | // DISASM-NEXT: 201030: ff 25 e2 0f 00 00 jmpq *4066(%rip) |
| 46 | 48 | // DISASM-NEXT: 201036: 68 00 00 00 00 pushq $0 |
| 47 | 49 | // DISASM-NEXT: 20103b: e9 e0 ff ff ff jmp -32 <.plt> |
| 50 | // DISASM-EMPTY: | |
| 51 | // DISASM-NEXT: zed2@plt: | |
| 48 | 52 | // DISASM-NEXT: 201040: ff 25 da 0f 00 00 jmpq *4058(%rip) |
| 49 | 53 | // DISASM-NEXT: 201046: 68 01 00 00 00 pushq $1 |
| 50 | 54 | // DISASM-NEXT: 20104b: e9 d0 ff ff ff jmp -48 <.plt> |
| 51 | 55 | // DISASM-NEXT: 201050: ff 25 d2 0f 00 00 jmpq *4050(%rip) |
| 52 | 56 | // DISASM-NEXT: 201056: 68 00 00 00 00 pushq $0 |
| 53 | // DISASM-NEXT: 20105b: e9 e0 ff ff ff jmp -32 <.plt+0x20> | |
| 57 | // DISASM-NEXT: 20105b: e9 e0 ff ff ff jmp -32 <zed2@plt> | |
| 54 | 58 | // DISASM-NEXT: 201060: ff 25 ca 0f 00 00 jmpq *4042(%rip) |
| 55 | 59 | // DISASM-NEXT: 201066: 68 01 00 00 00 pushq $1 |
| 56 | // DISASM-NEXT: 20106b: e9 d0 ff ff ff jmp -48 <.plt+0x20> | |
| 60 | // DISASM-NEXT: 20106b: e9 d0 ff ff ff jmp -48 <zed2@plt> | |
| 57 | 61 | |
| 58 | 62 | .text |
| 59 | 63 | .type foo STT_GNU_IFUNC |
deps/lld/test/ELF/gnu-ifunc-relative.s+9-7| ... | ... | @@ -1,7 +1,9 @@ |
| 1 | 1 | // REQUIRES: x86 |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: ld.lld -static %t.o -o %tout | |
| 4 | // RUN: llvm-readobj -r -t %tout | FileCheck %s | |
| 3 | // RUN: ld.lld --strip-all %t.o -o %t | |
| 4 | // RUN: llvm-readobj -r %t | FileCheck %s | |
| 5 | // RUN: ld.lld %t.o -o %t | |
| 6 | // RUN: llvm-readobj -r -t %t | FileCheck %s --check-prefixes=CHECK,SYM | |
| 5 | 7 | |
| 6 | 8 | .type foo STT_GNU_IFUNC |
| 7 | 9 | .globl foo |
| ... | ... | @@ -16,8 +18,8 @@ _start: |
| 16 | 18 | // CHECK-NEXT: R_X86_64_IRELATIVE - 0x[[ADDR:.*]] |
| 17 | 19 | // CHECK-NEXT: } |
| 18 | 20 | |
| 19 | // CHECK: Name: foo | |
| 20 | // CHECK-NEXT: Value: 0x[[ADDR]] | |
| 21 | // CHECK-NEXT: Size: 0 | |
| 22 | // CHECK-NEXT: Binding: Global | |
| 23 | // CHECK-NEXT: Type: GNU_IFunc | |
| 21 | // SYM: Name: foo | |
| 22 | // SYM-NEXT: Value: 0x[[ADDR]] | |
| 23 | // SYM-NEXT: Size: 0 | |
| 24 | // SYM-NEXT: Binding: Global | |
| 25 | // SYM-NEXT: Type: GNU_IFunc |
deps/lld/test/ELF/gnu-ifunc-shared.s+5-1| ... | ... | @@ -23,15 +23,19 @@ |
| 23 | 23 | // DISASM-NEXT: 1020: ff 35 e2 0f 00 00 pushq 4066(%rip) |
| 24 | 24 | // DISASM-NEXT: 1026: ff 25 e4 0f 00 00 jmpq *4068(%rip) |
| 25 | 25 | // DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax) |
| 26 | // DISASM-EMPTY: | |
| 27 | // DISASM-NEXT: fct2@plt: | |
| 26 | 28 | // DISASM-NEXT: 1030: ff 25 e2 0f 00 00 jmpq *4066(%rip) |
| 27 | 29 | // DISASM-NEXT: 1036: 68 00 00 00 00 pushq $0 |
| 28 | 30 | // DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt> |
| 31 | // DISASM-EMPTY: | |
| 32 | // DISASM-NEXT: f2@plt: | |
| 29 | 33 | // DISASM-NEXT: 1040: ff 25 da 0f 00 00 jmpq *4058(%rip) |
| 30 | 34 | // DISASM-NEXT: 1046: 68 01 00 00 00 pushq $1 |
| 31 | 35 | // DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt> |
| 32 | 36 | // DISASM-NEXT: 1050: ff 25 d2 0f 00 00 jmpq *4050(%rip) |
| 33 | 37 | // DISASM-NEXT: 1056: 68 00 00 00 00 pushq $0 |
| 34 | // DISASM-NEXT: 105b: e9 e0 ff ff ff jmp -32 <.plt+0x20> | |
| 38 | // DISASM-NEXT: 105b: e9 e0 ff ff ff jmp -32 <f2@plt> | |
| 35 | 39 | |
| 36 | 40 | // CHECK: Relocations [ |
| 37 | 41 | // CHECK-NEXT: Section (4) .rela.plt { |
deps/lld/test/ELF/gnu-ifunc.s+3-1| ... | ... | @@ -16,10 +16,12 @@ |
| 16 | 16 | // CHECK-NEXT: Offset: 0x158 |
| 17 | 17 | // CHECK-NEXT: Size: 48 |
| 18 | 18 | // CHECK-NEXT: Link: 0 |
| 19 | // CHECK-NEXT: Info: 0 | |
| 19 | // CHECK-NEXT: Info: [[GOTPLT:.*]] | |
| 20 | 20 | // CHECK-NEXT: AddressAlignment: 8 |
| 21 | 21 | // CHECK-NEXT: EntrySize: 24 |
| 22 | 22 | // CHECK-NEXT: } |
| 23 | // CHECK: Index: [[GOTPLT]] | |
| 24 | // CHECK-NEXT: Name: .got.plt | |
| 23 | 25 | // CHECK: Relocations [ |
| 24 | 26 | // CHECK-NEXT: Section ({{.*}}) .rela.plt { |
| 25 | 27 | // CHECK-NEXT: 0x202000 R_X86_64_IRELATIVE |
deps/lld/test/ELF/gnu-unique.s+2-2| ... | ... | @@ -20,7 +20,7 @@ _start: |
| 20 | 20 | .type symb, @gnu_unique_object |
| 21 | 21 | symb: |
| 22 | 22 | |
| 23 | # GNU: Name: symb@ | |
| 23 | # GNU: Name: symb | |
| 24 | 24 | # GNU-NEXT: Value: |
| 25 | 25 | # GNU-NEXT: Size: 0 |
| 26 | 26 | # GNU-NEXT: Binding: Unique |
| ... | ... | @@ -29,7 +29,7 @@ symb: |
| 29 | 29 | # GNU-NEXT: Section: .data |
| 30 | 30 | # GNU-NEXT: } |
| 31 | 31 | |
| 32 | # NO: Name: symb@ | |
| 32 | # NO: Name: symb | |
| 33 | 33 | # NO-NEXT: Value: |
| 34 | 34 | # NO-NEXT: Size: 0 |
| 35 | 35 | # NO-NEXT: Binding: Global |
deps/lld/test/ELF/got-i386.s+9-9| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | // CHECK-NEXT: SHF_ALLOC |
| 11 | 11 | // CHECK-NEXT: SHF_WRITE |
| 12 | 12 | // CHECK-NEXT: ] |
| 13 | // CHECK-NEXT: Address: 0x12000 | |
| 13 | // CHECK-NEXT: Address: 0x402000 | |
| 14 | 14 | // CHECK-NEXT: Offset: |
| 15 | 15 | // CHECK-NEXT: Size: 0 |
| 16 | 16 | // CHECK-NEXT: Link: |
| ... | ... | @@ -19,7 +19,7 @@ |
| 19 | 19 | |
| 20 | 20 | // CHECK: Symbol { |
| 21 | 21 | // CHECK: Name: bar |
| 22 | // CHECK-NEXT: Value: 0x12000 | |
| 22 | // CHECK-NEXT: Value: 0x402000 | |
| 23 | 23 | // CHECK-NEXT: Size: 10 |
| 24 | 24 | // CHECK-NEXT: Binding: Global |
| 25 | 25 | // CHECK-NEXT: Type: Object |
| ... | ... | @@ -28,7 +28,7 @@ |
| 28 | 28 | // CHECK-NEXT: } |
| 29 | 29 | // CHECK-NEXT: Symbol { |
| 30 | 30 | // CHECK-NEXT: Name: obj |
| 31 | // CHECK-NEXT: Value: 0x1200A | |
| 31 | // CHECK-NEXT: Value: 0x40200A | |
| 32 | 32 | // CHECK-NEXT: Size: 10 |
| 33 | 33 | // CHECK-NEXT: Binding: Global |
| 34 | 34 | // CHECK-NEXT: Type: Object |
| ... | ... | @@ -36,14 +36,14 @@ |
| 36 | 36 | // CHECK-NEXT: Section: .bss |
| 37 | 37 | // CHECK-NEXT: } |
| 38 | 38 | |
| 39 | // 0x12000 - 0 = addr(.got) = 0x12000 | |
| 40 | // 0x1200A - 10 = addr(.got) = 0x12000 | |
| 41 | // 0x1200A + 5 - 15 = addr(.got) = 0x12000 | |
| 39 | // 0x402000 - 0 = addr(.got) = 0x402000 | |
| 40 | // 0x40200A - 10 = addr(.got) = 0x402000 | |
| 41 | // 0x40200A + 5 - 15 = addr(.got) = 0x402000 | |
| 42 | 42 | // DISASM: Disassembly of section .text: |
| 43 | 43 | // DISASM-NEXT: _start: |
| 44 | // DISASM-NEXT: 11000: c7 81 00 00 00 00 01 00 00 00 movl $1, (%ecx) | |
| 45 | // DISASM-NEXT: 1100a: c7 81 0a 00 00 00 02 00 00 00 movl $2, 10(%ecx) | |
| 46 | // DISASM-NEXT: 11014: c7 81 0f 00 00 00 03 00 00 00 movl $3, 15(%ecx) | |
| 44 | // DISASM-NEXT: 401000: c7 81 00 00 00 00 01 00 00 00 movl $1, (%ecx) | |
| 45 | // DISASM-NEXT: 40100a: c7 81 0a 00 00 00 02 00 00 00 movl $2, 10(%ecx) | |
| 46 | // DISASM-NEXT: 401014: c7 81 0f 00 00 00 03 00 00 00 movl $3, 15(%ecx) | |
| 47 | 47 | |
| 48 | 48 | .global _start |
| 49 | 49 | _start: |
deps/lld/test/ELF/got32-i386-pie-rw.s+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | # REQUIRES: x86 |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o |
| 3 | 3 | # RUN: ld.lld %t.o -o %t -pie |
| 4 | # RUN: llvm-readelf -r -s %t | FileCheck %s | |
| 4 | # RUN: llvm-readelf -r -S %t | FileCheck %s | |
| 5 | 5 | |
| 6 | 6 | # Unlike bfd and gold we accept this. |
| 7 | 7 |
deps/lld/test/ELF/got32-i386.s+2-2| ... | ... | @@ -14,10 +14,10 @@ _start: |
| 14 | 14 | |
| 15 | 15 | ## 73728 == 0x12000 == ADDR(.got) |
| 16 | 16 | # CHECK: _start: |
| 17 | # CHECK-NEXT: 11001: 8b 1d {{.*}} movl 73728, %ebx | |
| 17 | # CHECK-NEXT: 401001: 8b 1d {{.*}} movl 4202496, %ebx | |
| 18 | 18 | # CHECK: Sections: |
| 19 | 19 | # CHECK: Name Size Address |
| 20 | # CHECK: .got 00000004 0000000000012000 | |
| 20 | # CHECK: .got 00000004 0000000000402000 | |
| 21 | 21 | |
| 22 | 22 | # RUN: not ld.lld %t.o -o %t -pie 2>&1 | FileCheck %s --check-prefix=ERR |
| 23 | 23 | # ERR: error: can't create dynamic relocation R_386_GOT32 against symbol: foo in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output |
deps/lld/test/ELF/got32x-i386.s+5-5| ... | ... | @@ -33,13 +33,13 @@ |
| 33 | 33 | |
| 34 | 34 | ## 73728 == 0x12000 == ADDR(.got) |
| 35 | 35 | # CHECK: _start: |
| 36 | # CHECK-NEXT: 11001: 8b 05 {{.*}} movl 77824, %eax | |
| 37 | # CHECK-NEXT: 11007: 8b 1d {{.*}} movl 77824, %ebx | |
| 38 | # CHECK-NEXT: 1100d: 8b 80 {{.*}} movl -4(%eax), %eax | |
| 39 | # CHECK-NEXT: 11013: 8b 83 {{.*}} movl -4(%ebx), %eax | |
| 36 | # CHECK-NEXT: 401001: 8b 05 {{.*}} movl 4206592, %eax | |
| 37 | # CHECK-NEXT: 401007: 8b 1d {{.*}} movl 4206592, %ebx | |
| 38 | # CHECK-NEXT: 40100d: 8b 80 {{.*}} movl -4(%eax), %eax | |
| 39 | # CHECK-NEXT: 401013: 8b 83 {{.*}} movl -4(%ebx), %eax | |
| 40 | 40 | # CHECK: Sections: |
| 41 | 41 | # CHECK: Name Size Address |
| 42 | # CHECK: .got 00000004 0000000000013000 | |
| 42 | # CHECK: .got 00000004 0000000000403000 | |
| 43 | 43 | |
| 44 | 44 | # RUN: not ld.lld %S/Inputs/i386-got32x-baseless.elf -o %t1 -pie 2>&1 | \ |
| 45 | 45 | # RUN: FileCheck %s --check-prefix=ERR |
deps/lld/test/ELF/hexagon-eflag.s created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | # REQUIRES: hexagon | |
| 2 | # RUN: llvm-mc -filetype=obj -mv62 -triple=hexagon-unknown-elf %s -o %t | |
| 3 | # RUN: llvm-mc -filetype=obj -mv60 -triple=hexagon-unknown-elf %S/Inputs/hexagon.s -o %t2 | |
| 4 | # RUN: ld.lld %t2 %t -o %t3 | |
| 5 | # RUN: llvm-readelf -h %t3 | FileCheck %s | |
| 6 | # Verify that the largest arch in the input list is selected. | |
| 7 | # CHECK: Flags: 0x62 |
deps/lld/test/ELF/hexagon-shared.s created+46| ... | ... | @@ -0,0 +1,46 @@ |
| 1 | # REQUIRES: hexagon | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %s -o %t | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=hexagon-unknown-elf %S/Inputs/hexagon-shared.s -o %t2.o | |
| 4 | # RUN: ld.lld -shared %t2.o -soname %t3.so -o %t3.so | |
| 5 | # RUN: ld.lld -shared %t %t3.so -soname %t4.so -o %t4.so | |
| 6 | # RUN: llvm-objdump -d -j .plt %t4.so | FileCheck --check-prefix=PLT %s | |
| 7 | # RUN: llvm-objdump -d -j .text %t4.so | FileCheck --check-prefix=TEXT %s | |
| 8 | # RUN: llvm-objdump -D -j .got %t4.so | FileCheck --check-prefix=GOT %s | |
| 9 | ||
| 10 | .global foo | |
| 11 | foo: | |
| 12 | ||
| 13 | # _HEX_32_PCREL | |
| 14 | .word _DYNAMIC - . | |
| 15 | call ##bar | |
| 16 | ||
| 17 | # R_HEX_PLT_B22_PCREL | |
| 18 | call bar@PLT | |
| 19 | ||
| 20 | # R_HEX_GOT_11_X and R_HEX_GOT_32_6_X | |
| 21 | r2=add(pc,##_GLOBAL_OFFSET_TABLE_@PCREL) | |
| 22 | r0 = memw (r2+##bar@GOT) | |
| 23 | jumpr r0 | |
| 24 | ||
| 25 | # R_HEX_GOT_16_X | |
| 26 | r0 = add(r1,##bar@GOT) | |
| 27 | ||
| 28 | # PLT: { immext(#65472 | |
| 29 | # PLT: r28 = add(pc,##65488) } | |
| 30 | # PLT: { r14 -= add(r28,#16) | |
| 31 | # PLT: r15 = memw(r28+#8) | |
| 32 | # PLT: r28 = memw(r28+#4) } | |
| 33 | # PLT: { r14 = asr(r14,#2) | |
| 34 | # PLT: jumpr r28 } | |
| 35 | # PLT: { trap0(#219) } | |
| 36 | # PLT: immext(#65472) | |
| 37 | # PLT: r14 = add(pc,##65472) } | |
| 38 | # PLT: r28 = memw(r14+#0) } | |
| 39 | # PLT: jumpr r28 } | |
| 40 | ||
| 41 | # TEXT: 10000: 00 00 02 00 00020000 | |
| 42 | # TEXT: { 	call 0x10050 } | |
| 43 | # TEXT: r0 = add(r1,##65664) } | |
| 44 | ||
| 45 | # GOT: .got: | |
| 46 | # GOT: 30080:	00 00 00 00 00000000 <unknown> |
deps/lld/test/ELF/hexagon.s+199-7| ... | ... | @@ -4,28 +4,220 @@ |
| 4 | 4 | # RUN: ld.lld %t2 %t -o %t3 |
| 5 | 5 | # RUN: llvm-objdump -d %t3 | FileCheck %s |
| 6 | 6 | |
| 7 | # Note: 69632 == 0x11000 | |
| 7 | # Note: 131072 == 0x20000 | |
| 8 | 8 | # R_HEX_32_6_X |
| 9 | 9 | # R_HEX_12_X |
| 10 | 10 | if (p0) r0 = ##_start |
| 11 | # CHECK: immext(#69632) | |
| 12 | # CHECK: if (p0) r0 = ##69632 | |
| 11 | # CHECK: immext(#131072) | |
| 12 | # CHECK: if (p0) r0 = ##131072 | |
| 13 | 13 | |
| 14 | 14 | # R_HEX_B15_PCREL |
| 15 | 15 | if (p0) jump:nt #_start |
| 16 | # CHECK: if (p0) jump:nt 0x11000 | |
| 16 | # CHECK: if (p0) jump:nt 0x20000 | |
| 17 | 17 | |
| 18 | 18 | # R_HEX_B32_PCREL_X |
| 19 | 19 | # R_HEX_B15_PCREL_X |
| 20 | 20 | if (p0) jump:nt ##_start |
| 21 | # CHECK: if (p0) jump:nt 0x11000 | |
| 21 | # CHECK: if (p0) jump:nt 0x20000 | |
| 22 | 22 | |
| 23 | 23 | # R_HEX_B22_PCREL |
| 24 | 24 | call #_start |
| 25 | # CHECK: call 0x11000 | |
| 25 | # CHECK: call 0x20000 | |
| 26 | 26 | |
| 27 | 27 | # R_HEX_B32_PCREL_X |
| 28 | 28 | # R_HEX_B22_PCREL_X |
| 29 | 29 | call ##_start |
| 30 | 30 | # CHECK: immext(#4294967232) |
| 31 | # CHECK: call 0x11000 | |
| 31 | # CHECK: call 0x20000 | |
| 32 | ||
| 33 | # R_HEX_6_X tests: | |
| 34 | # One test for each mask in the lookup table. | |
| 35 | ||
| 36 | #0x38000000 | |
| 37 | if (!P0) memw(r0+#8)=##_start | |
| 38 | # CHECK: 38c0c100 	if (!p0) memw(r0+#8) = ##131072 } | |
| 39 | ||
| 40 | #0x39000000 | |
| 41 | { p0 = p1 | |
| 42 | if (!P0.new) memw(r0+#0)=##_start } | |
| 43 | # CHECK: 39c0c000 	if (!p0.new) memw(r0+#0) = ##131072 } | |
| 44 | ||
| 45 | #0x3e000000 | |
| 46 | memw(r0+##_start)+=r1 | |
| 47 | # CHECK: 3e40c001 	memw(r0+##131072) += r1 } | |
| 48 | ||
| 49 | #0x3f000000 | |
| 50 | memw(r0+##_start)+=#4 | |
| 51 | # CHECK: 3f40c004 	memw(r0+##131072) += #4 } | |
| 52 | ||
| 53 | #0x40000000 | |
| 54 | { r0 = r1 | |
| 55 | if (p0) memb(r0+##_start)=r0.new } | |
| 56 | # CHECK: 40a0c200 	if (p0) memb(r0+##131072) = r0.new } | |
| 57 | ||
| 58 | #0x41000000 | |
| 59 | if (p0) r0=memb(r1+##_start) | |
| 60 | # CHECK: 4101c000 	if (p0) r0 = memb(r1+##131072) } | |
| 61 | ||
| 62 | #0x42000000 | |
| 63 | { r0 = r1 | |
| 64 | p0 = p1 | |
| 65 | if (p0.new) memb(r0+##_start)=r0.new } | |
| 66 | # CHECK: 42a0c200 	if (p0.new) memb(r0+##131072) = r0.new } | |
| 67 | ||
| 68 | #0x43000000 | |
| 69 | { p0 = p1 | |
| 70 | if (P0.new) r0=memb(r0+##_start) } | |
| 71 | # CHECK: 4300c000 	if (p0.new) r0 = memb(r0+##131072) } | |
| 72 | ||
| 73 | #0x44000000 | |
| 74 | if (!p0) memb(r0+##_start)=r1 | |
| 75 | # CHECK: 4400c100 	if (!p0) memb(r0+##131072) = r1 } | |
| 76 | ||
| 77 | #0x45000000 | |
| 78 | if (!p0) r0=memb(r1+##_start) | |
| 79 | # CHECK: 4501c000 	if (!p0) r0 = memb(r1+##131072) } | |
| 80 | ||
| 81 | #0x46000000 | |
| 82 | { p0 = p1 | |
| 83 | if (!p0.new) memb(r0+##_start)=r1 } | |
| 84 | # CHECK: 4600c100 	if (!p0.new) memb(r0+##131072) = r1 } | |
| 85 | ||
| 86 | #0x47000000 | |
| 87 | { p0 = p1 | |
| 88 | if (!p0.new) r0=memb(r1+##_start) } | |
| 89 | # CHECK: 4701c000 	if (!p0.new) r0 = memb(r1+##131072) } | |
| 90 | ||
| 91 | #0x6a000000 -- Note 4294967132 == -0xa4 the distance between | |
| 92 | # here and _start, so this will change if | |
| 93 | # tests are added between here and _start | |
| 94 | r0=add(pc,##_start@pcrel) | |
| 95 | # CHECK: 6a49ce00 	r0 = add(pc,##4294967132) } | |
| 96 | ||
| 97 | #0x7c000000 | |
| 98 | r1:0=combine(#8,##_start) | |
| 99 | # CHECK: 7c80c100 	r1:0 = combine(#8,##131072) } | |
| 100 | ||
| 101 | #0x9a000000 | |
| 102 | r1:0=memb_fifo(r2=##_start) | |
| 103 | # CHECK: 9a82d000 	r1:0 = memb_fifo(r2=##131072) } | |
| 104 | ||
| 105 | #0x9b000000 | |
| 106 | r0=memb(r1=##_start) | |
| 107 | # CHECK: 9b01d000 	r0 = memb(r1=##131072) } | |
| 108 | ||
| 109 | #0x9c000000 | |
| 110 | r1:0=memb_fifo(r2<<#2+##_start) | |
| 111 | # CHECK: 9c82f000 	r1:0 = memb_fifo(r2<<#2+##131072) } | |
| 112 | ||
| 113 | #0x9d000000 | |
| 114 | r0=memb(r1<<#2+##_start) | |
| 115 | # CHECK: 9d01f000 	r0 = memb(r1<<#2+##131072) } | |
| 116 | ||
| 117 | #0x9f000000 | |
| 118 | if (!p0) r0=memb(##_start) | |
| 119 | # CHECK: 9f00e880 	if (!p0) r0 = memb(##131072) } | |
| 120 | ||
| 121 | #0xab000000 | |
| 122 | memb(r0=##_start)=r1 | |
| 123 | # CHECK: ab00c180 	memb(r0=##131072) = r1 } | |
| 124 | ||
| 125 | #0xad000000 | |
| 126 | memb(r0<<#2+##_start)=r1 | |
| 127 | # CHECK: ad00e180 	memb(r0<<#2+##131072) = r1 } | |
| 128 | ||
| 129 | #0xaf000000 | |
| 130 | if (!p0) memb(##_start)=r1 | |
| 131 | # CHECK: af00c184 	if (!p0) memb(##131072) = r1 } | |
| 132 | ||
| 133 | #0xd7000000 | |
| 134 | r0=add(##_start,mpyi(r1,r2)) | |
| 135 | # CHECK: d701c200 	r0 = add(##131072,mpyi(r1,r2)) } | |
| 136 | ||
| 137 | #0xd8000000 | |
| 138 | R0=add(##_start,mpyi(r0,#2)) | |
| 139 | # CHECK: d800c002 	r0 = add(##131072,mpyi(r0,#2)) } | |
| 140 | ||
| 141 | #0xdb000000 | |
| 142 | r0=add(r1,add(r2,##_start)) | |
| 143 | # CHECK: db01c002 	r0 = add(r1,add(r2,##131072)) } | |
| 144 | ||
| 145 | #0xdf000000 | |
| 146 | r0=add(r1,mpyi(r2,##_start)) | |
| 147 | # CHECK: df82c001 	r0 = add(r1,mpyi(r2,##131072)) } | |
| 148 | ||
| 149 | # Duplex form of R_HEX_6_X | |
| 150 | # R_HEX_32_6_X | |
| 151 | # R_HEX_6_X | |
| 152 | { r0 = ##_start; r2 = r16 } | |
| 153 | # CHECK: 28003082 	r0 = ##131072; 	r2 = r16 } | |
| 154 | ||
| 155 | # R_HEX_HI16 | |
| 156 | r0.h = #HI(_start) | |
| 157 | # CHECK: r0.h = #2 | |
| 158 | ||
| 159 | # R_HEX_LO16 | |
| 160 | r0.l = #LO(_start) | |
| 161 | # CHECK: r0.l = #0 | |
| 162 | ||
| 163 | # R_HEX_8_X has 3 relocation mask variations | |
| 164 | #0xde000000 | |
| 165 | r0=sub(##_start, asl(r0, #1)) | |
| 166 | # CHECK: de00c106 r0 = sub(##131072,asl(r0,#1)) } | |
| 167 | ||
| 168 | #0x3c000000 | |
| 169 | memw(r0+#0) = ##_start | |
| 170 | # CHECK: 3c40c000 	memw(r0+#0) = ##131072 } | |
| 171 | ||
| 172 | # The rest: | |
| 173 | r1:0=combine(r2,##_start); | |
| 174 | # CHECK: 7302e000 	r1:0 = combine(r2,##131072) } | |
| 175 | ||
| 176 | # R_HEX_32: | |
| 177 | r_hex_32: | |
| 178 | .word _start | |
| 179 | # CHECK: 00020000 | |
| 180 | ||
| 181 | # R_HEX_16_X has 4 relocation mask variations | |
| 182 | # 0x48000000 | |
| 183 | memw(##_start) = r0 | |
| 184 | # CHECK: 4880c000 memw(##131072) = r0 } | |
| 185 | ||
| 186 | # 0x49000000 | |
| 187 | r0 = memw(##_start) | |
| 188 | # CHECK: 4980c000 r0 = memw(##131072) | |
| 189 | ||
| 190 | # 0x78000000 | |
| 191 | r0 = ##_start | |
| 192 | # CHECK: 7800c000 r0 = ##131072 } | |
| 193 | ||
| 194 | # 0xb0000000 | |
| 195 | r0 = add(r1, ##_start) | |
| 196 | # CHECK: b001c000 r0 = add(r1,##131072) } | |
| 197 | ||
| 198 | # R_HEX_B9_PCREL: | |
| 199 | {r0=#1 ; jump #_start} | |
| 200 | # CHECK: jump 0x20000 | |
| 201 | ||
| 202 | # R_HEX_B9_PCREL_X: | |
| 203 | {r0=#1 ; jump ##_start} | |
| 204 | # CHECK: jump 0x20000 | |
| 205 | ||
| 206 | # R_HEX_B13_PCREL | |
| 207 | if (r0 == #0) jump:t #_start | |
| 208 | # CHECK: if (r0==#0) jump:t 0x20000 | |
| 209 | ||
| 210 | # R_HEX_9_X | |
| 211 | p0 = !cmp.gtu(r0, ##_start) | |
| 212 | # CHECK: p0 = !cmp.gtu(r0,##131072) | |
| 213 | ||
| 214 | # R_HEX_10_X | |
| 215 | p0 = !cmp.gt(r0, ##_start) | |
| 216 | # CHECK: p0 = !cmp.gt(r0,##131072) | |
| 217 | ||
| 218 | # R_HEX_11_X | |
| 219 | r0 = memw(r1+##_start) | |
| 220 | # CHECK: r0 = memw(r1+##131072) | |
| 221 | ||
| 222 | memw(r0+##_start) = r1 | |
| 223 | # CHECK: memw(r0+##131072) = r1 |
deps/lld/test/ELF/i386-linkonce.s created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=i386-linux-gnu %s -o %t.o | |
| 3 | // RUN: llvm-mc -filetype=obj -triple=i386-linux-gnu %p/Inputs/i386-linkonce.s -o %t2.o | |
| 4 | // RUN: llvm-ar rcs %t2.a %t2.o | |
| 5 | // RUN: ld.lld %t.o %t2.a -o %t | |
| 6 | ||
| 7 | .globl _start | |
| 8 | _start: | |
| 9 | call _strchr1 |
deps/lld/test/ELF/i386-pc8-pc16-addend.s+4-4| ... | ... | @@ -4,11 +4,11 @@ |
| 4 | 4 | # RUN: ld.lld %t1.o -o %t.out |
| 5 | 5 | # RUN: llvm-objdump -s -t %t.out | FileCheck %s |
| 6 | 6 | # CHECK: Contents of section .text: |
| 7 | # CHECK-NEXT: 11000 020000 | |
| 8 | ## 0x11003 - 0x11000 + addend(-1) = 0x02 | |
| 9 | ## 0x11003 - 0x11001 + addend(-2) = 0x0000 | |
| 7 | # CHECK-NEXT: 401000 020000 | |
| 8 | ## 0x401003 - 0x401000 + addend(-1) = 0x02 | |
| 9 | ## 0x401003 - 0x401001 + addend(-2) = 0x0000 | |
| 10 | 10 | # CHECK: SYMBOL TABLE: |
| 11 | # CHECK: 00011003 .und | |
| 11 | # CHECK: 00401003 .und | |
| 12 | 12 | |
| 13 | 13 | .byte und-.-1 |
| 14 | 14 | .short und-.-2 |
deps/lld/test/ELF/i386-retpoline-nopic.s+48-48| ... | ... | @@ -8,56 +8,56 @@ |
| 8 | 8 | |
| 9 | 9 | // CHECK: Disassembly of section .plt: |
| 10 | 10 | // CHECK-NEXT: .plt: |
| 11 | // CHECK-NEXT: 11010: ff 35 04 20 01 00 pushl 73732 | |
| 12 | // CHECK-NEXT: 11016: 50 pushl %eax | |
| 13 | // CHECK-NEXT: 11017: a1 08 20 01 00 movl 73736, %eax | |
| 14 | // CHECK-NEXT: 1101c: e8 0f 00 00 00 calll 15 <.plt+0x20> | |
| 15 | // CHECK-NEXT: 11021: f3 90 pause | |
| 16 | // CHECK-NEXT: 11023: 0f ae e8 lfence | |
| 17 | // CHECK-NEXT: 11026: eb f9 jmp -7 <.plt+0x11> | |
| 18 | // CHECK-NEXT: 11028: cc int3 | |
| 19 | // CHECK-NEXT: 11029: cc int3 | |
| 20 | // CHECK-NEXT: 1102a: cc int3 | |
| 21 | // CHECK-NEXT: 1102b: cc int3 | |
| 22 | // CHECK-NEXT: 1102c: cc int3 | |
| 23 | // CHECK-NEXT: 1102d: cc int3 | |
| 24 | // CHECK-NEXT: 1102e: cc int3 | |
| 25 | // CHECK-NEXT: 1102f: cc int3 | |
| 26 | // CHECK-NEXT: 11030: 89 0c 24 movl %ecx, (%esp) | |
| 27 | // CHECK-NEXT: 11033: 8b 4c 24 04 movl 4(%esp), %ecx | |
| 28 | // CHECK-NEXT: 11037: 89 44 24 04 movl %eax, 4(%esp) | |
| 29 | // CHECK-NEXT: 1103b: 89 c8 movl %ecx, %eax | |
| 30 | // CHECK-NEXT: 1103d: 59 popl %ecx | |
| 31 | // CHECK-NEXT: 1103e: c3 retl | |
| 32 | // CHECK-NEXT: 1103f: cc int3 | |
| 33 | // CHECK-NEXT: 11040: 50 pushl %eax | |
| 34 | // CHECK-NEXT: 11041: a1 0c 20 01 00 movl 73740, %eax | |
| 35 | // CHECK-NEXT: 11046: e8 e5 ff ff ff calll -27 <.plt+0x20> | |
| 36 | // CHECK-NEXT: 1104b: e9 d1 ff ff ff jmp -47 <.plt+0x11> | |
| 37 | // CHECK-NEXT: 11050: 68 00 00 00 00 pushl $0 | |
| 38 | // CHECK-NEXT: 11055: e9 b6 ff ff ff jmp -74 <.plt> | |
| 39 | // CHECK-NEXT: 1105a: cc int3 | |
| 40 | // CHECK-NEXT: 1105b: cc int3 | |
| 41 | // CHECK-NEXT: 1105c: cc int3 | |
| 42 | // CHECK-NEXT: 1105d: cc int3 | |
| 43 | // CHECK-NEXT: 1105e: cc int3 | |
| 44 | // CHECK-NEXT: 1105f: cc int3 | |
| 45 | // CHECK-NEXT: 11060: 50 pushl %eax | |
| 46 | // CHECK-NEXT: 11061: a1 10 20 01 00 movl 73744, %eax | |
| 47 | // CHECK-NEXT: 11066: e8 c5 ff ff ff calll -59 <.plt+0x20> | |
| 48 | // CHECK-NEXT: 1106b: e9 b1 ff ff ff jmp -79 <.plt+0x11> | |
| 49 | // CHECK-NEXT: 11070: 68 08 00 00 00 pushl $8 | |
| 50 | // CHECK-NEXT: 11075: e9 96 ff ff ff jmp -106 <.plt> | |
| 51 | // CHECK-NEXT: 1107a: cc int3 | |
| 52 | // CHECK-NEXT: 1107b: cc int3 | |
| 53 | // CHECK-NEXT: 1107c: cc int3 | |
| 54 | // CHECK-NEXT: 1107d: cc int3 | |
| 55 | // CHECK-NEXT: 1107e: cc int3 | |
| 56 | // CHECK-NEXT: 1107f: cc int3 | |
| 11 | // CHECK-NEXT: 401010: ff 35 04 20 40 00 pushl 4202500 | |
| 12 | // CHECK-NEXT: 401016: 50 pushl %eax | |
| 13 | // CHECK-NEXT: 401017: a1 08 20 40 00 movl 4202504, %eax | |
| 14 | // CHECK-NEXT: 40101c: e8 0f 00 00 00 calll 15 <.plt+0x20> | |
| 15 | // CHECK-NEXT: 401021: f3 90 pause | |
| 16 | // CHECK-NEXT: 401023: 0f ae e8 lfence | |
| 17 | // CHECK-NEXT: 401026: eb f9 jmp -7 <.plt+0x11> | |
| 18 | // CHECK-NEXT: 401028: cc int3 | |
| 19 | // CHECK-NEXT: 401029: cc int3 | |
| 20 | // CHECK-NEXT: 40102a: cc int3 | |
| 21 | // CHECK-NEXT: 40102b: cc int3 | |
| 22 | // CHECK-NEXT: 40102c: cc int3 | |
| 23 | // CHECK-NEXT: 40102d: cc int3 | |
| 24 | // CHECK-NEXT: 40102e: cc int3 | |
| 25 | // CHECK-NEXT: 40102f: cc int3 | |
| 26 | // CHECK-NEXT: 401030: 89 0c 24 movl %ecx, (%esp) | |
| 27 | // CHECK-NEXT: 401033: 8b 4c 24 04 movl 4(%esp), %ecx | |
| 28 | // CHECK-NEXT: 401037: 89 44 24 04 movl %eax, 4(%esp) | |
| 29 | // CHECK-NEXT: 40103b: 89 c8 movl %ecx, %eax | |
| 30 | // CHECK-NEXT: 40103d: 59 popl %ecx | |
| 31 | // CHECK-NEXT: 40103e: c3 retl | |
| 32 | // CHECK-NEXT: 40103f: cc int3 | |
| 33 | // CHECK-NEXT: 401040: 50 pushl %eax | |
| 34 | // CHECK-NEXT: 401041: a1 0c 20 40 00 movl 4202508, %eax | |
| 35 | // CHECK-NEXT: 401046: e8 e5 ff ff ff calll -27 <.plt+0x20> | |
| 36 | // CHECK-NEXT: 40104b: e9 d1 ff ff ff jmp -47 <.plt+0x11> | |
| 37 | // CHECK-NEXT: 401050: 68 00 00 00 00 pushl $0 | |
| 38 | // CHECK-NEXT: 401055: e9 b6 ff ff ff jmp -74 <.plt> | |
| 39 | // CHECK-NEXT: 40105a: cc int3 | |
| 40 | // CHECK-NEXT: 40105b: cc int3 | |
| 41 | // CHECK-NEXT: 40105c: cc int3 | |
| 42 | // CHECK-NEXT: 40105d: cc int3 | |
| 43 | // CHECK-NEXT: 40105e: cc int3 | |
| 44 | // CHECK-NEXT: 40105f: cc int3 | |
| 45 | // CHECK-NEXT: 401060: 50 pushl %eax | |
| 46 | // CHECK-NEXT: 401061: a1 10 20 40 00 movl 4202512, %eax | |
| 47 | // CHECK-NEXT: 401066: e8 c5 ff ff ff calll -59 <.plt+0x20> | |
| 48 | // CHECK-NEXT: 40106b: e9 b1 ff ff ff jmp -79 <.plt+0x11> | |
| 49 | // CHECK-NEXT: 401070: 68 08 00 00 00 pushl $8 | |
| 50 | // CHECK-NEXT: 401075: e9 96 ff ff ff jmp -106 <.plt> | |
| 51 | // CHECK-NEXT: 40107a: cc int3 | |
| 52 | // CHECK-NEXT: 40107b: cc int3 | |
| 53 | // CHECK-NEXT: 40107c: cc int3 | |
| 54 | // CHECK-NEXT: 40107d: cc int3 | |
| 55 | // CHECK-NEXT: 40107e: cc int3 | |
| 56 | // CHECK-NEXT: 40107f: cc int3 | |
| 57 | 57 | |
| 58 | 58 | // CHECK: Contents of section .got.plt: |
| 59 | // CHECK-NEXT: 00300100 00000000 00000000 50100100 | |
| 60 | // CHECK-NEXT: 70100100 | |
| 59 | // CHECK-NEXT: 00304000 00000000 00000000 50104000 | |
| 60 | // CHECK-NEXT: 70104000 | |
| 61 | 61 | |
| 62 | 62 | .global _start |
| 63 | 63 | _start: |
deps/lld/test/ELF/image-base.s+3| ... | ... | @@ -3,6 +3,9 @@ |
| 3 | 3 | # RUN: ld.lld -image-base=0x1000000 %t -o %t1 |
| 4 | 4 | # RUN: llvm-readobj -program-headers %t1 | FileCheck %s |
| 5 | 5 | |
| 6 | # RUN: not ld.lld -image-base=ABC %t -o %t1 2>&1 | FileCheck --check-prefix=ERR %s | |
| 7 | # ERR: error: -image-base: number expected, but got ABC | |
| 8 | ||
| 6 | 9 | # RUN: ld.lld -image-base=0x1000 -z max-page-size=0x2000 %t -o %t1 2>&1 | FileCheck --check-prefix=WARN %s |
| 7 | 10 | # WARN: warning: -image-base: address isn't multiple of page size: 0x1000 |
| 8 | 11 |
deps/lld/test/ELF/incompatible-ar-first.s+1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | // REQUIRES: x86 |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/archive.s -o %ta.o |
| 3 | // RUN: rm -f %t.a | |
| 3 | 4 | // RUN: llvm-ar rc %t.a %ta.o |
| 4 | 5 | // RUN: llvm-mc -filetype=obj -triple=i686-linux %s -o %tb.o |
| 5 | 6 | // RUN: not ld.lld %t.a %tb.o -o /dev/null 2>&1 | FileCheck %s |
deps/lld/test/ELF/incompatible.s+1| ... | ... | @@ -48,6 +48,7 @@ |
| 48 | 48 | // We used to fail to identify this incompatibility and crash trying to |
| 49 | 49 | // read a 64 bit file as a 32 bit one. |
| 50 | 50 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/archive2.s -o %ta.o |
| 51 | // RUN: rm -f %t.a | |
| 51 | 52 | // RUN: llvm-ar rc %t.a %ta.o |
| 52 | 53 | // RUN: llvm-mc -filetype=obj -triple=i686-linux %s -o %tb.o |
| 53 | 54 | // RUN: not ld.lld %t.a %tb.o 2>&1 -o %t | FileCheck --check-prefix=ARCHIVE %s |
deps/lld/test/ELF/invalid-linkerscript.test+7-1| ... | ... | @@ -50,5 +50,11 @@ |
| 50 | 50 | |
| 51 | 51 | # RUN: echo "OUTPUT_FORMAT(x y z)" > %t8 |
| 52 | 52 | # RUN: not ld.lld %t8 no-such-file 2>&1 | FileCheck -check-prefix=ERR8 %s |
| 53 | # ERR8: , expected, but got y | |
| 53 | # RUN: not ld.lld -m elf_amd64 %t8 no-such-file 2>&1 | FileCheck -check-prefix=ERR8 %s | |
| 54 | # ERR8: unknown output format name: x | |
| 54 | 55 | # ERR8: cannot open no-such-file: |
| 56 | ||
| 57 | # RUN: echo "OUTPUT_FORMAT(elf64-x86-64 y z)" > %t9 | |
| 58 | # RUN: not ld.lld %t9 no-such-file 2>&1 | FileCheck -check-prefix=ERR9 %s | |
| 59 | # ERR9: , expected, but got y | |
| 60 | # ERR9: cannot open no-such-file: |
deps/lld/test/ELF/invalid/Inputs/shentsize-zero.elf deleted| Binary files a/deps/lld/test/ELF/invalid/Inputs/shentsize-zero.elf and /dev/null differ |
deps/lld/test/ELF/invalid/Inputs/sht-group.elf deleted| Binary files a/deps/lld/test/ELF/invalid/Inputs/sht-group.elf and /dev/null differ |
deps/lld/test/ELF/invalid/Inputs/undefined-local-symbol-in-dso.so created| Binary files /dev/null and b/deps/lld/test/ELF/invalid/Inputs/undefined-local-symbol-in-dso.so differ |
deps/lld/test/ELF/invalid/comdat-broken.test created+25| ... | ... | @@ -0,0 +1,25 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: yaml2obj %s -o %t.o | |
| 4 | # RUN: not ld.lld %t.o -o %t.exe 2>&1 | FileCheck %s | |
| 5 | # RUN: not ld.lld %t.o %t.o -o %t.exe 2>&1 | FileCheck %s | |
| 6 | ||
| 7 | # CHECK: error: {{.*}}.o: unsupported SHT_GROUP format | |
| 8 | ||
| 9 | --- !ELF | |
| 10 | FileHeader: | |
| 11 | Class: ELFCLASS64 | |
| 12 | Data: ELFDATA2LSB | |
| 13 | Type: ET_REL | |
| 14 | Machine: EM_X86_64 | |
| 15 | Sections: | |
| 16 | - Name: .group | |
| 17 | Type: SHT_GROUP | |
| 18 | Link: .symtab | |
| 19 | Info: foo | |
| 20 | Members: | |
| 21 | - SectionOrType: 0xFF | |
| 22 | - SectionOrType: 3 | |
| 23 | Symbols: | |
| 24 | Global: | |
| 25 | - Name: foo |
deps/lld/test/ELF/invalid/ehframe-broken-relocation.test created+31| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | # RUN: yaml2obj %s -o %t.o | |
| 2 | # RUN: not ld.lld --icf=all %t.o -o /dev/null 2>&1 | FileCheck %s | |
| 3 | # CHECK: .eh_frame: relocation is not in any piece | |
| 4 | ||
| 5 | !ELF | |
| 6 | FileHeader: | |
| 7 | Class: ELFCLASS64 | |
| 8 | Data: ELFDATA2LSB | |
| 9 | OSABI: ELFOSABI_FREEBSD | |
| 10 | Type: ET_REL | |
| 11 | Machine: EM_X86_64 | |
| 12 | Sections: | |
| 13 | - Name: .eh_frame | |
| 14 | Type: SHT_PROGBITS | |
| 15 | Flags: [ SHF_ALLOC] | |
| 16 | Content: "1400000000000000017a5200017810011b0c070890010000140000001c00000000000000000000000000000000000000" | |
| 17 | - Name: .rela.eh_frame | |
| 18 | Type: SHT_RELA | |
| 19 | Link: .symtab | |
| 20 | Info: .eh_frame | |
| 21 | Relocations: | |
| 22 | - Offset: 0x99999999 | |
| 23 | Symbol: zed | |
| 24 | Type: R_X86_64_64 | |
| 25 | Symbols: | |
| 26 | Global: | |
| 27 | - Name: zed | |
| 28 | Type: STT_FUNC | |
| 29 | Section: .eh_frame | |
| 30 | Value: 0x0 | |
| 31 | Size: 8 |
deps/lld/test/ELF/invalid/invalid-soname.test created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: yaml2obj %s -o %t.so | |
| 3 | # RUN: not ld.lld %t.so -o %t.exe 2>&1 | FileCheck %s | |
| 4 | ||
| 5 | # CHECK: error: {{.*}}.so: invalid DT_SONAME entry | |
| 6 | ||
| 7 | --- !ELF | |
| 8 | FileHeader: | |
| 9 | Class: ELFCLASS64 | |
| 10 | Data: ELFDATA2LSB | |
| 11 | Type: ET_DYN | |
| 12 | Machine: EM_X86_64 | |
| 13 | Sections: | |
| 14 | - Name: .test | |
| 15 | Type: SHT_DYNAMIC | |
| 16 | Flags: [ SHF_ALLOC ] | |
| 17 | Content: "0e000000000000000000000000000001" | |
| 18 | Link: .strtab |
deps/lld/test/ELF/invalid/linkorder-invalid-sec.test created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: yaml2obj %s -o %t.o | |
| 3 | # RUN: not ld.lld %t.o -o %t.exe 2>&1 | FileCheck %s | |
| 4 | # CHECK: invalid sh_link index: 12345 | |
| 5 | ||
| 6 | --- !ELF | |
| 7 | FileHeader: | |
| 8 | Class: ELFCLASS64 | |
| 9 | Data: ELFDATA2LSB | |
| 10 | Type: ET_REL | |
| 11 | Machine: EM_X86_64 | |
| 12 | Sections: | |
| 13 | - Name: .linkorder | |
| 14 | Type: SHT_PROGBITS | |
| 15 | Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_LINK_ORDER ] | |
| 16 | Link: 12345 |
deps/lld/test/ELF/invalid/linkorder-invalid-sec2.test created+16| ... | ... | @@ -0,0 +1,16 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: yaml2obj %s -o %t.o | |
| 3 | # RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s | |
| 4 | # CHECK: invalid sh_link index: 0 | |
| 5 | ||
| 6 | --- !ELF | |
| 7 | FileHeader: | |
| 8 | Class: ELFCLASS64 | |
| 9 | Data: ELFDATA2LSB | |
| 10 | Type: ET_REL | |
| 11 | Machine: EM_X86_64 | |
| 12 | Sections: | |
| 13 | - Name: .linkorder | |
| 14 | Type: SHT_PROGBITS | |
| 15 | Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_LINK_ORDER ] | |
| 16 | Link: 0 |
deps/lld/test/ELF/invalid/merge-invalid-size.s-3| ... | ... | @@ -3,8 +3,5 @@ |
| 3 | 3 | // RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s |
| 4 | 4 | // CHECK: SHF_MERGE section size must be a multiple of sh_entsize |
| 5 | 5 | |
| 6 | // Test that we accept a zero sh_entsize. | |
| 7 | // RUN: ld.lld %p/Inputs/shentsize-zero.elf -o /dev/null | |
| 8 | ||
| 9 | 6 | .section .foo,"aM",@progbits,4 |
| 10 | 7 | .short 42 |
deps/lld/test/ELF/invalid/merge-zero-size.test created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: yaml2obj %s -o %t.o | |
| 4 | ||
| 5 | # Test that we accept a zero sh_entsize for SHF_MERGE section. | |
| 6 | # RUN: ld.lld %t.o -o %t.exe | |
| 7 | ||
| 8 | !ELF | |
| 9 | FileHeader: | |
| 10 | Class: ELFCLASS64 | |
| 11 | Data: ELFDATA2LSB | |
| 12 | OSABI: ELFOSABI_FREEBSD | |
| 13 | Type: ET_REL | |
| 14 | Machine: EM_X86_64 | |
| 15 | Sections: | |
| 16 | - Type: SHT_PROGBITS | |
| 17 | Name: .strings | |
| 18 | Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ] | |
| 19 | AddressAlign: 0x04 | |
| 20 | Content: "FFFFFFFFFFFFFFFF" | |
| 21 | EntSize: 0x0 |
deps/lld/test/ELF/invalid/non-terminated-string.test created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | # RUN: yaml2obj %s -o %t | |
| 2 | # RUN: not ld.lld %t -o %tout 2>&1 | FileCheck %s | |
| 3 | ||
| 4 | # CHECK: {{.*}}:(.merge): string is not null terminated | |
| 5 | ||
| 6 | !ELF | |
| 7 | FileHeader: | |
| 8 | Class: ELFCLASS64 | |
| 9 | Data: ELFDATA2LSB | |
| 10 | OSABI: ELFOSABI_FREEBSD | |
| 11 | Type: ET_REL | |
| 12 | Machine: EM_X86_64 | |
| 13 | Sections: | |
| 14 | - Type: SHT_PROGBITS | |
| 15 | Name: .merge | |
| 16 | Flags: [ SHF_ALLOC, SHF_MERGE, SHF_STRINGS ] | |
| 17 | AddressAlign: 0x04 | |
| 18 | Content: "AABB" | |
| 19 | EntSize: 0x2 |
deps/lld/test/ELF/invalid/sht-group-wrong-section.test created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: yaml2obj %s -o %t.o | |
| 3 | # RUN: not ld.lld %t.o %t.o -o %t.exe 2>&1 | FileCheck %s | |
| 4 | # CHECK: error: {{.*}}.o: invalid section index in group: 12345 | |
| 5 | ||
| 6 | --- !ELF | |
| 7 | FileHeader: | |
| 8 | Class: ELFCLASS64 | |
| 9 | Data: ELFDATA2LSB | |
| 10 | Type: ET_REL | |
| 11 | Machine: EM_X86_64 | |
| 12 | Sections: | |
| 13 | - Name: .group | |
| 14 | Type: SHT_GROUP | |
| 15 | Link: .symtab | |
| 16 | Info: foo | |
| 17 | Members: | |
| 18 | - SectionOrType: GRP_COMDAT | |
| 19 | - SectionOrType: 12345 | |
| 20 | Symbols: | |
| 21 | Global: | |
| 22 | - Name: foo |
deps/lld/test/ELF/invalid/sht-group.s deleted-3| ... | ... | @@ -1,3 +0,0 @@ |
| 1 | ## sht-group.elf contains SHT_GROUP section with invalid sh_info. | |
| 2 | # RUN: not ld.lld %p/Inputs/sht-group.elf -o /dev/null 2>&1 | FileCheck %s | |
| 3 | # CHECK: invalid symbol index |
deps/lld/test/ELF/invalid/sht-group.test created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: yaml2obj %s -o %t.o | |
| 3 | # RUN: not ld.lld %t.o -o %t.exe 2>&1 | FileCheck %s | |
| 4 | # CHECK: invalid symbol index | |
| 5 | ||
| 6 | --- !ELF | |
| 7 | FileHeader: | |
| 8 | Class: ELFCLASS64 | |
| 9 | Data: ELFDATA2LSB | |
| 10 | Type: ET_REL | |
| 11 | Machine: EM_X86_64 | |
| 12 | Sections: | |
| 13 | - Name: .group | |
| 14 | Type: SHT_GROUP | |
| 15 | Link: .symtab | |
| 16 | Info: 12345 | |
| 17 | Members: | |
| 18 | - SectionOrType: GRP_COMDAT |
deps/lld/test/ELF/invalid/undefined-local-symbol-in-dso.test created+66| ... | ... | @@ -0,0 +1,66 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # LLD used to crash when linking against a DSO with an undefined STB_LOCAL | |
| 4 | # symbol in the global part of the dynamic symbol table (i.e. an STB_LOCAL | |
| 5 | # symbol with an index >= the sh_info of the dynamic symbol table section). Such | |
| 6 | # a DSO is very broken, because local symbols should precede all global symbols | |
| 7 | # in the symbol table, and because having a symbol that's both undefined and | |
| 8 | # STB_LOCAL is a nonsensical combination. Nevertheless, we should warn on such | |
| 9 | # input files instead of crashing. | |
| 10 | ||
| 11 | # We've found actual broken DSOs of this sort in the wild, but for this test, we | |
| 12 | # created a reduced broken input file. There are no tools capable of producing a | |
| 13 | # broken DSO of this nature, so instead we created a valid DSO with an undefined | |
| 14 | # global symbol in the dynamic symbol table and then manually edited the binary | |
| 15 | # to make that symbol local. The valid DSO was created as follows: | |
| 16 | ||
| 17 | ``` | |
| 18 | % cat undef.s | |
| 19 | .hidden bar | |
| 20 | bar: | |
| 21 | 	movq	foo@GOT, %rax | |
| 22 | ||
| 23 | % llvm-mc -triple=x86_64-linux-gnu -filetype=obj -o undef.o undef.s | |
| 24 | % ld.lld --no-rosegment -shared -o undefined-local-symbol-in-dso.so undef.o | |
| 25 | % strip undef.so | |
| 26 | ``` | |
| 27 | ||
| 28 | # (--no-rosegment and stripping are unnecessary; they just produce a smaller | |
| 29 | # binary) | |
| 30 | ||
| 31 | # This DSO should only have a single dynamic symbol table entry for foo, and | |
| 32 | # then we can use a small C program to modify that symbol table entry to be | |
| 33 | # STB_LOCAL instead of STB_GLOBAL. | |
| 34 | ||
| 35 | ``` | |
| 36 | #include <elf.h> | |
| 37 | #include <stdio.h> | |
| 38 | ||
| 39 | int main(int argc, char *argv[]) { | |
| 40 | FILE *F = fopen(argv[1], "rb+"); | |
| 41 | ||
| 42 | Elf64_Ehdr Ehdr; | |
| 43 | fread(&Ehdr, sizeof(Ehdr), 1, F); | |
| 44 | fseek(F, Ehdr.e_shoff, SEEK_SET); | |
| 45 | ||
| 46 | Elf64_Shdr Shdr; | |
| 47 | do { | |
| 48 | fread(&Shdr, sizeof(Shdr), 1, F); | |
| 49 | } while (Shdr.sh_type != SHT_DYNSYM); | |
| 50 | ||
| 51 | Elf64_Sym Sym; | |
| 52 | fseek(F, Shdr.sh_offset + sizeof(Elf64_Sym), SEEK_SET); | |
| 53 | fread(&Sym, sizeof(Sym), 1, F); | |
| 54 | Sym.st_info = STB_LOCAL << 4 | ELF64_ST_TYPE(Sym.st_info); | |
| 55 | fseek(F, Shdr.sh_offset + sizeof(Elf64_Sym), SEEK_SET); | |
| 56 | fwrite(&Sym, sizeof(Sym), 1, F); | |
| 57 | fclose(F); | |
| 58 | } | |
| 59 | ``` | |
| 60 | ||
| 61 | # (the C program just takes its input DSO and modifies the binding of the first | |
| 62 | # dynamic symbol table entry to be STB_LOCAL instead of STB_GLOBAL) | |
| 63 | ||
| 64 | # RUN: ld.lld %p/Inputs/undefined-local-symbol-in-dso.so -o %t 2>&1 | \ | |
| 65 | # RUN: FileCheck -check-prefix=WARN %s | |
| 66 | # WARN: found local symbol 'foo' in global part of symbol table in file {{.*}}undefined-local-symbol-in-dso.so |
deps/lld/test/ELF/lazy-arch-conflict.s created+7| ... | ... | @@ -0,0 +1,7 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo '.globl foo; .weak foo; .quad foo;' | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t64.o | |
| 4 | # RUN: echo '.globl foo; foo:' | llvm-mc -filetype=obj -triple=i686-pc-linux - -o %t32.o | |
| 5 | # RUN: not ld.lld %t64.o --start-lib %t32.o --end-lib -o /dev/null 2>&1 | FileCheck %s | |
| 6 | ||
| 7 | # CHECK: error: incompatible file: {{.*}}32.o |
deps/lld/test/ELF/linkerscript/align-r.test+1-1| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/align.s -o %t1.o |
| 6 | 6 | # RUN: ld.lld -r -o %t2.o --script %s %t1.o |
| 7 | # RUN: llvm-readelf -s %t2.o | FileCheck %s | |
| 7 | # RUN: llvm-readelf -S %t2.o | FileCheck %s | |
| 8 | 8 | |
| 9 | 9 | # CHECK: Section Headers: |
| 10 | 10 | # CHECK-NEXT: Name Type Address Off Size ES Flg Lk Inf Al |
deps/lld/test/ELF/linkerscript/align4.test-1| ... | ... | @@ -4,7 +4,6 @@ |
| 4 | 4 | # RUN: llvm-objdump -t %t | FileCheck %s |
| 5 | 5 | |
| 6 | 6 | # CHECK-LABEL: SYMBOL TABLE: |
| 7 | # CHECK-NEXT: 0000000000000000 *UND* 00000000 | |
| 8 | 7 | # CHECK-NEXT: 0000000000014008 .text 00000000 _start |
| 9 | 8 | # CHECK-NEXT: 0000000000010000 *ABS* 00000000 __code_base__ |
| 10 | 9 | # CHECK-NEXT: 0000000000001000 *ABS* 00000000 VAR |
deps/lld/test/ELF/linkerscript/discard-section-err.s+6-14| ... | ... | @@ -7,25 +7,17 @@ |
| 7 | 7 | # RUN: FileCheck -check-prefix=SHSTRTAB %s |
| 8 | 8 | # SHSTRTAB: discarding .shstrtab section is not allowed |
| 9 | 9 | |
| 10 | ## We allow discarding .dynamic, check we don't crash. | |
| 10 | 11 | # RUN: echo "SECTIONS { /DISCARD/ : { *(.dynamic) } }" > %t.script |
| 11 | # RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ | |
| 12 | # RUN: FileCheck -check-prefix=DYNAMIC %s | |
| 13 | # DYNAMIC: discarding .dynamic section is not allowed | |
| 12 | # RUN: ld.lld -pie -o %t --script %t.script %t.o | |
| 14 | 13 | |
| 14 | ## We allow discarding .dynsym, check we don't crash. | |
| 15 | 15 | # RUN: echo "SECTIONS { /DISCARD/ : { *(.dynsym) } }" > %t.script |
| 16 | # RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ | |
| 17 | # RUN: FileCheck -check-prefix=DYNSYM %s | |
| 18 | # DYNSYM: discarding .dynsym section is not allowed | |
| 16 | # RUN: ld.lld -pie -o %t --script %t.script %t.o | |
| 19 | 17 | |
| 18 | ## We allow discarding .dynstr, check we don't crash. | |
| 20 | 19 | # RUN: echo "SECTIONS { /DISCARD/ : { *(.dynstr) } }" > %t.script |
| 21 | # RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ | |
| 22 | # RUN: FileCheck -check-prefix=DYNSTR %s | |
| 23 | # DYNSTR: discarding .dynstr section is not allowed | |
| 24 | ||
| 25 | # RUN: echo "SECTIONS { /DISCARD/ : { *(.rela.plt) } }" > %t.script | |
| 26 | # RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ | |
| 27 | # RUN: FileCheck -check-prefix=RELAPLT %s | |
| 28 | # RELAPLT: discarding .rela.plt section is not allowed | |
| 20 | # RUN: ld.lld -pie -o %t --script %t.script %t.o | |
| 29 | 21 | |
| 30 | 22 | # RUN: echo "SECTIONS { /DISCARD/ : { *(.rela.dyn) } }" > %t.script |
| 31 | 23 | # RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | \ |
deps/lld/test/ELF/linkerscript/filename-spec.s+1| ... | ... | @@ -43,6 +43,7 @@ |
| 43 | 43 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.testdir1/filename-spec1.o |
| 44 | 44 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \ |
| 45 | 45 | # RUN: %p/Inputs/filename-spec.s -o %t.testdir2/filename-spec2.o |
| 46 | # RUN: rm -f %t.testdir1/lib1.a %t.testdir2/lib2.a | |
| 46 | 47 | # RUN: llvm-ar rsc %t.testdir1/lib1.a %t.testdir1/filename-spec1.o |
| 47 | 48 | # RUN: llvm-ar rsc %t.testdir2/lib2.a %t.testdir2/filename-spec2.o |
| 48 | 49 |
deps/lld/test/ELF/linkerscript/icf.s created+11| ... | ... | @@ -0,0 +1,11 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo "foo = 1; bar = 2;" > %t.script | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 5 | # RUN: ld.lld %t.o %t.script -o %t --icf=all --print-icf-sections | count 0 | |
| 6 | ||
| 7 | .section .text.foo,"ax",@progbits | |
| 8 | jmp foo | |
| 9 | ||
| 10 | .section .text.bar,"ax",@progbits | |
| 11 | jmp bar |
deps/lld/test/ELF/linkerscript/info-section-type.s+9| ... | ... | @@ -29,5 +29,14 @@ |
| 29 | 29 | # RUN: ld.lld -o %t --script %t.script %t.o |
| 30 | 30 | # RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=NONALLOC |
| 31 | 31 | |
| 32 | # RUN: echo "SECTIONS { .bar 0x20000 (INFO) : { *(.foo) } };" > %t.script | |
| 33 | # RUN: ld.lld -o %t --script %t.script %t.o | |
| 34 | # RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=NONALLOC | |
| 35 | ||
| 36 | # RUN: echo "SECTIONS { .bar 0x20000 (BAR) : { *(.foo) } };" > %t.script | |
| 37 | # RUN: not ld.lld -o %t --script %t.script %t.o 2>&1 |\ | |
| 38 | # RUN: FileCheck %s --check-prefix=UNKNOWN | |
| 39 | # UNKNOWN: unknown section directive: BAR | |
| 40 | ||
| 32 | 41 | .section .foo,"a",@progbits |
| 33 | 42 | .zero 1 |
deps/lld/test/ELF/linkerscript/lazy-symbols.test+1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | # REQUIRES: x86 |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/lazy-symbols.s -o %t1 |
| 3 | # RUN: rm -f %tar | |
| 3 | 4 | # RUN: llvm-ar rcs %tar %t1 |
| 4 | 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t2 |
| 5 | 6 | # RUN: ld.lld %t2 %tar --script %s -o %tout |
deps/lld/test/ELF/linkerscript/map-file.test+4-4| ... | ... | @@ -44,10 +44,10 @@ SECTIONS { |
| 44 | 44 | # CHECK-NEXT: 2017 2017 246 1 . += 0x123 * ( 1 + 1 ) |
| 45 | 45 | # CHECK-NEXT: 225d 225d 0 1 foo = . |
| 46 | 46 | # CHECK-NEXT: 225d 225d 0 1 bar = 0x42 - 0x26 |
| 47 | # CHECK-NEXT: 225d 0 0 1 sym1 = . | |
| 48 | # CHECK-NEXT: 225d 0 500 1 . += 0x500 | |
| 49 | # CHECK-NEXT: 275d 0 0 1 sym2 = . | |
| 50 | # CHECK-NEXT: 275d 0 0 1 PROVIDE ( sym3 = 42 ) | |
| 47 | # CHECK-NEXT: 225d 225d 0 1 sym1 = . | |
| 48 | # CHECK-NEXT: 225d 225d 500 1 . += 0x500 | |
| 49 | # CHECK-NEXT: 275d 275d 0 1 sym2 = . | |
| 50 | # CHECK-NEXT: 275d 275d 0 1 PROVIDE ( sym3 = 42 ) | |
| 51 | 51 | # CHECK-NEXT: 2760 2760 10 4 .text |
| 52 | 52 | # CHECK-NEXT: 2760 2760 10 4 {{.*}}{{/|\\}}map-file.test.tmp.o:(.text) |
| 53 | 53 | # CHECK-NEXT: 0 0 8 1 .comment |
deps/lld/test/ELF/linkerscript/map-file2.test+12-10| ... | ... | @@ -8,6 +8,7 @@ SECTIONS { |
| 8 | 8 | .aaa : { *(.aaa.*) } |
| 9 | 9 | .bbb : AT(0x2000) { *(.bbb.*) } |
| 10 | 10 | .ccc : AT(0x3000) { *(.ccc.*) } |
| 11 | . += 0x100; | |
| 11 | 12 | .ddd : { |
| 12 | 13 | BYTE(0x11) |
| 13 | 14 | . += 0x100; |
| ... | ... | @@ -24,16 +25,17 @@ SECTIONS { |
| 24 | 25 | # CHECK-NEXT: 1008 2000 8 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.bbb) |
| 25 | 26 | # CHECK-NEXT: 1010 3000 8 1 .ccc |
| 26 | 27 | # CHECK-NEXT: 1010 3000 8 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.ccc) |
| 27 | # CHECK-NEXT: 1018 3008 109 1 .ddd | |
| 28 | # CHECK-NEXT: 1018 3008 1 1 BYTE ( 0x11 ) | |
| 29 | # CHECK-NEXT: 1019 3009 100 1 . += 0x100 | |
| 30 | # CHECK-NEXT: 1119 3109 8 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.ddd) | |
| 31 | # CHECK-NEXT: 1128 3118 34 8 .eh_frame | |
| 32 | # CHECK-NEXT: 1128 3118 30 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.eh_frame+0x0) | |
| 33 | # CHECK-NEXT: 115c 314c 1 4 .text | |
| 34 | # CHECK-NEXT: 115c 314c 1 4 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.text) | |
| 35 | # CHECK-NEXT: 115c 314c 0 1 f(int) | |
| 36 | # CHECK-NEXT: 115c 314c 0 1 _start | |
| 28 | # CHECK-NEXT: 1018 3008 100 1 . += 0x100 | |
| 29 | # CHECK-NEXT: 1118 3108 109 1 .ddd | |
| 30 | # CHECK-NEXT: 1118 3108 1 1 BYTE ( 0x11 ) | |
| 31 | # CHECK-NEXT: 1119 3109 100 1 . += 0x100 | |
| 32 | # CHECK-NEXT: 1219 3209 8 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.ddd) | |
| 33 | # CHECK-NEXT: 1228 3218 34 8 .eh_frame | |
| 34 | # CHECK-NEXT: 1228 3218 30 1 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.eh_frame+0x0) | |
| 35 | # CHECK-NEXT: 125c 324c 1 4 .text | |
| 36 | # CHECK-NEXT: 125c 324c 1 4 {{.*}}{{/|\\}}map-file2.test.tmp.o:(.text) | |
| 37 | # CHECK-NEXT: 125c 324c 0 1 f(int) | |
| 38 | # CHECK-NEXT: 125c 324c 0 1 _start | |
| 37 | 39 | # CHECK-NEXT: 0 0 8 1 .comment |
| 38 | 40 | # CHECK-NEXT: 0 0 8 1 <internal>:(.comment) |
| 39 | 41 | # CHECK-NEXT: 0 0 48 8 .symtab |
deps/lld/test/ELF/linkerscript/memory-include.test created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo '.section .text,"ax"; .global _start; nop' > %t.s | |
| 4 | # RUN: echo '.section .data,"aw"; .quad 0' >> %t.s | |
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o | |
| 6 | ||
| 7 | # RUN: echo "RAM2 (rwx): ORIGIN = 0x3000, LENGTH = 0x100" > %t.inc | |
| 8 | # RUN: ld.lld -o %t.elf --script %s %t.o -L %T | |
| 9 | # RUN: llvm-objdump -section-headers %t.elf | FileCheck %s | |
| 10 | # CHECK: .data 00000008 0000000000002000 DATA | |
| 11 | # CHECK: .data2 00000008 0000000000003000 DATA | |
| 12 | ||
| 13 | MEMORY { | |
| 14 | ROM (rwx): ORIGIN = 0x1000, LENGTH = 0x100 | |
| 15 | RAM (rwx): ORIGIN = 0x2000, LENGTH = 0x100 | |
| 16 | INCLUDE "memory-include.test.tmp.inc" | |
| 17 | } | |
| 18 | ||
| 19 | SECTIONS { | |
| 20 | .text : { *(.text*) } > ROM | |
| 21 | .data : { *(.data*) } > RAM | |
| 22 | .data2 : { QUAD(0) } > RAM2 | |
| 23 | } |
deps/lld/test/ELF/linkerscript/merge-nonalloc.s created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: echo "SECTIONS { .text : { *(.text) *(.nonalloc) } }" > %t.script | |
| 4 | # RUN: ld.lld -shared -o %t.exe %t.script %t.o | |
| 5 | # RUN: llvm-objdump -syms %t.exe | FileCheck %s | |
| 6 | ||
| 7 | # CHECK: .text 00000000 nonalloc_start | |
| 8 | ||
| 9 | _start: | |
| 10 | nop | |
| 11 | ||
| 12 | .section .nonalloc,"",@progbits | |
| 13 | nonalloc_start: | |
| 14 | .long 0xcafe |
deps/lld/test/ELF/linkerscript/no-filename-spec.s created+17| ... | ... | @@ -0,0 +1,17 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: echo '.section .bar, "a"; .quad 1;' | \ | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %tfile1.o | |
| 4 | # RUN: echo '.section .zed, "a"; .quad 2;' | \ | |
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %tfile2.o | |
| 6 | ||
| 7 | ## We have a file name and no input sections description. In that case, all | |
| 8 | ## sections from the file specified should be included. Check that. | |
| 9 | # RUN: ld.lld -o %t --script %s %tfile1.o %tfile2.o | |
| 10 | # RUN: llvm-objdump -s %t | FileCheck %s | |
| 11 | ||
| 12 | # CHECK: Contents of section .foo: | |
| 13 | # CHECK-NEXT: 01000000 00000000 02000000 00000000 | |
| 14 | ||
| 15 | SECTIONS { | |
| 16 | .foo : { *file1.o *file2.o } | |
| 17 | } |
deps/lld/test/ELF/linkerscript/non-alloc-segment.s+1-1| ... | ... | @@ -16,7 +16,7 @@ |
| 16 | 16 | # RUN: .foo : {*(.foo)} :foo \ |
| 17 | 17 | # RUN: }" > %t.script |
| 18 | 18 | # RUN: ld.lld -o %t --script %t.script %t.o |
| 19 | # RUN: llvm-readelf -s -l %t | FileCheck %s | |
| 19 | # RUN: llvm-readelf -S -l %t | FileCheck %s | |
| 20 | 20 | # RUN: llvm-readobj -l %t | FileCheck --check-prefix=PHDR %s |
| 21 | 21 | |
| 22 | 22 | # CHECK: Program Headers: |
deps/lld/test/ELF/linkerscript/non-alloc.s+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | # RUN: echo "SECTIONS { .foo 0 : {*(foo)} }" > %t.script |
| 5 | 5 | # RUN: ld.lld --hash-style=sysv -o %t --script %t.script %t.o -shared |
| 6 | # RUN: llvm-readelf -s -l %t | FileCheck %s | |
| 6 | # RUN: llvm-readelf -S -l %t | FileCheck %s | |
| 7 | 7 | |
| 8 | 8 | # Test that we create all necessary PT_LOAD. We use to stop at the first |
| 9 | 9 | # non-alloc, causing us to not create PT_LOAD for linker generated sections. |
deps/lld/test/ELF/linkerscript/orphan-discard.s+1-1| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | # RUN: /DISCARD/ : { *(.comment) } \ |
| 11 | 11 | # RUN: }" > %t.script |
| 12 | 12 | # RUN: ld.lld -o %t --script %t.script %t.o |
| 13 | # RUN: llvm-readelf -s -symbols %t | FileCheck %s | |
| 13 | # RUN: llvm-readelf -S -symbols %t | FileCheck %s | |
| 14 | 14 | |
| 15 | 15 | # CHECK: .bss NOBITS ffffffff80002000 002008 000002 00 WA 0 0 4096 |
| 16 | 16 | # CHECK: ffffffff80003000 0 NOTYPE GLOBAL DEFAULT 3 _end |
deps/lld/test/ELF/linkerscript/orphan-phdrs.s+1-1| ... | ... | @@ -10,7 +10,7 @@ |
| 10 | 10 | # RUN: .rw : { *(.rw) } \ |
| 11 | 11 | # RUN: }" > %t.script |
| 12 | 12 | # RUN: ld.lld -o %t --script %t.script %t.o |
| 13 | # RUN: llvm-readelf -s -l %t | FileCheck %s | |
| 13 | # RUN: llvm-readelf -S -l %t | FileCheck %s | |
| 14 | 14 | |
| 15 | 15 | ## Check that the orphan section is placed correctly and belongs to |
| 16 | 16 | ## the correct segment. |
deps/lld/test/ELF/linkerscript/ouputformat.s deleted-9| ... | ... | @@ -1,9 +0,0 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: echo "OUTPUT_FORMAT(x, y, z)" > %t.script | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1 | |
| 4 | # RUN: ld.lld -shared -o %t2 %t1 %t.script | |
| 5 | # RUN: llvm-readobj %t2 > /dev/null | |
| 6 | ||
| 7 | # RUN: echo "OUTPUT_FORMAT(x, y)" > %t.script | |
| 8 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t1 | |
| 9 | # RUN: not ld.lld -shared -o %t2 %t1 %t.script |
deps/lld/test/ELF/linkerscript/output-section-include.test created+30| ... | ... | @@ -0,0 +1,30 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo '.section .text,"ax"; .global _start; nop' > %t.s | |
| 4 | # RUN: echo '.section .data,"aw"; .quad 0' >> %t.s | |
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o | |
| 6 | ||
| 7 | ## Empty include file. | |
| 8 | # RUN: echo "" > %t.inc | |
| 9 | # RUN: ld.lld -o %t.elf --script %s %t.o -L %T | |
| 10 | # RUN: llvm-objdump -section-headers %t.elf | FileCheck %s --check-prefix=CHECK1 | |
| 11 | # CHECK1: .data 00000008 0000000000002000 DATA | |
| 12 | ||
| 13 | ## Non-empty include file. | |
| 14 | # RUN: echo "QUAD(0)" > %t.inc | |
| 15 | # RUN: ld.lld -o %t.elf --script %s %t.o -L %T | |
| 16 | # RUN: llvm-objdump -section-headers %t.elf | FileCheck %s --check-prefix=CHECK2 | |
| 17 | # CHECK2: .data 00000010 0000000000002000 DATA | |
| 18 | ||
| 19 | MEMORY { | |
| 20 | ROM (rwx): ORIGIN = 0x1000, LENGTH = 0x100 | |
| 21 | RAM (rwx): ORIGIN = 0x2000, LENGTH = 0x100 | |
| 22 | } | |
| 23 | ||
| 24 | SECTIONS { | |
| 25 | .text : { *(.text*) } > ROM | |
| 26 | .data : { | |
| 27 | *(.data*) | |
| 28 | INCLUDE "output-section-include.test.tmp.inc" | |
| 29 | } > RAM | |
| 30 | } |
deps/lld/test/ELF/linkerscript/output-too-large.s+6| ... | ... | @@ -1,7 +1,13 @@ |
| 1 | 1 | # REQUIRES: x86 |
| 2 | ||
| 2 | 3 | # RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o |
| 3 | 4 | # RUN: echo "SECTIONS { .text : { . = 0xffffffff; *(.text*); } }" > %t.script |
| 4 | 5 | # RUN: not ld.lld --no-check-sections --script %t.script %t.o -o /dev/null 2>&1 | FileCheck %s |
| 6 | ||
| 7 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 8 | # RUN: echo "SECTIONS { .text : { . = 0x8fffffffffffffff; *(.text*); } }" > %t.script | |
| 9 | # RUN: not ld.lld --no-check-sections --script %t.script %t.o -o /dev/null 2>&1 | FileCheck %s | |
| 10 | ||
| 5 | 11 | # CHECK: error: output file too large |
| 6 | 12 | |
| 7 | 13 | .global _start |
deps/lld/test/ELF/linkerscript/phdrs.s+8| ... | ... | @@ -130,6 +130,14 @@ |
| 130 | 130 | |
| 131 | 131 | # BADHDR: {{.*}}.script:1: section header 'bar' is not listed in PHDRS |
| 132 | 132 | |
| 133 | # RUN: echo "PHDRS { text PT_LOAD FOOHDR; }" > %t1.script | |
| 134 | # RUN: not ld.lld -o /dev/null --script %t1.script %t 2>&1 | FileCheck --check-prefix=FOOHDR %s | |
| 135 | # FOOHDR: error: {{.*}}.script:1: unexpected header attribute: FOOHDR | |
| 136 | ||
| 137 | # RUN: echo "PHDRS { text PT_FOO FOOHDR; }" > %t1.script | |
| 138 | # RUN: not ld.lld -o /dev/null --script %t1.script %t 2>&1 | FileCheck --check-prefix=PTFOO %s | |
| 139 | # PTFOO: invalid program header type: PT_FOO | |
| 140 | ||
| 133 | 141 | .global _start |
| 134 | 142 | _start: |
| 135 | 143 | nop |
deps/lld/test/ELF/linkerscript/provide-shared2.s+1-1| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | # RUN: ld.lld -o %t --script %t.script %t.o %t2.so |
| 7 | 7 | # RUN: llvm-readelf --dyn-symbols %t | FileCheck %s |
| 8 | 8 | |
| 9 | # CHECK: 1 1: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS foo@ | |
| 9 | # CHECK: 1 1: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS foo | |
| 10 | 10 | |
| 11 | 11 | .global _start |
| 12 | 12 | _start: |
deps/lld/test/ELF/linkerscript/relocatable-discard.s created+21| ... | ... | @@ -0,0 +1,21 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: echo "SECTIONS { /DISCARD/ : { *(.discard.*) }}" > %t.script | |
| 4 | # RUN: ld.lld -o %t --script %t.script -r %t.o | |
| 5 | # RUN: llvm-readobj -sections %t | FileCheck %s | |
| 6 | ||
| 7 | ## Test shows that we do not crash after discarding the .discard.foo with -r. | |
| 8 | ## Previously it happened because of 2 reasons: | |
| 9 | ## 1) .rela.discard.foo was not handled properly and was not discarded. | |
| 10 | ## Remaining reference was invalid and caused the crash. | |
| 11 | ## 2) Third-party section .debug_info referencing discarded section | |
| 12 | ## did not handle this case properly and tried to apply the | |
| 13 | ## relocation instead of ignoring it. | |
| 14 | ||
| 15 | # CHECK-NOT: .discard | |
| 16 | ||
| 17 | .section .discard.foo,"ax" | |
| 18 | callq fn@PLT | |
| 19 | ||
| 20 | .section .debug_info,"",@progbits | |
| 21 | .long .discard.foo |
deps/lld/test/ELF/linkerscript/section-include.test created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: echo '.section .text,"ax"; .global _start; nop' > %t.s | |
| 4 | # RUN: echo '.section .data,"aw"; .quad 0' >> %t.s | |
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o | |
| 6 | ||
| 7 | ## Empty include file. | |
| 8 | # RUN: echo "" > %t.inc | |
| 9 | # RUN: ld.lld -o %t.elf --script %s %t.o -L %T | |
| 10 | # RUN: llvm-objdump -section-headers %t.elf | FileCheck %s --check-prefix=CHECK1 | |
| 11 | # CHECK1: .data 00000008 0000000000002000 DATA | |
| 12 | # CHECK1-NEXT: .data3 00000008 0000000000002008 DATA | |
| 13 | ||
| 14 | ## Non-empty include file. | |
| 15 | # RUN: echo ".data2 : { QUAD(0) } > RAM" > %t.inc | |
| 16 | # RUN: ld.lld -o %t.elf --script %s %t.o -L %T | |
| 17 | # RUN: llvm-objdump -section-headers %t.elf | FileCheck %s --check-prefix=CHECK2 | |
| 18 | # CHECK2: .data 00000008 0000000000002000 DATA | |
| 19 | # CHECK2-NEXT: .data2 00000008 0000000000002008 DATA | |
| 20 | # CHECK2-NEXT: .data3 00000008 0000000000002010 DATA | |
| 21 | ||
| 22 | MEMORY { | |
| 23 | ROM (rwx): ORIGIN = 0x1000, LENGTH = 0x100 | |
| 24 | RAM (rwx): ORIGIN = 0x2000, LENGTH = 0x100 | |
| 25 | } | |
| 26 | ||
| 27 | SECTIONS { | |
| 28 | .text : { *(.text*) } > ROM | |
| 29 | .data : { *(.data*) } > RAM | |
| 30 | INCLUDE "section-include.test.tmp.inc" | |
| 31 | .data3 : { QUAD(0) } > RAM | |
| 32 | } |
deps/lld/test/ELF/linkerscript/sections-va-overflow.test+2-2| ... | ... | @@ -7,7 +7,7 @@ PHDRS { |
| 7 | 7 | ph_text PT_LOAD FILEHDR PHDRS FLAGS (0x1 | 0x4); |
| 8 | 8 | } |
| 9 | 9 | |
| 10 | SECTIONS { | |
| 10 | SECTIONS { | |
| 11 | 11 | . = 0xffffffff20000000; |
| 12 | 12 | .text : { *(.text*) } : ph_text |
| 13 | 13 | .test 0x1000 : { BYTE(0) } |
| ... | ... | @@ -18,5 +18,5 @@ SECTIONS { |
| 18 | 18 | ## with VA 0xffffffff20000000. That might be technically correct, but most probably |
| 19 | 19 | ## is a result of a broken script file and causes file offset calculation overflow. |
| 20 | 20 | ## It seems we do not have to support it, so we don't and we report an error in this case. |
| 21 | # ERR: error: unable to place section .text at file offset [0xFFFFFFFF20000000, 0xFFFFFFFE40000000]; check your linker script for overflows | |
| 21 | # ERR: error: unable to place section .text at file offset [0xFFFFFFFF20000000, 0xFFFFFFFF20000000]; check your linker script for overflows | |
| 22 | 22 | # ERR-NOT: unable to place section .bss |
deps/lld/test/ELF/linkerscript/segment-none.s+2-2| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | # RUN: .foo : {*(.foo)} :NONE \ |
| 10 | 10 | # RUN: }" > %t.script |
| 11 | 11 | # RUN: ld.lld -o %t --script %t.script %t.o |
| 12 | # RUN: llvm-readelf -s -l %t | FileCheck %s | |
| 12 | # RUN: llvm-readelf -S -l %t | FileCheck %s | |
| 13 | 13 | |
| 14 | 14 | ## Test that section .foo is placed in segment NONE when assigned to segment |
| 15 | 15 | ## NONE in the linker script and segment NONE is defined. |
| ... | ... | @@ -19,7 +19,7 @@ |
| 19 | 19 | # RUN: .foo : {*(.foo)} :NONE \ |
| 20 | 20 | # RUN: }" > %t.script |
| 21 | 21 | # RUN: ld.lld -o %t --script %t.script %t.o |
| 22 | # RUN: llvm-readelf -s -l %t | FileCheck --check-prefix=DEFINED %s | |
| 22 | # RUN: llvm-readelf -S -l %t | FileCheck --check-prefix=DEFINED %s | |
| 23 | 23 | |
| 24 | 24 | # CHECK: Section to Segment mapping: |
| 25 | 25 | # CHECK-NEXT: Segment Sections... |
deps/lld/test/ELF/linkerscript/sizeof.s-1| ... | ... | @@ -18,7 +18,6 @@ |
| 18 | 18 | # CHECK-NEXT: 2 .bbb 00000010 |
| 19 | 19 | # CHECK-NEXT: 3 .ccc 00000018 |
| 20 | 20 | # CHECK: SYMBOL TABLE: |
| 21 | # CHECK-NEXT: 0000000000000000 *UND* 00000000 | |
| 22 | 21 | # CHECK-NEXT: .text 00000000 _start |
| 23 | 22 | # CHECK-NEXT: 0000000000000008 *ABS* 00000000 _aaa |
| 24 | 23 | # CHECK-NEXT: 0000000000000010 *ABS* 00000000 _bbb |
deps/lld/test/ELF/linkerscript/sizeofheaders.s-1| ... | ... | @@ -9,7 +9,6 @@ |
| 9 | 9 | # RUN: llvm-objdump -t %t1 | FileCheck %s |
| 10 | 10 | |
| 11 | 11 | #CHECK: SYMBOL TABLE: |
| 12 | #CHECK-NEXT: 0000000000000000 *UND* 00000000 | |
| 13 | 12 | #CHECK-NEXT: 00000000000000e8 .text 00000000 _start |
| 14 | 13 | #CHECK-NEXT: 00000000000000e8 *ABS* 00000000 _size |
| 15 | 14 |
deps/lld/test/ELF/linkerscript/sort-init.s+4-2| ... | ... | @@ -1,16 +1,18 @@ |
| 1 | 1 | # REQUIRES: x86 |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o |
| 3 | # RUN: echo "SECTIONS { .init_array : { *(SORT_BY_INIT_PRIORITY(.init_array.*)) } }" > %t1.script | |
| 3 | # RUN: echo "SECTIONS { .init_array : { *(SORT_BY_INIT_PRIORITY(.init_array.* foo*)) } }" > %t1.script | |
| 4 | 4 | # RUN: ld.lld --script %t1.script %t1.o -o %t2 |
| 5 | 5 | # RUN: llvm-objdump -s %t2 | FileCheck %s |
| 6 | 6 | |
| 7 | 7 | # CHECK: Contents of section .init_array: |
| 8 | # CHECK-NEXT: 03020000 00000000 010405 | |
| 8 | # CHECK-NEXT: 03020000 00060000 010405 | |
| 9 | 9 | |
| 10 | 10 | .globl _start |
| 11 | 11 | _start: |
| 12 | 12 | nop |
| 13 | 13 | |
| 14 | .section foo, "aw", @init_array | |
| 15 | .byte 6 | |
| 14 | 16 | .section .init_array, "aw", @init_array |
| 15 | 17 | .align 8 |
| 16 | 18 | .byte 1 |
deps/lld/test/ELF/linkerscript/sort-non-script.s+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | |
| 4 | 4 | # RUN: echo "SECTIONS { foo : {*(foo)} }" > %t.script |
| 5 | 5 | # RUN: ld.lld --hash-style=sysv -o %t --script %t.script %t.o -shared |
| 6 | # RUN: llvm-readelf -s %t | FileCheck %s | |
| 6 | # RUN: llvm-readelf -S %t | FileCheck %s | |
| 7 | 7 | |
| 8 | 8 | # CHECK: .dynsym {{.*}} A |
| 9 | 9 | # CHECK-NEXT: .hash {{.*}} A |
deps/lld/test/ELF/linkerscript/symbol-assignexpr.s-1| ... | ... | @@ -25,7 +25,6 @@ |
| 25 | 25 | # RUN: llvm-objdump -t %t1 | FileCheck %s |
| 26 | 26 | |
| 27 | 27 | # CHECK: SYMBOL TABLE: |
| 28 | # CHECK-NEXT: 0000000000000000 *UND* 00000000 | |
| 29 | 28 | # CHECK-NEXT: 0000000000000000 .text 00000000 _start |
| 30 | 29 | # CHECK-NEXT: 0000000000005678 *ABS* 00000000 bar |
| 31 | 30 | # CHECK-NEXT: 0000000000009abc *ABS* 00000000 baz |
deps/lld/test/ELF/linkerscript/symbol-location.s created+15| ... | ... | @@ -0,0 +1,15 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: echo "foo = 1;" > %t.script | |
| 4 | # RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | FileCheck %s | |
| 5 | ||
| 6 | ## Here we check that symbol 'foo' location is reported properly. | |
| 7 | ||
| 8 | # CHECK: error: relocation R_X86_64_PLT32 cannot refer to absolute symbol: foo | |
| 9 | # CHECK: >>> defined in {{.*}}.script:1 | |
| 10 | # CHECK: >>> referenced by {{.*}}.o:(.text+0x1) | |
| 11 | ||
| 12 | .text | |
| 13 | .globl _start | |
| 14 | _start: | |
| 15 | call foo@PLT |
deps/lld/test/ELF/linkerscript/symbol-memoryexpr.s-1| ... | ... | @@ -13,7 +13,6 @@ |
| 13 | 13 | # RUN: llvm-objdump -t %t1 | FileCheck %s |
| 14 | 14 | |
| 15 | 15 | # CHECK: SYMBOL TABLE: |
| 16 | # CHECK-NEXT: 0000000000000000 *UND* 00000000 | |
| 17 | 16 | # CHECK-NEXT: 0000000000008000 .text 00000000 _start |
| 18 | 17 | # CHECK-NEXT: 0000000000008000 *ABS* 00000000 origin |
| 19 | 18 | # CHECK-NEXT: 0000000000040000 *ABS* 00000000 length |
deps/lld/test/ELF/linkerscript/target.s created+18| ... | ... | @@ -0,0 +1,18 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 4 | # RUN: echo "TARGET(binary) INPUT(\"%t.o\") TARGET(elf64-x86-64) INPUT(\"%t.o\")" > %t.script | |
| 5 | # RUN: ld.lld --script %t.script -o %t.exe | |
| 6 | # RUN: llvm-readelf -symbols %t.exe | FileCheck %s | |
| 7 | ||
| 8 | # CHECK: _binary_ | |
| 9 | # CHECK: foobar | |
| 10 | ||
| 11 | # RUN: echo "TARGET(foo)" > %t2.script | |
| 12 | # RUN: not ld.lld --script %t2.script -o /dev/null 2>&1 | FileCheck -check-prefix=ERR %s | |
| 13 | ||
| 14 | # ERR: unknown target: foo | |
| 15 | ||
| 16 | .global foobar | |
| 17 | foobar: | |
| 18 | nop |
deps/lld/test/ELF/linkerscript/unused-synthetic.s+1-1| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | # RUN: }" > %t.script |
| 8 | 8 | # RUN: ld.lld -shared -o %t.so --script %t.script %t.o |
| 9 | 9 | |
| 10 | # RUN: llvm-readelf -s %t.so | FileCheck %s | |
| 10 | # RUN: llvm-readelf -S %t.so | FileCheck %s | |
| 11 | 11 | # CHECK-NOT: .got |
| 12 | 12 | # CHECK-NOT: .plt |
| 13 | 13 | # CHECK: .dynsym |
deps/lld/test/ELF/linkerscript/version-script.s+3-3| ... | ... | @@ -14,11 +14,11 @@ |
| 14 | 14 | # CHECK: Symbols [ |
| 15 | 15 | # CHECK-NEXT: Symbol { |
| 16 | 16 | # CHECK-NEXT: Version: 0 |
| 17 | # CHECK-NEXT: Name: @ | |
| 17 | # CHECK-NEXT: Name: | |
| 18 | 18 | # CHECK-NEXT: } |
| 19 | 19 | # CHECK-NEXT: Symbol { |
| 20 | 20 | # CHECK-NEXT: Version: 0 |
| 21 | # CHECK-NEXT: Name: und@ | |
| 21 | # CHECK-NEXT: Name: und | |
| 22 | 22 | # CHECK-NEXT: } |
| 23 | 23 | # CHECK-NEXT: Symbol { |
| 24 | 24 | # CHECK-NEXT: Version: 2 |
| ... | ... | @@ -41,7 +41,7 @@ |
| 41 | 41 | # UNDEF: Symbols [ |
| 42 | 42 | # UNDEF-NEXT: Symbol { |
| 43 | 43 | # UNDEF-NEXT: Version: 0 |
| 44 | # UNDEF-NEXT: Name: @ | |
| 44 | # UNDEF-NEXT: Name: | |
| 45 | 45 | # UNDEF-NEXT: } |
| 46 | 46 | # UNDEF-NEXT: Symbol { |
| 47 | 47 | # UNDEF-NEXT: Version: 2 |
deps/lld/test/ELF/local-dynamic.s+2-2| ... | ... | @@ -65,7 +65,7 @@ |
| 65 | 65 | |
| 66 | 66 | // CHECK: DynamicSymbols [ |
| 67 | 67 | // CHECK-NEXT: Symbol { |
| 68 | // CHECK-NEXT: Name: @ | |
| 68 | // CHECK-NEXT: Name: | |
| 69 | 69 | // CHECK-NEXT: Value: 0x0 |
| 70 | 70 | // CHECK-NEXT: Size: 0 |
| 71 | 71 | // CHECK-NEXT: Binding: Local |
| ... | ... | @@ -74,7 +74,7 @@ |
| 74 | 74 | // CHECK-NEXT: Section: Undefined |
| 75 | 75 | // CHECK-NEXT: } |
| 76 | 76 | // CHECK-NEXT: Symbol { |
| 77 | // CHECK-NEXT: Name: _start@ | |
| 77 | // CHECK-NEXT: Name: _start | |
| 78 | 78 | // CHECK-NEXT: Value: |
| 79 | 79 | // CHECK-NEXT: Size: 0 |
| 80 | 80 | // CHECK-NEXT: Binding: Global |
deps/lld/test/ELF/local-ver-preemptible.s created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: echo '.global foo; .type foo, @function; foo:' | \ | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.so.o | |
| 4 | # RUN: ld.lld %t.so.o -o %t.so -shared | |
| 5 | ||
| 6 | # RUN: echo "{ global: main; local: *; };" > %t.script | |
| 7 | ||
| 8 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 9 | # RUN: ld.lld %t.o %t.so -o %t -version-script %t.script | |
| 10 | # RUN: llvm-readelf -r --symbols %t | FileCheck %s | |
| 11 | ||
| 12 | # CHECK: Relocation section '.rela.plt' at offset {{.*}} contains 1 entries: | |
| 13 | # CHECK: R_X86_64_JUMP_SLOT 0000000000201020 foo + 0 | |
| 14 | ||
| 15 | # CHECK: Symbol table '.dynsym' contains 2 entries: | |
| 16 | # CHECK-NEXT: Num: Value Size Type Bind Vis Ndx Name | |
| 17 | # CHECK-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND | |
| 18 | # CHECK-NEXT: 1: 0000000000201020 0 FUNC GLOBAL DEFAULT UND foo | |
| 19 | ||
| 20 | .globl _start | |
| 21 | _start: | |
| 22 | movl $foo - ., %eax |
deps/lld/test/ELF/lto-plugin-ignore.s+2-2| ... | ... | @@ -6,5 +6,5 @@ |
| 6 | 6 | # RUN: -plugin-opt=-data-sections -plugin-opt=thinlto -o /dev/null |
| 7 | 7 | |
| 8 | 8 | # RUN: not ld.lld %t -plugin-opt=-abc -plugin-opt=-xyz 2>&1 | FileCheck %s |
| 9 | # CHECK: error: --plugin-opt: ld.lld{{.*}}: Unknown command line argument '-abc' | |
| 10 | # CHECK: error: --plugin-opt: ld.lld{{.*}}: Unknown command line argument '-xyz' | |
| 9 | # CHECK: ld.lld: error: --plugin-opt: ld.lld{{.*}}: Unknown command line argument '-abc' | |
| 10 | # CHECK: ld.lld: error: --plugin-opt: ld.lld{{.*}}: Unknown command line argument '-xyz' |
deps/lld/test/ELF/lto/Inputs/libcall-archive.s created+2| ... | ... | @@ -0,0 +1,2 @@ |
| 1 | .globl __sync_val_compare_and_swap_8 | |
| 2 | __sync_val_compare_and_swap_8: |
deps/lld/test/ELF/lto/amdgcn.ll created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | ; REQUIRES: amdgpu | |
| 2 | ; RUN: llvm-as %s -o %t.o | |
| 3 | ; RUN: ld.lld %t.o -o %t | |
| 4 | ||
| 5 | ; Make sure the amdgcn triple is handled | |
| 6 | ||
| 7 | target triple = "amdgcn-amd-amdhsa" | |
| 8 | target datalayout = "e-p:64:64-p1:64:64-p2:32:32-p3:32:32-p4:64:64-p5:32:32-p6:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5" | |
| 9 | ||
| 10 | define void @_start() { | |
| 11 | ret void | |
| 12 | } |
deps/lld/test/ELF/lto/cache.ll+20| ... | ... | @@ -1,4 +1,6 @@ |
| 1 | 1 | ; REQUIRES: x86 |
| 2 | ; NetBSD: noatime mounts currently inhibit 'touch' from updating atime | |
| 3 | ; UNSUPPORTED: system-netbsd | |
| 2 | 4 | |
| 3 | 5 | ; RUN: opt -module-hash -module-summary %s -o %t.o |
| 4 | 6 | ; RUN: opt -module-hash -module-summary %p/Inputs/cache.ll -o %t2.o |
| ... | ... | @@ -19,6 +21,10 @@ |
| 19 | 21 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=128k:prune_interval=0s -o %t3 %t2.o %t.o |
| 20 | 22 | ; RUN: ls %t.cache | count 5 |
| 21 | 23 | |
| 24 | ; Increase the age of llvmcache-foo, which will give it the oldest time stamp | |
| 25 | ; so that it is processed and removed first. | |
| 26 | ; RUN: %python -c 'import os,sys,time; t=time.time()-120; os.utime(sys.argv[1],(t,t))' %t.cache/llvmcache-foo | |
| 27 | ||
| 22 | 28 | ; This should remove it. |
| 23 | 29 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=32k:prune_interval=0s -o %t3 %t2.o %t.o |
| 24 | 30 | ; RUN: ls %t.cache | count 4 |
| ... | ... | @@ -31,6 +37,20 @@ |
| 31 | 37 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy prune_after=0s:cache_size=0%:cache_size_files=1:prune_interval=0s -o %t3 %t2.o %t.o |
| 32 | 38 | ; RUN: ls %t.cache | count 3 |
| 33 | 39 | |
| 40 | ; Check that we remove the least recently used file first. | |
| 41 | ; RUN: rm -fr %t.cache | |
| 42 | ; RUN: mkdir %t.cache | |
| 43 | ; RUN: echo xyz > %t.cache/llvmcache-old | |
| 44 | ; RUN: touch -t 198002011200 %t.cache/llvmcache-old | |
| 45 | ; RUN: echo xyz > %t.cache/llvmcache-newer | |
| 46 | ; RUN: touch -t 198002021200 %t.cache/llvmcache-newer | |
| 47 | ; RUN: ld.lld --thinlto-cache-dir=%t.cache --thinlto-cache-policy prune_after=0s:cache_size=0%:cache_size_files=3:prune_interval=0s -o %t3 %t2.o %t.o | |
| 48 | ; RUN: ls %t.cache | FileCheck %s | |
| 49 | ||
| 50 | ; CHECK-NOT: llvmcache-old | |
| 51 | ; CHECK: llvmcache-newer | |
| 52 | ; CHECK-NOT: llvmcache-old | |
| 53 | ||
| 34 | 54 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| 35 | 55 | target triple = "x86_64-unknown-linux-gnu" |
| 36 | 56 |
deps/lld/test/ELF/lto/data-ordering-lto.s+1-1| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | # RUN: echo "pat " >> %t_order_lto.txt |
| 9 | 9 | |
| 10 | 10 | # RUN: ld.lld --symbol-ordering-file %t_order_lto.txt %t.o %t.bc -o %t2.out |
| 11 | # RUN: llvm-readelf -t %t2.out| FileCheck %s | |
| 11 | # RUN: llvm-readelf --symbols %t2.out| FileCheck %s | |
| 12 | 12 | |
| 13 | 13 | # Check that the order is tin -> dipsy -> pat. |
| 14 | 14 |
deps/lld/test/ELF/lto/defsym.ll+2-2| ... | ... | @@ -3,14 +3,14 @@ |
| 3 | 3 | ; RUN: llvm-as %s -o %t.o |
| 4 | 4 | ; RUN: llvm-as %S/Inputs/defsym-bar.ll -o %t1.o |
| 5 | 5 | ; RUN: ld.lld %t.o %t1.o -shared -o %t.so -defsym=bar2=bar3 -save-temps |
| 6 | ; RUN: llvm-readelf -t %t.so.lto.o | FileCheck --check-prefix=OBJ %s | |
| 6 | ; RUN: llvm-readelf --symbols %t.so.lto.o | FileCheck --check-prefix=OBJ %s | |
| 7 | 7 | ; RUN: llvm-objdump -d %t.so | FileCheck %s |
| 8 | 8 | |
| 9 | 9 | ; ThinLTO |
| 10 | 10 | ; RUN: opt -module-summary %s -o %t.o |
| 11 | 11 | ; RUN: opt -module-summary %S/Inputs/defsym-bar.ll -o %t1.o |
| 12 | 12 | ; RUN: ld.lld %t.o %t1.o -shared -o %t2.so -defsym=bar2=bar3 -save-temps |
| 13 | ; RUN: llvm-readelf -t %t2.so1.lto.o | FileCheck --check-prefix=OBJ %s | |
| 13 | ; RUN: llvm-readelf --symbols %t2.so1.lto.o | FileCheck --check-prefix=OBJ %s | |
| 14 | 14 | ; RUN: llvm-objdump -d %t2.so | FileCheck %s --check-prefix=THIN |
| 15 | 15 | |
| 16 | 16 | ; OBJ: UND bar2 |
deps/lld/test/ELF/lto/dynamic-list.ll+1-1| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | ; RUN: ld.lld -o %t --dynamic-list %t.list -pie %t.o |
| 5 | 5 | ; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s |
| 6 | 6 | |
| 7 | ; CHECK: Name: foo@ | |
| 7 | ; CHECK: Name: foo | |
| 8 | 8 | ; CHECK-NEXT: Value: 0x1010 |
| 9 | 9 | ; CHECK-NEXT: Size: 1 |
| 10 | 10 | ; CHECK-NEXT: Binding: Global (0x1) |
deps/lld/test/ELF/lto/emit-llvm.ll created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | ; REQUIRES: x86 | |
| 2 | ||
| 3 | ; RUN: opt -module-hash -module-summary %s -o %t.o | |
| 4 | ; RUN: ld.lld --plugin-opt=emit-llvm -o %t.out.o %t.o | |
| 5 | ; RUN: llvm-dis < %t.out.o -o - | FileCheck %s | |
| 6 | ||
| 7 | ; CHECK: define internal void @main() | |
| 8 | ||
| 9 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" | |
| 10 | target triple = "x86_64-unknown-linux-gnu" | |
| 11 | ||
| 12 | define void @main() { | |
| 13 | ret void | |
| 14 | } |
deps/lld/test/ELF/lto/libcall-archive.ll+5-1| ... | ... | @@ -2,10 +2,14 @@ |
| 2 | 2 | ; RUN: rm -f %t.a |
| 3 | 3 | ; RUN: llvm-as -o %t.o %s |
| 4 | 4 | ; RUN: llvm-as -o %t2.o %S/Inputs/libcall-archive.ll |
| 5 | ; RUN: llvm-ar rcs %t.a %t2.o | |
| 5 | ; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %t3.o %S/Inputs/libcall-archive.s | |
| 6 | ; RUN: llvm-ar rcs %t.a %t2.o %t3.o | |
| 6 | 7 | ; RUN: ld.lld -o %t %t.o %t.a |
| 7 | 8 | ; RUN: llvm-nm %t | FileCheck %s |
| 9 | ; RUN: ld.lld -o %t2 %t.o --start-lib %t2.o %t3.o --end-lib | |
| 10 | ; RUN: llvm-nm %t2 | FileCheck %s | |
| 8 | 11 | |
| 12 | ; CHECK-NOT: T __sync_val_compare_and_swap_8 | |
| 9 | 13 | ; CHECK: T _start |
| 10 | 14 | ; CHECK: T memcpy |
| 11 | 15 |
deps/lld/test/ELF/lto/ltopasses-custom.ll+2-2| ... | ... | @@ -27,11 +27,11 @@ define void @barrier() { |
| 27 | 27 | ; RUN: not ld.lld -m elf_x86_64 %t.o -o %t2.so \ |
| 28 | 28 | ; RUN: --lto-newpm-passes=iamnotapass -shared 2>&1 | \ |
| 29 | 29 | ; RUN: FileCheck %s --check-prefix=INVALID |
| 30 | ; INVALID: unable to parse pass pipeline description: iamnotapass | |
| 30 | ; INVALID: unable to parse pass pipeline description 'iamnotapass': unknown pass name 'iamnotapass' | |
| 31 | 31 | |
| 32 | 32 | ; Check that invalid AA pipelines are rejected gracefully. |
| 33 | 33 | ; RUN: not ld.lld -m elf_x86_64 %t.o -o %t2.so \ |
| 34 | 34 | ; RUN: --lto-newpm-passes=globaldce --lto-aa-pipeline=patatino \ |
| 35 | 35 | ; RUN: -shared 2>&1 | \ |
| 36 | 36 | ; RUN: FileCheck %s --check-prefix=INVALIDAA |
| 37 | ; INVALIDAA: unable to parse AA pipeline description: patatino | |
| 37 | ; INVALIDAA: unknown alias analysis name 'patatino' |
deps/lld/test/ELF/lto/opt-remarks.ll+6-4| ... | ... | @@ -23,9 +23,10 @@ |
| 23 | 23 | ; YAML-NEXT: - Callee: tinkywinky |
| 24 | 24 | ; YAML-NEXT: - String: ' inlined into ' |
| 25 | 25 | ; YAML-NEXT: - Caller: main |
| 26 | ; YAML-NEXT: - String: ' with cost=' | |
| 26 | ; YAML-NEXT: - String: ' with ' | |
| 27 | ; YAML-NEXT: - String: '(cost=' | |
| 27 | 28 | ; YAML-NEXT: - Cost: '0' |
| 28 | ; YAML-NEXT: - String: ' (threshold=' | |
| 29 | ; YAML-NEXT: - String: ', threshold=' | |
| 29 | 30 | ; YAML-NEXT: - Threshold: '337' |
| 30 | 31 | ; YAML-NEXT: - String: ')' |
| 31 | 32 | ; YAML-NEXT: ... |
| ... | ... | @@ -39,9 +40,10 @@ |
| 39 | 40 | ; YAML-HOT-NEXT: - Callee: tinkywinky |
| 40 | 41 | ; YAML-HOT-NEXT: - String: ' inlined into ' |
| 41 | 42 | ; YAML-HOT-NEXT: - Caller: main |
| 42 | ; YAML-HOT-NEXT: - String: ' with cost=' | |
| 43 | ; YAML-HOT-NEXT: - String: ' with ' | |
| 44 | ; YAML-HOT-NEXT: - String: '(cost=' | |
| 43 | 45 | ; YAML-HOT-NEXT: - Cost: '0' |
| 44 | ; YAML-HOT-NEXT: - String: ' (threshold=' | |
| 46 | ; YAML-HOT-NEXT: - String: ', threshold=' | |
| 45 | 47 | ; YAML-HOT-NEXT: - Threshold: '337' |
| 46 | 48 | ; YAML-HOT-NEXT: - String: ')' |
| 47 | 49 | ; YAML-HOT-NEXT: ... |
deps/lld/test/ELF/lto/ppc64le.ll created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | ; REQUIRES: ppc | |
| 2 | ||
| 3 | ; RUN: llvm-as %s -o %t.o | |
| 4 | ; RUN: ld.lld %t.o -o %t | |
| 5 | ||
| 6 | target datalayout = "e-m:e-i64:64-n32:64" | |
| 7 | target triple = "powerpc64le-unknown-linux-gnu" | |
| 8 | ||
| 9 | define void @__start() { | |
| 10 | entry: | |
| 11 | ret void | |
| 12 | } |
deps/lld/test/ELF/lto/r600.ll created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | ; REQUIRES: amdgpu | |
| 2 | ; RUN: llvm-as %s -o %t.o | |
| 3 | ; RUN: ld.lld %t.o -o %t | |
| 4 | ||
| 5 | ; Make sure the r600 triple is handled | |
| 6 | ||
| 7 | target triple = "r600-mesa-mesa3d" | |
| 8 | target datalayout = "e-p:32:32-i64:64-v16:16-v24:32-v32:32-v48:64-v96:128-v192:256-v256:256-v512:512-v1024:1024-v2048:2048-n32:64-S32-A5" | |
| 9 | ||
| 10 | define void @_start() { | |
| 11 | ret void | |
| 12 | } |
deps/lld/test/ELF/lto/relocatable.ll+9| ... | ... | @@ -41,6 +41,15 @@ |
| 41 | 41 | ; CHECK-NEXT: Section: .text.foo |
| 42 | 42 | ; CHECK-NEXT: } |
| 43 | 43 | ; CHECK-NEXT: Symbol { |
| 44 | ; CHECK-NEXT: Name: | |
| 45 | ; CHECK-NEXT: Value: 0x0 | |
| 46 | ; CHECK-NEXT: Size: 0 | |
| 47 | ; CHECK-NEXT: Binding: Local | |
| 48 | ; CHECK-NEXT: Type: Section | |
| 49 | ; CHECK-NEXT: Other: 0 | |
| 50 | ; CHECK-NEXT: Section: .llvm_addrsig | |
| 51 | ; CHECK-NEXT: } | |
| 52 | ; CHECK-NEXT: Symbol { | |
| 44 | 53 | ; CHECK-NEXT: Name: foo |
| 45 | 54 | ; CHECK-NEXT: Value: 0x0 |
| 46 | 55 | ; CHECK-NEXT: Size: 1 |
deps/lld/test/ELF/lto/section-name.ll+2-2| ... | ... | @@ -1,9 +1,9 @@ |
| 1 | 1 | ; REQUIRES: x86 |
| 2 | 2 | ; RUN: llvm-as %s -o %t.o |
| 3 | 3 | ; RUN: ld.lld %t.o -o %t.so -shared |
| 4 | ; RUN: llvm-readelf -s %t.so | FileCheck %s | |
| 4 | ; RUN: llvm-readelf -S %t.so | FileCheck %s | |
| 5 | 5 | ; RUN: ld.lld %t.o -o %t.so -shared --gc-sections |
| 6 | ; RUN: llvm-readelf -s %t.so | FileCheck --check-prefix=GC %s | |
| 6 | ; RUN: llvm-readelf -S %t.so | FileCheck --check-prefix=GC %s | |
| 7 | 7 | |
| 8 | 8 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| 9 | 9 | target triple = "x86_64-unknown-linux-gnu" |
deps/lld/test/ELF/lto/shlib-undefined.ll+1-1| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | ; RUN: ld.lld -o %t %t.o %t2.so |
| 7 | 7 | ; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s |
| 8 | 8 | |
| 9 | ; CHECK: Name: __progname@ | |
| 9 | ; CHECK: Name: __progname | |
| 10 | 10 | ; CHECK-NEXT: Value: 0x201010 |
| 11 | 11 | ; CHECK-NEXT: Size: 1 |
| 12 | 12 | ; CHECK-NEXT: Binding: Global (0x1) |
deps/lld/test/ELF/lto/symbol-ordering-lto.s+1-1| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | # RUN: echo "pat " >> %t_order_lto.txt |
| 9 | 9 | |
| 10 | 10 | # RUN: ld.lld --symbol-ordering-file %t_order_lto.txt %t.o %t.bc -o %t2.out |
| 11 | # RUN: llvm-readelf -t %t2.out| FileCheck %s | |
| 11 | # RUN: llvm-readelf --symbols %t2.out| FileCheck %s | |
| 12 | 12 | |
| 13 | 13 | # Check that the order is tin -> _start -> pat. |
| 14 | 14 |
deps/lld/test/ELF/lto/thinlto-obj-path.ll+2-1| ... | ... | @@ -7,7 +7,8 @@ |
| 7 | 7 | ; RUN: rm -f %t4.o |
| 8 | 8 | ; RUN: ld.lld --plugin-opt=thinlto-index-only --plugin-opt=obj-path=%t4.o -shared %t1.o %t2.o -o %t3 |
| 9 | 9 | ; RUN: llvm-readobj -h %t4.o | FileCheck %s |
| 10 | ; RUN: llvm-nm %t4.o | count 0 | |
| 10 | ; RUN: llvm-nm %t4.o 2>&1 | FileCheck %s -check-prefix=NO-SYMBOLS | |
| 11 | ; NO-SYMBOLS: no symbols | |
| 11 | 12 | |
| 12 | 13 | ; CHECK: Format: ELF64-x86-64 |
| 13 | 14 |
deps/lld/test/ELF/lto/thinlto-object-suffix-replace.ll+6-6| ... | ... | @@ -29,12 +29,12 @@ |
| 29 | 29 | ; RUN: -o %t3 2>&1 | FileCheck %s --check-prefix=ERR1 |
| 30 | 30 | ; ERR1: --plugin-opt=thinlto-object-suffix-replace= expects 'old;new' format, but got abc:def |
| 31 | 31 | |
| 32 | ; Ensure lld generates error if old suffix doesn't exist in file name | |
| 33 | ; RUN: rm -f %t1.o | |
| 34 | ; RUN: not ld.lld --plugin-opt=thinlto-index-only \ | |
| 35 | ; RUN: --plugin-opt=thinlto-object-suffix-replace=".abc;.o" -shared %t1.thinlink.bc \ | |
| 36 | ; RUN: -o %t3 2>&1 | FileCheck %s --check-prefix=ERR2 | |
| 37 | ; ERR2: error: -thinlto-object-suffix-replace=.abc;.o was given, but {{.*}} does not end with the suffix | |
| 32 | ; If filename does not end with old suffix, no suffix change should occur, | |
| 33 | ; so ".thinlto.bc" will simply be appended to the input file name. | |
| 34 | ; RUN: rm -f %t1.thinlink.bc.thinlto.bc | |
| 35 | ; RUN: ld.lld --plugin-opt=thinlto-index-only \ | |
| 36 | ; RUN: --plugin-opt=thinlto-object-suffix-replace=".abc;.o" -shared %t1.thinlink.bc -o /dev/null | |
| 37 | ; RUN: ls %t1.thinlink.bc.thinlto.bc | |
| 38 | 38 | |
| 39 | 39 | target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128" |
| 40 | 40 | target triple = "x86_64-unknown-linux-gnu" |
deps/lld/test/ELF/lto/undefined-puts.ll+1-1| ... | ... | @@ -25,4 +25,4 @@ declare i32 @printf(i8*, ...) |
| 25 | 25 | |
| 26 | 26 | ; CHECK: DynamicSymbols [ |
| 27 | 27 | ; CHECK: Symbol { |
| 28 | ; CHECK: Name: puts@ | |
| 28 | ; CHECK: Name: puts |
deps/lld/test/ELF/lto/version-script.ll+1-1| ... | ... | @@ -21,7 +21,7 @@ define void @bar() { |
| 21 | 21 | |
| 22 | 22 | ; DSO: DynamicSymbols [ |
| 23 | 23 | ; DSO: Symbol { |
| 24 | ; DSO: Name: @ (0) | |
| 24 | ; DSO: Name: | |
| 25 | 25 | ; DSO: Value: 0x0 |
| 26 | 26 | ; DSO: Size: 0 |
| 27 | 27 | ; DSO: Binding: Local |
deps/lld/test/ELF/lto/wrap-2.ll+6-2| ... | ... | @@ -28,11 +28,15 @@ |
| 28 | 28 | ; THIN-NEXT: jmp{{.*}}<bar> |
| 29 | 29 | |
| 30 | 30 | ; Check that bar and __wrap_bar retain their original binding. |
| 31 | ; BIND: Name: __wrap_bar | |
| 31 | ; BIND: Name: bar | |
| 32 | 32 | ; BIND-NEXT: Value: |
| 33 | 33 | ; BIND-NEXT: Size: |
| 34 | 34 | ; BIND-NEXT: Binding: Local |
| 35 | ; BIND: Name: bar | |
| 35 | ; BIND: Name: __real_bar | |
| 36 | ; BIND-NEXT: Value: | |
| 37 | ; BIND-NEXT: Size: | |
| 38 | ; BIND-NEXT: Binding: Local | |
| 39 | ; BIND: Name: __wrap_bar | |
| 36 | 40 | ; BIND-NEXT: Value: |
| 37 | 41 | ; BIND-NEXT: Size: |
| 38 | 42 | ; BIND-NEXT: Binding: Local |
deps/lld/test/ELF/map-file-i686.s+12-12| ... | ... | @@ -7,15 +7,15 @@ |
| 7 | 7 | _start: |
| 8 | 8 | nop |
| 9 | 9 | |
| 10 | // CHECK: VMA LMA Size Align Out In Symbol | |
| 11 | // CHECK-NEXT: 11000 11000 1 4 .text | |
| 12 | // CHECK-NEXT: 11000 11000 1 4 {{.*}}{{/|\\}}map-file-i686.s.tmp1.o:(.text) | |
| 13 | // CHECK-NEXT: 11000 11000 0 1 _start | |
| 14 | // CHECK-NEXT: 0 0 8 1 .comment | |
| 15 | // CHECK-NEXT: 0 0 8 1 <internal>:(.comment) | |
| 16 | // CHECK-NEXT: 0 0 20 4 .symtab | |
| 17 | // CHECK-NEXT: 0 0 20 4 <internal>:(.symtab) | |
| 18 | // CHECK-NEXT: 0 0 2a 1 .shstrtab | |
| 19 | // CHECK-NEXT: 0 0 2a 1 <internal>:(.shstrtab) | |
| 20 | // CHECK-NEXT: 0 0 8 1 .strtab | |
| 21 | // CHECK-NEXT: 0 0 8 1 <internal>:(.strtab) | |
| 10 | // CHECK: VMA LMA Size Align Out In Symbol | |
| 11 | // CHECK-NEXT: 401000 401000 1 4 .text | |
| 12 | // CHECK-NEXT: 401000 401000 1 4 {{.*}}{{/|\\}}map-file-i686.s.tmp1.o:(.text) | |
| 13 | // CHECK-NEXT: 401000 401000 0 1 _start | |
| 14 | // CHECK-NEXT: 0 0 8 1 .comment | |
| 15 | // CHECK-NEXT: 0 0 8 1 <internal>:(.comment) | |
| 16 | // CHECK-NEXT: 0 0 20 4 .symtab | |
| 17 | // CHECK-NEXT: 0 0 20 4 <internal>:(.symtab) | |
| 18 | // CHECK-NEXT: 0 0 2a 1 .shstrtab | |
| 19 | // CHECK-NEXT: 0 0 2a 1 <internal>:(.shstrtab) | |
| 20 | // CHECK-NEXT: 0 0 8 1 .strtab | |
| 21 | // CHECK-NEXT: 0 0 8 1 <internal>:(.strtab) |
deps/lld/test/ELF/merge-string-error.s+1-1| ... | ... | @@ -8,4 +8,4 @@ |
| 8 | 8 | .data |
| 9 | 9 | .long .rodata.str1.1 + 4 |
| 10 | 10 | |
| 11 | // CHECK: merge-string-error.s.tmp.o:(.rodata.str1.1): entry is past the end of the section | |
| 11 | // CHECK: merge-string-error.s.tmp.o:(.rodata.str1.1): offset is outside the section |
deps/lld/test/ELF/mergeable-errors.s created+8| ... | ... | @@ -0,0 +1,8 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: not ld.lld %t.o -o %t1 2>&1 | FileCheck %s | |
| 4 | ||
| 5 | # CHECK: error: {{.*}}.o:(.mergeable): string is not null terminated | |
| 6 | ||
| 7 | .section .mergeable,"MS",@progbits,2 | |
| 8 | .short 0x1122 |
deps/lld/test/ELF/mips-32.s+2-2| ... | ... | @@ -41,8 +41,8 @@ v2: |
| 41 | 41 | # ^-- v2+4 ^-- v1 |
| 42 | 42 | |
| 43 | 43 | # SYM: SYMBOL TABLE: |
| 44 | # SYM: 00020000 l .data 00000004 v1 | |
| 45 | # SYM: 00020004 g .data 00000008 v2 | |
| 44 | # SYM: 00020000 l O .data 00000004 v1 | |
| 45 | # SYM: 00020004 g O .data 00000008 v2 | |
| 46 | 46 | |
| 47 | 47 | # REL: Relocations [ |
| 48 | 48 | # REL-NEXT: Section (7) .rel.dyn { |
deps/lld/test/ELF/mips-64.s+2-2| ... | ... | @@ -25,8 +25,8 @@ v2: |
| 25 | 25 | |
| 26 | 26 | |
| 27 | 27 | # SYM: SYMBOL TABLE: |
| 28 | # SYM: 00020000 l .data 00000004 v1 | |
| 29 | # SYM: 00020008 g .data 00000008 v2 | |
| 28 | # SYM: 00020000 l O .data 00000004 v1 | |
| 29 | # SYM: 00020008 g O .data 00000008 v2 | |
| 30 | 30 | |
| 31 | 31 | # CHECK: Relocations [ |
| 32 | 32 | # CHECK-NEXT: Section (7) .rel.dyn { |
deps/lld/test/ELF/mips-dynamic.s+3-3| ... | ... | @@ -97,9 +97,9 @@ |
| 97 | 97 | # DSO-NEXT: Size: 8 |
| 98 | 98 | # DSO: ] |
| 99 | 99 | # DSO: DynamicSymbols [ |
| 100 | # DSO: Name: @ | |
| 101 | # DSO: Name: __start@ | |
| 102 | # DSO: Name: _foo@ | |
| 100 | # DSO: Name: | |
| 101 | # DSO: Name: __start | |
| 102 | # DSO: Name: _foo | |
| 103 | 103 | # DSO: ] |
| 104 | 104 | # DSO: DynamicSection [ |
| 105 | 105 | # DSO-NEXT: Tag Type Name/Value |
deps/lld/test/ELF/mips-dynsym-sort.s+3-3| ... | ... | @@ -36,7 +36,7 @@ __start: |
| 36 | 36 | # the MIPS rules. v2 comes first as it is not in the GOT. |
| 37 | 37 | # v1 and v3 are sorted according to their order in the GOT. |
| 38 | 38 | # CHECK: DynamicSymbols [ |
| 39 | # CHECK: Name: v2@ | |
| 40 | # CHECK: Name: v3@ | |
| 41 | # CHECK: Name: v1@ | |
| 39 | # CHECK: Name: v2 | |
| 40 | # CHECK: Name: v3 | |
| 41 | # CHECK: Name: v1 | |
| 42 | 42 | # CHECK: ] |
deps/lld/test/ELF/mips-gnu-hash.s+1-1| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o |
| 8 | 8 | # RUN: not ld.lld -shared -hash-style=gnu %t-el.o -o /dev/null 2>&1 | FileCheck %s |
| 9 | 9 | |
| 10 | # CHECK: the .gnu.hash section is not compatible with the MIPS target. | |
| 10 | # CHECK: the .gnu.hash section is not compatible with the MIPS target | |
| 11 | 11 | |
| 12 | 12 | .globl __start |
| 13 | 13 | __start: |
deps/lld/test/ELF/mips-got-and-copy.s+2-2| ... | ... | @@ -32,7 +32,7 @@ |
| 32 | 32 | # CHECK-NEXT: Value: 0x[[DATA0]] |
| 33 | 33 | # CHECK-NEXT: Type: Object |
| 34 | 34 | # CHECK-NEXT: Section: .bss |
| 35 | # CHECK-NEXT: Name: data0@ | |
| 35 | # CHECK-NEXT: Name: data0 | |
| 36 | 36 | # CHECK-NEXT: } |
| 37 | 37 | # CHECK-NEXT: Entry { |
| 38 | 38 | # CHECK-NEXT: Address: |
| ... | ... | @@ -41,7 +41,7 @@ |
| 41 | 41 | # CHECK-NEXT: Value: 0x[[DATA1]] |
| 42 | 42 | # CHECK-NEXT: Type: Object |
| 43 | 43 | # CHECK-NEXT: Section: .bss |
| 44 | # CHECK-NEXT: Name: data1@ | |
| 44 | # CHECK-NEXT: Name: data1 | |
| 45 | 45 | # CHECK-NEXT: } |
| 46 | 46 | # CHECK-NEXT: ] |
| 47 | 47 | # CHECK-NEXT: Number of TLS and multi-GOT entries: 0 |
deps/lld/test/ELF/mips-got-extsym.s+1-1| ... | ... | @@ -43,7 +43,7 @@ |
| 43 | 43 | # CHECK-NEXT: Value: 0x0 |
| 44 | 44 | # CHECK-NEXT: Type: None |
| 45 | 45 | # CHECK-NEXT: Section: Undefined |
| 46 | # CHECK-NEXT: Name: _foo@ | |
| 46 | # CHECK-NEXT: Name: _foo | |
| 47 | 47 | # CHECK-NEXT: } |
| 48 | 48 | # CHECK-NEXT: ] |
| 49 | 49 |
deps/lld/test/ELF/mips-got-relocs.s+2-2| ... | ... | @@ -48,7 +48,7 @@ v1: |
| 48 | 48 | # EXE_SYM: SYMBOL TABLE: |
| 49 | 49 | # EXE_SYM: 00038000 .got 00000000 .hidden _gp |
| 50 | 50 | # ^-- .got + GP offset (0x7ff0) |
| 51 | # EXE_SYM: 00030000 g .data		 00000004 v1 | |
| 51 | # EXE_SYM: 00030000 g O .data		 00000004 v1 | |
| 52 | 52 | |
| 53 | 53 | |
| 54 | 54 | # EXE_GOT_BE: Contents of section .got: |
| ... | ... | @@ -72,7 +72,7 @@ v1: |
| 72 | 72 | # DSO_SYM: SYMBOL TABLE: |
| 73 | 73 | # DSO_SYM: 00028000 .got 00000000 .hidden _gp |
| 74 | 74 | # ^-- .got + GP offset (0x7ff0) |
| 75 | # DSO_SYM: 00020000 g .data		 00000004 v1 | |
| 75 | # DSO_SYM: 00020000 g O .data		 00000004 v1 | |
| 76 | 76 | |
| 77 | 77 | # DSO_GOT_BE: Contents of section .got: |
| 78 | 78 | # DSO_GOT_BE: 20010 00000000 80000000 00020000 |
deps/lld/test/ELF/mips-got16-relocatable.s+2-6| ... | ... | @@ -14,9 +14,7 @@ |
| 14 | 14 | # OBJ-NEXT: 00000000: R_MIPS_GOT16 .data |
| 15 | 15 | # OBJ-NEXT: 4: 27 24 00 00 addiu $4, $25, 0 |
| 16 | 16 | # OBJ-NEXT: 00000004: R_MIPS_LO16 .data |
| 17 | # OBJ-NEXT: 8: ef ef ef ef <unknown> | |
| 18 | # OBJ-NEXT: c: ef ef ef ef <unknown> | |
| 19 | # OBJ-NEXT: 10: 8f 99 00 00 lw $25, 0($gp) | |
| 17 | # OBJ: 10: 8f 99 00 00 lw $25, 0($gp) | |
| 20 | 18 | # OBJ-NEXT: 00000010: R_MIPS_GOT16 .data |
| 21 | 19 | # OBJ-NEXT: 14: 27 24 00 10 addiu $4, $25, 16 |
| 22 | 20 | # OBJ-NEXT: 00000014: R_MIPS_LO16 .data |
| ... | ... | @@ -25,9 +23,7 @@ |
| 25 | 23 | # SO-NEXT: .text: |
| 26 | 24 | # SO-NEXT: 10000: 8f 99 80 18 lw $25, -32744($gp) |
| 27 | 25 | # SO-NEXT: 10004: 27 24 00 00 addiu $4, $25, 0 |
| 28 | # SO-NEXT: 10008: ef ef ef ef <unknown> | |
| 29 | # SO-NEXT: 1000c: ef ef ef ef <unknown> | |
| 30 | # SO-NEXT: 10010: 8f 99 80 18 lw $25, -32744($gp) | |
| 26 | # SO: 10010: 8f 99 80 18 lw $25, -32744($gp) | |
| 31 | 27 | # SO-NEXT: 10014: 27 24 00 10 addiu $4, $25, 16 |
| 32 | 28 | |
| 33 | 29 | .text |
deps/lld/test/ELF/mips-got16.s+1-1| ... | ... | @@ -96,7 +96,7 @@ |
| 96 | 96 | # GOT-NEXT: Value: 0x0 |
| 97 | 97 | # GOT-NEXT: Type: None |
| 98 | 98 | # GOT-NEXT: Section: Undefined |
| 99 | # GOT-NEXT: Name: foo@ | |
| 99 | # GOT-NEXT: Name: foo | |
| 100 | 100 | # GOT-NEXT: } |
| 101 | 101 | # GOT-NEXT: ] |
| 102 | 102 | # GOT-NEXT: Number of TLS and multi-GOT entries: 0 |
deps/lld/test/ELF/mips-hilo.s+3-3| ... | ... | @@ -47,6 +47,6 @@ g1: |
| 47 | 47 | # ^-- %lo(l1-4) |
| 48 | 48 | |
| 49 | 49 | # CHECK: SYMBOL TABLE: |
| 50 | # CHECK: 0030000 l .data 00000004 l1 | |
| 51 | # CHECK: 0020000 .text 00000000 __start | |
| 52 | # CHECK: 0030004 g .data 00000004 g1 | |
| 50 | # CHECK: 0030000 l O .data 00000004 l1 | |
| 51 | # CHECK: 0020000 .text 00000000 __start | |
| 52 | # CHECK: 0030004 g O .data 00000004 g1 |
deps/lld/test/ELF/mips-mgot.s+7-7| ... | ... | @@ -18,13 +18,13 @@ |
| 18 | 18 | # CHECK-NEXT: 60040 00000000 00000000 00000000 |
| 19 | 19 | |
| 20 | 20 | # CHECK: SYMBOL TABLE: |
| 21 | # CHECK: 00000000 l .tdata 00000000 loc0 | |
| 22 | # CHECK: 00010000 .text 00000000 foo0 | |
| 23 | # CHECK: 00000000 g .tdata 00000000 tls0 | |
| 24 | # CHECK: 00010020 .text 00000000 foo1 | |
| 25 | # CHECK: 00000004 g .tdata 00000000 tls1 | |
| 26 | # CHECK: 00010030 .text 00000000 foo2 | |
| 27 | # CHECK: 00000008 g .tdata 00000000 tls2 | |
| 21 | # CHECK: 00000000 l O .tdata 00000000 loc0 | |
| 22 | # CHECK: 00010000 .text 00000000 foo0 | |
| 23 | # CHECK: 00000000 g O .tdata 00000000 tls0 | |
| 24 | # CHECK: 00010020 .text 00000000 foo1 | |
| 25 | # CHECK: 00000004 g O .tdata 00000000 tls1 | |
| 26 | # CHECK: 00010030 .text 00000000 foo2 | |
| 27 | # CHECK: 00000008 g O .tdata 00000000 tls2 | |
| 28 | 28 | |
| 29 | 29 | # GOT: Relocations [ |
| 30 | 30 | # GOT-NEXT: Section (7) .rel.dyn { |
deps/lld/test/ELF/mips-micro-jal.s+3-9| ... | ... | @@ -57,9 +57,7 @@ |
| 57 | 57 | # EB-NEXT: 20022: 45 f9 jalrs16 $25 |
| 58 | 58 | # EB-NEXT: 20024: 0f 83 move $gp, $3 |
| 59 | 59 | # EB-NEXT: 20026: 0c 00 nop |
| 60 | # EB-NEXT: 20028: 00 00 00 00 nop | |
| 61 | # EB-NEXT: 2002c: 00 00 00 00 nop | |
| 62 | ||
| 60 | # EB-NEXT: ... | |
| 63 | 61 | # EB-NEXT: 20030: 79 00 3f f7 addiupc $2, 65500 |
| 64 | 62 | # EB-NEXT: 20034: ff 22 00 00 lw $25, 0($2) |
| 65 | 63 | # EB-NEXT: 20038: 45 99 jr16 $25 |
| ... | ... | @@ -76,9 +74,7 @@ |
| 76 | 74 | # EL-NEXT: 20022: f9 45 jalrs16 $25 |
| 77 | 75 | # EL-NEXT: 20024: 83 0f move $gp, $3 |
| 78 | 76 | # EL-NEXT: 20026: 00 0c nop |
| 79 | # EL-NEXT: 20028: 00 00 00 00 nop | |
| 80 | # EL-NEXT: 2002c: 00 00 00 00 nop | |
| 81 | ||
| 77 | # EL-NEXT: ... | |
| 82 | 78 | # EL-NEXT: 20030: 00 79 f7 3f addiupc $2, 65500 |
| 83 | 79 | # EL-NEXT: 20034: 22 ff 00 00 lw $25, 0($2) |
| 84 | 80 | # EL-NEXT: 20038: 99 45 jr16 $25 |
| ... | ... | @@ -127,9 +123,7 @@ |
| 127 | 123 | # MIXED-NEXT: 20032: 45 f9 jalrs16 $25 |
| 128 | 124 | # MIXED-NEXT: 20034: 0f 83 move $gp, $3 |
| 129 | 125 | # MIXED-NEXT: 20036: 0c 00 nop |
| 130 | # MIXED-NEXT: 20038: 00 00 00 00 nop | |
| 131 | # MIXED-NEXT: 2003c: 00 00 00 00 nop | |
| 132 | ||
| 126 | # MIXED-NEXT: ... | |
| 133 | 127 | # MIXED-NEXT: 20040: 79 00 3f f3 addiupc $2, 65484 |
| 134 | 128 | # MIXED-NEXT: 20044: ff 22 00 00 lw $25, 0($2) |
| 135 | 129 | # MIXED-NEXT: 20048: 45 99 jr16 $25 |
deps/lld/test/ELF/mips-micro-plt.s+1-1| ... | ... | @@ -80,7 +80,7 @@ |
| 80 | 80 | # CHECK-NEXT: Value: 0x20041 |
| 81 | 81 | # CHECK-NEXT: Type: Function |
| 82 | 82 | # CHECK-NEXT: Section: Undefined |
| 83 | # CHECK-NEXT: Name: foo0@ | |
| 83 | # CHECK-NEXT: Name: foo0 | |
| 84 | 84 | # CHECK-NEXT: } |
| 85 | 85 | # CHECK-NEXT: ] |
| 86 | 86 | # CHECK-NEXT: } |
deps/lld/test/ELF/mips-npic-call-pic-os.s+18-17| ... | ... | @@ -19,37 +19,37 @@ |
| 19 | 19 | # CHECK-NEXT: 20004: 08 00 80 08 j 131104 <foo1a> |
| 20 | 20 | # CHECK-NEXT: 20008: 27 39 00 20 addiu $25, $25, 32 |
| 21 | 21 | # CHECK-NEXT: 2000c: 00 00 00 00 nop |
| 22 | ||
| 22 | 23 | # CHECK: __LA25Thunk_foo1b: |
| 23 | 24 | # CHECK-NEXT: 20010: 3c 19 00 02 lui $25, 2 |
| 24 | 25 | # CHECK-NEXT: 20014: 08 00 80 09 j 131108 <foo1b> |
| 25 | 26 | # CHECK-NEXT: 20018: 27 39 00 24 addiu $25, $25, 36 |
| 26 | 27 | # CHECK-NEXT: 2001c: 00 00 00 00 nop |
| 28 | ||
| 27 | 29 | # CHECK: foo1a: |
| 28 | 30 | # CHECK-NEXT: 20020: 00 00 00 00 nop |
| 31 | ||
| 29 | 32 | # CHECK: foo1b: |
| 30 | 33 | # CHECK-NEXT: 20024: 00 00 00 00 nop |
| 34 | ||
| 31 | 35 | # CHECK: __LA25Thunk_foo2: |
| 32 | 36 | # CHECK-NEXT: 20028: 3c 19 00 02 lui $25, 2 |
| 33 | 37 | # CHECK-NEXT: 2002c: 08 00 80 10 j 131136 <foo2> |
| 34 | 38 | # CHECK-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64 |
| 35 | 39 | # CHECK-NEXT: 20034: 00 00 00 00 nop |
| 36 | # CHECK-NEXT: 20038: ef ef ef ef <unknown> | |
| 37 | # CHECK-NEXT: 2003c: ef ef ef ef <unknown> | |
| 40 | ||
| 38 | 41 | # CHECK: foo2: |
| 39 | 42 | # CHECK-NEXT: 20040: 00 00 00 00 nop |
| 43 | ||
| 40 | 44 | # CHECK: __LA25Thunk_fpic: |
| 41 | 45 | # CHECK-NEXT: 20044: 3c 19 00 02 lui $25, 2 |
| 42 | 46 | # CHECK-NEXT: 20048: 08 00 80 18 j 131168 <fpic> |
| 43 | 47 | # CHECK-NEXT: 2004c: 27 39 00 60 addiu $25, $25, 96 |
| 44 | 48 | # CHECK-NEXT: 20050: 00 00 00 00 nop |
| 45 | # CHECK-NEXT: 20054: ef ef ef ef <unknown> | |
| 46 | # CHECK-NEXT: 20058: ef ef ef ef <unknown> | |
| 47 | # CHECK-NEXT: 2005c: ef ef ef ef <unknown> | |
| 49 | ||
| 48 | 50 | # CHECK: fpic: |
| 49 | 51 | # CHECK-NEXT: 20060: 00 00 00 00 nop |
| 50 | # CHECK-NEXT: 20064: ef ef ef ef <unknown> | |
| 51 | # CHECK-NEXT: 20068: ef ef ef ef <unknown> | |
| 52 | # CHECK-NEXT: 2006c: ef ef ef ef <unknown> | |
| 52 | ||
| 53 | 53 | # CHECK: fnpic: |
| 54 | 54 | # CHECK-NEXT: 20070: 00 00 00 00 nop |
| 55 | 55 | # CHECK-NEXT: Disassembly of section differentos: |
| ... | ... | @@ -79,40 +79,41 @@ |
| 79 | 79 | # REVERSE-NEXT: 20004: 08 00 80 08 j 131104 <foo1a> |
| 80 | 80 | # REVERSE-NEXT: 20008: 27 39 00 20 addiu $25, $25, 32 |
| 81 | 81 | # REVERSE-NEXT: 2000c: 00 00 00 00 nop |
| 82 | ||
| 82 | 83 | # REVERSE: __LA25Thunk_foo1b: |
| 83 | 84 | # REVERSE-NEXT: 20010: 3c 19 00 02 lui $25, 2 |
| 84 | 85 | # REVERSE-NEXT: 20014: 08 00 80 09 j 131108 <foo1b> |
| 85 | 86 | # REVERSE-NEXT: 20018: 27 39 00 24 addiu $25, $25, 36 |
| 86 | 87 | # REVERSE-NEXT: 2001c: 00 00 00 00 nop |
| 88 | ||
| 87 | 89 | # REVERSE: foo1a: |
| 88 | 90 | # REVERSE-NEXT: 20020: 00 00 00 00 nop |
| 91 | ||
| 89 | 92 | # REVERSE: foo1b: |
| 90 | 93 | # REVERSE-NEXT: 20024: 00 00 00 00 nop |
| 94 | ||
| 91 | 95 | # REVERSE: __LA25Thunk_foo2: |
| 92 | 96 | # REVERSE-NEXT: 20028: 3c 19 00 02 lui $25, 2 |
| 93 | 97 | # REVERSE-NEXT: 2002c: 08 00 80 10 j 131136 <foo2> |
| 94 | 98 | # REVERSE-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64 |
| 95 | 99 | # REVERSE-NEXT: 20034: 00 00 00 00 nop |
| 96 | # REVERSE-NEXT: 20038: ef ef ef ef <unknown> | |
| 97 | # REVERSE-NEXT: 2003c: ef ef ef ef <unknown> | |
| 100 | ||
| 98 | 101 | # REVERSE: foo2: |
| 99 | 102 | # REVERSE-NEXT: 20040: 00 00 00 00 nop |
| 100 | # REVERSE-NEXT: 20044: ef ef ef ef <unknown> | |
| 101 | # REVERSE-NEXT: 20048: ef ef ef ef <unknown> | |
| 102 | # REVERSE-NEXT: 2004c: ef ef ef ef <unknown> | |
| 103 | ||
| 103 | 104 | # REVERSE: __LA25Thunk_fpic: |
| 104 | 105 | # REVERSE-NEXT: 20050: 3c 19 00 02 lui $25, 2 |
| 105 | 106 | # REVERSE-NEXT: 20054: 08 00 80 18 j 131168 <fpic> |
| 106 | 107 | # REVERSE-NEXT: 20058: 27 39 00 60 addiu $25, $25, 96 |
| 107 | 108 | # REVERSE-NEXT: 2005c: 00 00 00 00 nop |
| 109 | ||
| 108 | 110 | # REVERSE: fpic: |
| 109 | 111 | # REVERSE-NEXT: 20060: 00 00 00 00 nop |
| 110 | # REVERSE-NEXT: 20064: ef ef ef ef <unknown> | |
| 111 | # REVERSE-NEXT: 20068: ef ef ef ef <unknown> | |
| 112 | # REVERSE-NEXT: 2006c: ef ef ef ef <unknown> | |
| 112 | ||
| 113 | 113 | # REVERSE: fnpic: |
| 114 | 114 | # REVERSE-NEXT: 20070: 00 00 00 00 nop |
| 115 | # REVERSE-NEXT: Disassembly of section differentos: | |
| 115 | ||
| 116 | # REVERSE: Disassembly of section differentos: | |
| 116 | 117 | # REVERSE-NEXT: __start: |
| 117 | 118 | # REVERSE-NEXT: 20074: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a> |
| 118 | 119 | # REVERSE-NEXT: 20078: 00 00 00 00 nop |
deps/lld/test/ELF/mips-npic-call-pic-script.s+29-85| ... | ... | @@ -19,91 +19,28 @@ |
| 19 | 19 | # CHECK-NEXT: 20004: 08 00 80 08 j 131104 <foo1a> |
| 20 | 20 | # CHECK-NEXT: 20008: 27 39 00 20 addiu $25, $25, 32 |
| 21 | 21 | # CHECK-NEXT: 2000c: 00 00 00 00 nop |
| 22 | ||
| 22 | 23 | # CHECK: __LA25Thunk_foo1b: |
| 23 | 24 | # CHECK-NEXT: 20010: 3c 19 00 02 lui $25, 2 |
| 24 | 25 | # CHECK-NEXT: 20014: 08 00 80 09 j 131108 <foo1b> |
| 25 | 26 | # CHECK-NEXT: 20018: 27 39 00 24 addiu $25, $25, 36 |
| 26 | 27 | # CHECK-NEXT: 2001c: 00 00 00 00 nop |
| 28 | ||
| 27 | 29 | # CHECK: foo1a: |
| 28 | 30 | # CHECK-NEXT: 20020: 00 00 00 00 nop |
| 31 | ||
| 29 | 32 | # CHECK: foo1b: |
| 30 | 33 | # CHECK-NEXT: 20024: 00 00 00 00 nop |
| 34 | ||
| 31 | 35 | # CHECK: __LA25Thunk_foo2: |
| 32 | 36 | # CHECK-NEXT: 20028: 3c 19 00 02 lui $25, 2 |
| 33 | 37 | # CHECK-NEXT: 2002c: 08 00 80 10 j 131136 <foo2> |
| 34 | 38 | # CHECK-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64 |
| 35 | 39 | # CHECK-NEXT: 20034: 00 00 00 00 nop |
| 36 | # CHECK-NEXT: 20038: ef ef ef ef <unknown> | |
| 37 | # CHECK-NEXT: 2003c: ef ef ef ef <unknown> | |
| 40 | ||
| 38 | 41 | # CHECK: foo2: |
| 39 | 42 | # CHECK-NEXT: 20040: 00 00 00 00 nop |
| 40 | # CHECK-NEXT: 20044: ef ef ef ef <unknown> | |
| 41 | # CHECK-NEXT: 20048: ef ef ef ef <unknown> | |
| 42 | # CHECK-NEXT: 2004c: ef ef ef ef <unknown> | |
| 43 | # CHECK-NEXT: 20050: ef ef ef ef <unknown> | |
| 44 | # CHECK-NEXT: 20054: ef ef ef ef <unknown> | |
| 45 | # CHECK-NEXT: 20058: ef ef ef ef <unknown> | |
| 46 | # CHECK-NEXT: 2005c: ef ef ef ef <unknown> | |
| 47 | # CHECK-NEXT: 20060: ef ef ef ef <unknown> | |
| 48 | # CHECK-NEXT: 20064: ef ef ef ef <unknown> | |
| 49 | # CHECK-NEXT: 20068: ef ef ef ef <unknown> | |
| 50 | # CHECK-NEXT: 2006c: ef ef ef ef <unknown> | |
| 51 | # CHECK-NEXT: 20070: ef ef ef ef <unknown> | |
| 52 | # CHECK-NEXT: 20074: ef ef ef ef <unknown> | |
| 53 | # CHECK-NEXT: 20078: ef ef ef ef <unknown> | |
| 54 | # CHECK-NEXT: 2007c: ef ef ef ef <unknown> | |
| 55 | # CHECK-NEXT: 20080: ef ef ef ef <unknown> | |
| 56 | # CHECK-NEXT: 20084: ef ef ef ef <unknown> | |
| 57 | # CHECK-NEXT: 20088: ef ef ef ef <unknown> | |
| 58 | # CHECK-NEXT: 2008c: ef ef ef ef <unknown> | |
| 59 | # CHECK-NEXT: 20090: ef ef ef ef <unknown> | |
| 60 | # CHECK-NEXT: 20094: ef ef ef ef <unknown> | |
| 61 | # CHECK-NEXT: 20098: ef ef ef ef <unknown> | |
| 62 | # CHECK-NEXT: 2009c: ef ef ef ef <unknown> | |
| 63 | # CHECK-NEXT: 200a0: ef ef ef ef <unknown> | |
| 64 | # CHECK-NEXT: 200a4: ef ef ef ef <unknown> | |
| 65 | # CHECK-NEXT: 200a8: ef ef ef ef <unknown> | |
| 66 | # CHECK-NEXT: 200ac: ef ef ef ef <unknown> | |
| 67 | # CHECK-NEXT: 200b0: ef ef ef ef <unknown> | |
| 68 | # CHECK-NEXT: 200b4: ef ef ef ef <unknown> | |
| 69 | # CHECK-NEXT: 200b8: ef ef ef ef <unknown> | |
| 70 | # CHECK-NEXT: 200bc: ef ef ef ef <unknown> | |
| 71 | # CHECK-NEXT: 200c0: ef ef ef ef <unknown> | |
| 72 | # CHECK-NEXT: 200c4: ef ef ef ef <unknown> | |
| 73 | # CHECK-NEXT: 200c8: ef ef ef ef <unknown> | |
| 74 | # CHECK-NEXT: 200cc: ef ef ef ef <unknown> | |
| 75 | # CHECK-NEXT: 200d0: ef ef ef ef <unknown> | |
| 76 | # CHECK-NEXT: 200d4: ef ef ef ef <unknown> | |
| 77 | # CHECK-NEXT: 200d8: ef ef ef ef <unknown> | |
| 78 | # CHECK-NEXT: 200dc: ef ef ef ef <unknown> | |
| 79 | # CHECK-NEXT: 200e0: ef ef ef ef <unknown> | |
| 80 | # CHECK-NEXT: 200e4: ef ef ef ef <unknown> | |
| 81 | # CHECK-NEXT: 200e8: ef ef ef ef <unknown> | |
| 82 | # CHECK-NEXT: 200ec: ef ef ef ef <unknown> | |
| 83 | # CHECK-NEXT: 200f0: ef ef ef ef <unknown> | |
| 84 | # CHECK-NEXT: 200f4: ef ef ef ef <unknown> | |
| 85 | # CHECK-NEXT: 200f8: ef ef ef ef <unknown> | |
| 86 | # CHECK-NEXT: 200fc: ef ef ef ef <unknown> | |
| 87 | # CHECK-NEXT: 20100: ef ef ef ef <unknown> | |
| 88 | # CHECK-NEXT: 20104: ef ef ef ef <unknown> | |
| 89 | # CHECK-NEXT: 20108: ef ef ef ef <unknown> | |
| 90 | # CHECK-NEXT: 2010c: ef ef ef ef <unknown> | |
| 91 | # CHECK-NEXT: 20110: ef ef ef ef <unknown> | |
| 92 | # CHECK-NEXT: 20114: ef ef ef ef <unknown> | |
| 93 | # CHECK-NEXT: 20118: ef ef ef ef <unknown> | |
| 94 | # CHECK-NEXT: 2011c: ef ef ef ef <unknown> | |
| 95 | # CHECK-NEXT: 20120: ef ef ef ef <unknown> | |
| 96 | # CHECK-NEXT: 20124: ef ef ef ef <unknown> | |
| 97 | # CHECK-NEXT: 20128: ef ef ef ef <unknown> | |
| 98 | # CHECK-NEXT: 2012c: ef ef ef ef <unknown> | |
| 99 | # CHECK-NEXT: 20130: ef ef ef ef <unknown> | |
| 100 | # CHECK-NEXT: 20134: ef ef ef ef <unknown> | |
| 101 | # CHECK-NEXT: 20138: ef ef ef ef <unknown> | |
| 102 | # CHECK-NEXT: 2013c: ef ef ef ef <unknown> | |
| 103 | # CHECK-NEXT: 20140: ef ef ef ef <unknown> | |
| 104 | # CHECK-NEXT: 20144: ef ef ef ef <unknown> | |
| 105 | # CHECK-NEXT: 20148: ef ef ef ef <unknown> | |
| 106 | # CHECK-NEXT: 2014c: ef ef ef ef <unknown> | |
| 43 | ||
| 107 | 44 | # CHECK: __start: |
| 108 | 45 | # CHECK-NEXT: 20150: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a> |
| 109 | 46 | # CHECK-NEXT: 20154: 00 00 00 00 nop |
| ... | ... | @@ -117,16 +54,16 @@ |
| 117 | 54 | # CHECK-NEXT: 20174: 00 00 00 00 nop |
| 118 | 55 | # CHECK-NEXT: 20178: 0c 00 80 68 jal 131488 <fnpic> |
| 119 | 56 | # CHECK-NEXT: 2017c: 00 00 00 00 nop |
| 57 | ||
| 120 | 58 | # CHECK: __LA25Thunk_fpic: |
| 121 | 59 | # CHECK-NEXT: 20180: 3c 19 00 02 lui $25, 2 |
| 122 | 60 | # CHECK-NEXT: 20184: 08 00 80 64 j 131472 <fpic> |
| 123 | 61 | # CHECK-NEXT: 20188: 27 39 01 90 addiu $25, $25, 400 |
| 124 | 62 | # CHECK-NEXT: 2018c: 00 00 00 00 nop |
| 63 | ||
| 125 | 64 | # CHECK: fpic: |
| 126 | 65 | # CHECK-NEXT: 20190: 00 00 00 00 nop |
| 127 | # CHECK-NEXT: 20194: ef ef ef ef <unknown> | |
| 128 | # CHECK-NEXT: 20198: ef ef ef ef <unknown> | |
| 129 | # CHECK-NEXT: 2019c: ef ef ef ef <unknown> | |
| 66 | ||
| 130 | 67 | # CHECK: fnpic: |
| 131 | 68 | # CHECK-NEXT: 201a0: 00 00 00 00 nop |
| 132 | 69 | |
| ... | ... | @@ -145,6 +82,7 @@ __start: |
| 145 | 82 | # RUN: echo "SECTIONS { .text 0x20000 : { *(.text) } }" > %t2.script |
| 146 | 83 | # RUN: ld.lld --script %t2.script %t-npic.o %t-pic.o %t-sto-pic.o -o %t2.exe |
| 147 | 84 | # RUN: llvm-objdump -d %t2.exe | FileCheck -check-prefix=ORPH1 %s |
| 85 | ||
| 148 | 86 | # ORPH1: Disassembly of section .text: |
| 149 | 87 | # ORPH1-NEXT: __start: |
| 150 | 88 | # ORPH1-NEXT: 20000: 0c 00 80 15 jal 131156 <__LA25Thunk_foo1a> |
| ... | ... | @@ -159,42 +97,43 @@ __start: |
| 159 | 97 | # ORPH1-NEXT: 20024: 00 00 00 00 nop |
| 160 | 98 | # ORPH1-NEXT: 20028: 0c 00 80 14 jal 131152 <fnpic> |
| 161 | 99 | # ORPH1-NEXT: 2002c: 00 00 00 00 nop |
| 100 | ||
| 162 | 101 | # ORPH1: __LA25Thunk_fpic: |
| 163 | 102 | # ORPH1-NEXT: 20030: 3c 19 00 02 lui $25, 2 |
| 164 | 103 | # ORPH1-NEXT: 20034: 08 00 80 10 j 131136 <fpic> |
| 165 | 104 | # ORPH1-NEXT: 20038: 27 39 00 40 addiu $25, $25, 64 |
| 166 | 105 | # ORPH1-NEXT: 2003c: 00 00 00 00 nop |
| 106 | ||
| 167 | 107 | # ORPH1: fpic: |
| 168 | 108 | # ORPH1-NEXT: 20040: 00 00 00 00 nop |
| 169 | # ORPH1-NEXT: 20044: ef ef ef ef <unknown> | |
| 170 | # ORPH1-NEXT: 20048: ef ef ef ef <unknown> | |
| 171 | # ORPH1-NEXT: 2004c: ef ef ef ef <unknown> | |
| 109 | ||
| 172 | 110 | # ORPH1: fnpic: |
| 173 | 111 | # ORPH1-NEXT: 20050: 00 00 00 00 nop |
| 112 | ||
| 174 | 113 | # ORPH1: __LA25Thunk_foo1a: |
| 175 | 114 | # ORPH1-NEXT: 20054: 3c 19 00 02 lui $25, 2 |
| 176 | 115 | # ORPH1-NEXT: 20058: 08 00 80 20 j 131200 <foo1a> |
| 177 | 116 | # ORPH1-NEXT: 2005c: 27 39 00 80 addiu $25, $25, 128 |
| 178 | 117 | # ORPH1-NEXT: 20060: 00 00 00 00 nop |
| 118 | ||
| 179 | 119 | # ORPH1: __LA25Thunk_foo1b: |
| 180 | 120 | # ORPH1-NEXT: 20064: 3c 19 00 02 lui $25, 2 |
| 181 | 121 | # ORPH1-NEXT: 20068: 08 00 80 21 j 131204 <foo1b> |
| 182 | 122 | # ORPH1-NEXT: 2006c: 27 39 00 84 addiu $25, $25, 132 |
| 183 | 123 | # ORPH1-NEXT: 20070: 00 00 00 00 nop |
| 184 | # ORPH1-NEXT: 20074: ef ef ef ef <unknown> | |
| 185 | # ORPH1-NEXT: 20078: ef ef ef ef <unknown> | |
| 186 | # ORPH1-NEXT: 2007c: ef ef ef ef <unknown> | |
| 124 | ||
| 187 | 125 | # ORPH1: foo1a: |
| 188 | 126 | # ORPH1-NEXT: 20080: 00 00 00 00 nop |
| 127 | ||
| 189 | 128 | # ORPH1: foo1b: |
| 190 | 129 | # ORPH1-NEXT: 20084: 00 00 00 00 nop |
| 130 | ||
| 191 | 131 | # ORPH1: __LA25Thunk_foo2: |
| 192 | 132 | # ORPH1-NEXT: 20088: 3c 19 00 02 lui $25, 2 |
| 193 | 133 | # ORPH1-NEXT: 2008c: 08 00 80 28 j 131232 <foo2> |
| 194 | 134 | # ORPH1-NEXT: 20090: 27 39 00 a0 addiu $25, $25, 160 |
| 195 | 135 | # ORPH1-NEXT: 20094: 00 00 00 00 nop |
| 196 | # ORPH1-NEXT: 20098: ef ef ef ef <unknown> | |
| 197 | # ORPH1-NEXT: 2009c: ef ef ef ef <unknown> | |
| 136 | ||
| 198 | 137 | # ORPH1: foo2: |
| 199 | 138 | # ORPH1-NEXT: 200a0: 00 00 00 00 nop |
| 200 | 139 | |
| ... | ... | @@ -203,6 +142,7 @@ __start: |
| 203 | 142 | # RUN: echo "SECTIONS { .out 0x20000 : { *(.text) } }" > %t3.script |
| 204 | 143 | # RUN: ld.lld --script %t3.script %t-npic.o %t-pic.o %t-sto-pic.o -o %t3.exe |
| 205 | 144 | # RUN: llvm-objdump -d %t3.exe | FileCheck -check-prefix=ORPH2 %s |
| 145 | ||
| 206 | 146 | # ORPH2: Disassembly of section .out: |
| 207 | 147 | # ORPH2-NEXT: __start: |
| 208 | 148 | # ORPH2-NEXT: 20000: 0c 00 80 18 jal 131168 <__LA25Thunk_foo1a> |
| ... | ... | @@ -217,39 +157,43 @@ __start: |
| 217 | 157 | # ORPH2-NEXT: 20024: 00 00 00 00 nop |
| 218 | 158 | # ORPH2-NEXT: 20028: 0c 00 80 14 jal 131152 <fnpic> |
| 219 | 159 | # ORPH2-NEXT: 2002c: 00 00 00 00 nop |
| 160 | ||
| 220 | 161 | # ORPH2: __LA25Thunk_fpic: |
| 221 | 162 | # ORPH2-NEXT: 20030: 3c 19 00 02 lui $25, 2 |
| 222 | 163 | # ORPH2-NEXT: 20034: 08 00 80 10 j 131136 <fpic> |
| 223 | 164 | # ORPH2-NEXT: 20038: 27 39 00 40 addiu $25, $25, 64 |
| 224 | 165 | # ORPH2-NEXT: 2003c: 00 00 00 00 nop |
| 166 | ||
| 225 | 167 | # ORPH2: fpic: |
| 226 | 168 | # ORPH2-NEXT: 20040: 00 00 00 00 nop |
| 227 | # ORPH2-NEXT: 20044: ef ef ef ef <unknown> | |
| 228 | # ORPH2-NEXT: 20048: ef ef ef ef <unknown> | |
| 229 | # ORPH2-NEXT: 2004c: ef ef ef ef <unknown> | |
| 169 | ||
| 230 | 170 | # ORPH2: fnpic: |
| 231 | 171 | # ORPH2-NEXT: 20050: 00 00 00 00 nop |
| 232 | 172 | # ORPH2-NEXT: Disassembly of section .text: |
| 173 | ||
| 233 | 174 | # ORPH2-NEXT: __LA25Thunk_foo1a: |
| 234 | 175 | # ORPH2-NEXT: 20060: 3c 19 00 02 lui $25, 2 |
| 235 | 176 | # ORPH2-NEXT: 20064: 08 00 80 20 j 131200 <foo1a> |
| 236 | 177 | # ORPH2-NEXT: 20068: 27 39 00 80 addiu $25, $25, 128 |
| 237 | 178 | # ORPH2-NEXT: 2006c: 00 00 00 00 nop |
| 179 | ||
| 238 | 180 | # ORPH2: __LA25Thunk_foo1b: |
| 239 | 181 | # ORPH2-NEXT: 20070: 3c 19 00 02 lui $25, 2 |
| 240 | 182 | # ORPH2-NEXT: 20074: 08 00 80 21 j 131204 <foo1b> |
| 241 | 183 | # ORPH2-NEXT: 20078: 27 39 00 84 addiu $25, $25, 132 |
| 242 | 184 | # ORPH2-NEXT: 2007c: 00 00 00 00 nop |
| 185 | ||
| 243 | 186 | # ORPH2: foo1a: |
| 244 | 187 | # ORPH2-NEXT: 20080: 00 00 00 00 nop |
| 188 | ||
| 245 | 189 | # ORPH2: foo1b: |
| 246 | 190 | # ORPH2-NEXT: 20084: 00 00 00 00 nop |
| 191 | ||
| 247 | 192 | # ORPH2: __LA25Thunk_foo2: |
| 248 | 193 | # ORPH2-NEXT: 20088: 3c 19 00 02 lui $25, 2 |
| 249 | 194 | # ORPH2-NEXT: 2008c: 08 00 80 28 j 131232 <foo2> |
| 250 | 195 | # ORPH2-NEXT: 20090: 27 39 00 a0 addiu $25, $25, 160 |
| 251 | 196 | # ORPH2-NEXT: 20094: 00 00 00 00 nop |
| 252 | # ORPH2-NEXT: 20098: ef ef ef ef <unknown> | |
| 253 | # ORPH2-NEXT: 2009c: ef ef ef ef <unknown> | |
| 197 | ||
| 254 | 198 | # ORPH2: foo2: |
| 255 | 199 | # ORPH2-NEXT: 200a0: 00 00 00 00 nop |
deps/lld/test/ELF/mips-npic-call-pic.s+9-16| ... | ... | @@ -51,8 +51,6 @@ |
| 51 | 51 | # CHECK-NEXT: 2005c: 08 00 80 1c j 131184 <foo2> |
| 52 | 52 | # CHECK-NEXT: 20060: 27 39 00 70 addiu $25, $25, 112 |
| 53 | 53 | # CHECK-NEXT: 20064: 00 00 00 00 nop |
| 54 | # CHECK-NEXT: 20068: ef ef ef ef <unknown> | |
| 55 | # CHECK-NEXT: 2006c: ef ef ef ef <unknown> | |
| 56 | 54 | |
| 57 | 55 | # CHECK: foo2: |
| 58 | 56 | # CHECK-NEXT: 20070: 00 00 00 00 nop |
| ... | ... | @@ -62,15 +60,9 @@ |
| 62 | 60 | # CHECK-NEXT: 20078: 08 00 80 24 j 131216 <fpic> |
| 63 | 61 | # CHECK-NEXT: 2007c: 27 39 00 90 addiu $25, $25, 144 |
| 64 | 62 | # CHECK-NEXT: 20080: 00 00 00 00 nop |
| 65 | # CHECK-NEXT: 20084: ef ef ef ef <unknown> | |
| 66 | # CHECK-NEXT: 20088: ef ef ef ef <unknown> | |
| 67 | # CHECK-NEXT: 2008c: ef ef ef ef <unknown> | |
| 68 | 63 | |
| 69 | 64 | # CHECK: fpic: |
| 70 | 65 | # CHECK-NEXT: 20090: 00 00 00 00 nop |
| 71 | # CHECK-NEXT: 20094: ef ef ef ef <unknown> | |
| 72 | # CHECK-NEXT: 20098: ef ef ef ef <unknown> | |
| 73 | # CHECK-NEXT: 2009c: ef ef ef ef <unknown> | |
| 74 | 66 | |
| 75 | 67 | # CHECK: fnpic: |
| 76 | 68 | # CHECK-NEXT: 200a0: 00 00 00 00 nop |
| ... | ... | @@ -87,27 +79,28 @@ |
| 87 | 79 | # REVERSE-NEXT: 20004: 08 00 80 08 j 131104 <foo1a> |
| 88 | 80 | # REVERSE-NEXT: 20008: 27 39 00 20 addiu $25, $25, 32 |
| 89 | 81 | # REVERSE-NEXT: 2000c: 00 00 00 00 nop |
| 82 | ||
| 90 | 83 | # REVERSE: __LA25Thunk_foo1b: |
| 91 | 84 | # REVERSE-NEXT: 20010: 3c 19 00 02 lui $25, 2 |
| 92 | 85 | # REVERSE-NEXT: 20014: 08 00 80 09 j 131108 <foo1b> |
| 93 | 86 | # REVERSE-NEXT: 20018: 27 39 00 24 addiu $25, $25, 36 |
| 94 | 87 | # REVERSE-NEXT: 2001c: 00 00 00 00 nop |
| 88 | ||
| 95 | 89 | # REVERSE: foo1a: |
| 96 | 90 | # REVERSE-NEXT: 20020: 00 00 00 00 nop |
| 91 | ||
| 97 | 92 | # REVERSE: foo1b: |
| 98 | 93 | # REVERSE-NEXT: 20024: 00 00 00 00 nop |
| 94 | ||
| 99 | 95 | # REVERSE: __LA25Thunk_foo2: |
| 100 | 96 | # REVERSE-NEXT: 20028: 3c 19 00 02 lui $25, 2 |
| 101 | 97 | # REVERSE-NEXT: 2002c: 08 00 80 10 j 131136 <foo2> |
| 102 | 98 | # REVERSE-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64 |
| 103 | 99 | # REVERSE-NEXT: 20034: 00 00 00 00 nop |
| 104 | # REVERSE-NEXT: 20038: ef ef ef ef <unknown> | |
| 105 | # REVERSE-NEXT: 2003c: ef ef ef ef <unknown> | |
| 100 | ||
| 106 | 101 | # REVERSE: foo2: |
| 107 | 102 | # REVERSE-NEXT: 20040: 00 00 00 00 nop |
| 108 | # REVERSE-NEXT: 20044: ef ef ef ef <unknown> | |
| 109 | # REVERSE-NEXT: 20048: ef ef ef ef <unknown> | |
| 110 | # REVERSE-NEXT: 2004c: ef ef ef ef <unknown> | |
| 103 | ||
| 111 | 104 | # REVERSE: __start: |
| 112 | 105 | # REVERSE-NEXT: 20050: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a> |
| 113 | 106 | # REVERSE-NEXT: 20054: 00 00 00 00 nop |
| ... | ... | @@ -121,16 +114,16 @@ |
| 121 | 114 | # REVERSE-NEXT: 20074: 00 00 00 00 nop |
| 122 | 115 | # REVERSE-NEXT: 20078: 0c 00 80 28 jal 131232 <fnpic> |
| 123 | 116 | # REVERSE-NEXT: 2007c: 00 00 00 00 nop |
| 117 | ||
| 124 | 118 | # REVERSE: __LA25Thunk_fpic: |
| 125 | 119 | # REVERSE-NEXT: 20080: 3c 19 00 02 lui $25, 2 |
| 126 | 120 | # REVERSE-NEXT: 20084: 08 00 80 24 j 131216 <fpic> |
| 127 | 121 | # REVERSE-NEXT: 20088: 27 39 00 90 addiu $25, $25, 144 |
| 128 | 122 | # REVERSE-NEXT: 2008c: 00 00 00 00 nop |
| 123 | ||
| 129 | 124 | # REVERSE: fpic: |
| 130 | 125 | # REVERSE-NEXT: 20090: 00 00 00 00 nop |
| 131 | # REVERSE-NEXT: 20094: ef ef ef ef <unknown> | |
| 132 | # REVERSE-NEXT: 20098: ef ef ef ef <unknown> | |
| 133 | # REVERSE-NEXT: 2009c: ef ef ef ef <unknown> | |
| 126 | ||
| 134 | 127 | # REVERSE: fnpic: |
| 135 | 128 | # REVERSE-NEXT: 200a0: 00 00 00 00 nop |
| 136 | 129 |
deps/lld/test/ELF/mips-sto-plt.s+2-2| ... | ... | @@ -9,7 +9,7 @@ |
| 9 | 9 | # RUN: llvm-readobj -dt -mips-plt-got %t.exe | FileCheck %s |
| 10 | 10 | |
| 11 | 11 | # CHECK: Symbol { |
| 12 | # CHECK: Name: foo0@ | |
| 12 | # CHECK: Name: foo0 | |
| 13 | 13 | # CHECK-NEXT: Value: 0x0 |
| 14 | 14 | # CHECK-NEXT: Size: 0 |
| 15 | 15 | # CHECK-NEXT: Binding: Global |
| ... | ... | @@ -18,7 +18,7 @@ |
| 18 | 18 | # CHECK-NEXT: Section: Undefined |
| 19 | 19 | # CHECK-NEXT: } |
| 20 | 20 | # CHECK-NEXT: Symbol { |
| 21 | # CHECK-NEXT: Name: foo1@ | |
| 21 | # CHECK-NEXT: Name: foo1 | |
| 22 | 22 | # CHECK-NEXT: Value: 0x[[FOO1:[0-9A-F]+]] |
| 23 | 23 | # CHECK-NEXT: Size: 0 |
| 24 | 24 | # CHECK-NEXT: Binding: Global |
deps/lld/test/ELF/mips-tls-64.s+3-3| ... | ... | @@ -28,9 +28,9 @@ |
| 28 | 28 | # DIS-NEXT: 30040 00000000 00000001 00000000 00000000 |
| 29 | 29 | # DIS-NEXT: 30050 00000000 00000001 ffffffff ffff8004 |
| 30 | 30 | |
| 31 | # DIS: 0000000000000000 l .tdata 00000000 loc | |
| 32 | # DIS: 0000000000000004 g .tdata 00000000 bar | |
| 33 | # DIS: 0000000000000000 g *UND* 00000000 foo | |
| 31 | # DIS: 0000000000000000 l O .tdata 00000000 loc | |
| 32 | # DIS: 0000000000000004 g O .tdata 00000000 bar | |
| 33 | # DIS: 0000000000000000 g O *UND* 00000000 foo | |
| 34 | 34 | |
| 35 | 35 | # CHECK: Relocations [ |
| 36 | 36 | # CHECK-NEXT: Section (7) .rel.dyn { |
deps/lld/test/ELF/mips-tls-hilo.s+1-1| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | # DIS-NEXT: 2000c: 24 62 90 00 addiu $2, $3, -28672 |
| 21 | 21 | # %lo(loc0 - .tdata - 0x7000) --^ |
| 22 | 22 | |
| 23 | # DIS: 00000000 l .tdata 00000000 loc0 | |
| 23 | # DIS: 00000000 l O .tdata 00000000 loc0 | |
| 24 | 24 | |
| 25 | 25 | # CHECK: Relocations [ |
| 26 | 26 | # CHECK-NEXT: ] |
deps/lld/test/ELF/mips-tls-static-64.s+2-2| ... | ... | @@ -11,8 +11,8 @@ |
| 11 | 11 | # CHECK-NEXT: 30010 ffff9004 |
| 12 | 12 | # |
| 13 | 13 | # CHECK: SYMBOL TABLE: |
| 14 | # CHECK: 0000000000020004 .text 00000000 __tls_get_addr | |
| 15 | # CHECK: 0000000000000000 g .tdata 00000000 tls1 | |
| 14 | # CHECK: 0000000000020004 .text 00000000 __tls_get_addr | |
| 15 | # CHECK: 0000000000000000 g O .tdata 00000000 tls1 | |
| 16 | 16 | |
| 17 | 17 | .text |
| 18 | 18 | .global __start |
deps/lld/test/ELF/mips-tls-static.s+2-2| ... | ... | @@ -13,8 +13,8 @@ |
| 13 | 13 | # CHECK-NEXT: 30020 ffff8000 00000001 00000000 |
| 14 | 14 | # |
| 15 | 15 | # CHECK: SYMBOL TABLE: |
| 16 | # CHECK: 0002000c .text 00000000 __tls_get_addr | |
| 17 | # CHECK: 00000000 g .tdata 00000000 tls1 | |
| 16 | # CHECK: 0002000c .text 00000000 __tls_get_addr | |
| 17 | # CHECK: 00000000 g O .tdata 00000000 tls1 | |
| 18 | 18 | |
| 19 | 19 | .text |
| 20 | 20 | .global __start |
deps/lld/test/ELF/mips-tls.s+3-3| ... | ... | @@ -26,9 +26,9 @@ |
| 26 | 26 | # DIS-NEXT: 30020 00000000 00000000 00000001 00000000 |
| 27 | 27 | # DIS-NEXT: 30030 00000001 ffff8004 |
| 28 | 28 | |
| 29 | # DIS: 00000000 l .tdata 00000000 loc | |
| 30 | # DIS: 00000004 g .tdata 00000000 bar | |
| 31 | # DIS: 00000000 g *UND* 00000000 foo | |
| 29 | # DIS: 00000000 l O .tdata 00000000 loc | |
| 30 | # DIS: 00000004 g O .tdata 00000000 bar | |
| 31 | # DIS: 00000000 g O *UND* 00000000 foo | |
| 32 | 32 | |
| 33 | 33 | # CHECK: Relocations [ |
| 34 | 34 | # CHECK-NEXT: Section (7) .rel.dyn { |
deps/lld/test/ELF/mips-traps.s created+22| ... | ... | @@ -0,0 +1,22 @@ |
| 1 | # Check trap instruction encoding. | |
| 2 | ||
| 3 | # REQUIRES: mips | |
| 4 | ||
| 5 | # RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mcpu=mips32r6 -o %t.o %s | |
| 6 | # RUN: ld.lld -r -o %t %t.o %t.o | |
| 7 | # RUN: llvm-objdump -d -r %t | FileCheck --check-prefix=EB %s | |
| 8 | ||
| 9 | # RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux -mcpu=mips32r6 -o %t.o %s | |
| 10 | # RUN: ld.lld -r -o %t %t.o %t.o | |
| 11 | # RUN: llvm-objdump -d -r %t | FileCheck --check-prefix=EL %s | |
| 12 | ||
| 13 | # EB: 8: 04 17 00 01 sigrie 1 | |
| 14 | # EL: 8: 01 00 17 04 sigrie 1 | |
| 15 | ||
| 16 | .text | |
| 17 | lw $t9, %got(.data)($gp) | |
| 18 | addiu $a0, $t9, %lo(.data) | |
| 19 | ||
| 20 | .data | |
| 21 | data: | |
| 22 | .word 0 |
deps/lld/test/ELF/msp430.s created+43| ... | ... | @@ -0,0 +1,43 @@ |
| 1 | ; REQUIRES: msp430 | |
| 2 | ; RUN: llvm-mc -filetype=obj -triple=msp430-elf -o %t1.o %s | |
| 3 | ; RUN: echo -e '.global _start\n _start: nop' | llvm-mc -filetype=obj -triple=msp430-elf -o %t2.o - | |
| 4 | ; RUN: ld.lld -o %t.exe --Tdata=0x2000 --Ttext=0x8000 --defsym=_byte=0x21 %t2.o %t1.o | |
| 5 | ; RUN: llvm-objdump -s -d %t.exe | FileCheck %s | |
| 6 | ||
| 7 | ;; Check handling of basic msp430 relocation types. | |
| 8 | ||
| 9 | .text | |
| 10 | .global foo | |
| 11 | foo: | |
| 12 | ;; R_MSP430_10_PCREL | |
| 13 | jmp _start | |
| 14 | ||
| 15 | ; CHECK: Disassembly of section .text: | |
| 16 | ; CHECK-NEXT: _start: | |
| 17 | ; CHECK-NEXT: 8000: {{.*}} nop | |
| 18 | ; CHECK: foo: | |
| 19 | ; CHECK-NEXT: 8004: {{.*}} jmp $-4 | |
| 20 | ||
| 21 | ;; R_MSP430_16_BYTE | |
| 22 | call #_start | |
| 23 | ||
| 24 | ; CHECK: call #32768 | |
| 25 | ||
| 26 | ;; R_MSP430_16_PCREL_BYTE | |
| 27 | mov #-1, _start | |
| 28 | ||
| 29 | ; CHECK: 800a: {{.*}} mov #-1, -12 | |
| 30 | ||
| 31 | .data | |
| 32 | ;; R_MSP430_8 | |
| 33 | .byte _byte | |
| 34 | ;; R_MSP430_16 | |
| 35 | .word _start | |
| 36 | ;; R_MSP430_32 | |
| 37 | .long _start | |
| 38 | ||
| 39 | ; CHECK: Contents of section .data: | |
| 40 | ; CHECK-NEXT: 2000 21008000 800000 | |
| 41 | ||
| 42 | ; RUN: od -x %t.exe | FileCheck -check-prefix=TRAP %s | |
| 43 | ; TRAP: 4343 4343 4343 4343 4343 4343 4343 4343 |
deps/lld/test/ELF/no-discard-this_module.s created+41| ... | ... | @@ -0,0 +1,41 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -save-temp-labels %s -o %t | |
| 3 | // RUN: ld.lld %t -o %t2 | |
| 4 | // RUN: llvm-readobj -s -sd -t %t2 | FileCheck %s | |
| 5 | ||
| 6 | .global _start | |
| 7 | _start: | |
| 8 | ||
| 9 | // This section and symbol is used by Linux kernel modules. Ensure it's not | |
| 10 | // accidentally discarded. | |
| 11 | .section .gnu.linkonce.this_module: | |
| 12 | __this_module: | |
| 13 | .byte 0x00 | |
| 14 | ||
| 15 | // CHECK: Section { | |
| 16 | // CHECK: Index: | |
| 17 | // CHECK: Name: .gnu.linkonce.this_module | |
| 18 | // CHECK-NEXT: Type: SHT_PROGBITS | |
| 19 | // CHECK-NEXT: Flags [ | |
| 20 | // CHECK-NEXT: ] | |
| 21 | // CHECK-NEXT: Address: | |
| 22 | // CHECK-NEXT: Offset: | |
| 23 | // CHECK-NEXT: Size: | |
| 24 | // CHECK-NEXT: Link: | |
| 25 | // CHECK-NEXT: Info: | |
| 26 | // CHECK-NEXT: AddressAlignment: | |
| 27 | // CHECK-NEXT: EntrySize: | |
| 28 | // CHECK-NEXT: SectionData ( | |
| 29 | // CHECK-NEXT: 0000: 00 |.| | |
| 30 | // CHECK-NEXT: ) | |
| 31 | // CHECK-NEXT: } | |
| 32 | ||
| 33 | // CHECK: Symbol { | |
| 34 | // CHECK: Name: __this_module | |
| 35 | // CHECK-NEXT: Value: | |
| 36 | // CHECK-NEXT: Size: | |
| 37 | // CHECK-NEXT: Binding: Local | |
| 38 | // CHECK-NEXT: Type: None | |
| 39 | // CHECK-NEXT: Other: | |
| 40 | // CHECK-NEXT: Section: .gnu.linkonce.this_module: | |
| 41 | // CHECK-NEXT: } |
deps/lld/test/ELF/no-obj.s+1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | // REQUIRES: x86 |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | // RUN: rm -f %t.a | |
| 3 | 4 | // RUN: llvm-ar rcs %t.a %t.o |
| 4 | 5 | // RUN: not ld.lld -o /dev/null -u _start %t.a 2>&1 | FileCheck %s |
| 5 | 6 |
deps/lld/test/ELF/note-first-page.s created+12| ... | ... | @@ -0,0 +1,12 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 3 | # RUN: ld.lld %t.o --build-id=md5 --shared -o %t.so | |
| 4 | # RUN: llvm-readelf -S %t.so | FileCheck %s | |
| 5 | ||
| 6 | # Check .note.gnu.build-id is placed before other potentially large sections | |
| 7 | # (.dynsym .dynstr (and .rela.dyn in PIE)). This ensures the note information | |
| 8 | # available in core files because various core dumpers ensure the first page is | |
| 9 | # available. | |
| 10 | ||
| 11 | # CHECK: [ 1] .note.gnu.build-id | |
| 12 | # CHECK: [ 2] .dynsym |
deps/lld/test/ELF/oformat-binary.s+1| ... | ... | @@ -20,6 +20,7 @@ |
| 20 | 20 | # ERR: unknown --oformat value: foo |
| 21 | 21 | |
| 22 | 22 | # RUN: ld.lld -o /dev/null %t --oformat elf |
| 23 | # RUN: ld.lld -o /dev/null %t --oformat elf-foo | |
| 23 | 24 | |
| 24 | 25 | .text |
| 25 | 26 | .align 4 |
deps/lld/test/ELF/pack-dyn-relocs-loop.s created+66| ... | ... | @@ -0,0 +1,66 @@ |
| 1 | // REQUIRES: arm, aarch64 | |
| 2 | ||
| 3 | // RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-android %s -o %t.o | |
| 4 | // RUN: ld.lld -shared %t.o -o %t.so --pack-dyn-relocs=android | |
| 5 | // RUN: llvm-readobj -s %t.so | FileCheck %s | |
| 6 | ||
| 7 | // This test is making sure the Android packed relocation support doesn't | |
| 8 | // cause an infinite loop due to the size of the section oscillating | |
| 9 | // (because the size of the section impacts the layout of the following | |
| 10 | // sections). | |
| 11 | ||
| 12 | // This test is very sensitive to the exact section sizes and offsets, | |
| 13 | // so check that they don't change. | |
| 14 | // CHECK: Name: .rela.dyn (33) | |
| 15 | // CHECK-NEXT: Type: SHT_ANDROID_RELA (0x60000002) | |
| 16 | // CHECK-NEXT: Flags [ (0x2) | |
| 17 | // CHECK-NEXT: SHF_ALLOC (0x2) | |
| 18 | // CHECK-NEXT: ] | |
| 19 | // CHECK-NEXT: Address: 0x210 | |
| 20 | // CHECK-NEXT: Offset: 0x210 | |
| 21 | // CHECK-NEXT: Size: 21 | |
| 22 | ||
| 23 | // CHECK: Name: x (43) | |
| 24 | // CHECK-NEXT: Type: SHT_PROGBITS (0x1) | |
| 25 | // CHECK-NEXT: Flags [ (0x2) | |
| 26 | // CHECK-NEXT: SHF_ALLOC (0x2) | |
| 27 | // CHECK-NEXT: ] | |
| 28 | // CHECK-NEXT: Address: 0x225 | |
| 29 | // CHECK-NEXT: Offset: 0x225 | |
| 30 | // CHECK-NEXT: Size: 64980 | |
| 31 | ||
| 32 | // CHECK: Name: barr (45) | |
| 33 | // CHECK-NEXT: Type: SHT_PROGBITS (0x1) | |
| 34 | // CHECK-NEXT: Flags [ (0x2) | |
| 35 | // CHECK-NEXT: SHF_ALLOC (0x2) | |
| 36 | // CHECK-NEXT: ] | |
| 37 | // CHECK-NEXT: Address: 0xFFFA | |
| 38 | // CHECK-NEXT: Offset: 0xFFFA | |
| 39 | // CHECK-NEXT: Size: 0 | |
| 40 | ||
| 41 | // CHECK: Name: foo (62) | |
| 42 | // CHECK-NEXT: Type: SHT_PROGBITS (0x1) | |
| 43 | // CHECK-NEXT: Flags [ (0x3) | |
| 44 | // CHECK-NEXT: SHF_ALLOC (0x2) | |
| 45 | // CHECK-NEXT: SHF_WRITE (0x1) | |
| 46 | // CHECK-NEXT: ] | |
| 47 | // CHECK-NEXT: Address: 0x10004 | |
| 48 | // CHECK-NEXT: Offset: 0x10004 | |
| 49 | // CHECK-NEXT: Size: 12 | |
| 50 | ||
| 51 | ||
| 52 | .data | |
| 53 | .long 0 | |
| 54 | ||
| 55 | .section foo,"aw" | |
| 56 | foof: | |
| 57 | .long foof | |
| 58 | .long bar-53 | |
| 59 | .long bar | |
| 60 | ||
| 61 | .section x,"a" | |
| 62 | .zero 64980 | |
| 63 | ||
| 64 | .section barr,"a" | |
| 65 | .p2align 1 | |
| 66 | bar: |
deps/lld/test/ELF/pack-dyn-relocs-tls-aarch64.s created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | // REQUIRES: aarch64 | |
| 2 | ||
| 3 | // RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.o | |
| 4 | // RUN: ld.lld -shared --pack-dyn-relocs=android %t.o -o %t.so | |
| 5 | // RUN: llvm-readobj -relocations %t.so | FileCheck %s | |
| 6 | ||
| 7 | // Bug 37841: Symbol::getVA must work on TLS symbols during the layout loop in | |
| 8 | // finalizeSections. | |
| 9 | ||
| 10 | .global foo | |
| 11 | foo: | |
| 12 | adrp x0, :tlsdesc:tlsvar1 | |
| 13 | ldr x1, [x0, :tlsdesc_lo12:tlsvar1] | |
| 14 | add x0, x0, :tlsdesc_lo12:tlsvar1 | |
| 15 | .tlsdesccall tlsvar1 | |
| 16 | ||
| 17 | // Also test an atypical IE access from a shared object to a local TLS symbol. | |
| 18 | ||
| 19 | .global bar | |
| 20 | bar: | |
| 21 | adrp x0, :gottprel:tlsvar2 | |
| 22 | ldr x0, [x0, #:gottprel_lo12:tlsvar2] | |
| 23 | ||
| 24 | .section .tdata,"awT",@progbits | |
| 25 | .space 0x1234 | |
| 26 | tlsvar1: | |
| 27 | .word 42 | |
| 28 | tlsvar2: | |
| 29 | .word 17 | |
| 30 | ||
| 31 | // CHECK: Section ({{.+}}) .rela.dyn { | |
| 32 | // CHECK-NEXT: R_AARCH64_TLSDESC - 0x1234 | |
| 33 | // CHECK-NEXT: R_AARCH64_TLS_TPREL64 - 0x1238 | |
| 34 | // CHECK-NEXT: } |
deps/lld/test/ELF/pack-dyn-relocs-tls-x86-64.s created+23| ... | ... | @@ -0,0 +1,23 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | ||
| 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 4 | // RUN: ld.lld -shared --pack-dyn-relocs=android %t.o -o %t.so | |
| 5 | // RUN: llvm-readobj -relocations %t.so | FileCheck %s | |
| 6 | ||
| 7 | // Bug 37841: Symbol::getVA must work on TLS symbols during the layout loop in | |
| 8 | // finalizeSections. This test uses an atypical IE access in a shared object to | |
| 9 | // access a local TLS symbol, because a more typical access would avoid the | |
| 10 | // bug. | |
| 11 | ||
| 12 | .globl foo | |
| 13 | foo: | |
| 14 | movq tlsvar@GOTTPOFF(%rip), %rcx | |
| 15 | ||
| 16 | .section .tdata,"awT",@progbits | |
| 17 | .space 0x1234 | |
| 18 | tlsvar: | |
| 19 | .word 42 | |
| 20 | ||
| 21 | // CHECK: Section ({{.+}}) .rela.dyn { | |
| 22 | // CHECK-NEXT: R_X86_64_TPOFF64 - 0x1234 | |
| 23 | // CHECK-NEXT: } |
deps/lld/test/ELF/plt-aarch64.s+46-36| ... | ... | @@ -85,6 +85,8 @@ |
| 85 | 85 | |
| 86 | 86 | // foo@plt |
| 87 | 87 | // Page(0x30018) - Page(0x10030) = 0x20000 - 0x10000 = 0x10000 = 65536 |
| 88 | // DISASMDSO-EMPTY: | |
| 89 | // DISASMDSO-NEXT: foo@plt: | |
| 88 | 90 | // DISASMDSO-NEXT: 10030:	90 00 00 90 	adrp	x16, #65536 |
| 89 | 91 | // 0x3018 & 0xFFF = 0x18 = 24 |
| 90 | 92 | // DISASMDSO-NEXT: 10034:	11 0e 40 f9 	ldr	x17, [x16, #24] |
| ... | ... | @@ -93,6 +95,8 @@ |
| 93 | 95 | |
| 94 | 96 | // bar@plt |
| 95 | 97 | // Page(0x30020) - Page(0x10040) = 0x20000 - 0x10000 = 0x10000 = 65536 |
| 98 | // DISASMDSO-EMPTY: | |
| 99 | // DISASMDSO-NEXT: bar@plt: | |
| 96 | 100 | // DISASMDSO-NEXT: 10040:	90 00 00 90 	adrp	x16, #65536 |
| 97 | 101 | // 0x3020 & 0xFFF = 0x20 = 32 |
| 98 | 102 | // DISASMDSO-NEXT: 10044:	11 12 40 f9 	ldr	x17, [x16, #32] |
| ... | ... | @@ -101,6 +105,8 @@ |
| 101 | 105 | |
| 102 | 106 | // weak@plt |
| 103 | 107 | // Page(0x30028) - Page(0x10050) = 0x20000 - 0x10000 = 0x10000 = 65536 |
| 108 | // DISASMDSO-EMPTY: | |
| 109 | // DISASMDSO-NEXT: weak@plt: | |
| 104 | 110 | // DISASMDSO-NEXT: 10050:	90 00 00 90 	adrp	x16, #65536 |
| 105 | 111 | // 0x3028 & 0xFFF = 0x28 = 40 |
| 106 | 112 | // DISASMDSO-NEXT: 10054:	11 16 40 f9 	ldr	x17, [x16, #40] |
| ... | ... | @@ -113,7 +119,7 @@ |
| 113 | 119 | // CHECKEXE-NEXT: SHF_ALLOC |
| 114 | 120 | // CHECKEXE-NEXT: SHF_EXECINSTR |
| 115 | 121 | // CHECKEXE-NEXT: ] |
| 116 | // CHECKEXE-NEXT: Address: 0x20010 | |
| 122 | // CHECKEXE-NEXT: Address: 0x210010 | |
| 117 | 123 | // CHECKEXE-NEXT: Offset: |
| 118 | 124 | // CHECKEXE-NEXT: Size: 64 |
| 119 | 125 | // CHECKEXE-NEXT: Link: |
| ... | ... | @@ -126,7 +132,7 @@ |
| 126 | 132 | // CHECKEXE-NEXT: SHF_ALLOC |
| 127 | 133 | // CHECKEXE-NEXT: SHF_WRITE |
| 128 | 134 | // CHECKEXE-NEXT: ] |
| 129 | // CHECKEXE-NEXT: Address: 0x30000 | |
| 135 | // CHECKEXE-NEXT: Address: 0x220000 | |
| 130 | 136 | // CHECKEXE-NEXT: Offset: |
| 131 | 137 | // CHECKEXE-NEXT: Size: 40 |
| 132 | 138 | // CHECKEXE-NEXT: Link: |
| ... | ... | @@ -136,59 +142,63 @@ |
| 136 | 142 | // CHECKEXE: Relocations [ |
| 137 | 143 | // CHECKEXE-NEXT: Section ({{.*}}) .rela.plt { |
| 138 | 144 | |
| 139 | // &(.got.plt[3]) = 0x30000 + 3 * 8 = 0x30018 | |
| 140 | // CHECKEXE-NEXT: 0x30018 R_AARCH64_JUMP_SLOT bar 0x0 | |
| 145 | // &(.got.plt[3]) = 0x220000 + 3 * 8 = 0x220018 | |
| 146 | // CHECKEXE-NEXT: 0x220018 R_AARCH64_JUMP_SLOT bar 0x0 | |
| 141 | 147 | |
| 142 | // &(.got.plt[4]) = 0x30000 + 4 * 8 = 0x30020 | |
| 143 | // CHECKEXE-NEXT: 0x30020 R_AARCH64_JUMP_SLOT weak 0x0 | |
| 148 | // &(.got.plt[4]) = 0x220000 + 4 * 8 = 0x220020 | |
| 149 | // CHECKEXE-NEXT: 0x220020 R_AARCH64_JUMP_SLOT weak 0x0 | |
| 144 | 150 | // CHECKEXE-NEXT: } |
| 145 | 151 | // CHECKEXE-NEXT: ] |
| 146 | 152 | |
| 147 | 153 | // DUMPEXE: Contents of section .got.plt: |
| 148 | 154 | // .got.plt[0..2] = 0 (reserved) |
| 149 | 155 | // .got.plt[3..4] = .plt = 0x40010 |
| 150 | // DUMPEXE-NEXT: 30000 00000000 00000000 00000000 00000000 ................ | |
| 151 | // DUMPEXE-NEXT: 30010 00000000 00000000 10000200 00000000 ................ | |
| 152 | // DUMPEXE-NEXT: 30020 10000200 00000000 ........ | |
| 156 | // DUMPEXE-NEXT: 220000 00000000 00000000 00000000 00000000 | |
| 157 | // DUMPEXE-NEXT: 220010 00000000 00000000 10002100 00000000 | |
| 158 | // DUMPEXE-NEXT: 220020 10002100 00000000 | |
| 153 | 159 | |
| 154 | 160 | // DISASMEXE: _start: |
| 155 | // 0x2000c - 0x20000 = 0xc = 12 | |
| 156 | // DISASMEXE-NEXT: 20000:	03 00 00 14 	b	#12 | |
| 157 | // 0x20030 - 0x20004 = 0x2c = 44 | |
| 158 | // DISASMEXE-NEXT: 20004:	0b 00 00 14 	b	#44 | |
| 159 | // 0x20040 - 0x20008 = 0x38 = 56 | |
| 160 | // DISASMEXE-NEXT: 20008:	0e 00 00 14 	b	#56 | |
| 161 | // 0x21000c - 0x210000 = 0xc = 12 | |
| 162 | // DISASMEXE-NEXT: 210000:	03 00 00 14 	b	#12 | |
| 163 | // 0x210030 - 0x210004 = 0x2c = 44 | |
| 164 | // DISASMEXE-NEXT: 210004:	0b 00 00 14 	b	#44 | |
| 165 | // 0x210040 - 0x210008 = 0x38 = 56 | |
| 166 | // DISASMEXE-NEXT: 210008:	0e 00 00 14 	b	#56 | |
| 161 | 167 | |
| 162 | 168 | // DISASMEXE: foo: |
| 163 | // DISASMEXE-NEXT: 2000c:	1f 20 03 d5 	nop | |
| 169 | // DISASMEXE-NEXT: 21000c:	1f 20 03 d5 	nop | |
| 164 | 170 | |
| 165 | 171 | // DISASMEXE: Disassembly of section .plt: |
| 166 | 172 | // DISASMEXE-NEXT: .plt: |
| 167 | // DISASMEXE-NEXT: 20010:	f0 7b bf a9 	stp	x16, x30, [sp, #-16]! | |
| 168 | // &(.got.plt[2]) = 0x300B0 + 2 * 8 = 0x300C0 | |
| 169 | // Page(0x30010) - Page(0x20014) = 0x30000 - 0x20000 = 0x10000 = 65536 | |
| 170 | // DISASMEXE-NEXT: 20014:	90 00 00 90 	adrp	x16, #65536 | |
| 173 | // DISASMEXE-NEXT: 210010:	f0 7b bf a9 	stp	x16, x30, [sp, #-16]! | |
| 174 | // &(.got.plt[2]) = 0x2200B0 + 2 * 8 = 0x2200C0 | |
| 175 | // Page(0x220010) - Page(0x210014) = 0x220000 - 0x210000 = 0x10000 = 65536 | |
| 176 | // DISASMEXE-NEXT: 210014:	90 00 00 90 	adrp	x16, #65536 | |
| 171 | 177 | // 0x120c0 & 0xFFF = 0xC0 = 192 |
| 172 | // DISASMEXE-NEXT: 20018:	11 0a 40 f9 	ldr	x17, [x16, #16] | |
| 173 | // DISASMEXE-NEXT: 2001c:	10 42 00 91 	add	x16, x16, #16 | |
| 174 | // DISASMEXE-NEXT: 20020:	20 02 1f d6 	br	x17 | |
| 175 | // DISASMEXE-NEXT: 20024:	1f 20 03 d5 	nop | |
| 176 | // DISASMEXE-NEXT: 20028:	1f 20 03 d5 	nop | |
| 177 | // DISASMEXE-NEXT: 2002c:	1f 20 03 d5 	nop | |
| 178 | // DISASMEXE-NEXT: 210018:	11 0a 40 f9 	ldr	x17, [x16, #16] | |
| 179 | // DISASMEXE-NEXT: 21001c:	10 42 00 91 	add	x16, x16, #16 | |
| 180 | // DISASMEXE-NEXT: 210020:	20 02 1f d6 	br	x17 | |
| 181 | // DISASMEXE-NEXT: 210024:	1f 20 03 d5 	nop | |
| 182 | // DISASMEXE-NEXT: 210028:	1f 20 03 d5 	nop | |
| 183 | // DISASMEXE-NEXT: 21002c:	1f 20 03 d5 	nop | |
| 178 | 184 | |
| 179 | 185 | // bar@plt |
| 180 | // Page(0x40018) - Page(0x20030) = 0x30000 - 0x20000 = 0x10000 = 65536 | |
| 181 | // DISASMEXE-NEXT: 20030:	90 00 00 90 	adrp	x16, #65536 | |
| 182 | // DISASMEXE-NEXT: 20034:	11 0e 40 f9 	ldr	x17, [x16, #24] | |
| 183 | // DISASMEXE-NEXT: 20038:	10 62 00 91 	add	x16, x16, #24 | |
| 184 | // DISASMEXE-NEXT: 2003c:	20 02 1f d6 	br	x17 | |
| 186 | // Page(0x40018) - Page(0x210030) = 0x220000 - 0x210000 = 0x10000 = 65536 | |
| 187 | // DISASMEXE-EMPTY: | |
| 188 | // DISASMEXE-NEXT: bar@plt: | |
| 189 | // DISASMEXE-NEXT: 210030:	90 00 00 90 	adrp	x16, #65536 | |
| 190 | // DISASMEXE-NEXT: 210034:	11 0e 40 f9 	ldr	x17, [x16, #24] | |
| 191 | // DISASMEXE-NEXT: 210038:	10 62 00 91 	add	x16, x16, #24 | |
| 192 | // DISASMEXE-NEXT: 21003c:	20 02 1f d6 	br	x17 | |
| 185 | 193 | |
| 186 | 194 | // weak@plt |
| 187 | // Page(0x40020) - Page(0x20040) = 0x30000 - 0x20000 = 0x10000 = 65536 | |
| 188 | // DISASMEXE-NEXT: 20040:	90 00 00 90 	adrp	x16, #65536 | |
| 189 | // DISASMEXE-NEXT: 20044:	11 12 40 f9 	ldr	x17, [x16, #32] | |
| 190 | // DISASMEXE-NEXT: 20048:	10 82 00 91 	add	x16, x16, #32 | |
| 191 | // DISASMEXE-NEXT: 2004c:	20 02 1f d6 	br	x17 | |
| 195 | // Page(0x40020) - Page(0x210040) = 0x220000 - 0x210000 = 0x10000 = 65536 | |
| 196 | // DISASMEXE-EMPTY: | |
| 197 | // DISASMEXE-NEXT: weak@plt: | |
| 198 | // DISASMEXE-NEXT: 210040:	90 00 00 90 	adrp	x16, #65536 | |
| 199 | // DISASMEXE-NEXT: 210044:	11 12 40 f9 	ldr	x17, [x16, #32] | |
| 200 | // DISASMEXE-NEXT: 210048:	10 82 00 91 	add	x16, x16, #32 | |
| 201 | // DISASMEXE-NEXT: 21004c:	20 02 1f d6 	br	x17 | |
| 192 | 202 | |
| 193 | 203 | .global _start,foo,bar |
| 194 | 204 | .weak weak |
deps/lld/test/ELF/plt-i686.s+36-32| ... | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | // CHECK-NEXT: SHF_ALLOC |
| 18 | 18 | // CHECK-NEXT: SHF_EXECINSTR |
| 19 | 19 | // CHECK-NEXT: ] |
| 20 | // CHECK-NEXT: Address: 0x11020 | |
| 20 | // CHECK-NEXT: Address: 0x401020 | |
| 21 | 21 | // CHECK-NEXT: Offset: |
| 22 | 22 | // CHECK-NEXT: Size: 48 |
| 23 | 23 | // CHECK-NEXT: Link: 0 |
| ... | ... | @@ -30,7 +30,7 @@ |
| 30 | 30 | // CHECK-NEXT: SHF_ALLOC |
| 31 | 31 | // CHECK-NEXT: SHF_WRITE |
| 32 | 32 | // CHECK-NEXT: ] |
| 33 | // CHECK-NEXT: Address: 0x12000 | |
| 33 | // CHECK-NEXT: Address: 0x402000 | |
| 34 | 34 | // CHECK-NEXT: Offset: 0x2000 |
| 35 | 35 | // CHECK-NEXT: Size: 20 |
| 36 | 36 | // CHECK-NEXT: Link: 0 |
| ... | ... | @@ -42,8 +42,8 @@ |
| 42 | 42 | // 0x12000 + got.plt.reserved(12) + 4 = 0x12010 |
| 43 | 43 | // CHECK: Relocations [ |
| 44 | 44 | // CHECK-NEXT: Section ({{.*}}) .rel.plt { |
| 45 | // CHECK-NEXT: 0x1200C R_386_JUMP_SLOT bar 0x0 | |
| 46 | // CHECK-NEXT: 0x12010 R_386_JUMP_SLOT zed 0x0 | |
| 45 | // CHECK-NEXT: 0x40200C R_386_JUMP_SLOT bar 0x0 | |
| 46 | // CHECK-NEXT: 0x402010 R_386_JUMP_SLOT zed 0x0 | |
| 47 | 47 | // CHECK-NEXT: } |
| 48 | 48 | // CHECK-NEXT: ] |
| 49 | 49 | |
| ... | ... | @@ -51,40 +51,44 @@ |
| 51 | 51 | // values: |
| 52 | 52 | |
| 53 | 53 | // 16 is the size of PLT[0] |
| 54 | // (0x11010 + 16) - (0x11000 + 1) - 4 = 27 | |
| 55 | // (0x11010 + 16) - (0x11005 + 1) - 4 = 22 | |
| 56 | // (0x11020 + 16) - (0x1100a + 1) - 4 = 33 | |
| 54 | // (0x401010 + 16) - (0x401000 + 1) - 4 = 27 | |
| 55 | // (0x401010 + 16) - (0x401005 + 1) - 4 = 22 | |
| 56 | // (0x401020 + 16) - (0x40100a + 1) - 4 = 33 | |
| 57 | 57 | |
| 58 | 58 | // DISASM: local: |
| 59 | // DISASM-NEXT: 11000: {{.*}} | |
| 60 | // DISASM-NEXT: 11002: {{.*}} | |
| 59 | // DISASM-NEXT: 401000: {{.*}} | |
| 60 | // DISASM-NEXT: 401002: {{.*}} | |
| 61 | 61 | // DISASM: _start: |
| 62 | // 0x11013 + 5 - 24 = 0x11000 | |
| 63 | // DISASM-NEXT: 11004: e9 27 00 00 00 jmp 39 | |
| 64 | // DISASM-NEXT: 11009: e9 22 00 00 00 jmp 34 | |
| 65 | // DISASM-NEXT: 1100e: e9 2d 00 00 00 jmp 45 | |
| 66 | // DISASM-NEXT: 11013: e9 e8 ff ff ff jmp -24 | |
| 62 | // 0x401013 + 5 - 24 = 0x401000 | |
| 63 | // DISASM-NEXT: 401004: e9 27 00 00 00 jmp 39 | |
| 64 | // DISASM-NEXT: 401009: e9 22 00 00 00 jmp 34 | |
| 65 | // DISASM-NEXT: 40100e: e9 2d 00 00 00 jmp 45 | |
| 66 | // DISASM-NEXT: 401013: e9 e8 ff ff ff jmp -24 | |
| 67 | 67 | |
| 68 | // 0x11010 - 0x1102b - 5 = -32 | |
| 69 | // 0x11010 - 0x1103b - 5 = -48 | |
| 70 | // 77828 = 0x13004 = .got.plt (0x13000) + 4 | |
| 71 | // 77832 = 0x13008 = .got.plt (0x13000) + 8 | |
| 72 | // 77836 = 0x1300C = .got.plt (0x13000) + got.plt.reserved(12) | |
| 73 | // 77840 = 0x13010 = .got.plt (0x13000) + got.plt.reserved(12) + 4 | |
| 68 | // 0x401010 - 0x40102b - 5 = -32 | |
| 69 | // 0x401010 - 0x40103b - 5 = -48 | |
| 70 | // 4202500 = 0x402004 = .got.plt (0x402000) + 4 | |
| 71 | // 4202504 = 0x402008 = .got.plt (0x402000) + 8 | |
| 72 | // 4202508 = 0x40200C = .got.plt (0x402000) + got.plt.reserved(12) | |
| 73 | // 4202512 = 0x402010 = .got.plt (0x402000) + got.plt.reserved(12) + 4 | |
| 74 | 74 | // DISASM: Disassembly of section .plt: |
| 75 | 75 | // DISASM-NEXT: .plt: |
| 76 | // DISASM-NEXT: 11020: ff 35 04 20 01 00 pushl 73732 | |
| 77 | // DISASM-NEXT: 11026: ff 25 08 20 01 00 jmpl *73736 | |
| 78 | // DISASM-NEXT: 1102c: 90 nop | |
| 79 | // DISASM-NEXT: 1102d: 90 nop | |
| 80 | // DISASM-NEXT: 1102e: 90 nop | |
| 81 | // DISASM-NEXT: 1102f: 90 nop | |
| 82 | // DISASM-NEXT: 11030: ff 25 0c 20 01 00 jmpl *73740 | |
| 83 | // DISASM-NEXT: 11036: 68 00 00 00 00 pushl $0 | |
| 84 | // DISASM-NEXT: 1103b: e9 e0 ff ff ff jmp -32 <.plt> | |
| 85 | // DISASM-NEXT: 11040: ff 25 10 20 01 00 jmpl *73744 | |
| 86 | // DISASM-NEXT: 11046: 68 08 00 00 00 pushl $8 | |
| 87 | // DISASM-NEXT: 1104b: e9 d0 ff ff ff jmp -48 <.plt> | |
| 76 | // DISASM-NEXT: 401020: ff 35 04 20 40 00 pushl 4202500 | |
| 77 | // DISASM-NEXT: 401026: ff 25 08 20 40 00 jmpl *4202504 | |
| 78 | // DISASM-NEXT: 40102c: 90 nop | |
| 79 | // DISASM-NEXT: 40102d: 90 nop | |
| 80 | // DISASM-NEXT: 40102e: 90 nop | |
| 81 | // DISASM-NEXT: 40102f: 90 nop | |
| 82 | // DISASM-EMPTY: | |
| 83 | // DISASM-NEXT: bar@plt: | |
| 84 | // DISASM-NEXT: 401030: ff 25 0c 20 40 00 jmpl *4202508 | |
| 85 | // DISASM-NEXT: 401036: 68 00 00 00 00 pushl $0 | |
| 86 | // DISASM-NEXT: 40103b: e9 e0 ff ff ff jmp -32 <.plt> | |
| 87 | // DISASM-EMPTY: | |
| 88 | // DISASM-NEXT: zed@plt: | |
| 89 | // DISASM-NEXT: 401040: ff 25 10 20 40 00 jmpl *4202512 | |
| 90 | // DISASM-NEXT: 401046: 68 08 00 00 00 pushl $8 | |
| 91 | // DISASM-NEXT: 40104b: e9 d0 ff ff ff jmp -48 <.plt> | |
| 88 | 92 | |
| 89 | 93 | // CHECKSHARED: Name: .plt |
| 90 | 94 | // CHECKSHARED-NEXT: Type: SHT_PROGBITS |
deps/lld/test/ELF/plt.s+10| ... | ... | @@ -73,12 +73,18 @@ |
| 73 | 73 | // DISASM-NEXT: 1020: ff 35 e2 0f 00 00 pushq 4066(%rip) |
| 74 | 74 | // DISASM-NEXT: 1026: ff 25 e4 0f 00 00 jmpq *4068(%rip) |
| 75 | 75 | // DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax) |
| 76 | // DISASM-EMPTY: | |
| 77 | // DISASM-NEXT: bar@plt: | |
| 76 | 78 | // DISASM-NEXT: 1030: ff 25 e2 0f 00 00 jmpq *4066(%rip) |
| 77 | 79 | // DISASM-NEXT: 1036: 68 00 00 00 00 pushq $0 |
| 78 | 80 | // DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt> |
| 81 | // DISASM-EMPTY: | |
| 82 | // DISASM-NEXT: zed@plt: | |
| 79 | 83 | // DISASM-NEXT: 1040: ff 25 da 0f 00 00 jmpq *4058(%rip) |
| 80 | 84 | // DISASM-NEXT: 1046: 68 01 00 00 00 pushq $1 |
| 81 | 85 | // DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt> |
| 86 | // DISASM-EMPTY: | |
| 87 | // DISASM-NEXT: _start@plt: | |
| 82 | 88 | // DISASM-NEXT: 1050: ff 25 d2 0f 00 00 jmpq *4050(%rip) |
| 83 | 89 | // DISASM-NEXT: 1056: 68 02 00 00 00 pushq $2 |
| 84 | 90 | // DISASM-NEXT: 105b: e9 c0 ff ff ff jmp -64 <.plt> |
| ... | ... | @@ -102,9 +108,13 @@ |
| 102 | 108 | // DISASM2-NEXT: 201020: ff 35 e2 0f 00 00 pushq 4066(%rip) |
| 103 | 109 | // DISASM2-NEXT: 201026: ff 25 e4 0f 00 00 jmpq *4068(%rip) |
| 104 | 110 | // DISASM2-NEXT: 20102c: 0f 1f 40 00 nopl (%rax) |
| 111 | // DISASM2-EMPTY: | |
| 112 | // DISASM2-NEXT: bar@plt: | |
| 105 | 113 | // DISASM2-NEXT: 201030: ff 25 e2 0f 00 00 jmpq *4066(%rip) |
| 106 | 114 | // DISASM2-NEXT: 201036: 68 00 00 00 00 pushq $0 |
| 107 | 115 | // DISASM2-NEXT: 20103b: e9 e0 ff ff ff jmp -32 <.plt> |
| 116 | // DISASM2-EMPTY: | |
| 117 | // DISASM2-NEXT: zed@plt: | |
| 108 | 118 | // DISASM2-NEXT: 201040: ff 25 da 0f 00 00 jmpq *4058(%rip) |
| 109 | 119 | // DISASM2-NEXT: 201046: 68 01 00 00 00 pushq $1 |
| 110 | 120 | // DISASM2-NEXT: 20104b: e9 d0 ff ff ff jmp -48 <.plt> |
deps/lld/test/ELF/ppc-relocs.s+14-3| ... | ... | @@ -55,6 +55,17 @@ mystr: |
| 55 | 55 | # CHECK: .FR_PPC_REL24: |
| 56 | 56 | # CHECK: 1101c: 48 00 00 04 b .+4 |
| 57 | 57 | |
| 58 | .section .R_PPC_REL14,"ax",@progbits | |
| 59 | .globl .FR_PPC_REL14 | |
| 60 | .FR_PPC_REL14: | |
| 61 | beq .Lfooy | |
| 62 | .section .R_PPC_REL14_2,"ax",@progbits | |
| 63 | .Lfooy: | |
| 64 | ||
| 65 | # CHECK: Disassembly of section .R_PPC_REL14: | |
| 66 | # CHECK: .FR_PPC_REL14: | |
| 67 | # CHECK: 11020: {{.*}} bt 2, .+4 | |
| 68 | ||
| 58 | 69 | .section .R_PPC_REL32,"ax",@progbits |
| 59 | 70 | .globl .FR_PPC_REL32 |
| 60 | 71 | .FR_PPC_REL32: |
| ... | ... | @@ -64,7 +75,7 @@ mystr: |
| 64 | 75 | |
| 65 | 76 | # CHECK: Disassembly of section .R_PPC_REL32: |
| 66 | 77 | # CHECK: .FR_PPC_REL32: |
| 67 | # CHECK: 11020: 00 00 00 04 | |
| 78 | # CHECK: 11024: 00 00 00 04 | |
| 68 | 79 | |
| 69 | 80 | .section .R_PPC_ADDR32,"ax",@progbits |
| 70 | 81 | .globl .FR_PPC_ADDR32 |
| ... | ... | @@ -75,7 +86,7 @@ mystr: |
| 75 | 86 | |
| 76 | 87 | # CHECK: Disassembly of section .R_PPC_ADDR32: |
| 77 | 88 | # CHECK: .FR_PPC_ADDR32: |
| 78 | # CHECK: 11024: 00 01 10 28 | |
| 89 | # CHECK: 11028: 00 01 10 2c | |
| 79 | 90 | |
| 80 | 91 | .align 2 |
| 81 | 92 | .section .R_PPC_PLTREL24,"ax",@progbits |
| ... | ... | @@ -87,4 +98,4 @@ mystr: |
| 87 | 98 | |
| 88 | 99 | # CHECK: Disassembly of section .R_PPC_PLTREL24: |
| 89 | 100 | # CHECK: .R_PPC_PLTREL24: |
| 90 | # CHECK: 11028: 48 00 00 04 b .+4 | |
| 101 | # CHECK: 1102c: 48 00 00 04 b .+4 |
deps/lld/test/ELF/ppc64-bsymbolic-toc-restore.s created+68| ... | ... | @@ -0,0 +1,68 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-bsymbolic-local-def.s -o %t2.o | |
| 5 | # RUN: ld.lld -Bsymbolic -shared %t1.o %t2.o -o %t | |
| 6 | # RUN: llvm-objdump -d -r %t | FileCheck %s | |
| 7 | # RUN: not ld.lld -shared %t1.o %t2.o -o %t 2>&1 | FileCheck --check-prefix=FAIL %s | |
| 8 | ||
| 9 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t1.o | |
| 10 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-bsymbolic-local-def.s -o %t2.o | |
| 11 | # RUN: ld.lld -Bsymbolic -shared %t1.o %t2.o -o %t | |
| 12 | # RUN: llvm-objdump -d -r %t | FileCheck %s | |
| 13 | # RUN: not ld.lld -shared %t1.o %t2.o -o %t 2>&1 | FileCheck --check-prefix=FAIL %s | |
| 14 | ||
| 15 | # FAIL: call lacks nop, can't restore toc | |
| 16 | ||
| 17 | # Test to document the toc-restore behavior with -Bsymbolic option. Since | |
| 18 | # -Bsymbolic causes the call to bind to the internal defintion we know the | |
| 19 | # caller and callee share the same TOC base. This means branching to the | |
| 20 | # local entry point of the callee, and no need for a nop to follow the call | |
| 21 | # (since there is no need to restore the TOC-pointer after the call). | |
| 22 | ||
| 23 | .abiversion 2 | |
| 24 | .section ".text" | |
| 25 | ||
| 26 | .p2align 2 | |
| 27 | .global caller | |
| 28 | .type caller, @function | |
| 29 | caller: | |
| 30 | .Lcaller_gep: | |
| 31 | addis 2, 12, .TOC.-.Lcaller_gep@ha | |
| 32 | addi 2, 2, .TOC.-.Lcaller_gep@l | |
| 33 | .Lcaller_lep: | |
| 34 | .localentry caller, .-caller | |
| 35 | mflr 0 | |
| 36 | std 0, -16(1) | |
| 37 | stdu 1, -32(1) | |
| 38 | bl def | |
| 39 | mr 31, 3 | |
| 40 | bl not_defined | |
| 41 | nop | |
| 42 | add 3, 3, 31 | |
| 43 | addi 1, 1, 32 | |
| 44 | ld 0, -16(1) | |
| 45 | mtlr 0 | |
| 46 | blr | |
| 47 | ||
| 48 | # Note that the bl .+44 is a call to def's local entry, jumping past the first 2 | |
| 49 | # instructions. Branching to the global entry would corrupt the TOC pointer | |
| 50 | # since the global entry requires that %r12 hold the address of the function | |
| 51 | # being called. | |
| 52 | ||
| 53 | # CHECK-LABEL: caller | |
| 54 | # CHECK: bl .+44 | |
| 55 | # CHECK-NEXT: mr 31, 3 | |
| 56 | # CHECK-NEXT: bl .+67108816 | |
| 57 | # CHECK-NEXT: ld 2, 24(1) | |
| 58 | # CHECK-NEXT: add 3, 3, 31 | |
| 59 | # CHECK-NEXT: addi 1, 1, 32 | |
| 60 | # CHECK-NEXT: ld 0, -16(1) | |
| 61 | # CHECK-NEXT: mtlr 0 | |
| 62 | # CHECK-NEXT: blr | |
| 63 | # CHECK-EMPTY: | |
| 64 | # CHECK-NEXT: def: | |
| 65 | # CHECK-NEXT: addis 2, 12, 2 | |
| 66 | # CHECK-NEXT: addi 2, 2, -32636 | |
| 67 | # CHECK-NEXT: li 3, 55 | |
| 68 | # CHECK-NEXT: blr |
deps/lld/test/ELF/ppc64-call-reach.s created+94| ... | ... | @@ -0,0 +1,94 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ | |
| 5 | # RUN: %t.o -o %t | |
| 6 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 7 | # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ | |
| 8 | # RUN: %t.o -o %t | |
| 9 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 10 | # RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \ | |
| 11 | # RUN: %t.o -o %t | |
| 12 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=NEGOFFSET %s | |
| 13 | # RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \ | |
| 14 | # RUN: %t.o -o %t | |
| 15 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=THUNK %s | |
| 16 | # RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s | |
| 17 | # RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \ | |
| 18 | # RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s | |
| 19 | ||
| 20 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o | |
| 21 | # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ | |
| 22 | # RUN: %t.o -o %t | |
| 23 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 24 | # RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \ | |
| 25 | # RUN: %t.o -o %t | |
| 26 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 27 | # RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \ | |
| 28 | # RUN: %t.o -o %t | |
| 29 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=NEGOFFSET %s | |
| 30 | # RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \ | |
| 31 | # RUN: %t.o -o %t | |
| 32 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=THUNK %s | |
| 33 | # RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s | |
| 34 | # RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \ | |
| 35 | # RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s | |
| 36 | ||
| 37 | # MISSALIGNED: ld.lld: error: {{.*}}.o:(.text+0x14): improper alignment for relocation R_PPC64_REL24: 0x19 is not aligned to 4 bytes | |
| 38 | # MISSALIGNED: ld.lld: error: {{.*}}.o:(.text+0x24): improper alignment for relocation R_PPC64_REL24: 0xB is not aligned to 4 bytes | |
| 39 | ||
| 40 | .global test | |
| 41 | .p2align 4 | |
| 42 | .type test,@function | |
| 43 | test: | |
| 44 | .Lgep: | |
| 45 | addis 2, 12, .TOC.-.Lgep@ha | |
| 46 | addi 2, 2, .TOC.-.Lgep@l | |
| 47 | .Llep: | |
| 48 | .localentry test, .Llep-.Lgep | |
| 49 | mflr 0 | |
| 50 | std 0, 16(1) | |
| 51 | stdu 1, 32(1) | |
| 52 | bl callee | |
| 53 | addi 1, 1, 32 | |
| 54 | ld 0, 16(1) | |
| 55 | mtlr 0 | |
| 56 | b tail_callee | |
| 57 | ||
| 58 | # Check that we are branching to the definitions, and not range-extending | |
| 59 | # thunks. | |
| 60 | # CHECK-LABEL: test | |
| 61 | # CHECK: 10010014: {{.*}} bl .+33554428 | |
| 62 | # CHECK: 10010024: {{.*}} b .+33554428 | |
| 63 | ||
| 64 | # NEGOFFSET-LABEL: test | |
| 65 | # NEGOFFSET: 10010014: {{.*}} bl .+33554432 | |
| 66 | # NEGOFFSET: 10010024: {{.*}} b .+33554432 | |
| 67 | ||
| 68 | # .branch_lt[0] | |
| 69 | # THUNK-LABEL: __long_branch_callee: | |
| 70 | # THUNK-NEXT: 10010000: {{.*}} addis 12, 2, -1 | |
| 71 | # THUNK-NEXT: ld 12, -32768(12) | |
| 72 | # THUNK-NEXT: mtctr 12 | |
| 73 | # THUNK-NEXT: bctr | |
| 74 | ||
| 75 | # .branch_lt[1] | |
| 76 | # THUNK-LABEL: __long_branch_tail_callee: | |
| 77 | # THUNK-NEXT: 10010010: {{.*}} addis 12, 2, -1 | |
| 78 | # THUNK-NEXT: ld 12, -32760(12) | |
| 79 | # THUNK-NEXT: mtctr 12 | |
| 80 | # THUNK-NEXT: bctr | |
| 81 | ||
| 82 | # Each call now branches to a thunk, and although it is printed as positive | |
| 83 | # the offset is interpreted as a signed 26 bit value so 67108812 is actually | |
| 84 | # -52. | |
| 85 | # THUNK-LABEL: test: | |
| 86 | # THUNK: 10010034: {{.*}} bl .+67108812 | |
| 87 | # THUNK: 10010044: {{.*}} b .+67108812 | |
| 88 | ||
| 89 | # The offset from the TOC to the .branch_lt section is (-1 << 16) - 32768. | |
| 90 | # Name Type Address Off Size | |
| 91 | # BRANCHLT: .branch_lt PROGBITS 0000000010020000 020000 000010 | |
| 92 | # BRANCHLT: .got PROGBITS 0000000010030000 030000 000008 | |
| 93 | # BRANCHLT-NOT: .plt | |
| 94 |
deps/lld/test/ELF/ppc64-dq.s created+32| ... | ... | @@ -0,0 +1,32 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | # RUN: ld.lld %t.o -o %t | |
| 5 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 6 | ||
| 7 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o | |
| 8 | # RUN: ld.lld %t.o -o %t | |
| 9 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 10 | ||
| 11 | .global test | |
| 12 | .p2align 4 | |
| 13 | .type test,@function | |
| 14 | test: | |
| 15 | .Lgep: | |
| 16 | addis 2, 12, .TOC.-.Lgep@ha | |
| 17 | addi 2, 2, .TOC.-.Lgep@l | |
| 18 | .Llep: | |
| 19 | .localentry test, .Llep-.Lgep | |
| 20 | addis 3, 2, qword@toc@ha | |
| 21 | lxv 3, qword@toc@l(3) | |
| 22 | addis 3, 2, qword@toc@ha | |
| 23 | stxv 3, qword@toc@l(3) | |
| 24 | blr | |
| 25 | ||
| 26 | .comm qword, 16, 16 | |
| 27 | ||
| 28 | # Verify that we don't overwrite any of the extended opcode bits on a DQ form | |
| 29 | # instruction. | |
| 30 | # CHECK-LABEL: test | |
| 31 | # CHECK: lxv 3, -32768(3) | |
| 32 | # CHECK: stxv 3, -32768(3) |
deps/lld/test/ELF/ppc64-dtprel.s+4-4| ... | ... | @@ -2,15 +2,15 @@ |
| 2 | 2 | |
| 3 | 3 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o |
| 4 | 4 | // RUN: ld.lld -shared %t.o -o %t.so |
| 5 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 6 | // RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 5 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 6 | // RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 7 | 7 | // RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s |
| 8 | 8 | // RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=GotDisLE %s |
| 9 | 9 | |
| 10 | 10 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o |
| 11 | 11 | // RUN: ld.lld -shared %t.o -o %t.so |
| 12 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 13 | // RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 12 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 13 | // RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 14 | 14 | // RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s |
| 15 | 15 | // RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=GotDisBE %s |
| 16 | 16 |
deps/lld/test/ELF/ppc64-entry-point.s created+49| ... | ... | @@ -0,0 +1,49 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t | |
| 4 | # RUN: ld.lld %t -o %t2 | |
| 5 | # RUN: llvm-objdump -D %t2 | FileCheck %s | |
| 6 | # RUN: llvm-objdump -D %t2 | FileCheck -check-prefix=CHECK-LE %s | |
| 7 | ||
| 8 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t | |
| 9 | # RUN: ld.lld %t -o %t2 | |
| 10 | # RUN: llvm-objdump -D %t2 | FileCheck %s | |
| 11 | # RUN: llvm-objdump -D %t2 | FileCheck -check-prefix=CHECK-BE %s | |
| 12 | ||
| 13 | .text | |
| 14 | .abiversion 2 | |
| 15 | .globl _start | |
| 16 | .p2align 4 | |
| 17 | .type _start,@function | |
| 18 | ||
| 19 | _start: | |
| 20 | .Lfunc_begin0: | |
| 21 | .Lfunc_gep0: | |
| 22 | lis 4, .Lfunc_gep0@ha | |
| 23 | addi 4, 4, .Lfunc_gep0@l | |
| 24 | # now r4 should contain the address of _start | |
| 25 | ||
| 26 | lis 5, .TOC.-.Lfunc_gep0@ha | |
| 27 | addi 5, 5, .TOC.-.Lfunc_gep0@l | |
| 28 | # now r5 should contain the offset s.t. r4 + r5 = TOC base | |
| 29 | ||
| 30 | # exit 55 | |
| 31 | li 0, 1 | |
| 32 | li 3, 55 | |
| 33 | sc | |
| 34 | .Lfunc_end0: | |
| 35 | .size _start, .Lfunc_end0-.Lfunc_begin0 | |
| 36 | ||
| 37 | // CHECK: 10010000: {{.*}} lis 4, 4097 | |
| 38 | // CHECK-NEXT: 10010004: {{.*}} addi 4, 4, 0 | |
| 39 | // CHECK-NEXT: 10010008: {{.*}} lis 5, 2 | |
| 40 | // CHECK-NEXT: 1001000c: {{.*}} addi 5, 5, -32768 | |
| 41 | ||
| 42 | // CHECK-LE: Disassembly of section .got: | |
| 43 | // CHECK-LE-NEXT: .got: | |
| 44 | // CHECK-LE-NEXT: 10020000: 00 80 02 10 | |
| 45 | ||
| 46 | // CHECK-BE: Disassembly of section .got: | |
| 47 | // CHECK-BE-NEXT: .got: | |
| 48 | // CHECK-BE-NEXT: 10020000: 00 00 00 00 {{.*}} | |
| 49 | // CHECK-BE-NEXT: 10020004: 10 02 80 00 {{.*}} |
deps/lld/test/ELF/ppc64-error-missaligned-dq.s created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | # | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s | |
| 5 | ||
| 6 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o | |
| 7 | # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s | |
| 8 | ||
| 9 | # CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8001 is not aligned to 16 bytes | |
| 10 | ||
| 11 | .global test | |
| 12 | .p2align 4 | |
| 13 | .type test,@function | |
| 14 | test: | |
| 15 | .Lgep: | |
| 16 | addis 2, 12, .TOC.-.Lgep@ha | |
| 17 | addi 2, 2, .TOC.-.Lgep@l | |
| 18 | .Llep: | |
| 19 | .localentry test, .Llep-.Lgep | |
| 20 | addis 3, 2, qword@toc@ha | |
| 21 | lxv 3, qword@toc@l(3) | |
| 22 | blr | |
| 23 | ||
| 24 | .comm pad, 1, 1 | |
| 25 | .comm qword, 16, 1 | |
| 26 |
deps/lld/test/ELF/ppc64-error-missaligned-ds.s created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s | |
| 5 | ||
| 6 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o | |
| 7 | # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s | |
| 8 | ||
| 9 | # CHECK: improper alignment for relocation R_PPC64_TOC16_LO_DS: 0x8001 is not aligned to 4 bytes | |
| 10 | ||
| 11 | .global test | |
| 12 | .p2align 4 | |
| 13 | .type test,@function | |
| 14 | test: | |
| 15 | .Lgep: | |
| 16 | addis 2, 12, .TOC.-.Lgep@ha | |
| 17 | addi 2, 2, .TOC.-.Lgep@l | |
| 18 | .Llep: | |
| 19 | .localentry test, .Llep-.Lgep | |
| 20 | addis 3, 2, word@toc@ha | |
| 21 | lwa 3, word@toc@l(3) | |
| 22 | blr | |
| 23 | ||
| 24 | .comm pad, 1, 1 | |
| 25 | .comm word, 4, 1 | |
| 26 |
deps/lld/test/ELF/ppc64-func-entry-points.s+1-1| ... | ... | @@ -75,6 +75,6 @@ glob: |
| 75 | 75 | // CHECK: foo_external_diff: |
| 76 | 76 | // CHECK-NEXT: 10010080: {{.*}} addis 2, 12, 2 |
| 77 | 77 | // CHECK-NEXT: 10010084: {{.*}} addi 2, 2, 32640 |
| 78 | // CHECK-NEXT: 10010088: {{.*}} addis 5, 2, 0 | |
| 78 | // CHECK-NEXT: 10010088: {{.*}} nop | |
| 79 | 79 | // CHECK: foo_external_same: |
| 80 | 80 | // CHECK-NEXT: 100100b0: {{.*}} add 3, 4, 3 |
deps/lld/test/ELF/ppc64-gd-to-ie.s+4-4| ... | ... | @@ -5,16 +5,16 @@ |
| 5 | 5 | # RUN: ld.lld -shared %t2.o -o %t3.so |
| 6 | 6 | # RUN: ld.lld %t.o %t3.so -o %t |
| 7 | 7 | # RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=CheckGot %s |
| 8 | # RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 9 | # RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s | |
| 8 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 9 | # RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 10 | 10 | |
| 11 | 11 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o |
| 12 | 12 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-tls.s -o %t2.o |
| 13 | 13 | # RUN: ld.lld -shared %t2.o -o %t3.so |
| 14 | 14 | # RUN: ld.lld %t.o %t3.so -o %t |
| 15 | 15 | # RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=CheckGot %s |
| 16 | # RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 17 | # RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s | |
| 16 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 17 | # RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 18 | 18 | |
| 19 | 19 | .text |
| 20 | 20 | .abiversion 2 |
deps/lld/test/ELF/ppc64-general-dynamic-tls.s+6-6| ... | ... | @@ -2,17 +2,17 @@ |
| 2 | 2 | |
| 3 | 3 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o |
| 4 | 4 | // RUN: ld.lld -shared %t.o -o %t.so |
| 5 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 6 | // RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 5 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 6 | // RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 7 | 7 | // RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s |
| 8 | // RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s | |
| 8 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=Dis %s | |
| 9 | 9 | |
| 10 | 10 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o |
| 11 | 11 | // RUN: ld.lld -shared %t.o -o %t.so |
| 12 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 13 | // RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 12 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 13 | // RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 14 | 14 | // RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s |
| 15 | // RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s | |
| 15 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=Dis %s | |
| 16 | 16 | |
| 17 | 17 | 	.text |
| 18 | 18 | 	.abiversion 2 |
deps/lld/test/ELF/ppc64-got-indirect.s+2-2| ... | ... | @@ -83,8 +83,8 @@ glob: |
| 83 | 83 | # CHECK: _start: |
| 84 | 84 | # CHECK-NEXT: 10010000: {{.*}} addis 2, 12, 3 |
| 85 | 85 | # CHECK-NEXT: 10010004: {{.*}} addi 2, 2, -32768 |
| 86 | # CHECK-NEXT: 10010008: {{.*}} addis 3, 2, 0 | |
| 87 | # CHECK-NEXT: 1001000c: {{.*}} ld 3, -32760(3) | |
| 86 | # CHECK-NEXT: 10010008: {{.*}} nop | |
| 87 | # CHECK-NEXT: 1001000c: {{.*}} ld 3, -32760(2) | |
| 88 | 88 | # CHECK: 1001001c: {{.*}} lwa 3, 0(3) |
| 89 | 89 | |
| 90 | 90 | # CHECK-LE: Disassembly of section .data: |
deps/lld/test/ELF/ppc64-got-off.s created+67| ... | ... | @@ -0,0 +1,67 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | # RUN: ld.lld -shared --no-toc-optimize %t.o -o %t | |
| 5 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 6 | ||
| 7 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o | |
| 8 | # RUN: ld.lld -shared --no-toc-optimize %t.o -o %t | |
| 9 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 10 | ||
| 11 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 12 | # RUN: ld.lld -shared %t.o -o %t | |
| 13 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=OPT %s | |
| 14 | ||
| 15 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o | |
| 16 | # RUN: ld.lld -shared %t.o -o %t | |
| 17 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=OPT %s | |
| 18 | ||
| 19 | .abiversion 2 | |
| 20 | .section ".text" | |
| 21 | ||
| 22 | .p2align 2 | |
| 23 | .global func | |
| 24 | .type func, @function | |
| 25 | func: | |
| 26 | .Lfunc_gep: | |
| 27 | addis 2, 12, .TOC.-.Lfunc_gep@ha | |
| 28 | addi 2, 2, .TOC.-.Lfunc_gep@l | |
| 29 | .Lfunc_lep: | |
| 30 | .localentry func, .-func | |
| 31 | addis 3, 2, a@got@ha | |
| 32 | ld 3, a@got@l(3) | |
| 33 | ld 4, a@got(2) | |
| 34 | lis 5, a@got@h | |
| 35 | ori 5, 5, a@got@l | |
| 36 | li 6, 0 | |
| 37 | ori 6, 6, a@got | |
| 38 | blr | |
| 39 | ||
| 40 | # CHECK-LABEL: func | |
| 41 | # CHECK: addis 3, 2, 0 | |
| 42 | # CHECK-NEXT: ld 3, -32760(3) | |
| 43 | # CHECK-NEXT: ld 4, -32760(2) | |
| 44 | # CHECK-NEXT: lis 5, -1 | |
| 45 | # CHECK-NEXT: ori 5, 5, 32776 | |
| 46 | # CHECK-NEXT: li 6, 0 | |
| 47 | # CHECK-NEXT: ori 6, 6, 32776 | |
| 48 | ||
| 49 | # OPT-LABEL: func | |
| 50 | # OPT: nop | |
| 51 | # OPT-NEXT: ld 3, -32760(2) | |
| 52 | # OPT-NEXT: ld 4, -32760(2) | |
| 53 | # OPT-NEXT: lis 5, -1 | |
| 54 | # OPT-NEXT: ori 5, 5, 32776 | |
| 55 | # OPT-NEXT: li 6, 0 | |
| 56 | # OPT-NEXT: ori 6, 6, 32776 | |
| 57 | ||
| 58 | # Since the got entry for a is .got[1] and the TOC base points to | |
| 59 | # .got + 0x8000, the offset for a@got is -0x7FF8 --> -32760 | |
| 60 | ||
| 61 | .section ".data" | |
| 62 | .global a | |
| 63 | .type a, @object | |
| 64 | .size a, 4 | |
| 65 | .p2align 2 | |
| 66 | a: | |
| 67 | .long 0x1000 |
deps/lld/test/ELF/ppc64-initial-exec-tls.s+6-6| ... | ... | @@ -4,19 +4,19 @@ |
| 4 | 4 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-tls.s -o %t2.o |
| 5 | 5 | // RUN: ld.lld -shared %t2.o -o %t2.so |
| 6 | 6 | // RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.so -o %t |
| 7 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 8 | // RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s | |
| 7 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 8 | // RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 9 | 9 | // RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=CheckGot %s |
| 10 | // RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 10 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 11 | 11 | |
| 12 | 12 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o |
| 13 | 13 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-tls.s -o %t2.o |
| 14 | 14 | // RUN: ld.lld -shared %t2.o -o %t2.so |
| 15 | 15 | // RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.so -o %t |
| 16 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 17 | // RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s | |
| 16 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 17 | // RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 18 | 18 | // RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=CheckGot %s |
| 19 | // RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 19 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 20 | 20 | |
| 21 | 21 | 	.text |
| 22 | 22 | 	.abiversion 2 |
deps/lld/test/ELF/ppc64-local-dynamic.s+6-6| ... | ... | @@ -2,17 +2,17 @@ |
| 2 | 2 | |
| 3 | 3 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o |
| 4 | 4 | // RUN: ld.lld -shared %t.o -o %t.so |
| 5 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 6 | // RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 5 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 6 | // RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 7 | 7 | // RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s |
| 8 | // RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s | |
| 8 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=Dis %s | |
| 9 | 9 | |
| 10 | 10 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o |
| 11 | 11 | // RUN: ld.lld -shared %t.o -o %t.so |
| 12 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 13 | // RUN: llvm-readelf -relocations --wide %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 12 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 13 | // RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s | |
| 14 | 14 | // RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s |
| 15 | // RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s | |
| 15 | // RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=Dis %s | |
| 16 | 16 | |
| 17 | 17 | .text |
| 18 | 18 | .abiversion 2 |
deps/lld/test/ELF/ppc64-local-exec-tls.s+2-2| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | // REQUIRES: ppc |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o |
| 3 | 3 | // RUN: ld.lld %t.o -o %t |
| 4 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 5 | // RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 4 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 5 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 6 | 6 | |
| 7 | 7 | 	.text |
| 8 | 8 | 	.abiversion 2 |
deps/lld/test/ELF/ppc64-long-branch.s created+121| ... | ... | @@ -0,0 +1,121 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-func-global-entry.s -o %t2.o | |
| 5 | # RUN: ld.lld -shared %t2.o -o %t3.so | |
| 6 | # RUN: ld.lld --no-toc-optimize %t.o %t3.so -o %t | |
| 7 | # RUN: llvm-objdump -d -start-address=0x10010000 -stop-address=0x10010018 %t | FileCheck %s -check-prefix=CALLEE_DUMP | |
| 8 | # RUN: llvm-objdump -d -start-address=0x12010020 -stop-address=0x12010084 %t | FileCheck %s -check-prefix=CALLER_DUMP | |
| 9 | # RUN: llvm-objdump -D -start-address=0x12020008 -stop-address=0x12020010 %t | FileCheck %s -check-prefix=BRANCH_LT_LE | |
| 10 | # RUN: llvm-readelf --sections %t | FileCheck %s -check-prefix=SECTIONS | |
| 11 | ||
| 12 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o | |
| 13 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-func-global-entry.s -o %t2.o | |
| 14 | # RUN: ld.lld -shared %t2.o -o %t3.so | |
| 15 | # RUN: ld.lld --no-toc-optimize %t.o %t3.so -o %t | |
| 16 | # RUN: llvm-objdump -d -start-address=0x10010000 -stop-address=0x10010018 %t | FileCheck %s -check-prefix=CALLEE_DUMP | |
| 17 | # RUN: llvm-objdump -d -start-address=0x12010020 -stop-address=0x12010084 %t | FileCheck %s -check-prefix=CALLER_DUMP | |
| 18 | # RUN: llvm-objdump -D -start-address=0x12020008 -stop-address=0x12020010 %t | FileCheck %s -check-prefix=BRANCH_LT_BE | |
| 19 | # RUN: llvm-readelf --sections %t | FileCheck %s -check-prefix=SECTIONS | |
| 20 | ||
| 21 | .text | |
| 22 | .abiversion 2 | |
| 23 | .protected callee | |
| 24 | .globl callee | |
| 25 | .p2align 4 | |
| 26 | .type callee,@function | |
| 27 | callee: | |
| 28 | .Lfunc_gep0: | |
| 29 | addis 2, 12, .TOC.-.Lfunc_gep0@ha | |
| 30 | addi 2, 2, .TOC.-.Lfunc_gep0@l | |
| 31 | .Lfunc_lep0: | |
| 32 | .localentry callee, .Lfunc_lep0-.Lfunc_gep0 | |
| 33 | addis 4, 2, .LC0@toc@ha | |
| 34 | ld 4, .LC0@toc@l(4) | |
| 35 | lwz 3, 0(4) | |
| 36 | blr | |
| 37 | ||
| 38 | .space 0x2000000 | |
| 39 | ||
| 40 | .protected _start | |
| 41 | .global _start | |
| 42 | .p2align 4 | |
| 43 | .type _start,@function | |
| 44 | _start: | |
| 45 | .Lfunc_begin1: | |
| 46 | .Lfunc_gep1: | |
| 47 | addis 2, 12, .TOC.-.Lfunc_gep1@ha | |
| 48 | addi 2, 2, .TOC.-.Lfunc_gep1@l | |
| 49 | .Lfunc_lep1: | |
| 50 | .localentry	_start, .Lfunc_lep1-.Lfunc_gep1 | |
| 51 | mflr 0 | |
| 52 | std 0, 16(1) | |
| 53 | stdu 1, -32(1) | |
| 54 | bl callee | |
| 55 | bl foo_external_diff | |
| 56 | nop | |
| 57 | addi 1, 1, 32 | |
| 58 | ld 0, 16(1) | |
| 59 | mtlr 0 | |
| 60 | ||
| 61 | addis 4, 2, .LC1@toc@ha | |
| 62 | ld 4, .LC1@toc@l(4) | |
| 63 | lwz 4, 0(4) | |
| 64 | add 3, 3, 4 | |
| 65 | blr | |
| 66 | ||
| 67 | ||
| 68 | .section .toc,"aw",@progbits | |
| 69 | .LC0: | |
| 70 | .tc a[TC],a | |
| 71 | .LC1: | |
| 72 | .tc b[TC],b | |
| 73 | ||
| 74 | ||
| 75 | .data | |
| 76 | .type a,@object | |
| 77 | .globl a | |
| 78 | .p2align 2 | |
| 79 | a: | |
| 80 | .long 11 | |
| 81 | .size a, 4 | |
| 82 | ||
| 83 | .type b,@object | |
| 84 | .global b | |
| 85 | .p2align 2 | |
| 86 | b: | |
| 87 | .long 33 | |
| 88 | .size b, 4 | |
| 89 | ||
| 90 | # Verify address of the callee | |
| 91 | # CALLEE_DUMP: callee: | |
| 92 | # CALLEE_DUMP: 10010000: {{.*}} addis 2, 12, 515 | |
| 93 | # CALLEE_DUMP: 10010004: {{.*}} addi 2, 2, -32544 | |
| 94 | # CALLEE_DUMP: 10010008: {{.*}} addis 4, 2, 0 | |
| 95 | ||
| 96 | # Verify the address of _start, and the call to the long-branch thunk. | |
| 97 | # CALLER_DUMP: _start: | |
| 98 | # CALLER_DUMP: 12010020: {{.*}} addis 2, 12, 3 | |
| 99 | # CALLER_DUMP: 12010038: {{.*}} bl .+56 | |
| 100 | ||
| 101 | # Verify the thunks contents: TOC-pointer + offset = .branch_lt[0] | |
| 102 | # 0x120380e8 + (-2 << 16 + 32552) = 0x12020008 | |
| 103 | # CALLER_DUMP: __long_branch_callee: | |
| 104 | # CALLER_DUMP: 12010060: {{.*}} addis 12, 2, -2 | |
| 105 | # CALLER_DUMP: 12010064: {{.*}} ld 12, 32552(12) | |
| 106 | # CALLER_DUMP: 12010068: {{.*}} mtctr 12 | |
| 107 | # CALLER_DUMP: 1201006c: {{.*}} bctr | |
| 108 | ||
| 109 | # BRANCH_LT_LE: Disassembly of section .branch_lt: | |
| 110 | # BRANCH_LT_LE-NEXT: .branch_lt: | |
| 111 | # BRANCH_LT_LE-NEXT: 12020008: 08 00 01 10 | |
| 112 | # BRANCH_LT_LE-NEXT: 1202000c: 00 00 00 00 | |
| 113 | ||
| 114 | # BRANCH_LT_BE: Disassembly of section .branch_lt: | |
| 115 | # BRANCH_LT_BE-NEXT: .branch_lt: | |
| 116 | # BRANCH_LT_BE-NEXT: 12020008: 00 00 00 00 | |
| 117 | # BRANCH_LT_BE-NEXT: 1202000c: 10 01 00 08 | |
| 118 | ||
| 119 | # [Nr] Name Type Address Off Size | |
| 120 | # SECTIONS: [ 9] .branch_lt PROGBITS 0000000012020008 2020008 000008 | |
| 121 | # SECTIONS: [11] .got PROGBITS 00000000120300e0 20300e0 000008 |
deps/lld/test/ELF/ppc64-rel-so-local-calls.s+2-2| ... | ... | @@ -1,11 +1,11 @@ |
| 1 | 1 | // REQUIRES: ppc |
| 2 | 2 | |
| 3 | 3 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o |
| 4 | // RUN: ld.lld -shared -z notext %t.o -o %t.so | |
| 4 | // RUN: ld.lld -shared %t.o -o %t.so | |
| 5 | 5 | // RUN: llvm-readelf -dyn-relocations %t.so | FileCheck %s |
| 6 | 6 | |
| 7 | 7 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o |
| 8 | // RUN: ld.lld -shared -z notext %t.o -o %t.so | |
| 8 | // RUN: ld.lld -shared %t.o -o %t.so | |
| 9 | 9 | // RUN: llvm-readelf -dyn-relocations %t.so | FileCheck %s |
| 10 | 10 | |
| 11 | 11 |
deps/lld/test/ELF/ppc64-relocs.s+30-19| ... | ... | @@ -63,7 +63,7 @@ _start: |
| 63 | 63 | |
| 64 | 64 | # CHECK: Disassembly of section .R_PPC64_TOC16_HA: |
| 65 | 65 | # CHECK: .FR_PPC64_TOC16_HA: |
| 66 | # CHECK: 10010018: {{.*}} addis 1, 2, 0 | |
| 66 | # CHECK: 10010018: {{.*}} nop | |
| 67 | 67 | |
| 68 | 68 | .section .R_PPC64_REL24,"ax",@progbits |
| 69 | 69 | .globl .FR_PPC64_REL24 |
| ... | ... | @@ -76,6 +76,17 @@ _start: |
| 76 | 76 | # CHECK: .FR_PPC64_REL24: |
| 77 | 77 | # CHECK: 1001001c: {{.*}} b .+4 |
| 78 | 78 | |
| 79 | .section .R_PPC64_REL14,"ax",@progbits | |
| 80 | .globl .FR_PPC64_REL14 | |
| 81 | .FR_PPC64_REL14: | |
| 82 | beq .Lfooy | |
| 83 | .section .R_PPC64_REL14_2,"ax",@progbits | |
| 84 | .Lfooy: | |
| 85 | ||
| 86 | # CHECK: Disassembly of section .R_PPC64_REL14: | |
| 87 | # CHECK: .FR_PPC64_REL14: | |
| 88 | # CHECK: 10010020: {{.*}} bt 2, .+4 | |
| 89 | ||
| 79 | 90 | .section .R_PPC64_ADDR16_LO,"ax",@progbits |
| 80 | 91 | .globl .FR_PPC64_ADDR16_LO |
| 81 | 92 | .FR_PPC64_ADDR16_LO: |
| ... | ... | @@ -83,7 +94,7 @@ _start: |
| 83 | 94 | |
| 84 | 95 | # CHECK: Disassembly of section .R_PPC64_ADDR16_LO: |
| 85 | 96 | # CHECK: .FR_PPC64_ADDR16_LO: |
| 86 | # CHECK: 10010020: {{.*}} li 1, 0 | |
| 97 | # CHECK: 10010024: {{.*}} li 1, 0 | |
| 87 | 98 | |
| 88 | 99 | .section .R_PPC64_ADDR16_HI,"ax",@progbits |
| 89 | 100 | .globl .FR_PPC64_ADDR16_HI |
| ... | ... | @@ -92,7 +103,7 @@ _start: |
| 92 | 103 | |
| 93 | 104 | # CHECK: Disassembly of section .R_PPC64_ADDR16_HI: |
| 94 | 105 | # CHECK: .FR_PPC64_ADDR16_HI: |
| 95 | # CHECK: 10010024: {{.*}} li 1, 4097 | |
| 106 | # CHECK: 10010028: {{.*}} li 1, 4097 | |
| 96 | 107 | |
| 97 | 108 | .section .R_PPC64_ADDR16_HA,"ax",@progbits |
| 98 | 109 | .globl .FR_PPC64_ADDR16_HA |
| ... | ... | @@ -101,7 +112,7 @@ _start: |
| 101 | 112 | |
| 102 | 113 | # CHECK: Disassembly of section .R_PPC64_ADDR16_HA: |
| 103 | 114 | # CHECK: .FR_PPC64_ADDR16_HA: |
| 104 | # CHECK: 10010028: {{.*}} li 1, 4097 | |
| 115 | # CHECK: 1001002c: {{.*}} li 1, 4097 | |
| 105 | 116 | |
| 106 | 117 | .section .R_PPC64_ADDR16_HIGHER,"ax",@progbits |
| 107 | 118 | .globl .FR_PPC64_ADDR16_HIGHER |
| ... | ... | @@ -110,7 +121,7 @@ _start: |
| 110 | 121 | |
| 111 | 122 | # CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHER: |
| 112 | 123 | # CHECK: .FR_PPC64_ADDR16_HIGHER: |
| 113 | # CHECK: 1001002c: {{.*}} li 1, 0 | |
| 124 | # CHECK: 10010030: {{.*}} li 1, 0 | |
| 114 | 125 | |
| 115 | 126 | .section .R_PPC64_ADDR16_HIGHERA,"ax",@progbits |
| 116 | 127 | .globl .FR_PPC64_ADDR16_HIGHERA |
| ... | ... | @@ -119,7 +130,7 @@ _start: |
| 119 | 130 | |
| 120 | 131 | # CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHERA: |
| 121 | 132 | # CHECK: .FR_PPC64_ADDR16_HIGHERA: |
| 122 | # CHECK: 10010030: {{.*}} li 1, 0 | |
| 133 | # CHECK: 10010034: {{.*}} li 1, 0 | |
| 123 | 134 | |
| 124 | 135 | .section .R_PPC64_ADDR16_HIGHEST,"ax",@progbits |
| 125 | 136 | .globl .FR_PPC64_ADDR16_HIGHEST |
| ... | ... | @@ -128,7 +139,7 @@ _start: |
| 128 | 139 | |
| 129 | 140 | # CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHEST: |
| 130 | 141 | # CHECK: .FR_PPC64_ADDR16_HIGHEST: |
| 131 | # CHECK: 10010034: {{.*}} li 1, 0 | |
| 142 | # CHECK: 10010038: {{.*}} li 1, 0 | |
| 132 | 143 | |
| 133 | 144 | .section .R_PPC64_ADDR16_HIGHESTA,"ax",@progbits |
| 134 | 145 | .globl .FR_PPC64_ADDR16_HIGHESTA |
| ... | ... | @@ -137,7 +148,7 @@ _start: |
| 137 | 148 | |
| 138 | 149 | # CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHESTA: |
| 139 | 150 | # CHECK: .FR_PPC64_ADDR16_HIGHESTA: |
| 140 | # CHECK: 10010038: {{.*}} li 1, 0 | |
| 151 | # CHECK: 1001003c: {{.*}} li 1, 0 | |
| 141 | 152 | |
| 142 | 153 | .section .R_PPC64_REL32, "ax",@progbits |
| 143 | 154 | .globl .FR_PPC64_REL32 |
| ... | ... | @@ -149,20 +160,20 @@ _start: |
| 149 | 160 | |
| 150 | 161 | # DATALE: Disassembly of section .rodata: |
| 151 | 162 | # DATALE: .rodata: |
| 152 | # DATALE: 10000190: b4 fe 00 00 | |
| 163 | # DATALE: 10000190: b8 fe 00 00 | |
| 153 | 164 | |
| 154 | 165 | # DATABE: Disassembly of section .rodata: |
| 155 | 166 | # DATABE: .rodata: |
| 156 | # DATABE: 10000190: 00 00 fe b4 | |
| 167 | # DATABE: 10000190: 00 00 fe b8 | |
| 157 | 168 | |
| 158 | 169 | # Address of rodata + value stored at rodata entry |
| 159 | 170 | # should equal address of LBB0_2. |
| 160 | 171 | # 0x10000190 + 0xfeb4 = 0x10010044 |
| 161 | 172 | # CHECK: Disassembly of section .R_PPC64_REL32: |
| 162 | 173 | # CHECK: .FR_PPC64_REL32: |
| 163 | # CHECK: 1001003c: {{.*}} addis 5, 2, 0 | |
| 164 | # CHECK: 10010040: {{.*}} ld 5, -32736(5) | |
| 165 | # CHECK: 10010044: {{.*}} add 3, 3, 4 | |
| 174 | # CHECK: 10010040: {{.*}} nop | |
| 175 | # CHECK: 10010044: {{.*}} ld 5, -32736(2) | |
| 176 | # CHECK: 10010048: {{.*}} add 3, 3, 4 | |
| 166 | 177 | |
| 167 | 178 | .section .R_PPC64_REL64, "ax",@progbits |
| 168 | 179 | .globl .FR_PPC64_REL64 |
| ... | ... | @@ -178,16 +189,16 @@ __foo: |
| 178 | 189 | |
| 179 | 190 | # Check that address of eh_frame entry + value stored |
| 180 | 191 | # should equal the address of foo. Since it is not aligned, |
| 181 | # the entry is not stored exactly at 100001a8. It starts at | |
| 182 | # address 0x100001aa and has the value 0xfeaa. | |
| 183 | # 0x100001aa + 0xfeaa = 0x10010054 | |
| 192 | # the entry is not stored exactly at 10000198. It starts at | |
| 193 | # address 0x1000019a and has the value 0xfeaa. | |
| 194 | # 0x100001aa + 0xfeae = 0x10010058 | |
| 184 | 195 | # DATALE: Disassembly of section .eh_frame: |
| 185 | 196 | # DATALE: .eh_frame: |
| 186 | # DATALE: 100001a8: {{.*}} aa fe | |
| 197 | # DATALE: 100001a8: {{.*}} ae fe | |
| 187 | 198 | |
| 188 | 199 | # DATABE: Disassembly of section .eh_frame: |
| 189 | 200 | # DATABE: .eh_frame: |
| 190 | # DATABE: 100001b0: fe aa {{.*}} | |
| 201 | # DATABE: 100001b0: fe ae {{.*}} | |
| 191 | 202 | |
| 192 | 203 | # CHECK: __foo |
| 193 | # CHECK-NEXT: 10010054: {{.*}} li 3, 0 | |
| 204 | # CHECK-NEXT: 10010058: {{.*}} li 3, 0 |
deps/lld/test/ELF/ppc64-shared-long_branch.s created+114| ... | ... | @@ -0,0 +1,114 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | # RUN: ld.lld --no-toc-optimize -shared %t.o -o %t | |
| 5 | # RUN: llvm-objdump -d -start-address=0x10000 -stop-address=0x10018 %t | FileCheck %s -check-prefix=CALLEE_DUMP | |
| 6 | # RUN: llvm-objdump -d -start-address=0x2010020 -stop-address=0x2010070 %t | FileCheck %s -check-prefix=CALLER_DUMP | |
| 7 | # RUN: llvm-readelf --sections %t | FileCheck %s -check-prefix=SECTIONS | |
| 8 | # RUN: llvm-readelf --relocations %t | FileCheck %s -check-prefix=DYNRELOC | |
| 9 | ||
| 10 | ||
| 11 | # _start calls protected function callee. Since callee is protected no plt stub | |
| 12 | # is needed. The binary however has been padded out with space so that the call | |
| 13 | # distance is further then a bl instrution can reach. | |
| 14 | ||
| 15 | .text | |
| 16 | .abiversion 2 | |
| 17 | .protected callee | |
| 18 | .global callee | |
| 19 | .p2align 4 | |
| 20 | .type callee,@function | |
| 21 | callee: | |
| 22 | .Lfunc_gep0: | |
| 23 | addis 2, 12, .TOC.-.Lfunc_gep0@ha | |
| 24 | addi 2, 2, .TOC.-.Lfunc_gep0@l | |
| 25 | .Lfunc_lep0: | |
| 26 | .localentry callee, .Lfunc_lep0-.Lfunc_gep0 | |
| 27 | addis 4, 2, .LC0@toc@ha | |
| 28 | ld 4, .LC0@toc@l(4) | |
| 29 | lwz 3, 0(4) | |
| 30 | blr | |
| 31 | ||
| 32 | .space 0x2000000 | |
| 33 | ||
| 34 | .protected _start | |
| 35 | .globl _start | |
| 36 | .p2align 4 | |
| 37 | .type _start,@function | |
| 38 | _start: | |
| 39 | .Lfunc_begin1: | |
| 40 | .Lfunc_gep1: | |
| 41 | addis 2, 12, .TOC.-.Lfunc_gep1@ha | |
| 42 | addi 2, 2, .TOC.-.Lfunc_gep1@l | |
| 43 | .Lfunc_lep1: | |
| 44 | .localentry _start, .Lfunc_lep1-.Lfunc_gep1 | |
| 45 | mflr 0 | |
| 46 | std 0, 16(1) | |
| 47 | stdu 1, -32(1) | |
| 48 | bl callee | |
| 49 | bl ext_callee | |
| 50 | nop | |
| 51 | addi 1, 1, 32 | |
| 52 | ld 0, 16(1) | |
| 53 | mtlr 0 | |
| 54 | ||
| 55 | addis 4, 2, .LC1@toc@ha | |
| 56 | ld 4, .LC1@toc@l(4) | |
| 57 | lwz 4, 0(4) | |
| 58 | add 3, 3, 4 | |
| 59 | blr | |
| 60 | ||
| 61 | ||
| 62 | .section .toc,"aw",@progbits | |
| 63 | .LC0: | |
| 64 | .tc a[TC],a | |
| 65 | .LC1: | |
| 66 | .tc b[TC],b | |
| 67 | ||
| 68 | ||
| 69 | .data | |
| 70 | .type a,@object | |
| 71 | .globl a | |
| 72 | .p2align 2 | |
| 73 | a: | |
| 74 | .long 11 | |
| 75 | .size a, 4 | |
| 76 | ||
| 77 | .type b,@object | |
| 78 | .globl b | |
| 79 | .p2align 2 | |
| 80 | b: | |
| 81 | .long 33 | |
| 82 | .size b, 4 | |
| 83 | ||
| 84 | # Verify address of the callee | |
| 85 | # CALLEE_DUMP: callee: | |
| 86 | # CALLEE_DUMP: 10000: {{.*}} addis 2, 12, 515 | |
| 87 | # CALLEE_DUMP: 10004: {{.*}} addi 2, 2, -32528 | |
| 88 | # CALLEE_DUMP: 10008: {{.*}} addis 4, 2, 0 | |
| 89 | ||
| 90 | # Verify the address of _start, and the call to the long-branch thunk. | |
| 91 | # CALLER_DUMP: _start: | |
| 92 | # CALLER_DUMP: 2010020: {{.*}} addis 2, 12, 3 | |
| 93 | # CALLER_DUMP: 2010038: {{.*}} bl .+56 | |
| 94 | ||
| 95 | # Verify the thunks contents: TOC-pointer + offset = .branch_lt[0] | |
| 96 | # 0x20380F0 + 32552 = 0x2040018 | |
| 97 | # CALLER_DUMP: __long_branch_callee: | |
| 98 | # CALLER_DUMP: 2010060: {{.*}} addis 12, 2, 0 | |
| 99 | # CALLER_DUMP: 2010064: {{.*}} ld 12, 32552(12) | |
| 100 | # CALLER_DUMP: 2010068: {{.*}} mtctr 12 | |
| 101 | # CALLER_DUMP: 201006c: {{.*}} bctr | |
| 102 | ||
| 103 | # .got section is at address 0x20300f0 so TOC pointer points to 0x20400F0. | |
| 104 | # .plt section has a 2 entry header and a single entry for the long branch. | |
| 105 | # [Nr] Name Type Address Off Size | |
| 106 | # SECTIONS: [11] .got PROGBITS 00000000020300f0 20300f0 000008 | |
| 107 | # SECTIONS: [13] .plt NOBITS 0000000002040000 2030108 000018 | |
| 108 | # SECTIONS: [14] .branch_lt NOBITS 0000000002040018 2030108 000008 | |
| 109 | ||
| 110 | # There is a relative dynamic relocation for (.plt + 16 bytes), with a base | |
| 111 | # address equal to callees local entry point (0x10000 + 8). | |
| 112 | # DYNRELOC: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 3 entries: | |
| 113 | # DYNRELOC: Offset Info Type Symbol's Value | |
| 114 | # DYNRELOC: 0000000002040018 0000000000000016 R_PPC64_RELATIVE 10008 |
deps/lld/test/ELF/ppc64-split-stack-adjust-fail.s created+53| ... | ... | @@ -0,0 +1,53 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-no-split-stack.s -o %t2.o | |
| 5 | ||
| 6 | # RUN: not ld.lld --defsym __morestack=0x10010000 %t1.o %t2.o -o %t 2>&1 | FileCheck %s | |
| 7 | ||
| 8 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t1.o | |
| 9 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-no-split-stack.s -o %t2.o | |
| 10 | ||
| 11 | # RUN: not ld.lld --defsym __morestack=0x10010000 %t1.o %t2.o -o %t 2>&1 | FileCheck %s | |
| 12 | ||
| 13 | # CHECK: error: {{.*}}.o:(.text): wrong_regs (with -fsplit-stack) calls nss_callee (without -fsplit-stack), but couldn't adjust its prologue | |
| 14 | ||
| 15 | .abiversion 2 | |
| 16 | .section ".text" | |
| 17 | ||
| 18 | .p2align 2 | |
| 19 | .global wrong_regs | |
| 20 | .type wrong_regs, @function | |
| 21 | ||
| 22 | wrong_regs: | |
| 23 | .Lwr_gep: | |
| 24 | addis 2, 12, .TOC.-.Lwr_gep@ha | |
| 25 | addi 2, 2, .TOC.-.Lwr_gep@l | |
| 26 | .localentry wrong_regs, .-wrong_regs | |
| 27 | ld 0, -0x7040(13) | |
| 28 | addis 5, 2, -1 | |
| 29 | addi 5, 5, -32 | |
| 30 | addi 12, 1, -32 | |
| 31 | nop | |
| 32 | cmpld 7, 12, 0 | |
| 33 | blt- 7, .Lwr_alloc_more | |
| 34 | .Lwr_body: | |
| 35 | mflr 0 | |
| 36 | std 0, 16(1) | |
| 37 | stdu 1, -32(1) | |
| 38 | bl nss_callee | |
| 39 | addi 1, 1, 32 | |
| 40 | ld 0, 16(1) | |
| 41 | mtlr 0 | |
| 42 | blr | |
| 43 | .Lwr_alloc_more: | |
| 44 | mflr 0 | |
| 45 | std 0, 16(1) | |
| 46 | bl __morestack | |
| 47 | ld 0, 16(1) | |
| 48 | mtlr 0 | |
| 49 | blr | |
| 50 | b .Lwr_body | |
| 51 | .size wrong_regs, .-wrong_regs | |
| 52 | ||
| 53 | .section .note.GNU-split-stack,"",@progbits |
deps/lld/test/ELF/ppc64-split-stack-adjust-overflow.s created+64| ... | ... | @@ -0,0 +1,64 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-no-split-stack.s -o %t2.o | |
| 5 | ||
| 6 | # RUN: not ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 2>&1 | \ | |
| 7 | # RUN: FileCheck -check-prefix=OVERFLOW %s | |
| 8 | # RUN: not ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 \ | |
| 9 | # RUN: -split-stack-adjust-size 4097 2>&1 | FileCheck -check-prefix=OVERFLOW %s | |
| 10 | # RUN: ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 -split-stack-adjust-size 4096 | |
| 11 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 12 | ||
| 13 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t1.o | |
| 14 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-no-split-stack.s -o %t2.o | |
| 15 | ||
| 16 | # RUN: not ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 2>&1 | \ | |
| 17 | # RUN: FileCheck -check-prefix=OVERFLOW %s | |
| 18 | # RUN: not ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 \ | |
| 19 | # RUN: -split-stack-adjust-size 4097 2>&1 | FileCheck -check-prefix=OVERFLOW %s | |
| 20 | # RUN: ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 -split-stack-adjust-size 4096 | |
| 21 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 22 | ||
| 23 | # OVERFLOW: error: {{.*}}.o:(function caller: .text+0x8): split-stack prologue adjustment overflows | |
| 24 | ||
| 25 | .p2align 2 | |
| 26 | .global caller | |
| 27 | .type caller, @function | |
| 28 | caller: | |
| 29 | .Lcaller_gep: | |
| 30 | addis 2, 12, .TOC.-.Lcaller_gep@ha | |
| 31 | addi 2, 2, .TOC.-.Lcaller_gep@l | |
| 32 | .localentry caller, .-caller | |
| 33 | ld 0, -0x7040(13) | |
| 34 | addis 12, 1, -32768 | |
| 35 | addi 12, 12, 4096 | |
| 36 | cmpld 7, 12, 0 | |
| 37 | blt- 7, .Lcaller_alloc_more | |
| 38 | .Lcaller_body: | |
| 39 | mflr 0 | |
| 40 | std 0, 16(1) | |
| 41 | stdu 1, -32(1) | |
| 42 | bl nss_callee | |
| 43 | addi 1, 1, 32 | |
| 44 | ld 0, 16(1) | |
| 45 | mtlr 0 | |
| 46 | blr | |
| 47 | .Lcaller_alloc_more: | |
| 48 | mflr 0 | |
| 49 | std 0, 16(1) | |
| 50 | bl __morestack | |
| 51 | ld 0, 16(1) | |
| 52 | mtlr 0 | |
| 53 | blr | |
| 54 | b .Lcaller_body | |
| 55 | .size caller, .-caller | |
| 56 | ||
| 57 | # CHECK-LABEL: caller | |
| 58 | # CHECK: ld 0, -28736(13) | |
| 59 | # CHECK-NEXT: addis 12, 1, -32768 | |
| 60 | # CHECK-NEXT: nop | |
| 61 | # CHECK-NEXT: cmpld 7, 12, 0 | |
| 62 | # CHECK-NEXT: bt- 28, .+36 | |
| 63 | ||
| 64 | .section .note.GNU-split-stack,"",@progbits |
deps/lld/test/ELF/ppc64-split-stack-adjust-size-success.s created+108| ... | ... | @@ -0,0 +1,108 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-no-split-stack.s -o %t2.o | |
| 5 | ||
| 6 | # RUN: ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 -split-stack-adjust-size 32768 | |
| 7 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 8 | # RUN: ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 -split-stack-adjust-size 4096 | |
| 9 | # RUN: llvm-objdump -d %t | FileCheck %s -check-prefix=SMALL | |
| 10 | # RUN: ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 -split-stack-adjust-size 0 | |
| 11 | # RUN: llvm-objdump -d %t | FileCheck %s -check-prefix=ZERO | |
| 12 | # RUN: not ld.lld %t1.o %t2.o -o %t -split-stack-adjust-size -1 2>&1 | FileCheck %s -check-prefix=ERR | |
| 13 | # ERR: error: --split-stack-adjust-size: size must be >= 0 | |
| 14 | ||
| 15 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t1.o | |
| 16 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-no-split-stack.s -o %t2.o | |
| 17 | ||
| 18 | # RUN: ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 -split-stack-adjust-size 32768 | |
| 19 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 20 | # RUN: ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 -split-stack-adjust-size 4096 | |
| 21 | # RUN: llvm-objdump -d %t | FileCheck %s -check-prefix=SMALL | |
| 22 | # RUN: ld.lld %t1.o %t2.o -o %t --defsym __morestack=0x10010000 -split-stack-adjust-size 0 | |
| 23 | # RUN: llvm-objdump -d %t | FileCheck %s -check-prefix=ZERO | |
| 24 | .p2align 2 | |
| 25 | .global caller | |
| 26 | .type caller, @function | |
| 27 | caller: | |
| 28 | .Lcaller_gep: | |
| 29 | addis 2, 12, .TOC.-.Lcaller_gep@ha | |
| 30 | addi 2, 2, .TOC.-.Lcaller_gep@l | |
| 31 | .localentry caller, .-caller | |
| 32 | ld 0, -0x7040(13) | |
| 33 | addi 12, 1, -32 | |
| 34 | nop | |
| 35 | cmpld 7, 12, 0 | |
| 36 | blt- 7, .Lcaller_alloc_more | |
| 37 | .Lcaller_body: | |
| 38 | mflr 0 | |
| 39 | std 0, 16(1) | |
| 40 | stdu 1, -32(1) | |
| 41 | bl nss_callee | |
| 42 | addi 1, 1, 32 | |
| 43 | ld 0, 16(1) | |
| 44 | mtlr 0 | |
| 45 | blr | |
| 46 | .Lcaller_alloc_more: | |
| 47 | mflr 0 | |
| 48 | std 0, 16(1) | |
| 49 | bl __morestack | |
| 50 | ld 0, 16(1) | |
| 51 | mtlr 0 | |
| 52 | blr | |
| 53 | b .Lcaller_body | |
| 54 | .size caller, .-caller | |
| 55 | ||
| 56 | # CHECK-LABEL: caller | |
| 57 | # CHECK: ld 0, -28736(13) | |
| 58 | # CHECK-NEXT: addis 12, 1, -1 | |
| 59 | # CHECK-NEXT: addi 12, 12, 32736 | |
| 60 | # CHECK-NEXT: cmpld 7, 12, 0 | |
| 61 | # CHECK-NEXT: bt- 28, .+36 | |
| 62 | ||
| 63 | # SMALL-LABEL: caller | |
| 64 | # SMALL: ld 0, -28736(13) | |
| 65 | # SMALL-NEXT: addi 12, 1, -4128 | |
| 66 | # SMALL-NEXT: nop | |
| 67 | # SMALL-NEXT: cmpld 7, 12, 0 | |
| 68 | # SMALL-NEXT: bt- 28, .+36 | |
| 69 | ||
| 70 | # ZERO-LABEL: caller | |
| 71 | # ZERO: ld 0, -28736(13) | |
| 72 | # ZERO-NEXT: addi 12, 1, -32 | |
| 73 | # ZERO-NEXT: nop | |
| 74 | # ZERO-NEXT: cmpld 7, 12, 0 | |
| 75 | # ZERO-NEXT: bt- 28, .+36 | |
| 76 | .p2align 2 | |
| 77 | .global main | |
| 78 | 	.type main, @function | |
| 79 | main: | |
| 80 | .Lmain_gep: | |
| 81 | addis 2,12,.TOC.-.Lmain_gep@ha | |
| 82 | addi 2,2,.TOC.-.Lmain_gep@l | |
| 83 | .localentry	main,.-main | |
| 84 | ld 0,-0x7040(13) | |
| 85 | addi 12,1,-32 | |
| 86 | nop | |
| 87 | cmpld 7,12,0 | |
| 88 | blt- 7, .Lmain_morestack | |
| 89 | .Lmain_body: | |
| 90 | mflr 0 | |
| 91 | std 0, 16(1) | |
| 92 | stdu 1, -32(1) | |
| 93 | bl caller | |
| 94 | addi 1, 1, 32 | |
| 95 | ld 0, 16(1) | |
| 96 | mtlr 0 | |
| 97 | blr | |
| 98 | .Lmain_morestack: | |
| 99 | mflr 0 | |
| 100 | std 0, 16(1) | |
| 101 | bl __morestack | |
| 102 | ld 0, 16(1) | |
| 103 | mtlr 0 | |
| 104 | blr | |
| 105 | b .Lmain_body | |
| 106 | .size main,.-main | |
| 107 | ||
| 108 | .section .note.GNU-split-stack,"",@progbits |
deps/lld/test/ELF/ppc64-split-stack-prologue-adjust-success.s created+224| ... | ... | @@ -0,0 +1,224 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-no-split-stack.s -o %t2.o | |
| 5 | # RUN: ld.lld --defsym __morestack=0x10010000 %t1.o %t2.o -o %t | |
| 6 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 7 | ||
| 8 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t1.o | |
| 9 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-no-split-stack.s -o %t2.o | |
| 10 | # RUN: ld.lld --defsym __morestack=0x10010000 %t1.o %t2.o -o %t | |
| 11 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 12 | ||
| 13 | .abiversion 2 | |
| 14 | .section ".text" | |
| 15 | ||
| 16 | ||
| 17 | # A caller with a stack that is small enough that the addis instruction | |
| 18 | # from the split-stack prologue is unneeded, and after the prologue adjustment | |
| 19 | # the stack size still fits whithin 16 bits. | |
| 20 | .p2align 2 | |
| 21 | .global caller_small_stack | |
| 22 | .type caller_small_stack, @function | |
| 23 | caller_small_stack: | |
| 24 | .Lcss_gep: | |
| 25 | addis 2, 12, .TOC.-.Lcss_gep@ha | |
| 26 | addi 2, 2, .TOC.-.Lcss_gep@l | |
| 27 | .localentry caller_small_stack, .-caller_small_stack | |
| 28 | ld 0, -0x7040(13) | |
| 29 | addi 12, 1, -32 | |
| 30 | nop | |
| 31 | cmpld 7, 12, 0 | |
| 32 | blt- 7, .Lcss_alloc_more | |
| 33 | .Lcss_body: | |
| 34 | mflr 0 | |
| 35 | std 0, 16(1) | |
| 36 | stdu 1, -32(1) | |
| 37 | bl nss_callee | |
| 38 | addi 1, 1, 32 | |
| 39 | ld 0, 16(1) | |
| 40 | mtlr 0 | |
| 41 | blr | |
| 42 | .Lcss_alloc_more: | |
| 43 | mflr 0 | |
| 44 | std 0, 16(1) | |
| 45 | bl __morestack | |
| 46 | ld 0, 16(1) | |
| 47 | mtlr 0 | |
| 48 | blr | |
| 49 | b .Lcss_body | |
| 50 | .size caller_small_stack, .-caller_small_stack | |
| 51 | ||
| 52 | # CHECK-LABEL: caller_small_stack | |
| 53 | # CHECK: ld 0, -28736(13) | |
| 54 | # CHECK-NEXT: addi 12, 1, -16416 | |
| 55 | # CHECK-NEXT: nop | |
| 56 | # CHECK-NEXT: cmpld 7, 12, 0 | |
| 57 | # CHECK-NEXT: bt- 28, .+36 | |
| 58 | ||
| 59 | # A caller that has a stack size that fits whithin 16 bits, but the adjusted | |
| 60 | # stack size after prologue adjustment now overflows 16 bits needing both addis | |
| 61 | # and addi instructions. | |
| 62 | .p2align 2 | |
| 63 | .global caller_med_stack | |
| 64 | .type caller_med_stack, @function | |
| 65 | caller_med_stack: | |
| 66 | .Lcms_gep: | |
| 67 | addis 2, 12, .TOC.-.Lcms_gep@ha | |
| 68 | addi 12, 12, .TOC.-.Lcms_gep@l | |
| 69 | .localentry caller_med_stack, .-caller_med_stack | |
| 70 | ld 0, -0x7040(13) | |
| 71 | addi 12, 1, -32764 | |
| 72 | nop | |
| 73 | cmpld 7, 12, 0 | |
| 74 | blt- 7, .Lcms_alloc_more | |
| 75 | .Lcms_body: | |
| 76 | mflr 0 | |
| 77 | std 0, 16(1) | |
| 78 | stdu 1, -32764(1) | |
| 79 | bl nss_callee | |
| 80 | addi 1, 1, 32764 | |
| 81 | ld 0, 16(1) | |
| 82 | mtlr 0 | |
| 83 | blr | |
| 84 | .Lcms_alloc_more: | |
| 85 | mflr 0 | |
| 86 | std 0, 16(1) | |
| 87 | bl __morestack | |
| 88 | ld 0, 16(1) | |
| 89 | mtlr 0 | |
| 90 | blr | |
| 91 | b .Lcms_body | |
| 92 | .size caller_med_stack, .-caller_med_stack | |
| 93 | ||
| 94 | # A caller with a large enough stack frame that both the addis and | |
| 95 | # addi instructions are used in the split-stack prologue. | |
| 96 | .p2align 2 | |
| 97 | .global caller_large_stack | |
| 98 | .type caller_large_stack, @function | |
| 99 | caller_large_stack: | |
| 100 | .Lcls_gep: | |
| 101 | addis 2, 12, .TOC.-.Lcls_gep@ha | |
| 102 | addi 12, 12, .TOC.-.Lcls_gep@l | |
| 103 | .localentry caller_large_stack, .-caller_large_stack | |
| 104 | ld 0, -0x7040(13) | |
| 105 | addis 12, 1, -1 | |
| 106 | addi 12, 12, -32 | |
| 107 | cmpld 7, 12, 0 | |
| 108 | blt- 7, .Lcls_alloc_more | |
| 109 | .Lcls_body: | |
| 110 | mflr 0 | |
| 111 | std 0, 16(1) | |
| 112 | lis 0, -1 | |
| 113 | addi 0, 0, -32 | |
| 114 | stdux 1, 0, 1 | |
| 115 | bl nss_callee | |
| 116 | ld 1, 0(1) | |
| 117 | ld 0, 16(1) | |
| 118 | mtlr 0 | |
| 119 | blr | |
| 120 | .Lcls_alloc_more: | |
| 121 | mflr 0 | |
| 122 | std 0, 16(1) | |
| 123 | bl __morestack | |
| 124 | ld 0, 16(1) | |
| 125 | mtlr 0 | |
| 126 | blr | |
| 127 | b .Lcls_body | |
| 128 | .size caller_large_stack, .-caller_large_stack | |
| 129 | ||
| 130 | # CHECK-LABEL: caller_large_stack | |
| 131 | # CHECK: ld 0, -28736(13) | |
| 132 | # CHECK-NEXT: addis 12, 1, -1 | |
| 133 | # CHECK-NEXT: addi 12, 12, -16416 | |
| 134 | # CHECK-NEXT: cmpld 7, 12, 0 | |
| 135 | # CHECK-NEXT: bt- 28, .+44 | |
| 136 | ||
| 137 | # A caller with a stack size that is larger then 16 bits, but aligned such that | |
| 138 | # the addi instruction is unneeded. | |
| 139 | .p2align 2 | |
| 140 | .global caller_large_aligned_stack | |
| 141 | .type caller_large_aligned_stack, @function | |
| 142 | caller_large_aligned_stack: | |
| 143 | .Lclas_gep: | |
| 144 | addis 2, 12, .TOC.-.Lclas_gep@ha | |
| 145 | addi 12, 12, .TOC.-.Lclas_gep@l | |
| 146 | .localentry caller_large_aligned_stack, .-caller_large_aligned_stack | |
| 147 | ld 0, -0x7040(13) | |
| 148 | addis 12, 1, -2 | |
| 149 | nop | |
| 150 | cmpld 7, 12, 0 | |
| 151 | blt- 7, .Lclas_alloc_more | |
| 152 | .Lclas_body: | |
| 153 | mflr 0 | |
| 154 | std 0, 16(1) | |
| 155 | lis 0, -2 | |
| 156 | stdux 1, 0, 1 | |
| 157 | bl nss_callee | |
| 158 | ld 1, 0(1) | |
| 159 | ld 0, 16(1) | |
| 160 | mtlr 0 | |
| 161 | blr | |
| 162 | .Lclas_alloc_more: | |
| 163 | mflr 0 | |
| 164 | std 0, 16(1) | |
| 165 | bl __morestack | |
| 166 | ld 0, 16(1) | |
| 167 | mtlr 0 | |
| 168 | blr | |
| 169 | b .Lclas_body | |
| 170 | .size caller_large_aligned_stack, .-caller_large_aligned_stack | |
| 171 | ||
| 172 | # CHECK-LABEL: caller_large_aligned_stack | |
| 173 | # CHECK: ld 0, -28736(13) | |
| 174 | # CHECK-NEXT: addis 12, 1, -2 | |
| 175 | # CHECK-NEXT: addi 12, 12, -16384 | |
| 176 | # CHECK-NEXT: cmpld 7, 12, 0 | |
| 177 | # CHECK-NEXT: bt- 28, .+40 | |
| 178 | ||
| 179 | # main only calls split-stack functions or __morestack so | |
| 180 | # there should be no adjustment of its split-stack prologue. | |
| 181 | .p2align 2 | |
| 182 | .global main | |
| 183 | 	.type main, @function | |
| 184 | main: | |
| 185 | .Lmain_gep: | |
| 186 | addis 2, 12,.TOC.-.Lmain_gep@ha | |
| 187 | addi 2, 2,.TOC.-.Lmain_gep@l | |
| 188 | .localentry	main,.-main | |
| 189 | ld 0, -0x7040(13) | |
| 190 | addi 12,1,-32 | |
| 191 | nop | |
| 192 | cmpld 7, 12,0 | |
| 193 | blt- 7, .Lmain_morestack | |
| 194 | .Lmain_body: | |
| 195 | mflr 0 | |
| 196 | std 0, 16(1) | |
| 197 | stdu 1, -32(1) | |
| 198 | bl caller_small_stack | |
| 199 | nop | |
| 200 | bl caller_med_stack | |
| 201 | nop | |
| 202 | bl caller_large_stack | |
| 203 | nop | |
| 204 | bl caller_large_aligned_stack | |
| 205 | addi 1, 1, 32 | |
| 206 | ld 0, 16(1) | |
| 207 | mtlr 0 | |
| 208 | blr | |
| 209 | .Lmain_morestack: | |
| 210 | mflr 0 | |
| 211 | std 0, 16(1) | |
| 212 | bl __morestack | |
| 213 | ld 0, 16(1) | |
| 214 | mtlr 0 | |
| 215 | blr | |
| 216 | b .Lmain_body | |
| 217 | .size main,.-main | |
| 218 | # CHECK-LABEL: main | |
| 219 | # CHECK: ld 0, -28736(13) | |
| 220 | # CHECK-NEXT: addi 12, 1, -32 | |
| 221 | # CHECK-NEXT: nop | |
| 222 | # CHECK-NEXT: cmpld 7, 12, 0 | |
| 223 | ||
| 224 | .section .note.GNU-split-stack,"",@progbits |
deps/lld/test/ELF/ppc64-tls-gd-le-small.s created+61| ... | ... | @@ -0,0 +1,61 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | # RUN: llvm-objdump -d -r %t.o | FileCheck --check-prefix=CHECK-INPUT %s | |
| 5 | # RUN: ld.lld --defsym __tls_get_addr=0x10001000 %t.o -o %t | |
| 6 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=CHECK-DIS %s | |
| 7 | # RUN: llvm-readelf -relocations %t | FileCheck --check-prefix=DYN-RELOCS %s | |
| 8 | ||
| 9 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o | |
| 10 | # RUN: llvm-objdump -d -r %t.o | FileCheck --check-prefix=CHECK-INPUT %s | |
| 11 | # RUN: ld.lld --defsym __tls_get_addr=0x10001000 %t.o -o %t | |
| 12 | # RUN: llvm-objdump -d %t | FileCheck --check-prefix=CHECK-DIS %s | |
| 13 | # RUN: llvm-readelf -relocations %t | FileCheck --check-prefix=DYN-RELOCS %s | |
| 14 | ||
| 15 | # Test checks the relaxation of a 'small' general-dynamic tls access into a | |
| 16 | # local-exec tls access. | |
| 17 | ||
| 18 | .text | |
| 19 | .abiversion 2 | |
| 20 | ||
| 21 | .global test | |
| 22 | .p2align 4 | |
| 23 | .type test, @function | |
| 24 | ||
| 25 | test: | |
| 26 | .Lgep: | |
| 27 | addis 2, 12, .TOC.-.Lgep@ha | |
| 28 | addi 2, 2, .TOC.-.Lgep@l | |
| 29 | .localentry test, .-test | |
| 30 | mflr 0 | |
| 31 | std 0, 16(1) | |
| 32 | stdu 1, -32(1) | |
| 33 | addi 3, 2, a@got@tlsgd | |
| 34 | bl __tls_get_addr(a@tlsgd) | |
| 35 | nop | |
| 36 | lwz 3, 0(3) | |
| 37 | addi 1, 1, 32 | |
| 38 | ld 0, 16(1) | |
| 39 | mtlr 0 | |
| 40 | blr | |
| 41 | ||
| 42 | .type a, @object | |
| 43 | .section .tdata,"awT",@progbits | |
| 44 | .global a | |
| 45 | .p2align 2 | |
| 46 | a: | |
| 47 | .long 55 | |
| 48 | .size a, 4 | |
| 49 | ||
| 50 | # CHECK-INPUT: addi 3, 2, 0 | |
| 51 | # CHECK-INPUT-NEXT: R_PPC64_GOT_TLSGD16 a | |
| 52 | # CHECK-INPUT-NEXT: bl .+0 | |
| 53 | # CHECK-INPUT-NEXT: R_PPC64_TLSGD a | |
| 54 | # CHECK-INPUT-NEXT: R_PPC64_REL24 __tls_get_addr | |
| 55 | ||
| 56 | # CHECK-DIS: addis 3, 13, 0 | |
| 57 | # CHECK-DIS-NEXT: nop | |
| 58 | # CHECK-DIS-NEXT: addi 3, 3, -28672 | |
| 59 | # CHECK-DIS-NEXT: lwz 3, 0(3) | |
| 60 | ||
| 61 | # DYN-RELOCS: There are no relocations in this file |
deps/lld/test/ELF/ppc64-tls-gd-le.s+6-6| ... | ... | @@ -1,16 +1,16 @@ |
| 1 | 1 | // REQUIRES: ppc |
| 2 | 2 | |
| 3 | 3 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o |
| 4 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 4 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 5 | 5 | // RUN: ld.lld %t.o -o %t |
| 6 | // RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 7 | // RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s | |
| 6 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 7 | // RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 8 | 8 | |
| 9 | 9 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o |
| 10 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 10 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 11 | 11 | // RUN: ld.lld %t.o -o %t |
| 12 | // RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 13 | // RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s | |
| 12 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 13 | // RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 14 | 14 | |
| 15 | 15 | 	.text |
| 16 | 16 | 	.abiversion 2 |
deps/lld/test/ELF/ppc64-tls-ie-le.s created+140| ... | ... | @@ -0,0 +1,140 @@ |
| 1 | // REQUIRES: ppc | |
| 2 | ||
| 3 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-tls-ie-le.s -o %t2.o | |
| 5 | // RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.o -o %t | |
| 6 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 7 | // RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 8 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 9 | ||
| 10 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o | |
| 11 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-tls-ie-le.s -o %t2.o | |
| 12 | // RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.o -o %t | |
| 13 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 14 | // RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 15 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 16 | ||
| 17 | 	.text | |
| 18 | 	.abiversion 2 | |
| 19 | test1: # @test1 | |
| 20 | 	addis 3, 2, c@got@tprel@ha | |
| 21 | 	ld 3, c@got@tprel@l(3) | |
| 22 | 	lbzx 3, 3, c@tls | |
| 23 | 	blr | |
| 24 | test2: # @test2 | |
| 25 | 	addis 3, 2, s@got@tprel@ha | |
| 26 | 	ld 3, s@got@tprel@l(3) | |
| 27 | 	lhzx 3, 3, s@tls | |
| 28 | 	blr | |
| 29 | test3: # @test3 | |
| 30 | 	addis 3, 2, i@got@tprel@ha | |
| 31 | 	ld 3, i@got@tprel@l(3) | |
| 32 | 	lwzx 3, 3, i@tls | |
| 33 | 	blr | |
| 34 | test4: # @test4 | |
| 35 | 	addis 3, 2, l@got@tprel@ha | |
| 36 | 	ld 3, l@got@tprel@l(3) | |
| 37 | 	ldx 3, 3, l@tls | |
| 38 | 	blr | |
| 39 | test5: # @test5 | |
| 40 | 	addis 4, 2, c@got@tprel@ha | |
| 41 | 	ld 4, c@got@tprel@l(4) | |
| 42 | 	stbx 3, 4, c@tls | |
| 43 | 	blr | |
| 44 | test6: # @test6 | |
| 45 | 	addis 4, 2, s@got@tprel@ha | |
| 46 | 	ld 4, s@got@tprel@l(4) | |
| 47 | 	sthx 3, 4, s@tls | |
| 48 | 	blr | |
| 49 | test7: # @test7 | |
| 50 | 	addis 4, 2, i@got@tprel@ha | |
| 51 | 	ld 4, i@got@tprel@l(4) | |
| 52 | 	stwx 3, 4, i@tls | |
| 53 | 	blr | |
| 54 | test8: # @test8 | |
| 55 | 	addis 4, 2, l@got@tprel@ha | |
| 56 | 	ld 4, l@got@tprel@l(4) | |
| 57 | 	stdx 3, 4, l@tls | |
| 58 | 	blr | |
| 59 | test9: # @test9 | |
| 60 | 	addis 3, 2, i@got@tprel@ha | |
| 61 | 	ld 3, i@got@tprel@l(3) | |
| 62 | 	add 3, 3, i@tls | |
| 63 | 	blr | |
| 64 | test_ds: # @test_ds | |
| 65 | 	ld 4, l@got@tprel(2) | |
| 66 | 	stdx 3, 4, l@tls | |
| 67 | 	blr | |
| 68 | ||
| 69 | ||
| 70 | // Verify that the input has initial-exec tls relocation types. | |
| 71 | // InputRelocs: Relocation section '.rela.text' | |
| 72 | // InputRelocs: R_PPC64_GOT_TPREL16_HA {{0+}} c + 0 | |
| 73 | // InputRelocs: R_PPC64_GOT_TPREL16_LO_DS {{0+}} c + 0 | |
| 74 | // InputRelocs: R_PPC64_TLS {{0+}} c + 0 | |
| 75 | // InputRelocs: R_PPC64_GOT_TPREL16_HA {{0+}} s + 0 | |
| 76 | // InputRelocs: R_PPC64_GOT_TPREL16_LO_DS {{0+}} s + 0 | |
| 77 | // InputRelocs: R_PPC64_TLS {{0+}} s + 0 | |
| 78 | // InputRelocs: R_PPC64_GOT_TPREL16_HA {{0+}} i + 0 | |
| 79 | // InputRelocs: R_PPC64_GOT_TPREL16_LO_DS {{0+}} i + 0 | |
| 80 | // InputRelocs: R_PPC64_TLS {{0+}} i + 0 | |
| 81 | // InputRelocs: R_PPC64_GOT_TPREL16_HA {{0+}} l + 0 | |
| 82 | // InputRelocs: R_PPC64_GOT_TPREL16_LO_DS {{0+}} l + 0 | |
| 83 | // InputRelocs: R_PPC64_TLS {{0+}} l + 0 | |
| 84 | // InputRelocs: R_PPC64_GOT_TPREL16_DS {{0+}} l + 0 | |
| 85 | // InputRelocs: R_PPC64_TLS {{0+}} l + 0 | |
| 86 | ||
| 87 | // Verify that no initial-exec relocations exist for the dynamic linker. | |
| 88 | // OutputRelocs-NOT: R_PPC64_TPREL64 {{0+}} c + 0 | |
| 89 | // OutputRelocs-NPT: R_PPC64_TPREL64 {{0+}} s + 0 | |
| 90 | // OutputRelocs-NOT: R_PPC64_TPREL64 {{0+}} i + 0 | |
| 91 | // OutputRelocs-NOT: R_PPC64_TPREL64 {{0+}} l + 0 | |
| 92 | ||
| 93 | // Dis: test1: | |
| 94 | // Dis: nop | |
| 95 | // Dis: addis 3, 13, 0 | |
| 96 | // Dis: lbz 3, -28672(3) | |
| 97 | ||
| 98 | // Dis: test2: | |
| 99 | // Dis: nop | |
| 100 | // Dis: addis 3, 13, 0 | |
| 101 | // Dis: lhz 3, -28670(3) | |
| 102 | ||
| 103 | // Dis: test3: | |
| 104 | // Dis: nop | |
| 105 | // Dis: addis 3, 13, 0 | |
| 106 | // Dis: lwz 3, -28668(3) | |
| 107 | ||
| 108 | // Dis: test4: | |
| 109 | // Dis: nop | |
| 110 | // Dis: addis 3, 13, 0 | |
| 111 | // Dis: ld 3, -28664(3) | |
| 112 | ||
| 113 | // Dis: test5: | |
| 114 | // Dis: nop | |
| 115 | // Dis: addis 4, 13, 0 | |
| 116 | // Dis: stb 3, -28672(4) | |
| 117 | ||
| 118 | // Dis: test6: | |
| 119 | // Dis: nop | |
| 120 | // Dis: addis 4, 13, 0 | |
| 121 | // Dis: sth 3, -28670(4) | |
| 122 | ||
| 123 | // Dis: test7: | |
| 124 | // Dis: nop | |
| 125 | // Dis: addis 4, 13, 0 | |
| 126 | // Dis: stw 3, -28668(4) | |
| 127 | ||
| 128 | // Dis: test8: | |
| 129 | // Dis: nop | |
| 130 | // Dis: addis 4, 13, 0 | |
| 131 | // Dis: std 3, -28664(4) | |
| 132 | ||
| 133 | // Dis: test9: | |
| 134 | // Dis: nop | |
| 135 | // Dis: addis 3, 13, 0 | |
| 136 | // Dis: addi 3, 3, -28668 | |
| 137 | ||
| 138 | // Dis: test_ds: | |
| 139 | // Dis: addis 4, 13, 0 | |
| 140 | // Dis: std 3, -28664(4) |
deps/lld/test/ELF/ppc64-tls-ld-le.s+6-6| ... | ... | @@ -1,16 +1,16 @@ |
| 1 | 1 | // REQUIRES: ppc |
| 2 | 2 | |
| 3 | 3 | // RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o |
| 4 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 4 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 5 | 5 | // RUN: ld.lld %t.o -o %t |
| 6 | // RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 7 | // RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s | |
| 6 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 7 | // RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 8 | 8 | |
| 9 | 9 | // RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o |
| 10 | // RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 10 | // RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 11 | 11 | // RUN: ld.lld %t.o -o %t |
| 12 | // RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 13 | // RUN: llvm-readelf -relocations --wide %t | FileCheck --check-prefix=OutputRelocs %s | |
| 12 | // RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s | |
| 13 | // RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s | |
| 14 | 14 | |
| 15 | 15 | 	.text |
| 16 | 16 | 	.abiversion 2 |
deps/lld/test/ELF/ppc64-toc-addis-nop-lqsq.s created+73| ... | ... | @@ -0,0 +1,73 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-readelf -relocations --wide %p/Inputs/ppc64le-quadword-ldst.o | FileCheck --check-prefix=QuadInputRelocs %s | |
| 4 | ||
| 5 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o | |
| 6 | # RUN: ld.lld -shared %t2.o -o %t2.so | |
| 7 | ||
| 8 | # RUN: ld.lld %t2.so %p/Inputs/ppc64le-quadword-ldst.o -o %t | |
| 9 | # RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 10 | ||
| 11 | # RUN: ld.lld --no-toc-optimize %t2.so %p/Inputs/ppc64le-quadword-ldst.o -o %t | |
| 12 | # RUN: llvm-objdump -D %t | FileCheck --check-prefix=NoOpt %s | |
| 13 | ||
| 14 | # QuadInputRelocs: Relocation section '.rela.text' | |
| 15 | # QuadInputRelocs: R_PPC64_TOC16_LO_DS 0000000000000000 quadLd | |
| 16 | # QuadInputRelocs: R_PPC64_TOC16_LO_DS 0000000000000010 quadSt | |
| 17 | ||
| 18 | # The powerpc backend doesn't support the quadword load/store instructions yet. | |
| 19 | # So they are tested by linking against an object file assembled with | |
| 20 | # `as -mpower9 -o ppc64le-quadword-ldst.o in.s` and checking the encoding of | |
| 21 | # the unknown instructions in the dissasembly. Source used as input: | |
| 22 | #quads: | |
| 23 | #.Lbegin_quads: | |
| 24 | #.Lgep_quads: | |
| 25 | # addis 2, 12, .TOC.-.Lgep_quads@ha | |
| 26 | # addi 2, 2, .TOC.-.Lgep_quads@l | |
| 27 | #.Llep_quads: | |
| 28 | #.localentry quads, .Llep_quads-.Lgep_quads | |
| 29 | # addis 3, 2, quadLd@toc@ha | |
| 30 | # lq 4, quadLd@toc@l(3) | |
| 31 | # addis 3, 2, quadSt@toc@ha | |
| 32 | # stq 4, quadSt@toc@l(3) | |
| 33 | # blr | |
| 34 | # | |
| 35 | # .p2align 4 | |
| 36 | # .global quadLd | |
| 37 | # .lcomm quadLd, 16 | |
| 38 | # | |
| 39 | # .global quadSt | |
| 40 | # .lcomm quadSt, 16 | |
| 41 | ||
| 42 | ||
| 43 | # e0 82 7f 70 decodes to | 111000 | 00100 | 00010 | 16-bit imm | | |
| 44 | # | 56 | 4 | 2 | 32624 | | |
| 45 | # which is `lq r4, 32624(r2)` | |
| 46 | # f8 82 7f 82 decodes to | 111110 | 00100 | 00010 | 14-bit imm | 10 | | |
| 47 | # | 62 | 4 | 2 | 8160 | 2 | | |
| 48 | # The immediate represents a word offset so this dissasembles to: | |
| 49 | # `stq r4, 32640(r2)` | |
| 50 | # Dis-LABEL: quads: | |
| 51 | # Dis-NEXT: addis | |
| 52 | # Dis-NEXT: addi | |
| 53 | # Dis-NEXT: nop | |
| 54 | # Dis-NEXT: 70 7f 82 e0 <unknown> | |
| 55 | # Dis-NEXT: nop | |
| 56 | # Dis-NEXT: 82 7f 82 f8 <unknown> | |
| 57 | # Dis-NEXT: blr | |
| 58 | ||
| 59 | # e0 83 7f 70 decodes to | 111000 | 00100 | 00011 | 16-bit imm | | |
| 60 | # | 56 | 4 | 3 | 32624 | | |
| 61 | # `lq r4, 32624(r3)` | |
| 62 | # f8 83 7f 82 decodes to | 111110 | 00100 | 00010 | 14-bit imm | 10 | | |
| 63 | # | 62 | 4 | 2 | 8160 | 2 | | |
| 64 | # `stq r4, 32640(r3)` | |
| 65 | # NoOpt-LABEL: quads: | |
| 66 | # NoOpt-NEXT: addis | |
| 67 | # NoOpt-NEXT: addi | |
| 68 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 69 | # NoOpt-NEXT: 70 7f 83 e0 <unknown> | |
| 70 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 71 | # NoOpt-NEXT: 82 7f 83 f8 <unknown> | |
| 72 | # NoOpt-NEXT: blr | |
| 73 |
deps/lld/test/ELF/ppc64-toc-addis-nop.s created+272| ... | ... | @@ -0,0 +1,272 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o | |
| 4 | # RUN: llvm-readelf -relocations --wide %t.o | FileCheck --check-prefix=InputRelocs %s | |
| 5 | ||
| 6 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o | |
| 7 | # RUN: ld.lld -shared %t2.o -o %t2.so | |
| 8 | # | |
| 9 | # RUN: ld.lld %t2.so %t.o -o %t | |
| 10 | # RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s | |
| 11 | # | |
| 12 | # RUN: ld.lld --no-toc-optimize %t2.so %t.o -o %t | |
| 13 | # RUN: llvm-objdump -D %t | FileCheck --check-prefix=NoOpt %s | |
| 14 | ||
| 15 | # InputRelocs: Relocation section '.rela.text' | |
| 16 | # InputRelocs: R_PPC64_TOC16_HA | |
| 17 | # InputRelocs: R_PPC64_TOC16_LO | |
| 18 | # InputRelocs: R_PPC64_TOC16_LO_DS | |
| 19 | ||
| 20 | ||
| 21 | .text | |
| 22 | 	.abiversion 2 | |
| 23 | ||
| 24 | .global bytes | |
| 25 | .p2align 4 | |
| 26 | .type bytes,@function | |
| 27 | bytes: | |
| 28 | .Lbytes_gep: | |
| 29 | addis 2, 12, .TOC.-.Lbytes_gep@ha | |
| 30 | addi 2, 2, .TOC.-.Lbytes_gep@l | |
| 31 | .Lbytes_lep: | |
| 32 | .localentry bytes, .Lbytes_lep-.Lbytes_gep | |
| 33 | addis 3, 2, byteLd@toc@ha | |
| 34 | lbz 3, byteLd@toc@l(3) | |
| 35 | addis 4, 2, byteSt@toc@ha | |
| 36 | stb 3, byteSt@toc@l(4) | |
| 37 | blr | |
| 38 | # Dis-LABEL: bytes | |
| 39 | # Dis-NEXT: addis | |
| 40 | # Dis-NEXT: addi | |
| 41 | # Dis-NEXT: nop | |
| 42 | # Dis-NEXT: lbz 3, 32624(2) | |
| 43 | # Dis-NEXT: nop | |
| 44 | # Dis-NEXT: stb 3, 32625(2) | |
| 45 | # Dis-NEXT: blr | |
| 46 | ||
| 47 | # NoOpt-LABEL: bytes | |
| 48 | # NoOpt-NEXT: addis | |
| 49 | # NoOpt-NEXT: addi | |
| 50 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 51 | # NoOpt-NEXT: lbz 3, 32624(3) | |
| 52 | # NoOpt-NEXT: addis 4, 2, 0 | |
| 53 | # NoOpt-NEXT: stb 3, 32625(4) | |
| 54 | # NoOpt-NEXT: blr | |
| 55 | ||
| 56 | .global halfs | |
| 57 | .p2align 4 | |
| 58 | .type halfs,@function | |
| 59 | halfs: | |
| 60 | .Lhalfs_gep: | |
| 61 | addis 2, 12, .TOC.-.Lhalfs_gep@ha | |
| 62 | addi 2, 2, .TOC.-.Lhalfs_gep@l | |
| 63 | .Lhalfs_lep: | |
| 64 | .localentry halfs, .Lhalfs_lep-.Lhalfs_gep | |
| 65 | addis 3, 2, halfLd@toc@ha | |
| 66 | lhz 3, halfLd@toc@l(3) | |
| 67 | addis 4, 2, halfLd@toc@ha | |
| 68 | lha 4, halfLd@toc@l(4) | |
| 69 | addis 5, 2, halfSt@toc@ha | |
| 70 | sth 4, halfSt@toc@l(5) | |
| 71 | blr | |
| 72 | # Dis-LABEL: halfs | |
| 73 | # Dis-NEXT: addis | |
| 74 | # Dis-NEXT: addi | |
| 75 | # Dis-NEXT: nop | |
| 76 | # Dis-NEXT: lhz 3, 32626(2) | |
| 77 | # Dis-NEXT: nop | |
| 78 | # Dis-NEXT: lha 4, 32626(2) | |
| 79 | # Dis-NEXT: nop | |
| 80 | # Dis-NEXT: sth 4, 32628(2) | |
| 81 | # Dis-NEXT: blr | |
| 82 | ||
| 83 | # NoOpt-LABEL: halfs | |
| 84 | # NoOpt-NEXT: addis | |
| 85 | # NoOpt-NEXT: addi | |
| 86 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 87 | # NoOpt-NEXT: lhz 3, 32626(3) | |
| 88 | # NoOpt-NEXT: addis 4, 2, 0 | |
| 89 | # NoOpt-NEXT: lha 4, 32626(4) | |
| 90 | # NoOpt-NEXT: addis 5, 2, 0 | |
| 91 | # NoOpt-NEXT: sth 4, 32628(5) | |
| 92 | # NoOpt-NEXT: blr | |
| 93 | ||
| 94 | ||
| 95 | .global words | |
| 96 | .p2align 4 | |
| 97 | .type words,@function | |
| 98 | words: | |
| 99 | .Lwords_gep: | |
| 100 | addis 2, 12, .TOC.-.Lwords_gep@ha | |
| 101 | addi 2, 2, .TOC.-.Lwords_gep@l | |
| 102 | .Lwords_lep: | |
| 103 | .localentry words, .Lwords_lep-.Lwords_gep | |
| 104 | addis 3, 2, wordLd@toc@ha | |
| 105 | lwz 3, wordLd@toc@l(3) | |
| 106 | addis 4, 2, wordLd@toc@ha | |
| 107 | lwa 4, wordLd@toc@l(4) | |
| 108 | addis 5, 2, wordSt@toc@ha | |
| 109 | stw 4, wordSt@toc@l(5) | |
| 110 | blr | |
| 111 | # Dis-LABEL: words | |
| 112 | # Dis-NEXT: addis | |
| 113 | # Dis-NEXT: addi | |
| 114 | # Dis-NEXT: nop | |
| 115 | # Dis-NEXT: lwz 3, 32632(2) | |
| 116 | # Dis-NEXT: nop | |
| 117 | # Dis-NEXT: lwa 4, 32632(2) | |
| 118 | # Dis-NEXT: nop | |
| 119 | # Dis-NEXT: stw 4, 32636(2) | |
| 120 | # Dis-NEXT: blr | |
| 121 | ||
| 122 | # NoOpt-LABEL: words | |
| 123 | # NoOpt-NEXT: addis | |
| 124 | # NoOpt-NEXT: addi | |
| 125 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 126 | # NoOpt-NEXT: lwz 3, 32632(3) | |
| 127 | # NoOpt-NEXT: addis 4, 2, 0 | |
| 128 | # NoOpt-NEXT: lwa 4, 32632(4) | |
| 129 | # NoOpt-NEXT: addis 5, 2, 0 | |
| 130 | # NoOpt-NEXT: stw 4, 32636(5) | |
| 131 | # NoOpt-NEXT: blr | |
| 132 | ||
| 133 | .global doublewords | |
| 134 | .p2align 4 | |
| 135 | .type doublewords,@function | |
| 136 | doublewords: | |
| 137 | .Ldoublewords_gep: | |
| 138 | addis 2, 12, .TOC.-.Ldoublewords_gep@ha | |
| 139 | addi 2, 2, .TOC.-.Ldoublewords_gep@l | |
| 140 | .Ldoublewords_lep: | |
| 141 | .localentry doublewords, .Ldoublewords_lep-.Ldoublewords_gep | |
| 142 | addis 3, 2, dwordLd@toc@ha | |
| 143 | ld 3, dwordLd@toc@l(3) | |
| 144 | addis 4, 2, dwordSt@toc@ha | |
| 145 | std 3, dwordSt@toc@l(4) | |
| 146 | blr | |
| 147 | ||
| 148 | # Dis-LABEL: doublewords | |
| 149 | # Dis-NEXT: addis | |
| 150 | # Dis-NEXT: addi | |
| 151 | # Dis-NEXT: nop | |
| 152 | # Dis-NEXT: ld 3, 32640(2) | |
| 153 | # Dis-NEXT: nop | |
| 154 | # Dis-NEXT: std 3, 32648(2) | |
| 155 | # Dis-NEXT: blr | |
| 156 | ||
| 157 | # NoOpt-LABEL: doublewords | |
| 158 | # NoOpt-NEXT: addis | |
| 159 | # NoOpt-NEXT: addi | |
| 160 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 161 | # NoOpt-NEXT: ld 3, 32640(3) | |
| 162 | # NoOpt-NEXT: addis 4, 2, 0 | |
| 163 | # NoOpt-NEXT: std 3, 32648(4) | |
| 164 | # NoOpt-NEXT: blr | |
| 165 | ||
| 166 | .global vec_dq | |
| 167 | .p2align 4 | |
| 168 | .type vec_dq,@function | |
| 169 | vec_dq: | |
| 170 | .Lvec_dq_gep: | |
| 171 | addis 2, 12, .TOC.-.Lvec_dq_gep@ha | |
| 172 | addi 2, 2, .TOC.-.Lvec_dq_gep@l | |
| 173 | .Lvec_dq_lep: | |
| 174 | .localentry vec_dq, .Lvec_dq_lep-.Lvec_dq_gep | |
| 175 | addis 3, 2, vecLd@toc@ha | |
| 176 | lxv 3, vecLd@toc@l(3) | |
| 177 | addis 3, 2, vecSt@toc@ha | |
| 178 | stxv 3, vecSt@toc@l(3) | |
| 179 | blr | |
| 180 | ||
| 181 | # Dis-LABEL: vec_dq | |
| 182 | # Dis-NEXT: addis | |
| 183 | # Dis-NEXT: addi | |
| 184 | # Dis-NEXT: nop | |
| 185 | # Dis-NEXT: lxv 3, 32656(2) | |
| 186 | # Dis-NEXT: nop | |
| 187 | # Dis-NEXT: stxv 3, 32672(2) | |
| 188 | # Dis-NEXT: blr | |
| 189 | ||
| 190 | # NoOpt-LABEL: vec_dq | |
| 191 | # NoOpt-NEXT: addis | |
| 192 | # NoOpt-NEXT: addi | |
| 193 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 194 | # NoOpt-NEXT: lxv 3, 32656(3) | |
| 195 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 196 | # NoOpt-NEXT: stxv 3, 32672(3) | |
| 197 | # NoOpt-NEXT: blr | |
| 198 | ||
| 199 | .global vec_ds | |
| 200 | .p2align 4 | |
| 201 | .type vec_ds,@function | |
| 202 | vec_ds: | |
| 203 | .Lvec_ds_gep: | |
| 204 | addis 2, 12, .TOC.-.Lvec_ds_gep@ha | |
| 205 | addi 2, 2, .TOC.-.Lvec_ds_gep@l | |
| 206 | .Lvec_ds_lep: | |
| 207 | .localentry vec_ds, .Lvec_dq_lep-.Lvec_dq_gep | |
| 208 | addis 3, 2, vecLd@toc@ha | |
| 209 | lxsd 3, vecLd@toc@l(3) | |
| 210 | addis 3, 2, vecSt@toc@ha | |
| 211 | stxsd 3, vecSt@toc@l(3) | |
| 212 | addis 3, 2, vecLd@toc@ha | |
| 213 | lxssp 3, vecLd@toc@l(3) | |
| 214 | addis 3, 2, vecSt@toc@ha | |
| 215 | stxssp 3, vecSt@toc@l(3) | |
| 216 | blr | |
| 217 | # Dis-LABEL: vec_ds | |
| 218 | # Dis-NEXT: addis | |
| 219 | # Dis-NEXT: addi | |
| 220 | # Dis-NEXT: nop | |
| 221 | # Dis-NEXT: lxsd 3, 32656(2) | |
| 222 | # Dis-NEXT: nop | |
| 223 | # Dis-NEXT: stxsd 3, 32672(2) | |
| 224 | # Dis-NEXT: nop | |
| 225 | # Dis-NEXT: lxssp 3, 32656(2) | |
| 226 | # Dis-NEXT: nop | |
| 227 | # Dis-NEXT: stxssp 3, 32672(2) | |
| 228 | # Dis-NEXT: blr | |
| 229 | ||
| 230 | # NoOpt-LABEL: vec_ds | |
| 231 | # NoOpt-NEXT: addis | |
| 232 | # NoOpt-NEXT: addi | |
| 233 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 234 | # NoOpt-NEXT: lxsd 3, 32656(3) | |
| 235 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 236 | # NoOpt-NEXT: stxsd 3, 32672(3) | |
| 237 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 238 | # NoOpt-NEXT: lxssp 3, 32656(3) | |
| 239 | # NoOpt-NEXT: addis 3, 2, 0 | |
| 240 | # NoOpt-NEXT: stxssp 3, 32672(3) | |
| 241 | # NoOpt-NEXT: blr | |
| 242 | ||
| 243 | ||
| 244 | .global byteLd | |
| 245 | .lcomm byteLd, 1, 1 | |
| 246 | ||
| 247 | .global byteSt | |
| 248 | .lcomm byteSt, 1, 1 | |
| 249 | ||
| 250 | .global halfLd | |
| 251 | .lcomm halfLd, 2, 2 | |
| 252 | ||
| 253 | .global halfSt | |
| 254 | .lcomm halfSt, 2, 2 | |
| 255 | ||
| 256 | .global wordLd | |
| 257 | .lcomm wordLd, 4, 4 | |
| 258 | ||
| 259 | .global wordSt | |
| 260 | .lcomm wordSt, 4, 4 | |
| 261 | ||
| 262 | .global dwordLd | |
| 263 | .lcomm dwordLd, 8, 8 | |
| 264 | ||
| 265 | .global dwordSt | |
| 266 | .lcomm dwordSt, 8, 8 | |
| 267 | ||
| 268 | .global vecLd | |
| 269 | .lcomm vecLd, 16, 16 | |
| 270 | ||
| 271 | .global vecSt | |
| 272 | .lcomm vecSt, 16, 16 |
deps/lld/test/ELF/ppc64-toc-rel.s+11-19| ... | ... | @@ -1,13 +1,15 @@ |
| 1 | 1 | # REQUIRES: ppc |
| 2 | 2 | |
| 3 | 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o |
| 4 | # RUN: llvm-readobj -relocations %t.o | FileCheck -check-prefix=RELOCS %s | |
| 4 | # RUN: llvm-readobj -relocations %t.o | FileCheck -check-prefix=RELOCS-LE %s | |
| 5 | 5 | # RUN: ld.lld %t.o -o %t2 |
| 6 | 6 | # RUN: llvm-objdump -D %t2 | FileCheck %s |
| 7 | # RUN: llvm-objdump -D %t2 | FileCheck -check-prefix=CHECK-LE %s | |
| 7 | 8 | |
| 8 | 9 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o |
| 9 | 10 | # RUN: llvm-readobj -relocations %t.o | FileCheck -check-prefix=RELOCS-BE %s |
| 10 | 11 | # RUN: ld.lld %t.o -o %t2 |
| 12 | # RUN: llvm-objdump -D %t2 | FileCheck %s | |
| 11 | 13 | # RUN: llvm-objdump -D %t2 | FileCheck -check-prefix=CHECK-BE %s |
| 12 | 14 | |
| 13 | 15 | # Make sure we calculate the offset correctly for a toc-relative access to a |
| ... | ... | @@ -45,15 +47,15 @@ _start: |
| 45 | 47 | |
| 46 | 48 | # Verify the relocations that get emitted for the global variable are the |
| 47 | 49 | # expected ones. |
| 48 | # RELOCS: Relocations [ | |
| 49 | # RELOCS-NEXT: .rela.text { | |
| 50 | # RELOCS: 0x8 R_PPC64_TOC16_HA global_a 0x0 | |
| 51 | # RELOCS: 0xC R_PPC64_TOC16_LO global_a 0x0 | |
| 50 | # RELOCS-LE: Relocations [ | |
| 51 | # RELOCS-LE-NEXT: .rela.text { | |
| 52 | # RELOCS-LE: 0x8 R_PPC64_TOC16_HA global_a 0x0 | |
| 53 | # RELOCS-LE: 0xC R_PPC64_TOC16_LO global_a 0x0 | |
| 52 | 54 | |
| 53 | 55 | # RELOCS-BE: Relocations [ |
| 54 | 56 | # RELOCS-BE-NEXT: .rela.text { |
| 55 | 57 | # RELOCS-BE: 0xA R_PPC64_TOC16_HA global_a 0x0 |
| 56 | # RELOCS-NE: 0xE R_PPC64_TOC16_LO global_a 0x0 | |
| 58 | # RELOCS-BE: 0xE R_PPC64_TOC16_LO global_a 0x0 | |
| 57 | 59 | |
| 58 | 60 | # Want to check _start for the values used to build the offset from the TOC base |
| 59 | 61 | # to global_a. The .TOC. symbol is expected at address 0x10030000, and the |
| ... | ... | @@ -70,19 +72,9 @@ _start: |
| 70 | 72 | # CHECK-NEXT: global_a: |
| 71 | 73 | # CHECK-NEXT: 10020000: {{.*}} |
| 72 | 74 | |
| 73 | # CHECK: Disassembly of section .got: | |
| 74 | # CHECK-NEXT: .got: | |
| 75 | # CHECK-NEXT: 10030000: 00 80 03 10 | |
| 76 | ||
| 77 | ||
| 78 | # CHECK-BE: Disassembly of section .text: | |
| 79 | # CHECK-BE-NEXT: _start: | |
| 80 | # CHECK-BE: 10010008: {{.*}} addis 3, 2, -1 | |
| 81 | # CHECK-BE-NEXT: 1001000c: {{.*}} addi 3, 3, -32768 | |
| 82 | ||
| 83 | # CHECK-BE: Disassembly of section .data: | |
| 84 | # CHECK-BE-NEXT: global_a: | |
| 85 | # CHECK-BE-NEXT: 10020000: {{.*}} | |
| 75 | # CHECK-LE: Disassembly of section .got: | |
| 76 | # CHECK-LE-NEXT: .got: | |
| 77 | # CHECK-LE-NEXT: 10030000: 00 80 03 10 | |
| 86 | 78 | |
| 87 | 79 | # CHECK-BE: Disassembly of section .got: |
| 88 | 80 | # CHECK-BE-NEXT: .got: |
deps/lld/test/ELF/ppc64-toc-restore-recursive-call.s created+52| ... | ... | @@ -0,0 +1,52 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o | |
| 4 | # RUN: ld.lld -shared %t1.o -o %t | |
| 5 | # RUN: llvm-objdump -d -r %t | FileCheck %s | |
| 6 | ||
| 7 | # For a recursive call that is interposable the linker calls the plt-stub rather | |
| 8 | # then calling the function directly. Since the call is through a plt stub and | |
| 9 | # might be interposed with a different definition at runtime, a toc-restore is | |
| 10 | # required to follow the call. | |
| 11 | ||
| 12 | # The decision to use a plt-stub for the recursive call is not one I feel | |
| 13 | # strongly about either way. It was done because it matches what bfd and gold do | |
| 14 | # for recursive calls as well as keeps the logic for recursive calls consistent | |
| 15 | # with non-recursive calls. | |
| 16 | ||
| 17 | # CHECK-LABEL: __plt_recursive_func: | |
| 18 | # CHECK-NEXT: 10000: | |
| 19 | # CHECK-LABEL: recursive_func | |
| 20 | # CHECK-NEXT: 10014: | |
| 21 | # CHECK: 1003c: {{[0-9a-fA-F ]+}} bl .+67108804 | |
| 22 | # CHECK-NEXT: ld 2, 24(1) | |
| 23 | ||
| 24 | .abiversion 2 | |
| 25 | .section ".text" | |
| 26 | .p2align 2 | |
| 27 | .global recursive_func | |
| 28 | .type recursive_func, @function | |
| 29 | recursive_func: | |
| 30 | .Lrf_gep: | |
| 31 | addis 2, 12, .TOC.-.Lrf_gep@ha | |
| 32 | addi 2, 2, .TOC.-.Lrf_gep@l | |
| 33 | .localentry recursive_func, .-recursive_func | |
| 34 | cmpldi 3, 2 | |
| 35 | blt 0, .Lend | |
| 36 | ||
| 37 | mflr 0 | |
| 38 | std 0, 16(1) | |
| 39 | stdu 1, -32(1) | |
| 40 | addi 5, 3, -1 | |
| 41 | mulld 4, 4, 3 | |
| 42 | mr 3, 5 | |
| 43 | bl recursive_func | |
| 44 | nop | |
| 45 | mr 4, 3 | |
| 46 | addi 1, 1, 32 | |
| 47 | ld 0, 16(1) | |
| 48 | mtlr 0 | |
| 49 | ||
| 50 | .Lend: | |
| 51 | extsw 3, 4 | |
| 52 | blr |
deps/lld/test/ELF/ppc64-toc-restore.s+1-1| ... | ... | @@ -22,7 +22,7 @@ bar_local: |
| 22 | 22 | blr |
| 23 | 23 | |
| 24 | 24 | # Calling external function foo in a shared object needs a nop. |
| 25 | # Calling local function bar_local doe snot need a nop. | |
| 25 | # Calling local function bar_local doe not need a nop. | |
| 26 | 26 | .global _start |
| 27 | 27 | _start: |
| 28 | 28 | bl foo |
deps/lld/test/ELF/ppc64-tocopt-option.s created+14| ... | ... | @@ -0,0 +1,14 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t | |
| 4 | # RUN: not ld.lld %t --toc-optimize -o /dev/null 2>&1 | FileCheck %s | |
| 5 | ||
| 6 | # CHECK: error: --toc-optimize is only supported on the PowerPC64 target | |
| 7 | ||
| 8 | .global __start | |
| 9 | .type __start,@function | |
| 10 | ||
| 11 | .text | |
| 12 | .quad 0 | |
| 13 | __start: | |
| 14 |
deps/lld/test/ELF/ppc64_entry_point.s deleted-50| ... | ... | @@ -1,50 +0,0 @@ |
| 1 | # REQUIRES: ppc | |
| 2 | ||
| 3 | # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t | |
| 4 | # RUN: ld.lld %t -o %t2 | |
| 5 | # RUN: llvm-objdump -D %t2 | FileCheck %s | |
| 6 | ||
| 7 | # RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t | |
| 8 | # RUN: ld.lld %t -o %t2 | |
| 9 | # RUN: llvm-objdump -D %t2 | FileCheck -check-prefix=CHECK-BE %s | |
| 10 | ||
| 11 | .text | |
| 12 | .abiversion 2 | |
| 13 | .globl _start | |
| 14 | .p2align 4 | |
| 15 | .type _start,@function | |
| 16 | ||
| 17 | _start: | |
| 18 | .Lfunc_begin0: | |
| 19 | .Lfunc_gep0: | |
| 20 | lis 4, .Lfunc_gep0@ha | |
| 21 | addi 4, 4, .Lfunc_gep0@l | |
| 22 | # now r4 should contain the address of _start | |
| 23 | ||
| 24 | lis 5, .TOC.-.Lfunc_gep0@ha | |
| 25 | addi 5, 5, .TOC.-.Lfunc_gep0@l | |
| 26 | # now r5 should contain the offset s.t. r4 + r5 = TOC base | |
| 27 | ||
| 28 | # exit 55 | |
| 29 | li 0, 1 | |
| 30 | li 3, 55 | |
| 31 | sc | |
| 32 | .Lfunc_end0: | |
| 33 | .size _start, .Lfunc_end0-.Lfunc_begin0 | |
| 34 | ||
| 35 | // CHECK: 10010000: {{.*}} lis 4, 4097 | |
| 36 | // CHECK-NEXT: 10010004: {{.*}} addi 4, 4, 0 | |
| 37 | // CHECK-NEXT: 10010008: {{.*}} lis 5, 2 | |
| 38 | // CHECK-NEXT: 1001000c: {{.*}} addi 5, 5, -32768 | |
| 39 | // CHECK: Disassembly of section .got: | |
| 40 | // CHECK-NEXT: .got: | |
| 41 | // CHECK-NEXT: 10020000: 00 80 02 10 | |
| 42 | ||
| 43 | // CHECK-BE: 10010000: {{.*}} lis 4, 4097 | |
| 44 | // CHECK-BE-NEXT: 10010004: {{.*}} addi 4, 4, 0 | |
| 45 | // CHECK-BE-NEXT: 10010008: {{.*}} lis 5, 2 | |
| 46 | // CHECK-BE-NEXT: 1001000c: {{.*}} addi 5, 5, -32768 | |
| 47 | // CHECK-BE: Disassembly of section .got: | |
| 48 | // CHECK-BE-NEXT: .got: | |
| 49 | // CHECK-BE-NEXT: 10020000: 00 00 00 00 {{.*}} | |
| 50 | // CHECK-BE-NEXT: 10020004: 10 02 80 00 {{.*}} |
deps/lld/test/ELF/pr34660.s+1-1| ... | ... | @@ -3,7 +3,7 @@ |
| 3 | 3 | # RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o |
| 4 | 4 | # RUN: ld.lld --hash-style=sysv -shared %t.o -o %t |
| 5 | 5 | # RUN: llvm-objdump %t -d | FileCheck %s --check-prefix=DISASM |
| 6 | # RUN: llvm-readelf %t -t | FileCheck %s --check-prefix=SYM | |
| 6 | # RUN: llvm-readelf %t --symbols | FileCheck %s --check-prefix=SYM | |
| 7 | 7 | |
| 8 | 8 | # It would be much easier to understand/read this test if llvm-objdump would print |
| 9 | 9 | # the immediates in hex. |
deps/lld/test/ELF/progname.s+1-1| ... | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | // RUN: ld.lld -dynamic-list %t.dynlist -o %t %t.o %t.so |
| 18 | 18 | // RUN: llvm-readobj -dyn-symbols %t | FileCheck %s |
| 19 | 19 | |
| 20 | // CHECK: Name: __progname@ | |
| 20 | // CHECK: Name: __progname | |
| 21 | 21 | // CHECK-NEXT: Value: 0x201000 |
| 22 | 22 | // CHECK-NEXT: Size: 0 |
| 23 | 23 | // CHECK-NEXT: Binding: Global (0x1) |
deps/lld/test/ELF/protected-shared.s+2-2| ... | ... | @@ -32,7 +32,7 @@ bar: |
| 32 | 32 | |
| 33 | 33 | // CHECK: DynamicSymbols [ |
| 34 | 34 | // CHECK-NEXT: Symbol { |
| 35 | // CHECK-NEXT: Name: @ | |
| 35 | // CHECK-NEXT: Name: | |
| 36 | 36 | // CHECK-NEXT: Value: 0x0 |
| 37 | 37 | // CHECK-NEXT: Size: 0 |
| 38 | 38 | // CHECK-NEXT: Binding: Local (0x0) |
| ... | ... | @@ -41,7 +41,7 @@ bar: |
| 41 | 41 | // CHECK-NEXT: Section: Undefined (0x0) |
| 42 | 42 | // CHECK-NEXT: } |
| 43 | 43 | // CHECK-NEXT: Symbol { |
| 44 | // CHECK-NEXT: Name: foo@ | |
| 44 | // CHECK-NEXT: Name: foo | |
| 45 | 45 | // CHECK-NEXT: Value: 0x0 |
| 46 | 46 | // CHECK-NEXT: Size: 0 |
| 47 | 47 | // CHECK-NEXT: Binding: Global |
deps/lld/test/ELF/push-state.s+3| ... | ... | @@ -32,5 +32,8 @@ |
| 32 | 32 | // RUN: ld.lld -o %t.exe -L%t.dir -push-state -static -pop-state %t1.o -lfoo |
| 33 | 33 | // RUN: not ld.lld -o %t.exe -L%t.dir -push-state -static %t1.o -lfoo |
| 34 | 34 | |
| 35 | // RUN: not ld.lld -o %t.exe -pop-state %t.a %t1.o -M 2>&1 | FileCheck -check-prefix=ERR %s | |
| 36 | // ERR: error: unbalanced --push-state/--pop-state | |
| 37 | ||
| 35 | 38 | .globl _start |
| 36 | 39 | _start: |
deps/lld/test/ELF/relative-dynamic-reloc-ppc64.s+2-2| ... | ... | @@ -32,7 +32,7 @@ |
| 32 | 32 | |
| 33 | 33 | // CHECK: DynamicSymbols [ |
| 34 | 34 | // CHECK-NEXT: Symbol { |
| 35 | // CHECK-NEXT: Name: @ | |
| 35 | // CHECK-NEXT: Name: | |
| 36 | 36 | // CHECK-NEXT: Value: 0x0 |
| 37 | 37 | // CHECK-NEXT: Size: 0 |
| 38 | 38 | // CHECK-NEXT: Binding: Local |
| ... | ... | @@ -41,7 +41,7 @@ |
| 41 | 41 | // CHECK-NEXT: Section: Undefined |
| 42 | 42 | // CHECK-NEXT: } |
| 43 | 43 | // CHECK-NEXT: Symbol { |
| 44 | // CHECK-NEXT: Name: external@ | |
| 44 | // CHECK-NEXT: Name: external | |
| 45 | 45 | // CHECK-NEXT: Value: 0x0 |
| 46 | 46 | // CHECK-NEXT: Size: 0 |
| 47 | 47 | // CHECK-NEXT: Binding: Global |
deps/lld/test/ELF/relative-dynamic-reloc.s+2-2| ... | ... | @@ -28,7 +28,7 @@ |
| 28 | 28 | |
| 29 | 29 | // CHECK: DynamicSymbols [ |
| 30 | 30 | // CHECK-NEXT: Symbol { |
| 31 | // CHECK-NEXT: Name: @ | |
| 31 | // CHECK-NEXT: Name: | |
| 32 | 32 | // CHECK-NEXT: Value: 0x0 |
| 33 | 33 | // CHECK-NEXT: Size: 0 |
| 34 | 34 | // CHECK-NEXT: Binding: Local |
| ... | ... | @@ -37,7 +37,7 @@ |
| 37 | 37 | // CHECK-NEXT: Section: Undefined |
| 38 | 38 | // CHECK-NEXT: } |
| 39 | 39 | // CHECK-NEXT: Symbol { |
| 40 | // CHECK-NEXT: Name: external@ | |
| 40 | // CHECK-NEXT: Name: external | |
| 41 | 41 | // CHECK-NEXT: Value: 0x0 |
| 42 | 42 | // CHECK-NEXT: Size: 0 |
| 43 | 43 | // CHECK-NEXT: Binding: Global |
deps/lld/test/ELF/relocatable-bss.s+1-1| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | # CHECK-NEXT: Version: |
| 21 | 21 | # CHECK-NEXT: Entry: |
| 22 | 22 | # CHECK-NEXT: ProgramHeaderOffset: |
| 23 | # CHECK-NEXT: SectionHeaderOffset: 0xD8 | |
| 23 | # CHECK-NEXT: SectionHeaderOffset: 0xE8 | |
| 24 | 24 | # CHECK-NEXT: Flags [ |
| 25 | 25 | # CHECK-NEXT: ] |
| 26 | 26 | # CHECK-NEXT: HeaderSize: |
deps/lld/test/ELF/relocatable-comdat-multiple.s+2-2| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | # CHECK-NEXT: Group { |
| 9 | 9 | # CHECK-NEXT: Name: .group |
| 10 | 10 | # CHECK-NEXT: Index: 2 |
| 11 | # CHECK-NEXT: Link: 8 | |
| 11 | # CHECK-NEXT: Link: 9 | |
| 12 | 12 | # CHECK-NEXT: Info: 1 |
| 13 | 13 | # CHECK-NEXT: Type: COMDAT |
| 14 | 14 | # CHECK-NEXT: Signature: aaa |
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | # CHECK-NEXT: Group { |
| 21 | 21 | # CHECK-NEXT: Name: .group |
| 22 | 22 | # CHECK-NEXT: Index: 5 |
| 23 | # CHECK-NEXT: Link: 8 | |
| 23 | # CHECK-NEXT: Link: 9 | |
| 24 | 24 | # CHECK-NEXT: Info: 6 |
| 25 | 25 | # CHECK-NEXT: Type: COMDAT |
| 26 | 26 | # CHECK-NEXT: Signature: bbb |
deps/lld/test/ELF/relocatable-comdat.s+1-1| ... | ... | @@ -30,7 +30,7 @@ |
| 30 | 30 | # CHECK-NEXT: Group { |
| 31 | 31 | # CHECK-NEXT: Name: .group |
| 32 | 32 | # CHECK-NEXT: Index: 2 |
| 33 | # CHECK-NEXT: Link: 5 | |
| 33 | # CHECK-NEXT: Link: 6 | |
| 34 | 34 | # CHECK-NEXT: Info: 1 |
| 35 | 35 | # CHECK-NEXT: Type: COMDAT |
| 36 | 36 | # CHECK-NEXT: Signature: abc |
deps/lld/test/ELF/relocatable-comdat2.s+2-2| ... | ... | @@ -13,7 +13,7 @@ |
| 13 | 13 | # CHECK-NEXT: Group { |
| 14 | 14 | # CHECK-NEXT: Name: .group |
| 15 | 15 | # CHECK-NEXT: Index: 2 |
| 16 | # CHECK-NEXT: Link: 7 | |
| 16 | # CHECK-NEXT: Link: 8 | |
| 17 | 17 | # CHECK-NEXT: Info: 1 |
| 18 | 18 | # CHECK-NEXT: Type: COMDAT |
| 19 | 19 | # CHECK-NEXT: Signature: bar |
| ... | ... | @@ -24,7 +24,7 @@ |
| 24 | 24 | # CHECK-NEXT: Group { |
| 25 | 25 | # CHECK-NEXT: Name: .group |
| 26 | 26 | # CHECK-NEXT: Index: 4 |
| 27 | # CHECK-NEXT: Link: 7 | |
| 27 | # CHECK-NEXT: Link: 8 | |
| 28 | 28 | # CHECK-NEXT: Info: 2 |
| 29 | 29 | # CHECK-NEXT: Type: COMDAT |
| 30 | 30 | # CHECK-NEXT: Signature: zed |
deps/lld/test/ELF/relocatable-compressed-input.s+1-1| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | # RUN: ld.lld %t1 -o %t2 -r |
| 8 | 8 | # RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s |
| 9 | 9 | |
| 10 | ## Check we decompress section and remove ".z" prefix specific for zlib-gnu compression. | |
| 10 | ## Check we uncompress section and remove ".z" prefix specific for zlib-gnu compression. | |
| 11 | 11 | # CHECK: Section { |
| 12 | 12 | # CHECK: Index: |
| 13 | 13 | # CHECK: Name: .debug_str |
deps/lld/test/ELF/relocatable-many-sections.s+10-8| ... | ... | @@ -9,8 +9,8 @@ |
| 9 | 9 | ## sections amount is greater than SHN_LORESERVE. |
| 10 | 10 | # RUN: llvm-readobj -file-headers %t | FileCheck %s --check-prefix=HDR |
| 11 | 11 | # HDR: ElfHeader { |
| 12 | # HDR: SectionHeaderCount: 0 (65543) | |
| 13 | # HDR-NEXT: StringTableSectionIndex: 65535 (65541) | |
| 12 | # HDR: SectionHeaderCount: 0 (65544) | |
| 13 | # HDR-NEXT: StringTableSectionIndex: 65535 (65542) | |
| 14 | 14 | |
| 15 | 15 | ## Check that: |
| 16 | 16 | ## 1) 65541 is the index of .shstrtab section. |
| ... | ... | @@ -18,13 +18,15 @@ |
| 18 | 18 | ## 3) .symtab_shndxr entry size and alignment == 4. |
| 19 | 19 | ## 4) .symtab_shndxr has size equal to |
| 20 | 20 | ## (sizeof(.symtab) / entsize(.symtab)) * entsize(.symtab_shndxr) = 0x4 * 0x180048 / 0x18 == 0x04000c |
| 21 | ||
| 21 | 22 | # RUN: llvm-readelf -sections -symbols %t | FileCheck %s |
| 22 | ## [Nr] Name Type Address Off Size ES Flg Lk Inf Al | |
| 23 | # CHECK: [65538] .bar | |
| 24 | # CHECK-NEXT: [65539] .symtab SYMTAB 0000000000000000 000040 180078 18 65542 65539 8 | |
| 25 | # CHECK-NEXT: [65540] .symtab_shndxr SYMTAB SECTION INDICES 0000000000000000 1800b8 040014 04 65539 0 4 | |
| 26 | # CHECK-NEXT: [65541] .shstrtab STRTAB 0000000000000000 1c00cc 0f0035 00 0 0 1 | |
| 27 | # CHECK-NEXT: [65542] .strtab STRTAB 0000000000000000 2b0101 00000c 00 | |
| 23 | # [Nr] Name Type Address Off Size ES Flg Lk Inf Al | |
| 24 | # CHECK: [65539] .note.GNU-stack PROGBITS 0000000000000000 000040 000000 00 0 0 1 | |
| 25 | # CHECK: [65540] .symtab SYMTAB 0000000000000000 000040 180078 18 65543 65539 8 | |
| 26 | # CHECK: [65541] .symtab_shndxr SYMTAB SECTION INDICES 0000000000000000 1800b8 040014 04 65540 0 4 | |
| 27 | # CHECK: [65542] .shstrtab STRTAB 0000000000000000 1c00cc 0f0045 00 0 0 1 | |
| 28 | # CHECK: [65543] .strtab STRTAB 0000000000000000 2b0111 00000c 00 0 0 1 | |
| 29 | ||
| 28 | 30 | # 5) Check we are able to represent symbol foo with section (.bar) index > 0xFF00 (SHN_LORESERVE). |
| 29 | 31 | # CHECK: GLOBAL DEFAULT 65538 foo |
| 30 | 32 |
deps/lld/test/ELF/relocatable-rel-iplt.s created+56| ... | ... | @@ -0,0 +1,56 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=i686-- %s -o %t1.o | |
| 3 | # RUN: ld.lld -r %t1.o -o %t2.o | |
| 4 | # RUN: llvm-readobj -t %t2.o | FileCheck %s | |
| 5 | ||
| 6 | // CHECK: Symbols [ | |
| 7 | // CHECK-NEXT: Symbol { | |
| 8 | // CHECK-NEXT: Name: (0) | |
| 9 | // CHECK-NEXT: Value: 0x0 | |
| 10 | // CHECK-NEXT: Size: 0 | |
| 11 | // CHECK-NEXT: Binding: Local (0x0) | |
| 12 | // CHECK-NEXT: Type: None (0x0) | |
| 13 | // CHECK-NEXT: Other: 0 | |
| 14 | // CHECK-NEXT: Section: Undefined (0x0) | |
| 15 | // CHECK-NEXT: } | |
| 16 | // CHECK-NEXT: Symbol { | |
| 17 | // CHECK-NEXT: Name: (0) | |
| 18 | // CHECK-NEXT: Value: 0x0 | |
| 19 | // CHECK-NEXT: Size: 0 | |
| 20 | // CHECK-NEXT: Binding: Local (0x0) | |
| 21 | // CHECK-NEXT: Type: Section (0x3) | |
| 22 | // CHECK-NEXT: Other: 0 | |
| 23 | // CHECK-NEXT: Section: .text (0x1) | |
| 24 | // CHECK-NEXT: } | |
| 25 | // CHECK-NEXT: Symbol { | |
| 26 | // CHECK-NEXT: Name: __rel_iplt_end (1) | |
| 27 | // CHECK-NEXT: Value: 0x0 | |
| 28 | // CHECK-NEXT: Size: 0 | |
| 29 | // CHECK-NEXT: Binding: Weak (0x2) | |
| 30 | // CHECK-NEXT: Type: None (0x0) | |
| 31 | // CHECK-NEXT: Other [ (0x2) | |
| 32 | // CHECK-NEXT: STV_HIDDEN (0x2) | |
| 33 | // CHECK-NEXT: ] | |
| 34 | // CHECK-NEXT: Section: Undefined (0x0) | |
| 35 | // CHECK-NEXT: } | |
| 36 | // CHECK-NEXT: Symbol { | |
| 37 | // CHECK-NEXT: Name: __rel_iplt_start (16) | |
| 38 | // CHECK-NEXT: Value: 0x0 | |
| 39 | // CHECK-NEXT: Size: 0 | |
| 40 | // CHECK-NEXT: Binding: Weak (0x2) | |
| 41 | // CHECK-NEXT: Type: None (0x0) | |
| 42 | // CHECK-NEXT: Other [ (0x2) | |
| 43 | // CHECK-NEXT: STV_HIDDEN (0x2) | |
| 44 | // CHECK-NEXT: ] | |
| 45 | // CHECK-NEXT: Section: Undefined (0x0) | |
| 46 | // CHECK-NEXT: } | |
| 47 | // CHECK-NEXT: ] | |
| 48 | ||
| 49 | 	movl	__rel_iplt_start, %eax | |
| 50 | 	movl	__rel_iplt_end, %eax | |
| 51 | 	ret | |
| 52 | ||
| 53 | 	.hidden	__rel_iplt_start | |
| 54 | 	.hidden	__rel_iplt_end | |
| 55 | 	.weak	__rel_iplt_start | |
| 56 | 	.weak	__rel_iplt_end |
deps/lld/test/ELF/relocatable.s+14-2| ... | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable2.s -o %t3.o |
| 5 | 5 | # RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t |
| 6 | 6 | # RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s |
| 7 | # RUN: llvm-objdump -section-headers %t | FileCheck -check-prefix=SECTION %s | |
| 7 | 8 | # RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s |
| 8 | 9 | |
| 9 | 10 | ## Test --relocatable alias |
| ... | ... | @@ -37,8 +38,8 @@ |
| 37 | 38 | # CHECK-NEXT: ProgramHeaderEntrySize: 0 |
| 38 | 39 | # CHECK-NEXT: ProgramHeaderCount: 0 |
| 39 | 40 | # CHECK-NEXT: SectionHeaderEntrySize: 64 |
| 40 | # CHECK-NEXT: SectionHeaderCount: 7 | |
| 41 | # CHECK-NEXT: StringTableSectionIndex: 5 | |
| 41 | # CHECK-NEXT: SectionHeaderCount: 8 | |
| 42 | # CHECK-NEXT: StringTableSectionIndex: 6 | |
| 42 | 43 | # CHECK-NEXT: } |
| 43 | 44 | |
| 44 | 45 | # CHECK: Relocations [ |
| ... | ... | @@ -51,6 +52,17 @@ |
| 51 | 52 | # CHECK-NEXT: 0x4E R_X86_64_32S yyy 0x0 |
| 52 | 53 | # CHECK-NEXT: } |
| 53 | 54 | |
| 55 | # SECTION: Sections: | |
| 56 | # SECTION: Idx Name Size Address Type | |
| 57 | # SECTION: 0 00000000 0000000000000000 | |
| 58 | # SECTION: 1 .text 00000056 0000000000000000 TEXT | |
| 59 | # SECTION: 2 .rela.text 00000090 0000000000000000 | |
| 60 | # SECTION: 3 .bss 00000018 0000000000000000 BSS | |
| 61 | # SECTION: 4 .note.GNU-stack 00000000 0000000000000000 | |
| 62 | # SECTION: 5 .symtab 00000168 0000000000000000 | |
| 63 | # SECTION: 6 .shstrtab 00000041 0000000000000000 | |
| 64 | # SECTION: 7 .strtab 0000002d 0000000000000000 | |
| 65 | ||
| 54 | 66 | # CHECKTEXT: Disassembly of section .text: |
| 55 | 67 | # CHECKTEXT-NEXT: main: |
| 56 | 68 | # CHECKTEXT-NEXT: 0: c7 04 25 00 00 00 00 05 00 00 00 movl $5, 0 |
deps/lld/test/ELF/relocation-b-aarch64.test+2-2| ... | ... | @@ -9,9 +9,9 @@ |
| 9 | 9 | |
| 10 | 10 | # CHECK: Disassembly of section .text: |
| 11 | 11 | # CHECK-NEXT: foo: |
| 12 | # CHECK-NEXT: 20000: 01 00 00 14 b #4 | |
| 12 | # CHECK-NEXT: 210000: 01 00 00 14 b #4 | |
| 13 | 13 | # CHECK: bar: |
| 14 | # CHECK-NEXT: 20004: ff ff ff 17 b #-4 | |
| 14 | # CHECK-NEXT: 210004: ff ff ff 17 b #-4 | |
| 15 | 15 | |
| 16 | 16 | !ELF |
| 17 | 17 | FileHeader: |
deps/lld/test/ELF/relocation-before-merge-start.s created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux | |
| 3 | // RUN: not ld.lld %t.o -o /dev/null -shared 2>&1 | FileCheck %s | |
| 4 | // CHECK: relocation-before-merge-start.s.tmp.o:(.foo): offset is outside the section | |
| 5 | ||
| 6 | .data | |
| 7 | .long .foo - 1 | |
| 8 | .section	.foo,"aM",@progbits,4 | |
| 9 | .quad 0 |
deps/lld/test/ELF/relocation-common.s+6-6| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | |
| 3 | // RUN: ld.lld %t -o %tout | |
| 4 | // RUN: llvm-objdump -t -d %tout | FileCheck %s | |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 3 | # RUN: ld.lld %t.o -o %t | |
| 4 | # RUN: llvm-objdump -t -d %t | FileCheck %s | |
| 5 | 5 | |
| 6 | 6 | .global _start |
| 7 | 7 | _start: |
| ... | ... | @@ -10,5 +10,5 @@ _start: |
| 10 | 10 | .global sym1 |
| 11 | 11 | .comm sym1,4,4 |
| 12 | 12 | |
| 13 | // CHECK: 201000: {{.*}} movl $1, 4086(%rip) | |
| 14 | // CHECK: 0000000000202000 g .bss 00000004 sym1 | |
| 13 | # CHECK: 201000: {{.*}} movl $1, 4086(%rip) | |
| 14 | # CHECK: 0000000000202000 g O .bss 00000004 sym1 |
deps/lld/test/ELF/relocation-copy-i686.s+7-7| ... | ... | @@ -21,7 +21,7 @@ movl $9, z |
| 21 | 21 | // CHECK-NEXT: SHF_ALLOC |
| 22 | 22 | // CHECK-NEXT: SHF_WRITE |
| 23 | 23 | // CHECK-NEXT: ] |
| 24 | // CHECK-NEXT: Address: 0x13000 | |
| 24 | // CHECK-NEXT: Address: 0x403000 | |
| 25 | 25 | // CHECK-NEXT: Offset: |
| 26 | 26 | // CHECK-NEXT: Size: 24 |
| 27 | 27 | // CHECK-NEXT: Link: 0 |
| ... | ... | @@ -52,12 +52,12 @@ movl $9, z |
| 52 | 52 | // CHECK-NEXT: } |
| 53 | 53 | // CHECK-NEXT: ] |
| 54 | 54 | |
| 55 | // 77824 = 0x13000 | |
| 55 | // 4206592 = 0x403000 | |
| 56 | 56 | // 16 is alignment here |
| 57 | // 77840 = 0x13000 + 16 | |
| 58 | // 77844 = 0x13000 + 16 + 4 | |
| 57 | // 4206608 = 0x403000 + 16 | |
| 58 | // 4206612 = 0x403000 + 16 + 4 | |
| 59 | 59 | // CODE: Disassembly of section .text: |
| 60 | 60 | // CODE-NEXT: main: |
| 61 | // CODE-NEXT: 11000: c7 05 00 30 01 00 05 00 00 00 movl $5, 77824 | |
| 62 | // CODE-NEXT: 1100a: c7 05 10 30 01 00 07 00 00 00 movl $7, 77840 | |
| 63 | // CODE-NEXT: 11014: c7 05 14 30 01 00 09 00 00 00 movl $9, 77844 | |
| 61 | // CODE-NEXT: 401000: c7 05 00 30 40 00 05 00 00 00 movl $5, 4206592 | |
| 62 | // CODE-NEXT: 40100a: c7 05 10 30 40 00 07 00 00 00 movl $7, 4206608 | |
| 63 | // CODE-NEXT: 401014: c7 05 14 30 40 00 09 00 00 00 movl $9, 4206612 |
deps/lld/test/ELF/relocation-i686.s+15-15| ... | ... | @@ -27,14 +27,14 @@ R_386_PC32_2: |
| 27 | 27 | |
| 28 | 28 | // CHECK: Disassembly of section .R_386_32: |
| 29 | 29 | // CHECK-NEXT: R_386_32: |
| 30 | // CHECK-NEXT: 11000: {{.*}} movl $69633, %edx | |
| 30 | // CHECK-NEXT: 401000: {{.*}} movl $4198401, %edx | |
| 31 | 31 | |
| 32 | 32 | // CHECK: Disassembly of section .R_386_PC32: |
| 33 | 33 | // CHECK-NEXT: R_386_PC32: |
| 34 | // CHECK-NEXT: 11005: e8 04 00 00 00 calll 4 | |
| 34 | // CHECK-NEXT: 401005: e8 04 00 00 00 calll 4 | |
| 35 | 35 | |
| 36 | 36 | // CHECK: R_386_PC32_2: |
| 37 | // CHECK-NEXT: 1100e: 90 nop | |
| 37 | // CHECK-NEXT: 40100e: 90 nop | |
| 38 | 38 | |
| 39 | 39 | // Create a .got |
| 40 | 40 | movl bar@GOT, %eax |
| ... | ... | @@ -45,7 +45,7 @@ movl bar@GOT, %eax |
| 45 | 45 | // ADDR-NEXT: SHF_ALLOC |
| 46 | 46 | // ADDR-NEXT: SHF_EXECINSTR |
| 47 | 47 | // ADDR-NEXT: ] |
| 48 | // ADDR-NEXT: Address: 0x11040 | |
| 48 | // ADDR-NEXT: Address: 0x401040 | |
| 49 | 49 | // ADDR-NEXT: Offset: 0x1040 |
| 50 | 50 | // ADDR-NEXT: Size: 32 |
| 51 | 51 | |
| ... | ... | @@ -55,7 +55,7 @@ movl bar@GOT, %eax |
| 55 | 55 | // ADDR-NEXT: SHF_ALLOC |
| 56 | 56 | // ADDR-NEXT: SHF_WRITE |
| 57 | 57 | // ADDR-NEXT: ] |
| 58 | // ADDR-NEXT: Address: 0x13078 | |
| 58 | // ADDR-NEXT: Address: 0x403078 | |
| 59 | 59 | // ADDR-NEXT: Offset: |
| 60 | 60 | // ADDR-NEXT: Size: 8 |
| 61 | 61 | |
| ... | ... | @@ -63,18 +63,18 @@ movl bar@GOT, %eax |
| 63 | 63 | R_386_GOTPC: |
| 64 | 64 | movl $_GLOBAL_OFFSET_TABLE_, %eax |
| 65 | 65 | |
| 66 | // 0x12078 + 8 - 0x11014 = 4204 | |
| 66 | // 0x402078 + 8 - 0x401014 = 4204 | |
| 67 | 67 | |
| 68 | 68 | // CHECK: Disassembly of section .R_386_GOTPC: |
| 69 | 69 | // CHECK-NEXT: R_386_GOTPC: |
| 70 | // CHECK-NEXT: 11014: {{.*}} movl $8300, %eax | |
| 70 | // CHECK-NEXT: 401014: {{.*}} movl $8300, %eax | |
| 71 | 71 | |
| 72 | 72 | .section .dynamic_reloc, "ax",@progbits |
| 73 | 73 | call bar |
| 74 | // addr(.plt) + 16 - (0x11019 + 5) = 50 | |
| 74 | // addr(.plt) + 16 - (0x401019 + 5) = 50 | |
| 75 | 75 | // CHECK: Disassembly of section .dynamic_reloc: |
| 76 | 76 | // CHECK-NEXT: .dynamic_reloc: |
| 77 | // CHECK-NEXT: 11019: e8 32 00 00 00 calll 50 | |
| 77 | // CHECK-NEXT: 401019: e8 32 00 00 00 calll 50 | |
| 78 | 78 | |
| 79 | 79 | .section .R_386_GOT32,"ax",@progbits |
| 80 | 80 | .global R_386_GOT32 |
| ... | ... | @@ -84,13 +84,13 @@ R_386_GOT32: |
| 84 | 84 | movl bar+8@GOT, %eax |
| 85 | 85 | movl zed+4@GOT, %eax |
| 86 | 86 | |
| 87 | // 4294967288 = 0xFFFFFFF8 = got[0](0x12070) - .got(0x12070) - sizeof(.got)(8) | |
| 88 | // 4294967292 = 0xFFFFFFFC = got[1](0x12074) - .got(0x12070) - sizeof(.got)(8) | |
| 87 | // 4294967288 = 0xFFFFFFF8 = got[0](0x402070) - .got(0x402070) - sizeof(.got)(8) | |
| 88 | // 4294967292 = 0xFFFFFFFC = got[1](0x402074) - .got(0x402070) - sizeof(.got)(8) | |
| 89 | 89 | // 0xFFFFFFF8 + 8 = 0 |
| 90 | 90 | // 0xFFFFFFFC + 4 = 0 |
| 91 | 91 | // CHECK: Disassembly of section .R_386_GOT32: |
| 92 | 92 | // CHECK-NEXT: R_386_GOT32: |
| 93 | // CHECK-NEXT: 1101e: a1 f8 ff ff ff movl 4294967288, %eax | |
| 94 | // CHECK-NEXT: 11023: a1 fc ff ff ff movl 4294967292, %eax | |
| 95 | // CHECK-NEXT: 11028: a1 00 00 00 00 movl 0, %eax | |
| 96 | // CHECK-NEXT: 1102d: a1 00 00 00 00 movl 0, %eax | |
| 93 | // CHECK-NEXT: 40101e: a1 f8 ff ff ff movl 4294967288, %eax | |
| 94 | // CHECK-NEXT: 401023: a1 fc ff ff ff movl 4294967292, %eax | |
| 95 | // CHECK-NEXT: 401028: a1 00 00 00 00 movl 0, %eax | |
| 96 | // CHECK-NEXT: 40102d: a1 00 00 00 00 movl 0, %eax |
deps/lld/test/ELF/relocation-past-merge-end.s+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | // REQUIRES: x86 |
| 2 | 2 | // RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux |
| 3 | 3 | // RUN: not ld.lld %t.o -o /dev/null -shared 2>&1 | FileCheck %s |
| 4 | // CHECK: relocation-past-merge-end.s.tmp.o:(.foo): entry is past the end of the section | |
| 4 | // CHECK: relocation-past-merge-end.s.tmp.o:(.foo): offset is outside the section | |
| 5 | 5 | |
| 6 | 6 | .data |
| 7 | 7 | .long .foo + 10 |
deps/lld/test/ELF/relocation-size-shared.s+1-14| ... | ... | @@ -28,20 +28,7 @@ |
| 28 | 28 | // DISASM-NEXT: 20100c: 00 00 |
| 29 | 29 | // DISASM-NEXT: 20100e: 00 00 |
| 30 | 30 | // DISASM-NEXT: 201010: 1b 00 |
| 31 | // DISASM-NEXT: 201012: 00 00 | |
| 32 | // DISASM-NEXT: 201014: 00 00 | |
| 33 | // DISASM-NEXT: 201016: 00 00 | |
| 34 | // DISASM-NEXT: 201018: 00 00 | |
| 35 | // DISASM-NEXT: 20101a: 00 00 | |
| 36 | // DISASM-NEXT: 20101c: 00 00 | |
| 37 | // DISASM-NEXT: 20101e: 00 00 | |
| 38 | // DISASM-NEXT: 201020: 00 00 | |
| 39 | // DISASM-NEXT: 201022: 00 00 | |
| 40 | // DISASM-NEXT: 201024: 00 00 | |
| 41 | // DISASM-NEXT: 201026: 00 00 | |
| 42 | // DISASM-NEXT: 201028: 00 00 | |
| 43 | // DISASM-NEXT: 20102a: 00 00 | |
| 44 | // DISASM-NEXT: 20102c: 00 00 | |
| 31 | // DISASM-NEXT: ... | |
| 45 | 32 | // DISASM-NEXT: 20102e: 00 00 |
| 46 | 33 | // DISASM: _start: |
| 47 | 34 | // DISASM-NEXT: 201030: 8b 04 25 19 00 00 00 movl 25, %eax |
deps/lld/test/ELF/relocation-size.s+1-12| ... | ... | @@ -57,18 +57,7 @@ |
| 57 | 57 | |
| 58 | 58 | // DISASMSHARED: Disassembly of section test: |
| 59 | 59 | // DISASMSHARED-NEXT: _data: |
| 60 | // DISASMSHARED-NEXT: 1000: 00 00 | |
| 61 | // DISASMSHARED-NEXT: 1002: 00 00 | |
| 62 | // DISASMSHARED-NEXT: 1004: 00 00 | |
| 63 | // DISASMSHARED-NEXT: 1006: 00 00 | |
| 64 | // DISASMSHARED-NEXT: 1008: 00 00 | |
| 65 | // DISASMSHARED-NEXT: 100a: 00 00 | |
| 66 | // DISASMSHARED-NEXT: 100c: 00 00 | |
| 67 | // DISASMSHARED-NEXT: 100e: 00 00 | |
| 68 | // DISASMSHARED-NEXT: 1010: 00 00 | |
| 69 | // DISASMSHARED-NEXT: 1012: 00 00 | |
| 70 | // DISASMSHARED-NEXT: 1014: 00 00 | |
| 71 | // DISASMSHARED-NEXT: 1016: 00 00 | |
| 60 | // DISASMSHARED-NEXT: ... | |
| 72 | 61 | // DISASMSHARED-NEXT: 1018: 19 00 |
| 73 | 62 | // DISASMSHARED-NEXT: 101a: 00 00 |
| 74 | 63 | // DISASMSHARED-NEXT: 101c: 00 00 |
deps/lld/test/ELF/reproduce-backslash.s+1-1| ... | ... | @@ -6,4 +6,4 @@ |
| 6 | 6 | # RUN: ld.lld %T/foo\\.o --reproduce %T/repro.tar -o /dev/null |
| 7 | 7 | # RUN: tar tf %T/repro.tar | FileCheck %s |
| 8 | 8 | |
| 9 | # CHECK: repro/{{.*}}/foo\\.o | |
| 9 | # CHECK: repro/{{.*}}/foo\{{[\]?}}.o |
deps/lld/test/ELF/retain-symbols-file.s+1-1| ... | ... | @@ -11,7 +11,7 @@ |
| 11 | 11 | |
| 12 | 12 | # CHECK: DynamicSymbols [ |
| 13 | 13 | # CHECK-NEXT: Symbol { |
| 14 | # CHECK-NEXT: Name: @ | |
| 14 | # CHECK-NEXT: Name: | |
| 15 | 15 | # CHECK-NEXT: Value: |
| 16 | 16 | # CHECK-NEXT: Size: |
| 17 | 17 | # CHECK-NEXT: Binding: |
deps/lld/test/ELF/riscv-branch.test created+119| ... | ... | @@ -0,0 +1,119 @@ |
| 1 | # .option norelax | |
| 2 | # .global _start | |
| 3 | # _start: | |
| 4 | # beq x0, x0, _start | |
| 5 | # | |
| 6 | # .section .reloc_max, "ax", @progbits | |
| 7 | # L1: | |
| 8 | # beq x0, x0, L1 + 0xffe | |
| 9 | # | |
| 10 | # .section .reloc_min, "ax", @progbits | |
| 11 | # L2: | |
| 12 | # beq x0, x0, L2 - 0x1000 | |
| 13 | # | |
| 14 | # REQUIRES: riscv | |
| 15 | # RUN: yaml2obj %s -o %t.o | |
| 16 | # RUN: ld.lld %t.o -o %t | |
| 17 | # RUN: obj2yaml %t | FileCheck %s | |
| 18 | # | |
| 19 | # CHECK: - Name: .text | |
| 20 | # CHECK: Content: '63000000' | |
| 21 | # 11000: 00000063 beqz zero,11000 <_start> | |
| 22 | # | |
| 23 | # CHECK: - Name: .reloc_max | |
| 24 | # CHECK: Content: E30F007E | |
| 25 | # 11004: 7e000fe3 beqz zero,12002 | |
| 26 | # | |
| 27 | # CHECK: - Name: .reloc_min | |
| 28 | # CHECK: Content: '63000080' | |
| 29 | # 11008: 80000063 beqz zero,10008 | |
| 30 | ||
| 31 | --- !ELF | |
| 32 | FileHeader: | |
| 33 | Class: ELFCLASS32 | |
| 34 | Data: ELFDATA2LSB | |
| 35 | Type: ET_REL | |
| 36 | Machine: EM_RISCV | |
| 37 | Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] | |
| 38 | Sections: | |
| 39 | - Name: .text | |
| 40 | Type: SHT_PROGBITS | |
| 41 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 42 | AddressAlign: 0x0000000000000002 | |
| 43 | Content: '63000000' | |
| 44 | - Name: .rela.text | |
| 45 | Type: SHT_RELA | |
| 46 | Flags: [ SHF_INFO_LINK ] | |
| 47 | Link: .symtab | |
| 48 | AddressAlign: 0x0000000000000004 | |
| 49 | Info: .text | |
| 50 | Relocations: | |
| 51 | - Offset: 0x0000000000000000 | |
| 52 | Symbol: _start | |
| 53 | Type: R_RISCV_BRANCH | |
| 54 | - Name: .data | |
| 55 | Type: SHT_PROGBITS | |
| 56 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 57 | AddressAlign: 0x0000000000000001 | |
| 58 | Content: '' | |
| 59 | - Name: .bss | |
| 60 | Type: SHT_NOBITS | |
| 61 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 62 | AddressAlign: 0x0000000000000001 | |
| 63 | - Name: .reloc_max | |
| 64 | Type: SHT_PROGBITS | |
| 65 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 66 | AddressAlign: 0x0000000000000001 | |
| 67 | Content: E30F007E | |
| 68 | - Name: .rela.reloc_max | |
| 69 | Type: SHT_RELA | |
| 70 | Flags: [ SHF_INFO_LINK ] | |
| 71 | Link: .symtab | |
| 72 | AddressAlign: 0x0000000000000004 | |
| 73 | Info: .reloc_max | |
| 74 | Relocations: | |
| 75 | - Offset: 0x0000000000000000 | |
| 76 | Symbol: L1 | |
| 77 | Type: R_RISCV_BRANCH | |
| 78 | Addend: 4094 | |
| 79 | - Name: .reloc_min | |
| 80 | Type: SHT_PROGBITS | |
| 81 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 82 | AddressAlign: 0x0000000000000001 | |
| 83 | Content: '63000080' | |
| 84 | - Name: .rela.reloc_min | |
| 85 | Type: SHT_RELA | |
| 86 | Flags: [ SHF_INFO_LINK ] | |
| 87 | Link: .symtab | |
| 88 | AddressAlign: 0x0000000000000004 | |
| 89 | Info: .reloc_min | |
| 90 | Relocations: | |
| 91 | - Offset: 0x0000000000000000 | |
| 92 | Symbol: L2 | |
| 93 | Type: R_RISCV_BRANCH | |
| 94 | Addend: -4096 | |
| 95 | Symbols: | |
| 96 | Local: | |
| 97 | - Name: .text | |
| 98 | Type: STT_SECTION | |
| 99 | Section: .text | |
| 100 | - Name: .data | |
| 101 | Type: STT_SECTION | |
| 102 | Section: .data | |
| 103 | - Name: .bss | |
| 104 | Type: STT_SECTION | |
| 105 | Section: .bss | |
| 106 | - Name: .reloc_max | |
| 107 | Type: STT_SECTION | |
| 108 | Section: .reloc_max | |
| 109 | - Name: L1 | |
| 110 | Section: .reloc_max | |
| 111 | - Name: .reloc_min | |
| 112 | Type: STT_SECTION | |
| 113 | Section: .reloc_min | |
| 114 | - Name: L2 | |
| 115 | Section: .reloc_min | |
| 116 | Global: | |
| 117 | - Name: _start | |
| 118 | Section: .text | |
| 119 | ... |
deps/lld/test/ELF/riscv-call.test created+95| ... | ... | @@ -0,0 +1,95 @@ |
| 1 | # .option norelax | |
| 2 | # .global _start | |
| 3 | # _start: | |
| 4 | # call _start + 4 | |
| 5 | # | |
| 6 | # .section .reloc_neg, "ax", @progbits | |
| 7 | # L1: | |
| 8 | # call L1 - 4 | |
| 9 | # | |
| 10 | # REQUIRES: riscv | |
| 11 | # RUN: yaml2obj %s -o %t.o | |
| 12 | # RUN: ld.lld %t.o -o %t | |
| 13 | # RUN: obj2yaml %t | FileCheck %s | |
| 14 | # | |
| 15 | # CHECK: - Name: .text | |
| 16 | # CHECK: Content: '97000000E7804000' | |
| 17 | # | |
| 18 | # 11000: 00000097 auipc ra,0x0 | |
| 19 | # 11004: 004080e7 jalr 4(ra) | |
| 20 | # | |
| 21 | # CHECK: - Name: .reloc_neg | |
| 22 | # CHECK: Content: 97000000E780C0FF | |
| 23 | # | |
| 24 | # 11008: 00000097 auipc ra,0x0 | |
| 25 | # 1100c: ffc080e7 jalr -4(ra) | |
| 26 | ||
| 27 | --- !ELF | |
| 28 | FileHeader: | |
| 29 | Class: ELFCLASS32 | |
| 30 | Data: ELFDATA2LSB | |
| 31 | Type: ET_REL | |
| 32 | Machine: EM_RISCV | |
| 33 | Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] | |
| 34 | Sections: | |
| 35 | - Name: .text | |
| 36 | Type: SHT_PROGBITS | |
| 37 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 38 | AddressAlign: 0x0000000000000002 | |
| 39 | Content: '97000000E7800000' | |
| 40 | - Name: .rela.text | |
| 41 | Type: SHT_RELA | |
| 42 | Flags: [ SHF_INFO_LINK ] | |
| 43 | Link: .symtab | |
| 44 | AddressAlign: 0x0000000000000004 | |
| 45 | Info: .text | |
| 46 | Relocations: | |
| 47 | - Offset: 0x0000000000000000 | |
| 48 | Symbol: _start | |
| 49 | Type: R_RISCV_CALL | |
| 50 | Addend: 4 | |
| 51 | - Name: .data | |
| 52 | Type: SHT_PROGBITS | |
| 53 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 54 | AddressAlign: 0x0000000000000001 | |
| 55 | Content: '' | |
| 56 | - Name: .bss | |
| 57 | Type: SHT_NOBITS | |
| 58 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 59 | AddressAlign: 0x0000000000000001 | |
| 60 | - Name: .reloc_neg | |
| 61 | Type: SHT_PROGBITS | |
| 62 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 63 | AddressAlign: 0x0000000000000001 | |
| 64 | Content: '97000000E7800000' | |
| 65 | - Name: .rela.reloc_neg | |
| 66 | Type: SHT_RELA | |
| 67 | Flags: [ SHF_INFO_LINK ] | |
| 68 | Link: .symtab | |
| 69 | AddressAlign: 0x0000000000000004 | |
| 70 | Info: .reloc_neg | |
| 71 | Relocations: | |
| 72 | - Offset: 0x0000000000000000 | |
| 73 | Symbol: L1 | |
| 74 | Type: R_RISCV_CALL | |
| 75 | Addend: -4 | |
| 76 | Symbols: | |
| 77 | Local: | |
| 78 | - Name: .text | |
| 79 | Type: STT_SECTION | |
| 80 | Section: .text | |
| 81 | - Name: .data | |
| 82 | Type: STT_SECTION | |
| 83 | Section: .data | |
| 84 | - Name: .bss | |
| 85 | Type: STT_SECTION | |
| 86 | Section: .bss | |
| 87 | - Name: .reloc_neg | |
| 88 | Type: STT_SECTION | |
| 89 | Section: .reloc_neg | |
| 90 | - Name: L1 | |
| 91 | Section: .reloc_neg | |
| 92 | Global: | |
| 93 | - Name: _start | |
| 94 | Section: .text | |
| 95 | ... |
deps/lld/test/ELF/riscv-hi20-lo12.test created+86| ... | ... | @@ -0,0 +1,86 @@ |
| 1 | # .option norelax | |
| 2 | # .global _start | |
| 3 | # | |
| 4 | # .section .reloc_12345678, "ax", @progbits | |
| 5 | # _start: | |
| 6 | # foo = 0x12345678 | |
| 7 | # lui a0, %hi(foo) | |
| 8 | # addi a0, a0, %lo(foo) | |
| 9 | # lw a0, %lo(foo)(a0) | |
| 10 | # | |
| 11 | # .section .reloc_fedcba98, "ax", @progbits | |
| 12 | # foo = 0xfedcba98 | |
| 13 | # lui a0, %hi(foo) | |
| 14 | # addi a0, a0, %lo(foo) | |
| 15 | # | |
| 16 | # REQUIRES: riscv | |
| 17 | # RUN: yaml2obj %s -o %t.o | |
| 18 | # RUN: ld.lld %t.o -o %t | |
| 19 | # RUN: obj2yaml %t | FileCheck %s | |
| 20 | # | |
| 21 | # CHECK: - Name: .reloc_12345678 | |
| 22 | # CHECK: Content: '375534121305856703258567' | |
| 23 | # 11000: 12345537 lui a0,0x12345 | |
| 24 | # 11004: 67850513 addi a0,a0,1656 # 12345678 <__global_pointer$+0x12332e78> | |
| 25 | # 11008: 67852503 lw a0,1656(a0) | |
| 26 | # | |
| 27 | # CHECK: - Name: .reloc_fedcba98 | |
| 28 | # CHECK: Content: 37C5DCFE130585A9 | |
| 29 | # 1100c: fedcc537 lui a0,0xfedcc | |
| 30 | # 11010: a9850513 addi a0,a0,-1384 # fedcba98 <__global_pointer$+0xfedb9298> | |
| 31 | ||
| 32 | --- !ELF | |
| 33 | FileHeader: | |
| 34 | Class: ELFCLASS32 | |
| 35 | Data: ELFDATA2LSB | |
| 36 | Type: ET_REL | |
| 37 | Machine: EM_RISCV | |
| 38 | Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] | |
| 39 | Sections: | |
| 40 | - Name: .text | |
| 41 | Type: SHT_PROGBITS | |
| 42 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 43 | AddressAlign: 0x0000000000000002 | |
| 44 | Content: '' | |
| 45 | - Name: .data | |
| 46 | Type: SHT_PROGBITS | |
| 47 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 48 | AddressAlign: 0x0000000000000001 | |
| 49 | Content: '' | |
| 50 | - Name: .bss | |
| 51 | Type: SHT_NOBITS | |
| 52 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 53 | AddressAlign: 0x0000000000000001 | |
| 54 | - Name: .reloc_12345678 | |
| 55 | Type: SHT_PROGBITS | |
| 56 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 57 | AddressAlign: 0x0000000000000001 | |
| 58 | Content: '375534121305856703258567' | |
| 59 | - Name: .reloc_fedcba98 | |
| 60 | Type: SHT_PROGBITS | |
| 61 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 62 | AddressAlign: 0x0000000000000001 | |
| 63 | Content: 37C5DCFE130585A9 | |
| 64 | Symbols: | |
| 65 | Local: | |
| 66 | - Name: .text | |
| 67 | Type: STT_SECTION | |
| 68 | Section: .text | |
| 69 | - Name: .data | |
| 70 | Type: STT_SECTION | |
| 71 | Section: .data | |
| 72 | - Name: .bss | |
| 73 | Type: STT_SECTION | |
| 74 | Section: .bss | |
| 75 | - Name: .reloc_12345678 | |
| 76 | Type: STT_SECTION | |
| 77 | Section: .reloc_12345678 | |
| 78 | - Name: foo | |
| 79 | Value: 0x00000000FEDCBA98 | |
| 80 | - Name: .reloc_fedcba98 | |
| 81 | Type: STT_SECTION | |
| 82 | Section: .reloc_fedcba98 | |
| 83 | Global: | |
| 84 | - Name: _start | |
| 85 | Section: .reloc_12345678 | |
| 86 | ... |
deps/lld/test/ELF/riscv-jal-error.test created+93| ... | ... | @@ -0,0 +1,93 @@ |
| 1 | # .option norelax | |
| 2 | # .global _start | |
| 3 | # | |
| 4 | # _start: | |
| 5 | # L1: | |
| 6 | # jal x0, L1 + 0x100000 | |
| 7 | # L2: | |
| 8 | # jal x0, L2 - 0x100002 | |
| 9 | # L3: | |
| 10 | # jal x0, L3 + 1 | |
| 11 | # L4: | |
| 12 | # c.jal L4 + 1 | |
| 13 | # | |
| 14 | # REQUIRES: riscv | |
| 15 | # RUN: yaml2obj %s -o %t.o | |
| 16 | # RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s | |
| 17 | # | |
| 18 | # CHECK: {{.*}}(.text+0x0): relocation R_RISCV_JAL out of range | |
| 19 | # CHECK: {{.*}}(.text+0x4): relocation R_RISCV_JAL out of range | |
| 20 | # CHECK: {{.*}}(.text+0x8): improper alignment for relocation R_RISCV_JAL | |
| 21 | # CHECK: {{.*}}(.text+0xC): improper alignment for relocation R_RISCV_RVC_JUMP | |
| 22 | ||
| 23 | --- !ELF | |
| 24 | FileHeader: | |
| 25 | Class: ELFCLASS32 | |
| 26 | Data: ELFDATA2LSB | |
| 27 | Type: ET_REL | |
| 28 | Machine: EM_RISCV | |
| 29 | Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] | |
| 30 | Sections: | |
| 31 | - Name: .text | |
| 32 | Type: SHT_PROGBITS | |
| 33 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 34 | AddressAlign: 0x0000000000000002 | |
| 35 | Content: 6F0000806FF0FF7F6F0000000120 | |
| 36 | - Name: .rela.text | |
| 37 | Type: SHT_RELA | |
| 38 | Flags: [ SHF_INFO_LINK ] | |
| 39 | Link: .symtab | |
| 40 | AddressAlign: 0x0000000000000004 | |
| 41 | Info: .text | |
| 42 | Relocations: | |
| 43 | - Offset: 0x0000000000000000 | |
| 44 | Symbol: L1 | |
| 45 | Type: R_RISCV_JAL | |
| 46 | Addend: 1048576 | |
| 47 | - Offset: 0x0000000000000004 | |
| 48 | Symbol: L2 | |
| 49 | Type: R_RISCV_JAL | |
| 50 | Addend: -1048578 | |
| 51 | - Offset: 0x0000000000000008 | |
| 52 | Symbol: L3 | |
| 53 | Type: R_RISCV_JAL | |
| 54 | Addend: 1 | |
| 55 | - Offset: 0x000000000000000C | |
| 56 | Symbol: L4 | |
| 57 | Type: R_RISCV_RVC_JUMP | |
| 58 | Addend: 1 | |
| 59 | - Name: .data | |
| 60 | Type: SHT_PROGBITS | |
| 61 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 62 | AddressAlign: 0x0000000000000001 | |
| 63 | Content: '' | |
| 64 | - Name: .bss | |
| 65 | Type: SHT_NOBITS | |
| 66 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 67 | AddressAlign: 0x0000000000000001 | |
| 68 | Symbols: | |
| 69 | Local: | |
| 70 | - Name: .text | |
| 71 | Type: STT_SECTION | |
| 72 | Section: .text | |
| 73 | - Name: .data | |
| 74 | Type: STT_SECTION | |
| 75 | Section: .data | |
| 76 | - Name: .bss | |
| 77 | Type: STT_SECTION | |
| 78 | Section: .bss | |
| 79 | - Name: L1 | |
| 80 | Section: .text | |
| 81 | - Name: L2 | |
| 82 | Section: .text | |
| 83 | Value: 0x0000000000000004 | |
| 84 | - Name: L3 | |
| 85 | Section: .text | |
| 86 | Value: 0x0000000000000008 | |
| 87 | - Name: L4 | |
| 88 | Section: .text | |
| 89 | Value: 0x000000000000000C | |
| 90 | Global: | |
| 91 | - Name: _start | |
| 92 | Section: .text | |
| 93 | ... |
deps/lld/test/ELF/riscv-jal.test created+161| ... | ... | @@ -0,0 +1,161 @@ |
| 1 | # .option norelax | |
| 2 | # .global _start | |
| 3 | # | |
| 4 | # .section .reloc_zero, "ax", @progbits | |
| 5 | # _start: | |
| 6 | # L1: | |
| 7 | # jal x0, L1 | |
| 8 | # L2: | |
| 9 | # c.jal L2 | |
| 10 | # | |
| 11 | # .section .reloc_max, "ax", @progbits | |
| 12 | # L3: | |
| 13 | # jal x0, L3 + 0xffffe | |
| 14 | # L4: | |
| 15 | # c.jal L4 + 0x7fe | |
| 16 | # | |
| 17 | # .section .reloc_min, "ax", @progbits | |
| 18 | # L5: | |
| 19 | # jal x0, L5 - 0x100000 | |
| 20 | # L6: | |
| 21 | # c.jal L6 - 0x800 | |
| 22 | # | |
| 23 | # REQUIRES: riscv | |
| 24 | # RUN: yaml2obj %s -o %t.o | |
| 25 | # RUN: ld.lld %t.o -o %t | |
| 26 | # RUN: obj2yaml %t | FileCheck %s | |
| 27 | # | |
| 28 | # CHECK: - Name: .reloc_zero | |
| 29 | # CHECK: Content: 6F0000000120 | |
| 30 | # 11000: 0000006f j 11000 | |
| 31 | # 11004: 2001 jal 11004 | |
| 32 | # | |
| 33 | # CHECK: - Name: .reloc_max | |
| 34 | # CHECK: Content: 6FF0FF7FFD2F | |
| 35 | # 11006: 7ffff06f j 111004 | |
| 36 | # 1100a: 2ffd jal 11808 | |
| 37 | # | |
| 38 | # CHECK: - Name: .reloc_min | |
| 39 | # CHECK: Content: 6F0000800130 | |
| 40 | # 1100c: 8000006f j fff1100c | |
| 41 | # 11010: 3001 jal 10810 | |
| 42 | ||
| 43 | --- !ELF | |
| 44 | FileHeader: | |
| 45 | Class: ELFCLASS32 | |
| 46 | Data: ELFDATA2LSB | |
| 47 | Type: ET_REL | |
| 48 | Machine: EM_RISCV | |
| 49 | Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] | |
| 50 | Sections: | |
| 51 | - Name: .text | |
| 52 | Type: SHT_PROGBITS | |
| 53 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 54 | AddressAlign: 0x0000000000000002 | |
| 55 | Content: '' | |
| 56 | - Name: .data | |
| 57 | Type: SHT_PROGBITS | |
| 58 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 59 | AddressAlign: 0x0000000000000001 | |
| 60 | Content: '' | |
| 61 | - Name: .bss | |
| 62 | Type: SHT_NOBITS | |
| 63 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 64 | AddressAlign: 0x0000000000000001 | |
| 65 | - Name: .reloc_zero | |
| 66 | Type: SHT_PROGBITS | |
| 67 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 68 | AddressAlign: 0x0000000000000001 | |
| 69 | Content: 6F0000000120 | |
| 70 | - Name: .rela.reloc_zero | |
| 71 | Type: SHT_RELA | |
| 72 | Flags: [ SHF_INFO_LINK ] | |
| 73 | Link: .symtab | |
| 74 | AddressAlign: 0x0000000000000004 | |
| 75 | Info: .reloc_zero | |
| 76 | Relocations: | |
| 77 | - Offset: 0x0000000000000000 | |
| 78 | Symbol: L1 | |
| 79 | Type: R_RISCV_JAL | |
| 80 | - Offset: 0x0000000000000004 | |
| 81 | Symbol: L2 | |
| 82 | Type: R_RISCV_RVC_JUMP | |
| 83 | - Name: .reloc_max | |
| 84 | Type: SHT_PROGBITS | |
| 85 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 86 | AddressAlign: 0x0000000000000001 | |
| 87 | Content: 6FF0FF7FFD2F | |
| 88 | - Name: .rela.reloc_max | |
| 89 | Type: SHT_RELA | |
| 90 | Flags: [ SHF_INFO_LINK ] | |
| 91 | Link: .symtab | |
| 92 | AddressAlign: 0x0000000000000004 | |
| 93 | Info: .reloc_max | |
| 94 | Relocations: | |
| 95 | - Offset: 0x0000000000000000 | |
| 96 | Symbol: L3 | |
| 97 | Type: R_RISCV_JAL | |
| 98 | Addend: 1048574 | |
| 99 | - Offset: 0x0000000000000004 | |
| 100 | Symbol: L4 | |
| 101 | Type: R_RISCV_RVC_JUMP | |
| 102 | Addend: 2046 | |
| 103 | - Name: .reloc_min | |
| 104 | Type: SHT_PROGBITS | |
| 105 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 106 | AddressAlign: 0x0000000000000001 | |
| 107 | Content: 6F0000800130 | |
| 108 | - Name: .rela.reloc_min | |
| 109 | Type: SHT_RELA | |
| 110 | Flags: [ SHF_INFO_LINK ] | |
| 111 | Link: .symtab | |
| 112 | AddressAlign: 0x0000000000000004 | |
| 113 | Info: .reloc_min | |
| 114 | Relocations: | |
| 115 | - Offset: 0x0000000000000000 | |
| 116 | Symbol: L5 | |
| 117 | Type: R_RISCV_JAL | |
| 118 | Addend: -1048576 | |
| 119 | - Offset: 0x0000000000000004 | |
| 120 | Symbol: L6 | |
| 121 | Type: R_RISCV_RVC_JUMP | |
| 122 | Addend: -2048 | |
| 123 | Symbols: | |
| 124 | Local: | |
| 125 | - Name: .text | |
| 126 | Type: STT_SECTION | |
| 127 | Section: .text | |
| 128 | - Name: .data | |
| 129 | Type: STT_SECTION | |
| 130 | Section: .data | |
| 131 | - Name: .bss | |
| 132 | Type: STT_SECTION | |
| 133 | Section: .bss | |
| 134 | - Name: .reloc_zero | |
| 135 | Type: STT_SECTION | |
| 136 | Section: .reloc_zero | |
| 137 | - Name: L1 | |
| 138 | Section: .reloc_zero | |
| 139 | - Name: L2 | |
| 140 | Section: .reloc_zero | |
| 141 | Value: 0x0000000000000004 | |
| 142 | - Name: .reloc_max | |
| 143 | Type: STT_SECTION | |
| 144 | Section: .reloc_max | |
| 145 | - Name: L3 | |
| 146 | Section: .reloc_max | |
| 147 | - Name: L4 | |
| 148 | Section: .reloc_max | |
| 149 | Value: 0x0000000000000004 | |
| 150 | - Name: .reloc_min | |
| 151 | Type: STT_SECTION | |
| 152 | Section: .reloc_min | |
| 153 | - Name: L5 | |
| 154 | Section: .reloc_min | |
| 155 | - Name: L6 | |
| 156 | Section: .reloc_min | |
| 157 | Value: 0x0000000000000004 | |
| 158 | Global: | |
| 159 | - Name: _start | |
| 160 | Section: .reloc_zero | |
| 161 | ... |
deps/lld/test/ELF/riscv-pcrel-hilo.test created+103| ... | ... | @@ -0,0 +1,103 @@ |
| 1 | # .option norelax | |
| 2 | # .global _start | |
| 3 | # | |
| 4 | # _start: | |
| 5 | # auipc a0, %pcrel_hi(_start + 4) | |
| 6 | # addi a0, a0, %pcrel_lo(_start) | |
| 7 | # | |
| 8 | # .section .reloc_neg, "ax", @progbits | |
| 9 | # L1: | |
| 10 | # auipc a0, %pcrel_hi(L1 - 2) | |
| 11 | # addi a0, a0, %pcrel_lo(L1) | |
| 12 | # | |
| 13 | # | |
| 14 | # REQUIRES: riscv | |
| 15 | # RUN: yaml2obj %s -o %t.o | |
| 16 | # RUN: ld.lld %t.o -o %t | |
| 17 | # RUN: obj2yaml %t | FileCheck %s | |
| 18 | # | |
| 19 | # CHECK: - Name: .text | |
| 20 | # CHECK: Content: '1705000013054500' | |
| 21 | # 11000: 00000517 auipc a0,0x0 | |
| 22 | # 11004: 00450513 addi a0,a0,4 # 11004 <_start+0x4> | |
| 23 | # | |
| 24 | # CHECK: - Name: .reloc_neg | |
| 25 | # CHECK: Content: 170500001305E5FF | |
| 26 | # 11008: 00000517 auipc a0,0x0 | |
| 27 | # 1100c: ffe50513 addi a0,a0,-2 # 11006 <_start+0x6> | |
| 28 | ||
| 29 | --- !ELF | |
| 30 | FileHeader: | |
| 31 | Class: ELFCLASS32 | |
| 32 | Data: ELFDATA2LSB | |
| 33 | Type: ET_REL | |
| 34 | Machine: EM_RISCV | |
| 35 | Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ] | |
| 36 | Sections: | |
| 37 | - Name: .text | |
| 38 | Type: SHT_PROGBITS | |
| 39 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 40 | AddressAlign: 0x0000000000000002 | |
| 41 | Content: '1705000013050500' | |
| 42 | - Name: .rela.text | |
| 43 | Type: SHT_RELA | |
| 44 | Flags: [ SHF_INFO_LINK ] | |
| 45 | Link: .symtab | |
| 46 | AddressAlign: 0x0000000000000004 | |
| 47 | Info: .text | |
| 48 | Relocations: | |
| 49 | - Offset: 0x0000000000000000 | |
| 50 | Symbol: _start | |
| 51 | Type: R_RISCV_PCREL_HI20 | |
| 52 | Addend: 4 | |
| 53 | - Offset: 0x0000000000000004 | |
| 54 | Symbol: _start | |
| 55 | Type: R_RISCV_PCREL_LO12_I | |
| 56 | - Name: .data | |
| 57 | Type: SHT_PROGBITS | |
| 58 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 59 | AddressAlign: 0x0000000000000001 | |
| 60 | Content: '' | |
| 61 | - Name: .bss | |
| 62 | Type: SHT_NOBITS | |
| 63 | Flags: [ SHF_WRITE, SHF_ALLOC ] | |
| 64 | AddressAlign: 0x0000000000000001 | |
| 65 | - Name: .reloc_neg | |
| 66 | Type: SHT_PROGBITS | |
| 67 | Flags: [ SHF_ALLOC, SHF_EXECINSTR ] | |
| 68 | AddressAlign: 0x0000000000000001 | |
| 69 | Content: '1705000013050500' | |
| 70 | - Name: .rela.reloc_neg | |
| 71 | Type: SHT_RELA | |
| 72 | Flags: [ SHF_INFO_LINK ] | |
| 73 | Link: .symtab | |
| 74 | AddressAlign: 0x0000000000000004 | |
| 75 | Info: .reloc_neg | |
| 76 | Relocations: | |
| 77 | - Offset: 0x0000000000000000 | |
| 78 | Symbol: L1 | |
| 79 | Type: R_RISCV_PCREL_HI20 | |
| 80 | Addend: -2 | |
| 81 | - Offset: 0x0000000000000004 | |
| 82 | Symbol: L1 | |
| 83 | Type: R_RISCV_PCREL_LO12_I | |
| 84 | Symbols: | |
| 85 | Local: | |
| 86 | - Name: .text | |
| 87 | Type: STT_SECTION | |
| 88 | Section: .text | |
| 89 | - Name: .data | |
| 90 | Type: STT_SECTION | |
| 91 | Section: .data | |
| 92 | - Name: .bss | |
| 93 | Type: STT_SECTION | |
| 94 | Section: .bss | |
| 95 | - Name: .reloc_neg | |
| 96 | Type: STT_SECTION | |
| 97 | Section: .reloc_neg | |
| 98 | - Name: L1 | |
| 99 | Section: .reloc_neg | |
| 100 | Global: | |
| 101 | - Name: _start | |
| 102 | Section: .text | |
| 103 | ... |
deps/lld/test/ELF/shared.s+10-10| ... | ... | @@ -141,7 +141,7 @@ |
| 141 | 141 | // CHECK-NEXT: } |
| 142 | 142 | // CHECK-NEXT: Symbol { |
| 143 | 143 | // CHECK-NEXT: Name: _DYNAMIC |
| 144 | // CHECK-NEXT: Value: 0x12000 | |
| 144 | // CHECK-NEXT: Value: 0x402000 | |
| 145 | 145 | // CHECK-NEXT: Size: 0 |
| 146 | 146 | // CHECK-NEXT: Binding: Local |
| 147 | 147 | // CHECK-NEXT: Type: None |
| ... | ... | @@ -152,7 +152,7 @@ |
| 152 | 152 | // CHECK-NEXT: } |
| 153 | 153 | // CHECK-NEXT: Symbol { |
| 154 | 154 | // CHECK-NEXT: Name: _start |
| 155 | // CHECK-NEXT: Value: 0x11000 | |
| 155 | // CHECK-NEXT: Value: 0x401000 | |
| 156 | 156 | // CHECK-NEXT: Size: 0 |
| 157 | 157 | // CHECK-NEXT: Binding: Global |
| 158 | 158 | // CHECK-NEXT: Type: None |
| ... | ... | @@ -181,7 +181,7 @@ |
| 181 | 181 | |
| 182 | 182 | // CHECK: DynamicSymbols [ |
| 183 | 183 | // CHECK-NEXT: Symbol { |
| 184 | // CHECK-NEXT: Name: @ | |
| 184 | // CHECK-NEXT: Name: | |
| 185 | 185 | // CHECK-NEXT: Value: 0x0 |
| 186 | 186 | // CHECK-NEXT: Size: 0 |
| 187 | 187 | // CHECK-NEXT: Binding: Local |
| ... | ... | @@ -190,8 +190,8 @@ |
| 190 | 190 | // CHECK-NEXT: Section: Undefined |
| 191 | 191 | // CHECK-NEXT: } |
| 192 | 192 | // CHECK-NEXT: Symbol { |
| 193 | // CHECK-NEXT: Name: _start@ | |
| 194 | // CHECK-NEXT: Value: 0x11000 | |
| 193 | // CHECK-NEXT: Name: _start | |
| 194 | // CHECK-NEXT: Value: 0x401000 | |
| 195 | 195 | // CHECK-NEXT: Size: 0 |
| 196 | 196 | // CHECK-NEXT: Binding: Global |
| 197 | 197 | // CHECK-NEXT: Type: Non |
| ... | ... | @@ -199,7 +199,7 @@ |
| 199 | 199 | // CHECK-NEXT: Section: .text |
| 200 | 200 | // CHECK-NEXT: } |
| 201 | 201 | // CHECK-NEXT: Symbol { |
| 202 | // CHECK-NEXT: Name: bar@ | |
| 202 | // CHECK-NEXT: Name: bar | |
| 203 | 203 | // CHECK-NEXT: Value: 0x0 |
| 204 | 204 | // CHECK-NEXT: Size: 0 |
| 205 | 205 | // CHECK-NEXT: Binding: Global |
| ... | ... | @@ -208,7 +208,7 @@ |
| 208 | 208 | // CHECK-NEXT: Section: Undefined |
| 209 | 209 | // CHECK-NEXT: } |
| 210 | 210 | // CHECK-NEXT: Symbol { |
| 211 | // CHECK-NEXT: Name: zed@ | |
| 211 | // CHECK-NEXT: Name: zed | |
| 212 | 212 | // CHECK-NEXT: Value: 0x0 |
| 213 | 213 | // CHECK-NEXT: Size: 0 |
| 214 | 214 | // CHECK-NEXT: Binding: Global |
| ... | ... | @@ -220,7 +220,7 @@ |
| 220 | 220 | |
| 221 | 221 | // DONT_EXPORT: DynamicSymbols [ |
| 222 | 222 | // DONT_EXPORT-NEXT: Symbol { |
| 223 | // DONT_EXPORT-NEXT: Name: @ | |
| 223 | // DONT_EXPORT-NEXT: Name: | |
| 224 | 224 | // DONT_EXPORT-NEXT: Value: 0x0 |
| 225 | 225 | // DONT_EXPORT-NEXT: Size: 0 |
| 226 | 226 | // DONT_EXPORT-NEXT: Binding: Local (0x0) |
| ... | ... | @@ -229,7 +229,7 @@ |
| 229 | 229 | // DONT_EXPORT-NEXT: Section: Undefined (0x0) |
| 230 | 230 | // DONT_EXPORT-NEXT: } |
| 231 | 231 | // DONT_EXPORT-NEXT: Symbol { |
| 232 | // DONT_EXPORT-NEXT: Name: bar@ | |
| 232 | // DONT_EXPORT-NEXT: Name: bar | |
| 233 | 233 | // DONT_EXPORT-NEXT: Value: 0x0 |
| 234 | 234 | // DONT_EXPORT-NEXT: Size: 0 |
| 235 | 235 | // DONT_EXPORT-NEXT: Binding: Global |
| ... | ... | @@ -238,7 +238,7 @@ |
| 238 | 238 | // DONT_EXPORT-NEXT: Section: Undefined |
| 239 | 239 | // DONT_EXPORT-NEXT: } |
| 240 | 240 | // DONT_EXPORT-NEXT: Symbol { |
| 241 | // DONT_EXPORT-NEXT: Name: zed@ | |
| 241 | // DONT_EXPORT-NEXT: Name: zed | |
| 242 | 242 | // DONT_EXPORT-NEXT: Value: 0x0 |
| 243 | 243 | // DONT_EXPORT-NEXT: Size: 0 |
| 244 | 244 | // DONT_EXPORT-NEXT: Binding: Global |
deps/lld/test/ELF/sht-group-empty.test created+55| ... | ... | @@ -0,0 +1,55 @@ |
| 1 | # RUN: yaml2obj %s -o %t.o | |
| 2 | # RUN: ld.lld %t.o %t.o -o %t -r | |
| 3 | # RUN: llvm-readobj -s %t | FileCheck %s | |
| 4 | ||
| 5 | # CHECK: Name: .text.foo | |
| 6 | # CHECK: Name: .rela.text.foo | |
| 7 | ||
| 8 | --- !ELF | |
| 9 | FileHeader: | |
| 10 | Class: ELFCLASS64 | |
| 11 | Data: ELFDATA2LSB | |
| 12 | Type: ET_REL | |
| 13 | Machine: EM_X86_64 | |
| 14 | Sections: | |
| 15 | - Name: .group | |
| 16 | Type: SHT_GROUP | |
| 17 | Link: .symtab | |
| 18 | Info: foo | |
| 19 | Members: | |
| 20 | - SectionOrType: GRP_COMDAT | |
| 21 | - SectionOrType: .text.foo | |
| 22 | - SectionOrType: .text.bar | |
| 23 | - SectionOrType: .note | |
| 24 | - Name: .note | |
| 25 | Type: SHT_NOTE | |
| 26 | Flags: [ SHF_GROUP ] | |
| 27 | - Name: .text.foo | |
| 28 | Type: SHT_PROGBITS | |
| 29 | Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ] | |
| 30 | - Name: .text.bar | |
| 31 | Type: SHT_PROGBITS | |
| 32 | Flags: [ SHF_ALLOC, SHF_EXECINSTR, SHF_GROUP ] | |
| 33 | - Name: .rela.text.foo | |
| 34 | Type: SHT_RELA | |
| 35 | Flags: [ SHF_INFO_LINK, SHF_GROUP ] | |
| 36 | Link: .symtab | |
| 37 | Info: .text.foo | |
| 38 | Relocations: | |
| 39 | - Offset: 0x0000000000000000 | |
| 40 | Symbol: foo | |
| 41 | Type: R_X86_64_64 | |
| 42 | - Name: .rela.text.bar | |
| 43 | Type: SHT_RELA | |
| 44 | Flags: [ SHF_INFO_LINK, SHF_GROUP ] | |
| 45 | Link: .symtab | |
| 46 | Info: .text.bar | |
| 47 | Relocations: | |
| 48 | - Offset: 0x0000000000000000 | |
| 49 | Symbol: bar | |
| 50 | Type: R_X86_64_64 | |
| 51 | Symbols: | |
| 52 | Global: | |
| 53 | - Name: foo | |
| 54 | - Name: bar | |
| 55 |
deps/lld/test/ELF/sort-norosegment.s+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | 3 | |
| 4 | 4 | # RUN: ld.lld --hash-style=sysv -no-rosegment -o %t %t.o -shared |
| 5 | # RUN: llvm-readelf -s %t | FileCheck %s | |
| 5 | # RUN: llvm-readelf -S %t | FileCheck %s | |
| 6 | 6 | |
| 7 | 7 | # CHECK: .dynsym {{.*}} A |
| 8 | 8 | # CHECK-NEXT: .hash {{.*}} A |
deps/lld/test/ELF/static-error.s created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/shared.s -o %t.o | |
| 3 | // RUN: ld.lld -shared -o %t.so %t.o | |
| 4 | ||
| 5 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 6 | // RUN: ld.lld -o /dev/null %t.o %t.so | |
| 7 | // RUN: not ld.lld -o /dev/null -static %t.o %t.so 2>&1 | FileCheck %s | |
| 8 | ||
| 9 | // CHECK: attempted static link of dynamic object | |
| 10 | ||
| 11 | .global _start | |
| 12 | _start: | |
| 13 | nop |
deps/lld/test/ELF/static-with-export-dynamic.s+1-1| ... | ... | @@ -18,7 +18,7 @@ |
| 18 | 18 | // CHECK-NEXT: } |
| 19 | 19 | // CHECK-NEXT: Symbol { |
| 20 | 20 | // CHECK-NEXT: Name: _start |
| 21 | // CHECK-NEXT: Value: 0x11000 | |
| 21 | // CHECK-NEXT: Value: 0x401000 | |
| 22 | 22 | // CHECK-NEXT: Size: 0 |
| 23 | 23 | // CHECK-NEXT: Binding: Global |
| 24 | 24 | // CHECK-NEXT: Type: None |
deps/lld/test/ELF/strip-debug.s+3-1| ... | ... | @@ -1,4 +1,4 @@ |
| 1 | # REQUIRES: x86 | |
| 1 | # REQUIRES: x86, zlib | |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t |
| 3 | 3 | # RUN: ld.lld %t -o %t2 --strip-debug |
| 4 | 4 | # RUN: llvm-readobj -sections %t2 | FileCheck %s |
| ... | ... | @@ -12,3 +12,5 @@ |
| 12 | 12 | |
| 13 | 13 | .section .debug_Foo,"",@progbits |
| 14 | 14 | .section .zdebug_Bar,"",@progbits |
| 15 | .ascii "ZLIB" | |
| 16 | .quad 0 |
deps/lld/test/ELF/symbol-ordering-file-warnings.s+5-8| ... | ... | @@ -19,11 +19,6 @@ |
| 19 | 19 | # RUN: --unresolved-symbols=ignore-all --no-warn-symbol-ordering --warn-symbol-ordering 2>&1 | \ |
| 20 | 20 | # RUN: FileCheck %s --check-prefixes=WARN,MISSING |
| 21 | 21 | |
| 22 | # Check that a warning is emitted for undefined symbols. | |
| 23 | # RUN: echo "undefined" > %t-order-undef.txt | |
| 24 | # RUN: ld.lld %t1.o %t3.o -o %t --symbol-ordering-file %t-order-undef.txt \ | |
| 25 | # RUN: --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,UNDEFINED | |
| 26 | ||
| 27 | 22 | # Check that a warning is emitted for imported shared symbols. |
| 28 | 23 | # RUN: echo "shared" > %t-order-shared.txt |
| 29 | 24 | # RUN: ld.lld %t1.o %t.so -o %t --symbol-ordering-file %t-order-shared.txt \ |
| ... | ... | @@ -97,7 +92,7 @@ |
| 97 | 92 | # RUN: echo "_GLOBAL_OFFSET_TABLE_" >> %t-order-multi.txt |
| 98 | 93 | # RUN: echo "_start" >> %t-order-multi.txt |
| 99 | 94 | # RUN: ld.lld %t1.o %t3.o %t.so -o %t --symbol-ordering-file %t-order-multi.txt --gc-sections -T %t.script \ |
| 100 | # RUN: --unresolved-symbols=ignore-all 2>&1 | FileCheck %s --check-prefixes=WARN,SAMESYM,ABSOLUTE,SHARED,UNDEFINED,GC,DISCARD,MISSING2,SYNTHETIC | |
| 95 | # RUN: 2>&1 | FileCheck %s --check-prefixes=WARN,SAMESYM,ABSOLUTE,SHARED,UNDEFINED,GC,DISCARD,MISSING2,SYNTHETIC | |
| 101 | 96 | |
| 102 | 97 | # WARN-NOT: warning: |
| 103 | 98 | # SAMESYM: warning: {{.*}}.txt: duplicate ordered symbol: _start |
| ... | ... | @@ -115,10 +110,12 @@ |
| 115 | 110 | # ABSOLUTE: warning: {{.*}}1.o: unable to order absolute symbol: absolute |
| 116 | 111 | # WARN-NOT: warning: |
| 117 | 112 | # MISSING: warning: symbol ordering file: no such symbol: missing |
| 113 | # WARN-NOT: warning: | |
| 118 | 114 | # MISSING2: warning: symbol ordering file: no such symbol: missing_sym |
| 115 | # WARN-NOT: warning: | |
| 119 | 116 | # COMDAT: warning: {{.*}}1.o: unable to order discarded symbol: comdat |
| 120 | # MULTI: warning: {{.*}}3.o: unable to order undefined symbol: multi | |
| 121 | # MULTI-NEXT: warning: {{.*}}2.o: unable to order absolute symbol: multi | |
| 117 | # WARN-NOT: warning: | |
| 118 | # MULTI: warning: {{.*}}2.o: unable to order absolute symbol: multi | |
| 122 | 119 | # WARN-NOT: warning: |
| 123 | 120 | |
| 124 | 121 | absolute = 0x1234 |
deps/lld/test/ELF/textrel.s created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnu %s -o %t.o | |
| 3 | ||
| 4 | # Without --warn-text-ifunc, lld should run fine: | |
| 5 | # RUN: ld.lld -z notext %t.o -o %t2 | |
| 6 | ||
| 7 | # With --warn-text-ifunc, lld should run with warnings: | |
| 8 | # RUN: ld.lld --warn-ifunc-textrel -z notext %t.o -o /dev/null 2>&1 | FileCheck %s | |
| 9 | # CHECK: using ifunc symbols when text relocations are allowed may produce | |
| 10 | # CHECK-SAME: a binary that will segfault, if the object file is linked with | |
| 11 | # CHECK-SAME: old version of glibc (glibc 2.28 and earlier). If this applies to | |
| 12 | # CHECK-SAME: you, consider recompiling the object files without -fPIC and | |
| 13 | # CHECK-SAME: without -Wl,-z,notext option. Use -no-warn-ifunc-textrel to | |
| 14 | # CHECK-SAME: turn off this warning. | |
| 15 | # CHECK: >>> defined in {{.*}} | |
| 16 | # CHECK: >>> referenced by {{.*}}:(.text+0x8) | |
| 17 | ||
| 18 | # Without text relocations, lld should run fine: | |
| 19 | # RUN: ld.lld --fatal-warnings %t.o -o /dev/null | |
| 20 | ||
| 21 | .text | |
| 22 | .globl a_func_impl | |
| 23 | a_func_impl: | |
| 24 | nop | |
| 25 | ||
| 26 | .globl selector | |
| 27 | .type selector,@function | |
| 28 | selector: | |
| 29 | movl $a_func_impl, %eax | |
| 30 | retq | |
| 31 | ||
| 32 | .globl a_func | |
| 33 | .type a_func,@gnu_indirect_function | |
| 34 | .set a_func, selector | |
| 35 | ||
| 36 | .globl _start | |
| 37 | .type _start,@function | |
| 38 | main: | |
| 39 | callq a_func | |
| 40 | retq |
deps/lld/test/ELF/tls-i686.s+10-10| ... | ... | @@ -32,16 +32,16 @@ _start: |
| 32 | 32 | |
| 33 | 33 | // DIS: Disassembly of section test: |
| 34 | 34 | // DIS-NEXT: _start: |
| 35 | // DIS-NEXT: 11000: ba 08 00 00 00 movl $8, %edx | |
| 36 | // DIS-NEXT: 11005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx | |
| 37 | // DIS-NEXT: 1100c: 29 d0 subl %edx, %eax | |
| 38 | // DIS-NEXT: 1100e: ba 04 00 00 00 movl $4, %edx | |
| 39 | // DIS-NEXT: 11013: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx | |
| 40 | // DIS-NEXT: 1101a: 29 d0 subl %edx, %eax | |
| 41 | // DIS-NEXT: 1101c: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx | |
| 42 | // DIS-NEXT: 11023: 8d 81 f8 ff ff ff leal -8(%ecx), %eax | |
| 43 | // DIS-NEXT: 11029: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx | |
| 44 | // DIS-NEXT: 11030: 8d 81 77 00 00 00 leal 119(%ecx), %eax | |
| 35 | // DIS-NEXT: 401000: ba 08 00 00 00 movl $8, %edx | |
| 36 | // DIS-NEXT: 401005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx | |
| 37 | // DIS-NEXT: 40100c: 29 d0 subl %edx, %eax | |
| 38 | // DIS-NEXT: 40100e: ba 04 00 00 00 movl $4, %edx | |
| 39 | // DIS-NEXT: 401013: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx | |
| 40 | // DIS-NEXT: 40101a: 29 d0 subl %edx, %eax | |
| 41 | // DIS-NEXT: 40101c: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx | |
| 42 | // DIS-NEXT: 401023: 8d 81 f8 ff ff ff leal -8(%ecx), %eax | |
| 43 | // DIS-NEXT: 401029: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx | |
| 44 | // DIS-NEXT: 401030: 8d 81 77 00 00 00 leal 119(%ecx), %eax | |
| 45 | 45 | |
| 46 | 46 | // RELOC: Relocations [ |
| 47 | 47 | // RELOC-NEXT: ] |
deps/lld/test/ELF/tls-in-archive.s+1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | // REQUIRES: x86 |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/tls-in-archive.s -o %t1.o |
| 3 | // RUN: rm -f %t.a | |
| 3 | 4 | // RUN: llvm-ar cru %t.a %t1.o |
| 4 | 5 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o |
| 5 | 6 | // RUN: ld.lld %t2.o %t.a -o /dev/null |
deps/lld/test/ELF/tls-opt-gdiele-i686.s+10-10| ... | ... | @@ -8,21 +8,21 @@ |
| 8 | 8 | |
| 9 | 9 | // NORELOC: Relocations [ |
| 10 | 10 | // NORELOC-NEXT: Section ({{.*}}) .rel.dyn { |
| 11 | // NORELOC-NEXT: 0x12058 R_386_TLS_TPOFF tlsshared0 0x0 | |
| 12 | // NORELOC-NEXT: 0x1205C R_386_TLS_TPOFF tlsshared1 0x0 | |
| 11 | // NORELOC-NEXT: 0x402058 R_386_TLS_TPOFF tlsshared0 0x0 | |
| 12 | // NORELOC-NEXT: 0x40205C R_386_TLS_TPOFF tlsshared1 0x0 | |
| 13 | 13 | // NORELOC-NEXT: } |
| 14 | 14 | // NORELOC-NEXT: ] |
| 15 | 15 | |
| 16 | 16 | // DISASM: Disassembly of section .text: |
| 17 | 17 | // DISASM-NEXT: _start: |
| 18 | // DISASM-NEXT: 11000: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 19 | // DISASM-NEXT: 11006: 03 83 f8 ff ff ff addl -8(%ebx), %eax | |
| 20 | // DISASM-NEXT: 1100c: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 21 | // DISASM-NEXT: 11012: 03 83 fc ff ff ff addl -4(%ebx), %eax | |
| 22 | // DISASM-NEXT: 11018: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 23 | // DISASM-NEXT: 1101e: 81 e8 08 00 00 00 subl $8, %eax | |
| 24 | // DISASM-NEXT: 11024: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 25 | // DISASM-NEXT: 1102a: 81 e8 04 00 00 00 subl $4, %eax | |
| 18 | // DISASM-NEXT: 401000: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 19 | // DISASM-NEXT: 401006: 03 83 f8 ff ff ff addl -8(%ebx), %eax | |
| 20 | // DISASM-NEXT: 40100c: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 21 | // DISASM-NEXT: 401012: 03 83 fc ff ff ff addl -4(%ebx), %eax | |
| 22 | // DISASM-NEXT: 401018: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 23 | // DISASM-NEXT: 40101e: 81 e8 08 00 00 00 subl $8, %eax | |
| 24 | // DISASM-NEXT: 401024: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 25 | // DISASM-NEXT: 40102a: 81 e8 04 00 00 00 subl $4, %eax | |
| 26 | 26 | |
| 27 | 27 | .type tlsexe1,@object |
| 28 | 28 | .section .tbss,"awT",@nobits |
deps/lld/test/ELF/tls-opt-i686.s+16-16| ... | ... | @@ -10,25 +10,25 @@ |
| 10 | 10 | // DISASM: Disassembly of section .text: |
| 11 | 11 | // DISASM-NEXT: _start: |
| 12 | 12 | // LD -> LE: |
| 13 | // DISASM-NEXT: 11000: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 14 | // DISASM-NEXT: 11006: 90 nop | |
| 15 | // DISASM-NEXT: 11007: 8d 74 26 00 leal (%esi,%eiz), %esi | |
| 16 | // DISASM-NEXT: 1100b: 8d 90 f8 ff ff ff leal -8(%eax), %edx | |
| 17 | // DISASM-NEXT: 11011: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 18 | // DISASM-NEXT: 11017: 90 nop | |
| 19 | // DISASM-NEXT: 11018: 8d 74 26 00 leal (%esi,%eiz), %esi | |
| 20 | // DISASM-NEXT: 1101c: 8d 90 fc ff ff ff leal -4(%eax), %edx | |
| 13 | // DISASM-NEXT: 401000: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 14 | // DISASM-NEXT: 401006: 90 nop | |
| 15 | // DISASM-NEXT: 401007: 8d 74 26 00 leal (%esi,%eiz), %esi | |
| 16 | // DISASM-NEXT: 40100b: 8d 90 f8 ff ff ff leal -8(%eax), %edx | |
| 17 | // DISASM-NEXT: 401011: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 18 | // DISASM-NEXT: 401017: 90 nop | |
| 19 | // DISASM-NEXT: 401018: 8d 74 26 00 leal (%esi,%eiz), %esi | |
| 20 | // DISASM-NEXT: 40101c: 8d 90 fc ff ff ff leal -4(%eax), %edx | |
| 21 | 21 | // IE -> LE: |
| 22 | 22 | // 4294967288 == 0xFFFFFFF8 |
| 23 | 23 | // 4294967292 == 0xFFFFFFFC |
| 24 | // DISASM-NEXT: 11022: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 25 | // DISASM-NEXT: 11028: c7 c0 f8 ff ff ff movl $4294967288, %eax | |
| 26 | // DISASM-NEXT: 1102e: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 27 | // DISASM-NEXT: 11034: c7 c0 fc ff ff ff movl $4294967292, %eax | |
| 28 | // DISASM-NEXT: 1103a: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 29 | // DISASM-NEXT: 11040: 8d 80 f8 ff ff ff leal -8(%eax), %eax | |
| 30 | // DISASM-NEXT: 11046: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 31 | // DISASM-NEXT: 1104c: 8d 80 fc ff ff ff leal -4(%eax), %eax | |
| 24 | // DISASM-NEXT: 401022: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 25 | // DISASM-NEXT: 401028: c7 c0 f8 ff ff ff movl $4294967288, %eax | |
| 26 | // DISASM-NEXT: 40102e: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 27 | // DISASM-NEXT: 401034: c7 c0 fc ff ff ff movl $4294967292, %eax | |
| 28 | // DISASM-NEXT: 40103a: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 29 | // DISASM-NEXT: 401040: 8d 80 f8 ff ff ff leal -8(%eax), %eax | |
| 30 | // DISASM-NEXT: 401046: 65 a1 00 00 00 00 movl %gs:0, %eax | |
| 31 | // DISASM-NEXT: 40104c: 8d 80 fc ff ff ff leal -4(%eax), %eax | |
| 32 | 32 | .type tls0,@object |
| 33 | 33 | .section .tbss,"awT",@nobits |
| 34 | 34 | .globl tls0 |
deps/lld/test/ELF/tls-opt-iele-i686-nopic.s+21-21| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | // GOTREL-NEXT: SHF_ALLOC |
| 15 | 15 | // GOTREL-NEXT: SHF_WRITE |
| 16 | 16 | // GOTREL-NEXT: ] |
| 17 | // GOTREL-NEXT: Address: 0x12058 | |
| 17 | // GOTREL-NEXT: Address: 0x402058 | |
| 18 | 18 | // GOTREL-NEXT: Offset: 0x2058 |
| 19 | 19 | // GOTREL-NEXT: Size: 8 |
| 20 | 20 | // GOTREL-NEXT: Link: 0 |
| ... | ... | @@ -24,8 +24,8 @@ |
| 24 | 24 | // GOTREL-NEXT: } |
| 25 | 25 | // GOTREL: Relocations [ |
| 26 | 26 | // GOTREL-NEXT: Section ({{.*}}) .rel.dyn { |
| 27 | // GOTREL-NEXT: 0x12058 R_386_TLS_TPOFF tlsshared0 0x0 | |
| 28 | // GOTREL-NEXT: 0x1205C R_386_TLS_TPOFF tlsshared1 0x0 | |
| 27 | // GOTREL-NEXT: 0x402058 R_386_TLS_TPOFF tlsshared0 0x0 | |
| 28 | // GOTREL-NEXT: 0x40205C R_386_TLS_TPOFF tlsshared1 0x0 | |
| 29 | 29 | // GOTREL-NEXT: } |
| 30 | 30 | // GOTREL-NEXT: ] |
| 31 | 31 | |
| ... | ... | @@ -33,24 +33,24 @@ |
| 33 | 33 | // DISASM-NEXT: _start: |
| 34 | 34 | // 4294967288 = 0xFFFFFFF8 |
| 35 | 35 | // 4294967292 = 0xFFFFFFFC |
| 36 | // 73808 = (.got)[0] = 0x12058 | |
| 37 | // 73812 = (.got)[1] = 0x1205C | |
| 38 | // DISASM-NEXT: 11000: c7 c1 f8 ff ff ff movl $4294967288, %ecx | |
| 39 | // DISASM-NEXT: 11006: 65 8b 01 movl %gs:(%ecx), %eax | |
| 40 | // DISASM-NEXT: 11009: b8 f8 ff ff ff movl $4294967288, %eax | |
| 41 | // DISASM-NEXT: 1100e: 65 8b 00 movl %gs:(%eax), %eax | |
| 42 | // DISASM-NEXT: 11011: 81 c1 f8 ff ff ff addl $4294967288, %ecx | |
| 43 | // DISASM-NEXT: 11017: 65 8b 01 movl %gs:(%ecx), %eax | |
| 44 | // DISASM-NEXT: 1101a: c7 c1 fc ff ff ff movl $4294967292, %ecx | |
| 45 | // DISASM-NEXT: 11020: 65 8b 01 movl %gs:(%ecx), %eax | |
| 46 | // DISASM-NEXT: 11023: b8 fc ff ff ff movl $4294967292, %eax | |
| 47 | // DISASM-NEXT: 11028: 65 8b 00 movl %gs:(%eax), %eax | |
| 48 | // DISASM-NEXT: 1102b: 81 c1 fc ff ff ff addl $4294967292, %ecx | |
| 49 | // DISASM-NEXT: 11031: 65 8b 01 movl %gs:(%ecx), %eax | |
| 50 | // DISASM-NEXT: 11034: 8b 0d 58 20 01 00 movl 73816, %ecx | |
| 51 | // DISASM-NEXT: 1103a: 65 8b 01 movl %gs:(%ecx), %eax | |
| 52 | // DISASM-NEXT: 1103d: 03 0d 5c 20 01 00 addl 73820, %ecx | |
| 53 | // DISASM-NEXT: 11043: 65 8b 01 movl %gs:(%ecx), %eax | |
| 36 | // 4202584 = (.got)[0] = 0x402058 | |
| 37 | // 4202588 = (.got)[1] = 0x40205C | |
| 38 | // DISASM-NEXT: 401000: c7 c1 f8 ff ff ff movl $4294967288, %ecx | |
| 39 | // DISASM-NEXT: 401006: 65 8b 01 movl %gs:(%ecx), %eax | |
| 40 | // DISASM-NEXT: 401009: b8 f8 ff ff ff movl $4294967288, %eax | |
| 41 | // DISASM-NEXT: 40100e: 65 8b 00 movl %gs:(%eax), %eax | |
| 42 | // DISASM-NEXT: 401011: 81 c1 f8 ff ff ff addl $4294967288, %ecx | |
| 43 | // DISASM-NEXT: 401017: 65 8b 01 movl %gs:(%ecx), %eax | |
| 44 | // DISASM-NEXT: 40101a: c7 c1 fc ff ff ff movl $4294967292, %ecx | |
| 45 | // DISASM-NEXT: 401020: 65 8b 01 movl %gs:(%ecx), %eax | |
| 46 | // DISASM-NEXT: 401023: b8 fc ff ff ff movl $4294967292, %eax | |
| 47 | // DISASM-NEXT: 401028: 65 8b 00 movl %gs:(%eax), %eax | |
| 48 | // DISASM-NEXT: 40102b: 81 c1 fc ff ff ff addl $4294967292, %ecx | |
| 49 | // DISASM-NEXT: 401031: 65 8b 01 movl %gs:(%ecx), %eax | |
| 50 | // DISASM-NEXT: 401034: 8b 0d 58 20 40 00 movl 4202584, %ecx | |
| 51 | // DISASM-NEXT: 40103a: 65 8b 01 movl %gs:(%ecx), %eax | |
| 52 | // DISASM-NEXT: 40103d: 03 0d 5c 20 40 00 addl 4202588, %ecx | |
| 53 | // DISASM-NEXT: 401043: 65 8b 01 movl %gs:(%ecx), %eax | |
| 54 | 54 | |
| 55 | 55 | .type tlslocal0,@object |
| 56 | 56 | .section .tbss,"awT",@nobits |
deps/lld/test/ELF/tls-opt-x86_64-noplt.s created+88| ... | ... | @@ -0,0 +1,88 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | ||
| 3 | // Checks whether the TLS optimizations match the cases in Chapter 11 of | |
| 4 | // https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf | |
| 5 | ||
| 6 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 7 | // RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o | |
| 8 | // RUN: ld.lld -shared %tso.o -o %t.so | |
| 9 | // RUN: ld.lld %t.o %t.so -o %t1 | |
| 10 | // RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=RELOC %s | |
| 11 | // RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s | |
| 12 | ||
| 13 | // RELOC: Relocations [ | |
| 14 | // RELOC-NEXT: Section {{.*}} .rela.dyn { | |
| 15 | // RELOC-NEXT: 0x2020C0 R_X86_64_TPOFF64 tlsshared0 0x0 | |
| 16 | // RELOC-NEXT: 0x2020C8 R_X86_64_TPOFF64 tlsshared1 0x0 | |
| 17 | // RELOC-NEXT: } | |
| 18 | // RELOC-NEXT: ] | |
| 19 | ||
| 20 | // DISASM: _start: | |
| 21 | ||
| 22 | // Table 11.5: GD -> IE Code Transition (LP64) | |
| 23 | // DISASM-NEXT: 201000: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax | |
| 24 | // DISASM-NEXT: 201009: 48 03 05 b0 10 00 00 addq 4272(%rip), %rax | |
| 25 | // DISASM-NEXT: 201010: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax | |
| 26 | // DISASM-NEXT: 201019: 48 03 05 a8 10 00 00 addq 4264(%rip), %rax | |
| 27 | ||
| 28 | // Table 11.7: GD -> LE Code Transition (LP64) | |
| 29 | // DISASM-NEXT: 201020: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax | |
| 30 | // DISASM-NEXT: 201029: 48 8d 80 f8 ff ff ff leaq -8(%rax), %rax | |
| 31 | // DISASM-NEXT: 201030: 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax | |
| 32 | // DISASM-NEXT: 201039: 48 8d 80 fc ff ff ff leaq -4(%rax), %rax | |
| 33 | ||
| 34 | ||
| 35 | // Table 11.9: LD -> LE Code Transition (LP64) | |
| 36 | // DISASM-NEXT: 201040: 66 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax | |
| 37 | // DISASM-NEXT: 20104d: 66 66 66 66 64 48 8b 04 25 00 00 00 00 movq %fs:0, %rax | |
| 38 | ||
| 39 | .type tls0,@object | |
| 40 | .section .tbss,"awT",@nobits | |
| 41 | .globl tls0 | |
| 42 | .align 4 | |
| 43 | tls0: | |
| 44 | .long 0 | |
| 45 | .size tls0, 4 | |
| 46 | ||
| 47 | .type tls1,@object | |
| 48 | .globl tls1 | |
| 49 | .align 4 | |
| 50 | tls1: | |
| 51 | .long 0 | |
| 52 | .size tls1, 4 | |
| 53 | ||
| 54 | .section .text | |
| 55 | .globl _start | |
| 56 | _start: | |
| 57 | // Table 11.5: GD -> IE Code Transition (LP64) | |
| 58 | .byte 0x66 | |
| 59 | leaq tlsshared0@tlsgd(%rip),%rdi | |
| 60 | .byte 0x66 | |
| 61 | rex64 | |
| 62 | call *__tls_get_addr@GOTPCREL(%rip) | |
| 63 | ||
| 64 | .byte 0x66 | |
| 65 | leaq tlsshared1@tlsgd(%rip),%rdi | |
| 66 | .byte 0x66 | |
| 67 | rex64 | |
| 68 | call *__tls_get_addr@GOTPCREL(%rip) | |
| 69 | ||
| 70 | // Table 11.7: GD -> LE Code Transition (LP64) | |
| 71 | .byte 0x66 | |
| 72 | leaq tls0@tlsgd(%rip),%rdi | |
| 73 | .byte 0x66 | |
| 74 | rex64 | |
| 75 | call *__tls_get_addr@GOTPCREL(%rip) | |
| 76 | ||
| 77 | .byte 0x66 | |
| 78 | leaq tls1@tlsgd(%rip),%rdi | |
| 79 | .byte 0x66 | |
| 80 | rex64 | |
| 81 | call *__tls_get_addr@GOTPCREL(%rip) | |
| 82 | ||
| 83 | // Table 11.9: LD -> LE Code Transition (LP64) | |
| 84 | leaq tls0@tlsld(%rip),%rdi | |
| 85 | call *__tls_get_addr@GOTPCREL(%rip) | |
| 86 | ||
| 87 | leaq tls1@tlsld(%rip),%rdi | |
| 88 | call *__tls_get_addr@GOTPCREL(%rip) |
deps/lld/test/ELF/tls-static.s-1| ... | ... | @@ -4,7 +4,6 @@ |
| 4 | 4 | // RUN: ld.lld -static %t -o %tout |
| 5 | 5 | // RUN: ld.lld %t -o %tout |
| 6 | 6 | // RUN: ld.lld -shared %tso -o %tshared |
| 7 | // RUN: ld.lld -static %t %tshared -o %tout | |
| 8 | 7 | |
| 9 | 8 | .global _start |
| 10 | 9 | _start: |
deps/lld/test/ELF/tls-weak-undef.s+1| ... | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \ |
| 6 | 6 | // RUN: %p/Inputs/tls-in-archive.s -o %t1.o |
| 7 | // RUN: rm -f %t.a | |
| 7 | 8 | // RUN: llvm-ar cru %t.a %t1.o |
| 8 | 9 | // RUN: ld.lld %t.o %t.a -o %t |
| 9 | 10 |
deps/lld/test/ELF/trace-ar.s+1| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.foo.o |
| 3 | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/trace-ar1.s -o %t.obj1.o |
| 4 | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/trace-ar2.s -o %t.obj2.o |
| 5 | # RUN: rm -f %t.boo.a | |
| 5 | 6 | # RUN: llvm-ar rcs %t.boo.a %t.obj1.o %t.obj2.o |
| 6 | 7 | |
| 7 | 8 | ## Check how -t works with achieves |
deps/lld/test/ELF/trace-symbols.s+2| ... | ... | @@ -8,7 +8,9 @@ |
| 8 | 8 | # RUN: %p/Inputs/trace-symbols-foo-strong.s -o %t2 |
| 9 | 9 | # RUN: ld.lld -shared %t1 -o %t1.so |
| 10 | 10 | # RUN: ld.lld -shared %t2 -o %t2.so |
| 11 | # RUN: rm -f %t1.a | |
| 11 | 12 | # RUN: llvm-ar rcs %t1.a %t1 |
| 13 | # RUN: rm -f %t2.a | |
| 12 | 14 | # RUN: llvm-ar rcs %t2.a %t2 |
| 13 | 15 | |
| 14 | 16 | # RUN: ld.lld -y foo -trace-symbol common -trace-symbol=hsymbol \ |
deps/lld/test/ELF/undef-broken-debug.test+1-1| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | # The debug info has a broken relocation. Check that we don't crash |
| 6 | 6 | # and still report the undefined symbol. |
| 7 | 7 | |
| 8 | # CHECK: error: unsupported relocation target while parsing debug info | |
| 8 | # CHECK: error: {{.*}}.o: relocation R_X86_64_64 at 0x29 has unsupported target | |
| 9 | 9 | # CHECK: error: undefined symbol: bar |
| 10 | 10 | |
| 11 | 11 | --- !ELF |
deps/lld/test/ELF/undef-version-script.s+3-3| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | |
| 7 | 7 | # CHECK: DynamicSymbols [ |
| 8 | 8 | # CHECK-NEXT: Symbol { |
| 9 | # CHECK-NEXT: Name: @ | |
| 9 | # CHECK-NEXT: Name: | |
| 10 | 10 | # CHECK-NEXT: Value: 0x0 |
| 11 | 11 | # CHECK-NEXT: Size: 0 |
| 12 | 12 | # CHECK-NEXT: Binding: Local (0x0) |
| ... | ... | @@ -15,7 +15,7 @@ |
| 15 | 15 | # CHECK-NEXT: Section: Undefined (0x0) |
| 16 | 16 | # CHECK-NEXT: } |
| 17 | 17 | # CHECK-NEXT: Symbol { |
| 18 | # CHECK-NEXT: Name: bar@ | |
| 18 | # CHECK-NEXT: Name: bar | |
| 19 | 19 | # CHECK-NEXT: Value: 0x0 |
| 20 | 20 | # CHECK-NEXT: Size: 0 |
| 21 | 21 | # CHECK-NEXT: Binding: Weak (0x2) |
| ... | ... | @@ -24,7 +24,7 @@ |
| 24 | 24 | # CHECK-NEXT: Section: Undefined (0x0) |
| 25 | 25 | # CHECK-NEXT: } |
| 26 | 26 | # CHECK-NEXT: Symbol { |
| 27 | # CHECK-NEXT: Name: foo@ | |
| 27 | # CHECK-NEXT: Name: foo | |
| 28 | 28 | # CHECK-NEXT: Value: 0x0 |
| 29 | 29 | # CHECK-NEXT: Size: 0 |
| 30 | 30 | # CHECK-NEXT: Binding: Global (0x1) |
deps/lld/test/ELF/undef-with-plt-addr-i686.s+2-2| ... | ... | @@ -17,7 +17,7 @@ mov $set_data, %eax |
| 17 | 17 | // CHECK-NEXT: SHF_ALLOC |
| 18 | 18 | // CHECK-NEXT: SHF_EXECINSTR |
| 19 | 19 | // CHECK-NEXT: ] |
| 20 | // CHECK-NEXT: Address: 0x11010 | |
| 20 | // CHECK-NEXT: Address: 0x401010 | |
| 21 | 21 | |
| 22 | 22 | // CHECK: Name: set_data |
| 23 | // CHECK-NEXT: Value: 0x11020 | |
| 23 | // CHECK-NEXT: Value: 0x401020 |
deps/lld/test/ELF/undef.s+5| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/undef.s -o %t2.o |
| 4 | 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/undef-debug.s -o %t3.o |
| 5 | 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/undef-bad-debug.s -o %t4.o |
| 6 | # RUN: rm -f %t2.a | |
| 6 | 7 | # RUN: llvm-ar rc %t2.a %t2.o |
| 7 | 8 | # RUN: not ld.lld %t.o %t2.a %t3.o %t4.o -o %t.exe 2>&1 | FileCheck %s |
| 8 | 9 | # RUN: not ld.lld -pie %t.o %t2.a %t3.o %t4.o -o %t.exe 2>&1 | FileCheck %s |
| ... | ... | @@ -19,6 +20,9 @@ |
| 19 | 20 | # CHECK: >>> referenced by undef.s |
| 20 | 21 | # CHECK: >>> {{.*}}:(.text+0x10) |
| 21 | 22 | |
| 23 | # CHECK: error: undefined symbol: vtable for Foo | |
| 24 | # CHECK: the vtable symbol may be undefined because the class is missing its key function (see https://lld.llvm.org/missingkeyfunction) | |
| 25 | ||
| 22 | 26 | # CHECK: error: undefined symbol: zed2 |
| 23 | 27 | # CHECK: >>> referenced by {{.*}}.o:(.text+0x0) in archive {{.*}}2.a |
| 24 | 28 | |
| ... | ... | @@ -59,3 +63,4 @@ _start: |
| 59 | 63 | call bar |
| 60 | 64 | call zed1 |
| 61 | 65 | call _Z3fooi |
| 66 | call _ZTV3Foo |
deps/lld/test/ELF/verdef-defaultver.s+4-4| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | |
| 9 | 9 | # DSO: DynamicSymbols [ |
| 10 | 10 | # DSO-NEXT: Symbol { |
| 11 | # DSO-NEXT: Name: @ | |
| 11 | # DSO-NEXT: Name: | |
| 12 | 12 | # DSO-NEXT: Value: 0x0 |
| 13 | 13 | # DSO-NEXT: Size: 0 |
| 14 | 14 | # DSO-NEXT: Binding: Local |
| ... | ... | @@ -61,7 +61,7 @@ |
| 61 | 61 | # DSO-NEXT: Symbols [ |
| 62 | 62 | # DSO-NEXT: Symbol { |
| 63 | 63 | # DSO-NEXT: Version: 0 |
| 64 | # DSO-NEXT: Name: @ | |
| 64 | # DSO-NEXT: Name: | |
| 65 | 65 | # DSO-NEXT: } |
| 66 | 66 | # DSO-NEXT: Symbol { |
| 67 | 67 | # DSO-NEXT: Version: 2 |
| ... | ... | @@ -112,7 +112,7 @@ |
| 112 | 112 | |
| 113 | 113 | # EXE: DynamicSymbols [ |
| 114 | 114 | # EXE-NEXT: Symbol { |
| 115 | # EXE-NEXT: Name: @ | |
| 115 | # EXE-NEXT: Name: | |
| 116 | 116 | # EXE-NEXT: Value: 0x0 |
| 117 | 117 | # EXE-NEXT: Size: 0 |
| 118 | 118 | # EXE-NEXT: Binding: Local |
| ... | ... | @@ -156,7 +156,7 @@ |
| 156 | 156 | # EXE-NEXT: Symbols [ |
| 157 | 157 | # EXE-NEXT: Symbol { |
| 158 | 158 | # EXE-NEXT: Version: 0 |
| 159 | # EXE-NEXT: Name: @ | |
| 159 | # EXE-NEXT: Name: | |
| 160 | 160 | # EXE-NEXT: } |
| 161 | 161 | # EXE-NEXT: Symbol { |
| 162 | 162 | # EXE-NEXT: Version: 2 |
deps/lld/test/ELF/verdef.s+2-2| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | # DSO-NEXT: Symbols [ |
| 15 | 15 | # DSO-NEXT: Symbol { |
| 16 | 16 | # DSO-NEXT: Version: 0 |
| 17 | # DSO-NEXT: Name: @ | |
| 17 | # DSO-NEXT: Name: | |
| 18 | 18 | # DSO-NEXT: } |
| 19 | 19 | # DSO-NEXT: Symbol { |
| 20 | 20 | # DSO-NEXT: Version: 2 |
| ... | ... | @@ -76,7 +76,7 @@ |
| 76 | 76 | # MAIN-NEXT: Symbols [ |
| 77 | 77 | # MAIN-NEXT: Symbol { |
| 78 | 78 | # MAIN-NEXT: Version: 0 |
| 79 | # MAIN-NEXT: Name: @ | |
| 79 | # MAIN-NEXT: Name: | |
| 80 | 80 | # MAIN-NEXT: } |
| 81 | 81 | # MAIN-NEXT: Symbol { |
| 82 | 82 | # MAIN-NEXT: Version: 2 |
deps/lld/test/ELF/verneed.s+2-2| ... | ... | @@ -76,7 +76,7 @@ |
| 76 | 76 | |
| 77 | 77 | # CHECK: DynamicSymbols [ |
| 78 | 78 | # CHECK-NEXT: Symbol { |
| 79 | # CHECK-NEXT: Name: @ | |
| 79 | # CHECK-NEXT: Name: | |
| 80 | 80 | # CHECK-NEXT: Value: 0x0 |
| 81 | 81 | # CHECK-NEXT: Size: 0 |
| 82 | 82 | # CHECK-NEXT: Binding: Local (0x0) |
| ... | ... | @@ -125,7 +125,7 @@ |
| 125 | 125 | # CHECK-NEXT: Symbols [ |
| 126 | 126 | # CHECK-NEXT: Symbol { |
| 127 | 127 | # CHECK-NEXT: Version: 0 |
| 128 | # CHECK-NEXT: Name: @ | |
| 128 | # CHECK-NEXT: Name: | |
| 129 | 129 | # CHECK-NEXT: } |
| 130 | 130 | # CHECK-NEXT: Symbol { |
| 131 | 131 | # CHECK-NEXT: Version: 2 |
deps/lld/test/ELF/version-exclude-libs.s+1| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | 1 | // REQUIRES: x86 |
| 2 | 2 | // RUN: llvm-mc %p/Inputs/versiondef.s -o %t.o -filetype=obj -triple=x86_64-pc-linux |
| 3 | // RUN: rm -f %t.a | |
| 3 | 4 | // RUN: llvm-ar -r %t.a %t.o |
| 4 | 5 | // RUN: llvm-mc %s -o %t2.o -filetype=obj -triple=x86_64-pc-linux |
| 5 | 6 | // RUN: ld.lld %t2.o %t.a --shared --exclude-libs ALL -o %t.so |
deps/lld/test/ELF/version-script-complex-wildcards.s+4-4| ... | ... | @@ -4,14 +4,14 @@ |
| 4 | 4 | # RUN: echo "FOO { global: extern \"C++\" { ab[c]*; }; };" > %t.script |
| 5 | 5 | # RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so |
| 6 | 6 | # RUN: llvm-readobj -V %t.so | FileCheck %s --check-prefix=ABC |
| 7 | # ABC: Name: _Z3abbi@ | |
| 7 | # ABC: Name: _Z3abbi | |
| 8 | 8 | # ABC: Name: _Z3abci@@FOO |
| 9 | 9 | |
| 10 | 10 | # RUN: echo "FOO { global: extern \"C++\" { ab[b]*; }; };" > %t1.script |
| 11 | 11 | # RUN: ld.lld --version-script %t1.script -shared %t.o -o %t1.so |
| 12 | 12 | # RUN: llvm-readobj -V %t1.so | FileCheck %s --check-prefix=ABB |
| 13 | 13 | # ABB: Name: _Z3abbi@@FOO |
| 14 | # ABB: Name: _Z3abci@ | |
| 14 | # ABB: Name: _Z3abci | |
| 15 | 15 | |
| 16 | 16 | # RUN: echo "FOO { global: extern \"C++\" { ab[a-b]*; }; };" > %t2.script |
| 17 | 17 | # RUN: ld.lld --version-script %t2.script -shared %t.o -o %t2.so |
| ... | ... | @@ -34,8 +34,8 @@ |
| 34 | 34 | # RUN: echo "FOO { global: extern \"C++\" { ab[^a-c]*; }; };" > %t6.script |
| 35 | 35 | # RUN: ld.lld --version-script %t6.script -shared %t.o -o %t6.so |
| 36 | 36 | # RUN: llvm-readobj -V %t6.so | FileCheck %s --check-prefix=NO |
| 37 | # NO: Name: _Z3abbi@ | |
| 38 | # NO: Name: _Z3abci@ | |
| 37 | # NO: Name: _Z3abbi | |
| 38 | # NO: Name: _Z3abci | |
| 39 | 39 | |
| 40 | 40 | # RUN: echo "FOO { global: extern \"C++\" { ab[^c-z]*; }; };" > %t7.script |
| 41 | 41 | # RUN: ld.lld --version-script %t7.script -shared %t.o -o %t7.so |
deps/lld/test/ELF/version-script-extern-undefined.s+2-2| ... | ... | @@ -8,11 +8,11 @@ |
| 8 | 8 | # CHECK: Symbols [ |
| 9 | 9 | # CHECK-NEXT: Symbol { |
| 10 | 10 | # CHECK-NEXT: Version: 0 |
| 11 | # CHECK-NEXT: Name: @ | |
| 11 | # CHECK-NEXT: Name: | |
| 12 | 12 | # CHECK-NEXT: } |
| 13 | 13 | # CHECK-NEXT: Symbol { |
| 14 | 14 | # CHECK-NEXT: Version: 1 |
| 15 | # CHECK-NEXT: Name: _Z3abbi@ | |
| 15 | # CHECK-NEXT: Name: _Z3abbi | |
| 16 | 16 | # CHECK-NEXT: } |
| 17 | 17 | # CHECK-NEXT: ] |
| 18 | 18 |
deps/lld/test/ELF/version-script-extern-wildcards.s+1-1| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | |
| 9 | 9 | # CHECK: Version symbols { |
| 10 | 10 | # CHECK: Symbols [ |
| 11 | # CHECK: Name: _Z3bari@ | |
| 11 | # CHECK: Name: _Z3bari | |
| 12 | 12 | # CHECK: Name: _Z3fooi@@FOO |
| 13 | 13 | # CHECK: Name: _Z3zedi@@BAR |
| 14 | 14 |
deps/lld/test/ELF/version-script-extern.s+2-2| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | |
| 13 | 13 | # DSO: DynamicSymbols [ |
| 14 | 14 | # DSO-NEXT: Symbol { |
| 15 | # DSO-NEXT: Name: @ | |
| 15 | # DSO-NEXT: Name: | |
| 16 | 16 | # DSO-NEXT: Value: 0x0 |
| 17 | 17 | # DSO-NEXT: Size: 0 |
| 18 | 18 | # DSO-NEXT: Binding: Local |
| ... | ... | @@ -74,7 +74,7 @@ |
| 74 | 74 | # DSO-NEXT: Symbols [ |
| 75 | 75 | # DSO-NEXT: Symbol { |
| 76 | 76 | # DSO-NEXT: Version: 0 |
| 77 | # DSO-NEXT: Name: @ | |
| 77 | # DSO-NEXT: Name: | |
| 78 | 78 | # DSO-NEXT: } |
| 79 | 79 | # DSO-NEXT: Symbol { |
| 80 | 80 | # DSO-NEXT: Version: 3 |
deps/lld/test/ELF/version-script-extern2.s+1-1| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | # CHECK: Symbols [ |
| 9 | 9 | # CHECK-NEXT: Symbol { |
| 10 | 10 | # CHECK-NEXT: Version: 0 |
| 11 | # CHECK-NEXT: Name: @ | |
| 11 | # CHECK-NEXT: Name: | |
| 12 | 12 | # CHECK-NEXT: } |
| 13 | 13 | # CHECK-NEXT: Symbol { |
| 14 | 14 | # CHECK-NEXT: Version: 2 |
deps/lld/test/ELF/version-script-hide-so-symbol.s+1-1| ... | ... | @@ -12,7 +12,7 @@ |
| 12 | 12 | |
| 13 | 13 | # CHECK: DynamicSymbols [ |
| 14 | 14 | # CHECK-NEXT: Symbol { |
| 15 | # CHECK-NEXT: Name: @ (0) | |
| 15 | # CHECK-NEXT: Name: | |
| 16 | 16 | # CHECK-NEXT: Value: 0x0 |
| 17 | 17 | # CHECK-NEXT: Size: 0 |
| 18 | 18 | # CHECK-NEXT: Binding: Local |
deps/lld/test/ELF/version-script-locals-extern.s+4-4| ... | ... | @@ -7,11 +7,11 @@ |
| 7 | 7 | # ABB: Symbols [ |
| 8 | 8 | # ABB-NEXT: Symbol { |
| 9 | 9 | # ABB-NEXT: Version: 0 |
| 10 | # ABB-NEXT: Name: @ | |
| 10 | # ABB-NEXT: Name: | |
| 11 | 11 | # ABB-NEXT: } |
| 12 | 12 | # ABB-NEXT: Symbol { |
| 13 | 13 | # ABB-NEXT: Version: 1 |
| 14 | # ABB-NEXT: Name: _Z3abci@ | |
| 14 | # ABB-NEXT: Name: _Z3abci | |
| 15 | 15 | # ABB-NEXT: } |
| 16 | 16 | # ABB-NEXT: ] |
| 17 | 17 | |
| ... | ... | @@ -26,11 +26,11 @@ |
| 26 | 26 | # ABC: Symbols [ |
| 27 | 27 | # ABC-NEXT: Symbol { |
| 28 | 28 | # ABC-NEXT: Version: 0 |
| 29 | # ABC-NEXT: Name: @ | |
| 29 | # ABC-NEXT: Name: | |
| 30 | 30 | # ABC-NEXT: } |
| 31 | 31 | # ABC-NEXT: Symbol { |
| 32 | 32 | # ABC-NEXT: Version: 1 |
| 33 | # ABC-NEXT: Name: _Z3abbi@ | |
| 33 | # ABC-NEXT: Name: _Z3abbi | |
| 34 | 34 | # ABC-NEXT: } |
| 35 | 35 | # ABC-NEXT: ] |
| 36 | 36 |
deps/lld/test/ELF/version-script-symver2.s+1-1| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | # CHECK: Symbols [ |
| 8 | 8 | # CHECK-NEXT: Symbol { |
| 9 | 9 | # CHECK-NEXT: Version: 0 |
| 10 | # CHECK-NEXT: Name: @ | |
| 10 | # CHECK-NEXT: Name: | |
| 11 | 11 | # CHECK-NEXT: } |
| 12 | 12 | # CHECK-NEXT: Symbol { |
| 13 | 13 | # CHECK-NEXT: Version: 3 |
deps/lld/test/ELF/version-script-weak.s+1-1| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | # CHECK-NEXT: } |
| 15 | 15 | # CHECK-NEXT: ] |
| 16 | 16 | # CHECK: Symbol { |
| 17 | # CHECK: Name: foo@ | |
| 17 | # CHECK: Name: foo | |
| 18 | 18 | # CHECK-NEXT: Value: 0x0 |
| 19 | 19 | # CHECK-NEXT: Size: 0 |
| 20 | 20 | # CHECK-NEXT: Binding: Weak |
deps/lld/test/ELF/version-script.s+14-14| ... | ... | @@ -50,7 +50,7 @@ |
| 50 | 50 | |
| 51 | 51 | # DSO: DynamicSymbols [ |
| 52 | 52 | # DSO-NEXT: Symbol { |
| 53 | # DSO-NEXT: Name: @ | |
| 53 | # DSO-NEXT: Name: | |
| 54 | 54 | # DSO-NEXT: Value: 0x0 |
| 55 | 55 | # DSO-NEXT: Size: 0 |
| 56 | 56 | # DSO-NEXT: Binding: Local (0x0) |
| ... | ... | @@ -59,7 +59,7 @@ |
| 59 | 59 | # DSO-NEXT: Section: Undefined (0x0) |
| 60 | 60 | # DSO-NEXT: } |
| 61 | 61 | # DSO-NEXT: Symbol { |
| 62 | # DSO-NEXT: Name: bar@ | |
| 62 | # DSO-NEXT: Name: bar | |
| 63 | 63 | # DSO-NEXT: Value: 0x0 |
| 64 | 64 | # DSO-NEXT: Size: 0 |
| 65 | 65 | # DSO-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -68,7 +68,7 @@ |
| 68 | 68 | # DSO-NEXT: Section: Undefined (0x0) |
| 69 | 69 | # DSO-NEXT: } |
| 70 | 70 | # DSO-NEXT: Symbol { |
| 71 | # DSO-NEXT: Name: foo1@ | |
| 71 | # DSO-NEXT: Name: foo1 | |
| 72 | 72 | # DSO-NEXT: Value: 0x1000 |
| 73 | 73 | # DSO-NEXT: Size: 0 |
| 74 | 74 | # DSO-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -77,7 +77,7 @@ |
| 77 | 77 | # DSO-NEXT: Section: .text |
| 78 | 78 | # DSO-NEXT: } |
| 79 | 79 | # DSO-NEXT: Symbol { |
| 80 | # DSO-NEXT: Name: foo3@ | |
| 80 | # DSO-NEXT: Name: foo3 | |
| 81 | 81 | # DSO-NEXT: Value: 0x1007 |
| 82 | 82 | # DSO-NEXT: Size: 0 |
| 83 | 83 | # DSO-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -89,7 +89,7 @@ |
| 89 | 89 | |
| 90 | 90 | # DSO2: DynamicSymbols [ |
| 91 | 91 | # DSO2-NEXT: Symbol { |
| 92 | # DSO2-NEXT: Name: @ | |
| 92 | # DSO2-NEXT: Name: | |
| 93 | 93 | # DSO2-NEXT: Value: 0x0 |
| 94 | 94 | # DSO2-NEXT: Size: 0 |
| 95 | 95 | # DSO2-NEXT: Binding: Local (0x0) |
| ... | ... | @@ -98,7 +98,7 @@ |
| 98 | 98 | # DSO2-NEXT: Section: Undefined (0x0) |
| 99 | 99 | # DSO2-NEXT: } |
| 100 | 100 | # DSO2-NEXT: Symbol { |
| 101 | # DSO2-NEXT: Name: bar@ | |
| 101 | # DSO2-NEXT: Name: bar | |
| 102 | 102 | # DSO2-NEXT: Value: 0x0 |
| 103 | 103 | # DSO2-NEXT: Size: 0 |
| 104 | 104 | # DSO2-NEXT: Binding: Global (0x1) |
| ... | ... | @@ -110,7 +110,7 @@ |
| 110 | 110 | |
| 111 | 111 | # VERDSO: DynamicSymbols [ |
| 112 | 112 | # VERDSO-NEXT: Symbol { |
| 113 | # VERDSO-NEXT: Name: @ | |
| 113 | # VERDSO-NEXT: Name: | |
| 114 | 114 | # VERDSO-NEXT: Value: 0x0 |
| 115 | 115 | # VERDSO-NEXT: Size: 0 |
| 116 | 116 | # VERDSO-NEXT: Binding: Local |
| ... | ... | @@ -119,7 +119,7 @@ |
| 119 | 119 | # VERDSO-NEXT: Section: Undefined |
| 120 | 120 | # VERDSO-NEXT: } |
| 121 | 121 | # VERDSO-NEXT: Symbol { |
| 122 | # VERDSO-NEXT: Name: bar@ | |
| 122 | # VERDSO-NEXT: Name: bar | |
| 123 | 123 | # VERDSO-NEXT: Value: 0x0 |
| 124 | 124 | # VERDSO-NEXT: Size: 0 |
| 125 | 125 | # VERDSO-NEXT: Binding: Global |
| ... | ... | @@ -158,7 +158,7 @@ |
| 158 | 158 | |
| 159 | 159 | # ALL: DynamicSymbols [ |
| 160 | 160 | # ALL-NEXT: Symbol { |
| 161 | # ALL-NEXT: Name: @ | |
| 161 | # ALL-NEXT: Name: | |
| 162 | 162 | # ALL-NEXT: Value: 0x0 |
| 163 | 163 | # ALL-NEXT: Size: 0 |
| 164 | 164 | # ALL-NEXT: Binding: Local |
| ... | ... | @@ -167,7 +167,7 @@ |
| 167 | 167 | # ALL-NEXT: Section: Undefined |
| 168 | 168 | # ALL-NEXT: } |
| 169 | 169 | # ALL-NEXT: Symbol { |
| 170 | # ALL-NEXT: Name: _start@ | |
| 170 | # ALL-NEXT: Name: _start | |
| 171 | 171 | # ALL-NEXT: Value: |
| 172 | 172 | # ALL-NEXT: Size: 0 |
| 173 | 173 | # ALL-NEXT: Binding: Global |
| ... | ... | @@ -176,7 +176,7 @@ |
| 176 | 176 | # ALL-NEXT: Section: .text |
| 177 | 177 | # ALL-NEXT: } |
| 178 | 178 | # ALL-NEXT: Symbol { |
| 179 | # ALL-NEXT: Name: bar@ | |
| 179 | # ALL-NEXT: Name: bar | |
| 180 | 180 | # ALL-NEXT: Value: |
| 181 | 181 | # ALL-NEXT: Size: 0 |
| 182 | 182 | # ALL-NEXT: Binding: Global |
| ... | ... | @@ -185,7 +185,7 @@ |
| 185 | 185 | # ALL-NEXT: Section: Undefined |
| 186 | 186 | # ALL-NEXT: } |
| 187 | 187 | # ALL-NEXT: Symbol { |
| 188 | # ALL-NEXT: Name: foo1@ | |
| 188 | # ALL-NEXT: Name: foo1 | |
| 189 | 189 | # ALL-NEXT: Value: |
| 190 | 190 | # ALL-NEXT: Size: 0 |
| 191 | 191 | # ALL-NEXT: Binding: Global |
| ... | ... | @@ -194,7 +194,7 @@ |
| 194 | 194 | # ALL-NEXT: Section: .text |
| 195 | 195 | # ALL-NEXT: } |
| 196 | 196 | # ALL-NEXT: Symbol { |
| 197 | # ALL-NEXT: Name: foo2@ | |
| 197 | # ALL-NEXT: Name: foo2 | |
| 198 | 198 | # ALL-NEXT: Value: |
| 199 | 199 | # ALL-NEXT: Size: 0 |
| 200 | 200 | # ALL-NEXT: Binding: Global |
| ... | ... | @@ -203,7 +203,7 @@ |
| 203 | 203 | # ALL-NEXT: Section: .text |
| 204 | 204 | # ALL-NEXT: } |
| 205 | 205 | # ALL-NEXT: Symbol { |
| 206 | # ALL-NEXT: Name: foo3@ | |
| 206 | # ALL-NEXT: Name: foo3 | |
| 207 | 207 | # ALL-NEXT: Value: |
| 208 | 208 | # ALL-NEXT: Size: 0 |
| 209 | 209 | # ALL-NEXT: Binding: Global |
deps/lld/test/ELF/version-wildcard.test+2-2| ... | ... | @@ -7,7 +7,7 @@ |
| 7 | 7 | |
| 8 | 8 | # CHECK: DynamicSymbols [ |
| 9 | 9 | # CHECK-NEXT: Symbol { |
| 10 | # CHECK-NEXT: Name: @ | |
| 10 | # CHECK-NEXT: Name: | |
| 11 | 11 | # CHECK-NEXT: Value: 0x0 |
| 12 | 12 | # CHECK-NEXT: Size: 0 |
| 13 | 13 | # CHECK-NEXT: Binding: Local |
| ... | ... | @@ -52,7 +52,7 @@ |
| 52 | 52 | |
| 53 | 53 | # MIX: DynamicSymbols [ |
| 54 | 54 | # MIX-NEXT: Symbol { |
| 55 | # MIX-NEXT: Name: @ | |
| 55 | # MIX-NEXT: Name: | |
| 56 | 56 | # MIX-NEXT: Value: 0x0 |
| 57 | 57 | # MIX-NEXT: Size: 0 |
| 58 | 58 | # MIX-NEXT: Binding: Local |
deps/lld/test/ELF/visibility.s+1-1| ... | ... | @@ -82,7 +82,7 @@ |
| 82 | 82 | |
| 83 | 83 | // CHECK: DynamicSymbols [ |
| 84 | 84 | // CHECK-NEXT: Symbol { |
| 85 | // CHECK-NEXT: Name: @ | |
| 85 | // CHECK-NEXT: Name: | |
| 86 | 86 | // CHECK-NEXT: Value: 0x0 |
| 87 | 87 | // CHECK-NEXT: Size: 0 |
| 88 | 88 | // CHECK-NEXT: Binding: Local |
deps/lld/test/ELF/weak-undef-export.s+2-2| ... | ... | @@ -8,7 +8,7 @@ |
| 8 | 8 | |
| 9 | 9 | # CHECK: DynamicSymbols [ |
| 10 | 10 | # CHECK-NEXT: Symbol { |
| 11 | # CHECK-NEXT: Name: @ (0) | |
| 11 | # CHECK-NEXT: Name: | |
| 12 | 12 | # CHECK-NEXT: Value: 0x0 |
| 13 | 13 | # CHECK-NEXT: Size: 0 |
| 14 | 14 | # CHECK-NEXT: Binding: Local (0x0) |
| ... | ... | @@ -17,7 +17,7 @@ |
| 17 | 17 | # CHECK-NEXT: Section: Undefined (0x0) |
| 18 | 18 | # CHECK-NEXT: } |
| 19 | 19 | # CHECK-NEXT: Symbol { |
| 20 | # CHECK-NEXT: Name: foo@ (1) | |
| 20 | # CHECK-NEXT: Name: foo | |
| 21 | 21 | # CHECK-NEXT: Value: 0x0 |
| 22 | 22 | # CHECK-NEXT: Size: 0 |
| 23 | 23 | # CHECK-NEXT: Binding: Weak (0x2) |
deps/lld/test/ELF/weak-undef.s+2-2| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | # CHECK: DynamicSymbols [ |
| 7 | 7 | # CHECK-NEXT: Symbol { |
| 8 | # CHECK-NEXT: Name: @ | |
| 8 | # CHECK-NEXT: Name: | |
| 9 | 9 | # CHECK-NEXT: Value: 0x0 |
| 10 | 10 | # CHECK-NEXT: Size: 0 |
| 11 | 11 | # CHECK-NEXT: Binding: Local (0x0) |
| ... | ... | @@ -14,7 +14,7 @@ |
| 14 | 14 | # CHECK-NEXT: Section: Undefined (0x0) |
| 15 | 15 | # CHECK-NEXT: } |
| 16 | 16 | # CHECK-NEXT: Symbol { |
| 17 | # CHECK-NEXT: Name: foo@ | |
| 17 | # CHECK-NEXT: Name: foo | |
| 18 | 18 | # CHECK-NEXT: Value: 0x0 |
| 19 | 19 | # CHECK-NEXT: Size: 0 |
| 20 | 20 | # CHECK-NEXT: Binding: Weak |
deps/lld/test/ELF/wrap-entry.s created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o | |
| 3 | ||
| 4 | // RUN: ld.lld -o %t.exe %t.o -wrap=_start | |
| 5 | // RUN: llvm-readobj -file-headers %t.exe | FileCheck %s | |
| 6 | ||
| 7 | // CHECK: Entry: 0x201001 | |
| 8 | ||
| 9 | .global _start, __wrap__start | |
| 10 | _start: | |
| 11 | nop | |
| 12 | __wrap__start: | |
| 13 | nop |
deps/lld/test/ELF/wrap-no-real.s+6-52| ... | ... | @@ -15,60 +15,14 @@ |
| 15 | 15 | // CHECK-NEXT: movl $0x11010, %edx |
| 16 | 16 | // CHECK-NEXT: movl $0x11000, %edx |
| 17 | 17 | |
| 18 | // RUN: llvm-readobj -t %t | FileCheck -check-prefix=SYM %s | |
| 18 | // RUN: llvm-objdump -t %t | FileCheck -check-prefix=SYM %s | |
| 19 | 19 | |
| 20 | // Test the full symbol table. It is verbose, but lld at times | |
| 21 | // produced duplicated symbols which are hard to test otherwise. | |
| 22 | 20 | |
| 23 | // SYM: Symbols [ | |
| 24 | // SYM-NEXT: Symbol { | |
| 25 | // SYM-NEXT: Name: (0) | |
| 26 | // SYM-NEXT: Value: | |
| 27 | // SYM-NEXT: Size: | |
| 28 | // SYM-NEXT: Binding: | |
| 29 | // SYM-NEXT: Type | |
| 30 | // SYM-NEXT: Other: | |
| 31 | // SYM-NEXT: Section: | |
| 32 | // SYM-NEXT: } | |
| 33 | // SYM-NEXT: Symbol { | |
| 34 | // SYM-NEXT: Name: _DYNAMIC | |
| 35 | // SYM-NEXT: Value: | |
| 36 | // SYM-NEXT: Size: | |
| 37 | // SYM-NEXT: Binding: | |
| 38 | // SYM-NEXT: Type: | |
| 39 | // SYM-NEXT: Other [ | |
| 40 | // SYM-NEXT: STV_HIDDEN | |
| 41 | // SYM-NEXT: ] | |
| 42 | // SYM-NEXT: Section: .dynamic | |
| 43 | // SYM-NEXT: } | |
| 44 | // SYM-NEXT: Symbol { | |
| 45 | // SYM-NEXT: Name: foo | |
| 46 | // SYM-NEXT: Value: 0x11000 | |
| 47 | // SYM-NEXT: Size: | |
| 48 | // SYM-NEXT: Binding: | |
| 49 | // SYM-NEXT: Type: | |
| 50 | // SYM-NEXT: Other: | |
| 51 | // SYM-NEXT: Section: | |
| 52 | // SYM-NEXT: } | |
| 53 | // SYM-NEXT: Symbol { | |
| 54 | // SYM-NEXT: Name: _start | |
| 55 | // SYM-NEXT: Value: | |
| 56 | // SYM-NEXT: Size: | |
| 57 | // SYM-NEXT: Binding: | |
| 58 | // SYM-NEXT: Type | |
| 59 | // SYM-NEXT: Other: | |
| 60 | // SYM-NEXT: Section: | |
| 61 | // SYM-NEXT: } | |
| 62 | // SYM-NEXT: Symbol { | |
| 63 | // SYM-NEXT: Name: __wrap_foo | |
| 64 | // SYM-NEXT: Value: 0x11010 | |
| 65 | // SYM-NEXT: Size: | |
| 66 | // SYM-NEXT: Binding: | |
| 67 | // SYM-NEXT: Type: | |
| 68 | // SYM-NEXT: Other: | |
| 69 | // SYM-NEXT: Section: | |
| 70 | // SYM-NEXT: } | |
| 71 | // SYM-NEXT: ] | |
| 21 | // SYM: 0000000000202000 .dynamic 00000000 .hidden _DYNAMIC | |
| 22 | // SYM-NEXT: 0000000000011000 *ABS* 00000000 __real_foo | |
| 23 | // SYM-NEXT: 0000000000011010 *ABS* 00000000 __wrap_foo | |
| 24 | // SYM-NEXT: 0000000000201000 .text 00000000 _start | |
| 25 | // SYM-NEXT: 0000000000011000 *ABS* 00000000 foo | |
| 72 | 26 | |
| 73 | 27 | .global _start |
| 74 | 28 | _start: |
deps/lld/test/ELF/wrap-plt.s created+45| ... | ... | @@ -0,0 +1,45 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | |
| 3 | ||
| 4 | // RUN: ld.lld -o %t2 %t -wrap foo -shared | |
| 5 | // RUN: llvm-readobj -s -r %t2 | FileCheck %s | |
| 6 | // RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s | |
| 7 | ||
| 8 | // CHECK: Name: .plt | |
| 9 | // CHECK-NEXT: Type: SHT_PROGBITS | |
| 10 | // CHECK-NEXT: Flags [ | |
| 11 | // CHECK-NEXT: SHF_ALLOC | |
| 12 | // CHECK-NEXT: SHF_EXECINSTR | |
| 13 | // CHECK-NEXT: ] | |
| 14 | // CHECK-NEXT: Address: 0x1020 | |
| 15 | // CHECK-NEXT: Offset: | |
| 16 | // CHECK-NEXT: Size: 48 | |
| 17 | // CHECK-NEXT: Link: 0 | |
| 18 | // CHECK-NEXT: Info: 0 | |
| 19 | // CHECK-NEXT: AddressAlignment: 16 | |
| 20 | ||
| 21 | // CHECK: Relocations [ | |
| 22 | // CHECK-NEXT: Section ({{.*}}) .rela.plt { | |
| 23 | // CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT __wrap_foo 0x0 | |
| 24 | // CHECK-NEXT: 0x2020 R_X86_64_JUMP_SLOT _start 0x0 | |
| 25 | // CHECK-NEXT: } | |
| 26 | // CHECK-NEXT: ] | |
| 27 | ||
| 28 | // DISASM: _start: | |
| 29 | // DISASM-NEXT: jmp 41 | |
| 30 | // DISASM-NEXT: jmp 36 | |
| 31 | // DISASM-NEXT: jmp 47 | |
| 32 | ||
| 33 | .global foo | |
| 34 | foo: | |
| 35 | nop | |
| 36 | ||
| 37 | .global __wrap_foo | |
| 38 | __wrap_foo: | |
| 39 | nop | |
| 40 | ||
| 41 | .global _start | |
| 42 | _start: | |
| 43 | jmp foo@plt | |
| 44 | jmp __wrap_foo@plt | |
| 45 | jmp _start@plt |
deps/lld/test/ELF/wrap-with-archive.s created+13| ... | ... | @@ -0,0 +1,13 @@ |
| 1 | // REQUIRES: x86 | |
| 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t | |
| 3 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/wrap-with-archive.s -o %t2 | |
| 4 | // RUN: llvm-ar rcs %t3 %t2 | |
| 5 | // RUN: ld.lld -o %t4 %t %t3 -wrap get_executable_start | |
| 6 | ||
| 7 | // Regression test for https://bugs.llvm.org/show_bug.cgi?id=40134 | |
| 8 | 	 | |
| 9 | .global get_executable_start | |
| 10 | .global _start | |
| 11 | ||
| 12 | _start: | |
| 13 | 	jmp get_executable_start |
deps/lld/test/ELF/wrap.s+1-1| ... | ... | @@ -34,7 +34,7 @@ |
| 34 | 34 | // SYM2-NEXT: STV_PROTECTED |
| 35 | 35 | // SYM2-NEXT: ] |
| 36 | 36 | // SYM3: Name: __real_foo |
| 37 | // SYM3-NEXT: Value: 0x11020 | |
| 37 | // SYM3-NEXT: Value: 0x11000 | |
| 38 | 38 | // SYM3-NEXT: Size: |
| 39 | 39 | // SYM3-NEXT: Binding: Global |
| 40 | 40 | // SYM3-NEXT: Type: None |
deps/lld/test/ELF/x86-64-combined-dynrel.s created+40| ... | ... | @@ -0,0 +1,40 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc --triple=x86_64-pc-linux -filetype=obj -o %t.o %s | |
| 3 | # RUN: echo "SECTIONS { \ | |
| 4 | # RUN: .text : { *(.text) } \ | |
| 5 | # RUN: .rela.dyn : { *(.rela.dyn) *(.rela.plt) } \ | |
| 6 | # RUN: } " > %t.script | |
| 7 | # RUN: ld.lld %t.o -o %t.so --shared --script %t.script | |
| 8 | # RUN: llvm-readobj --section-headers --dynamic-table %t.so | FileCheck %s | |
| 9 | ||
| 10 | // The linker script above combines the .rela.dyn and .rela.plt into a single | |
| 11 | // table. ELF is clear that the DT_PLTRELSZ should match the subset of | |
| 12 | // relocations that is associated with the PLT. It is less clear about what | |
| 13 | // the value of DT_RELASZ should be. ELF implies that it should be the size | |
| 14 | // of the single table so that DT_RELASZ includes DT_PLTRELSZ. The loader in | |
| 15 | // glibc permits this as long as .rela.plt comes after .rela.dyn in the | |
| 16 | // combined table. | |
| 17 | ||
| 18 | .text | |
| 19 | .globl func | |
| 20 | .type func, %function | |
| 21 | .globl foo | |
| 22 | .type foo, %object | |
| 23 | ||
| 24 | .globl _start | |
| 25 | .type _start, %function | |
| 26 | _start: | |
| 27 | call func@plt | |
| 28 | movq func@GOTPCREL (%rip), %rax | |
| 29 | ||
| 30 | # CHECK: Name: .rela.dyn | |
| 31 | # CHECK-NEXT: Type: SHT_RELA | |
| 32 | # CHECK-NEXT: Flags [ | |
| 33 | # CHECK-NEXT: SHF_ALLOC | |
| 34 | # CHECK-NEXT: ] | |
| 35 | # CHECK-NEXT: Address: | |
| 36 | # CHECK-NEXT: Offset: | |
| 37 | # CHECK-NEXT: Size: 48 | |
| 38 | ||
| 39 | # CHECK: 0x0000000000000008 RELASZ 48 | |
| 40 | # CHECK: 0x0000000000000002 PLTRELSZ 24 |
deps/lld/test/ELF/x86-64-reloc-error2.s+1-1| ... | ... | @@ -4,7 +4,7 @@ |
| 4 | 4 | |
| 5 | 5 | ## Check we are able to find a function symbol that encloses |
| 6 | 6 | ## a given location when reporting error messages. |
| 7 | # CHECK: {{.*}}.o:(function func): relocation R_X86_64_32S out of range: -281474974609408 is not in [-2147483648, 2147483647] | |
| 7 | # CHECK: {{.*}}.o:(function func: .text.func+0x3): relocation R_X86_64_32S out of range: -281474974609408 is not in [-2147483648, 2147483647] | |
| 8 | 8 | |
| 9 | 9 | # This mergeable section will be garbage collected. We had a crash issue in that case. Test it. |
| 10 | 10 | .section .rodata.str1,"aMS",@progbits,1 |
deps/lld/test/ELF/x86-64-reloc-gotoff64.s+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | // REQUIRES: x86 |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | 3 | // RUN: ld.lld %t.o -shared -o %t.so |
| 4 | // RUN: llvm-readelf -s %t.so | FileCheck %s -check-prefix=SECTION | |
| 4 | // RUN: llvm-readelf -S %t.so | FileCheck %s -check-prefix=SECTION | |
| 5 | 5 | // RUN: llvm-objdump -d %t.so | FileCheck %s |
| 6 | 6 | |
| 7 | 7 | // SECTION: .dynamic DYNAMIC 0000000000003000 |
deps/lld/test/ELF/x86-64-reloc-gotpc64.s+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | // REQUIRES: x86 |
| 2 | 2 | // RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o |
| 3 | 3 | // RUN: ld.lld %t.o -shared -o %t.so |
| 4 | // RUN: llvm-readelf -s %t.so | FileCheck %s -check-prefix=SECTION | |
| 4 | // RUN: llvm-readelf -S %t.so | FileCheck %s -check-prefix=SECTION | |
| 5 | 5 | // RUN: llvm-objdump -d %t.so | FileCheck %s |
| 6 | 6 | |
| 7 | 7 | // SECTION: .got PROGBITS 0000000000003070 003070 000000 |
deps/lld/test/ELF/x86-64-reloc-range-debug-loc.s+1-1| ... | ... | @@ -5,7 +5,7 @@ |
| 5 | 5 | |
| 6 | 6 | ## Check we are able to report file and location from debug information |
| 7 | 7 | ## when reporting such kind of errors. |
| 8 | # CHECK: error: test.s:3: relocation R_X86_64_32 out of range: 68719476736 is not in [0, 4294967295] | |
| 8 | # CHECK: error: test.s:3:(.text+0x1): relocation R_X86_64_32 out of range: 68719476736 is not in [0, 4294967295] | |
| 9 | 9 | |
| 10 | 10 | .section .text,"ax",@progbits |
| 11 | 11 | foo: |
deps/lld/test/ELF/x86-64-reloc-range.s+2| ... | ... | @@ -1,6 +1,8 @@ |
| 1 | 1 | // REQUIRES: x86 |
| 2 | 2 | // RUN: llvm-mc %s -o %t.o -triple x86_64-pc-linux -filetype=obj |
| 3 | 3 | // RUN: not ld.lld %t.o -o /dev/null -shared 2>&1 | FileCheck %s |
| 4 | // RUN: ld.lld --noinhibit-exec -shared %t.o -o %t 2>&1 | FileCheck %s | |
| 5 | // RUN: ls %t | |
| 4 | 6 | |
| 5 | 7 | // CHECK: {{.*}}:(.text+0x3): relocation R_X86_64_PC32 out of range: 2147483648 is not in [-2147483648, 2147483647] |
| 6 | 8 | // CHECK-NOT: relocation |
deps/lld/test/ELF/x86-64-retpoline-znow-static-iplt.s created+26| ... | ... | @@ -0,0 +1,26 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o | |
| 3 | # RUN: ld.lld -z retpolineplt -z now %t.o -o %t | |
| 4 | # RUN: llvm-objdump -d -no-show-raw-insn %t | FileCheck %s | |
| 5 | ||
| 6 | #0x201001+5 + 42 = 0x201030 (foo@plt) | |
| 7 | # CHECK: _start: | |
| 8 | # CHECK-NEXT: 201001: callq 42 | |
| 9 | ||
| 10 | #Static IPLT header due to -z retpolineplt | |
| 11 | # CHECK: 0000000000201010 .plt: | |
| 12 | # CHECK-NEXT: 201010: callq 11 <.plt+0x10> | |
| 13 | # CHECK-NEXT: 201015: pause | |
| 14 | # CHECK-NEXT: 201017: lfence | |
| 15 | #foo@plt | |
| 16 | # CHECK: 201030: movq 4041(%rip), %r11 | |
| 17 | # CHECK-NEXT: 201037: jmp -44 <.plt> | |
| 18 | ||
| 19 | .type foo STT_GNU_IFUNC | |
| 20 | .globl foo | |
| 21 | foo: | |
| 22 | ret | |
| 23 | ||
| 24 | .globl _start | |
| 25 | _start: | |
| 26 | call foo |
deps/lld/test/ELF/x86-64-split-stack-prologue-adjust-fail.s+8-4| ... | ... | @@ -1,14 +1,18 @@ |
| 1 | 1 | # REQUIRES: x86 |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t2.o | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-extra.s -o %t2.o | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t3.o | |
| 4 | 5 | |
| 5 | # RUN: not ld.lld --defsym __morestack=0x100 %t1.o %t2.o -o %t 2>&1 | FileCheck %s | |
| 6 | # RUN: not ld.lld --defsym __morestack=0x100 --defsym __more_stack_nonsplit=0x200 %t1.o %t2.o %t3.o -o %t 2>&1 | FileCheck %s | |
| 6 | 7 | |
| 7 | 8 | # An unknown prologue gives a match failure |
| 8 | # CHECK: unable to adjust the enclosing function's | |
| 9 | # CHECK: error: {{.*}}.o:(.text): unknown_prologue (with -fsplit-stack) calls non_split (without -fsplit-stack), but couldn't adjust its prologue | |
| 9 | 10 | |
| 10 | 11 | # RUN: not ld.lld -r --defsym __morestack=0x100 %t1.o %t2.o -o %t 2>&1 | FileCheck %s -check-prefix=RELOCATABLE |
| 11 | # RELOCATABLE: Cannot mix split-stack and non-split-stack in a relocatable link | |
| 12 | # RELOCATABLE: cannot mix split-stack and non-split-stack in a relocatable link | |
| 13 | ||
| 14 | # RUN: not ld.lld --defsym __morestack=0x100 --defsym _start=0x300 %t1.o %t2.o %t3.o -o %t 2>&1 | FileCheck %s -check-prefix=ERROR | |
| 15 | # ERROR: Mixing split-stack objects requires a definition of __morestack_non_split | |
| 12 | 16 | |
| 13 | 17 | 	.text |
| 14 | 18 |
deps/lld/test/ELF/x86-64-split-stack-prologue-adjust-shared.s created+31| ... | ... | @@ -0,0 +1,31 @@ |
| 1 | # REQUIRES: x86 | |
| 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-extra.s -o %t2.o | |
| 3 | # RUN: ld.lld --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 %t2.o -o %t4.so -shared | |
| 4 | ||
| 5 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o | |
| 6 | # RUN: ld.lld --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 %t1.o %t4.so -o %t | |
| 7 | # RUN: llvm-objdump -d %t | FileCheck %s | |
| 8 | ||
| 9 | # For a cross .so call, make sure lld produced the conservative call to __morestack_non_split. | |
| 10 | # CHECK: prologue1_cross_so_call: | |
| 11 | # CHECK-NEXT: stc{{.*$}} | |
| 12 | # CHECK-NEXT: nopl{{.*$}} | |
| 13 | # CHECK: jae{{.*$}} | |
| 14 | # CHECK-NEXT: callq{{.*}}<__morestack_non_split> | |
| 15 | ||
| 16 | 	.text | |
| 17 | ||
| 18 | 	.global	prologue1_cross_so_call | |
| 19 | 	.type	prologue1_cross_so_call,@function | |
| 20 | prologue1_cross_so_call: | |
| 21 | 	cmp %fs:0x70,%rsp | |
| 22 | 	jae 1f | |
| 23 | 	callq __morestack | |
| 24 | 	retq | |
| 25 | 1: | |
| 26 | 	callq split | |
| 27 | 	retq | |
| 28 | 	.size	prologue1_cross_so_call,. - prologue1_cross_so_call | |
| 29 | ||
| 30 | 	.section	.note.GNU-stack,"",@progbits | |
| 31 | 	.section	.note.GNU-split-stack,"",@progbits |
deps/lld/test/ELF/x86-64-split-stack-prologue-adjust-silent.s+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o |
| 3 | 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t2.o |
| 4 | 4 | |
| 5 | # RUN: ld.lld --defsym __morestack=0x100 %t1.o %t2.o -o %t | |
| 5 | # RUN: ld.lld --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 %t1.o %t2.o -o %t | |
| 6 | 6 | # RUN: llvm-objdump -d %t 2>&1 | FileCheck %s |
| 7 | 7 | |
| 8 | 8 | # An unknown prologue ordinarily gives a match failure, except that this |
deps/lld/test/ELF/x86-64-split-stack-prologue-adjust-success.s+13-22| ... | ... | @@ -1,8 +1,9 @@ |
| 1 | 1 | # REQUIRES: x86 |
| 2 | 2 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t2.o | |
| 3 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-extra.s -o %t2.o | |
| 4 | # RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-split-stack-main.s -o %t3.o | |
| 4 | 5 | |
| 5 | # RUN: ld.lld --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 %t1.o %t2.o -o %t -z notext | |
| 6 | # RUN: ld.lld --defsym __morestack=0x100 --defsym __morestack_non_split=0x200 %t1.o %t2.o %t3.o -o %t -z notext | |
| 6 | 7 | # RUN: llvm-objdump -d %t | FileCheck %s |
| 7 | 8 | |
| 8 | 9 | # Avoid duplicating the prologue for every test via macros. |
| ... | ... | @@ -25,11 +26,11 @@ prologue1_calls_\function_to_call: |
| 25 | 26 | 	.size	prologue1_calls_\function_to_call,. - prologue1_calls_\function_to_call |
| 26 | 27 | .endm |
| 27 | 28 | |
| 28 | .macro prologue2 function_to_call register | |
| 29 | .macro prologue2 function_to_call register compare_amount | |
| 29 | 30 | 	.global	prologue2_calls_\function_to_call\register |
| 30 | 31 | 	.type	prologue2_calls_\function_to_call\register,@function |
| 31 | 32 | prologue2_calls_\function_to_call\register: |
| 32 | 	lea	-0x200(%rsp),%\register | |
| 33 | 	lea	-\compare_amount(%rsp),%\register | |
| 33 | 34 | 	cmp	%fs:0x70,%\register |
| 34 | 35 | 	jae	1f |
| 35 | 36 | 	callq	__morestack |
| ... | ... | @@ -65,20 +66,20 @@ prologue1 split |
| 65 | 66 | # calls plain __morestack, that any raw bytes written to the prologue |
| 66 | 67 | # make sense, and that the register number is preserved. |
| 67 | 68 | # CHECK: prologue2_calls_splitr10: |
| 68 | # CHECK-NEXT: lea{{.*}} -{{[0-9]+}}(%rsp),{{.*}}%r10 | |
| 69 | # CHECK-NEXT: lea{{.*}} -512(%rsp),{{.*}}%r10 | |
| 69 | 70 | # CHECK: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r{{[0-9]+}} |
| 70 | 71 | # CHECK: jae{{.*}} |
| 71 | 72 | # CHECK-NEXT: callq{{.*}}<__morestack> |
| 72 | 73 | |
| 73 | prologue2 split r10 | |
| 74 | prologue2 split r10 0x200 | |
| 74 | 75 | |
| 75 | 76 | # CHECK: prologue2_calls_splitr11: |
| 76 | # CHECK-NEXT: lea{{.*}} -{{[0-9]+}}(%rsp),{{.*}}%r11 | |
| 77 | # CHECK-NEXT: lea{{.*}} -256(%rsp),{{.*}}%r11 | |
| 77 | 78 | # CHECK: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r{{[0-9]+}} |
| 78 | 79 | # CHECK: jae{{.*}} |
| 79 | 80 | # CHECK-NEXT: callq{{.*}}<__morestack> |
| 80 | 81 | |
| 81 | prologue2 split r11 | |
| 82 | prologue2 split r11 0x100 | |
| 82 | 83 | |
| 83 | 84 | # For split-stack code calling non-split-stack code, ensure prologue v1 |
| 84 | 85 | # calls __morestack_non_split, and that any raw bytes written to the prologue |
| ... | ... | @@ -95,30 +96,20 @@ prologue1 non_split |
| 95 | 96 | # calls __morestack_non_split, that any raw bytes written to the prologue |
| 96 | 97 | # make sense, and that the register number is preserved |
| 97 | 98 | # CHECK: prologue2_calls_non_splitr10: |
| 98 | # CHECK-NEXT: lea{{.*$}} | |
| 99 | # CHECK-NEXT: lea{{.*}} -16640(%rsp),{{.*}}%r10 | |
| 99 | 100 | # CHECK: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r10 |
| 100 | 101 | # CHECK: jae{{.*$}} |
| 101 | 102 | # CHECK-NEXT: callq{{.*}}<__morestack_non_split> |
| 102 | 103 | |
| 103 | prologue2 non_split r10 | |
| 104 | prologue2 non_split r10 0x100 | |
| 104 | 105 | |
| 105 | 106 | # CHECK: prologue2_calls_non_splitr11: |
| 106 | # CHECK-NEXT: lea{{.*$}} | |
| 107 | # CHECK-NEXT: lea{{.*}} -16896(%rsp),{{.*}}%r11 | |
| 107 | 108 | # CHECK: cmp{{.*}}%fs:{{[^,]*}},{{.*}}%r11 |
| 108 | 109 | # CHECK: jae{{.*$}} |
| 109 | 110 | # CHECK-NEXT: callq{{.*}}<__morestack_non_split> |
| 110 | 111 | |
| 111 | prologue2 non_split r11 | |
| 112 | #	call foo@plt # for code-coverage. | |
| 113 | ||
| 114 | ||
| 115 | ||
| 116 | 	.global	split | |
| 117 | 	.type	split,@function | |
| 118 | split: | |
| 119 | 	retq | |
| 120 | ||
| 121 | 	.size	split,. - split | |
| 112 | prologue2 non_split r11 0x200 | |
| 122 | 113 | |
| 123 | 114 | 	.section	.note.GNU-stack,"",@progbits |
| 124 | 115 | 	.section	.note.GNU-split-stack,"",@progbits |
deps/lld/test/ELF/znotext-plt-relocations-protected.s+6-1| ... | ... | @@ -4,7 +4,12 @@ |
| 4 | 4 | # RUN: ld.lld %t2.o -o %t2.so -shared |
| 5 | 5 | # RUN: not ld.lld -z notext %t.o %t2.so -o /dev/null 2>&1 | FileCheck %s |
| 6 | 6 | |
| 7 | # CHECK: error: cannot preempt symbol: foo | |
| 7 | # CHECK: error: cannot preempt symbol: foo | |
| 8 | # CHECK-NEXT: >>> defined in {{.*}}2.so | |
| 9 | # CHECK-NEXT: >>> referenced by test.cpp | |
| 10 | # CHECK-NEXT: >>> {{.*}}.o:(.text+0x0) | |
| 11 | ||
| 12 | .file "test.cpp" | |
| 8 | 13 | |
| 9 | 14 | .global _start |
| 10 | 15 | _start: |
deps/lld/test/ELF/zstack-size.s+3| ... | ... | @@ -6,6 +6,9 @@ |
| 6 | 6 | # RUN: ld.lld -z stack-size=0 %t -o %t2 |
| 7 | 7 | # RUN: llvm-readobj -program-headers %t2 | FileCheck %s -check-prefix=CHECK2 |
| 8 | 8 | |
| 9 | # RUN: ld.lld -z stack-size=0x2000 -z stack-size=0x1000 %t -o %t3 | |
| 10 | # RUN: llvm-readobj -program-headers %t3 | FileCheck %s -check-prefix=CHECK1 | |
| 11 | ||
| 9 | 12 | .global _start |
| 10 | 13 | _start: |
| 11 | 14 | nop |
deps/lld/test/MinGW/driver.test+6| ... | ... | @@ -145,3 +145,9 @@ RUN: ld.lld -### foo.o -m i386pep --Map bar.map | FileCheck -check-prefix=MAP %s |
| 145 | 145 | RUN: ld.lld -### foo.o -m i386pep -Map=bar.map | FileCheck -check-prefix=MAP %s |
| 146 | 146 | RUN: ld.lld -### foo.o -m i386pep --Map=bar.map | FileCheck -check-prefix=MAP %s |
| 147 | 147 | MAP: -lldmap:bar.map |
| 148 | ||
| 149 | RUN: ld.lld -### foo.o -m i386pe -require-defined _foo --require-defined _bar -require-defined=_baz --require-defined=_foo2 | FileCheck -check-prefix=REQUIRE-DEFINED %s | |
| 150 | REQUIRE-DEFINED: -include:_foo -include:_bar -include:_baz -include:_foo2 | |
| 151 | ||
| 152 | RUN: ld.lld -### -m i386pep foo.o -Llibpath | FileCheck -check-prefix LIBPATH %s | |
| 153 | LIBPATH: -libpath:libpath |
deps/lld/test/lit.cfg.py+14-4| ... | ... | @@ -45,13 +45,18 @@ tool_patterns = [ |
| 45 | 45 | |
| 46 | 46 | llvm_config.add_tool_substitutions(tool_patterns) |
| 47 | 47 | |
| 48 | # LLD tests tend to be flaky on NetBSD, so add some retries. | |
| 49 | # We don't do this on other platforms because it's slower. | |
| 50 | if platform.system() in ['NetBSD']: | |
| 51 | config.test_retry_attempts = 2 | |
| 52 | ||
| 48 | 53 | # When running under valgrind, we mangle '-vg' onto the end of the triple so we |
| 49 | 54 | # can check it with XFAIL and XTARGET. |
| 50 | 55 | if lit_config.useValgrind: |
| 51 | 56 | config.target_triple += '-vg' |
| 52 | 57 | |
| 53 | 58 | # Running on ELF based *nix |
| 54 | if platform.system() in ['FreeBSD', 'Linux']: | |
| 59 | if platform.system() in ['FreeBSD', 'NetBSD', 'Linux']: | |
| 55 | 60 | config.available_features.add('system-linker-elf') |
| 56 | 61 | |
| 57 | 62 | # Set if host-cxxabi's demangler can handle target's symbols. |
| ... | ... | @@ -67,7 +72,9 @@ llvm_config.feature_config( |
| 67 | 72 | 'AVR': 'avr', |
| 68 | 73 | 'Hexagon': 'hexagon', |
| 69 | 74 | 'Mips': 'mips', |
| 75 | 'MSP430': 'msp430', | |
| 70 | 76 | 'PowerPC': 'ppc', |
| 77 | 'RISCV': 'riscv', | |
| 71 | 78 | 'Sparc': 'sparc', |
| 72 | 79 | 'WebAssembly': 'wasm', |
| 73 | 80 | 'X86': 'x86'}) |
| ... | ... | @@ -93,7 +100,10 @@ if config.have_dia_sdk: |
| 93 | 100 | tar_executable = lit.util.which('tar', config.environment['PATH']) |
| 94 | 101 | if tar_executable: |
| 95 | 102 | tar_version = subprocess.Popen( |
| 96 | [tar_executable, '--version'], stdout=subprocess.PIPE, env={'LANG': 'C'}) | |
| 97 | if 'GNU tar' in tar_version.stdout.read().decode(): | |
| 103 | [tar_executable, '--version'], | |
| 104 | stdout=subprocess.PIPE, | |
| 105 | stderr=subprocess.PIPE, | |
| 106 | env={'LANG': 'C'}) | |
| 107 | sout, _ = tar_version.communicate() | |
| 108 | if 'GNU tar' in sout.decode(): | |
| 98 | 109 | config.available_features.add('gnutar') |
| 99 | tar_version.wait() |
deps/lld/test/lit.site.cfg.py.in+2-1| ... | ... | @@ -25,7 +25,8 @@ except KeyError as e: |
| 25 | 25 | key, = e.args |
| 26 | 26 | lit_config.fatal("unable to find %r parameter, use '--param=%s=VALUE'" % (key,key)) |
| 27 | 27 | |
| 28 | @LIT_SITE_CFG_IN_FOOTER@ | |
| 28 | import lit.llvm | |
| 29 | lit.llvm.initialize(lit_config, config) | |
| 29 | 30 | |
| 30 | 31 | # Let the main config do the real work. |
| 31 | 32 | lit_config.load_config(config, "@LLD_SOURCE_DIR@/test/lit.cfg.py") |
deps/lld/test/mach-o/cstring-sections.yaml+4-4| ... | ... | @@ -36,25 +36,25 @@ sections: |
| 36 | 36 | # CHECK: content: [ 61, 62, 63, 00 ] |
| 37 | 37 | # CHECK: merge: by-content |
| 38 | 38 | # CHECK: section-choice: custom-required |
| 39 | # CHECK: section-name: __TEXT/__objc_methname | |
| 39 | # CHECK: section-name: '__TEXT/__objc_methname' | |
| 40 | 40 | # CHECK: - scope: hidden |
| 41 | 41 | # CHECK: type: c-string |
| 42 | 42 | # CHECK: content: [ 64, 65, 66, 00 ] |
| 43 | 43 | # CHECK: merge: by-content |
| 44 | 44 | # CHECK: section-choice: custom-required |
| 45 | # CHECK: section-name: __TEXT/__objc_methname | |
| 45 | # CHECK: section-name: '__TEXT/__objc_methname' | |
| 46 | 46 | # CHECK: - scope: hidden |
| 47 | 47 | # CHECK: type: c-string |
| 48 | 48 | # CHECK: content: [ 61, 62, 63, 00 ] |
| 49 | 49 | # CHECK: merge: by-content |
| 50 | 50 | # CHECK: section-choice: custom-required |
| 51 | # CHECK: section-name: __TEXT/__objc_classname | |
| 51 | # CHECK: section-name: '__TEXT/__objc_classname' | |
| 52 | 52 | # CHECK: - scope: hidden |
| 53 | 53 | # CHECK: type: c-string |
| 54 | 54 | # CHECK: content: [ 67, 68, 69, 00 ] |
| 55 | 55 | # CHECK: merge: by-content |
| 56 | 56 | # CHECK: section-choice: custom-required |
| 57 | # CHECK: section-name: __TEXT/__objc_classname | |
| 57 | # CHECK: section-name: '__TEXT/__objc_classname' | |
| 58 | 58 | # CHECK: - scope: hidden |
| 59 | 59 | # CHECK: type: c-string |
| 60 | 60 | # CHECK: content: [ 61, 62, 63, 00 ] |
deps/lld/test/mach-o/parse-data-relocs-x86_64.yaml+1-1| ... | ... | @@ -367,6 +367,6 @@ page-size: 0x00000000 |
| 367 | 367 | # CHECK: type: unknown |
| 368 | 368 | # CHECK: content: [ 00, 00, 00, 00, 00, 00, 00, 00 ] |
| 369 | 369 | # CHECK: section-choice: custom-required |
| 370 | # CHECK: section-name: __DATA/__custom | |
| 370 | # CHECK: section-name: '__DATA/__custom' | |
| 371 | 371 | # CHECK: dead-strip: never |
| 372 | 372 |
deps/lld/test/mach-o/parse-data.yaml+1-1| ... | ... | @@ -115,5 +115,5 @@ global-symbols: |
| 115 | 115 | # CHECK: type: unknown |
| 116 | 116 | # CHECK: content: [ 01, 02, 03, 04, 05, 06, 07, 08 ] |
| 117 | 117 | # CHECK: section-choice: custom-required |
| 118 | # CHECK: section-name: __CUST/__custom | |
| 118 | # CHECK: section-name: '__CUST/__custom' | |
| 119 | 119 |
deps/lld/test/mach-o/sectcreate.yaml+1-1| ... | ... | @@ -8,5 +8,5 @@ |
| 8 | 8 | # CHECK: type: sectcreate |
| 9 | 9 | # CHECK: content: [ 68, 65, 6C, 6C, 6F, 0A ] |
| 10 | 10 | # CHECK: section-choice: custom-required |
| 11 | # CHECK: section-name: __DATA/__data | |
| 11 | # CHECK: section-name: '__DATA/__data' | |
| 12 | 12 | # CHECK: dead-strip: never |
deps/lld/test/wasm/Inputs/event-section1.ll created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" | |
| 2 | target triple = "wasm32-unknown-unknown" | |
| 3 | ||
| 4 | declare void @llvm.wasm.throw(i32, i8*) | |
| 5 | ||
| 6 | define void @foo(i8* %p) { | |
| 7 | call void @llvm.wasm.throw(i32 0, i8* %p) | |
| 8 | ret void | |
| 9 | } |
deps/lld/test/wasm/Inputs/event-section2.ll created+9| ... | ... | @@ -0,0 +1,9 @@ |
| 1 | target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" | |
| 2 | target triple = "wasm32-unknown-unknown" | |
| 3 | ||
| 4 | declare void @llvm.wasm.throw(i32, i8*) | |
| 5 | ||
| 6 | define void @bar(i8* %p) { | |
| 7 | call void @llvm.wasm.throw(i32 0, i8* %p) | |
| 8 | ret void | |
| 9 | } |
deps/lld/test/wasm/Inputs/globals.yaml+1-1| ... | ... | @@ -34,7 +34,7 @@ Sections: |
| 34 | 34 | Offset: 0x00000004 |
| 35 | 35 | - Type: CUSTOM |
| 36 | 36 | Name: linking |
| 37 | Version: 1 | |
| 37 | Version: 2 | |
| 38 | 38 | SymbolTable: |
| 39 | 39 | - Index: 0 |
| 40 | 40 | Kind: GLOBAL |
deps/lld/test/wasm/Inputs/undefined-globals.yaml+1-1| ... | ... | @@ -32,7 +32,7 @@ Sections: |
| 32 | 32 | Offset: 0x00000004 |
| 33 | 33 | - Type: CUSTOM |
| 34 | 34 | Name: linking |
| 35 | Version: 1 | |
| 35 | Version: 2 | |
| 36 | 36 | SymbolTable: |
| 37 | 37 | - Index: 0 |
| 38 | 38 | Kind: GLOBAL |
deps/lld/test/wasm/alias.ll+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj -o %t.o %s |
| 2 | ; RUN: wasm-ld %t.o -o %t.wasm | |
| 2 | ; RUN: wasm-ld --export=start_alias %t.o -o %t.wasm | |
| 3 | 3 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 4 | 4 | |
| 5 | 5 | target triple = "wasm32-unknown-unknown" |
| ... | ... | @@ -25,7 +25,7 @@ entry: |
| 25 | 25 | ; CHECK-NEXT: FunctionTypes: [ 0, 0 ] |
| 26 | 26 | ; CHECK-NEXT: - Type: TABLE |
| 27 | 27 | ; CHECK-NEXT: Tables: |
| 28 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 28 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 29 | 29 | ; CHECK-NEXT: Limits: |
| 30 | 30 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 31 | 31 | ; CHECK-NEXT: Initial: 0x00000001 |
deps/lld/test/wasm/archive-export.ll created+50| ... | ... | @@ -0,0 +1,50 @@ |
| 1 | Test that --export will also fetch lazy symbols from archives | |
| 2 | ||
| 3 | RUN: llc -filetype=obj %S/Inputs/start.ll -o %t.o | |
| 4 | RUN: llc -filetype=obj %S/Inputs/archive1.ll -o %t.a1.o | |
| 5 | RUN: llc -filetype=obj %S/Inputs/archive2.ll -o %t.a2.o | |
| 6 | RUN: rm -f %t.a | |
| 7 | RUN: llvm-ar rcs %t.a %t.a1.o %t.a2.o | |
| 8 | RUN: wasm-ld --export-dynamic --export=archive2_symbol -o %t.wasm %t.a %t.o | |
| 9 | RUN: obj2yaml %t.wasm | FileCheck %s | |
| 10 | RUN: wasm-ld --export-dynamic -o %t.wasm %t.a %t.o | |
| 11 | RUN: obj2yaml %t.wasm | FileCheck %s -check-prefix=NOEXPORT | |
| 12 | ||
| 13 | CHECK: Exports: | |
| 14 | CHECK-NEXT: - Name: memory | |
| 15 | CHECK-NEXT: Kind: MEMORY | |
| 16 | CHECK-NEXT: Index: 0 | |
| 17 | CHECK-NEXT: - Name: __heap_base | |
| 18 | CHECK-NEXT: Kind: GLOBAL | |
| 19 | CHECK-NEXT: Index: 1 | |
| 20 | CHECK-NEXT: - Name: __data_end | |
| 21 | CHECK-NEXT: Kind: GLOBAL | |
| 22 | CHECK-NEXT: Index: 2 | |
| 23 | CHECK-NEXT: - Name: foo | |
| 24 | CHECK-NEXT: Kind: FUNCTION | |
| 25 | CHECK-NEXT: Index: 2 | |
| 26 | CHECK-NEXT: - Name: bar | |
| 27 | CHECK-NEXT: Kind: FUNCTION | |
| 28 | CHECK-NEXT: Index: 3 | |
| 29 | CHECK-NEXT: - Name: archive2_symbol | |
| 30 | CHECK-NEXT: Kind: FUNCTION | |
| 31 | CHECK-NEXT: Index: 4 | |
| 32 | CHECK-NEXT: - Name: _start | |
| 33 | CHECK-NEXT: Kind: FUNCTION | |
| 34 | CHECK-NEXT: Index: 1 | |
| 35 | CHECK-NEXT: - Type: CODE | |
| 36 | ||
| 37 | NOEXPORT: Exports: | |
| 38 | NOEXPORT-NEXT: - Name: memory | |
| 39 | NOEXPORT-NEXT: Kind: MEMORY | |
| 40 | NOEXPORT-NEXT: Index: 0 | |
| 41 | NOEXPORT-NEXT: - Name: __heap_base | |
| 42 | NOEXPORT-NEXT: Kind: GLOBAL | |
| 43 | NOEXPORT-NEXT: Index: 1 | |
| 44 | NOEXPORT-NEXT: - Name: __data_end | |
| 45 | NOEXPORT-NEXT: Kind: GLOBAL | |
| 46 | NOEXPORT-NEXT: Index: 2 | |
| 47 | NOEXPORT-NEXT: - Name: _start | |
| 48 | NOEXPORT-NEXT: Kind: FUNCTION | |
| 49 | NOEXPORT-NEXT: Index: 1 | |
| 50 | NOEXPORT-NEXT: - Type: CODE |
deps/lld/test/wasm/archive.ll+1| ... | ... | @@ -3,6 +3,7 @@ |
| 3 | 3 | ; RUN: llc -filetype=obj %S/Inputs/archive2.ll -o %t.a2.o |
| 4 | 4 | ; RUN: llc -filetype=obj %S/Inputs/archive3.ll -o %t.a3.o |
| 5 | 5 | ; RUN: llc -filetype=obj %S/Inputs/hello.ll -o %t.hello.o |
| 6 | ; RUN: rm -f %t.a | |
| 6 | 7 | ; RUN: llvm-ar rcs %t.a %t.a1.o %t.a2.o %t.a3.o %t.hello.o |
| 7 | 8 | ; RUN: rm -f %t.imports |
| 8 | 9 | ; RUN: not wasm-ld %t.a %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED %s |
deps/lld/test/wasm/call-indirect.ll+5-5| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj %p/Inputs/call-indirect.ll -o %t2.o |
| 2 | 2 | ; RUN: llc -filetype=obj %s -o %t.o |
| 3 | ; RUN: wasm-ld -o %t.wasm %t2.o %t.o | |
| 3 | ; RUN: wasm-ld --export-dynamic -o %t.wasm %t2.o %t.o | |
| 4 | 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 5 | 5 | |
| 6 | 6 | ; bitcode generated from the following C code: |
| ... | ... | @@ -60,7 +60,7 @@ define void @call_ptr(i64 (i64)* %arg) { |
| 60 | 60 | ; CHECK-NEXT: FunctionTypes: [ 3, 0, 3, 1, 3, 4 ] |
| 61 | 61 | ; CHECK-NEXT: - Type: TABLE |
| 62 | 62 | ; CHECK-NEXT: Tables: |
| 63 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 63 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 64 | 64 | ; CHECK-NEXT: Limits: |
| 65 | 65 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 66 | 66 | ; CHECK-NEXT: Initial: 0x00000003 |
| ... | ... | @@ -105,9 +105,6 @@ define void @call_ptr(i64 (i64)* %arg) { |
| 105 | 105 | ; CHECK-NEXT: - Name: __data_end |
| 106 | 106 | ; CHECK-NEXT: Kind: GLOBAL |
| 107 | 107 | ; CHECK-NEXT: Index: 2 |
| 108 | ; CHECK-NEXT: - Name: _start | |
| 109 | ; CHECK-NEXT: Kind: FUNCTION | |
| 110 | ; CHECK-NEXT: Index: 4 | |
| 111 | 108 | ; CHECK-NEXT: - Name: bar |
| 112 | 109 | ; CHECK-NEXT: Kind: FUNCTION |
| 113 | 110 | ; CHECK-NEXT: Index: 1 |
| ... | ... | @@ -117,6 +114,9 @@ define void @call_ptr(i64 (i64)* %arg) { |
| 117 | 114 | ; CHECK-NEXT: - Name: foo |
| 118 | 115 | ; CHECK-NEXT: Kind: FUNCTION |
| 119 | 116 | ; CHECK-NEXT: Index: 3 |
| 117 | ; CHECK-NEXT: - Name: _start | |
| 118 | ; CHECK-NEXT: Kind: FUNCTION | |
| 119 | ; CHECK-NEXT: Index: 4 | |
| 120 | 120 | ; CHECK-NEXT: - Name: indirect_func |
| 121 | 121 | ; CHECK-NEXT: Kind: GLOBAL |
| 122 | 122 | ; CHECK-NEXT: Index: 3 |
deps/lld/test/wasm/comdats.ll+1-1| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %p/Inputs/comdat1.ll -o %t1.o |
| 2 | 2 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %p/Inputs/comdat2.ll -o %t2.o |
| 3 | 3 | ; RUN: llc -filetype=obj -mtriple=wasm32-unknown-uknown-wasm %s -o %t.o |
| 4 | ; RUN: wasm-ld -o %t.wasm %t.o %t1.o %t2.o | |
| 4 | ; RUN: wasm-ld --export-dynamic -o %t.wasm %t.o %t1.o %t2.o | |
| 5 | 5 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 6 | 6 | |
| 7 | 7 | target triple = "wasm32-unknown-unknown" |
deps/lld/test/wasm/compress-relocs.ll+7-3| ... | ... | @@ -1,9 +1,11 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj %p/Inputs/call-indirect.ll -o %t2.o |
| 2 | 2 | ; RUN: llc -filetype=obj %s -o %t.o |
| 3 | ; RUN: wasm-ld -o %t.wasm %t2.o %t.o | |
| 3 | ; RUN: wasm-ld --export-dynamic -o %t.wasm %t2.o %t.o | |
| 4 | 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 5 | ||
| 6 | ; RUN: wasm-ld -O2 -o %t-compressed.wasm %t2.o %t.o | |
| 5 | ; RUN: wasm-ld --export-dynamic -O2 -o %t-opt.wasm %t2.o %t.o | |
| 6 | ; RUN: obj2yaml %t-opt.wasm | FileCheck %s | |
| 7 | ; RUN: not wasm-ld --compress-relocations -o %t-compressed.wasm %t2.o %t.o 2>&1 | FileCheck %s -check-prefix=ERROR | |
| 8 | ; RUN: wasm-ld --export-dynamic --strip-debug --compress-relocations -o %t-compressed.wasm %t2.o %t.o | |
| 7 | 9 | ; RUN: obj2yaml %t-compressed.wasm | FileCheck %s -check-prefix=COMPRESS |
| 8 | 10 | |
| 9 | 11 | target triple = "wasm32-unknown-unknown-wasm" |
| ... | ... | @@ -18,5 +20,7 @@ entry: |
| 18 | 20 | ret void |
| 19 | 21 | } |
| 20 | 22 | |
| 23 | ; ERROR: wasm-ld: error: --compress-relocations is incompatible with output debug information. Please pass --strip-debug or --strip-all | |
| 24 | ||
| 21 | 25 | ; CHECK: Body: 4100280284888080002100410028028088808000118080808000001A2000118180808000001A0B |
| 22 | 26 | ; COMPRESS: Body: 41002802840821004100280280081100001A20001101001A0B |
deps/lld/test/wasm/cxx-mangling.ll+11-9| ... | ... | @@ -1,8 +1,8 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj %s -o %t.o |
| 2 | ; RUN: wasm-ld --demangle -o %t_demangle.wasm %t.o | |
| 3 | ; RUN: obj2yaml %t_demangle.wasm | FileCheck %s | |
| 4 | ; RUN: wasm-ld --no-demangle -o %t_nodemangle.wasm %t.o | |
| 5 | ; RUN: obj2yaml %t_nodemangle.wasm | FileCheck %s | |
| 2 | ; RUN: wasm-ld --export=_Z3fooi --demangle -o %t_demangle.wasm %t.o | |
| 3 | ; RUN: obj2yaml %t_demangle.wasm | FileCheck --check-prefixes=CHECK,DEMANGLE %s | |
| 4 | ; RUN: wasm-ld --export=_Z3fooi --no-demangle -o %t_nodemangle.wasm %t.o | |
| 5 | ; RUN: obj2yaml %t_nodemangle.wasm | FileCheck --check-prefixes=CHECK,MANGLE %s | |
| 6 | 6 | |
| 7 | 7 | target triple = "wasm32-unknown-unknown" |
| 8 | 8 | |
| ... | ... | @@ -32,12 +32,12 @@ define void @_start() { |
| 32 | 32 | ; CHECK-NEXT: - Name: __data_end |
| 33 | 33 | ; CHECK-NEXT: Kind: GLOBAL |
| 34 | 34 | ; CHECK-NEXT: Index: 2 |
| 35 | ; CHECK-NEXT: - Name: _start | |
| 36 | ; CHECK-NEXT: Kind: FUNCTION | |
| 37 | ; CHECK-NEXT: Index: 3 | |
| 38 | 35 | ; CHECK-NEXT: - Name: _Z3fooi |
| 39 | 36 | ; CHECK-NEXT: Kind: FUNCTION |
| 40 | 37 | ; CHECK-NEXT: Index: 2 |
| 38 | ; CHECK-NEXT: - Name: _start | |
| 39 | ; CHECK-NEXT: Kind: FUNCTION | |
| 40 | ; CHECK-NEXT: Index: 3 | |
| 41 | 41 | ; CHECK-NEXT: - Type: CODE |
| 42 | 42 | ; CHECK-NEXT: Functions: |
| 43 | 43 | ; CHECK-NEXT: - Index: 0 |
| ... | ... | @@ -58,9 +58,11 @@ define void @_start() { |
| 58 | 58 | ; CHECK-NEXT: - Index: 0 |
| 59 | 59 | ; CHECK-NEXT: Name: __wasm_call_ctors |
| 60 | 60 | ; CHECK-NEXT: - Index: 1 |
| 61 | ; CHECK-NEXT: Name: 'undefined function bar(int)' | |
| 61 | ; DEMANGLE-NEXT: Name: 'undefined function bar(int)' | |
| 62 | ; MANGLE-NEXT: Name: undefined function _Z3bari | |
| 62 | 63 | ; CHECK-NEXT: - Index: 2 |
| 63 | ; CHECK-NEXT: Name: 'foo(int)' | |
| 64 | ; DEMANGLE-NEXT: Name: 'foo(int)' | |
| 65 | ; MANGLE-NEXT: Name: _Z3fooi | |
| 64 | 66 | ; CHECK-NEXT: - Index: 3 |
| 65 | 67 | ; CHECK-NEXT: Name: _start |
| 66 | 68 | ; CHECK-NEXT: ... |
deps/lld/test/wasm/data-layout.ll+10| ... | ... | @@ -68,6 +68,16 @@ target triple = "wasm32-unknown-unknown" |
| 68 | 68 | ; CHECK-MAX-NEXT: Initial: 0x00000002 |
| 69 | 69 | ; CHECK-MAX-NEXT: Maximum: 0x00000002 |
| 70 | 70 | |
| 71 | ; RUN: wasm-ld -no-gc-sections --allow-undefined --no-entry --shared-memory \ | |
| 72 | ; RUN: --initial-memory=131072 --max-memory=131072 -o %t_max.wasm %t.o \ | |
| 73 | ; RUN: %t.hello.o | |
| 74 | ; RUN: obj2yaml %t_max.wasm | FileCheck %s -check-prefix=CHECK-SHARED | |
| 75 | ||
| 76 | ; CHECK-SHARED: - Type: MEMORY | |
| 77 | ; CHECK-SHARED-NEXT: Memories: | |
| 78 | ; CHECK-SHARED-NEXT: - Flags: [ HAS_MAX, IS_SHARED ] | |
| 79 | ; CHECK-SHARED-NEXT: Initial: 0x00000002 | |
| 80 | ; CHECK-SHARED-NEXT: Maximum: 0x00000002 | |
| 71 | 81 | |
| 72 | 82 | ; RUN: wasm-ld --relocatable -o %t_reloc.wasm %t.o %t.hello.o |
| 73 | 83 | ; RUN: obj2yaml %t_reloc.wasm | FileCheck %s -check-prefix=RELOC |
deps/lld/test/wasm/data-segment-merging.ll+17-34| ... | ... | @@ -5,44 +5,27 @@ target triple = "wasm32-unknown-unknown" |
| 5 | 5 | @c = hidden global [9 x i8] c"whatever\00", align 1 |
| 6 | 6 | @d = hidden global i32 42, align 4 |
| 7 | 7 | |
| 8 | @e = private constant [9 x i8] c"constant\00", align 1 | |
| 9 | @f = private constant i8 43, align 4 | |
| 10 | ||
| 8 | 11 | ; RUN: llc -filetype=obj %s -o %t.data-segment-merging.o |
| 9 | 12 | |
| 10 | 13 | ; RUN: wasm-ld -no-gc-sections --no-entry -o %t.merged.wasm %t.data-segment-merging.o |
| 11 | 14 | ; RUN: obj2yaml %t.merged.wasm | FileCheck %s --check-prefix=MERGE |
| 12 | ; MERGE: - Type: DATA | |
| 13 | ; MERGE-NEXT: Segments: | |
| 14 | ; MERGE-NEXT: - SectionOffset: 7 | |
| 15 | ; MERGE-NEXT: MemoryIndex: 0 | |
| 16 | ; MERGE-NEXT: Offset: | |
| 17 | ; MERGE-NEXT: Opcode: I32_CONST | |
| 18 | ; MERGE-NEXT: Value: 1024 | |
| 19 | ; MERGE-NEXT: Content: 68656C6C6F00676F6F6462796500776861746576657200002A000000 | |
| 15 | ; MERGE: - Type: DATA | |
| 16 | ; MERGE: Segments: | |
| 17 | ; MERGE: Content: 68656C6C6F00676F6F6462796500776861746576657200002A000000 | |
| 18 | ; MERGE: Content: 636F6E7374616E74000000002B | |
| 19 | ; MERGE-NOT: Content: | |
| 20 | 20 | |
| 21 | 21 | ; RUN: wasm-ld -no-gc-sections --no-entry --no-merge-data-segments -o %t.separate.wasm %t.data-segment-merging.o |
| 22 | 22 | ; RUN: obj2yaml %t.separate.wasm | FileCheck %s --check-prefix=SEPARATE |
| 23 | ; SEPARATE: - Type: DATA | |
| 24 | ; SEPARATE-NEXT: Segments: | |
| 25 | ; SEPARATE-NEXT: - SectionOffset: 7 | |
| 26 | ; SEPARATE-NEXT: MemoryIndex: 0 | |
| 27 | ; SEPARATE-NEXT: Offset: | |
| 28 | ; SEPARATE-NEXT: Opcode: I32_CONST | |
| 29 | ; SEPARATE-NEXT: Value: 1024 | |
| 30 | ; SEPARATE-NEXT: Content: 68656C6C6F00 | |
| 31 | ; SEPARATE-NEXT: - SectionOffset: 19 | |
| 32 | ; SEPARATE-NEXT: MemoryIndex: 0 | |
| 33 | ; SEPARATE-NEXT: Offset: | |
| 34 | ; SEPARATE-NEXT: Opcode: I32_CONST | |
| 35 | ; SEPARATE-NEXT: Value: 1030 | |
| 36 | ; SEPARATE-NEXT: Content: 676F6F6462796500 | |
| 37 | ; SEPARATE-NEXT: - SectionOffset: 33 | |
| 38 | ; SEPARATE-NEXT: MemoryIndex: 0 | |
| 39 | ; SEPARATE-NEXT: Offset: | |
| 40 | ; SEPARATE-NEXT: Opcode: I32_CONST | |
| 41 | ; SEPARATE-NEXT: Value: 1038 | |
| 42 | ; SEPARATE-NEXT: Content: '776861746576657200' | |
| 43 | ; SEPARATE-NEXT: - SectionOffset: 48 | |
| 44 | ; SEPARATE-NEXT: MemoryIndex: 0 | |
| 45 | ; SEPARATE-NEXT: Offset: | |
| 46 | ; SEPARATE-NEXT: Opcode: I32_CONST | |
| 47 | ; SEPARATE-NEXT: Value: 1048 | |
| 48 | ; SEPARATE-NEXT: Content: 2A000000 | |
| 23 | ; SEPARATE: - Type: DATA | |
| 24 | ; SEPARATE: Segments: | |
| 25 | ; SEPARATE: Content: 68656C6C6F00 | |
| 26 | ; SEPARATE: Content: 676F6F6462796500 | |
| 27 | ; SEPARATE: Content: '776861746576657200' | |
| 28 | ; SEPARATE: Content: 2A000000 | |
| 29 | ; SEPARATE: Content: 636F6E7374616E7400 | |
| 30 | ; SEPARATE: Content: 2B | |
| 31 | ; SEPARATE-NOT: Content: |
deps/lld/test/wasm/debug-removed-fn.ll created+44| ... | ... | @@ -0,0 +1,44 @@ |
| 1 | ; RUN: llc -filetype=obj < %s -o %t.o | |
| 2 | ; RUN: wasm-ld %t.o --no-entry --export=foo -o %t.wasm | |
| 3 | ; RUN: llvm-dwarfdump -debug-line %t.wasm | FileCheck %s | |
| 4 | ||
| 5 | ; CHECK: Address | |
| 6 | ; CHECK: 0x0000000000000005 | |
| 7 | ; CHECK: 0x0000000000000000 | |
| 8 | ||
| 9 | ; ModuleID = 't.bc' | |
| 10 | target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" | |
| 11 | target triple = "wasm32-unknown-unknown-wasm" | |
| 12 | ||
| 13 | ; Function Attrs: noinline nounwind optnone | |
| 14 | define hidden i32 @foo() #0 !dbg !7 { | |
| 15 | entry: | |
| 16 | ret i32 42, !dbg !11 | |
| 17 | } | |
| 18 | ||
| 19 | ; Function Attrs: noinline nounwind optnone | |
| 20 | define hidden i32 @bar() #0 !dbg !12 { | |
| 21 | entry: | |
| 22 | ret i32 6, !dbg !13 | |
| 23 | } | |
| 24 | ||
| 25 | attributes #0 = { noinline nounwind optnone "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "no-frame-pointer-elim"="false" "no-infs-fp-math"="false" "no-jump-tables"="false" "no-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="generic" "unsafe-fp-math"="false" "use-soft-float"="false" } | |
| 26 | ||
| 27 | !llvm.dbg.cu = !{!0} | |
| 28 | !llvm.module.flags = !{!3, !4, !5} | |
| 29 | !llvm.ident = !{!6} | |
| 30 | ||
| 31 | !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang version 7.0.0 (trunk 337293)", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2) | |
| 32 | !1 = !DIFile(filename: "t.c", directory: "/d/y") | |
| 33 | !2 = !{} | |
| 34 | !3 = !{i32 2, !"Dwarf Version", i32 4} | |
| 35 | !4 = !{i32 2, !"Debug Info Version", i32 3} | |
| 36 | !5 = !{i32 1, !"wchar_size", i32 4} | |
| 37 | !6 = !{!"clang version 7.0.0 (trunk 337293)"} | |
| 38 | !7 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 1, type: !8, isLocal: false, isDefinition: true, scopeLine: 1, isOptimized: false, unit: !0, retainedNodes: !2) | |
| 39 | !8 = !DISubroutineType(types: !9) | |
| 40 | !9 = !{!10} | |
| 41 | !10 = !DIBasicType(name: "int", size: 32, encoding: DW_ATE_signed) | |
| 42 | !11 = !DILocation(line: 2, column: 3, scope: !7) | |
| 43 | !12 = distinct !DISubprogram(name: "bar", scope: !1, file: !1, line: 5, type: !8, isLocal: false, isDefinition: true, scopeLine: 5, isOptimized: false, unit: !0, retainedNodes: !2) | |
| 44 | !13 = !DILocation(line: 6, column: 3, scope: !12) |
deps/lld/test/wasm/debuginfo.test+2-2| ... | ... | @@ -43,7 +43,7 @@ CHECK-NEXT: DW_AT_name	("hi_foo.c") |
| 43 | 43 | |
| 44 | 44 | CHECK: DW_TAG_variable |
| 45 | 45 | CHECK-NEXT: DW_AT_name	("y") |
| 46 | CHECK-NEXT: DW_AT_type	(0x00000097 "int[]") | |
| 46 | CHECK-NEXT: DW_AT_type	(0x00000097 "int[2]") | |
| 47 | 47 | CHECK-NEXT: DW_AT_external	(true) |
| 48 | 48 | CHECK-NEXT: DW_AT_decl_file	("{{.*}}hi_foo.c") |
| 49 | 49 | CHECK-NEXT: DW_AT_decl_line	(1) |
| ... | ... | @@ -65,7 +65,7 @@ CHECK-NEXT: DW_AT_encoding	(DW_ATE_unsigned) |
| 65 | 65 | |
| 66 | 66 | CHECK: DW_TAG_variable |
| 67 | 67 | CHECK-NEXT: DW_AT_name	("z") |
| 68 | CHECK-NEXT: DW_AT_type	(0x00000097 "int[]") | |
| 68 | CHECK-NEXT: DW_AT_type	(0x00000097 "int[2]") | |
| 69 | 69 | CHECK-NEXT: DW_AT_external	(true) |
| 70 | 70 | CHECK-NEXT: DW_AT_decl_file	("{{.*}}hi_foo.c") |
| 71 | 71 | CHECK-NEXT: DW_AT_decl_line	(8) |
deps/lld/test/wasm/demangle.ll+8-6| ... | ... | @@ -1,17 +1,19 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj %s -o %t.o |
| 2 | ; RUN: not wasm-ld --undefined _Z3fooi \ | |
| 3 | ; RUN: -o %t.wasm %t.o 2>&1 | FileCheck %s | |
| 2 | ; RUN: not wasm-ld -o %t.wasm %t.o 2>&1 | FileCheck %s | |
| 4 | 3 | |
| 5 | ; CHECK: error: undefined symbol: foo(int) | |
| 4 | ; CHECK: error: {{.*}}.o: undefined symbol: foo(int) | |
| 6 | 5 | |
| 7 | ; RUN: not wasm-ld --no-demangle --undefined _Z3fooi \ | |
| 8 | ; RUN: -o %t.wasm %t.o 2>&1 | FileCheck -check-prefix=CHECK-NODEMANGLE %s | |
| 6 | ; RUN: not wasm-ld --no-demangle \ | |
| 7 | ; RUN: -o %t.wasm %t.o 2>&1 | FileCheck -check-prefix=CHECK-NODEMANGLE %s | |
| 9 | 8 | |
| 10 | ; CHECK-NODEMANGLE: error: undefined symbol: _Z3fooi | |
| 9 | ; CHECK-NODEMANGLE: error: {{.*}}.o: undefined symbol: _Z3fooi | |
| 11 | 10 | |
| 12 | 11 | target triple = "wasm32-unknown-unknown" |
| 13 | 12 | |
| 13 | declare void @_Z3fooi(i32); | |
| 14 | ||
| 14 | 15 | define hidden void @_start() local_unnamed_addr { |
| 15 | 16 | entry: |
| 17 | call void @_Z3fooi(i32 1) | |
| 16 | 18 | ret void |
| 17 | 19 | } |
deps/lld/test/wasm/event-section.ll created+34| ... | ... | @@ -0,0 +1,34 @@ |
| 1 | ; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %p/Inputs/event-section1.ll -o %t1.o | |
| 2 | ; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %p/Inputs/event-section2.ll -o %t2.o | |
| 3 | ; RUN: llc -filetype=obj -exception-model=wasm -mattr=+exception-handling %s -o %t.o | |
| 4 | ; RUN: wasm-ld -o %t.wasm %t.o %t1.o %t2.o | |
| 5 | ; RUN: obj2yaml %t.wasm | FileCheck %s | |
| 6 | ||
| 7 | target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" | |
| 8 | target triple = "wasm32-unknown-unknown" | |
| 9 | ||
| 10 | declare void @foo(i8*) | |
| 11 | declare void @bar(i8*) | |
| 12 | ||
| 13 | define void @_start() { | |
| 14 | call void @foo(i8* null) | |
| 15 | call void @bar(i8* null) | |
| 16 | ret void | |
| 17 | } | |
| 18 | ||
| 19 | ; CHECK: Sections: | |
| 20 | ; CHECK-NEXT: - Type: TYPE | |
| 21 | ; CHECK-NEXT: Signatures: | |
| 22 | ; CHECK-NEXT: - Index: 0 | |
| 23 | ; CHECK-NEXT: ReturnType: NORESULT | |
| 24 | ; CHECK-NEXT: ParamTypes: [] | |
| 25 | ; CHECK-NEXT: - Index: 1 | |
| 26 | ; CHECK-NEXT: ReturnType: NORESULT | |
| 27 | ; CHECK-NEXT: ParamTypes: | |
| 28 | ; CHECK-NEXT: - I32 | |
| 29 | ||
| 30 | ; CHECK: - Type: EVENT | |
| 31 | ; CHECK-NEXT: Events: | |
| 32 | ; CHECK-NEXT: - Index: 0 | |
| 33 | ; CHECK-NEXT: Attribute: 0 | |
| 34 | ; CHECK-NEXT: SigIndex: 1 |
deps/lld/test/wasm/export-all.ll+1-1| ... | ... | @@ -42,7 +42,7 @@ entry: |
| 42 | 42 | ; CHECK-NOT: - Name: internal_func |
| 43 | 43 | |
| 44 | 44 | ; EXPORT: - Type: EXPORT |
| 45 | ; EXPORT: - Name: _start | |
| 46 | 45 | ; EXPORT: - Name: bar |
| 47 | 46 | ; EXPORT: - Name: foo |
| 47 | ; EXPORT: - Name: _start | |
| 48 | 48 | ; EXPORT-NOT: - Name: internal_func |
deps/lld/test/wasm/export-table.test+1-1| ... | ... | @@ -6,7 +6,7 @@ |
| 6 | 6 | |
| 7 | 7 | # CHECK: - Type: TABLE |
| 8 | 8 | # CHECK-NEXT: Tables: |
| 9 | # CHECK-NEXT: - ElemType: ANYFUNC | |
| 9 | # CHECK-NEXT: - ElemType: FUNCREF | |
| 10 | 10 | # CHECK-NEXT: Limits: |
| 11 | 11 | # CHECK-NEXT: Flags: [ HAS_MAX ] |
| 12 | 12 | # CHECK-NEXT: Initial: 0x00000001 |
deps/lld/test/wasm/export.ll+3-3| ... | ... | @@ -28,10 +28,10 @@ entry: |
| 28 | 28 | ; CHECK-NEXT: - Name: __data_end |
| 29 | 29 | ; CHECK-NEXT: Kind: GLOBAL |
| 30 | 30 | ; CHECK-NEXT: Index: 2 |
| 31 | ; CHECK-NEXT: - Name: _start | |
| 32 | ; CHECK-NEXT: Kind: FUNCTION | |
| 33 | ; CHECK-NEXT: Index: 2 | |
| 34 | 31 | ; CHECK-NEXT: - Name: hidden_function |
| 35 | 32 | ; CHECK-NEXT: Kind: FUNCTION |
| 36 | 33 | ; CHECK-NEXT: Index: 1 |
| 34 | ; CHECK-NEXT: - Name: _start | |
| 35 | ; CHECK-NEXT: Kind: FUNCTION | |
| 36 | ; CHECK-NEXT: Index: 2 | |
| 37 | 37 | ; CHECK-NEXT: - Type: CODE |
deps/lld/test/wasm/import-memory.test+17| ... | ... | @@ -31,3 +31,20 @@ |
| 31 | 31 | # CHECK-MAX-NEXT: Initial: 0x00000004 |
| 32 | 32 | # CHECK-MAX-NEXT: Maximum: 0x00000005 |
| 33 | 33 | # CHECK-MAX-NEXT: - Type: |
| 34 | ||
| 35 | # RUN: wasm-ld --import-memory --shared-memory --initial-memory=262144 \ | |
| 36 | # RUN: --max-memory=327680 -o %t.max.wasm %t.start.o | |
| 37 | # RUN: obj2yaml %t.max.wasm | FileCheck -check-prefix=CHECK-SHARED %s | |
| 38 | ||
| 39 | # Verify the --shared-memory flag works with imports | |
| 40 | ||
| 41 | # CHECK-SHARED: - Type: IMPORT | |
| 42 | # CHECK-SHARED-NEXT: Imports: | |
| 43 | # CHECK-SHARED-NEXT: - Module: env | |
| 44 | # CHECK-SHARED-NEXT: Field: memory | |
| 45 | # CHECK-SHARED-NEXT: Kind: MEMORY | |
| 46 | # CHECK-SHARED-NEXT: Memory: | |
| 47 | # CHECK-SHARED-NEXT: Flags: [ HAS_MAX, IS_SHARED ] | |
| 48 | # CHECK-SHARED-NEXT: Initial: 0x00000004 | |
| 49 | # CHECK-SHARED-NEXT: Maximum: 0x00000005 | |
| 50 | # CHECK-SHARED-NEXT: - Type: |
deps/lld/test/wasm/import-table.test+1-3| ... | ... | @@ -10,9 +10,7 @@ |
| 10 | 10 | # CHECK-NEXT: Field: __indirect_function_table |
| 11 | 11 | # CHECK-NEXT: Kind: TABLE |
| 12 | 12 | # CHECK-NEXT: Table: |
| 13 | # CHECK-NEXT: ElemType: ANYFUNC | |
| 13 | # CHECK-NEXT: ElemType: FUNCREF | |
| 14 | 14 | # CHECK-NEXT: Limits: |
| 15 | # CHECK-NEXT: Flags: [ HAS_MAX ] | |
| 16 | 15 | # CHECK-NEXT: Initial: 0x00000001 |
| 17 | # CHECK-NEXT: Maximum: 0x00000001 | |
| 18 | 16 |
deps/lld/test/wasm/load-undefined.test+6-8| ... | ... | @@ -4,6 +4,7 @@ |
| 4 | 4 | ; RUN: llc -filetype=obj %S/Inputs/ret64.ll -o %t.o |
| 5 | 5 | ; RUN: llc -filetype=obj %S/Inputs/ret32.ll -o %t2.o |
| 6 | 6 | ; RUN: llc -filetype=obj %S/Inputs/start.ll -o %t.start.o |
| 7 | ; RUN: rm -f %t2.a | |
| 7 | 8 | ; RUN: llvm-ar rcs %t2.a %t2.o |
| 8 | 9 | ; RUN: wasm-ld %t.start.o --no-gc-sections %t2.a %t.o -o %t.wasm -u ret32 --undefined ret64 |
| 9 | 10 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| ... | ... | @@ -17,9 +18,9 @@ |
| 17 | 18 | ; CHECK-NEXT: - Index: 1 |
| 18 | 19 | ; CHECK-NEXT: Name: _start |
| 19 | 20 | ; CHECK-NEXT: - Index: 2 |
| 20 | ; CHECK-NEXT: Name: ret32 | |
| 21 | ; CHECK-NEXT: - Index: 3 | |
| 22 | 21 | ; CHECK-NEXT: Name: ret64 |
| 22 | ; CHECK-NEXT: - Index: 3 | |
| 23 | ; CHECK-NEXT: Name: ret32 | |
| 23 | 24 | ; CHECK-NEXT: ... |
| 24 | 25 | |
| 25 | 26 | ; NO-LOAD: Name: name |
| ... | ... | @@ -32,9 +33,6 @@ |
| 32 | 33 | ; NO-LOAD-NEXT: Name: ret64 |
| 33 | 34 | ; NO-LOAD-NEXT: ... |
| 34 | 35 | |
| 35 | ; Verify that referencing a symbol that doesn't exist won't work | |
| 36 | ; RUN: not wasm-ld %t.start.o -o %t.wasm -u symboldoesnotexist 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED1 %s | |
| 37 | ; CHECK-UNDEFINED1: error: undefined symbol: symboldoesnotexist | |
| 38 | ||
| 39 | ; RUN: not wasm-ld %t.start.o -o %t.wasm --undefined symboldoesnotexist --allow-undefined 2>&1 | FileCheck -check-prefix=CHECK-UNDEFINED2 %s | |
| 40 | ; CHECK-UNDEFINED2: symbol forced with --undefined not found: symboldoesnotexist | |
| 36 | ; Verify that referencing a symbol that is not found doesn't result in a link | |
| 37 | ; failure. This matches the behaviour of the ELF linker. | |
| 38 | ; RUN: wasm-ld %t.start.o -o %t.wasm -u symboldoesnotexist |
deps/lld/test/wasm/local-symbols.ll+3-2| ... | ... | @@ -1,5 +1,6 @@ |
| 1 | ; Test that internal symbols can still be GC'd when with --export-dynamic. | |
| 1 | 2 | ; RUN: llc -filetype=obj %s -o %t.o |
| 2 | ; RUN: wasm-ld -o %t.wasm %t.o | |
| 3 | ; RUN: wasm-ld --export-dynamic -o %t.wasm %t.o | |
| 3 | 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 4 | 5 | |
| 5 | 6 | target triple = "wasm32-unknown-unknown" |
| ... | ... | @@ -35,7 +36,7 @@ entry: |
| 35 | 36 | ; CHECK-NEXT: FunctionTypes: [ 0, 1, 0 ] |
| 36 | 37 | ; CHECK-NEXT: - Type: TABLE |
| 37 | 38 | ; CHECK-NEXT: Tables: |
| 38 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 39 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 39 | 40 | ; CHECK-NEXT: Limits: |
| 40 | 41 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 41 | 42 | ; CHECK-NEXT: Initial: 0x00000001 |
deps/lld/test/wasm/locals-duplicate.test+7-7| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj %p/Inputs/locals-duplicate1.ll -o %t1.o |
| 2 | 2 | ; RUN: llc -filetype=obj %p/Inputs/locals-duplicate2.ll -o %t2.o |
| 3 | ; RUN: wasm-ld --no-entry -o %t.wasm %t1.o %t2.o | |
| 3 | ; RUN: wasm-ld --export-dynamic --no-entry -o %t.wasm %t1.o %t2.o | |
| 4 | 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 5 | 5 | |
| 6 | 6 | ; CHECK: --- !WASM |
| ... | ... | @@ -20,7 +20,7 @@ |
| 20 | 20 | ; CHECK-NEXT: 1, 1, 1 ] |
| 21 | 21 | ; CHECK-NEXT: - Type: TABLE |
| 22 | 22 | ; CHECK-NEXT: Tables: |
| 23 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 23 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 24 | 24 | ; CHECK-NEXT: Limits: |
| 25 | 25 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 26 | 26 | ; CHECK-NEXT: Initial: 0x00000007 |
| ... | ... | @@ -253,7 +253,7 @@ |
| 253 | 253 | ; RELOC-NEXT: 0, 0 ] |
| 254 | 254 | ; RELOC-NEXT: - Type: TABLE |
| 255 | 255 | ; RELOC-NEXT: Tables: |
| 256 | ; RELOC-NEXT: - ElemType: ANYFUNC | |
| 256 | ; RELOC-NEXT: - ElemType: FUNCREF | |
| 257 | 257 | ; RELOC-NEXT: Limits: |
| 258 | 258 | ; RELOC-NEXT: Flags: [ HAS_MAX ] |
| 259 | 259 | ; RELOC-NEXT: Initial: 0x00000007 |
| ... | ... | @@ -382,7 +382,7 @@ |
| 382 | 382 | ; RELOC-NEXT: Content: '0000000000000000' |
| 383 | 383 | ; RELOC-NEXT: - Type: CUSTOM |
| 384 | 384 | ; RELOC-NEXT: Name: linking |
| 385 | ; RELOC-NEXT: Version: 1 | |
| 385 | ; RELOC-NEXT: Version: 2 | |
| 386 | 386 | ; RELOC-NEXT: SymbolTable: |
| 387 | 387 | ; RELOC-NEXT: - Index: 0 |
| 388 | 388 | ; RELOC-NEXT: Kind: FUNCTION |
| ... | ... | @@ -516,15 +516,15 @@ |
| 516 | 516 | ; RELOC-NEXT: SegmentInfo: |
| 517 | 517 | ; RELOC-NEXT: - Index: 0 |
| 518 | 518 | ; RELOC-NEXT: Name: .bss.colliding_global1 |
| 519 | ; RELOC-NEXT: Alignment: 4 | |
| 519 | ; RELOC-NEXT: Alignment: 2 | |
| 520 | 520 | ; RELOC-NEXT: Flags: [ ] |
| 521 | 521 | ; RELOC-NEXT: - Index: 1 |
| 522 | 522 | ; RELOC-NEXT: Name: .bss.colliding_global2 |
| 523 | ; RELOC-NEXT: Alignment: 4 | |
| 523 | ; RELOC-NEXT: Alignment: 2 | |
| 524 | 524 | ; RELOC-NEXT: Flags: [ ] |
| 525 | 525 | ; RELOC-NEXT: - Index: 2 |
| 526 | 526 | ; RELOC-NEXT: Name: .bss.colliding_global3 |
| 527 | ; RELOC-NEXT: Alignment: 4 | |
| 527 | ; RELOC-NEXT: Alignment: 2 | |
| 528 | 528 | ; RELOC-NEXT: Flags: [ ] |
| 529 | 529 | ; RELOC-NEXT: - Type: CUSTOM |
| 530 | 530 | ; RELOC-NEXT: Name: name |
deps/lld/test/wasm/lto/archive.ll+1-1| ... | ... | @@ -2,7 +2,7 @@ |
| 2 | 2 | ; RUN: rm -f %t.a |
| 3 | 3 | ; RUN: llvm-ar rcs %t.a %t1.o |
| 4 | 4 | ; RUN: llvm-as %s -o %t2.o |
| 5 | ; RUN: wasm-ld %t2.o %t.a -o %t3 | |
| 5 | ; RUN: wasm-ld --export-dynamic %t2.o %t.a -o %t3 | |
| 6 | 6 | ; RUN: obj2yaml %t3 | FileCheck %s |
| 7 | 7 | |
| 8 | 8 | target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128" |
deps/lld/test/wasm/lto/cache.ll+6| ... | ... | @@ -1,5 +1,7 @@ |
| 1 | 1 | ; RUN: opt -module-hash -module-summary %s -o %t.o |
| 2 | 2 | ; RUN: opt -module-hash -module-summary %p/Inputs/cache.ll -o %t2.o |
| 3 | ; NetBSD: noatime mounts currently inhibit 'touch' from updating atime | |
| 4 | ; UNSUPPORTED: system-netbsd | |
| 3 | 5 | |
| 4 | 6 | ; RUN: rm -Rf %t.cache && mkdir %t.cache |
| 5 | 7 | ; Create two files that would be removed by cache pruning due to age. |
| ... | ... | @@ -17,6 +19,10 @@ |
| 17 | 19 | ; RUN: wasm-ld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=128k:prune_interval=0s -o %t.wasm %t2.o %t.o |
| 18 | 20 | ; RUN: ls %t.cache | count 5 |
| 19 | 21 | |
| 22 | ; Increase the age of llvmcache-foo, which will give it the oldest time stamp | |
| 23 | ; so that it is processed and removed first. | |
| 24 | ; RUN: %python -c 'import os,sys,time; t=time.time()-120; os.utime(sys.argv[1],(t,t))' %t.cache/llvmcache-foo | |
| 25 | ||
| 20 | 26 | ; This should remove it. |
| 21 | 27 | ; RUN: wasm-ld --thinlto-cache-dir=%t.cache --thinlto-cache-policy cache_size_bytes=32k:prune_interval=0s -o %t.wasm %t2.o %t.o |
| 22 | 28 | ; RUN: ls %t.cache | count 4 |
deps/lld/test/wasm/lto/export.ll+3-3| ... | ... | @@ -29,10 +29,10 @@ entry: |
| 29 | 29 | ; CHECK-NEXT: - Name: __data_end |
| 30 | 30 | ; CHECK-NEXT: Kind: GLOBAL |
| 31 | 31 | ; CHECK-NEXT: Index: 2 |
| 32 | ; CHECK-NEXT: - Name: _start | |
| 33 | ; CHECK-NEXT: Kind: FUNCTION | |
| 34 | ; CHECK-NEXT: Index: 2 | |
| 35 | 32 | ; CHECK-NEXT: - Name: hidden_function |
| 36 | 33 | ; CHECK-NEXT: Kind: FUNCTION |
| 37 | 34 | ; CHECK-NEXT: Index: 1 |
| 35 | ; CHECK-NEXT: - Name: _start | |
| 36 | ; CHECK-NEXT: Kind: FUNCTION | |
| 37 | ; CHECK-NEXT: Index: 2 | |
| 38 | 38 | ; CHECK-NEXT: - Type: CODE |
deps/lld/test/wasm/lto/signature-mismatch.ll created+19| ... | ... | @@ -0,0 +1,19 @@ |
| 1 | ; RUN: llc -filetype=obj -o %t.o %s | |
| 2 | ; RUN: llvm-as %S/Inputs/archive.ll -o %t1.o | |
| 3 | ; RUN: not wasm-ld --fatal-warnings %t.o %t1.o -o %t.wasm 2>&1 | FileCheck %s | |
| 4 | ||
| 5 | ; Test that functions defined in bitcode correctly report signature | |
| 6 | ; mistmaches with existing undefined sybmols in normal objects. | |
| 7 | ||
| 8 | target triple = "wasm32-unknown-unknown" | |
| 9 | ||
| 10 | ; f is defined to take no argument in archive.ll which is compiled to bitcode | |
| 11 | declare void @f(i32); | |
| 12 | ||
| 13 | define void @_start() { | |
| 14 | call void @f(i32 0) | |
| 15 | ret void | |
| 16 | } | |
| 17 | ||
| 18 | ; CHECK: >>> defined as (i32) -> void in {{.*}}signature-mismatch.ll.tmp1.o | |
| 19 | ; CHECK: >>> defined as () -> void in lto.tmp |
deps/lld/test/wasm/many-functions.ll+3-3| ... | ... | @@ -815,7 +815,7 @@ entry: |
| 815 | 815 | ; CHECK-NEXT: Content: '01000000' |
| 816 | 816 | ; CHECK-NEXT: - Type: CUSTOM |
| 817 | 817 | ; CHECK-NEXT: Name: linking |
| 818 | ; CHECK-NEXT: Version: 1 | |
| 818 | ; CHECK-NEXT: Version: 2 | |
| 819 | 819 | ; CHECK-NEXT: SymbolTable: |
| 820 | 820 | ; CHECK-NEXT: - Index: 0 |
| 821 | 821 | ; CHECK-NEXT: Kind: FUNCTION |
| ... | ... | @@ -1482,9 +1482,9 @@ entry: |
| 1482 | 1482 | ; CHECK-NEXT: SegmentInfo: |
| 1483 | 1483 | ; CHECK-NEXT: - Index: 0 |
| 1484 | 1484 | ; CHECK-NEXT: Name: .data.g0 |
| 1485 | ; CHECK-NEXT: Alignment: 4 | |
| 1485 | ; CHECK-NEXT: Alignment: 2 | |
| 1486 | 1486 | ; CHECK-NEXT: Flags: [ ] |
| 1487 | 1487 | ; CHECK-NEXT: - Index: 1 |
| 1488 | 1488 | ; CHECK-NEXT: Name: .data.foo |
| 1489 | ; CHECK-NEXT: Alignment: 4 | |
| 1489 | ; CHECK-NEXT: Alignment: 2 | |
| 1490 | 1490 | ; CHECK-NEXT: Flags: [ ] |
deps/lld/test/wasm/relocatable.ll+8-8| ... | ... | @@ -63,7 +63,7 @@ entry: |
| 63 | 63 | ; CHECK-NEXT: FunctionTypes: [ 2, 1, 1 ] |
| 64 | 64 | ; CHECK-NEXT: - Type: TABLE |
| 65 | 65 | ; CHECK-NEXT: Tables: |
| 66 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 66 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 67 | 67 | ; CHECK-NEXT: Limits: |
| 68 | 68 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 69 | 69 | ; CHECK-NEXT: Initial: 0x00000004 |
| ... | ... | @@ -157,7 +157,7 @@ entry: |
| 157 | 157 | ; CHECK-NEXT: Content: '616263' |
| 158 | 158 | ; CHECK-NEXT: - Type: CUSTOM |
| 159 | 159 | ; CHECK-NEXT: Name: linking |
| 160 | ; CHECK-NEXT: Version: 1 | |
| 160 | ; CHECK-NEXT: Version: 2 | |
| 161 | 161 | ; CHECK-NEXT: SymbolTable: |
| 162 | 162 | ; CHECK-NEXT: - Index: 0 |
| 163 | 163 | ; CHECK-NEXT: Kind: FUNCTION |
| ... | ... | @@ -232,27 +232,27 @@ entry: |
| 232 | 232 | ; CHECK-NEXT: SegmentInfo: |
| 233 | 233 | ; CHECK-NEXT: - Index: 0 |
| 234 | 234 | ; CHECK-NEXT: Name: .rodata.hello_str |
| 235 | ; CHECK-NEXT: Alignment: 1 | |
| 235 | ; CHECK-NEXT: Alignment: 0 | |
| 236 | 236 | ; CHECK-NEXT: Flags: [ ] |
| 237 | 237 | ; CHECK-NEXT: - Index: 1 |
| 238 | 238 | ; CHECK-NEXT: Name: .data.func_addr1 |
| 239 | ; CHECK-NEXT: Alignment: 4 | |
| 239 | ; CHECK-NEXT: Alignment: 2 | |
| 240 | 240 | ; CHECK-NEXT: Flags: [ ] |
| 241 | 241 | ; CHECK-NEXT: - Index: 2 |
| 242 | 242 | ; CHECK-NEXT: Name: .data.func_addr2 |
| 243 | ; CHECK-NEXT: Alignment: 4 | |
| 243 | ; CHECK-NEXT: Alignment: 2 | |
| 244 | 244 | ; CHECK-NEXT: Flags: [ ] |
| 245 | 245 | ; CHECK-NEXT: - Index: 3 |
| 246 | 246 | ; CHECK-NEXT: Name: .data.func_addr3 |
| 247 | ; CHECK-NEXT: Alignment: 4 | |
| 247 | ; CHECK-NEXT: Alignment: 2 | |
| 248 | 248 | ; CHECK-NEXT: Flags: [ ] |
| 249 | 249 | ; CHECK-NEXT: - Index: 4 |
| 250 | 250 | ; CHECK-NEXT: Name: .data.data_addr1 |
| 251 | ; CHECK-NEXT: Alignment: 8 | |
| 251 | ; CHECK-NEXT: Alignment: 3 | |
| 252 | 252 | ; CHECK-NEXT: Flags: [ ] |
| 253 | 253 | ; CHECK-NEXT: - Index: 5 |
| 254 | 254 | ; CHECK-NEXT: Name: .rodata.data_comdat |
| 255 | ; CHECK-NEXT: Alignment: 1 | |
| 255 | ; CHECK-NEXT: Alignment: 0 | |
| 256 | 256 | ; CHECK-NEXT: Flags: [ ] |
| 257 | 257 | ; CHECK-NEXT: Comdats: |
| 258 | 258 | ; CHECK-NEXT: - Name: func_comdat |
deps/lld/test/wasm/shared.ll created+82| ... | ... | @@ -0,0 +1,82 @@ |
| 1 | ; RUN: llc -O0 -filetype=obj %s -o %t.o | |
| 2 | ; RUN: wasm-ld -shared -o %t.wasm %t.o | |
| 3 | ; RUN: obj2yaml %t.wasm | FileCheck %s | |
| 4 | ||
| 5 | target triple = "wasm32-unknown-unknown" | |
| 6 | ||
| 7 | @data = hidden global i32 2, align 4 | |
| 8 | @indirect_func = local_unnamed_addr global void ()* @foo, align 4 | |
| 9 | @indirect_func_external = local_unnamed_addr global void ()* @func_external, align 4 | |
| 10 | ||
| 11 | define default void @foo() { | |
| 12 | entry: | |
| 13 | ; To ensure we use __stack_pointer | |
| 14 | %ptr = alloca i32 | |
| 15 | %0 = load i32, i32* @data, align 4 | |
| 16 | %1 = load i32, i32* @data_external, align 4 | |
| 17 | %2 = load void ()*, void ()** @indirect_func, align 4 | |
| 18 | call void %2() | |
| 19 | ret void | |
| 20 | } | |
| 21 | ||
| 22 | declare void @func_external() | |
| 23 | ||
| 24 | @data_external = external global i32 | |
| 25 | ||
| 26 | ||
| 27 | ; check for dylink section at start | |
| 28 | ||
| 29 | ; CHECK: Sections: | |
| 30 | ; CHECK-NEXT: - Type: CUSTOM | |
| 31 | ; CHECK-NEXT: Name: dylink | |
| 32 | ; CHECK-NEXT: MemorySize: 8 | |
| 33 | ; CHECK-NEXT: MemoryAlignment: 2 | |
| 34 | ; CHECK-NEXT: TableSize: 2 | |
| 35 | ; CHECK-NEXT: TableAlignment: 0 | |
| 36 | ||
| 37 | ; check for import of __table_base and __memory_base globals | |
| 38 | ||
| 39 | ; CHECK: - Type: IMPORT | |
| 40 | ; CHECK-NEXT: Imports: | |
| 41 | ; CHECK-NEXT: - Module: env | |
| 42 | ; CHECK-NEXT: Field: __indirect_function_table | |
| 43 | ; CHECK-NEXT: Kind: TABLE | |
| 44 | ; CHECK-NEXT: Table: | |
| 45 | ; CHECK-NEXT: ElemType: FUNCREF | |
| 46 | ; CHECK-NEXT: Limits: | |
| 47 | ; CHECK-NEXT: Initial: 0x00000002 | |
| 48 | ; CHECK-NEXT: - Module: env | |
| 49 | ; CHECK-NEXT: Field: __stack_pointer | |
| 50 | ; CHECK-NEXT: Kind: GLOBAL | |
| 51 | ; CHECK-NEXT: GlobalType: I32 | |
| 52 | ; CHECK-NEXT: GlobalMutable: true | |
| 53 | ; CHECK-NEXT: - Module: env | |
| 54 | ; CHECK-NEXT: Field: __memory_base | |
| 55 | ; CHECK-NEXT: Kind: GLOBAL | |
| 56 | ; CHECK-NEXT: GlobalType: I32 | |
| 57 | ; CHECK-NEXT: GlobalMutable: false | |
| 58 | ; CHECK-NEXT: - Module: env | |
| 59 | ; CHECK-NEXT: Field: __table_base | |
| 60 | ; CHECK-NEXT: Kind: GLOBAL | |
| 61 | ; CHECK-NEXT: GlobalType: I32 | |
| 62 | ; CHECK-NEXT: GlobalMutable: false | |
| 63 | ||
| 64 | ; check for elem segment initialized with __table_base global as offset | |
| 65 | ||
| 66 | ; CHECK: - Type: ELEM | |
| 67 | ; CHECK-NEXT: Segments: | |
| 68 | ; CHECK-NEXT: - Offset: | |
| 69 | ; CHECK-NEXT: Opcode: GLOBAL_GET | |
| 70 | ; CHECK-NEXT: Index: 2 | |
| 71 | ; CHECK-NEXT: Functions: [ 2, 0 ] | |
| 72 | ||
| 73 | ; check the data segment initialized with __memory_base global as offset | |
| 74 | ||
| 75 | ; CHECK: - Type: DATA | |
| 76 | ; CHECK-NEXT: Segments: | |
| 77 | ; CHECK-NEXT: - SectionOffset: 6 | |
| 78 | ; CHECK-NEXT: MemoryIndex: 0 | |
| 79 | ; CHECK-NEXT: Offset: | |
| 80 | ; CHECK-NEXT: Opcode: GLOBAL_GET | |
| 81 | ; CHECK-NEXT: Index: 1 | |
| 82 | ; CHECK-NEXT: Content: '0000000001000000' |
deps/lld/test/wasm/signature-mismatch-weak.ll+2-2| ... | ... | @@ -14,5 +14,5 @@ entry: |
| 14 | 14 | } |
| 15 | 15 | |
| 16 | 16 | ; CHECK: warning: function signature mismatch: weakFn |
| 17 | ; CHECK-NEXT: >>> defined as () -> I32 in {{.*}}signature-mismatch-weak.ll.tmp.o | |
| 18 | ; CHECK-NEXT: >>> defined as () -> I64 in {{.*}}signature-mismatch-weak.ll.tmp.strong.o | |
| 17 | ; CHECK-NEXT: >>> defined as () -> i32 in {{.*}}signature-mismatch-weak.ll.tmp.o | |
| 18 | ; CHECK-NEXT: >>> defined as () -> i64 in {{.*}}signature-mismatch-weak.ll.tmp.strong.o |
deps/lld/test/wasm/signature-mismatch.ll+4-4| ... | ... | @@ -18,9 +18,9 @@ entry: |
| 18 | 18 | declare i32 @ret32(i32, i64, i32) local_unnamed_addr #1 |
| 19 | 19 | |
| 20 | 20 | ; CHECK: error: function signature mismatch: ret32 |
| 21 | ; CHECK-NEXT: >>> defined as (I32, I64, I32) -> I32 in {{.*}}.main.o | |
| 22 | ; CHECK-NEXT: >>> defined as (F32) -> I32 in {{.*}}.ret32.o | |
| 21 | ; CHECK-NEXT: >>> defined as (i32, i64, i32) -> i32 in {{.*}}.main.o | |
| 22 | ; CHECK-NEXT: >>> defined as (f32) -> i32 in {{.*}}.ret32.o | |
| 23 | 23 | |
| 24 | 24 | ; REVERSE: error: function signature mismatch: ret32 |
| 25 | ; REVERSE-NEXT: >>> defined as (F32) -> I32 in {{.*}}.ret32.o | |
| 26 | ; REVERSE-NEXT: >>> defined as (I32, I64, I32) -> I32 in {{.*}}.main.o | |
| 25 | ; REVERSE-NEXT: >>> defined as (f32) -> i32 in {{.*}}.ret32.o | |
| 26 | ; REVERSE-NEXT: >>> defined as (i32, i64, i32) -> i32 in {{.*}}.main.o |
deps/lld/test/wasm/stack-pointer.ll+2-2| ... | ... | @@ -31,7 +31,7 @@ entry: |
| 31 | 31 | ; CHECK-NEXT: FunctionTypes: [ 0 ] |
| 32 | 32 | ; CHECK-NEXT: - Type: TABLE |
| 33 | 33 | ; CHECK-NEXT: Tables: |
| 34 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 34 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 35 | 35 | ; CHECK-NEXT: Limits: |
| 36 | 36 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 37 | 37 | ; CHECK-NEXT: Initial: 0x00000001 |
| ... | ... | @@ -50,7 +50,7 @@ entry: |
| 50 | 50 | ; CHECK-NEXT: Body: 23808080800041106B1A41000B |
| 51 | 51 | ; CHECK-NEXT: - Type: CUSTOM |
| 52 | 52 | ; CHECK-NEXT: Name: linking |
| 53 | ; CHECK-NEXT: Version: 1 | |
| 53 | ; CHECK-NEXT: Version: 2 | |
| 54 | 54 | ; CHECK-NEXT: SymbolTable: |
| 55 | 55 | ; CHECK-NEXT: - Index: 0 |
| 56 | 56 | ; CHECK-NEXT: Kind: FUNCTION |
deps/lld/test/wasm/strip-all.test created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.start.o | |
| 2 | RUN: wasm-ld --strip-all -o %t.wasm %t.start.o | |
| 3 | RUN: obj2yaml %t.wasm | FileCheck %s | |
| 4 | ||
| 5 | # Test alias -s | |
| 6 | RUN: wasm-ld -s -o %t.wasm %t.start.o | |
| 7 | RUN: obj2yaml %t.wasm | FileCheck %s | |
| 8 | ||
| 9 | # Check that there is no name section | |
| 10 | CHECK-NOT: Name: name |
deps/lld/test/wasm/strip-debug.test+4| ... | ... | @@ -2,5 +2,9 @@ RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.start.o |
| 2 | 2 | RUN: wasm-ld --strip-debug -o %t.wasm %t.start.o |
| 3 | 3 | RUN: obj2yaml %t.wasm | FileCheck %s |
| 4 | 4 | |
| 5 | # Test alias -S | |
| 6 | RUN: wasm-ld -S -o %t.wasm %t.start.o | |
| 7 | RUN: obj2yaml %t.wasm | FileCheck %s | |
| 8 | ||
| 5 | 9 | # Check that there is no name section |
| 6 | 10 | CHECK-NOT: Name: name |
deps/lld/test/wasm/undefined-entry.test+3-5| ... | ... | @@ -1,11 +1,9 @@ |
| 1 | 1 | RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o |
| 2 | 2 | RUN: not wasm-ld -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s |
| 3 | RUN: not wasm-ld --allow-undefined -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s | |
| 3 | 4 | RUN: not wasm-ld -entry=foo -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s -check-prefix=CHECK-CUSTOM |
| 4 | RUN: not wasm-ld --allow-undefined -o %t.wasm %t.ret32.o 2>&1 | FileCheck %s -check-prefix=CHECK-ALLOW | |
| 5 | 5 | |
| 6 | CHECK: error: undefined symbol: _start | |
| 7 | CHECK-CUSTOM: error: undefined symbol: foo | |
| 8 | CHECK-ALLOW: error: entry symbol not defined (pass --no-entry to supress): | |
| 9 | _start | |
| 6 | CHECK: error: entry symbol not defined (pass --no-entry to supress): _start | |
| 7 | CHECK-CUSTOM: error: entry symbol not defined (pass --no-entry to supress): foo | |
| 10 | 8 | |
| 11 | 9 | RUN: wasm-ld --no-entry -o %t.wasm %t.ret32.o |
deps/lld/test/wasm/undefined-weak-call.ll+2-2| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj %s -o %t.o |
| 2 | ; RUN: wasm-ld --no-entry --print-gc-sections %t.o \ | |
| 2 | ; RUN: wasm-ld --entry=callWeakFuncs --print-gc-sections %t.o \ | |
| 3 | 3 | ; RUN: -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-GC %s |
| 4 | 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 5 | 5 | |
| ... | ... | @@ -45,7 +45,7 @@ define i32 @callWeakFuncs() { |
| 45 | 45 | ; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 1, 2 ] |
| 46 | 46 | ; CHECK-NEXT: - Type: TABLE |
| 47 | 47 | ; CHECK-NEXT: Tables: |
| 48 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 48 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 49 | 49 | ; CHECK-NEXT: Limits: |
| 50 | 50 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 51 | 51 | ; CHECK-NEXT: Initial: 0x00000001 |
deps/lld/test/wasm/undefined.ll+2-2| ... | ... | @@ -1,10 +1,10 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj %s -o %t.o |
| 2 | 2 | ; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o |
| 3 | 3 | |
| 4 | ; Fails due to undefined 'foo' and also 'baz' | |
| 4 | ; Fails due to undefined 'foo' | |
| 5 | 5 | ; RUN: not wasm-ld --undefined=baz -o %t.wasm %t.o 2>&1 | FileCheck %s |
| 6 | 6 | ; CHECK: error: {{.*}}.o: undefined symbol: foo |
| 7 | ; CHECK: error: undefined symbol: baz | |
| 7 | ; CHECK-NOT: undefined symbol: baz | |
| 8 | 8 | |
| 9 | 9 | ; Succeeds if we pass a file containing 'foo' as --allow-undefined-file. |
| 10 | 10 | ; RUN: echo 'foo' > %t.txt |
deps/lld/test/wasm/visibility-hidden.ll+30-6| ... | ... | @@ -1,11 +1,18 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj -o %t.o %s |
| 2 | 2 | ; RUN: llc -filetype=obj %S/Inputs/hidden.ll -o %t2.o |
| 3 | ; RUN: rm -f %t2.a | |
| 3 | 4 | ; RUN: llvm-ar rcs %t2.a %t2.o |
| 4 | ; RUN: wasm-ld %t.o %t2.a -o %t.wasm | |
| 5 | ||
| 6 | ; Test that symbols with hidden visitiblity are not export, even with | |
| 7 | ; --export-dynamic | |
| 8 | ; RUN: wasm-ld --export-dynamic %t.o %t2.a -o %t.wasm | |
| 5 | 9 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 6 | 10 | |
| 7 | ; Test that hidden symbols are not exported, whether pulled in from an archive | |
| 8 | ; or directly. | |
| 11 | ; Test that symbols with default visitiblity are not exported without | |
| 12 | ; --export-dynamic | |
| 13 | ; RUN: wasm-ld %t.o %t2.a -o %t.nodef.wasm | |
| 14 | ; RUN: obj2yaml %t.nodef.wasm | FileCheck %s -check-prefix=NO-DEFAULT | |
| 15 | ||
| 9 | 16 | |
| 10 | 17 | target triple = "wasm32-unknown-unknown" |
| 11 | 18 | |
| ... | ... | @@ -42,13 +49,30 @@ entry: |
| 42 | 49 | ; CHECK-NEXT: - Name: __data_end |
| 43 | 50 | ; CHECK-NEXT: Kind: GLOBAL |
| 44 | 51 | ; CHECK-NEXT: Index: 2 |
| 45 | ; CHECK-NEXT: - Name: _start | |
| 46 | ; CHECK-NEXT: Kind: FUNCTION | |
| 47 | ; CHECK-NEXT: Index: 3 | |
| 48 | 52 | ; CHECK-NEXT: - Name: objectDefault |
| 49 | 53 | ; CHECK-NEXT: Kind: FUNCTION |
| 50 | 54 | ; CHECK-NEXT: Index: 2 |
| 55 | ; CHECK-NEXT: - Name: _start | |
| 56 | ; CHECK-NEXT: Kind: FUNCTION | |
| 57 | ; CHECK-NEXT: Index: 3 | |
| 51 | 58 | ; CHECK-NEXT: - Name: archiveDefault |
| 52 | 59 | ; CHECK-NEXT: Kind: FUNCTION |
| 53 | 60 | ; CHECK-NEXT: Index: 5 |
| 54 | 61 | ; CHECK-NEXT: - Type: |
| 62 | ||
| 63 | ||
| 64 | ; NO-DEFAULT: - Type: EXPORT | |
| 65 | ; NO-DEFAULT-NEXT: Exports: | |
| 66 | ; NO-DEFAULT-NEXT: - Name: memory | |
| 67 | ; NO-DEFAULT-NEXT: Kind: MEMORY | |
| 68 | ; NO-DEFAULT-NEXT: Index: 0 | |
| 69 | ; NO-DEFAULT-NEXT: - Name: __heap_base | |
| 70 | ; NO-DEFAULT-NEXT: Kind: GLOBAL | |
| 71 | ; NO-DEFAULT-NEXT: Index: 1 | |
| 72 | ; NO-DEFAULT-NEXT: - Name: __data_end | |
| 73 | ; NO-DEFAULT-NEXT: Kind: GLOBAL | |
| 74 | ; NO-DEFAULT-NEXT: Index: 2 | |
| 75 | ; NO-DEFAULT-NEXT: - Name: _start | |
| 76 | ; NO-DEFAULT-NEXT: Kind: FUNCTION | |
| 77 | ; NO-DEFAULT-NEXT: Index: 3 | |
| 78 | ; NO-DEFAULT-NEXT: - Type: |
deps/lld/test/wasm/weak-alias-overide.ll+5-5| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj -o %t.o %s |
| 2 | 2 | ; RUN: llc -filetype=obj %S/Inputs/weak-alias.ll -o %t2.o |
| 3 | ; RUN: wasm-ld %t.o %t2.o -o %t.wasm | |
| 3 | ; RUN: wasm-ld --export-dynamic %t.o %t2.o -o %t.wasm | |
| 4 | 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 5 | 5 | |
| 6 | 6 | ; Test that the strongly defined alias_fn from this file is used both here |
| ... | ... | @@ -35,7 +35,7 @@ entry: |
| 35 | 35 | ; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 1, 1, 1, 1, 1 ] |
| 36 | 36 | ; CHECK-NEXT: - Type: TABLE |
| 37 | 37 | ; CHECK-NEXT: Tables: |
| 38 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 38 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 39 | 39 | ; CHECK-NEXT: Limits: |
| 40 | 40 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 41 | 41 | ; CHECK-NEXT: Initial: 0x00000003 |
| ... | ... | @@ -74,12 +74,12 @@ entry: |
| 74 | 74 | ; CHECK-NEXT: - Name: __data_end |
| 75 | 75 | ; CHECK-NEXT: Kind: GLOBAL |
| 76 | 76 | ; CHECK-NEXT: Index: 2 |
| 77 | ; CHECK-NEXT: - Name: _start | |
| 78 | ; CHECK-NEXT: Kind: FUNCTION | |
| 79 | ; CHECK-NEXT: Index: 2 | |
| 80 | 77 | ; CHECK-NEXT: - Name: alias_fn |
| 81 | 78 | ; CHECK-NEXT: Kind: FUNCTION |
| 82 | 79 | ; CHECK-NEXT: Index: 1 |
| 80 | ; CHECK-NEXT: - Name: _start | |
| 81 | ; CHECK-NEXT: Kind: FUNCTION | |
| 82 | ; CHECK-NEXT: Index: 2 | |
| 83 | 83 | ; CHECK-NEXT: - Name: direct_fn |
| 84 | 84 | ; CHECK-NEXT: Kind: FUNCTION |
| 85 | 85 | ; CHECK-NEXT: Index: 3 |
deps/lld/test/wasm/weak-alias.ll+4-4| ... | ... | @@ -1,6 +1,6 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj -o %t.o %s |
| 2 | 2 | ; RUN: llc -filetype=obj %S/Inputs/weak-alias.ll -o %t2.o |
| 3 | ; RUN: wasm-ld %t.o %t2.o -o %t.wasm | |
| 3 | ; RUN: wasm-ld --export-dynamic %t.o %t2.o -o %t.wasm | |
| 4 | 4 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 5 | 5 | |
| 6 | 6 | ; Test that weak aliases (alias_fn is a weak alias of direct_fn) are linked correctly |
| ... | ... | @@ -32,7 +32,7 @@ entry: |
| 32 | 32 | ; CHECK-NEXT: FunctionTypes: [ 0, 0, 1, 1, 1, 1, 1 ] |
| 33 | 33 | ; CHECK-NEXT: - Type: TABLE |
| 34 | 34 | ; CHECK-NEXT: Tables: |
| 35 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 35 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 36 | 36 | ; CHECK-NEXT: Limits: |
| 37 | 37 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 38 | 38 | ; CHECK-NEXT: Initial: 0x00000002 |
| ... | ... | @@ -170,7 +170,7 @@ entry: |
| 170 | 170 | ; RELOC-NEXT: FunctionTypes: [ 0, 1, 1, 1, 1, 1 ] |
| 171 | 171 | ; RELOC-NEXT: - Type: TABLE |
| 172 | 172 | ; RELOC-NEXT: Tables: |
| 173 | ; RELOC-NEXT: - ElemType: ANYFUNC | |
| 173 | ; RELOC-NEXT: - ElemType: FUNCREF | |
| 174 | 174 | ; RELOC-NEXT: Limits: |
| 175 | 175 | ; RELOC-NEXT: Flags: [ HAS_MAX ] |
| 176 | 176 | ; RELOC-NEXT: Initial: 0x00000002 |
| ... | ... | @@ -250,7 +250,7 @@ entry: |
| 250 | 250 | ; RELOC-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B |
| 251 | 251 | ; RELOC-NEXT: - Type: CUSTOM |
| 252 | 252 | ; RELOC-NEXT: Name: linking |
| 253 | ; RELOC-NEXT: Version: 1 | |
| 253 | ; RELOC-NEXT: Version: 2 | |
| 254 | 254 | ; RELOC-NEXT: SymbolTable: |
| 255 | 255 | ; RELOC-NEXT: - Index: 0 |
| 256 | 256 | ; RELOC-NEXT: Kind: FUNCTION |
deps/lld/test/wasm/weak-symbols.ll+6-11| ... | ... | @@ -1,7 +1,7 @@ |
| 1 | 1 | ; RUN: llc -filetype=obj %p/Inputs/weak-symbol1.ll -o %t1.o |
| 2 | 2 | ; RUN: llc -filetype=obj %p/Inputs/weak-symbol2.ll -o %t2.o |
| 3 | 3 | ; RUN: llc -filetype=obj %s -o %t.o |
| 4 | ; RUN: wasm-ld -no-gc-sections -o %t.wasm %t.o %t1.o %t2.o | |
| 4 | ; RUN: wasm-ld --export-dynamic -o %t.wasm %t.o %t1.o %t2.o | |
| 5 | 5 | ; RUN: obj2yaml %t.wasm | FileCheck %s |
| 6 | 6 | |
| 7 | 7 | target triple = "wasm32-unknown-unknown" |
| ... | ... | @@ -29,10 +29,10 @@ entry: |
| 29 | 29 | ; CHECK-NEXT: ReturnType: I32 |
| 30 | 30 | ; CHECK-NEXT: ParamTypes: |
| 31 | 31 | ; CHECK-NEXT: - Type: FUNCTION |
| 32 | ; CHECK-NEXT: FunctionTypes: [ 0, 0, 1, 1, 1, 1 ] | |
| 32 | ; CHECK-NEXT: FunctionTypes: [ 0, 0, 1, 1, 1 ] | |
| 33 | 33 | ; CHECK-NEXT: - Type: TABLE |
| 34 | 34 | ; CHECK-NEXT: Tables: |
| 35 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 35 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 36 | 36 | ; CHECK-NEXT: Limits: |
| 37 | 37 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 38 | 38 | ; CHECK-NEXT: Initial: 0x00000002 |
| ... | ... | @@ -59,7 +59,7 @@ entry: |
| 59 | 59 | ; CHECK-NEXT: Mutable: false |
| 60 | 60 | ; CHECK-NEXT: InitExpr: |
| 61 | 61 | ; CHECK-NEXT: Opcode: I32_CONST |
| 62 | ; CHECK-NEXT: Value: 1032 | |
| 62 | ; CHECK-NEXT: Value: 1028 | |
| 63 | 63 | ; CHECK-NEXT: - Index: 3 |
| 64 | 64 | ; CHECK-NEXT: Type: I32 |
| 65 | 65 | ; CHECK-NEXT: Mutable: false |
| ... | ... | @@ -91,7 +91,7 @@ entry: |
| 91 | 91 | ; CHECK-NEXT: Index: 3 |
| 92 | 92 | ; CHECK-NEXT: - Name: exportWeak2 |
| 93 | 93 | ; CHECK-NEXT: Kind: FUNCTION |
| 94 | ; CHECK-NEXT: Index: 5 | |
| 94 | ; CHECK-NEXT: Index: 4 | |
| 95 | 95 | ; CHECK-NEXT: - Type: ELEM |
| 96 | 96 | ; CHECK-NEXT: Segments: |
| 97 | 97 | ; CHECK-NEXT: - Offset: |
| ... | ... | @@ -114,9 +114,6 @@ entry: |
| 114 | 114 | ; CHECK-NEXT: Body: 4181808080000B |
| 115 | 115 | ; CHECK-NEXT: - Index: 4 |
| 116 | 116 | ; CHECK-NEXT: Locals: |
| 117 | ; CHECK-NEXT: Body: 41020B | |
| 118 | ; CHECK-NEXT: - Index: 5 | |
| 119 | ; CHECK-NEXT: Locals: | |
| 120 | 117 | ; CHECK-NEXT: Body: 4181808080000B |
| 121 | 118 | ; CHECK-NEXT: - Type: DATA |
| 122 | 119 | ; CHECK-NEXT: Segments: |
| ... | ... | @@ -125,7 +122,7 @@ entry: |
| 125 | 122 | ; CHECK-NEXT: Offset: |
| 126 | 123 | ; CHECK-NEXT: Opcode: I32_CONST |
| 127 | 124 | ; CHECK-NEXT: Value: 1024 |
| 128 | ; CHECK-NEXT: Content: '0100000002000000' | |
| 125 | ; CHECK-NEXT: Content: '01000000' | |
| 129 | 126 | ; CHECK-NEXT: - Type: CUSTOM |
| 130 | 127 | ; CHECK-NEXT: Name: name |
| 131 | 128 | ; CHECK-NEXT: FunctionNames: |
| ... | ... | @@ -138,7 +135,5 @@ entry: |
| 138 | 135 | ; CHECK-NEXT: - Index: 3 |
| 139 | 136 | ; CHECK-NEXT: Name: exportWeak1 |
| 140 | 137 | ; CHECK-NEXT: - Index: 4 |
| 141 | ; CHECK-NEXT: Name: weakFn | |
| 142 | ; CHECK-NEXT: - Index: 5 | |
| 143 | 138 | ; CHECK-NEXT: Name: exportWeak2 |
| 144 | 139 | ; CHECK-NEXT: ... |
deps/lld/test/wasm/weak-undefined.ll+4-9| ... | ... | @@ -22,7 +22,8 @@ define i32* @get_address_of_global_var() #0 { |
| 22 | 22 | |
| 23 | 23 | define void @_start() #0 { |
| 24 | 24 | entry: |
| 25 | %call = call i32* @get_address_of_global_var() | |
| 25 | %call1 = call i32* @get_address_of_global_var() | |
| 26 | %call2 = call i8* @get_address_of_foo() | |
| 26 | 27 | ret void |
| 27 | 28 | } |
| 28 | 29 | |
| ... | ... | @@ -42,7 +43,7 @@ entry: |
| 42 | 43 | ; CHECK-NEXT: FunctionTypes: [ 0, 1, 1, 0 ] |
| 43 | 44 | ; CHECK-NEXT: - Type: TABLE |
| 44 | 45 | ; CHECK-NEXT: Tables: |
| 45 | ; CHECK-NEXT: - ElemType: ANYFUNC | |
| 46 | ; CHECK-NEXT: - ElemType: FUNCREF | |
| 46 | 47 | ; CHECK-NEXT: Limits: |
| 47 | 48 | ; CHECK-NEXT: Flags: [ HAS_MAX ] |
| 48 | 49 | ; CHECK-NEXT: Initial: 0x00000001 |
| ... | ... | @@ -84,12 +85,6 @@ entry: |
| 84 | 85 | ; CHECK-NEXT: - Name: _start |
| 85 | 86 | ; CHECK-NEXT: Kind: FUNCTION |
| 86 | 87 | ; CHECK-NEXT: Index: 3 |
| 87 | ; CHECK-NEXT: - Name: get_address_of_foo | |
| 88 | ; CHECK-NEXT: Kind: FUNCTION | |
| 89 | ; CHECK-NEXT: Index: 1 | |
| 90 | ; CHECK-NEXT: - Name: get_address_of_global_var | |
| 91 | ; CHECK-NEXT: Kind: FUNCTION | |
| 92 | ; CHECK-NEXT: Index: 2 | |
| 93 | 88 | ; CHECK-NEXT: - Type: CODE |
| 94 | 89 | ; CHECK-NEXT: Functions: |
| 95 | 90 | ; CHECK-NEXT: - Index: 0 |
| ... | ... | @@ -103,5 +98,5 @@ entry: |
| 103 | 98 | ; CHECK-NEXT: Body: 4180808080000B |
| 104 | 99 | ; CHECK-NEXT: - Index: 3 |
| 105 | 100 | ; CHECK-NEXT: Locals: |
| 106 | ; CHECK-NEXT: Body: 1082808080001A0B | |
| 101 | ; CHECK-NEXT: Body: 1082808080001A1081808080001A0B | |
| 107 | 102 | ; CHECK-NEXT: ... |
deps/lld/tools/lld/lld.cpp+1-1| ... | ... | @@ -138,7 +138,7 @@ int main(int Argc, const char **Argv) { |
| 138 | 138 | return !wasm::link(Args, canExitEarly()); |
| 139 | 139 | default: |
| 140 | 140 | die("lld is a generic driver.\n" |
| 141 | "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-lld" | |
| 141 | "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld" | |
| 142 | 142 | " (WebAssembly) instead"); |
| 143 | 143 | } |
| 144 | 144 | } |
deps/lld/wasm/Config.h+8-1| ... | ... | @@ -20,18 +20,22 @@ namespace wasm { |
| 20 | 20 | |
| 21 | 21 | struct Configuration { |
| 22 | 22 | bool AllowUndefined; |
| 23 | bool CompressRelocTargets; | |
| 23 | bool CompressRelocations; | |
| 24 | 24 | bool Demangle; |
| 25 | 25 | bool DisableVerify; |
| 26 | 26 | bool ExportAll; |
| 27 | bool ExportDynamic; | |
| 27 | 28 | bool ExportTable; |
| 28 | 29 | bool GcSections; |
| 29 | 30 | bool ImportMemory; |
| 31 | bool SharedMemory; | |
| 30 | 32 | bool ImportTable; |
| 31 | 33 | bool MergeDataSegments; |
| 34 | bool Pie; | |
| 32 | 35 | bool PrintGcSections; |
| 33 | 36 | bool Relocatable; |
| 34 | 37 | bool SaveTemps; |
| 38 | bool Shared; | |
| 35 | 39 | bool StripAll; |
| 36 | 40 | bool StripDebug; |
| 37 | 41 | bool StackFirst; |
| ... | ... | @@ -50,6 +54,9 @@ struct Configuration { |
| 50 | 54 | llvm::StringSet<> AllowUndefinedSymbols; |
| 51 | 55 | std::vector<llvm::StringRef> SearchPaths; |
| 52 | 56 | llvm::CachePruningPolicy ThinLTOCachePolicy; |
| 57 | ||
| 58 | // True if we are creating position-independent code. | |
| 59 | bool Pic; | |
| 53 | 60 | }; |
| 54 | 61 | |
| 55 | 62 | // The only instance of Configuration struct. |
deps/lld/wasm/Driver.cpp+184-104| ... | ... | @@ -31,6 +31,7 @@ |
| 31 | 31 | #define DEBUG_TYPE "lld" |
| 32 | 32 | |
| 33 | 33 | using namespace llvm; |
| 34 | using namespace llvm::object; | |
| 34 | 35 | using namespace llvm::sys; |
| 35 | 36 | using namespace llvm::wasm; |
| 36 | 37 | |
| ... | ... | @@ -78,7 +79,7 @@ private: |
| 78 | 79 | |
| 79 | 80 | bool lld::wasm::link(ArrayRef<const char *> Args, bool CanExitEarly, |
| 80 | 81 | raw_ostream &Error) { |
| 81 | errorHandler().LogName = sys::path::filename(Args[0]); | |
| 82 | errorHandler().LogName = args::getFilenameWithoutExe(Args[0]); | |
| 82 | 83 | errorHandler().ErrorOS = &Error; |
| 83 | 84 | errorHandler().ColorDiagnostics = Error.has_colors(); |
| 84 | 85 | errorHandler().ErrorLimitExceededMsg = |
| ... | ... | @@ -186,8 +187,7 @@ static void readImportFile(StringRef Filename) { |
| 186 | 187 | |
| 187 | 188 | // Returns slices of MB by parsing MB as an archive file. |
| 188 | 189 | // Each slice consists of a member file in the archive. |
| 189 | std::vector<MemoryBufferRef> static getArchiveMembers( | |
| 190 | MemoryBufferRef MB) { | |
| 190 | std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef MB) { | |
| 191 | 191 | std::unique_ptr<Archive> File = |
| 192 | 192 | CHECK(Archive::create(MB), |
| 193 | 193 | MB.getBufferIdentifier() + ": failed to parse archive"); |
| ... | ... | @@ -205,8 +205,8 @@ std::vector<MemoryBufferRef> static getArchiveMembers( |
| 205 | 205 | V.push_back(MBRef); |
| 206 | 206 | } |
| 207 | 207 | if (Err) |
| 208 | fatal(MB.getBufferIdentifier() + ": Archive::children failed: " + | |
| 209 | toString(std::move(Err))); | |
| 208 | fatal(MB.getBufferIdentifier() + | |
| 209 | ": Archive::children failed: " + toString(std::move(Err))); | |
| 210 | 210 | |
| 211 | 211 | // Take ownership of memory buffers created for members of thin archives. |
| 212 | 212 | for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers()) |
| ... | ... | @@ -306,17 +306,14 @@ static void handleWeakUndefines() { |
| 306 | 306 | |
| 307 | 307 | // It is possible for undefined functions not to have a signature (eg. if |
| 308 | 308 | // added via "--undefined"), but weak undefined ones do have a signature. |
| 309 | assert(FuncSym->FunctionType); | |
| 310 | const WasmSignature &Sig = *FuncSym->FunctionType; | |
| 309 | assert(FuncSym->Signature); | |
| 310 | const WasmSignature &Sig = *FuncSym->Signature; | |
| 311 | 311 | |
| 312 | 312 | // Add a synthetic dummy for weak undefined functions. These dummies will |
| 313 | 313 | // be GC'd if not used as the target of any "call" instructions. |
| 314 | Optional<std::string> SymName = demangleItanium(Sym->getName()); | |
| 315 | StringRef DebugName = | |
| 316 | Saver.save("undefined function " + | |
| 317 | (SymName ? StringRef(*SymName) : Sym->getName())); | |
| 318 | SyntheticFunction *Func = | |
| 319 | make<SyntheticFunction>(Sig, Sym->getName(), DebugName); | |
| 314 | std::string SymName = toString(*Sym); | |
| 315 | StringRef DebugName = Saver.save("undefined function " + SymName); | |
| 316 | auto *Func = make<SyntheticFunction>(Sig, Sym->getName(), DebugName); | |
| 320 | 317 | Func->setBody(UnreachableFn); |
| 321 | 318 | // Ensure it compares equal to the null pointer, and so that table relocs |
| 322 | 319 | // don't pull in the stub body (only call-operand relocs should do that). |
| ... | ... | @@ -328,51 +325,24 @@ static void handleWeakUndefines() { |
| 328 | 325 | } |
| 329 | 326 | } |
| 330 | 327 | |
| 331 | // Force Sym to be entered in the output. Used for -u or equivalent. | |
| 332 | static Symbol *addUndefined(StringRef Name) { | |
| 333 | Symbol *S = Symtab->addUndefinedFunction(Name, 0, nullptr, nullptr); | |
| 334 | ||
| 335 | // Since symbol S may not be used inside the program, LTO may | |
| 336 | // eliminate it. Mark the symbol as "used" to prevent it. | |
| 337 | S->IsUsedInRegularObj = true; | |
| 338 | ||
| 339 | return S; | |
| 340 | } | |
| 341 | ||
| 342 | void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | |
| 343 | WasmOptTable Parser; | |
| 344 | opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); | |
| 345 | ||
| 346 | // Handle --help | |
| 347 | if (Args.hasArg(OPT_help)) { | |
| 348 | Parser.PrintHelp(outs(), ArgsArr[0], "LLVM Linker", false); | |
| 349 | return; | |
| 350 | } | |
| 351 | ||
| 352 | // Handle --version | |
| 353 | if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) { | |
| 354 | outs() << getLLDVersion() << "\n"; | |
| 355 | return; | |
| 356 | } | |
| 357 | ||
| 358 | // Parse and evaluate -mllvm options. | |
| 359 | std::vector<const char *> V; | |
| 360 | V.push_back("wasm-ld (LLVM option parsing)"); | |
| 361 | for (auto *Arg : Args.filtered(OPT_mllvm)) | |
| 362 | V.push_back(Arg->getValue()); | |
| 363 | cl::ParseCommandLineOptions(V.size(), V.data()); | |
| 364 | ||
| 365 | errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); | |
| 366 | ||
| 328 | // Some Config members do not directly correspond to any particular | |
| 329 | // command line options, but computed based on other Config values. | |
| 330 | // This function initialize such members. See Config.h for the details | |
| 331 | // of these values. | |
| 332 | static void setConfigs(opt::InputArgList &Args) { | |
| 367 | 333 | Config->AllowUndefined = Args.hasArg(OPT_allow_undefined); |
| 334 | Config->CompressRelocations = Args.hasArg(OPT_compress_relocations); | |
| 368 | 335 | Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true); |
| 369 | 336 | Config->DisableVerify = Args.hasArg(OPT_disable_verify); |
| 370 | 337 | Config->Entry = getEntry(Args, Args.hasArg(OPT_relocatable) ? "" : "_start"); |
| 371 | 338 | Config->ExportAll = Args.hasArg(OPT_export_all); |
| 339 | Config->ExportDynamic = Args.hasFlag(OPT_export_dynamic, | |
| 340 | OPT_no_export_dynamic, false); | |
| 372 | 341 | Config->ExportTable = Args.hasArg(OPT_export_table); |
| 373 | 342 | errorHandler().FatalWarnings = |
| 374 | 343 | Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false); |
| 375 | 344 | Config->ImportMemory = Args.hasArg(OPT_import_memory); |
| 345 | Config->SharedMemory = Args.hasArg(OPT_shared_memory); | |
| 376 | 346 | Config->ImportTable = Args.hasArg(OPT_import_table); |
| 377 | 347 | Config->LTOO = args::getInteger(Args, OPT_lto_O, 2); |
| 378 | 348 | Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1); |
| ... | ... | @@ -384,10 +354,12 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 384 | 354 | Config->MergeDataSegments = |
| 385 | 355 | Args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments, |
| 386 | 356 | !Config->Relocatable); |
| 357 | Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false); | |
| 387 | 358 | Config->PrintGcSections = |
| 388 | 359 | Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false); |
| 389 | 360 | Config->SaveTemps = Args.hasArg(OPT_save_temps); |
| 390 | 361 | Config->SearchPaths = args::getStrings(Args, OPT_L); |
| 362 | Config->Shared = Args.hasArg(OPT_shared); | |
| 391 | 363 | Config->StripAll = Args.hasArg(OPT_strip_all); |
| 392 | 364 | Config->StripDebug = Args.hasArg(OPT_strip_debug); |
| 393 | 365 | Config->StackFirst = Args.hasArg(OPT_stack_first); |
| ... | ... | @@ -404,8 +376,14 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 404 | 376 | Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0); |
| 405 | 377 | Config->ZStackSize = |
| 406 | 378 | args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize); |
| 379 | } | |
| 407 | 380 | |
| 408 | Config->CompressRelocTargets = Config->Optimize > 0 && !Config->Relocatable; | |
| 381 | // Some command line options or some combinations of them are not allowed. | |
| 382 | // This function checks for such errors. | |
| 383 | static void checkOptions(opt::InputArgList &Args) { | |
| 384 | if (!Config->StripDebug && !Config->StripAll && Config->CompressRelocations) | |
| 385 | error("--compress-relocations is incompatible with output debug" | |
| 386 | " information. Please pass --strip-debug or --strip-all"); | |
| 409 | 387 | |
| 410 | 388 | if (Config->LTOO > 3) |
| 411 | 389 | error("invalid optimization level for LTO: " + Twine(Config->LTOO)); |
| ... | ... | @@ -414,13 +392,8 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 414 | 392 | if (Config->ThinLTOJobs == 0) |
| 415 | 393 | error("--thinlto-jobs: number of threads must be > 0"); |
| 416 | 394 | |
| 417 | if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file)) | |
| 418 | readImportFile(Arg->getValue()); | |
| 419 | ||
| 420 | if (!Args.hasArg(OPT_INPUT)) { | |
| 421 | error("no input files"); | |
| 422 | return; | |
| 423 | } | |
| 395 | if (Config->Pie && Config->Shared) | |
| 396 | error("-shared and -pie may not be used together"); | |
| 424 | 397 | |
| 425 | 398 | if (Config->OutputFile.empty()) |
| 426 | 399 | error("no output file specified"); |
| ... | ... | @@ -433,46 +406,151 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 433 | 406 | error("entry point specified for relocatable output file"); |
| 434 | 407 | if (Config->GcSections) |
| 435 | 408 | error("-r and --gc-sections may not be used together"); |
| 409 | if (Config->CompressRelocations) | |
| 410 | error("-r -and --compress-relocations may not be used together"); | |
| 436 | 411 | if (Args.hasArg(OPT_undefined)) |
| 437 | 412 | error("-r -and --undefined may not be used together"); |
| 413 | if (Config->Pie) | |
| 414 | error("-r and -pie may not be used together"); | |
| 438 | 415 | } |
| 416 | } | |
| 439 | 417 | |
| 440 | Symbol *EntrySym = nullptr; | |
| 441 | if (!Config->Relocatable) { | |
| 418 | // Force Sym to be entered in the output. Used for -u or equivalent. | |
| 419 | static Symbol *handleUndefined(StringRef Name) { | |
| 420 | Symbol *Sym = Symtab->find(Name); | |
| 421 | if (!Sym) | |
| 422 | return nullptr; | |
| 423 | ||
| 424 | // Since symbol S may not be used inside the program, LTO may | |
| 425 | // eliminate it. Mark the symbol as "used" to prevent it. | |
| 426 | Sym->IsUsedInRegularObj = true; | |
| 427 | ||
| 428 | if (auto *LazySym = dyn_cast<LazySymbol>(Sym)) | |
| 429 | LazySym->fetch(); | |
| 430 | ||
| 431 | return Sym; | |
| 432 | } | |
| 433 | ||
| 434 | static UndefinedGlobal * | |
| 435 | createUndefinedGlobal(StringRef Name, llvm::wasm::WasmGlobalType *Type) { | |
| 436 | auto *Sym = | |
| 437 | cast<UndefinedGlobal>(Symtab->addUndefinedGlobal(Name, 0, nullptr, Type)); | |
| 438 | Config->AllowUndefinedSymbols.insert(Sym->getName()); | |
| 439 | Sym->IsUsedInRegularObj = true; | |
| 440 | return Sym; | |
| 441 | } | |
| 442 | ||
| 443 | // Create ABI-defined synthetic symbols | |
| 444 | static void createSyntheticSymbols() { | |
| 445 | static WasmSignature NullSignature = {{}, {}}; | |
| 446 | static llvm::wasm::WasmGlobalType GlobalTypeI32 = {WASM_TYPE_I32, false}; | |
| 447 | static llvm::wasm::WasmGlobalType MutableGlobalTypeI32 = {WASM_TYPE_I32, | |
| 448 | true}; | |
| 449 | ||
| 450 | if (!Config->Relocatable) | |
| 451 | WasmSym::CallCtors = Symtab->addSyntheticFunction( | |
| 452 | "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN, | |
| 453 | make<SyntheticFunction>(NullSignature, "__wasm_call_ctors")); | |
| 454 | ||
| 455 | // The __stack_pointer is imported in the shared library case, and exported | |
| 456 | // in the non-shared (executable) case. | |
| 457 | if (Config->Shared) { | |
| 458 | WasmSym::StackPointer = | |
| 459 | createUndefinedGlobal("__stack_pointer", &MutableGlobalTypeI32); | |
| 460 | } else { | |
| 442 | 461 | llvm::wasm::WasmGlobal Global; |
| 443 | 462 | Global.Type = {WASM_TYPE_I32, true}; |
| 444 | 463 | Global.InitExpr.Value.Int32 = 0; |
| 445 | 464 | Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST; |
| 446 | 465 | Global.SymbolName = "__stack_pointer"; |
| 447 | InputGlobal *StackPointer = make<InputGlobal>(Global, nullptr); | |
| 466 | auto *StackPointer = make<InputGlobal>(Global, nullptr); | |
| 448 | 467 | StackPointer->Live = true; |
| 449 | ||
| 450 | static WasmSignature NullSignature = {{}, WASM_TYPE_NORESULT}; | |
| 451 | ||
| 452 | // Add synthetic symbols before any others | |
| 453 | WasmSym::CallCtors = Symtab->addSyntheticFunction( | |
| 454 | "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN, | |
| 455 | make<SyntheticFunction>(NullSignature, "__wasm_call_ctors")); | |
| 468 | // For non-PIC code | |
| 456 | 469 | // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global |
| 457 | 470 | // spec proposal is implemented in all major browsers. |
| 458 | 471 | // See: https://github.com/WebAssembly/mutable-global |
| 459 | 472 | WasmSym::StackPointer = Symtab->addSyntheticGlobal( |
| 460 | 473 | "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer); |
| 461 | 474 | WasmSym::HeapBase = Symtab->addSyntheticDataSymbol("__heap_base", 0); |
| 462 | WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol( | |
| 463 | "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN); | |
| 464 | 475 | WasmSym::DataEnd = Symtab->addSyntheticDataSymbol("__data_end", 0); |
| 465 | 476 | |
| 466 | // For now, since we don't actually use the start function as the | |
| 467 | // wasm start symbol, we don't need to care about it signature. | |
| 468 | if (!Config->Entry.empty()) | |
| 469 | EntrySym = addUndefined(Config->Entry); | |
| 477 | // These two synthetic symbols exist purely for the embedder so we always | |
| 478 | // want to export them. | |
| 479 | WasmSym::HeapBase->ForceExport = true; | |
| 480 | WasmSym::DataEnd->ForceExport = true; | |
| 481 | } | |
| 482 | ||
| 483 | if (Config->Pic) { | |
| 484 | // For PIC code, we import two global variables (__memory_base and | |
| 485 | // __table_base) from the environment and use these as the offset at | |
| 486 | // which to load our static data and function table. | |
| 487 | // See: | |
| 488 | // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md | |
| 489 | WasmSym::MemoryBase = | |
| 490 | createUndefinedGlobal("__memory_base", &GlobalTypeI32); | |
| 491 | WasmSym::TableBase = createUndefinedGlobal("__table_base", &GlobalTypeI32); | |
| 492 | WasmSym::MemoryBase->markLive(); | |
| 493 | WasmSym::TableBase->markLive(); | |
| 494 | } | |
| 495 | ||
| 496 | WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol( | |
| 497 | "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN); | |
| 498 | } | |
| 499 | ||
| 500 | void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { | |
| 501 | WasmOptTable Parser; | |
| 502 | opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); | |
| 503 | ||
| 504 | // Handle --help | |
| 505 | if (Args.hasArg(OPT_help)) { | |
| 506 | Parser.PrintHelp(outs(), | |
| 507 | (std::string(ArgsArr[0]) + " [options] file...").c_str(), | |
| 508 | "LLVM Linker", false); | |
| 509 | return; | |
| 510 | } | |
| 470 | 511 | |
| 471 | // Handle the `--undefined <sym>` options. | |
| 472 | for (auto *Arg : Args.filtered(OPT_undefined)) | |
| 473 | addUndefined(Arg->getValue()); | |
| 512 | // Handle --version | |
| 513 | if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) { | |
| 514 | outs() << getLLDVersion() << "\n"; | |
| 515 | return; | |
| 474 | 516 | } |
| 475 | 517 | |
| 518 | // Parse and evaluate -mllvm options. | |
| 519 | std::vector<const char *> V; | |
| 520 | V.push_back("wasm-ld (LLVM option parsing)"); | |
| 521 | for (auto *Arg : Args.filtered(OPT_mllvm)) | |
| 522 | V.push_back(Arg->getValue()); | |
| 523 | cl::ParseCommandLineOptions(V.size(), V.data()); | |
| 524 | ||
| 525 | errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20); | |
| 526 | ||
| 527 | setConfigs(Args); | |
| 528 | checkOptions(Args); | |
| 529 | ||
| 530 | if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file)) | |
| 531 | readImportFile(Arg->getValue()); | |
| 532 | ||
| 533 | if (!Args.hasArg(OPT_INPUT)) { | |
| 534 | error("no input files"); | |
| 535 | return; | |
| 536 | } | |
| 537 | ||
| 538 | Config->Pic = Config->Pie || Config->Shared; | |
| 539 | ||
| 540 | if (Config->Pic) { | |
| 541 | if (Config->ExportTable) | |
| 542 | error("-shared/-pie is incompatible with --export-table"); | |
| 543 | Config->ImportTable = true; | |
| 544 | } | |
| 545 | ||
| 546 | if (Config->Shared) { | |
| 547 | Config->ExportDynamic = true; | |
| 548 | Config->AllowUndefined = true; | |
| 549 | } | |
| 550 | ||
| 551 | if (!Config->Relocatable) | |
| 552 | createSyntheticSymbols(); | |
| 553 | ||
| 476 | 554 | createFiles(Args); |
| 477 | 555 | if (errorCount()) |
| 478 | 556 | return; |
| ... | ... | @@ -484,44 +562,46 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) { |
| 484 | 562 | if (errorCount()) |
| 485 | 563 | return; |
| 486 | 564 | |
| 487 | // Add synthetic dummies for weak undefined functions. | |
| 488 | if (!Config->Relocatable) | |
| 489 | handleWeakUndefines(); | |
| 565 | // Handle the `--undefined <sym>` options. | |
| 566 | for (auto *Arg : Args.filtered(OPT_undefined)) | |
| 567 | handleUndefined(Arg->getValue()); | |
| 490 | 568 | |
| 491 | // Handle --export. | |
| 569 | // Handle the `--export <sym>` options | |
| 570 | // This works like --undefined but also exports the symbol if its found | |
| 492 | 571 | for (auto *Arg : Args.filtered(OPT_export)) { |
| 493 | StringRef Name = Arg->getValue(); | |
| 494 | Symbol *Sym = Symtab->find(Name); | |
| 572 | Symbol *Sym = handleUndefined(Arg->getValue()); | |
| 495 | 573 | if (Sym && Sym->isDefined()) |
| 496 | 574 | Sym->ForceExport = true; |
| 497 | 575 | else if (!Config->AllowUndefined) |
| 498 | error("symbol exported via --export not found: " + Name); | |
| 576 | error(Twine("symbol exported via --export not found: ") + | |
| 577 | Arg->getValue()); | |
| 499 | 578 | } |
| 500 | 579 | |
| 501 | // Do link-time optimization if given files are LLVM bitcode files. | |
| 502 | // This compiles bitcode files into real object files. | |
| 503 | Symtab->addCombinedLTOObject(); | |
| 504 | if (errorCount()) | |
| 505 | return; | |
| 580 | Symbol *EntrySym = nullptr; | |
| 581 | if (!Config->Relocatable) { | |
| 582 | // Add synthetic dummies for weak undefined functions. | |
| 583 | handleWeakUndefines(); | |
| 506 | 584 | |
| 507 | // Make sure we have resolved all symbols. | |
| 508 | if (!Config->Relocatable && !Config->AllowUndefined) { | |
| 509 | Symtab->reportRemainingUndefines(); | |
| 510 | } else { | |
| 511 | // Even when using --allow-undefined we still want to report the absence of | |
| 512 | // our initial set of undefined symbols (i.e. the entry point and symbols | |
| 513 | // specified via --undefined). | |
| 514 | // Part of the reason for this is that these function don't have signatures | |
| 515 | // so which means they cannot be written as wasm function imports. | |
| 516 | for (auto *Arg : Args.filtered(OPT_undefined)) { | |
| 517 | Symbol *Sym = Symtab->find(Arg->getValue()); | |
| 518 | if (!Sym->isDefined()) | |
| 519 | error("symbol forced with --undefined not found: " + Sym->getName()); | |
| 585 | if (!Config->Shared && !Config->Entry.empty()) { | |
| 586 | EntrySym = handleUndefined(Config->Entry); | |
| 587 | if (EntrySym && EntrySym->isDefined()) | |
| 588 | EntrySym->ForceExport = true; | |
| 589 | else | |
| 590 | error("entry symbol not defined (pass --no-entry to supress): " + | |
| 591 | Config->Entry); | |
| 520 | 592 | } |
| 521 | if (EntrySym && !EntrySym->isDefined()) | |
| 522 | error("entry symbol not defined (pass --no-entry to supress): " + | |
| 523 | EntrySym->getName()); | |
| 593 | ||
| 594 | // Make sure we have resolved all symbols. | |
| 595 | if (!Config->AllowUndefined) | |
| 596 | Symtab->reportRemainingUndefines(); | |
| 524 | 597 | } |
| 598 | ||
| 599 | if (errorCount()) | |
| 600 | return; | |
| 601 | ||
| 602 | // Do link-time optimization if given files are LLVM bitcode files. | |
| 603 | // This compiles bitcode files into real object files. | |
| 604 | Symtab->addCombinedLTOObject(); | |
| 525 | 605 | if (errorCount()) |
| 526 | 606 | return; |
| 527 | 607 |
deps/lld/wasm/InputChunks.cpp+12-15| ... | ... | @@ -25,7 +25,9 @@ using namespace lld::wasm; |
| 25 | 25 | |
| 26 | 26 | static StringRef ReloctTypeToString(uint8_t RelocType) { |
| 27 | 27 | switch (RelocType) { |
| 28 | #define WASM_RELOC(NAME, REL) case REL: return #NAME; | |
| 28 | #define WASM_RELOC(NAME, REL) \ | |
| 29 | case REL: \ | |
| 30 | return #NAME; | |
| 29 | 31 | #include "llvm/BinaryFormat/WasmRelocs.def" |
| 30 | 32 | #undef WASM_RELOC |
| 31 | 33 | } |
| ... | ... | @@ -43,16 +45,6 @@ StringRef InputChunk::getComdatName() const { |
| 43 | 45 | return File->getWasmObj()->linkingData().Comdats[Index]; |
| 44 | 46 | } |
| 45 | 47 | |
| 46 | void InputChunk::copyRelocations(const WasmSection &Section) { | |
| 47 | if (Section.Relocations.empty()) | |
| 48 | return; | |
| 49 | size_t Start = getInputSectionOffset(); | |
| 50 | size_t Size = getInputSize(); | |
| 51 | for (const WasmRelocation &R : Section.Relocations) | |
| 52 | if (R.Offset >= Start && R.Offset < Start + Size) | |
| 53 | Relocations.push_back(R); | |
| 54 | } | |
| 55 | ||
| 56 | 48 | void InputChunk::verifyRelocTargets() const { |
| 57 | 49 | for (const WasmRelocation &Rel : Relocations) { |
| 58 | 50 | uint32_t ExistingValue; |
| ... | ... | @@ -63,6 +55,7 @@ void InputChunk::verifyRelocTargets() const { |
| 63 | 55 | case R_WEBASSEMBLY_TYPE_INDEX_LEB: |
| 64 | 56 | case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: |
| 65 | 57 | case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: |
| 58 | case R_WEBASSEMBLY_EVENT_INDEX_LEB: | |
| 66 | 59 | case R_WEBASSEMBLY_MEMORY_ADDR_LEB: |
| 67 | 60 | ExistingValue = decodeULEB128(Loc, &BytesRead); |
| 68 | 61 | break; |
| ... | ... | @@ -119,6 +112,7 @@ void InputChunk::writeTo(uint8_t *Buf) const { |
| 119 | 112 | case R_WEBASSEMBLY_TYPE_INDEX_LEB: |
| 120 | 113 | case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: |
| 121 | 114 | case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: |
| 115 | case R_WEBASSEMBLY_EVENT_INDEX_LEB: | |
| 122 | 116 | case R_WEBASSEMBLY_MEMORY_ADDR_LEB: |
| 123 | 117 | encodeULEB128(Value, Loc, 5); |
| 124 | 118 | break; |
| ... | ... | @@ -188,6 +182,7 @@ static unsigned writeCompressedReloc(uint8_t *Buf, const WasmRelocation &Rel, |
| 188 | 182 | case R_WEBASSEMBLY_TYPE_INDEX_LEB: |
| 189 | 183 | case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: |
| 190 | 184 | case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: |
| 185 | case R_WEBASSEMBLY_EVENT_INDEX_LEB: | |
| 191 | 186 | case R_WEBASSEMBLY_MEMORY_ADDR_LEB: |
| 192 | 187 | return encodeULEB128(Value, Buf); |
| 193 | 188 | case R_WEBASSEMBLY_TABLE_INDEX_SLEB: |
| ... | ... | @@ -203,6 +198,7 @@ static unsigned getRelocWidthPadded(const WasmRelocation &Rel) { |
| 203 | 198 | case R_WEBASSEMBLY_TYPE_INDEX_LEB: |
| 204 | 199 | case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: |
| 205 | 200 | case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: |
| 201 | case R_WEBASSEMBLY_EVENT_INDEX_LEB: | |
| 206 | 202 | case R_WEBASSEMBLY_MEMORY_ADDR_LEB: |
| 207 | 203 | case R_WEBASSEMBLY_TABLE_INDEX_SLEB: |
| 208 | 204 | case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: |
| ... | ... | @@ -228,7 +224,7 @@ static unsigned getRelocWidth(const WasmRelocation &Rel, uint32_t Value) { |
| 228 | 224 | // This function only computes the final output size. It must be called |
| 229 | 225 | // before getSize() is used to calculate of layout of the code section. |
| 230 | 226 | void InputFunction::calculateSize() { |
| 231 | if (!File || !Config->CompressRelocTargets) | |
| 227 | if (!File || !Config->CompressRelocations) | |
| 232 | 228 | return; |
| 233 | 229 | |
| 234 | 230 | LLVM_DEBUG(dbgs() << "calculateSize: " << getName() << "\n"); |
| ... | ... | @@ -242,7 +238,7 @@ void InputFunction::calculateSize() { |
| 242 | 238 | uint32_t End = Start + Function->Size; |
| 243 | 239 | |
| 244 | 240 | uint32_t LastRelocEnd = Start + FunctionSizeLength; |
| 245 | for (WasmRelocation &Rel : Relocations) { | |
| 241 | for (const WasmRelocation &Rel : Relocations) { | |
| 246 | 242 | LLVM_DEBUG(dbgs() << " region: " << (Rel.Offset - LastRelocEnd) << "\n"); |
| 247 | 243 | CompressedFuncSize += Rel.Offset - LastRelocEnd; |
| 248 | 244 | CompressedFuncSize += getRelocWidth(Rel, File->calcNewValue(Rel)); |
| ... | ... | @@ -263,11 +259,12 @@ void InputFunction::calculateSize() { |
| 263 | 259 | // Override the default writeTo method so that we can (optionally) write the |
| 264 | 260 | // compressed version of the function. |
| 265 | 261 | void InputFunction::writeTo(uint8_t *Buf) const { |
| 266 | if (!File || !Config->CompressRelocTargets) | |
| 262 | if (!File || !Config->CompressRelocations) | |
| 267 | 263 | return InputChunk::writeTo(Buf); |
| 268 | 264 | |
| 269 | 265 | Buf += OutputOffset; |
| 270 | uint8_t *Orig = Buf; (void)Orig; | |
| 266 | uint8_t *Orig = Buf; | |
| 267 | (void)Orig; | |
| 271 | 268 | |
| 272 | 269 | const uint8_t *SecStart = File->CodeSection->Content.data(); |
| 273 | 270 | const uint8_t *FuncStart = SecStart + getInputSectionOffset(); |
deps/lld/wasm/InputChunks.h+14-26| ... | ... | @@ -24,18 +24,9 @@ |
| 24 | 24 | #include "Config.h" |
| 25 | 25 | #include "InputFiles.h" |
| 26 | 26 | #include "lld/Common/ErrorHandler.h" |
| 27 | #include "lld/Common/LLVM.h" | |
| 27 | 28 | #include "llvm/Object/Wasm.h" |
| 28 | 29 | |
| 29 | using llvm::object::WasmSection; | |
| 30 | using llvm::object::WasmSegment; | |
| 31 | using llvm::wasm::WasmFunction; | |
| 32 | using llvm::wasm::WasmRelocation; | |
| 33 | using llvm::wasm::WasmSignature; | |
| 34 | ||
| 35 | namespace llvm { | |
| 36 | class raw_ostream; | |
| 37 | } | |
| 38 | ||
| 39 | 30 | namespace lld { |
| 40 | 31 | namespace wasm { |
| 41 | 32 | |
| ... | ... | @@ -49,17 +40,18 @@ public: |
| 49 | 40 | Kind kind() const { return SectionKind; } |
| 50 | 41 | |
| 51 | 42 | virtual uint32_t getSize() const { return data().size(); } |
| 52 | ||
| 53 | void copyRelocations(const WasmSection &Section); | |
| 43 | virtual uint32_t getInputSize() const { return getSize(); }; | |
| 54 | 44 | |
| 55 | 45 | virtual void writeTo(uint8_t *SectionStart) const; |
| 56 | 46 | |
| 57 | 47 | ArrayRef<WasmRelocation> getRelocations() const { return Relocations; } |
| 48 | void setRelocations(ArrayRef<WasmRelocation> Rs) { Relocations = Rs; } | |
| 58 | 49 | |
| 59 | 50 | virtual StringRef getName() const = 0; |
| 60 | 51 | virtual StringRef getDebugName() const = 0; |
| 61 | 52 | virtual uint32_t getComdat() const = 0; |
| 62 | 53 | StringRef getComdatName() const; |
| 54 | virtual uint32_t getInputSectionOffset() const = 0; | |
| 63 | 55 | |
| 64 | 56 | size_t NumRelocations() const { return Relocations.size(); } |
| 65 | 57 | void writeRelocations(llvm::raw_ostream &OS) const; |
| ... | ... | @@ -77,14 +69,12 @@ protected: |
| 77 | 69 | : File(F), Live(!Config->GcSections), SectionKind(K) {} |
| 78 | 70 | virtual ~InputChunk() = default; |
| 79 | 71 | virtual ArrayRef<uint8_t> data() const = 0; |
| 80 | virtual uint32_t getInputSectionOffset() const = 0; | |
| 81 | virtual uint32_t getInputSize() const { return getSize(); }; | |
| 82 | 72 | |
| 83 | 73 | // Verifies the existing data at relocation targets matches our expectations. |
| 84 | 74 | // This is performed only debug builds as an extra sanity check. |
| 85 | 75 | void verifyRelocTargets() const; |
| 86 | 76 | |
| 87 | std::vector<WasmRelocation> Relocations; | |
| 77 | ArrayRef<WasmRelocation> Relocations; | |
| 88 | 78 | Kind SectionKind; |
| 89 | 79 | }; |
| 90 | 80 | |
| ... | ... | @@ -107,15 +97,15 @@ public: |
| 107 | 97 | StringRef getName() const override { return Segment.Data.Name; } |
| 108 | 98 | StringRef getDebugName() const override { return StringRef(); } |
| 109 | 99 | uint32_t getComdat() const override { return Segment.Data.Comdat; } |
| 100 | uint32_t getInputSectionOffset() const override { | |
| 101 | return Segment.SectionOffset; | |
| 102 | } | |
| 110 | 103 | |
| 111 | 104 | const OutputSegment *OutputSeg = nullptr; |
| 112 | 105 | int32_t OutputSegmentOffset = 0; |
| 113 | 106 | |
| 114 | 107 | protected: |
| 115 | 108 | ArrayRef<uint8_t> data() const override { return Segment.Data.Content; } |
| 116 | uint32_t getInputSectionOffset() const override { | |
| 117 | return Segment.SectionOffset; | |
| 118 | } | |
| 119 | 109 | |
| 120 | 110 | const WasmSegment &Segment; |
| 121 | 111 | }; |
| ... | ... | @@ -139,15 +129,19 @@ public: |
| 139 | 129 | uint32_t getFunctionInputOffset() const { return getInputSectionOffset(); } |
| 140 | 130 | uint32_t getFunctionCodeOffset() const { return Function->CodeOffset; } |
| 141 | 131 | uint32_t getSize() const override { |
| 142 | if (Config->CompressRelocTargets && File) { | |
| 132 | if (Config->CompressRelocations && File) { | |
| 143 | 133 | assert(CompressedSize); |
| 144 | 134 | return CompressedSize; |
| 145 | 135 | } |
| 146 | 136 | return data().size(); |
| 147 | 137 | } |
| 138 | uint32_t getInputSize() const override { return Function->Size; } | |
| 148 | 139 | uint32_t getFunctionIndex() const { return FunctionIndex.getValue(); } |
| 149 | 140 | bool hasFunctionIndex() const { return FunctionIndex.hasValue(); } |
| 150 | 141 | void setFunctionIndex(uint32_t Index); |
| 142 | uint32_t getInputSectionOffset() const override { | |
| 143 | return Function->CodeSectionOffset; | |
| 144 | } | |
| 151 | 145 | uint32_t getTableIndex() const { return TableIndex.getValue(); } |
| 152 | 146 | bool hasTableIndex() const { return TableIndex.hasValue(); } |
| 153 | 147 | void setTableIndex(uint32_t Index); |
| ... | ... | @@ -162,17 +156,11 @@ public: |
| 162 | 156 | |
| 163 | 157 | protected: |
| 164 | 158 | ArrayRef<uint8_t> data() const override { |
| 165 | assert(!Config->CompressRelocTargets); | |
| 159 | assert(!Config->CompressRelocations); | |
| 166 | 160 | return File->CodeSection->Content.slice(getInputSectionOffset(), |
| 167 | 161 | Function->Size); |
| 168 | 162 | } |
| 169 | 163 | |
| 170 | uint32_t getInputSize() const override { return Function->Size; } | |
| 171 | ||
| 172 | uint32_t getInputSectionOffset() const override { | |
| 173 | return Function->CodeSectionOffset; | |
| 174 | } | |
| 175 | ||
| 176 | 164 | const WasmFunction *Function; |
| 177 | 165 | llvm::Optional<uint32_t> FunctionIndex; |
| 178 | 166 | llvm::Optional<uint32_t> TableIndex; |
deps/lld/wasm/InputEvent.h created+63| ... | ... | @@ -0,0 +1,63 @@ |
| 1 | //===- InputEvent.h ---------------------------------------------*- C++ -*-===// | |
| 2 | // | |
| 3 | // The LLVM Linker | |
| 4 | // | |
| 5 | // This file is distributed under the University of Illinois Open Source | |
| 6 | // License. See LICENSE.TXT for details. | |
| 7 | // | |
| 8 | //===----------------------------------------------------------------------===// | |
| 9 | // | |
| 10 | // Wasm events are features that suspend the current execution and transfer the | |
| 11 | // control flow to a corresponding handler. Currently the only supported event | |
| 12 | // kind is exceptions. | |
| 13 | // | |
| 14 | //===----------------------------------------------------------------------===// | |
| 15 | ||
| 16 | #ifndef LLD_WASM_INPUT_EVENT_H | |
| 17 | #define LLD_WASM_INPUT_EVENT_H | |
| 18 | ||
| 19 | #include "Config.h" | |
| 20 | #include "InputFiles.h" | |
| 21 | #include "WriterUtils.h" | |
| 22 | #include "lld/Common/ErrorHandler.h" | |
| 23 | #include "llvm/Object/Wasm.h" | |
| 24 | ||
| 25 | namespace lld { | |
| 26 | namespace wasm { | |
| 27 | ||
| 28 | // Represents a single Wasm Event within an input file. These are combined to | |
| 29 | // form the final EVENTS section. | |
| 30 | class InputEvent { | |
| 31 | public: | |
| 32 | InputEvent(const WasmSignature &S, const WasmEvent &E, ObjFile *F) | |
| 33 | : File(F), Event(E), Signature(S), Live(!Config->GcSections) {} | |
| 34 | ||
| 35 | StringRef getName() const { return Event.SymbolName; } | |
| 36 | const WasmEventType &getType() const { return Event.Type; } | |
| 37 | ||
| 38 | uint32_t getEventIndex() const { return EventIndex.getValue(); } | |
| 39 | bool hasEventIndex() const { return EventIndex.hasValue(); } | |
| 40 | void setEventIndex(uint32_t Index) { | |
| 41 | assert(!hasEventIndex()); | |
| 42 | EventIndex = Index; | |
| 43 | } | |
| 44 | ||
| 45 | ObjFile *File; | |
| 46 | WasmEvent Event; | |
| 47 | const WasmSignature &Signature; | |
| 48 | ||
| 49 | bool Live = false; | |
| 50 | ||
| 51 | protected: | |
| 52 | llvm::Optional<uint32_t> EventIndex; | |
| 53 | }; | |
| 54 | ||
| 55 | } // namespace wasm | |
| 56 | ||
| 57 | inline std::string toString(const wasm::InputEvent *E) { | |
| 58 | return (toString(E->File) + ":(" + E->getName() + ")").str(); | |
| 59 | } | |
| 60 | ||
| 61 | } // namespace lld | |
| 62 | ||
| 63 | #endif // LLD_WASM_INPUT_EVENT_H |
deps/lld/wasm/InputFiles.cpp+71-22| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | #include "InputFiles.h" |
| 11 | 11 | #include "Config.h" |
| 12 | 12 | #include "InputChunks.h" |
| 13 | #include "InputEvent.h" | |
| 13 | 14 | #include "InputGlobal.h" |
| 14 | 15 | #include "SymbolTable.h" |
| 15 | 16 | #include "lld/Common/ErrorHandler.h" |
| ... | ... | @@ -57,12 +58,13 @@ void ObjFile::dumpInfo() const { |
| 57 | 58 | log("info for: " + getName() + |
| 58 | 59 | "\n Symbols : " + Twine(Symbols.size()) + |
| 59 | 60 | "\n Function Imports : " + Twine(WasmObj->getNumImportedFunctions()) + |
| 60 | "\n Global Imports : " + Twine(WasmObj->getNumImportedGlobals())); | |
| 61 | "\n Global Imports : " + Twine(WasmObj->getNumImportedGlobals()) + | |
| 62 | "\n Event Imports : " + Twine(WasmObj->getNumImportedEvents())); | |
| 61 | 63 | } |
| 62 | 64 | |
| 63 | 65 | // Relocations contain either symbol or type indices. This function takes a |
| 64 | 66 | // relocation and returns relocated index (i.e. translates from the input |
| 65 | // sybmol/type space to the output symbol/type space). | |
| 67 | // symbol/type space to the output symbol/type space). | |
| 66 | 68 | uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const { |
| 67 | 69 | if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) { |
| 68 | 70 | assert(TypeIsUsed[Reloc.Index]); |
| ... | ... | @@ -94,16 +96,17 @@ uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const { |
| 94 | 96 | switch (Reloc.Type) { |
| 95 | 97 | case R_WEBASSEMBLY_TABLE_INDEX_I32: |
| 96 | 98 | case R_WEBASSEMBLY_TABLE_INDEX_SLEB: { |
| 97 | const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index]; | |
| 99 | const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index]; | |
| 98 | 100 | return TableEntries[Sym.Info.ElementIndex]; |
| 99 | 101 | } |
| 100 | 102 | case R_WEBASSEMBLY_MEMORY_ADDR_SLEB: |
| 101 | 103 | case R_WEBASSEMBLY_MEMORY_ADDR_I32: |
| 102 | 104 | case R_WEBASSEMBLY_MEMORY_ADDR_LEB: { |
| 103 | const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index]; | |
| 105 | const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index]; | |
| 104 | 106 | if (Sym.isUndefined()) |
| 105 | 107 | return 0; |
| 106 | const WasmSegment& Segment = WasmObj->dataSegments()[Sym.Info.DataRef.Segment]; | |
| 108 | const WasmSegment &Segment = | |
| 109 | WasmObj->dataSegments()[Sym.Info.DataRef.Segment]; | |
| 107 | 110 | return Segment.Data.Offset.Value.Int32 + Sym.Info.DataRef.Offset + |
| 108 | 111 | Reloc.Addend; |
| 109 | 112 | } |
| ... | ... | @@ -118,8 +121,9 @@ uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const { |
| 118 | 121 | case R_WEBASSEMBLY_TYPE_INDEX_LEB: |
| 119 | 122 | return Reloc.Index; |
| 120 | 123 | case R_WEBASSEMBLY_FUNCTION_INDEX_LEB: |
| 121 | case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: { | |
| 122 | const WasmSymbol& Sym = WasmObj->syms()[Reloc.Index]; | |
| 124 | case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: | |
| 125 | case R_WEBASSEMBLY_EVENT_INDEX_LEB: { | |
| 126 | const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index]; | |
| 123 | 127 | return Sym.Info.ElementIndex; |
| 124 | 128 | } |
| 125 | 129 | default: |
| ... | ... | @@ -146,10 +150,13 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const { |
| 146 | 150 | return getFunctionSymbol(Reloc.Index)->getFunctionIndex(); |
| 147 | 151 | case R_WEBASSEMBLY_GLOBAL_INDEX_LEB: |
| 148 | 152 | return getGlobalSymbol(Reloc.Index)->getGlobalIndex(); |
| 153 | case R_WEBASSEMBLY_EVENT_INDEX_LEB: | |
| 154 | return getEventSymbol(Reloc.Index)->getEventIndex(); | |
| 149 | 155 | case R_WEBASSEMBLY_FUNCTION_OFFSET_I32: |
| 150 | 156 | if (auto *Sym = dyn_cast<DefinedFunction>(getFunctionSymbol(Reloc.Index))) { |
| 151 | return Sym->Function->OutputOffset + | |
| 152 | Sym->Function->getFunctionCodeOffset() + Reloc.Addend; | |
| 157 | if (Sym->isLive()) | |
| 158 | return Sym->Function->OutputOffset + | |
| 159 | Sym->Function->getFunctionCodeOffset() + Reloc.Addend; | |
| 153 | 160 | } |
| 154 | 161 | return 0; |
| 155 | 162 | case R_WEBASSEMBLY_SECTION_OFFSET_I32: |
| ... | ... | @@ -159,6 +166,37 @@ uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const { |
| 159 | 166 | } |
| 160 | 167 | } |
| 161 | 168 | |
| 169 | template <class T> | |
| 170 | static void setRelocs(const std::vector<T *> &Chunks, | |
| 171 | const WasmSection *Section) { | |
| 172 | if (!Section) | |
| 173 | return; | |
| 174 | ||
| 175 | ArrayRef<WasmRelocation> Relocs = Section->Relocations; | |
| 176 | assert(std::is_sorted(Relocs.begin(), Relocs.end(), | |
| 177 | [](const WasmRelocation &R1, const WasmRelocation &R2) { | |
| 178 | return R1.Offset < R2.Offset; | |
| 179 | })); | |
| 180 | assert(std::is_sorted( | |
| 181 | Chunks.begin(), Chunks.end(), [](InputChunk *C1, InputChunk *C2) { | |
| 182 | return C1->getInputSectionOffset() < C2->getInputSectionOffset(); | |
| 183 | })); | |
| 184 | ||
| 185 | auto RelocsNext = Relocs.begin(); | |
| 186 | auto RelocsEnd = Relocs.end(); | |
| 187 | auto RelocLess = [](const WasmRelocation &R, uint32_t Val) { | |
| 188 | return R.Offset < Val; | |
| 189 | }; | |
| 190 | for (InputChunk *C : Chunks) { | |
| 191 | auto RelocsStart = std::lower_bound(RelocsNext, RelocsEnd, | |
| 192 | C->getInputSectionOffset(), RelocLess); | |
| 193 | RelocsNext = std::lower_bound( | |
| 194 | RelocsStart, RelocsEnd, C->getInputSectionOffset() + C->getInputSize(), | |
| 195 | RelocLess); | |
| 196 | C->setRelocations(ArrayRef<WasmRelocation>(RelocsStart, RelocsNext)); | |
| 197 | } | |
| 198 | } | |
| 199 | ||
| 162 | 200 | void ObjFile::parse() { |
| 163 | 201 | // Parse a memory buffer as a wasm file. |
| 164 | 202 | LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n"); |
| ... | ... | @@ -200,7 +238,7 @@ void ObjFile::parse() { |
| 200 | 238 | DataSection = &Section; |
| 201 | 239 | } else if (Section.Type == WASM_SEC_CUSTOM) { |
| 202 | 240 | CustomSections.emplace_back(make<InputSection>(Section, this)); |
| 203 | CustomSections.back()->copyRelocations(Section); | |
| 241 | CustomSections.back()->setRelocations(Section.Relocations); | |
| 204 | 242 | CustomSectionsByIndex[SectionIndex] = CustomSections.back(); |
| 205 | 243 | } |
| 206 | 244 | SectionIndex++; |
| ... | ... | @@ -215,11 +253,9 @@ void ObjFile::parse() { |
| 215 | 253 | UsedComdats[I] = Symtab->addComdat(Comdats[I]); |
| 216 | 254 | |
| 217 | 255 | // Populate `Segments`. |
| 218 | for (const WasmSegment &S : WasmObj->dataSegments()) { | |
| 219 | InputSegment *Seg = make<InputSegment>(S, this); | |
| 220 | Seg->copyRelocations(*DataSection); | |
| 221 | Segments.emplace_back(Seg); | |
| 222 | } | |
| 256 | for (const WasmSegment &S : WasmObj->dataSegments()) | |
| 257 | Segments.emplace_back(make<InputSegment>(S, this)); | |
| 258 | setRelocs(Segments, DataSection); | |
| 223 | 259 | |
| 224 | 260 | // Populate `Functions`. |
| 225 | 261 | ArrayRef<WasmFunction> Funcs = WasmObj->functions(); |
| ... | ... | @@ -227,17 +263,19 @@ void ObjFile::parse() { |
| 227 | 263 | ArrayRef<WasmSignature> Types = WasmObj->types(); |
| 228 | 264 | Functions.reserve(Funcs.size()); |
| 229 | 265 | |
| 230 | for (size_t I = 0, E = Funcs.size(); I != E; ++I) { | |
| 231 | InputFunction *F = | |
| 232 | make<InputFunction>(Types[FuncTypes[I]], &Funcs[I], this); | |
| 233 | F->copyRelocations(*CodeSection); | |
| 234 | Functions.emplace_back(F); | |
| 235 | } | |
| 266 | for (size_t I = 0, E = Funcs.size(); I != E; ++I) | |
| 267 | Functions.emplace_back( | |
| 268 | make<InputFunction>(Types[FuncTypes[I]], &Funcs[I], this)); | |
| 269 | setRelocs(Functions, CodeSection); | |
| 236 | 270 | |
| 237 | 271 | // Populate `Globals`. |
| 238 | 272 | for (const WasmGlobal &G : WasmObj->globals()) |
| 239 | 273 | Globals.emplace_back(make<InputGlobal>(G, this)); |
| 240 | 274 | |
| 275 | // Populate `Events`. | |
| 276 | for (const WasmEvent &E : WasmObj->events()) | |
| 277 | Events.emplace_back(make<InputEvent>(Types[E.Type.SigIndex], E, this)); | |
| 278 | ||
| 241 | 279 | // Populate `Symbols` based on the WasmSymbols in the object. |
| 242 | 280 | Symbols.reserve(WasmObj->getNumberOfSymbols()); |
| 243 | 281 | for (const SymbolRef &Sym : WasmObj->symbols()) { |
| ... | ... | @@ -264,6 +302,10 @@ GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t Index) const { |
| 264 | 302 | return cast<GlobalSymbol>(Symbols[Index]); |
| 265 | 303 | } |
| 266 | 304 | |
| 305 | EventSymbol *ObjFile::getEventSymbol(uint32_t Index) const { | |
| 306 | return cast<EventSymbol>(Symbols[Index]); | |
| 307 | } | |
| 308 | ||
| 267 | 309 | SectionSymbol *ObjFile::getSectionSymbol(uint32_t Index) const { |
| 268 | 310 | return cast<SectionSymbol>(Symbols[Index]); |
| 269 | 311 | } |
| ... | ... | @@ -318,6 +360,13 @@ Symbol *ObjFile::createDefined(const WasmSymbol &Sym) { |
| 318 | 360 | assert(Sym.isBindingLocal()); |
| 319 | 361 | return make<SectionSymbol>(Name, Flags, Section, this); |
| 320 | 362 | } |
| 363 | case WASM_SYMBOL_TYPE_EVENT: { | |
| 364 | InputEvent *Event = | |
| 365 | Events[Sym.Info.ElementIndex - WasmObj->getNumImportedEvents()]; | |
| 366 | if (Sym.isBindingLocal()) | |
| 367 | return make<DefinedEvent>(Name, Flags, this, Event); | |
| 368 | return Symtab->addDefinedEvent(Name, Flags, this, Event); | |
| 369 | } | |
| 321 | 370 | } |
| 322 | 371 | llvm_unreachable("unknown symbol kind"); |
| 323 | 372 | } |
| ... | ... | @@ -328,7 +377,7 @@ Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) { |
| 328 | 377 | |
| 329 | 378 | switch (Sym.Info.Kind) { |
| 330 | 379 | case WASM_SYMBOL_TYPE_FUNCTION: |
| 331 | return Symtab->addUndefinedFunction(Name, Flags, this, Sym.FunctionType); | |
| 380 | return Symtab->addUndefinedFunction(Name, Flags, this, Sym.Signature); | |
| 332 | 381 | case WASM_SYMBOL_TYPE_DATA: |
| 333 | 382 | return Symtab->addUndefinedData(Name, Flags, this); |
| 334 | 383 | case WASM_SYMBOL_TYPE_GLOBAL: |
deps/lld/wasm/InputFiles.h+5-17| ... | ... | @@ -20,21 +20,6 @@ |
| 20 | 20 | #include "llvm/Support/MemoryBuffer.h" |
| 21 | 21 | #include <vector> |
| 22 | 22 | |
| 23 | using llvm::object::Archive; | |
| 24 | using llvm::object::WasmObjectFile; | |
| 25 | using llvm::object::WasmSection; | |
| 26 | using llvm::object::WasmSymbol; | |
| 27 | using llvm::wasm::WasmGlobal; | |
| 28 | using llvm::wasm::WasmImport; | |
| 29 | using llvm::wasm::WasmRelocation; | |
| 30 | using llvm::wasm::WasmSignature; | |
| 31 | ||
| 32 | namespace llvm { | |
| 33 | namespace lto { | |
| 34 | class InputFile; | |
| 35 | } | |
| 36 | } // namespace llvm | |
| 37 | ||
| 38 | 23 | namespace lld { |
| 39 | 24 | namespace wasm { |
| 40 | 25 | |
| ... | ... | @@ -42,6 +27,7 @@ class InputChunk; |
| 42 | 27 | class InputFunction; |
| 43 | 28 | class InputSegment; |
| 44 | 29 | class InputGlobal; |
| 30 | class InputEvent; | |
| 45 | 31 | class InputSection; |
| 46 | 32 | |
| 47 | 33 | class InputFile { |
| ... | ... | @@ -84,12 +70,12 @@ public: |
| 84 | 70 | explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {} |
| 85 | 71 | static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; } |
| 86 | 72 | |
| 87 | void addMember(const Archive::Symbol *Sym); | |
| 73 | void addMember(const llvm::object::Archive::Symbol *Sym); | |
| 88 | 74 | |
| 89 | 75 | void parse() override; |
| 90 | 76 | |
| 91 | 77 | private: |
| 92 | std::unique_ptr<Archive> File; | |
| 78 | std::unique_ptr<llvm::object::Archive> File; | |
| 93 | 79 | llvm::DenseSet<uint64_t> Seen; |
| 94 | 80 | }; |
| 95 | 81 | |
| ... | ... | @@ -123,6 +109,7 @@ public: |
| 123 | 109 | std::vector<InputSegment *> Segments; |
| 124 | 110 | std::vector<InputFunction *> Functions; |
| 125 | 111 | std::vector<InputGlobal *> Globals; |
| 112 | std::vector<InputEvent *> Events; | |
| 126 | 113 | std::vector<InputSection *> CustomSections; |
| 127 | 114 | llvm::DenseMap<uint32_t, InputSection *> CustomSectionsByIndex; |
| 128 | 115 | |
| ... | ... | @@ -131,6 +118,7 @@ public: |
| 131 | 118 | DataSymbol *getDataSymbol(uint32_t Index) const; |
| 132 | 119 | GlobalSymbol *getGlobalSymbol(uint32_t Index) const; |
| 133 | 120 | SectionSymbol *getSectionSymbol(uint32_t Index) const; |
| 121 | EventSymbol *getEventSymbol(uint32_t Index) const; | |
| 134 | 122 | |
| 135 | 123 | private: |
| 136 | 124 | Symbol *createDefined(const WasmSymbol &Sym); |
deps/lld/wasm/InputGlobal.h-3| ... | ... | @@ -16,9 +16,6 @@ |
| 16 | 16 | #include "lld/Common/ErrorHandler.h" |
| 17 | 17 | #include "llvm/Object/Wasm.h" |
| 18 | 18 | |
| 19 | using llvm::wasm::WasmGlobal; | |
| 20 | using llvm::wasm::WasmInitExpr; | |
| 21 | ||
| 22 | 19 | namespace lld { |
| 23 | 20 | namespace wasm { |
| 24 | 21 |
deps/lld/wasm/LTO.cpp+12-5| ... | ... | @@ -36,8 +36,6 @@ |
| 36 | 36 | #include <vector> |
| 37 | 37 | |
| 38 | 38 | using namespace llvm; |
| 39 | using namespace llvm::object; | |
| 40 | ||
| 41 | 39 | using namespace lld; |
| 42 | 40 | using namespace lld::wasm; |
| 43 | 41 | |
| ... | ... | @@ -55,6 +53,14 @@ static std::unique_ptr<lto::LTO> createLTO() { |
| 55 | 53 | C.DisableVerify = Config->DisableVerify; |
| 56 | 54 | C.DiagHandler = diagnosticHandler; |
| 57 | 55 | C.OptLevel = Config->LTOO; |
| 56 | C.MAttrs = GetMAttrs(); | |
| 57 | ||
| 58 | if (Config->Relocatable) | |
| 59 | C.RelocModel = None; | |
| 60 | else if (Config->Pic) | |
| 61 | C.RelocModel = Reloc::PIC_; | |
| 62 | else | |
| 63 | C.RelocModel = Reloc::Static; | |
| 58 | 64 | |
| 59 | 65 | if (Config->SaveTemps) |
| 60 | 66 | checkError(C.addSaveTemps(Config->OutputFile.str() + ".", |
| ... | ... | @@ -72,10 +78,11 @@ BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {} |
| 72 | 78 | BitcodeCompiler::~BitcodeCompiler() = default; |
| 73 | 79 | |
| 74 | 80 | static void undefine(Symbol *S) { |
| 75 | if (isa<DefinedFunction>(S)) | |
| 76 | replaceSymbol<UndefinedFunction>(S, S->getName(), 0); | |
| 81 | if (auto F = dyn_cast<DefinedFunction>(S)) | |
| 82 | replaceSymbol<UndefinedFunction>(F, F->getName(), 0, F->getFile(), | |
| 83 | F->Signature); | |
| 77 | 84 | else if (isa<DefinedData>(S)) |
| 78 | replaceSymbol<UndefinedData>(S, S->getName(), 0); | |
| 85 | replaceSymbol<UndefinedData>(S, S->getName(), 0, S->getFile()); | |
| 79 | 86 | else |
| 80 | 87 | llvm_unreachable("unexpected symbol kind"); |
| 81 | 88 | } |
deps/lld/wasm/MarkLive.cpp+4-2| ... | ... | @@ -22,6 +22,7 @@ |
| 22 | 22 | #include "MarkLive.h" |
| 23 | 23 | #include "Config.h" |
| 24 | 24 | #include "InputChunks.h" |
| 25 | #include "InputEvent.h" | |
| 25 | 26 | #include "InputGlobal.h" |
| 26 | 27 | #include "SymbolTable.h" |
| 27 | 28 | #include "Symbols.h" |
| ... | ... | @@ -30,8 +31,6 @@ |
| 30 | 31 | |
| 31 | 32 | using namespace llvm; |
| 32 | 33 | using namespace llvm::wasm; |
| 33 | using namespace lld; | |
| 34 | using namespace lld::wasm; | |
| 35 | 34 | |
| 36 | 35 | void lld::wasm::markLive() { |
| 37 | 36 | if (!Config->GcSections) |
| ... | ... | @@ -107,6 +106,9 @@ void lld::wasm::markLive() { |
| 107 | 106 | for (InputGlobal *G : Obj->Globals) |
| 108 | 107 | if (!G->Live) |
| 109 | 108 | message("removing unused section " + toString(G)); |
| 109 | for (InputEvent *E : Obj->Events) | |
| 110 | if (!E->Live) | |
| 111 | message("removing unused section " + toString(E)); | |
| 110 | 112 | } |
| 111 | 113 | for (InputChunk *C : Symtab->SyntheticFunctions) |
| 112 | 114 | if (!C->Live) |
deps/lld/wasm/Options.td+33-16| ... | ... | @@ -6,9 +6,10 @@ class F<string name>: Flag<["--", "-"], name>; |
| 6 | 6 | class J<string name>: Joined<["--", "-"], name>; |
| 7 | 7 | class S<string name>: Separate<["--", "-"], name>; |
| 8 | 8 | |
| 9 | multiclass Eq<string name> { | |
| 10 | def "": Separate<["--", "-"], name>; | |
| 11 | def _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>; | |
| 9 | multiclass Eq<string name, string help> { | |
| 10 | def NAME: Separate<["--", "-"], name>; | |
| 11 | def NAME # _eq: Joined<["--", "-"], name # "=">, Alias<!cast<Separate>(NAME)>, | |
| 12 | HelpText<help>; | |
| 12 | 13 | } |
| 13 | 14 | |
| 14 | 15 | multiclass B<string name, string help1, string help2> { |
| ... | ... | @@ -16,17 +17,24 @@ multiclass B<string name, string help1, string help2> { |
| 16 | 17 | def no_ # NAME: Flag<["--", "-"], "no-" # name>, HelpText<help2>; |
| 17 | 18 | } |
| 18 | 19 | |
| 19 | // The follow flags are shared with the ELF linker | |
| 20 | // The following flags are shared with the ELF linker | |
| 20 | 21 | def color_diagnostics: F<"color-diagnostics">, |
| 21 | 22 | HelpText<"Use colors in diagnostics">; |
| 22 | 23 | |
| 23 | 24 | def color_diagnostics_eq: J<"color-diagnostics=">, |
| 24 | 25 | HelpText<"Use colors in diagnostics; one of 'always', 'never', 'auto'">; |
| 25 | 26 | |
| 27 | def compress_relocations: F<"compress-relocations">, | |
| 28 | HelpText<"Compress the relocation targets in the code section.">; | |
| 29 | ||
| 26 | 30 | defm demangle: B<"demangle", |
| 27 | 31 | "Demangle symbol names", |
| 28 | 32 | "Do not demangle symbol names">; |
| 29 | 33 | |
| 34 | defm export_dynamic: B<"export-dynamic", | |
| 35 | "Put symbols in the dynamic symbol table", | |
| 36 | "Do not put symbols in the dynamic symbol table (default)">; | |
| 37 | ||
| 30 | 38 | def entry: S<"entry">, MetaVarName<"<entry>">, |
| 31 | 39 | HelpText<"Name of entry point symbol">; |
| 32 | 40 | |
| ... | ... | @@ -67,20 +75,25 @@ def o: JoinedOrSeparate<["-"], "o">, MetaVarName<"<path>">, |
| 67 | 75 | |
| 68 | 76 | def O: JoinedOrSeparate<["-"], "O">, HelpText<"Optimize output file size">; |
| 69 | 77 | |
| 78 | defm pie: B<"pie", | |
| 79 | "Create a position independent executable", | |
| 80 | "Do not create a position independent executable (default)">; | |
| 81 | ||
| 70 | 82 | defm print_gc_sections: B<"print-gc-sections", |
| 71 | 83 | "List removed unused sections", |
| 72 | 84 | "Do not list removed unused sections">; |
| 73 | 85 | |
| 74 | 86 | def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">; |
| 75 | 87 | |
| 88 | def shared: F<"shared">, HelpText<"Build a shared object">; | |
| 89 | ||
| 76 | 90 | def strip_all: F<"strip-all">, HelpText<"Strip all symbols">; |
| 77 | 91 | |
| 78 | 92 | def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">; |
| 79 | 93 | |
| 80 | 94 | def threads: F<"threads">, HelpText<"Run the linker multi-threaded">; |
| 81 | 95 | |
| 82 | defm undefined: Eq<"undefined">, | |
| 83 | HelpText<"Force undefined symbol during linking">; | |
| 96 | defm undefined: Eq<"undefined", "Force undefined symbol during linking">; | |
| 84 | 97 | |
| 85 | 98 | def v: Flag<["-"], "v">, HelpText<"Display the version number">; |
| 86 | 99 | |
| ... | ... | @@ -102,8 +115,7 @@ def allow_undefined_file: J<"allow-undefined-file=">, |
| 102 | 115 | def allow_undefined_file_s: Separate<["-"], "allow-undefined-file">, |
| 103 | 116 | Alias<allow_undefined_file>; |
| 104 | 117 | |
| 105 | defm export: Eq<"export">, | |
| 106 | HelpText<"Force a symbol to be exported">; | |
| 118 | defm export: Eq<"export", "Force a symbol to be exported">; | |
| 107 | 119 | |
| 108 | 120 | def export_all: F<"export-all">, |
| 109 | 121 | HelpText<"Export all symbols (normally combined with --no-gc-sections)">; |
| ... | ... | @@ -117,6 +129,9 @@ def global_base: J<"global-base=">, |
| 117 | 129 | def import_memory: F<"import-memory">, |
| 118 | 130 | HelpText<"Import memory from the environment">; |
| 119 | 131 | |
| 132 | def shared_memory: F<"shared-memory">, | |
| 133 | HelpText<"Use shared linear memory">; | |
| 134 | ||
| 120 | 135 | def import_table: F<"import-table">, |
| 121 | 136 | HelpText<"Import function table from the environment">; |
| 122 | 137 | |
| ... | ... | @@ -137,12 +152,15 @@ defm whole_archive: B<"whole-archive", |
| 137 | 152 | "Do not force load of all members in a static library (default)">; |
| 138 | 153 | |
| 139 | 154 | // Aliases |
| 140 | def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>; | |
| 141 | def alias_entry_entry: J<"entry=">, Alias<entry>; | |
| 142 | def alias_initial_memory_i: Flag<["-"], "i">, Alias<initial_memory>; | |
| 143 | def alias_max_memory_m: Flag<["-"], "m">, Alias<max_memory>; | |
| 144 | def alias_relocatable_r: Flag<["-"], "r">, Alias<relocatable>; | |
| 145 | def alias_undefined_u: JoinedOrSeparate<["-"], "u">, Alias<undefined>; | |
| 155 | def: JoinedOrSeparate<["-"], "e">, Alias<entry>; | |
| 156 | def: J<"entry=">, Alias<entry>; | |
| 157 | def: Flag<["-"], "E">, Alias<export_dynamic>, HelpText<"Alias for --export-dynamic">; | |
| 158 | def: Flag<["-"], "i">, Alias<initial_memory>; | |
| 159 | def: Flag<["-"], "m">, Alias<max_memory>; | |
| 160 | def: Flag<["-"], "r">, Alias<relocatable>; | |
| 161 | def: Flag<["-"], "s">, Alias<strip_all>, HelpText<"Alias for --strip-all">; | |
| 162 | def: Flag<["-"], "S">, Alias<strip_debug>, HelpText<"Alias for --strip-debug">; | |
| 163 | def: JoinedOrSeparate<["-"], "u">, Alias<undefined>; | |
| 146 | 164 | |
| 147 | 165 | // LTO-related options. |
| 148 | 166 | def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">, |
| ... | ... | @@ -153,6 +171,5 @@ def disable_verify: F<"disable-verify">; |
| 153 | 171 | def save_temps: F<"save-temps">; |
| 154 | 172 | def thinlto_cache_dir: J<"thinlto-cache-dir=">, |
| 155 | 173 | HelpText<"Path to ThinLTO cached object file directory">; |
| 156 | defm thinlto_cache_policy: Eq<"thinlto-cache-policy">, | |
| 157 | HelpText<"Pruning policy for the ThinLTO cache">; | |
| 174 | defm thinlto_cache_policy: Eq<"thinlto-cache-policy", "Pruning policy for the ThinLTO cache">; | |
| 158 | 175 | def thinlto_jobs: J<"thinlto-jobs=">, HelpText<"Number of ThinLTO jobs">; |
deps/lld/wasm/OutputSections.cpp+13-3| ... | ... | @@ -40,6 +40,8 @@ static StringRef sectionTypeToString(uint32_t SectionType) { |
| 40 | 40 | return "MEMORY"; |
| 41 | 41 | case WASM_SEC_GLOBAL: |
| 42 | 42 | return "GLOBAL"; |
| 43 | case WASM_SEC_EVENT: | |
| 44 | return "EVENT"; | |
| 43 | 45 | case WASM_SEC_EXPORT: |
| 44 | 46 | return "EXPORT"; |
| 45 | 47 | case WASM_SEC_START: |
| ... | ... | @@ -136,9 +138,17 @@ DataSection::DataSection(ArrayRef<OutputSegment *> Segments) |
| 136 | 138 | for (OutputSegment *Segment : Segments) { |
| 137 | 139 | raw_string_ostream OS(Segment->Header); |
| 138 | 140 | writeUleb128(OS, 0, "memory index"); |
| 139 | writeUleb128(OS, WASM_OPCODE_I32_CONST, "opcode:i32const"); | |
| 140 | writeSleb128(OS, Segment->StartVA, "memory offset"); | |
| 141 | writeUleb128(OS, WASM_OPCODE_END, "opcode:end"); | |
| 141 | WasmInitExpr InitExpr; | |
| 142 | if (Config->Pic) { | |
| 143 | assert(Segments.size() <= 1 && | |
| 144 | "Currenly only a single data segment is supported in PIC mode"); | |
| 145 | InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET; | |
| 146 | InitExpr.Value.Global = WasmSym::MemoryBase->getGlobalIndex(); | |
| 147 | } else { | |
| 148 | InitExpr.Opcode = WASM_OPCODE_I32_CONST; | |
| 149 | InitExpr.Value.Int32 = Segment->StartVA; | |
| 150 | } | |
| 151 | writeInitExpr(OS, InitExpr); | |
| 142 | 152 | writeUleb128(OS, Segment->Size, "segment size"); |
| 143 | 153 | OS.flush(); |
| 144 | 154 |
deps/lld/wasm/OutputSections.h+3-5| ... | ... | @@ -13,11 +13,9 @@ |
| 13 | 13 | #include "InputChunks.h" |
| 14 | 14 | #include "WriterUtils.h" |
| 15 | 15 | #include "lld/Common/ErrorHandler.h" |
| 16 | #include "lld/Common/LLVM.h" | |
| 16 | 17 | #include "llvm/ADT/DenseMap.h" |
| 17 | 18 | |
| 18 | using llvm::raw_ostream; | |
| 19 | using llvm::raw_string_ostream; | |
| 20 | ||
| 21 | 19 | namespace lld { |
| 22 | 20 | |
| 23 | 21 | namespace wasm { |
| ... | ... | @@ -82,7 +80,7 @@ public: |
| 82 | 80 | std::string Body; |
| 83 | 81 | |
| 84 | 82 | protected: |
| 85 | raw_string_ostream BodyOutputStream; | |
| 83 | llvm::raw_string_ostream BodyOutputStream; | |
| 86 | 84 | }; |
| 87 | 85 | |
| 88 | 86 | class CodeSection : public OutputSection { |
| ... | ... | @@ -113,7 +111,7 @@ protected: |
| 113 | 111 | size_t BodySize = 0; |
| 114 | 112 | }; |
| 115 | 113 | |
| 116 | // Represents a custom section in the output file. Wasm custom sections are | |
| 114 | // Represents a custom section in the output file. Wasm custom sections are | |
| 117 | 115 | // used for storing user-defined metadata. Unlike the core sections types |
| 118 | 116 | // they are identified by their string name. |
| 119 | 117 | // The linker combines custom sections that have the same name by simply |
deps/lld/wasm/OutputSegment.h+1-1| ... | ... | @@ -26,7 +26,7 @@ public: |
| 26 | 26 | void addInputSegment(InputSegment *InSeg) { |
| 27 | 27 | Alignment = std::max(Alignment, InSeg->getAlignment()); |
| 28 | 28 | InputSegments.push_back(InSeg); |
| 29 | Size = llvm::alignTo(Size, InSeg->getAlignment()); | |
| 29 | Size = llvm::alignTo(Size, 1 << InSeg->getAlignment()); | |
| 30 | 30 | InSeg->OutputSeg = this; |
| 31 | 31 | InSeg->OutputSegmentOffset = Size; |
| 32 | 32 | Size += InSeg->getSize(); |
deps/lld/wasm/SymbolTable.cpp+88-59| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | #include "SymbolTable.h" |
| 11 | 11 | #include "Config.h" |
| 12 | 12 | #include "InputChunks.h" |
| 13 | #include "InputEvent.h" | |
| 13 | 14 | #include "InputGlobal.h" |
| 14 | 15 | #include "WriterUtils.h" |
| 15 | 16 | #include "lld/Common/ErrorHandler.h" |
| ... | ... | @@ -20,6 +21,7 @@ |
| 20 | 21 | |
| 21 | 22 | using namespace llvm; |
| 22 | 23 | using namespace llvm::wasm; |
| 24 | using namespace llvm::object; | |
| 23 | 25 | using namespace lld; |
| 24 | 26 | using namespace lld::wasm; |
| 25 | 27 | |
| ... | ... | @@ -60,7 +62,6 @@ void SymbolTable::addCombinedLTOObject() { |
| 60 | 62 | } |
| 61 | 63 | |
| 62 | 64 | void SymbolTable::reportRemainingUndefines() { |
| 63 | SetVector<Symbol *> Undefs; | |
| 64 | 65 | for (Symbol *Sym : SymVector) { |
| 65 | 66 | if (!Sym->isUndefined() || Sym->isWeak()) |
| 66 | 67 | continue; |
| ... | ... | @@ -68,34 +69,26 @@ void SymbolTable::reportRemainingUndefines() { |
| 68 | 69 | continue; |
| 69 | 70 | if (!Sym->IsUsedInRegularObj) |
| 70 | 71 | continue; |
| 71 | Undefs.insert(Sym); | |
| 72 | error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym)); | |
| 72 | 73 | } |
| 73 | ||
| 74 | if (Undefs.empty()) | |
| 75 | return; | |
| 76 | ||
| 77 | for (ObjFile *File : ObjectFiles) | |
| 78 | for (Symbol *Sym : File->getSymbols()) | |
| 79 | if (Undefs.count(Sym)) | |
| 80 | error(toString(File) + ": undefined symbol: " + toString(*Sym)); | |
| 81 | ||
| 82 | for (Symbol *Sym : Undefs) | |
| 83 | if (!Sym->getFile()) | |
| 84 | error("undefined symbol: " + toString(*Sym)); | |
| 85 | 74 | } |
| 86 | 75 | |
| 87 | 76 | Symbol *SymbolTable::find(StringRef Name) { |
| 88 | 77 | return SymMap.lookup(CachedHashStringRef(Name)); |
| 89 | 78 | } |
| 90 | 79 | |
| 91 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) { | |
| 80 | std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) { | |
| 81 | bool Inserted = false; | |
| 92 | 82 | Symbol *&Sym = SymMap[CachedHashStringRef(Name)]; |
| 93 | if (Sym) | |
| 94 | return {Sym, false}; | |
| 95 | Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); | |
| 96 | Sym->IsUsedInRegularObj = false; | |
| 97 | SymVector.emplace_back(Sym); | |
| 98 | return {Sym, true}; | |
| 83 | if (!Sym) { | |
| 84 | Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>()); | |
| 85 | Sym->IsUsedInRegularObj = false; | |
| 86 | SymVector.emplace_back(Sym); | |
| 87 | Inserted = true; | |
| 88 | } | |
| 89 | if (!File || File->kind() == InputFile::ObjectKind) | |
| 90 | Sym->IsUsedInRegularObj = true; | |
| 91 | return {Sym, Inserted}; | |
| 99 | 92 | } |
| 100 | 93 | |
| 101 | 94 | static void reportTypeError(const Symbol *Existing, const InputFile *File, |
| ... | ... | @@ -106,6 +99,8 @@ static void reportTypeError(const Symbol *Existing, const InputFile *File, |
| 106 | 99 | " in " + toString(File)); |
| 107 | 100 | } |
| 108 | 101 | |
| 102 | // Check the type of new symbol matches that of the symbol is replacing. | |
| 103 | // For functions this can also involve verifying that the signatures match. | |
| 109 | 104 | static void checkFunctionType(Symbol *Existing, const InputFile *File, |
| 110 | 105 | const WasmSignature *NewSig) { |
| 111 | 106 | auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing); |
| ... | ... | @@ -117,9 +112,9 @@ static void checkFunctionType(Symbol *Existing, const InputFile *File, |
| 117 | 112 | if (!NewSig) |
| 118 | 113 | return; |
| 119 | 114 | |
| 120 | const WasmSignature *OldSig = ExistingFunction->FunctionType; | |
| 115 | const WasmSignature *OldSig = ExistingFunction->Signature; | |
| 121 | 116 | if (!OldSig) { |
| 122 | ExistingFunction->FunctionType = NewSig; | |
| 117 | ExistingFunction->Signature = NewSig; | |
| 123 | 118 | return; |
| 124 | 119 | } |
| 125 | 120 | |
| ... | ... | @@ -130,8 +125,6 @@ static void checkFunctionType(Symbol *Existing, const InputFile *File, |
| 130 | 125 | toString(*NewSig) + " in " + toString(File)); |
| 131 | 126 | } |
| 132 | 127 | |
| 133 | // Check the type of new symbol matches that of the symbol is replacing. | |
| 134 | // For functions this can also involve verifying that the signatures match. | |
| 135 | 128 | static void checkGlobalType(const Symbol *Existing, const InputFile *File, |
| 136 | 129 | const WasmGlobalType *NewType) { |
| 137 | 130 | if (!isa<GlobalSymbol>(Existing)) { |
| ... | ... | @@ -147,6 +140,28 @@ static void checkGlobalType(const Symbol *Existing, const InputFile *File, |
| 147 | 140 | } |
| 148 | 141 | } |
| 149 | 142 | |
| 143 | static void checkEventType(const Symbol *Existing, const InputFile *File, | |
| 144 | const WasmEventType *NewType, | |
| 145 | const WasmSignature *NewSig) { | |
| 146 | auto ExistingEvent = dyn_cast<EventSymbol>(Existing); | |
| 147 | if (!isa<EventSymbol>(Existing)) { | |
| 148 | reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT); | |
| 149 | return; | |
| 150 | } | |
| 151 | ||
| 152 | const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType(); | |
| 153 | const WasmSignature *OldSig = ExistingEvent->Signature; | |
| 154 | if (NewType->Attribute != OldType->Attribute) | |
| 155 | error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " + | |
| 156 | toString(*OldType) + " in " + toString(Existing->getFile()) + | |
| 157 | "\n>>> defined as " + toString(*NewType) + " in " + toString(File)); | |
| 158 | if (*NewSig != *OldSig) | |
| 159 | warn("Event signature mismatch: " + Existing->getName() + | |
| 160 | "\n>>> defined as " + toString(*OldSig) + " in " + | |
| 161 | toString(Existing->getFile()) + "\n>>> defined as " + | |
| 162 | toString(*NewSig) + " in " + toString(File)); | |
| 163 | } | |
| 164 | ||
| 150 | 165 | static void checkDataType(const Symbol *Existing, const InputFile *File) { |
| 151 | 166 | if (!isa<DataSymbol>(Existing)) |
| 152 | 167 | reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA); |
| ... | ... | @@ -158,15 +173,15 @@ DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name, |
| 158 | 173 | LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n"); |
| 159 | 174 | assert(!find(Name)); |
| 160 | 175 | SyntheticFunctions.emplace_back(Function); |
| 161 | return replaceSymbol<DefinedFunction>(insert(Name).first, Name, Flags, | |
| 162 | nullptr, Function); | |
| 176 | return replaceSymbol<DefinedFunction>(insert(Name, nullptr).first, Name, | |
| 177 | Flags, nullptr, Function); | |
| 163 | 178 | } |
| 164 | 179 | |
| 165 | 180 | DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name, |
| 166 | 181 | uint32_t Flags) { |
| 167 | 182 | LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n"); |
| 168 | 183 | assert(!find(Name)); |
| 169 | return replaceSymbol<DefinedData>(insert(Name).first, Name, Flags); | |
| 184 | return replaceSymbol<DefinedData>(insert(Name, nullptr).first, Name, Flags); | |
| 170 | 185 | } |
| 171 | 186 | |
| 172 | 187 | DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, |
| ... | ... | @@ -175,8 +190,8 @@ DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags, |
| 175 | 190 | << "\n"); |
| 176 | 191 | assert(!find(Name)); |
| 177 | 192 | SyntheticGlobals.emplace_back(Global); |
| 178 | return replaceSymbol<DefinedGlobal>(insert(Name).first, Name, Flags, nullptr, | |
| 179 | Global); | |
| 193 | return replaceSymbol<DefinedGlobal>(insert(Name, nullptr).first, Name, Flags, | |
| 194 | nullptr, Global); | |
| 180 | 195 | } |
| 181 | 196 | |
| 182 | 197 | static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, |
| ... | ... | @@ -210,13 +225,12 @@ static bool shouldReplace(const Symbol *Existing, InputFile *NewFile, |
| 210 | 225 | Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, |
| 211 | 226 | InputFile *File, |
| 212 | 227 | InputFunction *Function) { |
| 213 | LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << "\n"); | |
| 228 | LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " [" | |
| 229 | << (Function ? toString(Function->Signature) : "none") | |
| 230 | << "]\n"); | |
| 214 | 231 | Symbol *S; |
| 215 | 232 | bool WasInserted; |
| 216 | std::tie(S, WasInserted) = insert(Name); | |
| 217 | ||
| 218 | if (!File || File->kind() == InputFile::ObjectKind) | |
| 219 | S->IsUsedInRegularObj = true; | |
| 233 | std::tie(S, WasInserted) = insert(Name, File); | |
| 220 | 234 | |
| 221 | 235 | if (WasInserted || S->isLazy()) { |
| 222 | 236 | replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); |
| ... | ... | @@ -226,8 +240,16 @@ Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags, |
| 226 | 240 | if (Function) |
| 227 | 241 | checkFunctionType(S, File, &Function->Signature); |
| 228 | 242 | |
| 229 | if (shouldReplace(S, File, Flags)) | |
| 230 | replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); | |
| 243 | if (shouldReplace(S, File, Flags)) { | |
| 244 | // If the new defined function doesn't have signture (i.e. bitcode | |
| 245 | // functions) but the old symbols does then preserve the old signature | |
| 246 | const WasmSignature *OldSig = nullptr; | |
| 247 | if (auto* F = dyn_cast<FunctionSymbol>(S)) | |
| 248 | OldSig = F->Signature; | |
| 249 | auto NewSym = replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function); | |
| 250 | if (!NewSym->Signature) | |
| 251 | NewSym->Signature = OldSig; | |
| 252 | } | |
| 231 | 253 | return S; |
| 232 | 254 | } |
| 233 | 255 | |
| ... | ... | @@ -238,10 +260,7 @@ Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, |
| 238 | 260 | << "\n"); |
| 239 | 261 | Symbol *S; |
| 240 | 262 | bool WasInserted; |
| 241 | std::tie(S, WasInserted) = insert(Name); | |
| 242 | ||
| 243 | if (!File || File->kind() == InputFile::ObjectKind) | |
| 244 | S->IsUsedInRegularObj = true; | |
| 263 | std::tie(S, WasInserted) = insert(Name, File); | |
| 245 | 264 | |
| 246 | 265 | if (WasInserted || S->isLazy()) { |
| 247 | 266 | replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size); |
| ... | ... | @@ -258,12 +277,10 @@ Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags, |
| 258 | 277 | Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, |
| 259 | 278 | InputFile *File, InputGlobal *Global) { |
| 260 | 279 | LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n"); |
| 280 | ||
| 261 | 281 | Symbol *S; |
| 262 | 282 | bool WasInserted; |
| 263 | std::tie(S, WasInserted) = insert(Name); | |
| 264 | ||
| 265 | if (!File || File->kind() == InputFile::ObjectKind) | |
| 266 | S->IsUsedInRegularObj = true; | |
| 283 | std::tie(S, WasInserted) = insert(Name, File); | |
| 267 | 284 | |
| 268 | 285 | if (WasInserted || S->isLazy()) { |
| 269 | 286 | replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global); |
| ... | ... | @@ -277,17 +294,35 @@ Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags, |
| 277 | 294 | return S; |
| 278 | 295 | } |
| 279 | 296 | |
| 297 | Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags, | |
| 298 | InputFile *File, InputEvent *Event) { | |
| 299 | LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n"); | |
| 300 | ||
| 301 | Symbol *S; | |
| 302 | bool WasInserted; | |
| 303 | std::tie(S, WasInserted) = insert(Name, File); | |
| 304 | ||
| 305 | if (WasInserted || S->isLazy()) { | |
| 306 | replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event); | |
| 307 | return S; | |
| 308 | } | |
| 309 | ||
| 310 | checkEventType(S, File, &Event->getType(), &Event->Signature); | |
| 311 | ||
| 312 | if (shouldReplace(S, File, Flags)) | |
| 313 | replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event); | |
| 314 | return S; | |
| 315 | } | |
| 316 | ||
| 280 | 317 | Symbol *SymbolTable::addUndefinedFunction(StringRef Name, uint32_t Flags, |
| 281 | 318 | InputFile *File, |
| 282 | 319 | const WasmSignature *Sig) { |
| 283 | LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << "\n"); | |
| 320 | LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name << | |
| 321 | " [" << (Sig ? toString(*Sig) : "none") << "]\n"); | |
| 284 | 322 | |
| 285 | 323 | Symbol *S; |
| 286 | 324 | bool WasInserted; |
| 287 | std::tie(S, WasInserted) = insert(Name); | |
| 288 | ||
| 289 | if (!File || File->kind() == InputFile::ObjectKind) | |
| 290 | S->IsUsedInRegularObj = true; | |
| 325 | std::tie(S, WasInserted) = insert(Name, File); | |
| 291 | 326 | |
| 292 | 327 | if (WasInserted) |
| 293 | 328 | replaceSymbol<UndefinedFunction>(S, Name, Flags, File, Sig); |
| ... | ... | @@ -305,10 +340,7 @@ Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags, |
| 305 | 340 | |
| 306 | 341 | Symbol *S; |
| 307 | 342 | bool WasInserted; |
| 308 | std::tie(S, WasInserted) = insert(Name); | |
| 309 | ||
| 310 | if (!File || File->kind() == InputFile::ObjectKind) | |
| 311 | S->IsUsedInRegularObj = true; | |
| 343 | std::tie(S, WasInserted) = insert(Name, File); | |
| 312 | 344 | |
| 313 | 345 | if (WasInserted) |
| 314 | 346 | replaceSymbol<UndefinedData>(S, Name, Flags, File); |
| ... | ... | @@ -326,10 +358,7 @@ Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, uint32_t Flags, |
| 326 | 358 | |
| 327 | 359 | Symbol *S; |
| 328 | 360 | bool WasInserted; |
| 329 | std::tie(S, WasInserted) = insert(Name); | |
| 330 | ||
| 331 | if (!File || File->kind() == InputFile::ObjectKind) | |
| 332 | S->IsUsedInRegularObj = true; | |
| 361 | std::tie(S, WasInserted) = insert(Name, File); | |
| 333 | 362 | |
| 334 | 363 | if (WasInserted) |
| 335 | 364 | replaceSymbol<UndefinedGlobal>(S, Name, Flags, File, Type); |
| ... | ... | @@ -346,7 +375,7 @@ void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) { |
| 346 | 375 | |
| 347 | 376 | Symbol *S; |
| 348 | 377 | bool WasInserted; |
| 349 | std::tie(S, WasInserted) = insert(Name); | |
| 378 | std::tie(S, WasInserted) = insert(Name, nullptr); | |
| 350 | 379 | |
| 351 | 380 | if (WasInserted) { |
| 352 | 381 | replaceSymbol<LazySymbol>(S, Name, File, *Sym); |
deps/lld/wasm/SymbolTable.h+5-6| ... | ... | @@ -13,12 +13,9 @@ |
| 13 | 13 | #include "InputFiles.h" |
| 14 | 14 | #include "LTO.h" |
| 15 | 15 | #include "Symbols.h" |
| 16 | #include "lld/Common/LLVM.h" | |
| 16 | 17 | #include "llvm/ADT/CachedHashString.h" |
| 17 | 18 | #include "llvm/ADT/DenseSet.h" |
| 18 | #include "llvm/Support/raw_ostream.h" | |
| 19 | ||
| 20 | using llvm::wasm::WasmGlobalType; | |
| 21 | using llvm::wasm::WasmSignature; | |
| 22 | 19 | |
| 23 | 20 | namespace lld { |
| 24 | 21 | namespace wasm { |
| ... | ... | @@ -59,6 +56,8 @@ public: |
| 59 | 56 | uint32_t Size); |
| 60 | 57 | Symbol *addDefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, |
| 61 | 58 | InputGlobal *G); |
| 59 | Symbol *addDefinedEvent(StringRef Name, uint32_t Flags, InputFile *File, | |
| 60 | InputEvent *E); | |
| 62 | 61 | |
| 63 | 62 | Symbol *addUndefinedFunction(StringRef Name, uint32_t Flags, InputFile *File, |
| 64 | 63 | const WasmSignature *Signature); |
| ... | ... | @@ -66,7 +65,7 @@ public: |
| 66 | 65 | Symbol *addUndefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, |
| 67 | 66 | const WasmGlobalType *Type); |
| 68 | 67 | |
| 69 | void addLazy(ArchiveFile *F, const Archive::Symbol *Sym); | |
| 68 | void addLazy(ArchiveFile *F, const llvm::object::Archive::Symbol *Sym); | |
| 70 | 69 | |
| 71 | 70 | bool addComdat(StringRef Name); |
| 72 | 71 | |
| ... | ... | @@ -77,7 +76,7 @@ public: |
| 77 | 76 | InputFunction *Function); |
| 78 | 77 | |
| 79 | 78 | private: |
| 80 | std::pair<Symbol *, bool> insert(StringRef Name); | |
| 79 | std::pair<Symbol *, bool> insert(StringRef Name, InputFile *File); | |
| 81 | 80 | |
| 82 | 81 | llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> SymMap; |
| 83 | 82 | std::vector<Symbol *> SymVector; |
deps/lld/wasm/Symbols.cpp+48-4| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | #include "Symbols.h" |
| 11 | 11 | #include "Config.h" |
| 12 | 12 | #include "InputChunks.h" |
| 13 | #include "InputEvent.h" | |
| 13 | 14 | #include "InputFiles.h" |
| 14 | 15 | #include "InputGlobal.h" |
| 15 | 16 | #include "OutputSegment.h" |
| ... | ... | @@ -27,7 +28,9 @@ DefinedFunction *WasmSym::CallCtors; |
| 27 | 28 | DefinedData *WasmSym::DsoHandle; |
| 28 | 29 | DefinedData *WasmSym::DataEnd; |
| 29 | 30 | DefinedData *WasmSym::HeapBase; |
| 30 | DefinedGlobal *WasmSym::StackPointer; | |
| 31 | GlobalSymbol *WasmSym::StackPointer; | |
| 32 | UndefinedGlobal *WasmSym::TableBase; | |
| 33 | UndefinedGlobal *WasmSym::MemoryBase; | |
| 31 | 34 | |
| 32 | 35 | WasmSymbolType Symbol::getWasmType() const { |
| 33 | 36 | if (isa<FunctionSymbol>(this)) |
| ... | ... | @@ -36,6 +39,8 @@ WasmSymbolType Symbol::getWasmType() const { |
| 36 | 39 | return WASM_SYMBOL_TYPE_DATA; |
| 37 | 40 | if (isa<GlobalSymbol>(this)) |
| 38 | 41 | return WASM_SYMBOL_TYPE_GLOBAL; |
| 42 | if (isa<EventSymbol>(this)) | |
| 43 | return WASM_SYMBOL_TYPE_EVENT; | |
| 39 | 44 | if (isa<SectionSymbol>(this)) |
| 40 | 45 | return WASM_SYMBOL_TYPE_SECTION; |
| 41 | 46 | llvm_unreachable("invalid symbol kind"); |
| ... | ... | @@ -52,6 +57,8 @@ InputChunk *Symbol::getChunk() const { |
| 52 | 57 | bool Symbol::isLive() const { |
| 53 | 58 | if (auto *G = dyn_cast<DefinedGlobal>(this)) |
| 54 | 59 | return G->Global->Live; |
| 60 | if (auto *E = dyn_cast<DefinedEvent>(this)) | |
| 61 | return E->Event->Live; | |
| 55 | 62 | if (InputChunk *C = getChunk()) |
| 56 | 63 | return C->Live; |
| 57 | 64 | return Referenced; |
| ... | ... | @@ -60,6 +67,8 @@ bool Symbol::isLive() const { |
| 60 | 67 | void Symbol::markLive() { |
| 61 | 68 | if (auto *G = dyn_cast<DefinedGlobal>(this)) |
| 62 | 69 | G->Global->Live = true; |
| 70 | if (auto *E = dyn_cast<DefinedEvent>(this)) | |
| 71 | E->Event->Live = true; | |
| 63 | 72 | if (InputChunk *C = getChunk()) |
| 64 | 73 | C->Live = true; |
| 65 | 74 | Referenced = true; |
| ... | ... | @@ -105,7 +114,10 @@ bool Symbol::isExported() const { |
| 105 | 114 | if (ForceExport || Config->ExportAll) |
| 106 | 115 | return true; |
| 107 | 116 | |
| 108 | return !isHidden(); | |
| 117 | if (Config->ExportDynamic && !isHidden()) | |
| 118 | return true; | |
| 119 | ||
| 120 | return false; | |
| 109 | 121 | } |
| 110 | 122 | |
| 111 | 123 | uint32_t FunctionSymbol::getFunctionIndex() const { |
| ... | ... | @@ -207,6 +219,32 @@ DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File, |
| 207 | 219 | Global ? &Global->getType() : nullptr), |
| 208 | 220 | Global(Global) {} |
| 209 | 221 | |
| 222 | uint32_t EventSymbol::getEventIndex() const { | |
| 223 | if (auto *F = dyn_cast<DefinedEvent>(this)) | |
| 224 | return F->Event->getEventIndex(); | |
| 225 | assert(EventIndex != INVALID_INDEX); | |
| 226 | return EventIndex; | |
| 227 | } | |
| 228 | ||
| 229 | void EventSymbol::setEventIndex(uint32_t Index) { | |
| 230 | LLVM_DEBUG(dbgs() << "setEventIndex " << Name << " -> " << Index << "\n"); | |
| 231 | assert(EventIndex == INVALID_INDEX); | |
| 232 | EventIndex = Index; | |
| 233 | } | |
| 234 | ||
| 235 | bool EventSymbol::hasEventIndex() const { | |
| 236 | if (auto *F = dyn_cast<DefinedEvent>(this)) | |
| 237 | return F->Event->hasEventIndex(); | |
| 238 | return EventIndex != INVALID_INDEX; | |
| 239 | } | |
| 240 | ||
| 241 | DefinedEvent::DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File, | |
| 242 | InputEvent *Event) | |
| 243 | : EventSymbol(Name, DefinedEventKind, Flags, File, | |
| 244 | Event ? &Event->getType() : nullptr, | |
| 245 | Event ? &Event->Signature : nullptr), | |
| 246 | Event(Event) {} | |
| 247 | ||
| 210 | 248 | uint32_t SectionSymbol::getOutputSectionIndex() const { |
| 211 | 249 | LLVM_DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n"); |
| 212 | 250 | assert(OutputSectionIndex != INVALID_INDEX); |
| ... | ... | @@ -223,10 +261,14 @@ void SectionSymbol::setOutputSectionIndex(uint32_t Index) { |
| 223 | 261 | void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); } |
| 224 | 262 | |
| 225 | 263 | std::string lld::toString(const wasm::Symbol &Sym) { |
| 264 | return lld::maybeDemangleSymbol(Sym.getName()); | |
| 265 | } | |
| 266 | ||
| 267 | std::string lld::maybeDemangleSymbol(StringRef Name) { | |
| 226 | 268 | if (Config->Demangle) |
| 227 | if (Optional<std::string> S = demangleItanium(Sym.getName())) | |
| 269 | if (Optional<std::string> S = demangleItanium(Name)) | |
| 228 | 270 | return *S; |
| 229 | return Sym.getName(); | |
| 271 | return Name; | |
| 230 | 272 | } |
| 231 | 273 | |
| 232 | 274 | std::string lld::toString(wasm::Symbol::Kind Kind) { |
| ... | ... | @@ -237,6 +279,8 @@ std::string lld::toString(wasm::Symbol::Kind Kind) { |
| 237 | 279 | return "DefinedData"; |
| 238 | 280 | case wasm::Symbol::DefinedGlobalKind: |
| 239 | 281 | return "DefinedGlobal"; |
| 282 | case wasm::Symbol::DefinedEventKind: | |
| 283 | return "DefinedEvent"; | |
| 240 | 284 | case wasm::Symbol::UndefinedFunctionKind: |
| 241 | 285 | return "UndefinedFunction"; |
| 242 | 286 | case wasm::Symbol::UndefinedDataKind: |
deps/lld/wasm/Symbols.h+72-21| ... | ... | @@ -15,21 +15,17 @@ |
| 15 | 15 | #include "llvm/Object/Archive.h" |
| 16 | 16 | #include "llvm/Object/Wasm.h" |
| 17 | 17 | |
| 18 | using llvm::object::Archive; | |
| 19 | using llvm::object::WasmSymbol; | |
| 20 | using llvm::wasm::WasmGlobal; | |
| 21 | using llvm::wasm::WasmGlobalType; | |
| 22 | using llvm::wasm::WasmSignature; | |
| 23 | using llvm::wasm::WasmSymbolType; | |
| 24 | ||
| 25 | 18 | namespace lld { |
| 26 | 19 | namespace wasm { |
| 27 | 20 | |
| 21 | using llvm::wasm::WasmSymbolType; | |
| 22 | ||
| 28 | 23 | class InputFile; |
| 29 | 24 | class InputChunk; |
| 30 | 25 | class InputSegment; |
| 31 | 26 | class InputFunction; |
| 32 | 27 | class InputGlobal; |
| 28 | class InputEvent; | |
| 33 | 29 | class InputSection; |
| 34 | 30 | |
| 35 | 31 | #define INVALID_INDEX UINT32_MAX |
| ... | ... | @@ -41,6 +37,7 @@ public: |
| 41 | 37 | DefinedFunctionKind, |
| 42 | 38 | DefinedDataKind, |
| 43 | 39 | DefinedGlobalKind, |
| 40 | DefinedEventKind, | |
| 44 | 41 | SectionKind, |
| 45 | 42 | UndefinedFunctionKind, |
| 46 | 43 | UndefinedDataKind, |
| ... | ... | @@ -52,7 +49,8 @@ public: |
| 52 | 49 | |
| 53 | 50 | bool isDefined() const { |
| 54 | 51 | return SymbolKind == DefinedFunctionKind || SymbolKind == DefinedDataKind || |
| 55 | SymbolKind == DefinedGlobalKind || SymbolKind == SectionKind; | |
| 52 | SymbolKind == DefinedGlobalKind || SymbolKind == DefinedEventKind || | |
| 53 | SymbolKind == SectionKind; | |
| 56 | 54 | } |
| 57 | 55 | |
| 58 | 56 | bool isUndefined() const { |
| ... | ... | @@ -126,12 +124,12 @@ public: |
| 126 | 124 | void setFunctionIndex(uint32_t Index); |
| 127 | 125 | bool hasFunctionIndex() const; |
| 128 | 126 | |
| 129 | const WasmSignature *FunctionType; | |
| 127 | const WasmSignature *Signature; | |
| 130 | 128 | |
| 131 | 129 | protected: |
| 132 | 130 | FunctionSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, |
| 133 | const WasmSignature *Type) | |
| 134 | : Symbol(Name, K, Flags, F), FunctionType(Type) {} | |
| 131 | const WasmSignature *Sig) | |
| 132 | : Symbol(Name, K, Flags, F), Signature(Sig) {} | |
| 135 | 133 | |
| 136 | 134 | uint32_t TableIndex = INVALID_INDEX; |
| 137 | 135 | uint32_t FunctionIndex = INVALID_INDEX; |
| ... | ... | @@ -245,8 +243,6 @@ protected: |
| 245 | 243 | const WasmGlobalType *GlobalType) |
| 246 | 244 | : Symbol(Name, K, Flags, F), GlobalType(GlobalType) {} |
| 247 | 245 | |
| 248 | // Explicit function type, needed for undefined or synthetic functions only. | |
| 249 | // For regular defined globals this information comes from the InputChunk. | |
| 250 | 246 | const WasmGlobalType *GlobalType; |
| 251 | 247 | uint32_t GlobalIndex = INVALID_INDEX; |
| 252 | 248 | }; |
| ... | ... | @@ -274,16 +270,61 @@ public: |
| 274 | 270 | } |
| 275 | 271 | }; |
| 276 | 272 | |
| 273 | // Wasm events are features that suspend the current execution and transfer the | |
| 274 | // control flow to a corresponding handler. Currently the only supported event | |
| 275 | // kind is exceptions. | |
| 276 | // | |
| 277 | // Event tags are values to distinguish different events. For exceptions, they | |
| 278 | // can be used to distinguish different language's exceptions, i.e., all C++ | |
| 279 | // exceptions have the same tag. Wasm can generate code capable of doing | |
| 280 | // different handling actions based on the tag of caught exceptions. | |
| 281 | // | |
| 282 | // A single EventSymbol object represents a single tag. C++ exception event | |
| 283 | // symbol is a weak symbol generated in every object file in which exceptions | |
| 284 | // are used, and has name '__cpp_exception' for linking. | |
| 285 | class EventSymbol : public Symbol { | |
| 286 | public: | |
| 287 | static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; } | |
| 288 | ||
| 289 | const WasmEventType *getEventType() const { return EventType; } | |
| 290 | ||
| 291 | // Get/set the event index | |
| 292 | uint32_t getEventIndex() const; | |
| 293 | void setEventIndex(uint32_t Index); | |
| 294 | bool hasEventIndex() const; | |
| 295 | ||
| 296 | const WasmSignature *Signature; | |
| 297 | ||
| 298 | protected: | |
| 299 | EventSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F, | |
| 300 | const WasmEventType *EventType, const WasmSignature *Sig) | |
| 301 | : Symbol(Name, K, Flags, F), Signature(Sig), EventType(EventType) {} | |
| 302 | ||
| 303 | const WasmEventType *EventType; | |
| 304 | uint32_t EventIndex = INVALID_INDEX; | |
| 305 | }; | |
| 306 | ||
| 307 | class DefinedEvent : public EventSymbol { | |
| 308 | public: | |
| 309 | DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File, | |
| 310 | InputEvent *Event); | |
| 311 | ||
| 312 | static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; } | |
| 313 | ||
| 314 | InputEvent *Event; | |
| 315 | }; | |
| 316 | ||
| 277 | 317 | class LazySymbol : public Symbol { |
| 278 | 318 | public: |
| 279 | LazySymbol(StringRef Name, InputFile *File, const Archive::Symbol &Sym) | |
| 319 | LazySymbol(StringRef Name, InputFile *File, | |
| 320 | const llvm::object::Archive::Symbol &Sym) | |
| 280 | 321 | : Symbol(Name, LazyKind, 0, File), ArchiveSymbol(Sym) {} |
| 281 | 322 | |
| 282 | 323 | static bool classof(const Symbol *S) { return S->kind() == LazyKind; } |
| 283 | 324 | void fetch(); |
| 284 | 325 | |
| 285 | 326 | private: |
| 286 | Archive::Symbol ArchiveSymbol; | |
| 327 | llvm::object::Archive::Symbol ArchiveSymbol; | |
| 287 | 328 | }; |
| 288 | 329 | |
| 289 | 330 | // linker-generated symbols |
| ... | ... | @@ -291,7 +332,7 @@ struct WasmSym { |
| 291 | 332 | // __stack_pointer |
| 292 | 333 | // Global that holds the address of the top of the explicit value stack in |
| 293 | 334 | // linear memory. |
| 294 | static DefinedGlobal *StackPointer; | |
| 335 | static GlobalSymbol *StackPointer; | |
| 295 | 336 | |
| 296 | 337 | // __data_end |
| 297 | 338 | // Symbol marking the end of the data and bss. |
| ... | ... | @@ -310,6 +351,14 @@ struct WasmSym { |
| 310 | 351 | // __dso_handle |
| 311 | 352 | // Symbol used in calls to __cxa_atexit to determine current DLL |
| 312 | 353 | static DefinedData *DsoHandle; |
| 354 | ||
| 355 | // __table_base | |
| 356 | // Used in PIC code for offset of indirect function table | |
| 357 | static UndefinedGlobal *TableBase; | |
| 358 | ||
| 359 | // __memory_base | |
| 360 | // Used in PIC code for offset of global data | |
| 361 | static UndefinedGlobal *MemoryBase; | |
| 313 | 362 | }; |
| 314 | 363 | |
| 315 | 364 | // A buffer class that is large enough to hold any Symbol-derived |
| ... | ... | @@ -319,10 +368,11 @@ union SymbolUnion { |
| 319 | 368 | alignas(DefinedFunction) char A[sizeof(DefinedFunction)]; |
| 320 | 369 | alignas(DefinedData) char B[sizeof(DefinedData)]; |
| 321 | 370 | alignas(DefinedGlobal) char C[sizeof(DefinedGlobal)]; |
| 322 | alignas(LazySymbol) char D[sizeof(LazySymbol)]; | |
| 323 | alignas(UndefinedFunction) char E[sizeof(UndefinedFunction)]; | |
| 324 | alignas(UndefinedData) char F[sizeof(UndefinedData)]; | |
| 325 | alignas(UndefinedGlobal) char G[sizeof(UndefinedGlobal)]; | |
| 371 | alignas(DefinedEvent) char D[sizeof(DefinedEvent)]; | |
| 372 | alignas(LazySymbol) char E[sizeof(LazySymbol)]; | |
| 373 | alignas(UndefinedFunction) char F[sizeof(UndefinedFunction)]; | |
| 374 | alignas(UndefinedData) char G[sizeof(UndefinedData)]; | |
| 375 | alignas(UndefinedGlobal) char H[sizeof(UndefinedGlobal)]; | |
| 326 | 376 | alignas(SectionSymbol) char I[sizeof(SectionSymbol)]; |
| 327 | 377 | }; |
| 328 | 378 | |
| ... | ... | @@ -330,7 +380,7 @@ template <typename T, typename... ArgT> |
| 330 | 380 | T *replaceSymbol(Symbol *S, ArgT &&... Arg) { |
| 331 | 381 | static_assert(std::is_trivially_destructible<T>(), |
| 332 | 382 | "Symbol types must be trivially destructible"); |
| 333 | static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small"); | |
| 383 | static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small"); | |
| 334 | 384 | static_assert(alignof(T) <= alignof(SymbolUnion), |
| 335 | 385 | "SymbolUnion not aligned enough"); |
| 336 | 386 | assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr && |
| ... | ... | @@ -349,6 +399,7 @@ T *replaceSymbol(Symbol *S, ArgT &&... Arg) { |
| 349 | 399 | // Returns a symbol name for an error message. |
| 350 | 400 | std::string toString(const wasm::Symbol &Sym); |
| 351 | 401 | std::string toString(wasm::Symbol::Kind Kind); |
| 402 | std::string maybeDemangleSymbol(StringRef Name); | |
| 352 | 403 | |
| 353 | 404 | } // namespace lld |
| 354 | 405 |
deps/lld/wasm/Writer.cpp+155-35| ... | ... | @@ -10,6 +10,7 @@ |
| 10 | 10 | #include "Writer.h" |
| 11 | 11 | #include "Config.h" |
| 12 | 12 | #include "InputChunks.h" |
| 13 | #include "InputEvent.h" | |
| 13 | 14 | #include "InputGlobal.h" |
| 14 | 15 | #include "OutputSections.h" |
| 15 | 16 | #include "OutputSegment.h" |
| ... | ... | @@ -39,7 +40,6 @@ using namespace lld; |
| 39 | 40 | using namespace lld::wasm; |
| 40 | 41 | |
| 41 | 42 | static constexpr int kStackAlignment = 16; |
| 42 | static constexpr int kInitialTableOffset = 1; | |
| 43 | 43 | static constexpr const char *kFunctionTableName = "__indirect_function_table"; |
| 44 | 44 | |
| 45 | 45 | namespace { |
| ... | ... | @@ -81,6 +81,7 @@ private: |
| 81 | 81 | void createFunctionSection(); |
| 82 | 82 | void createTableSection(); |
| 83 | 83 | void createGlobalSection(); |
| 84 | void createEventSection(); | |
| 84 | 85 | void createExportSection(); |
| 85 | 86 | void createImportSection(); |
| 86 | 87 | void createMemorySection(); |
| ... | ... | @@ -90,6 +91,7 @@ private: |
| 90 | 91 | void createCustomSections(); |
| 91 | 92 | |
| 92 | 93 | // Custom sections |
| 94 | void createDylinkSection(); | |
| 93 | 95 | void createRelocSections(); |
| 94 | 96 | void createLinkingSection(); |
| 95 | 97 | void createNameSection(); |
| ... | ... | @@ -98,18 +100,25 @@ private: |
| 98 | 100 | void writeSections(); |
| 99 | 101 | |
| 100 | 102 | uint64_t FileSize = 0; |
| 103 | uint32_t TableBase = 0; | |
| 101 | 104 | uint32_t NumMemoryPages = 0; |
| 102 | 105 | uint32_t MaxMemoryPages = 0; |
| 106 | // Memory size and aligment. Written to the "dylink" section | |
| 107 | // when build with -shared or -pie. | |
| 108 | uint32_t MemAlign = 0; | |
| 109 | uint32_t MemSize = 0; | |
| 103 | 110 | |
| 104 | 111 | std::vector<const WasmSignature *> Types; |
| 105 | 112 | DenseMap<WasmSignature, int32_t> TypeIndices; |
| 106 | 113 | std::vector<const Symbol *> ImportedSymbols; |
| 107 | 114 | unsigned NumImportedFunctions = 0; |
| 108 | 115 | unsigned NumImportedGlobals = 0; |
| 116 | unsigned NumImportedEvents = 0; | |
| 109 | 117 | std::vector<WasmExport> Exports; |
| 110 | 118 | std::vector<const DefinedData *> DefinedFakeGlobals; |
| 111 | 119 | std::vector<InputGlobal *> InputGlobals; |
| 112 | 120 | std::vector<InputFunction *> InputFunctions; |
| 121 | std::vector<InputEvent *> InputEvents; | |
| 113 | 122 | std::vector<const FunctionSymbol *> IndirectFunctions; |
| 114 | 123 | std::vector<const Symbol *> SymtabEntries; |
| 115 | 124 | std::vector<WasmInitEntry> InitFunctions; |
| ... | ... | @@ -155,17 +164,19 @@ void Writer::createImportSection() { |
| 155 | 164 | Import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX; |
| 156 | 165 | Import.Memory.Maximum = MaxMemoryPages; |
| 157 | 166 | } |
| 167 | if (Config->SharedMemory) | |
| 168 | Import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED; | |
| 158 | 169 | writeImport(OS, Import); |
| 159 | 170 | } |
| 160 | 171 | |
| 161 | 172 | if (Config->ImportTable) { |
| 162 | uint32_t TableSize = kInitialTableOffset + IndirectFunctions.size(); | |
| 173 | uint32_t TableSize = TableBase + IndirectFunctions.size(); | |
| 163 | 174 | WasmImport Import; |
| 164 | 175 | Import.Module = "env"; |
| 165 | 176 | Import.Field = kFunctionTableName; |
| 166 | 177 | Import.Kind = WASM_EXTERNAL_TABLE; |
| 167 | Import.Table.ElemType = WASM_TYPE_ANYFUNC; | |
| 168 | Import.Table.Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize}; | |
| 178 | Import.Table.ElemType = WASM_TYPE_FUNCREF; | |
| 179 | Import.Table.Limits = {0, TableSize, 0}; | |
| 169 | 180 | writeImport(OS, Import); |
| 170 | 181 | } |
| 171 | 182 | |
| ... | ... | @@ -175,11 +186,15 @@ void Writer::createImportSection() { |
| 175 | 186 | Import.Field = Sym->getName(); |
| 176 | 187 | if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) { |
| 177 | 188 | Import.Kind = WASM_EXTERNAL_FUNCTION; |
| 178 | Import.SigIndex = lookupType(*FunctionSym->FunctionType); | |
| 179 | } else { | |
| 180 | auto *GlobalSym = cast<GlobalSymbol>(Sym); | |
| 189 | Import.SigIndex = lookupType(*FunctionSym->Signature); | |
| 190 | } else if (auto *GlobalSym = dyn_cast<GlobalSymbol>(Sym)) { | |
| 181 | 191 | Import.Kind = WASM_EXTERNAL_GLOBAL; |
| 182 | 192 | Import.Global = *GlobalSym->getGlobalType(); |
| 193 | } else { | |
| 194 | auto *EventSym = cast<EventSymbol>(Sym); | |
| 195 | Import.Kind = WASM_EXTERNAL_EVENT; | |
| 196 | Import.Event.Attribute = EventSym->getEventType()->Attribute; | |
| 197 | Import.Event.SigIndex = lookupType(*EventSym->Signature); | |
| 183 | 198 | } |
| 184 | 199 | writeImport(OS, Import); |
| 185 | 200 | } |
| ... | ... | @@ -214,8 +229,12 @@ void Writer::createMemorySection() { |
| 214 | 229 | |
| 215 | 230 | bool HasMax = MaxMemoryPages != 0; |
| 216 | 231 | writeUleb128(OS, 1, "memory count"); |
| 217 | writeUleb128(OS, HasMax ? static_cast<unsigned>(WASM_LIMITS_FLAG_HAS_MAX) : 0, | |
| 218 | "memory limits flags"); | |
| 232 | unsigned Flags = 0; | |
| 233 | if (HasMax) | |
| 234 | Flags |= WASM_LIMITS_FLAG_HAS_MAX; | |
| 235 | if (Config->SharedMemory) | |
| 236 | Flags |= WASM_LIMITS_FLAG_IS_SHARED; | |
| 237 | writeUleb128(OS, Flags, "memory limits flags"); | |
| 219 | 238 | writeUleb128(OS, NumMemoryPages, "initial pages"); |
| 220 | 239 | if (HasMax) |
| 221 | 240 | writeUleb128(OS, MaxMemoryPages, "max pages"); |
| ... | ... | @@ -241,6 +260,31 @@ void Writer::createGlobalSection() { |
| 241 | 260 | } |
| 242 | 261 | } |
| 243 | 262 | |
| 263 | // The event section contains a list of declared wasm events associated with the | |
| 264 | // module. Currently the only supported event kind is exceptions. A single event | |
| 265 | // entry represents a single event with an event tag. All C++ exceptions are | |
| 266 | // represented by a single event. An event entry in this section contains | |
| 267 | // information on what kind of event it is (e.g. exception) and the type of | |
| 268 | // values contained in a single event object. (In wasm, an event can contain | |
| 269 | // multiple values of primitive types. But for C++ exceptions, we just throw a | |
| 270 | // pointer which is an i32 value (for wasm32 architecture), so the signature of | |
| 271 | // C++ exception is (i32)->(void), because all event types are assumed to have | |
| 272 | // void return type to share WasmSignature with functions.) | |
| 273 | void Writer::createEventSection() { | |
| 274 | unsigned NumEvents = InputEvents.size(); | |
| 275 | if (NumEvents == 0) | |
| 276 | return; | |
| 277 | ||
| 278 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_EVENT); | |
| 279 | raw_ostream &OS = Section->getStream(); | |
| 280 | ||
| 281 | writeUleb128(OS, NumEvents, "event count"); | |
| 282 | for (InputEvent *E : InputEvents) { | |
| 283 | E->Event.Type.SigIndex = lookupType(E->Signature); | |
| 284 | writeEvent(OS, E->Event); | |
| 285 | } | |
| 286 | } | |
| 287 | ||
| 244 | 288 | void Writer::createTableSection() { |
| 245 | 289 | if (Config->ImportTable) |
| 246 | 290 | return; |
| ... | ... | @@ -253,14 +297,14 @@ void Writer::createTableSection() { |
| 253 | 297 | // no address-taken function will fail at validation time since it is |
| 254 | 298 | // a validation error to include a call_indirect instruction if there |
| 255 | 299 | // is not table. |
| 256 | uint32_t TableSize = kInitialTableOffset + IndirectFunctions.size(); | |
| 300 | uint32_t TableSize = TableBase + IndirectFunctions.size(); | |
| 257 | 301 | |
| 258 | 302 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_TABLE); |
| 259 | 303 | raw_ostream &OS = Section->getStream(); |
| 260 | 304 | |
| 261 | 305 | writeUleb128(OS, 1, "table count"); |
| 262 | 306 | WasmLimits Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize}; |
| 263 | writeTableType(OS, WasmTable{WASM_TYPE_ANYFUNC, Limits}); | |
| 307 | writeTableType(OS, WasmTable{WASM_TYPE_FUNCREF, Limits}); | |
| 264 | 308 | } |
| 265 | 309 | |
| 266 | 310 | void Writer::createExportSection() { |
| ... | ... | @@ -319,12 +363,17 @@ void Writer::createElemSection() { |
| 319 | 363 | writeUleb128(OS, 1, "segment count"); |
| 320 | 364 | writeUleb128(OS, 0, "table index"); |
| 321 | 365 | WasmInitExpr InitExpr; |
| 322 | InitExpr.Opcode = WASM_OPCODE_I32_CONST; | |
| 323 | InitExpr.Value.Int32 = kInitialTableOffset; | |
| 366 | if (Config->Pic) { | |
| 367 | InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET; | |
| 368 | InitExpr.Value.Global = WasmSym::TableBase->getGlobalIndex(); | |
| 369 | } else { | |
| 370 | InitExpr.Opcode = WASM_OPCODE_I32_CONST; | |
| 371 | InitExpr.Value.Int32 = TableBase; | |
| 372 | } | |
| 324 | 373 | writeInitExpr(OS, InitExpr); |
| 325 | 374 | writeUleb128(OS, IndirectFunctions.size(), "elem count"); |
| 326 | 375 | |
| 327 | uint32_t TableIndex = kInitialTableOffset; | |
| 376 | uint32_t TableIndex = TableBase; | |
| 328 | 377 | for (const FunctionSymbol *Sym : IndirectFunctions) { |
| 329 | 378 | assert(Sym->getTableIndex() == TableIndex); |
| 330 | 379 | writeUleb128(OS, Sym->getFunctionIndex(), "function index"); |
| ... | ... | @@ -419,6 +468,21 @@ public: |
| 419 | 468 | raw_string_ostream OS{Body}; |
| 420 | 469 | }; |
| 421 | 470 | |
| 471 | // Create the custom "dylink" section containing information for the dynamic | |
| 472 | // linker. | |
| 473 | // See | |
| 474 | // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md | |
| 475 | void Writer::createDylinkSection() { | |
| 476 | SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "dylink"); | |
| 477 | raw_ostream &OS = Section->getStream(); | |
| 478 | ||
| 479 | writeUleb128(OS, MemSize, "MemSize"); | |
| 480 | writeUleb128(OS, MemAlign, "MemAlign"); | |
| 481 | writeUleb128(OS, IndirectFunctions.size(), "TableSize"); | |
| 482 | writeUleb128(OS, 0, "TableAlign"); | |
| 483 | writeUleb128(OS, 0, "Needed"); // TODO: Support "needed" shared libraries | |
| 484 | } | |
| 485 | ||
| 422 | 486 | // Create the custom "linking" section containing linker metadata. |
| 423 | 487 | // This is only created when relocatable output is requested. |
| 424 | 488 | void Writer::createLinkingSection() { |
| ... | ... | @@ -448,6 +512,10 @@ void Writer::createLinkingSection() { |
| 448 | 512 | writeUleb128(Sub.OS, G->getGlobalIndex(), "index"); |
| 449 | 513 | if (Sym->isDefined()) |
| 450 | 514 | writeStr(Sub.OS, Sym->getName(), "sym name"); |
| 515 | } else if (auto *E = dyn_cast<EventSymbol>(Sym)) { | |
| 516 | writeUleb128(Sub.OS, E->getEventIndex(), "index"); | |
| 517 | if (Sym->isDefined()) | |
| 518 | writeStr(Sub.OS, Sym->getName(), "sym name"); | |
| 451 | 519 | } else if (isa<DataSymbol>(Sym)) { |
| 452 | 520 | writeStr(Sub.OS, Sym->getName(), "sym name"); |
| 453 | 521 | if (auto *DataSym = dyn_cast<DefinedData>(Sym)) { |
| ... | ... | @@ -548,8 +616,7 @@ void Writer::createNameSection() { |
| 548 | 616 | for (const Symbol *S : ImportedSymbols) { |
| 549 | 617 | if (auto *F = dyn_cast<FunctionSymbol>(S)) { |
| 550 | 618 | writeUleb128(Sub.OS, F->getFunctionIndex(), "func index"); |
| 551 | Optional<std::string> Name = demangleItanium(F->getName()); | |
| 552 | writeStr(Sub.OS, Name ? StringRef(*Name) : F->getName(), "symbol name"); | |
| 619 | writeStr(Sub.OS, toString(*S), "symbol name"); | |
| 553 | 620 | } |
| 554 | 621 | } |
| 555 | 622 | for (const InputFunction *F : InputFunctions) { |
| ... | ... | @@ -558,8 +625,7 @@ void Writer::createNameSection() { |
| 558 | 625 | if (!F->getDebugName().empty()) { |
| 559 | 626 | writeStr(Sub.OS, F->getDebugName(), "symbol name"); |
| 560 | 627 | } else { |
| 561 | Optional<std::string> Name = demangleItanium(F->getName()); | |
| 562 | writeStr(Sub.OS, Name ? StringRef(*Name) : F->getName(), "symbol name"); | |
| 628 | writeStr(Sub.OS, maybeDemangleSymbol(F->getName()), "symbol name"); | |
| 563 | 629 | } |
| 564 | 630 | } |
| 565 | 631 | } |
| ... | ... | @@ -586,16 +652,16 @@ void Writer::writeSections() { |
| 586 | 652 | // - heap start / unallocated |
| 587 | 653 | // |
| 588 | 654 | // The --stack-first option means that stack is placed before any static data. |
| 589 | // This can be useful since it means that stack overflow traps immediately rather | |
| 590 | // than overwriting global data, but also increases code size since all static | |
| 591 | // data loads and stores requires larger offsets. | |
| 655 | // This can be useful since it means that stack overflow traps immediately | |
| 656 | // rather than overwriting global data, but also increases code size since all | |
| 657 | // static data loads and stores requires larger offsets. | |
| 592 | 658 | void Writer::layoutMemory() { |
| 593 | 659 | createOutputSegments(); |
| 594 | 660 | |
| 595 | 661 | uint32_t MemoryPtr = 0; |
| 596 | 662 | |
| 597 | 663 | auto PlaceStack = [&]() { |
| 598 | if (Config->Relocatable) | |
| 664 | if (Config->Relocatable || Config->Shared) | |
| 599 | 665 | return; |
| 600 | 666 | MemoryPtr = alignTo(MemoryPtr, kStackAlignment); |
| 601 | 667 | if (Config->ZStackSize != alignTo(Config->ZStackSize, kStackAlignment)) |
| ... | ... | @@ -603,7 +669,8 @@ void Writer::layoutMemory() { |
| 603 | 669 | log("mem: stack size = " + Twine(Config->ZStackSize)); |
| 604 | 670 | log("mem: stack base = " + Twine(MemoryPtr)); |
| 605 | 671 | MemoryPtr += Config->ZStackSize; |
| 606 | WasmSym::StackPointer->Global->Global.InitExpr.Value.Int32 = MemoryPtr; | |
| 672 | auto *SP = cast<DefinedGlobal>(WasmSym::StackPointer); | |
| 673 | SP->Global->Global.InitExpr.Value.Int32 = MemoryPtr; | |
| 607 | 674 | log("mem: stack top = " + Twine(MemoryPtr)); |
| 608 | 675 | }; |
| 609 | 676 | |
| ... | ... | @@ -621,8 +688,10 @@ void Writer::layoutMemory() { |
| 621 | 688 | if (WasmSym::DsoHandle) |
| 622 | 689 | WasmSym::DsoHandle->setVirtualAddress(DataStart); |
| 623 | 690 | |
| 691 | MemAlign = 0; | |
| 624 | 692 | for (OutputSegment *Seg : Segments) { |
| 625 | MemoryPtr = alignTo(MemoryPtr, Seg->Alignment); | |
| 693 | MemAlign = std::max(MemAlign, Seg->Alignment); | |
| 694 | MemoryPtr = alignTo(MemoryPtr, 1 << Seg->Alignment); | |
| 626 | 695 | Seg->StartVA = MemoryPtr; |
| 627 | 696 | log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", Seg->Name, |
| 628 | 697 | MemoryPtr, Seg->Size, Seg->Alignment)); |
| ... | ... | @@ -635,6 +704,11 @@ void Writer::layoutMemory() { |
| 635 | 704 | |
| 636 | 705 | log("mem: static data = " + Twine(MemoryPtr - DataStart)); |
| 637 | 706 | |
| 707 | if (Config->Shared) { | |
| 708 | MemSize = MemoryPtr; | |
| 709 | return; | |
| 710 | } | |
| 711 | ||
| 638 | 712 | if (!Config->StackFirst) |
| 639 | 713 | PlaceStack(); |
| 640 | 714 | |
| ... | ... | @@ -654,8 +728,8 @@ void Writer::layoutMemory() { |
| 654 | 728 | else |
| 655 | 729 | MemoryPtr = Config->InitialMemory; |
| 656 | 730 | } |
| 657 | uint32_t MemSize = alignTo(MemoryPtr, WasmPageSize); | |
| 658 | NumMemoryPages = MemSize / WasmPageSize; | |
| 731 | MemSize = MemoryPtr; | |
| 732 | NumMemoryPages = alignTo(MemoryPtr, WasmPageSize) / WasmPageSize; | |
| 659 | 733 | log("mem: total pages = " + Twine(NumMemoryPages)); |
| 660 | 734 | |
| 661 | 735 | if (Config->MaxMemory != 0) { |
| ... | ... | @@ -678,12 +752,15 @@ SyntheticSection *Writer::createSyntheticSection(uint32_t Type, |
| 678 | 752 | |
| 679 | 753 | void Writer::createSections() { |
| 680 | 754 | // Known sections |
| 755 | if (Config->Pic) | |
| 756 | createDylinkSection(); | |
| 681 | 757 | createTypeSection(); |
| 682 | 758 | createImportSection(); |
| 683 | 759 | createFunctionSection(); |
| 684 | 760 | createTableSection(); |
| 685 | 761 | createMemorySection(); |
| 686 | 762 | createGlobalSection(); |
| 763 | createEventSection(); | |
| 687 | 764 | createExportSection(); |
| 688 | 765 | createElemSection(); |
| 689 | 766 | createCodeSection(); |
| ... | ... | @@ -722,8 +799,10 @@ void Writer::calculateImports() { |
| 722 | 799 | ImportedSymbols.emplace_back(Sym); |
| 723 | 800 | if (auto *F = dyn_cast<FunctionSymbol>(Sym)) |
| 724 | 801 | F->setFunctionIndex(NumImportedFunctions++); |
| 802 | else if (auto *G = dyn_cast<GlobalSymbol>(Sym)) | |
| 803 | G->setGlobalIndex(NumImportedGlobals++); | |
| 725 | 804 | else |
| 726 | cast<GlobalSymbol>(Sym)->setGlobalIndex(NumImportedGlobals++); | |
| 805 | cast<EventSymbol>(Sym)->setEventIndex(NumImportedEvents++); | |
| 727 | 806 | } |
| 728 | 807 | } |
| 729 | 808 | |
| ... | ... | @@ -759,6 +838,8 @@ void Writer::calculateExports() { |
| 759 | 838 | continue; |
| 760 | 839 | } |
| 761 | 840 | Export = {Name, WASM_EXTERNAL_GLOBAL, G->getGlobalIndex()}; |
| 841 | } else if (auto *E = dyn_cast<DefinedEvent>(Sym)) { | |
| 842 | Export = {Name, WASM_EXTERNAL_EVENT, E->getEventIndex()}; | |
| 762 | 843 | } else { |
| 763 | 844 | auto *D = cast<DefinedData>(Sym); |
| 764 | 845 | DefinedFakeGlobals.emplace_back(D); |
| ... | ... | @@ -836,6 +917,8 @@ void Writer::calculateTypes() { |
| 836 | 917 | // 1. Any signature used in the TYPE relocation |
| 837 | 918 | // 2. The signatures of all imported functions |
| 838 | 919 | // 3. The signatures of all defined functions |
| 920 | // 4. The signatures of all imported events | |
| 921 | // 5. The signatures of all defined events | |
| 839 | 922 | |
| 840 | 923 | for (ObjFile *File : Symtab->ObjectFiles) { |
| 841 | 924 | ArrayRef<WasmSignature> Types = File->getWasmObj()->types(); |
| ... | ... | @@ -844,16 +927,23 @@ void Writer::calculateTypes() { |
| 844 | 927 | File->TypeMap[I] = registerType(Types[I]); |
| 845 | 928 | } |
| 846 | 929 | |
| 847 | for (const Symbol *Sym : ImportedSymbols) | |
| 930 | for (const Symbol *Sym : ImportedSymbols) { | |
| 848 | 931 | if (auto *F = dyn_cast<FunctionSymbol>(Sym)) |
| 849 | registerType(*F->FunctionType); | |
| 932 | registerType(*F->Signature); | |
| 933 | else if (auto *E = dyn_cast<EventSymbol>(Sym)) | |
| 934 | registerType(*E->Signature); | |
| 935 | } | |
| 850 | 936 | |
| 851 | 937 | for (const InputFunction *F : InputFunctions) |
| 852 | 938 | registerType(F->Signature); |
| 939 | ||
| 940 | for (const InputEvent *E : InputEvents) | |
| 941 | registerType(E->Signature); | |
| 853 | 942 | } |
| 854 | 943 | |
| 855 | 944 | void Writer::assignIndexes() { |
| 856 | uint32_t FunctionIndex = NumImportedFunctions + InputFunctions.size(); | |
| 945 | assert(InputFunctions.empty()); | |
| 946 | uint32_t FunctionIndex = NumImportedFunctions; | |
| 857 | 947 | auto AddDefinedFunction = [&](InputFunction *Func) { |
| 858 | 948 | if (!Func->Live) |
| 859 | 949 | return; |
| ... | ... | @@ -870,7 +960,7 @@ void Writer::assignIndexes() { |
| 870 | 960 | AddDefinedFunction(Func); |
| 871 | 961 | } |
| 872 | 962 | |
| 873 | uint32_t TableIndex = kInitialTableOffset; | |
| 963 | uint32_t TableIndex = TableBase; | |
| 874 | 964 | auto HandleRelocs = [&](InputChunk *Chunk) { |
| 875 | 965 | if (!Chunk->Live) |
| 876 | 966 | return; |
| ... | ... | @@ -902,7 +992,8 @@ void Writer::assignIndexes() { |
| 902 | 992 | HandleRelocs(P); |
| 903 | 993 | } |
| 904 | 994 | |
| 905 | uint32_t GlobalIndex = NumImportedGlobals + InputGlobals.size(); | |
| 995 | assert(InputGlobals.empty()); | |
| 996 | uint32_t GlobalIndex = NumImportedGlobals; | |
| 906 | 997 | auto AddDefinedGlobal = [&](InputGlobal *Global) { |
| 907 | 998 | if (Global->Live) { |
| 908 | 999 | LLVM_DEBUG(dbgs() << "AddDefinedGlobal: " << GlobalIndex << "\n"); |
| ... | ... | @@ -919,9 +1010,29 @@ void Writer::assignIndexes() { |
| 919 | 1010 | for (InputGlobal *Global : File->Globals) |
| 920 | 1011 | AddDefinedGlobal(Global); |
| 921 | 1012 | } |
| 1013 | ||
| 1014 | assert(InputEvents.empty()); | |
| 1015 | uint32_t EventIndex = NumImportedEvents; | |
| 1016 | auto AddDefinedEvent = [&](InputEvent *Event) { | |
| 1017 | if (Event->Live) { | |
| 1018 | LLVM_DEBUG(dbgs() << "AddDefinedEvent: " << EventIndex << "\n"); | |
| 1019 | Event->setEventIndex(EventIndex++); | |
| 1020 | InputEvents.push_back(Event); | |
| 1021 | } | |
| 1022 | }; | |
| 1023 | ||
| 1024 | for (ObjFile *File : Symtab->ObjectFiles) { | |
| 1025 | LLVM_DEBUG(dbgs() << "Events: " << File->getName() << "\n"); | |
| 1026 | for (InputEvent *Event : File->Events) | |
| 1027 | AddDefinedEvent(Event); | |
| 1028 | } | |
| 922 | 1029 | } |
| 923 | 1030 | |
| 924 | 1031 | static StringRef getOutputDataSegmentName(StringRef Name) { |
| 1032 | // With PIC code we currently only support a single data segment since | |
| 1033 | // we only have a single __memory_base to use as our base address. | |
| 1034 | if (Config->Pic) | |
| 1035 | return "data"; | |
| 925 | 1036 | if (!Config->MergeDataSegments) |
| 926 | 1037 | return Name; |
| 927 | 1038 | if (Name.startswith(".text.")) |
| ... | ... | @@ -930,6 +1041,8 @@ static StringRef getOutputDataSegmentName(StringRef Name) { |
| 930 | 1041 | return ".data"; |
| 931 | 1042 | if (Name.startswith(".bss.")) |
| 932 | 1043 | return ".bss"; |
| 1044 | if (Name.startswith(".rodata.")) | |
| 1045 | return ".rodata"; | |
| 933 | 1046 | return Name; |
| 934 | 1047 | } |
| 935 | 1048 | |
| ... | ... | @@ -977,7 +1090,7 @@ void Writer::createCtorFunction() { |
| 977 | 1090 | OS << BodyContent; |
| 978 | 1091 | } |
| 979 | 1092 | |
| 980 | ArrayRef<uint8_t> Body = toArrayRef(Saver.save(FunctionBody)); | |
| 1093 | ArrayRef<uint8_t> Body = arrayRefFromStringRef(Saver.save(FunctionBody)); | |
| 981 | 1094 | cast<SyntheticFunction>(WasmSym::CallCtors->Function)->setBody(Body); |
| 982 | 1095 | } |
| 983 | 1096 | |
| ... | ... | @@ -989,7 +1102,7 @@ void Writer::calculateInitFunctions() { |
| 989 | 1102 | const WasmLinkingData &L = File->getWasmObj()->linkingData(); |
| 990 | 1103 | for (const WasmInitFunc &F : L.InitFunctions) { |
| 991 | 1104 | FunctionSymbol *Sym = File->getFunctionSymbol(F.Symbol); |
| 992 | if (*Sym->FunctionType != WasmSignature{{}, WASM_TYPE_NORESULT}) | |
| 1105 | if (*Sym->Signature != WasmSignature{{}, {}}) | |
| 993 | 1106 | error("invalid signature for init func: " + toString(*Sym)); |
| 994 | 1107 | InitFunctions.emplace_back(WasmInitEntry{Sym, F.Priority}); |
| 995 | 1108 | } |
| ... | ... | @@ -1004,9 +1117,14 @@ void Writer::calculateInitFunctions() { |
| 1004 | 1117 | } |
| 1005 | 1118 | |
| 1006 | 1119 | void Writer::run() { |
| 1007 | if (Config->Relocatable) | |
| 1120 | if (Config->Relocatable || Config->Pic) | |
| 1008 | 1121 | Config->GlobalBase = 0; |
| 1009 | 1122 | |
| 1123 | // For PIC code the table base is assigned dynamically by the loader. | |
| 1124 | // For non-PIC, we start at 1 so that accessing table index 0 always traps. | |
| 1125 | if (!Config->Pic) | |
| 1126 | TableBase = 1; | |
| 1127 | ||
| 1010 | 1128 | log("-- calculateImports"); |
| 1011 | 1129 | calculateImports(); |
| 1012 | 1130 | log("-- assignIndexes"); |
| ... | ... | @@ -1029,8 +1147,10 @@ void Writer::run() { |
| 1029 | 1147 | if (errorHandler().Verbose) { |
| 1030 | 1148 | log("Defined Functions: " + Twine(InputFunctions.size())); |
| 1031 | 1149 | log("Defined Globals : " + Twine(InputGlobals.size())); |
| 1150 | log("Defined Events : " + Twine(InputEvents.size())); | |
| 1032 | 1151 | log("Function Imports : " + Twine(NumImportedFunctions)); |
| 1033 | 1152 | log("Global Imports : " + Twine(NumImportedGlobals)); |
| 1153 | log("Event Imports : " + Twine(NumImportedEvents)); | |
| 1034 | 1154 | for (ObjFile *File : Symtab->ObjectFiles) |
| 1035 | 1155 | File->dumpInfo(); |
| 1036 | 1156 | } |
deps/lld/wasm/WriterUtils.cpp+43-39| ... | ... | @@ -17,22 +17,6 @@ |
| 17 | 17 | |
| 18 | 18 | using namespace llvm; |
| 19 | 19 | using namespace llvm::wasm; |
| 20 | using namespace lld::wasm; | |
| 21 | ||
| 22 | static const char *valueTypeToString(uint8_t Type) { | |
| 23 | switch (Type) { | |
| 24 | case WASM_TYPE_I32: | |
| 25 | return "i32"; | |
| 26 | case WASM_TYPE_I64: | |
| 27 | return "i64"; | |
| 28 | case WASM_TYPE_F32: | |
| 29 | return "f32"; | |
| 30 | case WASM_TYPE_F64: | |
| 31 | return "f64"; | |
| 32 | default: | |
| 33 | llvm_unreachable("invalid value type"); | |
| 34 | } | |
| 35 | } | |
| 36 | 20 | |
| 37 | 21 | namespace lld { |
| 38 | 22 | |
| ... | ... | @@ -73,21 +57,20 @@ void wasm::writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg) { |
| 73 | 57 | support::endian::write(OS, Number, support::little); |
| 74 | 58 | } |
| 75 | 59 | |
| 76 | void wasm::writeValueType(raw_ostream &OS, uint8_t Type, const Twine &Msg) { | |
| 77 | writeU8(OS, Type, Msg + "[type: " + valueTypeToString(Type) + "]"); | |
| 60 | void wasm::writeValueType(raw_ostream &OS, ValType Type, const Twine &Msg) { | |
| 61 | writeU8(OS, static_cast<uint8_t>(Type), | |
| 62 | Msg + "[type: " + toString(Type) + "]"); | |
| 78 | 63 | } |
| 79 | 64 | |
| 80 | 65 | void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) { |
| 81 | 66 | writeU8(OS, WASM_TYPE_FUNC, "signature type"); |
| 82 | writeUleb128(OS, Sig.ParamTypes.size(), "param Count"); | |
| 83 | for (uint8_t ParamType : Sig.ParamTypes) { | |
| 67 | writeUleb128(OS, Sig.Params.size(), "param Count"); | |
| 68 | for (ValType ParamType : Sig.Params) { | |
| 84 | 69 | writeValueType(OS, ParamType, "param type"); |
| 85 | 70 | } |
| 86 | if (Sig.ReturnType == WASM_TYPE_NORESULT) { | |
| 87 | writeUleb128(OS, 0, "result Count"); | |
| 88 | } else { | |
| 89 | writeUleb128(OS, 1, "result Count"); | |
| 90 | writeValueType(OS, Sig.ReturnType, "result type"); | |
| 71 | writeUleb128(OS, Sig.Returns.size(), "result Count"); | |
| 72 | if (Sig.Returns.size()) { | |
| 73 | writeValueType(OS, Sig.Returns[0], "result type"); | |
| 91 | 74 | } |
| 92 | 75 | } |
| 93 | 76 | |
| ... | ... | @@ -100,7 +83,7 @@ void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) { |
| 100 | 83 | case WASM_OPCODE_I64_CONST: |
| 101 | 84 | writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)"); |
| 102 | 85 | break; |
| 103 | case WASM_OPCODE_GET_GLOBAL: | |
| 86 | case WASM_OPCODE_GLOBAL_GET: | |
| 104 | 87 | writeUleb128(OS, InitExpr.Value.Global, "literal (global index)"); |
| 105 | 88 | break; |
| 106 | 89 | default: |
| ... | ... | @@ -117,7 +100,8 @@ void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) { |
| 117 | 100 | } |
| 118 | 101 | |
| 119 | 102 | void wasm::writeGlobalType(raw_ostream &OS, const WasmGlobalType &Type) { |
| 120 | writeValueType(OS, Type.Type, "global type"); | |
| 103 | // TODO: Update WasmGlobalType to use ValType and remove this cast. | |
| 104 | writeValueType(OS, ValType(Type.Type), "global type"); | |
| 121 | 105 | writeU8(OS, Type.Mutable, "global mutable"); |
| 122 | 106 | } |
| 123 | 107 | |
| ... | ... | @@ -126,8 +110,17 @@ void wasm::writeGlobal(raw_ostream &OS, const WasmGlobal &Global) { |
| 126 | 110 | writeInitExpr(OS, Global.InitExpr); |
| 127 | 111 | } |
| 128 | 112 | |
| 113 | void wasm::writeEventType(raw_ostream &OS, const WasmEventType &Type) { | |
| 114 | writeUleb128(OS, Type.Attribute, "event attribute"); | |
| 115 | writeUleb128(OS, Type.SigIndex, "sig index"); | |
| 116 | } | |
| 117 | ||
| 118 | void wasm::writeEvent(raw_ostream &OS, const WasmEvent &Event) { | |
| 119 | writeEventType(OS, Event.Type); | |
| 120 | } | |
| 121 | ||
| 129 | 122 | void wasm::writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type) { |
| 130 | writeU8(OS, WASM_TYPE_ANYFUNC, "table type"); | |
| 123 | writeU8(OS, WASM_TYPE_FUNCREF, "table type"); | |
| 131 | 124 | writeLimits(OS, Type.Limits); |
| 132 | 125 | } |
| 133 | 126 | |
| ... | ... | @@ -142,6 +135,9 @@ void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) { |
| 142 | 135 | case WASM_EXTERNAL_GLOBAL: |
| 143 | 136 | writeGlobalType(OS, Import.Global); |
| 144 | 137 | break; |
| 138 | case WASM_EXTERNAL_EVENT: | |
| 139 | writeEventType(OS, Import.Event); | |
| 140 | break; | |
| 145 | 141 | case WASM_EXTERNAL_MEMORY: |
| 146 | 142 | writeLimits(OS, Import.Memory); |
| 147 | 143 | break; |
| ... | ... | @@ -178,13 +174,15 @@ void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) { |
| 178 | 174 | std::string lld::toString(ValType Type) { |
| 179 | 175 | switch (Type) { |
| 180 | 176 | case ValType::I32: |
| 181 | return "I32"; | |
| 177 | return "i32"; | |
| 182 | 178 | case ValType::I64: |
| 183 | return "I64"; | |
| 179 | return "i64"; | |
| 184 | 180 | case ValType::F32: |
| 185 | return "F32"; | |
| 181 | return "f32"; | |
| 186 | 182 | case ValType::F64: |
| 187 | return "F64"; | |
| 183 | return "f64"; | |
| 184 | case ValType::V128: | |
| 185 | return "v128"; | |
| 188 | 186 | case ValType::EXCEPT_REF: |
| 189 | 187 | return "except_ref"; |
| 190 | 188 | } |
| ... | ... | @@ -193,20 +191,26 @@ std::string lld::toString(ValType Type) { |
| 193 | 191 | |
| 194 | 192 | std::string lld::toString(const WasmSignature &Sig) { |
| 195 | 193 | SmallString<128> S("("); |
| 196 | for (uint32_t Type : Sig.ParamTypes) { | |
| 194 | for (ValType Type : Sig.Params) { | |
| 197 | 195 | if (S.size() != 1) |
| 198 | 196 | S += ", "; |
| 199 | S += toString(static_cast<ValType>(Type)); | |
| 197 | S += toString(Type); | |
| 200 | 198 | } |
| 201 | 199 | S += ") -> "; |
| 202 | if (Sig.ReturnType == WASM_TYPE_NORESULT) | |
| 200 | if (Sig.Returns.size() == 0) | |
| 203 | 201 | S += "void"; |
| 204 | 202 | else |
| 205 | S += toString(static_cast<ValType>(Sig.ReturnType)); | |
| 203 | S += toString(Sig.Returns[0]); | |
| 206 | 204 | return S.str(); |
| 207 | 205 | } |
| 208 | 206 | |
| 209 | std::string lld::toString(const WasmGlobalType &Sig) { | |
| 210 | return (Sig.Mutable ? "var " : "const ") + | |
| 211 | toString(static_cast<ValType>(Sig.Type)); | |
| 207 | std::string lld::toString(const WasmGlobalType &Type) { | |
| 208 | return (Type.Mutable ? "var " : "const ") + | |
| 209 | toString(static_cast<ValType>(Type.Type)); | |
| 210 | } | |
| 211 | ||
| 212 | std::string lld::toString(const WasmEventType &Type) { | |
| 213 | if (Type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION) | |
| 214 | return "exception"; | |
| 215 | return "unknown"; | |
| 212 | 216 | } |
deps/lld/wasm/WriterUtils.h+8-5| ... | ... | @@ -13,9 +13,6 @@ |
| 13 | 13 | #include "lld/Common/LLVM.h" |
| 14 | 14 | #include "llvm/ADT/Twine.h" |
| 15 | 15 | #include "llvm/Object/Wasm.h" |
| 16 | #include "llvm/Support/raw_ostream.h" | |
| 17 | ||
| 18 | using llvm::raw_ostream; | |
| 19 | 16 | |
| 20 | 17 | namespace lld { |
| 21 | 18 | namespace wasm { |
| ... | ... | @@ -35,7 +32,8 @@ void writeU8(raw_ostream &OS, uint8_t byte, const Twine &Msg); |
| 35 | 32 | |
| 36 | 33 | void writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg); |
| 37 | 34 | |
| 38 | void writeValueType(raw_ostream &OS, uint8_t Type, const Twine &Msg); | |
| 35 | void writeValueType(raw_ostream &OS, llvm::wasm::ValType Type, | |
| 36 | const Twine &Msg); | |
| 39 | 37 | |
| 40 | 38 | void writeSig(raw_ostream &OS, const llvm::wasm::WasmSignature &Sig); |
| 41 | 39 | |
| ... | ... | @@ -47,6 +45,10 @@ void writeGlobalType(raw_ostream &OS, const llvm::wasm::WasmGlobalType &Type); |
| 47 | 45 | |
| 48 | 46 | void writeGlobal(raw_ostream &OS, const llvm::wasm::WasmGlobal &Global); |
| 49 | 47 | |
| 48 | void writeEventType(raw_ostream &OS, const llvm::wasm::WasmEventType &Type); | |
| 49 | ||
| 50 | void writeEvent(raw_ostream &OS, const llvm::wasm::WasmEvent &Event); | |
| 51 | ||
| 50 | 52 | void writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type); |
| 51 | 53 | |
| 52 | 54 | void writeImport(raw_ostream &OS, const llvm::wasm::WasmImport &Import); |
| ... | ... | @@ -57,7 +59,8 @@ void writeExport(raw_ostream &OS, const llvm::wasm::WasmExport &Export); |
| 57 | 59 | |
| 58 | 60 | std::string toString(llvm::wasm::ValType Type); |
| 59 | 61 | std::string toString(const llvm::wasm::WasmSignature &Sig); |
| 60 | std::string toString(const llvm::wasm::WasmGlobalType &Sig); | |
| 62 | std::string toString(const llvm::wasm::WasmGlobalType &Type); | |
| 63 | std::string toString(const llvm::wasm::WasmEventType &Type); | |
| 61 | 64 | |
| 62 | 65 | } // namespace lld |
| 63 | 66 |