authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-03 12:43:55-04:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2019-08-03 12:56:35-04:00
logffab950e0cce8b1be2755e070d0684d817138f15
tree67b9e76445bdb6294d2a3c8c848635098737a47e
parent63ebd9d12e48765514777418e12f55576ff63509
signature Commit is signed but in an unrecognized format.

update embedded LLD to 9.0.0rc1


1556 files changed, 49295 insertions(+), 31778 deletions(-)

CMakeLists.txt+4-1
...@@ -88,6 +88,7 @@ else()...@@ -88,6 +88,7 @@ else()
88 set(EMBEDDED_LLD_LIB_SOURCES88 set(EMBEDDED_LLD_LIB_SOURCES
89 "${CMAKE_SOURCE_DIR}/deps/lld/Common/Args.cpp"89 "${CMAKE_SOURCE_DIR}/deps/lld/Common/Args.cpp"
90 "${CMAKE_SOURCE_DIR}/deps/lld/Common/ErrorHandler.cpp"90 "${CMAKE_SOURCE_DIR}/deps/lld/Common/ErrorHandler.cpp"
91 "${CMAKE_SOURCE_DIR}/deps/lld/Common/Filesystem.cpp"
91 "${CMAKE_SOURCE_DIR}/deps/lld/Common/Memory.cpp"92 "${CMAKE_SOURCE_DIR}/deps/lld/Common/Memory.cpp"
92 "${CMAKE_SOURCE_DIR}/deps/lld/Common/Reproduce.cpp"93 "${CMAKE_SOURCE_DIR}/deps/lld/Common/Reproduce.cpp"
93 "${CMAKE_SOURCE_DIR}/deps/lld/Common/Strings.cpp"94 "${CMAKE_SOURCE_DIR}/deps/lld/Common/Strings.cpp"
...@@ -148,7 +149,6 @@ else()...@@ -148,7 +149,6 @@ else()
148 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Driver.cpp"149 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Driver.cpp"
149 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/DriverUtils.cpp"150 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/DriverUtils.cpp"
150 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/EhFrame.cpp"151 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/EhFrame.cpp"
151 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/Filesystem.cpp"
152 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/ICF.cpp"152 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/ICF.cpp"
153 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputFiles.cpp"153 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputFiles.cpp"
154 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputSection.cpp"154 "${CMAKE_SOURCE_DIR}/deps/lld/ELF/InputSection.cpp"
...@@ -171,6 +171,7 @@ else()...@@ -171,6 +171,7 @@ else()
171 set(EMBEDDED_LLD_COFF_SOURCES171 set(EMBEDDED_LLD_COFF_SOURCES
172 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Chunks.cpp"172 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Chunks.cpp"
173 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/DLL.cpp"173 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/DLL.cpp"
174 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/DebugTypes.cpp"
174 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Driver.cpp"175 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/Driver.cpp"
175 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/DriverUtils.cpp"176 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/DriverUtils.cpp"
176 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/ICF.cpp"177 "${CMAKE_SOURCE_DIR}/deps/lld/COFF/ICF.cpp"
...@@ -194,8 +195,10 @@ else()...@@ -194,8 +195,10 @@ else()
194 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/LTO.cpp"195 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/LTO.cpp"
195 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/MarkLive.cpp"196 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/MarkLive.cpp"
196 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/OutputSections.cpp"197 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/OutputSections.cpp"
198 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/Relocations.cpp"
197 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/SymbolTable.cpp"199 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/SymbolTable.cpp"
198 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/Symbols.cpp"200 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/Symbols.cpp"
201 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/SyntheticSections.cpp"
199 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/Writer.cpp"202 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/Writer.cpp"
200 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/WriterUtils.cpp"203 "${CMAKE_SOURCE_DIR}/deps/lld/wasm/WriterUtils.cpp"
201 )204 )
deps/lld-prebuilt/COFF/Options.inc+41-10
...@@ -13,9 +13,8 @@...@@ -13,9 +13,8 @@
13#define COMMA ,13#define COMMA ,
14PREFIX(prefix_0, {nullptr})14PREFIX(prefix_0, {nullptr})
15PREFIX(prefix_2, {"--" COMMA nullptr})15PREFIX(prefix_2, {"--" COMMA nullptr})
16PREFIX(prefix_3, {"/" COMMA "-" COMMA nullptr})16PREFIX(prefix_1, {"/" COMMA "-" COMMA "/?" COMMA "-?" COMMA nullptr})
17PREFIX(prefix_1, {"/" COMMA "-" COMMA "-?" COMMA nullptr})17PREFIX(prefix_3, {"/??" COMMA "-??" COMMA "/?" COMMA "-?" COMMA nullptr})
18PREFIX(prefix_4, {"/?" COMMA "-?" COMMA nullptr})
19#undef COMMA18#undef COMMA
20#endif // PREFIX19#endif // PREFIX
2120
...@@ -61,13 +60,17 @@ OPTION(prefix_1, "debugtype:", debugtype, Joined, INVALID, INVALID, nullptr, 0,...@@ -61,13 +60,17 @@ OPTION(prefix_1, "debugtype:", debugtype, Joined, INVALID, INVALID, nullptr, 0,
61 "Debug Info Options", nullptr, nullptr)60 "Debug Info Options", nullptr, nullptr)
62OPTION(prefix_1, "debug", debug, Flag, INVALID, INVALID, nullptr, 0, 0,61OPTION(prefix_1, "debug", debug, Flag, INVALID, INVALID, nullptr, 0, 0,
63 "Embed a symbol table in the image", nullptr, nullptr)62 "Embed a symbol table in the image", nullptr, nullptr)
64OPTION(prefix_3, "def:", deffile, Joined, INVALID, INVALID, nullptr, 0, 0,63OPTION(prefix_1, "def:", deffile, Joined, INVALID, INVALID, nullptr, 0, 0,
65 "Use module-definition file", nullptr, nullptr)64 "Use module-definition file", nullptr, nullptr)
66OPTION(prefix_1, "defaultlib:", defaultlib, Joined, INVALID, INVALID, nullptr, 0, 0,65OPTION(prefix_1, "defaultlib:", defaultlib, Joined, INVALID, INVALID, nullptr, 0, 0,
67 "Add the library to the list of input files", nullptr, nullptr)66 "Add the library to the list of input files", nullptr, nullptr)
68OPTION(prefix_1, "delay:", delay, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)67OPTION(prefix_1, "delay:", delay, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
69OPTION(prefix_1, "delayload:", delayload, Joined, INVALID, INVALID, nullptr, 0, 0,68OPTION(prefix_1, "delayload:", delayload, Joined, INVALID, INVALID, nullptr, 0, 0,
70 "Delay loaded DLL name", nullptr, nullptr)69 "Delay loaded DLL name", nullptr, nullptr)
70OPTION(prefix_1, "demangle:no", demangle_no, Flag, INVALID, INVALID, nullptr, 0, 0,
71 "Do not demangle symbols in output", nullptr, nullptr)
72OPTION(prefix_1, "demangle", demangle, Flag, INVALID, INVALID, nullptr, 0, 0,
73 "Demangle symbols in output (default)", nullptr, nullptr)
71OPTION(prefix_1, "disallowlib:", disallowlib, Joined, INVALID, nodefaultlib, nullptr, 0, 0, nullptr, nullptr, nullptr)74OPTION(prefix_1, "disallowlib:", disallowlib, Joined, INVALID, nodefaultlib, nullptr, 0, 0, nullptr, nullptr, nullptr)
72OPTION(prefix_1, "dll", dll, Flag, INVALID, INVALID, nullptr, 0, 0,75OPTION(prefix_1, "dll", dll, Flag, INVALID, INVALID, nullptr, 0, 0,
73 "Create a DLL", nullptr, nullptr)76 "Create a DLL", nullptr, nullptr)
...@@ -83,22 +86,29 @@ OPTION(prefix_1, "entry:", entry, Joined, INVALID, INVALID, nullptr, 0, 0,...@@ -83,22 +86,29 @@ OPTION(prefix_1, "entry:", entry, Joined, INVALID, INVALID, nullptr, 0, 0,
83OPTION(prefix_1, "errorlimit:", errorlimit, Joined, INVALID, INVALID, nullptr, 0, 0,86OPTION(prefix_1, "errorlimit:", errorlimit, Joined, INVALID, INVALID, nullptr, 0, 0,
84 "Maximum number of errors to emit before stopping (0 = no limit)", nullptr, nullptr)87 "Maximum number of errors to emit before stopping (0 = no limit)", nullptr, nullptr)
85OPTION(prefix_1, "errorreport:", errorreport, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)88OPTION(prefix_1, "errorreport:", errorreport, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
89OPTION(prefix_1, "exclude-all-symbols", exclude_all_symbols, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
86OPTION(prefix_1, "export-all-symbols", export_all_symbols, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)90OPTION(prefix_1, "export-all-symbols", export_all_symbols, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
87OPTION(prefix_1, "export:", export, Joined, INVALID, INVALID, nullptr, 0, 0,91OPTION(prefix_1, "export:", export, Joined, INVALID, INVALID, nullptr, 0, 0,
88 "Export a function", nullptr, nullptr)92 "Export a function", nullptr, nullptr)
89OPTION(prefix_1, "failifmismatch:", failifmismatch, Joined, INVALID, INVALID, nullptr, 0, 0,93OPTION(prefix_1, "failifmismatch:", failifmismatch, Joined, INVALID, INVALID, nullptr, 0, 0,
90 "", nullptr, nullptr)94 "", nullptr, nullptr)
91OPTION(prefix_1, "fastfail", fastfail, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)95OPTION(prefix_1, "fastfail", fastfail, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
96OPTION(prefix_1, "filealign:", filealign, Joined, INVALID, INVALID, nullptr, 0, 0,
97 "Section alignment in the output file", nullptr, nullptr)
92OPTION(prefix_1, "fixed:no", fixed_no, Flag, INVALID, INVALID, nullptr, 0, 0,98OPTION(prefix_1, "fixed:no", fixed_no, Flag, INVALID, INVALID, nullptr, 0, 0,
93 "Enable base relocations (default)", nullptr, nullptr)99 "Enable base relocations (default)", nullptr, nullptr)
94OPTION(prefix_1, "fixed", fixed, Flag, INVALID, INVALID, nullptr, 0, 0,100OPTION(prefix_1, "fixed", fixed, Flag, INVALID, INVALID, nullptr, 0, 0,
95 "Disable base relocations", nullptr, nullptr)101 "Disable base relocations", nullptr, nullptr)
102OPTION(prefix_1, "force:multipleres", force_multipleres, Flag, INVALID, INVALID, nullptr, 0, 0,
103 "Allow multiply defined resources when creating executables", nullptr, nullptr)
96OPTION(prefix_1, "force:multiple", force_multiple, Flag, INVALID, INVALID, nullptr, 0, 0,104OPTION(prefix_1, "force:multiple", force_multiple, Flag, INVALID, INVALID, nullptr, 0, 0,
97 "Allow multiply defined symbols when creating executables", nullptr, nullptr)105 "Allow multiply defined symbols when creating executables", nullptr, nullptr)
98OPTION(prefix_1, "force:unresolved", force_unresolved, Flag, INVALID, INVALID, nullptr, 0, 0,106OPTION(prefix_1, "force:unresolved", force_unresolved, Flag, INVALID, INVALID, nullptr, 0, 0,
99 "Allow undefined symbols when creating executables", nullptr, nullptr)107 "Allow undefined symbols when creating executables", nullptr, nullptr)
100OPTION(prefix_1, "force", force, Flag, INVALID, INVALID, nullptr, 0, 0,108OPTION(prefix_1, "force", force, Flag, INVALID, INVALID, nullptr, 0, 0,
101 "Allow undefined and multiply defined symbols when creating executables", nullptr, nullptr)109 "Allow undefined and multiply defined symbols when creating executables", nullptr, nullptr)
110OPTION(prefix_1, "functionpadmin:", functionpadmin_opt, Joined, INVALID, INVALID, nullptr, 0, 0,
111 "Prepares an image for hotpatching", nullptr, nullptr)
102OPTION(prefix_1, "functionpadmin", functionpadmin, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)112OPTION(prefix_1, "functionpadmin", functionpadmin, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
103OPTION(prefix_1, "guard:", guard, Joined, INVALID, INVALID, nullptr, 0, 0,113OPTION(prefix_1, "guard:", guard, Joined, INVALID, INVALID, nullptr, 0, 0,
104 "Control flow guard", nullptr, nullptr)114 "Control flow guard", nullptr, nullptr)
...@@ -116,8 +126,10 @@ OPTION(prefix_1, "ignore:", ignore, Joined, INVALID, INVALID, nullptr, 0, 0,...@@ -116,8 +126,10 @@ OPTION(prefix_1, "ignore:", ignore, Joined, INVALID, INVALID, nullptr, 0, 0,
116OPTION(prefix_1, "ignoreidl", ignoreidl, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)126OPTION(prefix_1, "ignoreidl", ignoreidl, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
117OPTION(prefix_1, "implib:", implib, Joined, INVALID, INVALID, nullptr, 0, 0,127OPTION(prefix_1, "implib:", implib, Joined, INVALID, INVALID, nullptr, 0, 0,
118 "Import library name", nullptr, nullptr)128 "Import library name", nullptr, nullptr)
119OPTION(prefix_3, "include:", incl, Joined, INVALID, INVALID, nullptr, 0, 0,129OPTION(prefix_1, "include:", incl, Joined, INVALID, INVALID, nullptr, 0, 0,
120 "Force symbol to be added to symbol table as undefined one", nullptr, nullptr)130 "Force symbol to be added to symbol table as undefined one", nullptr, nullptr)
131OPTION(prefix_1, "includeoptional:", include_optional, Joined, INVALID, INVALID, nullptr, 0, 0,
132 "Add symbol as undefined, but allow it to remain undefined", nullptr, nullptr)
121OPTION(prefix_1, "incremental:no", incremental_no, Flag, INVALID, INVALID, nullptr, 0, 0,133OPTION(prefix_1, "incremental:no", incremental_no, Flag, INVALID, INVALID, nullptr, 0, 0,
122 "Overwrite import library even if contents are unchanged", nullptr, nullptr)134 "Overwrite import library even if contents are unchanged", nullptr, nullptr)
123OPTION(prefix_1, "incremental", incremental, Flag, INVALID, INVALID, nullptr, 0, 0,135OPTION(prefix_1, "incremental", incremental, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -141,7 +153,7 @@ OPTION(prefix_1, "lldltocache:", lldltocache, Joined, INVALID, INVALID, nullptr,...@@ -141,7 +153,7 @@ OPTION(prefix_1, "lldltocache:", lldltocache, Joined, INVALID, INVALID, nullptr,
141 "Path to ThinLTO cached object file directory", nullptr, nullptr)153 "Path to ThinLTO cached object file directory", nullptr, nullptr)
142OPTION(prefix_1, "lldltocachepolicy:", lldltocachepolicy, Joined, INVALID, INVALID, nullptr, 0, 0,154OPTION(prefix_1, "lldltocachepolicy:", lldltocachepolicy, Joined, INVALID, INVALID, nullptr, 0, 0,
143 "Pruning policy for the ThinLTO cache", nullptr, nullptr)155 "Pruning policy for the ThinLTO cache", nullptr, nullptr)
144OPTION(prefix_3, "lldmap:", lldmap_file, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)156OPTION(prefix_1, "lldmap:", lldmap_file, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
145OPTION(prefix_1, "lldmap", lldmap, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)157OPTION(prefix_1, "lldmap", lldmap, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
146OPTION(prefix_1, "lldmingw", lldmingw, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)158OPTION(prefix_1, "lldmingw", lldmingw, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
147OPTION(prefix_1, "lldsavetemps", lldsavetemps, Flag, INVALID, INVALID, nullptr, 0, 0,159OPTION(prefix_1, "lldsavetemps", lldsavetemps, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -186,7 +198,7 @@ OPTION(prefix_1, "order:", order, Joined, INVALID, INVALID, nullptr, 0, 0,...@@ -186,7 +198,7 @@ OPTION(prefix_1, "order:", order, Joined, INVALID, INVALID, nullptr, 0, 0,
186 "Put functions in order", nullptr, nullptr)198 "Put functions in order", nullptr, nullptr)
187OPTION(prefix_1, "out:", out, Joined, INVALID, INVALID, nullptr, 0, 0,199OPTION(prefix_1, "out:", out, Joined, INVALID, INVALID, nullptr, 0, 0,
188 "Path to file to write output", nullptr, nullptr)200 "Path to file to write output", nullptr, nullptr)
189OPTION(prefix_3, "output-def:", output_def, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)201OPTION(prefix_1, "output-def:", output_def, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
190OPTION(prefix_1, "pdb:", pdb, Joined, INVALID, INVALID, nullptr, 0, 0,202OPTION(prefix_1, "pdb:", pdb, Joined, INVALID, INVALID, nullptr, 0, 0,
191 "PDB file path", nullptr, nullptr)203 "PDB file path", nullptr, nullptr)
192OPTION(prefix_1, "pdbaltpath:", pdbaltpath, Joined, INVALID, INVALID, nullptr, 0, 0,204OPTION(prefix_1, "pdbaltpath:", pdbaltpath, Joined, INVALID, INVALID, nullptr, 0, 0,
...@@ -208,8 +220,27 @@ OPTION(prefix_1, "stub:", stub, Joined, INVALID, INVALID, nullptr, 0, 0,...@@ -208,8 +220,27 @@ OPTION(prefix_1, "stub:", stub, Joined, INVALID, INVALID, nullptr, 0, 0,
208 "Specify DOS stub file", nullptr, nullptr)220 "Specify DOS stub file", nullptr, nullptr)
209OPTION(prefix_1, "subsystem:", subsystem, Joined, INVALID, INVALID, nullptr, 0, 0,221OPTION(prefix_1, "subsystem:", subsystem, Joined, INVALID, INVALID, nullptr, 0, 0,
210 "Specify subsystem", nullptr, nullptr)222 "Specify subsystem", nullptr, nullptr)
211OPTION(prefix_1, "swaprun:cd", swaprun_cd, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)223OPTION(prefix_1, "summary", summary, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
212OPTION(prefix_1, "swaprun:net", swaprun_net, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)224OPTION(prefix_1, "swaprun:cd", swaprun_cd, Flag, INVALID, swaprun, "cd\0", 0, 0,
225 "Make loader run output binary from swap instead of from CD", nullptr, nullptr)
226OPTION(prefix_1, "swaprun:net", swaprun_net, Flag, INVALID, swaprun, "net\0", 0, 0,
227 "Make loader run output binary from swap instead of from network", nullptr, nullptr)
228OPTION(prefix_1, "swaprun:", swaprun, Joined, INVALID, INVALID, nullptr, 0, 0,
229 "Comma-separated list of 'cd' or 'net'", nullptr, nullptr)
230OPTION(prefix_1, "thinlto-emit-imports-files", thinlto_emit_imports_files, Flag, INVALID, INVALID, nullptr, 0, 0,
231 "Emit .imports files with -thinlto-index-only", nullptr, nullptr)
232OPTION(prefix_1, "thinlto-index-only:", thinlto_index_only_arg, Joined, INVALID, INVALID, nullptr, 0, 0,
233 "-thinlto-index-only and also write native module names to file", nullptr, nullptr)
234OPTION(prefix_1, "thinlto-index-only", thinlto_index_only, Flag, INVALID, INVALID, nullptr, 0, 0,
235 "Instead of linking, emit ThinLTO index files", nullptr, nullptr)
236OPTION(prefix_1, "thinlto-object-suffix-replace:", thinlto_object_suffix_replace, Joined, INVALID, INVALID, nullptr, 0, 0,
237 "'old;new' replace old suffix with new suffix in ThinLTO index", nullptr, nullptr)
238OPTION(prefix_1, "thinlto-prefix-replace:", thinlto_prefix_replace, Joined, INVALID, INVALID, nullptr, 0, 0,
239 "'old;new' replace old prefix with new prefix in ThinLTO outputs", nullptr, nullptr)
240OPTION(prefix_1, "threads:no", threads_no, Flag, INVALID, INVALID, nullptr, 0, 0,
241 "Do not run the linker multi-threaded", nullptr, nullptr)
242OPTION(prefix_1, "threads", threads, Flag, INVALID, INVALID, nullptr, 0, 0,
243 "Run the linker multi-threaded (default)", nullptr, nullptr)
213OPTION(prefix_1, "throwingnew", throwingnew, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)244OPTION(prefix_1, "throwingnew", throwingnew, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
214OPTION(prefix_1, "timestamp:", timestamp, Joined, INVALID, INVALID, nullptr, 0, 0,245OPTION(prefix_1, "timestamp:", timestamp, Joined, INVALID, INVALID, nullptr, 0, 0,
215 "Specify the PE header timestamp", nullptr, nullptr)246 "Specify the PE header timestamp", nullptr, nullptr)
...@@ -233,7 +264,7 @@ OPTION(prefix_1, "WX:no", WX_no, Flag, INVALID, INVALID, nullptr, 0, 0,...@@ -233,7 +264,7 @@ OPTION(prefix_1, "WX:no", WX_no, Flag, INVALID, INVALID, nullptr, 0, 0,
233 "Don't treat warnings as errors", nullptr, nullptr)264 "Don't treat warnings as errors", nullptr, nullptr)
234OPTION(prefix_1, "WX", WX, Flag, INVALID, INVALID, nullptr, 0, 0,265OPTION(prefix_1, "WX", WX, Flag, INVALID, INVALID, nullptr, 0, 0,
235 "Treat warnings as errors", nullptr, nullptr)266 "Treat warnings as errors", nullptr, nullptr)
236OPTION(prefix_4, "", help_q, Flag, INVALID, help, nullptr, 0, 0, nullptr, nullptr, nullptr)267OPTION(prefix_3, "", help_q, Flag, INVALID, help, nullptr, 0, 0, nullptr, nullptr, nullptr)
237#endif // OPTION268#endif // OPTION
238269
239#ifdef OPTTABLE_ARG_INIT270#ifdef OPTTABLE_ARG_INIT
deps/lld-prebuilt/ELF/Options.inc+91-51
...@@ -29,13 +29,14 @@ PREFIX(prefix_2, {"--" COMMA "-" COMMA nullptr})...@@ -29,13 +29,14 @@ PREFIX(prefix_2, {"--" COMMA "-" COMMA nullptr})
2929
30OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)30OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
31OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)31OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
32OPTION(prefix_1, "(", anonymous_30, Flag, INVALID, start_group, nullptr, 0, 0,32OPTION(prefix_1, "(", anonymous_31, Flag, INVALID, start_group, nullptr, 0, 0,
33 "Alias for --start-group", nullptr, nullptr)33 "Alias for --start-group", nullptr, nullptr)
34OPTION(prefix_1, ")", anonymous_12, Flag, INVALID, end_group, nullptr, 0, 0,34OPTION(prefix_1, ")", anonymous_12, Flag, INVALID, end_group, nullptr, 0, 0,
35 "Alias for --end-group", nullptr, nullptr)35 "Alias for --end-group", nullptr, nullptr)
36OPTION(prefix_2, "allow-multiple-definition", allow_multiple_definition, Flag, INVALID, INVALID, nullptr, 0, 0,36OPTION(prefix_2, "allow-multiple-definition", allow_multiple_definition, Flag, INVALID, INVALID, nullptr, 0, 0,
37 "Allow multiple definitions", nullptr, nullptr)37 "Allow multiple definitions", nullptr, nullptr)
38OPTION(prefix_2, "allow-shlib-undefined", anonymous_47, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)38OPTION(prefix_2, "allow-shlib-undefined", allow_shlib_undefined, Flag, INVALID, INVALID, nullptr, 0, 0,
39 "Allow unresolved references in shared libraries (default when linking a shared library)", nullptr, nullptr)
39OPTION(prefix_2, "apply-dynamic-relocs", apply_dynamic_relocs, Flag, INVALID, INVALID, nullptr, 0, 0,40OPTION(prefix_2, "apply-dynamic-relocs", apply_dynamic_relocs, Flag, INVALID, INVALID, nullptr, 0, 0,
40 "Apply link-time values for dynamic relocations", nullptr, nullptr)41 "Apply link-time values for dynamic relocations", nullptr, nullptr)
41OPTION(prefix_2, "as-needed", as_needed, Flag, INVALID, INVALID, nullptr, 0, 0,42OPTION(prefix_2, "as-needed", as_needed, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -45,7 +46,7 @@ OPTION(prefix_2, "auxiliary=", auxiliary_eq, Joined, INVALID, auxiliary, nullptr...@@ -45,7 +46,7 @@ OPTION(prefix_2, "auxiliary=", auxiliary_eq, Joined, INVALID, auxiliary, nullptr
45OPTION(prefix_2, "auxiliary", auxiliary, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)46OPTION(prefix_2, "auxiliary", auxiliary, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
46OPTION(prefix_2, "Bdynamic", Bdynamic, Flag, INVALID, INVALID, nullptr, 0, 0,47OPTION(prefix_2, "Bdynamic", Bdynamic, Flag, INVALID, INVALID, nullptr, 0, 0,
47 "Link against shared libraries (default)", nullptr, nullptr)48 "Link against shared libraries (default)", nullptr, nullptr)
48OPTION(prefix_2, "Bshareable", anonymous_28, Flag, INVALID, shared, nullptr, 0, 0,49OPTION(prefix_2, "Bshareable", anonymous_29, Flag, INVALID, shared, nullptr, 0, 0,
49 "Alias for --shared", nullptr, nullptr)50 "Alias for --shared", nullptr, nullptr)
50OPTION(prefix_2, "Bstatic", Bstatic, Flag, INVALID, INVALID, nullptr, 0, 0,51OPTION(prefix_2, "Bstatic", Bstatic, Flag, INVALID, INVALID, nullptr, 0, 0,
51 "Do not link against shared libraries", nullptr, nullptr)52 "Do not link against shared libraries", nullptr, nullptr)
...@@ -87,7 +88,9 @@ OPTION(prefix_2, "defsym=", defsym_eq, Joined, INVALID, defsym, nullptr, 0, 0,...@@ -87,7 +88,9 @@ OPTION(prefix_2, "defsym=", defsym_eq, Joined, INVALID, defsym, nullptr, 0, 0,
87OPTION(prefix_2, "defsym", defsym, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<symbol>=<value>", nullptr)88OPTION(prefix_2, "defsym", defsym, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<symbol>=<value>", nullptr)
88OPTION(prefix_2, "demangle", demangle, Flag, INVALID, INVALID, nullptr, 0, 0,89OPTION(prefix_2, "demangle", demangle, Flag, INVALID, INVALID, nullptr, 0, 0,
89 "Demangle symbol names (default)", nullptr, nullptr)90 "Demangle symbol names (default)", nullptr, nullptr)
90OPTION(prefix_2, "detect-odr-violations", anonymous_48, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)91OPTION(prefix_2, "dependent-libraries", dependent_libraries, Flag, INVALID, INVALID, nullptr, 0, 0,
92 "Process dependent library specifiers from input files (default)", nullptr, nullptr)
93OPTION(prefix_2, "detect-odr-violations", anonymous_50, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
91OPTION(prefix_2, "disable-new-dtags", disable_new_dtags, Flag, INVALID, INVALID, nullptr, 0, 0,94OPTION(prefix_2, "disable-new-dtags", disable_new_dtags, Flag, INVALID, INVALID, nullptr, 0, 0,
92 "Disable new dynamic tags", nullptr, nullptr)95 "Disable new dynamic tags", nullptr, nullptr)
93OPTION(prefix_2, "disable-verify", disable_verify, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)96OPTION(prefix_2, "disable-verify", disable_verify, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
...@@ -111,10 +114,10 @@ OPTION(prefix_2, "dy", anonymous_2, Flag, INVALID, Bdynamic, nullptr, 0, 0,...@@ -111,10 +114,10 @@ OPTION(prefix_2, "dy", anonymous_2, Flag, INVALID, Bdynamic, nullptr, 0, 0,
111 "Alias for --Bdynamic", nullptr, nullptr)114 "Alias for --Bdynamic", nullptr, nullptr)
112OPTION(prefix_1, "d", anonymous_6, Flag, INVALID, define_common, nullptr, 0, 0,115OPTION(prefix_1, "d", anonymous_6, Flag, INVALID, define_common, nullptr, 0, 0,
113 "Alias for --define-common", nullptr, nullptr)116 "Alias for --define-common", nullptr, nullptr)
114OPTION(prefix_2, "EB", anonymous_65, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)117OPTION(prefix_2, "EB", anonymous_69, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
115OPTION(prefix_2, "eh-frame-hdr", eh_frame_hdr, Flag, INVALID, INVALID, nullptr, 0, 0,118OPTION(prefix_2, "eh-frame-hdr", eh_frame_hdr, Flag, INVALID, INVALID, nullptr, 0, 0,
116 "Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header", nullptr, nullptr)119 "Request creation of .eh_frame_hdr section and PT_GNU_EH_FRAME segment header", nullptr, nullptr)
117OPTION(prefix_2, "EL", anonymous_66, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)120OPTION(prefix_2, "EL", anonymous_70, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
118OPTION(prefix_2, "emit-relocs", emit_relocs, Flag, INVALID, INVALID, nullptr, 0, 0,121OPTION(prefix_2, "emit-relocs", emit_relocs, Flag, INVALID, INVALID, nullptr, 0, 0,
119 "Generate relocations in output", nullptr, nullptr)122 "Generate relocations in output", nullptr, nullptr)
120OPTION(prefix_2, "enable-new-dtags", enable_new_dtags, Flag, INVALID, INVALID, nullptr, 0, 0,123OPTION(prefix_2, "enable-new-dtags", enable_new_dtags, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -155,6 +158,8 @@ OPTION(prefix_2, "fini=", fini_eq, Joined, INVALID, fini, nullptr, 0, 0,...@@ -155,6 +158,8 @@ OPTION(prefix_2, "fini=", fini_eq, Joined, INVALID, fini, nullptr, 0, 0,
155OPTION(prefix_2, "fini", fini, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<symbol>", nullptr)158OPTION(prefix_2, "fini", fini, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<symbol>", nullptr)
156OPTION(prefix_2, "fix-cortex-a53-843419", fix_cortex_a53_843419, Flag, INVALID, INVALID, nullptr, 0, 0,159OPTION(prefix_2, "fix-cortex-a53-843419", fix_cortex_a53_843419, Flag, INVALID, INVALID, nullptr, 0, 0,
157 "Apply fixes for AArch64 Cortex-A53 erratum 843419", nullptr, nullptr)160 "Apply fixes for AArch64 Cortex-A53 erratum 843419", nullptr, nullptr)
161OPTION(prefix_2, "force-bti", force_bti, Flag, INVALID, INVALID, nullptr, 0, 0,
162 "Force enable AArch64 BTI in PLT, warn if Input ELF file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property", nullptr, nullptr)
158OPTION(prefix_2, "format=", format_eq, Joined, INVALID, format, nullptr, 0, 0,163OPTION(prefix_2, "format=", format_eq, Joined, INVALID, format, nullptr, 0, 0,
159 "Change the input format of the inputs following this option", "[default,elf,binary]", nullptr)164 "Change the input format of the inputs following this option", "[default,elf,binary]", nullptr)
160OPTION(prefix_2, "format", format, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "[default,elf,binary]", nullptr)165OPTION(prefix_2, "format", format, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "[default,elf,binary]", nullptr)
...@@ -168,14 +173,14 @@ OPTION(prefix_2, "gdb-index", gdb_index, Flag, INVALID, INVALID, nullptr, 0, 0,...@@ -168,14 +173,14 @@ OPTION(prefix_2, "gdb-index", gdb_index, Flag, INVALID, INVALID, nullptr, 0, 0,
168 "Generate .gdb_index section", nullptr, nullptr)173 "Generate .gdb_index section", nullptr, nullptr)
169OPTION(prefix_2, "gnu-unique", gnu_unique, Flag, INVALID, INVALID, nullptr, 0, 0,174OPTION(prefix_2, "gnu-unique", gnu_unique, Flag, INVALID, INVALID, nullptr, 0, 0,
170 "Enable STB_GNU_UNIQUE symbol binding (default)", nullptr, nullptr)175 "Enable STB_GNU_UNIQUE symbol binding (default)", nullptr, nullptr)
171OPTION(prefix_1, "G", anonymous_67, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)176OPTION(prefix_1, "G", anonymous_71, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
172OPTION(prefix_1, "g", anonymous_49, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)177OPTION(prefix_1, "g", anonymous_51, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
173OPTION(prefix_2, "hash-style=", hash_style_eq, Joined, INVALID, hash_style, nullptr, 0, 0,178OPTION(prefix_2, "hash-style=", hash_style_eq, Joined, INVALID, hash_style, nullptr, 0, 0,
174 "Specify hash style (sysv, gnu or both)", nullptr, nullptr)179 "Specify hash style (sysv, gnu or both)", nullptr, nullptr)
175OPTION(prefix_2, "hash-style", hash_style, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)180OPTION(prefix_2, "hash-style", hash_style, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
176OPTION(prefix_2, "help", help, Flag, INVALID, INVALID, nullptr, 0, 0,181OPTION(prefix_2, "help", help, Flag, INVALID, INVALID, nullptr, 0, 0,
177 "Print option help", nullptr, nullptr)182 "Print option help", nullptr, nullptr)
178OPTION(prefix_1, "h", anonymous_29, JoinedOrSeparate, INVALID, soname, nullptr, 0, 0,183OPTION(prefix_1, "h", anonymous_30, JoinedOrSeparate, INVALID, soname, nullptr, 0, 0,
179 "Alias for --soname", nullptr, nullptr)184 "Alias for --soname", nullptr, nullptr)
180OPTION(prefix_2, "icf=all", icf_all, Flag, INVALID, INVALID, nullptr, 0, 0,185OPTION(prefix_2, "icf=all", icf_all, Flag, INVALID, INVALID, nullptr, 0, 0,
181 "Enable identical code folding", nullptr, nullptr)186 "Enable identical code folding", nullptr, nullptr)
...@@ -205,9 +210,13 @@ OPTION(prefix_2, "library-path", library_path, Separate, INVALID, INVALID, nullp...@@ -205,9 +210,13 @@ OPTION(prefix_2, "library-path", library_path, Separate, INVALID, INVALID, nullp
205OPTION(prefix_2, "library=", library_eq, Joined, INVALID, library, nullptr, 0, 0,210OPTION(prefix_2, "library=", library_eq, Joined, INVALID, library, nullptr, 0, 0,
206 "Root name of library to use", "<libName>", nullptr)211 "Root name of library to use", "<libName>", nullptr)
207OPTION(prefix_2, "library", library, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<libName>", nullptr)212OPTION(prefix_2, "library", library, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<libName>", nullptr)
208OPTION(prefix_2, "long-plt", anonymous_50, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)213OPTION(prefix_2, "long-plt", anonymous_52, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
209OPTION(prefix_2, "lto-aa-pipeline=", lto_aa_pipeline, Joined, INVALID, INVALID, nullptr, 0, 0,214OPTION(prefix_2, "lto-aa-pipeline=", lto_aa_pipeline, Joined, INVALID, INVALID, nullptr, 0, 0,
210 "AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes", nullptr, nullptr)215 "AA pipeline to run during LTO. Used in conjunction with -lto-newpm-passes", nullptr, nullptr)
216OPTION(prefix_2, "lto-cs-profile-file=", lto_cs_profile_file, Joined, INVALID, INVALID, nullptr, 0, 0,
217 "Context sensitive profile file path", nullptr, nullptr)
218OPTION(prefix_2, "lto-cs-profile-generate", lto_cs_profile_generate, Flag, INVALID, INVALID, nullptr, 0, 0,
219 "Perform context senstive PGO instrumentation", nullptr, nullptr)
211OPTION(prefix_2, "lto-debug-pass-manager", lto_debug_pass_manager, Flag, INVALID, INVALID, nullptr, 0, 0,220OPTION(prefix_2, "lto-debug-pass-manager", lto_debug_pass_manager, Flag, INVALID, INVALID, nullptr, 0, 0,
212 "Debug new pass manager", nullptr, nullptr)221 "Debug new pass manager", nullptr, nullptr)
213OPTION(prefix_2, "lto-new-pass-manager", lto_new_pass_manager, Flag, INVALID, INVALID, nullptr, 0, 0,222OPTION(prefix_2, "lto-new-pass-manager", lto_new_pass_manager, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -235,14 +244,17 @@ OPTION(prefix_2, "mips-got-size", mips_got_size, Separate, INVALID, INVALID, nul...@@ -235,14 +244,17 @@ OPTION(prefix_2, "mips-got-size", mips_got_size, Separate, INVALID, INVALID, nul
235OPTION(prefix_2, "mllvm=", mllvm_eq, Joined, INVALID, mllvm, nullptr, 0, 0,244OPTION(prefix_2, "mllvm=", mllvm_eq, Joined, INVALID, mllvm, nullptr, 0, 0,
236 "Additional arguments to forward to LLVM's option processing", nullptr, nullptr)245 "Additional arguments to forward to LLVM's option processing", nullptr, nullptr)
237OPTION(prefix_2, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)246OPTION(prefix_2, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
238OPTION(prefix_1, "M", anonymous_24, Flag, INVALID, print_map, nullptr, 0, 0,247OPTION(prefix_1, "M", anonymous_25, Flag, INVALID, print_map, nullptr, 0, 0,
239 "Alias for --print-map", nullptr, nullptr)248 "Alias for --print-map", nullptr, nullptr)
240OPTION(prefix_1, "m", m, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,249OPTION(prefix_1, "m", m, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
241 "Set target emulation", nullptr, nullptr)250 "Set target emulation", nullptr, nullptr)
242OPTION(prefix_2, "no-add-needed", anonymous_51, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)251OPTION(prefix_2, "nmagic", nmagic, Flag, INVALID, INVALID, nullptr, 0, 0,
252 "Do not page align sections, link against static libraries.", "<magic>", nullptr)
253OPTION(prefix_2, "no-add-needed", anonymous_53, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
243OPTION(prefix_2, "no-allow-multiple-definition", no_allow_multiple_definition, Flag, INVALID, INVALID, nullptr, 0, 0,254OPTION(prefix_2, "no-allow-multiple-definition", no_allow_multiple_definition, Flag, INVALID, INVALID, nullptr, 0, 0,
244 "Do not allow multiple definitions (default)", nullptr, nullptr)255 "Do not allow multiple definitions (default)", nullptr, nullptr)
245OPTION(prefix_2, "no-allow-shlib-undefined", anonymous_52, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)256OPTION(prefix_2, "no-allow-shlib-undefined", no_allow_shlib_undefined, Flag, INVALID, INVALID, nullptr, 0, 0,
257 "Do not allow unresolved references in shared libraries (default when linking an executable)", nullptr, nullptr)
246OPTION(prefix_2, "no-apply-dynamic-relocs", no_apply_dynamic_relocs, Flag, INVALID, INVALID, nullptr, 0, 0,258OPTION(prefix_2, "no-apply-dynamic-relocs", no_apply_dynamic_relocs, Flag, INVALID, INVALID, nullptr, 0, 0,
247 "Do not apply link-time values for dynamic relocations (default)", nullptr, nullptr)259 "Do not apply link-time values for dynamic relocations (default)", nullptr, nullptr)
248OPTION(prefix_2, "no-as-needed", no_as_needed, Flag, INVALID, INVALID, nullptr, 0, 0,260OPTION(prefix_2, "no-as-needed", no_as_needed, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -253,14 +265,16 @@ OPTION(prefix_2, "no-check-sections", no_check_sections, Flag, INVALID, INVALID,...@@ -253,14 +265,16 @@ OPTION(prefix_2, "no-check-sections", no_check_sections, Flag, INVALID, INVALID,
253 "Do not check section addresses for overlaps", nullptr, nullptr)265 "Do not check section addresses for overlaps", nullptr, nullptr)
254OPTION(prefix_2, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0,266OPTION(prefix_2, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0,
255 "Do not use colors in diagnostics", nullptr, nullptr)267 "Do not use colors in diagnostics", nullptr, nullptr)
256OPTION(prefix_2, "no-copy-dt-needed-entries", anonymous_53, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)268OPTION(prefix_2, "no-copy-dt-needed-entries", anonymous_54, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
257OPTION(prefix_2, "no-cref", no_cref, Flag, INVALID, INVALID, nullptr, 0, 0,269OPTION(prefix_2, "no-cref", no_cref, Flag, INVALID, INVALID, nullptr, 0, 0,
258 "Do not output cross reference table", nullptr, nullptr)270 "Do not output cross reference table", nullptr, nullptr)
259OPTION(prefix_2, "no-ctors-in-init-array", anonymous_54, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)271OPTION(prefix_2, "no-ctors-in-init-array", anonymous_55, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
260OPTION(prefix_2, "no-define-common", no_define_common, Flag, INVALID, INVALID, nullptr, 0, 0,272OPTION(prefix_2, "no-define-common", no_define_common, Flag, INVALID, INVALID, nullptr, 0, 0,
261 "Do not assign space to common symbols", nullptr, nullptr)273 "Do not assign space to common symbols", nullptr, nullptr)
262OPTION(prefix_2, "no-demangle", no_demangle, Flag, INVALID, INVALID, nullptr, 0, 0,274OPTION(prefix_2, "no-demangle", no_demangle, Flag, INVALID, INVALID, nullptr, 0, 0,
263 "Do not demangle symbol names", nullptr, nullptr)275 "Do not demangle symbol names", nullptr, nullptr)
276OPTION(prefix_2, "no-dependent-libraries", no_dependent_libraries, Flag, INVALID, INVALID, nullptr, 0, 0,
277 "Ignore dependent library specifiers from input files", nullptr, nullptr)
264OPTION(prefix_2, "no-dynamic-linker", no_dynamic_linker, Flag, INVALID, INVALID, nullptr, 0, 0,278OPTION(prefix_2, "no-dynamic-linker", no_dynamic_linker, Flag, INVALID, INVALID, nullptr, 0, 0,
265 "Inhibit output of .interp section", nullptr, nullptr)279 "Inhibit output of .interp section", nullptr, nullptr)
266OPTION(prefix_2, "no-eh-frame-hdr", no_eh_frame_hdr, Flag, INVALID, INVALID, nullptr, 0, 0,280OPTION(prefix_2, "no-eh-frame-hdr", no_eh_frame_hdr, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -277,16 +291,19 @@ OPTION(prefix_2, "no-gdb-index", no_gdb_index, Flag, INVALID, INVALID, nullptr,...@@ -277,16 +291,19 @@ OPTION(prefix_2, "no-gdb-index", no_gdb_index, Flag, INVALID, INVALID, nullptr,
277 "Do not generate .gdb_index section (default)", nullptr, nullptr)291 "Do not generate .gdb_index section (default)", nullptr, nullptr)
278OPTION(prefix_2, "no-gnu-unique", no_gnu_unique, Flag, INVALID, INVALID, nullptr, 0, 0,292OPTION(prefix_2, "no-gnu-unique", no_gnu_unique, Flag, INVALID, INVALID, nullptr, 0, 0,
279 "Disable STB_GNU_UNIQUE symbol binding", nullptr, nullptr)293 "Disable STB_GNU_UNIQUE symbol binding", nullptr, nullptr)
280OPTION(prefix_2, "no-keep-memory", anonymous_55, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)294OPTION(prefix_2, "no-keep-memory", anonymous_56, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
281OPTION(prefix_2, "no-merge-exidx-entries", no_merge_exidx_entries, Flag, INVALID, INVALID, nullptr, 0, 0,295OPTION(prefix_2, "no-merge-exidx-entries", no_merge_exidx_entries, Flag, INVALID, INVALID, nullptr, 0, 0,
282 "Disable merging .ARM.exidx entries", nullptr, nullptr)296 "Disable merging .ARM.exidx entries", nullptr, nullptr)
283OPTION(prefix_2, "no-mmap-output-file", anonymous_56, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)297OPTION(prefix_2, "no-mmap-output-file", anonymous_57, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
298OPTION(prefix_2, "no-nmagic", no_nmagic, Flag, INVALID, INVALID, nullptr, 0, 0,
299 "Page align sections (default)", "<magic>", nullptr)
284OPTION(prefix_2, "no-omagic", no_omagic, Flag, INVALID, INVALID, nullptr, 0, 0,300OPTION(prefix_2, "no-omagic", no_omagic, Flag, INVALID, INVALID, nullptr, 0, 0,
285 "Do not set the text data sections to be writable", "<magic>", nullptr)301 "Do not set the text data sections to be writable, page align sections (default)", "<magic>", nullptr)
286OPTION(prefix_2, "no-pic-executable", anonymous_19, Flag, INVALID, no_pie, nullptr, 0, 0,302OPTION(prefix_2, "no-pic-executable", anonymous_19, Flag, INVALID, no_pie, nullptr, 0, 0,
287 "Alias for --no-pie", nullptr, nullptr)303 "Alias for --no-pie", nullptr, nullptr)
288OPTION(prefix_2, "no-pie", no_pie, Flag, INVALID, INVALID, nullptr, 0, 0,304OPTION(prefix_2, "no-pie", no_pie, Flag, INVALID, INVALID, nullptr, 0, 0,
289 "Do not create a position independent executable (default)", nullptr, nullptr)305 "Do not create a position independent executable (default)", nullptr, nullptr)
306OPTION(prefix_2, "no-pipeline-knowledge", anonymous_58, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
290OPTION(prefix_2, "no-print-gc-sections", no_print_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,307OPTION(prefix_2, "no-print-gc-sections", no_print_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,
291 "Do not list removed unused sections (default)", nullptr, nullptr)308 "Do not list removed unused sections (default)", nullptr, nullptr)
292OPTION(prefix_2, "no-print-icf-sections", no_print_icf_sections, Flag, INVALID, INVALID, nullptr, 0, 0,309OPTION(prefix_2, "no-print-icf-sections", no_print_icf_sections, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -309,7 +326,7 @@ OPTION(prefix_2, "no-warn-common", no_warn_common, Flag, INVALID, INVALID, nullp...@@ -309,7 +326,7 @@ OPTION(prefix_2, "no-warn-common", no_warn_common, Flag, INVALID, INVALID, nullp
309 "Do not warn about duplicate common symbols (default)", nullptr, nullptr)326 "Do not warn about duplicate common symbols (default)", nullptr, nullptr)
310OPTION(prefix_2, "no-warn-ifunc-textrel", no_warn_ifunc_textrel, Flag, INVALID, INVALID, nullptr, 0, 0,327OPTION(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)328 "Do not warn about using ifunc symbols with text relocations (default)", nullptr, nullptr)
312OPTION(prefix_2, "no-warn-mismatch", anonymous_57, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)329OPTION(prefix_2, "no-warn-mismatch", anonymous_59, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
313OPTION(prefix_2, "no-warn-symbol-ordering", no_warn_symbol_ordering, Flag, INVALID, INVALID, nullptr, 0, 0,330OPTION(prefix_2, "no-warn-symbol-ordering", no_warn_symbol_ordering, Flag, INVALID, INVALID, nullptr, 0, 0,
314 "Do not warn about problems with the symbol ordering file", nullptr, nullptr)331 "Do not warn about problems with the symbol ordering file", nullptr, nullptr)
315OPTION(prefix_2, "no-whole-archive", no_whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0,332OPTION(prefix_2, "no-whole-archive", no_whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -320,31 +337,39 @@ OPTION(prefix_2, "non_shared", anonymous_4, Flag, INVALID, Bstatic, nullptr, 0,...@@ -320,31 +337,39 @@ OPTION(prefix_2, "non_shared", anonymous_4, Flag, INVALID, Bstatic, nullptr, 0,
320 "Alias for --Bstatic", nullptr, nullptr)337 "Alias for --Bstatic", nullptr, nullptr)
321OPTION(prefix_2, "nostdlib", nostdlib, Flag, INVALID, INVALID, nullptr, 0, 0,338OPTION(prefix_2, "nostdlib", nostdlib, Flag, INVALID, INVALID, nullptr, 0, 0,
322 "Only search directories specified on the command line", nullptr, nullptr)339 "Only search directories specified on the command line", nullptr, nullptr)
323OPTION(prefix_1, "N", anonymous_20, Flag, INVALID, omagic, nullptr, 0, 0,340OPTION(prefix_1, "N", anonymous_21, Flag, INVALID, omagic, nullptr, 0, 0,
324 "Alias for --omagic", nullptr, nullptr)341 "Alias for --omagic", nullptr, nullptr)
342OPTION(prefix_1, "n", anonymous_20, Flag, INVALID, nmagic, nullptr, 0, 0,
343 "Alias for --nmagic", nullptr, nullptr)
325OPTION(prefix_3, "oformat", oformat, Separate, INVALID, INVALID, nullptr, 0, 0,344OPTION(prefix_3, "oformat", oformat, Separate, INVALID, INVALID, nullptr, 0, 0,
326 "Specify the binary format for the output object file", "<format>", nullptr)345 "Specify the binary format for the output object file", "<format>", nullptr)
327OPTION(prefix_3, "omagic", omagic, Flag, INVALID, INVALID, nullptr, 0, 0,346OPTION(prefix_3, "omagic", omagic, Flag, INVALID, INVALID, nullptr, 0, 0,
328 "Set the text and data sections to be readable and writable", "<magic>", nullptr)347 "Set the text and data sections to be readable and writable, do not page align sections, link against static libraries", "<magic>", nullptr)
329OPTION(prefix_3, "opt-remarks-filename", opt_remarks_filename, Separate, INVALID, INVALID, nullptr, 0, 0,348OPTION(prefix_3, "opt-remarks-filename", opt_remarks_filename, Separate, INVALID, INVALID, nullptr, 0, 0,
330 "YAML output file for optimization remarks", nullptr, nullptr)349 "YAML output file for optimization remarks", nullptr, nullptr)
350OPTION(prefix_3, "opt-remarks-format", opt_remarks_format, Separate, INVALID, INVALID, nullptr, 0, 0,
351 "The format used for serializing remarks (default: YAML)", nullptr, nullptr)
352OPTION(prefix_3, "opt-remarks-passes", opt_remarks_passes, Separate, INVALID, INVALID, nullptr, 0, 0,
353 "Regex for the passes that need to be serialized to the output file", nullptr, nullptr)
331OPTION(prefix_3, "opt-remarks-with-hotness", opt_remarks_with_hotness, Flag, INVALID, INVALID, nullptr, 0, 0,354OPTION(prefix_3, "opt-remarks-with-hotness", opt_remarks_with_hotness, Flag, INVALID, INVALID, nullptr, 0, 0,
332 "Include hotness information in the optimization remarks file", nullptr, nullptr)355 "Include hotness information in the optimization remarks file", nullptr, nullptr)
333OPTION(prefix_2, "orphan-handling=", orphan_handling_eq, Joined, INVALID, orphan_handling, nullptr, 0, 0,356OPTION(prefix_2, "orphan-handling=", orphan_handling_eq, Joined, INVALID, orphan_handling, nullptr, 0, 0,
334 "Control how orphan sections are handled when linker script used", nullptr, nullptr)357 "Control how orphan sections are handled when linker script used", nullptr, nullptr)
335OPTION(prefix_2, "orphan-handling", orphan_handling, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)358OPTION(prefix_2, "orphan-handling", orphan_handling, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
336OPTION(prefix_3, "output=", anonymous_21, Joined, INVALID, o, nullptr, 0, 0,359OPTION(prefix_3, "output=", anonymous_22, Joined, INVALID, o, nullptr, 0, 0,
337 "Alias for -o", nullptr, nullptr)360 "Alias for -o", nullptr, nullptr)
338OPTION(prefix_3, "output", anonymous_22, Separate, INVALID, o, nullptr, 0, 0,361OPTION(prefix_3, "output", anonymous_23, Separate, INVALID, o, nullptr, 0, 0,
339 "Alias for -o", nullptr, nullptr)362 "Alias for -o", nullptr, nullptr)
340OPTION(prefix_1, "O", O, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,363OPTION(prefix_1, "O", O, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
341 "Optimize output file size", nullptr, nullptr)364 "Optimize output file size", nullptr, nullptr)
342OPTION(prefix_1, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,365OPTION(prefix_1, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
343 "Path to file to write output", "<path>", nullptr)366 "Path to file to write output", "<path>", nullptr)
367OPTION(prefix_2, "pac-plt", pac_plt, Flag, INVALID, INVALID, nullptr, 0, 0,
368 "AArch64 only, use pointer authentication in PLT", nullptr, nullptr)
344OPTION(prefix_2, "pack-dyn-relocs=", pack_dyn_relocs_eq, Joined, INVALID, pack_dyn_relocs, nullptr, 0, 0,369OPTION(prefix_2, "pack-dyn-relocs=", pack_dyn_relocs_eq, Joined, INVALID, pack_dyn_relocs, nullptr, 0, 0,
345 "Pack dynamic relocations in the given format", "[none,android,relr,android+relr]", nullptr)370 "Pack dynamic relocations in the given format", "[none,android,relr,android+relr]", nullptr)
346OPTION(prefix_2, "pack-dyn-relocs", pack_dyn_relocs, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "[none,android,relr,android+relr]", nullptr)371OPTION(prefix_2, "pack-dyn-relocs", pack_dyn_relocs, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "[none,android,relr,android+relr]", nullptr)
347OPTION(prefix_2, "pic-executable", anonymous_23, Flag, INVALID, pie, nullptr, 0, 0,372OPTION(prefix_2, "pic-executable", anonymous_24, Flag, INVALID, pie, nullptr, 0, 0,
348 "Alias for --pie", nullptr, nullptr)373 "Alias for --pie", nullptr, nullptr)
349OPTION(prefix_2, "pic-veneer", pic_veneer, Flag, INVALID, INVALID, nullptr, 0, 0,374OPTION(prefix_2, "pic-veneer", pic_veneer, Flag, INVALID, INVALID, nullptr, 0, 0,
350 "Always generate position independent thunks (veneers)", nullptr, nullptr)375 "Always generate position independent thunks (veneers)", nullptr, nullptr)
...@@ -353,26 +378,30 @@ OPTION(prefix_2, "pie", pie, Flag, INVALID, INVALID, nullptr, 0, 0,...@@ -353,26 +378,30 @@ OPTION(prefix_2, "pie", pie, Flag, INVALID, INVALID, nullptr, 0, 0,
353OPTION(prefix_2, "plugin-opt=-fresolution=", plugin_opt_fresolution_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)378OPTION(prefix_2, "plugin-opt=-fresolution=", plugin_opt_fresolution_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
354OPTION(prefix_2, "plugin-opt=-pass-through=", plugin_opt_pass_through_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)379OPTION(prefix_2, "plugin-opt=-pass-through=", plugin_opt_pass_through_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
355OPTION(prefix_2, "plugin-opt=/", plugin_opt_slash, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)380OPTION(prefix_2, "plugin-opt=/", plugin_opt_slash, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
356OPTION(prefix_2, "plugin-opt=debug-pass-manager", anonymous_40, Flag, INVALID, lto_debug_pass_manager, nullptr, 0, 0,381OPTION(prefix_2, "plugin-opt=cs-profile-generate", anonymous_46, Flag, INVALID, lto_cs_profile_generate, nullptr, 0, 0,
382 "Alias for -lto-cs-profile-generate", nullptr, nullptr)
383OPTION(prefix_2, "plugin-opt=cs-profile-path=", anonymous_47, Joined, INVALID, lto_cs_profile_file, nullptr, 0, 0,
384 "Alias for -lto-cs-profile-file", nullptr, nullptr)
385OPTION(prefix_2, "plugin-opt=debug-pass-manager", anonymous_41, Flag, INVALID, lto_debug_pass_manager, nullptr, 0, 0,
357 "Alias for -lto-debug-pass-manager", nullptr, nullptr)386 "Alias for -lto-debug-pass-manager", nullptr, nullptr)
358OPTION(prefix_2, "plugin-opt=disable-verify", anonymous_41, Flag, INVALID, disable_verify, nullptr, 0, 0,387OPTION(prefix_2, "plugin-opt=disable-verify", anonymous_42, Flag, INVALID, disable_verify, nullptr, 0, 0,
359 "Alias for -disable-verify", nullptr, nullptr)388 "Alias for -disable-verify", nullptr, nullptr)
360OPTION(prefix_2, "plugin-opt=dwo_dir=", plugin_opt_dwo_dir_eq, Joined, INVALID, INVALID, nullptr, 0, 0,389OPTION(prefix_2, "plugin-opt=dwo_dir=", plugin_opt_dwo_dir_eq, Joined, INVALID, INVALID, nullptr, 0, 0,
361 "Directory to store .dwo files when LTO and debug fission are used", nullptr, nullptr)390 "Directory to store .dwo files when LTO and debug fission are used", nullptr, nullptr)
362OPTION(prefix_2, "plugin-opt=emit-llvm", plugin_opt_emit_llvm, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)391OPTION(prefix_2, "plugin-opt=emit-llvm", plugin_opt_emit_llvm, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
363OPTION(prefix_2, "plugin-opt=jobs=", anonymous_42, Joined, INVALID, thinlto_jobs, nullptr, 0, 0,392OPTION(prefix_2, "plugin-opt=jobs=", anonymous_43, Joined, INVALID, thinlto_jobs, nullptr, 0, 0,
364 "Alias for -thinlto-jobs", nullptr, nullptr)393 "Alias for -thinlto-jobs", nullptr, nullptr)
365OPTION(prefix_2, "plugin-opt=lto-partitions=", anonymous_43, Joined, INVALID, lto_partitions, nullptr, 0, 0,394OPTION(prefix_2, "plugin-opt=lto-partitions=", anonymous_44, Joined, INVALID, lto_partitions, nullptr, 0, 0,
366 "Alias for -lto-partitions", nullptr, nullptr)395 "Alias for -lto-partitions", nullptr, nullptr)
367OPTION(prefix_2, "plugin-opt=mcpu=", plugin_opt_mcpu_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)396OPTION(prefix_2, "plugin-opt=mcpu=", plugin_opt_mcpu_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
368OPTION(prefix_2, "plugin-opt=new-pass-manager", anonymous_44, Flag, INVALID, lto_new_pass_manager, nullptr, 0, 0,397OPTION(prefix_2, "plugin-opt=new-pass-manager", anonymous_45, Flag, INVALID, lto_new_pass_manager, nullptr, 0, 0,
369 "Alias for -lto-new-pass-manager", nullptr, nullptr)398 "Alias for -lto-new-pass-manager", nullptr, nullptr)
370OPTION(prefix_2, "plugin-opt=obj-path=", plugin_opt_obj_path_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)399OPTION(prefix_2, "plugin-opt=obj-path=", plugin_opt_obj_path_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
371OPTION(prefix_2, "plugin-opt=O", anonymous_39, Joined, INVALID, lto_O, nullptr, 0, 0,400OPTION(prefix_2, "plugin-opt=O", anonymous_40, Joined, INVALID, lto_O, nullptr, 0, 0,
372 "Alias for -lto-O", nullptr, nullptr)401 "Alias for -lto-O", nullptr, nullptr)
373OPTION(prefix_2, "plugin-opt=sample-profile=", anonymous_45, Joined, INVALID, lto_sample_profile, nullptr, 0, 0,402OPTION(prefix_2, "plugin-opt=sample-profile=", anonymous_48, Joined, INVALID, lto_sample_profile, nullptr, 0, 0,
374 "Alias for -lto-sample-profile", nullptr, nullptr)403 "Alias for -lto-sample-profile", nullptr, nullptr)
375OPTION(prefix_2, "plugin-opt=save-temps", anonymous_46, Flag, INVALID, save_temps, nullptr, 0, 0,404OPTION(prefix_2, "plugin-opt=save-temps", anonymous_49, Flag, INVALID, save_temps, nullptr, 0, 0,
376 "Alias for -save-temps", nullptr, nullptr)405 "Alias for -save-temps", nullptr, nullptr)
377OPTION(prefix_2, "plugin-opt=thinlto-emit-imports-files", plugin_opt_thinlto_emit_imports_files, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)406OPTION(prefix_2, "plugin-opt=thinlto-emit-imports-files", plugin_opt_thinlto_emit_imports_files, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
378OPTION(prefix_2, "plugin-opt=thinlto-index-only=", plugin_opt_thinlto_index_only_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)407OPTION(prefix_2, "plugin-opt=thinlto-index-only=", plugin_opt_thinlto_index_only_eq, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
...@@ -394,9 +423,13 @@ OPTION(prefix_2, "print-icf-sections", print_icf_sections, Flag, INVALID, INVALI...@@ -394,9 +423,13 @@ OPTION(prefix_2, "print-icf-sections", print_icf_sections, Flag, INVALID, INVALI
394 "List identical folded sections", nullptr, nullptr)423 "List identical folded sections", nullptr, nullptr)
395OPTION(prefix_2, "print-map", print_map, Flag, INVALID, INVALID, nullptr, 0, 0,424OPTION(prefix_2, "print-map", print_map, Flag, INVALID, INVALID, nullptr, 0, 0,
396 "Print a link map to the standard output", nullptr, nullptr)425 "Print a link map to the standard output", nullptr, nullptr)
426OPTION(prefix_2, "print-symbol-order=", print_symbol_order_eq, Joined, INVALID, print_symbol_order, nullptr, 0, 0,
427 "Print a symbol order specified by --call-graph-ordering-file into the speficied file", nullptr, nullptr)
428OPTION(prefix_2, "print-symbol-order", print_symbol_order, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
397OPTION(prefix_2, "push-state", push_state, Flag, INVALID, INVALID, nullptr, 0, 0,429OPTION(prefix_2, "push-state", push_state, Flag, INVALID, INVALID, nullptr, 0, 0,
398 "Save the current state of -as-needed, -static and -whole-archive", nullptr, nullptr)430 "Save the current state of -as-needed, -static and -whole-archive", nullptr, nullptr)
399OPTION(prefix_2, "Qy", anonymous_68, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)431OPTION(prefix_1, "p", anonymous_60, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
432OPTION(prefix_2, "Qy", anonymous_72, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
400OPTION(prefix_1, "q", anonymous_11, Flag, INVALID, emit_relocs, nullptr, 0, 0,433OPTION(prefix_1, "q", anonymous_11, Flag, INVALID, emit_relocs, nullptr, 0, 0,
401 "Alias for --emit-relocs", nullptr, nullptr)434 "Alias for --emit-relocs", nullptr, nullptr)
402OPTION(prefix_2, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0, 0,435OPTION(prefix_2, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -404,20 +437,21 @@ OPTION(prefix_2, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0,...@@ -404,20 +437,21 @@ OPTION(prefix_2, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0,
404OPTION(prefix_2, "reproduce=", reproduce_eq, Joined, INVALID, reproduce, nullptr, 0, 0,437OPTION(prefix_2, "reproduce=", reproduce_eq, Joined, INVALID, reproduce, nullptr, 0, 0,
405 "Dump linker invocation and input files for debugging", nullptr, nullptr)438 "Dump linker invocation and input files for debugging", nullptr, nullptr)
406OPTION(prefix_2, "reproduce", reproduce, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)439OPTION(prefix_2, "reproduce", reproduce, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
440OPTION(prefix_2, "require-cet", require_cet, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
407OPTION(prefix_2, "retain-symbols-file=", retain_symbols_file_eq, Joined, INVALID, retain_symbols_file, nullptr, 0, 0,441OPTION(prefix_2, "retain-symbols-file=", retain_symbols_file_eq, Joined, INVALID, retain_symbols_file, nullptr, 0, 0,
408 "Retain only the symbols listed in the file", "<file>", nullptr)442 "Retain only the symbols listed in the file", "<file>", nullptr)
409OPTION(prefix_2, "retain-symbols-file", retain_symbols_file, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<file>", nullptr)443OPTION(prefix_2, "retain-symbols-file", retain_symbols_file, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<file>", nullptr)
410OPTION(prefix_2, "rpath-link=", anonymous_59, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)444OPTION(prefix_2, "rpath-link=", anonymous_62, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
411OPTION(prefix_2, "rpath-link", anonymous_58, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)445OPTION(prefix_2, "rpath-link", anonymous_61, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
412OPTION(prefix_2, "rpath=", rpath_eq, Joined, INVALID, rpath, nullptr, 0, 0,446OPTION(prefix_2, "rpath=", rpath_eq, Joined, INVALID, rpath, nullptr, 0, 0,
413 "Add a DT_RUNPATH to the output", nullptr, nullptr)447 "Add a DT_RUNPATH to the output", nullptr, nullptr)
414OPTION(prefix_2, "rpath", rpath, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)448OPTION(prefix_2, "rpath", rpath, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
415OPTION(prefix_2, "rsp-quoting=", rsp_quoting_eq, Joined, INVALID, rsp_quoting, nullptr, 0, 0,449OPTION(prefix_2, "rsp-quoting=", rsp_quoting_eq, Joined, INVALID, rsp_quoting, nullptr, 0, 0,
416 "Quoting style for response files", "[posix,windows]", nullptr)450 "Quoting style for response files", "[posix,windows]", nullptr)
417OPTION(prefix_2, "rsp-quoting", rsp_quoting, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "[posix,windows]", nullptr)451OPTION(prefix_2, "rsp-quoting", rsp_quoting, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "[posix,windows]", nullptr)
418OPTION(prefix_1, "R", anonymous_26, JoinedOrSeparate, INVALID, rpath, nullptr, 0, 0,452OPTION(prefix_1, "R", anonymous_27, JoinedOrSeparate, INVALID, rpath, nullptr, 0, 0,
419 "Alias for --rpath", nullptr, nullptr)453 "Alias for --rpath", nullptr, nullptr)
420OPTION(prefix_1, "r", anonymous_25, Flag, INVALID, relocatable, nullptr, 0, 0,454OPTION(prefix_1, "r", anonymous_26, Flag, INVALID, relocatable, nullptr, 0, 0,
421 "Alias for --relocatable", nullptr, nullptr)455 "Alias for --relocatable", nullptr, nullptr)
422OPTION(prefix_2, "save-temps", save_temps, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)456OPTION(prefix_2, "save-temps", save_temps, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
423OPTION(prefix_2, "script=", script_eq, Joined, INVALID, script, nullptr, 0, 0,457OPTION(prefix_2, "script=", script_eq, Joined, INVALID, script, nullptr, 0, 0,
...@@ -426,12 +460,13 @@ OPTION(prefix_2, "script", script, Separate, INVALID, INVALID, nullptr, 0, 0, nu...@@ -426,12 +460,13 @@ OPTION(prefix_2, "script", script, Separate, INVALID, INVALID, nullptr, 0, 0, nu
426OPTION(prefix_2, "section-start=", section_start_eq, Joined, INVALID, section_start, nullptr, 0, 0,460OPTION(prefix_2, "section-start=", section_start_eq, Joined, INVALID, section_start, nullptr, 0, 0,
427 "Set address of section", "<address>", nullptr)461 "Set address of section", "<address>", nullptr)
428OPTION(prefix_2, "section-start", section_start, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<address>", nullptr)462OPTION(prefix_2, "section-start", section_start, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<address>", nullptr)
463OPTION(prefix_2, "secure-plt", anonymous_63, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
429OPTION(prefix_2, "shared", shared, Flag, INVALID, INVALID, nullptr, 0, 0,464OPTION(prefix_2, "shared", shared, Flag, INVALID, INVALID, nullptr, 0, 0,
430 "Build a shared object", nullptr, nullptr)465 "Build a shared object", nullptr, nullptr)
431OPTION(prefix_2, "soname=", soname_eq, Joined, INVALID, soname, nullptr, 0, 0,466OPTION(prefix_2, "soname=", soname_eq, Joined, INVALID, soname, nullptr, 0, 0,
432 "Set DT_SONAME", nullptr, nullptr)467 "Set DT_SONAME", nullptr, nullptr)
433OPTION(prefix_2, "soname", soname, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)468OPTION(prefix_2, "soname", soname, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
434OPTION(prefix_2, "sort-common", anonymous_60, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)469OPTION(prefix_2, "sort-common", anonymous_64, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
435OPTION(prefix_2, "sort-section=", sort_section_eq, Joined, INVALID, sort_section, nullptr, 0, 0,470OPTION(prefix_2, "sort-section=", sort_section_eq, Joined, INVALID, sort_section, nullptr, 0, 0,
436 "Specifies sections sorting rule when linkerscript is used", nullptr, nullptr)471 "Specifies sections sorting rule when linkerscript is used", nullptr, nullptr)
437OPTION(prefix_2, "sort-section", sort_section, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)472OPTION(prefix_2, "sort-section", sort_section, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
...@@ -444,7 +479,7 @@ OPTION(prefix_2, "start-lib", start_lib, Flag, INVALID, INVALID, nullptr, 0, 0,...@@ -444,7 +479,7 @@ OPTION(prefix_2, "start-lib", start_lib, Flag, INVALID, INVALID, nullptr, 0, 0,
444 "Start a grouping of objects that should be treated as if they were together in an archive", nullptr, nullptr)479 "Start a grouping of objects that should be treated as if they were together in an archive", nullptr, nullptr)
445OPTION(prefix_2, "static", anonymous_5, Flag, INVALID, Bstatic, nullptr, 0, 0,480OPTION(prefix_2, "static", anonymous_5, Flag, INVALID, Bstatic, nullptr, 0, 0,
446 "Alias for --Bstatic", nullptr, nullptr)481 "Alias for --Bstatic", nullptr, nullptr)
447OPTION(prefix_2, "stats", anonymous_61, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)482OPTION(prefix_2, "stats", anonymous_65, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
448OPTION(prefix_2, "strip-all", strip_all, Flag, INVALID, INVALID, nullptr, 0, 0,483OPTION(prefix_2, "strip-all", strip_all, Flag, INVALID, INVALID, nullptr, 0, 0,
449 "Strip all symbols", nullptr, nullptr)484 "Strip all symbols", nullptr, nullptr)
450OPTION(prefix_2, "strip-debug", strip_debug, Flag, INVALID, INVALID, nullptr, 0, 0,485OPTION(prefix_2, "strip-debug", strip_debug, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -455,9 +490,9 @@ OPTION(prefix_2, "symbol-ordering-file", symbol_ordering_file, Separate, INVALID...@@ -455,9 +490,9 @@ OPTION(prefix_2, "symbol-ordering-file", symbol_ordering_file, Separate, INVALID
455OPTION(prefix_2, "sysroot=", sysroot_eq, Joined, INVALID, sysroot, nullptr, 0, 0,490OPTION(prefix_2, "sysroot=", sysroot_eq, Joined, INVALID, sysroot, nullptr, 0, 0,
456 "Set the system root", nullptr, nullptr)491 "Set the system root", nullptr, nullptr)
457OPTION(prefix_2, "sysroot", sysroot, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)492OPTION(prefix_2, "sysroot", sysroot, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
458OPTION(prefix_1, "S", anonymous_32, Flag, INVALID, strip_debug, nullptr, 0, 0,493OPTION(prefix_1, "S", anonymous_33, Flag, INVALID, strip_debug, nullptr, 0, 0,
459 "Alias for --strip-debug", nullptr, nullptr)494 "Alias for --strip-debug", nullptr, nullptr)
460OPTION(prefix_1, "s", anonymous_31, Flag, INVALID, strip_all, nullptr, 0, 0,495OPTION(prefix_1, "s", anonymous_32, Flag, INVALID, strip_all, nullptr, 0, 0,
461 "Alias for --strip-all", nullptr, nullptr)496 "Alias for --strip-all", nullptr, nullptr)
462OPTION(prefix_2, "target1-abs", target1_abs, Flag, INVALID, INVALID, nullptr, 0, 0,497OPTION(prefix_2, "target1-abs", target1_abs, Flag, INVALID, INVALID, nullptr, 0, 0,
463 "Interpret R_ARM_TARGET1 as R_ARM_ABS32 (default)", nullptr, nullptr)498 "Interpret R_ARM_TARGET1 as R_ARM_ABS32 (default)", nullptr, nullptr)
...@@ -488,17 +523,20 @@ OPTION(prefix_2, "trace-symbol=", trace_symbol_eq, Joined, INVALID, trace_symbol...@@ -488,17 +523,20 @@ OPTION(prefix_2, "trace-symbol=", trace_symbol_eq, Joined, INVALID, trace_symbol
488OPTION(prefix_2, "trace-symbol", trace_symbol, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)523OPTION(prefix_2, "trace-symbol", trace_symbol, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
489OPTION(prefix_2, "trace", trace, Flag, INVALID, INVALID, nullptr, 0, 0,524OPTION(prefix_2, "trace", trace, Flag, INVALID, INVALID, nullptr, 0, 0,
490 "Print the names of the input files", nullptr, nullptr)525 "Print the names of the input files", nullptr, nullptr)
491OPTION(prefix_4, "Ttext-segment=", anonymous_36, Joined, INVALID, Ttext, nullptr, 0, 0,526OPTION(prefix_4, "Ttext-segment=", anonymous_37, Joined, INVALID, Ttext, nullptr, 0, 0,
492 "Alias for --Ttext", nullptr, nullptr)527 "Alias for --Ttext", nullptr, nullptr)
493OPTION(prefix_4, "Ttext-segment", anonymous_35, Separate, INVALID, Ttext, nullptr, 0, 0,528OPTION(prefix_4, "Ttext-segment", anonymous_36, Separate, INVALID, Ttext, nullptr, 0, 0,
494 "Alias for --Ttext", nullptr, nullptr)529 "Alias for --Ttext", nullptr, nullptr)
495OPTION(prefix_2, "Ttext=", Ttext_eq, Joined, INVALID, Ttext, nullptr, 0, 0,530OPTION(prefix_2, "Ttext=", Ttext_eq, Joined, INVALID, Ttext, nullptr, 0, 0,
496 "Same as --section-start with .text as the sectionname", nullptr, nullptr)531 "Same as --section-start with .text as the sectionname", nullptr, nullptr)
497OPTION(prefix_2, "Ttext", Ttext, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)532OPTION(prefix_2, "Ttext", Ttext, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
498OPTION(prefix_1, "T", anonymous_27, JoinedOrSeparate, INVALID, script, nullptr, 0, 0,533OPTION(prefix_1, "T", anonymous_28, JoinedOrSeparate, INVALID, script, nullptr, 0, 0,
499 "Alias for --script", nullptr, nullptr)534 "Alias for --script", nullptr, nullptr)
500OPTION(prefix_1, "t", anonymous_33, Flag, INVALID, trace, nullptr, 0, 0,535OPTION(prefix_1, "t", anonymous_34, Flag, INVALID, trace, nullptr, 0, 0,
501 "Alias for --trace", nullptr, nullptr)536 "Alias for --trace", nullptr, nullptr)
537OPTION(prefix_2, "undefined-glob=", undefined_glob_eq, Joined, INVALID, undefined_glob, nullptr, 0, 0,
538 "Force undefined symbol during linking", "<pattern>", nullptr)
539OPTION(prefix_2, "undefined-glob", undefined_glob, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<pattern>", nullptr)
502OPTION(prefix_2, "undefined-version", undefined_version, Flag, INVALID, INVALID, nullptr, 0, 0,540OPTION(prefix_2, "undefined-version", undefined_version, Flag, INVALID, INVALID, nullptr, 0, 0,
503 "Allow unused version in version script (default)", nullptr, nullptr)541 "Allow unused version in version script (default)", nullptr, nullptr)
504OPTION(prefix_2, "undefined=", undefined_eq, Joined, INVALID, undefined, nullptr, 0, 0,542OPTION(prefix_2, "undefined=", undefined_eq, Joined, INVALID, undefined, nullptr, 0, 0,
...@@ -509,7 +547,7 @@ OPTION(prefix_2, "unresolved-symbols=", unresolved_symbols_eq, Joined, INVALID,...@@ -509,7 +547,7 @@ OPTION(prefix_2, "unresolved-symbols=", unresolved_symbols_eq, Joined, INVALID,
509OPTION(prefix_2, "unresolved-symbols", unresolved_symbols, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)547OPTION(prefix_2, "unresolved-symbols", unresolved_symbols, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
510OPTION(prefix_2, "use-android-relr-tags", use_android_relr_tags, Flag, INVALID, INVALID, nullptr, 0, 0,548OPTION(prefix_2, "use-android-relr-tags", use_android_relr_tags, Flag, INVALID, INVALID, nullptr, 0, 0,
511 "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*", nullptr, nullptr)549 "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*", nullptr, nullptr)
512OPTION(prefix_1, "u", anonymous_37, JoinedOrSeparate, INVALID, undefined, nullptr, 0, 0,550OPTION(prefix_1, "u", anonymous_38, JoinedOrSeparate, INVALID, undefined, nullptr, 0, 0,
513 "Alias for --undefined", nullptr, nullptr)551 "Alias for --undefined", nullptr, nullptr)
514OPTION(prefix_2, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0,552OPTION(prefix_2, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0,
515 "Verbose mode", nullptr, nullptr)553 "Verbose mode", nullptr, nullptr)
...@@ -518,7 +556,9 @@ OPTION(prefix_2, "version-script=", version_script_eq, Joined, INVALID, version_...@@ -518,7 +556,9 @@ OPTION(prefix_2, "version-script=", version_script_eq, Joined, INVALID, version_
518OPTION(prefix_2, "version-script", version_script, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)556OPTION(prefix_2, "version-script", version_script, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
519OPTION(prefix_2, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0,557OPTION(prefix_2, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0,
520 "Display the version number and exit", nullptr, nullptr)558 "Display the version number and exit", nullptr, nullptr)
521OPTION(prefix_1, "V", anonymous_38, Flag, INVALID, version, nullptr, 0, 0,559OPTION(prefix_2, "vs-diagnostics", visual_studio_diagnostics_format, Flag, INVALID, INVALID, nullptr, 0, 0,
560 "Format diagnostics for Visual Studio compatiblity", nullptr, nullptr)
561OPTION(prefix_1, "V", anonymous_39, Flag, INVALID, version, nullptr, 0, 0,
522 "Alias for --version", nullptr, nullptr)562 "Alias for --version", nullptr, nullptr)
523OPTION(prefix_1, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0,563OPTION(prefix_1, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0,
524 "Display the version number", nullptr, nullptr)564 "Display the version number", nullptr, nullptr)
...@@ -526,11 +566,11 @@ OPTION(prefix_2, "warn-backrefs", warn_backrefs, Flag, INVALID, INVALID, nullptr...@@ -526,11 +566,11 @@ OPTION(prefix_2, "warn-backrefs", warn_backrefs, Flag, INVALID, INVALID, nullptr
526 "Warn about backward symbol references to fetch archive members", nullptr, nullptr)566 "Warn about backward symbol references to fetch archive members", nullptr, nullptr)
527OPTION(prefix_2, "warn-common", warn_common, Flag, INVALID, INVALID, nullptr, 0, 0,567OPTION(prefix_2, "warn-common", warn_common, Flag, INVALID, INVALID, nullptr, 0, 0,
528 "Warn about duplicate common symbols", nullptr, nullptr)568 "Warn about duplicate common symbols", nullptr, nullptr)
529OPTION(prefix_2, "warn-execstack", anonymous_62, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)569OPTION(prefix_2, "warn-execstack", anonymous_66, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
530OPTION(prefix_2, "warn-ifunc-textrel", warn_ifunc_textrel, Flag, INVALID, INVALID, nullptr, 0, 0,570OPTION(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)571 "Warn about using ifunc symbols with text relocations", nullptr, nullptr)
532OPTION(prefix_2, "warn-once", anonymous_63, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)572OPTION(prefix_2, "warn-once", anonymous_67, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
533OPTION(prefix_2, "warn-shared-textrel", anonymous_64, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)573OPTION(prefix_2, "warn-shared-textrel", anonymous_68, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
534OPTION(prefix_2, "warn-symbol-ordering", warn_symbol_ordering, Flag, INVALID, INVALID, nullptr, 0, 0,574OPTION(prefix_2, "warn-symbol-ordering", warn_symbol_ordering, Flag, INVALID, INVALID, nullptr, 0, 0,
535 "Warn about problems with the symbol ordering file (default)", nullptr, nullptr)575 "Warn about problems with the symbol ordering file (default)", nullptr, nullptr)
536OPTION(prefix_2, "warn-unresolved-symbols", warn_unresolved_symbols, Flag, INVALID, INVALID, nullptr, 0, 0,576OPTION(prefix_2, "warn-unresolved-symbols", warn_unresolved_symbols, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -544,7 +584,7 @@ OPTION(prefix_1, "X", anonymous_10, Flag, INVALID, discard_locals, nullptr, 0, 0...@@ -544,7 +584,7 @@ OPTION(prefix_1, "X", anonymous_10, Flag, INVALID, discard_locals, nullptr, 0, 0
544 "Alias for --discard-locals", nullptr, nullptr)584 "Alias for --discard-locals", nullptr, nullptr)
545OPTION(prefix_1, "x", anonymous_9, Flag, INVALID, discard_all, nullptr, 0, 0,585OPTION(prefix_1, "x", anonymous_9, Flag, INVALID, discard_all, nullptr, 0, 0,
546 "Alias for --discard-all", nullptr, nullptr)586 "Alias for --discard-all", nullptr, nullptr)
547OPTION(prefix_1, "y", anonymous_34, JoinedOrSeparate, INVALID, trace_symbol, nullptr, 0, 0,587OPTION(prefix_1, "y", anonymous_35, JoinedOrSeparate, INVALID, trace_symbol, nullptr, 0, 0,
548 "Alias for --trace-symbol", nullptr, nullptr)588 "Alias for --trace-symbol", nullptr, nullptr)
549OPTION(prefix_1, "z", z, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,589OPTION(prefix_1, "z", z, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
550 "Linker option extensions", "<option>", nullptr)590 "Linker option extensions", "<option>", nullptr)
deps/lld-prebuilt/MinGW/Options.inc+50-26
...@@ -30,31 +30,39 @@ OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullp...@@ -30,31 +30,39 @@ OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullp
30OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)30OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
31OPTION(prefix_1, "###", _HASH_HASH_HASH, Flag, INVALID, INVALID, nullptr, 0, 0,31OPTION(prefix_1, "###", _HASH_HASH_HASH, Flag, INVALID, INVALID, nullptr, 0, 0,
32 "Print (but do not run) the commands to run for this compilation", nullptr, nullptr)32 "Print (but do not run) the commands to run for this compilation", nullptr, nullptr)
33OPTION(prefix_2, "appcontainer", appcontainer, Flag, INVALID, INVALID, nullptr, 0, 0,
34 "Set the appcontainer flag in the executable", nullptr, nullptr)
33OPTION(prefix_2, "Bdynamic", Bdynamic, Flag, INVALID, INVALID, nullptr, 0, 0,35OPTION(prefix_2, "Bdynamic", Bdynamic, Flag, INVALID, INVALID, nullptr, 0, 0,
34 "Link against shared libraries", nullptr, nullptr)36 "Link against shared libraries", nullptr, nullptr)
35OPTION(prefix_2, "Bstatic", Bstatic, Flag, INVALID, INVALID, nullptr, 0, 0,37OPTION(prefix_2, "Bstatic", Bstatic, Flag, INVALID, INVALID, nullptr, 0, 0,
36 "Do not link against shared libraries", nullptr, nullptr)38 "Do not link against shared libraries", nullptr, nullptr)
37OPTION(prefix_2, "build-id", build_id, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)39OPTION(prefix_2, "build-id", anonymous_1, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
38OPTION(prefix_2, "disable-auto-image-base", disable_auto_image_base, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)40OPTION(prefix_2, "disable-auto-image-base", anonymous_2, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
39OPTION(prefix_2, "dynamicbase", dynamicbase, Flag, INVALID, INVALID, nullptr, 0, 0,41OPTION(prefix_2, "dynamicbase", dynamicbase, Flag, INVALID, INVALID, nullptr, 0, 0,
40 "Enable ASLR", nullptr, nullptr)42 "Enable ASLR", nullptr, nullptr)
41OPTION(prefix_2, "enable-auto-image-base", enable_auto_image_base, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)43OPTION(prefix_2, "enable-auto-image-base", anonymous_3, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
42OPTION(prefix_2, "enable-auto-import", enable_auto_import, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)44OPTION(prefix_2, "enable-auto-import", anonymous_4, Flag, INVALID, INVALID, nullptr, 0, 0,
43OPTION(prefix_2, "end-group", end_group, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)45 "Ignored; listed for libtool compatibility", nullptr, nullptr)
46OPTION(prefix_2, "end-group", anonymous_5, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
44OPTION(prefix_2, "entry", entry, Separate, INVALID, INVALID, nullptr, 0, 0,47OPTION(prefix_2, "entry", entry, Separate, INVALID, INVALID, nullptr, 0, 0,
45 "Name of entry point symbol", "<entry>", nullptr)48 "Name of entry point symbol", "<entry>", nullptr)
49OPTION(prefix_2, "exclude-all-symbols", exclude_all_symbols, Flag, INVALID, INVALID, nullptr, 0, 0,
50 "Don't automatically export any symbols", nullptr, nullptr)
46OPTION(prefix_2, "export-all-symbols", export_all_symbols, Flag, INVALID, INVALID, nullptr, 0, 0,51OPTION(prefix_2, "export-all-symbols", export_all_symbols, Flag, INVALID, INVALID, nullptr, 0, 0,
47 "Export all symbols even if a def file or dllexport attributes are used", nullptr, nullptr)52 "Export all symbols even if a def file or dllexport attributes are used", nullptr, nullptr)
48OPTION(prefix_1, "e", alias_entry_e, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr)53OPTION(prefix_1, "e", alias_entry_e, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr)
49OPTION(prefix_3, "full-shutdown", full_shutdown, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)54OPTION(prefix_3, "full-shutdown", anonymous_6, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
50OPTION(prefix_2, "gc-sections", gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,55OPTION(prefix_2, "gc-sections", gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,
51 "Remove unused sections", nullptr, nullptr)56 "Remove unused sections", nullptr, nullptr)
52OPTION(prefix_2, "high-entropy-va", high_entropy_va, Flag, INVALID, INVALID, nullptr, 0, 0,57OPTION(prefix_2, "help", help, Flag, INVALID, INVALID, nullptr, 0, 0,
53 "Enable 64-bit ASLR", nullptr, nullptr)58 "Print option help", nullptr, nullptr)
59OPTION(prefix_2, "high-entropy-va", anonymous_7, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
54OPTION(prefix_2, "icf=", icf, Joined, INVALID, INVALID, nullptr, 0, 0,60OPTION(prefix_2, "icf=", icf, Joined, INVALID, INVALID, nullptr, 0, 0,
55 "Identical code folding", nullptr, nullptr)61 "Identical code folding", nullptr, nullptr)
56OPTION(prefix_2, "image-base", image_base, Separate, INVALID, INVALID, nullptr, 0, 0,62OPTION(prefix_2, "image-base", image_base, Separate, INVALID, INVALID, nullptr, 0, 0,
57 "Base address of the program", nullptr, nullptr)63 "Base address of the program", nullptr, nullptr)
64OPTION(prefix_2, "insert-timestamp", insert_timestamp, Flag, INVALID, INVALID, nullptr, 0, 0,
65 "Include PE header timestamp", nullptr, nullptr)
58OPTION(prefix_2, "kill-at", kill_at, Flag, INVALID, INVALID, nullptr, 0, 0,66OPTION(prefix_2, "kill-at", kill_at, Flag, INVALID, INVALID, nullptr, 0, 0,
59 "Remove @n from exported symbols", nullptr, nullptr)67 "Remove @n from exported symbols", nullptr, nullptr)
60OPTION(prefix_3, "large-address-aware", large_address_aware, Flag, INVALID, INVALID, nullptr, 0, 0,68OPTION(prefix_3, "large-address-aware", large_address_aware, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -63,56 +71,72 @@ OPTION(prefix_1, "L", L, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,...@@ -63,56 +71,72 @@ OPTION(prefix_1, "L", L, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
63 "Add a directory to the library search path", "<dir>", nullptr)71 "Add a directory to the library search path", "<dir>", nullptr)
64OPTION(prefix_1, "l", l, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,72OPTION(prefix_1, "l", l, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
65 "Root name of library to use", "<libName>", nullptr)73 "Root name of library to use", "<libName>", nullptr)
66OPTION(prefix_2, "major-image-version", major_image_version, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)74OPTION(prefix_2, "major-image-version", anonymous_8, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
75OPTION(prefix_3, "major-os-version=", major_os_version_eq, Joined, INVALID, major_os_version, nullptr, 0, 0, nullptr, nullptr, nullptr)
76OPTION(prefix_3, "major-os-version", major_os_version, Separate, INVALID, INVALID, nullptr, 0, 0,
77 "Set the OS and subsystem major version", nullptr, nullptr)
78OPTION(prefix_3, "major-subsystem-version=", major_subsystem_version_eq, Joined, INVALID, major_subsystem_version, nullptr, 0, 0, nullptr, nullptr, nullptr)
79OPTION(prefix_3, "major-subsystem-version", major_subsystem_version, Separate, INVALID, INVALID, nullptr, 0, 0,
80 "Set the OS and subsystem major version", nullptr, nullptr)
67OPTION(prefix_2, "Map=", map_eq, Joined, INVALID, map, nullptr, 0, 0, nullptr, nullptr, nullptr)81OPTION(prefix_2, "Map=", map_eq, Joined, INVALID, map, nullptr, 0, 0, nullptr, nullptr, nullptr)
68OPTION(prefix_2, "Map", map, Separate, INVALID, INVALID, nullptr, 0, 0,82OPTION(prefix_2, "Map", map, Separate, INVALID, INVALID, nullptr, 0, 0,
69 "Output a linker map", nullptr, nullptr)83 "Output a linker map", nullptr, nullptr)
70OPTION(prefix_2, "minor-image-version", minor_image_version, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)84OPTION(prefix_2, "minor-image-version", anonymous_9, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
85OPTION(prefix_3, "minor-os-version=", minor_os_version_eq, Joined, INVALID, minor_os_version, nullptr, 0, 0, nullptr, nullptr, nullptr)
86OPTION(prefix_3, "minor-os-version", minor_os_version, Separate, INVALID, INVALID, nullptr, 0, 0,
87 "Set the OS and subsystem minor version", nullptr, nullptr)
88OPTION(prefix_3, "minor-subsystem-version=", minor_subsystem_version_eq, Joined, INVALID, minor_subsystem_version, nullptr, 0, 0, nullptr, nullptr, nullptr)
89OPTION(prefix_3, "minor-subsystem-version", minor_subsystem_version, Separate, INVALID, INVALID, nullptr, 0, 0,
90 "Set the OS and subsystem minor version", nullptr, nullptr)
71OPTION(prefix_2, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)91OPTION(prefix_2, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
72OPTION(prefix_1, "m", m, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,92OPTION(prefix_1, "m", m, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
73 "Set target emulation", nullptr, nullptr)93 "Set target emulation", nullptr, nullptr)
74OPTION(prefix_2, "no-gc-sections", no_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,94OPTION(prefix_2, "no-gc-sections", no_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,
75 "Don't remove unused sections", nullptr, nullptr)95 "Don't remove unused sections", nullptr, nullptr)
76OPTION(prefix_2, "no-seh", no_seh, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)96OPTION(prefix_2, "no-insert-timestamp", no_insert_timestamp, Flag, INVALID, INVALID, nullptr, 0, 0,
97 "Don't include PE header timestamp", nullptr, nullptr)
98OPTION(prefix_2, "no-seh", anonymous_10, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
77OPTION(prefix_2, "no-whole-archive", no_whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0,99OPTION(prefix_2, "no-whole-archive", no_whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0,
78 "No longer include all object files for following archives", nullptr, nullptr)100 "No longer include all object files for following archives", nullptr, nullptr)
79OPTION(prefix_2, "nxcompat", nxcompat, Flag, INVALID, INVALID, nullptr, 0, 0,101OPTION(prefix_2, "nxcompat", anonymous_11, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
80 "Enable data execution prevention", nullptr, nullptr)
81OPTION(prefix_3, "out-implib=", out_implib_eq, Joined, INVALID, out_implib, nullptr, 0, 0, nullptr, nullptr, nullptr)102OPTION(prefix_3, "out-implib=", out_implib_eq, Joined, INVALID, out_implib, nullptr, 0, 0, nullptr, nullptr, nullptr)
82OPTION(prefix_3, "out-implib", out_implib, Separate, INVALID, INVALID, nullptr, 0, 0,103OPTION(prefix_3, "out-implib", out_implib, Separate, INVALID, INVALID, nullptr, 0, 0,
83 "Import library name", nullptr, nullptr)104 "Import library name", nullptr, nullptr)
84OPTION(prefix_2, "output-def", output_def, Separate, INVALID, INVALID, nullptr, 0, 0,105OPTION(prefix_2, "output-def", output_def, Separate, INVALID, INVALID, nullptr, 0, 0,
85 "Output def file", nullptr, nullptr)106 "Output def file", nullptr, nullptr)
86OPTION(prefix_1, "O", O, Joined, INVALID, INVALID, nullptr, 0, 0,107OPTION(prefix_1, "O", anonymous_0, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
87 "Optimize output file size", nullptr, nullptr)
88OPTION(prefix_1, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,108OPTION(prefix_1, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
89 "Path to file to write output", "<path>", nullptr)109 "Path to file to write output", "<path>", nullptr)
110OPTION(prefix_2, "pdb=", pdb_eq, Joined, INVALID, pdb, nullptr, 0, 0, nullptr, nullptr, nullptr)
90OPTION(prefix_2, "pdb", pdb, Separate, INVALID, INVALID, nullptr, 0, 0,111OPTION(prefix_2, "pdb", pdb, Separate, INVALID, INVALID, nullptr, 0, 0,
91 "Specify output PDB debug information file", nullptr, nullptr)112 "Output PDB debug info file, chosen implicitly if the argument is empty", nullptr, nullptr)
92OPTION(prefix_2, "pic-executable", pic_executable, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)113OPTION(prefix_2, "pic-executable", anonymous_12, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
93OPTION(prefix_2, "plugin-opt=", anonymous_3, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)114OPTION(prefix_2, "plugin-opt=", anonymous_16, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
94OPTION(prefix_2, "plugin-opt", anonymous_2, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)115OPTION(prefix_2, "plugin-opt", anonymous_15, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
95OPTION(prefix_2, "plugin=", anonymous_1, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)116OPTION(prefix_2, "plugin=", anonymous_14, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
96OPTION(prefix_2, "plugin", anonymous_0, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)117OPTION(prefix_2, "plugin", anonymous_13, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
97OPTION(prefix_2, "require-defined=", require_defined_eq, Joined, INVALID, require_defined, nullptr, 0, 0, nullptr, nullptr, nullptr)118OPTION(prefix_2, "require-defined=", require_defined_eq, Joined, INVALID, require_defined, nullptr, 0, 0, nullptr, nullptr, nullptr)
98OPTION(prefix_2, "require-defined", require_defined, Separate, INVALID, INVALID, nullptr, 0, 0,119OPTION(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)120 "Force symbol to be added to symbol table as an undefined one", nullptr, nullptr)
100OPTION(prefix_2, "shared", shared, Flag, INVALID, INVALID, nullptr, 0, 0,121OPTION(prefix_2, "shared", shared, Flag, INVALID, INVALID, nullptr, 0, 0,
101 "Build a shared object", nullptr, nullptr)122 "Build a shared object", nullptr, nullptr)
102OPTION(prefix_2, "stack", stack, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)123OPTION(prefix_2, "stack", stack, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
103OPTION(prefix_2, "start-group", start_group, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)124OPTION(prefix_2, "start-group", anonymous_18, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
104OPTION(prefix_2, "strip-all", strip_all, Flag, INVALID, INVALID, nullptr, 0, 0,125OPTION(prefix_2, "strip-all", strip_all, Flag, INVALID, INVALID, nullptr, 0, 0,
105 "Omit all symbol information from the output binary", nullptr, nullptr)126 "Omit all symbol information from the output binary", nullptr, nullptr)
106OPTION(prefix_2, "strip-debug", strip_debug, Flag, INVALID, INVALID, nullptr, 0, 0,127OPTION(prefix_2, "strip-debug", strip_debug, Flag, INVALID, INVALID, nullptr, 0, 0,
107 "Omit all debug information, but keep symbol information", nullptr, nullptr)128 "Omit all debug information, but keep symbol information", nullptr, nullptr)
129OPTION(prefix_2, "subsystem=", subs_eq, Joined, INVALID, subs, nullptr, 0, 0, nullptr, nullptr, nullptr)
108OPTION(prefix_2, "subsystem", subs, Separate, INVALID, INVALID, nullptr, 0, 0,130OPTION(prefix_2, "subsystem", subs, Separate, INVALID, INVALID, nullptr, 0, 0,
109 "Specify subsystem", nullptr, nullptr)131 "Specify subsystem", nullptr, nullptr)
110OPTION(prefix_2, "sysroot", sysroot, Joined, INVALID, INVALID, nullptr, 0, 0,132OPTION(prefix_2, "sysroot", anonymous_17, Joined, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
111 "Sysroot", nullptr, nullptr)
112OPTION(prefix_1, "S", alias_strip_S, Flag, INVALID, strip_debug, nullptr, 0, 0, nullptr, nullptr, nullptr)133OPTION(prefix_1, "S", alias_strip_S, Flag, INVALID, strip_debug, nullptr, 0, 0, nullptr, nullptr, nullptr)
113OPTION(prefix_1, "s", alias_strip_s, Flag, INVALID, strip_all, nullptr, 0, 0, nullptr, nullptr, nullptr)134OPTION(prefix_1, "s", alias_strip_s, Flag, INVALID, strip_all, nullptr, 0, 0, nullptr, nullptr, nullptr)
114OPTION(prefix_2, "tsaware", tsaware, Flag, INVALID, INVALID, nullptr, 0, 0,135OPTION(prefix_2, "tsaware", anonymous_19, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
115 "Create Terminal Server aware executable", nullptr, nullptr)136OPTION(prefix_2, "undefined=", undefined_eq, Joined, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr)
137OPTION(prefix_2, "undefined", undefined_long, Separate, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr)
138OPTION(prefix_2, "u", undefined, Separate, INVALID, INVALID, nullptr, 0, 0,
139 "Include symbol in the link, if available", nullptr, nullptr)
116OPTION(prefix_2, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0,140OPTION(prefix_2, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0,
117 "Verbose mode", nullptr, nullptr)141 "Verbose mode", nullptr, nullptr)
118OPTION(prefix_2, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0,142OPTION(prefix_2, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0,
deps/lld-prebuilt/lld/Common/Version.inc+3-3
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1#define LLD_VERSION 8.0.01#define LLD_VERSION 9.0.0
2#define LLD_VERSION_STRING "8.0.0"2#define LLD_VERSION_STRING "9.0.0"
3#define LLD_VERSION_MAJOR 83#define LLD_VERSION_MAJOR 9
4#define LLD_VERSION_MINOR 04#define LLD_VERSION_MINOR 0
5#define LLD_REVISION_STRING ""5#define LLD_REVISION_STRING ""
6#define LLD_REPOSITORY_STRING ""6#define LLD_REPOSITORY_STRING ""
deps/lld-prebuilt/wasm/Options.inc+28-1
...@@ -27,11 +27,15 @@ PREFIX(prefix_1, {"--" COMMA "-" COMMA nullptr})...@@ -27,11 +27,15 @@ PREFIX(prefix_1, {"--" COMMA "-" COMMA nullptr})
2727
28OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)28OPTION(prefix_0, "<input>", INPUT, Input, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
29OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)29OPTION(prefix_0, "<unknown>", UNKNOWN, Unknown, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
30OPTION(prefix_1, "active-segments", active_segments, Flag, INVALID, INVALID, nullptr, 0, 0,
31 "Force segments to be active (default with unshared memory)", nullptr, nullptr)
30OPTION(prefix_1, "allow-undefined-file=", allow_undefined_file, Joined, INVALID, INVALID, nullptr, 0, 0,32OPTION(prefix_1, "allow-undefined-file=", allow_undefined_file, Joined, INVALID, INVALID, nullptr, 0, 0,
31 "Allow symbols listed in <file> to be undefined in linked binary", nullptr, nullptr)33 "Allow symbols listed in <file> to be undefined in linked binary", nullptr, nullptr)
32OPTION(prefix_2, "allow-undefined-file", allow_undefined_file_s, Separate, INVALID, allow_undefined_file, nullptr, 0, 0, nullptr, nullptr, nullptr)34OPTION(prefix_2, "allow-undefined-file", allow_undefined_file_s, Separate, INVALID, allow_undefined_file, nullptr, 0, 0, nullptr, nullptr, nullptr)
33OPTION(prefix_1, "allow-undefined", allow_undefined, Flag, INVALID, INVALID, nullptr, 0, 0,35OPTION(prefix_1, "allow-undefined", allow_undefined, Flag, INVALID, INVALID, nullptr, 0, 0,
34 "Allow undefined symbols in linked binary", nullptr, nullptr)36 "Allow undefined symbols in linked binary", nullptr, nullptr)
37OPTION(prefix_1, "check-features", check_features, Flag, INVALID, INVALID, nullptr, 0, 0,
38 "Check feature compatibility of linked objects (default)", nullptr, nullptr)
35OPTION(prefix_1, "color-diagnostics=", color_diagnostics_eq, Joined, INVALID, INVALID, nullptr, 0, 0,39OPTION(prefix_1, "color-diagnostics=", color_diagnostics_eq, Joined, INVALID, INVALID, nullptr, 0, 0,
36 "Use colors in diagnostics; one of 'always', 'never', 'auto'", nullptr, nullptr)40 "Use colors in diagnostics; one of 'always', 'never', 'auto'", nullptr, nullptr)
37OPTION(prefix_1, "color-diagnostics", color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0,41OPTION(prefix_1, "color-diagnostics", color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -41,6 +45,8 @@ OPTION(prefix_1, "compress-relocations", compress_relocations, Flag, INVALID, IN...@@ -41,6 +45,8 @@ OPTION(prefix_1, "compress-relocations", compress_relocations, Flag, INVALID, IN
41OPTION(prefix_1, "demangle", demangle, Flag, INVALID, INVALID, nullptr, 0, 0,45OPTION(prefix_1, "demangle", demangle, Flag, INVALID, INVALID, nullptr, 0, 0,
42 "Demangle symbol names", nullptr, nullptr)46 "Demangle symbol names", nullptr, nullptr)
43OPTION(prefix_1, "disable-verify", disable_verify, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)47OPTION(prefix_1, "disable-verify", disable_verify, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
48OPTION(prefix_1, "emit-relocs", emit_relocs, Flag, INVALID, INVALID, nullptr, 0, 0,
49 "Generate relocations in output", nullptr, nullptr)
44OPTION(prefix_1, "entry=", anonymous_1, Joined, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr)50OPTION(prefix_1, "entry=", anonymous_1, Joined, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr)
45OPTION(prefix_1, "entry", entry, Separate, INVALID, INVALID, nullptr, 0, 0,51OPTION(prefix_1, "entry", entry, Separate, INVALID, INVALID, nullptr, 0, 0,
46 "Name of entry point symbol", "<entry>", nullptr)52 "Name of entry point symbol", "<entry>", nullptr)
...@@ -60,6 +66,8 @@ OPTION(prefix_2, "E", anonymous_2, Flag, INVALID, export_dynamic, nullptr, 0, 0,...@@ -60,6 +66,8 @@ OPTION(prefix_2, "E", anonymous_2, Flag, INVALID, export_dynamic, nullptr, 0, 0,
60OPTION(prefix_2, "e", anonymous_0, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr)66OPTION(prefix_2, "e", anonymous_0, JoinedOrSeparate, INVALID, entry, nullptr, 0, 0, nullptr, nullptr, nullptr)
61OPTION(prefix_1, "fatal-warnings", fatal_warnings, Flag, INVALID, INVALID, nullptr, 0, 0,67OPTION(prefix_1, "fatal-warnings", fatal_warnings, Flag, INVALID, INVALID, nullptr, 0, 0,
62 "Treat warnings as errors", nullptr, nullptr)68 "Treat warnings as errors", nullptr, nullptr)
69OPTION(prefix_1, "features=", features, CommaJoined, INVALID, INVALID, nullptr, 0, 0,
70 "Comma-separated used features, inferred from input objects by default.", nullptr, nullptr)
63OPTION(prefix_1, "gc-sections", gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,71OPTION(prefix_1, "gc-sections", gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,
64 "Enable garbage collection of unused sections", nullptr, nullptr)72 "Enable garbage collection of unused sections", nullptr, nullptr)
65OPTION(prefix_1, "global-base=", global_base, Joined, INVALID, INVALID, nullptr, 0, 0,73OPTION(prefix_1, "global-base=", global_base, Joined, INVALID, INVALID, nullptr, 0, 0,
...@@ -88,6 +96,8 @@ OPTION(prefix_1, "merge-data-segments", merge_data_segments, Flag, INVALID, INVA...@@ -88,6 +96,8 @@ OPTION(prefix_1, "merge-data-segments", merge_data_segments, Flag, INVALID, INVA
88OPTION(prefix_1, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0,96OPTION(prefix_1, "mllvm", mllvm, Separate, INVALID, INVALID, nullptr, 0, 0,
89 "Options to pass to LLVM", nullptr, nullptr)97 "Options to pass to LLVM", nullptr, nullptr)
90OPTION(prefix_2, "m", anonymous_4, Flag, INVALID, max_memory, nullptr, 0, 0, nullptr, nullptr, nullptr)98OPTION(prefix_2, "m", anonymous_4, Flag, INVALID, max_memory, nullptr, 0, 0, nullptr, nullptr, nullptr)
99OPTION(prefix_1, "no-check-features", no_check_features, Flag, INVALID, INVALID, nullptr, 0, 0,
100 "Ignore feature compatibility of linked objects", nullptr, nullptr)
91OPTION(prefix_1, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0,101OPTION(prefix_1, "no-color-diagnostics", no_color_diagnostics, Flag, INVALID, INVALID, nullptr, 0, 0,
92 "Do not use colors in diagnostics", nullptr, nullptr)102 "Do not use colors in diagnostics", nullptr, nullptr)
93OPTION(prefix_1, "no-demangle", no_demangle, Flag, INVALID, INVALID, nullptr, 0, 0,103OPTION(prefix_1, "no-demangle", no_demangle, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -113,12 +123,17 @@ OPTION(prefix_2, "O", O, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,...@@ -113,12 +123,17 @@ OPTION(prefix_2, "O", O, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
113 "Optimize output file size", nullptr, nullptr)123 "Optimize output file size", nullptr, nullptr)
114OPTION(prefix_2, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,124OPTION(prefix_2, "o", o, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
115 "Path to file to write output", "<path>", nullptr)125 "Path to file to write output", "<path>", nullptr)
126OPTION(prefix_1, "passive-segments", passive_segments, Flag, INVALID, INVALID, nullptr, 0, 0,
127 "Force segments to be passive (default with shared memory)", nullptr, nullptr)
116OPTION(prefix_1, "pie", pie, Flag, INVALID, INVALID, nullptr, 0, 0,128OPTION(prefix_1, "pie", pie, Flag, INVALID, INVALID, nullptr, 0, 0,
117 "Create a position independent executable", nullptr, nullptr)129 "Create a position independent executable", nullptr, nullptr)
118OPTION(prefix_1, "print-gc-sections", print_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,130OPTION(prefix_1, "print-gc-sections", print_gc_sections, Flag, INVALID, INVALID, nullptr, 0, 0,
119 "List removed unused sections", nullptr, nullptr)131 "List removed unused sections", nullptr, nullptr)
120OPTION(prefix_1, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0, 0,132OPTION(prefix_1, "relocatable", relocatable, Flag, INVALID, INVALID, nullptr, 0, 0,
121 "Create relocatable object file", nullptr, nullptr)133 "Create relocatable object file", nullptr, nullptr)
134OPTION(prefix_1, "reproduce=", reproduce_eq, Joined, INVALID, reproduce, nullptr, 0, 0,
135 "Dump linker invocation and input files for debugging", nullptr, nullptr)
136OPTION(prefix_1, "reproduce", reproduce, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
122OPTION(prefix_2, "r", anonymous_5, Flag, INVALID, relocatable, nullptr, 0, 0, nullptr, nullptr, nullptr)137OPTION(prefix_2, "r", anonymous_5, Flag, INVALID, relocatable, nullptr, 0, 0, nullptr, nullptr, nullptr)
123OPTION(prefix_1, "save-temps", save_temps, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)138OPTION(prefix_1, "save-temps", save_temps, Flag, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
124OPTION(prefix_1, "shared-memory", shared_memory, Flag, INVALID, INVALID, nullptr, 0, 0,139OPTION(prefix_1, "shared-memory", shared_memory, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -144,10 +159,17 @@ OPTION(prefix_1, "thinlto-jobs=", thinlto_jobs, Joined, INVALID, INVALID, nullpt...@@ -144,10 +159,17 @@ OPTION(prefix_1, "thinlto-jobs=", thinlto_jobs, Joined, INVALID, INVALID, nullpt
144 "Number of ThinLTO jobs", nullptr, nullptr)159 "Number of ThinLTO jobs", nullptr, nullptr)
145OPTION(prefix_1, "threads", threads, Flag, INVALID, INVALID, nullptr, 0, 0,160OPTION(prefix_1, "threads", threads, Flag, INVALID, INVALID, nullptr, 0, 0,
146 "Run the linker multi-threaded", nullptr, nullptr)161 "Run the linker multi-threaded", nullptr, nullptr)
162OPTION(prefix_1, "trace-symbol=", trace_symbol_eq, Joined, INVALID, trace_symbol, nullptr, 0, 0,
163 "Trace references to symbols", nullptr, nullptr)
164OPTION(prefix_1, "trace-symbol", trace_symbol, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
165OPTION(prefix_1, "trace", trace, Flag, INVALID, INVALID, nullptr, 0, 0,
166 "Print the names of the input files", nullptr, nullptr)
167OPTION(prefix_2, "t", anonymous_8, Flag, INVALID, trace, nullptr, 0, 0,
168 "Alias for --trace", nullptr, nullptr)
147OPTION(prefix_1, "undefined=", undefined_eq, Joined, INVALID, undefined, nullptr, 0, 0,169OPTION(prefix_1, "undefined=", undefined_eq, Joined, INVALID, undefined, nullptr, 0, 0,
148 "Force undefined symbol during linking", nullptr, nullptr)170 "Force undefined symbol during linking", nullptr, nullptr)
149OPTION(prefix_1, "undefined", undefined, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)171OPTION(prefix_1, "undefined", undefined, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, nullptr, nullptr)
150OPTION(prefix_2, "u", anonymous_8, JoinedOrSeparate, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr)172OPTION(prefix_2, "u", anonymous_10, JoinedOrSeparate, INVALID, undefined, nullptr, 0, 0, nullptr, nullptr, nullptr)
151OPTION(prefix_1, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0,173OPTION(prefix_1, "verbose", verbose, Flag, INVALID, INVALID, nullptr, 0, 0,
152 "Verbose mode", nullptr, nullptr)174 "Verbose mode", nullptr, nullptr)
153OPTION(prefix_1, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0,175OPTION(prefix_1, "version", version, Flag, INVALID, INVALID, nullptr, 0, 0,
...@@ -156,6 +178,11 @@ OPTION(prefix_2, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0,...@@ -156,6 +178,11 @@ OPTION(prefix_2, "v", v, Flag, INVALID, INVALID, nullptr, 0, 0,
156 "Display the version number", nullptr, nullptr)178 "Display the version number", nullptr, nullptr)
157OPTION(prefix_1, "whole-archive", whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0,179OPTION(prefix_1, "whole-archive", whole_archive, Flag, INVALID, INVALID, nullptr, 0, 0,
158 "Force load of all members in a static library", nullptr, nullptr)180 "Force load of all members in a static library", nullptr, nullptr)
181OPTION(prefix_1, "wrap=", wrap_eq, Joined, INVALID, wrap, nullptr, 0, 0,
182 "Use wrapper functions for symbol", "<symbol>=<symbol>", nullptr)
183OPTION(prefix_1, "wrap", wrap, Separate, INVALID, INVALID, nullptr, 0, 0, nullptr, "<symbol>=<symbol>", nullptr)
184OPTION(prefix_2, "y", anonymous_9, JoinedOrSeparate, INVALID, trace_symbol, nullptr, 0, 0,
185 "Alias for --trace-symbol", nullptr, nullptr)
159OPTION(prefix_2, "z", z, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,186OPTION(prefix_2, "z", z, JoinedOrSeparate, INVALID, INVALID, nullptr, 0, 0,
160 "Linker option extensions", "<option>", nullptr)187 "Linker option extensions", "<option>", nullptr)
161#endif // OPTION188#endif // OPTION
deps/lld/COFF/CMakeLists.txt+1
...@@ -8,6 +8,7 @@ endif()...@@ -8,6 +8,7 @@ endif()
88
9add_lld_library(lldCOFF9add_lld_library(lldCOFF
10 Chunks.cpp10 Chunks.cpp
11 DebugTypes.cpp
11 DLL.cpp12 DLL.cpp
12 Driver.cpp13 Driver.cpp
13 DriverUtils.cpp14 DriverUtils.cpp
deps/lld/COFF/Chunks.cpp+444-405
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Chunks.cpp ---------------------------------------------------------===//1//===- Chunks.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -30,203 +29,201 @@ using llvm::support::ulittle32_t;...@@ -30,203 +29,201 @@ using llvm::support::ulittle32_t;
30namespace lld {29namespace lld {
31namespace coff {30namespace coff {
3231
33SectionChunk::SectionChunk(ObjFile *F, const coff_section *H)32SectionChunk::SectionChunk(ObjFile *f, const coff_section *h)
34 : Chunk(SectionKind), Repl(this), Header(H), File(F),33 : Chunk(SectionKind), file(f), header(h), repl(this) {
35 Relocs(File->getCOFFObj()->getRelocations(Header)) {34 // Initialize relocs.
36 // Initialize SectionName.35 setRelocs(file->getCOFFObj()->getRelocations(header));
37 File->getCOFFObj()->getSectionName(Header, SectionName);36
37 // Initialize sectionName.
38 StringRef sectionName;
39 if (Expected<StringRef> e = file->getCOFFObj()->getSectionName(header))
40 sectionName = *e;
41 sectionNameData = sectionName.data();
42 sectionNameSize = sectionName.size();
43
44 setAlignment(header->getAlignment());
3845
39 Alignment = Header->getAlignment();46 hasData = !(header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA);
4047
41 // If linker GC is disabled, every chunk starts out alive. If linker GC is48 // If linker GC is disabled, every chunk starts out alive. If linker GC is
42 // enabled, treat non-comdat sections as roots. Generally optimized object49 // enabled, treat non-comdat sections as roots. Generally optimized object
43 // files will be built with -ffunction-sections or /Gy, so most things worth50 // files will be built with -ffunction-sections or /Gy, so most things worth
44 // stripping will be in a comdat.51 // stripping will be in a comdat.
45 Live = !Config->DoGC || !isCOMDAT();52 live = !config->doGC || !isCOMDAT();
46}53}
4754
48// Initialize the RelocTargets vector, to allow redirecting certain relocations55// SectionChunk is one of the most frequently allocated classes, so it is
49// to a thunk instead of the actual symbol the relocation's symbol table index56// important to keep it as compact as possible. As of this writing, the number
50// indicates.57// below is the size of this class on x64 platforms.
51void SectionChunk::readRelocTargets() {58static_assert(sizeof(SectionChunk) <= 88, "SectionChunk grew unexpectedly");
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.
59void SectionChunk::resetRelocTargets() {
60 for (size_t I = 0, E = Relocs.size(); I < E; ++I)
61 RelocTargets[I] = File->getSymbol(Relocs[I].SymbolTableIndex);
62}
6359
64static void add16(uint8_t *P, int16_t V) { write16le(P, read16le(P) + V); }60static void add16(uint8_t *p, int16_t v) { write16le(p, read16le(p) + v); }
65static void add32(uint8_t *P, int32_t V) { write32le(P, read32le(P) + V); }61static void add32(uint8_t *p, int32_t v) { write32le(p, read32le(p) + v); }
66static void add64(uint8_t *P, int64_t V) { write64le(P, read64le(P) + V); }62static void add64(uint8_t *p, int64_t v) { write64le(p, read64le(p) + v); }
67static void or16(uint8_t *P, uint16_t V) { write16le(P, read16le(P) | V); }63static void or16(uint8_t *p, uint16_t v) { write16le(p, read16le(p) | v); }
68static void or32(uint8_t *P, uint32_t V) { write32le(P, read32le(P) | V); }64static void or32(uint8_t *p, uint32_t v) { write32le(p, read32le(p) | v); }
6965
70// Verify that given sections are appropriate targets for SECREL66// Verify that given sections are appropriate targets for SECREL
71// relocations. This check is relaxed because unfortunately debug67// relocations. This check is relaxed because unfortunately debug
72// sections have section-relative relocations against absolute symbols.68// sections have section-relative relocations against absolute symbols.
73static bool checkSecRel(const SectionChunk *Sec, OutputSection *OS) {69static bool checkSecRel(const SectionChunk *sec, OutputSection *os) {
74 if (OS)70 if (os)
75 return true;71 return true;
76 if (Sec->isCodeView())72 if (sec->isCodeView())
77 return false;73 return false;
78 error("SECREL relocation cannot be applied to absolute symbols");74 error("SECREL relocation cannot be applied to absolute symbols");
79 return false;75 return false;
80}76}
8177
82static void applySecRel(const SectionChunk *Sec, uint8_t *Off,78static void applySecRel(const SectionChunk *sec, uint8_t *off,
83 OutputSection *OS, uint64_t S) {79 OutputSection *os, uint64_t s) {
84 if (!checkSecRel(Sec, OS))80 if (!checkSecRel(sec, os))
85 return;81 return;
86 uint64_t SecRel = S - OS->getRVA();82 uint64_t secRel = s - os->getRVA();
87 if (SecRel > UINT32_MAX) {83 if (secRel > UINT32_MAX) {
88 error("overflow in SECREL relocation in section: " + Sec->getSectionName());84 error("overflow in SECREL relocation in section: " + sec->getSectionName());
89 return;85 return;
90 }86 }
91 add32(Off, SecRel);87 add32(off, secRel);
92}88}
9389
94static void applySecIdx(uint8_t *Off, OutputSection *OS) {90static void applySecIdx(uint8_t *off, OutputSection *os) {
95 // Absolute symbol doesn't have section index, but section index relocation91 // Absolute symbol doesn't have section index, but section index relocation
96 // against absolute symbol should be resolved to one plus the last output92 // against absolute symbol should be resolved to one plus the last output
97 // section index. This is required for compatibility with MSVC.93 // section index. This is required for compatibility with MSVC.
98 if (OS)94 if (os)
99 add16(Off, OS->SectionIndex);95 add16(off, os->sectionIndex);
100 else96 else
101 add16(Off, DefinedAbsolute::NumOutputSections + 1);97 add16(off, DefinedAbsolute::numOutputSections + 1);
102}98}
10399
104void SectionChunk::applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS,100void SectionChunk::applyRelX64(uint8_t *off, uint16_t type, OutputSection *os,
105 uint64_t S, uint64_t P) const {101 uint64_t s, uint64_t p) const {
106 switch (Type) {102 switch (type) {
107 case IMAGE_REL_AMD64_ADDR32: add32(Off, S + Config->ImageBase); break;103 case IMAGE_REL_AMD64_ADDR32: add32(off, s + config->imageBase); break;
108 case IMAGE_REL_AMD64_ADDR64: add64(Off, S + Config->ImageBase); break;104 case IMAGE_REL_AMD64_ADDR64: add64(off, s + config->imageBase); break;
109 case IMAGE_REL_AMD64_ADDR32NB: add32(Off, S); break;105 case IMAGE_REL_AMD64_ADDR32NB: add32(off, s); break;
110 case IMAGE_REL_AMD64_REL32: add32(Off, S - P - 4); break;106 case IMAGE_REL_AMD64_REL32: add32(off, s - p - 4); break;
111 case IMAGE_REL_AMD64_REL32_1: add32(Off, S - P - 5); break;107 case IMAGE_REL_AMD64_REL32_1: add32(off, s - p - 5); break;
112 case IMAGE_REL_AMD64_REL32_2: add32(Off, S - P - 6); break;108 case IMAGE_REL_AMD64_REL32_2: add32(off, s - p - 6); break;
113 case IMAGE_REL_AMD64_REL32_3: add32(Off, S - P - 7); break;109 case IMAGE_REL_AMD64_REL32_3: add32(off, s - p - 7); break;
114 case IMAGE_REL_AMD64_REL32_4: add32(Off, S - P - 8); break;110 case IMAGE_REL_AMD64_REL32_4: add32(off, s - p - 8); break;
115 case IMAGE_REL_AMD64_REL32_5: add32(Off, S - P - 9); break;111 case IMAGE_REL_AMD64_REL32_5: add32(off, s - p - 9); break;
116 case IMAGE_REL_AMD64_SECTION: applySecIdx(Off, OS); break;112 case IMAGE_REL_AMD64_SECTION: applySecIdx(off, os); break;
117 case IMAGE_REL_AMD64_SECREL: applySecRel(this, Off, OS, S); break;113 case IMAGE_REL_AMD64_SECREL: applySecRel(this, off, os, s); break;
118 default:114 default:
119 error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " +115 error("unsupported relocation type 0x" + Twine::utohexstr(type) + " in " +
120 toString(File));116 toString(file));
121 }117 }
122}118}
123119
124void SectionChunk::applyRelX86(uint8_t *Off, uint16_t Type, OutputSection *OS,120void SectionChunk::applyRelX86(uint8_t *off, uint16_t type, OutputSection *os,
125 uint64_t S, uint64_t P) const {121 uint64_t s, uint64_t p) const {
126 switch (Type) {122 switch (type) {
127 case IMAGE_REL_I386_ABSOLUTE: break;123 case IMAGE_REL_I386_ABSOLUTE: break;
128 case IMAGE_REL_I386_DIR32: add32(Off, S + Config->ImageBase); break;124 case IMAGE_REL_I386_DIR32: add32(off, s + config->imageBase); break;
129 case IMAGE_REL_I386_DIR32NB: add32(Off, S); break;125 case IMAGE_REL_I386_DIR32NB: add32(off, s); break;
130 case IMAGE_REL_I386_REL32: add32(Off, S - P - 4); break;126 case IMAGE_REL_I386_REL32: add32(off, s - p - 4); break;
131 case IMAGE_REL_I386_SECTION: applySecIdx(Off, OS); break;127 case IMAGE_REL_I386_SECTION: applySecIdx(off, os); break;
132 case IMAGE_REL_I386_SECREL: applySecRel(this, Off, OS, S); break;128 case IMAGE_REL_I386_SECREL: applySecRel(this, off, os, s); break;
133 default:129 default:
134 error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " +130 error("unsupported relocation type 0x" + Twine::utohexstr(type) + " in " +
135 toString(File));131 toString(file));
136 }132 }
137}133}
138134
139static void applyMOV(uint8_t *Off, uint16_t V) {135static void applyMOV(uint8_t *off, uint16_t v) {
140 write16le(Off, (read16le(Off) & 0xfbf0) | ((V & 0x800) >> 1) | ((V >> 12) & 0xf));136 write16le(off, (read16le(off) & 0xfbf0) | ((v & 0x800) >> 1) | ((v >> 12) & 0xf));
141 write16le(Off + 2, (read16le(Off + 2) & 0x8f00) | ((V & 0x700) << 4) | (V & 0xff));137 write16le(off + 2, (read16le(off + 2) & 0x8f00) | ((v & 0x700) << 4) | (v & 0xff));
142}138}
143139
144static uint16_t readMOV(uint8_t *Off, bool MOVT) {140static uint16_t readMOV(uint8_t *off, bool movt) {
145 uint16_t Op1 = read16le(Off);141 uint16_t op1 = read16le(off);
146 if ((Op1 & 0xfbf0) != (MOVT ? 0xf2c0 : 0xf240))142 if ((op1 & 0xfbf0) != (movt ? 0xf2c0 : 0xf240))
147 error("unexpected instruction in " + Twine(MOVT ? "MOVT" : "MOVW") +143 error("unexpected instruction in " + Twine(movt ? "MOVT" : "MOVW") +
148 " instruction in MOV32T relocation");144 " instruction in MOV32T relocation");
149 uint16_t Op2 = read16le(Off + 2);145 uint16_t op2 = read16le(off + 2);
150 if ((Op2 & 0x8000) != 0)146 if ((op2 & 0x8000) != 0)
151 error("unexpected instruction in " + Twine(MOVT ? "MOVT" : "MOVW") +147 error("unexpected instruction in " + Twine(movt ? "MOVT" : "MOVW") +
152 " instruction in MOV32T relocation");148 " instruction in MOV32T relocation");
153 return (Op2 & 0x00ff) | ((Op2 >> 4) & 0x0700) | ((Op1 << 1) & 0x0800) |149 return (op2 & 0x00ff) | ((op2 >> 4) & 0x0700) | ((op1 << 1) & 0x0800) |
154 ((Op1 & 0x000f) << 12);150 ((op1 & 0x000f) << 12);
155}151}
156152
157void applyMOV32T(uint8_t *Off, uint32_t V) {153void applyMOV32T(uint8_t *off, uint32_t v) {
158 uint16_t ImmW = readMOV(Off, false); // read MOVW operand154 uint16_t immW = readMOV(off, false); // read MOVW operand
159 uint16_t ImmT = readMOV(Off + 4, true); // read MOVT operand155 uint16_t immT = readMOV(off + 4, true); // read MOVT operand
160 uint32_t Imm = ImmW | (ImmT << 16);156 uint32_t imm = immW | (immT << 16);
161 V += Imm; // add the immediate offset157 v += imm; // add the immediate offset
162 applyMOV(Off, V); // set MOVW operand158 applyMOV(off, v); // set MOVW operand
163 applyMOV(Off + 4, V >> 16); // set MOVT operand159 applyMOV(off + 4, v >> 16); // set MOVT operand
164}160}
165161
166static void applyBranch20T(uint8_t *Off, int32_t V) {162static void applyBranch20T(uint8_t *off, int32_t v) {
167 if (!isInt<21>(V))163 if (!isInt<21>(v))
168 error("relocation out of range");164 error("relocation out of range");
169 uint32_t S = V < 0 ? 1 : 0;165 uint32_t s = v < 0 ? 1 : 0;
170 uint32_t J1 = (V >> 19) & 1;166 uint32_t j1 = (v >> 19) & 1;
171 uint32_t J2 = (V >> 18) & 1;167 uint32_t j2 = (v >> 18) & 1;
172 or16(Off, (S << 10) | ((V >> 12) & 0x3f));168 or16(off, (s << 10) | ((v >> 12) & 0x3f));
173 or16(Off + 2, (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));169 or16(off + 2, (j1 << 13) | (j2 << 11) | ((v >> 1) & 0x7ff));
174}170}
175171
176void applyBranch24T(uint8_t *Off, int32_t V) {172void applyBranch24T(uint8_t *off, int32_t v) {
177 if (!isInt<25>(V))173 if (!isInt<25>(v))
178 error("relocation out of range");174 error("relocation out of range");
179 uint32_t S = V < 0 ? 1 : 0;175 uint32_t s = v < 0 ? 1 : 0;
180 uint32_t J1 = ((~V >> 23) & 1) ^ S;176 uint32_t j1 = ((~v >> 23) & 1) ^ s;
181 uint32_t J2 = ((~V >> 22) & 1) ^ S;177 uint32_t j2 = ((~v >> 22) & 1) ^ s;
182 or16(Off, (S << 10) | ((V >> 12) & 0x3ff));178 or16(off, (s << 10) | ((v >> 12) & 0x3ff));
183 // Clear out the J1 and J2 bits which may be set.179 // Clear out the J1 and J2 bits which may be set.
184 write16le(Off + 2, (read16le(Off + 2) & 0xd000) | (J1 << 13) | (J2 << 11) | ((V >> 1) & 0x7ff));180 write16le(off + 2, (read16le(off + 2) & 0xd000) | (j1 << 13) | (j2 << 11) | ((v >> 1) & 0x7ff));
185}181}
186182
187void SectionChunk::applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS,183void SectionChunk::applyRelARM(uint8_t *off, uint16_t type, OutputSection *os,
188 uint64_t S, uint64_t P) const {184 uint64_t s, uint64_t p) const {
189 // Pointer to thumb code must have the LSB set.185 // Pointer to thumb code must have the LSB set.
190 uint64_t SX = S;186 uint64_t sx = s;
191 if (OS && (OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE))187 if (os && (os->header.Characteristics & IMAGE_SCN_MEM_EXECUTE))
192 SX |= 1;188 sx |= 1;
193 switch (Type) {189 switch (type) {
194 case IMAGE_REL_ARM_ADDR32: add32(Off, SX + Config->ImageBase); break;190 case IMAGE_REL_ARM_ADDR32: add32(off, sx + config->imageBase); break;
195 case IMAGE_REL_ARM_ADDR32NB: add32(Off, SX); break;191 case IMAGE_REL_ARM_ADDR32NB: add32(off, sx); break;
196 case IMAGE_REL_ARM_MOV32T: applyMOV32T(Off, SX + Config->ImageBase); break;192 case IMAGE_REL_ARM_MOV32T: applyMOV32T(off, sx + config->imageBase); break;
197 case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(Off, SX - P - 4); break;193 case IMAGE_REL_ARM_BRANCH20T: applyBranch20T(off, sx - p - 4); break;
198 case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(Off, SX - P - 4); break;194 case IMAGE_REL_ARM_BRANCH24T: applyBranch24T(off, sx - p - 4); break;
199 case IMAGE_REL_ARM_BLX23T: applyBranch24T(Off, SX - P - 4); break;195 case IMAGE_REL_ARM_BLX23T: applyBranch24T(off, sx - p - 4); break;
200 case IMAGE_REL_ARM_SECTION: applySecIdx(Off, OS); break;196 case IMAGE_REL_ARM_SECTION: applySecIdx(off, os); break;
201 case IMAGE_REL_ARM_SECREL: applySecRel(this, Off, OS, S); break;197 case IMAGE_REL_ARM_SECREL: applySecRel(this, off, os, s); break;
198 case IMAGE_REL_ARM_REL32: add32(off, sx - p - 4); break;
202 default:199 default:
203 error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " +200 error("unsupported relocation type 0x" + Twine::utohexstr(type) + " in " +
204 toString(File));201 toString(file));
205 }202 }
206}203}
207204
208// Interpret the existing immediate value as a byte offset to the205// Interpret the existing immediate value as a byte offset to the
209// target symbol, then update the instruction with the immediate as206// target symbol, then update the instruction with the immediate as
210// the page offset from the current instruction to the target.207// the page offset from the current instruction to the target.
211void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift) {208void applyArm64Addr(uint8_t *off, uint64_t s, uint64_t p, int shift) {
212 uint32_t Orig = read32le(Off);209 uint32_t orig = read32le(off);
213 uint64_t Imm = ((Orig >> 29) & 0x3) | ((Orig >> 3) & 0x1FFFFC);210 uint64_t imm = ((orig >> 29) & 0x3) | ((orig >> 3) & 0x1FFFFC);
214 S += Imm;211 s += imm;
215 Imm = (S >> Shift) - (P >> Shift);212 imm = (s >> shift) - (p >> shift);
216 uint32_t ImmLo = (Imm & 0x3) << 29;213 uint32_t immLo = (imm & 0x3) << 29;
217 uint32_t ImmHi = (Imm & 0x1FFFFC) << 3;214 uint32_t immHi = (imm & 0x1FFFFC) << 3;
218 uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3);215 uint64_t mask = (0x3 << 29) | (0x1FFFFC << 3);
219 write32le(Off, (Orig & ~Mask) | ImmLo | ImmHi);216 write32le(off, (orig & ~mask) | immLo | immHi);
220}217}
221218
222// Update the immediate field in a AARCH64 ldr, str, and add instruction.219// Update the immediate field in a AARCH64 ldr, str, and add instruction.
223// Optionally limit the range of the written immediate by one or more bits220// Optionally limit the range of the written immediate by one or more bits
224// (RangeLimit).221// (rangeLimit).
225void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit) {222void applyArm64Imm(uint8_t *off, uint64_t imm, uint32_t rangeLimit) {
226 uint32_t Orig = read32le(Off);223 uint32_t orig = read32le(off);
227 Imm += (Orig >> 10) & 0xFFF;224 imm += (orig >> 10) & 0xFFF;
228 Orig &= ~(0xFFF << 10);225 orig &= ~(0xFFF << 10);
229 write32le(Off, Orig | ((Imm & (0xFFF >> RangeLimit)) << 10));226 write32le(off, orig | ((imm & (0xFFF >> rangeLimit)) << 10));
230}227}
231228
232// Add the 12 bit page offset to the existing immediate.229// Add the 12 bit page offset to the existing immediate.
...@@ -237,171 +234,178 @@ void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit) {...@@ -237,171 +234,178 @@ void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit) {
237// Even if larger loads/stores have a larger range, limit the234// Even if larger loads/stores have a larger range, limit the
238// effective offset to 12 bit, since it is intended to be a235// effective offset to 12 bit, since it is intended to be a
239// page offset.236// page offset.
240static void applyArm64Ldr(uint8_t *Off, uint64_t Imm) {237static void applyArm64Ldr(uint8_t *off, uint64_t imm) {
241 uint32_t Orig = read32le(Off);238 uint32_t orig = read32le(off);
242 uint32_t Size = Orig >> 30;239 uint32_t size = orig >> 30;
243 // 0x04000000 indicates SIMD/FP registers240 // 0x04000000 indicates SIMD/FP registers
244 // 0x00800000 indicates 128 bit241 // 0x00800000 indicates 128 bit
245 if ((Orig & 0x4800000) == 0x4800000)242 if ((orig & 0x4800000) == 0x4800000)
246 Size += 4;243 size += 4;
247 if ((Imm & ((1 << Size) - 1)) != 0)244 if ((imm & ((1 << size) - 1)) != 0)
248 error("misaligned ldr/str offset");245 error("misaligned ldr/str offset");
249 applyArm64Imm(Off, Imm >> Size, Size);246 applyArm64Imm(off, imm >> size, size);
250}247}
251248
252static void applySecRelLow12A(const SectionChunk *Sec, uint8_t *Off,249static void applySecRelLow12A(const SectionChunk *sec, uint8_t *off,
253 OutputSection *OS, uint64_t S) {250 OutputSection *os, uint64_t s) {
254 if (checkSecRel(Sec, OS))251 if (checkSecRel(sec, os))
255 applyArm64Imm(Off, (S - OS->getRVA()) & 0xfff, 0);252 applyArm64Imm(off, (s - os->getRVA()) & 0xfff, 0);
256}253}
257254
258static void applySecRelHigh12A(const SectionChunk *Sec, uint8_t *Off,255static void applySecRelHigh12A(const SectionChunk *sec, uint8_t *off,
259 OutputSection *OS, uint64_t S) {256 OutputSection *os, uint64_t s) {
260 if (!checkSecRel(Sec, OS))257 if (!checkSecRel(sec, os))
261 return;258 return;
262 uint64_t SecRel = (S - OS->getRVA()) >> 12;259 uint64_t secRel = (s - os->getRVA()) >> 12;
263 if (0xfff < SecRel) {260 if (0xfff < secRel) {
264 error("overflow in SECREL_HIGH12A relocation in section: " +261 error("overflow in SECREL_HIGH12A relocation in section: " +
265 Sec->getSectionName());262 sec->getSectionName());
266 return;263 return;
267 }264 }
268 applyArm64Imm(Off, SecRel & 0xfff, 0);265 applyArm64Imm(off, secRel & 0xfff, 0);
269}266}
270267
271static void applySecRelLdr(const SectionChunk *Sec, uint8_t *Off,268static void applySecRelLdr(const SectionChunk *sec, uint8_t *off,
272 OutputSection *OS, uint64_t S) {269 OutputSection *os, uint64_t s) {
273 if (checkSecRel(Sec, OS))270 if (checkSecRel(sec, os))
274 applyArm64Ldr(Off, (S - OS->getRVA()) & 0xfff);271 applyArm64Ldr(off, (s - os->getRVA()) & 0xfff);
275}272}
276273
277void applyArm64Branch26(uint8_t *Off, int64_t V) {274void applyArm64Branch26(uint8_t *off, int64_t v) {
278 if (!isInt<28>(V))275 if (!isInt<28>(v))
279 error("relocation out of range");276 error("relocation out of range");
280 or32(Off, (V & 0x0FFFFFFC) >> 2);277 or32(off, (v & 0x0FFFFFFC) >> 2);
281}278}
282279
283static void applyArm64Branch19(uint8_t *Off, int64_t V) {280static void applyArm64Branch19(uint8_t *off, int64_t v) {
284 if (!isInt<21>(V))281 if (!isInt<21>(v))
285 error("relocation out of range");282 error("relocation out of range");
286 or32(Off, (V & 0x001FFFFC) << 3);283 or32(off, (v & 0x001FFFFC) << 3);
287}284}
288285
289static void applyArm64Branch14(uint8_t *Off, int64_t V) {286static void applyArm64Branch14(uint8_t *off, int64_t v) {
290 if (!isInt<16>(V))287 if (!isInt<16>(v))
291 error("relocation out of range");288 error("relocation out of range");
292 or32(Off, (V & 0x0000FFFC) << 3);289 or32(off, (v & 0x0000FFFC) << 3);
293}290}
294291
295void SectionChunk::applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS,292void SectionChunk::applyRelARM64(uint8_t *off, uint16_t type, OutputSection *os,
296 uint64_t S, uint64_t P) const {293 uint64_t s, uint64_t p) const {
297 switch (Type) {294 switch (type) {
298 case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(Off, S, P, 12); break;295 case IMAGE_REL_ARM64_PAGEBASE_REL21: applyArm64Addr(off, s, p, 12); break;
299 case IMAGE_REL_ARM64_REL21: applyArm64Addr(Off, S, P, 0); break;296 case IMAGE_REL_ARM64_REL21: applyArm64Addr(off, s, p, 0); break;
300 case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(Off, S & 0xfff, 0); break;297 case IMAGE_REL_ARM64_PAGEOFFSET_12A: applyArm64Imm(off, s & 0xfff, 0); break;
301 case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(Off, S & 0xfff); break;298 case IMAGE_REL_ARM64_PAGEOFFSET_12L: applyArm64Ldr(off, s & 0xfff); break;
302 case IMAGE_REL_ARM64_BRANCH26: applyArm64Branch26(Off, S - P); break;299 case IMAGE_REL_ARM64_BRANCH26: applyArm64Branch26(off, s - p); break;
303 case IMAGE_REL_ARM64_BRANCH19: applyArm64Branch19(Off, S - P); break;300 case IMAGE_REL_ARM64_BRANCH19: applyArm64Branch19(off, s - p); break;
304 case IMAGE_REL_ARM64_BRANCH14: applyArm64Branch14(Off, S - P); break;301 case IMAGE_REL_ARM64_BRANCH14: applyArm64Branch14(off, s - p); break;
305 case IMAGE_REL_ARM64_ADDR32: add32(Off, S + Config->ImageBase); break;302 case IMAGE_REL_ARM64_ADDR32: add32(off, s + config->imageBase); break;
306 case IMAGE_REL_ARM64_ADDR32NB: add32(Off, S); break;303 case IMAGE_REL_ARM64_ADDR32NB: add32(off, s); break;
307 case IMAGE_REL_ARM64_ADDR64: add64(Off, S + Config->ImageBase); break;304 case IMAGE_REL_ARM64_ADDR64: add64(off, s + config->imageBase); break;
308 case IMAGE_REL_ARM64_SECREL: applySecRel(this, Off, OS, S); break;305 case IMAGE_REL_ARM64_SECREL: applySecRel(this, off, os, s); break;
309 case IMAGE_REL_ARM64_SECREL_LOW12A: applySecRelLow12A(this, Off, OS, S); break;306 case IMAGE_REL_ARM64_SECREL_LOW12A: applySecRelLow12A(this, off, os, s); break;
310 case IMAGE_REL_ARM64_SECREL_HIGH12A: applySecRelHigh12A(this, Off, OS, S); break;307 case IMAGE_REL_ARM64_SECREL_HIGH12A: applySecRelHigh12A(this, off, os, s); break;
311 case IMAGE_REL_ARM64_SECREL_LOW12L: applySecRelLdr(this, Off, OS, S); break;308 case IMAGE_REL_ARM64_SECREL_LOW12L: applySecRelLdr(this, off, os, s); break;
312 case IMAGE_REL_ARM64_SECTION: applySecIdx(Off, OS); break;309 case IMAGE_REL_ARM64_SECTION: applySecIdx(off, os); break;
310 case IMAGE_REL_ARM64_REL32: add32(off, s - p - 4); break;
313 default:311 default:
314 error("unsupported relocation type 0x" + Twine::utohexstr(Type) + " in " +312 error("unsupported relocation type 0x" + Twine::utohexstr(type) + " in " +
315 toString(File));313 toString(file));
316 }314 }
317}315}
318316
319static void maybeReportRelocationToDiscarded(const SectionChunk *FromChunk,317static void maybeReportRelocationToDiscarded(const SectionChunk *fromChunk,
320 Defined *Sym,318 Defined *sym,
321 const coff_relocation &Rel) {319 const coff_relocation &rel) {
322 // Don't report these errors when the relocation comes from a debug info320 // 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) can321 // section or in mingw mode. MinGW mode object files (built by GCC) can
324 // have leftover sections with relocations against discarded comdat322 // have leftover sections with relocations against discarded comdat
325 // sections. Such sections are left as is, with relocations untouched.323 // sections. Such sections are left as is, with relocations untouched.
326 if (FromChunk->isCodeView() || FromChunk->isDWARF() || Config->MinGW)324 if (fromChunk->isCodeView() || fromChunk->isDWARF() || config->mingw)
327 return;325 return;
328326
329 // Get the name of the symbol. If it's null, it was discarded early, so we327 // 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.328 // have to go back to the object file.
331 ObjFile *File = FromChunk->File;329 ObjFile *file = fromChunk->file;
332 StringRef Name;330 StringRef name;
333 if (Sym) {331 if (sym) {
334 Name = Sym->getName();332 name = sym->getName();
335 } else {333 } else {
336 COFFSymbolRef COFFSym =334 COFFSymbolRef coffSym =
337 check(File->getCOFFObj()->getSymbol(Rel.SymbolTableIndex));335 check(file->getCOFFObj()->getSymbol(rel.SymbolTableIndex));
338 File->getCOFFObj()->getSymbolName(COFFSym, Name);336 file->getCOFFObj()->getSymbolName(coffSym, name);
339 }337 }
340338
341 error("relocation against symbol in discarded section: " + Name +339 std::vector<std::string> symbolLocations =
342 getSymbolLocations(File, Rel.SymbolTableIndex));340 getSymbolLocations(file, rel.SymbolTableIndex);
341
342 std::string out;
343 llvm::raw_string_ostream os(out);
344 os << "relocation against symbol in discarded section: " + name;
345 for (const std::string &s : symbolLocations)
346 os << s;
347 error(os.str());
343}348}
344349
345void SectionChunk::writeTo(uint8_t *Buf) const {350void SectionChunk::writeTo(uint8_t *buf) const {
346 if (!hasData())351 if (!hasData)
347 return;352 return;
348 // Copy section contents from source object file to output file.353 // Copy section contents from source object file to output file.
349 ArrayRef<uint8_t> A = getContents();354 ArrayRef<uint8_t> a = getContents();
350 if (!A.empty())355 if (!a.empty())
351 memcpy(Buf + OutputSectionOff, A.data(), A.size());356 memcpy(buf, a.data(), a.size());
352357
353 // Apply relocations.358 // Apply relocations.
354 size_t InputSize = getSize();359 size_t inputSize = getSize();
355 for (size_t I = 0, E = Relocs.size(); I < E; I++) {360 for (size_t i = 0, e = relocsSize; i < e; i++) {
356 const coff_relocation &Rel = Relocs[I];361 const coff_relocation &rel = relocsData[i];
357362
358 // Check for an invalid relocation offset. This check isn't perfect, because363 // Check for an invalid relocation offset. This check isn't perfect, because
359 // we don't have the relocation size, which is only known after checking the364 // we don't have the relocation size, which is only known after checking the
360 // machine and relocation type. As a result, a relocation may overwrite the365 // machine and relocation type. As a result, a relocation may overwrite the
361 // beginning of the following input section.366 // beginning of the following input section.
362 if (Rel.VirtualAddress >= InputSize) {367 if (rel.VirtualAddress >= inputSize) {
363 error("relocation points beyond the end of its parent section");368 error("relocation points beyond the end of its parent section");
364 continue;369 continue;
365 }370 }
366371
367 uint8_t *Off = Buf + OutputSectionOff + Rel.VirtualAddress;372 uint8_t *off = buf + rel.VirtualAddress;
368373
369 // Use the potentially remapped Symbol instead of the one that the374 auto *sym =
370 // relocation points to.375 dyn_cast_or_null<Defined>(file->getSymbol(rel.SymbolTableIndex));
371 auto *Sym = dyn_cast_or_null<Defined>(RelocTargets[I]);
372376
373 // Get the output section of the symbol for this relocation. The output377 // Get the output section of the symbol for this relocation. The output
374 // section is needed to compute SECREL and SECTION relocations used in debug378 // section is needed to compute SECREL and SECTION relocations used in debug
375 // info.379 // info.
376 Chunk *C = Sym ? Sym->getChunk() : nullptr;380 Chunk *c = sym ? sym->getChunk() : nullptr;
377 OutputSection *OS = C ? C->getOutputSection() : nullptr;381 OutputSection *os = c ? c->getOutputSection() : nullptr;
378382
379 // Skip the relocation if it refers to a discarded section, and diagnose it383 // 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 be384 // 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, unless385 // null. If it was discarded late, the output section will be null, unless
382 // it was an absolute or synthetic symbol.386 // it was an absolute or synthetic symbol.
383 if (!Sym ||387 if (!sym ||
384 (!OS && !isa<DefinedAbsolute>(Sym) && !isa<DefinedSynthetic>(Sym))) {388 (!os && !isa<DefinedAbsolute>(sym) && !isa<DefinedSynthetic>(sym))) {
385 maybeReportRelocationToDiscarded(this, Sym, Rel);389 maybeReportRelocationToDiscarded(this, sym, rel);
386 continue;390 continue;
387 }391 }
388392
389 uint64_t S = Sym->getRVA();393 uint64_t s = sym->getRVA();
390394
391 // Compute the RVA of the relocation for relative relocations.395 // Compute the RVA of the relocation for relative relocations.
392 uint64_t P = RVA + Rel.VirtualAddress;396 uint64_t p = rva + rel.VirtualAddress;
393 switch (Config->Machine) {397 switch (config->machine) {
394 case AMD64:398 case AMD64:
395 applyRelX64(Off, Rel.Type, OS, S, P);399 applyRelX64(off, rel.Type, os, s, p);
396 break;400 break;
397 case I386:401 case I386:
398 applyRelX86(Off, Rel.Type, OS, S, P);402 applyRelX86(off, rel.Type, os, s, p);
399 break;403 break;
400 case ARMNT:404 case ARMNT:
401 applyRelARM(Off, Rel.Type, OS, S, P);405 applyRelARM(off, rel.Type, os, s, p);
402 break;406 break;
403 case ARM64:407 case ARM64:
404 applyRelARM64(Off, Rel.Type, OS, S, P);408 applyRelARM64(off, rel.Type, os, s, p);
405 break;409 break;
406 default:410 default:
407 llvm_unreachable("unknown machine type");411 llvm_unreachable("unknown machine type");
...@@ -409,28 +413,32 @@ void SectionChunk::writeTo(uint8_t *Buf) const {...@@ -409,28 +413,32 @@ void SectionChunk::writeTo(uint8_t *Buf) const {
409 }413 }
410}414}
411415
412void SectionChunk::addAssociative(SectionChunk *Child) {416void SectionChunk::addAssociative(SectionChunk *child) {
413 AssocChildren.push_back(Child);417 // Insert this child at the head of the list.
418 assert(child->assocChildren == nullptr &&
419 "associated sections cannot have their own associated children");
420 child->assocChildren = assocChildren;
421 assocChildren = child;
414}422}
415423
416static uint8_t getBaserelType(const coff_relocation &Rel) {424static uint8_t getBaserelType(const coff_relocation &rel) {
417 switch (Config->Machine) {425 switch (config->machine) {
418 case AMD64:426 case AMD64:
419 if (Rel.Type == IMAGE_REL_AMD64_ADDR64)427 if (rel.Type == IMAGE_REL_AMD64_ADDR64)
420 return IMAGE_REL_BASED_DIR64;428 return IMAGE_REL_BASED_DIR64;
421 return IMAGE_REL_BASED_ABSOLUTE;429 return IMAGE_REL_BASED_ABSOLUTE;
422 case I386:430 case I386:
423 if (Rel.Type == IMAGE_REL_I386_DIR32)431 if (rel.Type == IMAGE_REL_I386_DIR32)
424 return IMAGE_REL_BASED_HIGHLOW;432 return IMAGE_REL_BASED_HIGHLOW;
425 return IMAGE_REL_BASED_ABSOLUTE;433 return IMAGE_REL_BASED_ABSOLUTE;
426 case ARMNT:434 case ARMNT:
427 if (Rel.Type == IMAGE_REL_ARM_ADDR32)435 if (rel.Type == IMAGE_REL_ARM_ADDR32)
428 return IMAGE_REL_BASED_HIGHLOW;436 return IMAGE_REL_BASED_HIGHLOW;
429 if (Rel.Type == IMAGE_REL_ARM_MOV32T)437 if (rel.Type == IMAGE_REL_ARM_MOV32T)
430 return IMAGE_REL_BASED_ARM_MOV32T;438 return IMAGE_REL_BASED_ARM_MOV32T;
431 return IMAGE_REL_BASED_ABSOLUTE;439 return IMAGE_REL_BASED_ABSOLUTE;
432 case ARM64:440 case ARM64:
433 if (Rel.Type == IMAGE_REL_ARM64_ADDR64)441 if (rel.Type == IMAGE_REL_ARM64_ADDR64)
434 return IMAGE_REL_BASED_DIR64;442 return IMAGE_REL_BASED_DIR64;
435 return IMAGE_REL_BASED_ABSOLUTE;443 return IMAGE_REL_BASED_ABSOLUTE;
436 default:444 default:
...@@ -442,18 +450,16 @@ static uint8_t getBaserelType(const coff_relocation &Rel) {...@@ -442,18 +450,16 @@ static uint8_t getBaserelType(const coff_relocation &Rel) {
442// Collect all locations that contain absolute addresses, which need to be450// Collect all locations that contain absolute addresses, which need to be
443// fixed by the loader if load-time relocation is needed.451// fixed by the loader if load-time relocation is needed.
444// Only called when base relocation is enabled.452// Only called when base relocation is enabled.
445void SectionChunk::getBaserels(std::vector<Baserel> *Res) {453void SectionChunk::getBaserels(std::vector<Baserel> *res) {
446 for (size_t I = 0, E = Relocs.size(); I < E; I++) {454 for (size_t i = 0, e = relocsSize; i < e; i++) {
447 const coff_relocation &Rel = Relocs[I];455 const coff_relocation &rel = relocsData[i];
448 uint8_t Ty = getBaserelType(Rel);456 uint8_t ty = getBaserelType(rel);
449 if (Ty == IMAGE_REL_BASED_ABSOLUTE)457 if (ty == IMAGE_REL_BASED_ABSOLUTE)
450 continue;458 continue;
451 // Use the potentially remapped Symbol instead of the one that the459 Symbol *target = file->getSymbol(rel.SymbolTableIndex);
452 // relocation points to.460 if (!target || isa<DefinedAbsolute>(target))
453 Symbol *Target = RelocTargets[I];
454 if (!Target || isa<DefinedAbsolute>(Target))
455 continue;461 continue;
456 Res->emplace_back(RVA + Rel.VirtualAddress, Ty);462 res->emplace_back(rva + rel.VirtualAddress, ty);
457 }463 }
458}464}
459465
...@@ -464,7 +470,7 @@ void SectionChunk::getBaserels(std::vector<Baserel> *Res) {...@@ -464,7 +470,7 @@ void SectionChunk::getBaserels(std::vector<Baserel> *Res) {
464// another DLL) This returns the size the relocation is supposed to update,470// 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 pseudo471// in bits, or 0 if the relocation cannot be handled as a runtime pseudo
466// relocation.472// relocation.
467static int getRuntimePseudoRelocSize(uint16_t Type) {473static int getRuntimePseudoRelocSize(uint16_t type) {
468 // Relocations that either contain an absolute address, or a plain474 // Relocations that either contain an absolute address, or a plain
469 // relative offset, since the runtime pseudo reloc implementation475 // relative offset, since the runtime pseudo reloc implementation
470 // adds 8/16/32/64 bit values to a memory address.476 // adds 8/16/32/64 bit values to a memory address.
...@@ -490,9 +496,9 @@ static int getRuntimePseudoRelocSize(uint16_t Type) {...@@ -490,9 +496,9 @@ static int getRuntimePseudoRelocSize(uint16_t Type) {
490 // the image, or temporarily changed at runtime with VirtualProtect.496 // the image, or temporarily changed at runtime with VirtualProtect.
491 // Since this only operates on direct address values, it doesn't work for497 // Since this only operates on direct address values, it doesn't work for
492 // ARM/ARM64 relocations, other than the plain ADDR32/ADDR64 relocations.498 // ARM/ARM64 relocations, other than the plain ADDR32/ADDR64 relocations.
493 switch (Config->Machine) {499 switch (config->machine) {
494 case AMD64:500 case AMD64:
495 switch (Type) {501 switch (type) {
496 case IMAGE_REL_AMD64_ADDR64:502 case IMAGE_REL_AMD64_ADDR64:
497 return 64;503 return 64;
498 case IMAGE_REL_AMD64_ADDR32:504 case IMAGE_REL_AMD64_ADDR32:
...@@ -507,7 +513,7 @@ static int getRuntimePseudoRelocSize(uint16_t Type) {...@@ -507,7 +513,7 @@ static int getRuntimePseudoRelocSize(uint16_t Type) {
507 return 0;513 return 0;
508 }514 }
509 case I386:515 case I386:
510 switch (Type) {516 switch (type) {
511 case IMAGE_REL_I386_DIR32:517 case IMAGE_REL_I386_DIR32:
512 case IMAGE_REL_I386_REL32:518 case IMAGE_REL_I386_REL32:
513 return 32;519 return 32;
...@@ -515,14 +521,14 @@ static int getRuntimePseudoRelocSize(uint16_t Type) {...@@ -515,14 +521,14 @@ static int getRuntimePseudoRelocSize(uint16_t Type) {
515 return 0;521 return 0;
516 }522 }
517 case ARMNT:523 case ARMNT:
518 switch (Type) {524 switch (type) {
519 case IMAGE_REL_ARM_ADDR32:525 case IMAGE_REL_ARM_ADDR32:
520 return 32;526 return 32;
521 default:527 default:
522 return 0;528 return 0;
523 }529 }
524 case ARM64:530 case ARM64:
525 switch (Type) {531 switch (type) {
526 case IMAGE_REL_ARM64_ADDR64:532 case IMAGE_REL_ARM64_ADDR64:
527 return 64;533 return 64;
528 case IMAGE_REL_ARM64_ADDR32:534 case IMAGE_REL_ARM64_ADDR32:
...@@ -541,75 +547,106 @@ static int getRuntimePseudoRelocSize(uint16_t Type) {...@@ -541,75 +547,106 @@ static int getRuntimePseudoRelocSize(uint16_t Type) {
541// to a module local variable, which turned out to actually need to be547// to a module local variable, which turned out to actually need to be
542// imported from another DLL).548// imported from another DLL).
543void SectionChunk::getRuntimePseudoRelocs(549void SectionChunk::getRuntimePseudoRelocs(
544 std::vector<RuntimePseudoReloc> &Res) {550 std::vector<RuntimePseudoReloc> &res) {
545 for (const coff_relocation &Rel : Relocs) {551 for (const coff_relocation &rel : getRelocs()) {
546 auto *Target =552 auto *target =
547 dyn_cast_or_null<Defined>(File->getSymbol(Rel.SymbolTableIndex));553 dyn_cast_or_null<Defined>(file->getSymbol(rel.SymbolTableIndex));
548 if (!Target || !Target->IsRuntimePseudoReloc)554 if (!target || !target->isRuntimePseudoReloc)
549 continue;555 continue;
550 int SizeInBits = getRuntimePseudoRelocSize(Rel.Type);556 int sizeInBits = getRuntimePseudoRelocSize(rel.Type);
551 if (SizeInBits == 0) {557 if (sizeInBits == 0) {
552 error("unable to automatically import from " + Target->getName() +558 error("unable to automatically import from " + target->getName() +
553 " with relocation type " +559 " with relocation type " +
554 File->getCOFFObj()->getRelocationTypeName(Rel.Type) + " in " +560 file->getCOFFObj()->getRelocationTypeName(rel.Type) + " in " +
555 toString(File));561 toString(file));
556 continue;562 continue;
557 }563 }
558 // SizeInBits is used to initialize the Flags field; currently no564 // sizeInBits is used to initialize the Flags field; currently no
559 // other flags are defined.565 // other flags are defined.
560 Res.emplace_back(566 res.emplace_back(
561 RuntimePseudoReloc(Target, this, Rel.VirtualAddress, SizeInBits));567 RuntimePseudoReloc(target, this, rel.VirtualAddress, sizeInBits));
562 }568 }
563}569}
564570
565bool SectionChunk::hasData() const {
566 return !(Header->Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA);
567}
568
569uint32_t SectionChunk::getOutputCharacteristics() const {
570 return Header->Characteristics & (PermMask | TypeMask);
571}
572
573bool SectionChunk::isCOMDAT() const {571bool SectionChunk::isCOMDAT() const {
574 return Header->Characteristics & IMAGE_SCN_LNK_COMDAT;572 return header->Characteristics & IMAGE_SCN_LNK_COMDAT;
575}573}
576574
577void SectionChunk::printDiscardedMessage() const {575void SectionChunk::printDiscardedMessage() const {
578 // Removed by dead-stripping. If it's removed by ICF, ICF already576 // Removed by dead-stripping. If it's removed by ICF, ICF already
579 // printed out the name, so don't repeat that here.577 // printed out the name, so don't repeat that here.
580 if (Sym && this == Repl)578 if (sym && this == repl)
581 message("Discarded " + Sym->getName());579 message("Discarded " + sym->getName());
582}580}
583581
584StringRef SectionChunk::getDebugName() {582StringRef SectionChunk::getDebugName() const {
585 if (Sym)583 if (sym)
586 return Sym->getName();584 return sym->getName();
587 return "";585 return "";
588}586}
589587
590ArrayRef<uint8_t> SectionChunk::getContents() const {588ArrayRef<uint8_t> SectionChunk::getContents() const {
591 ArrayRef<uint8_t> A;589 ArrayRef<uint8_t> a;
592 File->getCOFFObj()->getSectionContents(Header, A);590 cantFail(file->getCOFFObj()->getSectionContents(header, a));
593 return A;591 return a;
594}592}
595593
596void SectionChunk::replace(SectionChunk *Other) {594ArrayRef<uint8_t> SectionChunk::consumeDebugMagic() {
597 Alignment = std::max(Alignment, Other->Alignment);595 assert(isCodeView());
598 Other->Repl = Repl;596 return consumeDebugMagic(getContents(), getSectionName());
599 Other->Live = false;597}
598
599ArrayRef<uint8_t> SectionChunk::consumeDebugMagic(ArrayRef<uint8_t> data,
600 StringRef sectionName) {
601 if (data.empty())
602 return {};
603
604 // First 4 bytes are section magic.
605 if (data.size() < 4)
606 fatal("the section is too short: " + sectionName);
607
608 if (!sectionName.startswith(".debug$"))
609 fatal("invalid section: " + sectionName);
610
611 uint32_t magic = support::endian::read32le(data.data());
612 uint32_t expectedMagic = sectionName == ".debug$H"
613 ? DEBUG_HASHES_SECTION_MAGIC
614 : DEBUG_SECTION_MAGIC;
615 if (magic != expectedMagic) {
616 warn("ignoring section " + sectionName + " with unrecognized magic 0x" +
617 utohexstr(magic));
618 return {};
619 }
620 return data.slice(4);
621}
622
623SectionChunk *SectionChunk::findByName(ArrayRef<SectionChunk *> sections,
624 StringRef name) {
625 for (SectionChunk *c : sections)
626 if (c->getSectionName() == name)
627 return c;
628 return nullptr;
629}
630
631void SectionChunk::replace(SectionChunk *other) {
632 p2Align = std::max(p2Align, other->p2Align);
633 other->repl = repl;
634 other->live = false;
600}635}
601636
602uint32_t SectionChunk::getSectionNumber() const {637uint32_t SectionChunk::getSectionNumber() const {
603 DataRefImpl R;638 DataRefImpl r;
604 R.p = reinterpret_cast<uintptr_t>(Header);639 r.p = reinterpret_cast<uintptr_t>(header);
605 SectionRef S(R, File->getCOFFObj());640 SectionRef s(r, file->getCOFFObj());
606 return S.getIndex() + 1;641 return s.getIndex() + 1;
607}642}
608643
609CommonChunk::CommonChunk(const COFFSymbolRef S) : Sym(S) {644CommonChunk::CommonChunk(const COFFSymbolRef s) : sym(s) {
610 // Common symbols are aligned on natural boundaries up to 32 bytes.645 // The value of a common symbol is its size. Align all common symbols smaller
646 // than 32 bytes naturally, i.e. round the size up to the next power of two.
611 // This is what MSVC link.exe does.647 // This is what MSVC link.exe does.
612 Alignment = std::min(uint64_t(32), PowerOf2Ceil(Sym.getValue()));648 setAlignment(std::min(32U, uint32_t(PowerOf2Ceil(sym.getValue()))));
649 hasData = false;
613}650}
614651
615uint32_t CommonChunk::getOutputCharacteristics() const {652uint32_t CommonChunk::getOutputCharacteristics() const {
...@@ -617,139 +654,139 @@ uint32_t CommonChunk::getOutputCharacteristics() const {...@@ -617,139 +654,139 @@ uint32_t CommonChunk::getOutputCharacteristics() const {
617 IMAGE_SCN_MEM_WRITE;654 IMAGE_SCN_MEM_WRITE;
618}655}
619656
620void StringChunk::writeTo(uint8_t *Buf) const {657void StringChunk::writeTo(uint8_t *buf) const {
621 memcpy(Buf + OutputSectionOff, Str.data(), Str.size());658 memcpy(buf, str.data(), str.size());
622 Buf[OutputSectionOff + Str.size()] = '\0';659 buf[str.size()] = '\0';
623}660}
624661
625ImportThunkChunkX64::ImportThunkChunkX64(Defined *S) : ImpSymbol(S) {662ImportThunkChunkX64::ImportThunkChunkX64(Defined *s) : ImportThunkChunk(s) {
626 // Intel Optimization Manual says that all branch targets663 // Intel Optimization Manual says that all branch targets
627 // should be 16-byte aligned. MSVC linker does this too.664 // should be 16-byte aligned. MSVC linker does this too.
628 Alignment = 16;665 setAlignment(16);
629}666}
630667
631void ImportThunkChunkX64::writeTo(uint8_t *Buf) const {668void ImportThunkChunkX64::writeTo(uint8_t *buf) const {
632 memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86));669 memcpy(buf, importThunkX86, sizeof(importThunkX86));
633 // The first two bytes is a JMP instruction. Fill its operand.670 // The first two bytes is a JMP instruction. Fill its operand.
634 write32le(Buf + OutputSectionOff + 2, ImpSymbol->getRVA() - RVA - getSize());671 write32le(buf + 2, impSymbol->getRVA() - rva - getSize());
635}672}
636673
637void ImportThunkChunkX86::getBaserels(std::vector<Baserel> *Res) {674void ImportThunkChunkX86::getBaserels(std::vector<Baserel> *res) {
638 Res->emplace_back(getRVA() + 2);675 res->emplace_back(getRVA() + 2);
639}676}
640677
641void ImportThunkChunkX86::writeTo(uint8_t *Buf) const {678void ImportThunkChunkX86::writeTo(uint8_t *buf) const {
642 memcpy(Buf + OutputSectionOff, ImportThunkX86, sizeof(ImportThunkX86));679 memcpy(buf, importThunkX86, sizeof(importThunkX86));
643 // The first two bytes is a JMP instruction. Fill its operand.680 // The first two bytes is a JMP instruction. Fill its operand.
644 write32le(Buf + OutputSectionOff + 2,681 write32le(buf + 2,
645 ImpSymbol->getRVA() + Config->ImageBase);682 impSymbol->getRVA() + config->imageBase);
646}683}
647684
648void ImportThunkChunkARM::getBaserels(std::vector<Baserel> *Res) {685void ImportThunkChunkARM::getBaserels(std::vector<Baserel> *res) {
649 Res->emplace_back(getRVA(), IMAGE_REL_BASED_ARM_MOV32T);686 res->emplace_back(getRVA(), IMAGE_REL_BASED_ARM_MOV32T);
650}687}
651688
652void ImportThunkChunkARM::writeTo(uint8_t *Buf) const {689void ImportThunkChunkARM::writeTo(uint8_t *buf) const {
653 memcpy(Buf + OutputSectionOff, ImportThunkARM, sizeof(ImportThunkARM));690 memcpy(buf, importThunkARM, sizeof(importThunkARM));
654 // Fix mov.w and mov.t operands.691 // Fix mov.w and mov.t operands.
655 applyMOV32T(Buf + OutputSectionOff, ImpSymbol->getRVA() + Config->ImageBase);692 applyMOV32T(buf, impSymbol->getRVA() + config->imageBase);
656}693}
657694
658void ImportThunkChunkARM64::writeTo(uint8_t *Buf) const {695void ImportThunkChunkARM64::writeTo(uint8_t *buf) const {
659 int64_t Off = ImpSymbol->getRVA() & 0xfff;696 int64_t off = impSymbol->getRVA() & 0xfff;
660 memcpy(Buf + OutputSectionOff, ImportThunkARM64, sizeof(ImportThunkARM64));697 memcpy(buf, importThunkARM64, sizeof(importThunkARM64));
661 applyArm64Addr(Buf + OutputSectionOff, ImpSymbol->getRVA(), RVA, 12);698 applyArm64Addr(buf, impSymbol->getRVA(), rva, 12);
662 applyArm64Ldr(Buf + OutputSectionOff + 4, Off);699 applyArm64Ldr(buf + 4, off);
663}700}
664701
665// A Thumb2, PIC, non-interworking range extension thunk.702// A Thumb2, PIC, non-interworking range extension thunk.
666const uint8_t ArmThunk[] = {703const uint8_t armThunk[] = {
667 0x40, 0xf2, 0x00, 0x0c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)704 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)705 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4)
669 0xe7, 0x44, // L1: add pc, ip706 0xe7, 0x44, // L1: add pc, ip
670};707};
671708
672size_t RangeExtensionThunkARM::getSize() const {709size_t RangeExtensionThunkARM::getSize() const {
673 assert(Config->Machine == ARMNT);710 assert(config->machine == ARMNT);
674 return sizeof(ArmThunk);711 return sizeof(armThunk);
675}712}
676713
677void RangeExtensionThunkARM::writeTo(uint8_t *Buf) const {714void RangeExtensionThunkARM::writeTo(uint8_t *buf) const {
678 assert(Config->Machine == ARMNT);715 assert(config->machine == ARMNT);
679 uint64_t Offset = Target->getRVA() - RVA - 12;716 uint64_t offset = target->getRVA() - rva - 12;
680 memcpy(Buf + OutputSectionOff, ArmThunk, sizeof(ArmThunk));717 memcpy(buf, armThunk, sizeof(armThunk));
681 applyMOV32T(Buf + OutputSectionOff, uint32_t(Offset));718 applyMOV32T(buf, uint32_t(offset));
682}719}
683720
684// A position independent ARM64 adrp+add thunk, with a maximum range of721// A position independent ARM64 adrp+add thunk, with a maximum range of
685// +/- 4 GB, which is enough for any PE-COFF.722// +/- 4 GB, which is enough for any PE-COFF.
686const uint8_t Arm64Thunk[] = {723const uint8_t arm64Thunk[] = {
687 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest724 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest
688 0x10, 0x02, 0x00, 0x91, // add x16, x16, :lo12:Dest725 0x10, 0x02, 0x00, 0x91, // add x16, x16, :lo12:Dest
689 0x00, 0x02, 0x1f, 0xd6, // br x16726 0x00, 0x02, 0x1f, 0xd6, // br x16
690};727};
691728
692size_t RangeExtensionThunkARM64::getSize() const {729size_t RangeExtensionThunkARM64::getSize() const {
693 assert(Config->Machine == ARM64);730 assert(config->machine == ARM64);
694 return sizeof(Arm64Thunk);731 return sizeof(arm64Thunk);
695}732}
696733
697void RangeExtensionThunkARM64::writeTo(uint8_t *Buf) const {734void RangeExtensionThunkARM64::writeTo(uint8_t *buf) const {
698 assert(Config->Machine == ARM64);735 assert(config->machine == ARM64);
699 memcpy(Buf + OutputSectionOff, Arm64Thunk, sizeof(Arm64Thunk));736 memcpy(buf, arm64Thunk, sizeof(arm64Thunk));
700 applyArm64Addr(Buf + OutputSectionOff + 0, Target->getRVA(), RVA, 12);737 applyArm64Addr(buf + 0, target->getRVA(), rva, 12);
701 applyArm64Imm(Buf + OutputSectionOff + 4, Target->getRVA() & 0xfff, 0);738 applyArm64Imm(buf + 4, target->getRVA() & 0xfff, 0);
702}739}
703740
704void LocalImportChunk::getBaserels(std::vector<Baserel> *Res) {741void LocalImportChunk::getBaserels(std::vector<Baserel> *res) {
705 Res->emplace_back(getRVA());742 res->emplace_back(getRVA());
706}743}
707744
708size_t LocalImportChunk::getSize() const { return Config->Wordsize; }745size_t LocalImportChunk::getSize() const { return config->wordsize; }
709746
710void LocalImportChunk::writeTo(uint8_t *Buf) const {747void LocalImportChunk::writeTo(uint8_t *buf) const {
711 if (Config->is64()) {748 if (config->is64()) {
712 write64le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase);749 write64le(buf, sym->getRVA() + config->imageBase);
713 } else {750 } else {
714 write32le(Buf + OutputSectionOff, Sym->getRVA() + Config->ImageBase);751 write32le(buf, sym->getRVA() + config->imageBase);
715 }752 }
716}753}
717754
718void RVATableChunk::writeTo(uint8_t *Buf) const {755void RVATableChunk::writeTo(uint8_t *buf) const {
719 ulittle32_t *Begin = reinterpret_cast<ulittle32_t *>(Buf + OutputSectionOff);756 ulittle32_t *begin = reinterpret_cast<ulittle32_t *>(buf);
720 size_t Cnt = 0;757 size_t cnt = 0;
721 for (const ChunkAndOffset &CO : Syms)758 for (const ChunkAndOffset &co : syms)
722 Begin[Cnt++] = CO.InputChunk->getRVA() + CO.Offset;759 begin[cnt++] = co.inputChunk->getRVA() + co.offset;
723 std::sort(Begin, Begin + Cnt);760 std::sort(begin, begin + cnt);
724 assert(std::unique(Begin, Begin + Cnt) == Begin + Cnt &&761 assert(std::unique(begin, begin + cnt) == begin + cnt &&
725 "RVA tables should be de-duplicated");762 "RVA tables should be de-duplicated");
726}763}
727764
728// MinGW specific, for the "automatic import of variables from DLLs" feature.765// MinGW specific, for the "automatic import of variables from DLLs" feature.
729size_t PseudoRelocTableChunk::getSize() const {766size_t PseudoRelocTableChunk::getSize() const {
730 if (Relocs.empty())767 if (relocs.empty())
731 return 0;768 return 0;
732 return 12 + 12 * Relocs.size();769 return 12 + 12 * relocs.size();
733}770}
734771
735// MinGW specific.772// MinGW specific.
736void PseudoRelocTableChunk::writeTo(uint8_t *Buf) const {773void PseudoRelocTableChunk::writeTo(uint8_t *buf) const {
737 if (Relocs.empty())774 if (relocs.empty())
738 return;775 return;
739776
740 ulittle32_t *Table = reinterpret_cast<ulittle32_t *>(Buf + OutputSectionOff);777 ulittle32_t *table = reinterpret_cast<ulittle32_t *>(buf);
741 // This is the list header, to signal the runtime pseudo relocation v2778 // This is the list header, to signal the runtime pseudo relocation v2
742 // format.779 // format.
743 Table[0] = 0;780 table[0] = 0;
744 Table[1] = 0;781 table[1] = 0;
745 Table[2] = 1;782 table[2] = 1;
746783
747 size_t Idx = 3;784 size_t idx = 3;
748 for (const RuntimePseudoReloc &RPR : Relocs) {785 for (const RuntimePseudoReloc &rpr : relocs) {
749 Table[Idx + 0] = RPR.Sym->getRVA();786 table[idx + 0] = rpr.sym->getRVA();
750 Table[Idx + 1] = RPR.Target->getRVA() + RPR.TargetOffset;787 table[idx + 1] = rpr.target->getRVA() + rpr.targetOffset;
751 Table[Idx + 2] = RPR.Flags;788 table[idx + 2] = rpr.flags;
752 Idx += 3;789 idx += 3;
753 }790 }
754}791}
755792
...@@ -792,26 +829,26 @@ void PseudoRelocTableChunk::writeTo(uint8_t *Buf) const {...@@ -792,26 +829,26 @@ void PseudoRelocTableChunk::writeTo(uint8_t *Buf) const {
792//829//
793// Usually we have a lot of relocations for each page, so the number of830// Usually we have a lot of relocations for each page, so the number of
794// bytes for one .reloc entry is close to 2 bytes on average.831// bytes for one .reloc entry is close to 2 bytes on average.
795BaserelChunk::BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End) {832BaserelChunk::BaserelChunk(uint32_t page, Baserel *begin, Baserel *end) {
796 // Block header consists of 4 byte page RVA and 4 byte block size.833 // Block header consists of 4 byte page RVA and 4 byte block size.
797 // Each entry is 2 byte. Last entry may be padding.834 // Each entry is 2 byte. Last entry may be padding.
798 Data.resize(alignTo((End - Begin) * 2 + 8, 4));835 data.resize(alignTo((end - begin) * 2 + 8, 4));
799 uint8_t *P = Data.data();836 uint8_t *p = data.data();
800 write32le(P, Page);837 write32le(p, page);
801 write32le(P + 4, Data.size());838 write32le(p + 4, data.size());
802 P += 8;839 p += 8;
803 for (Baserel *I = Begin; I != End; ++I) {840 for (Baserel *i = begin; i != end; ++i) {
804 write16le(P, (I->Type << 12) | (I->RVA - Page));841 write16le(p, (i->type << 12) | (i->rva - page));
805 P += 2;842 p += 2;
806 }843 }
807}844}
808845
809void BaserelChunk::writeTo(uint8_t *Buf) const {846void BaserelChunk::writeTo(uint8_t *buf) const {
810 memcpy(Buf + OutputSectionOff, Data.data(), Data.size());847 memcpy(buf, data.data(), data.size());
811}848}
812849
813uint8_t Baserel::getDefaultType() {850uint8_t Baserel::getDefaultType() {
814 switch (Config->Machine) {851 switch (config->machine) {
815 case AMD64:852 case AMD64:
816 case ARM64:853 case ARM64:
817 return IMAGE_REL_BASED_DIR64;854 return IMAGE_REL_BASED_DIR64;
...@@ -823,36 +860,38 @@ uint8_t Baserel::getDefaultType() {...@@ -823,36 +860,38 @@ uint8_t Baserel::getDefaultType() {
823 }860 }
824}861}
825862
826std::map<uint32_t, MergeChunk *> MergeChunk::Instances;863MergeChunk *MergeChunk::instances[Log2MaxSectionAlignment + 1] = {};
827864
828MergeChunk::MergeChunk(uint32_t Alignment)865MergeChunk::MergeChunk(uint32_t alignment)
829 : Builder(StringTableBuilder::RAW, Alignment) {866 : builder(StringTableBuilder::RAW, alignment) {
830 this->Alignment = Alignment;867 setAlignment(alignment);
831}868}
832869
833void MergeChunk::addSection(SectionChunk *C) {870void MergeChunk::addSection(SectionChunk *c) {
834 auto *&MC = Instances[C->Alignment];871 assert(isPowerOf2_32(c->getAlignment()));
835 if (!MC)872 uint8_t p2Align = llvm::Log2_32(c->getAlignment());
836 MC = make<MergeChunk>(C->Alignment);873 assert(p2Align < array_lengthof(instances));
837 MC->Sections.push_back(C);874 auto *&mc = instances[p2Align];
875 if (!mc)
876 mc = make<MergeChunk>(c->getAlignment());
877 mc->sections.push_back(c);
838}878}
839879
840void MergeChunk::finalizeContents() {880void MergeChunk::finalizeContents() {
841 if (!Finalized) {881 assert(!finalized && "should only finalize once");
842 for (SectionChunk *C : Sections)882 for (SectionChunk *c : sections)
843 if (C->Live)883 if (c->live)
844 Builder.add(toStringRef(C->getContents()));884 builder.add(toStringRef(c->getContents()));
845 Builder.finalize();885 builder.finalize();
846 Finalized = true;886 finalized = true;
847 }887}
848888
849 for (SectionChunk *C : Sections) {889void MergeChunk::assignSubsectionRVAs() {
850 if (!C->Live)890 for (SectionChunk *c : sections) {
891 if (!c->live)
851 continue;892 continue;
852 size_t Off = Builder.getOffset(toStringRef(C->getContents()));893 size_t off = builder.getOffset(toStringRef(c->getContents()));
853 C->setOutputSection(Out);894 c->setRVA(rva + off);
854 C->setRVA(RVA + Off);
855 C->OutputSectionOff = OutputSectionOff + Off;
856 }895 }
857}896}
858897
...@@ -861,21 +900,21 @@ uint32_t MergeChunk::getOutputCharacteristics() const {...@@ -861,21 +900,21 @@ uint32_t MergeChunk::getOutputCharacteristics() const {
861}900}
862901
863size_t MergeChunk::getSize() const {902size_t MergeChunk::getSize() const {
864 return Builder.getSize();903 return builder.getSize();
865}904}
866905
867void MergeChunk::writeTo(uint8_t *Buf) const {906void MergeChunk::writeTo(uint8_t *buf) const {
868 Builder.write(Buf + OutputSectionOff);907 builder.write(buf);
869}908}
870909
871// MinGW specific.910// MinGW specific.
872size_t AbsolutePointerChunk::getSize() const { return Config->Wordsize; }911size_t AbsolutePointerChunk::getSize() const { return config->wordsize; }
873912
874void AbsolutePointerChunk::writeTo(uint8_t *Buf) const {913void AbsolutePointerChunk::writeTo(uint8_t *buf) const {
875 if (Config->is64()) {914 if (config->is64()) {
876 write64le(Buf + OutputSectionOff, Value);915 write64le(buf, value);
877 } else {916 } else {
878 write32le(Buf + OutputSectionOff, Value);917 write32le(buf, value);
879 }918 }
880}919}
881920
deps/lld/COFF/Chunks.h+368-209
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Chunks.h -------------------------------------------------*- C++ -*-===//1//===- Chunks.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -14,6 +13,7 @@...@@ -14,6 +13,7 @@
14#include "InputFiles.h"13#include "InputFiles.h"
15#include "lld/Common/LLVM.h"14#include "lld/Common/LLVM.h"
16#include "llvm/ADT/ArrayRef.h"15#include "llvm/ADT/ArrayRef.h"
16#include "llvm/ADT/PointerIntPair.h"
17#include "llvm/ADT/iterator.h"17#include "llvm/ADT/iterator.h"
18#include "llvm/ADT/iterator_range.h"18#include "llvm/ADT/iterator_range.h"
19#include "llvm/MC/StringTableBuilder.h"19#include "llvm/MC/StringTableBuilder.h"
...@@ -40,10 +40,13 @@ class RuntimePseudoReloc;...@@ -40,10 +40,13 @@ class RuntimePseudoReloc;
40class Symbol;40class Symbol;
4141
42// Mask for permissions (discardable, writable, readable, executable, etc).42// Mask for permissions (discardable, writable, readable, executable, etc).
43const uint32_t PermMask = 0xFE000000;43const uint32_t permMask = 0xFE000000;
4444
45// Mask for section types (code, data, bss).45// Mask for section types (code, data, bss).
46const uint32_t TypeMask = 0x000000E0;46const uint32_t typeMask = 0x000000E0;
47
48// The log base 2 of the largest section alignment, which is log2(8192), or 13.
49enum : unsigned { Log2MaxSectionAlignment = 13 };
4750
48// A Chunk represents a chunk of data that will occupy space in the51// A Chunk represents a chunk of data that will occupy space in the
49// output (if the resolver chose that). It may or may not be backed by52// output (if the resolver chose that). It may or may not be backed by
...@@ -51,81 +54,126 @@ const uint32_t TypeMask = 0x000000E0;...@@ -51,81 +54,126 @@ const uint32_t TypeMask = 0x000000E0;
51// doesn't even have actual data (if common or bss).54// doesn't even have actual data (if common or bss).
52class Chunk {55class Chunk {
53public:56public:
54 enum Kind { SectionKind, OtherKind };57 enum Kind : uint8_t { SectionKind, OtherKind, ImportThunkKind };
55 Kind kind() const { return ChunkKind; }58 Kind kind() const { return chunkKind; }
56 virtual ~Chunk() = default;
5759
58 // Returns the size of this chunk (even if this is a common or BSS.)60 // Returns the size of this chunk (even if this is a common or BSS.)
59 virtual size_t getSize() const = 0;61 size_t getSize() const;
62
63 // Returns chunk alignment in power of two form. Value values are powers of
64 // two from 1 to 8192.
65 uint32_t getAlignment() const { return 1U << p2Align; }
66
67 // Update the chunk section alignment measured in bytes. Internally alignment
68 // is stored in log2.
69 void setAlignment(uint32_t align) {
70 // Treat zero byte alignment as 1 byte alignment.
71 align = align ? align : 1;
72 assert(llvm::isPowerOf2_32(align) && "alignment is not a power of 2");
73 p2Align = llvm::Log2_32(align);
74 assert(p2Align <= Log2MaxSectionAlignment &&
75 "impossible requested alignment");
76 }
6077
61 // Write this chunk to a mmap'ed file, assuming Buf is pointing to78 // Write this chunk to a mmap'ed file, assuming Buf is pointing to
62 // beginning of the file. Because this function may use RVA values79 // beginning of the file. Because this function may use RVA values
63 // of other chunks for relocations, you need to set them properly80 // of other chunks for relocations, you need to set them properly
64 // before calling this function.81 // before calling this function.
65 virtual void writeTo(uint8_t *Buf) const {}82 void writeTo(uint8_t *buf) const;
83
84 // The writer sets and uses the addresses. In practice, PE images cannot be
85 // larger than 2GB. Chunks are always laid as part of the image, so Chunk RVAs
86 // can be stored with 32 bits.
87 uint32_t getRVA() const { return rva; }
88 void setRVA(uint64_t v) {
89 rva = (uint32_t)v;
90 assert(rva == v && "RVA truncated");
91 }
6692
67 // Called by the writer once before assigning addresses and writing93 // Returns readable/writable/executable bits.
68 // the output.94 uint32_t getOutputCharacteristics() const;
69 virtual void readRelocTargets() {}
7095
71 // Called if restarting thunk addition.96 // Returns the section name if this is a section chunk.
72 virtual void resetRelocTargets() {}97 // It is illegal to call this function on non-section chunks.
98 StringRef getSectionName() const;
7399
74 // Called by the writer after an RVA is assigned, but before calling100 // An output section has pointers to chunks in the section, and each
75 // getSize().101 // chunk has a back pointer to an output section.
76 virtual void finalizeContents() {}102 void setOutputSectionIdx(uint16_t o) { osidx = o; }
103 uint16_t getOutputSectionIdx() const { return osidx; }
104 OutputSection *getOutputSection() const;
77105
78 // The writer sets and uses the addresses.106 // Windows-specific.
79 uint64_t getRVA() const { return RVA; }107 // Collect all locations that contain absolute addresses for base relocations.
80 void setRVA(uint64_t V) { RVA = V; }108 void getBaserels(std::vector<Baserel> *res);
81109
110 // Returns a human-readable name of this chunk. Chunks are unnamed chunks of
111 // bytes, so this is used only for logging or debugging.
112 StringRef getDebugName() const;
113
114 // Return true if this file has the hotpatch flag set to true in the
115 // S_COMPILE3 record in codeview debug info. Also returns true for some thunks
116 // synthesized by the linker.
117 bool isHotPatchable() const;
118
119protected:
120 Chunk(Kind k = OtherKind) : chunkKind(k), hasData(true), p2Align(0) {}
121
122 const Kind chunkKind;
123
124public:
82 // Returns true if this has non-zero data. BSS chunks return125 // Returns true if this has non-zero data. BSS chunks return
83 // false. If false is returned, the space occupied by this chunk126 // false. If false is returned, the space occupied by this chunk
84 // will be filled with zeros.127 // will be filled with zeros. Corresponds to the
85 virtual bool hasData() const { return true; }128 // IMAGE_SCN_CNT_UNINITIALIZED_DATA section characteristic bit.
129 uint8_t hasData : 1;
130
131public:
132 // The alignment of this chunk, stored in log2 form. The writer uses the
133 // value.
134 uint8_t p2Align : 7;
135
136 // The output section index for this chunk. The first valid section number is
137 // one.
138 uint16_t osidx = 0;
139
140 // The RVA of this chunk in the output. The writer sets a value.
141 uint32_t rva = 0;
142};
143
144class NonSectionChunk : public Chunk {
145public:
146 virtual ~NonSectionChunk() = default;
147
148 // Returns the size of this chunk (even if this is a common or BSS.)
149 virtual size_t getSize() const = 0;
86150
87 // Returns readable/writable/executable bits.
88 virtual uint32_t getOutputCharacteristics() const { return 0; }151 virtual uint32_t getOutputCharacteristics() const { return 0; }
89152
153 // Write this chunk to a mmap'ed file, assuming Buf is pointing to
154 // beginning of the file. Because this function may use RVA values
155 // of other chunks for relocations, you need to set them properly
156 // before calling this function.
157 virtual void writeTo(uint8_t *buf) const {}
158
90 // Returns the section name if this is a section chunk.159 // Returns the section name if this is a section chunk.
91 // It is illegal to call this function on non-section chunks.160 // It is illegal to call this function on non-section chunks.
92 virtual StringRef getSectionName() const {161 virtual StringRef getSectionName() const {
93 llvm_unreachable("unimplemented getSectionName");162 llvm_unreachable("unimplemented getSectionName");
94 }163 }
95164
96 // An output section has pointers to chunks in the section, and each
97 // chunk has a back pointer to an output section.
98 void setOutputSection(OutputSection *O) { Out = O; }
99 OutputSection *getOutputSection() const { return Out; }
100
101 // Windows-specific.165 // Windows-specific.
102 // Collect all locations that contain absolute addresses for base relocations.166 // Collect all locations that contain absolute addresses for base relocations.
103 virtual void getBaserels(std::vector<Baserel> *Res) {}167 virtual void getBaserels(std::vector<Baserel> *res) {}
104168
105 // Returns a human-readable name of this chunk. Chunks are unnamed chunks of169 // Returns a human-readable name of this chunk. Chunks are unnamed chunks of
106 // bytes, so this is used only for logging or debugging.170 // bytes, so this is used only for logging or debugging.
107 virtual StringRef getDebugName() { return ""; }171 virtual StringRef getDebugName() const { return ""; }
108172
109 // The alignment of this chunk. The writer uses the value.173 static bool classof(const Chunk *c) { return c->kind() != SectionKind; }
110 uint32_t Alignment = 1;
111174
112protected:175protected:
113 Chunk(Kind K = OtherKind) : ChunkKind(K) {}176 NonSectionChunk(Kind k = OtherKind) : Chunk(k) {}
114 const Kind ChunkKind;
115
116 // The RVA of this chunk in the output. The writer sets a value.
117 uint64_t RVA = 0;
118
119 // The output section for this chunk.
120 OutputSection *Out = nullptr;
121
122public:
123 // The offset from beginning of the output section. The writer sets a value.
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;
129};177};
130178
131// A chunk corresponding a section of an input file.179// A chunk corresponding a section of an input file.
...@@ -139,39 +187,41 @@ public:...@@ -139,39 +187,41 @@ public:
139 std::random_access_iterator_tag, Symbol *> {187 std::random_access_iterator_tag, Symbol *> {
140 friend SectionChunk;188 friend SectionChunk;
141189
142 ObjFile *File;190 ObjFile *file;
143191
144 symbol_iterator(ObjFile *File, const coff_relocation *I)192 symbol_iterator(ObjFile *file, const coff_relocation *i)
145 : symbol_iterator::iterator_adaptor_base(I), File(File) {}193 : symbol_iterator::iterator_adaptor_base(i), file(file) {}
146194
147 public:195 public:
148 symbol_iterator() = default;196 symbol_iterator() = default;
149197
150 Symbol *operator*() const { return File->getSymbol(I->SymbolTableIndex); }198 Symbol *operator*() const { return file->getSymbol(I->SymbolTableIndex); }
151 };199 };
152200
153 SectionChunk(ObjFile *File, const coff_section *Header);201 SectionChunk(ObjFile *file, const coff_section *header);
154 static bool classof(const Chunk *C) { return C->kind() == SectionKind; }202 static bool classof(const Chunk *c) { return c->kind() == SectionKind; }
155 void readRelocTargets() override;203 size_t getSize() const { return header->SizeOfRawData; }
156 void resetRelocTargets() override;
157 size_t getSize() const override { return Header->SizeOfRawData; }
158 ArrayRef<uint8_t> getContents() const;204 ArrayRef<uint8_t> getContents() const;
159 void writeTo(uint8_t *Buf) const override;205 void writeTo(uint8_t *buf) const;
160 bool hasData() const override;206
161 uint32_t getOutputCharacteristics() const override;207 uint32_t getOutputCharacteristics() const {
162 StringRef getSectionName() const override { return SectionName; }208 return header->Characteristics & (permMask | typeMask);
163 void getBaserels(std::vector<Baserel> *Res) override;209 }
210 StringRef getSectionName() const {
211 return StringRef(sectionNameData, sectionNameSize);
212 }
213 void getBaserels(std::vector<Baserel> *res);
164 bool isCOMDAT() const;214 bool isCOMDAT() const;
165 void applyRelX64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,215 void applyRelX64(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s,
166 uint64_t P) const;216 uint64_t p) const;
167 void applyRelX86(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,217 void applyRelX86(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s,
168 uint64_t P) const;218 uint64_t p) const;
169 void applyRelARM(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,219 void applyRelARM(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s,
170 uint64_t P) const;220 uint64_t p) const;
171 void applyRelARM64(uint8_t *Off, uint16_t Type, OutputSection *OS, uint64_t S,221 void applyRelARM64(uint8_t *off, uint16_t type, OutputSection *os, uint64_t s,
172 uint64_t P) const;222 uint64_t p) const;
173223
174 void getRuntimePseudoRelocs(std::vector<RuntimePseudoReloc> &Res);224 void getRuntimePseudoRelocs(std::vector<RuntimePseudoReloc> &res);
175225
176 // Called if the garbage collector decides to not include this chunk226 // Called if the garbage collector decides to not include this chunk
177 // in a final output. It's supposed to print out a log message to stdout.227 // in a final output. It's supposed to print out a log message to stdout.
...@@ -179,69 +229,169 @@ public:...@@ -179,69 +229,169 @@ public:
179229
180 // Adds COMDAT associative sections to this COMDAT section. A chunk230 // Adds COMDAT associative sections to this COMDAT section. A chunk
181 // and its children are treated as a group by the garbage collector.231 // and its children are treated as a group by the garbage collector.
182 void addAssociative(SectionChunk *Child);232 void addAssociative(SectionChunk *child);
183233
184 StringRef getDebugName() override;234 StringRef getDebugName() const;
185235
186 // True if this is a codeview debug info chunk. These will not be laid out in236 // True if this is a codeview debug info chunk. These will not be laid out in
187 // the image. Instead they will end up in the PDB, if one is requested.237 // the image. Instead they will end up in the PDB, if one is requested.
188 bool isCodeView() const {238 bool isCodeView() const {
189 return SectionName == ".debug" || SectionName.startswith(".debug$");239 return getSectionName() == ".debug" || getSectionName().startswith(".debug$");
190 }240 }
191241
192 // True if this is a DWARF debug info or exception handling chunk.242 // True if this is a DWARF debug info or exception handling chunk.
193 bool isDWARF() const {243 bool isDWARF() const {
194 return SectionName.startswith(".debug_") || SectionName == ".eh_frame";244 return getSectionName().startswith(".debug_") || getSectionName() == ".eh_frame";
195 }245 }
196246
197 // Allow iteration over the bodies of this chunk's relocated symbols.247 // Allow iteration over the bodies of this chunk's relocated symbols.
198 llvm::iterator_range<symbol_iterator> symbols() const {248 llvm::iterator_range<symbol_iterator> symbols() const {
199 return llvm::make_range(symbol_iterator(File, Relocs.begin()),249 return llvm::make_range(symbol_iterator(file, relocsData),
200 symbol_iterator(File, Relocs.end()));250 symbol_iterator(file, relocsData + relocsSize));
251 }
252
253 ArrayRef<coff_relocation> getRelocs() const {
254 return llvm::makeArrayRef(relocsData, relocsSize);
201 }255 }
202256
257 // Reloc setter used by ARM range extension thunk insertion.
258 void setRelocs(ArrayRef<coff_relocation> newRelocs) {
259 relocsData = newRelocs.data();
260 relocsSize = newRelocs.size();
261 assert(relocsSize == newRelocs.size() && "reloc size truncation");
262 }
263
264 // Single linked list iterator for associated comdat children.
265 class AssociatedIterator
266 : public llvm::iterator_facade_base<
267 AssociatedIterator, std::forward_iterator_tag, SectionChunk> {
268 public:
269 AssociatedIterator() = default;
270 AssociatedIterator(SectionChunk *head) : cur(head) {}
271 AssociatedIterator &operator=(const AssociatedIterator &r) {
272 cur = r.cur;
273 return *this;
274 }
275 bool operator==(const AssociatedIterator &r) const { return cur == r.cur; }
276 const SectionChunk &operator*() const { return *cur; }
277 SectionChunk &operator*() { return *cur; }
278 AssociatedIterator &operator++() {
279 cur = cur->assocChildren;
280 return *this;
281 }
282
283 private:
284 SectionChunk *cur = nullptr;
285 };
286
203 // Allow iteration over the associated child chunks for this section.287 // Allow iteration over the associated child chunks for this section.
204 ArrayRef<SectionChunk *> children() const { return AssocChildren; }288 llvm::iterator_range<AssociatedIterator> children() const {
289 return llvm::make_range(AssociatedIterator(assocChildren),
290 AssociatedIterator(nullptr));
291 }
205292
206 // The section ID this chunk belongs to in its Obj.293 // The section ID this chunk belongs to in its Obj.
207 uint32_t getSectionNumber() const;294 uint32_t getSectionNumber() const;
208295
209 // A pointer pointing to a replacement for this chunk.296 ArrayRef<uint8_t> consumeDebugMagic();
210 // Initially it points to "this" object. If this chunk is merged
211 // with other chunk by ICF, it points to another chunk,
212 // and this chunk is considered as dead.
213 SectionChunk *Repl;
214297
215 // The CRC of the contents as described in the COFF spec 4.5.5.298 static ArrayRef<uint8_t> consumeDebugMagic(ArrayRef<uint8_t> data,
216 // Auxiliary Format 5: Section Definitions. Used for ICF.299 StringRef sectionName);
217 uint32_t Checksum = 0;
218300
219 const coff_section *Header;301 static SectionChunk *findByName(ArrayRef<SectionChunk *> sections,
302 StringRef name);
220303
221 // The file that this chunk was created from.304 // The file that this chunk was created from.
222 ObjFile *File;305 ObjFile *file;
306
307 // Pointer to the COFF section header in the input file.
308 const coff_section *header;
223309
224 // The COMDAT leader symbol if this is a COMDAT chunk.310 // The COMDAT leader symbol if this is a COMDAT chunk.
225 DefinedRegular *Sym = nullptr;311 DefinedRegular *sym = nullptr;
226312
227 ArrayRef<coff_relocation> Relocs;313 // The CRC of the contents as described in the COFF spec 4.5.5.
314 // Auxiliary Format 5: Section Definitions. Used for ICF.
315 uint32_t checksum = 0;
228316
229 // Used by the garbage collector.317 // Used by the garbage collector.
230 bool Live;318 bool live;
319
320 // Whether this section needs to be kept distinct from other sections during
321 // ICF. This is set by the driver using address-significance tables.
322 bool keepUnique = false;
231323
232 // When inserting a thunk, we need to adjust a relocation to point to324 // The COMDAT selection if this is a COMDAT chunk.
233 // the thunk instead of the actual original target Symbol.325 llvm::COFF::COMDATType selection = (llvm::COFF::COMDATType)0;
234 std::vector<Symbol *> RelocTargets;326
327 // A pointer pointing to a replacement for this chunk.
328 // Initially it points to "this" object. If this chunk is merged
329 // with other chunk by ICF, it points to another chunk,
330 // and this chunk is considered as dead.
331 SectionChunk *repl;
235332
236private:333private:
237 StringRef SectionName;334 SectionChunk *assocChildren = nullptr;
238 std::vector<SectionChunk *> AssocChildren;
239335
240 // Used for ICF (Identical COMDAT Folding)336 // Used for ICF (Identical COMDAT Folding)
241 void replace(SectionChunk *Other);337 void replace(SectionChunk *other);
242 uint32_t Class[2] = {0, 0};338 uint32_t eqClass[2] = {0, 0};
339
340 // Relocations for this section. Size is stored below.
341 const coff_relocation *relocsData;
342
343 // Section name string. Size is stored below.
344 const char *sectionNameData;
345
346 uint32_t relocsSize = 0;
347 uint32_t sectionNameSize = 0;
243};348};
244349
350// Inline methods to implement faux-virtual dispatch for SectionChunk.
351
352inline size_t Chunk::getSize() const {
353 if (isa<SectionChunk>(this))
354 return static_cast<const SectionChunk *>(this)->getSize();
355 else
356 return static_cast<const NonSectionChunk *>(this)->getSize();
357}
358
359inline uint32_t Chunk::getOutputCharacteristics() const {
360 if (isa<SectionChunk>(this))
361 return static_cast<const SectionChunk *>(this)->getOutputCharacteristics();
362 else
363 return static_cast<const NonSectionChunk *>(this)
364 ->getOutputCharacteristics();
365}
366
367inline void Chunk::writeTo(uint8_t *buf) const {
368 if (isa<SectionChunk>(this))
369 static_cast<const SectionChunk *>(this)->writeTo(buf);
370 else
371 static_cast<const NonSectionChunk *>(this)->writeTo(buf);
372}
373
374inline StringRef Chunk::getSectionName() const {
375 if (isa<SectionChunk>(this))
376 return static_cast<const SectionChunk *>(this)->getSectionName();
377 else
378 return static_cast<const NonSectionChunk *>(this)->getSectionName();
379}
380
381inline void Chunk::getBaserels(std::vector<Baserel> *res) {
382 if (isa<SectionChunk>(this))
383 static_cast<SectionChunk *>(this)->getBaserels(res);
384 else
385 static_cast<NonSectionChunk *>(this)->getBaserels(res);
386}
387
388inline StringRef Chunk::getDebugName() const {
389 if (isa<SectionChunk>(this))
390 return static_cast<const SectionChunk *>(this)->getDebugName();
391 else
392 return static_cast<const NonSectionChunk *>(this)->getDebugName();
393}
394
245// This class is used to implement an lld-specific feature (not implemented in395// This class is used to implement an lld-specific feature (not implemented in
246// MSVC) that minimizes the output size by finding string literals sharing tail396// MSVC) that minimizes the output size by finding string literals sharing tail
247// parts and merging them.397// parts and merging them.
...@@ -251,60 +401,60 @@ private:...@@ -251,60 +401,60 @@ private:
251// The MergeChunk then tail merges the strings using the StringTableBuilder401// The MergeChunk then tail merges the strings using the StringTableBuilder
252// class and assigns RVAs and section offsets to each of the member chunks based402// class and assigns RVAs and section offsets to each of the member chunks based
253// on the offsets assigned by the StringTableBuilder.403// on the offsets assigned by the StringTableBuilder.
254class MergeChunk : public Chunk {404class MergeChunk : public NonSectionChunk {
255public:405public:
256 MergeChunk(uint32_t Alignment);406 MergeChunk(uint32_t alignment);
257 static void addSection(SectionChunk *C);407 static void addSection(SectionChunk *c);
258 void finalizeContents() override;408 void finalizeContents();
409 void assignSubsectionRVAs();
259410
260 uint32_t getOutputCharacteristics() const override;411 uint32_t getOutputCharacteristics() const override;
261 StringRef getSectionName() const override { return ".rdata"; }412 StringRef getSectionName() const override { return ".rdata"; }
262 size_t getSize() const override;413 size_t getSize() const override;
263 void writeTo(uint8_t *Buf) const override;414 void writeTo(uint8_t *buf) const override;
264415
265 static std::map<uint32_t, MergeChunk *> Instances;416 static MergeChunk *instances[Log2MaxSectionAlignment + 1];
266 std::vector<SectionChunk *> Sections;417 std::vector<SectionChunk *> sections;
267418
268private:419private:
269 llvm::StringTableBuilder Builder;420 llvm::StringTableBuilder builder;
270 bool Finalized = false;421 bool finalized = false;
271};422};
272423
273// A chunk for common symbols. Common chunks don't have actual data.424// A chunk for common symbols. Common chunks don't have actual data.
274class CommonChunk : public Chunk {425class CommonChunk : public NonSectionChunk {
275public:426public:
276 CommonChunk(const COFFSymbolRef Sym);427 CommonChunk(const COFFSymbolRef sym);
277 size_t getSize() const override { return Sym.getValue(); }428 size_t getSize() const override { return sym.getValue(); }
278 bool hasData() const override { return false; }
279 uint32_t getOutputCharacteristics() const override;429 uint32_t getOutputCharacteristics() const override;
280 StringRef getSectionName() const override { return ".bss"; }430 StringRef getSectionName() const override { return ".bss"; }
281431
282private:432private:
283 const COFFSymbolRef Sym;433 const COFFSymbolRef sym;
284};434};
285435
286// A chunk for linker-created strings.436// A chunk for linker-created strings.
287class StringChunk : public Chunk {437class StringChunk : public NonSectionChunk {
288public:438public:
289 explicit StringChunk(StringRef S) : Str(S) {}439 explicit StringChunk(StringRef s) : str(s) {}
290 size_t getSize() const override { return Str.size() + 1; }440 size_t getSize() const override { return str.size() + 1; }
291 void writeTo(uint8_t *Buf) const override;441 void writeTo(uint8_t *buf) const override;
292442
293private:443private:
294 StringRef Str;444 StringRef str;
295};445};
296446
297static const uint8_t ImportThunkX86[] = {447static const uint8_t importThunkX86[] = {
298 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0448 0xff, 0x25, 0x00, 0x00, 0x00, 0x00, // JMP *0x0
299};449};
300450
301static const uint8_t ImportThunkARM[] = {451static const uint8_t importThunkARM[] = {
302 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0452 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0
303 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0453 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0
304 0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip]454 0xdc, 0xf8, 0x00, 0xf0, // ldr.w pc, [ip]
305};455};
306456
307static const uint8_t ImportThunkARM64[] = {457static const uint8_t importThunkARM64[] = {
308 0x10, 0x00, 0x00, 0x90, // adrp x16, #0458 0x10, 0x00, 0x00, 0x90, // adrp x16, #0
309 0x10, 0x02, 0x40, 0xf9, // ldr x16, [x16]459 0x10, 0x02, 0x40, 0xf9, // ldr x16, [x16]
310 0x00, 0x02, 0x1f, 0xd6, // br x16460 0x00, 0x02, 0x1f, 0xd6, // br x16
...@@ -313,87 +463,85 @@ static const uint8_t ImportThunkARM64[] = {...@@ -313,87 +463,85 @@ static const uint8_t ImportThunkARM64[] = {
313// Windows-specific.463// Windows-specific.
314// A chunk for DLL import jump table entry. In a final output, its464// A chunk for DLL import jump table entry. In a final output, its
315// contents will be a JMP instruction to some __imp_ symbol.465// contents will be a JMP instruction to some __imp_ symbol.
316class ImportThunkChunkX64 : public Chunk {466class ImportThunkChunk : public NonSectionChunk {
317public:467public:
318 explicit ImportThunkChunkX64(Defined *S);468 ImportThunkChunk(Defined *s)
319 size_t getSize() const override { return sizeof(ImportThunkX86); }469 : NonSectionChunk(ImportThunkKind), impSymbol(s) {}
320 void writeTo(uint8_t *Buf) const override;470 static bool classof(const Chunk *c) { return c->kind() == ImportThunkKind; }
321471
322private:472protected:
323 Defined *ImpSymbol;473 Defined *impSymbol;
324};474};
325475
326class ImportThunkChunkX86 : public Chunk {476class ImportThunkChunkX64 : public ImportThunkChunk {
327public:477public:
328 explicit ImportThunkChunkX86(Defined *S) : ImpSymbol(S) {}478 explicit ImportThunkChunkX64(Defined *s);
329 size_t getSize() const override { return sizeof(ImportThunkX86); }479 size_t getSize() const override { return sizeof(importThunkX86); }
330 void getBaserels(std::vector<Baserel> *Res) override;480 void writeTo(uint8_t *buf) const override;
331 void writeTo(uint8_t *Buf) const override;
332
333private:
334 Defined *ImpSymbol;
335};481};
336482
337class ImportThunkChunkARM : public Chunk {483class ImportThunkChunkX86 : public ImportThunkChunk {
338public:484public:
339 explicit ImportThunkChunkARM(Defined *S) : ImpSymbol(S) {}485 explicit ImportThunkChunkX86(Defined *s) : ImportThunkChunk(s) {}
340 size_t getSize() const override { return sizeof(ImportThunkARM); }486 size_t getSize() const override { return sizeof(importThunkX86); }
341 void getBaserels(std::vector<Baserel> *Res) override;487 void getBaserels(std::vector<Baserel> *res) override;
342 void writeTo(uint8_t *Buf) const override;488 void writeTo(uint8_t *buf) const override;
343
344private:
345 Defined *ImpSymbol;
346};489};
347490
348class ImportThunkChunkARM64 : public Chunk {491class ImportThunkChunkARM : public ImportThunkChunk {
349public:492public:
350 explicit ImportThunkChunkARM64(Defined *S) : ImpSymbol(S) {}493 explicit ImportThunkChunkARM(Defined *s) : ImportThunkChunk(s) {}
351 size_t getSize() const override { return sizeof(ImportThunkARM64); }494 size_t getSize() const override { return sizeof(importThunkARM); }
352 void writeTo(uint8_t *Buf) const override;495 void getBaserels(std::vector<Baserel> *res) override;
496 void writeTo(uint8_t *buf) const override;
497};
353498
354private:499class ImportThunkChunkARM64 : public ImportThunkChunk {
355 Defined *ImpSymbol;500public:
501 explicit ImportThunkChunkARM64(Defined *s) : ImportThunkChunk(s) {}
502 size_t getSize() const override { return sizeof(importThunkARM64); }
503 void writeTo(uint8_t *buf) const override;
356};504};
357505
358class RangeExtensionThunkARM : public Chunk {506class RangeExtensionThunkARM : public NonSectionChunk {
359public:507public:
360 explicit RangeExtensionThunkARM(Defined *T) : Target(T) {}508 explicit RangeExtensionThunkARM(Defined *t) : target(t) {}
361 size_t getSize() const override;509 size_t getSize() const override;
362 void writeTo(uint8_t *Buf) const override;510 void writeTo(uint8_t *buf) const override;
363511
364 Defined *Target;512 Defined *target;
365};513};
366514
367class RangeExtensionThunkARM64 : public Chunk {515class RangeExtensionThunkARM64 : public NonSectionChunk {
368public:516public:
369 explicit RangeExtensionThunkARM64(Defined *T) : Target(T) {}517 explicit RangeExtensionThunkARM64(Defined *t) : target(t) {}
370 size_t getSize() const override;518 size_t getSize() const override;
371 void writeTo(uint8_t *Buf) const override;519 void writeTo(uint8_t *buf) const override;
372520
373 Defined *Target;521 Defined *target;
374};522};
375523
376// Windows-specific.524// Windows-specific.
377// See comments for DefinedLocalImport class.525// See comments for DefinedLocalImport class.
378class LocalImportChunk : public Chunk {526class LocalImportChunk : public NonSectionChunk {
379public:527public:
380 explicit LocalImportChunk(Defined *S) : Sym(S) {528 explicit LocalImportChunk(Defined *s) : sym(s) {
381 Alignment = Config->Wordsize;529 setAlignment(config->wordsize);
382 }530 }
383 size_t getSize() const override;531 size_t getSize() const override;
384 void getBaserels(std::vector<Baserel> *Res) override;532 void getBaserels(std::vector<Baserel> *res) override;
385 void writeTo(uint8_t *Buf) const override;533 void writeTo(uint8_t *buf) const override;
386534
387private:535private:
388 Defined *Sym;536 Defined *sym;
389};537};
390538
391// Duplicate RVAs are not allowed in RVA tables, so unique symbols by chunk and539// Duplicate RVAs are not allowed in RVA tables, so unique symbols by chunk and
392// offset into the chunk. Order does not matter as the RVA table will be sorted540// offset into the chunk. Order does not matter as the RVA table will be sorted
393// later.541// later.
394struct ChunkAndOffset {542struct ChunkAndOffset {
395 Chunk *InputChunk;543 Chunk *inputChunk;
396 uint32_t Offset;544 uint32_t offset;
397545
398 struct DenseMapInfo {546 struct DenseMapInfo {
399 static ChunkAndOffset getEmptyKey() {547 static ChunkAndOffset getEmptyKey() {
...@@ -402,12 +550,12 @@ struct ChunkAndOffset {...@@ -402,12 +550,12 @@ struct ChunkAndOffset {
402 static ChunkAndOffset getTombstoneKey() {550 static ChunkAndOffset getTombstoneKey() {
403 return {llvm::DenseMapInfo<Chunk *>::getTombstoneKey(), 0};551 return {llvm::DenseMapInfo<Chunk *>::getTombstoneKey(), 0};
404 }552 }
405 static unsigned getHashValue(const ChunkAndOffset &CO) {553 static unsigned getHashValue(const ChunkAndOffset &co) {
406 return llvm::DenseMapInfo<std::pair<Chunk *, uint32_t>>::getHashValue(554 return llvm::DenseMapInfo<std::pair<Chunk *, uint32_t>>::getHashValue(
407 {CO.InputChunk, CO.Offset});555 {co.inputChunk, co.offset});
408 }556 }
409 static bool isEqual(const ChunkAndOffset &LHS, const ChunkAndOffset &RHS) {557 static bool isEqual(const ChunkAndOffset &lhs, const ChunkAndOffset &rhs) {
410 return LHS.InputChunk == RHS.InputChunk && LHS.Offset == RHS.Offset;558 return lhs.inputChunk == rhs.inputChunk && lhs.offset == rhs.offset;
411 }559 }
412 };560 };
413};561};
...@@ -415,48 +563,48 @@ struct ChunkAndOffset {...@@ -415,48 +563,48 @@ struct ChunkAndOffset {
415using SymbolRVASet = llvm::DenseSet<ChunkAndOffset>;563using SymbolRVASet = llvm::DenseSet<ChunkAndOffset>;
416564
417// Table which contains symbol RVAs. Used for /safeseh and /guard:cf.565// Table which contains symbol RVAs. Used for /safeseh and /guard:cf.
418class RVATableChunk : public Chunk {566class RVATableChunk : public NonSectionChunk {
419public:567public:
420 explicit RVATableChunk(SymbolRVASet S) : Syms(std::move(S)) {}568 explicit RVATableChunk(SymbolRVASet s) : syms(std::move(s)) {}
421 size_t getSize() const override { return Syms.size() * 4; }569 size_t getSize() const override { return syms.size() * 4; }
422 void writeTo(uint8_t *Buf) const override;570 void writeTo(uint8_t *buf) const override;
423571
424private:572private:
425 SymbolRVASet Syms;573 SymbolRVASet syms;
426};574};
427575
428// Windows-specific.576// Windows-specific.
429// This class represents a block in .reloc section.577// This class represents a block in .reloc section.
430// See the PE/COFF spec 5.6 for details.578// See the PE/COFF spec 5.6 for details.
431class BaserelChunk : public Chunk {579class BaserelChunk : public NonSectionChunk {
432public:580public:
433 BaserelChunk(uint32_t Page, Baserel *Begin, Baserel *End);581 BaserelChunk(uint32_t page, Baserel *begin, Baserel *end);
434 size_t getSize() const override { return Data.size(); }582 size_t getSize() const override { return data.size(); }
435 void writeTo(uint8_t *Buf) const override;583 void writeTo(uint8_t *buf) const override;
436584
437private:585private:
438 std::vector<uint8_t> Data;586 std::vector<uint8_t> data;
439};587};
440588
441class Baserel {589class Baserel {
442public:590public:
443 Baserel(uint32_t V, uint8_t Ty) : RVA(V), Type(Ty) {}591 Baserel(uint32_t v, uint8_t ty) : rva(v), type(ty) {}
444 explicit Baserel(uint32_t V) : Baserel(V, getDefaultType()) {}592 explicit Baserel(uint32_t v) : Baserel(v, getDefaultType()) {}
445 uint8_t getDefaultType();593 uint8_t getDefaultType();
446594
447 uint32_t RVA;595 uint32_t rva;
448 uint8_t Type;596 uint8_t type;
449};597};
450598
451// This is a placeholder Chunk, to allow attaching a DefinedSynthetic to a599// 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 MinGW600// 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 concept601// specific symbol __RUNTIME_PSEUDO_RELOC_LIST_END__, even though the concept
454// of an empty chunk isn't MinGW specific.602// of an empty chunk isn't MinGW specific.
455class EmptyChunk : public Chunk {603class EmptyChunk : public NonSectionChunk {
456public:604public:
457 EmptyChunk() {}605 EmptyChunk() {}
458 size_t getSize() const override { return 0; }606 size_t getSize() const override { return 0; }
459 void writeTo(uint8_t *Buf) const override {}607 void writeTo(uint8_t *buf) const override {}
460};608};
461609
462// MinGW specific, for the "automatic import of variables from DLLs" feature.610// MinGW specific, for the "automatic import of variables from DLLs" feature.
...@@ -465,17 +613,17 @@ public:...@@ -465,17 +613,17 @@ public:
465// the reference didn't use the dllimport attribute. The MinGW runtime will613// the reference didn't use the dllimport attribute. The MinGW runtime will
466// process this table after loading, before handling control over to user614// process this table after loading, before handling control over to user
467// code.615// code.
468class PseudoRelocTableChunk : public Chunk {616class PseudoRelocTableChunk : public NonSectionChunk {
469public:617public:
470 PseudoRelocTableChunk(std::vector<RuntimePseudoReloc> &Relocs)618 PseudoRelocTableChunk(std::vector<RuntimePseudoReloc> &relocs)
471 : Relocs(std::move(Relocs)) {619 : relocs(std::move(relocs)) {
472 Alignment = 4;620 setAlignment(4);
473 }621 }
474 size_t getSize() const override;622 size_t getSize() const override;
475 void writeTo(uint8_t *Buf) const override;623 void writeTo(uint8_t *buf) const override;
476624
477private:625private:
478 std::vector<RuntimePseudoReloc> Relocs;626 std::vector<RuntimePseudoReloc> relocs;
479};627};
480628
481// MinGW specific; information about one individual location in the image629// MinGW specific; information about one individual location in the image
...@@ -483,37 +631,48 @@ private:...@@ -483,37 +631,48 @@ private:
483// one individual element in the PseudoRelocTableChunk table.631// one individual element in the PseudoRelocTableChunk table.
484class RuntimePseudoReloc {632class RuntimePseudoReloc {
485public:633public:
486 RuntimePseudoReloc(Defined *Sym, SectionChunk *Target, uint32_t TargetOffset,634 RuntimePseudoReloc(Defined *sym, SectionChunk *target, uint32_t targetOffset,
487 int Flags)635 int flags)
488 : Sym(Sym), Target(Target), TargetOffset(TargetOffset), Flags(Flags) {}636 : sym(sym), target(target), targetOffset(targetOffset), flags(flags) {}
489637
490 Defined *Sym;638 Defined *sym;
491 SectionChunk *Target;639 SectionChunk *target;
492 uint32_t TargetOffset;640 uint32_t targetOffset;
493 // The Flags field contains the size of the relocation, in bits. No other641 // The Flags field contains the size of the relocation, in bits. No other
494 // flags are currently defined.642 // flags are currently defined.
495 int Flags;643 int flags;
496};644};
497645
498// MinGW specific. A Chunk that contains one pointer-sized absolute value.646// MinGW specific. A Chunk that contains one pointer-sized absolute value.
499class AbsolutePointerChunk : public Chunk {647class AbsolutePointerChunk : public NonSectionChunk {
500public:648public:
501 AbsolutePointerChunk(uint64_t Value) : Value(Value) {649 AbsolutePointerChunk(uint64_t value) : value(value) {
502 Alignment = getSize();650 setAlignment(getSize());
503 }651 }
504 size_t getSize() const override;652 size_t getSize() const override;
505 void writeTo(uint8_t *Buf) const override;653 void writeTo(uint8_t *buf) const override;
506654
507private:655private:
508 uint64_t Value;656 uint64_t value;
509};657};
510658
511void applyMOV32T(uint8_t *Off, uint32_t V);659// Return true if this file has the hotpatch flag set to true in the S_COMPILE3
512void applyBranch24T(uint8_t *Off, int32_t V);660// record in codeview debug info. Also returns true for some thunks synthesized
661// by the linker.
662inline bool Chunk::isHotPatchable() const {
663 if (auto *sc = dyn_cast<SectionChunk>(this))
664 return sc->file->hotPatchable;
665 else if (isa<ImportThunkChunk>(this))
666 return true;
667 return false;
668}
669
670void applyMOV32T(uint8_t *off, uint32_t v);
671void applyBranch24T(uint8_t *off, int32_t v);
513672
514void applyArm64Addr(uint8_t *Off, uint64_t S, uint64_t P, int Shift);673void applyArm64Addr(uint8_t *off, uint64_t s, uint64_t p, int shift);
515void applyArm64Imm(uint8_t *Off, uint64_t Imm, uint32_t RangeLimit);674void applyArm64Imm(uint8_t *off, uint64_t imm, uint32_t rangeLimit);
516void applyArm64Branch26(uint8_t *Off, int64_t V);675void applyArm64Branch26(uint8_t *off, int64_t v);
517676
518} // namespace coff677} // namespace coff
519} // namespace lld678} // namespace lld
deps/lld/COFF/Config.h+130-111
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Config.h -------------------------------------------------*- C++ -*-===//1//===- Config.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -29,6 +28,7 @@ class DefinedAbsolute;...@@ -29,6 +28,7 @@ class DefinedAbsolute;
29class DefinedRelative;28class DefinedRelative;
30class StringChunk;29class StringChunk;
31class Symbol;30class Symbol;
31class InputFile;
3232
33// Short aliases.33// Short aliases.
34static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;34static const auto AMD64 = llvm::COFF::IMAGE_FILE_MACHINE_AMD64;
...@@ -38,30 +38,30 @@ static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386;...@@ -38,30 +38,30 @@ static const auto I386 = llvm::COFF::IMAGE_FILE_MACHINE_I386;
3838
39// Represents an /export option.39// Represents an /export option.
40struct Export {40struct Export {
41 StringRef Name; // N in /export:N or /export:E=N41 StringRef name; // N in /export:N or /export:E=N
42 StringRef ExtName; // E in /export:E=N42 StringRef extName; // E in /export:E=N
43 Symbol *Sym = nullptr;43 Symbol *sym = nullptr;
44 uint16_t Ordinal = 0;44 uint16_t ordinal = 0;
45 bool Noname = false;45 bool noname = false;
46 bool Data = false;46 bool data = false;
47 bool Private = false;47 bool isPrivate = false;
48 bool Constant = false;48 bool constant = false;
4949
50 // If an export is a form of /export:foo=dllname.bar, that means50 // If an export is a form of /export:foo=dllname.bar, that means
51 // that foo should be exported as an alias to bar in the DLL.51 // that foo should be exported as an alias to bar in the DLL.
52 // ForwardTo is set to "dllname.bar" part. Usually empty.52 // forwardTo is set to "dllname.bar" part. Usually empty.
53 StringRef ForwardTo;53 StringRef forwardTo;
54 StringChunk *ForwardChunk = nullptr;54 StringChunk *forwardChunk = nullptr;
5555
56 // True if this /export option was in .drectves section.56 // True if this /export option was in .drectves section.
57 bool Directives = false;57 bool directives = false;
58 StringRef SymbolName;58 StringRef symbolName;
59 StringRef ExportName; // Name in DLL59 StringRef exportName; // Name in DLL
6060
61 bool operator==(const Export &E) {61 bool operator==(const Export &e) {
62 return (Name == E.Name && ExtName == E.ExtName &&62 return (name == e.name && extName == e.extName &&
63 Ordinal == E.Ordinal && Noname == E.Noname &&63 ordinal == e.ordinal && noname == e.noname &&
64 Data == E.Data && Private == E.Private);64 data == e.data && isPrivate == e.isPrivate);
65 }65 }
66};66};
6767
...@@ -81,130 +81,149 @@ enum class GuardCFLevel {...@@ -81,130 +81,149 @@ enum class GuardCFLevel {
81// Global configuration.81// Global configuration.
82struct Configuration {82struct Configuration {
83 enum ManifestKind { SideBySide, Embed, No };83 enum ManifestKind { SideBySide, Embed, No };
84 bool is64() { return Machine == AMD64 || Machine == ARM64; }84 bool is64() { return machine == AMD64 || machine == ARM64; }
8585
86 llvm::COFF::MachineTypes Machine = IMAGE_FILE_MACHINE_UNKNOWN;86 llvm::COFF::MachineTypes machine = IMAGE_FILE_MACHINE_UNKNOWN;
87 size_t Wordsize;87 size_t wordsize;
88 bool Verbose = false;88 bool verbose = false;
89 WindowsSubsystem Subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;89 WindowsSubsystem subsystem = llvm::COFF::IMAGE_SUBSYSTEM_UNKNOWN;
90 Symbol *Entry = nullptr;90 Symbol *entry = nullptr;
91 bool NoEntry = false;91 bool noEntry = false;
92 std::string OutputFile;92 std::string outputFile;
93 std::string ImportName;93 std::string importName;
94 bool DoGC = true;94 bool demangle = true;
95 bool DoICF = true;95 bool doGC = true;
96 bool TailMerge;96 bool doICF = true;
97 bool Relocatable = true;97 bool tailMerge;
98 bool ForceMultiple = false;98 bool relocatable = true;
99 bool ForceUnresolved = false;99 bool forceMultiple = false;
100 bool Debug = false;100 bool forceMultipleRes = false;
101 bool DebugDwarf = false;101 bool forceUnresolved = false;
102 bool DebugGHashes = false;102 bool debug = false;
103 bool DebugSymtab = false;103 bool debugDwarf = false;
104 bool ShowTiming = false;104 bool debugGHashes = false;
105 unsigned DebugTypes = static_cast<unsigned>(DebugType::None);105 bool debugSymtab = false;
106 std::vector<std::string> NatvisFiles;106 bool showTiming = false;
107 llvm::SmallString<128> PDBAltPath;107 bool showSummary = false;
108 llvm::SmallString<128> PDBPath;108 unsigned debugTypes = static_cast<unsigned>(DebugType::None);
109 llvm::SmallString<128> PDBSourcePath;109 std::vector<std::string> natvisFiles;
110 std::vector<llvm::StringRef> Argv;110 llvm::SmallString<128> pdbAltPath;
111 llvm::SmallString<128> pdbPath;
112 llvm::SmallString<128> pdbSourcePath;
113 std::vector<llvm::StringRef> argv;
111114
112 // Symbols in this set are considered as live by the garbage collector.115 // Symbols in this set are considered as live by the garbage collector.
113 std::vector<Symbol *> GCRoot;116 std::vector<Symbol *> gcroot;
114117
115 std::set<StringRef> NoDefaultLibs;118 std::set<std::string> noDefaultLibs;
116 bool NoDefaultLibAll = false;119 bool noDefaultLibAll = false;
117120
118 // True if we are creating a DLL.121 // True if we are creating a DLL.
119 bool DLL = false;122 bool dll = false;
120 StringRef Implib;123 StringRef implib;
121 std::vector<Export> Exports;124 std::vector<Export> exports;
122 std::set<std::string> DelayLoads;125 std::set<std::string> delayLoads;
123 std::map<std::string, int> DLLOrder;126 std::map<std::string, int> dllOrder;
124 Symbol *DelayLoadHelper = nullptr;127 Symbol *delayLoadHelper = nullptr;
125128
126 bool SaveTemps = false;129 bool saveTemps = false;
127130
128 // /guard:cf131 // /guard:cf
129 GuardCFLevel GuardCF = GuardCFLevel::Off;132 GuardCFLevel guardCF = GuardCFLevel::Off;
130133
131 // Used for SafeSEH.134 // Used for SafeSEH.
132 Symbol *SEHTable = nullptr;135 bool safeSEH = false;
133 Symbol *SEHCount = nullptr;136 Symbol *sehTable = nullptr;
137 Symbol *sehCount = nullptr;
134138
135 // Used for /opt:lldlto=N139 // Used for /opt:lldlto=N
136 unsigned LTOO = 2;140 unsigned ltoo = 2;
137141
138 // Used for /opt:lldltojobs=N142 // Used for /opt:lldltojobs=N
139 unsigned ThinLTOJobs = 0;143 unsigned thinLTOJobs = 0;
140 // Used for /opt:lldltopartitions=N144 // Used for /opt:lldltopartitions=N
141 unsigned LTOPartitions = 1;145 unsigned ltoPartitions = 1;
142146
143 // Used for /opt:lldltocache=path147 // Used for /opt:lldltocache=path
144 StringRef LTOCache;148 StringRef ltoCache;
145 // Used for /opt:lldltocachepolicy=policy149 // Used for /opt:lldltocachepolicy=policy
146 llvm::CachePruningPolicy LTOCachePolicy;150 llvm::CachePruningPolicy ltoCachePolicy;
147151
148 // Used for /merge:from=to (e.g. /merge:.rdata=.text)152 // Used for /merge:from=to (e.g. /merge:.rdata=.text)
149 std::map<StringRef, StringRef> Merge;153 std::map<StringRef, StringRef> merge;
150154
151 // Used for /section=.name,{DEKPRSW} to set section attributes.155 // Used for /section=.name,{DEKPRSW} to set section attributes.
152 std::map<StringRef, uint32_t> Section;156 std::map<StringRef, uint32_t> section;
153157
154 // Options for manifest files.158 // Options for manifest files.
155 ManifestKind Manifest = No;159 ManifestKind manifest = No;
156 int ManifestID = 1;160 int manifestID = 1;
157 StringRef ManifestDependency;161 StringRef manifestDependency;
158 bool ManifestUAC = true;162 bool manifestUAC = true;
159 std::vector<std::string> ManifestInput;163 std::vector<std::string> manifestInput;
160 StringRef ManifestLevel = "'asInvoker'";164 StringRef manifestLevel = "'asInvoker'";
161 StringRef ManifestUIAccess = "'false'";165 StringRef manifestUIAccess = "'false'";
162 StringRef ManifestFile;166 StringRef manifestFile;
163167
164 // Used for /aligncomm.168 // Used for /aligncomm.
165 std::map<std::string, int> AlignComm;169 std::map<std::string, int> alignComm;
166170
167 // Used for /failifmismatch.171 // Used for /failifmismatch.
168 std::map<StringRef, StringRef> MustMatch;172 std::map<StringRef, std::pair<StringRef, InputFile *>> mustMatch;
169173
170 // Used for /alternatename.174 // Used for /alternatename.
171 std::map<StringRef, StringRef> AlternateNames;175 std::map<StringRef, StringRef> alternateNames;
172176
173 // Used for /order.177 // Used for /order.
174 llvm::StringMap<int> Order;178 llvm::StringMap<int> order;
175179
176 // Used for /lldmap.180 // Used for /lldmap.
177 std::string MapFile;181 std::string mapFile;
178182
179 uint64_t ImageBase = -1;183 // Used for /thinlto-index-only:
180 uint64_t StackReserve = 1024 * 1024;184 llvm::StringRef thinLTOIndexOnlyArg;
181 uint64_t StackCommit = 4096;185
182 uint64_t HeapReserve = 1024 * 1024;186 // Used for /thinlto-object-prefix-replace:
183 uint64_t HeapCommit = 4096;187 std::pair<llvm::StringRef, llvm::StringRef> thinLTOPrefixReplace;
184 uint32_t MajorImageVersion = 0;188
185 uint32_t MinorImageVersion = 0;189 // Used for /thinlto-object-suffix-replace:
186 uint32_t MajorOSVersion = 6;190 std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
187 uint32_t MinorOSVersion = 0;191
188 uint32_t Timestamp = 0;192 uint64_t imageBase = -1;
189 bool DynamicBase = true;193 uint64_t fileAlign = 512;
190 bool AllowBind = true;194 uint64_t stackReserve = 1024 * 1024;
191 bool NxCompat = true;195 uint64_t stackCommit = 4096;
192 bool AllowIsolation = true;196 uint64_t heapReserve = 1024 * 1024;
193 bool TerminalServerAware = true;197 uint64_t heapCommit = 4096;
194 bool LargeAddressAware = false;198 uint32_t majorImageVersion = 0;
195 bool HighEntropyVA = false;199 uint32_t minorImageVersion = 0;
196 bool AppContainer = false;200 uint32_t majorOSVersion = 6;
197 bool MinGW = false;201 uint32_t minorOSVersion = 0;
198 bool WarnMissingOrderSymbol = true;202 uint32_t timestamp = 0;
199 bool WarnLocallyDefinedImported = true;203 uint32_t functionPadMin = 0;
200 bool WarnDebugInfoUnusable = true;204 bool dynamicBase = true;
201 bool Incremental = true;205 bool allowBind = true;
202 bool IntegrityCheck = false;206 bool nxCompat = true;
203 bool KillAt = false;207 bool allowIsolation = true;
204 bool Repro = false;208 bool terminalServerAware = true;
209 bool largeAddressAware = false;
210 bool highEntropyVA = false;
211 bool appContainer = false;
212 bool mingw = false;
213 bool warnMissingOrderSymbol = true;
214 bool warnLocallyDefinedImported = true;
215 bool warnDebugInfoUnusable = true;
216 bool incremental = true;
217 bool integrityCheck = false;
218 bool killAt = false;
219 bool repro = false;
220 bool swaprunCD = false;
221 bool swaprunNet = false;
222 bool thinLTOEmitImportsFiles;
223 bool thinLTOIndexOnly;
205};224};
206225
207extern Configuration *Config;226extern Configuration *config;
208227
209} // namespace coff228} // namespace coff
210} // namespace lld229} // namespace lld
deps/lld/COFF/DLL.cpp+399-308
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- DLL.cpp ------------------------------------------------------------===//1//===- DLL.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -36,161 +35,167 @@ namespace {...@@ -36,161 +35,167 @@ namespace {
36// Import table35// Import table
3736
38// A chunk for the import descriptor table.37// A chunk for the import descriptor table.
39class HintNameChunk : public Chunk {38class HintNameChunk : public NonSectionChunk {
40public:39public:
41 HintNameChunk(StringRef N, uint16_t H) : Name(N), Hint(H) {}40 HintNameChunk(StringRef n, uint16_t h) : name(n), hint(h) {}
4241
43 size_t getSize() const override {42 size_t getSize() const override {
44 // Starts with 2 byte Hint field, followed by a null-terminated string,43 // Starts with 2 byte Hint field, followed by a null-terminated string,
45 // ends with 0 or 1 byte padding.44 // ends with 0 or 1 byte padding.
46 return alignTo(Name.size() + 3, 2);45 return alignTo(name.size() + 3, 2);
47 }46 }
4847
49 void writeTo(uint8_t *Buf) const override {48 void writeTo(uint8_t *buf) const override {
50 memset(Buf + OutputSectionOff, 0, getSize());49 memset(buf, 0, getSize());
51 write16le(Buf + OutputSectionOff, Hint);50 write16le(buf, hint);
52 memcpy(Buf + OutputSectionOff + 2, Name.data(), Name.size());51 memcpy(buf + 2, name.data(), name.size());
53 }52 }
5453
55private:54private:
56 StringRef Name;55 StringRef name;
57 uint16_t Hint;56 uint16_t hint;
58};57};
5958
60// A chunk for the import descriptor table.59// A chunk for the import descriptor table.
61class LookupChunk : public Chunk {60class LookupChunk : public NonSectionChunk {
62public:61public:
63 explicit LookupChunk(Chunk *C) : HintName(C) { Alignment = Config->Wordsize; }62 explicit LookupChunk(Chunk *c) : hintName(c) {
64 size_t getSize() const override { return Config->Wordsize; }63 setAlignment(config->wordsize);
64 }
65 size_t getSize() const override { return config->wordsize; }
6566
66 void writeTo(uint8_t *Buf) const override {67 void writeTo(uint8_t *buf) const override {
67 if (Config->is64())68 if (config->is64())
68 write64le(Buf + OutputSectionOff, HintName->getRVA());69 write64le(buf, hintName->getRVA());
69 else70 else
70 write32le(Buf + OutputSectionOff, HintName->getRVA());71 write32le(buf, hintName->getRVA());
71 }72 }
7273
73 Chunk *HintName;74 Chunk *hintName;
74};75};
7576
76// A chunk for the import descriptor table.77// A chunk for the import descriptor table.
77// This chunk represent import-by-ordinal symbols.78// This chunk represent import-by-ordinal symbols.
78// See Microsoft PE/COFF spec 7.1. Import Header for details.79// See Microsoft PE/COFF spec 7.1. Import Header for details.
79class OrdinalOnlyChunk : public Chunk {80class OrdinalOnlyChunk : public NonSectionChunk {
80public:81public:
81 explicit OrdinalOnlyChunk(uint16_t V) : Ordinal(V) {82 explicit OrdinalOnlyChunk(uint16_t v) : ordinal(v) {
82 Alignment = Config->Wordsize;83 setAlignment(config->wordsize);
83 }84 }
84 size_t getSize() const override { return Config->Wordsize; }85 size_t getSize() const override { return config->wordsize; }
8586
86 void writeTo(uint8_t *Buf) const override {87 void writeTo(uint8_t *buf) const override {
87 // An import-by-ordinal slot has MSB 1 to indicate that88 // An import-by-ordinal slot has MSB 1 to indicate that
88 // this is import-by-ordinal (and not import-by-name).89 // this is import-by-ordinal (and not import-by-name).
89 if (Config->is64()) {90 if (config->is64()) {
90 write64le(Buf + OutputSectionOff, (1ULL << 63) | Ordinal);91 write64le(buf, (1ULL << 63) | ordinal);
91 } else {92 } else {
92 write32le(Buf + OutputSectionOff, (1ULL << 31) | Ordinal);93 write32le(buf, (1ULL << 31) | ordinal);
93 }94 }
94 }95 }
9596
96 uint16_t Ordinal;97 uint16_t ordinal;
97};98};
9899
99// A chunk for the import descriptor table.100// A chunk for the import descriptor table.
100class ImportDirectoryChunk : public Chunk {101class ImportDirectoryChunk : public NonSectionChunk {
101public:102public:
102 explicit ImportDirectoryChunk(Chunk *N) : DLLName(N) {}103 explicit ImportDirectoryChunk(Chunk *n) : dllName(n) {}
103 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }104 size_t getSize() const override { return sizeof(ImportDirectoryTableEntry); }
104105
105 void writeTo(uint8_t *Buf) const override {106 void writeTo(uint8_t *buf) const override {
106 memset(Buf + OutputSectionOff, 0, getSize());107 memset(buf, 0, getSize());
107108
108 auto *E = (coff_import_directory_table_entry *)(Buf + OutputSectionOff);109 auto *e = (coff_import_directory_table_entry *)(buf);
109 E->ImportLookupTableRVA = LookupTab->getRVA();110 e->ImportLookupTableRVA = lookupTab->getRVA();
110 E->NameRVA = DLLName->getRVA();111 e->NameRVA = dllName->getRVA();
111 E->ImportAddressTableRVA = AddressTab->getRVA();112 e->ImportAddressTableRVA = addressTab->getRVA();
112 }113 }
113114
114 Chunk *DLLName;115 Chunk *dllName;
115 Chunk *LookupTab;116 Chunk *lookupTab;
116 Chunk *AddressTab;117 Chunk *addressTab;
117};118};
118119
119// A chunk representing null terminator in the import table.120// A chunk representing null terminator in the import table.
120// Contents of this chunk is always null bytes.121// Contents of this chunk is always null bytes.
121class NullChunk : public Chunk {122class NullChunk : public NonSectionChunk {
122public:123public:
123 explicit NullChunk(size_t N) : Size(N) {}124 explicit NullChunk(size_t n) : size(n) { hasData = false; }
124 bool hasData() const override { return false; }125 size_t getSize() const override { return size; }
125 size_t getSize() const override { return Size; }
126126
127 void writeTo(uint8_t *Buf) const override {127 void writeTo(uint8_t *buf) const override {
128 memset(Buf + OutputSectionOff, 0, Size);128 memset(buf, 0, size);
129 }129 }
130130
131private:131private:
132 size_t Size;132 size_t size;
133};133};
134134
135static std::vector<std::vector<DefinedImportData *>>135static std::vector<std::vector<DefinedImportData *>>
136binImports(const std::vector<DefinedImportData *> &Imports) {136binImports(const std::vector<DefinedImportData *> &imports) {
137 // Group DLL-imported symbols by DLL name because that's how137 // Group DLL-imported symbols by DLL name because that's how
138 // symbols are layed out in the import descriptor table.138 // symbols are layed out in the import descriptor table.
139 auto Less = [](const std::string &A, const std::string &B) {139 auto less = [](const std::string &a, const std::string &b) {
140 return Config->DLLOrder[A] < Config->DLLOrder[B];140 return config->dllOrder[a] < config->dllOrder[b];
141 };141 };
142 std::map<std::string, std::vector<DefinedImportData *>,142 std::map<std::string, std::vector<DefinedImportData *>,
143 bool(*)(const std::string &, const std::string &)> M(Less);143 bool(*)(const std::string &, const std::string &)> m(less);
144 for (DefinedImportData *Sym : Imports)144 for (DefinedImportData *sym : imports)
145 M[Sym->getDLLName().lower()].push_back(Sym);145 m[sym->getDLLName().lower()].push_back(sym);
146146
147 std::vector<std::vector<DefinedImportData *>> V;147 std::vector<std::vector<DefinedImportData *>> v;
148 for (auto &KV : M) {148 for (auto &kv : m) {
149 // Sort symbols by name for each group.149 // Sort symbols by name for each group.
150 std::vector<DefinedImportData *> &Syms = KV.second;150 std::vector<DefinedImportData *> &syms = kv.second;
151 std::sort(Syms.begin(), Syms.end(),151 std::sort(syms.begin(), syms.end(),
152 [](DefinedImportData *A, DefinedImportData *B) {152 [](DefinedImportData *a, DefinedImportData *b) {
153 return A->getName() < B->getName();153 return a->getName() < b->getName();
154 });154 });
155 V.push_back(std::move(Syms));155 v.push_back(std::move(syms));
156 }156 }
157 return V;157 return v;
158}158}
159159
160// Export table160// Export table
161// See Microsoft PE/COFF spec 4.3 for details.161// See Microsoft PE/COFF spec 4.3 for details.
162162
163// A chunk for the delay import descriptor table etnry.163// A chunk for the delay import descriptor table etnry.
164class DelayDirectoryChunk : public Chunk {164class DelayDirectoryChunk : public NonSectionChunk {
165public:165public:
166 explicit DelayDirectoryChunk(Chunk *N) : DLLName(N) {}166 explicit DelayDirectoryChunk(Chunk *n) : dllName(n) {}
167167
168 size_t getSize() const override {168 size_t getSize() const override {
169 return sizeof(delay_import_directory_table_entry);169 return sizeof(delay_import_directory_table_entry);
170 }170 }
171171
172 void writeTo(uint8_t *Buf) const override {172 void writeTo(uint8_t *buf) const override {
173 memset(Buf + OutputSectionOff, 0, getSize());173 memset(buf, 0, getSize());
174174
175 auto *E = (delay_import_directory_table_entry *)(Buf + OutputSectionOff);175 auto *e = (delay_import_directory_table_entry *)(buf);
176 E->Attributes = 1;176 e->Attributes = 1;
177 E->Name = DLLName->getRVA();177 e->Name = dllName->getRVA();
178 E->ModuleHandle = ModuleHandle->getRVA();178 e->ModuleHandle = moduleHandle->getRVA();
179 E->DelayImportAddressTable = AddressTab->getRVA();179 e->DelayImportAddressTable = addressTab->getRVA();
180 E->DelayImportNameTable = NameTab->getRVA();180 e->DelayImportNameTable = nameTab->getRVA();
181 }181 }
182182
183 Chunk *DLLName;183 Chunk *dllName;
184 Chunk *ModuleHandle;184 Chunk *moduleHandle;
185 Chunk *AddressTab;185 Chunk *addressTab;
186 Chunk *NameTab;186 Chunk *nameTab;
187};187};
188188
189// Initial contents for delay-loaded functions.189// Initial contents for delay-loaded functions.
190// This code calls __delayLoadHelper2 function to resolve a symbol190// This code calls __delayLoadHelper2 function to resolve a symbol
191// and then overwrites its jump table slot with the result191// and then overwrites its jump table slot with the result
192// for subsequent function calls.192// for subsequent function calls.
193static const uint8_t ThunkX64[] = {193static const uint8_t thunkX64[] = {
194 0x48, 0x8D, 0x05, 0, 0, 0, 0, // lea rax, [__imp_<FUNCNAME>]
195 0xE9, 0, 0, 0, 0, // jmp __tailMerge_<lib>
196};
197
198static const uint8_t tailMergeX64[] = {
194 0x51, // push rcx199 0x51, // push rcx
195 0x52, // push rdx200 0x52, // push rdx
196 0x41, 0x50, // push r8201 0x41, 0x50, // push r8
...@@ -200,7 +205,7 @@ static const uint8_t ThunkX64[] = {...@@ -200,7 +205,7 @@ static const uint8_t ThunkX64[] = {
200 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1205 0x66, 0x0F, 0x7F, 0x4C, 0x24, 0x10, // movdqa xmmword ptr [rsp+10h], xmm1
201 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2206 0x66, 0x0F, 0x7F, 0x54, 0x24, 0x20, // movdqa xmmword ptr [rsp+20h], xmm2
202 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3207 0x66, 0x0F, 0x7F, 0x5C, 0x24, 0x30, // movdqa xmmword ptr [rsp+30h], xmm3
203 0x48, 0x8D, 0x15, 0, 0, 0, 0, // lea rdx, [__imp_<FUNCNAME>]208 0x48, 0x8B, 0xD0, // mov rdx, rax
204 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]209 0x48, 0x8D, 0x0D, 0, 0, 0, 0, // lea rcx, [___DELAY_IMPORT_...]
205 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2210 0xE8, 0, 0, 0, 0, // call __delayLoadHelper2
206 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]211 0x66, 0x0F, 0x6F, 0x04, 0x24, // movdqa xmm0, xmmword ptr [rsp]
...@@ -215,10 +220,15 @@ static const uint8_t ThunkX64[] = {...@@ -215,10 +220,15 @@ static const uint8_t ThunkX64[] = {
215 0xFF, 0xE0, // jmp rax220 0xFF, 0xE0, // jmp rax
216};221};
217222
218static const uint8_t ThunkX86[] = {223static const uint8_t thunkX86[] = {
224 0xB8, 0, 0, 0, 0, // mov eax, offset ___imp__<FUNCNAME>
225 0xE9, 0, 0, 0, 0, // jmp __tailMerge_<lib>
226};
227
228static const uint8_t tailMergeX86[] = {
219 0x51, // push ecx229 0x51, // push ecx
220 0x52, // push edx230 0x52, // push edx
221 0x68, 0, 0, 0, 0, // push offset ___imp__<FUNCNAME>231 0x50, // push eax
222 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll232 0x68, 0, 0, 0, 0, // push offset ___DELAY_IMPORT_DESCRIPTOR_<DLLNAME>_dll
223 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8233 0xE8, 0, 0, 0, 0, // call ___delayLoadHelper2@8
224 0x5A, // pop edx234 0x5A, // pop edx
...@@ -226,9 +236,13 @@ static const uint8_t ThunkX86[] = {...@@ -226,9 +236,13 @@ static const uint8_t ThunkX86[] = {
226 0xFF, 0xE0, // jmp eax236 0xFF, 0xE0, // jmp eax
227};237};
228238
229static const uint8_t ThunkARM[] = {239static const uint8_t thunkARM[] = {
230 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_<FUNCNAME>240 0x40, 0xf2, 0x00, 0x0c, // mov.w ip, #0 __imp_<FUNCNAME>
231 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_<FUNCNAME>241 0xc0, 0xf2, 0x00, 0x0c, // mov.t ip, #0 __imp_<FUNCNAME>
242 0x00, 0xf0, 0x00, 0xb8, // b.w __tailMerge_<lib>
243};
244
245static const uint8_t tailMergeARM[] = {
232 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr}246 0x2d, 0xe9, 0x0f, 0x48, // push.w {r0, r1, r2, r3, r11, lr}
233 0x0d, 0xf2, 0x10, 0x0b, // addw r11, sp, #16247 0x0d, 0xf2, 0x10, 0x0b, // addw r11, sp, #16
234 0x2d, 0xed, 0x10, 0x0b, // vpush {d0, d1, d2, d3, d4, d5, d6, d7}248 0x2d, 0xed, 0x10, 0x0b, // vpush {d0, d1, d2, d3, d4, d5, d6, d7}
...@@ -242,9 +256,13 @@ static const uint8_t ThunkARM[] = {...@@ -242,9 +256,13 @@ static const uint8_t ThunkARM[] = {
242 0x60, 0x47, // bx ip256 0x60, 0x47, // bx ip
243};257};
244258
245static const uint8_t ThunkARM64[] = {259static const uint8_t thunkARM64[] = {
246 0x11, 0x00, 0x00, 0x90, // adrp x17, #0 __imp_<FUNCNAME>260 0x11, 0x00, 0x00, 0x90, // adrp x17, #0 __imp_<FUNCNAME>
247 0x31, 0x02, 0x00, 0x91, // add x17, x17, #0 :lo12:__imp_<FUNCNAME>261 0x31, 0x02, 0x00, 0x91, // add x17, x17, #0 :lo12:__imp_<FUNCNAME>
262 0x00, 0x00, 0x00, 0x14, // b __tailMerge_<lib>
263};
264
265static const uint8_t tailMergeARM64[] = {
248 0xfd, 0x7b, 0xb3, 0xa9, // stp x29, x30, [sp, #-208]!266 0xfd, 0x7b, 0xb3, 0xa9, // stp x29, x30, [sp, #-208]!
249 0xfd, 0x03, 0x00, 0x91, // mov x29, sp267 0xfd, 0x03, 0x00, 0x91, // mov x29, sp
250 0xe0, 0x07, 0x01, 0xa9, // stp x0, x1, [sp, #16]268 0xe0, 0x07, 0x01, 0xa9, // stp x0, x1, [sp, #16]
...@@ -273,372 +291,445 @@ static const uint8_t ThunkARM64[] = {...@@ -273,372 +291,445 @@ static const uint8_t ThunkARM64[] = {
273};291};
274292
275// A chunk for the delay import thunk.293// A chunk for the delay import thunk.
276class ThunkChunkX64 : public Chunk {294class ThunkChunkX64 : public NonSectionChunk {
295public:
296 ThunkChunkX64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
297
298 size_t getSize() const override { return sizeof(thunkX64); }
299
300 void writeTo(uint8_t *buf) const override {
301 memcpy(buf, thunkX64, sizeof(thunkX64));
302 write32le(buf + 3, imp->getRVA() - rva - 7);
303 write32le(buf + 8, tailMerge->getRVA() - rva - 12);
304 }
305
306 Defined *imp = nullptr;
307 Chunk *tailMerge = nullptr;
308};
309
310class TailMergeChunkX64 : public NonSectionChunk {
311public:
312 TailMergeChunkX64(Chunk *d, Defined *h) : desc(d), helper(h) {}
313
314 size_t getSize() const override { return sizeof(tailMergeX64); }
315
316 void writeTo(uint8_t *buf) const override {
317 memcpy(buf, tailMergeX64, sizeof(tailMergeX64));
318 write32le(buf + 39, desc->getRVA() - rva - 43);
319 write32le(buf + 44, helper->getRVA() - rva - 48);
320 }
321
322 Chunk *desc = nullptr;
323 Defined *helper = nullptr;
324};
325
326class ThunkChunkX86 : public NonSectionChunk {
277public:327public:
278 ThunkChunkX64(Defined *I, Chunk *D, Defined *H)328 ThunkChunkX86(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
279 : Imp(I), Desc(D), Helper(H) {}
280329
281 size_t getSize() const override { return sizeof(ThunkX64); }330 size_t getSize() const override { return sizeof(thunkX86); }
282331
283 void writeTo(uint8_t *Buf) const override {332 void writeTo(uint8_t *buf) const override {
284 memcpy(Buf + OutputSectionOff, ThunkX64, sizeof(ThunkX64));333 memcpy(buf, thunkX86, sizeof(thunkX86));
285 write32le(Buf + OutputSectionOff + 36, Imp->getRVA() - RVA - 40);334 write32le(buf + 1, imp->getRVA() + config->imageBase);
286 write32le(Buf + OutputSectionOff + 43, Desc->getRVA() - RVA - 47);335 write32le(buf + 6, tailMerge->getRVA() - rva - 10);
287 write32le(Buf + OutputSectionOff + 48, Helper->getRVA() - RVA - 52);
288 }336 }
289337
290 Defined *Imp = nullptr;338 void getBaserels(std::vector<Baserel> *res) override {
291 Chunk *Desc = nullptr;339 res->emplace_back(rva + 1);
292 Defined *Helper = nullptr;340 }
341
342 Defined *imp = nullptr;
343 Chunk *tailMerge = nullptr;
293};344};
294345
295class ThunkChunkX86 : public Chunk {346class TailMergeChunkX86 : public NonSectionChunk {
296public:347public:
297 ThunkChunkX86(Defined *I, Chunk *D, Defined *H)348 TailMergeChunkX86(Chunk *d, Defined *h) : desc(d), helper(h) {}
298 : Imp(I), Desc(D), Helper(H) {}
299349
300 size_t getSize() const override { return sizeof(ThunkX86); }350 size_t getSize() const override { return sizeof(tailMergeX86); }
301351
302 void writeTo(uint8_t *Buf) const override {352 void writeTo(uint8_t *buf) const override {
303 memcpy(Buf + OutputSectionOff, ThunkX86, sizeof(ThunkX86));353 memcpy(buf, tailMergeX86, sizeof(tailMergeX86));
304 write32le(Buf + OutputSectionOff + 3, Imp->getRVA() + Config->ImageBase);354 write32le(buf + 4, desc->getRVA() + config->imageBase);
305 write32le(Buf + OutputSectionOff + 8, Desc->getRVA() + Config->ImageBase);355 write32le(buf + 9, helper->getRVA() - rva - 13);
306 write32le(Buf + OutputSectionOff + 13, Helper->getRVA() - RVA - 17);
307 }356 }
308357
309 void getBaserels(std::vector<Baserel> *Res) override {358 void getBaserels(std::vector<Baserel> *res) override {
310 Res->emplace_back(RVA + 3);359 res->emplace_back(rva + 4);
311 Res->emplace_back(RVA + 8);
312 }360 }
313361
314 Defined *Imp = nullptr;362 Chunk *desc = nullptr;
315 Chunk *Desc = nullptr;363 Defined *helper = nullptr;
316 Defined *Helper = nullptr;
317};364};
318365
319class ThunkChunkARM : public Chunk {366class ThunkChunkARM : public NonSectionChunk {
320public:367public:
321 ThunkChunkARM(Defined *I, Chunk *D, Defined *H)368 ThunkChunkARM(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
322 : Imp(I), Desc(D), Helper(H) {}
323369
324 size_t getSize() const override { return sizeof(ThunkARM); }370 size_t getSize() const override { return sizeof(thunkARM); }
325371
326 void writeTo(uint8_t *Buf) const override {372 void writeTo(uint8_t *buf) const override {
327 memcpy(Buf + OutputSectionOff, ThunkARM, sizeof(ThunkARM));373 memcpy(buf, thunkARM, sizeof(thunkARM));
328 applyMOV32T(Buf + OutputSectionOff + 0, Imp->getRVA() + Config->ImageBase);374 applyMOV32T(buf + 0, imp->getRVA() + config->imageBase);
329 applyMOV32T(Buf + OutputSectionOff + 22, Desc->getRVA() + Config->ImageBase);375 applyBranch24T(buf + 8, tailMerge->getRVA() - rva - 12);
330 applyBranch24T(Buf + OutputSectionOff + 30, Helper->getRVA() - RVA - 34);
331 }376 }
332377
333 void getBaserels(std::vector<Baserel> *Res) override {378 void getBaserels(std::vector<Baserel> *res) override {
334 Res->emplace_back(RVA + 0, IMAGE_REL_BASED_ARM_MOV32T);379 res->emplace_back(rva + 0, IMAGE_REL_BASED_ARM_MOV32T);
335 Res->emplace_back(RVA + 22, IMAGE_REL_BASED_ARM_MOV32T);
336 }380 }
337381
338 Defined *Imp = nullptr;382 Defined *imp = nullptr;
339 Chunk *Desc = nullptr;383 Chunk *tailMerge = nullptr;
340 Defined *Helper = nullptr;
341};384};
342385
343class ThunkChunkARM64 : public Chunk {386class TailMergeChunkARM : public NonSectionChunk {
344public:387public:
345 ThunkChunkARM64(Defined *I, Chunk *D, Defined *H)388 TailMergeChunkARM(Chunk *d, Defined *h) : desc(d), helper(h) {}
346 : Imp(I), Desc(D), Helper(H) {}389
390 size_t getSize() const override { return sizeof(tailMergeARM); }
347391
348 size_t getSize() const override { return sizeof(ThunkARM64); }392 void writeTo(uint8_t *buf) const override {
393 memcpy(buf, tailMergeARM, sizeof(tailMergeARM));
394 applyMOV32T(buf + 14, desc->getRVA() + config->imageBase);
395 applyBranch24T(buf + 22, helper->getRVA() - rva - 26);
396 }
349397
350 void writeTo(uint8_t *Buf) const override {398 void getBaserels(std::vector<Baserel> *res) override {
351 memcpy(Buf + OutputSectionOff, ThunkARM64, sizeof(ThunkARM64));399 res->emplace_back(rva + 14, IMAGE_REL_BASED_ARM_MOV32T);
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 }400 }
359401
360 Defined *Imp = nullptr;402 Chunk *desc = nullptr;
361 Chunk *Desc = nullptr;403 Defined *helper = nullptr;
362 Defined *Helper = nullptr;404};
405
406class ThunkChunkARM64 : public NonSectionChunk {
407public:
408 ThunkChunkARM64(Defined *i, Chunk *tm) : imp(i), tailMerge(tm) {}
409
410 size_t getSize() const override { return sizeof(thunkARM64); }
411
412 void writeTo(uint8_t *buf) const override {
413 memcpy(buf, thunkARM64, sizeof(thunkARM64));
414 applyArm64Addr(buf + 0, imp->getRVA(), rva + 0, 12);
415 applyArm64Imm(buf + 4, imp->getRVA() & 0xfff, 0);
416 applyArm64Branch26(buf + 8, tailMerge->getRVA() - rva - 8);
417 }
418
419 Defined *imp = nullptr;
420 Chunk *tailMerge = nullptr;
421};
422
423class TailMergeChunkARM64 : public NonSectionChunk {
424public:
425 TailMergeChunkARM64(Chunk *d, Defined *h) : desc(d), helper(h) {}
426
427 size_t getSize() const override { return sizeof(tailMergeARM64); }
428
429 void writeTo(uint8_t *buf) const override {
430 memcpy(buf, tailMergeARM64, sizeof(tailMergeARM64));
431 applyArm64Addr(buf + 44, desc->getRVA(), rva + 44, 12);
432 applyArm64Imm(buf + 48, desc->getRVA() & 0xfff, 0);
433 applyArm64Branch26(buf + 52, helper->getRVA() - rva - 52);
434 }
435
436 Chunk *desc = nullptr;
437 Defined *helper = nullptr;
363};438};
364439
365// A chunk for the import descriptor table.440// A chunk for the import descriptor table.
366class DelayAddressChunk : public Chunk {441class DelayAddressChunk : public NonSectionChunk {
367public:442public:
368 explicit DelayAddressChunk(Chunk *C) : Thunk(C) {443 explicit DelayAddressChunk(Chunk *c) : thunk(c) {
369 Alignment = Config->Wordsize;444 setAlignment(config->wordsize);
370 }445 }
371 size_t getSize() const override { return Config->Wordsize; }446 size_t getSize() const override { return config->wordsize; }
372447
373 void writeTo(uint8_t *Buf) const override {448 void writeTo(uint8_t *buf) const override {
374 if (Config->is64()) {449 if (config->is64()) {
375 write64le(Buf + OutputSectionOff, Thunk->getRVA() + Config->ImageBase);450 write64le(buf, thunk->getRVA() + config->imageBase);
376 } else {451 } else {
377 uint32_t Bit = 0;452 uint32_t bit = 0;
378 // Pointer to thumb code must have the LSB set, so adjust it.453 // Pointer to thumb code must have the LSB set, so adjust it.
379 if (Config->Machine == ARMNT)454 if (config->machine == ARMNT)
380 Bit = 1;455 bit = 1;
381 write32le(Buf + OutputSectionOff, (Thunk->getRVA() + Config->ImageBase) | Bit);456 write32le(buf, (thunk->getRVA() + config->imageBase) | bit);
382 }457 }
383 }458 }
384459
385 void getBaserels(std::vector<Baserel> *Res) override {460 void getBaserels(std::vector<Baserel> *res) override {
386 Res->emplace_back(RVA);461 res->emplace_back(rva);
387 }462 }
388463
389 Chunk *Thunk;464 Chunk *thunk;
390};465};
391466
392// Export table467// Export table
393// Read Microsoft PE/COFF spec 5.3 for details.468// Read Microsoft PE/COFF spec 5.3 for details.
394469
395// A chunk for the export descriptor table.470// A chunk for the export descriptor table.
396class ExportDirectoryChunk : public Chunk {471class ExportDirectoryChunk : public NonSectionChunk {
397public:472public:
398 ExportDirectoryChunk(int I, int J, Chunk *D, Chunk *A, Chunk *N, Chunk *O)473 ExportDirectoryChunk(int i, int j, Chunk *d, Chunk *a, Chunk *n, Chunk *o)
399 : MaxOrdinal(I), NameTabSize(J), DLLName(D), AddressTab(A), NameTab(N),474 : maxOrdinal(i), nameTabSize(j), dllName(d), addressTab(a), nameTab(n),
400 OrdinalTab(O) {}475 ordinalTab(o) {}
401476
402 size_t getSize() const override {477 size_t getSize() const override {
403 return sizeof(export_directory_table_entry);478 return sizeof(export_directory_table_entry);
404 }479 }
405480
406 void writeTo(uint8_t *Buf) const override {481 void writeTo(uint8_t *buf) const override {
407 memset(Buf + OutputSectionOff, 0, getSize());482 memset(buf, 0, getSize());
408483
409 auto *E = (export_directory_table_entry *)(Buf + OutputSectionOff);484 auto *e = (export_directory_table_entry *)(buf);
410 E->NameRVA = DLLName->getRVA();485 e->NameRVA = dllName->getRVA();
411 E->OrdinalBase = 0;486 e->OrdinalBase = 0;
412 E->AddressTableEntries = MaxOrdinal + 1;487 e->AddressTableEntries = maxOrdinal + 1;
413 E->NumberOfNamePointers = NameTabSize;488 e->NumberOfNamePointers = nameTabSize;
414 E->ExportAddressTableRVA = AddressTab->getRVA();489 e->ExportAddressTableRVA = addressTab->getRVA();
415 E->NamePointerRVA = NameTab->getRVA();490 e->NamePointerRVA = nameTab->getRVA();
416 E->OrdinalTableRVA = OrdinalTab->getRVA();491 e->OrdinalTableRVA = ordinalTab->getRVA();
417 }492 }
418493
419 uint16_t MaxOrdinal;494 uint16_t maxOrdinal;
420 uint16_t NameTabSize;495 uint16_t nameTabSize;
421 Chunk *DLLName;496 Chunk *dllName;
422 Chunk *AddressTab;497 Chunk *addressTab;
423 Chunk *NameTab;498 Chunk *nameTab;
424 Chunk *OrdinalTab;499 Chunk *ordinalTab;
425};500};
426501
427class AddressTableChunk : public Chunk {502class AddressTableChunk : public NonSectionChunk {
428public:503public:
429 explicit AddressTableChunk(size_t MaxOrdinal) : Size(MaxOrdinal + 1) {}504 explicit AddressTableChunk(size_t maxOrdinal) : size(maxOrdinal + 1) {}
430 size_t getSize() const override { return Size * 4; }505 size_t getSize() const override { return size * 4; }
431506
432 void writeTo(uint8_t *Buf) const override {507 void writeTo(uint8_t *buf) const override {
433 memset(Buf + OutputSectionOff, 0, getSize());508 memset(buf, 0, getSize());
434509
435 for (const Export &E : Config->Exports) {510 for (const Export &e : config->exports) {
436 uint8_t *P = Buf + OutputSectionOff + E.Ordinal * 4;511 uint8_t *p = buf + e.ordinal * 4;
437 uint32_t Bit = 0;512 uint32_t bit = 0;
438 // Pointer to thumb code must have the LSB set, so adjust it.513 // Pointer to thumb code must have the LSB set, so adjust it.
439 if (Config->Machine == ARMNT && !E.Data)514 if (config->machine == ARMNT && !e.data)
440 Bit = 1;515 bit = 1;
441 if (E.ForwardChunk) {516 if (e.forwardChunk) {
442 write32le(P, E.ForwardChunk->getRVA() | Bit);517 write32le(p, e.forwardChunk->getRVA() | bit);
443 } else {518 } else {
444 write32le(P, cast<Defined>(E.Sym)->getRVA() | Bit);519 write32le(p, cast<Defined>(e.sym)->getRVA() | bit);
445 }520 }
446 }521 }
447 }522 }
448523
449private:524private:
450 size_t Size;525 size_t size;
451};526};
452527
453class NamePointersChunk : public Chunk {528class NamePointersChunk : public NonSectionChunk {
454public:529public:
455 explicit NamePointersChunk(std::vector<Chunk *> &V) : Chunks(V) {}530 explicit NamePointersChunk(std::vector<Chunk *> &v) : chunks(v) {}
456 size_t getSize() const override { return Chunks.size() * 4; }531 size_t getSize() const override { return chunks.size() * 4; }
457532
458 void writeTo(uint8_t *Buf) const override {533 void writeTo(uint8_t *buf) const override {
459 uint8_t *P = Buf + OutputSectionOff;534 for (Chunk *c : chunks) {
460 for (Chunk *C : Chunks) {535 write32le(buf, c->getRVA());
461 write32le(P, C->getRVA());536 buf += 4;
462 P += 4;
463 }537 }
464 }538 }
465539
466private:540private:
467 std::vector<Chunk *> Chunks;541 std::vector<Chunk *> chunks;
468};542};
469543
470class ExportOrdinalChunk : public Chunk {544class ExportOrdinalChunk : public NonSectionChunk {
471public:545public:
472 explicit ExportOrdinalChunk(size_t I) : Size(I) {}546 explicit ExportOrdinalChunk(size_t i) : size(i) {}
473 size_t getSize() const override { return Size * 2; }547 size_t getSize() const override { return size * 2; }
474548
475 void writeTo(uint8_t *Buf) const override {549 void writeTo(uint8_t *buf) const override {
476 uint8_t *P = Buf + OutputSectionOff;550 for (Export &e : config->exports) {
477 for (Export &E : Config->Exports) {551 if (e.noname)
478 if (E.Noname)
479 continue;552 continue;
480 write16le(P, E.Ordinal);553 write16le(buf, e.ordinal);
481 P += 2;554 buf += 2;
482 }555 }
483 }556 }
484557
485private:558private:
486 size_t Size;559 size_t size;
487};560};
488561
489} // anonymous namespace562} // anonymous namespace
490563
491void IdataContents::create() {564void IdataContents::create() {
492 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);565 std::vector<std::vector<DefinedImportData *>> v = binImports(imports);
493566
494 // Create .idata contents for each DLL.567 // Create .idata contents for each DLL.
495 for (std::vector<DefinedImportData *> &Syms : V) {568 for (std::vector<DefinedImportData *> &syms : v) {
496 // Create lookup and address tables. If they have external names,569 // Create lookup and address tables. If they have external names,
497 // we need to create HintName chunks to store the names.570 // we need to create hintName chunks to store the names.
498 // If they don't (if they are import-by-ordinals), we store only571 // If they don't (if they are import-by-ordinals), we store only
499 // ordinal values to the table.572 // ordinal values to the table.
500 size_t Base = Lookups.size();573 size_t base = lookups.size();
501 for (DefinedImportData *S : Syms) {574 for (DefinedImportData *s : syms) {
502 uint16_t Ord = S->getOrdinal();575 uint16_t ord = s->getOrdinal();
503 if (S->getExternalName().empty()) {576 if (s->getExternalName().empty()) {
504 Lookups.push_back(make<OrdinalOnlyChunk>(Ord));577 lookups.push_back(make<OrdinalOnlyChunk>(ord));
505 Addresses.push_back(make<OrdinalOnlyChunk>(Ord));578 addresses.push_back(make<OrdinalOnlyChunk>(ord));
506 continue;579 continue;
507 }580 }
508 auto *C = make<HintNameChunk>(S->getExternalName(), Ord);581 auto *c = make<HintNameChunk>(s->getExternalName(), ord);
509 Lookups.push_back(make<LookupChunk>(C));582 lookups.push_back(make<LookupChunk>(c));
510 Addresses.push_back(make<LookupChunk>(C));583 addresses.push_back(make<LookupChunk>(c));
511 Hints.push_back(C);584 hints.push_back(c);
512 }585 }
513 // Terminate with null values.586 // Terminate with null values.
514 Lookups.push_back(make<NullChunk>(Config->Wordsize));587 lookups.push_back(make<NullChunk>(config->wordsize));
515 Addresses.push_back(make<NullChunk>(Config->Wordsize));588 addresses.push_back(make<NullChunk>(config->wordsize));
516589
517 for (int I = 0, E = Syms.size(); I < E; ++I)590 for (int i = 0, e = syms.size(); i < e; ++i)
518 Syms[I]->setLocation(Addresses[Base + I]);591 syms[i]->setLocation(addresses[base + i]);
519592
520 // Create the import table header.593 // Create the import table header.
521 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));594 dllNames.push_back(make<StringChunk>(syms[0]->getDLLName()));
522 auto *Dir = make<ImportDirectoryChunk>(DLLNames.back());595 auto *dir = make<ImportDirectoryChunk>(dllNames.back());
523 Dir->LookupTab = Lookups[Base];596 dir->lookupTab = lookups[base];
524 Dir->AddressTab = Addresses[Base];597 dir->addressTab = addresses[base];
525 Dirs.push_back(Dir);598 dirs.push_back(dir);
526 }599 }
527 // Add null terminator.600 // Add null terminator.
528 Dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));601 dirs.push_back(make<NullChunk>(sizeof(ImportDirectoryTableEntry)));
529}602}
530603
531std::vector<Chunk *> DelayLoadContents::getChunks() {604std::vector<Chunk *> DelayLoadContents::getChunks() {
532 std::vector<Chunk *> V;605 std::vector<Chunk *> v;
533 V.insert(V.end(), Dirs.begin(), Dirs.end());606 v.insert(v.end(), dirs.begin(), dirs.end());
534 V.insert(V.end(), Names.begin(), Names.end());607 v.insert(v.end(), names.begin(), names.end());
535 V.insert(V.end(), HintNames.begin(), HintNames.end());608 v.insert(v.end(), hintNames.begin(), hintNames.end());
536 V.insert(V.end(), DLLNames.begin(), DLLNames.end());609 v.insert(v.end(), dllNames.begin(), dllNames.end());
537 return V;610 return v;
538}611}
539612
540std::vector<Chunk *> DelayLoadContents::getDataChunks() {613std::vector<Chunk *> DelayLoadContents::getDataChunks() {
541 std::vector<Chunk *> V;614 std::vector<Chunk *> v;
542 V.insert(V.end(), ModuleHandles.begin(), ModuleHandles.end());615 v.insert(v.end(), moduleHandles.begin(), moduleHandles.end());
543 V.insert(V.end(), Addresses.begin(), Addresses.end());616 v.insert(v.end(), addresses.begin(), addresses.end());
544 return V;617 return v;
545}618}
546619
547uint64_t DelayLoadContents::getDirSize() {620uint64_t DelayLoadContents::getDirSize() {
548 return Dirs.size() * sizeof(delay_import_directory_table_entry);621 return dirs.size() * sizeof(delay_import_directory_table_entry);
549}622}
550623
551void DelayLoadContents::create(Defined *H) {624void DelayLoadContents::create(Defined *h) {
552 Helper = H;625 helper = h;
553 std::vector<std::vector<DefinedImportData *>> V = binImports(Imports);626 std::vector<std::vector<DefinedImportData *>> v = binImports(imports);
554627
555 // Create .didat contents for each DLL.628 // Create .didat contents for each DLL.
556 for (std::vector<DefinedImportData *> &Syms : V) {629 for (std::vector<DefinedImportData *> &syms : v) {
557 // Create the delay import table header.630 // Create the delay import table header.
558 DLLNames.push_back(make<StringChunk>(Syms[0]->getDLLName()));631 dllNames.push_back(make<StringChunk>(syms[0]->getDLLName()));
559 auto *Dir = make<DelayDirectoryChunk>(DLLNames.back());632 auto *dir = make<DelayDirectoryChunk>(dllNames.back());
560633
561 size_t Base = Addresses.size();634 size_t base = addresses.size();
562 for (DefinedImportData *S : Syms) {635 Chunk *tm = newTailMergeChunk(dir);
563 Chunk *T = newThunkChunk(S, Dir);636 for (DefinedImportData *s : syms) {
564 auto *A = make<DelayAddressChunk>(T);637 Chunk *t = newThunkChunk(s, tm);
565 Addresses.push_back(A);638 auto *a = make<DelayAddressChunk>(t);
566 Thunks.push_back(T);639 addresses.push_back(a);
567 StringRef ExtName = S->getExternalName();640 thunks.push_back(t);
568 if (ExtName.empty()) {641 StringRef extName = s->getExternalName();
569 Names.push_back(make<OrdinalOnlyChunk>(S->getOrdinal()));642 if (extName.empty()) {
643 names.push_back(make<OrdinalOnlyChunk>(s->getOrdinal()));
570 } else {644 } else {
571 auto *C = make<HintNameChunk>(ExtName, 0);645 auto *c = make<HintNameChunk>(extName, 0);
572 Names.push_back(make<LookupChunk>(C));646 names.push_back(make<LookupChunk>(c));
573 HintNames.push_back(C);647 hintNames.push_back(c);
574 }648 }
575 }649 }
650 thunks.push_back(tm);
576 // Terminate with null values.651 // Terminate with null values.
577 Addresses.push_back(make<NullChunk>(8));652 addresses.push_back(make<NullChunk>(8));
578 Names.push_back(make<NullChunk>(8));653 names.push_back(make<NullChunk>(8));
579654
580 for (int I = 0, E = Syms.size(); I < E; ++I)655 for (int i = 0, e = syms.size(); i < e; ++i)
581 Syms[I]->setLocation(Addresses[Base + I]);656 syms[i]->setLocation(addresses[base + i]);
582 auto *MH = make<NullChunk>(8);657 auto *mh = make<NullChunk>(8);
583 MH->Alignment = 8;658 mh->setAlignment(8);
584 ModuleHandles.push_back(MH);659 moduleHandles.push_back(mh);
585660
586 // Fill the delay import table header fields.661 // Fill the delay import table header fields.
587 Dir->ModuleHandle = MH;662 dir->moduleHandle = mh;
588 Dir->AddressTab = Addresses[Base];663 dir->addressTab = addresses[base];
589 Dir->NameTab = Names[Base];664 dir->nameTab = names[base];
590 Dirs.push_back(Dir);665 dirs.push_back(dir);
591 }666 }
592 // Add null terminator.667 // Add null terminator.
593 Dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));668 dirs.push_back(make<NullChunk>(sizeof(delay_import_directory_table_entry)));
594}669}
595670
596Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *S, Chunk *Dir) {671Chunk *DelayLoadContents::newTailMergeChunk(Chunk *dir) {
597 switch (Config->Machine) {672 switch (config->machine) {
598 case AMD64:673 case AMD64:
599 return make<ThunkChunkX64>(S, Dir, Helper);674 return make<TailMergeChunkX64>(dir, helper);
600 case I386:675 case I386:
601 return make<ThunkChunkX86>(S, Dir, Helper);676 return make<TailMergeChunkX86>(dir, helper);
602 case ARMNT:677 case ARMNT:
603 return make<ThunkChunkARM>(S, Dir, Helper);678 return make<TailMergeChunkARM>(dir, helper);
604 case ARM64:679 case ARM64:
605 return make<ThunkChunkARM64>(S, Dir, Helper);680 return make<TailMergeChunkARM64>(dir, helper);
681 default:
682 llvm_unreachable("unsupported machine type");
683 }
684}
685
686Chunk *DelayLoadContents::newThunkChunk(DefinedImportData *s,
687 Chunk *tailMerge) {
688 switch (config->machine) {
689 case AMD64:
690 return make<ThunkChunkX64>(s, tailMerge);
691 case I386:
692 return make<ThunkChunkX86>(s, tailMerge);
693 case ARMNT:
694 return make<ThunkChunkARM>(s, tailMerge);
695 case ARM64:
696 return make<ThunkChunkARM64>(s, tailMerge);
606 default:697 default:
607 llvm_unreachable("unsupported machine type");698 llvm_unreachable("unsupported machine type");
608 }699 }
609}700}
610701
611EdataContents::EdataContents() {702EdataContents::EdataContents() {
612 uint16_t MaxOrdinal = 0;703 uint16_t maxOrdinal = 0;
613 for (Export &E : Config->Exports)704 for (Export &e : config->exports)
614 MaxOrdinal = std::max(MaxOrdinal, E.Ordinal);705 maxOrdinal = std::max(maxOrdinal, e.ordinal);
615706
616 auto *DLLName = make<StringChunk>(sys::path::filename(Config->OutputFile));707 auto *dllName = make<StringChunk>(sys::path::filename(config->outputFile));
617 auto *AddressTab = make<AddressTableChunk>(MaxOrdinal);708 auto *addressTab = make<AddressTableChunk>(maxOrdinal);
618 std::vector<Chunk *> Names;709 std::vector<Chunk *> names;
619 for (Export &E : Config->Exports)710 for (Export &e : config->exports)
620 if (!E.Noname)711 if (!e.noname)
621 Names.push_back(make<StringChunk>(E.ExportName));712 names.push_back(make<StringChunk>(e.exportName));
622713
623 std::vector<Chunk *> Forwards;714 std::vector<Chunk *> forwards;
624 for (Export &E : Config->Exports) {715 for (Export &e : config->exports) {
625 if (E.ForwardTo.empty())716 if (e.forwardTo.empty())
626 continue;717 continue;
627 E.ForwardChunk = make<StringChunk>(E.ForwardTo);718 e.forwardChunk = make<StringChunk>(e.forwardTo);
628 Forwards.push_back(E.ForwardChunk);719 forwards.push_back(e.forwardChunk);
629 }720 }
630721
631 auto *NameTab = make<NamePointersChunk>(Names);722 auto *nameTab = make<NamePointersChunk>(names);
632 auto *OrdinalTab = make<ExportOrdinalChunk>(Names.size());723 auto *ordinalTab = make<ExportOrdinalChunk>(names.size());
633 auto *Dir = make<ExportDirectoryChunk>(MaxOrdinal, Names.size(), DLLName,724 auto *dir = make<ExportDirectoryChunk>(maxOrdinal, names.size(), dllName,
634 AddressTab, NameTab, OrdinalTab);725 addressTab, nameTab, ordinalTab);
635 Chunks.push_back(Dir);726 chunks.push_back(dir);
636 Chunks.push_back(DLLName);727 chunks.push_back(dllName);
637 Chunks.push_back(AddressTab);728 chunks.push_back(addressTab);
638 Chunks.push_back(NameTab);729 chunks.push_back(nameTab);
639 Chunks.push_back(OrdinalTab);730 chunks.push_back(ordinalTab);
640 Chunks.insert(Chunks.end(), Names.begin(), Names.end());731 chunks.insert(chunks.end(), names.begin(), names.end());
641 Chunks.insert(Chunks.end(), Forwards.begin(), Forwards.end());732 chunks.insert(chunks.end(), forwards.begin(), forwards.end());
642}733}
643734
644} // namespace coff735} // namespace coff
deps/lld/COFF/DLL.h+30-30
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- DLL.h ----------------------------------------------------*- C++ -*-===//1//===- DLL.h ----------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -22,45 +21,46 @@ namespace coff {...@@ -22,45 +21,46 @@ namespace coff {
22// call create() to populate the chunk vectors.21// call create() to populate the chunk vectors.
23class IdataContents {22class IdataContents {
24public:23public:
25 void add(DefinedImportData *Sym) { Imports.push_back(Sym); }24 void add(DefinedImportData *sym) { imports.push_back(sym); }
26 bool empty() { return Imports.empty(); }25 bool empty() { return imports.empty(); }
2726
28 void create();27 void create();
2928
30 std::vector<DefinedImportData *> Imports;29 std::vector<DefinedImportData *> imports;
31 std::vector<Chunk *> Dirs;30 std::vector<Chunk *> dirs;
32 std::vector<Chunk *> Lookups;31 std::vector<Chunk *> lookups;
33 std::vector<Chunk *> Addresses;32 std::vector<Chunk *> addresses;
34 std::vector<Chunk *> Hints;33 std::vector<Chunk *> hints;
35 std::vector<Chunk *> DLLNames;34 std::vector<Chunk *> dllNames;
36};35};
3736
38// Windows-specific.37// Windows-specific.
39// DelayLoadContents creates all chunks for the delay-load DLL import table.38// DelayLoadContents creates all chunks for the delay-load DLL import table.
40class DelayLoadContents {39class DelayLoadContents {
41public:40public:
42 void add(DefinedImportData *Sym) { Imports.push_back(Sym); }41 void add(DefinedImportData *sym) { imports.push_back(sym); }
43 bool empty() { return Imports.empty(); }42 bool empty() { return imports.empty(); }
44 void create(Defined *Helper);43 void create(Defined *helper);
45 std::vector<Chunk *> getChunks();44 std::vector<Chunk *> getChunks();
46 std::vector<Chunk *> getDataChunks();45 std::vector<Chunk *> getDataChunks();
47 ArrayRef<Chunk *> getCodeChunks() { return Thunks; }46 ArrayRef<Chunk *> getCodeChunks() { return thunks; }
4847
49 uint64_t getDirRVA() { return Dirs[0]->getRVA(); }48 uint64_t getDirRVA() { return dirs[0]->getRVA(); }
50 uint64_t getDirSize();49 uint64_t getDirSize();
5150
52private:51private:
53 Chunk *newThunkChunk(DefinedImportData *S, Chunk *Dir);52 Chunk *newThunkChunk(DefinedImportData *s, Chunk *tailMerge);
53 Chunk *newTailMergeChunk(Chunk *dir);
5454
55 Defined *Helper;55 Defined *helper;
56 std::vector<DefinedImportData *> Imports;56 std::vector<DefinedImportData *> imports;
57 std::vector<Chunk *> Dirs;57 std::vector<Chunk *> dirs;
58 std::vector<Chunk *> ModuleHandles;58 std::vector<Chunk *> moduleHandles;
59 std::vector<Chunk *> Addresses;59 std::vector<Chunk *> addresses;
60 std::vector<Chunk *> Names;60 std::vector<Chunk *> names;
61 std::vector<Chunk *> HintNames;61 std::vector<Chunk *> hintNames;
62 std::vector<Chunk *> Thunks;62 std::vector<Chunk *> thunks;
63 std::vector<Chunk *> DLLNames;63 std::vector<Chunk *> dllNames;
64};64};
6565
66// Windows-specific.66// Windows-specific.
...@@ -68,11 +68,11 @@ private:...@@ -68,11 +68,11 @@ private:
68class EdataContents {68class EdataContents {
69public:69public:
70 EdataContents();70 EdataContents();
71 std::vector<Chunk *> Chunks;71 std::vector<Chunk *> chunks;
7272
73 uint64_t getRVA() { return Chunks[0]->getRVA(); }73 uint64_t getRVA() { return chunks[0]->getRVA(); }
74 uint64_t getSize() {74 uint64_t getSize() {
75 return Chunks.back()->getRVA() + Chunks.back()->getSize() - getRVA();75 return chunks.back()->getRVA() + chunks.back()->getSize() - getRVA();
76 }76 }
77};77};
7878
deps/lld/COFF/DebugTypes.cpp created+268
...@@ -0,0 +1,268 @@
1//===- DebugTypes.cpp -----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "DebugTypes.h"
10#include "Driver.h"
11#include "InputFiles.h"
12#include "lld/Common/ErrorHandler.h"
13#include "llvm/DebugInfo/CodeView/TypeRecord.h"
14#include "llvm/DebugInfo/PDB/GenericError.h"
15#include "llvm/DebugInfo/PDB/Native/InfoStream.h"
16#include "llvm/DebugInfo/PDB/Native/NativeSession.h"
17#include "llvm/DebugInfo/PDB/Native/PDBFile.h"
18#include "llvm/Support/Path.h"
19
20using namespace lld;
21using namespace lld::coff;
22using namespace llvm;
23using namespace llvm::codeview;
24
25namespace {
26// The TypeServerSource class represents a PDB type server, a file referenced by
27// OBJ files compiled with MSVC /Zi. A single PDB can be shared by several OBJ
28// files, therefore there must be only once instance per OBJ lot. The file path
29// is discovered from the dependent OBJ's debug type stream. The
30// TypeServerSource object is then queued and loaded by the COFF Driver. The
31// debug type stream for such PDB files will be merged first in the final PDB,
32// before any dependent OBJ.
33class TypeServerSource : public TpiSource {
34public:
35 explicit TypeServerSource(MemoryBufferRef m, llvm::pdb::NativeSession *s)
36 : TpiSource(PDB, nullptr), session(s), mb(m) {}
37
38 // Queue a PDB type server for loading in the COFF Driver
39 static void enqueue(const ObjFile *dependentFile,
40 const TypeServer2Record &ts);
41
42 // Create an instance
43 static Expected<TypeServerSource *> getInstance(MemoryBufferRef m);
44
45 // Fetch the PDB instance loaded for a corresponding dependent OBJ.
46 static Expected<TypeServerSource *>
47 findFromFile(const ObjFile *dependentFile);
48
49 static std::map<std::string, std::pair<std::string, TypeServerSource *>>
50 instances;
51
52 // The interface to the PDB (if it was opened successfully)
53 std::unique_ptr<llvm::pdb::NativeSession> session;
54
55private:
56 MemoryBufferRef mb;
57};
58
59// This class represents the debug type stream of an OBJ file that depends on a
60// PDB type server (see TypeServerSource).
61class UseTypeServerSource : public TpiSource {
62public:
63 UseTypeServerSource(const ObjFile *f, const TypeServer2Record *ts)
64 : TpiSource(UsingPDB, f), typeServerDependency(*ts) {}
65
66 // Information about the PDB type server dependency, that needs to be loaded
67 // in before merging this OBJ.
68 TypeServer2Record typeServerDependency;
69};
70
71// This class represents the debug type stream of a Microsoft precompiled
72// headers OBJ (PCH OBJ). This OBJ kind needs to be merged first in the output
73// PDB, before any other OBJs that depend on this. Note that only MSVC generate
74// such files, clang does not.
75class PrecompSource : public TpiSource {
76public:
77 PrecompSource(const ObjFile *f) : TpiSource(PCH, f) {}
78};
79
80// This class represents the debug type stream of an OBJ file that depends on a
81// Microsoft precompiled headers OBJ (see PrecompSource).
82class UsePrecompSource : public TpiSource {
83public:
84 UsePrecompSource(const ObjFile *f, const PrecompRecord *precomp)
85 : TpiSource(UsingPCH, f), precompDependency(*precomp) {}
86
87 // Information about the Precomp OBJ dependency, that needs to be loaded in
88 // before merging this OBJ.
89 PrecompRecord precompDependency;
90};
91} // namespace
92
93static std::vector<std::unique_ptr<TpiSource>> GC;
94
95TpiSource::TpiSource(TpiKind k, const ObjFile *f) : kind(k), file(f) {
96 GC.push_back(std::unique_ptr<TpiSource>(this));
97}
98
99TpiSource *lld::coff::makeTpiSource(const ObjFile *f) {
100 return new TpiSource(TpiSource::Regular, f);
101}
102
103TpiSource *lld::coff::makeUseTypeServerSource(const ObjFile *f,
104 const TypeServer2Record *ts) {
105 TypeServerSource::enqueue(f, *ts);
106 return new UseTypeServerSource(f, ts);
107}
108
109TpiSource *lld::coff::makePrecompSource(const ObjFile *f) {
110 return new PrecompSource(f);
111}
112
113TpiSource *lld::coff::makeUsePrecompSource(const ObjFile *f,
114 const PrecompRecord *precomp) {
115 return new UsePrecompSource(f, precomp);
116}
117
118namespace lld {
119namespace coff {
120template <>
121const PrecompRecord &retrieveDependencyInfo(const TpiSource *source) {
122 assert(source->kind == TpiSource::UsingPCH);
123 return ((const UsePrecompSource *)source)->precompDependency;
124}
125
126template <>
127const TypeServer2Record &retrieveDependencyInfo(const TpiSource *source) {
128 assert(source->kind == TpiSource::UsingPDB);
129 return ((const UseTypeServerSource *)source)->typeServerDependency;
130}
131} // namespace coff
132} // namespace lld
133
134std::map<std::string, std::pair<std::string, TypeServerSource *>>
135 TypeServerSource::instances;
136
137// Make a PDB path assuming the PDB is in the same folder as the OBJ
138static std::string getPdbBaseName(const ObjFile *file, StringRef tSPath) {
139 StringRef localPath =
140 !file->parentName.empty() ? file->parentName : file->getName();
141 SmallString<128> path = sys::path::parent_path(localPath);
142
143 // Currently, type server PDBs are only created by MSVC cl, which only runs
144 // on Windows, so we can assume type server paths are Windows style.
145 sys::path::append(path, sys::path::filename(tSPath, sys::path::Style::windows));
146 return path.str();
147}
148
149// The casing of the PDB path stamped in the OBJ can differ from the actual path
150// on disk. With this, we ensure to always use lowercase as a key for the
151// PDBInputFile::Instances map, at least on Windows.
152static std::string normalizePdbPath(StringRef path) {
153#if defined(_WIN32)
154 return path.lower();
155#else // LINUX
156 return path;
157#endif
158}
159
160// If existing, return the actual PDB path on disk.
161static Optional<std::string> findPdbPath(StringRef pdbPath,
162 const ObjFile *dependentFile) {
163 // Ensure the file exists before anything else. In some cases, if the path
164 // points to a removable device, Driver::enqueuePath() would fail with an
165 // error (EAGAIN, "resource unavailable try again") which we want to skip
166 // silently.
167 if (llvm::sys::fs::exists(pdbPath))
168 return normalizePdbPath(pdbPath);
169 std::string ret = getPdbBaseName(dependentFile, pdbPath);
170 if (llvm::sys::fs::exists(ret))
171 return normalizePdbPath(ret);
172 return None;
173}
174
175// Fetch the PDB instance that was already loaded by the COFF Driver.
176Expected<TypeServerSource *>
177TypeServerSource::findFromFile(const ObjFile *dependentFile) {
178 const TypeServer2Record &ts =
179 retrieveDependencyInfo<TypeServer2Record>(dependentFile->debugTypesObj);
180
181 Optional<std::string> p = findPdbPath(ts.Name, dependentFile);
182 if (!p)
183 return createFileError(ts.Name, errorCodeToError(std::error_code(
184 ENOENT, std::generic_category())));
185
186 auto it = TypeServerSource::instances.find(*p);
187 // The PDB file exists on disk, at this point we expect it to have been
188 // inserted in the map by TypeServerSource::loadPDB()
189 assert(it != TypeServerSource::instances.end());
190
191 std::pair<std::string, TypeServerSource *> &pdb = it->second;
192
193 if (!pdb.second)
194 return createFileError(
195 *p, createStringError(inconvertibleErrorCode(), pdb.first.c_str()));
196
197 pdb::PDBFile &pdbFile = (pdb.second)->session->getPDBFile();
198 pdb::InfoStream &info = cantFail(pdbFile.getPDBInfoStream());
199
200 // Just because a file with a matching name was found doesn't mean it can be
201 // used. The GUID must match between the PDB header and the OBJ
202 // TypeServer2 record. The 'Age' is used by MSVC incremental compilation.
203 if (info.getGuid() != ts.getGuid())
204 return createFileError(
205 ts.Name,
206 make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date));
207
208 return pdb.second;
209}
210
211// FIXME: Temporary interface until PDBLinker::maybeMergeTypeServerPDB() is
212// moved here.
213Expected<llvm::pdb::NativeSession *>
214lld::coff::findTypeServerSource(const ObjFile *f) {
215 Expected<TypeServerSource *> ts = TypeServerSource::findFromFile(f);
216 if (!ts)
217 return ts.takeError();
218 return ts.get()->session.get();
219}
220
221// Queue a PDB type server for loading in the COFF Driver
222void TypeServerSource::enqueue(const ObjFile *dependentFile,
223 const TypeServer2Record &ts) {
224 // Start by finding where the PDB is located (either the record path or next
225 // to the OBJ file)
226 Optional<std::string> p = findPdbPath(ts.Name, dependentFile);
227 if (!p)
228 return;
229 auto it = TypeServerSource::instances.emplace(
230 *p, std::pair<std::string, TypeServerSource *>{});
231 if (!it.second)
232 return; // another OBJ already scheduled this PDB for load
233
234 driver->enqueuePath(*p, false);
235}
236
237// Create an instance of TypeServerSource or an error string if the PDB couldn't
238// be loaded. The error message will be displayed later, when the referring OBJ
239// will be merged in. NOTE - a PDB load failure is not a link error: some
240// debug info will simply be missing from the final PDB - that is the default
241// accepted behavior.
242void lld::coff::loadTypeServerSource(llvm::MemoryBufferRef m) {
243 std::string path = normalizePdbPath(m.getBufferIdentifier());
244
245 Expected<TypeServerSource *> ts = TypeServerSource::getInstance(m);
246 if (!ts)
247 TypeServerSource::instances[path] = {toString(ts.takeError()), nullptr};
248 else
249 TypeServerSource::instances[path] = {{}, *ts};
250}
251
252Expected<TypeServerSource *> TypeServerSource::getInstance(MemoryBufferRef m) {
253 std::unique_ptr<llvm::pdb::IPDBSession> iSession;
254 Error err = pdb::NativeSession::createFromPdb(
255 MemoryBuffer::getMemBuffer(m, false), iSession);
256 if (err)
257 return std::move(err);
258
259 std::unique_ptr<llvm::pdb::NativeSession> session(
260 static_cast<pdb::NativeSession *>(iSession.release()));
261
262 pdb::PDBFile &pdbFile = session->getPDBFile();
263 Expected<pdb::InfoStream &> info = pdbFile.getPDBInfoStream();
264 // All PDB Files should have an Info stream.
265 if (!info)
266 return info.takeError();
267 return new TypeServerSource(m, session.release());
268}
deps/lld/COFF/DebugTypes.h created+60
...@@ -0,0 +1,60 @@
1//===- DebugTypes.h ---------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_COFF_DEBUGTYPES_H
10#define LLD_COFF_DEBUGTYPES_H
11
12#include "llvm/Support/Error.h"
13#include "llvm/Support/MemoryBuffer.h"
14
15namespace llvm {
16namespace codeview {
17class PrecompRecord;
18class TypeServer2Record;
19} // namespace codeview
20namespace pdb {
21class NativeSession;
22}
23} // namespace llvm
24
25namespace lld {
26namespace coff {
27
28class ObjFile;
29
30class TpiSource {
31public:
32 enum TpiKind { Regular, PCH, UsingPCH, PDB, UsingPDB };
33
34 TpiSource(TpiKind k, const ObjFile *f);
35 virtual ~TpiSource() {}
36
37 const TpiKind kind;
38 const ObjFile *file;
39};
40
41TpiSource *makeTpiSource(const ObjFile *f);
42TpiSource *makeUseTypeServerSource(const ObjFile *f,
43 const llvm::codeview::TypeServer2Record *ts);
44TpiSource *makePrecompSource(const ObjFile *f);
45TpiSource *makeUsePrecompSource(const ObjFile *f,
46 const llvm::codeview::PrecompRecord *precomp);
47
48void loadTypeServerSource(llvm::MemoryBufferRef m);
49
50// Temporary interface to get the dependency
51template <typename T> const T &retrieveDependencyInfo(const TpiSource *source);
52
53// Temporary interface until we move PDBLinker::maybeMergeTypeServerPDB here
54llvm::Expected<llvm::pdb::NativeSession *>
55findTypeServerSource(const ObjFile *f);
56
57} // namespace coff
58} // namespace lld
59
60#endif
\ No newline at end of file
deps/lld/COFF/Driver.cpp+1066-856
...@@ -1,14 +1,14 @@...@@ -1,14 +1,14 @@
1//===- Driver.cpp ---------------------------------------------------------===//1//===- Driver.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
10#include "Driver.h"9#include "Driver.h"
11#include "Config.h"10#include "Config.h"
11#include "DebugTypes.h"
12#include "ICF.h"12#include "ICF.h"
13#include "InputFiles.h"13#include "InputFiles.h"
14#include "MarkLive.h"14#include "MarkLive.h"
...@@ -19,7 +19,9 @@...@@ -19,7 +19,9 @@
19#include "lld/Common/Args.h"19#include "lld/Common/Args.h"
20#include "lld/Common/Driver.h"20#include "lld/Common/Driver.h"
21#include "lld/Common/ErrorHandler.h"21#include "lld/Common/ErrorHandler.h"
22#include "lld/Common/Filesystem.h"
22#include "lld/Common/Memory.h"23#include "lld/Common/Memory.h"
24#include "lld/Common/Threads.h"
23#include "lld/Common/Timer.h"25#include "lld/Common/Timer.h"
24#include "lld/Common/Version.h"26#include "lld/Common/Version.h"
25#include "llvm/ADT/Optional.h"27#include "llvm/ADT/Optional.h"
...@@ -28,6 +30,7 @@...@@ -28,6 +30,7 @@
28#include "llvm/Object/ArchiveWriter.h"30#include "llvm/Object/ArchiveWriter.h"
29#include "llvm/Object/COFFImportFile.h"31#include "llvm/Object/COFFImportFile.h"
30#include "llvm/Object/COFFModuleDefinition.h"32#include "llvm/Object/COFFModuleDefinition.h"
33#include "llvm/Object/WindowsMachineFlag.h"
31#include "llvm/Option/Arg.h"34#include "llvm/Option/Arg.h"
32#include "llvm/Option/ArgList.h"35#include "llvm/Option/ArgList.h"
33#include "llvm/Option/Option.h"36#include "llvm/Option/Option.h"
...@@ -51,43 +54,68 @@ using llvm::sys::Process;...@@ -51,43 +54,68 @@ using llvm::sys::Process;
51namespace lld {54namespace lld {
52namespace coff {55namespace coff {
5356
54static Timer InputFileTimer("Input File Reading", Timer::root());57static Timer inputFileTimer("Input File Reading", Timer::root());
5558
56Configuration *Config;59Configuration *config;
57LinkerDriver *Driver;60LinkerDriver *driver;
5861
59bool link(ArrayRef<const char *> Args, bool CanExitEarly, raw_ostream &Diag) {62bool link(ArrayRef<const char *> args, bool canExitEarly, raw_ostream &diag) {
60 errorHandler().LogName = args::getFilenameWithoutExe(Args[0]);63 errorHandler().logName = args::getFilenameWithoutExe(args[0]);
61 errorHandler().ErrorOS = &Diag;64 errorHandler().errorOS = &diag;
62 errorHandler().ColorDiagnostics = Diag.has_colors();65 errorHandler().colorDiagnostics = diag.has_colors();
63 errorHandler().ErrorLimitExceededMsg =66 errorHandler().errorLimitExceededMsg =
64 "too many errors emitted, stopping now"67 "too many errors emitted, stopping now"
65 " (use /errorlimit:0 to see all errors)";68 " (use /errorlimit:0 to see all errors)";
66 errorHandler().ExitEarly = CanExitEarly;69 errorHandler().exitEarly = canExitEarly;
67 Config = make<Configuration>();70 config = make<Configuration>();
6871
69 Symtab = make<SymbolTable>();72 symtab = make<SymbolTable>();
7073
71 Driver = make<LinkerDriver>();74 driver = make<LinkerDriver>();
72 Driver->link(Args);75 driver->link(args);
7376
74 // Call exit() if we can to avoid calling destructors.77 // Call exit() if we can to avoid calling destructors.
75 if (CanExitEarly)78 if (canExitEarly)
76 exitLld(errorCount() ? 1 : 0);79 exitLld(errorCount() ? 1 : 0);
7780
78 freeArena();81 freeArena();
79 ObjFile::Instances.clear();82 ObjFile::instances.clear();
80 ImportFile::Instances.clear();83 ImportFile::instances.clear();
81 BitcodeFile::Instances.clear();84 BitcodeFile::instances.clear();
85 memset(MergeChunk::instances, 0, sizeof(MergeChunk::instances));
82 return !errorCount();86 return !errorCount();
83}87}
8488
89// Parse options of the form "old;new".
90static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args,
91 unsigned id) {
92 auto *arg = args.getLastArg(id);
93 if (!arg)
94 return {"", ""};
95
96 StringRef s = arg->getValue();
97 std::pair<StringRef, StringRef> ret = s.split(';');
98 if (ret.second.empty())
99 error(arg->getSpelling() + " expects 'old;new' format, but got " + s);
100 return ret;
101}
102
85// Drop directory components and replace extension with ".exe" or ".dll".103// Drop directory components and replace extension with ".exe" or ".dll".
86static std::string getOutputPath(StringRef Path) {104static std::string getOutputPath(StringRef path) {
87 auto P = Path.find_last_of("\\/");105 auto p = path.find_last_of("\\/");
88 StringRef S = (P == StringRef::npos) ? Path : Path.substr(P + 1);106 StringRef s = (p == StringRef::npos) ? path : path.substr(p + 1);
89 const char* E = Config->DLL ? ".dll" : ".exe";107 const char* e = config->dll ? ".dll" : ".exe";
90 return (S.substr(0, S.rfind('.')) + E).str();108 return (s.substr(0, s.rfind('.')) + e).str();
109}
110
111// Returns true if S matches /crtend.?\.o$/.
112static bool isCrtend(StringRef s) {
113 if (!s.endswith(".o"))
114 return false;
115 s = s.drop_back(2);
116 if (s.endswith("crtend"))
117 return true;
118 return !s.empty() && s.drop_back().endswith("crtend");
91}119}
92120
93// ErrorOr is not default constructible, so it cannot be used as the type121// ErrorOr is not default constructible, so it cannot be used as the type
...@@ -95,347 +123,401 @@ static std::string getOutputPath(StringRef Path) {...@@ -95,347 +123,401 @@ static std::string getOutputPath(StringRef Path) {
95// FIXME: We could open the file in createFutureForFile and avoid needing to123// FIXME: We could open the file in createFutureForFile and avoid needing to
96// return an error here, but for the moment that would cost us a file descriptor124// return an error here, but for the moment that would cost us a file descriptor
97// (a limited resource on Windows) for the duration that the future is pending.125// (a limited resource on Windows) for the duration that the future is pending.
98typedef std::pair<std::unique_ptr<MemoryBuffer>, std::error_code> MBErrPair;126using MBErrPair = std::pair<std::unique_ptr<MemoryBuffer>, std::error_code>;
99127
100// Create a std::future that opens and maps a file using the best strategy for128// Create a std::future that opens and maps a file using the best strategy for
101// the host platform.129// the host platform.
102static std::future<MBErrPair> createFutureForFile(std::string Path) {130static std::future<MBErrPair> createFutureForFile(std::string path) {
103#if _WIN32131#if _WIN32
104 // On Windows, file I/O is relatively slow so it is best to do this132 // On Windows, file I/O is relatively slow so it is best to do this
105 // asynchronously.133 // asynchronously.
106 auto Strategy = std::launch::async;134 auto strategy = std::launch::async;
107#else135#else
108 auto Strategy = std::launch::deferred;136 auto strategy = std::launch::deferred;
109#endif137#endif
110 return std::async(Strategy, [=]() {138 return std::async(strategy, [=]() {
111 auto MBOrErr = MemoryBuffer::getFile(Path,139 auto mbOrErr = MemoryBuffer::getFile(path,
112 /*FileSize*/ -1,140 /*FileSize*/ -1,
113 /*RequiresNullTerminator*/ false);141 /*RequiresNullTerminator*/ false);
114 if (!MBOrErr)142 if (!mbOrErr)
115 return MBErrPair{nullptr, MBOrErr.getError()};143 return MBErrPair{nullptr, mbOrErr.getError()};
116 return MBErrPair{std::move(*MBOrErr), std::error_code()};144 return MBErrPair{std::move(*mbOrErr), std::error_code()};
117 });145 });
118}146}
119147
120// Symbol names are mangled by prepending "_" on x86.148// Symbol names are mangled by prepending "_" on x86.
121static StringRef mangle(StringRef Sym) {149static StringRef mangle(StringRef sym) {
122 assert(Config->Machine != IMAGE_FILE_MACHINE_UNKNOWN);150 assert(config->machine != IMAGE_FILE_MACHINE_UNKNOWN);
123 if (Config->Machine == I386)151 if (config->machine == I386)
124 return Saver.save("_" + Sym);152 return saver.save("_" + sym);
125 return Sym;153 return sym;
126}154}
127155
128static bool findUnderscoreMangle(StringRef Sym) {156static bool findUnderscoreMangle(StringRef sym) {
129 StringRef Entry = Symtab->findMangle(mangle(Sym));157 Symbol *s = symtab->findMangle(mangle(sym));
130 return !Entry.empty() && !isa<Undefined>(Symtab->find(Entry));158 return s && !isa<Undefined>(s);
131}159}
132160
133MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> MB) {161MemoryBufferRef LinkerDriver::takeBuffer(std::unique_ptr<MemoryBuffer> mb) {
134 MemoryBufferRef MBRef = *MB;162 MemoryBufferRef mbref = *mb;
135 make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take ownership163 make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take ownership
136164
137 if (Driver->Tar)165 if (driver->tar)
138 Driver->Tar->append(relativeToRoot(MBRef.getBufferIdentifier()),166 driver->tar->append(relativeToRoot(mbref.getBufferIdentifier()),
139 MBRef.getBuffer());167 mbref.getBuffer());
140 return MBRef;168 return mbref;
141}169}
142170
143void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> MB,171void LinkerDriver::addBuffer(std::unique_ptr<MemoryBuffer> mb,
144 bool WholeArchive) {172 bool wholeArchive) {
145 StringRef Filename = MB->getBufferIdentifier();173 StringRef filename = mb->getBufferIdentifier();
146174
147 MemoryBufferRef MBRef = takeBuffer(std::move(MB));175 MemoryBufferRef mbref = takeBuffer(std::move(mb));
148 FilePaths.push_back(Filename);176 filePaths.push_back(filename);
149177
150 // File type is detected by contents, not by file extension.178 // File type is detected by contents, not by file extension.
151 switch (identify_magic(MBRef.getBuffer())) {179 switch (identify_magic(mbref.getBuffer())) {
152 case file_magic::windows_resource:180 case file_magic::windows_resource:
153 Resources.push_back(MBRef);181 resources.push_back(mbref);
154 break;182 break;
155 case file_magic::archive:183 case file_magic::archive:
156 if (WholeArchive) {184 if (wholeArchive) {
157 std::unique_ptr<Archive> File =185 std::unique_ptr<Archive> file =
158 CHECK(Archive::create(MBRef), Filename + ": failed to parse archive");186 CHECK(Archive::create(mbref), filename + ": failed to parse archive");
159187
160 for (MemoryBufferRef M : getArchiveMembers(File.get()))188 for (MemoryBufferRef m : getArchiveMembers(file.get()))
161 addArchiveBuffer(M, "<whole-archive>", Filename);189 addArchiveBuffer(m, "<whole-archive>", filename, 0);
162 return;190 return;
163 }191 }
164 Symtab->addFile(make<ArchiveFile>(MBRef));192 symtab->addFile(make<ArchiveFile>(mbref));
165 break;193 break;
166 case file_magic::bitcode:194 case file_magic::bitcode:
167 Symtab->addFile(make<BitcodeFile>(MBRef));195 symtab->addFile(make<BitcodeFile>(mbref, "", 0));
168 break;196 break;
169 case file_magic::coff_object:197 case file_magic::coff_object:
170 case file_magic::coff_import_library:198 case file_magic::coff_import_library:
171 Symtab->addFile(make<ObjFile>(MBRef));199 symtab->addFile(make<ObjFile>(mbref));
200 break;
201 case file_magic::pdb:
202 loadTypeServerSource(mbref);
172 break;203 break;
173 case file_magic::coff_cl_gl_object:204 case file_magic::coff_cl_gl_object:
174 error(Filename + ": is not a native COFF file. Recompile without /GL");205 error(filename + ": is not a native COFF file. Recompile without /GL");
175 break;206 break;
176 case file_magic::pecoff_executable:207 case file_magic::pecoff_executable:
177 if (Filename.endswith_lower(".dll")) {208 if (filename.endswith_lower(".dll")) {
178 error(Filename + ": bad file type. Did you specify a DLL instead of an "209 error(filename + ": bad file type. Did you specify a DLL instead of an "
179 "import library?");210 "import library?");
180 break;211 break;
181 }212 }
182 LLVM_FALLTHROUGH;213 LLVM_FALLTHROUGH;
183 default:214 default:
184 error(MBRef.getBufferIdentifier() + ": unknown file type");215 error(mbref.getBufferIdentifier() + ": unknown file type");
185 break;216 break;
186 }217 }
187}218}
188219
189void LinkerDriver::enqueuePath(StringRef Path, bool WholeArchive) {220void LinkerDriver::enqueuePath(StringRef path, bool wholeArchive) {
190 auto Future =221 auto future =
191 std::make_shared<std::future<MBErrPair>>(createFutureForFile(Path));222 std::make_shared<std::future<MBErrPair>>(createFutureForFile(path));
192 std::string PathStr = Path;223 std::string pathStr = path;
193 enqueueTask([=]() {224 enqueueTask([=]() {
194 auto MBOrErr = Future->get();225 auto mbOrErr = future->get();
195 if (MBOrErr.second)226 if (mbOrErr.second) {
196 error("could not open " + PathStr + ": " + MBOrErr.second.message());227 std::string msg =
197 else228 "could not open '" + pathStr + "': " + mbOrErr.second.message();
198 Driver->addBuffer(std::move(MBOrErr.first), WholeArchive);229 // Check if the filename is a typo for an option flag. OptTable thinks
230 // that all args that are not known options and that start with / are
231 // filenames, but e.g. `/nodefaultlibs` is more likely a typo for
232 // the option `/nodefaultlib` than a reference to a file in the root
233 // directory.
234 std::string nearest;
235 if (COFFOptTable().findNearest(pathStr, nearest) > 1)
236 error(msg);
237 else
238 error(msg + "; did you mean '" + nearest + "'");
239 } else
240 driver->addBuffer(std::move(mbOrErr.first), wholeArchive);
199 });241 });
200}242}
201243
202void LinkerDriver::addArchiveBuffer(MemoryBufferRef MB, StringRef SymName,244void LinkerDriver::addArchiveBuffer(MemoryBufferRef mb, StringRef symName,
203 StringRef ParentName) {245 StringRef parentName,
204 file_magic Magic = identify_magic(MB.getBuffer());246 uint64_t offsetInArchive) {
205 if (Magic == file_magic::coff_import_library) {247 file_magic magic = identify_magic(mb.getBuffer());
206 Symtab->addFile(make<ImportFile>(MB));248 if (magic == file_magic::coff_import_library) {
249 InputFile *imp = make<ImportFile>(mb);
250 imp->parentName = parentName;
251 symtab->addFile(imp);
207 return;252 return;
208 }253 }
209254
210 InputFile *Obj;255 InputFile *obj;
211 if (Magic == file_magic::coff_object) {256 if (magic == file_magic::coff_object) {
212 Obj = make<ObjFile>(MB);257 obj = make<ObjFile>(mb);
213 } else if (Magic == file_magic::bitcode) {258 } else if (magic == file_magic::bitcode) {
214 Obj = make<BitcodeFile>(MB);259 obj = make<BitcodeFile>(mb, parentName, offsetInArchive);
215 } else {260 } else {
216 error("unknown file type: " + MB.getBufferIdentifier());261 error("unknown file type: " + mb.getBufferIdentifier());
217 return;262 return;
218 }263 }
219264
220 Obj->ParentName = ParentName;265 obj->parentName = parentName;
221 Symtab->addFile(Obj);266 symtab->addFile(obj);
222 log("Loaded " + toString(Obj) + " for " + SymName);267 log("Loaded " + toString(obj) + " for " + symName);
223}268}
224269
225void LinkerDriver::enqueueArchiveMember(const Archive::Child &C,270void LinkerDriver::enqueueArchiveMember(const Archive::Child &c,
226 StringRef SymName,271 StringRef symName,
227 StringRef ParentName) {272 StringRef parentName) {
228 if (!C.getParent()->isThin()) {273
229 MemoryBufferRef MB = CHECK(274 auto reportBufferError = [=](Error &&e,
230 C.getMemoryBufferRef(),275 StringRef childName) {
231 "could not get the buffer for the member defining symbol " + SymName);276 fatal("could not get the buffer for the member defining symbol " +
232 enqueueTask([=]() { Driver->addArchiveBuffer(MB, SymName, ParentName); });277 symName + ": " + parentName + "(" + childName + "): " +
278 toString(std::move(e)));
279 };
280
281 if (!c.getParent()->isThin()) {
282 uint64_t offsetInArchive = c.getChildOffset();
283 Expected<MemoryBufferRef> mbOrErr = c.getMemoryBufferRef();
284 if (!mbOrErr)
285 reportBufferError(mbOrErr.takeError(), check(c.getFullName()));
286 MemoryBufferRef mb = mbOrErr.get();
287 enqueueTask([=]() {
288 driver->addArchiveBuffer(mb, symName, parentName, offsetInArchive);
289 });
233 return;290 return;
234 }291 }
235292
236 auto Future = std::make_shared<std::future<MBErrPair>>(createFutureForFile(293 std::string childName = CHECK(
237 CHECK(C.getFullName(),294 c.getFullName(),
238 "could not get the filename for the member defining symbol " +295 "could not get the filename for the member defining symbol " +
239 SymName)));296 symName);
297 auto future = std::make_shared<std::future<MBErrPair>>(
298 createFutureForFile(childName));
240 enqueueTask([=]() {299 enqueueTask([=]() {
241 auto MBOrErr = Future->get();300 auto mbOrErr = future->get();
242 if (MBOrErr.second)301 if (mbOrErr.second)
243 fatal("could not get the buffer for the member defining " + SymName +302 reportBufferError(errorCodeToError(mbOrErr.second), childName);
244 ": " + MBOrErr.second.message());303 driver->addArchiveBuffer(takeBuffer(std::move(mbOrErr.first)), symName,
245 Driver->addArchiveBuffer(takeBuffer(std::move(MBOrErr.first)), SymName,304 parentName, /* OffsetInArchive */ 0);
246 ParentName);
247 });305 });
248}306}
249307
250static bool isDecorated(StringRef Sym) {308static bool isDecorated(StringRef sym) {
251 return Sym.startswith("@") || Sym.contains("@@") || Sym.startswith("?") ||309 return sym.startswith("@") || sym.contains("@@") || sym.startswith("?") ||
252 (!Config->MinGW && Sym.contains('@'));310 (!config->mingw && sym.contains('@'));
253}311}
254312
255// Parses .drectve section contents and returns a list of files313// Parses .drectve section contents and returns a list of files
256// specified by /defaultlib.314// specified by /defaultlib.
257void LinkerDriver::parseDirectives(StringRef S) {315void LinkerDriver::parseDirectives(InputFile *file) {
258 ArgParser Parser;316 StringRef s = file->getDirectives();
317 if (s.empty())
318 return;
319
320 log("Directives: " + toString(file) + ": " + s);
321
322 ArgParser parser;
259 // .drectve is always tokenized using Windows shell rules.323 // .drectve is always tokenized using Windows shell rules.
260 // /EXPORT: option can appear too many times, processing in fastpath.324 // /EXPORT: option can appear too many times, processing in fastpath.
261 opt::InputArgList Args;325 opt::InputArgList args;
262 std::vector<StringRef> Exports;326 std::vector<StringRef> exports;
263 std::tie(Args, Exports) = Parser.parseDirectives(S);327 std::tie(args, exports) = parser.parseDirectives(s);
264328
265 for (StringRef E : Exports) {329 for (StringRef e : exports) {
266 // If a common header file contains dllexported function330 // If a common header file contains dllexported function
267 // declarations, many object files may end up with having the331 // declarations, many object files may end up with having the
268 // same /EXPORT options. In order to save cost of parsing them,332 // same /EXPORT options. In order to save cost of parsing them,
269 // we dedup them first.333 // we dedup them first.
270 if (!DirectivesExports.insert(E).second)334 if (!directivesExports.insert(e).second)
271 continue;335 continue;
272336
273 Export Exp = parseExport(E);337 Export exp = parseExport(e);
274 if (Config->Machine == I386 && Config->MinGW) {338 if (config->machine == I386 && config->mingw) {
275 if (!isDecorated(Exp.Name))339 if (!isDecorated(exp.name))
276 Exp.Name = Saver.save("_" + Exp.Name);340 exp.name = saver.save("_" + exp.name);
277 if (!Exp.ExtName.empty() && !isDecorated(Exp.ExtName))341 if (!exp.extName.empty() && !isDecorated(exp.extName))
278 Exp.ExtName = Saver.save("_" + Exp.ExtName);342 exp.extName = saver.save("_" + exp.extName);
279 }343 }
280 Exp.Directives = true;344 exp.directives = true;
281 Config->Exports.push_back(Exp);345 config->exports.push_back(exp);
282 }346 }
283347
284 for (auto *Arg : Args) {348 for (auto *arg : args) {
285 switch (Arg->getOption().getUnaliasedOption().getID()) {349 switch (arg->getOption().getID()) {
286 case OPT_aligncomm:350 case OPT_aligncomm:
287 parseAligncomm(Arg->getValue());351 parseAligncomm(arg->getValue());
288 break;352 break;
289 case OPT_alternatename:353 case OPT_alternatename:
290 parseAlternateName(Arg->getValue());354 parseAlternateName(arg->getValue());
291 break;355 break;
292 case OPT_defaultlib:356 case OPT_defaultlib:
293 if (Optional<StringRef> Path = findLib(Arg->getValue()))357 if (Optional<StringRef> path = findLib(arg->getValue()))
294 enqueuePath(*Path, false);358 enqueuePath(*path, false);
295 break;359 break;
296 case OPT_entry:360 case OPT_entry:
297 Config->Entry = addUndefined(mangle(Arg->getValue()));361 config->entry = addUndefined(mangle(arg->getValue()));
298 break;362 break;
299 case OPT_failifmismatch:363 case OPT_failifmismatch:
300 checkFailIfMismatch(Arg->getValue());364 checkFailIfMismatch(arg->getValue(), file);
301 break;365 break;
302 case OPT_incl:366 case OPT_incl:
303 addUndefined(Arg->getValue());367 addUndefined(arg->getValue());
304 break;368 break;
305 case OPT_merge:369 case OPT_merge:
306 parseMerge(Arg->getValue());370 parseMerge(arg->getValue());
307 break;371 break;
308 case OPT_nodefaultlib:372 case OPT_nodefaultlib:
309 Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));373 config->noDefaultLibs.insert(doFindLib(arg->getValue()).lower());
310 break;374 break;
311 case OPT_section:375 case OPT_section:
312 parseSection(Arg->getValue());376 parseSection(arg->getValue());
313 break;377 break;
314 case OPT_subsystem:378 case OPT_subsystem:
315 parseSubsystem(Arg->getValue(), &Config->Subsystem,379 parseSubsystem(arg->getValue(), &config->subsystem,
316 &Config->MajorOSVersion, &Config->MinorOSVersion);380 &config->majorOSVersion, &config->minorOSVersion);
317 break;381 break;
382 // Only add flags here that link.exe accepts in
383 // `#pragma comment(linker, "/flag")`-generated sections.
318 case OPT_editandcontinue:384 case OPT_editandcontinue:
319 case OPT_fastfail:
320 case OPT_guardsym:385 case OPT_guardsym:
321 case OPT_natvis:
322 case OPT_throwingnew:386 case OPT_throwingnew:
323 break;387 break;
324 default:388 default:
325 error(Arg->getSpelling() + " is not allowed in .drectve");389 error(arg->getSpelling() + " is not allowed in .drectve");
326 }390 }
327 }391 }
328}392}
329393
330// Find file from search paths. You can omit ".obj", this function takes394// Find file from search paths. You can omit ".obj", this function takes
331// care of that. Note that the returned path is not guaranteed to exist.395// care of that. Note that the returned path is not guaranteed to exist.
332StringRef LinkerDriver::doFindFile(StringRef Filename) {396StringRef LinkerDriver::doFindFile(StringRef filename) {
333 bool HasPathSep = (Filename.find_first_of("/\\") != StringRef::npos);397 bool hasPathSep = (filename.find_first_of("/\\") != StringRef::npos);
334 if (HasPathSep)398 if (hasPathSep)
335 return Filename;399 return filename;
336 bool HasExt = Filename.contains('.');400 bool hasExt = filename.contains('.');
337 for (StringRef Dir : SearchPaths) {401 for (StringRef dir : searchPaths) {
338 SmallString<128> Path = Dir;402 SmallString<128> path = dir;
339 sys::path::append(Path, Filename);403 sys::path::append(path, filename);
340 if (sys::fs::exists(Path.str()))404 if (sys::fs::exists(path.str()))
341 return Saver.save(Path.str());405 return saver.save(path.str());
342 if (!HasExt) {406 if (!hasExt) {
343 Path.append(".obj");407 path.append(".obj");
344 if (sys::fs::exists(Path.str()))408 if (sys::fs::exists(path.str()))
345 return Saver.save(Path.str());409 return saver.save(path.str());
346 }410 }
347 }411 }
348 return Filename;412 return filename;
349}413}
350414
351static Optional<sys::fs::UniqueID> getUniqueID(StringRef Path) {415static Optional<sys::fs::UniqueID> getUniqueID(StringRef path) {
352 sys::fs::UniqueID Ret;416 sys::fs::UniqueID ret;
353 if (sys::fs::getUniqueID(Path, Ret))417 if (sys::fs::getUniqueID(path, ret))
354 return None;418 return None;
355 return Ret;419 return ret;
356}420}
357421
358// Resolves a file path. This never returns the same path422// Resolves a file path. This never returns the same path
359// (in that case, it returns None).423// (in that case, it returns None).
360Optional<StringRef> LinkerDriver::findFile(StringRef Filename) {424Optional<StringRef> LinkerDriver::findFile(StringRef filename) {
361 StringRef Path = doFindFile(Filename);425 StringRef path = doFindFile(filename);
362426
363 if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path)) {427 if (Optional<sys::fs::UniqueID> id = getUniqueID(path)) {
364 bool Seen = !VisitedFiles.insert(*ID).second;428 bool seen = !visitedFiles.insert(*id).second;
365 if (Seen)429 if (seen)
366 return None;430 return None;
367 }431 }
368432
369 if (Path.endswith_lower(".lib"))433 if (path.endswith_lower(".lib"))
370 VisitedLibs.insert(sys::path::filename(Path));434 visitedLibs.insert(sys::path::filename(path));
371 return Path;435 return path;
372}436}
373437
374// MinGW specific. If an embedded directive specified to link to438// MinGW specific. If an embedded directive specified to link to
375// foo.lib, but it isn't found, try libfoo.a instead.439// foo.lib, but it isn't found, try libfoo.a instead.
376StringRef LinkerDriver::doFindLibMinGW(StringRef Filename) {440StringRef LinkerDriver::doFindLibMinGW(StringRef filename) {
377 if (Filename.contains('/') || Filename.contains('\\'))441 if (filename.contains('/') || filename.contains('\\'))
378 return Filename;442 return filename;
379443
380 SmallString<128> S = Filename;444 SmallString<128> s = filename;
381 sys::path::replace_extension(S, ".a");445 sys::path::replace_extension(s, ".a");
382 StringRef LibName = Saver.save("lib" + S.str());446 StringRef libName = saver.save("lib" + s.str());
383 return doFindFile(LibName);447 return doFindFile(libName);
384}448}
385449
386// Find library file from search path.450// Find library file from search path.
387StringRef LinkerDriver::doFindLib(StringRef Filename) {451StringRef LinkerDriver::doFindLib(StringRef filename) {
388 // Add ".lib" to Filename if that has no file extension.452 // Add ".lib" to Filename if that has no file extension.
389 bool HasExt = Filename.contains('.');453 bool hasExt = filename.contains('.');
390 if (!HasExt)454 if (!hasExt)
391 Filename = Saver.save(Filename + ".lib");455 filename = saver.save(filename + ".lib");
392 StringRef Ret = doFindFile(Filename);456 StringRef ret = doFindFile(filename);
393 // For MinGW, if the find above didn't turn up anything, try457 // For MinGW, if the find above didn't turn up anything, try
394 // looking for a MinGW formatted library name.458 // looking for a MinGW formatted library name.
395 if (Config->MinGW && Ret == Filename)459 if (config->mingw && ret == filename)
396 return doFindLibMinGW(Filename);460 return doFindLibMinGW(filename);
397 return Ret;461 return ret;
398}462}
399463
400// Resolves a library path. /nodefaultlib options are taken into464// Resolves a library path. /nodefaultlib options are taken into
401// consideration. This never returns the same path (in that case,465// consideration. This never returns the same path (in that case,
402// it returns None).466// it returns None).
403Optional<StringRef> LinkerDriver::findLib(StringRef Filename) {467Optional<StringRef> LinkerDriver::findLib(StringRef filename) {
404 if (Config->NoDefaultLibAll)468 if (config->noDefaultLibAll)
405 return None;469 return None;
406 if (!VisitedLibs.insert(Filename.lower()).second)470 if (!visitedLibs.insert(filename.lower()).second)
407 return None;471 return None;
408472
409 StringRef Path = doFindLib(Filename);473 StringRef path = doFindLib(filename);
410 if (Config->NoDefaultLibs.count(Path))474 if (config->noDefaultLibs.count(path.lower()))
411 return None;475 return None;
412476
413 if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path))477 if (Optional<sys::fs::UniqueID> id = getUniqueID(path))
414 if (!VisitedFiles.insert(*ID).second)478 if (!visitedFiles.insert(*id).second)
415 return None;479 return None;
416 return Path;480 return path;
417}481}
418482
419// Parses LIB environment which contains a list of search paths.483// Parses LIB environment which contains a list of search paths.
420void LinkerDriver::addLibSearchPaths() {484void LinkerDriver::addLibSearchPaths() {
421 Optional<std::string> EnvOpt = Process::GetEnv("LIB");485 Optional<std::string> envOpt = Process::GetEnv("LIB");
422 if (!EnvOpt.hasValue())486 if (!envOpt.hasValue())
423 return;487 return;
424 StringRef Env = Saver.save(*EnvOpt);488 StringRef env = saver.save(*envOpt);
425 while (!Env.empty()) {489 while (!env.empty()) {
426 StringRef Path;490 StringRef path;
427 std::tie(Path, Env) = Env.split(';');491 std::tie(path, env) = env.split(';');
428 SearchPaths.push_back(Path);492 searchPaths.push_back(path);
429 }493 }
430}494}
431495
432Symbol *LinkerDriver::addUndefined(StringRef Name) {496Symbol *LinkerDriver::addUndefined(StringRef name) {
433 Symbol *B = Symtab->addUndefined(Name);497 Symbol *b = symtab->addUndefined(name);
434 if (!B->IsGCRoot) {498 if (!b->isGCRoot) {
435 B->IsGCRoot = true;499 b->isGCRoot = true;
436 Config->GCRoot.push_back(B);500 config->gcroot.push_back(b);
437 }501 }
438 return B;502 return b;
503}
504
505StringRef LinkerDriver::mangleMaybe(Symbol *s) {
506 // If the plain symbol name has already been resolved, do nothing.
507 Undefined *unmangled = dyn_cast<Undefined>(s);
508 if (!unmangled)
509 return "";
510
511 // Otherwise, see if a similar, mangled symbol exists in the symbol table.
512 Symbol *mangled = symtab->findMangle(unmangled->getName());
513 if (!mangled)
514 return "";
515
516 // If we find a similar mangled symbol, make this an alias to it and return
517 // its name.
518 log(unmangled->getName() + " aliased to " + mangled->getName());
519 unmangled->weakAlias = symtab->addUndefined(mangled->getName());
520 return mangled->getName();
439}521}
440522
441// Windows specific -- find default entry point name.523// Windows specific -- find default entry point name.
...@@ -444,15 +526,15 @@ Symbol *LinkerDriver::addUndefined(StringRef Name) {...@@ -444,15 +526,15 @@ Symbol *LinkerDriver::addUndefined(StringRef Name) {
444// each of which corresponds to a user-defined "main" function. This function526// each of which corresponds to a user-defined "main" function. This function
445// infers an entry point from a user-defined "main" function.527// infers an entry point from a user-defined "main" function.
446StringRef LinkerDriver::findDefaultEntry() {528StringRef LinkerDriver::findDefaultEntry() {
447 assert(Config->Subsystem != IMAGE_SUBSYSTEM_UNKNOWN &&529 assert(config->subsystem != IMAGE_SUBSYSTEM_UNKNOWN &&
448 "must handle /subsystem before calling this");530 "must handle /subsystem before calling this");
449531
450 if (Config->MinGW)532 if (config->mingw)
451 return mangle(Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI533 return mangle(config->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI
452 ? "WinMainCRTStartup"534 ? "WinMainCRTStartup"
453 : "mainCRTStartup");535 : "mainCRTStartup");
454536
455 if (Config->Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {537 if (config->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
456 if (findUnderscoreMangle("wWinMain")) {538 if (findUnderscoreMangle("wWinMain")) {
457 if (!findUnderscoreMangle("WinMain"))539 if (!findUnderscoreMangle("WinMain"))
458 return mangle("wWinMainCRTStartup");540 return mangle("wWinMainCRTStartup");
...@@ -469,44 +551,44 @@ StringRef LinkerDriver::findDefaultEntry() {...@@ -469,44 +551,44 @@ StringRef LinkerDriver::findDefaultEntry() {
469}551}
470552
471WindowsSubsystem LinkerDriver::inferSubsystem() {553WindowsSubsystem LinkerDriver::inferSubsystem() {
472 if (Config->DLL)554 if (config->dll)
473 return IMAGE_SUBSYSTEM_WINDOWS_GUI;555 return IMAGE_SUBSYSTEM_WINDOWS_GUI;
474 if (Config->MinGW)556 if (config->mingw)
475 return IMAGE_SUBSYSTEM_WINDOWS_CUI;557 return IMAGE_SUBSYSTEM_WINDOWS_CUI;
476 // Note that link.exe infers the subsystem from the presence of these558 // Note that link.exe infers the subsystem from the presence of these
477 // functions even if /entry: or /nodefaultlib are passed which causes them559 // functions even if /entry: or /nodefaultlib are passed which causes them
478 // to not be called.560 // to not be called.
479 bool HaveMain = findUnderscoreMangle("main");561 bool haveMain = findUnderscoreMangle("main");
480 bool HaveWMain = findUnderscoreMangle("wmain");562 bool haveWMain = findUnderscoreMangle("wmain");
481 bool HaveWinMain = findUnderscoreMangle("WinMain");563 bool haveWinMain = findUnderscoreMangle("WinMain");
482 bool HaveWWinMain = findUnderscoreMangle("wWinMain");564 bool haveWWinMain = findUnderscoreMangle("wWinMain");
483 if (HaveMain || HaveWMain) {565 if (haveMain || haveWMain) {
484 if (HaveWinMain || HaveWWinMain) {566 if (haveWinMain || haveWWinMain) {
485 warn(std::string("found ") + (HaveMain ? "main" : "wmain") + " and " +567 warn(std::string("found ") + (haveMain ? "main" : "wmain") + " and " +
486 (HaveWinMain ? "WinMain" : "wWinMain") +568 (haveWinMain ? "WinMain" : "wWinMain") +
487 "; defaulting to /subsystem:console");569 "; defaulting to /subsystem:console");
488 }570 }
489 return IMAGE_SUBSYSTEM_WINDOWS_CUI;571 return IMAGE_SUBSYSTEM_WINDOWS_CUI;
490 }572 }
491 if (HaveWinMain || HaveWWinMain)573 if (haveWinMain || haveWWinMain)
492 return IMAGE_SUBSYSTEM_WINDOWS_GUI;574 return IMAGE_SUBSYSTEM_WINDOWS_GUI;
493 return IMAGE_SUBSYSTEM_UNKNOWN;575 return IMAGE_SUBSYSTEM_UNKNOWN;
494}576}
495577
496static uint64_t getDefaultImageBase() {578static uint64_t getDefaultImageBase() {
497 if (Config->is64())579 if (config->is64())
498 return Config->DLL ? 0x180000000 : 0x140000000;580 return config->dll ? 0x180000000 : 0x140000000;
499 return Config->DLL ? 0x10000000 : 0x400000;581 return config->dll ? 0x10000000 : 0x400000;
500}582}
501583
502static std::string createResponseFile(const opt::InputArgList &Args,584static std::string createResponseFile(const opt::InputArgList &args,
503 ArrayRef<StringRef> FilePaths,585 ArrayRef<StringRef> filePaths,
504 ArrayRef<StringRef> SearchPaths) {586 ArrayRef<StringRef> searchPaths) {
505 SmallString<0> Data;587 SmallString<0> data;
506 raw_svector_ostream OS(Data);588 raw_svector_ostream os(data);
507589
508 for (auto *Arg : Args) {590 for (auto *arg : args) {
509 switch (Arg->getOption().getID()) {591 switch (arg->getOption().getID()) {
510 case OPT_linkrepro:592 case OPT_linkrepro:
511 case OPT_INPUT:593 case OPT_INPUT:
512 case OPT_defaultlib:594 case OPT_defaultlib:
...@@ -518,32 +600,37 @@ static std::string createResponseFile(const opt::InputArgList &Args,...@@ -518,32 +600,37 @@ static std::string createResponseFile(const opt::InputArgList &Args,
518 case OPT_manifestinput:600 case OPT_manifestinput:
519 case OPT_manifestuac:601 case OPT_manifestuac:
520 break;602 break;
603 case OPT_implib:
604 case OPT_pdb:
605 case OPT_out:
606 os << arg->getSpelling() << sys::path::filename(arg->getValue()) << "\n";
607 break;
521 default:608 default:
522 OS << toString(*Arg) << "\n";609 os << toString(*arg) << "\n";
523 }610 }
524 }611 }
525612
526 for (StringRef Path : SearchPaths) {613 for (StringRef path : searchPaths) {
527 std::string RelPath = relativeToRoot(Path);614 std::string relPath = relativeToRoot(path);
528 OS << "/libpath:" << quote(RelPath) << "\n";615 os << "/libpath:" << quote(relPath) << "\n";
529 }616 }
530617
531 for (StringRef Path : FilePaths)618 for (StringRef path : filePaths)
532 OS << quote(relativeToRoot(Path)) << "\n";619 os << quote(relativeToRoot(path)) << "\n";
533620
534 return Data.str();621 return data.str();
535}622}
536623
537enum class DebugKind { Unknown, None, Full, FastLink, GHash, Dwarf, Symtab };624enum class DebugKind { Unknown, None, Full, FastLink, GHash, Dwarf, Symtab };
538625
539static DebugKind parseDebugKind(const opt::InputArgList &Args) {626static DebugKind parseDebugKind(const opt::InputArgList &args) {
540 auto *A = Args.getLastArg(OPT_debug, OPT_debug_opt);627 auto *a = args.getLastArg(OPT_debug, OPT_debug_opt);
541 if (!A)628 if (!a)
542 return DebugKind::None;629 return DebugKind::None;
543 if (A->getNumValues() == 0)630 if (a->getNumValues() == 0)
544 return DebugKind::Full;631 return DebugKind::Full;
545632
546 DebugKind Debug = StringSwitch<DebugKind>(A->getValue())633 DebugKind debug = StringSwitch<DebugKind>(a->getValue())
547 .CaseLower("none", DebugKind::None)634 .CaseLower("none", DebugKind::None)
548 .CaseLower("full", DebugKind::Full)635 .CaseLower("full", DebugKind::Full)
549 .CaseLower("fastlink", DebugKind::FastLink)636 .CaseLower("fastlink", DebugKind::FastLink)
...@@ -553,67 +640,68 @@ static DebugKind parseDebugKind(const opt::InputArgList &Args) {...@@ -553,67 +640,68 @@ static DebugKind parseDebugKind(const opt::InputArgList &Args) {
553 .CaseLower("symtab", DebugKind::Symtab)640 .CaseLower("symtab", DebugKind::Symtab)
554 .Default(DebugKind::Unknown);641 .Default(DebugKind::Unknown);
555642
556 if (Debug == DebugKind::FastLink) {643 if (debug == DebugKind::FastLink) {
557 warn("/debug:fastlink unsupported; using /debug:full");644 warn("/debug:fastlink unsupported; using /debug:full");
558 return DebugKind::Full;645 return DebugKind::Full;
559 }646 }
560 if (Debug == DebugKind::Unknown) {647 if (debug == DebugKind::Unknown) {
561 error("/debug: unknown option: " + Twine(A->getValue()));648 error("/debug: unknown option: " + Twine(a->getValue()));
562 return DebugKind::None;649 return DebugKind::None;
563 }650 }
564 return Debug;651 return debug;
565}652}
566653
567static unsigned parseDebugTypes(const opt::InputArgList &Args) {654static unsigned parseDebugTypes(const opt::InputArgList &args) {
568 unsigned DebugTypes = static_cast<unsigned>(DebugType::None);655 unsigned debugTypes = static_cast<unsigned>(DebugType::None);
569656
570 if (auto *A = Args.getLastArg(OPT_debugtype)) {657 if (auto *a = args.getLastArg(OPT_debugtype)) {
571 SmallVector<StringRef, 3> Types;658 SmallVector<StringRef, 3> types;
572 A->getSpelling().split(Types, ',', /*KeepEmpty=*/false);659 StringRef(a->getValue())
660 .split(types, ',', /*MaxSplit=*/-1, /*KeepEmpty=*/false);
573661
574 for (StringRef Type : Types) {662 for (StringRef type : types) {
575 unsigned V = StringSwitch<unsigned>(Type.lower())663 unsigned v = StringSwitch<unsigned>(type.lower())
576 .Case("cv", static_cast<unsigned>(DebugType::CV))664 .Case("cv", static_cast<unsigned>(DebugType::CV))
577 .Case("pdata", static_cast<unsigned>(DebugType::PData))665 .Case("pdata", static_cast<unsigned>(DebugType::PData))
578 .Case("fixup", static_cast<unsigned>(DebugType::Fixup))666 .Case("fixup", static_cast<unsigned>(DebugType::Fixup))
579 .Default(0);667 .Default(0);
580 if (V == 0) {668 if (v == 0) {
581 warn("/debugtype: unknown option: " + Twine(A->getValue()));669 warn("/debugtype: unknown option '" + type + "'");
582 continue;670 continue;
583 }671 }
584 DebugTypes |= V;672 debugTypes |= v;
585 }673 }
586 return DebugTypes;674 return debugTypes;
587 }675 }
588676
589 // Default debug types677 // Default debug types
590 DebugTypes = static_cast<unsigned>(DebugType::CV);678 debugTypes = static_cast<unsigned>(DebugType::CV);
591 if (Args.hasArg(OPT_driver))679 if (args.hasArg(OPT_driver))
592 DebugTypes |= static_cast<unsigned>(DebugType::PData);680 debugTypes |= static_cast<unsigned>(DebugType::PData);
593 if (Args.hasArg(OPT_profile))681 if (args.hasArg(OPT_profile))
594 DebugTypes |= static_cast<unsigned>(DebugType::Fixup);682 debugTypes |= static_cast<unsigned>(DebugType::Fixup);
595683
596 return DebugTypes;684 return debugTypes;
597}685}
598686
599static std::string getMapFile(const opt::InputArgList &Args) {687static std::string getMapFile(const opt::InputArgList &args) {
600 auto *Arg = Args.getLastArg(OPT_lldmap, OPT_lldmap_file);688 auto *arg = args.getLastArg(OPT_lldmap, OPT_lldmap_file);
601 if (!Arg)689 if (!arg)
602 return "";690 return "";
603 if (Arg->getOption().getID() == OPT_lldmap_file)691 if (arg->getOption().getID() == OPT_lldmap_file)
604 return Arg->getValue();692 return arg->getValue();
605693
606 assert(Arg->getOption().getID() == OPT_lldmap);694 assert(arg->getOption().getID() == OPT_lldmap);
607 StringRef OutFile = Config->OutputFile;695 StringRef outFile = config->outputFile;
608 return (OutFile.substr(0, OutFile.rfind('.')) + ".map").str();696 return (outFile.substr(0, outFile.rfind('.')) + ".map").str();
609}697}
610698
611static std::string getImplibPath() {699static std::string getImplibPath() {
612 if (!Config->Implib.empty())700 if (!config->implib.empty())
613 return Config->Implib;701 return config->implib;
614 SmallString<128> Out = StringRef(Config->OutputFile);702 SmallString<128> out = StringRef(config->outputFile);
615 sys::path::replace_extension(Out, ".lib");703 sys::path::replace_extension(out, ".lib");
616 return Out.str();704 return out.str();
617}705}
618706
619//707//
...@@ -624,289 +712,346 @@ static std::string getImplibPath() {...@@ -624,289 +712,346 @@ static std::string getImplibPath() {
624// LINK | {value} | {value}.{.dll/.exe} | {output name}712// LINK | {value} | {value}.{.dll/.exe} | {output name}
625// LIB | {value} | {value}.dll | {output name}.dll713// LIB | {value} | {value}.dll | {output name}.dll
626//714//
627static std::string getImportName(bool AsLib) {715static std::string getImportName(bool asLib) {
628 SmallString<128> Out;716 SmallString<128> out;
629717
630 if (Config->ImportName.empty()) {718 if (config->importName.empty()) {
631 Out.assign(sys::path::filename(Config->OutputFile));719 out.assign(sys::path::filename(config->outputFile));
632 if (AsLib)720 if (asLib)
633 sys::path::replace_extension(Out, ".dll");721 sys::path::replace_extension(out, ".dll");
634 } else {722 } else {
635 Out.assign(Config->ImportName);723 out.assign(config->importName);
636 if (!sys::path::has_extension(Out))724 if (!sys::path::has_extension(out))
637 sys::path::replace_extension(Out,725 sys::path::replace_extension(out,
638 (Config->DLL || AsLib) ? ".dll" : ".exe");726 (config->dll || asLib) ? ".dll" : ".exe");
639 }727 }
640728
641 return Out.str();729 return out.str();
642}730}
643731
644static void createImportLibrary(bool AsLib) {732static void createImportLibrary(bool asLib) {
645 std::vector<COFFShortExport> Exports;733 std::vector<COFFShortExport> exports;
646 for (Export &E1 : Config->Exports) {734 for (Export &e1 : config->exports) {
647 COFFShortExport E2;735 COFFShortExport e2;
648 E2.Name = E1.Name;736 e2.Name = e1.name;
649 E2.SymbolName = E1.SymbolName;737 e2.SymbolName = e1.symbolName;
650 E2.ExtName = E1.ExtName;738 e2.ExtName = e1.extName;
651 E2.Ordinal = E1.Ordinal;739 e2.Ordinal = e1.ordinal;
652 E2.Noname = E1.Noname;740 e2.Noname = e1.noname;
653 E2.Data = E1.Data;741 e2.Data = e1.data;
654 E2.Private = E1.Private;742 e2.Private = e1.isPrivate;
655 E2.Constant = E1.Constant;743 e2.Constant = e1.constant;
656 Exports.push_back(E2);744 exports.push_back(e2);
657 }745 }
658746
659 auto HandleError = [](Error &&E) {747 auto handleError = [](Error &&e) {
660 handleAllErrors(std::move(E),748 handleAllErrors(std::move(e),
661 [](ErrorInfoBase &EIB) { error(EIB.message()); });749 [](ErrorInfoBase &eib) { error(eib.message()); });
662 };750 };
663 std::string LibName = getImportName(AsLib);751 std::string libName = getImportName(asLib);
664 std::string Path = getImplibPath();752 std::string path = getImplibPath();
665753
666 if (!Config->Incremental) {754 if (!config->incremental) {
667 HandleError(writeImportLibrary(LibName, Path, Exports, Config->Machine,755 handleError(writeImportLibrary(libName, path, exports, config->machine,
668 Config->MinGW));756 config->mingw));
669 return;757 return;
670 }758 }
671759
672 // If the import library already exists, replace it only if the contents760 // If the import library already exists, replace it only if the contents
673 // have changed.761 // have changed.
674 ErrorOr<std::unique_ptr<MemoryBuffer>> OldBuf = MemoryBuffer::getFile(762 ErrorOr<std::unique_ptr<MemoryBuffer>> oldBuf = MemoryBuffer::getFile(
675 Path, /*FileSize*/ -1, /*RequiresNullTerminator*/ false);763 path, /*FileSize*/ -1, /*RequiresNullTerminator*/ false);
676 if (!OldBuf) {764 if (!oldBuf) {
677 HandleError(writeImportLibrary(LibName, Path, Exports, Config->Machine,765 handleError(writeImportLibrary(libName, path, exports, config->machine,
678 Config->MinGW));766 config->mingw));
679 return;767 return;
680 }768 }
681769
682 SmallString<128> TmpName;770 SmallString<128> tmpName;
683 if (std::error_code EC =771 if (std::error_code ec =
684 sys::fs::createUniqueFile(Path + ".tmp-%%%%%%%%.lib", TmpName))772 sys::fs::createUniqueFile(path + ".tmp-%%%%%%%%.lib", tmpName))
685 fatal("cannot create temporary file for import library " + Path + ": " +773 fatal("cannot create temporary file for import library " + path + ": " +
686 EC.message());774 ec.message());
687775
688 if (Error E = writeImportLibrary(LibName, TmpName, Exports, Config->Machine,776 if (Error e = writeImportLibrary(libName, tmpName, exports, config->machine,
689 Config->MinGW)) {777 config->mingw)) {
690 HandleError(std::move(E));778 handleError(std::move(e));
691 return;779 return;
692 }780 }
693781
694 std::unique_ptr<MemoryBuffer> NewBuf = check(MemoryBuffer::getFile(782 std::unique_ptr<MemoryBuffer> newBuf = check(MemoryBuffer::getFile(
695 TmpName, /*FileSize*/ -1, /*RequiresNullTerminator*/ false));783 tmpName, /*FileSize*/ -1, /*RequiresNullTerminator*/ false));
696 if ((*OldBuf)->getBuffer() != NewBuf->getBuffer()) {784 if ((*oldBuf)->getBuffer() != newBuf->getBuffer()) {
697 OldBuf->reset();785 oldBuf->reset();
698 HandleError(errorCodeToError(sys::fs::rename(TmpName, Path)));786 handleError(errorCodeToError(sys::fs::rename(tmpName, path)));
699 } else {787 } else {
700 sys::fs::remove(TmpName);788 sys::fs::remove(tmpName);
701 }789 }
702}790}
703791
704static void parseModuleDefs(StringRef Path) {792static void parseModuleDefs(StringRef path) {
705 std::unique_ptr<MemoryBuffer> MB = CHECK(793 std::unique_ptr<MemoryBuffer> mb = CHECK(
706 MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path);794 MemoryBuffer::getFile(path, -1, false, true), "could not open " + path);
707 COFFModuleDefinition M = check(parseCOFFModuleDefinition(795 COFFModuleDefinition m = check(parseCOFFModuleDefinition(
708 MB->getMemBufferRef(), Config->Machine, Config->MinGW));796 mb->getMemBufferRef(), config->machine, config->mingw));
709797
710 if (Config->OutputFile.empty())798 if (config->outputFile.empty())
711 Config->OutputFile = Saver.save(M.OutputFile);799 config->outputFile = saver.save(m.OutputFile);
712 Config->ImportName = Saver.save(M.ImportName);800 config->importName = saver.save(m.ImportName);
713 if (M.ImageBase)801 if (m.ImageBase)
714 Config->ImageBase = M.ImageBase;802 config->imageBase = m.ImageBase;
715 if (M.StackReserve)803 if (m.StackReserve)
716 Config->StackReserve = M.StackReserve;804 config->stackReserve = m.StackReserve;
717 if (M.StackCommit)805 if (m.StackCommit)
718 Config->StackCommit = M.StackCommit;806 config->stackCommit = m.StackCommit;
719 if (M.HeapReserve)807 if (m.HeapReserve)
720 Config->HeapReserve = M.HeapReserve;808 config->heapReserve = m.HeapReserve;
721 if (M.HeapCommit)809 if (m.HeapCommit)
722 Config->HeapCommit = M.HeapCommit;810 config->heapCommit = m.HeapCommit;
723 if (M.MajorImageVersion)811 if (m.MajorImageVersion)
724 Config->MajorImageVersion = M.MajorImageVersion;812 config->majorImageVersion = m.MajorImageVersion;
725 if (M.MinorImageVersion)813 if (m.MinorImageVersion)
726 Config->MinorImageVersion = M.MinorImageVersion;814 config->minorImageVersion = m.MinorImageVersion;
727 if (M.MajorOSVersion)815 if (m.MajorOSVersion)
728 Config->MajorOSVersion = M.MajorOSVersion;816 config->majorOSVersion = m.MajorOSVersion;
729 if (M.MinorOSVersion)817 if (m.MinorOSVersion)
730 Config->MinorOSVersion = M.MinorOSVersion;818 config->minorOSVersion = m.MinorOSVersion;
731819
732 for (COFFShortExport E1 : M.Exports) {820 for (COFFShortExport e1 : m.Exports) {
733 Export E2;821 Export e2;
734 // In simple cases, only Name is set. Renamed exports are parsed822 // In simple cases, only Name is set. Renamed exports are parsed
735 // and set as "ExtName = Name". If Name has the form "OtherDll.Func",823 // and set as "ExtName = Name". If Name has the form "OtherDll.Func",
736 // it shouldn't be a normal exported function but a forward to another824 // it shouldn't be a normal exported function but a forward to another
737 // DLL instead. This is supported by both MS and GNU linkers.825 // DLL instead. This is supported by both MS and GNU linkers.
738 if (E1.ExtName != E1.Name && StringRef(E1.Name).contains('.')) {826 if (e1.ExtName != e1.Name && StringRef(e1.Name).contains('.')) {
739 E2.Name = Saver.save(E1.ExtName);827 e2.name = saver.save(e1.ExtName);
740 E2.ForwardTo = Saver.save(E1.Name);828 e2.forwardTo = saver.save(e1.Name);
741 Config->Exports.push_back(E2);829 config->exports.push_back(e2);
742 continue;830 continue;
743 }831 }
744 E2.Name = Saver.save(E1.Name);832 e2.name = saver.save(e1.Name);
745 E2.ExtName = Saver.save(E1.ExtName);833 e2.extName = saver.save(e1.ExtName);
746 E2.Ordinal = E1.Ordinal;834 e2.ordinal = e1.Ordinal;
747 E2.Noname = E1.Noname;835 e2.noname = e1.Noname;
748 E2.Data = E1.Data;836 e2.data = e1.Data;
749 E2.Private = E1.Private;837 e2.isPrivate = e1.Private;
750 E2.Constant = E1.Constant;838 e2.constant = e1.Constant;
751 Config->Exports.push_back(E2);839 config->exports.push_back(e2);
752 }840 }
753}841}
754842
755void LinkerDriver::enqueueTask(std::function<void()> Task) {843void LinkerDriver::enqueueTask(std::function<void()> task) {
756 TaskQueue.push_back(std::move(Task));844 taskQueue.push_back(std::move(task));
757}845}
758846
759bool LinkerDriver::run() {847bool LinkerDriver::run() {
760 ScopedTimer T(InputFileTimer);848 ScopedTimer t(inputFileTimer);
761849
762 bool DidWork = !TaskQueue.empty();850 bool didWork = !taskQueue.empty();
763 while (!TaskQueue.empty()) {851 while (!taskQueue.empty()) {
764 TaskQueue.front()();852 taskQueue.front()();
765 TaskQueue.pop_front();853 taskQueue.pop_front();
766 }854 }
767 return DidWork;855 return didWork;
768}856}
769857
770// Parse an /order file. If an option is given, the linker places858// Parse an /order file. If an option is given, the linker places
771// COMDAT sections in the same order as their names appear in the859// COMDAT sections in the same order as their names appear in the
772// given file.860// given file.
773static void parseOrderFile(StringRef Arg) {861static void parseOrderFile(StringRef arg) {
774 // For some reason, the MSVC linker requires a filename to be862 // For some reason, the MSVC linker requires a filename to be
775 // preceded by "@".863 // preceded by "@".
776 if (!Arg.startswith("@")) {864 if (!arg.startswith("@")) {
777 error("malformed /order option: '@' missing");865 error("malformed /order option: '@' missing");
778 return;866 return;
779 }867 }
780868
781 // Get a list of all comdat sections for error checking.869 // Get a list of all comdat sections for error checking.
782 DenseSet<StringRef> Set;870 DenseSet<StringRef> set;
783 for (Chunk *C : Symtab->getChunks())871 for (Chunk *c : symtab->getChunks())
784 if (auto *Sec = dyn_cast<SectionChunk>(C))872 if (auto *sec = dyn_cast<SectionChunk>(c))
785 if (Sec->Sym)873 if (sec->sym)
786 Set.insert(Sec->Sym->getName());874 set.insert(sec->sym->getName());
787875
788 // Open a file.876 // Open a file.
789 StringRef Path = Arg.substr(1);877 StringRef path = arg.substr(1);
790 std::unique_ptr<MemoryBuffer> MB = CHECK(878 std::unique_ptr<MemoryBuffer> mb = CHECK(
791 MemoryBuffer::getFile(Path, -1, false, true), "could not open " + Path);879 MemoryBuffer::getFile(path, -1, false, true), "could not open " + path);
792880
793 // Parse a file. An order file contains one symbol per line.881 // Parse a file. An order file contains one symbol per line.
794 // All symbols that were not present in a given order file are882 // All symbols that were not present in a given order file are
795 // considered to have the lowest priority 0 and are placed at883 // considered to have the lowest priority 0 and are placed at
796 // end of an output section.884 // end of an output section.
797 for (std::string S : args::getLines(MB->getMemBufferRef())) {885 for (std::string s : args::getLines(mb->getMemBufferRef())) {
798 if (Config->Machine == I386 && !isDecorated(S))886 if (config->machine == I386 && !isDecorated(s))
799 S = "_" + S;887 s = "_" + s;
800888
801 if (Set.count(S) == 0) {889 if (set.count(s) == 0) {
802 if (Config->WarnMissingOrderSymbol)890 if (config->warnMissingOrderSymbol)
803 warn("/order:" + Arg + ": missing symbol: " + S + " [LNK4037]");891 warn("/order:" + arg + ": missing symbol: " + s + " [LNK4037]");
804 }892 }
805 else893 else
806 Config->Order[S] = INT_MIN + Config->Order.size();894 config->order[s] = INT_MIN + config->order.size();
807 }895 }
808}896}
809897
810static void markAddrsig(Symbol *S) {898static void markAddrsig(Symbol *s) {
811 if (auto *D = dyn_cast_or_null<Defined>(S))899 if (auto *d = dyn_cast_or_null<Defined>(s))
812 if (Chunk *C = D->getChunk())900 if (SectionChunk *c = dyn_cast_or_null<SectionChunk>(d->getChunk()))
813 C->KeepUnique = true;901 c->keepUnique = true;
814}902}
815903
816static void findKeepUniqueSections() {904static void findKeepUniqueSections() {
817 // Exported symbols could be address-significant in other executables or DSOs,905 // Exported symbols could be address-significant in other executables or DSOs,
818 // so we conservatively mark them as address-significant.906 // so we conservatively mark them as address-significant.
819 for (Export &R : Config->Exports)907 for (Export &r : config->exports)
820 markAddrsig(R.Sym);908 markAddrsig(r.sym);
821909
822 // Visit the address-significance table in each object file and mark each910 // Visit the address-significance table in each object file and mark each
823 // referenced symbol as address-significant.911 // referenced symbol as address-significant.
824 for (ObjFile *Obj : ObjFile::Instances) {912 for (ObjFile *obj : ObjFile::instances) {
825 ArrayRef<Symbol *> Syms = Obj->getSymbols();913 ArrayRef<Symbol *> syms = obj->getSymbols();
826 if (Obj->AddrsigSec) {914 if (obj->addrsigSec) {
827 ArrayRef<uint8_t> Contents;915 ArrayRef<uint8_t> contents;
828 Obj->getCOFFObj()->getSectionContents(Obj->AddrsigSec, Contents);916 cantFail(
829 const uint8_t *Cur = Contents.begin();917 obj->getCOFFObj()->getSectionContents(obj->addrsigSec, contents));
830 while (Cur != Contents.end()) {918 const uint8_t *cur = contents.begin();
831 unsigned Size;919 while (cur != contents.end()) {
832 const char *Err;920 unsigned size;
833 uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err);921 const char *err;
834 if (Err)922 uint64_t symIndex = decodeULEB128(cur, &size, contents.end(), &err);
835 fatal(toString(Obj) + ": could not decode addrsig section: " + Err);923 if (err)
836 if (SymIndex >= Syms.size())924 fatal(toString(obj) + ": could not decode addrsig section: " + err);
837 fatal(toString(Obj) + ": invalid symbol index in addrsig section");925 if (symIndex >= syms.size())
838 markAddrsig(Syms[SymIndex]);926 fatal(toString(obj) + ": invalid symbol index in addrsig section");
839 Cur += Size;927 markAddrsig(syms[symIndex]);
928 cur += size;
840 }929 }
841 } else {930 } else {
842 // If an object file does not have an address-significance table,931 // If an object file does not have an address-significance table,
843 // conservatively mark all of its symbols as address-significant.932 // conservatively mark all of its symbols as address-significant.
844 for (Symbol *S : Syms)933 for (Symbol *s : syms)
845 markAddrsig(S);934 markAddrsig(s);
846 }935 }
847 }936 }
848}937}
849938
850// link.exe replaces each %foo% in AltPath with the contents of environment939// 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 basename940// 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 output941// of pdb's output path) and _EXT (expands to the extension of the output
853// binary).942// binary).
854// lld only supports %_PDB% and %_EXT% and warns on references to all other env943// lld only supports %_PDB% and %_EXT% and warns on references to all other env
855// vars.944// vars.
856static void parsePDBAltPath(StringRef AltPath) {945static void parsePDBAltPath(StringRef altPath) {
857 SmallString<128> Buf;946 SmallString<128> buf;
858 StringRef PDBBasename =947 StringRef pdbBasename =
859 sys::path::filename(Config->PDBPath, sys::path::Style::windows);948 sys::path::filename(config->pdbPath, sys::path::Style::windows);
860 StringRef BinaryExtension =949 StringRef binaryExtension =
861 sys::path::extension(Config->OutputFile, sys::path::Style::windows);950 sys::path::extension(config->outputFile, sys::path::Style::windows);
862 if (!BinaryExtension.empty())951 if (!binaryExtension.empty())
863 BinaryExtension = BinaryExtension.substr(1); // %_EXT% does not include '.'.952 binaryExtension = binaryExtension.substr(1); // %_EXT% does not include '.'.
864953
865 // Invariant:954 // Invariant:
866 // +--------- Cursor ('a...' might be the empty string).955 // +--------- cursor ('a...' might be the empty string).
867 // | +----- FirstMark956 // | +----- firstMark
868 // | | +- SecondMark957 // | | +- secondMark
869 // v v v958 // v v v
870 // a...%...%...959 // a...%...%...
871 size_t Cursor = 0;960 size_t cursor = 0;
872 while (Cursor < AltPath.size()) {961 while (cursor < altPath.size()) {
873 size_t FirstMark, SecondMark;962 size_t firstMark, secondMark;
874 if ((FirstMark = AltPath.find('%', Cursor)) == StringRef::npos ||963 if ((firstMark = altPath.find('%', cursor)) == StringRef::npos ||
875 (SecondMark = AltPath.find('%', FirstMark + 1)) == StringRef::npos) {964 (secondMark = altPath.find('%', firstMark + 1)) == StringRef::npos) {
876 // Didn't find another full fragment, treat rest of string as literal.965 // Didn't find another full fragment, treat rest of string as literal.
877 Buf.append(AltPath.substr(Cursor));966 buf.append(altPath.substr(cursor));
878 break;967 break;
879 }968 }
880969
881 // Found a full fragment. Append text in front of first %, and interpret970 // Found a full fragment. Append text in front of first %, and interpret
882 // text between first and second % as variable name.971 // text between first and second % as variable name.
883 Buf.append(AltPath.substr(Cursor, FirstMark - Cursor));972 buf.append(altPath.substr(cursor, firstMark - cursor));
884 StringRef Var = AltPath.substr(FirstMark, SecondMark - FirstMark + 1);973 StringRef var = altPath.substr(firstMark, secondMark - firstMark + 1);
885 if (Var.equals_lower("%_pdb%"))974 if (var.equals_lower("%_pdb%"))
886 Buf.append(PDBBasename);975 buf.append(pdbBasename);
887 else if (Var.equals_lower("%_ext%"))976 else if (var.equals_lower("%_ext%"))
888 Buf.append(BinaryExtension);977 buf.append(binaryExtension);
889 else {978 else {
890 warn("only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping " +979 warn("only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping " +
891 Var + " as literal");980 var + " as literal");
892 Buf.append(Var);981 buf.append(var);
893 }982 }
894983
895 Cursor = SecondMark + 1;984 cursor = secondMark + 1;
896 }985 }
897986
898 Config->PDBAltPath = Buf;987 config->pdbAltPath = buf;
899}988}
900989
901void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {990/// Check that at most one resource obj file was used.
902 // If the first command line argument is "/lib", link.exe acts like lib.exe.991/// Call after ObjFile::Instances is complete.
903 // We call our own implementation of lib.exe that understands bitcode files.992static void diagnoseMultipleResourceObjFiles() {
904 if (ArgsArr.size() > 1 && StringRef(ArgsArr[1]).equals_lower("/lib")) {993 // The .rsrc$01 section in a resource obj file contains a tree description
905 if (llvm::libDriverMain(ArgsArr.slice(1)) != 0)994 // of resources. Merging multiple resource obj files would require merging
906 fatal("lib failed");995 // the trees instead of using usual linker section merging semantics.
996 // Since link.exe disallows linking more than one resource obj file with
997 // LNK4078, mirror that. The normal use of resource files is to give the
998 // linker many .res files, which are then converted to a single resource obj
999 // file internally, so this is not a big restriction in practice.
1000 ObjFile *resourceObjFile = nullptr;
1001 for (ObjFile *f : ObjFile::instances) {
1002 if (!f->isResourceObjFile)
1003 continue;
1004
1005 if (!resourceObjFile) {
1006 resourceObjFile = f;
1007 continue;
1008 }
1009
1010 error(toString(f) +
1011 ": more than one resource obj file not allowed, already got " +
1012 toString(resourceObjFile));
1013 }
1014}
1015
1016// In MinGW, if no symbols are chosen to be exported, then all symbols are
1017// automatically exported by default. This behavior can be forced by the
1018// -export-all-symbols option, so that it happens even when exports are
1019// explicitly specified. The automatic behavior can be disabled using the
1020// -exclude-all-symbols option, so that lld-link behaves like link.exe rather
1021// than MinGW in the case that nothing is explicitly exported.
1022void LinkerDriver::maybeExportMinGWSymbols(const opt::InputArgList &args) {
1023 if (!config->dll)
907 return;1024 return;
1025
1026 if (!args.hasArg(OPT_export_all_symbols)) {
1027 if (!config->exports.empty())
1028 return;
1029 if (args.hasArg(OPT_exclude_all_symbols))
1030 return;
908 }1031 }
9091032
1033 AutoExporter exporter;
1034
1035 for (auto *arg : args.filtered(OPT_wholearchive_file))
1036 if (Optional<StringRef> path = doFindFile(arg->getValue()))
1037 exporter.addWholeArchive(*path);
1038
1039 symtab->forEachSymbol([&](Symbol *s) {
1040 auto *def = dyn_cast<Defined>(s);
1041 if (!exporter.shouldExport(def))
1042 return;
1043
1044 Export e;
1045 e.name = def->getName();
1046 e.sym = def;
1047 if (Chunk *c = def->getChunk())
1048 if (!(c->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
1049 e.data = true;
1050 config->exports.push_back(e);
1051 });
1052}
1053
1054void LinkerDriver::link(ArrayRef<const char *> argsArr) {
910 // Needed for LTO.1055 // Needed for LTO.
911 InitializeAllTargetInfos();1056 InitializeAllTargetInfos();
912 InitializeAllTargets();1057 InitializeAllTargets();
...@@ -914,279 +1059,308 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {...@@ -914,279 +1059,308 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
914 InitializeAllAsmParsers();1059 InitializeAllAsmParsers();
915 InitializeAllAsmPrinters();1060 InitializeAllAsmPrinters();
9161061
1062 // If the first command line argument is "/lib", link.exe acts like lib.exe.
1063 // We call our own implementation of lib.exe that understands bitcode files.
1064 if (argsArr.size() > 1 && StringRef(argsArr[1]).equals_lower("/lib")) {
1065 if (llvm::libDriverMain(argsArr.slice(1)) != 0)
1066 fatal("lib failed");
1067 return;
1068 }
1069
917 // Parse command line options.1070 // Parse command line options.
918 ArgParser Parser;1071 ArgParser parser;
919 opt::InputArgList Args = Parser.parseLINK(ArgsArr);1072 opt::InputArgList args = parser.parseLINK(argsArr);
9201073
921 // Parse and evaluate -mllvm options.1074 // Parse and evaluate -mllvm options.
922 std::vector<const char *> V;1075 std::vector<const char *> v;
923 V.push_back("lld-link (LLVM option parsing)");1076 v.push_back("lld-link (LLVM option parsing)");
924 for (auto *Arg : Args.filtered(OPT_mllvm))1077 for (auto *arg : args.filtered(OPT_mllvm))
925 V.push_back(Arg->getValue());1078 v.push_back(arg->getValue());
926 cl::ParseCommandLineOptions(V.size(), V.data());1079 cl::ParseCommandLineOptions(v.size(), v.data());
9271080
928 // Handle /errorlimit early, because error() depends on it.1081 // Handle /errorlimit early, because error() depends on it.
929 if (auto *Arg = Args.getLastArg(OPT_errorlimit)) {1082 if (auto *arg = args.getLastArg(OPT_errorlimit)) {
930 int N = 20;1083 int n = 20;
931 StringRef S = Arg->getValue();1084 StringRef s = arg->getValue();
932 if (S.getAsInteger(10, N))1085 if (s.getAsInteger(10, n))
933 error(Arg->getSpelling() + " number expected, but got " + S);1086 error(arg->getSpelling() + " number expected, but got " + s);
934 errorHandler().ErrorLimit = N;1087 errorHandler().errorLimit = n;
935 }1088 }
9361089
937 // Handle /help1090 // Handle /help
938 if (Args.hasArg(OPT_help)) {1091 if (args.hasArg(OPT_help)) {
939 printHelp(ArgsArr[0]);1092 printHelp(argsArr[0]);
940 return;1093 return;
941 }1094 }
9421095
943 if (Args.hasArg(OPT_show_timing))1096 lld::threadsEnabled = args.hasFlag(OPT_threads, OPT_threads_no, true);
944 Config->ShowTiming = true;1097
1098 if (args.hasArg(OPT_show_timing))
1099 config->showTiming = true;
9451100
946 ScopedTimer T(Timer::root());1101 config->showSummary = args.hasArg(OPT_summary);
1102
1103 ScopedTimer t(Timer::root());
947 // Handle --version, which is an lld extension. This option is a bit odd1104 // Handle --version, which is an lld extension. This option is a bit odd
948 // because it doesn't start with "/", but we deliberately chose "--" to1105 // because it doesn't start with "/", but we deliberately chose "--" to
949 // avoid conflict with /version and for compatibility with clang-cl.1106 // avoid conflict with /version and for compatibility with clang-cl.
950 if (Args.hasArg(OPT_dash_dash_version)) {1107 if (args.hasArg(OPT_dash_dash_version)) {
951 outs() << getLLDVersion() << "\n";1108 outs() << getLLDVersion() << "\n";
952 return;1109 return;
953 }1110 }
9541111
955 // Handle /lldmingw early, since it can potentially affect how other1112 // Handle /lldmingw early, since it can potentially affect how other
956 // options are handled.1113 // options are handled.
957 Config->MinGW = Args.hasArg(OPT_lldmingw);1114 config->mingw = args.hasArg(OPT_lldmingw);
9581115
959 if (auto *Arg = Args.getLastArg(OPT_linkrepro)) {1116 if (auto *arg = args.getLastArg(OPT_linkrepro)) {
960 SmallString<64> Path = StringRef(Arg->getValue());1117 SmallString<64> path = StringRef(arg->getValue());
961 sys::path::append(Path, "repro.tar");1118 sys::path::append(path, "repro.tar");
9621119
963 Expected<std::unique_ptr<TarWriter>> ErrOrWriter =1120 Expected<std::unique_ptr<TarWriter>> errOrWriter =
964 TarWriter::create(Path, "repro");1121 TarWriter::create(path, "repro");
9651122
966 if (ErrOrWriter) {1123 if (errOrWriter) {
967 Tar = std::move(*ErrOrWriter);1124 tar = std::move(*errOrWriter);
968 } else {1125 } else {
969 error("/linkrepro: failed to open " + Path + ": " +1126 error("/linkrepro: failed to open " + path + ": " +
970 toString(ErrOrWriter.takeError()));1127 toString(errOrWriter.takeError()));
971 }1128 }
972 }1129 }
9731130
974 if (!Args.hasArg(OPT_INPUT)) {1131 if (!args.hasArg(OPT_INPUT)) {
975 if (Args.hasArg(OPT_deffile))1132 if (args.hasArg(OPT_deffile))
976 Config->NoEntry = true;1133 config->noEntry = true;
977 else1134 else
978 fatal("no input files");1135 fatal("no input files");
979 }1136 }
9801137
981 // Construct search path list.1138 // Construct search path list.
982 SearchPaths.push_back("");1139 searchPaths.push_back("");
983 for (auto *Arg : Args.filtered(OPT_libpath))1140 for (auto *arg : args.filtered(OPT_libpath))
984 SearchPaths.push_back(Arg->getValue());1141 searchPaths.push_back(arg->getValue());
985 addLibSearchPaths();1142 addLibSearchPaths();
9861143
987 // Handle /ignore1144 // Handle /ignore
988 for (auto *Arg : Args.filtered(OPT_ignore)) {1145 for (auto *arg : args.filtered(OPT_ignore)) {
989 SmallVector<StringRef, 8> Vec;1146 SmallVector<StringRef, 8> vec;
990 StringRef(Arg->getValue()).split(Vec, ',');1147 StringRef(arg->getValue()).split(vec, ',');
991 for (StringRef S : Vec) {1148 for (StringRef s : vec) {
992 if (S == "4037")1149 if (s == "4037")
993 Config->WarnMissingOrderSymbol = false;1150 config->warnMissingOrderSymbol = false;
994 else if (S == "4099")1151 else if (s == "4099")
995 Config->WarnDebugInfoUnusable = false;1152 config->warnDebugInfoUnusable = false;
996 else if (S == "4217")1153 else if (s == "4217")
997 Config->WarnLocallyDefinedImported = false;1154 config->warnLocallyDefinedImported = false;
998 // Other warning numbers are ignored.1155 // Other warning numbers are ignored.
999 }1156 }
1000 }1157 }
10011158
1002 // Handle /out1159 // Handle /out
1003 if (auto *Arg = Args.getLastArg(OPT_out))1160 if (auto *arg = args.getLastArg(OPT_out))
1004 Config->OutputFile = Arg->getValue();1161 config->outputFile = arg->getValue();
10051162
1006 // Handle /verbose1163 // Handle /verbose
1007 if (Args.hasArg(OPT_verbose))1164 if (args.hasArg(OPT_verbose))
1008 Config->Verbose = true;1165 config->verbose = true;
1009 errorHandler().Verbose = Config->Verbose;1166 errorHandler().verbose = config->verbose;
10101167
1011 // Handle /force or /force:unresolved1168 // Handle /force or /force:unresolved
1012 if (Args.hasArg(OPT_force, OPT_force_unresolved))1169 if (args.hasArg(OPT_force, OPT_force_unresolved))
1013 Config->ForceUnresolved = true;1170 config->forceUnresolved = true;
10141171
1015 // Handle /force or /force:multiple1172 // Handle /force or /force:multiple
1016 if (Args.hasArg(OPT_force, OPT_force_multiple))1173 if (args.hasArg(OPT_force, OPT_force_multiple))
1017 Config->ForceMultiple = true;1174 config->forceMultiple = true;
1175
1176 // Handle /force or /force:multipleres
1177 if (args.hasArg(OPT_force, OPT_force_multipleres))
1178 config->forceMultipleRes = true;
10181179
1019 // Handle /debug1180 // Handle /debug
1020 DebugKind Debug = parseDebugKind(Args);1181 DebugKind debug = parseDebugKind(args);
1021 if (Debug == DebugKind::Full || Debug == DebugKind::Dwarf ||1182 if (debug == DebugKind::Full || debug == DebugKind::Dwarf ||
1022 Debug == DebugKind::GHash) {1183 debug == DebugKind::GHash) {
1023 Config->Debug = true;1184 config->debug = true;
1024 Config->Incremental = true;1185 config->incremental = true;
1025 }1186 }
10261187
1188 // Handle /demangle
1189 config->demangle = args.hasFlag(OPT_demangle, OPT_demangle_no);
1190
1027 // Handle /debugtype1191 // Handle /debugtype
1028 Config->DebugTypes = parseDebugTypes(Args);1192 config->debugTypes = parseDebugTypes(args);
10291193
1030 // Handle /pdb1194 // Handle /pdb
1031 bool ShouldCreatePDB =1195 bool shouldCreatePDB =
1032 (Debug == DebugKind::Full || Debug == DebugKind::GHash);1196 (debug == DebugKind::Full || debug == DebugKind::GHash);
1033 if (ShouldCreatePDB) {1197 if (shouldCreatePDB) {
1034 if (auto *Arg = Args.getLastArg(OPT_pdb))1198 if (auto *arg = args.getLastArg(OPT_pdb))
1035 Config->PDBPath = Arg->getValue();1199 config->pdbPath = arg->getValue();
1036 if (auto *Arg = Args.getLastArg(OPT_pdbaltpath))1200 if (auto *arg = args.getLastArg(OPT_pdbaltpath))
1037 Config->PDBAltPath = Arg->getValue();1201 config->pdbAltPath = arg->getValue();
1038 if (Args.hasArg(OPT_natvis))1202 if (args.hasArg(OPT_natvis))
1039 Config->NatvisFiles = Args.getAllArgValues(OPT_natvis);1203 config->natvisFiles = args.getAllArgValues(OPT_natvis);
10401204
1041 if (auto *Arg = Args.getLastArg(OPT_pdb_source_path))1205 if (auto *arg = args.getLastArg(OPT_pdb_source_path))
1042 Config->PDBSourcePath = Arg->getValue();1206 config->pdbSourcePath = arg->getValue();
1043 }1207 }
10441208
1045 // Handle /noentry1209 // Handle /noentry
1046 if (Args.hasArg(OPT_noentry)) {1210 if (args.hasArg(OPT_noentry)) {
1047 if (Args.hasArg(OPT_dll))1211 if (args.hasArg(OPT_dll))
1048 Config->NoEntry = true;1212 config->noEntry = true;
1049 else1213 else
1050 error("/noentry must be specified with /dll");1214 error("/noentry must be specified with /dll");
1051 }1215 }
10521216
1053 // Handle /dll1217 // Handle /dll
1054 if (Args.hasArg(OPT_dll)) {1218 if (args.hasArg(OPT_dll)) {
1055 Config->DLL = true;1219 config->dll = true;
1056 Config->ManifestID = 2;1220 config->manifestID = 2;
1057 }1221 }
10581222
1059 // Handle /dynamicbase and /fixed. We can't use hasFlag for /dynamicbase1223 // Handle /dynamicbase and /fixed. We can't use hasFlag for /dynamicbase
1060 // because we need to explicitly check whether that option or its inverse was1224 // because we need to explicitly check whether that option or its inverse was
1061 // present in the argument list in order to handle /fixed.1225 // present in the argument list in order to handle /fixed.
1062 auto *DynamicBaseArg = Args.getLastArg(OPT_dynamicbase, OPT_dynamicbase_no);1226 auto *dynamicBaseArg = args.getLastArg(OPT_dynamicbase, OPT_dynamicbase_no);
1063 if (DynamicBaseArg &&1227 if (dynamicBaseArg &&
1064 DynamicBaseArg->getOption().getID() == OPT_dynamicbase_no)1228 dynamicBaseArg->getOption().getID() == OPT_dynamicbase_no)
1065 Config->DynamicBase = false;1229 config->dynamicBase = false;
10661230
1067 // MSDN claims "/FIXED:NO is the default setting for a DLL, and /FIXED is the1231 // MSDN claims "/FIXED:NO is the default setting for a DLL, and /FIXED is the
1068 // default setting for any other project type.", but link.exe defaults to1232 // default setting for any other project type.", but link.exe defaults to
1069 // /FIXED:NO for exe outputs as well. Match behavior, not docs.1233 // /FIXED:NO for exe outputs as well. Match behavior, not docs.
1070 bool Fixed = Args.hasFlag(OPT_fixed, OPT_fixed_no, false);1234 bool fixed = args.hasFlag(OPT_fixed, OPT_fixed_no, false);
1071 if (Fixed) {1235 if (fixed) {
1072 if (DynamicBaseArg &&1236 if (dynamicBaseArg &&
1073 DynamicBaseArg->getOption().getID() == OPT_dynamicbase) {1237 dynamicBaseArg->getOption().getID() == OPT_dynamicbase) {
1074 error("/fixed must not be specified with /dynamicbase");1238 error("/fixed must not be specified with /dynamicbase");
1075 } else {1239 } else {
1076 Config->Relocatable = false;1240 config->relocatable = false;
1077 Config->DynamicBase = false;1241 config->dynamicBase = false;
1078 }1242 }
1079 }1243 }
10801244
1081 // Handle /appcontainer1245 // Handle /appcontainer
1082 Config->AppContainer =1246 config->appContainer =
1083 Args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false);1247 args.hasFlag(OPT_appcontainer, OPT_appcontainer_no, false);
10841248
1085 // Handle /machine1249 // Handle /machine
1086 if (auto *Arg = Args.getLastArg(OPT_machine))1250 if (auto *arg = args.getLastArg(OPT_machine)) {
1087 Config->Machine = getMachineType(Arg->getValue());1251 config->machine = getMachineType(arg->getValue());
1252 if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN)
1253 fatal(Twine("unknown /machine argument: ") + arg->getValue());
1254 }
10881255
1089 // Handle /nodefaultlib:<filename>1256 // Handle /nodefaultlib:<filename>
1090 for (auto *Arg : Args.filtered(OPT_nodefaultlib))1257 for (auto *arg : args.filtered(OPT_nodefaultlib))
1091 Config->NoDefaultLibs.insert(doFindLib(Arg->getValue()));1258 config->noDefaultLibs.insert(doFindLib(arg->getValue()).lower());
10921259
1093 // Handle /nodefaultlib1260 // Handle /nodefaultlib
1094 if (Args.hasArg(OPT_nodefaultlib_all))1261 if (args.hasArg(OPT_nodefaultlib_all))
1095 Config->NoDefaultLibAll = true;1262 config->noDefaultLibAll = true;
10961263
1097 // Handle /base1264 // Handle /base
1098 if (auto *Arg = Args.getLastArg(OPT_base))1265 if (auto *arg = args.getLastArg(OPT_base))
1099 parseNumbers(Arg->getValue(), &Config->ImageBase);1266 parseNumbers(arg->getValue(), &config->imageBase);
1267
1268 // Handle /filealign
1269 if (auto *arg = args.getLastArg(OPT_filealign)) {
1270 parseNumbers(arg->getValue(), &config->fileAlign);
1271 if (!isPowerOf2_64(config->fileAlign))
1272 error("/filealign: not a power of two: " + Twine(config->fileAlign));
1273 }
11001274
1101 // Handle /stack1275 // Handle /stack
1102 if (auto *Arg = Args.getLastArg(OPT_stack))1276 if (auto *arg = args.getLastArg(OPT_stack))
1103 parseNumbers(Arg->getValue(), &Config->StackReserve, &Config->StackCommit);1277 parseNumbers(arg->getValue(), &config->stackReserve, &config->stackCommit);
11041278
1105 // Handle /guard:cf1279 // Handle /guard:cf
1106 if (auto *Arg = Args.getLastArg(OPT_guard))1280 if (auto *arg = args.getLastArg(OPT_guard))
1107 parseGuard(Arg->getValue());1281 parseGuard(arg->getValue());
11081282
1109 // Handle /heap1283 // Handle /heap
1110 if (auto *Arg = Args.getLastArg(OPT_heap))1284 if (auto *arg = args.getLastArg(OPT_heap))
1111 parseNumbers(Arg->getValue(), &Config->HeapReserve, &Config->HeapCommit);1285 parseNumbers(arg->getValue(), &config->heapReserve, &config->heapCommit);
11121286
1113 // Handle /version1287 // Handle /version
1114 if (auto *Arg = Args.getLastArg(OPT_version))1288 if (auto *arg = args.getLastArg(OPT_version))
1115 parseVersion(Arg->getValue(), &Config->MajorImageVersion,1289 parseVersion(arg->getValue(), &config->majorImageVersion,
1116 &Config->MinorImageVersion);1290 &config->minorImageVersion);
11171291
1118 // Handle /subsystem1292 // Handle /subsystem
1119 if (auto *Arg = Args.getLastArg(OPT_subsystem))1293 if (auto *arg = args.getLastArg(OPT_subsystem))
1120 parseSubsystem(Arg->getValue(), &Config->Subsystem, &Config->MajorOSVersion,1294 parseSubsystem(arg->getValue(), &config->subsystem, &config->majorOSVersion,
1121 &Config->MinorOSVersion);1295 &config->minorOSVersion);
11221296
1123 // Handle /timestamp1297 // Handle /timestamp
1124 if (llvm::opt::Arg *Arg = Args.getLastArg(OPT_timestamp, OPT_repro)) {1298 if (llvm::opt::Arg *arg = args.getLastArg(OPT_timestamp, OPT_repro)) {
1125 if (Arg->getOption().getID() == OPT_repro) {1299 if (arg->getOption().getID() == OPT_repro) {
1126 Config->Timestamp = 0;1300 config->timestamp = 0;
1127 Config->Repro = true;1301 config->repro = true;
1128 } else {1302 } else {
1129 Config->Repro = false;1303 config->repro = false;
1130 StringRef Value(Arg->getValue());1304 StringRef value(arg->getValue());
1131 if (Value.getAsInteger(0, Config->Timestamp))1305 if (value.getAsInteger(0, config->timestamp))
1132 fatal(Twine("invalid timestamp: ") + Value +1306 fatal(Twine("invalid timestamp: ") + value +
1133 ". Expected 32-bit integer");1307 ". Expected 32-bit integer");
1134 }1308 }
1135 } else {1309 } else {
1136 Config->Repro = false;1310 config->repro = false;
1137 Config->Timestamp = time(nullptr);1311 config->timestamp = time(nullptr);
1138 }1312 }
11391313
1140 // Handle /alternatename1314 // Handle /alternatename
1141 for (auto *Arg : Args.filtered(OPT_alternatename))1315 for (auto *arg : args.filtered(OPT_alternatename))
1142 parseAlternateName(Arg->getValue());1316 parseAlternateName(arg->getValue());
11431317
1144 // Handle /include1318 // Handle /include
1145 for (auto *Arg : Args.filtered(OPT_incl))1319 for (auto *arg : args.filtered(OPT_incl))
1146 addUndefined(Arg->getValue());1320 addUndefined(arg->getValue());
11471321
1148 // Handle /implib1322 // Handle /implib
1149 if (auto *Arg = Args.getLastArg(OPT_implib))1323 if (auto *arg = args.getLastArg(OPT_implib))
1150 Config->Implib = Arg->getValue();1324 config->implib = arg->getValue();
11511325
1152 // Handle /opt.1326 // Handle /opt.
1153 bool DoGC = Debug == DebugKind::None || Args.hasArg(OPT_profile);1327 bool doGC = debug == DebugKind::None || args.hasArg(OPT_profile);
1154 unsigned ICFLevel =1328 unsigned icfLevel =
1155 Args.hasArg(OPT_profile) ? 0 : 1; // 0: off, 1: limited, 2: on1329 args.hasArg(OPT_profile) ? 0 : 1; // 0: off, 1: limited, 2: on
1156 unsigned TailMerge = 1;1330 unsigned tailMerge = 1;
1157 for (auto *Arg : Args.filtered(OPT_opt)) {1331 for (auto *arg : args.filtered(OPT_opt)) {
1158 std::string Str = StringRef(Arg->getValue()).lower();1332 std::string str = StringRef(arg->getValue()).lower();
1159 SmallVector<StringRef, 1> Vec;1333 SmallVector<StringRef, 1> vec;
1160 StringRef(Str).split(Vec, ',');1334 StringRef(str).split(vec, ',');
1161 for (StringRef S : Vec) {1335 for (StringRef s : vec) {
1162 if (S == "ref") {1336 if (s == "ref") {
1163 DoGC = true;1337 doGC = true;
1164 } else if (S == "noref") {1338 } else if (s == "noref") {
1165 DoGC = false;1339 doGC = false;
1166 } else if (S == "icf" || S.startswith("icf=")) {1340 } else if (s == "icf" || s.startswith("icf=")) {
1167 ICFLevel = 2;1341 icfLevel = 2;
1168 } else if (S == "noicf") {1342 } else if (s == "noicf") {
1169 ICFLevel = 0;1343 icfLevel = 0;
1170 } else if (S == "lldtailmerge") {1344 } else if (s == "lldtailmerge") {
1171 TailMerge = 2;1345 tailMerge = 2;
1172 } else if (S == "nolldtailmerge") {1346 } else if (s == "nolldtailmerge") {
1173 TailMerge = 0;1347 tailMerge = 0;
1174 } else if (S.startswith("lldlto=")) {1348 } else if (s.startswith("lldlto=")) {
1175 StringRef OptLevel = S.substr(7);1349 StringRef optLevel = s.substr(7);
1176 if (OptLevel.getAsInteger(10, Config->LTOO) || Config->LTOO > 3)1350 if (optLevel.getAsInteger(10, config->ltoo) || config->ltoo > 3)
1177 error("/opt:lldlto: invalid optimization level: " + OptLevel);1351 error("/opt:lldlto: invalid optimization level: " + optLevel);
1178 } else if (S.startswith("lldltojobs=")) {1352 } else if (s.startswith("lldltojobs=")) {
1179 StringRef Jobs = S.substr(11);1353 StringRef jobs = s.substr(11);
1180 if (Jobs.getAsInteger(10, Config->ThinLTOJobs) ||1354 if (jobs.getAsInteger(10, config->thinLTOJobs) ||
1181 Config->ThinLTOJobs == 0)1355 config->thinLTOJobs == 0)
1182 error("/opt:lldltojobs: invalid job count: " + Jobs);1356 error("/opt:lldltojobs: invalid job count: " + jobs);
1183 } else if (S.startswith("lldltopartitions=")) {1357 } else if (s.startswith("lldltopartitions=")) {
1184 StringRef N = S.substr(17);1358 StringRef n = s.substr(17);
1185 if (N.getAsInteger(10, Config->LTOPartitions) ||1359 if (n.getAsInteger(10, config->ltoPartitions) ||
1186 Config->LTOPartitions == 0)1360 config->ltoPartitions == 0)
1187 error("/opt:lldltopartitions: invalid partition count: " + N);1361 error("/opt:lldltopartitions: invalid partition count: " + n);
1188 } else if (S != "lbr" && S != "nolbr")1362 } else if (s != "lbr" && s != "nolbr")
1189 error("/opt: unknown option: " + S);1363 error("/opt: unknown option: " + s);
1190 }1364 }
1191 }1365 }
11921366
...@@ -1195,37 +1369,37 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {...@@ -1195,37 +1369,37 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
1195 // FIXME: LLD only implements "limited" ICF, i.e. it only merges identical1369 // FIXME: LLD only implements "limited" ICF, i.e. it only merges identical
1196 // code. If the user passes /OPT:ICF explicitly, LLD should merge identical1370 // code. If the user passes /OPT:ICF explicitly, LLD should merge identical
1197 // comdat readonly data.1371 // comdat readonly data.
1198 if (ICFLevel == 1 && !DoGC)1372 if (icfLevel == 1 && !doGC)
1199 ICFLevel = 0;1373 icfLevel = 0;
1200 Config->DoGC = DoGC;1374 config->doGC = doGC;
1201 Config->DoICF = ICFLevel > 0;1375 config->doICF = icfLevel > 0;
1202 Config->TailMerge = (TailMerge == 1 && Config->DoICF) || TailMerge == 2;1376 config->tailMerge = (tailMerge == 1 && config->doICF) || tailMerge == 2;
12031377
1204 // Handle /lldsavetemps1378 // Handle /lldsavetemps
1205 if (Args.hasArg(OPT_lldsavetemps))1379 if (args.hasArg(OPT_lldsavetemps))
1206 Config->SaveTemps = true;1380 config->saveTemps = true;
12071381
1208 // Handle /kill-at1382 // Handle /kill-at
1209 if (Args.hasArg(OPT_kill_at))1383 if (args.hasArg(OPT_kill_at))
1210 Config->KillAt = true;1384 config->killAt = true;
12111385
1212 // Handle /lldltocache1386 // Handle /lldltocache
1213 if (auto *Arg = Args.getLastArg(OPT_lldltocache))1387 if (auto *arg = args.getLastArg(OPT_lldltocache))
1214 Config->LTOCache = Arg->getValue();1388 config->ltoCache = arg->getValue();
12151389
1216 // Handle /lldsavecachepolicy1390 // Handle /lldsavecachepolicy
1217 if (auto *Arg = Args.getLastArg(OPT_lldltocachepolicy))1391 if (auto *arg = args.getLastArg(OPT_lldltocachepolicy))
1218 Config->LTOCachePolicy = CHECK(1392 config->ltoCachePolicy = CHECK(
1219 parseCachePruningPolicy(Arg->getValue()),1393 parseCachePruningPolicy(arg->getValue()),
1220 Twine("/lldltocachepolicy: invalid cache policy: ") + Arg->getValue());1394 Twine("/lldltocachepolicy: invalid cache policy: ") + arg->getValue());
12211395
1222 // Handle /failifmismatch1396 // Handle /failifmismatch
1223 for (auto *Arg : Args.filtered(OPT_failifmismatch))1397 for (auto *arg : args.filtered(OPT_failifmismatch))
1224 checkFailIfMismatch(Arg->getValue());1398 checkFailIfMismatch(arg->getValue(), nullptr);
12251399
1226 // Handle /merge1400 // Handle /merge
1227 for (auto *Arg : Args.filtered(OPT_merge))1401 for (auto *arg : args.filtered(OPT_merge))
1228 parseMerge(Arg->getValue());1402 parseMerge(arg->getValue());
12291403
1230 // Add default section merging rules after user rules. User rules take1404 // Add default section merging rules after user rules. User rules take
1231 // precedence, but we will emit a warning if there is a conflict.1405 // precedence, but we will emit a warning if there is a conflict.
...@@ -1235,130 +1409,137 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {...@@ -1235,130 +1409,137 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
1235 parseMerge(".xdata=.rdata");1409 parseMerge(".xdata=.rdata");
1236 parseMerge(".bss=.data");1410 parseMerge(".bss=.data");
12371411
1238 if (Config->MinGW) {1412 if (config->mingw) {
1239 parseMerge(".ctors=.rdata");1413 parseMerge(".ctors=.rdata");
1240 parseMerge(".dtors=.rdata");1414 parseMerge(".dtors=.rdata");
1241 parseMerge(".CRT=.rdata");1415 parseMerge(".CRT=.rdata");
1242 }1416 }
12431417
1244 // Handle /section1418 // Handle /section
1245 for (auto *Arg : Args.filtered(OPT_section))1419 for (auto *arg : args.filtered(OPT_section))
1246 parseSection(Arg->getValue());1420 parseSection(arg->getValue());
12471421
1248 // Handle /aligncomm1422 // Handle /aligncomm
1249 for (auto *Arg : Args.filtered(OPT_aligncomm))1423 for (auto *arg : args.filtered(OPT_aligncomm))
1250 parseAligncomm(Arg->getValue());1424 parseAligncomm(arg->getValue());
12511425
1252 // Handle /manifestdependency. This enables /manifest unless /manifest:no is1426 // Handle /manifestdependency. This enables /manifest unless /manifest:no is
1253 // also passed.1427 // also passed.
1254 if (auto *Arg = Args.getLastArg(OPT_manifestdependency)) {1428 if (auto *arg = args.getLastArg(OPT_manifestdependency)) {
1255 Config->ManifestDependency = Arg->getValue();1429 config->manifestDependency = arg->getValue();
1256 Config->Manifest = Configuration::SideBySide;1430 config->manifest = Configuration::SideBySide;
1257 }1431 }
12581432
1259 // Handle /manifest and /manifest:1433 // Handle /manifest and /manifest:
1260 if (auto *Arg = Args.getLastArg(OPT_manifest, OPT_manifest_colon)) {1434 if (auto *arg = args.getLastArg(OPT_manifest, OPT_manifest_colon)) {
1261 if (Arg->getOption().getID() == OPT_manifest)1435 if (arg->getOption().getID() == OPT_manifest)
1262 Config->Manifest = Configuration::SideBySide;1436 config->manifest = Configuration::SideBySide;
1263 else1437 else
1264 parseManifest(Arg->getValue());1438 parseManifest(arg->getValue());
1265 }1439 }
12661440
1267 // Handle /manifestuac1441 // Handle /manifestuac
1268 if (auto *Arg = Args.getLastArg(OPT_manifestuac))1442 if (auto *arg = args.getLastArg(OPT_manifestuac))
1269 parseManifestUAC(Arg->getValue());1443 parseManifestUAC(arg->getValue());
12701444
1271 // Handle /manifestfile1445 // Handle /manifestfile
1272 if (auto *Arg = Args.getLastArg(OPT_manifestfile))1446 if (auto *arg = args.getLastArg(OPT_manifestfile))
1273 Config->ManifestFile = Arg->getValue();1447 config->manifestFile = arg->getValue();
12741448
1275 // Handle /manifestinput1449 // Handle /manifestinput
1276 for (auto *Arg : Args.filtered(OPT_manifestinput))1450 for (auto *arg : args.filtered(OPT_manifestinput))
1277 Config->ManifestInput.push_back(Arg->getValue());1451 config->manifestInput.push_back(arg->getValue());
12781452
1279 if (!Config->ManifestInput.empty() &&1453 if (!config->manifestInput.empty() &&
1280 Config->Manifest != Configuration::Embed) {1454 config->manifest != Configuration::Embed) {
1281 fatal("/manifestinput: requires /manifest:embed");1455 fatal("/manifestinput: requires /manifest:embed");
1282 }1456 }
12831457
1458 config->thinLTOEmitImportsFiles = args.hasArg(OPT_thinlto_emit_imports_files);
1459 config->thinLTOIndexOnly = args.hasArg(OPT_thinlto_index_only) ||
1460 args.hasArg(OPT_thinlto_index_only_arg);
1461 config->thinLTOIndexOnlyArg =
1462 args.getLastArgValue(OPT_thinlto_index_only_arg);
1463 config->thinLTOPrefixReplace =
1464 getOldNewOptions(args, OPT_thinlto_prefix_replace);
1465 config->thinLTOObjectSuffixReplace =
1466 getOldNewOptions(args, OPT_thinlto_object_suffix_replace);
1284 // Handle miscellaneous boolean flags.1467 // Handle miscellaneous boolean flags.
1285 Config->AllowBind = Args.hasFlag(OPT_allowbind, OPT_allowbind_no, true);1468 config->allowBind = args.hasFlag(OPT_allowbind, OPT_allowbind_no, true);
1286 Config->AllowIsolation =1469 config->allowIsolation =
1287 Args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);1470 args.hasFlag(OPT_allowisolation, OPT_allowisolation_no, true);
1288 Config->Incremental =1471 config->incremental =
1289 Args.hasFlag(OPT_incremental, OPT_incremental_no,1472 args.hasFlag(OPT_incremental, OPT_incremental_no,
1290 !Config->DoGC && !Config->DoICF && !Args.hasArg(OPT_order) &&1473 !config->doGC && !config->doICF && !args.hasArg(OPT_order) &&
1291 !Args.hasArg(OPT_profile));1474 !args.hasArg(OPT_profile));
1292 Config->IntegrityCheck =1475 config->integrityCheck =
1293 Args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false);1476 args.hasFlag(OPT_integritycheck, OPT_integritycheck_no, false);
1294 Config->NxCompat = Args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);1477 config->nxCompat = args.hasFlag(OPT_nxcompat, OPT_nxcompat_no, true);
1295 Config->TerminalServerAware =1478 for (auto *arg : args.filtered(OPT_swaprun))
1296 !Config->DLL && Args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);1479 parseSwaprun(arg->getValue());
1297 Config->DebugDwarf = Debug == DebugKind::Dwarf;1480 config->terminalServerAware =
1298 Config->DebugGHashes = Debug == DebugKind::GHash;1481 !config->dll && args.hasFlag(OPT_tsaware, OPT_tsaware_no, true);
1299 Config->DebugSymtab = Debug == DebugKind::Symtab;1482 config->debugDwarf = debug == DebugKind::Dwarf;
13001483 config->debugGHashes = debug == DebugKind::GHash;
1301 Config->MapFile = getMapFile(Args);1484 config->debugSymtab = debug == DebugKind::Symtab;
13021485
1303 if (Config->Incremental && Args.hasArg(OPT_profile)) {1486 config->mapFile = getMapFile(args);
1487
1488 if (config->incremental && args.hasArg(OPT_profile)) {
1304 warn("ignoring '/incremental' due to '/profile' specification");1489 warn("ignoring '/incremental' due to '/profile' specification");
1305 Config->Incremental = false;1490 config->incremental = false;
1306 }1491 }
13071492
1308 if (Config->Incremental && Args.hasArg(OPT_order)) {1493 if (config->incremental && args.hasArg(OPT_order)) {
1309 warn("ignoring '/incremental' due to '/order' specification");1494 warn("ignoring '/incremental' due to '/order' specification");
1310 Config->Incremental = false;1495 config->incremental = false;
1311 }1496 }
13121497
1313 if (Config->Incremental && Config->DoGC) {1498 if (config->incremental && config->doGC) {
1314 warn("ignoring '/incremental' because REF is enabled; use '/opt:noref' to "1499 warn("ignoring '/incremental' because REF is enabled; use '/opt:noref' to "
1315 "disable");1500 "disable");
1316 Config->Incremental = false;1501 config->incremental = false;
1317 }1502 }
13181503
1319 if (Config->Incremental && Config->DoICF) {1504 if (config->incremental && config->doICF) {
1320 warn("ignoring '/incremental' because ICF is enabled; use '/opt:noicf' to "1505 warn("ignoring '/incremental' because ICF is enabled; use '/opt:noicf' to "
1321 "disable");1506 "disable");
1322 Config->Incremental = false;1507 config->incremental = false;
1323 }1508 }
13241509
1325 if (errorCount())1510 if (errorCount())
1326 return;1511 return;
13271512
1328 std::set<sys::fs::UniqueID> WholeArchives;1513 std::set<sys::fs::UniqueID> wholeArchives;
1329 AutoExporter Exporter;1514 for (auto *arg : args.filtered(OPT_wholearchive_file))
1330 for (auto *Arg : Args.filtered(OPT_wholearchive_file)) {1515 if (Optional<StringRef> path = doFindFile(arg->getValue()))
1331 if (Optional<StringRef> Path = doFindFile(Arg->getValue())) {1516 if (Optional<sys::fs::UniqueID> id = getUniqueID(*path))
1332 if (Optional<sys::fs::UniqueID> ID = getUniqueID(*Path))1517 wholeArchives.insert(*id);
1333 WholeArchives.insert(*ID);
1334 Exporter.addWholeArchive(*Path);
1335 }
1336 }
13371518
1338 // A predicate returning true if a given path is an argument for1519 // A predicate returning true if a given path is an argument for
1339 // /wholearchive:, or /wholearchive is enabled globally.1520 // /wholearchive:, or /wholearchive is enabled globally.
1340 // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj"1521 // This function is a bit tricky because "foo.obj /wholearchive:././foo.obj"
1341 // needs to be handled as "/wholearchive:foo.obj foo.obj".1522 // needs to be handled as "/wholearchive:foo.obj foo.obj".
1342 auto IsWholeArchive = [&](StringRef Path) -> bool {1523 auto isWholeArchive = [&](StringRef path) -> bool {
1343 if (Args.hasArg(OPT_wholearchive_flag))1524 if (args.hasArg(OPT_wholearchive_flag))
1344 return true;1525 return true;
1345 if (Optional<sys::fs::UniqueID> ID = getUniqueID(Path))1526 if (Optional<sys::fs::UniqueID> id = getUniqueID(path))
1346 return WholeArchives.count(*ID);1527 return wholeArchives.count(*id);
1347 return false;1528 return false;
1348 };1529 };
13491530
1350 // Create a list of input files. Files can be given as arguments1531 // Create a list of input files. Files can be given as arguments
1351 // for /defaultlib option.1532 // for /defaultlib option.
1352 for (auto *Arg : Args.filtered(OPT_INPUT, OPT_wholearchive_file))1533 for (auto *arg : args.filtered(OPT_INPUT, OPT_wholearchive_file))
1353 if (Optional<StringRef> Path = findFile(Arg->getValue()))1534 if (Optional<StringRef> path = findFile(arg->getValue()))
1354 enqueuePath(*Path, IsWholeArchive(*Path));1535 enqueuePath(*path, isWholeArchive(*path));
13551536
1356 for (auto *Arg : Args.filtered(OPT_defaultlib))1537 for (auto *arg : args.filtered(OPT_defaultlib))
1357 if (Optional<StringRef> Path = findLib(Arg->getValue()))1538 if (Optional<StringRef> path = findLib(arg->getValue()))
1358 enqueuePath(*Path, false);1539 enqueuePath(*path, false);
13591540
1360 // Windows specific -- Create a resource file containing a manifest file.1541 // Windows specific -- Create a resource file containing a manifest file.
1361 if (Config->Manifest == Configuration::Embed)1542 if (config->manifest == Configuration::Embed)
1362 addBuffer(createManifestRes(), false);1543 addBuffer(createManifestRes(), false);
13631544
1364 // Read all input files given via the command line.1545 // Read all input files given via the command line.
...@@ -1369,154 +1550,169 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {...@@ -1369,154 +1550,169 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
13691550
1370 // We should have inferred a machine type by now from the input files, but if1551 // We should have inferred a machine type by now from the input files, but if
1371 // not we assume x64.1552 // not we assume x64.
1372 if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {1553 if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) {
1373 warn("/machine is not specified. x64 is assumed");1554 warn("/machine is not specified. x64 is assumed");
1374 Config->Machine = AMD64;1555 config->machine = AMD64;
1375 }1556 }
1376 Config->Wordsize = Config->is64() ? 8 : 4;1557 config->wordsize = config->is64() ? 8 : 4;
1558
1559 // Handle /safeseh, x86 only, on by default, except for mingw.
1560 if (config->machine == I386 &&
1561 args.hasFlag(OPT_safeseh, OPT_safeseh_no, !config->mingw))
1562 config->safeSEH = true;
1563
1564 // Handle /functionpadmin
1565 for (auto *arg : args.filtered(OPT_functionpadmin, OPT_functionpadmin_opt))
1566 parseFunctionPadMin(arg, config->machine);
13771567
1378 // Input files can be Windows resource files (.res files). We use1568 // Input files can be Windows resource files (.res files). We use
1379 // WindowsResource to convert resource files to a regular COFF file,1569 // WindowsResource to convert resource files to a regular COFF file,
1380 // then link the resulting file normally.1570 // then link the resulting file normally.
1381 if (!Resources.empty())1571 if (!resources.empty())
1382 Symtab->addFile(make<ObjFile>(convertResToCOFF(Resources)));1572 symtab->addFile(make<ObjFile>(convertResToCOFF(resources)));
13831573
1384 if (Tar)1574 if (tar)
1385 Tar->append("response.txt",1575 tar->append("response.txt",
1386 createResponseFile(Args, FilePaths,1576 createResponseFile(args, filePaths,
1387 ArrayRef<StringRef>(SearchPaths).slice(1)));1577 ArrayRef<StringRef>(searchPaths).slice(1)));
13881578
1389 // Handle /largeaddressaware1579 // Handle /largeaddressaware
1390 Config->LargeAddressAware = Args.hasFlag(1580 config->largeAddressAware = args.hasFlag(
1391 OPT_largeaddressaware, OPT_largeaddressaware_no, Config->is64());1581 OPT_largeaddressaware, OPT_largeaddressaware_no, config->is64());
13921582
1393 // Handle /highentropyva1583 // Handle /highentropyva
1394 Config->HighEntropyVA =1584 config->highEntropyVA =
1395 Config->is64() &&1585 config->is64() &&
1396 Args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true);1586 args.hasFlag(OPT_highentropyva, OPT_highentropyva_no, true);
13971587
1398 if (!Config->DynamicBase &&1588 if (!config->dynamicBase &&
1399 (Config->Machine == ARMNT || Config->Machine == ARM64))1589 (config->machine == ARMNT || config->machine == ARM64))
1400 error("/dynamicbase:no is not compatible with " +1590 error("/dynamicbase:no is not compatible with " +
1401 machineToStr(Config->Machine));1591 machineToStr(config->machine));
14021592
1403 // Handle /export1593 // Handle /export
1404 for (auto *Arg : Args.filtered(OPT_export)) {1594 for (auto *arg : args.filtered(OPT_export)) {
1405 Export E = parseExport(Arg->getValue());1595 Export e = parseExport(arg->getValue());
1406 if (Config->Machine == I386) {1596 if (config->machine == I386) {
1407 if (!isDecorated(E.Name))1597 if (!isDecorated(e.name))
1408 E.Name = Saver.save("_" + E.Name);1598 e.name = saver.save("_" + e.name);
1409 if (!E.ExtName.empty() && !isDecorated(E.ExtName))1599 if (!e.extName.empty() && !isDecorated(e.extName))
1410 E.ExtName = Saver.save("_" + E.ExtName);1600 e.extName = saver.save("_" + e.extName);
1411 }1601 }
1412 Config->Exports.push_back(E);1602 config->exports.push_back(e);
1413 }1603 }
14141604
1415 // Handle /def1605 // Handle /def
1416 if (auto *Arg = Args.getLastArg(OPT_deffile)) {1606 if (auto *arg = args.getLastArg(OPT_deffile)) {
1417 // parseModuleDefs mutates Config object.1607 // parseModuleDefs mutates Config object.
1418 parseModuleDefs(Arg->getValue());1608 parseModuleDefs(arg->getValue());
1419 }1609 }
14201610
1421 // Handle generation of import library from a def file.1611 // Handle generation of import library from a def file.
1422 if (!Args.hasArg(OPT_INPUT)) {1612 if (!args.hasArg(OPT_INPUT)) {
1423 fixupExports();1613 fixupExports();
1424 createImportLibrary(/*AsLib=*/true);1614 createImportLibrary(/*asLib=*/true);
1425 return;1615 return;
1426 }1616 }
14271617
1428 // Windows specific -- if no /subsystem is given, we need to infer1618 // Windows specific -- if no /subsystem is given, we need to infer
1429 // that from entry point name. Must happen before /entry handling,1619 // that from entry point name. Must happen before /entry handling,
1430 // and after the early return when just writing an import library.1620 // and after the early return when just writing an import library.
1431 if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {1621 if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN) {
1432 Config->Subsystem = inferSubsystem();1622 config->subsystem = inferSubsystem();
1433 if (Config->Subsystem == IMAGE_SUBSYSTEM_UNKNOWN)1623 if (config->subsystem == IMAGE_SUBSYSTEM_UNKNOWN)
1434 fatal("subsystem must be defined");1624 fatal("subsystem must be defined");
1435 }1625 }
14361626
1437 // Handle /entry and /dll1627 // Handle /entry and /dll
1438 if (auto *Arg = Args.getLastArg(OPT_entry)) {1628 if (auto *arg = args.getLastArg(OPT_entry)) {
1439 Config->Entry = addUndefined(mangle(Arg->getValue()));1629 config->entry = addUndefined(mangle(arg->getValue()));
1440 } else if (!Config->Entry && !Config->NoEntry) {1630 } else if (!config->entry && !config->noEntry) {
1441 if (Args.hasArg(OPT_dll)) {1631 if (args.hasArg(OPT_dll)) {
1442 StringRef S = (Config->Machine == I386) ? "__DllMainCRTStartup@12"1632 StringRef s = (config->machine == I386) ? "__DllMainCRTStartup@12"
1443 : "_DllMainCRTStartup";1633 : "_DllMainCRTStartup";
1444 Config->Entry = addUndefined(S);1634 config->entry = addUndefined(s);
1445 } else {1635 } else {
1446 // Windows specific -- If entry point name is not given, we need to1636 // Windows specific -- If entry point name is not given, we need to
1447 // infer that from user-defined entry name.1637 // infer that from user-defined entry name.
1448 StringRef S = findDefaultEntry();1638 StringRef s = findDefaultEntry();
1449 if (S.empty())1639 if (s.empty())
1450 fatal("entry point must be defined");1640 fatal("entry point must be defined");
1451 Config->Entry = addUndefined(S);1641 config->entry = addUndefined(s);
1452 log("Entry name inferred: " + S);1642 log("Entry name inferred: " + s);
1453 }1643 }
1454 }1644 }
14551645
1456 // Handle /delayload1646 // Handle /delayload
1457 for (auto *Arg : Args.filtered(OPT_delayload)) {1647 for (auto *arg : args.filtered(OPT_delayload)) {
1458 Config->DelayLoads.insert(StringRef(Arg->getValue()).lower());1648 config->delayLoads.insert(StringRef(arg->getValue()).lower());
1459 if (Config->Machine == I386) {1649 if (config->machine == I386) {
1460 Config->DelayLoadHelper = addUndefined("___delayLoadHelper2@8");1650 config->delayLoadHelper = addUndefined("___delayLoadHelper2@8");
1461 } else {1651 } else {
1462 Config->DelayLoadHelper = addUndefined("__delayLoadHelper2");1652 config->delayLoadHelper = addUndefined("__delayLoadHelper2");
1463 }1653 }
1464 }1654 }
14651655
1466 // Set default image name if neither /out or /def set it.1656 // Set default image name if neither /out or /def set it.
1467 if (Config->OutputFile.empty()) {1657 if (config->outputFile.empty()) {
1468 Config->OutputFile =1658 config->outputFile =
1469 getOutputPath((*Args.filtered(OPT_INPUT).begin())->getValue());1659 getOutputPath((*args.filtered(OPT_INPUT).begin())->getValue());
1470 }1660 }
14711661
1472 if (ShouldCreatePDB) {1662 // Fail early if an output file is not writable.
1663 if (auto e = tryCreateFile(config->outputFile)) {
1664 error("cannot open output file " + config->outputFile + ": " + e.message());
1665 return;
1666 }
1667
1668 if (shouldCreatePDB) {
1473 // Put the PDB next to the image if no /pdb flag was passed.1669 // Put the PDB next to the image if no /pdb flag was passed.
1474 if (Config->PDBPath.empty()) {1670 if (config->pdbPath.empty()) {
1475 Config->PDBPath = Config->OutputFile;1671 config->pdbPath = config->outputFile;
1476 sys::path::replace_extension(Config->PDBPath, ".pdb");1672 sys::path::replace_extension(config->pdbPath, ".pdb");
1477 }1673 }
14781674
1479 // The embedded PDB path should be the absolute path to the PDB if no1675 // The embedded PDB path should be the absolute path to the PDB if no
1480 // /pdbaltpath flag was passed.1676 // /pdbaltpath flag was passed.
1481 if (Config->PDBAltPath.empty()) {1677 if (config->pdbAltPath.empty()) {
1482 Config->PDBAltPath = Config->PDBPath;1678 config->pdbAltPath = config->pdbPath;
14831679
1484 // It's important to make the path absolute and remove dots. This path1680 // It's important to make the path absolute and remove dots. This path
1485 // will eventually be written into the PE header, and certain Microsoft1681 // will eventually be written into the PE header, and certain Microsoft
1486 // tools won't work correctly if these assumptions are not held.1682 // tools won't work correctly if these assumptions are not held.
1487 sys::fs::make_absolute(Config->PDBAltPath);1683 sys::fs::make_absolute(config->pdbAltPath);
1488 sys::path::remove_dots(Config->PDBAltPath);1684 sys::path::remove_dots(config->pdbAltPath);
1489 } else {1685 } else {
1490 // Don't do this earlier, so that Config->OutputFile is ready.1686 // Don't do this earlier, so that Config->OutputFile is ready.
1491 parsePDBAltPath(Config->PDBAltPath);1687 parsePDBAltPath(config->pdbAltPath);
1492 }1688 }
1493 }1689 }
14941690
1495 // Set default image base if /base is not given.1691 // Set default image base if /base is not given.
1496 if (Config->ImageBase == uint64_t(-1))1692 if (config->imageBase == uint64_t(-1))
1497 Config->ImageBase = getDefaultImageBase();1693 config->imageBase = getDefaultImageBase();
14981694
1499 Symtab->addSynthetic(mangle("__ImageBase"), nullptr);1695 symtab->addSynthetic(mangle("__ImageBase"), nullptr);
1500 if (Config->Machine == I386) {1696 if (config->machine == I386) {
1501 Symtab->addAbsolute("___safe_se_handler_table", 0);1697 symtab->addAbsolute("___safe_se_handler_table", 0);
1502 Symtab->addAbsolute("___safe_se_handler_count", 0);1698 symtab->addAbsolute("___safe_se_handler_count", 0);
1503 }1699 }
15041700
1505 Symtab->addAbsolute(mangle("__guard_fids_count"), 0);1701 symtab->addAbsolute(mangle("__guard_fids_count"), 0);
1506 Symtab->addAbsolute(mangle("__guard_fids_table"), 0);1702 symtab->addAbsolute(mangle("__guard_fids_table"), 0);
1507 Symtab->addAbsolute(mangle("__guard_flags"), 0);1703 symtab->addAbsolute(mangle("__guard_flags"), 0);
1508 Symtab->addAbsolute(mangle("__guard_iat_count"), 0);1704 symtab->addAbsolute(mangle("__guard_iat_count"), 0);
1509 Symtab->addAbsolute(mangle("__guard_iat_table"), 0);1705 symtab->addAbsolute(mangle("__guard_iat_table"), 0);
1510 Symtab->addAbsolute(mangle("__guard_longjmp_count"), 0);1706 symtab->addAbsolute(mangle("__guard_longjmp_count"), 0);
1511 Symtab->addAbsolute(mangle("__guard_longjmp_table"), 0);1707 symtab->addAbsolute(mangle("__guard_longjmp_table"), 0);
1512 // Needed for MSVC 2017 15.5 CRT.1708 // Needed for MSVC 2017 15.5 CRT.
1513 Symtab->addAbsolute(mangle("__enclave_config"), 0);1709 symtab->addAbsolute(mangle("__enclave_config"), 0);
15141710
1515 if (Config->MinGW) {1711 if (config->mingw) {
1516 Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);1712 symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST__"), 0);
1517 Symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0);1713 symtab->addAbsolute(mangle("__RUNTIME_PSEUDO_RELOC_LIST_END__"), 0);
1518 Symtab->addAbsolute(mangle("__CTOR_LIST__"), 0);1714 symtab->addAbsolute(mangle("__CTOR_LIST__"), 0);
1519 Symtab->addAbsolute(mangle("__DTOR_LIST__"), 0);1715 symtab->addAbsolute(mangle("__DTOR_LIST__"), 0);
1520 }1716 }
15211717
1522 // This code may add new undefined symbols to the link, which may enqueue more1718 // This code may add new undefined symbols to the link, which may enqueue more
...@@ -1525,33 +1721,33 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {...@@ -1525,33 +1721,33 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
1525 do {1721 do {
1526 // Windows specific -- if entry point is not found,1722 // Windows specific -- if entry point is not found,
1527 // search for its mangled names.1723 // search for its mangled names.
1528 if (Config->Entry)1724 if (config->entry)
1529 Symtab->mangleMaybe(Config->Entry);1725 mangleMaybe(config->entry);
15301726
1531 // Windows specific -- Make sure we resolve all dllexported symbols.1727 // Windows specific -- Make sure we resolve all dllexported symbols.
1532 for (Export &E : Config->Exports) {1728 for (Export &e : config->exports) {
1533 if (!E.ForwardTo.empty())1729 if (!e.forwardTo.empty())
1534 continue;1730 continue;
1535 E.Sym = addUndefined(E.Name);1731 e.sym = addUndefined(e.name);
1536 if (!E.Directives)1732 if (!e.directives)
1537 Symtab->mangleMaybe(E.Sym);1733 e.symbolName = mangleMaybe(e.sym);
1538 }1734 }
15391735
1540 // Add weak aliases. Weak aliases is a mechanism to give remaining1736 // Add weak aliases. Weak aliases is a mechanism to give remaining
1541 // undefined symbols final chance to be resolved successfully.1737 // undefined symbols final chance to be resolved successfully.
1542 for (auto Pair : Config->AlternateNames) {1738 for (auto pair : config->alternateNames) {
1543 StringRef From = Pair.first;1739 StringRef from = pair.first;
1544 StringRef To = Pair.second;1740 StringRef to = pair.second;
1545 Symbol *Sym = Symtab->find(From);1741 Symbol *sym = symtab->find(from);
1546 if (!Sym)1742 if (!sym)
1547 continue;1743 continue;
1548 if (auto *U = dyn_cast<Undefined>(Sym))1744 if (auto *u = dyn_cast<Undefined>(sym))
1549 if (!U->WeakAlias)1745 if (!u->weakAlias)
1550 U->WeakAlias = Symtab->addUndefined(To);1746 u->weakAlias = symtab->addUndefined(to);
1551 }1747 }
15521748
1553 // Windows specific -- if __load_config_used can be resolved, resolve it.1749 // Windows specific -- if __load_config_used can be resolved, resolve it.
1554 if (Symtab->findUnderscore("_load_config_used"))1750 if (symtab->findUnderscore("_load_config_used"))
1555 addUndefined(mangle("_load_config_used"));1751 addUndefined(mangle("_load_config_used"));
1556 } while (run());1752 } while (run());
15571753
...@@ -1559,11 +1755,29 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {...@@ -1559,11 +1755,29 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
1559 return;1755 return;
15601756
1561 // Do LTO by compiling bitcode input files to a set of native COFF files then1757 // Do LTO by compiling bitcode input files to a set of native COFF files then
1562 // link those files.1758 // link those files (unless -thinlto-index-only was given, in which case we
1563 Symtab->addCombinedLTOObjects();1759 // resolve symbols and write indices, but don't generate native code or link).
1760 symtab->addCombinedLTOObjects();
1761
1762 // If -thinlto-index-only is given, we should create only "index
1763 // files" and not object files. Index file creation is already done
1764 // in addCombinedLTOObject, so we are done if that's the case.
1765 if (config->thinLTOIndexOnly)
1766 return;
1767
1768 // If we generated native object files from bitcode files, this resolves
1769 // references to the symbols we use from them.
1564 run();1770 run();
15651771
1566 if (Config->MinGW) {1772 if (args.hasArg(OPT_include_optional)) {
1773 // Handle /includeoptional
1774 for (auto *arg : args.filtered(OPT_include_optional))
1775 if (dyn_cast_or_null<Lazy>(symtab->find(arg->getValue())))
1776 addUndefined(arg->getValue());
1777 while (run());
1778 }
1779
1780 if (config->mingw) {
1567 // Load any further object files that might be needed for doing automatic1781 // Load any further object files that might be needed for doing automatic
1568 // imports.1782 // imports.
1569 //1783 //
...@@ -1577,95 +1791,91 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {...@@ -1577,95 +1791,91 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
1577 // normal object file as well (although that won't be used for the1791 // 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,1792 // actual autoimport later on). If this pass adds new undefined references,
1579 // we won't iterate further to resolve them.1793 // we won't iterate further to resolve them.
1580 Symtab->loadMinGWAutomaticImports();1794 symtab->loadMinGWAutomaticImports();
1581 run();1795 run();
1582 }1796 }
15831797
1584 // Make sure we have resolved all symbols.1798 // Make sure we have resolved all symbols.
1585 Symtab->reportRemainingUndefines();1799 symtab->reportRemainingUndefines();
1586 if (errorCount())1800 if (errorCount())
1587 return;1801 return;
15881802
1589 // Handle /safeseh.1803 if (config->mingw) {
1590 if (Args.hasFlag(OPT_safeseh, OPT_safeseh_no, false)) {1804 // In MinGW, all symbols are automatically exported if no symbols
1591 for (ObjFile *File : ObjFile::Instances)1805 // are chosen to be exported.
1592 if (!File->hasSafeSEH())1806 maybeExportMinGWSymbols(args);
1593 error("/safeseh: " + File->getName() + " is not compatible with SEH");1807
1594 if (errorCount())1808 // Make sure the crtend.o object is the last object file. This object
1595 return;1809 // file can contain terminating section chunks that need to be placed
1596 }1810 // last. GNU ld processes files and static libraries explicitly in the
15971811 // order provided on the command line, while lld will pull in needed
1598 // In MinGW, all symbols are automatically exported if no symbols1812 // files from static libraries only after the last object file on the
1599 // are chosen to be exported.1813 // command line.
1600 if (Config->DLL && ((Config->MinGW && Config->Exports.empty()) ||1814 for (auto i = ObjFile::instances.begin(), e = ObjFile::instances.end();
1601 Args.hasArg(OPT_export_all_symbols))) {1815 i != e; i++) {
1602 Exporter.initSymbolExcludes();1816 ObjFile *file = *i;
16031817 if (isCrtend(file->getName())) {
1604 Symtab->forEachSymbol([=](Symbol *S) {1818 ObjFile::instances.erase(i);
1605 auto *Def = dyn_cast<Defined>(S);1819 ObjFile::instances.push_back(file);
1606 if (!Exporter.shouldExport(Def))1820 break;
1607 return;1821 }
1608 Export E;1822 }
1609 E.Name = Def->getName();
1610 E.Sym = Def;
1611 if (Def->getChunk() &&
1612 !(Def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
1613 E.Data = true;
1614 Config->Exports.push_back(E);
1615 });
1616 }1823 }
16171824
1618 // Windows specific -- when we are creating a .dll file, we also1825 // Windows specific -- when we are creating a .dll file, we also
1619 // need to create a .lib file.1826 // need to create a .lib file.
1620 if (!Config->Exports.empty() || Config->DLL) {1827 if (!config->exports.empty() || config->dll) {
1621 fixupExports();1828 fixupExports();
1622 createImportLibrary(/*AsLib=*/false);1829 createImportLibrary(/*asLib=*/false);
1623 assignExportOrdinals();1830 assignExportOrdinals();
1624 }1831 }
16251832
1626 // Handle /output-def (MinGW specific).1833 // Handle /output-def (MinGW specific).
1627 if (auto *Arg = Args.getLastArg(OPT_output_def))1834 if (auto *arg = args.getLastArg(OPT_output_def))
1628 writeDefFile(Arg->getValue());1835 writeDefFile(arg->getValue());
16291836
1630 // Set extra alignment for .comm symbols1837 // Set extra alignment for .comm symbols
1631 for (auto Pair : Config->AlignComm) {1838 for (auto pair : config->alignComm) {
1632 StringRef Name = Pair.first;1839 StringRef name = pair.first;
1633 uint32_t Alignment = Pair.second;1840 uint32_t alignment = pair.second;
16341841
1635 Symbol *Sym = Symtab->find(Name);1842 Symbol *sym = symtab->find(name);
1636 if (!Sym) {1843 if (!sym) {
1637 warn("/aligncomm symbol " + Name + " not found");1844 warn("/aligncomm symbol " + name + " not found");
1638 continue;1845 continue;
1639 }1846 }
16401847
1641 // If the symbol isn't common, it must have been replaced with a regular1848 // If the symbol isn't common, it must have been replaced with a regular
1642 // symbol, which will carry its own alignment.1849 // symbol, which will carry its own alignment.
1643 auto *DC = dyn_cast<DefinedCommon>(Sym);1850 auto *dc = dyn_cast<DefinedCommon>(sym);
1644 if (!DC)1851 if (!dc)
1645 continue;1852 continue;
16461853
1647 CommonChunk *C = DC->getChunk();1854 CommonChunk *c = dc->getChunk();
1648 C->Alignment = std::max(C->Alignment, Alignment);1855 c->setAlignment(std::max(c->getAlignment(), alignment));
1649 }1856 }
16501857
1651 // Windows specific -- Create a side-by-side manifest file.1858 // Windows specific -- Create a side-by-side manifest file.
1652 if (Config->Manifest == Configuration::SideBySide)1859 if (config->manifest == Configuration::SideBySide)
1653 createSideBySideManifest();1860 createSideBySideManifest();
16541861
1655 // Handle /order. We want to do this at this moment because we1862 // Handle /order. We want to do this at this moment because we
1656 // need a complete list of comdat sections to warn on nonexistent1863 // need a complete list of comdat sections to warn on nonexistent
1657 // functions.1864 // functions.
1658 if (auto *Arg = Args.getLastArg(OPT_order))1865 if (auto *arg = args.getLastArg(OPT_order))
1659 parseOrderFile(Arg->getValue());1866 parseOrderFile(arg->getValue());
16601867
1661 // Identify unreferenced COMDAT sections.1868 // Identify unreferenced COMDAT sections.
1662 if (Config->DoGC)1869 if (config->doGC)
1663 markLive(Symtab->getChunks());1870 markLive(symtab->getChunks());
1871
1872 // Needs to happen after the last call to addFile().
1873 diagnoseMultipleResourceObjFiles();
16641874
1665 // Identify identical COMDAT sections to merge them.1875 // Identify identical COMDAT sections to merge them.
1666 if (Config->DoICF) {1876 if (config->doICF) {
1667 findKeepUniqueSections();1877 findKeepUniqueSections();
1668 doICF(Symtab->getChunks());1878 doICF(symtab->getChunks());
1669 }1879 }
16701880
1671 // Write the result.1881 // Write the result.
...@@ -1673,7 +1883,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {...@@ -1673,7 +1883,7 @@ void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {
16731883
1674 // Stop early so we can print the results.1884 // Stop early so we can print the results.
1675 Timer::root().stop();1885 Timer::root().stop();
1676 if (Config->ShowTiming)1886 if (config->showTiming)
1677 Timer::root().print();1887 Timer::root().print();
1678}1888}
16791889
deps/lld/COFF/Driver.h+58-53
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Driver.h -------------------------------------------------*- C++ -*-===//1//===- Driver.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -31,7 +30,7 @@ namespace lld {...@@ -31,7 +30,7 @@ namespace lld {
31namespace coff {30namespace coff {
3231
33class LinkerDriver;32class LinkerDriver;
34extern LinkerDriver *Driver;33extern LinkerDriver *driver;
3534
36using llvm::COFF::MachineTypes;35using llvm::COFF::MachineTypes;
37using llvm::COFF::WindowsSubsystem;36using llvm::COFF::WindowsSubsystem;
...@@ -45,65 +44,71 @@ public:...@@ -45,65 +44,71 @@ public:
45class ArgParser {44class ArgParser {
46public:45public:
47 // Concatenate LINK environment variable and given arguments and parse them.46 // Concatenate LINK environment variable and given arguments and parse them.
48 llvm::opt::InputArgList parseLINK(std::vector<const char *> Args);47 llvm::opt::InputArgList parseLINK(std::vector<const char *> args);
4948
50 // Tokenizes a given string and then parses as command line options.49 // Tokenizes a given string and then parses as command line options.
51 llvm::opt::InputArgList parse(StringRef S) { return parse(tokenize(S)); }50 llvm::opt::InputArgList parse(StringRef s) { return parse(tokenize(s)); }
5251
53 // Tokenizes a given string and then parses as command line options in52 // Tokenizes a given string and then parses as command line options in
54 // .drectve section. /EXPORT options are returned in second element53 // .drectve section. /EXPORT options are returned in second element
55 // to be processed in fastpath.54 // to be processed in fastpath.
56 std::pair<llvm::opt::InputArgList, std::vector<StringRef>>55 std::pair<llvm::opt::InputArgList, std::vector<StringRef>>
57 parseDirectives(StringRef S);56 parseDirectives(StringRef s);
5857
59private:58private:
60 // Parses command line options.59 // Parses command line options.
61 llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> Args);60 llvm::opt::InputArgList parse(llvm::ArrayRef<const char *> args);
6261
63 std::vector<const char *> tokenize(StringRef S);62 std::vector<const char *> tokenize(StringRef s);
6463
65 COFFOptTable Table;64 COFFOptTable table;
66};65};
6766
68class LinkerDriver {67class LinkerDriver {
69public:68public:
70 void link(llvm::ArrayRef<const char *> Args);69 void link(llvm::ArrayRef<const char *> args);
7170
72 // Used by the resolver to parse .drectve section contents.71 // Used by the resolver to parse .drectve section contents.
73 void parseDirectives(StringRef S);72 void parseDirectives(InputFile *file);
7473
75 // Used by ArchiveFile to enqueue members.74 // Used by ArchiveFile to enqueue members.
76 void enqueueArchiveMember(const Archive::Child &C, StringRef SymName,75 void enqueueArchiveMember(const Archive::Child &c, StringRef symName,
77 StringRef ParentName);76 StringRef parentName);
77
78 MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> mb);
7879
79 MemoryBufferRef takeBuffer(std::unique_ptr<MemoryBuffer> MB);80 void enqueuePath(StringRef path, bool wholeArchive);
8081
81private:82private:
82 std::unique_ptr<llvm::TarWriter> Tar; // for /linkrepro83 std::unique_ptr<llvm::TarWriter> tar; // for /linkrepro
8384
84 // Opens a file. Path has to be resolved already.85 // Opens a file. Path has to be resolved already.
85 MemoryBufferRef openFile(StringRef Path);86 MemoryBufferRef openFile(StringRef path);
8687
87 // Searches a file from search paths.88 // Searches a file from search paths.
88 Optional<StringRef> findFile(StringRef Filename);89 Optional<StringRef> findFile(StringRef filename);
89 Optional<StringRef> findLib(StringRef Filename);90 Optional<StringRef> findLib(StringRef filename);
90 StringRef doFindFile(StringRef Filename);91 StringRef doFindFile(StringRef filename);
91 StringRef doFindLib(StringRef Filename);92 StringRef doFindLib(StringRef filename);
92 StringRef doFindLibMinGW(StringRef Filename);93 StringRef doFindLibMinGW(StringRef filename);
9394
94 // Parses LIB environment which contains a list of search paths.95 // Parses LIB environment which contains a list of search paths.
95 void addLibSearchPaths();96 void addLibSearchPaths();
9697
97 // Library search path. The first element is always "" (current directory).98 // Library search path. The first element is always "" (current directory).
98 std::vector<StringRef> SearchPaths;99 std::vector<StringRef> searchPaths;
100
101 void maybeExportMinGWSymbols(const llvm::opt::InputArgList &args);
99102
100 // We don't want to add the same file more than once.103 // We don't want to add the same file more than once.
101 // Files are uniquified by their filesystem and file number.104 // Files are uniquified by their filesystem and file number.
102 std::set<llvm::sys::fs::UniqueID> VisitedFiles;105 std::set<llvm::sys::fs::UniqueID> visitedFiles;
106
107 std::set<std::string> visitedLibs;
103108
104 std::set<std::string> VisitedLibs;109 Symbol *addUndefined(StringRef sym);
105110
106 Symbol *addUndefined(StringRef Sym);111 StringRef mangleMaybe(Symbol *s);
107112
108 // Windows specific -- "main" is not the only main function in Windows.113 // Windows specific -- "main" is not the only main function in Windows.
109 // You can choose one from these four -- {w,}{WinMain,main}.114 // You can choose one from these four -- {w,}{WinMain,main}.
...@@ -115,60 +120,60 @@ private:...@@ -115,60 +120,60 @@ private:
115 StringRef findDefaultEntry();120 StringRef findDefaultEntry();
116 WindowsSubsystem inferSubsystem();121 WindowsSubsystem inferSubsystem();
117122
118 void addBuffer(std::unique_ptr<MemoryBuffer> MB, bool WholeArchive);123 void addBuffer(std::unique_ptr<MemoryBuffer> mb, bool wholeArchive);
119 void addArchiveBuffer(MemoryBufferRef MBRef, StringRef SymName,124 void addArchiveBuffer(MemoryBufferRef mbref, StringRef symName,
120 StringRef ParentName);125 StringRef parentName, uint64_t offsetInArchive);
121126
122 void enqueuePath(StringRef Path, bool WholeArchive);127 void enqueueTask(std::function<void()> task);
123
124 void enqueueTask(std::function<void()> Task);
125 bool run();128 bool run();
126129
127 std::list<std::function<void()>> TaskQueue;130 std::list<std::function<void()>> taskQueue;
128 std::vector<StringRef> FilePaths;131 std::vector<StringRef> filePaths;
129 std::vector<MemoryBufferRef> Resources;132 std::vector<MemoryBufferRef> resources;
130133
131 llvm::StringSet<> DirectivesExports;134 llvm::StringSet<> directivesExports;
132};135};
133136
134// Functions below this line are defined in DriverUtils.cpp.137// Functions below this line are defined in DriverUtils.cpp.
135138
136void printHelp(const char *Argv0);139void printHelp(const char *argv0);
137
138// For /machine option.
139MachineTypes getMachineType(StringRef Arg);
140StringRef machineToStr(MachineTypes MT);
141140
142// Parses a string in the form of "<integer>[,<integer>]".141// Parses a string in the form of "<integer>[,<integer>]".
143void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size = nullptr);142void parseNumbers(StringRef arg, uint64_t *addr, uint64_t *size = nullptr);
144143
145void parseGuard(StringRef Arg);144void parseGuard(StringRef arg);
146145
147// Parses a string in the form of "<integer>[.<integer>]".146// Parses a string in the form of "<integer>[.<integer>]".
148// Minor's default value is 0.147// Minor's default value is 0.
149void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor);148void parseVersion(StringRef arg, uint32_t *major, uint32_t *minor);
150149
151// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".150// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
152void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,151void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,
153 uint32_t *Minor);152 uint32_t *minor);
154153
155void parseAlternateName(StringRef);154void parseAlternateName(StringRef);
156void parseMerge(StringRef);155void parseMerge(StringRef);
157void parseSection(StringRef);156void parseSection(StringRef);
158void parseAligncomm(StringRef);157void parseAligncomm(StringRef);
159158
159// Parses a string in the form of "[:<integer>]"
160void parseFunctionPadMin(llvm::opt::Arg *a, llvm::COFF::MachineTypes machine);
161
160// Parses a string in the form of "EMBED[,=<integer>]|NO".162// Parses a string in the form of "EMBED[,=<integer>]|NO".
161void parseManifest(StringRef Arg);163void parseManifest(StringRef arg);
162164
163// Parses a string in the form of "level=<string>|uiAccess=<string>"165// Parses a string in the form of "level=<string>|uiAccess=<string>"
164void parseManifestUAC(StringRef Arg);166void parseManifestUAC(StringRef arg);
167
168// Parses a string in the form of "cd|net[,(cd|net)]*"
169void parseSwaprun(StringRef arg);
165170
166// Create a resource file containing a manifest XML.171// Create a resource file containing a manifest XML.
167std::unique_ptr<MemoryBuffer> createManifestRes();172std::unique_ptr<MemoryBuffer> createManifestRes();
168void createSideBySideManifest();173void createSideBySideManifest();
169174
170// Used for dllexported symbols.175// Used for dllexported symbols.
171Export parseExport(StringRef Arg);176Export parseExport(StringRef arg);
172void fixupExports();177void fixupExports();
173void assignExportOrdinals();178void assignExportOrdinals();
174179
...@@ -176,12 +181,12 @@ void assignExportOrdinals();...@@ -176,12 +181,12 @@ void assignExportOrdinals();
176// if value matches previous values for the key.181// if value matches previous values for the key.
177// This feature used in the directive section to reject182// This feature used in the directive section to reject
178// incompatible objects.183// incompatible objects.
179void checkFailIfMismatch(StringRef Arg);184void checkFailIfMismatch(StringRef arg, InputFile *source);
180185
181// Convert Windows resource files (.res files) to a .obj file.186// Convert Windows resource files (.res files) to a .obj file.
182MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs);187MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> mbs);
183188
184void runMSVCLinker(std::string Rsp, ArrayRef<StringRef> Objects);189void runMSVCLinker(std::string rsp, ArrayRef<StringRef> objects);
185190
186// Create enum with OPT_xxx values for each option in Options.td191// Create enum with OPT_xxx values for each option in Options.td
187enum {192enum {
deps/lld/COFF/DriverUtils.cpp+495-470
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- DriverUtils.cpp ----------------------------------------------------===//1//===- DriverUtils.cpp ----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -48,104 +47,78 @@ const uint16_t RT_MANIFEST = 24;...@@ -48,104 +47,78 @@ const uint16_t RT_MANIFEST = 24;
4847
49class Executor {48class Executor {
50public:49public:
51 explicit Executor(StringRef S) : Prog(Saver.save(S)) {}50 explicit Executor(StringRef s) : prog(saver.save(s)) {}
52 void add(StringRef S) { Args.push_back(Saver.save(S)); }51 void add(StringRef s) { args.push_back(saver.save(s)); }
53 void add(std::string &S) { Args.push_back(Saver.save(S)); }52 void add(std::string &s) { args.push_back(saver.save(s)); }
54 void add(Twine S) { Args.push_back(Saver.save(S)); }53 void add(Twine s) { args.push_back(saver.save(s)); }
55 void add(const char *S) { Args.push_back(Saver.save(S)); }54 void add(const char *s) { args.push_back(saver.save(s)); }
5655
57 void run() {56 void run() {
58 ErrorOr<std::string> ExeOrErr = sys::findProgramByName(Prog);57 ErrorOr<std::string> exeOrErr = sys::findProgramByName(prog);
59 if (auto EC = ExeOrErr.getError())58 if (auto ec = exeOrErr.getError())
60 fatal("unable to find " + Prog + " in PATH: " + EC.message());59 fatal("unable to find " + prog + " in PATH: " + ec.message());
61 StringRef Exe = Saver.save(*ExeOrErr);60 StringRef exe = saver.save(*exeOrErr);
62 Args.insert(Args.begin(), Exe);61 args.insert(args.begin(), exe);
6362
64 if (sys::ExecuteAndWait(Args[0], Args) != 0)63 if (sys::ExecuteAndWait(args[0], args) != 0)
65 fatal("ExecuteAndWait failed: " +64 fatal("ExecuteAndWait failed: " +
66 llvm::join(Args.begin(), Args.end(), " "));65 llvm::join(args.begin(), args.end(), " "));
67 }66 }
6867
69private:68private:
70 StringRef Prog;69 StringRef prog;
71 std::vector<StringRef> Args;70 std::vector<StringRef> args;
72};71};
7372
74} // anonymous namespace73} // anonymous namespace
7574
76// Returns /machine's value.
77MachineTypes getMachineType(StringRef S) {
78 MachineTypes MT = StringSwitch<MachineTypes>(S.lower())
79 .Cases("x64", "amd64", AMD64)
80 .Cases("x86", "i386", I386)
81 .Case("arm", ARMNT)
82 .Case("arm64", ARM64)
83 .Default(IMAGE_FILE_MACHINE_UNKNOWN);
84 if (MT != IMAGE_FILE_MACHINE_UNKNOWN)
85 return MT;
86 fatal("unknown /machine argument: " + S);
87}
88
89StringRef machineToStr(MachineTypes MT) {
90 switch (MT) {
91 case ARMNT:
92 return "arm";
93 case ARM64:
94 return "arm64";
95 case AMD64:
96 return "x64";
97 case I386:
98 return "x86";
99 default:
100 llvm_unreachable("unknown machine type");
101 }
102}
103
104// Parses a string in the form of "<integer>[,<integer>]".75// Parses a string in the form of "<integer>[,<integer>]".
105void parseNumbers(StringRef Arg, uint64_t *Addr, uint64_t *Size) {76void parseNumbers(StringRef arg, uint64_t *addr, uint64_t *size) {
106 StringRef S1, S2;77 StringRef s1, s2;
107 std::tie(S1, S2) = Arg.split(',');78 std::tie(s1, s2) = arg.split(',');
108 if (S1.getAsInteger(0, *Addr))79 if (s1.getAsInteger(0, *addr))
109 fatal("invalid number: " + S1);80 fatal("invalid number: " + s1);
110 if (Size && !S2.empty() && S2.getAsInteger(0, *Size))81 if (size && !s2.empty() && s2.getAsInteger(0, *size))
111 fatal("invalid number: " + S2);82 fatal("invalid number: " + s2);
112}83}
11384
114// Parses a string in the form of "<integer>[.<integer>]".85// Parses a string in the form of "<integer>[.<integer>]".
115// If second number is not present, Minor is set to 0.86// If second number is not present, Minor is set to 0.
116void parseVersion(StringRef Arg, uint32_t *Major, uint32_t *Minor) {87void parseVersion(StringRef arg, uint32_t *major, uint32_t *minor) {
117 StringRef S1, S2;88 StringRef s1, s2;
118 std::tie(S1, S2) = Arg.split('.');89 std::tie(s1, s2) = arg.split('.');
119 if (S1.getAsInteger(0, *Major))90 if (s1.getAsInteger(0, *major))
120 fatal("invalid number: " + S1);91 fatal("invalid number: " + s1);
121 *Minor = 0;92 *minor = 0;
122 if (!S2.empty() && S2.getAsInteger(0, *Minor))93 if (!s2.empty() && s2.getAsInteger(0, *minor))
123 fatal("invalid number: " + S2);94 fatal("invalid number: " + s2);
124}95}
12596
126void parseGuard(StringRef FullArg) {97void parseGuard(StringRef fullArg) {
127 SmallVector<StringRef, 1> SplitArgs;98 SmallVector<StringRef, 1> splitArgs;
128 FullArg.split(SplitArgs, ",");99 fullArg.split(splitArgs, ",");
129 for (StringRef Arg : SplitArgs) {100 for (StringRef arg : splitArgs) {
130 if (Arg.equals_lower("no"))101 if (arg.equals_lower("no"))
131 Config->GuardCF = GuardCFLevel::Off;102 config->guardCF = GuardCFLevel::Off;
132 else if (Arg.equals_lower("nolongjmp"))103 else if (arg.equals_lower("nolongjmp"))
133 Config->GuardCF = GuardCFLevel::NoLongJmp;104 config->guardCF = GuardCFLevel::NoLongJmp;
134 else if (Arg.equals_lower("cf") || Arg.equals_lower("longjmp"))105 else if (arg.equals_lower("cf") || arg.equals_lower("longjmp"))
135 Config->GuardCF = GuardCFLevel::Full;106 config->guardCF = GuardCFLevel::Full;
136 else107 else
137 fatal("invalid argument to /guard: " + Arg);108 fatal("invalid argument to /guard: " + arg);
138 }109 }
139}110}
140111
141// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".112// Parses a string in the form of "<subsystem>[,<integer>[.<integer>]]".
142void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,113void parseSubsystem(StringRef arg, WindowsSubsystem *sys, uint32_t *major,
143 uint32_t *Minor) {114 uint32_t *minor) {
144 StringRef SysStr, Ver;115 StringRef sysStr, ver;
145 std::tie(SysStr, Ver) = Arg.split(',');116 std::tie(sysStr, ver) = arg.split(',');
146 *Sys = StringSwitch<WindowsSubsystem>(SysStr.lower())117 std::string sysStrLower = sysStr.lower();
118 *sys = StringSwitch<WindowsSubsystem>(sysStrLower)
147 .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)119 .Case("boot_application", IMAGE_SUBSYSTEM_WINDOWS_BOOT_APPLICATION)
148 .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI)120 .Case("console", IMAGE_SUBSYSTEM_WINDOWS_CUI)
121 .Case("default", IMAGE_SUBSYSTEM_UNKNOWN)
149 .Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION)122 .Case("efi_application", IMAGE_SUBSYSTEM_EFI_APPLICATION)
150 .Case("efi_boot_service_driver", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)123 .Case("efi_boot_service_driver", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER)
151 .Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM)124 .Case("efi_rom", IMAGE_SUBSYSTEM_EFI_ROM)
...@@ -154,175 +127,217 @@ void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,...@@ -154,175 +127,217 @@ void parseSubsystem(StringRef Arg, WindowsSubsystem *Sys, uint32_t *Major,
154 .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI)127 .Case("posix", IMAGE_SUBSYSTEM_POSIX_CUI)
155 .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI)128 .Case("windows", IMAGE_SUBSYSTEM_WINDOWS_GUI)
156 .Default(IMAGE_SUBSYSTEM_UNKNOWN);129 .Default(IMAGE_SUBSYSTEM_UNKNOWN);
157 if (*Sys == IMAGE_SUBSYSTEM_UNKNOWN)130 if (*sys == IMAGE_SUBSYSTEM_UNKNOWN && sysStrLower != "default")
158 fatal("unknown subsystem: " + SysStr);131 fatal("unknown subsystem: " + sysStr);
159 if (!Ver.empty())132 if (!ver.empty())
160 parseVersion(Ver, Major, Minor);133 parseVersion(ver, major, minor);
161}134}
162135
163// Parse a string of the form of "<from>=<to>".136// Parse a string of the form of "<from>=<to>".
164// Results are directly written to Config.137// Results are directly written to Config.
165void parseAlternateName(StringRef S) {138void parseAlternateName(StringRef s) {
166 StringRef From, To;139 StringRef from, to;
167 std::tie(From, To) = S.split('=');140 std::tie(from, to) = s.split('=');
168 if (From.empty() || To.empty())141 if (from.empty() || to.empty())
169 fatal("/alternatename: invalid argument: " + S);142 fatal("/alternatename: invalid argument: " + s);
170 auto It = Config->AlternateNames.find(From);143 auto it = config->alternateNames.find(from);
171 if (It != Config->AlternateNames.end() && It->second != To)144 if (it != config->alternateNames.end() && it->second != to)
172 fatal("/alternatename: conflicts: " + S);145 fatal("/alternatename: conflicts: " + s);
173 Config->AlternateNames.insert(It, std::make_pair(From, To));146 config->alternateNames.insert(it, std::make_pair(from, to));
174}147}
175148
176// Parse a string of the form of "<from>=<to>".149// Parse a string of the form of "<from>=<to>".
177// Results are directly written to Config.150// Results are directly written to Config.
178void parseMerge(StringRef S) {151void parseMerge(StringRef s) {
179 StringRef From, To;152 StringRef from, to;
180 std::tie(From, To) = S.split('=');153 std::tie(from, to) = s.split('=');
181 if (From.empty() || To.empty())154 if (from.empty() || to.empty())
182 fatal("/merge: invalid argument: " + S);155 fatal("/merge: invalid argument: " + s);
183 if (From == ".rsrc" || To == ".rsrc")156 if (from == ".rsrc" || to == ".rsrc")
184 fatal("/merge: cannot merge '.rsrc' with any section");157 fatal("/merge: cannot merge '.rsrc' with any section");
185 if (From == ".reloc" || To == ".reloc")158 if (from == ".reloc" || to == ".reloc")
186 fatal("/merge: cannot merge '.reloc' with any section");159 fatal("/merge: cannot merge '.reloc' with any section");
187 auto Pair = Config->Merge.insert(std::make_pair(From, To));160 auto pair = config->merge.insert(std::make_pair(from, to));
188 bool Inserted = Pair.second;161 bool inserted = pair.second;
189 if (!Inserted) {162 if (!inserted) {
190 StringRef Existing = Pair.first->second;163 StringRef existing = pair.first->second;
191 if (Existing != To)164 if (existing != to)
192 warn(S + ": already merged into " + Existing);165 warn(s + ": already merged into " + existing);
193 }166 }
194}167}
195168
196static uint32_t parseSectionAttributes(StringRef S) {169static uint32_t parseSectionAttributes(StringRef s) {
197 uint32_t Ret = 0;170 uint32_t ret = 0;
198 for (char C : S.lower()) {171 for (char c : s.lower()) {
199 switch (C) {172 switch (c) {
200 case 'd':173 case 'd':
201 Ret |= IMAGE_SCN_MEM_DISCARDABLE;174 ret |= IMAGE_SCN_MEM_DISCARDABLE;
202 break;175 break;
203 case 'e':176 case 'e':
204 Ret |= IMAGE_SCN_MEM_EXECUTE;177 ret |= IMAGE_SCN_MEM_EXECUTE;
205 break;178 break;
206 case 'k':179 case 'k':
207 Ret |= IMAGE_SCN_MEM_NOT_CACHED;180 ret |= IMAGE_SCN_MEM_NOT_CACHED;
208 break;181 break;
209 case 'p':182 case 'p':
210 Ret |= IMAGE_SCN_MEM_NOT_PAGED;183 ret |= IMAGE_SCN_MEM_NOT_PAGED;
211 break;184 break;
212 case 'r':185 case 'r':
213 Ret |= IMAGE_SCN_MEM_READ;186 ret |= IMAGE_SCN_MEM_READ;
214 break;187 break;
215 case 's':188 case 's':
216 Ret |= IMAGE_SCN_MEM_SHARED;189 ret |= IMAGE_SCN_MEM_SHARED;
217 break;190 break;
218 case 'w':191 case 'w':
219 Ret |= IMAGE_SCN_MEM_WRITE;192 ret |= IMAGE_SCN_MEM_WRITE;
220 break;193 break;
221 default:194 default:
222 fatal("/section: invalid argument: " + S);195 fatal("/section: invalid argument: " + s);
223 }196 }
224 }197 }
225 return Ret;198 return ret;
226}199}
227200
228// Parses /section option argument.201// Parses /section option argument.
229void parseSection(StringRef S) {202void parseSection(StringRef s) {
230 StringRef Name, Attrs;203 StringRef name, attrs;
231 std::tie(Name, Attrs) = S.split(',');204 std::tie(name, attrs) = s.split(',');
232 if (Name.empty() || Attrs.empty())205 if (name.empty() || attrs.empty())
233 fatal("/section: invalid argument: " + S);206 fatal("/section: invalid argument: " + s);
234 Config->Section[Name] = parseSectionAttributes(Attrs);207 config->section[name] = parseSectionAttributes(attrs);
235}208}
236209
237// Parses /aligncomm option argument.210// Parses /aligncomm option argument.
238void parseAligncomm(StringRef S) {211void parseAligncomm(StringRef s) {
239 StringRef Name, Align;212 StringRef name, align;
240 std::tie(Name, Align) = S.split(',');213 std::tie(name, align) = s.split(',');
241 if (Name.empty() || Align.empty()) {214 if (name.empty() || align.empty()) {
242 error("/aligncomm: invalid argument: " + S);215 error("/aligncomm: invalid argument: " + s);
216 return;
217 }
218 int v;
219 if (align.getAsInteger(0, v)) {
220 error("/aligncomm: invalid argument: " + s);
243 return;221 return;
244 }222 }
245 int V;223 config->alignComm[name] = std::max(config->alignComm[name], 1 << v);
246 if (Align.getAsInteger(0, V)) {224}
247 error("/aligncomm: invalid argument: " + S);225
226// Parses /functionpadmin option argument.
227void parseFunctionPadMin(llvm::opt::Arg *a, llvm::COFF::MachineTypes machine) {
228 StringRef arg = a->getNumValues() ? a->getValue() : "";
229 if (!arg.empty()) {
230 // Optional padding in bytes is given.
231 if (arg.getAsInteger(0, config->functionPadMin))
232 error("/functionpadmin: invalid argument: " + arg);
248 return;233 return;
249 }234 }
250 Config->AlignComm[Name] = std::max(Config->AlignComm[Name], 1 << V);235 // No optional argument given.
236 // Set default padding based on machine, similar to link.exe.
237 // There is no default padding for ARM platforms.
238 if (machine == I386) {
239 config->functionPadMin = 5;
240 } else if (machine == AMD64) {
241 config->functionPadMin = 6;
242 } else {
243 error("/functionpadmin: invalid argument for this machine: " + arg);
244 }
251}245}
252246
253// Parses a string in the form of "EMBED[,=<integer>]|NO".247// Parses a string in the form of "EMBED[,=<integer>]|NO".
254// Results are directly written to Config.248// Results are directly written to Config.
255void parseManifest(StringRef Arg) {249void parseManifest(StringRef arg) {
256 if (Arg.equals_lower("no")) {250 if (arg.equals_lower("no")) {
257 Config->Manifest = Configuration::No;251 config->manifest = Configuration::No;
258 return;252 return;
259 }253 }
260 if (!Arg.startswith_lower("embed"))254 if (!arg.startswith_lower("embed"))
261 fatal("invalid option " + Arg);255 fatal("invalid option " + arg);
262 Config->Manifest = Configuration::Embed;256 config->manifest = Configuration::Embed;
263 Arg = Arg.substr(strlen("embed"));257 arg = arg.substr(strlen("embed"));
264 if (Arg.empty())258 if (arg.empty())
265 return;259 return;
266 if (!Arg.startswith_lower(",id="))260 if (!arg.startswith_lower(",id="))
267 fatal("invalid option " + Arg);261 fatal("invalid option " + arg);
268 Arg = Arg.substr(strlen(",id="));262 arg = arg.substr(strlen(",id="));
269 if (Arg.getAsInteger(0, Config->ManifestID))263 if (arg.getAsInteger(0, config->manifestID))
270 fatal("invalid option " + Arg);264 fatal("invalid option " + arg);
271}265}
272266
273// Parses a string in the form of "level=<string>|uiAccess=<string>|NO".267// Parses a string in the form of "level=<string>|uiAccess=<string>|NO".
274// Results are directly written to Config.268// Results are directly written to Config.
275void parseManifestUAC(StringRef Arg) {269void parseManifestUAC(StringRef arg) {
276 if (Arg.equals_lower("no")) {270 if (arg.equals_lower("no")) {
277 Config->ManifestUAC = false;271 config->manifestUAC = false;
278 return;272 return;
279 }273 }
280 for (;;) {274 for (;;) {
281 Arg = Arg.ltrim();275 arg = arg.ltrim();
282 if (Arg.empty())276 if (arg.empty())
283 return;277 return;
284 if (Arg.startswith_lower("level=")) {278 if (arg.startswith_lower("level=")) {
285 Arg = Arg.substr(strlen("level="));279 arg = arg.substr(strlen("level="));
286 std::tie(Config->ManifestLevel, Arg) = Arg.split(" ");280 std::tie(config->manifestLevel, arg) = arg.split(" ");
287 continue;281 continue;
288 }282 }
289 if (Arg.startswith_lower("uiaccess=")) {283 if (arg.startswith_lower("uiaccess=")) {
290 Arg = Arg.substr(strlen("uiaccess="));284 arg = arg.substr(strlen("uiaccess="));
291 std::tie(Config->ManifestUIAccess, Arg) = Arg.split(" ");285 std::tie(config->manifestUIAccess, arg) = arg.split(" ");
292 continue;286 continue;
293 }287 }
294 fatal("invalid option " + Arg);288 fatal("invalid option " + arg);
295 }289 }
296}290}
297291
292// Parses a string in the form of "cd|net[,(cd|net)]*"
293// Results are directly written to Config.
294void parseSwaprun(StringRef arg) {
295 do {
296 StringRef swaprun, newArg;
297 std::tie(swaprun, newArg) = arg.split(',');
298 if (swaprun.equals_lower("cd"))
299 config->swaprunCD = true;
300 else if (swaprun.equals_lower("net"))
301 config->swaprunNet = true;
302 else if (swaprun.empty())
303 error("/swaprun: missing argument");
304 else
305 error("/swaprun: invalid argument: " + swaprun);
306 // To catch trailing commas, e.g. `/spawrun:cd,`
307 if (newArg.empty() && arg.endswith(","))
308 error("/swaprun: missing argument");
309 arg = newArg;
310 } while (!arg.empty());
311}
312
298// An RAII temporary file class that automatically removes a temporary file.313// An RAII temporary file class that automatically removes a temporary file.
299namespace {314namespace {
300class TemporaryFile {315class TemporaryFile {
301public:316public:
302 TemporaryFile(StringRef Prefix, StringRef Extn, StringRef Contents = "") {317 TemporaryFile(StringRef prefix, StringRef extn, StringRef contents = "") {
303 SmallString<128> S;318 SmallString<128> s;
304 if (auto EC = sys::fs::createTemporaryFile("lld-" + Prefix, Extn, S))319 if (auto ec = sys::fs::createTemporaryFile("lld-" + prefix, extn, s))
305 fatal("cannot create a temporary file: " + EC.message());320 fatal("cannot create a temporary file: " + ec.message());
306 Path = S.str();321 path = s.str();
307322
308 if (!Contents.empty()) {323 if (!contents.empty()) {
309 std::error_code EC;324 std::error_code ec;
310 raw_fd_ostream OS(Path, EC, sys::fs::F_None);325 raw_fd_ostream os(path, ec, sys::fs::F_None);
311 if (EC)326 if (ec)
312 fatal("failed to open " + Path + ": " + EC.message());327 fatal("failed to open " + path + ": " + ec.message());
313 OS << Contents;328 os << contents;
314 }329 }
315 }330 }
316331
317 TemporaryFile(TemporaryFile &&Obj) {332 TemporaryFile(TemporaryFile &&obj) {
318 std::swap(Path, Obj.Path);333 std::swap(path, obj.path);
319 }334 }
320335
321 ~TemporaryFile() {336 ~TemporaryFile() {
322 if (Path.empty())337 if (path.empty())
323 return;338 return;
324 if (sys::fs::remove(Path))339 if (sys::fs::remove(path))
325 fatal("failed to remove " + Path);340 fatal("failed to remove " + path);
326 }341 }
327342
328 // Returns a memory buffer of this temporary file.343 // Returns a memory buffer of this temporary file.
...@@ -330,387 +345,390 @@ public:...@@ -330,387 +345,390 @@ public:
330 // so it is safe to remove the file immediately after this function345 // so it is safe to remove the file immediately after this function
331 // is called (you cannot remove an opened file on Windows.)346 // is called (you cannot remove an opened file on Windows.)
332 std::unique_ptr<MemoryBuffer> getMemoryBuffer() {347 std::unique_ptr<MemoryBuffer> getMemoryBuffer() {
333 // IsVolatileSize=true forces MemoryBuffer to not use mmap().348 // IsVolatile=true forces MemoryBuffer to not use mmap().
334 return CHECK(MemoryBuffer::getFile(Path, /*FileSize=*/-1,349 return CHECK(MemoryBuffer::getFile(path, /*FileSize=*/-1,
335 /*RequiresNullTerminator=*/false,350 /*RequiresNullTerminator=*/false,
336 /*IsVolatileSize=*/true),351 /*IsVolatile=*/true),
337 "could not open " + Path);352 "could not open " + path);
338 }353 }
339354
340 std::string Path;355 std::string path;
341};356};
342}357}
343358
344static std::string createDefaultXml() {359static std::string createDefaultXml() {
345 std::string Ret;360 std::string ret;
346 raw_string_ostream OS(Ret);361 raw_string_ostream os(ret);
347362
348 // Emit the XML. Note that we do *not* verify that the XML attributes are363 // Emit the XML. Note that we do *not* verify that the XML attributes are
349 // syntactically correct. This is intentional for link.exe compatibility.364 // syntactically correct. This is intentional for link.exe compatibility.
350 OS << "<?xml version=\"1.0\" standalone=\"yes\"?>\n"365 os << "<?xml version=\"1.0\" standalone=\"yes\"?>\n"
351 << "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\"\n"366 << "<assembly xmlns=\"urn:schemas-microsoft-com:asm.v1\"\n"
352 << " manifestVersion=\"1.0\">\n";367 << " manifestVersion=\"1.0\">\n";
353 if (Config->ManifestUAC) {368 if (config->manifestUAC) {
354 OS << " <trustInfo>\n"369 os << " <trustInfo>\n"
355 << " <security>\n"370 << " <security>\n"
356 << " <requestedPrivileges>\n"371 << " <requestedPrivileges>\n"
357 << " <requestedExecutionLevel level=" << Config->ManifestLevel372 << " <requestedExecutionLevel level=" << config->manifestLevel
358 << " uiAccess=" << Config->ManifestUIAccess << "/>\n"373 << " uiAccess=" << config->manifestUIAccess << "/>\n"
359 << " </requestedPrivileges>\n"374 << " </requestedPrivileges>\n"
360 << " </security>\n"375 << " </security>\n"
361 << " </trustInfo>\n";376 << " </trustInfo>\n";
362 }377 }
363 if (!Config->ManifestDependency.empty()) {378 if (!config->manifestDependency.empty()) {
364 OS << " <dependency>\n"379 os << " <dependency>\n"
365 << " <dependentAssembly>\n"380 << " <dependentAssembly>\n"
366 << " <assemblyIdentity " << Config->ManifestDependency << " />\n"381 << " <assemblyIdentity " << config->manifestDependency << " />\n"
367 << " </dependentAssembly>\n"382 << " </dependentAssembly>\n"
368 << " </dependency>\n";383 << " </dependency>\n";
369 }384 }
370 OS << "</assembly>\n";385 os << "</assembly>\n";
371 return OS.str();386 return os.str();
372}387}
373388
374static std::string createManifestXmlWithInternalMt(StringRef DefaultXml) {389static std::string createManifestXmlWithInternalMt(StringRef defaultXml) {
375 std::unique_ptr<MemoryBuffer> DefaultXmlCopy =390 std::unique_ptr<MemoryBuffer> defaultXmlCopy =
376 MemoryBuffer::getMemBufferCopy(DefaultXml);391 MemoryBuffer::getMemBufferCopy(defaultXml);
377392
378 windows_manifest::WindowsManifestMerger Merger;393 windows_manifest::WindowsManifestMerger merger;
379 if (auto E = Merger.merge(*DefaultXmlCopy.get()))394 if (auto e = merger.merge(*defaultXmlCopy.get()))
380 fatal("internal manifest tool failed on default xml: " +395 fatal("internal manifest tool failed on default xml: " +
381 toString(std::move(E)));396 toString(std::move(e)));
382397
383 for (StringRef Filename : Config->ManifestInput) {398 for (StringRef filename : config->manifestInput) {
384 std::unique_ptr<MemoryBuffer> Manifest =399 std::unique_ptr<MemoryBuffer> manifest =
385 check(MemoryBuffer::getFile(Filename));400 check(MemoryBuffer::getFile(filename));
386 if (auto E = Merger.merge(*Manifest.get()))401 if (auto e = merger.merge(*manifest.get()))
387 fatal("internal manifest tool failed on file " + Filename + ": " +402 fatal("internal manifest tool failed on file " + filename + ": " +
388 toString(std::move(E)));403 toString(std::move(e)));
389 }404 }
390405
391 return Merger.getMergedManifest().get()->getBuffer();406 return merger.getMergedManifest().get()->getBuffer();
392}407}
393408
394static std::string createManifestXmlWithExternalMt(StringRef DefaultXml) {409static std::string createManifestXmlWithExternalMt(StringRef defaultXml) {
395 // Create the default manifest file as a temporary file.410 // Create the default manifest file as a temporary file.
396 TemporaryFile Default("defaultxml", "manifest");411 TemporaryFile Default("defaultxml", "manifest");
397 std::error_code EC;412 std::error_code ec;
398 raw_fd_ostream OS(Default.Path, EC, sys::fs::F_Text);413 raw_fd_ostream os(Default.path, ec, sys::fs::F_Text);
399 if (EC)414 if (ec)
400 fatal("failed to open " + Default.Path + ": " + EC.message());415 fatal("failed to open " + Default.path + ": " + ec.message());
401 OS << DefaultXml;416 os << defaultXml;
402 OS.close();417 os.close();
403418
404 // Merge user-supplied manifests if they are given. Since libxml2 is not419 // Merge user-supplied manifests if they are given. Since libxml2 is not
405 // enabled, we must shell out to Microsoft's mt.exe tool.420 // enabled, we must shell out to Microsoft's mt.exe tool.
406 TemporaryFile User("user", "manifest");421 TemporaryFile user("user", "manifest");
407422
408 Executor E("mt.exe");423 Executor e("mt.exe");
409 E.add("/manifest");424 e.add("/manifest");
410 E.add(Default.Path);425 e.add(Default.path);
411 for (StringRef Filename : Config->ManifestInput) {426 for (StringRef filename : config->manifestInput) {
412 E.add("/manifest");427 e.add("/manifest");
413 E.add(Filename);428 e.add(filename);
414 }429 }
415 E.add("/nologo");430 e.add("/nologo");
416 E.add("/out:" + StringRef(User.Path));431 e.add("/out:" + StringRef(user.path));
417 E.run();432 e.run();
418433
419 return CHECK(MemoryBuffer::getFile(User.Path), "could not open " + User.Path)434 return CHECK(MemoryBuffer::getFile(user.path), "could not open " + user.path)
420 .get()435 .get()
421 ->getBuffer();436 ->getBuffer();
422}437}
423438
424static std::string createManifestXml() {439static std::string createManifestXml() {
425 std::string DefaultXml = createDefaultXml();440 std::string defaultXml = createDefaultXml();
426 if (Config->ManifestInput.empty())441 if (config->manifestInput.empty())
427 return DefaultXml;442 return defaultXml;
428443
429 if (windows_manifest::isAvailable())444 if (windows_manifest::isAvailable())
430 return createManifestXmlWithInternalMt(DefaultXml);445 return createManifestXmlWithInternalMt(defaultXml);
431446
432 return createManifestXmlWithExternalMt(DefaultXml);447 return createManifestXmlWithExternalMt(defaultXml);
433}448}
434449
435static std::unique_ptr<WritableMemoryBuffer>450static std::unique_ptr<WritableMemoryBuffer>
436createMemoryBufferForManifestRes(size_t ManifestSize) {451createMemoryBufferForManifestRes(size_t manifestSize) {
437 size_t ResSize = alignTo(452 size_t resSize = alignTo(
438 object::WIN_RES_MAGIC_SIZE + object::WIN_RES_NULL_ENTRY_SIZE +453 object::WIN_RES_MAGIC_SIZE + object::WIN_RES_NULL_ENTRY_SIZE +
439 sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) +454 sizeof(object::WinResHeaderPrefix) + sizeof(object::WinResIDs) +
440 sizeof(object::WinResHeaderSuffix) + ManifestSize,455 sizeof(object::WinResHeaderSuffix) + manifestSize,
441 object::WIN_RES_DATA_ALIGNMENT);456 object::WIN_RES_DATA_ALIGNMENT);
442 return WritableMemoryBuffer::getNewMemBuffer(ResSize, Config->OutputFile +457 return WritableMemoryBuffer::getNewMemBuffer(resSize, config->outputFile +
443 ".manifest.res");458 ".manifest.res");
444}459}
445460
446static void writeResFileHeader(char *&Buf) {461static void writeResFileHeader(char *&buf) {
447 memcpy(Buf, COFF::WinResMagic, sizeof(COFF::WinResMagic));462 memcpy(buf, COFF::WinResMagic, sizeof(COFF::WinResMagic));
448 Buf += sizeof(COFF::WinResMagic);463 buf += sizeof(COFF::WinResMagic);
449 memset(Buf, 0, object::WIN_RES_NULL_ENTRY_SIZE);464 memset(buf, 0, object::WIN_RES_NULL_ENTRY_SIZE);
450 Buf += object::WIN_RES_NULL_ENTRY_SIZE;465 buf += object::WIN_RES_NULL_ENTRY_SIZE;
451}466}
452467
453static void writeResEntryHeader(char *&Buf, size_t ManifestSize) {468static void writeResEntryHeader(char *&buf, size_t manifestSize) {
454 // Write the prefix.469 // Write the prefix.
455 auto *Prefix = reinterpret_cast<object::WinResHeaderPrefix *>(Buf);470 auto *prefix = reinterpret_cast<object::WinResHeaderPrefix *>(buf);
456 Prefix->DataSize = ManifestSize;471 prefix->DataSize = manifestSize;
457 Prefix->HeaderSize = sizeof(object::WinResHeaderPrefix) +472 prefix->HeaderSize = sizeof(object::WinResHeaderPrefix) +
458 sizeof(object::WinResIDs) +473 sizeof(object::WinResIDs) +
459 sizeof(object::WinResHeaderSuffix);474 sizeof(object::WinResHeaderSuffix);
460 Buf += sizeof(object::WinResHeaderPrefix);475 buf += sizeof(object::WinResHeaderPrefix);
461476
462 // Write the Type/Name IDs.477 // Write the Type/Name IDs.
463 auto *IDs = reinterpret_cast<object::WinResIDs *>(Buf);478 auto *iDs = reinterpret_cast<object::WinResIDs *>(buf);
464 IDs->setType(RT_MANIFEST);479 iDs->setType(RT_MANIFEST);
465 IDs->setName(Config->ManifestID);480 iDs->setName(config->manifestID);
466 Buf += sizeof(object::WinResIDs);481 buf += sizeof(object::WinResIDs);
467482
468 // Write the suffix.483 // Write the suffix.
469 auto *Suffix = reinterpret_cast<object::WinResHeaderSuffix *>(Buf);484 auto *suffix = reinterpret_cast<object::WinResHeaderSuffix *>(buf);
470 Suffix->DataVersion = 0;485 suffix->DataVersion = 0;
471 Suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE;486 suffix->MemoryFlags = object::WIN_RES_PURE_MOVEABLE;
472 Suffix->Language = SUBLANG_ENGLISH_US;487 suffix->Language = SUBLANG_ENGLISH_US;
473 Suffix->Version = 0;488 suffix->Version = 0;
474 Suffix->Characteristics = 0;489 suffix->Characteristics = 0;
475 Buf += sizeof(object::WinResHeaderSuffix);490 buf += sizeof(object::WinResHeaderSuffix);
476}491}
477492
478// Create a resource file containing a manifest XML.493// Create a resource file containing a manifest XML.
479std::unique_ptr<MemoryBuffer> createManifestRes() {494std::unique_ptr<MemoryBuffer> createManifestRes() {
480 std::string Manifest = createManifestXml();495 std::string manifest = createManifestXml();
481496
482 std::unique_ptr<WritableMemoryBuffer> Res =497 std::unique_ptr<WritableMemoryBuffer> res =
483 createMemoryBufferForManifestRes(Manifest.size());498 createMemoryBufferForManifestRes(manifest.size());
484499
485 char *Buf = Res->getBufferStart();500 char *buf = res->getBufferStart();
486 writeResFileHeader(Buf);501 writeResFileHeader(buf);
487 writeResEntryHeader(Buf, Manifest.size());502 writeResEntryHeader(buf, manifest.size());
488503
489 // Copy the manifest data into the .res file.504 // Copy the manifest data into the .res file.
490 std::copy(Manifest.begin(), Manifest.end(), Buf);505 std::copy(manifest.begin(), manifest.end(), buf);
491 return std::move(Res);506 return std::move(res);
492}507}
493508
494void createSideBySideManifest() {509void createSideBySideManifest() {
495 std::string Path = Config->ManifestFile;510 std::string path = config->manifestFile;
496 if (Path == "")511 if (path == "")
497 Path = Config->OutputFile + ".manifest";512 path = config->outputFile + ".manifest";
498 std::error_code EC;513 std::error_code ec;
499 raw_fd_ostream Out(Path, EC, sys::fs::F_Text);514 raw_fd_ostream out(path, ec, sys::fs::F_Text);
500 if (EC)515 if (ec)
501 fatal("failed to create manifest: " + EC.message());516 fatal("failed to create manifest: " + ec.message());
502 Out << createManifestXml();517 out << createManifestXml();
503}518}
504519
505// Parse a string in the form of520// Parse a string in the form of
506// "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]"521// "<name>[=<internalname>][,@ordinal[,NONAME]][,DATA][,PRIVATE]"
507// or "<name>=<dllname>.<name>".522// or "<name>=<dllname>.<name>".
508// Used for parsing /export arguments.523// Used for parsing /export arguments.
509Export parseExport(StringRef Arg) {524Export parseExport(StringRef arg) {
510 Export E;525 Export e;
511 StringRef Rest;526 StringRef rest;
512 std::tie(E.Name, Rest) = Arg.split(",");527 std::tie(e.name, rest) = arg.split(",");
513 if (E.Name.empty())528 if (e.name.empty())
514 goto err;529 goto err;
515530
516 if (E.Name.contains('=')) {531 if (e.name.contains('=')) {
517 StringRef X, Y;532 StringRef x, y;
518 std::tie(X, Y) = E.Name.split("=");533 std::tie(x, y) = e.name.split("=");
519534
520 // If "<name>=<dllname>.<name>".535 // If "<name>=<dllname>.<name>".
521 if (Y.contains(".")) {536 if (y.contains(".")) {
522 E.Name = X;537 e.name = x;
523 E.ForwardTo = Y;538 e.forwardTo = y;
524 return E;539 return e;
525 }540 }
526541
527 E.ExtName = X;542 e.extName = x;
528 E.Name = Y;543 e.name = y;
529 if (E.Name.empty())544 if (e.name.empty())
530 goto err;545 goto err;
531 }546 }
532547
533 // If "<name>=<internalname>[,@ordinal[,NONAME]][,DATA][,PRIVATE]"548 // If "<name>=<internalname>[,@ordinal[,NONAME]][,DATA][,PRIVATE]"
534 while (!Rest.empty()) {549 while (!rest.empty()) {
535 StringRef Tok;550 StringRef tok;
536 std::tie(Tok, Rest) = Rest.split(",");551 std::tie(tok, rest) = rest.split(",");
537 if (Tok.equals_lower("noname")) {552 if (tok.equals_lower("noname")) {
538 if (E.Ordinal == 0)553 if (e.ordinal == 0)
539 goto err;554 goto err;
540 E.Noname = true;555 e.noname = true;
541 continue;556 continue;
542 }557 }
543 if (Tok.equals_lower("data")) {558 if (tok.equals_lower("data")) {
544 E.Data = true;559 e.data = true;
545 continue;560 continue;
546 }561 }
547 if (Tok.equals_lower("constant")) {562 if (tok.equals_lower("constant")) {
548 E.Constant = true;563 e.constant = true;
549 continue;564 continue;
550 }565 }
551 if (Tok.equals_lower("private")) {566 if (tok.equals_lower("private")) {
552 E.Private = true;567 e.isPrivate = true;
553 continue;568 continue;
554 }569 }
555 if (Tok.startswith("@")) {570 if (tok.startswith("@")) {
556 int32_t Ord;571 int32_t ord;
557 if (Tok.substr(1).getAsInteger(0, Ord))572 if (tok.substr(1).getAsInteger(0, ord))
558 goto err;573 goto err;
559 if (Ord <= 0 || 65535 < Ord)574 if (ord <= 0 || 65535 < ord)
560 goto err;575 goto err;
561 E.Ordinal = Ord;576 e.ordinal = ord;
562 continue;577 continue;
563 }578 }
564 goto err;579 goto err;
565 }580 }
566 return E;581 return e;
567582
568err:583err:
569 fatal("invalid /export: " + Arg);584 fatal("invalid /export: " + arg);
570}585}
571586
572static StringRef undecorate(StringRef Sym) {587static StringRef undecorate(StringRef sym) {
573 if (Config->Machine != I386)588 if (config->machine != I386)
574 return Sym;589 return sym;
575 // In MSVC mode, a fully decorated stdcall function is exported590 // In MSVC mode, a fully decorated stdcall function is exported
576 // as-is with the leading underscore (with type IMPORT_NAME).591 // as-is with the leading underscore (with type IMPORT_NAME).
577 // In MinGW mode, a decorated stdcall function gets the underscore592 // In MinGW mode, a decorated stdcall function gets the underscore
578 // removed, just like normal cdecl functions.593 // removed, just like normal cdecl functions.
579 if (Sym.startswith("_") && Sym.contains('@') && !Config->MinGW)594 if (sym.startswith("_") && sym.contains('@') && !config->mingw)
580 return Sym;595 return sym;
581 return Sym.startswith("_") ? Sym.substr(1) : Sym;596 return sym.startswith("_") ? sym.substr(1) : sym;
582}597}
583598
584// Convert stdcall/fastcall style symbols into unsuffixed symbols,599// Convert stdcall/fastcall style symbols into unsuffixed symbols,
585// with or without a leading underscore. (MinGW specific.)600// with or without a leading underscore. (MinGW specific.)
586static StringRef killAt(StringRef Sym, bool Prefix) {601static StringRef killAt(StringRef sym, bool prefix) {
587 if (Sym.empty())602 if (sym.empty())
588 return Sym;603 return sym;
589 // Strip any trailing stdcall suffix604 // Strip any trailing stdcall suffix
590 Sym = Sym.substr(0, Sym.find('@', 1));605 sym = sym.substr(0, sym.find('@', 1));
591 if (!Sym.startswith("@")) {606 if (!sym.startswith("@")) {
592 if (Prefix && !Sym.startswith("_"))607 if (prefix && !sym.startswith("_"))
593 return Saver.save("_" + Sym);608 return saver.save("_" + sym);
594 return Sym;609 return sym;
595 }610 }
596 // For fastcall, remove the leading @ and replace it with an611 // For fastcall, remove the leading @ and replace it with an
597 // underscore, if prefixes are used.612 // underscore, if prefixes are used.
598 Sym = Sym.substr(1);613 sym = sym.substr(1);
599 if (Prefix)614 if (prefix)
600 Sym = Saver.save("_" + Sym);615 sym = saver.save("_" + sym);
601 return Sym;616 return sym;
602}617}
603618
604// Performs error checking on all /export arguments.619// Performs error checking on all /export arguments.
605// It also sets ordinals.620// It also sets ordinals.
606void fixupExports() {621void fixupExports() {
607 // Symbol ordinals must be unique.622 // Symbol ordinals must be unique.
608 std::set<uint16_t> Ords;623 std::set<uint16_t> ords;
609 for (Export &E : Config->Exports) {624 for (Export &e : config->exports) {
610 if (E.Ordinal == 0)625 if (e.ordinal == 0)
611 continue;626 continue;
612 if (!Ords.insert(E.Ordinal).second)627 if (!ords.insert(e.ordinal).second)
613 fatal("duplicate export ordinal: " + E.Name);628 fatal("duplicate export ordinal: " + e.name);
614 }
615
616 for (Export &E : Config->Exports) {
617 Symbol *Sym = E.Sym;
618 if (!E.ForwardTo.empty() || !Sym) {
619 E.SymbolName = E.Name;
620 } else {
621 if (auto *U = dyn_cast<Undefined>(Sym))
622 if (U->WeakAlias)
623 Sym = U->WeakAlias;
624 E.SymbolName = Sym->getName();
625 }
626 }629 }
627630
628 for (Export &E : Config->Exports) {631 for (Export &e : config->exports) {
629 if (!E.ForwardTo.empty()) {632 if (!e.forwardTo.empty()) {
630 E.ExportName = undecorate(E.Name);633 e.exportName = undecorate(e.name);
631 } else {634 } else {
632 E.ExportName = undecorate(E.ExtName.empty() ? E.Name : E.ExtName);635 e.exportName = undecorate(e.extName.empty() ? e.name : e.extName);
633 }636 }
634 }637 }
635638
636 if (Config->KillAt && Config->Machine == I386) {639 if (config->killAt && config->machine == I386) {
637 for (Export &E : Config->Exports) {640 for (Export &e : config->exports) {
638 E.Name = killAt(E.Name, true);641 e.name = killAt(e.name, true);
639 E.ExportName = killAt(E.ExportName, false);642 e.exportName = killAt(e.exportName, false);
640 E.ExtName = killAt(E.ExtName, true);643 e.extName = killAt(e.extName, true);
641 E.SymbolName = killAt(E.SymbolName, true);644 e.symbolName = killAt(e.symbolName, true);
642 }645 }
643 }646 }
644647
645 // Uniquefy by name.648 // Uniquefy by name.
646 DenseMap<StringRef, Export *> Map(Config->Exports.size());649 DenseMap<StringRef, Export *> map(config->exports.size());
647 std::vector<Export> V;650 std::vector<Export> v;
648 for (Export &E : Config->Exports) {651 for (Export &e : config->exports) {
649 auto Pair = Map.insert(std::make_pair(E.ExportName, &E));652 auto pair = map.insert(std::make_pair(e.exportName, &e));
650 bool Inserted = Pair.second;653 bool inserted = pair.second;
651 if (Inserted) {654 if (inserted) {
652 V.push_back(E);655 v.push_back(e);
653 continue;656 continue;
654 }657 }
655 Export *Existing = Pair.first->second;658 Export *existing = pair.first->second;
656 if (E == *Existing || E.Name != Existing->Name)659 if (e == *existing || e.name != existing->name)
657 continue;660 continue;
658 warn("duplicate /export option: " + E.Name);661 warn("duplicate /export option: " + e.name);
659 }662 }
660 Config->Exports = std::move(V);663 config->exports = std::move(v);
661664
662 // Sort by name.665 // Sort by name.
663 std::sort(Config->Exports.begin(), Config->Exports.end(),666 std::sort(config->exports.begin(), config->exports.end(),
664 [](const Export &A, const Export &B) {667 [](const Export &a, const Export &b) {
665 return A.ExportName < B.ExportName;668 return a.exportName < b.exportName;
666 });669 });
667}670}
668671
669void assignExportOrdinals() {672void assignExportOrdinals() {
670 // Assign unique ordinals if default (= 0).673 // Assign unique ordinals if default (= 0).
671 uint16_t Max = 0;674 uint16_t max = 0;
672 for (Export &E : Config->Exports)675 for (Export &e : config->exports)
673 Max = std::max(Max, E.Ordinal);676 max = std::max(max, e.ordinal);
674 for (Export &E : Config->Exports)677 for (Export &e : config->exports)
675 if (E.Ordinal == 0)678 if (e.ordinal == 0)
676 E.Ordinal = ++Max;679 e.ordinal = ++max;
677}680}
678681
679// Parses a string in the form of "key=value" and check682// Parses a string in the form of "key=value" and check
680// if value matches previous values for the same key.683// if value matches previous values for the same key.
681void checkFailIfMismatch(StringRef Arg) {684void checkFailIfMismatch(StringRef arg, InputFile *source) {
682 StringRef K, V;685 StringRef k, v;
683 std::tie(K, V) = Arg.split('=');686 std::tie(k, v) = arg.split('=');
684 if (K.empty() || V.empty())687 if (k.empty() || v.empty())
685 fatal("/failifmismatch: invalid argument: " + Arg);688 fatal("/failifmismatch: invalid argument: " + arg);
686 StringRef Existing = Config->MustMatch[K];689 std::pair<StringRef, InputFile *> existing = config->mustMatch[k];
687 if (!Existing.empty() && V != Existing)690 if (!existing.first.empty() && v != existing.first) {
688 fatal("/failifmismatch: mismatch detected: " + Existing + " and " + V +691 std::string sourceStr = source ? toString(source) : "cmd-line";
689 " for key " + K);692 std::string existingStr =
690 Config->MustMatch[K] = V;693 existing.second ? toString(existing.second) : "cmd-line";
694 fatal("/failifmismatch: mismatch detected for '" + k + "':\n>>> " +
695 existingStr + " has value " + existing.first + "\n>>> " + sourceStr +
696 " has value " + v);
697 }
698 config->mustMatch[k] = {v, source};
691}699}
692700
693// Convert Windows resource files (.res files) to a .obj file.701// Convert Windows resource files (.res files) to a .obj file.
694MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs) {702// Does what cvtres.exe does, but in-process and cross-platform.
695 object::WindowsResourceParser Parser;703MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> mbs) {
696704 object::WindowsResourceParser parser;
697 for (MemoryBufferRef MB : MBs) {705
698 std::unique_ptr<object::Binary> Bin = check(object::createBinary(MB));706 for (MemoryBufferRef mb : mbs) {
699 object::WindowsResource *RF = dyn_cast<object::WindowsResource>(Bin.get());707 std::unique_ptr<object::Binary> bin = check(object::createBinary(mb));
700 if (!RF)708 object::WindowsResource *rf = dyn_cast<object::WindowsResource>(bin.get());
709 if (!rf)
701 fatal("cannot compile non-resource file as resource");710 fatal("cannot compile non-resource file as resource");
702 if (auto EC = Parser.parse(RF))711
703 fatal("failed to parse .res file: " + toString(std::move(EC)));712 std::vector<std::string> duplicates;
713 if (auto ec = parser.parse(rf, duplicates))
714 fatal(toString(std::move(ec)));
715
716 for (const auto &dupeDiag : duplicates)
717 if (config->forceMultipleRes)
718 warn(dupeDiag);
719 else
720 error(dupeDiag);
704 }721 }
705722
706 Expected<std::unique_ptr<MemoryBuffer>> E =723 Expected<std::unique_ptr<MemoryBuffer>> e =
707 llvm::object::writeWindowsResourceCOFF(Config->Machine, Parser);724 llvm::object::writeWindowsResourceCOFF(config->machine, parser,
708 if (!E)725 config->timestamp);
709 fatal("failed to write .res to COFF: " + toString(E.takeError()));726 if (!e)
727 fatal("failed to write .res to COFF: " + toString(e.takeError()));
710728
711 MemoryBufferRef MBRef = **E;729 MemoryBufferRef mbref = **e;
712 make<std::unique_ptr<MemoryBuffer>>(std::move(*E)); // take ownership730 make<std::unique_ptr<MemoryBuffer>>(std::move(*e)); // take ownership
713 return MBRef;731 return mbref;
714}732}
715733
716// Create OptTable734// Create OptTable
...@@ -721,7 +739,7 @@ MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs) {...@@ -721,7 +739,7 @@ MemoryBufferRef convertResToCOFF(ArrayRef<MemoryBufferRef> MBs) {
721#undef PREFIX739#undef PREFIX
722740
723// Create table mapping all options defined in Options.td741// Create table mapping all options defined in Options.td
724static const llvm::opt::OptTable::Info InfoTable[] = {742static const llvm::opt::OptTable::Info infoTable[] = {
725#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \743#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
726 {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \744 {X1, X2, X10, X11, OPT_##ID, llvm::opt::Option::KIND##Class, \
727 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},745 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
...@@ -729,36 +747,36 @@ static const llvm::opt::OptTable::Info InfoTable[] = {...@@ -729,36 +747,36 @@ static const llvm::opt::OptTable::Info InfoTable[] = {
729#undef OPTION747#undef OPTION
730};748};
731749
732COFFOptTable::COFFOptTable() : OptTable(InfoTable, true) {}750COFFOptTable::COFFOptTable() : OptTable(infoTable, true) {}
733751
734// Set color diagnostics according to --color-diagnostics={auto,always,never}752// Set color diagnostics according to --color-diagnostics={auto,always,never}
735// or --no-color-diagnostics flags.753// or --no-color-diagnostics flags.
736static void handleColorDiagnostics(opt::InputArgList &Args) {754static void handleColorDiagnostics(opt::InputArgList &args) {
737 auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,755 auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
738 OPT_no_color_diagnostics);756 OPT_no_color_diagnostics);
739 if (!Arg)757 if (!arg)
740 return;758 return;
741 if (Arg->getOption().getID() == OPT_color_diagnostics) {759 if (arg->getOption().getID() == OPT_color_diagnostics) {
742 errorHandler().ColorDiagnostics = true;760 errorHandler().colorDiagnostics = true;
743 } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) {761 } else if (arg->getOption().getID() == OPT_no_color_diagnostics) {
744 errorHandler().ColorDiagnostics = false;762 errorHandler().colorDiagnostics = false;
745 } else {763 } else {
746 StringRef S = Arg->getValue();764 StringRef s = arg->getValue();
747 if (S == "always")765 if (s == "always")
748 errorHandler().ColorDiagnostics = true;766 errorHandler().colorDiagnostics = true;
749 else if (S == "never")767 else if (s == "never")
750 errorHandler().ColorDiagnostics = false;768 errorHandler().colorDiagnostics = false;
751 else if (S != "auto")769 else if (s != "auto")
752 error("unknown option: --color-diagnostics=" + S);770 error("unknown option: --color-diagnostics=" + s);
753 }771 }
754}772}
755773
756static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {774static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) {
757 if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) {775 if (auto *arg = args.getLastArg(OPT_rsp_quoting)) {
758 StringRef S = Arg->getValue();776 StringRef s = arg->getValue();
759 if (S != "windows" && S != "posix")777 if (s != "windows" && s != "posix")
760 error("invalid response file quoting: " + S);778 error("invalid response file quoting: " + s);
761 if (S == "windows")779 if (s == "windows")
762 return cl::TokenizeWindowsCommandLine;780 return cl::TokenizeWindowsCommandLine;
763 return cl::TokenizeGNUCommandLine;781 return cl::TokenizeGNUCommandLine;
764 }782 }
...@@ -767,104 +785,111 @@ static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {...@@ -767,104 +785,111 @@ static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
767}785}
768786
769// Parses a given list of options.787// Parses a given list of options.
770opt::InputArgList ArgParser::parse(ArrayRef<const char *> Argv) {788opt::InputArgList ArgParser::parse(ArrayRef<const char *> argv) {
771 // Make InputArgList from string vectors.789 // Make InputArgList from string vectors.
772 unsigned MissingIndex;790 unsigned missingIndex;
773 unsigned MissingCount;791 unsigned missingCount;
774792
775 // We need to get the quoting style for response files before parsing all793 // We need to get the quoting style for response files before parsing all
776 // options so we parse here before and ignore all the options but794 // options so we parse here before and ignore all the options but
777 // --rsp-quoting.795 // --rsp-quoting.
778 opt::InputArgList Args = Table.ParseArgs(Argv, MissingIndex, MissingCount);796 opt::InputArgList args = table.ParseArgs(argv, missingIndex, missingCount);
779797
780 // Expand response files (arguments in the form of @<filename>)798 // Expand response files (arguments in the form of @<filename>)
781 // and then parse the argument again.799 // and then parse the argument again.
782 SmallVector<const char *, 256> ExpandedArgv(Argv.data(), Argv.data() + Argv.size());800 SmallVector<const char *, 256> expandedArgv(argv.data(),
783 cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), ExpandedArgv);801 argv.data() + argv.size());
784 Args = Table.ParseArgs(makeArrayRef(ExpandedArgv).drop_front(), MissingIndex,802 cl::ExpandResponseFiles(saver, getQuotingStyle(args), expandedArgv);
785 MissingCount);803 args = table.ParseArgs(makeArrayRef(expandedArgv).drop_front(), missingIndex,
804 missingCount);
786805
787 // Print the real command line if response files are expanded.806 // Print the real command line if response files are expanded.
788 if (Args.hasArg(OPT_verbose) && Argv.size() != ExpandedArgv.size()) {807 if (args.hasArg(OPT_verbose) && argv.size() != expandedArgv.size()) {
789 std::string Msg = "Command line:";808 std::string msg = "Command line:";
790 for (const char *S : ExpandedArgv)809 for (const char *s : expandedArgv)
791 Msg += " " + std::string(S);810 msg += " " + std::string(s);
792 message(Msg);811 message(msg);
793 }812 }
794813
795 // Save the command line after response file expansion so we can write it to814 // Save the command line after response file expansion so we can write it to
796 // the PDB if necessary.815 // the PDB if necessary.
797 Config->Argv = {ExpandedArgv.begin(), ExpandedArgv.end()};816 config->argv = {expandedArgv.begin(), expandedArgv.end()};
798817
799 // Handle /WX early since it converts missing argument warnings to errors.818 // Handle /WX early since it converts missing argument warnings to errors.
800 errorHandler().FatalWarnings = Args.hasFlag(OPT_WX, OPT_WX_no, false);819 errorHandler().fatalWarnings = args.hasFlag(OPT_WX, OPT_WX_no, false);
801820
802 if (MissingCount)821 if (missingCount)
803 fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument");822 fatal(Twine(args.getArgString(missingIndex)) + ": missing argument");
804823
805 handleColorDiagnostics(Args);824 handleColorDiagnostics(args);
806825
807 for (auto *Arg : Args.filtered(OPT_UNKNOWN))826 for (auto *arg : args.filtered(OPT_UNKNOWN)) {
808 warn("ignoring unknown argument: " + Arg->getSpelling());827 std::string nearest;
828 if (table.findNearest(arg->getAsString(args), nearest) > 1)
829 warn("ignoring unknown argument '" + arg->getAsString(args) + "'");
830 else
831 warn("ignoring unknown argument '" + arg->getAsString(args) +
832 "', did you mean '" + nearest + "'");
833 }
809834
810 if (Args.hasArg(OPT_lib))835 if (args.hasArg(OPT_lib))
811 warn("ignoring /lib since it's not the first argument");836 warn("ignoring /lib since it's not the first argument");
812837
813 return Args;838 return args;
814}839}
815840
816// Tokenizes and parses a given string as command line in .drective section.841// Tokenizes and parses a given string as command line in .drective section.
817// /EXPORT options are processed in fastpath.842// /EXPORT options are processed in fastpath.
818std::pair<opt::InputArgList, std::vector<StringRef>>843std::pair<opt::InputArgList, std::vector<StringRef>>
819ArgParser::parseDirectives(StringRef S) {844ArgParser::parseDirectives(StringRef s) {
820 std::vector<StringRef> Exports;845 std::vector<StringRef> exports;
821 SmallVector<const char *, 16> Rest;846 SmallVector<const char *, 16> rest;
822847
823 for (StringRef Tok : tokenize(S)) {848 for (StringRef tok : tokenize(s)) {
824 if (Tok.startswith_lower("/export:") || Tok.startswith_lower("-export:"))849 if (tok.startswith_lower("/export:") || tok.startswith_lower("-export:"))
825 Exports.push_back(Tok.substr(strlen("/export:")));850 exports.push_back(tok.substr(strlen("/export:")));
826 else851 else
827 Rest.push_back(Tok.data());852 rest.push_back(tok.data());
828 }853 }
829854
830 // Make InputArgList from unparsed string vectors.855 // Make InputArgList from unparsed string vectors.
831 unsigned MissingIndex;856 unsigned missingIndex;
832 unsigned MissingCount;857 unsigned missingCount;
833858
834 opt::InputArgList Args = Table.ParseArgs(Rest, MissingIndex, MissingCount);859 opt::InputArgList args = table.ParseArgs(rest, missingIndex, missingCount);
835860
836 if (MissingCount)861 if (missingCount)
837 fatal(Twine(Args.getArgString(MissingIndex)) + ": missing argument");862 fatal(Twine(args.getArgString(missingIndex)) + ": missing argument");
838 for (auto *Arg : Args.filtered(OPT_UNKNOWN))863 for (auto *arg : args.filtered(OPT_UNKNOWN))
839 warn("ignoring unknown argument: " + Arg->getSpelling());864 warn("ignoring unknown argument: " + arg->getAsString(args));
840 return {std::move(Args), std::move(Exports)};865 return {std::move(args), std::move(exports)};
841}866}
842867
843// link.exe has an interesting feature. If LINK or _LINK_ environment868// link.exe has an interesting feature. If LINK or _LINK_ environment
844// variables exist, their contents are handled as command line strings.869// variables exist, their contents are handled as command line strings.
845// So you can pass extra arguments using them.870// So you can pass extra arguments using them.
846opt::InputArgList ArgParser::parseLINK(std::vector<const char *> Argv) {871opt::InputArgList ArgParser::parseLINK(std::vector<const char *> argv) {
847 // Concatenate LINK env and command line arguments, and then parse them.872 // Concatenate LINK env and command line arguments, and then parse them.
848 if (Optional<std::string> S = Process::GetEnv("LINK")) {873 if (Optional<std::string> s = Process::GetEnv("LINK")) {
849 std::vector<const char *> V = tokenize(*S);874 std::vector<const char *> v = tokenize(*s);
850 Argv.insert(std::next(Argv.begin()), V.begin(), V.end());875 argv.insert(std::next(argv.begin()), v.begin(), v.end());
851 }876 }
852 if (Optional<std::string> S = Process::GetEnv("_LINK_")) {877 if (Optional<std::string> s = Process::GetEnv("_LINK_")) {
853 std::vector<const char *> V = tokenize(*S);878 std::vector<const char *> v = tokenize(*s);
854 Argv.insert(std::next(Argv.begin()), V.begin(), V.end());879 argv.insert(std::next(argv.begin()), v.begin(), v.end());
855 }880 }
856 return parse(Argv);881 return parse(argv);
857}882}
858883
859std::vector<const char *> ArgParser::tokenize(StringRef S) {884std::vector<const char *> ArgParser::tokenize(StringRef s) {
860 SmallVector<const char *, 16> Tokens;885 SmallVector<const char *, 16> tokens;
861 cl::TokenizeWindowsCommandLine(S, Saver, Tokens);886 cl::TokenizeWindowsCommandLine(s, saver, tokens);
862 return std::vector<const char *>(Tokens.begin(), Tokens.end());887 return std::vector<const char *>(tokens.begin(), tokens.end());
863}888}
864889
865void printHelp(const char *Argv0) {890void printHelp(const char *argv0) {
866 COFFOptTable().PrintHelp(outs(),891 COFFOptTable().PrintHelp(outs(),
867 (std::string(Argv0) + " [options] file...").c_str(),892 (std::string(argv0) + " [options] file...").c_str(),
868 "LLVM Linker", false);893 "LLVM Linker", false);
869}894}
870895
deps/lld/COFF/ICF.cpp+139-140
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ICF.cpp ------------------------------------------------------------===//1//===- ICF.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -38,33 +37,32 @@ using namespace llvm;...@@ -38,33 +37,32 @@ using namespace llvm;
38namespace lld {37namespace lld {
39namespace coff {38namespace coff {
4039
41static Timer ICFTimer("ICF", Timer::root());40static Timer icfTimer("ICF", Timer::root());
4241
43class ICF {42class ICF {
44public:43public:
45 void run(ArrayRef<Chunk *> V);44 void run(ArrayRef<Chunk *> v);
4645
47private:46private:
48 void segregate(size_t Begin, size_t End, bool Constant);47 void segregate(size_t begin, size_t end, bool constant);
4948
50 bool assocEquals(const SectionChunk *A, const SectionChunk *B);49 bool assocEquals(const SectionChunk *a, const SectionChunk *b);
5150
52 bool equalsConstant(const SectionChunk *A, const SectionChunk *B);51 bool equalsConstant(const SectionChunk *a, const SectionChunk *b);
53 bool equalsVariable(const SectionChunk *A, const SectionChunk *B);52 bool equalsVariable(const SectionChunk *a, const SectionChunk *b);
5453
55 uint32_t getHash(SectionChunk *C);54 bool isEligible(SectionChunk *c);
56 bool isEligible(SectionChunk *C);
5755
58 size_t findBoundary(size_t Begin, size_t End);56 size_t findBoundary(size_t begin, size_t end);
5957
60 void forEachClassRange(size_t Begin, size_t End,58 void forEachClassRange(size_t begin, size_t end,
61 std::function<void(size_t, size_t)> Fn);59 std::function<void(size_t, size_t)> fn);
6260
63 void forEachClass(std::function<void(size_t, size_t)> Fn);61 void forEachClass(std::function<void(size_t, size_t)> fn);
6462
65 std::vector<SectionChunk *> Chunks;63 std::vector<SectionChunk *> chunks;
66 int Cnt = 0;64 int cnt = 0;
67 std::atomic<bool> Repeat = {false};65 std::atomic<bool> repeat = {false};
68};66};
6967
70// Returns true if section S is subject of ICF.68// Returns true if section S is subject of ICF.
...@@ -78,143 +76,144 @@ private:...@@ -78,143 +76,144 @@ private:
78// merge read-only sections in a couple of cases where the address of the76// merge read-only sections in a couple of cases where the address of the
79// section is insignificant to the user program and the behaviour matches that77// section is insignificant to the user program and the behaviour matches that
80// of the Visual C++ linker.78// of the Visual C++ linker.
81bool ICF::isEligible(SectionChunk *C) {79bool ICF::isEligible(SectionChunk *c) {
82 // Non-comdat chunks, dead chunks, and writable chunks are not elegible.80 // Non-comdat chunks, dead chunks, and writable chunks are not elegible.
83 bool Writable = C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE;81 bool writable = c->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_WRITE;
84 if (!C->isCOMDAT() || !C->Live || Writable)82 if (!c->isCOMDAT() || !c->live || writable)
85 return false;83 return false;
8684
87 // Code sections are eligible.85 // Code sections are eligible.
88 if (C->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)86 if (c->getOutputCharacteristics() & llvm::COFF::IMAGE_SCN_MEM_EXECUTE)
89 return true;87 return true;
9088
91 // .pdata and .xdata unwind info sections are eligible.89 // .pdata and .xdata unwind info sections are eligible.
92 StringRef OutSecName = C->getSectionName().split('$').first;90 StringRef outSecName = c->getSectionName().split('$').first;
93 if (OutSecName == ".pdata" || OutSecName == ".xdata")91 if (outSecName == ".pdata" || outSecName == ".xdata")
94 return true;92 return true;
9593
96 // So are vtables.94 // So are vtables.
97 if (C->Sym && C->Sym->getName().startswith("??_7"))95 if (c->sym && c->sym->getName().startswith("??_7"))
98 return true;96 return true;
9997
100 // Anything else not in an address-significance table is eligible.98 // Anything else not in an address-significance table is eligible.
101 return !C->KeepUnique;99 return !c->keepUnique;
102}100}
103101
104// Split an equivalence class into smaller classes.102// Split an equivalence class into smaller classes.
105void ICF::segregate(size_t Begin, size_t End, bool Constant) {103void ICF::segregate(size_t begin, size_t end, bool constant) {
106 while (Begin < End) {104 while (begin < end) {
107 // Divide [Begin, End) into two. Let Mid be the start index of the105 // Divide [Begin, End) into two. Let Mid be the start index of the
108 // second group.106 // second group.
109 auto Bound = std::stable_partition(107 auto bound = std::stable_partition(
110 Chunks.begin() + Begin + 1, Chunks.begin() + End, [&](SectionChunk *S) {108 chunks.begin() + begin + 1, chunks.begin() + end, [&](SectionChunk *s) {
111 if (Constant)109 if (constant)
112 return equalsConstant(Chunks[Begin], S);110 return equalsConstant(chunks[begin], s);
113 return equalsVariable(Chunks[Begin], S);111 return equalsVariable(chunks[begin], s);
114 });112 });
115 size_t Mid = Bound - Chunks.begin();113 size_t mid = bound - chunks.begin();
116114
117 // Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an115 // Split [Begin, End) into [Begin, Mid) and [Mid, End). We use Mid as an
118 // equivalence class ID because every group ends with a unique index.116 // equivalence class ID because every group ends with a unique index.
119 for (size_t I = Begin; I < Mid; ++I)117 for (size_t i = begin; i < mid; ++i)
120 Chunks[I]->Class[(Cnt + 1) % 2] = Mid;118 chunks[i]->eqClass[(cnt + 1) % 2] = mid;
121119
122 // If we created a group, we need to iterate the main loop again.120 // If we created a group, we need to iterate the main loop again.
123 if (Mid != End)121 if (mid != end)
124 Repeat = true;122 repeat = true;
125123
126 Begin = Mid;124 begin = mid;
127 }125 }
128}126}
129127
130// Returns true if two sections' associative children are equal.128// Returns true if two sections' associative children are equal.
131bool ICF::assocEquals(const SectionChunk *A, const SectionChunk *B) {129bool ICF::assocEquals(const SectionChunk *a, const SectionChunk *b) {
132 auto ChildClasses = [&](const SectionChunk *SC) {130 auto childClasses = [&](const SectionChunk *sc) {
133 std::vector<uint32_t> Classes;131 std::vector<uint32_t> classes;
134 for (const SectionChunk *C : SC->children())132 for (const SectionChunk &c : sc->children())
135 if (!C->SectionName.startswith(".debug") &&133 if (!c.getSectionName().startswith(".debug") &&
136 C->SectionName != ".gfids$y" && C->SectionName != ".gljmp$y")134 c.getSectionName() != ".gfids$y" && c.getSectionName() != ".gljmp$y")
137 Classes.push_back(C->Class[Cnt % 2]);135 classes.push_back(c.eqClass[cnt % 2]);
138 return Classes;136 return classes;
139 };137 };
140 return ChildClasses(A) == ChildClasses(B);138 return childClasses(a) == childClasses(b);
141}139}
142140
143// Compare "non-moving" part of two sections, namely everything141// Compare "non-moving" part of two sections, namely everything
144// except relocation targets.142// except relocation targets.
145bool ICF::equalsConstant(const SectionChunk *A, const SectionChunk *B) {143bool ICF::equalsConstant(const SectionChunk *a, const SectionChunk *b) {
146 if (A->Relocs.size() != B->Relocs.size())144 if (a->relocsSize != b->relocsSize)
147 return false;145 return false;
148146
149 // Compare relocations.147 // Compare relocations.
150 auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) {148 auto eq = [&](const coff_relocation &r1, const coff_relocation &r2) {
151 if (R1.Type != R2.Type ||149 if (r1.Type != r2.Type ||
152 R1.VirtualAddress != R2.VirtualAddress) {150 r1.VirtualAddress != r2.VirtualAddress) {
153 return false;151 return false;
154 }152 }
155 Symbol *B1 = A->File->getSymbol(R1.SymbolTableIndex);153 Symbol *b1 = a->file->getSymbol(r1.SymbolTableIndex);
156 Symbol *B2 = B->File->getSymbol(R2.SymbolTableIndex);154 Symbol *b2 = b->file->getSymbol(r2.SymbolTableIndex);
157 if (B1 == B2)155 if (b1 == b2)
158 return true;156 return true;
159 if (auto *D1 = dyn_cast<DefinedRegular>(B1))157 if (auto *d1 = dyn_cast<DefinedRegular>(b1))
160 if (auto *D2 = dyn_cast<DefinedRegular>(B2))158 if (auto *d2 = dyn_cast<DefinedRegular>(b2))
161 return D1->getValue() == D2->getValue() &&159 return d1->getValue() == d2->getValue() &&
162 D1->getChunk()->Class[Cnt % 2] == D2->getChunk()->Class[Cnt % 2];160 d1->getChunk()->eqClass[cnt % 2] == d2->getChunk()->eqClass[cnt % 2];
163 return false;161 return false;
164 };162 };
165 if (!std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(), Eq))163 if (!std::equal(a->getRelocs().begin(), a->getRelocs().end(),
164 b->getRelocs().begin(), eq))
166 return false;165 return false;
167166
168 // Compare section attributes and contents.167 // Compare section attributes and contents.
169 return A->getOutputCharacteristics() == B->getOutputCharacteristics() &&168 return a->getOutputCharacteristics() == b->getOutputCharacteristics() &&
170 A->SectionName == B->SectionName &&169 a->getSectionName() == b->getSectionName() &&
171 A->Header->SizeOfRawData == B->Header->SizeOfRawData &&170 a->header->SizeOfRawData == b->header->SizeOfRawData &&
172 A->Checksum == B->Checksum && A->getContents() == B->getContents() &&171 a->checksum == b->checksum && a->getContents() == b->getContents() &&
173 assocEquals(A, B);172 assocEquals(a, b);
174}173}
175174
176// Compare "moving" part of two sections, namely relocation targets.175// Compare "moving" part of two sections, namely relocation targets.
177bool ICF::equalsVariable(const SectionChunk *A, const SectionChunk *B) {176bool ICF::equalsVariable(const SectionChunk *a, const SectionChunk *b) {
178 // Compare relocations.177 // Compare relocations.
179 auto Eq = [&](const coff_relocation &R1, const coff_relocation &R2) {178 auto eq = [&](const coff_relocation &r1, const coff_relocation &r2) {
180 Symbol *B1 = A->File->getSymbol(R1.SymbolTableIndex);179 Symbol *b1 = a->file->getSymbol(r1.SymbolTableIndex);
181 Symbol *B2 = B->File->getSymbol(R2.SymbolTableIndex);180 Symbol *b2 = b->file->getSymbol(r2.SymbolTableIndex);
182 if (B1 == B2)181 if (b1 == b2)
183 return true;182 return true;
184 if (auto *D1 = dyn_cast<DefinedRegular>(B1))183 if (auto *d1 = dyn_cast<DefinedRegular>(b1))
185 if (auto *D2 = dyn_cast<DefinedRegular>(B2))184 if (auto *d2 = dyn_cast<DefinedRegular>(b2))
186 return D1->getChunk()->Class[Cnt % 2] == D2->getChunk()->Class[Cnt % 2];185 return d1->getChunk()->eqClass[cnt % 2] == d2->getChunk()->eqClass[cnt % 2];
187 return false;186 return false;
188 };187 };
189 return std::equal(A->Relocs.begin(), A->Relocs.end(), B->Relocs.begin(),188 return std::equal(a->getRelocs().begin(), a->getRelocs().end(),
190 Eq) &&189 b->getRelocs().begin(), eq) &&
191 assocEquals(A, B);190 assocEquals(a, b);
192}191}
193192
194// Find the first Chunk after Begin that has a different class from Begin.193// Find the first Chunk after Begin that has a different class from Begin.
195size_t ICF::findBoundary(size_t Begin, size_t End) {194size_t ICF::findBoundary(size_t begin, size_t end) {
196 for (size_t I = Begin + 1; I < End; ++I)195 for (size_t i = begin + 1; i < end; ++i)
197 if (Chunks[Begin]->Class[Cnt % 2] != Chunks[I]->Class[Cnt % 2])196 if (chunks[begin]->eqClass[cnt % 2] != chunks[i]->eqClass[cnt % 2])
198 return I;197 return i;
199 return End;198 return end;
200}199}
201200
202void ICF::forEachClassRange(size_t Begin, size_t End,201void ICF::forEachClassRange(size_t begin, size_t end,
203 std::function<void(size_t, size_t)> Fn) {202 std::function<void(size_t, size_t)> fn) {
204 while (Begin < End) {203 while (begin < end) {
205 size_t Mid = findBoundary(Begin, End);204 size_t mid = findBoundary(begin, end);
206 Fn(Begin, Mid);205 fn(begin, mid);
207 Begin = Mid;206 begin = mid;
208 }207 }
209}208}
210209
211// Call Fn on each class group.210// Call Fn on each class group.
212void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {211void ICF::forEachClass(std::function<void(size_t, size_t)> fn) {
213 // If the number of sections are too small to use threading,212 // If the number of sections are too small to use threading,
214 // call Fn sequentially.213 // call Fn sequentially.
215 if (Chunks.size() < 1024) {214 if (chunks.size() < 1024) {
216 forEachClassRange(0, Chunks.size(), Fn);215 forEachClassRange(0, chunks.size(), fn);
217 ++Cnt;216 ++cnt;
218 return;217 return;
219 }218 }
220219
...@@ -222,97 +221,97 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {...@@ -222,97 +221,97 @@ void ICF::forEachClass(std::function<void(size_t, size_t)> Fn) {
222 // The sharding must be completed before any calls to Fn are made221 // The sharding must be completed before any calls to Fn are made
223 // so that Fn can modify the Chunks in its shard without causing data222 // so that Fn can modify the Chunks in its shard without causing data
224 // races.223 // races.
225 const size_t NumShards = 256;224 const size_t numShards = 256;
226 size_t Step = Chunks.size() / NumShards;225 size_t step = chunks.size() / numShards;
227 size_t Boundaries[NumShards + 1];226 size_t boundaries[numShards + 1];
228 Boundaries[0] = 0;227 boundaries[0] = 0;
229 Boundaries[NumShards] = Chunks.size();228 boundaries[numShards] = chunks.size();
230 parallelForEachN(1, NumShards, [&](size_t I) {229 parallelForEachN(1, numShards, [&](size_t i) {
231 Boundaries[I] = findBoundary((I - 1) * Step, Chunks.size());230 boundaries[i] = findBoundary((i - 1) * step, chunks.size());
232 });231 });
233 parallelForEachN(1, NumShards + 1, [&](size_t I) {232 parallelForEachN(1, numShards + 1, [&](size_t i) {
234 if (Boundaries[I - 1] < Boundaries[I]) {233 if (boundaries[i - 1] < boundaries[i]) {
235 forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn);234 forEachClassRange(boundaries[i - 1], boundaries[i], fn);
236 }235 }
237 });236 });
238 ++Cnt;237 ++cnt;
239}238}
240239
241// Merge identical COMDAT sections.240// Merge identical COMDAT sections.
242// Two sections are considered the same if their section headers,241// Two sections are considered the same if their section headers,
243// contents and relocations are all the same.242// contents and relocations are all the same.
244void ICF::run(ArrayRef<Chunk *> Vec) {243void ICF::run(ArrayRef<Chunk *> vec) {
245 ScopedTimer T(ICFTimer);244 ScopedTimer t(icfTimer);
246245
247 // Collect only mergeable sections and group by hash value.246 // Collect only mergeable sections and group by hash value.
248 uint32_t NextId = 1;247 uint32_t nextId = 1;
249 for (Chunk *C : Vec) {248 for (Chunk *c : vec) {
250 if (auto *SC = dyn_cast<SectionChunk>(C)) {249 if (auto *sc = dyn_cast<SectionChunk>(c)) {
251 if (isEligible(SC))250 if (isEligible(sc))
252 Chunks.push_back(SC);251 chunks.push_back(sc);
253 else252 else
254 SC->Class[0] = NextId++;253 sc->eqClass[0] = nextId++;
255 }254 }
256 }255 }
257256
258 // Make sure that ICF doesn't merge sections that are being handled by string257 // Make sure that ICF doesn't merge sections that are being handled by string
259 // tail merging.258 // tail merging.
260 for (auto &P : MergeChunk::Instances)259 for (MergeChunk *mc : MergeChunk::instances)
261 for (SectionChunk *SC : P.second->Sections)260 if (mc)
262 SC->Class[0] = NextId++;261 for (SectionChunk *sc : mc->sections)
262 sc->eqClass[0] = nextId++;
263263
264 // Initially, we use hash values to partition sections.264 // Initially, we use hash values to partition sections.
265 parallelForEach(Chunks, [&](SectionChunk *SC) {265 parallelForEach(chunks, [&](SectionChunk *sc) {
266 SC->Class[0] = xxHash64(SC->getContents());266 sc->eqClass[0] = xxHash64(sc->getContents());
267 });267 });
268268
269 // Combine the hashes of the sections referenced by each section into its269 // Combine the hashes of the sections referenced by each section into its
270 // hash.270 // hash.
271 for (unsigned Cnt = 0; Cnt != 2; ++Cnt) {271 for (unsigned cnt = 0; cnt != 2; ++cnt) {
272 parallelForEach(Chunks, [&](SectionChunk *SC) {272 parallelForEach(chunks, [&](SectionChunk *sc) {
273 uint32_t Hash = SC->Class[Cnt % 2];273 uint32_t hash = sc->eqClass[cnt % 2];
274 for (Symbol *B : SC->symbols())274 for (Symbol *b : sc->symbols())
275 if (auto *Sym = dyn_cast_or_null<DefinedRegular>(B))275 if (auto *sym = dyn_cast_or_null<DefinedRegular>(b))
276 Hash += Sym->getChunk()->Class[Cnt % 2];276 hash += sym->getChunk()->eqClass[cnt % 2];
277 // Set MSB to 1 to avoid collisions with non-hash classs.277 // Set MSB to 1 to avoid collisions with non-hash classs.
278 SC->Class[(Cnt + 1) % 2] = Hash | (1U << 31);278 sc->eqClass[(cnt + 1) % 2] = hash | (1U << 31);
279 });279 });
280 }280 }
281281
282 // From now on, sections in Chunks are ordered so that sections in282 // From now on, sections in Chunks are ordered so that sections in
283 // the same group are consecutive in the vector.283 // the same group are consecutive in the vector.
284 std::stable_sort(Chunks.begin(), Chunks.end(),284 llvm::stable_sort(chunks, [](const SectionChunk *a, const SectionChunk *b) {
285 [](SectionChunk *A, SectionChunk *B) {285 return a->eqClass[0] < b->eqClass[0];
286 return A->Class[0] < B->Class[0];286 });
287 });
288287
289 // Compare static contents and assign unique IDs for each static content.288 // Compare static contents and assign unique IDs for each static content.
290 forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); });289 forEachClass([&](size_t begin, size_t end) { segregate(begin, end, true); });
291290
292 // Split groups by comparing relocations until convergence is obtained.291 // Split groups by comparing relocations until convergence is obtained.
293 do {292 do {
294 Repeat = false;293 repeat = false;
295 forEachClass(294 forEachClass(
296 [&](size_t Begin, size_t End) { segregate(Begin, End, false); });295 [&](size_t begin, size_t end) { segregate(begin, end, false); });
297 } while (Repeat);296 } while (repeat);
298297
299 log("ICF needed " + Twine(Cnt) + " iterations");298 log("ICF needed " + Twine(cnt) + " iterations");
300299
301 // Merge sections in the same classs.300 // Merge sections in the same classs.
302 forEachClass([&](size_t Begin, size_t End) {301 forEachClass([&](size_t begin, size_t end) {
303 if (End - Begin == 1)302 if (end - begin == 1)
304 return;303 return;
305304
306 log("Selected " + Chunks[Begin]->getDebugName());305 log("Selected " + chunks[begin]->getDebugName());
307 for (size_t I = Begin + 1; I < End; ++I) {306 for (size_t i = begin + 1; i < end; ++i) {
308 log(" Removed " + Chunks[I]->getDebugName());307 log(" Removed " + chunks[i]->getDebugName());
309 Chunks[Begin]->replace(Chunks[I]);308 chunks[begin]->replace(chunks[i]);
310 }309 }
311 });310 });
312}311}
313312
314// Entry point to ICF.313// Entry point to ICF.
315void doICF(ArrayRef<Chunk *> Chunks) { ICF().run(Chunks); }314void doICF(ArrayRef<Chunk *> chunks) { ICF().run(chunks); }
316315
317} // namespace coff316} // namespace coff
318} // namespace lld317} // namespace lld
deps/lld/COFF/ICF.h+4-5
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ICF.h --------------------------------------------------------------===//1//===- ICF.h --------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -18,7 +17,7 @@ namespace coff {...@@ -18,7 +17,7 @@ namespace coff {
1817
19class Chunk;18class Chunk;
2019
21void doICF(ArrayRef<Chunk *> Chunks);20void doICF(ArrayRef<Chunk *> chunks);
2221
23} // namespace coff22} // namespace coff
24} // namespace lld23} // namespace lld
deps/lld/COFF/InputFiles.cpp+603-312
...@@ -1,15 +1,15 @@...@@ -1,15 +1,15 @@
1//===- InputFiles.cpp -----------------------------------------------------===//1//===- InputFiles.cpp -----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
10#include "InputFiles.h"9#include "InputFiles.h"
11#include "Chunks.h"10#include "Chunks.h"
12#include "Config.h"11#include "Config.h"
12#include "DebugTypes.h"
13#include "Driver.h"13#include "Driver.h"
14#include "SymbolTable.h"14#include "SymbolTable.h"
15#include "Symbols.h"15#include "Symbols.h"
...@@ -20,6 +20,10 @@...@@ -20,6 +20,10 @@
20#include "llvm/ADT/Triple.h"20#include "llvm/ADT/Triple.h"
21#include "llvm/ADT/Twine.h"21#include "llvm/ADT/Twine.h"
22#include "llvm/BinaryFormat/COFF.h"22#include "llvm/BinaryFormat/COFF.h"
23#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
24#include "llvm/DebugInfo/CodeView/SymbolDeserializer.h"
25#include "llvm/DebugInfo/CodeView/SymbolRecord.h"
26#include "llvm/DebugInfo/CodeView/TypeDeserializer.h"
23#include "llvm/Object/Binary.h"27#include "llvm/Object/Binary.h"
24#include "llvm/Object/COFF.h"28#include "llvm/Object/COFF.h"
25#include "llvm/Support/Casting.h"29#include "llvm/Support/Casting.h"
...@@ -35,6 +39,7 @@...@@ -35,6 +39,7 @@
3539
36using namespace llvm;40using namespace llvm;
37using namespace llvm::COFF;41using namespace llvm::COFF;
42using namespace llvm::codeview;
38using namespace llvm::object;43using namespace llvm::object;
39using namespace llvm::support::endian;44using namespace llvm::support::endian;
4045
...@@ -44,80 +49,80 @@ using llvm::support::ulittle32_t;...@@ -44,80 +49,80 @@ using llvm::support::ulittle32_t;
44namespace lld {49namespace lld {
45namespace coff {50namespace coff {
4651
47std::vector<ObjFile *> ObjFile::Instances;52std::vector<ObjFile *> ObjFile::instances;
48std::vector<ImportFile *> ImportFile::Instances;53std::vector<ImportFile *> ImportFile::instances;
49std::vector<BitcodeFile *> BitcodeFile::Instances;54std::vector<BitcodeFile *> BitcodeFile::instances;
5055
51/// Checks that Source is compatible with being a weak alias to Target.56/// Checks that Source is compatible with being a weak alias to Target.
52/// If Source is Undefined and has no weak alias set, makes it a weak57/// If Source is Undefined and has no weak alias set, makes it a weak
53/// alias to Target.58/// alias to Target.
54static void checkAndSetWeakAlias(SymbolTable *Symtab, InputFile *F,59static void checkAndSetWeakAlias(SymbolTable *symtab, InputFile *f,
55 Symbol *Source, Symbol *Target) {60 Symbol *source, Symbol *target) {
56 if (auto *U = dyn_cast<Undefined>(Source)) {61 if (auto *u = dyn_cast<Undefined>(source)) {
57 if (U->WeakAlias && U->WeakAlias != Target) {62 if (u->weakAlias && u->weakAlias != target) {
58 // Weak aliases as produced by GCC are named in the form63 // Weak aliases as produced by GCC are named in the form
59 // .weak.<weaksymbol>.<othersymbol>, where <othersymbol> is the name64 // .weak.<weaksymbol>.<othersymbol>, where <othersymbol> is the name
60 // of another symbol emitted near the weak symbol.65 // of another symbol emitted near the weak symbol.
61 // Just use the definition from the first object file that defined66 // Just use the definition from the first object file that defined
62 // this weak symbol.67 // this weak symbol.
63 if (Config->MinGW)68 if (config->mingw)
64 return;69 return;
65 Symtab->reportDuplicate(Source, F);70 symtab->reportDuplicate(source, f);
66 }71 }
67 U->WeakAlias = Target;72 u->weakAlias = target;
68 }73 }
69}74}
7075
71ArchiveFile::ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}76ArchiveFile::ArchiveFile(MemoryBufferRef m) : InputFile(ArchiveKind, m) {}
7277
73void ArchiveFile::parse() {78void ArchiveFile::parse() {
74 // Parse a MemoryBufferRef as an archive file.79 // Parse a MemoryBufferRef as an archive file.
75 File = CHECK(Archive::create(MB), this);80 file = CHECK(Archive::create(mb), this);
7681
77 // Read the symbol table to construct Lazy objects.82 // Read the symbol table to construct Lazy objects.
78 for (const Archive::Symbol &Sym : File->symbols())83 for (const Archive::Symbol &sym : file->symbols())
79 Symtab->addLazy(this, Sym);84 symtab->addLazy(this, sym);
80}85}
8186
82// Returns a buffer pointing to a member file containing a given symbol.87// Returns a buffer pointing to a member file containing a given symbol.
83void ArchiveFile::addMember(const Archive::Symbol *Sym) {88void ArchiveFile::addMember(const Archive::Symbol *sym) {
84 const Archive::Child &C =89 const Archive::Child &c =
85 CHECK(Sym->getMember(),90 CHECK(sym->getMember(),
86 "could not get the member for symbol " + Sym->getName());91 "could not get the member for symbol " + sym->getName());
8792
88 // Return an empty buffer if we have already returned the same buffer.93 // Return an empty buffer if we have already returned the same buffer.
89 if (!Seen.insert(C.getChildOffset()).second)94 if (!seen.insert(c.getChildOffset()).second)
90 return;95 return;
9196
92 Driver->enqueueArchiveMember(C, Sym->getName(), getName());97 driver->enqueueArchiveMember(c, sym->getName(), getName());
93}98}
9499
95std::vector<MemoryBufferRef> getArchiveMembers(Archive *File) {100std::vector<MemoryBufferRef> getArchiveMembers(Archive *file) {
96 std::vector<MemoryBufferRef> V;101 std::vector<MemoryBufferRef> v;
97 Error Err = Error::success();102 Error err = Error::success();
98 for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {103 for (const ErrorOr<Archive::Child> &cOrErr : file->children(err)) {
99 Archive::Child C =104 Archive::Child c =
100 CHECK(COrErr,105 CHECK(cOrErr,
101 File->getFileName() + ": could not get the child of the archive");106 file->getFileName() + ": could not get the child of the archive");
102 MemoryBufferRef MBRef =107 MemoryBufferRef mbref =
103 CHECK(C.getMemoryBufferRef(),108 CHECK(c.getMemoryBufferRef(),
104 File->getFileName() +109 file->getFileName() +
105 ": could not get the buffer for a child of the archive");110 ": could not get the buffer for a child of the archive");
106 V.push_back(MBRef);111 v.push_back(mbref);
107 }112 }
108 if (Err)113 if (err)
109 fatal(File->getFileName() +114 fatal(file->getFileName() +
110 ": Archive::children failed: " + toString(std::move(Err)));115 ": Archive::children failed: " + toString(std::move(err)));
111 return V;116 return v;
112}117}
113118
114void ObjFile::parse() {119void ObjFile::parse() {
115 // Parse a memory buffer as a COFF file.120 // Parse a memory buffer as a COFF file.
116 std::unique_ptr<Binary> Bin = CHECK(createBinary(MB), this);121 std::unique_ptr<Binary> bin = CHECK(createBinary(mb), this);
117122
118 if (auto *Obj = dyn_cast<COFFObjectFile>(Bin.get())) {123 if (auto *obj = dyn_cast<COFFObjectFile>(bin.get())) {
119 Bin.release();124 bin.release();
120 COFFObj.reset(Obj);125 coffObj.reset(obj);
121 } else {126 } else {
122 fatal(toString(this) + " is not a COFF file");127 fatal(toString(this) + " is not a COFF file");
123 }128 }
...@@ -125,6 +130,15 @@ void ObjFile::parse() {...@@ -125,6 +130,15 @@ void ObjFile::parse() {
125 // Read section and symbol tables.130 // Read section and symbol tables.
126 initializeChunks();131 initializeChunks();
127 initializeSymbols();132 initializeSymbols();
133 initializeFlags();
134 initializeDependencies();
135}
136
137const coff_section* ObjFile::getSection(uint32_t i) {
138 const coff_section *sec;
139 if (auto ec = coffObj->getSection(i, sec))
140 fatal("getSection failed: #" + Twine(i) + ": " + ec.message());
141 return sec;
128}142}
129143
130// We set SectionChunk pointers in the SparseChunks vector to this value144// We set SectionChunk pointers in the SparseChunks vector to this value
...@@ -133,45 +147,42 @@ void ObjFile::parse() {...@@ -133,45 +147,42 @@ void ObjFile::parse() {
133// an associative section definition together with the parent comdat's leader,147// an associative section definition together with the parent comdat's leader,
134// we set the pointer to either nullptr (to mark the section as discarded) or a148// we set the pointer to either nullptr (to mark the section as discarded) or a
135// valid SectionChunk for that section.149// valid SectionChunk for that section.
136static SectionChunk *const PendingComdat = reinterpret_cast<SectionChunk *>(1);150static SectionChunk *const pendingComdat = reinterpret_cast<SectionChunk *>(1);
137151
138void ObjFile::initializeChunks() {152void ObjFile::initializeChunks() {
139 uint32_t NumSections = COFFObj->getNumberOfSections();153 uint32_t numSections = coffObj->getNumberOfSections();
140 Chunks.reserve(NumSections);154 chunks.reserve(numSections);
141 SparseChunks.resize(NumSections + 1);155 sparseChunks.resize(numSections + 1);
142 for (uint32_t I = 1; I < NumSections + 1; ++I) {156 for (uint32_t i = 1; i < numSections + 1; ++i) {
143 const coff_section *Sec;157 const coff_section *sec = getSection(i);
144 if (auto EC = COFFObj->getSection(I, Sec))158 if (sec->Characteristics & IMAGE_SCN_LNK_COMDAT)
145 fatal("getSection failed: #" + Twine(I) + ": " + EC.message());159 sparseChunks[i] = pendingComdat;
146
147 if (Sec->Characteristics & IMAGE_SCN_LNK_COMDAT)
148 SparseChunks[I] = PendingComdat;
149 else160 else
150 SparseChunks[I] = readSection(I, nullptr, "");161 sparseChunks[i] = readSection(i, nullptr, "");
151 }162 }
152}163}
153164
154SectionChunk *ObjFile::readSection(uint32_t SectionNumber,165SectionChunk *ObjFile::readSection(uint32_t sectionNumber,
155 const coff_aux_section_definition *Def,166 const coff_aux_section_definition *def,
156 StringRef LeaderName) {167 StringRef leaderName) {
157 const coff_section *Sec;168 const coff_section *sec = getSection(sectionNumber);
158 if (auto EC = COFFObj->getSection(SectionNumber, Sec))169
159 fatal("getSection failed: #" + Twine(SectionNumber) + ": " + EC.message());170 StringRef name;
160171 if (Expected<StringRef> e = coffObj->getSectionName(sec))
161 StringRef Name;172 name = *e;
162 if (auto EC = COFFObj->getSectionName(Sec, Name))173 else
163 fatal("getSectionName failed: #" + Twine(SectionNumber) + ": " +174 fatal("getSectionName failed: #" + Twine(sectionNumber) + ": " +
164 EC.message());175 toString(e.takeError()));
165176
166 if (Name == ".drectve") {177 if (name == ".drectve") {
167 ArrayRef<uint8_t> Data;178 ArrayRef<uint8_t> data;
168 COFFObj->getSectionContents(Sec, Data);179 cantFail(coffObj->getSectionContents(sec, data));
169 Directives = std::string((const char *)Data.data(), Data.size());180 directives = StringRef((const char *)data.data(), data.size());
170 return nullptr;181 return nullptr;
171 }182 }
172183
173 if (Name == ".llvm_addrsig") {184 if (name == ".llvm_addrsig") {
174 AddrsigSec = Sec;185 addrsigSec = sec;
175 return nullptr;186 return nullptr;
176 }187 }
177188
...@@ -186,377 +197,648 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber,...@@ -186,377 +197,648 @@ SectionChunk *ObjFile::readSection(uint32_t SectionNumber,
186 // and then write it to a separate .pdb file.197 // and then write it to a separate .pdb file.
187198
188 // Ignore DWARF debug info unless /debug is given.199 // Ignore DWARF debug info unless /debug is given.
189 if (!Config->Debug && Name.startswith(".debug_"))200 if (!config->debug && name.startswith(".debug_"))
190 return nullptr;201 return nullptr;
191202
192 if (Sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE)203 if (sec->Characteristics & llvm::COFF::IMAGE_SCN_LNK_REMOVE)
193 return nullptr;204 return nullptr;
194 auto *C = make<SectionChunk>(this, Sec);205 auto *c = make<SectionChunk>(this, sec);
195 if (Def)206 if (def)
196 C->Checksum = Def->CheckSum;207 c->checksum = def->CheckSum;
208
209 // link.exe uses the presence of .rsrc$01 for LNK4078, so match that.
210 if (name == ".rsrc$01")
211 isResourceObjFile = true;
197212
198 // CodeView sections are stored to a different vector because they are not213 // CodeView sections are stored to a different vector because they are not
199 // linked in the regular manner.214 // linked in the regular manner.
200 if (C->isCodeView())215 if (c->isCodeView())
201 DebugChunks.push_back(C);216 debugChunks.push_back(c);
202 else if (Config->GuardCF != GuardCFLevel::Off && Name == ".gfids$y")217 else if (name == ".gfids$y")
203 GuardFidChunks.push_back(C);218 guardFidChunks.push_back(c);
204 else if (Config->GuardCF != GuardCFLevel::Off && Name == ".gljmp$y")219 else if (name == ".gljmp$y")
205 GuardLJmpChunks.push_back(C);220 guardLJmpChunks.push_back(c);
206 else if (Name == ".sxdata")221 else if (name == ".sxdata")
207 SXDataChunks.push_back(C);222 sXDataChunks.push_back(c);
208 else if (Config->TailMerge && Sec->NumberOfRelocations == 0 &&223 else if (config->tailMerge && sec->NumberOfRelocations == 0 &&
209 Name == ".rdata" && LeaderName.startswith("??_C@"))224 name == ".rdata" && leaderName.startswith("??_C@"))
210 // COFF sections that look like string literal sections (i.e. no225 // COFF sections that look like string literal sections (i.e. no
211 // relocations, in .rdata, leader symbol name matches the MSVC name mangling226 // relocations, in .rdata, leader symbol name matches the MSVC name mangling
212 // for string literals) are subject to string tail merging.227 // for string literals) are subject to string tail merging.
213 MergeChunk::addSection(C);228 MergeChunk::addSection(c);
214 else229 else
215 Chunks.push_back(C);230 chunks.push_back(c);
216231
217 return C;232 return c;
218}233}
219234
220void ObjFile::readAssociativeDefinition(235void ObjFile::readAssociativeDefinition(
221 COFFSymbolRef Sym, const coff_aux_section_definition *Def) {236 COFFSymbolRef sym, const coff_aux_section_definition *def) {
222 readAssociativeDefinition(Sym, Def, Def->getNumber(Sym.isBigObj()));237 readAssociativeDefinition(sym, def, def->getNumber(sym.isBigObj()));
223}238}
224239
225void ObjFile::readAssociativeDefinition(COFFSymbolRef Sym,240void ObjFile::readAssociativeDefinition(COFFSymbolRef sym,
226 const coff_aux_section_definition *Def,241 const coff_aux_section_definition *def,
227 uint32_t ParentSection) {242 uint32_t parentIndex) {
228 SectionChunk *Parent = SparseChunks[ParentSection];243 SectionChunk *parent = sparseChunks[parentIndex];
244 int32_t sectionNumber = sym.getSectionNumber();
245
246 auto diag = [&]() {
247 StringRef name, parentName;
248 coffObj->getSymbolName(sym, name);
249
250 const coff_section *parentSec = getSection(parentIndex);
251 if (Expected<StringRef> e = coffObj->getSectionName(parentSec))
252 parentName = *e;
253 error(toString(this) + ": associative comdat " + name + " (sec " +
254 Twine(sectionNumber) + ") has invalid reference to section " +
255 parentName + " (sec " + Twine(parentIndex) + ")");
256 };
229257
230 // If the parent is pending, it probably means that its section definition258 if (parent == pendingComdat) {
231 // appears after us in the symbol table. Leave the associated section as259 // This can happen if an associative comdat refers to another associative
232 // pending; we will handle it during the second pass in initializeSymbols().260 // comdat that appears after it (invalid per COFF spec) or to a section
233 if (Parent == PendingComdat)261 // without any symbols.
262 diag();
234 return;263 return;
264 }
235265
236 // Check whether the parent is prevailing. If it is, so are we, and we read266 // Check whether the parent is prevailing. If it is, so are we, and we read
237 // the section; otherwise mark it as discarded.267 // the section; otherwise mark it as discarded.
238 int32_t SectionNumber = Sym.getSectionNumber();268 if (parent) {
239 if (Parent) {269 SectionChunk *c = readSection(sectionNumber, def, "");
240 SparseChunks[SectionNumber] = readSection(SectionNumber, Def, "");270 sparseChunks[sectionNumber] = c;
241 if (SparseChunks[SectionNumber])271 if (c) {
242 Parent->addAssociative(SparseChunks[SectionNumber]);272 c->selection = IMAGE_COMDAT_SELECT_ASSOCIATIVE;
273 parent->addAssociative(c);
274 }
243 } else {275 } else {
244 SparseChunks[SectionNumber] = nullptr;276 sparseChunks[sectionNumber] = nullptr;
245 }277 }
246}278}
247279
248void ObjFile::recordPrevailingSymbolForMingw(280void ObjFile::recordPrevailingSymbolForMingw(
249 COFFSymbolRef Sym, DenseMap<StringRef, uint32_t> &PrevailingSectionMap) {281 COFFSymbolRef sym, DenseMap<StringRef, uint32_t> &prevailingSectionMap) {
250 // For comdat symbols in executable sections, where this is the copy282 // For comdat symbols in executable sections, where this is the copy
251 // of the section chunk we actually include instead of discarding it,283 // of the section chunk we actually include instead of discarding it,
252 // add the symbol to a map to allow using it for implicitly284 // add the symbol to a map to allow using it for implicitly
253 // associating .[px]data$<func> sections to it.285 // associating .[px]data$<func> sections to it.
254 int32_t SectionNumber = Sym.getSectionNumber();286 int32_t sectionNumber = sym.getSectionNumber();
255 SectionChunk *SC = SparseChunks[SectionNumber];287 SectionChunk *sc = sparseChunks[sectionNumber];
256 if (SC && SC->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) {288 if (sc && sc->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE) {
257 StringRef Name;289 StringRef name;
258 COFFObj->getSymbolName(Sym, Name);290 coffObj->getSymbolName(sym, name);
259 PrevailingSectionMap[Name] = SectionNumber;291 if (getMachineType() == I386)
292 name.consume_front("_");
293 prevailingSectionMap[name] = sectionNumber;
260 }294 }
261}295}
262296
263void ObjFile::maybeAssociateSEHForMingw(297void ObjFile::maybeAssociateSEHForMingw(
264 COFFSymbolRef Sym, const coff_aux_section_definition *Def,298 COFFSymbolRef sym, const coff_aux_section_definition *def,
265 const DenseMap<StringRef, uint32_t> &PrevailingSectionMap) {299 const DenseMap<StringRef, uint32_t> &prevailingSectionMap) {
266 StringRef Name;300 StringRef name;
267 COFFObj->getSymbolName(Sym, Name);301 coffObj->getSymbolName(sym, name);
268 if (Name.consume_front(".pdata$") || Name.consume_front(".xdata$")) {302 if (name.consume_front(".pdata$") || name.consume_front(".xdata$") ||
269 // For MinGW, treat .[px]data$<func> as implicitly associative to303 name.consume_front(".eh_frame$")) {
270 // the symbol <func>.304 // For MinGW, treat .[px]data$<func> and .eh_frame$<func> as implicitly
271 auto ParentSym = PrevailingSectionMap.find(Name);305 // associative to the symbol <func>.
272 if (ParentSym != PrevailingSectionMap.end())306 auto parentSym = prevailingSectionMap.find(name);
273 readAssociativeDefinition(Sym, Def, ParentSym->second);307 if (parentSym != prevailingSectionMap.end())
308 readAssociativeDefinition(sym, def, parentSym->second);
274 }309 }
275}310}
276311
277Symbol *ObjFile::createRegular(COFFSymbolRef Sym) {312Symbol *ObjFile::createRegular(COFFSymbolRef sym) {
278 SectionChunk *SC = SparseChunks[Sym.getSectionNumber()];313 SectionChunk *sc = sparseChunks[sym.getSectionNumber()];
279 if (Sym.isExternal()) {314 if (sym.isExternal()) {
280 StringRef Name;315 StringRef name;
281 COFFObj->getSymbolName(Sym, Name);316 coffObj->getSymbolName(sym, name);
282 if (SC)317 if (sc)
283 return Symtab->addRegular(this, Name, Sym.getGeneric(), SC);318 return symtab->addRegular(this, name, sym.getGeneric(), sc);
284 // For MinGW symbols named .weak.* that point to a discarded section,319 // 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,320 // don't create an Undefined symbol. If nothing ever refers to the symbol,
286 // everything should be fine. If something actually refers to the symbol321 // everything should be fine. If something actually refers to the symbol
287 // (e.g. the undefined weak alias), linking will fail due to undefined322 // (e.g. the undefined weak alias), linking will fail due to undefined
288 // references at the end.323 // references at the end.
289 if (Config->MinGW && Name.startswith(".weak."))324 if (config->mingw && name.startswith(".weak."))
290 return nullptr;325 return nullptr;
291 return Symtab->addUndefined(Name, this, false);326 return symtab->addUndefined(name, this, false);
292 }327 }
293 if (SC)328 if (sc)
294 return make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,329 return make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,
295 /*IsExternal*/ false, Sym.getGeneric(), SC);330 /*IsExternal*/ false, sym.getGeneric(), sc);
296 return nullptr;331 return nullptr;
297}332}
298333
299void ObjFile::initializeSymbols() {334void ObjFile::initializeSymbols() {
300 uint32_t NumSymbols = COFFObj->getNumberOfSymbols();335 uint32_t numSymbols = coffObj->getNumberOfSymbols();
301 Symbols.resize(NumSymbols);336 symbols.resize(numSymbols);
302337
303 SmallVector<std::pair<Symbol *, uint32_t>, 8> WeakAliases;338 SmallVector<std::pair<Symbol *, uint32_t>, 8> weakAliases;
304 std::vector<uint32_t> PendingIndexes;339 std::vector<uint32_t> pendingIndexes;
305 PendingIndexes.reserve(NumSymbols);340 pendingIndexes.reserve(numSymbols);
306341
307 DenseMap<StringRef, uint32_t> PrevailingSectionMap;342 DenseMap<StringRef, uint32_t> prevailingSectionMap;
308 std::vector<const coff_aux_section_definition *> ComdatDefs(343 std::vector<const coff_aux_section_definition *> comdatDefs(
309 COFFObj->getNumberOfSections() + 1);344 coffObj->getNumberOfSections() + 1);
310345
311 for (uint32_t I = 0; I < NumSymbols; ++I) {346 for (uint32_t i = 0; i < numSymbols; ++i) {
312 COFFSymbolRef COFFSym = check(COFFObj->getSymbol(I));347 COFFSymbolRef coffSym = check(coffObj->getSymbol(i));
313 bool PrevailingComdat;348 bool prevailingComdat;
314 if (COFFSym.isUndefined()) {349 if (coffSym.isUndefined()) {
315 Symbols[I] = createUndefined(COFFSym);350 symbols[i] = createUndefined(coffSym);
316 } else if (COFFSym.isWeakExternal()) {351 } else if (coffSym.isWeakExternal()) {
317 Symbols[I] = createUndefined(COFFSym);352 symbols[i] = createUndefined(coffSym);
318 uint32_t TagIndex = COFFSym.getAux<coff_aux_weak_external>()->TagIndex;353 uint32_t tagIndex = coffSym.getAux<coff_aux_weak_external>()->TagIndex;
319 WeakAliases.emplace_back(Symbols[I], TagIndex);354 weakAliases.emplace_back(symbols[i], tagIndex);
320 } else if (Optional<Symbol *> OptSym =355 } else if (Optional<Symbol *> optSym =
321 createDefined(COFFSym, ComdatDefs, PrevailingComdat)) {356 createDefined(coffSym, comdatDefs, prevailingComdat)) {
322 Symbols[I] = *OptSym;357 symbols[i] = *optSym;
323 if (Config->MinGW && PrevailingComdat)358 if (config->mingw && prevailingComdat)
324 recordPrevailingSymbolForMingw(COFFSym, PrevailingSectionMap);359 recordPrevailingSymbolForMingw(coffSym, prevailingSectionMap);
325 } else {360 } else {
326 // createDefined() returns None if a symbol belongs to a section that361 // createDefined() returns None if a symbol belongs to a section that
327 // was pending at the point when the symbol was read. This can happen in362 // was pending at the point when the symbol was read. This can happen in
328 // two cases:363 // two cases:
329 // 1) section definition symbol for a comdat leader;364 // 1) section definition symbol for a comdat leader;
330 // 2) symbol belongs to a comdat section associated with a section whose365 // 2) symbol belongs to a comdat section associated with another section.
331 // section definition symbol appears later in the symbol table.
332 // In both of these cases, we can expect the section to be resolved by366 // In both of these cases, we can expect the section to be resolved by
333 // the time we finish visiting the remaining symbols in the symbol367 // the time we finish visiting the remaining symbols in the symbol
334 // table. So we postpone the handling of this symbol until that time.368 // table. So we postpone the handling of this symbol until that time.
335 PendingIndexes.push_back(I);369 pendingIndexes.push_back(i);
336 }370 }
337 I += COFFSym.getNumberOfAuxSymbols();371 i += coffSym.getNumberOfAuxSymbols();
338 }372 }
339373
340 for (uint32_t I : PendingIndexes) {374 for (uint32_t i : pendingIndexes) {
341 COFFSymbolRef Sym = check(COFFObj->getSymbol(I));375 COFFSymbolRef sym = check(coffObj->getSymbol(i));
342 if (const coff_aux_section_definition *Def = Sym.getSectionDefinition()) {376 if (const coff_aux_section_definition *def = sym.getSectionDefinition()) {
343 if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)377 if (def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)
344 readAssociativeDefinition(Sym, Def);378 readAssociativeDefinition(sym, def);
345 else if (Config->MinGW)379 else if (config->mingw)
346 maybeAssociateSEHForMingw(Sym, Def, PrevailingSectionMap);380 maybeAssociateSEHForMingw(sym, def, prevailingSectionMap);
347 }381 }
348 if (SparseChunks[Sym.getSectionNumber()] == PendingComdat) {382 if (sparseChunks[sym.getSectionNumber()] == pendingComdat) {
349 StringRef Name;383 StringRef name;
350 COFFObj->getSymbolName(Sym, Name);384 coffObj->getSymbolName(sym, name);
351 log("comdat section " + Name +385 log("comdat section " + name +
352 " without leader and unassociated, discarding");386 " without leader and unassociated, discarding");
353 continue;387 continue;
354 }388 }
355 Symbols[I] = createRegular(Sym);389 symbols[i] = createRegular(sym);
356 }390 }
357391
358 for (auto &KV : WeakAliases) {392 for (auto &kv : weakAliases) {
359 Symbol *Sym = KV.first;393 Symbol *sym = kv.first;
360 uint32_t Idx = KV.second;394 uint32_t idx = kv.second;
361 checkAndSetWeakAlias(Symtab, this, Sym, Symbols[Idx]);395 checkAndSetWeakAlias(symtab, this, sym, symbols[idx]);
362 }396 }
363}397}
364398
365Symbol *ObjFile::createUndefined(COFFSymbolRef Sym) {399Symbol *ObjFile::createUndefined(COFFSymbolRef sym) {
366 StringRef Name;400 StringRef name;
367 COFFObj->getSymbolName(Sym, Name);401 coffObj->getSymbolName(sym, name);
368 return Symtab->addUndefined(Name, this, Sym.isWeakExternal());402 return symtab->addUndefined(name, this, sym.isWeakExternal());
403}
404
405void ObjFile::handleComdatSelection(COFFSymbolRef sym, COMDATType &selection,
406 bool &prevailing, DefinedRegular *leader) {
407 if (prevailing)
408 return;
409 // There's already an existing comdat for this symbol: `Leader`.
410 // Use the comdats's selection field to determine if the new
411 // symbol in `Sym` should be discarded, produce a duplicate symbol
412 // error, etc.
413
414 SectionChunk *leaderChunk = nullptr;
415 COMDATType leaderSelection = IMAGE_COMDAT_SELECT_ANY;
416
417 if (leader->data) {
418 leaderChunk = leader->getChunk();
419 leaderSelection = leaderChunk->selection;
420 } else {
421 // FIXME: comdats from LTO files don't know their selection; treat them
422 // as "any".
423 selection = leaderSelection;
424 }
425
426 if ((selection == IMAGE_COMDAT_SELECT_ANY &&
427 leaderSelection == IMAGE_COMDAT_SELECT_LARGEST) ||
428 (selection == IMAGE_COMDAT_SELECT_LARGEST &&
429 leaderSelection == IMAGE_COMDAT_SELECT_ANY)) {
430 // cl.exe picks "any" for vftables when building with /GR- and
431 // "largest" when building with /GR. To be able to link object files
432 // compiled with each flag, "any" and "largest" are merged as "largest".
433 leaderSelection = selection = IMAGE_COMDAT_SELECT_LARGEST;
434 }
435
436 // Other than that, comdat selections must match. This is a bit more
437 // strict than link.exe which allows merging "any" and "largest" if "any"
438 // is the first symbol the linker sees, and it allows merging "largest"
439 // with everything (!) if "largest" is the first symbol the linker sees.
440 // Making this symmetric independent of which selection is seen first
441 // seems better though.
442 // (This behavior matches ModuleLinker::getComdatResult().)
443 if (selection != leaderSelection) {
444 log(("conflicting comdat type for " + toString(*leader) + ": " +
445 Twine((int)leaderSelection) + " in " + toString(leader->getFile()) +
446 " and " + Twine((int)selection) + " in " + toString(this))
447 .str());
448 symtab->reportDuplicate(leader, this);
449 return;
450 }
451
452 switch (selection) {
453 case IMAGE_COMDAT_SELECT_NODUPLICATES:
454 symtab->reportDuplicate(leader, this);
455 break;
456
457 case IMAGE_COMDAT_SELECT_ANY:
458 // Nothing to do.
459 break;
460
461 case IMAGE_COMDAT_SELECT_SAME_SIZE:
462 if (leaderChunk->getSize() != getSection(sym)->SizeOfRawData)
463 symtab->reportDuplicate(leader, this);
464 break;
465
466 case IMAGE_COMDAT_SELECT_EXACT_MATCH: {
467 SectionChunk newChunk(this, getSection(sym));
468 // link.exe only compares section contents here and doesn't complain
469 // if the two comdat sections have e.g. different alignment.
470 // Match that.
471 if (leaderChunk->getContents() != newChunk.getContents())
472 symtab->reportDuplicate(leader, this);
473 break;
474 }
475
476 case IMAGE_COMDAT_SELECT_ASSOCIATIVE:
477 // createDefined() is never called for IMAGE_COMDAT_SELECT_ASSOCIATIVE.
478 // (This means lld-link doesn't produce duplicate symbol errors for
479 // associative comdats while link.exe does, but associate comdats
480 // are never extern in practice.)
481 llvm_unreachable("createDefined not called for associative comdats");
482
483 case IMAGE_COMDAT_SELECT_LARGEST:
484 if (leaderChunk->getSize() < getSection(sym)->SizeOfRawData) {
485 // Replace the existing comdat symbol with the new one.
486 StringRef name;
487 coffObj->getSymbolName(sym, name);
488 // FIXME: This is incorrect: With /opt:noref, the previous sections
489 // make it into the final executable as well. Correct handling would
490 // be to undo reading of the whole old section that's being replaced,
491 // or doing one pass that determines what the final largest comdat
492 // is for all IMAGE_COMDAT_SELECT_LARGEST comdats and then reading
493 // only the largest one.
494 replaceSymbol<DefinedRegular>(leader, this, name, /*IsCOMDAT*/ true,
495 /*IsExternal*/ true, sym.getGeneric(),
496 nullptr);
497 prevailing = true;
498 }
499 break;
500
501 case IMAGE_COMDAT_SELECT_NEWEST:
502 llvm_unreachable("should have been rejected earlier");
503 }
369}504}
370505
371Optional<Symbol *> ObjFile::createDefined(506Optional<Symbol *> ObjFile::createDefined(
372 COFFSymbolRef Sym,507 COFFSymbolRef sym,
373 std::vector<const coff_aux_section_definition *> &ComdatDefs,508 std::vector<const coff_aux_section_definition *> &comdatDefs,
374 bool &Prevailing) {509 bool &prevailing) {
375 Prevailing = false;510 prevailing = false;
376 auto GetName = [&]() {511 auto getName = [&]() {
377 StringRef S;512 StringRef s;
378 COFFObj->getSymbolName(Sym, S);513 coffObj->getSymbolName(sym, s);
379 return S;514 return s;
380 };515 };
381516
382 if (Sym.isCommon()) {517 if (sym.isCommon()) {
383 auto *C = make<CommonChunk>(Sym);518 auto *c = make<CommonChunk>(sym);
384 Chunks.push_back(C);519 chunks.push_back(c);
385 return Symtab->addCommon(this, GetName(), Sym.getValue(), Sym.getGeneric(),520 return symtab->addCommon(this, getName(), sym.getValue(), sym.getGeneric(),
386 C);521 c);
387 }522 }
388523
389 if (Sym.isAbsolute()) {524 if (sym.isAbsolute()) {
390 StringRef Name = GetName();525 StringRef name = getName();
391526
392 // Skip special symbols.527 // Skip special symbols.
393 if (Name == "@comp.id")528 if (name == "@comp.id")
394 return nullptr;529 return nullptr;
395 if (Name == "@feat.00") {530 if (name == "@feat.00") {
396 Feat00Flags = Sym.getValue();531 feat00Flags = sym.getValue();
397 return nullptr;532 return nullptr;
398 }533 }
399534
400 if (Sym.isExternal())535 if (sym.isExternal())
401 return Symtab->addAbsolute(Name, Sym);536 return symtab->addAbsolute(name, sym);
402 return make<DefinedAbsolute>(Name, Sym);537 return make<DefinedAbsolute>(name, sym);
403 }538 }
404539
405 int32_t SectionNumber = Sym.getSectionNumber();540 int32_t sectionNumber = sym.getSectionNumber();
406 if (SectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)541 if (sectionNumber == llvm::COFF::IMAGE_SYM_DEBUG)
407 return nullptr;542 return nullptr;
408543
409 if (llvm::COFF::isReservedSectionNumber(SectionNumber))544 if (llvm::COFF::isReservedSectionNumber(sectionNumber))
410 fatal(toString(this) + ": " + GetName() +545 fatal(toString(this) + ": " + getName() +
411 " should not refer to special section " + Twine(SectionNumber));546 " should not refer to special section " + Twine(sectionNumber));
412547
413 if ((uint32_t)SectionNumber >= SparseChunks.size())548 if ((uint32_t)sectionNumber >= sparseChunks.size())
414 fatal(toString(this) + ": " + GetName() +549 fatal(toString(this) + ": " + getName() +
415 " should not refer to non-existent section " + Twine(SectionNumber));550 " should not refer to non-existent section " + Twine(sectionNumber));
416551
417 // Handle comdat leader symbols.552 // Comdat handling.
418 if (const coff_aux_section_definition *Def = ComdatDefs[SectionNumber]) {553 // A comdat symbol consists of two symbol table entries.
419 ComdatDefs[SectionNumber] = nullptr;554 // The first symbol entry has the name of the section (e.g. .text), fixed
420 Symbol *Leader;555 // values for the other fields, and one auxilliary record.
421 if (Sym.isExternal()) {556 // The second symbol entry has the name of the comdat symbol, called the
422 std::tie(Leader, Prevailing) =557 // "comdat leader".
423 Symtab->addComdat(this, GetName(), Sym.getGeneric());558 // When this function is called for the first symbol entry of a comdat,
559 // it sets comdatDefs and returns None, and when it's called for the second
560 // symbol entry it reads comdatDefs and then sets it back to nullptr.
561
562 // Handle comdat leader.
563 if (const coff_aux_section_definition *def = comdatDefs[sectionNumber]) {
564 comdatDefs[sectionNumber] = nullptr;
565 DefinedRegular *leader;
566
567 if (sym.isExternal()) {
568 std::tie(leader, prevailing) =
569 symtab->addComdat(this, getName(), sym.getGeneric());
424 } else {570 } else {
425 Leader = make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,571 leader = make<DefinedRegular>(this, /*Name*/ "", /*IsCOMDAT*/ false,
426 /*IsExternal*/ false, Sym.getGeneric());572 /*IsExternal*/ false, sym.getGeneric());
427 Prevailing = true;573 prevailing = true;
428 }574 }
429575
430 if (Prevailing) {576 if (def->Selection < (int)IMAGE_COMDAT_SELECT_NODUPLICATES ||
431 SectionChunk *C = readSection(SectionNumber, Def, GetName());577 // Intentionally ends at IMAGE_COMDAT_SELECT_LARGEST: link.exe
432 SparseChunks[SectionNumber] = C;578 // doesn't understand IMAGE_COMDAT_SELECT_NEWEST either.
433 C->Sym = cast<DefinedRegular>(Leader);579 def->Selection > (int)IMAGE_COMDAT_SELECT_LARGEST) {
434 cast<DefinedRegular>(Leader)->Data = &C->Repl;580 fatal("unknown comdat type " + std::to_string((int)def->Selection) +
435 } else {581 " for " + getName() + " in " + toString(this));
436 SparseChunks[SectionNumber] = nullptr;
437 }582 }
438 return Leader;583 COMDATType selection = (COMDATType)def->Selection;
439 }
440584
441 // Read associative section definitions and prepare to handle the comdat585 if (leader->isCOMDAT)
442 // leader symbol by setting the section's ComdatDefs pointer if we encounter a586 handleComdatSelection(sym, selection, prevailing, leader);
443 // non-associative comdat.587
444 if (SparseChunks[SectionNumber] == PendingComdat) {588 if (prevailing) {
445 if (const coff_aux_section_definition *Def = Sym.getSectionDefinition()) {589 SectionChunk *c = readSection(sectionNumber, def, getName());
446 if (Def->Selection == IMAGE_COMDAT_SELECT_ASSOCIATIVE)590 sparseChunks[sectionNumber] = c;
447 readAssociativeDefinition(Sym, Def);591 c->sym = cast<DefinedRegular>(leader);
448 else592 c->selection = selection;
449 ComdatDefs[SectionNumber] = Def;593 cast<DefinedRegular>(leader)->data = &c->repl;
594 } else {
595 sparseChunks[sectionNumber] = nullptr;
450 }596 }
597 return leader;
451 }598 }
452599
453 // readAssociativeDefinition() writes to SparseChunks, so need to check again.600 // Prepare to handle the comdat leader symbol by setting the section's
454 if (SparseChunks[SectionNumber] == PendingComdat)601 // ComdatDefs pointer if we encounter a non-associative comdat.
602 if (sparseChunks[sectionNumber] == pendingComdat) {
603 if (const coff_aux_section_definition *def = sym.getSectionDefinition()) {
604 if (def->Selection != IMAGE_COMDAT_SELECT_ASSOCIATIVE)
605 comdatDefs[sectionNumber] = def;
606 }
455 return None;607 return None;
608 }
456609
457 return createRegular(Sym);610 return createRegular(sym);
458}611}
459612
460MachineTypes ObjFile::getMachineType() {613MachineTypes ObjFile::getMachineType() {
461 if (COFFObj)614 if (coffObj)
462 return static_cast<MachineTypes>(COFFObj->getMachine());615 return static_cast<MachineTypes>(coffObj->getMachine());
463 return IMAGE_FILE_MACHINE_UNKNOWN;616 return IMAGE_FILE_MACHINE_UNKNOWN;
464}617}
465618
466StringRef ltrim1(StringRef S, const char *Chars) {619ArrayRef<uint8_t> ObjFile::getDebugSection(StringRef secName) {
467 if (!S.empty() && strchr(Chars, S[0]))620 if (SectionChunk *sec = SectionChunk::findByName(debugChunks, secName))
468 return S.substr(1);621 return sec->consumeDebugMagic();
469 return S;622 return {};
623}
624
625// OBJ files systematically store critical informations in a .debug$S stream,
626// even if the TU was compiled with no debug info. At least two records are
627// always there. S_OBJNAME stores a 32-bit signature, which is loaded into the
628// PCHSignature member. S_COMPILE3 stores compile-time cmd-line flags. This is
629// currently used to initialize the hotPatchable member.
630void ObjFile::initializeFlags() {
631 ArrayRef<uint8_t> data = getDebugSection(".debug$S");
632 if (data.empty())
633 return;
634
635 DebugSubsectionArray subsections;
636
637 BinaryStreamReader reader(data, support::little);
638 ExitOnError exitOnErr;
639 exitOnErr(reader.readArray(subsections, data.size()));
640
641 for (const DebugSubsectionRecord &ss : subsections) {
642 if (ss.kind() != DebugSubsectionKind::Symbols)
643 continue;
644
645 unsigned offset = 0;
646
647 // Only parse the first two records. We are only looking for S_OBJNAME
648 // and S_COMPILE3, and they usually appear at the beginning of the
649 // stream.
650 for (unsigned i = 0; i < 2; ++i) {
651 Expected<CVSymbol> sym = readSymbolFromStream(ss.getRecordData(), offset);
652 if (!sym) {
653 consumeError(sym.takeError());
654 return;
655 }
656 if (sym->kind() == SymbolKind::S_COMPILE3) {
657 auto cs =
658 cantFail(SymbolDeserializer::deserializeAs<Compile3Sym>(sym.get()));
659 hotPatchable =
660 (cs.Flags & CompileSym3Flags::HotPatch) != CompileSym3Flags::None;
661 }
662 if (sym->kind() == SymbolKind::S_OBJNAME) {
663 auto objName = cantFail(SymbolDeserializer::deserializeAs<ObjNameSym>(
664 sym.get()));
665 pchSignature = objName.Signature;
666 }
667 offset += sym->length();
668 }
669 }
670}
671
672// Depending on the compilation flags, OBJs can refer to external files,
673// necessary to merge this OBJ into the final PDB. We currently support two
674// types of external files: Precomp/PCH OBJs, when compiling with /Yc and /Yu.
675// And PDB type servers, when compiling with /Zi. This function extracts these
676// dependencies and makes them available as a TpiSource interface (see
677// DebugTypes.h). Both cases only happen with cl.exe: clang-cl produces regular
678// output even with /Yc and /Yu and with /Zi.
679void ObjFile::initializeDependencies() {
680 if (!config->debug)
681 return;
682
683 bool isPCH = false;
684
685 ArrayRef<uint8_t> data = getDebugSection(".debug$P");
686 if (!data.empty())
687 isPCH = true;
688 else
689 data = getDebugSection(".debug$T");
690
691 if (data.empty())
692 return;
693
694 CVTypeArray types;
695 BinaryStreamReader reader(data, support::little);
696 cantFail(reader.readArray(types, reader.getLength()));
697
698 CVTypeArray::Iterator firstType = types.begin();
699 if (firstType == types.end())
700 return;
701
702 debugTypes.emplace(types);
703
704 if (isPCH) {
705 debugTypesObj = makePrecompSource(this);
706 return;
707 }
708
709 if (firstType->kind() == LF_TYPESERVER2) {
710 TypeServer2Record ts = cantFail(
711 TypeDeserializer::deserializeAs<TypeServer2Record>(firstType->data()));
712 debugTypesObj = makeUseTypeServerSource(this, &ts);
713 return;
714 }
715
716 if (firstType->kind() == LF_PRECOMP) {
717 PrecompRecord precomp = cantFail(
718 TypeDeserializer::deserializeAs<PrecompRecord>(firstType->data()));
719 debugTypesObj = makeUsePrecompSource(this, &precomp);
720 return;
721 }
722
723 debugTypesObj = makeTpiSource(this);
724}
725
726StringRef ltrim1(StringRef s, const char *chars) {
727 if (!s.empty() && strchr(chars, s[0]))
728 return s.substr(1);
729 return s;
470}730}
471731
472void ImportFile::parse() {732void ImportFile::parse() {
473 const char *Buf = MB.getBufferStart();733 const char *buf = mb.getBufferStart();
474 const char *End = MB.getBufferEnd();734 const auto *hdr = reinterpret_cast<const coff_import_header *>(buf);
475 const auto *Hdr = reinterpret_cast<const coff_import_header *>(Buf);
476735
477 // Check if the total size is valid.736 // Check if the total size is valid.
478 if ((size_t)(End - Buf) != (sizeof(*Hdr) + Hdr->SizeOfData))737 if (mb.getBufferSize() != sizeof(*hdr) + hdr->SizeOfData)
479 fatal("broken import library");738 fatal("broken import library");
480739
481 // Read names and create an __imp_ symbol.740 // Read names and create an __imp_ symbol.
482 StringRef Name = Saver.save(StringRef(Buf + sizeof(*Hdr)));741 StringRef name = saver.save(StringRef(buf + sizeof(*hdr)));
483 StringRef ImpName = Saver.save("__imp_" + Name);742 StringRef impName = saver.save("__imp_" + name);
484 const char *NameStart = Buf + sizeof(coff_import_header) + Name.size() + 1;743 const char *nameStart = buf + sizeof(coff_import_header) + name.size() + 1;
485 DLLName = StringRef(NameStart);744 dllName = StringRef(nameStart);
486 StringRef ExtName;745 StringRef extName;
487 switch (Hdr->getNameType()) {746 switch (hdr->getNameType()) {
488 case IMPORT_ORDINAL:747 case IMPORT_ORDINAL:
489 ExtName = "";748 extName = "";
490 break;749 break;
491 case IMPORT_NAME:750 case IMPORT_NAME:
492 ExtName = Name;751 extName = name;
493 break;752 break;
494 case IMPORT_NAME_NOPREFIX:753 case IMPORT_NAME_NOPREFIX:
495 ExtName = ltrim1(Name, "?@_");754 extName = ltrim1(name, "?@_");
496 break;755 break;
497 case IMPORT_NAME_UNDECORATE:756 case IMPORT_NAME_UNDECORATE:
498 ExtName = ltrim1(Name, "?@_");757 extName = ltrim1(name, "?@_");
499 ExtName = ExtName.substr(0, ExtName.find('@'));758 extName = extName.substr(0, extName.find('@'));
500 break;759 break;
501 }760 }
502761
503 this->Hdr = Hdr;762 this->hdr = hdr;
504 ExternalName = ExtName;763 externalName = extName;
505764
506 ImpSym = Symtab->addImportData(ImpName, this);765 impSym = symtab->addImportData(impName, this);
507 // If this was a duplicate, we logged an error but may continue;766 // If this was a duplicate, we logged an error but may continue;
508 // in this case, ImpSym is nullptr.767 // in this case, impSym is nullptr.
509 if (!ImpSym)768 if (!impSym)
510 return;769 return;
511770
512 if (Hdr->getType() == llvm::COFF::IMPORT_CONST)771 if (hdr->getType() == llvm::COFF::IMPORT_CONST)
513 static_cast<void>(Symtab->addImportData(Name, this));772 static_cast<void>(symtab->addImportData(name, this));
514773
515 // If type is function, we need to create a thunk which jump to an774 // If type is function, we need to create a thunk which jump to an
516 // address pointed by the __imp_ symbol. (This allows you to call775 // address pointed by the __imp_ symbol. (This allows you to call
517 // DLL functions just like regular non-DLL functions.)776 // DLL functions just like regular non-DLL functions.)
518 if (Hdr->getType() == llvm::COFF::IMPORT_CODE)777 if (hdr->getType() == llvm::COFF::IMPORT_CODE)
519 ThunkSym = Symtab->addImportThunk(778 thunkSym = symtab->addImportThunk(
520 Name, cast_or_null<DefinedImportData>(ImpSym), Hdr->Machine);779 name, cast_or_null<DefinedImportData>(impSym), hdr->Machine);
780}
781
782BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
783 uint64_t offsetInArchive)
784 : InputFile(BitcodeKind, mb) {
785 std::string path = mb.getBufferIdentifier().str();
786 if (config->thinLTOIndexOnly)
787 path = replaceThinLTOSuffix(mb.getBufferIdentifier());
788
789 // ThinLTO assumes that all MemoryBufferRefs given to it have a unique
790 // name. If two archives define two members with the same name, this
791 // causes a collision which result in only one of the objects being taken
792 // into consideration at LTO time (which very likely causes undefined
793 // symbols later in the link stage). So we append file offset to make
794 // filename unique.
795 MemoryBufferRef mbref(
796 mb.getBuffer(),
797 saver.save(archiveName + path +
798 (archiveName.empty() ? "" : utostr(offsetInArchive))));
799
800 obj = check(lto::InputFile::create(mbref));
521}801}
522802
523void BitcodeFile::parse() {803void BitcodeFile::parse() {
524 Obj = check(lto::InputFile::create(MemoryBufferRef(804 std::vector<std::pair<Symbol *, bool>> comdat(obj->getComdatTable().size());
525 MB.getBuffer(), Saver.save(ParentName + MB.getBufferIdentifier()))));805 for (size_t i = 0; i != obj->getComdatTable().size(); ++i)
526 std::vector<std::pair<Symbol *, bool>> Comdat(Obj->getComdatTable().size());806 // FIXME: lto::InputFile doesn't keep enough data to do correct comdat
527 for (size_t I = 0; I != Obj->getComdatTable().size(); ++I)807 // selection handling.
528 Comdat[I] = Symtab->addComdat(this, Saver.save(Obj->getComdatTable()[I]));808 comdat[i] = symtab->addComdat(this, saver.save(obj->getComdatTable()[i]));
529 for (const lto::InputFile::Symbol &ObjSym : Obj->symbols()) {809 for (const lto::InputFile::Symbol &objSym : obj->symbols()) {
530 StringRef SymName = Saver.save(ObjSym.getName());810 StringRef symName = saver.save(objSym.getName());
531 int ComdatIndex = ObjSym.getComdatIndex();811 int comdatIndex = objSym.getComdatIndex();
532 Symbol *Sym;812 Symbol *sym;
533 if (ObjSym.isUndefined()) {813 if (objSym.isUndefined()) {
534 Sym = Symtab->addUndefined(SymName, this, false);814 sym = symtab->addUndefined(symName, this, false);
535 } else if (ObjSym.isCommon()) {815 } else if (objSym.isCommon()) {
536 Sym = Symtab->addCommon(this, SymName, ObjSym.getCommonSize());816 sym = symtab->addCommon(this, symName, objSym.getCommonSize());
537 } else if (ObjSym.isWeak() && ObjSym.isIndirect()) {817 } else if (objSym.isWeak() && objSym.isIndirect()) {
538 // Weak external.818 // Weak external.
539 Sym = Symtab->addUndefined(SymName, this, true);819 sym = symtab->addUndefined(symName, this, true);
540 std::string Fallback = ObjSym.getCOFFWeakExternalFallback();820 std::string fallback = objSym.getCOFFWeakExternalFallback();
541 Symbol *Alias = Symtab->addUndefined(Saver.save(Fallback));821 Symbol *alias = symtab->addUndefined(saver.save(fallback));
542 checkAndSetWeakAlias(Symtab, this, Sym, Alias);822 checkAndSetWeakAlias(symtab, this, sym, alias);
543 } else if (ComdatIndex != -1) {823 } else if (comdatIndex != -1) {
544 if (SymName == Obj->getComdatTable()[ComdatIndex])824 if (symName == obj->getComdatTable()[comdatIndex])
545 Sym = Comdat[ComdatIndex].first;825 sym = comdat[comdatIndex].first;
546 else if (Comdat[ComdatIndex].second)826 else if (comdat[comdatIndex].second)
547 Sym = Symtab->addRegular(this, SymName);827 sym = symtab->addRegular(this, symName);
548 else828 else
549 Sym = Symtab->addUndefined(SymName, this, false);829 sym = symtab->addUndefined(symName, this, false);
550 } else {830 } else {
551 Sym = Symtab->addRegular(this, SymName);831 sym = symtab->addRegular(this, symName);
552 }832 }
553 Symbols.push_back(Sym);833 symbols.push_back(sym);
834 if (objSym.isUsed())
835 config->gcroot.push_back(sym);
554 }836 }
555 Directives = Obj->getCOFFLinkerOpts();837 directives = obj->getCOFFLinkerOpts();
556}838}
557839
558MachineTypes BitcodeFile::getMachineType() {840MachineTypes BitcodeFile::getMachineType() {
559 switch (Triple(Obj->getTargetTriple()).getArch()) {841 switch (Triple(obj->getTargetTriple()).getArch()) {
560 case Triple::x86_64:842 case Triple::x86_64:
561 return AMD64;843 return AMD64;
562 case Triple::x86:844 case Triple::x86:
...@@ -569,22 +851,31 @@ MachineTypes BitcodeFile::getMachineType() {...@@ -569,22 +851,31 @@ MachineTypes BitcodeFile::getMachineType() {
569 return IMAGE_FILE_MACHINE_UNKNOWN;851 return IMAGE_FILE_MACHINE_UNKNOWN;
570 }852 }
571}853}
854
855std::string replaceThinLTOSuffix(StringRef path) {
856 StringRef suffix = config->thinLTOObjectSuffixReplace.first;
857 StringRef repl = config->thinLTOObjectSuffixReplace.second;
858
859 if (path.consume_back(suffix))
860 return (path + repl).str();
861 return path;
862}
572} // namespace coff863} // namespace coff
573} // namespace lld864} // namespace lld
574865
575// Returns the last element of a path, which is supposed to be a filename.866// Returns the last element of a path, which is supposed to be a filename.
576static StringRef getBasename(StringRef Path) {867static StringRef getBasename(StringRef path) {
577 return sys::path::filename(Path, sys::path::Style::windows);868 return sys::path::filename(path, sys::path::Style::windows);
578}869}
579870
580// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".871// Returns a string in the format of "foo.obj" or "foo.obj(bar.lib)".
581std::string lld::toString(const coff::InputFile *File) {872std::string lld::toString(const coff::InputFile *file) {
582 if (!File)873 if (!file)
583 return "<internal>";874 return "<internal>";
584 if (File->ParentName.empty())875 if (file->parentName.empty() || file->kind() == coff::InputFile::ImportKind)
585 return File->getName();876 return file->getName();
586877
587 return (getBasename(File->ParentName) + "(" + getBasename(File->getName()) +878 return (getBasename(file->parentName) + "(" + getBasename(file->getName()) +
588 ")")879 ")")
589 .str();880 .str();
590}881}
deps/lld/COFF/InputFiles.h+125-84
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputFiles.h ---------------------------------------------*- C++ -*-===//1//===- InputFiles.h ---------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -33,7 +32,7 @@ class DbiModuleDescriptorBuilder;...@@ -33,7 +32,7 @@ class DbiModuleDescriptorBuilder;
33namespace lld {32namespace lld {
34namespace coff {33namespace coff {
3534
36std::vector<MemoryBufferRef> getArchiveMembers(llvm::object::Archive *File);35std::vector<MemoryBufferRef> getArchiveMembers(llvm::object::Archive *file);
3736
38using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;37using llvm::COFF::IMAGE_FILE_MACHINE_UNKNOWN;
39using llvm::COFF::MachineTypes;38using llvm::COFF::MachineTypes;
...@@ -47,20 +46,22 @@ class Chunk;...@@ -47,20 +46,22 @@ class Chunk;
47class Defined;46class Defined;
48class DefinedImportData;47class DefinedImportData;
49class DefinedImportThunk;48class DefinedImportThunk;
49class DefinedRegular;
50class Lazy;50class Lazy;
51class SectionChunk;51class SectionChunk;
52class Symbol;52class Symbol;
53class Undefined;53class Undefined;
54class TpiSource;
5455
55// The root class of input files.56// The root class of input files.
56class InputFile {57class InputFile {
57public:58public:
58 enum Kind { ArchiveKind, ObjectKind, ImportKind, BitcodeKind };59 enum Kind { ArchiveKind, ObjectKind, ImportKind, BitcodeKind };
59 Kind kind() const { return FileKind; }60 Kind kind() const { return fileKind; }
60 virtual ~InputFile() {}61 virtual ~InputFile() {}
6162
62 // Returns the filename.63 // Returns the filename.
63 StringRef getName() const { return MB.getBufferIdentifier(); }64 StringRef getName() const { return mb.getBufferIdentifier(); }
6465
65 // Reads a file (the constructor doesn't do that).66 // Reads a file (the constructor doesn't do that).
66 virtual void parse() = 0;67 virtual void parse() = 0;
...@@ -68,158 +69,195 @@ public:...@@ -68,158 +69,195 @@ public:
68 // Returns the CPU type this file was compiled to.69 // Returns the CPU type this file was compiled to.
69 virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; }70 virtual MachineTypes getMachineType() { return IMAGE_FILE_MACHINE_UNKNOWN; }
7071
71 MemoryBufferRef MB;72 MemoryBufferRef mb;
7273
73 // An archive file name if this file is created from an archive.74 // An archive file name if this file is created from an archive.
74 StringRef ParentName;75 StringRef parentName;
7576
76 // Returns .drectve section contents if exist.77 // Returns .drectve section contents if exist.
77 StringRef getDirectives() { return StringRef(Directives).trim(); }78 StringRef getDirectives() { return directives; }
7879
79protected:80protected:
80 InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}81 InputFile(Kind k, MemoryBufferRef m) : mb(m), fileKind(k) {}
8182
82 std::string Directives;83 StringRef directives;
8384
84private:85private:
85 const Kind FileKind;86 const Kind fileKind;
86};87};
8788
88// .lib or .a file.89// .lib or .a file.
89class ArchiveFile : public InputFile {90class ArchiveFile : public InputFile {
90public:91public:
91 explicit ArchiveFile(MemoryBufferRef M);92 explicit ArchiveFile(MemoryBufferRef m);
92 static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }93 static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
93 void parse() override;94 void parse() override;
9495
95 // Enqueues an archive member load for the given symbol. If we've already96 // Enqueues an archive member load for the given symbol. If we've already
96 // enqueued a load for the same archive member, this function does nothing,97 // enqueued a load for the same archive member, this function does nothing,
97 // which ensures that we don't load the same member more than once.98 // which ensures that we don't load the same member more than once.
98 void addMember(const Archive::Symbol *Sym);99 void addMember(const Archive::Symbol *sym);
99100
100private:101private:
101 std::unique_ptr<Archive> File;102 std::unique_ptr<Archive> file;
102 std::string Filename;103 llvm::DenseSet<uint64_t> seen;
103 llvm::DenseSet<uint64_t> Seen;
104};104};
105105
106// .obj or .o file. This may be a member of an archive file.106// .obj or .o file. This may be a member of an archive file.
107class ObjFile : public InputFile {107class ObjFile : public InputFile {
108public:108public:
109 explicit ObjFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {}109 explicit ObjFile(MemoryBufferRef m) : InputFile(ObjectKind, m) {}
110 static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }110 static bool classof(const InputFile *f) { return f->kind() == ObjectKind; }
111 void parse() override;111 void parse() override;
112 MachineTypes getMachineType() override;112 MachineTypes getMachineType() override;
113 ArrayRef<Chunk *> getChunks() { return Chunks; }113 ArrayRef<Chunk *> getChunks() { return chunks; }
114 ArrayRef<SectionChunk *> getDebugChunks() { return DebugChunks; }114 ArrayRef<SectionChunk *> getDebugChunks() { return debugChunks; }
115 ArrayRef<SectionChunk *> getSXDataChunks() { return SXDataChunks; }115 ArrayRef<SectionChunk *> getSXDataChunks() { return sXDataChunks; }
116 ArrayRef<SectionChunk *> getGuardFidChunks() { return GuardFidChunks; }116 ArrayRef<SectionChunk *> getGuardFidChunks() { return guardFidChunks; }
117 ArrayRef<SectionChunk *> getGuardLJmpChunks() { return GuardLJmpChunks; }117 ArrayRef<SectionChunk *> getGuardLJmpChunks() { return guardLJmpChunks; }
118 ArrayRef<Symbol *> getSymbols() { return Symbols; }118 ArrayRef<Symbol *> getSymbols() { return symbols; }
119119
120 // Returns a Symbol object for the SymbolIndex'th symbol in the120 ArrayRef<uint8_t> getDebugSection(StringRef secName);
121
122 // Returns a Symbol object for the symbolIndex'th symbol in the
121 // underlying object file.123 // underlying object file.
122 Symbol *getSymbol(uint32_t SymbolIndex) {124 Symbol *getSymbol(uint32_t symbolIndex) {
123 return Symbols[SymbolIndex];125 return symbols[symbolIndex];
124 }126 }
125127
126 // Returns the underlying COFF file.128 // Returns the underlying COFF file.
127 COFFObjectFile *getCOFFObj() { return COFFObj.get(); }129 COFFObjectFile *getCOFFObj() { return coffObj.get(); }
128130
129 // Whether the object was already merged into the final PDB or not131 // Add a symbol for a range extension thunk. Return the new symbol table
130 bool wasProcessedForPDB() const { return !!ModuleDBI; }132 // index. This index can be used to modify a relocation.
133 uint32_t addRangeThunkSymbol(Symbol *thunk) {
134 symbols.push_back(thunk);
135 return symbols.size() - 1;
136 }
131137
132 static std::vector<ObjFile *> Instances;138 static std::vector<ObjFile *> instances;
133139
134 // Flags in the absolute @feat.00 symbol if it is present. These usually140 // Flags in the absolute @feat.00 symbol if it is present. These usually
135 // indicate if an object was compiled with certain security features enabled141 // indicate if an object was compiled with certain security features enabled
136 // like stack guard, safeseh, /guard:cf, or other things.142 // like stack guard, safeseh, /guard:cf, or other things.
137 uint32_t Feat00Flags = 0;143 uint32_t feat00Flags = 0;
138144
139 // True if this object file is compatible with SEH. COFF-specific and145 // True if this object file is compatible with SEH. COFF-specific and
140 // x86-only. COFF spec 5.10.1. The .sxdata section.146 // x86-only. COFF spec 5.10.1. The .sxdata section.
141 bool hasSafeSEH() { return Feat00Flags & 0x1; }147 bool hasSafeSEH() { return feat00Flags & 0x1; }
142148
143 // True if this file was compiled with /guard:cf.149 // True if this file was compiled with /guard:cf.
144 bool hasGuardCF() { return Feat00Flags & 0x800; }150 bool hasGuardCF() { return feat00Flags & 0x800; }
145151
146 // Pointer to the PDB module descriptor builder. Various debug info records152 // Pointer to the PDB module descriptor builder. Various debug info records
147 // will reference object files by "module index", which is here. Things like153 // will reference object files by "module index", which is here. Things like
148 // source files and section contributions are also recorded here. Will be null154 // source files and section contributions are also recorded here. Will be null
149 // if we are not producing a PDB.155 // if we are not producing a PDB.
150 llvm::pdb::DbiModuleDescriptorBuilder *ModuleDBI = nullptr;156 llvm::pdb::DbiModuleDescriptorBuilder *moduleDBI = nullptr;
151157
152 const coff_section *AddrsigSec = nullptr;158 const coff_section *addrsigSec = nullptr;
153159
154 // When using Microsoft precompiled headers, this is the PCH's key.160 // 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 the161 // The same key is used by both the precompiled object, and objects using the
156 // precompiled object. Any difference indicates out-of-date objects.162 // precompiled object. Any difference indicates out-of-date objects.
157 llvm::Optional<uint32_t> PCHSignature;163 llvm::Optional<uint32_t> pchSignature;
164
165 // Whether this is an object file created from .res files.
166 bool isResourceObjFile = false;
167
168 // Whether this file was compiled with /hotpatch.
169 bool hotPatchable = false;
170
171 // Whether the object was already merged into the final PDB.
172 bool mergedIntoPDB = false;
173
174 // If the OBJ has a .debug$T stream, this tells how it will be handled.
175 TpiSource *debugTypesObj = nullptr;
176
177 // The .debug$T stream if there's one.
178 llvm::Optional<llvm::codeview::CVTypeArray> debugTypes;
158179
159private:180private:
181 const coff_section* getSection(uint32_t i);
182 const coff_section *getSection(COFFSymbolRef sym) {
183 return getSection(sym.getSectionNumber());
184 }
185
160 void initializeChunks();186 void initializeChunks();
161 void initializeSymbols();187 void initializeSymbols();
188 void initializeFlags();
189 void initializeDependencies();
162190
163 SectionChunk *191 SectionChunk *
164 readSection(uint32_t SectionNumber,192 readSection(uint32_t sectionNumber,
165 const llvm::object::coff_aux_section_definition *Def,193 const llvm::object::coff_aux_section_definition *def,
166 StringRef LeaderName);194 StringRef leaderName);
167195
168 void readAssociativeDefinition(196 void readAssociativeDefinition(
169 COFFSymbolRef COFFSym,197 COFFSymbolRef coffSym,
170 const llvm::object::coff_aux_section_definition *Def);198 const llvm::object::coff_aux_section_definition *def);
171199
172 void readAssociativeDefinition(200 void readAssociativeDefinition(
173 COFFSymbolRef COFFSym,201 COFFSymbolRef coffSym,
174 const llvm::object::coff_aux_section_definition *Def,202 const llvm::object::coff_aux_section_definition *def,
175 uint32_t ParentSection);203 uint32_t parentSection);
176204
177 void recordPrevailingSymbolForMingw(205 void recordPrevailingSymbolForMingw(
178 COFFSymbolRef COFFSym,206 COFFSymbolRef coffSym,
179 llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap);207 llvm::DenseMap<StringRef, uint32_t> &prevailingSectionMap);
180208
181 void maybeAssociateSEHForMingw(209 void maybeAssociateSEHForMingw(
182 COFFSymbolRef Sym, const llvm::object::coff_aux_section_definition *Def,210 COFFSymbolRef sym, const llvm::object::coff_aux_section_definition *def,
183 const llvm::DenseMap<StringRef, uint32_t> &PrevailingSectionMap);211 const llvm::DenseMap<StringRef, uint32_t> &prevailingSectionMap);
212
213 // Given a new symbol Sym with comdat selection Selection, if the new
214 // symbol is not (yet) Prevailing and the existing comdat leader set to
215 // Leader, emits a diagnostic if the new symbol and its selection doesn't
216 // match the existing symbol and its selection. If either old or new
217 // symbol have selection IMAGE_COMDAT_SELECT_LARGEST, Sym might replace
218 // the existing leader. In that case, Prevailing is set to true.
219 void handleComdatSelection(COFFSymbolRef sym,
220 llvm::COFF::COMDATType &selection,
221 bool &prevailing, DefinedRegular *leader);
184222
185 llvm::Optional<Symbol *>223 llvm::Optional<Symbol *>
186 createDefined(COFFSymbolRef Sym,224 createDefined(COFFSymbolRef sym,
187 std::vector<const llvm::object::coff_aux_section_definition *>225 std::vector<const llvm::object::coff_aux_section_definition *>
188 &ComdatDefs,226 &comdatDefs,
189 bool &PrevailingComdat);227 bool &prevailingComdat);
190 Symbol *createRegular(COFFSymbolRef Sym);228 Symbol *createRegular(COFFSymbolRef sym);
191 Symbol *createUndefined(COFFSymbolRef Sym);229 Symbol *createUndefined(COFFSymbolRef sym);
192230
193 std::unique_ptr<COFFObjectFile> COFFObj;231 std::unique_ptr<COFFObjectFile> coffObj;
194232
195 // List of all chunks defined by this file. This includes both section233 // List of all chunks defined by this file. This includes both section
196 // chunks and non-section chunks for common symbols.234 // chunks and non-section chunks for common symbols.
197 std::vector<Chunk *> Chunks;235 std::vector<Chunk *> chunks;
198236
199 // CodeView debug info sections.237 // CodeView debug info sections.
200 std::vector<SectionChunk *> DebugChunks;238 std::vector<SectionChunk *> debugChunks;
201239
202 // Chunks containing symbol table indices of exception handlers. Only used for240 // Chunks containing symbol table indices of exception handlers. Only used for
203 // 32-bit x86.241 // 32-bit x86.
204 std::vector<SectionChunk *> SXDataChunks;242 std::vector<SectionChunk *> sXDataChunks;
205243
206 // Chunks containing symbol table indices of address taken symbols and longjmp244 // Chunks containing symbol table indices of address taken symbols and longjmp
207 // targets. These are not linked into the final binary when /guard:cf is set.245 // targets. These are not linked into the final binary when /guard:cf is set.
208 std::vector<SectionChunk *> GuardFidChunks;246 std::vector<SectionChunk *> guardFidChunks;
209 std::vector<SectionChunk *> GuardLJmpChunks;247 std::vector<SectionChunk *> guardLJmpChunks;
210248
211 // This vector contains the same chunks as Chunks, but they are249 // This vector contains the same chunks as Chunks, but they are
212 // indexed such that you can get a SectionChunk by section index.250 // indexed such that you can get a SectionChunk by section index.
213 // Nonexistent section indices are filled with null pointers.251 // Nonexistent section indices are filled with null pointers.
214 // (Because section number is 1-based, the first slot is always a252 // (Because section number is 1-based, the first slot is always a
215 // null pointer.)253 // null pointer.)
216 std::vector<SectionChunk *> SparseChunks;254 std::vector<SectionChunk *> sparseChunks;
217255
218 // This vector contains a list of all symbols defined or referenced by this256 // This vector contains a list of all symbols defined or referenced by this
219 // file. They are indexed such that you can get a Symbol by symbol257 // file. They are indexed such that you can get a Symbol by symbol
220 // index. Nonexistent indices (which are occupied by auxiliary258 // index. Nonexistent indices (which are occupied by auxiliary
221 // symbols in the real symbol table) are filled with null pointers.259 // symbols in the real symbol table) are filled with null pointers.
222 std::vector<Symbol *> Symbols;260 std::vector<Symbol *> symbols;
223};261};
224262
225// This type represents import library members that contain DLL names263// This type represents import library members that contain DLL names
...@@ -227,23 +265,23 @@ private:...@@ -227,23 +265,23 @@ private:
227// for details about the format.265// for details about the format.
228class ImportFile : public InputFile {266class ImportFile : public InputFile {
229public:267public:
230 explicit ImportFile(MemoryBufferRef M) : InputFile(ImportKind, M) {}268 explicit ImportFile(MemoryBufferRef m) : InputFile(ImportKind, m) {}
231269
232 static bool classof(const InputFile *F) { return F->kind() == ImportKind; }270 static bool classof(const InputFile *f) { return f->kind() == ImportKind; }
233271
234 static std::vector<ImportFile *> Instances;272 static std::vector<ImportFile *> instances;
235273
236 Symbol *ImpSym = nullptr;274 Symbol *impSym = nullptr;
237 Symbol *ThunkSym = nullptr;275 Symbol *thunkSym = nullptr;
238 std::string DLLName;276 std::string dllName;
239277
240private:278private:
241 void parse() override;279 void parse() override;
242280
243public:281public:
244 StringRef ExternalName;282 StringRef externalName;
245 const coff_import_header *Hdr;283 const coff_import_header *hdr;
246 Chunk *Location = nullptr;284 Chunk *location = nullptr;
247285
248 // We want to eliminate dllimported symbols if no one actually refers them.286 // We want to eliminate dllimported symbols if no one actually refers them.
249 // These "Live" bits are used to keep track of which import library members287 // These "Live" bits are used to keep track of which import library members
...@@ -253,28 +291,31 @@ public:...@@ -253,28 +291,31 @@ public:
253 // symbols provided by this import library member. We also track whether the291 // symbols provided by this import library member. We also track whether the
254 // imported symbol is used separately from whether the thunk is used in order292 // imported symbol is used separately from whether the thunk is used in order
255 // to avoid creating unnecessary thunks.293 // to avoid creating unnecessary thunks.
256 bool Live = !Config->DoGC;294 bool live = !config->doGC;
257 bool ThunkLive = !Config->DoGC;295 bool thunkLive = !config->doGC;
258};296};
259297
260// Used for LTO.298// Used for LTO.
261class BitcodeFile : public InputFile {299class BitcodeFile : public InputFile {
262public:300public:
263 explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}301 BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
264 static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }302 uint64_t offsetInArchive);
265 ArrayRef<Symbol *> getSymbols() { return Symbols; }303 static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
304 ArrayRef<Symbol *> getSymbols() { return symbols; }
266 MachineTypes getMachineType() override;305 MachineTypes getMachineType() override;
267 static std::vector<BitcodeFile *> Instances;306 static std::vector<BitcodeFile *> instances;
268 std::unique_ptr<llvm::lto::InputFile> Obj;307 std::unique_ptr<llvm::lto::InputFile> obj;
269308
270private:309private:
271 void parse() override;310 void parse() override;
272311
273 std::vector<Symbol *> Symbols;312 std::vector<Symbol *> symbols;
274};313};
314
315std::string replaceThinLTOSuffix(StringRef path);
275} // namespace coff316} // namespace coff
276317
277std::string toString(const coff::InputFile *File);318std::string toString(const coff::InputFile *file);
278} // namespace lld319} // namespace lld
279320
280#endif321#endif
deps/lld/COFF/LTO.cpp+121-67
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- LTO.cpp ------------------------------------------------------------===//1//===- LTO.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -11,6 +10,7 @@...@@ -11,6 +10,7 @@
11#include "Config.h"10#include "Config.h"
12#include "InputFiles.h"11#include "InputFiles.h"
13#include "Symbols.h"12#include "Symbols.h"
13#include "lld/Common/Args.h"
14#include "lld/Common/ErrorHandler.h"14#include "lld/Common/ErrorHandler.h"
15#include "lld/Common/Strings.h"15#include "lld/Common/Strings.h"
16#include "lld/Common/TargetOptionsCommandFlags.h"16#include "lld/Common/TargetOptionsCommandFlags.h"
...@@ -18,6 +18,7 @@...@@ -18,6 +18,7 @@
18#include "llvm/ADT/SmallString.h"18#include "llvm/ADT/SmallString.h"
19#include "llvm/ADT/StringRef.h"19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/Twine.h"20#include "llvm/ADT/Twine.h"
21#include "llvm/Bitcode/BitcodeWriter.h"
21#include "llvm/IR/DiagnosticPrinter.h"22#include "llvm/IR/DiagnosticPrinter.h"
22#include "llvm/LTO/Caching.h"23#include "llvm/LTO/Caching.h"
23#include "llvm/LTO/Config.h"24#include "llvm/LTO/Config.h"
...@@ -41,112 +42,165 @@ using namespace llvm::object;...@@ -41,112 +42,165 @@ using namespace llvm::object;
41using namespace lld;42using namespace lld;
42using namespace lld::coff;43using namespace lld::coff;
4344
44static std::unique_ptr<lto::LTO> createLTO() {45// Creates an empty file to and returns a raw_fd_ostream to write to it.
45 lto::Config C;46static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
46 C.Options = InitTargetOptionsFromCodeGenFlags();47 std::error_code ec;
48 auto ret =
49 llvm::make_unique<raw_fd_ostream>(file, ec, sys::fs::OpenFlags::F_None);
50 if (ec) {
51 error("cannot open " + file + ": " + ec.message());
52 return nullptr;
53 }
54 return ret;
55}
56
57static std::string getThinLTOOutputFile(StringRef path) {
58 return lto::getThinLTOOutputFile(path,
59 config->thinLTOPrefixReplace.first,
60 config->thinLTOPrefixReplace.second);
61}
62
63static lto::Config createConfig() {
64 lto::Config c;
65 c.Options = initTargetOptionsFromCodeGenFlags();
4766
48 // Always emit a section per function/datum with LTO. LLVM LTO should get most67 // Always emit a section per function/datum with LTO. LLVM LTO should get most
49 // of the benefit of linker GC, but there are still opportunities for ICF.68 // of the benefit of linker GC, but there are still opportunities for ICF.
50 C.Options.FunctionSections = true;69 c.Options.FunctionSections = true;
51 C.Options.DataSections = true;70 c.Options.DataSections = true;
5271
53 // Use static reloc model on 32-bit x86 because it usually results in more72 // Use static reloc model on 32-bit x86 because it usually results in more
54 // compact code, and because there are also known code generation bugs when73 // compact code, and because there are also known code generation bugs when
55 // using the PIC model (see PR34306).74 // using the PIC model (see PR34306).
56 if (Config->Machine == COFF::IMAGE_FILE_MACHINE_I386)75 if (config->machine == COFF::IMAGE_FILE_MACHINE_I386)
57 C.RelocModel = Reloc::Static;76 c.RelocModel = Reloc::Static;
58 else77 else
59 C.RelocModel = Reloc::PIC_;78 c.RelocModel = Reloc::PIC_;
60 C.DisableVerify = true;79 c.DisableVerify = true;
61 C.DiagHandler = diagnosticHandler;80 c.DiagHandler = diagnosticHandler;
62 C.OptLevel = Config->LTOO;81 c.OptLevel = config->ltoo;
63 C.CPU = GetCPUStr();82 c.CPU = getCPUStr();
64 C.MAttrs = GetMAttrs();83 c.MAttrs = getMAttrs();
6584 c.CGOptLevel = args::getCGOptLevel(config->ltoo);
66 if (Config->SaveTemps)85
67 checkError(C.addSaveTemps(std::string(Config->OutputFile) + ".",86 if (config->saveTemps)
87 checkError(c.addSaveTemps(std::string(config->outputFile) + ".",
68 /*UseInputModulePath*/ true));88 /*UseInputModulePath*/ true));
69 lto::ThinBackend Backend;89 return c;
70 if (Config->ThinLTOJobs != 0)
71 Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs);
72 return llvm::make_unique<lto::LTO>(std::move(C), Backend,
73 Config->LTOPartitions);
74}90}
7591
76BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {}92BitcodeCompiler::BitcodeCompiler() {
93 // Initialize indexFile.
94 if (!config->thinLTOIndexOnlyArg.empty())
95 indexFile = openFile(config->thinLTOIndexOnlyArg);
96
97 // Initialize ltoObj.
98 lto::ThinBackend backend;
99 if (config->thinLTOIndexOnly) {
100 auto OnIndexWrite = [&](StringRef S) { thinIndices.erase(S); };
101 backend = lto::createWriteIndexesThinBackend(
102 config->thinLTOPrefixReplace.first, config->thinLTOPrefixReplace.second,
103 config->thinLTOEmitImportsFiles, indexFile.get(), OnIndexWrite);
104 } else if (config->thinLTOJobs != 0) {
105 backend = lto::createInProcessThinBackend(config->thinLTOJobs);
106 }
107
108 ltoObj = llvm::make_unique<lto::LTO>(createConfig(), backend,
109 config->ltoPartitions);
110}
77111
78BitcodeCompiler::~BitcodeCompiler() = default;112BitcodeCompiler::~BitcodeCompiler() = default;
79113
80static void undefine(Symbol *S) { replaceSymbol<Undefined>(S, S->getName()); }114static void undefine(Symbol *s) { replaceSymbol<Undefined>(s, s->getName()); }
115
116void BitcodeCompiler::add(BitcodeFile &f) {
117 lto::InputFile &obj = *f.obj;
118 unsigned symNum = 0;
119 std::vector<Symbol *> symBodies = f.getSymbols();
120 std::vector<lto::SymbolResolution> resols(symBodies.size());
81121
82void BitcodeCompiler::add(BitcodeFile &F) {122 if (config->thinLTOIndexOnly)
83 lto::InputFile &Obj = *F.Obj;123 thinIndices.insert(obj.getName());
84 unsigned SymNum = 0;
85 std::vector<Symbol *> SymBodies = F.getSymbols();
86 std::vector<lto::SymbolResolution> Resols(SymBodies.size());
87124
88 // Provide a resolution to the LTO API for each symbol.125 // Provide a resolution to the LTO API for each symbol.
89 for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) {126 for (const lto::InputFile::Symbol &objSym : obj.symbols()) {
90 Symbol *Sym = SymBodies[SymNum];127 Symbol *sym = symBodies[symNum];
91 lto::SymbolResolution &R = Resols[SymNum];128 lto::SymbolResolution &r = resols[symNum];
92 ++SymNum;129 ++symNum;
93130
94 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile131 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
95 // reports two symbols for module ASM defined. Without this check, lld132 // reports two symbols for module ASM defined. Without this check, lld
96 // flags an undefined in IR with a definition in ASM as prevailing.133 // flags an undefined in IR with a definition in ASM as prevailing.
97 // Once IRObjectFile is fixed to report only one symbol this hack can134 // Once IRObjectFile is fixed to report only one symbol this hack can
98 // be removed.135 // be removed.
99 R.Prevailing = !ObjSym.isUndefined() && Sym->getFile() == &F;136 r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f;
100 R.VisibleToRegularObj = Sym->IsUsedInRegularObj;137 r.VisibleToRegularObj = sym->isUsedInRegularObj;
101 if (R.Prevailing)138 if (r.Prevailing)
102 undefine(Sym);139 undefine(sym);
103 }140 }
104 checkError(LTOObj->add(std::move(F.Obj), Resols));141 checkError(ltoObj->add(std::move(f.obj), resols));
105}142}
106143
107// Merge all the bitcode files we have seen, codegen the result144// Merge all the bitcode files we have seen, codegen the result
108// and return the resulting objects.145// and return the resulting objects.
109std::vector<StringRef> BitcodeCompiler::compile() {146std::vector<StringRef> BitcodeCompiler::compile() {
110 unsigned MaxTasks = LTOObj->getMaxTasks();147 unsigned maxTasks = ltoObj->getMaxTasks();
111 Buf.resize(MaxTasks);148 buf.resize(maxTasks);
112 Files.resize(MaxTasks);149 files.resize(maxTasks);
113150
114 // The /lldltocache option specifies the path to a directory in which to cache151 // The /lldltocache option specifies the path to a directory in which to cache
115 // native object files for ThinLTO incremental builds. If a path was152 // native object files for ThinLTO incremental builds. If a path was
116 // specified, configure LTO to use it as the cache directory.153 // specified, configure LTO to use it as the cache directory.
117 lto::NativeObjectCache Cache;154 lto::NativeObjectCache cache;
118 if (!Config->LTOCache.empty())155 if (!config->ltoCache.empty())
119 Cache = check(lto::localCache(156 cache = check(lto::localCache(
120 Config->LTOCache, [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {157 config->ltoCache, [&](size_t task, std::unique_ptr<MemoryBuffer> mb) {
121 Files[Task] = std::move(MB);158 files[task] = std::move(mb);
122 }));159 }));
123160
124 checkError(LTOObj->run(161 checkError(ltoObj->run(
125 [&](size_t Task) {162 [&](size_t task) {
126 return llvm::make_unique<lto::NativeObjectStream>(163 return llvm::make_unique<lto::NativeObjectStream>(
127 llvm::make_unique<raw_svector_ostream>(Buf[Task]));164 llvm::make_unique<raw_svector_ostream>(buf[task]));
128 },165 },
129 Cache));166 cache));
167
168 // Emit empty index files for non-indexed files
169 for (StringRef s : thinIndices) {
170 std::string path = getThinLTOOutputFile(s);
171 openFile(path + ".thinlto.bc");
172 if (config->thinLTOEmitImportsFiles)
173 openFile(path + ".imports");
174 }
175
176 // ThinLTO with index only option is required to generate only the index
177 // files. After that, we exit from linker and ThinLTO backend runs in a
178 // distributed environment.
179 if (config->thinLTOIndexOnly) {
180 if (indexFile)
181 indexFile->close();
182 return {};
183 }
130184
131 if (!Config->LTOCache.empty())185 if (!config->ltoCache.empty())
132 pruneCache(Config->LTOCache, Config->LTOCachePolicy);186 pruneCache(config->ltoCache, config->ltoCachePolicy);
133187
134 std::vector<StringRef> Ret;188 std::vector<StringRef> ret;
135 for (unsigned I = 0; I != MaxTasks; ++I) {189 for (unsigned i = 0; i != maxTasks; ++i) {
136 if (Buf[I].empty())190 if (buf[i].empty())
137 continue;191 continue;
138 if (Config->SaveTemps) {192 if (config->saveTemps) {
139 if (I == 0)193 if (i == 0)
140 saveBuffer(Buf[I], Config->OutputFile + ".lto.obj");194 saveBuffer(buf[i], config->outputFile + ".lto.obj");
141 else195 else
142 saveBuffer(Buf[I], Config->OutputFile + Twine(I) + ".lto.obj");196 saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.obj");
143 }197 }
144 Ret.emplace_back(Buf[I].data(), Buf[I].size());198 ret.emplace_back(buf[i].data(), buf[i].size());
145 }199 }
146200
147 for (std::unique_ptr<MemoryBuffer> &File : Files)201 for (std::unique_ptr<MemoryBuffer> &file : files)
148 if (File)202 if (file)
149 Ret.push_back(File->getBuffer());203 ret.push_back(file->getBuffer());
150204
151 return Ret;205 return ret;
152}206}
deps/lld/COFF/LTO.h+11-8
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- LTO.h ----------------------------------------------------*- C++ -*-===//1//===- LTO.h ----------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -22,7 +21,9 @@...@@ -22,7 +21,9 @@
22#define LLD_COFF_LTO_H21#define LLD_COFF_LTO_H
2322
24#include "lld/Common/LLVM.h"23#include "lld/Common/LLVM.h"
24#include "llvm/ADT/DenseSet.h"
25#include "llvm/ADT/SmallString.h"25#include "llvm/ADT/SmallString.h"
26#include "llvm/Support/raw_ostream.h"
26#include <memory>27#include <memory>
27#include <vector>28#include <vector>
2829
...@@ -43,13 +44,15 @@ public:...@@ -43,13 +44,15 @@ public:
43 BitcodeCompiler();44 BitcodeCompiler();
44 ~BitcodeCompiler();45 ~BitcodeCompiler();
4546
46 void add(BitcodeFile &F);47 void add(BitcodeFile &f);
47 std::vector<StringRef> compile();48 std::vector<StringRef> compile();
4849
49private:50private:
50 std::unique_ptr<llvm::lto::LTO> LTOObj;51 std::unique_ptr<llvm::lto::LTO> ltoObj;
51 std::vector<SmallString<0>> Buf;52 std::vector<SmallString<0>> buf;
52 std::vector<std::unique_ptr<MemoryBuffer>> Files;53 std::vector<std::unique_ptr<MemoryBuffer>> files;
54 std::unique_ptr<llvm::raw_fd_ostream> indexFile;
55 llvm::DenseSet<StringRef> thinIndices;
53};56};
54}57}
55}58}
deps/lld/COFF/MapFile.cpp+57-58
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MapFile.cpp --------------------------------------------------------===//1//===- MapFile.cpp --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -24,7 +23,7 @@...@@ -24,7 +23,7 @@
24#include "Symbols.h"23#include "Symbols.h"
25#include "Writer.h"24#include "Writer.h"
26#include "lld/Common/ErrorHandler.h"25#include "lld/Common/ErrorHandler.h"
27#include "llvm/Support/Parallel.h"26#include "lld/Common/Threads.h"
28#include "llvm/Support/raw_ostream.h"27#include "llvm/Support/raw_ostream.h"
2928
30using namespace llvm;29using namespace llvm;
...@@ -33,93 +32,93 @@ using namespace llvm::object;...@@ -33,93 +32,93 @@ using namespace llvm::object;
33using namespace lld;32using namespace lld;
34using namespace lld::coff;33using namespace lld::coff;
3534
36typedef DenseMap<const SectionChunk *, SmallVector<DefinedRegular *, 4>>35using SymbolMapTy =
37 SymbolMapTy;36 DenseMap<const SectionChunk *, SmallVector<DefinedRegular *, 4>>;
3837
39static const std::string Indent8 = " "; // 8 spaces38static const std::string indent8 = " "; // 8 spaces
40static const std::string Indent16 = " "; // 16 spaces39static const std::string indent16 = " "; // 16 spaces
4140
42// Print out the first three columns of a line.41// Print out the first three columns of a line.
43static void writeHeader(raw_ostream &OS, uint64_t Addr, uint64_t Size,42static void writeHeader(raw_ostream &os, uint64_t addr, uint64_t size,
44 uint64_t Align) {43 uint64_t align) {
45 OS << format("%08llx %08llx %5lld ", Addr, Size, Align);44 os << format("%08llx %08llx %5lld ", addr, size, align);
46}45}
4746
48// Returns a list of all symbols that we want to print out.47// Returns a list of all symbols that we want to print out.
49static std::vector<DefinedRegular *> getSymbols() {48static std::vector<DefinedRegular *> getSymbols() {
50 std::vector<DefinedRegular *> V;49 std::vector<DefinedRegular *> v;
51 for (ObjFile *File : ObjFile::Instances)50 for (ObjFile *file : ObjFile::instances)
52 for (Symbol *B : File->getSymbols())51 for (Symbol *b : file->getSymbols())
53 if (auto *Sym = dyn_cast_or_null<DefinedRegular>(B))52 if (auto *sym = dyn_cast_or_null<DefinedRegular>(b))
54 if (Sym && !Sym->getCOFFSymbol().isSectionDefinition())53 if (sym && !sym->getCOFFSymbol().isSectionDefinition())
55 V.push_back(Sym);54 v.push_back(sym);
56 return V;55 return v;
57}56}
5857
59// Returns a map from sections to their symbols.58// Returns a map from sections to their symbols.
60static SymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> Syms) {59static SymbolMapTy getSectionSyms(ArrayRef<DefinedRegular *> syms) {
61 SymbolMapTy Ret;60 SymbolMapTy ret;
62 for (DefinedRegular *S : Syms)61 for (DefinedRegular *s : syms)
63 Ret[S->getChunk()].push_back(S);62 ret[s->getChunk()].push_back(s);
6463
65 // Sort symbols by address.64 // Sort symbols by address.
66 for (auto &It : Ret) {65 for (auto &it : ret) {
67 SmallVectorImpl<DefinedRegular *> &V = It.second;66 SmallVectorImpl<DefinedRegular *> &v = it.second;
68 std::sort(V.begin(), V.end(), [](DefinedRegular *A, DefinedRegular *B) {67 std::sort(v.begin(), v.end(), [](DefinedRegular *a, DefinedRegular *b) {
69 return A->getRVA() < B->getRVA();68 return a->getRVA() < b->getRVA();
70 });69 });
71 }70 }
72 return Ret;71 return ret;
73}72}
7473
75// Construct a map from symbols to their stringified representations.74// Construct a map from symbols to their stringified representations.
76static DenseMap<DefinedRegular *, std::string>75static DenseMap<DefinedRegular *, std::string>
77getSymbolStrings(ArrayRef<DefinedRegular *> Syms) {76getSymbolStrings(ArrayRef<DefinedRegular *> syms) {
78 std::vector<std::string> Str(Syms.size());77 std::vector<std::string> str(syms.size());
79 for_each_n(parallel::par, (size_t)0, Syms.size(), [&](size_t I) {78 parallelForEachN((size_t)0, syms.size(), [&](size_t i) {
80 raw_string_ostream OS(Str[I]);79 raw_string_ostream os(str[i]);
81 writeHeader(OS, Syms[I]->getRVA(), 0, 0);80 writeHeader(os, syms[i]->getRVA(), 0, 0);
82 OS << Indent16 << toString(*Syms[I]);81 os << indent16 << toString(*syms[i]);
83 });82 });
8483
85 DenseMap<DefinedRegular *, std::string> Ret;84 DenseMap<DefinedRegular *, std::string> ret;
86 for (size_t I = 0, E = Syms.size(); I < E; ++I)85 for (size_t i = 0, e = syms.size(); i < e; ++i)
87 Ret[Syms[I]] = std::move(Str[I]);86 ret[syms[i]] = std::move(str[i]);
88 return Ret;87 return ret;
89}88}
9089
91void coff::writeMapFile(ArrayRef<OutputSection *> OutputSections) {90void coff::writeMapFile(ArrayRef<OutputSection *> outputSections) {
92 if (Config->MapFile.empty())91 if (config->mapFile.empty())
93 return;92 return;
9493
95 std::error_code EC;94 std::error_code ec;
96 raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None);95 raw_fd_ostream os(config->mapFile, ec, sys::fs::F_None);
97 if (EC)96 if (ec)
98 fatal("cannot open " + Config->MapFile + ": " + EC.message());97 fatal("cannot open " + config->mapFile + ": " + ec.message());
9998
100 // Collect symbol info that we want to print out.99 // Collect symbol info that we want to print out.
101 std::vector<DefinedRegular *> Syms = getSymbols();100 std::vector<DefinedRegular *> syms = getSymbols();
102 SymbolMapTy SectionSyms = getSectionSyms(Syms);101 SymbolMapTy sectionSyms = getSectionSyms(syms);
103 DenseMap<DefinedRegular *, std::string> SymStr = getSymbolStrings(Syms);102 DenseMap<DefinedRegular *, std::string> symStr = getSymbolStrings(syms);
104103
105 // Print out the header line.104 // Print out the header line.
106 OS << "Address Size Align Out In Symbol\n";105 os << "Address Size Align Out In Symbol\n";
107106
108 // Print out file contents.107 // Print out file contents.
109 for (OutputSection *Sec : OutputSections) {108 for (OutputSection *sec : outputSections) {
110 writeHeader(OS, Sec->getRVA(), Sec->getVirtualSize(), /*Align=*/PageSize);109 writeHeader(os, sec->getRVA(), sec->getVirtualSize(), /*align=*/pageSize);
111 OS << Sec->Name << '\n';110 os << sec->name << '\n';
112111
113 for (Chunk *C : Sec->Chunks) {112 for (Chunk *c : sec->chunks) {
114 auto *SC = dyn_cast<SectionChunk>(C);113 auto *sc = dyn_cast<SectionChunk>(c);
115 if (!SC)114 if (!sc)
116 continue;115 continue;
117116
118 writeHeader(OS, SC->getRVA(), SC->getSize(), SC->Alignment);117 writeHeader(os, sc->getRVA(), sc->getSize(), sc->getAlignment());
119 OS << Indent8 << SC->File->getName() << ":(" << SC->getSectionName()118 os << indent8 << sc->file->getName() << ":(" << sc->getSectionName()
120 << ")\n";119 << ")\n";
121 for (DefinedRegular *Sym : SectionSyms[SC])120 for (DefinedRegular *sym : sectionSyms[sc])
122 OS << SymStr[Sym] << '\n';121 os << symStr[sym] << '\n';
123 }122 }
124 }123 }
125}124}
deps/lld/COFF/MapFile.h+4-5
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MapFile.h ------------------------------------------------*- C++ -*-===//1//===- MapFile.h ------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -15,7 +14,7 @@...@@ -15,7 +14,7 @@
15namespace lld {14namespace lld {
16namespace coff {15namespace coff {
17class OutputSection;16class OutputSection;
18void writeMapFile(llvm::ArrayRef<OutputSection *> OutputSections);17void writeMapFile(llvm::ArrayRef<OutputSection *> outputSections);
19}18}
20}19}
2120
deps/lld/COFF/MarkLive.cpp+32-33
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MarkLive.cpp -------------------------------------------------------===//1//===- MarkLive.cpp -------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -16,57 +15,57 @@...@@ -16,57 +15,57 @@
16namespace lld {15namespace lld {
17namespace coff {16namespace coff {
1817
19static Timer GCTimer("GC", Timer::root());18static Timer gctimer("GC", Timer::root());
2019
21// Set live bit on for each reachable chunk. Unmarked (unreachable)20// Set live bit on for each reachable chunk. Unmarked (unreachable)
22// COMDAT chunks will be ignored by Writer, so they will be excluded21// COMDAT chunks will be ignored by Writer, so they will be excluded
23// from the final output.22// from the final output.
24void markLive(ArrayRef<Chunk *> Chunks) {23void markLive(ArrayRef<Chunk *> chunks) {
25 ScopedTimer T(GCTimer);24 ScopedTimer t(gctimer);
2625
27 // We build up a worklist of sections which have been marked as live. We only26 // We build up a worklist of sections which have been marked as live. We only
28 // push into the worklist when we discover an unmarked section, and we mark27 // push into the worklist when we discover an unmarked section, and we mark
29 // as we push, so sections never appear twice in the list.28 // as we push, so sections never appear twice in the list.
30 SmallVector<SectionChunk *, 256> Worklist;29 SmallVector<SectionChunk *, 256> worklist;
3130
32 // COMDAT section chunks are dead by default. Add non-COMDAT chunks.31 // COMDAT section chunks are dead by default. Add non-COMDAT chunks.
33 for (Chunk *C : Chunks)32 for (Chunk *c : chunks)
34 if (auto *SC = dyn_cast<SectionChunk>(C))33 if (auto *sc = dyn_cast<SectionChunk>(c))
35 if (SC->Live)34 if (sc->live)
36 Worklist.push_back(SC);35 worklist.push_back(sc);
3736
38 auto Enqueue = [&](SectionChunk *C) {37 auto enqueue = [&](SectionChunk *c) {
39 if (C->Live)38 if (c->live)
40 return;39 return;
41 C->Live = true;40 c->live = true;
42 Worklist.push_back(C);41 worklist.push_back(c);
43 };42 };
4443
45 auto AddSym = [&](Symbol *B) {44 auto addSym = [&](Symbol *b) {
46 if (auto *Sym = dyn_cast<DefinedRegular>(B))45 if (auto *sym = dyn_cast<DefinedRegular>(b))
47 Enqueue(Sym->getChunk());46 enqueue(sym->getChunk());
48 else if (auto *Sym = dyn_cast<DefinedImportData>(B))47 else if (auto *sym = dyn_cast<DefinedImportData>(b))
49 Sym->File->Live = true;48 sym->file->live = true;
50 else if (auto *Sym = dyn_cast<DefinedImportThunk>(B))49 else if (auto *sym = dyn_cast<DefinedImportThunk>(b))
51 Sym->WrappedSym->File->Live = Sym->WrappedSym->File->ThunkLive = true;50 sym->wrappedSym->file->live = sym->wrappedSym->file->thunkLive = true;
52 };51 };
5352
54 // Add GC root chunks.53 // Add GC root chunks.
55 for (Symbol *B : Config->GCRoot)54 for (Symbol *b : config->gcroot)
56 AddSym(B);55 addSym(b);
5756
58 while (!Worklist.empty()) {57 while (!worklist.empty()) {
59 SectionChunk *SC = Worklist.pop_back_val();58 SectionChunk *sc = worklist.pop_back_val();
60 assert(SC->Live && "We mark as live when pushing onto the worklist!");59 assert(sc->live && "We mark as live when pushing onto the worklist!");
6160
62 // Mark all symbols listed in the relocation table for this section.61 // Mark all symbols listed in the relocation table for this section.
63 for (Symbol *B : SC->symbols())62 for (Symbol *b : sc->symbols())
64 if (B)63 if (b)
65 AddSym(B);64 addSym(b);
6665
67 // Mark associative sections if any.66 // Mark associative sections if any.
68 for (SectionChunk *C : SC->children())67 for (SectionChunk &c : sc->children())
69 Enqueue(C);68 enqueue(&c);
70 }69 }
71}70}
7271
deps/lld/COFF/MarkLive.h+6-5
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MarkLive.h -----------------------------------------------*- C++ -*-===//1//===- MarkLive.h -----------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -16,7 +15,9 @@...@@ -16,7 +15,9 @@
16namespace lld {15namespace lld {
17namespace coff {16namespace coff {
1817
19void markLive(ArrayRef<Chunk *> Chunks);18class Chunk;
19
20void markLive(ArrayRef<Chunk *> chunks);
2021
21} // namespace coff22} // namespace coff
22} // namespace lld23} // namespace lld
deps/lld/COFF/MinGW.cpp+75-85
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MinGW.cpp ----------------------------------------------------------===//1//===- MinGW.cpp ----------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -19,8 +18,35 @@ using namespace lld::coff;...@@ -19,8 +18,35 @@ using namespace lld::coff;
19using namespace llvm;18using namespace llvm;
20using namespace llvm::COFF;19using namespace llvm::COFF;
2120
22void AutoExporter::initSymbolExcludes() {21AutoExporter::AutoExporter() {
23 ExcludeSymbolPrefixes = {22 excludeLibs = {
23 "libgcc",
24 "libgcc_s",
25 "libstdc++",
26 "libmingw32",
27 "libmingwex",
28 "libg2c",
29 "libsupc++",
30 "libobjc",
31 "libgcj",
32 "libclang_rt.builtins",
33 "libclang_rt.builtins-aarch64",
34 "libclang_rt.builtins-arm",
35 "libclang_rt.builtins-i386",
36 "libclang_rt.builtins-x86_64",
37 "libc++",
38 "libc++abi",
39 "libunwind",
40 "libmsvcrt",
41 "libucrtbase",
42 };
43
44 excludeObjects = {
45 "crt0.o", "crt1.o", "crt1u.o", "crt2.o", "crt2u.o", "dllcrt1.o",
46 "dllcrt2.o", "gcrt0.o", "gcrt1.o", "gcrt2.o", "crtbegin.o", "crtend.o",
47 };
48
49 excludeSymbolPrefixes = {
24 // Import symbols50 // Import symbols
25 "__imp_",51 "__imp_",
26 "__IMPORT_DESCRIPTOR_",52 "__IMPORT_DESCRIPTOR_",
...@@ -32,12 +58,14 @@ void AutoExporter::initSymbolExcludes() {...@@ -32,12 +58,14 @@ void AutoExporter::initSymbolExcludes() {
32 // Artifical symbols such as .refptr58 // Artifical symbols such as .refptr
33 ".",59 ".",
34 };60 };
35 ExcludeSymbolSuffixes = {61
62 excludeSymbolSuffixes = {
36 "_iname",63 "_iname",
37 "_NULL_THUNK_DATA",64 "_NULL_THUNK_DATA",
38 };65 };
39 if (Config->Machine == I386) {66
40 ExcludeSymbols = {67 if (config->machine == I386) {
68 excludeSymbols = {
41 "__NULL_IMPORT_DESCRIPTOR",69 "__NULL_IMPORT_DESCRIPTOR",
42 "__pei386_runtime_relocator",70 "__pei386_runtime_relocator",
43 "_do_pseudo_reloc",71 "_do_pseudo_reloc",
...@@ -52,9 +80,9 @@ void AutoExporter::initSymbolExcludes() {...@@ -52,9 +80,9 @@ void AutoExporter::initSymbolExcludes() {
52 "_DllEntryPoint@12",80 "_DllEntryPoint@12",
53 "_DllMainCRTStartup@12",81 "_DllMainCRTStartup@12",
54 };82 };
55 ExcludeSymbolPrefixes.insert("__head_");83 excludeSymbolPrefixes.insert("__head_");
56 } else {84 } else {
57 ExcludeSymbols = {85 excludeSymbols = {
58 "__NULL_IMPORT_DESCRIPTOR",86 "__NULL_IMPORT_DESCRIPTOR",
59 "_pei386_runtime_relocator",87 "_pei386_runtime_relocator",
60 "do_pseudo_reloc",88 "do_pseudo_reloc",
...@@ -69,108 +97,70 @@ void AutoExporter::initSymbolExcludes() {...@@ -69,108 +97,70 @@ void AutoExporter::initSymbolExcludes() {
69 "DllEntryPoint",97 "DllEntryPoint",
70 "DllMainCRTStartup",98 "DllMainCRTStartup",
71 };99 };
72 ExcludeSymbolPrefixes.insert("_head_");100 excludeSymbolPrefixes.insert("_head_");
73 }101 }
74}102}
75103
76AutoExporter::AutoExporter() {104void AutoExporter::addWholeArchive(StringRef path) {
77 ExcludeLibs = {105 StringRef libName = sys::path::filename(path);
78 "libgcc",
79 "libgcc_s",
80 "libstdc++",
81 "libmingw32",
82 "libmingwex",
83 "libg2c",
84 "libsupc++",
85 "libobjc",
86 "libgcj",
87 "libclang_rt.builtins",
88 "libclang_rt.builtins-aarch64",
89 "libclang_rt.builtins-arm",
90 "libclang_rt.builtins-i386",
91 "libclang_rt.builtins-x86_64",
92 "libc++",
93 "libc++abi",
94 "libunwind",
95 "libmsvcrt",
96 "libucrtbase",
97 };
98 ExcludeObjects = {
99 "crt0.o",
100 "crt1.o",
101 "crt1u.o",
102 "crt2.o",
103 "crt2u.o",
104 "dllcrt1.o",
105 "dllcrt2.o",
106 "gcrt0.o",
107 "gcrt1.o",
108 "gcrt2.o",
109 "crtbegin.o",
110 "crtend.o",
111 };
112}
113
114void AutoExporter::addWholeArchive(StringRef Path) {
115 StringRef LibName = sys::path::filename(Path);
116 // Drop the file extension, to match the processing below.106 // Drop the file extension, to match the processing below.
117 LibName = LibName.substr(0, LibName.rfind('.'));107 libName = libName.substr(0, libName.rfind('.'));
118 ExcludeLibs.erase(LibName);108 excludeLibs.erase(libName);
119}109}
120110
121bool AutoExporter::shouldExport(Defined *Sym) const {111bool AutoExporter::shouldExport(Defined *sym) const {
122 if (!Sym || !Sym->isLive() || !Sym->getChunk())112 if (!sym || !sym->isLive() || !sym->getChunk())
123 return false;113 return false;
124114
125 // Only allow the symbol kinds that make sense to export; in particular,115 // Only allow the symbol kinds that make sense to export; in particular,
126 // disallow import symbols.116 // disallow import symbols.
127 if (!isa<DefinedRegular>(Sym) && !isa<DefinedCommon>(Sym))117 if (!isa<DefinedRegular>(sym) && !isa<DefinedCommon>(sym))
128 return false;118 return false;
129 if (ExcludeSymbols.count(Sym->getName()))119 if (excludeSymbols.count(sym->getName()))
130 return false;120 return false;
131121
132 for (StringRef Prefix : ExcludeSymbolPrefixes.keys())122 for (StringRef prefix : excludeSymbolPrefixes.keys())
133 if (Sym->getName().startswith(Prefix))123 if (sym->getName().startswith(prefix))
134 return false;124 return false;
135 for (StringRef Suffix : ExcludeSymbolSuffixes.keys())125 for (StringRef suffix : excludeSymbolSuffixes.keys())
136 if (Sym->getName().endswith(Suffix))126 if (sym->getName().endswith(suffix))
137 return false;127 return false;
138128
139 // If a corresponding __imp_ symbol exists and is defined, don't export it.129 // If a corresponding __imp_ symbol exists and is defined, don't export it.
140 if (Symtab->find(("__imp_" + Sym->getName()).str()))130 if (symtab->find(("__imp_" + sym->getName()).str()))
141 return false;131 return false;
142132
143 // Check that file is non-null before dereferencing it, symbols not133 // Check that file is non-null before dereferencing it, symbols not
144 // originating in regular object files probably shouldn't be exported.134 // originating in regular object files probably shouldn't be exported.
145 if (!Sym->getFile())135 if (!sym->getFile())
146 return false;136 return false;
147137
148 StringRef LibName = sys::path::filename(Sym->getFile()->ParentName);138 StringRef libName = sys::path::filename(sym->getFile()->parentName);
149139
150 // Drop the file extension.140 // Drop the file extension.
151 LibName = LibName.substr(0, LibName.rfind('.'));141 libName = libName.substr(0, libName.rfind('.'));
152 if (!LibName.empty())142 if (!libName.empty())
153 return !ExcludeLibs.count(LibName);143 return !excludeLibs.count(libName);
154144
155 StringRef FileName = sys::path::filename(Sym->getFile()->getName());145 StringRef fileName = sys::path::filename(sym->getFile()->getName());
156 return !ExcludeObjects.count(FileName);146 return !excludeObjects.count(fileName);
157}147}
158148
159void coff::writeDefFile(StringRef Name) {149void coff::writeDefFile(StringRef name) {
160 std::error_code EC;150 std::error_code ec;
161 raw_fd_ostream OS(Name, EC, sys::fs::F_None);151 raw_fd_ostream os(name, ec, sys::fs::F_None);
162 if (EC)152 if (ec)
163 fatal("cannot open " + Name + ": " + EC.message());153 fatal("cannot open " + name + ": " + ec.message());
164154
165 OS << "EXPORTS\n";155 os << "EXPORTS\n";
166 for (Export &E : Config->Exports) {156 for (Export &e : config->exports) {
167 OS << " " << E.ExportName << " "157 os << " " << e.exportName << " "
168 << "@" << E.Ordinal;158 << "@" << e.ordinal;
169 if (auto *Def = dyn_cast_or_null<Defined>(E.Sym)) {159 if (auto *def = dyn_cast_or_null<Defined>(e.sym)) {
170 if (Def && Def->getChunk() &&160 if (def && def->getChunk() &&
171 !(Def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))161 !(def->getChunk()->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE))
172 OS << " DATA";162 os << " DATA";
173 }163 }
174 OS << "\n";164 os << "\n";
175 }165 }
176}166}
deps/lld/COFF/MinGW.h+11-14
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MinGW.h --------------------------------------------------*- C++ -*-===//1//===- MinGW.h --------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -23,20 +22,18 @@ class AutoExporter {...@@ -23,20 +22,18 @@ class AutoExporter {
23public:22public:
24 AutoExporter();23 AutoExporter();
2524
26 void initSymbolExcludes();25 void addWholeArchive(StringRef path);
27
28 void addWholeArchive(StringRef Path);
2926
30 llvm::StringSet<> ExcludeSymbols;27 llvm::StringSet<> excludeSymbols;
31 llvm::StringSet<> ExcludeSymbolPrefixes;28 llvm::StringSet<> excludeSymbolPrefixes;
32 llvm::StringSet<> ExcludeSymbolSuffixes;29 llvm::StringSet<> excludeSymbolSuffixes;
33 llvm::StringSet<> ExcludeLibs;30 llvm::StringSet<> excludeLibs;
34 llvm::StringSet<> ExcludeObjects;31 llvm::StringSet<> excludeObjects;
3532
36 bool shouldExport(Defined *Sym) const;33 bool shouldExport(Defined *sym) const;
37};34};
3835
39void writeDefFile(StringRef Name);36void writeDefFile(StringRef name);
4037
41} // namespace coff38} // namespace coff
42} // namespace lld39} // namespace lld
deps/lld/COFF/Options.td+48-17
...@@ -3,11 +3,11 @@ include "llvm/Option/OptParser.td"...@@ -3,11 +3,11 @@ include "llvm/Option/OptParser.td"
3// link.exe accepts options starting with either a dash or a slash.3// link.exe accepts options starting with either a dash or a slash.
44
5// Flag that takes no arguments.5// Flag that takes no arguments.
6class F<string name> : Flag<["/", "-", "-?"], name>;6class F<string name> : Flag<["/", "-", "/?", "-?"], name>;
77
8// Flag that takes one argument after ":".8// Flag that takes one argument after ":".
9class P<string name, string help> :9class P<string name, string help> :
10 Joined<["/", "-", "-?"], name#":">, HelpText<help>;10 Joined<["/", "-", "/?", "-?"], name#":">, HelpText<help>;
1111
12// Boolean flag which can be suffixed by ":no". Using it unsuffixed turns the12// Boolean flag which can be suffixed by ":no". Using it unsuffixed turns the
13// flag on and using it suffixed by ":no" turns it off.13// flag on and using it suffixed by ":no" turns it off.
...@@ -32,6 +32,9 @@ def errorlimit : P<"errorlimit",...@@ -32,6 +32,9 @@ def errorlimit : P<"errorlimit",
32def export : P<"export", "Export a function">;32def export : P<"export", "Export a function">;
33// No help text because /failifmismatch is not intended to be used by the user.33// No help text because /failifmismatch is not intended to be used by the user.
34def failifmismatch : P<"failifmismatch", "">;34def failifmismatch : P<"failifmismatch", "">;
35def filealign : P<"filealign", "Section alignment in the output file">;
36def functionpadmin : F<"functionpadmin">;
37def functionpadmin_opt : P<"functionpadmin", "Prepares an image for hotpatching">;
35def guard : P<"guard", "Control flow guard">;38def guard : P<"guard", "Control flow guard">;
36def heap : P<"heap", "Size of the heap">;39def heap : P<"heap", "Size of the heap">;
37def ignore : P<"ignore", "Specify warning codes to ignore">;40def ignore : P<"ignore", "Specify warning codes to ignore">;
...@@ -64,7 +67,8 @@ def timestamp : P<"timestamp", "Specify the PE header timestamp">;...@@ -64,7 +67,8 @@ def timestamp : P<"timestamp", "Specify the PE header timestamp">;
64def version : P<"version", "Specify a version number in the PE header">;67def version : P<"version", "Specify a version number in the PE header">;
65def wholearchive_file : P<"wholearchive", "Include all object files from this archive">;68def wholearchive_file : P<"wholearchive", "Include all object files from this archive">;
6669
67def disallowlib : Joined<["/", "-", "-?"], "disallowlib:">, Alias<nodefaultlib>;70def disallowlib : Joined<["/", "-", "/?", "-?"], "disallowlib:">,
71 Alias<nodefaultlib>;
6872
69def manifest : F<"manifest">, HelpText<"Create .manifest file">;73def manifest : F<"manifest">, HelpText<"Create .manifest file">;
70def manifest_colon : P<74def manifest_colon : P<
...@@ -82,11 +86,11 @@ def manifestinput : P<...@@ -82,11 +86,11 @@ def manifestinput : P<
82// We cannot use multiclass P because class name "incl" is different86// We cannot use multiclass P because class name "incl" is different
83// from its command line option name. We do this because "include" is87// from its command line option name. We do this because "include" is
84// a reserved keyword in tablegen.88// a reserved keyword in tablegen.
85def incl : Joined<["/", "-"], "include:">,89def incl : Joined<["/", "-", "/?", "-?"], "include:">,
86 HelpText<"Force symbol to be added to symbol table as undefined one">;90 HelpText<"Force symbol to be added to symbol table as undefined one">;
8791
88// "def" is also a keyword.92// "def" is also a keyword.
89def deffile : Joined<["/", "-"], "def:">,93def deffile : Joined<["/", "-", "/?", "-?"], "def:">,
90 HelpText<"Use module-definition file">;94 HelpText<"Use module-definition file">;
9195
92def debug : F<"debug">, HelpText<"Embed a symbol table in the image">;96def debug : F<"debug">, HelpText<"Embed a symbol table in the image">;
...@@ -101,8 +105,12 @@ def noentry : F<"noentry">,...@@ -101,8 +105,12 @@ def noentry : F<"noentry">,
101def profile : F<"profile">;105def profile : F<"profile">;
102def repro : F<"Brepro">,106def repro : F<"Brepro">,
103 HelpText<"Use a hash of the executable as the PE header timestamp">;107 HelpText<"Use a hash of the executable as the PE header timestamp">;
104def swaprun_cd : F<"swaprun:cd">;108def swaprun : P<"swaprun",
105def swaprun_net : F<"swaprun:net">;109 "Comma-separated list of 'cd' or 'net'">;
110def swaprun_cd : F<"swaprun:cd">, Alias<swaprun>, AliasArgs<["cd"]>,
111 HelpText<"Make loader run output binary from swap instead of from CD">;
112def swaprun_net : F<"swaprun:net">, Alias<swaprun>, AliasArgs<["net"]>,
113 HelpText<"Make loader run output binary from swap instead of from network">;
106def verbose : F<"verbose">;114def verbose : F<"verbose">;
107def wholearchive_flag : F<"wholearchive">;115def wholearchive_flag : F<"wholearchive">;
108116
...@@ -112,6 +120,8 @@ def force_unresolved : F<"force:unresolved">,...@@ -112,6 +120,8 @@ def force_unresolved : F<"force:unresolved">,
112 HelpText<"Allow undefined symbols when creating executables">;120 HelpText<"Allow undefined symbols when creating executables">;
113def force_multiple : F<"force:multiple">,121def force_multiple : F<"force:multiple">,
114 HelpText<"Allow multiply defined symbols when creating executables">;122 HelpText<"Allow multiply defined symbols when creating executables">;
123def force_multipleres : F<"force:multipleres">,
124 HelpText<"Allow multiply defined resources when creating executables">;
115defm WX : B<"WX", "Treat warnings as errors", "Don't treat warnings as errors">;125defm WX : B<"WX", "Treat warnings as errors", "Don't treat warnings as errors">;
116126
117defm allowbind : B<"allowbind", "Enable DLL binding (default)",127defm allowbind : B<"allowbind", "Enable DLL binding (default)",
...@@ -147,37 +157,58 @@ defm tsaware : B<"tsaware",...@@ -147,37 +157,58 @@ defm tsaware : B<"tsaware",
147 "Create non-Terminal Server aware executable">;157 "Create non-Terminal Server aware executable">;
148158
149def help : F<"help">;159def help : F<"help">;
150def help_q : Flag<["/?", "-?"], "">, Alias<help>;160
161// /?? and -?? must be before /? and -? to not confuse lib/Options.
162def help_q : Flag<["/??", "-??", "/?", "-?"], "">, Alias<help>;
151163
152// LLD extensions164// LLD extensions
165def exclude_all_symbols : F<"exclude-all-symbols">;
153def export_all_symbols : F<"export-all-symbols">;166def export_all_symbols : F<"export-all-symbols">;
167defm demangle : B<"demangle",
168 "Demangle symbols in output (default)",
169 "Do not demangle symbols in output">;
170def include_optional : Joined<["/", "-", "/?", "-?"], "includeoptional:">,
171 HelpText<"Add symbol as undefined, but allow it to remain undefined">;
154def kill_at : F<"kill-at">;172def kill_at : F<"kill-at">;
155def lldmingw : F<"lldmingw">;173def lldmingw : F<"lldmingw">;
156def output_def : Joined<["/", "-"], "output-def:">;174def output_def : Joined<["/", "-", "/?", "-?"], "output-def:">;
157def pdb_source_path : P<"pdbsourcepath",175def pdb_source_path : P<"pdbsourcepath",
158 "Base path used to make relative source file path absolute in PDB">;176 "Base path used to make relative source file path absolute in PDB">;
159def rsp_quoting : Joined<["--"], "rsp-quoting=">,177def rsp_quoting : Joined<["--"], "rsp-quoting=">,
160 HelpText<"Quoting style for response files, 'windows' (default) or 'posix'">;178 HelpText<"Quoting style for response files, 'windows' (default) or 'posix'">;
179def thinlto_emit_imports_files :
180 F<"thinlto-emit-imports-files">,
181 HelpText<"Emit .imports files with -thinlto-index-only">;
182def thinlto_index_only :
183 F<"thinlto-index-only">,
184 HelpText<"Instead of linking, emit ThinLTO index files">;
185def thinlto_index_only_arg : P<
186 "thinlto-index-only",
187 "-thinlto-index-only and also write native module names to file">;
188def thinlto_object_suffix_replace : P<
189 "thinlto-object-suffix-replace",
190 "'old;new' replace old suffix with new suffix in ThinLTO index">;
191def thinlto_prefix_replace: P<
192 "thinlto-prefix-replace",
193 "'old;new' replace old prefix with new prefix in ThinLTO outputs">;
161def dash_dash_version : Flag<["--"], "version">,194def dash_dash_version : Flag<["--"], "version">,
162 HelpText<"Print version information">;195 HelpText<"Print version information">;
196defm threads: B<"threads",
197 "Run the linker multi-threaded (default)",
198 "Do not run the linker multi-threaded">;
163199
164// Flags for debugging200// Flags for debugging
165def lldmap : F<"lldmap">;201def lldmap : F<"lldmap">;
166def lldmap_file : Joined<["/", "-"], "lldmap:">;202def lldmap_file : Joined<["/", "-", "/?", "-?"], "lldmap:">;
167def show_timing : F<"time">;203def show_timing : F<"time">;
204def summary : F<"summary">;
168205
169//==============================================================================206//==============================================================================
170// The flags below do nothing. They are defined only for link.exe compatibility.207// The flags below do nothing. They are defined only for link.exe compatibility.
171//==============================================================================208//==============================================================================
172209
173class QF<string name> : Joined<["/", "-", "-?"], name#":">;210class QF<string name> : Joined<["/", "-", "/?", "-?"], name#":">;
174211
175multiclass QB<string name> {
176 def "" : F<name>;
177 def _no : F<name#":no">;
178}
179
180def functionpadmin : F<"functionpadmin">;
181def ignoreidl : F<"ignoreidl">;212def ignoreidl : F<"ignoreidl">;
182def nologo : F<"nologo">;213def nologo : F<"nologo">;
183def throwingnew : F<"throwingnew">;214def throwingnew : F<"throwingnew">;
deps/lld/COFF/PDB.cpp+1046-981
...@@ -1,21 +1,23 @@...@@ -1,21 +1,23 @@
1//===- PDB.cpp ------------------------------------------------------------===//1//===- PDB.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
10#include "PDB.h"9#include "PDB.h"
11#include "Chunks.h"10#include "Chunks.h"
12#include "Config.h"11#include "Config.h"
12#include "DebugTypes.h"
13#include "Driver.h"13#include "Driver.h"
14#include "SymbolTable.h"14#include "SymbolTable.h"
15#include "Symbols.h"15#include "Symbols.h"
16#include "TypeMerger.h"
16#include "Writer.h"17#include "Writer.h"
17#include "lld/Common/ErrorHandler.h"18#include "lld/Common/ErrorHandler.h"
18#include "lld/Common/Timer.h"19#include "lld/Common/Timer.h"
20#include "lld/Common/Threads.h"
19#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"21#include "llvm/DebugInfo/CodeView/DebugFrameDataSubsection.h"
20#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"22#include "llvm/DebugInfo/CodeView/DebugSubsectionRecord.h"
21#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"23#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
...@@ -53,7 +55,6 @@...@@ -53,7 +55,6 @@
53#include "llvm/Support/Errc.h"55#include "llvm/Support/Errc.h"
54#include "llvm/Support/FormatVariadic.h"56#include "llvm/Support/FormatVariadic.h"
55#include "llvm/Support/JamCRC.h"57#include "llvm/Support/JamCRC.h"
56#include "llvm/Support/Parallel.h"
57#include "llvm/Support/Path.h"58#include "llvm/Support/Path.h"
58#include "llvm/Support/ScopedPrinter.h"59#include "llvm/Support/ScopedPrinter.h"
59#include <memory>60#include <memory>
...@@ -65,44 +66,34 @@ using namespace llvm::codeview;...@@ -65,44 +66,34 @@ using namespace llvm::codeview;
6566
66using llvm::object::coff_section;67using llvm::object::coff_section;
6768
68static ExitOnError ExitOnErr;69static ExitOnError exitOnErr;
6970
70static Timer TotalPdbLinkTimer("PDB Emission (Cumulative)", Timer::root());71static Timer totalPdbLinkTimer("PDB Emission (Cumulative)", Timer::root());
7172
72static Timer AddObjectsTimer("Add Objects", TotalPdbLinkTimer);73static Timer addObjectsTimer("Add Objects", totalPdbLinkTimer);
73static Timer TypeMergingTimer("Type Merging", AddObjectsTimer);74static Timer typeMergingTimer("Type Merging", addObjectsTimer);
74static Timer SymbolMergingTimer("Symbol Merging", AddObjectsTimer);75static Timer symbolMergingTimer("Symbol Merging", addObjectsTimer);
75static Timer GlobalsLayoutTimer("Globals Stream Layout", TotalPdbLinkTimer);76static Timer globalsLayoutTimer("Globals Stream Layout", totalPdbLinkTimer);
76static Timer TpiStreamLayoutTimer("TPI Stream Layout", TotalPdbLinkTimer);77static Timer tpiStreamLayoutTimer("TPI Stream Layout", totalPdbLinkTimer);
77static Timer DiskCommitTimer("Commit to Disk", TotalPdbLinkTimer);78static Timer diskCommitTimer("Commit to Disk", totalPdbLinkTimer);
7879
79namespace {80namespace {
80/// Map from type index and item index in a type server PDB to the
81/// corresponding index in the destination PDB.
82struct CVIndexMap {
83 SmallVector<TypeIndex, 0> TPIMap;
84 SmallVector<TypeIndex, 0> IPIMap;
85 bool IsTypeServerMap = false;
86 bool IsPrecompiledTypeMap = false;
87};
88
89class DebugSHandler;81class DebugSHandler;
9082
91class PDBLinker {83class PDBLinker {
92 friend DebugSHandler;84 friend DebugSHandler;
9385
94public:86public:
95 PDBLinker(SymbolTable *Symtab)87 PDBLinker(SymbolTable *symtab)
96 : Alloc(), Symtab(Symtab), Builder(Alloc), TypeTable(Alloc),88 : alloc(), symtab(symtab), builder(alloc), tMerger(alloc) {
97 IDTable(Alloc), GlobalTypeTable(Alloc), GlobalIDTable(Alloc) {
98 // This isn't strictly necessary, but link.exe usually puts an empty string89 // This isn't strictly necessary, but link.exe usually puts an empty string
99 // as the first "valid" string in the string table, so we do the same in90 // as the first "valid" string in the string table, so we do the same in
100 // order to maintain as much byte-for-byte compatibility as possible.91 // order to maintain as much byte-for-byte compatibility as possible.
101 PDBStrTab.insert("");92 pdbStrTab.insert("");
102 }93 }
10394
104 /// Emit the basic PDB structure: initial streams, headers, etc.95 /// Emit the basic PDB structure: initial streams, headers, etc.
105 void initialize(llvm::codeview::DebugInfo *BuildId);96 void initialize(llvm::codeview::DebugInfo *buildId);
10697
107 /// Add natvis files specified on the command line.98 /// Add natvis files specified on the command line.
108 void addNatvisFiles();99 void addNatvisFiles();
...@@ -110,10 +101,13 @@ public:...@@ -110,10 +101,13 @@ public:
110 /// Link CodeView from each object file in the symbol table into the PDB.101 /// Link CodeView from each object file in the symbol table into the PDB.
111 void addObjectsToPDB();102 void addObjectsToPDB();
112103
104 /// Link info for each import file in the symbol table into the PDB.
105 void addImportFilesToPDB(ArrayRef<OutputSection *> outputSections);
106
113 /// Link CodeView from a single object file into the target (output) PDB.107 /// 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 provided108 /// When a precompiled headers object is linked, its TPI map might be provided
115 /// externally.109 /// externally.
116 void addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap = nullptr);110 void addObjFile(ObjFile *file, CVIndexMap *externIndexMap = nullptr);
117111
118 /// Produce a mapping from the type and item indices used in the object112 /// Produce a mapping from the type and item indices used in the object
119 /// file to those in the destination PDB.113 /// file to those in the destination PDB.
...@@ -125,20 +119,17 @@ public:...@@ -125,20 +119,17 @@ public:
125 ///119 ///
126 /// If the object does not use a type server PDB (compiled with /Z7), we merge120 /// If the object does not use a type server PDB (compiled with /Z7), we merge
127 /// all the type and item records from the .debug$S stream and fill in the121 /// all the type and item records from the .debug$S stream and fill in the
128 /// caller-provided ObjectIndexMap.122 /// caller-provided objectIndexMap.
129 Expected<const CVIndexMap &> mergeDebugT(ObjFile *File,123 Expected<const CVIndexMap &> mergeDebugT(ObjFile *file,
130 CVIndexMap *ObjectIndexMap);124 CVIndexMap *objectIndexMap);
131125
132 /// Reads and makes available a PDB.126 /// Reads and makes available a PDB.
133 Expected<const CVIndexMap &> maybeMergeTypeServerPDB(ObjFile *File,127 Expected<const CVIndexMap &> maybeMergeTypeServerPDB(ObjFile *file);
134 const CVType &FirstType);
135128
136 /// Merges a precompiled headers TPI map into the current TPI map. The129 /// Merges a precompiled headers TPI map into the current TPI map. The
137 /// precompiled headers object will also be loaded and remapped in the130 /// precompiled headers object will also be loaded and remapped in the
138 /// process.131 /// process.
139 Expected<const CVIndexMap &>132 Error mergeInPrecompHeaderObj(ObjFile *file, CVIndexMap *objectIndexMap);
140 mergeInPrecompHeaderObj(ObjFile *File, const CVType &FirstType,
141 CVIndexMap *ObjectIndexMap);
142133
143 /// Reads and makes available a precompiled headers object.134 /// Reads and makes available a precompiled headers object.
144 ///135 ///
...@@ -149,109 +140,87 @@ public:...@@ -149,109 +140,87 @@ public:
149 ///140 ///
150 /// If the precompiled headers object was already loaded, this function will141 /// If the precompiled headers object was already loaded, this function will
151 /// simply return its (remapped) TPI map.142 /// simply return its (remapped) TPI map.
152 Expected<const CVIndexMap &> aquirePrecompObj(ObjFile *File,143 Expected<const CVIndexMap &> aquirePrecompObj(ObjFile *file);
153 PrecompRecord Precomp);
154144
155 /// Adds a precompiled headers object signature -> TPI mapping.145 /// Adds a precompiled headers object signature -> TPI mapping.
156 std::pair<CVIndexMap &, bool /*already there*/>146 std::pair<CVIndexMap &, bool /*already there*/>
157 registerPrecompiledHeaders(uint32_t Signature);147 registerPrecompiledHeaders(uint32_t signature);
158148
159 void mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap,149 void mergeSymbolRecords(ObjFile *file, const CVIndexMap &indexMap,
160 std::vector<ulittle32_t *> &StringTableRefs,150 std::vector<ulittle32_t *> &stringTableRefs,
161 BinaryStreamRef SymData);151 BinaryStreamRef symData);
162152
163 /// Add the section map and section contributions to the PDB.153 /// Add the section map and section contributions to the PDB.
164 void addSections(ArrayRef<OutputSection *> OutputSections,154 void addSections(ArrayRef<OutputSection *> outputSections,
165 ArrayRef<uint8_t> SectionTable);155 ArrayRef<uint8_t> sectionTable);
166
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 }
180156
181 /// Write the PDB to disk and store the Guid generated for it in *Guid.157 /// Write the PDB to disk and store the Guid generated for it in *Guid.
182 void commit(codeview::GUID *Guid);158 void commit(codeview::GUID *guid);
183
184private:
185 BumpPtrAllocator Alloc;
186
187 SymbolTable *Symtab;
188159
189 pdb::PDBFileBuilder Builder;160 // Print statistics regarding the final PDB
161 void printStats();
190162
191 /// Type records that will go into the PDB TPI stream.163private:
192 MergingTypeTableBuilder TypeTable;164 BumpPtrAllocator alloc;
193165
194 /// Item records that will go into the PDB IPI stream.166 SymbolTable *symtab;
195 MergingTypeTableBuilder IDTable;
196167
197 /// Type records that will go into the PDB TPI stream (for /DEBUG:GHASH)168 pdb::PDBFileBuilder builder;
198 GlobalTypeTableBuilder GlobalTypeTable;
199169
200 /// Item records that will go into the PDB IPI stream (for /DEBUG:GHASH)170 TypeMerger tMerger;
201 GlobalTypeTableBuilder GlobalIDTable;
202171
203 /// PDBs use a single global string table for filenames in the file checksum172 /// PDBs use a single global string table for filenames in the file checksum
204 /// table.173 /// table.
205 DebugStringTableSubsection PDBStrTab;174 DebugStringTableSubsection pdbStrTab;
206
207 llvm::SmallString<128> NativePath;
208175
209 /// A list of other PDBs which are loaded during the linking process and which176 llvm::SmallString<128> nativePath;
210 /// we need to keep around since the linking operation may reference pointers
211 /// inside of these PDBs.
212 llvm::SmallVector<std::unique_ptr<pdb::NativeSession>, 2> LoadedPDBs;
213177
214 std::vector<pdb::SecMapEntry> SectionMap;178 std::vector<pdb::SecMapEntry> sectionMap;
215179
216 /// Type index mappings of type server PDBs that we've loaded so far.180 /// Type index mappings of type server PDBs that we've loaded so far.
217 std::map<codeview::GUID, CVIndexMap> TypeServerIndexMappings;181 std::map<codeview::GUID, CVIndexMap> typeServerIndexMappings;
218182
219 /// Type index mappings of precompiled objects type map that we've loaded so183 /// Type index mappings of precompiled objects type map that we've loaded so
220 /// far.184 /// far.
221 std::map<uint32_t, CVIndexMap> PrecompTypeIndexMappings;185 std::map<uint32_t, CVIndexMap> precompTypeIndexMappings;
222186
223 /// List of TypeServer PDBs which cannot be loaded.187 // For statistics
224 /// Cached to prevent repeated load attempts.188 uint64_t globalSymbols = 0;
225 std::map<codeview::GUID, std::string> MissingTypeServerPDBs;189 uint64_t moduleSymbols = 0;
190 uint64_t publicSymbols = 0;
226};191};
227192
228class DebugSHandler {193class DebugSHandler {
229 PDBLinker &Linker;194 PDBLinker &linker;
230195
231 /// The object file whose .debug$S sections we're processing.196 /// The object file whose .debug$S sections we're processing.
232 ObjFile &File;197 ObjFile &file;
233198
234 /// The result of merging type indices.199 /// The result of merging type indices.
235 const CVIndexMap &IndexMap;200 const CVIndexMap &indexMap;
236201
237 /// The DEBUG_S_STRINGTABLE subsection. These strings are referred to by202 /// The DEBUG_S_STRINGTABLE subsection. These strings are referred to by
238 /// index from other records in the .debug$S section. All of these strings203 /// 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 to204 /// 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 the205 /// these strings need to have their indices re-written to refer to the
241 /// global PDB string table.206 /// global PDB string table.
242 DebugStringTableSubsectionRef CVStrTab;207 DebugStringTableSubsectionRef cVStrTab;
243208
244 /// The DEBUG_S_FILECHKSMS subsection. As above, these are referred to209 /// 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 the210 /// by other records in the .debug$S section and need to be merged into the
246 /// PDB.211 /// PDB.
247 DebugChecksumsSubsectionRef Checksums;212 DebugChecksumsSubsectionRef checksums;
213
214 /// The DEBUG_S_INLINEELINES subsection. There can be only one of these per
215 /// object file.
216 DebugInlineeLinesSubsectionRef inlineeLines;
248217
249 /// The DEBUG_S_FRAMEDATA subsection(s). There can be more than one of218 /// 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, they219 /// these and they need not appear in any specific order. However, they
251 /// contain string table references which need to be re-written, so we220 /// 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 been221 /// collect them all here and re-write them after all subsections have been
253 /// discovered and processed.222 /// discovered and processed.
254 std::vector<DebugFrameDataSubsectionRef> NewFpoFrames;223 std::vector<DebugFrameDataSubsectionRef> newFpoFrames;
255224
256 /// Pointers to raw memory that we determine have string table references225 /// Pointers to raw memory that we determine have string table references
257 /// that need to be re-written. We first process all .debug$S subsections226 /// that need to be re-written. We first process all .debug$S subsections
...@@ -259,13 +228,17 @@ class DebugSHandler {...@@ -259,13 +228,17 @@ class DebugSHandler {
259 /// up this list as we go. At the end, we use the string table (which must228 /// 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 these229 /// have been discovered by now else it is an error) to re-write these
261 /// references.230 /// references.
262 std::vector<ulittle32_t *> StringTableReferences;231 std::vector<ulittle32_t *> stringTableReferences;
263232
264public:233public:
265 DebugSHandler(PDBLinker &Linker, ObjFile &File, const CVIndexMap &IndexMap)234 DebugSHandler(PDBLinker &linker, ObjFile &file, const CVIndexMap &indexMap)
266 : Linker(Linker), File(File), IndexMap(IndexMap) {}235 : linker(linker), file(file), indexMap(indexMap) {}
236
237 void handleDebugS(lld::coff::SectionChunk &debugS);
238
239 std::shared_ptr<DebugInlineeLinesSubsection>
240 mergeInlineeLines(DebugChecksumsSubsection *newChecksums);
267241
268 void handleDebugS(lld::coff::SectionChunk &DebugS);
269 void finish();242 void finish();
270};243};
271}244}
...@@ -273,7 +246,7 @@ public:...@@ -273,7 +246,7 @@ public:
273// Visual Studio's debugger requires absolute paths in various places in the246// Visual Studio's debugger requires absolute paths in various places in the
274// PDB to work without additional configuration:247// PDB to work without additional configuration:
275// https://docs.microsoft.com/en-us/visualstudio/debugger/debug-source-files-common-properties-solution-property-pages-dialog-box248// https://docs.microsoft.com/en-us/visualstudio/debugger/debug-source-files-common-properties-solution-property-pages-dialog-box
276static void pdbMakeAbsolute(SmallVectorImpl<char> &FileName) {249static void pdbMakeAbsolute(SmallVectorImpl<char> &fileName) {
277 // The default behavior is to produce paths that are valid within the context250 // 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 on251 // 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 is252 // a POSIX system, we will output absolute POSIX paths. If the linker is
...@@ -281,16 +254,16 @@ static void pdbMakeAbsolute(SmallVectorImpl<char> &FileName) {...@@ -281,16 +254,16 @@ static void pdbMakeAbsolute(SmallVectorImpl<char> &FileName) {
281 // user desires any other kind of behavior, they should explicitly pass254 // user desires any other kind of behavior, they should explicitly pass
282 // /pdbsourcepath, in which case we will treat the exact string the user255 // /pdbsourcepath, in which case we will treat the exact string the user
283 // passed in as the gospel and not normalize, canonicalize it.256 // passed in as the gospel and not normalize, canonicalize it.
284 if (sys::path::is_absolute(FileName, sys::path::Style::windows) ||257 if (sys::path::is_absolute(fileName, sys::path::Style::windows) ||
285 sys::path::is_absolute(FileName, sys::path::Style::posix))258 sys::path::is_absolute(fileName, sys::path::Style::posix))
286 return;259 return;
287260
288 // It's not absolute in any path syntax. Relative paths necessarily refer to261 // 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 a262 // the local file system, so we can make it native without ending up with a
290 // nonsensical path.263 // nonsensical path.
291 if (Config->PDBSourcePath.empty()) {264 if (config->pdbSourcePath.empty()) {
292 sys::path::native(FileName);265 sys::path::native(fileName);
293 sys::fs::make_absolute(FileName);266 sys::fs::make_absolute(fileName);
294 return;267 return;
295 }268 }
296269
...@@ -298,397 +271,239 @@ static void pdbMakeAbsolute(SmallVectorImpl<char> &FileName) {...@@ -298,397 +271,239 @@ static void pdbMakeAbsolute(SmallVectorImpl<char> &FileName) {
298 // Since PDB's are more of a Windows thing, we make this conservative and only271 // 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, if272 // decide that it's a unix path if we're fairly certain. Specifically, if
300 // it starts with a forward slash.273 // it starts with a forward slash.
301 SmallString<128> AbsoluteFileName = Config->PDBSourcePath;274 SmallString<128> absoluteFileName = config->pdbSourcePath;
302 sys::path::Style GuessedStyle = AbsoluteFileName.startswith("/")275 sys::path::Style guessedStyle = absoluteFileName.startswith("/")
303 ? sys::path::Style::posix276 ? sys::path::Style::posix
304 : sys::path::Style::windows;277 : sys::path::Style::windows;
305 sys::path::append(AbsoluteFileName, GuessedStyle, FileName);278 sys::path::append(absoluteFileName, guessedStyle, fileName);
306 sys::path::native(AbsoluteFileName, GuessedStyle);279 sys::path::native(absoluteFileName, guessedStyle);
307 sys::path::remove_dots(AbsoluteFileName, true, GuessedStyle);280 sys::path::remove_dots(absoluteFileName, true, guessedStyle);
308281
309 FileName = std::move(AbsoluteFileName);282 fileName = std::move(absoluteFileName);
310}
311
312static SectionChunk *findByName(ArrayRef<SectionChunk *> Sections,
313 StringRef Name) {
314 for (SectionChunk *C : Sections)
315 if (C->getSectionName() == Name)
316 return C;
317 return nullptr;
318}
319
320static ArrayRef<uint8_t> consumeDebugMagic(ArrayRef<uint8_t> Data,
321 StringRef SecName) {
322 // First 4 bytes are section magic.
323 if (Data.size() < 4)
324 fatal(SecName + " too short");
325 if (support::endian::read32le(Data.data()) != COFF::DEBUG_SECTION_MAGIC)
326 fatal(SecName + " has an invalid magic");
327 return Data.slice(4);
328}
329
330static ArrayRef<uint8_t> getDebugSection(ObjFile *File, StringRef SecName) {
331 if (SectionChunk *Sec = findByName(File->getDebugChunks(), SecName))
332 return consumeDebugMagic(Sec->getContents(), SecName);
333 return {};
334}283}
335284
336// A COFF .debug$H section is currently a clang extension. This function checks285// A COFF .debug$H section is currently a clang extension. This function checks
337// if a .debug$H section is in a format that we expect / understand, so that we286// if a .debug$H section is in a format that we expect / understand, so that we
338// can ignore any sections which are coincidentally also named .debug$H but do287// can ignore any sections which are coincidentally also named .debug$H but do
339// not contain a format we recognize.288// not contain a format we recognize.
340static bool canUseDebugH(ArrayRef<uint8_t> DebugH) {289static bool canUseDebugH(ArrayRef<uint8_t> debugH) {
341 if (DebugH.size() < sizeof(object::debug_h_header))290 if (debugH.size() < sizeof(object::debug_h_header))
342 return false;291 return false;
343 auto *Header =292 auto *header =
344 reinterpret_cast<const object::debug_h_header *>(DebugH.data());293 reinterpret_cast<const object::debug_h_header *>(debugH.data());
345 DebugH = DebugH.drop_front(sizeof(object::debug_h_header));294 debugH = debugH.drop_front(sizeof(object::debug_h_header));
346 return Header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC &&295 return header->Magic == COFF::DEBUG_HASHES_SECTION_MAGIC &&
347 Header->Version == 0 &&296 header->Version == 0 &&
348 Header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1_8) &&297 header->HashAlgorithm == uint16_t(GlobalTypeHashAlg::SHA1_8) &&
349 (DebugH.size() % 8 == 0);298 (debugH.size() % 8 == 0);
350}299}
351300
352static Optional<ArrayRef<uint8_t>> getDebugH(ObjFile *File) {301static Optional<ArrayRef<uint8_t>> getDebugH(ObjFile *file) {
353 SectionChunk *Sec = findByName(File->getDebugChunks(), ".debug$H");302 SectionChunk *sec =
354 if (!Sec)303 SectionChunk::findByName(file->getDebugChunks(), ".debug$H");
304 if (!sec)
355 return llvm::None;305 return llvm::None;
356 ArrayRef<uint8_t> Contents = Sec->getContents();306 ArrayRef<uint8_t> contents = sec->getContents();
357 if (!canUseDebugH(Contents))307 if (!canUseDebugH(contents))
358 return None;308 return None;
359 return Contents;309 return contents;
360}310}
361311
362static ArrayRef<GloballyHashedType>312static ArrayRef<GloballyHashedType>
363getHashesFromDebugH(ArrayRef<uint8_t> DebugH) {313getHashesFromDebugH(ArrayRef<uint8_t> debugH) {
364 assert(canUseDebugH(DebugH));314 assert(canUseDebugH(debugH));
365315
366 DebugH = DebugH.drop_front(sizeof(object::debug_h_header));316 debugH = debugH.drop_front(sizeof(object::debug_h_header));
367 uint32_t Count = DebugH.size() / sizeof(GloballyHashedType);317 uint32_t count = debugH.size() / sizeof(GloballyHashedType);
368 return {reinterpret_cast<const GloballyHashedType *>(DebugH.data()), Count};318 return {reinterpret_cast<const GloballyHashedType *>(debugH.data()), count};
369}319}
370320
371static void addTypeInfo(pdb::TpiStreamBuilder &TpiBuilder,321static void addTypeInfo(pdb::TpiStreamBuilder &tpiBuilder,
372 TypeCollection &TypeTable) {322 TypeCollection &typeTable) {
373 // Start the TPI or IPI stream header.323 // Start the TPI or IPI stream header.
374 TpiBuilder.setVersionHeader(pdb::PdbTpiV80);324 tpiBuilder.setVersionHeader(pdb::PdbTpiV80);
375325
376 // Flatten the in memory type table and hash each type.326 // Flatten the in memory type table and hash each type.
377 TypeTable.ForEachRecord([&](TypeIndex TI, const CVType &Type) {327 typeTable.ForEachRecord([&](TypeIndex ti, const CVType &type) {
378 auto Hash = pdb::hashTypeRecord(Type);328 auto hash = pdb::hashTypeRecord(type);
379 if (auto E = Hash.takeError())329 if (auto e = hash.takeError())
380 fatal("type hashing error");330 fatal("type hashing error");
381 TpiBuilder.addTypeRecord(Type.RecordData, *Hash);331 tpiBuilder.addTypeRecord(type.RecordData, *hash);
382 });332 });
383}333}
384334
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.
390static 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;
417}
418
419Expected<const CVIndexMap &>335Expected<const CVIndexMap &>
420PDBLinker::mergeDebugT(ObjFile *File, CVIndexMap *ObjectIndexMap) {336PDBLinker::mergeDebugT(ObjFile *file, CVIndexMap *objectIndexMap) {
421 ScopedTimer T(TypeMergingTimer);337 ScopedTimer t(typeMergingTimer);
422338
423 bool IsPrecompiledHeader = false;339 if (!file->debugTypesObj)
424340 return *objectIndexMap; // no Types stream
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 }
432 if (Data.empty())
433 return *ObjectIndexMap; // no debug info
434341
435 // Precompiled headers objects need to save the index map for further342 // Precompiled headers objects need to save the index map for further
436 // reference by other objects which use the precompiled headers.343 // reference by other objects which use the precompiled headers.
437 if (IsPrecompiledHeader) {344 if (file->debugTypesObj->kind == TpiSource::PCH) {
438 uint32_t PCHSignature = extractPCHSignature(File);345 uint32_t pchSignature = file->pchSignature.getValueOr(0);
439 if (PCHSignature == 0)346 if (pchSignature == 0)
440 fatal("No signature found for the precompiled headers OBJ (" +347 fatal("No signature found for the precompiled headers OBJ (" +
441 File->getName() + ")");348 file->getName() + ")");
442349
443 // When a precompiled headers object comes first on the command-line, we350 // When a precompiled headers object comes first on the command-line, we
444 // update the mapping here. Otherwise, if an object referencing the351 // update the mapping here. Otherwise, if an object referencing the
445 // precompiled headers object comes first, the mapping is created in352 // precompiled headers object comes first, the mapping is created in
446 // aquirePrecompObj(), thus we would skip this block.353 // aquirePrecompObj(), thus we would skip this block.
447 if (!ObjectIndexMap->IsPrecompiledTypeMap) {354 if (!objectIndexMap->isPrecompiledTypeMap) {
448 auto R = registerPrecompiledHeaders(PCHSignature);355 auto r = registerPrecompiledHeaders(pchSignature);
449 if (R.second)356 if (r.second)
450 fatal(357 fatal(
451 "A precompiled headers OBJ with the same signature was already "358 "A precompiled headers OBJ with the same signature was already "
452 "provided! (" +359 "provided! (" +
453 File->getName() + ")");360 file->getName() + ")");
454361
455 ObjectIndexMap = &R.first;362 objectIndexMap = &r.first;
456 }363 }
457 }364 }
458365
459 BinaryByteStream Stream(Data, support::little);366 if (file->debugTypesObj->kind == TpiSource::UsingPDB) {
460 CVTypeArray Types;
461 BinaryStreamReader Reader(Stream);
462 if (auto EC = Reader.readArray(Types, Reader.getLength()))
463 fatal("Reader::readArray failed: " + toString(std::move(EC)));
464
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,367 // Look through type servers. If we've already seen this type server,
471 // don't merge any type information.368 // don't merge any type information.
472 return maybeMergeTypeServerPDB(File, *FirstType);369 return maybeMergeTypeServerPDB(file);
473 } else if (FirstType->kind() == LF_PRECOMP) {370 }
371
372 CVTypeArray &types = *file->debugTypes;
373
374 if (file->debugTypesObj->kind == TpiSource::UsingPCH) {
474 // This object was compiled with /Yu, so process the corresponding375 // This object was compiled with /Yu, so process the corresponding
475 // precompiled headers object (/Yc) first. Some type indices in the current376 // precompiled headers object (/Yc) first. Some type indices in the current
476 // object are referencing data in the precompiled headers object, so we need377 // object are referencing data in the precompiled headers object, so we need
477 // both to be loaded.378 // both to be loaded.
478 auto E = mergeInPrecompHeaderObj(File, *FirstType, ObjectIndexMap);379 Error e = mergeInPrecompHeaderObj(file, objectIndexMap);
479 if (!E)380 if (e)
480 return E.takeError();381 return std::move(e);
481382
482 // Drop LF_PRECOMP record from the input stream, as it needs to be replaced383 // Drop LF_PRECOMP record from the input stream, as it has been replaced
483 // with the precompiled headers object type stream.384 // with the precompiled headers Type stream in the mergeInPrecompHeaderObj()
484 // Note that we can't just call Types.drop_front(), as we explicitly want to385 // call above. Note that we can't just call Types.drop_front(), as we
485 // rebase the stream.386 // explicitly want to rebase the stream.
486 Types.setUnderlyingStream(387 CVTypeArray::Iterator firstType = types.begin();
487 Types.getUnderlyingStream().drop_front(FirstType->RecordData.size()));388 types.setUnderlyingStream(
389 types.getUnderlyingStream().drop_front(firstType->RecordData.size()));
488 }390 }
489391
490 // Fill in the temporary, caller-provided ObjectIndexMap.392 // Fill in the temporary, caller-provided ObjectIndexMap.
491 if (Config->DebugGHashes) {393 if (config->debugGHashes) {
492 ArrayRef<GloballyHashedType> Hashes;394 ArrayRef<GloballyHashedType> hashes;
493 std::vector<GloballyHashedType> OwnedHashes;395 std::vector<GloballyHashedType> ownedHashes;
494 if (Optional<ArrayRef<uint8_t>> DebugH = getDebugH(File))396 if (Optional<ArrayRef<uint8_t>> debugH = getDebugH(file))
495 Hashes = getHashesFromDebugH(*DebugH);397 hashes = getHashesFromDebugH(*debugH);
496 else {398 else {
497 OwnedHashes = GloballyHashedType::hashTypes(Types);399 ownedHashes = GloballyHashedType::hashTypes(types);
498 Hashes = OwnedHashes;400 hashes = ownedHashes;
499 }401 }
500402
501 if (auto Err = mergeTypeAndIdRecords(GlobalIDTable, GlobalTypeTable,403 if (auto err = mergeTypeAndIdRecords(
502 ObjectIndexMap->TPIMap, Types, Hashes,404 tMerger.globalIDTable, tMerger.globalTypeTable,
503 File->PCHSignature))405 objectIndexMap->tpiMap, types, hashes, file->pchSignature))
504 fatal("codeview::mergeTypeAndIdRecords failed: " +406 fatal("codeview::mergeTypeAndIdRecords failed: " +
505 toString(std::move(Err)));407 toString(std::move(err)));
506 } else {408 } else {
507 if (auto Err =409 if (auto err = mergeTypeAndIdRecords(tMerger.iDTable, tMerger.typeTable,
508 mergeTypeAndIdRecords(IDTable, TypeTable, ObjectIndexMap->TPIMap,410 objectIndexMap->tpiMap, types,
509 Types, File->PCHSignature))411 file->pchSignature))
510 fatal("codeview::mergeTypeAndIdRecords failed: " +412 fatal("codeview::mergeTypeAndIdRecords failed: " +
511 toString(std::move(Err)));413 toString(std::move(err)));
512 }414 }
513 return *ObjectIndexMap;415 return *objectIndexMap;
514}416}
515417
516static Expected<std::unique_ptr<pdb::NativeSession>>418Expected<const CVIndexMap &> PDBLinker::maybeMergeTypeServerPDB(ObjFile *file) {
517tryToLoadPDB(const codeview::GUID &GuidFromObj, StringRef TSPath) {419 Expected<llvm::pdb::NativeSession *> pdbSession = findTypeServerSource(file);
518 // Ensure the file exists before anything else. We want to return ENOENT,420 if (!pdbSession)
519 // "file not found", even if the path points to a removable device (in which421 return pdbSession.takeError();
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
524 ErrorOr<std::unique_ptr<MemoryBuffer>> MBOrErr = MemoryBuffer::getFile(
525 TSPath, /*FileSize=*/-1, /*RequiresNullTerminator=*/false);
526 if (!MBOrErr)
527 return errorCodeToError(MBOrErr.getError());
528
529 std::unique_ptr<pdb::IPDBSession> ThisSession;
530 if (auto EC = pdb::NativeSession::createFromPdb(
531 MemoryBuffer::getMemBuffer(Driver->takeBuffer(std::move(*MBOrErr)),
532 /*RequiresNullTerminator=*/false),
533 ThisSession))
534 return std::move(EC);
535
536 std::unique_ptr<pdb::NativeSession> NS(
537 static_cast<pdb::NativeSession *>(ThisSession.release()));
538 pdb::PDBFile &File = NS->getPDBFile();
539 auto ExpectedInfo = File.getPDBInfoStream();
540 // All PDB Files should have an Info stream.
541 if (!ExpectedInfo)
542 return ExpectedInfo.takeError();
543
544 // Just because a file with a matching name was found and it was an actual
545 // PDB file doesn't mean it matches. For it to match the InfoStream's GUID
546 // must match the GUID specified in the TypeServer2 record.
547 if (ExpectedInfo->getGuid() != GuidFromObj)
548 return make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date);
549
550 return std::move(NS);
551}
552422
553Expected<const CVIndexMap &>423 pdb::PDBFile &pdbFile = pdbSession.get()->getPDBFile();
554PDBLinker::maybeMergeTypeServerPDB(ObjFile *File, const CVType &FirstType) {424 pdb::InfoStream &info = cantFail(pdbFile.getPDBInfoStream());
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();
561 StringRef TSPath = TS.getName();
562
563 // First, check if the PDB has previously failed to load.
564 auto PrevErr = MissingTypeServerPDBs.find(TSId);
565 if (PrevErr != MissingTypeServerPDBs.end())
566 return createFileError(
567 TSPath,
568 make_error<StringError>(PrevErr->second, inconvertibleErrorCode()));
569425
570 // Second, check if we already loaded a PDB with this GUID. Return the type426 auto it = typeServerIndexMappings.emplace(info.getGuid(), CVIndexMap());
571 // index mapping if we have it.427 CVIndexMap &indexMap = it.first->second;
572 auto Insertion = TypeServerIndexMappings.insert({TSId, CVIndexMap()});428 if (!it.second)
573 CVIndexMap &IndexMap = Insertion.first->second;429 return indexMap; // already merged
574 if (!Insertion.second)
575 return IndexMap;
576430
577 // Mark this map as a type server map.431 // Mark this map as a type server map.
578 IndexMap.IsTypeServerMap = true;432 indexMap.isTypeServerMap = true;
579433
580 // Check for a PDB at:434 Expected<pdb::TpiStream &> expectedTpi = pdbFile.getPDBTpiStream();
581 // 1. The given file path435 if (auto e = expectedTpi.takeError())
582 // 2. Next to the object file or archive file436 fatal("Type server does not have TPI stream: " + toString(std::move(e)));
583 auto ExpectedSession = handleExpected(437 pdb::TpiStream *maybeIpi = nullptr;
584 tryToLoadPDB(TSId, TSPath),438 if (pdbFile.hasPDBIpiStream()) {
585 [&]() {439 Expected<pdb::TpiStream &> expectedIpi = pdbFile.getPDBIpiStream();
586 StringRef LocalPath =440 if (auto e = expectedIpi.takeError())
587 !File->ParentName.empty() ? File->ParentName : File->getName();441 fatal("Error getting type server IPI stream: " + toString(std::move(e)));
588 SmallString<128> Path = sys::path::parent_path(LocalPath);442 maybeIpi = &*expectedIpi;
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
605 if (auto E = ExpectedSession.takeError()) {
606 TypeServerIndexMappings.erase(TSId);
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));
616 }443 }
617444
618 pdb::NativeSession *Session = ExpectedSession->get();445 if (config->debugGHashes) {
619
620 // Keep a strong reference to this PDB, so that it's safe to hold pointers
621 // into the file.
622 LoadedPDBs.push_back(std::move(*ExpectedSession));
623
624 auto ExpectedTpi = Session->getPDBFile().getPDBTpiStream();
625 if (auto E = ExpectedTpi.takeError())
626 fatal("Type server does not have TPI stream: " + toString(std::move(E)));
627 auto ExpectedIpi = Session->getPDBFile().getPDBIpiStream();
628 if (auto E = ExpectedIpi.takeError())
629 fatal("Type server does not have TPI stream: " + toString(std::move(E)));
630
631 if (Config->DebugGHashes) {
632 // PDBs do not actually store global hashes, so when merging a type server446 // PDBs do not actually store global hashes, so when merging a type server
633 // PDB we have to synthesize global hashes. To do this, we first synthesize447 // PDB we have to synthesize global hashes. To do this, we first synthesize
634 // global hashes for the TPI stream, since it is independent, then we448 // global hashes for the TPI stream, since it is independent, then we
635 // synthesize hashes for the IPI stream, using the hashes for the TPI stream449 // synthesize hashes for the IPI stream, using the hashes for the TPI stream
636 // as inputs.450 // as inputs.
637 auto TpiHashes = GloballyHashedType::hashTypes(ExpectedTpi->typeArray());451 auto tpiHashes = GloballyHashedType::hashTypes(expectedTpi->typeArray());
638 auto IpiHashes =452 Optional<uint32_t> endPrecomp;
639 GloballyHashedType::hashIds(ExpectedIpi->typeArray(), TpiHashes);
640
641 Optional<uint32_t> EndPrecomp;
642 // Merge TPI first, because the IPI stream will reference type indices.453 // Merge TPI first, because the IPI stream will reference type indices.
643 if (auto Err = mergeTypeRecords(GlobalTypeTable, IndexMap.TPIMap,454 if (auto err =
644 ExpectedTpi->typeArray(), TpiHashes, EndPrecomp))455 mergeTypeRecords(tMerger.globalTypeTable, indexMap.tpiMap,
645 fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));456 expectedTpi->typeArray(), tpiHashes, endPrecomp))
457 fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err)));
646458
647 // Merge IPI.459 // Merge IPI.
648 if (auto Err =460 if (maybeIpi) {
649 mergeIdRecords(GlobalIDTable, IndexMap.TPIMap, IndexMap.IPIMap,461 auto ipiHashes =
650 ExpectedIpi->typeArray(), IpiHashes))462 GloballyHashedType::hashIds(maybeIpi->typeArray(), tpiHashes);
651 fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));463 if (auto err =
464 mergeIdRecords(tMerger.globalIDTable, indexMap.tpiMap,
465 indexMap.ipiMap, maybeIpi->typeArray(), ipiHashes))
466 fatal("codeview::mergeIdRecords failed: " + toString(std::move(err)));
467 }
652 } else {468 } else {
653 // Merge TPI first, because the IPI stream will reference type indices.469 // Merge TPI first, because the IPI stream will reference type indices.
654 if (auto Err = mergeTypeRecords(TypeTable, IndexMap.TPIMap,470 if (auto err = mergeTypeRecords(tMerger.typeTable, indexMap.tpiMap,
655 ExpectedTpi->typeArray()))471 expectedTpi->typeArray()))
656 fatal("codeview::mergeTypeRecords failed: " + toString(std::move(Err)));472 fatal("codeview::mergeTypeRecords failed: " + toString(std::move(err)));
657473
658 // Merge IPI.474 // Merge IPI.
659 if (auto Err = mergeIdRecords(IDTable, IndexMap.TPIMap, IndexMap.IPIMap,475 if (maybeIpi) {
660 ExpectedIpi->typeArray()))476 if (auto err = mergeIdRecords(tMerger.iDTable, indexMap.tpiMap,
661 fatal("codeview::mergeIdRecords failed: " + toString(std::move(Err)));477 indexMap.ipiMap, maybeIpi->typeArray()))
478 fatal("codeview::mergeIdRecords failed: " + toString(std::move(err)));
479 }
662 }480 }
663481
664 return IndexMap;482 return indexMap;
665}483}
666484
667Expected<const CVIndexMap &>485Error PDBLinker::mergeInPrecompHeaderObj(ObjFile *file,
668PDBLinker::mergeInPrecompHeaderObj(ObjFile *File, const CVType &FirstType,486 CVIndexMap *objectIndexMap) {
669 CVIndexMap *ObjectIndexMap) {487 const PrecompRecord &precomp =
670 PrecompRecord Precomp;488 retrieveDependencyInfo<PrecompRecord>(file->debugTypesObj);
671 if (auto EC = TypeDeserializer::deserializeAs(const_cast<CVType &>(FirstType),
672 Precomp))
673 fatal("error reading record: " + toString(std::move(EC)));
674489
675 auto E = aquirePrecompObj(File, Precomp);490 Expected<const CVIndexMap &> e = aquirePrecompObj(file);
676 if (!E)491 if (!e)
677 return E.takeError();492 return e.takeError();
678493
679 const CVIndexMap &PrecompIndexMap = *E;494 const CVIndexMap &precompIndexMap = *e;
680 assert(PrecompIndexMap.IsPrecompiledTypeMap);495 assert(precompIndexMap.isPrecompiledTypeMap);
681496
682 if (PrecompIndexMap.TPIMap.empty())497 if (precompIndexMap.tpiMap.empty())
683 return PrecompIndexMap;498 return Error::success();
684499
685 assert(Precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex);500 assert(precomp.getStartTypeIndex() == TypeIndex::FirstNonSimpleIndex);
686 assert(Precomp.getTypesCount() <= PrecompIndexMap.TPIMap.size());501 assert(precomp.getTypesCount() <= precompIndexMap.tpiMap.size());
687 // Use the previously remapped index map from the precompiled headers.502 // Use the previously remapped index map from the precompiled headers.
688 ObjectIndexMap->TPIMap.append(PrecompIndexMap.TPIMap.begin(),503 objectIndexMap->tpiMap.append(precompIndexMap.tpiMap.begin(),
689 PrecompIndexMap.TPIMap.begin() +504 precompIndexMap.tpiMap.begin() +
690 Precomp.getTypesCount());505 precomp.getTypesCount());
691 return *ObjectIndexMap;506 return Error::success();
692}507}
693508
694static bool equals_path(StringRef path1, StringRef path2) {509static bool equals_path(StringRef path1, StringRef path2) {
...@@ -700,101 +515,103 @@ static bool equals_path(StringRef path1, StringRef path2) {...@@ -700,101 +515,103 @@ static bool equals_path(StringRef path1, StringRef path2) {
700}515}
701516
702// Find by name an OBJ provided on the command line517// Find by name an OBJ provided on the command line
703static ObjFile *findObjByName(StringRef FileNameOnly) {518static ObjFile *findObjByName(StringRef fileNameOnly) {
704 SmallString<128> CurrentPath;519 SmallString<128> currentPath;
705520
706 for (ObjFile *F : ObjFile::Instances) {521 for (ObjFile *f : ObjFile::instances) {
707 StringRef CurrentFileName = sys::path::filename(F->getName());522 StringRef currentFileName = sys::path::filename(f->getName());
708523
709 // Compare based solely on the file name (link.exe behavior)524 // Compare based solely on the file name (link.exe behavior)
710 if (equals_path(CurrentFileName, FileNameOnly))525 if (equals_path(currentFileName, fileNameOnly))
711 return F;526 return f;
712 }527 }
713 return nullptr;528 return nullptr;
714}529}
715530
716std::pair<CVIndexMap &, bool /*already there*/>531std::pair<CVIndexMap &, bool /*already there*/>
717PDBLinker::registerPrecompiledHeaders(uint32_t Signature) {532PDBLinker::registerPrecompiledHeaders(uint32_t signature) {
718 auto Insertion = PrecompTypeIndexMappings.insert({Signature, CVIndexMap()});533 auto insertion = precompTypeIndexMappings.insert({signature, CVIndexMap()});
719 CVIndexMap &IndexMap = Insertion.first->second;534 CVIndexMap &indexMap = insertion.first->second;
720 if (!Insertion.second)535 if (!insertion.second)
721 return {IndexMap, true};536 return {indexMap, true};
722 // Mark this map as a precompiled types map.537 // Mark this map as a precompiled types map.
723 IndexMap.IsPrecompiledTypeMap = true;538 indexMap.isPrecompiledTypeMap = true;
724 return {IndexMap, false};539 return {indexMap, false};
725}540}
726541
727Expected<const CVIndexMap &>542Expected<const CVIndexMap &> PDBLinker::aquirePrecompObj(ObjFile *file) {
728PDBLinker::aquirePrecompObj(ObjFile *File, PrecompRecord Precomp) {543 const PrecompRecord &precomp =
544 retrieveDependencyInfo<PrecompRecord>(file->debugTypesObj);
545
729 // First, check if we already loaded the precompiled headers object with this546 // 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.547 // signature. Return the type index mapping if we've already seen it.
731 auto R = registerPrecompiledHeaders(Precomp.getSignature());548 auto r = registerPrecompiledHeaders(precomp.getSignature());
732 if (R.second)549 if (r.second)
733 return R.first;550 return r.first;
734551
735 CVIndexMap &IndexMap = R.first;552 CVIndexMap &indexMap = r.first;
736553
737 // Cross-compile warning: given that Clang doesn't generate LF_PRECOMP554 // 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,555 // 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.556 // the paths embedded in the OBJs are in the Windows format.
740 SmallString<128> PrecompFileName = sys::path::filename(557 SmallString<128> precompFileName = sys::path::filename(
741 Precomp.getPrecompFilePath(), sys::path::Style::windows);558 precomp.getPrecompFilePath(), sys::path::Style::windows);
742559
743 // link.exe requires that a precompiled headers object must always be provided560 // link.exe requires that a precompiled headers object must always be provided
744 // on the command-line, even if that's not necessary.561 // on the command-line, even if that's not necessary.
745 auto PrecompFile = findObjByName(PrecompFileName);562 auto precompFile = findObjByName(precompFileName);
746 if (!PrecompFile)563 if (!precompFile)
747 return createFileError(564 return createFileError(
748 PrecompFileName.str(),565 precompFileName.str(),
749 make_error<pdb::PDBError>(pdb::pdb_error_code::external_cmdline_ref));566 make_error<pdb::PDBError>(pdb::pdb_error_code::external_cmdline_ref));
750567
751 addObjFile(PrecompFile, &IndexMap);568 addObjFile(precompFile, &indexMap);
752569
753 if (!PrecompFile->PCHSignature)570 if (!precompFile->pchSignature)
754 fatal(PrecompFile->getName() + " is not a precompiled headers object");571 fatal(precompFile->getName() + " is not a precompiled headers object");
755572
756 if (Precomp.getSignature() != PrecompFile->PCHSignature.getValueOr(0))573 if (precomp.getSignature() != precompFile->pchSignature.getValueOr(0))
757 return createFileError(574 return createFileError(
758 Precomp.getPrecompFilePath().str(),575 precomp.getPrecompFilePath().str(),
759 make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date));576 make_error<pdb::PDBError>(pdb::pdb_error_code::signature_out_of_date));
760577
761 return IndexMap;578 return indexMap;
762}579}
763580
764static bool remapTypeIndex(TypeIndex &TI, ArrayRef<TypeIndex> TypeIndexMap) {581static bool remapTypeIndex(TypeIndex &ti, ArrayRef<TypeIndex> typeIndexMap) {
765 if (TI.isSimple())582 if (ti.isSimple())
766 return true;583 return true;
767 if (TI.toArrayIndex() >= TypeIndexMap.size())584 if (ti.toArrayIndex() >= typeIndexMap.size())
768 return false;585 return false;
769 TI = TypeIndexMap[TI.toArrayIndex()];586 ti = typeIndexMap[ti.toArrayIndex()];
770 return true;587 return true;
771}588}
772589
773static void remapTypesInSymbolRecord(ObjFile *File, SymbolKind SymKind,590static void remapTypesInSymbolRecord(ObjFile *file, SymbolKind symKind,
774 MutableArrayRef<uint8_t> RecordBytes,591 MutableArrayRef<uint8_t> recordBytes,
775 const CVIndexMap &IndexMap,592 const CVIndexMap &indexMap,
776 ArrayRef<TiReference> TypeRefs) {593 ArrayRef<TiReference> typeRefs) {
777 MutableArrayRef<uint8_t> Contents =594 MutableArrayRef<uint8_t> contents =
778 RecordBytes.drop_front(sizeof(RecordPrefix));595 recordBytes.drop_front(sizeof(RecordPrefix));
779 for (const TiReference &Ref : TypeRefs) {596 for (const TiReference &ref : typeRefs) {
780 unsigned ByteSize = Ref.Count * sizeof(TypeIndex);597 unsigned byteSize = ref.Count * sizeof(TypeIndex);
781 if (Contents.size() < Ref.Offset + ByteSize)598 if (contents.size() < ref.Offset + byteSize)
782 fatal("symbol record too short");599 fatal("symbol record too short");
783600
784 // This can be an item index or a type index. Choose the appropriate map.601 // This can be an item index or a type index. Choose the appropriate map.
785 ArrayRef<TypeIndex> TypeOrItemMap = IndexMap.TPIMap;602 ArrayRef<TypeIndex> typeOrItemMap = indexMap.tpiMap;
786 bool IsItemIndex = Ref.Kind == TiRefKind::IndexRef;603 bool isItemIndex = ref.Kind == TiRefKind::IndexRef;
787 if (IsItemIndex && IndexMap.IsTypeServerMap)604 if (isItemIndex && indexMap.isTypeServerMap)
788 TypeOrItemMap = IndexMap.IPIMap;605 typeOrItemMap = indexMap.ipiMap;
789606
790 MutableArrayRef<TypeIndex> TIs(607 MutableArrayRef<TypeIndex> tIs(
791 reinterpret_cast<TypeIndex *>(Contents.data() + Ref.Offset), Ref.Count);608 reinterpret_cast<TypeIndex *>(contents.data() + ref.Offset), ref.Count);
792 for (TypeIndex &TI : TIs) {609 for (TypeIndex &ti : tIs) {
793 if (!remapTypeIndex(TI, TypeOrItemMap)) {610 if (!remapTypeIndex(ti, typeOrItemMap)) {
794 log("ignoring symbol record of kind 0x" + utohexstr(SymKind) + " in " +611 log("ignoring symbol record of kind 0x" + utohexstr(symKind) + " in " +
795 File->getName() + " with bad " + (IsItemIndex ? "item" : "type") +612 file->getName() + " with bad " + (isItemIndex ? "item" : "type") +
796 " index 0x" + utohexstr(TI.getIndex()));613 " index 0x" + utohexstr(ti.getIndex()));
797 TI = TypeIndex(SimpleTypeKind::NotTranslated);614 ti = TypeIndex(SimpleTypeKind::NotTranslated);
798 continue;615 continue;
799 }616 }
800 }617 }
...@@ -802,26 +619,26 @@ static void remapTypesInSymbolRecord(ObjFile *File, SymbolKind SymKind,...@@ -802,26 +619,26 @@ static void remapTypesInSymbolRecord(ObjFile *File, SymbolKind SymKind,
802}619}
803620
804static void621static void
805recordStringTableReferenceAtOffset(MutableArrayRef<uint8_t> Contents,622recordStringTableReferenceAtOffset(MutableArrayRef<uint8_t> contents,
806 uint32_t Offset,623 uint32_t offset,
807 std::vector<ulittle32_t *> &StrTableRefs) {624 std::vector<ulittle32_t *> &strTableRefs) {
808 Contents =625 contents =
809 Contents.drop_front(Offset).take_front(sizeof(support::ulittle32_t));626 contents.drop_front(offset).take_front(sizeof(support::ulittle32_t));
810 ulittle32_t *Index = reinterpret_cast<ulittle32_t *>(Contents.data());627 ulittle32_t *index = reinterpret_cast<ulittle32_t *>(contents.data());
811 StrTableRefs.push_back(Index);628 strTableRefs.push_back(index);
812}629}
813630
814static void631static void
815recordStringTableReferences(SymbolKind Kind, MutableArrayRef<uint8_t> Contents,632recordStringTableReferences(SymbolKind kind, MutableArrayRef<uint8_t> contents,
816 std::vector<ulittle32_t *> &StrTableRefs) {633 std::vector<ulittle32_t *> &strTableRefs) {
817 // For now we only handle S_FILESTATIC, but we may need the same logic for634 // For now we only handle S_FILESTATIC, but we may need the same logic for
818 // S_DEFRANGE and S_DEFRANGE_SUBFIELD. However, I cannot seem to generate any635 // S_DEFRANGE and S_DEFRANGE_SUBFIELD. However, I cannot seem to generate any
819 // PDBs that contain these types of records, so because of the uncertainty636 // PDBs that contain these types of records, so because of the uncertainty
820 // they are omitted here until we can prove that it's necessary.637 // they are omitted here until we can prove that it's necessary.
821 switch (Kind) {638 switch (kind) {
822 case SymbolKind::S_FILESTATIC:639 case SymbolKind::S_FILESTATIC:
823 // FileStaticSym::ModFileOffset640 // FileStaticSym::ModFileOffset
824 recordStringTableReferenceAtOffset(Contents, 8, StrTableRefs);641 recordStringTableReferenceAtOffset(contents, 8, strTableRefs);
825 break;642 break;
826 case SymbolKind::S_DEFRANGE:643 case SymbolKind::S_DEFRANGE:
827 case SymbolKind::S_DEFRANGE_SUBFIELD:644 case SymbolKind::S_DEFRANGE_SUBFIELD:
...@@ -833,21 +650,21 @@ recordStringTableReferences(SymbolKind Kind, MutableArrayRef<uint8_t> Contents,...@@ -833,21 +650,21 @@ recordStringTableReferences(SymbolKind Kind, MutableArrayRef<uint8_t> Contents,
833 }650 }
834}651}
835652
836static SymbolKind symbolKind(ArrayRef<uint8_t> RecordData) {653static SymbolKind symbolKind(ArrayRef<uint8_t> recordData) {
837 const RecordPrefix *Prefix =654 const RecordPrefix *prefix =
838 reinterpret_cast<const RecordPrefix *>(RecordData.data());655 reinterpret_cast<const RecordPrefix *>(recordData.data());
839 return static_cast<SymbolKind>(uint16_t(Prefix->RecordKind));656 return static_cast<SymbolKind>(uint16_t(prefix->RecordKind));
840}657}
841658
842/// MSVC translates S_PROC_ID_END to S_END, and S_[LG]PROC32_ID to S_[LG]PROC32659/// MSVC translates S_PROC_ID_END to S_END, and S_[LG]PROC32_ID to S_[LG]PROC32
843static void translateIdSymbols(MutableArrayRef<uint8_t> &RecordData,660static void translateIdSymbols(MutableArrayRef<uint8_t> &recordData,
844 TypeCollection &IDTable) {661 TypeCollection &iDTable) {
845 RecordPrefix *Prefix = reinterpret_cast<RecordPrefix *>(RecordData.data());662 RecordPrefix *prefix = reinterpret_cast<RecordPrefix *>(recordData.data());
846663
847 SymbolKind Kind = symbolKind(RecordData);664 SymbolKind kind = symbolKind(recordData);
848665
849 if (Kind == SymbolKind::S_PROC_ID_END) {666 if (kind == SymbolKind::S_PROC_ID_END) {
850 Prefix->RecordKind = SymbolKind::S_END;667 prefix->RecordKind = SymbolKind::S_END;
851 return;668 return;
852 }669 }
853670
...@@ -856,89 +673,89 @@ static void translateIdSymbols(MutableArrayRef<uint8_t> &RecordData,...@@ -856,89 +673,89 @@ static void translateIdSymbols(MutableArrayRef<uint8_t> &RecordData,
856 // to the PDB file's ID stream index space, but we need to convert this to a673 // to the PDB file's ID stream index space, but we need to convert this to a
857 // symbol that refers to the type stream index space. So we remap again from674 // symbol that refers to the type stream index space. So we remap again from
858 // ID index space to type index space.675 // ID index space to type index space.
859 if (Kind == SymbolKind::S_GPROC32_ID || Kind == SymbolKind::S_LPROC32_ID) {676 if (kind == SymbolKind::S_GPROC32_ID || kind == SymbolKind::S_LPROC32_ID) {
860 SmallVector<TiReference, 1> Refs;677 SmallVector<TiReference, 1> refs;
861 auto Content = RecordData.drop_front(sizeof(RecordPrefix));678 auto content = recordData.drop_front(sizeof(RecordPrefix));
862 CVSymbol Sym(Kind, RecordData);679 CVSymbol sym(recordData);
863 discoverTypeIndicesInSymbol(Sym, Refs);680 discoverTypeIndicesInSymbol(sym, refs);
864 assert(Refs.size() == 1);681 assert(refs.size() == 1);
865 assert(Refs.front().Count == 1);682 assert(refs.front().Count == 1);
866683
867 TypeIndex *TI =684 TypeIndex *ti =
868 reinterpret_cast<TypeIndex *>(Content.data() + Refs[0].Offset);685 reinterpret_cast<TypeIndex *>(content.data() + refs[0].Offset);
869 // `TI` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in686 // `ti` is the index of a FuncIdRecord or MemberFuncIdRecord which lives in
870 // the IPI stream, whose `FunctionType` member refers to the TPI stream.687 // the IPI stream, whose `FunctionType` member refers to the TPI stream.
871 // Note that LF_FUNC_ID and LF_MEMFUNC_ID have the same record layout, and688 // Note that LF_FUNC_ID and LF_MEMFUNC_ID have the same record layout, and
872 // in both cases we just need the second type index.689 // in both cases we just need the second type index.
873 if (!TI->isSimple() && !TI->isNoneType()) {690 if (!ti->isSimple() && !ti->isNoneType()) {
874 CVType FuncIdData = IDTable.getType(*TI);691 CVType funcIdData = iDTable.getType(*ti);
875 SmallVector<TypeIndex, 2> Indices;692 SmallVector<TypeIndex, 2> indices;
876 discoverTypeIndices(FuncIdData, Indices);693 discoverTypeIndices(funcIdData, indices);
877 assert(Indices.size() == 2);694 assert(indices.size() == 2);
878 *TI = Indices[1];695 *ti = indices[1];
879 }696 }
880697
881 Kind = (Kind == SymbolKind::S_GPROC32_ID) ? SymbolKind::S_GPROC32698 kind = (kind == SymbolKind::S_GPROC32_ID) ? SymbolKind::S_GPROC32
882 : SymbolKind::S_LPROC32;699 : SymbolKind::S_LPROC32;
883 Prefix->RecordKind = uint16_t(Kind);700 prefix->RecordKind = uint16_t(kind);
884 }701 }
885}702}
886703
887/// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned.704/// Copy the symbol record. In a PDB, symbol records must be 4 byte aligned.
888/// The object file may not be aligned.705/// The object file may not be aligned.
889static MutableArrayRef<uint8_t>706static MutableArrayRef<uint8_t>
890copyAndAlignSymbol(const CVSymbol &Sym, MutableArrayRef<uint8_t> &AlignedMem) {707copyAndAlignSymbol(const CVSymbol &sym, MutableArrayRef<uint8_t> &alignedMem) {
891 size_t Size = alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb));708 size_t size = alignTo(sym.length(), alignOf(CodeViewContainer::Pdb));
892 assert(Size >= 4 && "record too short");709 assert(size >= 4 && "record too short");
893 assert(Size <= MaxRecordLength && "record too long");710 assert(size <= MaxRecordLength && "record too long");
894 assert(AlignedMem.size() >= Size && "didn't preallocate enough");711 assert(alignedMem.size() >= size && "didn't preallocate enough");
895712
896 // Copy the symbol record and zero out any padding bytes.713 // Copy the symbol record and zero out any padding bytes.
897 MutableArrayRef<uint8_t> NewData = AlignedMem.take_front(Size);714 MutableArrayRef<uint8_t> newData = alignedMem.take_front(size);
898 AlignedMem = AlignedMem.drop_front(Size);715 alignedMem = alignedMem.drop_front(size);
899 memcpy(NewData.data(), Sym.data().data(), Sym.length());716 memcpy(newData.data(), sym.data().data(), sym.length());
900 memset(NewData.data() + Sym.length(), 0, Size - Sym.length());717 memset(newData.data() + sym.length(), 0, size - sym.length());
901718
902 // Update the record prefix length. It should point to the beginning of the719 // Update the record prefix length. It should point to the beginning of the
903 // next record.720 // next record.
904 auto *Prefix = reinterpret_cast<RecordPrefix *>(NewData.data());721 auto *prefix = reinterpret_cast<RecordPrefix *>(newData.data());
905 Prefix->RecordLen = Size - 2;722 prefix->RecordLen = size - 2;
906 return NewData;723 return newData;
907}724}
908725
909struct ScopeRecord {726struct ScopeRecord {
910 ulittle32_t PtrParent;727 ulittle32_t ptrParent;
911 ulittle32_t PtrEnd;728 ulittle32_t ptrEnd;
912};729};
913730
914struct SymbolScope {731struct SymbolScope {
915 ScopeRecord *OpeningRecord;732 ScopeRecord *openingRecord;
916 uint32_t ScopeOffset;733 uint32_t scopeOffset;
917};734};
918735
919static void scopeStackOpen(SmallVectorImpl<SymbolScope> &Stack,736static void scopeStackOpen(SmallVectorImpl<SymbolScope> &stack,
920 uint32_t CurOffset, CVSymbol &Sym) {737 uint32_t curOffset, CVSymbol &sym) {
921 assert(symbolOpensScope(Sym.kind()));738 assert(symbolOpensScope(sym.kind()));
922 SymbolScope S;739 SymbolScope s;
923 S.ScopeOffset = CurOffset;740 s.scopeOffset = curOffset;
924 S.OpeningRecord = const_cast<ScopeRecord *>(741 s.openingRecord = const_cast<ScopeRecord *>(
925 reinterpret_cast<const ScopeRecord *>(Sym.content().data()));742 reinterpret_cast<const ScopeRecord *>(sym.content().data()));
926 S.OpeningRecord->PtrParent = Stack.empty() ? 0 : Stack.back().ScopeOffset;743 s.openingRecord->ptrParent = stack.empty() ? 0 : stack.back().scopeOffset;
927 Stack.push_back(S);744 stack.push_back(s);
928}745}
929746
930static void scopeStackClose(SmallVectorImpl<SymbolScope> &Stack,747static void scopeStackClose(SmallVectorImpl<SymbolScope> &stack,
931 uint32_t CurOffset, ObjFile *File) {748 uint32_t curOffset, InputFile *file) {
932 if (Stack.empty()) {749 if (stack.empty()) {
933 warn("symbol scopes are not balanced in " + File->getName());750 warn("symbol scopes are not balanced in " + file->getName());
934 return;751 return;
935 }752 }
936 SymbolScope S = Stack.pop_back_val();753 SymbolScope s = stack.pop_back_val();
937 S.OpeningRecord->PtrEnd = CurOffset;754 s.openingRecord->ptrEnd = curOffset;
938}755}
939756
940static bool symbolGoesInModuleStream(const CVSymbol &Sym, bool IsGlobalScope) {757static bool symbolGoesInModuleStream(const CVSymbol &sym, bool isGlobalScope) {
941 switch (Sym.kind()) {758 switch (sym.kind()) {
942 case SymbolKind::S_GDATA32:759 case SymbolKind::S_GDATA32:
943 case SymbolKind::S_CONSTANT:760 case SymbolKind::S_CONSTANT:
944 // We really should not be seeing S_PROCREF and S_LPROCREF in the first place761 // We really should not be seeing S_PROCREF and S_LPROCREF in the first place
...@@ -950,7 +767,7 @@ static bool symbolGoesInModuleStream(const CVSymbol &Sym, bool IsGlobalScope) {...@@ -950,7 +767,7 @@ static bool symbolGoesInModuleStream(const CVSymbol &Sym, bool IsGlobalScope) {
950 return false;767 return false;
951 // S_UDT records go in the module stream if it is not a global S_UDT.768 // S_UDT records go in the module stream if it is not a global S_UDT.
952 case SymbolKind::S_UDT:769 case SymbolKind::S_UDT:
953 return !IsGlobalScope;770 return !isGlobalScope;
954 // S_GDATA32 does not go in the module stream, but S_LDATA32 does.771 // S_GDATA32 does not go in the module stream, but S_LDATA32 does.
955 case SymbolKind::S_LDATA32:772 case SymbolKind::S_LDATA32:
956 default:773 default:
...@@ -958,8 +775,8 @@ static bool symbolGoesInModuleStream(const CVSymbol &Sym, bool IsGlobalScope) {...@@ -958,8 +775,8 @@ static bool symbolGoesInModuleStream(const CVSymbol &Sym, bool IsGlobalScope) {
958 }775 }
959}776}
960777
961static bool symbolGoesInGlobalsStream(const CVSymbol &Sym, bool IsGlobalScope) {778static bool symbolGoesInGlobalsStream(const CVSymbol &sym, bool isGlobalScope) {
962 switch (Sym.kind()) {779 switch (sym.kind()) {
963 case SymbolKind::S_CONSTANT:780 case SymbolKind::S_CONSTANT:
964 case SymbolKind::S_GDATA32:781 case SymbolKind::S_GDATA32:
965 // S_LDATA32 goes in both the module stream and the globals stream.782 // S_LDATA32 goes in both the module stream and the globals stream.
...@@ -974,36 +791,36 @@ static bool symbolGoesInGlobalsStream(const CVSymbol &Sym, bool IsGlobalScope) {...@@ -974,36 +791,36 @@ static bool symbolGoesInGlobalsStream(const CVSymbol &Sym, bool IsGlobalScope) {
974 return true;791 return true;
975 // S_UDT records go in the globals stream if it is a global S_UDT.792 // S_UDT records go in the globals stream if it is a global S_UDT.
976 case SymbolKind::S_UDT:793 case SymbolKind::S_UDT:
977 return IsGlobalScope;794 return isGlobalScope;
978 default:795 default:
979 return false;796 return false;
980 }797 }
981}798}
982799
983static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, uint16_t ModIndex,800static void addGlobalSymbol(pdb::GSIStreamBuilder &builder, uint16_t modIndex,
984 unsigned SymOffset, const CVSymbol &Sym) {801 unsigned symOffset, const CVSymbol &sym) {
985 switch (Sym.kind()) {802 switch (sym.kind()) {
986 case SymbolKind::S_CONSTANT:803 case SymbolKind::S_CONSTANT:
987 case SymbolKind::S_UDT:804 case SymbolKind::S_UDT:
988 case SymbolKind::S_GDATA32:805 case SymbolKind::S_GDATA32:
989 case SymbolKind::S_LDATA32:806 case SymbolKind::S_LDATA32:
990 case SymbolKind::S_PROCREF:807 case SymbolKind::S_PROCREF:
991 case SymbolKind::S_LPROCREF:808 case SymbolKind::S_LPROCREF:
992 Builder.addGlobalSymbol(Sym);809 builder.addGlobalSymbol(sym);
993 break;810 break;
994 case SymbolKind::S_GPROC32:811 case SymbolKind::S_GPROC32:
995 case SymbolKind::S_LPROC32: {812 case SymbolKind::S_LPROC32: {
996 SymbolRecordKind K = SymbolRecordKind::ProcRefSym;813 SymbolRecordKind k = SymbolRecordKind::ProcRefSym;
997 if (Sym.kind() == SymbolKind::S_LPROC32)814 if (sym.kind() == SymbolKind::S_LPROC32)
998 K = SymbolRecordKind::LocalProcRef;815 k = SymbolRecordKind::LocalProcRef;
999 ProcRefSym PS(K);816 ProcRefSym ps(k);
1000 PS.Module = ModIndex;817 ps.Module = modIndex;
1001 // For some reason, MSVC seems to add one to this value.818 // For some reason, MSVC seems to add one to this value.
1002 ++PS.Module;819 ++ps.Module;
1003 PS.Name = getSymbolName(Sym);820 ps.Name = getSymbolName(sym);
1004 PS.SumName = 0;821 ps.SumName = 0;
1005 PS.SymOffset = SymOffset;822 ps.SymOffset = symOffset;
1006 Builder.addGlobalSymbol(PS);823 builder.addGlobalSymbol(ps);
1007 break;824 break;
1008 }825 }
1009 default:826 default:
...@@ -1011,229 +828,304 @@ static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, uint16_t ModIndex,...@@ -1011,229 +828,304 @@ static void addGlobalSymbol(pdb::GSIStreamBuilder &Builder, uint16_t ModIndex,
1011 }828 }
1012}829}
1013830
1014void PDBLinker::mergeSymbolRecords(ObjFile *File, const CVIndexMap &IndexMap,831void PDBLinker::mergeSymbolRecords(ObjFile *file, const CVIndexMap &indexMap,
1015 std::vector<ulittle32_t *> &StringTableRefs,832 std::vector<ulittle32_t *> &stringTableRefs,
1016 BinaryStreamRef SymData) {833 BinaryStreamRef symData) {
1017 ArrayRef<uint8_t> SymsBuffer;834 ArrayRef<uint8_t> symsBuffer;
1018 cantFail(SymData.readBytes(0, SymData.getLength(), SymsBuffer));835 cantFail(symData.readBytes(0, symData.getLength(), symsBuffer));
1019 SmallVector<SymbolScope, 4> Scopes;836 SmallVector<SymbolScope, 4> scopes;
1020837
1021 // Iterate every symbol to check if any need to be realigned, and if so, how838 // Iterate every symbol to check if any need to be realigned, and if so, how
1022 // much space we need to allocate for them.839 // much space we need to allocate for them.
1023 bool NeedsRealignment = false;840 bool needsRealignment = false;
1024 unsigned TotalRealignedSize = 0;841 unsigned totalRealignedSize = 0;
1025 auto EC = forEachCodeViewRecord<CVSymbol>(842 auto ec = forEachCodeViewRecord<CVSymbol>(
1026 SymsBuffer, [&](CVSymbol Sym) -> llvm::Error {843 symsBuffer, [&](CVSymbol sym) -> llvm::Error {
1027 unsigned RealignedSize =844 unsigned realignedSize =
1028 alignTo(Sym.length(), alignOf(CodeViewContainer::Pdb));845 alignTo(sym.length(), alignOf(CodeViewContainer::Pdb));
1029 NeedsRealignment |= RealignedSize != Sym.length();846 needsRealignment |= realignedSize != sym.length();
1030 TotalRealignedSize += RealignedSize;847 totalRealignedSize += realignedSize;
1031 return Error::success();848 return Error::success();
1032 });849 });
1033850
1034 // If any of the symbol record lengths was corrupt, ignore them all, warn851 // If any of the symbol record lengths was corrupt, ignore them all, warn
1035 // about it, and move on.852 // about it, and move on.
1036 if (EC) {853 if (ec) {
1037 warn("corrupt symbol records in " + File->getName());854 warn("corrupt symbol records in " + file->getName());
1038 consumeError(std::move(EC));855 consumeError(std::move(ec));
1039 return;856 return;
1040 }857 }
1041858
1042 // If any symbol needed realignment, allocate enough contiguous memory for859 // If any symbol needed realignment, allocate enough contiguous memory for
1043 // them all. Typically symbol subsections are small enough that this will not860 // them all. Typically symbol subsections are small enough that this will not
1044 // cause fragmentation.861 // cause fragmentation.
1045 MutableArrayRef<uint8_t> AlignedSymbolMem;862 MutableArrayRef<uint8_t> alignedSymbolMem;
1046 if (NeedsRealignment) {863 if (needsRealignment) {
1047 void *AlignedData =864 void *alignedData =
1048 Alloc.Allocate(TotalRealignedSize, alignOf(CodeViewContainer::Pdb));865 alloc.Allocate(totalRealignedSize, alignOf(CodeViewContainer::Pdb));
1049 AlignedSymbolMem = makeMutableArrayRef(866 alignedSymbolMem = makeMutableArrayRef(
1050 reinterpret_cast<uint8_t *>(AlignedData), TotalRealignedSize);867 reinterpret_cast<uint8_t *>(alignedData), totalRealignedSize);
1051 }868 }
1052869
1053 // Iterate again, this time doing the real work.870 // Iterate again, this time doing the real work.
1054 unsigned CurSymOffset = File->ModuleDBI->getNextSymbolOffset();871 unsigned curSymOffset = file->moduleDBI->getNextSymbolOffset();
1055 ArrayRef<uint8_t> BulkSymbols;872 ArrayRef<uint8_t> bulkSymbols;
1056 cantFail(forEachCodeViewRecord<CVSymbol>(873 cantFail(forEachCodeViewRecord<CVSymbol>(
1057 SymsBuffer, [&](CVSymbol Sym) -> llvm::Error {874 symsBuffer, [&](CVSymbol sym) -> llvm::Error {
1058 // Align the record if required.875 // Align the record if required.
1059 MutableArrayRef<uint8_t> RecordBytes;876 MutableArrayRef<uint8_t> recordBytes;
1060 if (NeedsRealignment) {877 if (needsRealignment) {
1061 RecordBytes = copyAndAlignSymbol(Sym, AlignedSymbolMem);878 recordBytes = copyAndAlignSymbol(sym, alignedSymbolMem);
1062 Sym = CVSymbol(Sym.kind(), RecordBytes);879 sym = CVSymbol(recordBytes);
1063 } else {880 } else {
1064 // Otherwise, we can actually mutate the symbol directly, since we881 // Otherwise, we can actually mutate the symbol directly, since we
1065 // copied it to apply relocations.882 // copied it to apply relocations.
1066 RecordBytes = makeMutableArrayRef(883 recordBytes = makeMutableArrayRef(
1067 const_cast<uint8_t *>(Sym.data().data()), Sym.length());884 const_cast<uint8_t *>(sym.data().data()), sym.length());
1068 }885 }
1069886
1070 // Discover type index references in the record. Skip it if we don't887 // Discover type index references in the record. Skip it if we don't
1071 // know where they are.888 // know where they are.
1072 SmallVector<TiReference, 32> TypeRefs;889 SmallVector<TiReference, 32> typeRefs;
1073 if (!discoverTypeIndicesInSymbol(Sym, TypeRefs)) {890 if (!discoverTypeIndicesInSymbol(sym, typeRefs)) {
1074 log("ignoring unknown symbol record with kind 0x" +891 log("ignoring unknown symbol record with kind 0x" +
1075 utohexstr(Sym.kind()));892 utohexstr(sym.kind()));
1076 return Error::success();893 return Error::success();
1077 }894 }
1078895
1079 // Re-map all the type index references.896 // Re-map all the type index references.
1080 remapTypesInSymbolRecord(File, Sym.kind(), RecordBytes, IndexMap,897 remapTypesInSymbolRecord(file, sym.kind(), recordBytes, indexMap,
1081 TypeRefs);898 typeRefs);
1082899
1083 // An object file may have S_xxx_ID symbols, but these get converted to900 // An object file may have S_xxx_ID symbols, but these get converted to
1084 // "real" symbols in a PDB.901 // "real" symbols in a PDB.
1085 translateIdSymbols(RecordBytes, getIDTable());902 translateIdSymbols(recordBytes, tMerger.getIDTable());
1086 Sym = CVSymbol(symbolKind(RecordBytes), RecordBytes);903 sym = CVSymbol(recordBytes);
1087904
1088 // If this record refers to an offset in the object file's string table,905 // If this record refers to an offset in the object file's string table,
1089 // add that item to the global PDB string table and re-write the index.906 // add that item to the global PDB string table and re-write the index.
1090 recordStringTableReferences(Sym.kind(), RecordBytes, StringTableRefs);907 recordStringTableReferences(sym.kind(), recordBytes, stringTableRefs);
1091908
1092 // Fill in "Parent" and "End" fields by maintaining a stack of scopes.909 // Fill in "Parent" and "End" fields by maintaining a stack of scopes.
1093 if (symbolOpensScope(Sym.kind()))910 if (symbolOpensScope(sym.kind()))
1094 scopeStackOpen(Scopes, CurSymOffset, Sym);911 scopeStackOpen(scopes, curSymOffset, sym);
1095 else if (symbolEndsScope(Sym.kind()))912 else if (symbolEndsScope(sym.kind()))
1096 scopeStackClose(Scopes, CurSymOffset, File);913 scopeStackClose(scopes, curSymOffset, file);
1097914
1098 // Add the symbol to the globals stream if necessary. Do this before915 // Add the symbol to the globals stream if necessary. Do this before
1099 // adding the symbol to the module since we may need to get the next916 // adding the symbol to the module since we may need to get the next
1100 // symbol offset, and writing to the module's symbol stream will update917 // symbol offset, and writing to the module's symbol stream will update
1101 // that offset.918 // that offset.
1102 if (symbolGoesInGlobalsStream(Sym, Scopes.empty()))919 if (symbolGoesInGlobalsStream(sym, scopes.empty())) {
1103 addGlobalSymbol(Builder.getGsiBuilder(),920 addGlobalSymbol(builder.getGsiBuilder(),
1104 File->ModuleDBI->getModuleIndex(), CurSymOffset, Sym);921 file->moduleDBI->getModuleIndex(), curSymOffset, sym);
922 ++globalSymbols;
923 }
1105924
1106 if (symbolGoesInModuleStream(Sym, Scopes.empty())) {925 if (symbolGoesInModuleStream(sym, scopes.empty())) {
1107 // Add symbols to the module in bulk. If this symbol is contiguous926 // Add symbols to the module in bulk. If this symbol is contiguous
1108 // with the previous run of symbols to add, combine the ranges. If927 // 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.928 // not, close the previous range of symbols and start a new one.
1110 if (Sym.data().data() == BulkSymbols.end()) {929 if (sym.data().data() == bulkSymbols.end()) {
1111 BulkSymbols = makeArrayRef(BulkSymbols.data(),930 bulkSymbols = makeArrayRef(bulkSymbols.data(),
1112 BulkSymbols.size() + Sym.length());931 bulkSymbols.size() + sym.length());
1113 } else {932 } else {
1114 File->ModuleDBI->addSymbolsInBulk(BulkSymbols);933 file->moduleDBI->addSymbolsInBulk(bulkSymbols);
1115 BulkSymbols = RecordBytes;934 bulkSymbols = recordBytes;
1116 }935 }
1117 CurSymOffset += Sym.length();936 curSymOffset += sym.length();
937 ++moduleSymbols;
1118 }938 }
1119 return Error::success();939 return Error::success();
1120 }));940 }));
1121941
1122 // Add any remaining symbols we've accumulated.942 // Add any remaining symbols we've accumulated.
1123 File->ModuleDBI->addSymbolsInBulk(BulkSymbols);943 file->moduleDBI->addSymbolsInBulk(bulkSymbols);
1124}944}
1125945
1126// Allocate memory for a .debug$S / .debug$F section and relocate it.946// Allocate memory for a .debug$S / .debug$F section and relocate it.
1127static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &Alloc,947static ArrayRef<uint8_t> relocateDebugChunk(BumpPtrAllocator &alloc,
1128 SectionChunk &DebugChunk) {948 SectionChunk &debugChunk) {
1129 uint8_t *Buffer = Alloc.Allocate<uint8_t>(DebugChunk.getSize());949 uint8_t *buffer = alloc.Allocate<uint8_t>(debugChunk.getSize());
1130 assert(DebugChunk.OutputSectionOff == 0 &&950 assert(debugChunk.getOutputSectionIdx() == 0 &&
1131 "debug sections should not be in output sections");951 "debug sections should not be in output sections");
1132 DebugChunk.readRelocTargets();952 debugChunk.writeTo(buffer);
1133 DebugChunk.writeTo(Buffer);953 return makeArrayRef(buffer, debugChunk.getSize());
1134 return makeArrayRef(Buffer, DebugChunk.getSize());
1135}954}
1136955
1137static pdb::SectionContrib createSectionContrib(const Chunk *C, uint32_t Modi) {956static pdb::SectionContrib createSectionContrib(const Chunk *c, uint32_t modi) {
1138 OutputSection *OS = C->getOutputSection();957 OutputSection *os = c ? c->getOutputSection() : nullptr;
1139 pdb::SectionContrib SC;958 pdb::SectionContrib sc;
1140 memset(&SC, 0, sizeof(SC));959 memset(&sc, 0, sizeof(sc));
1141 SC.ISect = OS->SectionIndex;960 sc.ISect = os ? os->sectionIndex : llvm::pdb::kInvalidStreamIndex;
1142 SC.Off = C->getRVA() - OS->getRVA();961 sc.Off = c && os ? c->getRVA() - os->getRVA() : 0;
1143 SC.Size = C->getSize();962 sc.Size = c ? c->getSize() : -1;
1144 if (auto *SecChunk = dyn_cast<SectionChunk>(C)) {963 if (auto *secChunk = dyn_cast_or_null<SectionChunk>(c)) {
1145 SC.Characteristics = SecChunk->Header->Characteristics;964 sc.Characteristics = secChunk->header->Characteristics;
1146 SC.Imod = SecChunk->File->ModuleDBI->getModuleIndex();965 sc.Imod = secChunk->file->moduleDBI->getModuleIndex();
1147 ArrayRef<uint8_t> Contents = SecChunk->getContents();966 ArrayRef<uint8_t> contents = secChunk->getContents();
1148 JamCRC CRC(0);967 JamCRC crc(0);
1149 ArrayRef<char> CharContents = makeArrayRef(968 ArrayRef<char> charContents = makeArrayRef(
1150 reinterpret_cast<const char *>(Contents.data()), Contents.size());969 reinterpret_cast<const char *>(contents.data()), contents.size());
1151 CRC.update(CharContents);970 crc.update(charContents);
1152 SC.DataCrc = CRC.getCRC();971 sc.DataCrc = crc.getCRC();
1153 } else {972 } else {
1154 SC.Characteristics = OS->Header.Characteristics;973 sc.Characteristics = os ? os->header.Characteristics : 0;
1155 // FIXME: When we start creating DBI for import libraries, use those here.974 sc.Imod = modi;
1156 SC.Imod = Modi;
1157 }975 }
1158 SC.RelocCrc = 0; // FIXME976 sc.RelocCrc = 0; // FIXME
1159977
1160 return SC;978 return sc;
1161}979}
1162980
1163static uint32_t981static uint32_t
1164translateStringTableIndex(uint32_t ObjIndex,982translateStringTableIndex(uint32_t objIndex,
1165 const DebugStringTableSubsectionRef &ObjStrTable,983 const DebugStringTableSubsectionRef &objStrTable,
1166 DebugStringTableSubsection &PdbStrTable) {984 DebugStringTableSubsection &pdbStrTable) {
1167 auto ExpectedString = ObjStrTable.getString(ObjIndex);985 auto expectedString = objStrTable.getString(objIndex);
1168 if (!ExpectedString) {986 if (!expectedString) {
1169 warn("Invalid string table reference");987 warn("Invalid string table reference");
1170 consumeError(ExpectedString.takeError());988 consumeError(expectedString.takeError());
1171 return 0;989 return 0;
1172 }990 }
1173991
1174 return PdbStrTable.insert(*ExpectedString);992 return pdbStrTable.insert(*expectedString);
1175}993}
1176994
1177void DebugSHandler::handleDebugS(lld::coff::SectionChunk &DebugS) {995void DebugSHandler::handleDebugS(lld::coff::SectionChunk &debugS) {
1178 DebugSubsectionArray Subsections;996 DebugSubsectionArray subsections;
997
998 ArrayRef<uint8_t> relocatedDebugContents = SectionChunk::consumeDebugMagic(
999 relocateDebugChunk(linker.alloc, debugS), debugS.getSectionName());
11791000
1180 ArrayRef<uint8_t> RelocatedDebugContents = consumeDebugMagic(1001 BinaryStreamReader reader(relocatedDebugContents, support::little);
1181 relocateDebugChunk(Linker.Alloc, DebugS), DebugS.getSectionName());1002 exitOnErr(reader.readArray(subsections, relocatedDebugContents.size()));
11821003
1183 BinaryStreamReader Reader(RelocatedDebugContents, support::little);1004 for (const DebugSubsectionRecord &ss : subsections) {
1184 ExitOnErr(Reader.readArray(Subsections, RelocatedDebugContents.size()));1005 // Ignore subsections with the 'ignore' bit. Some versions of the Visual C++
1006 // runtime have subsections with this bit set.
1007 if (uint32_t(ss.kind()) & codeview::SubsectionIgnoreFlag)
1008 continue;
11851009
1186 for (const DebugSubsectionRecord &SS : Subsections) {1010 switch (ss.kind()) {
1187 switch (SS.kind()) {
1188 case DebugSubsectionKind::StringTable: {1011 case DebugSubsectionKind::StringTable: {
1189 assert(!CVStrTab.valid() &&1012 assert(!cVStrTab.valid() &&
1190 "Encountered multiple string table subsections!");1013 "Encountered multiple string table subsections!");
1191 ExitOnErr(CVStrTab.initialize(SS.getRecordData()));1014 exitOnErr(cVStrTab.initialize(ss.getRecordData()));
1192 break;1015 break;
1193 }1016 }
1194 case DebugSubsectionKind::FileChecksums:1017 case DebugSubsectionKind::FileChecksums:
1195 assert(!Checksums.valid() &&1018 assert(!checksums.valid() &&
1196 "Encountered multiple checksum subsections!");1019 "Encountered multiple checksum subsections!");
1197 ExitOnErr(Checksums.initialize(SS.getRecordData()));1020 exitOnErr(checksums.initialize(ss.getRecordData()));
1198 break;1021 break;
1199 case DebugSubsectionKind::Lines:1022 case DebugSubsectionKind::Lines:
1200 // We can add the relocated line table directly to the PDB without1023 // We can add the relocated line table directly to the PDB without
1201 // modification because the file checksum offsets will stay the same.1024 // modification because the file checksum offsets will stay the same.
1202 File.ModuleDBI->addDebugSubsection(SS);1025 file.moduleDBI->addDebugSubsection(ss);
1026 break;
1027 case DebugSubsectionKind::InlineeLines:
1028 assert(!inlineeLines.valid() &&
1029 "Encountered multiple inlinee lines subsections!");
1030 exitOnErr(inlineeLines.initialize(ss.getRecordData()));
1203 break;1031 break;
1204 case DebugSubsectionKind::FrameData: {1032 case DebugSubsectionKind::FrameData: {
1205 // We need to re-write string table indices here, so save off all1033 // We need to re-write string table indices here, so save off all
1206 // frame data subsections until we've processed the entire list of1034 // frame data subsections until we've processed the entire list of
1207 // subsections so that we can be sure we have the string table.1035 // subsections so that we can be sure we have the string table.
1208 DebugFrameDataSubsectionRef FDS;1036 DebugFrameDataSubsectionRef fds;
1209 ExitOnErr(FDS.initialize(SS.getRecordData()));1037 exitOnErr(fds.initialize(ss.getRecordData()));
1210 NewFpoFrames.push_back(std::move(FDS));1038 newFpoFrames.push_back(std::move(fds));
1211 break;1039 break;
1212 }1040 }
1213 case DebugSubsectionKind::Symbols: {1041 case DebugSubsectionKind::Symbols: {
1214 Linker.mergeSymbolRecords(&File, IndexMap, StringTableReferences,1042 linker.mergeSymbolRecords(&file, indexMap, stringTableReferences,
1215 SS.getRecordData());1043 ss.getRecordData());
1216 break;1044 break;
1217 }1045 }
1046
1047 case DebugSubsectionKind::CrossScopeImports:
1048 case DebugSubsectionKind::CrossScopeExports:
1049 // These appear to relate to cross-module optimization, so we might use
1050 // these for ThinLTO.
1051 break;
1052
1053 case DebugSubsectionKind::ILLines:
1054 case DebugSubsectionKind::FuncMDTokenMap:
1055 case DebugSubsectionKind::TypeMDTokenMap:
1056 case DebugSubsectionKind::MergedAssemblyInput:
1057 // These appear to relate to .Net assembly info.
1058 break;
1059
1060 case DebugSubsectionKind::CoffSymbolRVA:
1061 // Unclear what this is for.
1062 break;
1063
1218 default:1064 default:
1219 // FIXME: Process the rest of the subsections.1065 warn("ignoring unknown debug$S subsection kind 0x" +
1066 utohexstr(uint32_t(ss.kind())) + " in file " + toString(&file));
1220 break;1067 break;
1221 }1068 }
1222 }1069 }
1223}1070}
12241071
1072static Expected<StringRef>
1073getFileName(const DebugStringTableSubsectionRef &strings,
1074 const DebugChecksumsSubsectionRef &checksums, uint32_t fileID) {
1075 auto iter = checksums.getArray().at(fileID);
1076 if (iter == checksums.getArray().end())
1077 return make_error<CodeViewError>(cv_error_code::no_records);
1078 uint32_t offset = iter->FileNameOffset;
1079 return strings.getString(offset);
1080}
1081
1082std::shared_ptr<DebugInlineeLinesSubsection>
1083DebugSHandler::mergeInlineeLines(DebugChecksumsSubsection *newChecksums) {
1084 auto newInlineeLines = std::make_shared<DebugInlineeLinesSubsection>(
1085 *newChecksums, inlineeLines.hasExtraFiles());
1086
1087 for (const InlineeSourceLine &line : inlineeLines) {
1088 TypeIndex inlinee = line.Header->Inlinee;
1089 uint32_t fileID = line.Header->FileID;
1090 uint32_t sourceLine = line.Header->SourceLineNum;
1091
1092 ArrayRef<TypeIndex> typeOrItemMap =
1093 indexMap.isTypeServerMap ? indexMap.ipiMap : indexMap.tpiMap;
1094 if (!remapTypeIndex(inlinee, typeOrItemMap)) {
1095 log("ignoring inlinee line record in " + file.getName() +
1096 " with bad inlinee index 0x" + utohexstr(inlinee.getIndex()));
1097 continue;
1098 }
1099
1100 SmallString<128> filename =
1101 exitOnErr(getFileName(cVStrTab, checksums, fileID));
1102 pdbMakeAbsolute(filename);
1103 newInlineeLines->addInlineSite(inlinee, filename, sourceLine);
1104
1105 if (inlineeLines.hasExtraFiles()) {
1106 for (uint32_t extraFileId : line.ExtraFiles) {
1107 filename = exitOnErr(getFileName(cVStrTab, checksums, extraFileId));
1108 pdbMakeAbsolute(filename);
1109 newInlineeLines->addExtraFile(filename);
1110 }
1111 }
1112 }
1113
1114 return newInlineeLines;
1115}
1116
1225void DebugSHandler::finish() {1117void DebugSHandler::finish() {
1226 pdb::DbiStreamBuilder &DbiBuilder = Linker.Builder.getDbiBuilder();1118 pdb::DbiStreamBuilder &dbiBuilder = linker.builder.getDbiBuilder();
12271119
1228 // We should have seen all debug subsections across the entire object file now1120 // We should have seen all debug subsections across the entire object file now
1229 // which means that if a StringTable subsection and Checksums subsection were1121 // which means that if a StringTable subsection and Checksums subsection were
1230 // present, now is the time to handle them.1122 // present, now is the time to handle them.
1231 if (!CVStrTab.valid()) {1123 if (!cVStrTab.valid()) {
1232 if (Checksums.valid())1124 if (checksums.valid())
1233 fatal(".debug$S sections with a checksums subsection must also contain a "1125 fatal(".debug$S sections with a checksums subsection must also contain a "
1234 "string table subsection");1126 "string table subsection");
12351127
1236 if (!StringTableReferences.empty())1128 if (!stringTableReferences.empty())
1237 warn("No StringTable subsection was encountered, but there are string "1129 warn("No StringTable subsection was encountered, but there are string "
1238 "table references");1130 "table references");
1239 return;1131 return;
...@@ -1241,186 +1133,231 @@ void DebugSHandler::finish() {...@@ -1241,186 +1133,231 @@ void DebugSHandler::finish() {
12411133
1242 // Rewrite string table indices in the Fpo Data and symbol records to refer to1134 // 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.1135 // the global PDB string table instead of the object file string table.
1244 for (DebugFrameDataSubsectionRef &FDS : NewFpoFrames) {1136 for (DebugFrameDataSubsectionRef &fds : newFpoFrames) {
1245 const ulittle32_t *Reloc = FDS.getRelocPtr();1137 const ulittle32_t *reloc = fds.getRelocPtr();
1246 for (codeview::FrameData FD : FDS) {1138 for (codeview::FrameData fd : fds) {
1247 FD.RvaStart += *Reloc;1139 fd.RvaStart += *reloc;
1248 FD.FrameFunc =1140 fd.FrameFunc =
1249 translateStringTableIndex(FD.FrameFunc, CVStrTab, Linker.PDBStrTab);1141 translateStringTableIndex(fd.FrameFunc, cVStrTab, linker.pdbStrTab);
1250 DbiBuilder.addNewFpoData(FD);1142 dbiBuilder.addNewFpoData(fd);
1251 }1143 }
1252 }1144 }
12531145
1254 for (ulittle32_t *Ref : StringTableReferences)1146 for (ulittle32_t *ref : stringTableReferences)
1255 *Ref = translateStringTableIndex(*Ref, CVStrTab, Linker.PDBStrTab);1147 *ref = translateStringTableIndex(*ref, cVStrTab, linker.pdbStrTab);
12561148
1257 // Make a new file checksum table that refers to offsets in the PDB-wide1149 // Make a new file checksum table that refers to offsets in the PDB-wide
1258 // string table. Generally the string table subsection appears after the1150 // string table. Generally the string table subsection appears after the
1259 // checksum table, so we have to do this after looping over all the1151 // checksum table, so we have to do this after looping over all the
1260 // subsections.1152 // subsections.
1261 auto NewChecksums = make_unique<DebugChecksumsSubsection>(Linker.PDBStrTab);1153 auto newChecksums = make_unique<DebugChecksumsSubsection>(linker.pdbStrTab);
1262 for (FileChecksumEntry &FC : Checksums) {1154 for (FileChecksumEntry &fc : checksums) {
1263 SmallString<128> FileName =1155 SmallString<128> filename =
1264 ExitOnErr(CVStrTab.getString(FC.FileNameOffset));1156 exitOnErr(cVStrTab.getString(fc.FileNameOffset));
1265 pdbMakeAbsolute(FileName);1157 pdbMakeAbsolute(filename);
1266 ExitOnErr(Linker.Builder.getDbiBuilder().addModuleSourceFile(1158 exitOnErr(dbiBuilder.addModuleSourceFile(*file.moduleDBI, filename));
1267 *File.ModuleDBI, FileName));1159 newChecksums->addChecksum(filename, fc.Kind, fc.Checksum);
1268 NewChecksums->addChecksum(FileName, FC.Kind, FC.Checksum);
1269 }1160 }
1270 File.ModuleDBI->addDebugSubsection(std::move(NewChecksums));1161
1162 // Rewrite inlinee item indices if present.
1163 if (inlineeLines.valid())
1164 file.moduleDBI->addDebugSubsection(mergeInlineeLines(newChecksums.get()));
1165
1166 file.moduleDBI->addDebugSubsection(std::move(newChecksums));
1271}1167}
12721168
1273void PDBLinker::addObjFile(ObjFile *File, CVIndexMap *ExternIndexMap) {1169void PDBLinker::addObjFile(ObjFile *file, CVIndexMap *externIndexMap) {
1274 if (File->wasProcessedForPDB())1170 if (file->mergedIntoPDB)
1275 return;1171 return;
1276 // Add a module descriptor for every object file. We need to put an absolute1172 file->mergedIntoPDB = true;
1277 // path to the object into the PDB. If this is a plain object, we make its
1278 // path absolute. If it's an object in an archive, we make the archive path
1279 // absolute.
1280 bool InArchive = !File->ParentName.empty();
1281 SmallString<128> Path = InArchive ? File->ParentName : File->getName();
1282 pdbMakeAbsolute(Path);
1283 StringRef Name = InArchive ? File->getName() : StringRef(Path);
1284
1285 pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();
1286 File->ModuleDBI = &ExitOnErr(DbiBuilder.addModuleInfo(Name));
1287 File->ModuleDBI->setObjFileName(Path);
1288
1289 auto Chunks = File->getChunks();
1290 uint32_t Modi = File->ModuleDBI->getModuleIndex();
1291 for (Chunk *C : Chunks) {
1292 auto *SecChunk = dyn_cast<SectionChunk>(C);
1293 if (!SecChunk || !SecChunk->Live)
1294 continue;
1295 pdb::SectionContrib SC = createSectionContrib(SecChunk, Modi);
1296 File->ModuleDBI->setFirstSectionContrib(SC);
1297 break;
1298 }
12991173
1300 // Before we can process symbol substreams from .debug$S, we need to process1174 // Before we can process symbol substreams from .debug$S, we need to process
1301 // type information, file checksums, and the string table. Add type info to1175 // type information, file checksums, and the string table. Add type info to
1302 // the PDB first, so that we can get the map from object file type and item1176 // the PDB first, so that we can get the map from object file type and item
1303 // indices to PDB type and item indices.1177 // indices to PDB type and item indices.
1304 CVIndexMap ObjectIndexMap;1178 CVIndexMap objectIndexMap;
1305 auto IndexMapResult =1179 auto indexMapResult =
1306 mergeDebugT(File, ExternIndexMap ? ExternIndexMap : &ObjectIndexMap);1180 mergeDebugT(file, externIndexMap ? externIndexMap : &objectIndexMap);
13071181
1308 // If the .debug$T sections fail to merge, assume there is no debug info.1182 // If the .debug$T sections fail to merge, assume there is no debug info.
1309 if (!IndexMapResult) {1183 if (!indexMapResult) {
1310 if (!Config->WarnDebugInfoUnusable) {1184 if (!config->warnDebugInfoUnusable) {
1311 consumeError(IndexMapResult.takeError());1185 consumeError(indexMapResult.takeError());
1312 return;1186 return;
1313 }1187 }
1314 StringRef FileName = sys::path::filename(Path);1188 warn("Cannot use debug info for '" + toString(file) + "' [LNK4099]\n" +
1315 warn("Cannot use debug info for '" + FileName + "' [LNK4099]\n" +
1316 ">>> failed to load reference " +1189 ">>> failed to load reference " +
1317 StringRef(toString(IndexMapResult.takeError())));1190 StringRef(toString(indexMapResult.takeError())));
1318 return;1191 return;
1319 }1192 }
13201193
1321 ScopedTimer T(SymbolMergingTimer);1194 ScopedTimer t(symbolMergingTimer);
13221195
1323 DebugSHandler DSH(*this, *File, *IndexMapResult);1196 pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
1197 DebugSHandler dsh(*this, *file, *indexMapResult);
1324 // Now do all live .debug$S and .debug$F sections.1198 // Now do all live .debug$S and .debug$F sections.
1325 for (SectionChunk *DebugChunk : File->getDebugChunks()) {1199 for (SectionChunk *debugChunk : file->getDebugChunks()) {
1326 if (!DebugChunk->Live || DebugChunk->getSize() == 0)1200 if (!debugChunk->live || debugChunk->getSize() == 0)
1327 continue;1201 continue;
13281202
1329 if (DebugChunk->getSectionName() == ".debug$S") {1203 if (debugChunk->getSectionName() == ".debug$S") {
1330 DSH.handleDebugS(*DebugChunk);1204 dsh.handleDebugS(*debugChunk);
1331 continue;1205 continue;
1332 }1206 }
13331207
1334 if (DebugChunk->getSectionName() == ".debug$F") {1208 if (debugChunk->getSectionName() == ".debug$F") {
1335 ArrayRef<uint8_t> RelocatedDebugContents =1209 ArrayRef<uint8_t> relocatedDebugContents =
1336 relocateDebugChunk(Alloc, *DebugChunk);1210 relocateDebugChunk(alloc, *debugChunk);
13371211
1338 FixedStreamArray<object::FpoData> FpoRecords;1212 FixedStreamArray<object::FpoData> fpoRecords;
1339 BinaryStreamReader Reader(RelocatedDebugContents, support::little);1213 BinaryStreamReader reader(relocatedDebugContents, support::little);
1340 uint32_t Count = RelocatedDebugContents.size() / sizeof(object::FpoData);1214 uint32_t count = relocatedDebugContents.size() / sizeof(object::FpoData);
1341 ExitOnErr(Reader.readArray(FpoRecords, Count));1215 exitOnErr(reader.readArray(fpoRecords, count));
13421216
1343 // These are already relocated and don't refer to the string table, so we1217 // These are already relocated and don't refer to the string table, so we
1344 // can just copy it.1218 // can just copy it.
1345 for (const object::FpoData &FD : FpoRecords)1219 for (const object::FpoData &fd : fpoRecords)
1346 DbiBuilder.addOldFpoData(FD);1220 dbiBuilder.addOldFpoData(fd);
1347 continue;1221 continue;
1348 }1222 }
1349 }1223 }
13501224
1351 // Do any post-processing now that all .debug$S sections have been processed.1225 // Do any post-processing now that all .debug$S sections have been processed.
1352 DSH.finish();1226 dsh.finish();
1353}1227}
13541228
1355static PublicSym32 createPublic(Defined *Def) {1229// Add a module descriptor for every object file. We need to put an absolute
1356 PublicSym32 Pub(SymbolKind::S_PUB32);1230// path to the object into the PDB. If this is a plain object, we make its
1357 Pub.Name = Def->getName();1231// path absolute. If it's an object in an archive, we make the archive path
1358 if (auto *D = dyn_cast<DefinedCOFF>(Def)) {1232// absolute.
1359 if (D->getCOFFSymbol().isFunctionDefinition())1233static void createModuleDBI(pdb::PDBFileBuilder &builder) {
1360 Pub.Flags = PublicSymFlags::Function;1234 pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
1361 } else if (isa<DefinedImportThunk>(Def)) {1235 SmallString<128> objName;
1362 Pub.Flags = PublicSymFlags::Function;1236
1237 for (ObjFile *file : ObjFile::instances) {
1238
1239 bool inArchive = !file->parentName.empty();
1240 objName = inArchive ? file->parentName : file->getName();
1241 pdbMakeAbsolute(objName);
1242 StringRef modName = inArchive ? file->getName() : StringRef(objName);
1243
1244 file->moduleDBI = &exitOnErr(dbiBuilder.addModuleInfo(modName));
1245 file->moduleDBI->setObjFileName(objName);
1246
1247 ArrayRef<Chunk *> chunks = file->getChunks();
1248 uint32_t modi = file->moduleDBI->getModuleIndex();
1249
1250 for (Chunk *c : chunks) {
1251 auto *secChunk = dyn_cast<SectionChunk>(c);
1252 if (!secChunk || !secChunk->live)
1253 continue;
1254 pdb::SectionContrib sc = createSectionContrib(secChunk, modi);
1255 file->moduleDBI->setFirstSectionContrib(sc);
1256 break;
1257 }
1363 }1258 }
1259}
13641260
1365 OutputSection *OS = Def->getChunk()->getOutputSection();1261static PublicSym32 createPublic(Defined *def) {
1366 assert(OS && "all publics should be in final image");1262 PublicSym32 pub(SymbolKind::S_PUB32);
1367 Pub.Offset = Def->getRVA() - OS->getRVA();1263 pub.Name = def->getName();
1368 Pub.Segment = OS->SectionIndex;1264 if (auto *d = dyn_cast<DefinedCOFF>(def)) {
1369 return Pub;1265 if (d->getCOFFSymbol().isFunctionDefinition())
1266 pub.Flags = PublicSymFlags::Function;
1267 } else if (isa<DefinedImportThunk>(def)) {
1268 pub.Flags = PublicSymFlags::Function;
1269 }
1270
1271 OutputSection *os = def->getChunk()->getOutputSection();
1272 assert(os && "all publics should be in final image");
1273 pub.Offset = def->getRVA() - os->getRVA();
1274 pub.Segment = os->sectionIndex;
1275 return pub;
1370}1276}
13711277
1372// Add all object files to the PDB. Merge .debug$T sections into IpiData and1278// Add all object files to the PDB. Merge .debug$T sections into IpiData and
1373// TpiData.1279// TpiData.
1374void PDBLinker::addObjectsToPDB() {1280void PDBLinker::addObjectsToPDB() {
1375 ScopedTimer T1(AddObjectsTimer);1281 ScopedTimer t1(addObjectsTimer);
1376 for (ObjFile *File : ObjFile::Instances)1282
1377 addObjFile(File);1283 createModuleDBI(builder);
13781284
1379 Builder.getStringTableBuilder().setStrings(PDBStrTab);1285 for (ObjFile *file : ObjFile::instances)
1380 T1.stop();1286 addObjFile(file);
1287
1288 builder.getStringTableBuilder().setStrings(pdbStrTab);
1289 t1.stop();
13811290
1382 // Construct TPI and IPI stream contents.1291 // Construct TPI and IPI stream contents.
1383 ScopedTimer T2(TpiStreamLayoutTimer);1292 ScopedTimer t2(tpiStreamLayoutTimer);
1384 addTypeInfo(Builder.getTpiBuilder(), getTypeTable());1293 addTypeInfo(builder.getTpiBuilder(), tMerger.getTypeTable());
1385 addTypeInfo(Builder.getIpiBuilder(), getIDTable());1294 addTypeInfo(builder.getIpiBuilder(), tMerger.getIDTable());
1386 T2.stop();1295 t2.stop();
13871296
1388 ScopedTimer T3(GlobalsLayoutTimer);1297 ScopedTimer t3(globalsLayoutTimer);
1389 // Compute the public and global symbols.1298 // Compute the public and global symbols.
1390 auto &GsiBuilder = Builder.getGsiBuilder();1299 auto &gsiBuilder = builder.getGsiBuilder();
1391 std::vector<PublicSym32> Publics;1300 std::vector<PublicSym32> publics;
1392 Symtab->forEachSymbol([&Publics](Symbol *S) {1301 symtab->forEachSymbol([&publics](Symbol *s) {
1393 // Only emit defined, live symbols that have a chunk.1302 // Only emit defined, live symbols that have a chunk.
1394 auto *Def = dyn_cast<Defined>(S);1303 auto *def = dyn_cast<Defined>(s);
1395 if (Def && Def->isLive() && Def->getChunk())1304 if (def && def->isLive() && def->getChunk())
1396 Publics.push_back(createPublic(Def));1305 publics.push_back(createPublic(def));
1397 });1306 });
13981307
1399 if (!Publics.empty()) {1308 if (!publics.empty()) {
1309 publicSymbols = publics.size();
1400 // Sort the public symbols and add them to the stream.1310 // Sort the public symbols and add them to the stream.
1401 sort(parallel::par, Publics.begin(), Publics.end(),1311 parallelSort(publics, [](const PublicSym32 &l, const PublicSym32 &r) {
1402 [](const PublicSym32 &L, const PublicSym32 &R) {1312 return l.Name < r.Name;
1403 return L.Name < R.Name;1313 });
1404 });1314 for (const PublicSym32 &pub : publics)
1405 for (const PublicSym32 &Pub : Publics)1315 gsiBuilder.addPublicSymbol(pub);
1406 GsiBuilder.addPublicSymbol(Pub);
1407 }1316 }
1408}1317}
14091318
1319void PDBLinker::printStats() {
1320 if (!config->showSummary)
1321 return;
1322
1323 SmallString<256> buffer;
1324 raw_svector_ostream stream(buffer);
1325
1326 stream << center_justify("Summary", 80) << '\n'
1327 << std::string(80, '-') << '\n';
1328
1329 auto print = [&](uint64_t v, StringRef s) {
1330 stream << format_decimal(v, 15) << " " << s << '\n';
1331 };
1332
1333 print(ObjFile::instances.size(),
1334 "Input OBJ files (expanded from all cmd-line inputs)");
1335 print(typeServerIndexMappings.size(), "PDB type server dependencies");
1336 print(precompTypeIndexMappings.size(), "Precomp OBJ dependencies");
1337 print(tMerger.getTypeTable().size() + tMerger.getIDTable().size(),
1338 "Merged TPI records");
1339 print(pdbStrTab.size(), "Output PDB strings");
1340 print(globalSymbols, "Global symbol records");
1341 print(moduleSymbols, "Module symbol records");
1342 print(publicSymbols, "Public symbol records");
1343
1344 message(buffer);
1345}
1346
1410void PDBLinker::addNatvisFiles() {1347void PDBLinker::addNatvisFiles() {
1411 for (StringRef File : Config->NatvisFiles) {1348 for (StringRef file : config->natvisFiles) {
1412 ErrorOr<std::unique_ptr<MemoryBuffer>> DataOrErr =1349 ErrorOr<std::unique_ptr<MemoryBuffer>> dataOrErr =
1413 MemoryBuffer::getFile(File);1350 MemoryBuffer::getFile(file);
1414 if (!DataOrErr) {1351 if (!dataOrErr) {
1415 warn("Cannot open input file: " + File);1352 warn("Cannot open input file: " + file);
1416 continue;1353 continue;
1417 }1354 }
1418 Builder.addInjectedSource(File, std::move(*DataOrErr));1355 builder.addInjectedSource(file, std::move(*dataOrErr));
1419 }1356 }
1420}1357}
14211358
1422static codeview::CPUType toCodeViewMachine(COFF::MachineTypes Machine) {1359static codeview::CPUType toCodeViewMachine(COFF::MachineTypes machine) {
1423 switch (Machine) {1360 switch (machine) {
1424 case COFF::IMAGE_FILE_MACHINE_AMD64:1361 case COFF::IMAGE_FILE_MACHINE_AMD64:
1425 return codeview::CPUType::X64;1362 return codeview::CPUType::X64;
1426 case COFF::IMAGE_FILE_MACHINE_ARM:1363 case COFF::IMAGE_FILE_MACHINE_ARM:
...@@ -1439,201 +1376,329 @@ static codeview::CPUType toCodeViewMachine(COFF::MachineTypes Machine) {...@@ -1439,201 +1376,329 @@ static codeview::CPUType toCodeViewMachine(COFF::MachineTypes Machine) {
1439// Mimic MSVC which surrounds arguments containing whitespace with quotes.1376// Mimic MSVC which surrounds arguments containing whitespace with quotes.
1440// Double double-quotes are handled, so that the resulting string can be1377// Double double-quotes are handled, so that the resulting string can be
1441// executed again on the cmd-line.1378// executed again on the cmd-line.
1442static std::string quote(ArrayRef<StringRef> Args) {1379static std::string quote(ArrayRef<StringRef> args) {
1443 std::string R;1380 std::string r;
1444 R.reserve(256);1381 r.reserve(256);
1445 for (StringRef A : Args) {1382 for (StringRef a : args) {
1446 if (!R.empty())1383 if (!r.empty())
1447 R.push_back(' ');1384 r.push_back(' ');
1448 bool HasWS = A.find(' ') != StringRef::npos;1385 bool hasWS = a.find(' ') != StringRef::npos;
1449 bool HasQ = A.find('"') != StringRef::npos;1386 bool hasQ = a.find('"') != StringRef::npos;
1450 if (HasWS || HasQ)1387 if (hasWS || hasQ)
1451 R.push_back('"');1388 r.push_back('"');
1452 if (HasQ) {1389 if (hasQ) {
1453 SmallVector<StringRef, 4> S;1390 SmallVector<StringRef, 4> s;
1454 A.split(S, '"');1391 a.split(s, '"');
1455 R.append(join(S, "\"\""));1392 r.append(join(s, "\"\""));
1456 } else {1393 } else {
1457 R.append(A);1394 r.append(a);
1458 }1395 }
1459 if (HasWS || HasQ)1396 if (hasWS || hasQ)
1460 R.push_back('"');1397 r.push_back('"');
1461 }1398 }
1462 return R;1399 return r;
1463}1400}
14641401
1465static void addCommonLinkerModuleSymbols(StringRef Path,1402static void fillLinkerVerRecord(Compile3Sym &cs) {
1466 pdb::DbiModuleDescriptorBuilder &Mod,1403 cs.Machine = toCodeViewMachine(config->machine);
1467 BumpPtrAllocator &Allocator) {
1468 ObjNameSym ONS(SymbolRecordKind::ObjNameSym);
1469 Compile3Sym CS(SymbolRecordKind::Compile3Sym);
1470 EnvBlockSym EBS(SymbolRecordKind::EnvBlockSym);
1471
1472 ONS.Name = "* Linker *";
1473 ONS.Signature = 0;
1474
1475 CS.Machine = toCodeViewMachine(Config->Machine);
1476 // Interestingly, if we set the string to 0.0.0.0, then when trying to view1404 // Interestingly, if we set the string to 0.0.0.0, then when trying to view
1477 // local variables WinDbg emits an error that private symbols are not present.1405 // local variables WinDbg emits an error that private symbols are not present.
1478 // By setting this to a valid MSVC linker version string, local variables are1406 // By setting this to a valid MSVC linker version string, local variables are
1479 // displayed properly. As such, even though it is not representative of1407 // displayed properly. As such, even though it is not representative of
1480 // LLVM's version information, we need this for compatibility.1408 // LLVM's version information, we need this for compatibility.
1481 CS.Flags = CompileSym3Flags::None;1409 cs.Flags = CompileSym3Flags::None;
1482 CS.VersionBackendBuild = 25019;1410 cs.VersionBackendBuild = 25019;
1483 CS.VersionBackendMajor = 14;1411 cs.VersionBackendMajor = 14;
1484 CS.VersionBackendMinor = 10;1412 cs.VersionBackendMinor = 10;
1485 CS.VersionBackendQFE = 0;1413 cs.VersionBackendQFE = 0;
14861414
1487 // MSVC also sets the frontend to 0.0.0.0 since this is specifically for the1415 // MSVC also sets the frontend to 0.0.0.0 since this is specifically for the
1488 // linker module (which is by definition a backend), so we don't need to do1416 // linker module (which is by definition a backend), so we don't need to do
1489 // anything here. Also, it seems we can use "LLVM Linker" for the linker name1417 // anything here. Also, it seems we can use "LLVM Linker" for the linker name
1490 // without any problems. Only the backend version has to be hardcoded to a1418 // without any problems. Only the backend version has to be hardcoded to a
1491 // magic number.1419 // magic number.
1492 CS.VersionFrontendBuild = 0;1420 cs.VersionFrontendBuild = 0;
1493 CS.VersionFrontendMajor = 0;1421 cs.VersionFrontendMajor = 0;
1494 CS.VersionFrontendMinor = 0;1422 cs.VersionFrontendMinor = 0;
1495 CS.VersionFrontendQFE = 0;1423 cs.VersionFrontendQFE = 0;
1496 CS.Version = "LLVM Linker";1424 cs.Version = "LLVM Linker";
1497 CS.setLanguage(SourceLanguage::Link);1425 cs.setLanguage(SourceLanguage::Link);
14981426}
1499 ArrayRef<StringRef> Args = makeArrayRef(Config->Argv).drop_front();1427
1500 std::string ArgStr = quote(Args);1428static void addCommonLinkerModuleSymbols(StringRef path,
1501 EBS.Fields.push_back("cwd");1429 pdb::DbiModuleDescriptorBuilder &mod,
1430 BumpPtrAllocator &allocator) {
1431 ObjNameSym ons(SymbolRecordKind::ObjNameSym);
1432 EnvBlockSym ebs(SymbolRecordKind::EnvBlockSym);
1433 Compile3Sym cs(SymbolRecordKind::Compile3Sym);
1434 fillLinkerVerRecord(cs);
1435
1436 ons.Name = "* Linker *";
1437 ons.Signature = 0;
1438
1439 ArrayRef<StringRef> args = makeArrayRef(config->argv).drop_front();
1440 std::string argStr = quote(args);
1441 ebs.Fields.push_back("cwd");
1502 SmallString<64> cwd;1442 SmallString<64> cwd;
1503 if (Config->PDBSourcePath.empty())1443 if (config->pdbSourcePath.empty())
1504 sys::fs::current_path(cwd);1444 sys::fs::current_path(cwd);
1505 else1445 else
1506 cwd = Config->PDBSourcePath;1446 cwd = config->pdbSourcePath;
1507 EBS.Fields.push_back(cwd);1447 ebs.Fields.push_back(cwd);
1508 EBS.Fields.push_back("exe");1448 ebs.Fields.push_back("exe");
1509 SmallString<64> exe = Config->Argv[0];1449 SmallString<64> exe = config->argv[0];
1510 pdbMakeAbsolute(exe);1450 pdbMakeAbsolute(exe);
1511 EBS.Fields.push_back(exe);1451 ebs.Fields.push_back(exe);
1512 EBS.Fields.push_back("pdb");1452 ebs.Fields.push_back("pdb");
1513 EBS.Fields.push_back(Path);1453 ebs.Fields.push_back(path);
1514 EBS.Fields.push_back("cmd");1454 ebs.Fields.push_back("cmd");
1515 EBS.Fields.push_back(ArgStr);1455 ebs.Fields.push_back(argStr);
1516 Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(1456 mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
1517 ONS, Allocator, CodeViewContainer::Pdb));1457 ons, allocator, CodeViewContainer::Pdb));
1518 Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(1458 mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
1519 CS, Allocator, CodeViewContainer::Pdb));1459 cs, allocator, CodeViewContainer::Pdb));
1520 Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(1460 mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
1521 EBS, Allocator, CodeViewContainer::Pdb));1461 ebs, allocator, CodeViewContainer::Pdb));
1462}
1463
1464static void addLinkerModuleCoffGroup(PartialSection *sec,
1465 pdb::DbiModuleDescriptorBuilder &mod,
1466 OutputSection &os,
1467 BumpPtrAllocator &allocator) {
1468 // If there's a section, there's at least one chunk
1469 assert(!sec->chunks.empty());
1470 const Chunk *firstChunk = *sec->chunks.begin();
1471 const Chunk *lastChunk = *sec->chunks.rbegin();
1472
1473 // Emit COFF group
1474 CoffGroupSym cgs(SymbolRecordKind::CoffGroupSym);
1475 cgs.Name = sec->name;
1476 cgs.Segment = os.sectionIndex;
1477 cgs.Offset = firstChunk->getRVA() - os.getRVA();
1478 cgs.Size = lastChunk->getRVA() + lastChunk->getSize() - firstChunk->getRVA();
1479 cgs.Characteristics = sec->characteristics;
1480
1481 // Somehow .idata sections & sections groups in the debug symbol stream have
1482 // the "write" flag set. However the section header for the corresponding
1483 // .idata section doesn't have it.
1484 if (cgs.Name.startswith(".idata"))
1485 cgs.Characteristics |= llvm::COFF::IMAGE_SCN_MEM_WRITE;
1486
1487 mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
1488 cgs, allocator, CodeViewContainer::Pdb));
1489}
1490
1491static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &mod,
1492 OutputSection &os,
1493 BumpPtrAllocator &allocator) {
1494 SectionSym sym(SymbolRecordKind::SectionSym);
1495 sym.Alignment = 12; // 2^12 = 4KB
1496 sym.Characteristics = os.header.Characteristics;
1497 sym.Length = os.getVirtualSize();
1498 sym.Name = os.name;
1499 sym.Rva = os.getRVA();
1500 sym.SectionNumber = os.sectionIndex;
1501 mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(
1502 sym, allocator, CodeViewContainer::Pdb));
1503
1504 // Skip COFF groups in MinGW because it adds a significant footprint to the
1505 // PDB, due to each function being in its own section
1506 if (config->mingw)
1507 return;
1508
1509 // Output COFF groups for individual chunks of this section.
1510 for (PartialSection *sec : os.contribSections) {
1511 addLinkerModuleCoffGroup(sec, mod, os, allocator);
1512 }
1522}1513}
15231514
1524static void addLinkerModuleSectionSymbol(pdb::DbiModuleDescriptorBuilder &Mod,1515// Add all import files as modules to the PDB.
1525 OutputSection &OS,1516void PDBLinker::addImportFilesToPDB(ArrayRef<OutputSection *> outputSections) {
1526 BumpPtrAllocator &Allocator) {1517 if (ImportFile::instances.empty())
1527 SectionSym Sym(SymbolRecordKind::SectionSym);1518 return;
1528 Sym.Alignment = 12; // 2^12 = 4KB1519
1529 Sym.Characteristics = OS.Header.Characteristics;1520 std::map<std::string, llvm::pdb::DbiModuleDescriptorBuilder *> dllToModuleDbi;
1530 Sym.Length = OS.getVirtualSize();1521
1531 Sym.Name = OS.Name;1522 for (ImportFile *file : ImportFile::instances) {
1532 Sym.Rva = OS.getRVA();1523 if (!file->live)
1533 Sym.SectionNumber = OS.SectionIndex;1524 continue;
1534 Mod.addSymbol(codeview::SymbolSerializer::writeOneSymbol(1525
1535 Sym, Allocator, CodeViewContainer::Pdb));1526 if (!file->thunkSym)
1527 continue;
1528
1529 if (!file->thunkLive)
1530 continue;
1531
1532 std::string dll = StringRef(file->dllName).lower();
1533 llvm::pdb::DbiModuleDescriptorBuilder *&mod = dllToModuleDbi[dll];
1534 if (!mod) {
1535 pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
1536 SmallString<128> libPath = file->parentName;
1537 pdbMakeAbsolute(libPath);
1538 sys::path::native(libPath);
1539
1540 // Name modules similar to MSVC's link.exe.
1541 // The first module is the simple dll filename
1542 llvm::pdb::DbiModuleDescriptorBuilder &firstMod =
1543 exitOnErr(dbiBuilder.addModuleInfo(file->dllName));
1544 firstMod.setObjFileName(libPath);
1545 pdb::SectionContrib sc =
1546 createSectionContrib(nullptr, llvm::pdb::kInvalidStreamIndex);
1547 firstMod.setFirstSectionContrib(sc);
1548
1549 // The second module is where the import stream goes.
1550 mod = &exitOnErr(dbiBuilder.addModuleInfo("Import:" + file->dllName));
1551 mod->setObjFileName(libPath);
1552 }
1553
1554 DefinedImportThunk *thunk = cast<DefinedImportThunk>(file->thunkSym);
1555 Chunk *thunkChunk = thunk->getChunk();
1556 OutputSection *thunkOS = thunkChunk->getOutputSection();
1557
1558 ObjNameSym ons(SymbolRecordKind::ObjNameSym);
1559 Compile3Sym cs(SymbolRecordKind::Compile3Sym);
1560 Thunk32Sym ts(SymbolRecordKind::Thunk32Sym);
1561 ScopeEndSym es(SymbolRecordKind::ScopeEndSym);
1562
1563 ons.Name = file->dllName;
1564 ons.Signature = 0;
1565
1566 fillLinkerVerRecord(cs);
1567
1568 ts.Name = thunk->getName();
1569 ts.Parent = 0;
1570 ts.End = 0;
1571 ts.Next = 0;
1572 ts.Thunk = ThunkOrdinal::Standard;
1573 ts.Length = thunkChunk->getSize();
1574 ts.Segment = thunkOS->sectionIndex;
1575 ts.Offset = thunkChunk->getRVA() - thunkOS->getRVA();
1576
1577 mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol(
1578 ons, alloc, CodeViewContainer::Pdb));
1579 mod->addSymbol(codeview::SymbolSerializer::writeOneSymbol(
1580 cs, alloc, CodeViewContainer::Pdb));
1581
1582 SmallVector<SymbolScope, 4> scopes;
1583 CVSymbol newSym = codeview::SymbolSerializer::writeOneSymbol(
1584 ts, alloc, CodeViewContainer::Pdb);
1585 scopeStackOpen(scopes, mod->getNextSymbolOffset(), newSym);
1586
1587 mod->addSymbol(newSym);
1588
1589 newSym = codeview::SymbolSerializer::writeOneSymbol(es, alloc,
1590 CodeViewContainer::Pdb);
1591 scopeStackClose(scopes, mod->getNextSymbolOffset(), file);
1592
1593 mod->addSymbol(newSym);
1594
1595 pdb::SectionContrib sc =
1596 createSectionContrib(thunk->getChunk(), mod->getModuleIndex());
1597 mod->setFirstSectionContrib(sc);
1598 }
1536}1599}
15371600
1538// Creates a PDB file.1601// Creates a PDB file.
1539void coff::createPDB(SymbolTable *Symtab,1602void coff::createPDB(SymbolTable *symtab,
1540 ArrayRef<OutputSection *> OutputSections,1603 ArrayRef<OutputSection *> outputSections,
1541 ArrayRef<uint8_t> SectionTable,1604 ArrayRef<uint8_t> sectionTable,
1542 llvm::codeview::DebugInfo *BuildId) {1605 llvm::codeview::DebugInfo *buildId) {
1543 ScopedTimer T1(TotalPdbLinkTimer);1606 ScopedTimer t1(totalPdbLinkTimer);
1544 PDBLinker PDB(Symtab);1607 PDBLinker pdb(symtab);
15451608
1546 PDB.initialize(BuildId);1609 pdb.initialize(buildId);
1547 PDB.addObjectsToPDB();1610 pdb.addObjectsToPDB();
1548 PDB.addSections(OutputSections, SectionTable);1611 pdb.addImportFilesToPDB(outputSections);
1549 PDB.addNatvisFiles();1612 pdb.addSections(outputSections, sectionTable);
15501613 pdb.addNatvisFiles();
1551 ScopedTimer T2(DiskCommitTimer);1614
1552 codeview::GUID Guid;1615 ScopedTimer t2(diskCommitTimer);
1553 PDB.commit(&Guid);1616 codeview::GUID guid;
1554 memcpy(&BuildId->PDB70.Signature, &Guid, 16);1617 pdb.commit(&guid);
1618 memcpy(&buildId->PDB70.Signature, &guid, 16);
1619
1620 t2.stop();
1621 t1.stop();
1622 pdb.printStats();
1555}1623}
15561624
1557void PDBLinker::initialize(llvm::codeview::DebugInfo *BuildId) {1625void PDBLinker::initialize(llvm::codeview::DebugInfo *buildId) {
1558 ExitOnErr(Builder.initialize(4096)); // 4096 is blocksize1626 exitOnErr(builder.initialize(4096)); // 4096 is blocksize
15591627
1560 BuildId->Signature.CVSignature = OMF::Signature::PDB70;1628 buildId->Signature.CVSignature = OMF::Signature::PDB70;
1561 // Signature is set to a hash of the PDB contents when the PDB is done.1629 // Signature is set to a hash of the PDB contents when the PDB is done.
1562 memset(BuildId->PDB70.Signature, 0, 16);1630 memset(buildId->PDB70.Signature, 0, 16);
1563 BuildId->PDB70.Age = 1;1631 buildId->PDB70.Age = 1;
15641632
1565 // Create streams in MSF for predefined streams, namely1633 // Create streams in MSF for predefined streams, namely
1566 // PDB, TPI, DBI and IPI.1634 // PDB, TPI, DBI and IPI.
1567 for (int I = 0; I < (int)pdb::kSpecialStreamCount; ++I)1635 for (int i = 0; i < (int)pdb::kSpecialStreamCount; ++i)
1568 ExitOnErr(Builder.getMsfBuilder().addStream(0));1636 exitOnErr(builder.getMsfBuilder().addStream(0));
15691637
1570 // Add an Info stream.1638 // Add an Info stream.
1571 auto &InfoBuilder = Builder.getInfoBuilder();1639 auto &infoBuilder = builder.getInfoBuilder();
1572 InfoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);1640 infoBuilder.setVersion(pdb::PdbRaw_ImplVer::PdbImplVC70);
1573 InfoBuilder.setHashPDBContentsToGUID(true);1641 infoBuilder.setHashPDBContentsToGUID(true);
15741642
1575 // Add an empty DBI stream.1643 // Add an empty DBI stream.
1576 pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();1644 pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
1577 DbiBuilder.setAge(BuildId->PDB70.Age);1645 dbiBuilder.setAge(buildId->PDB70.Age);
1578 DbiBuilder.setVersionHeader(pdb::PdbDbiV70);1646 dbiBuilder.setVersionHeader(pdb::PdbDbiV70);
1579 DbiBuilder.setMachineType(Config->Machine);1647 dbiBuilder.setMachineType(config->machine);
1580 // Technically we are not link.exe 14.11, but there are known cases where1648 // Technically we are not link.exe 14.11, but there are known cases where
1581 // debugging tools on Windows expect Microsoft-specific version numbers or1649 // debugging tools on Windows expect Microsoft-specific version numbers or
1582 // they fail to work at all. Since we know we produce PDBs that are1650 // they fail to work at all. Since we know we produce PDBs that are
1583 // compatible with LINK 14.11, we set that version number here.1651 // compatible with LINK 14.11, we set that version number here.
1584 DbiBuilder.setBuildNumber(14, 11);1652 dbiBuilder.setBuildNumber(14, 11);
1585}1653}
15861654
1587void PDBLinker::addSections(ArrayRef<OutputSection *> OutputSections,1655void PDBLinker::addSections(ArrayRef<OutputSection *> outputSections,
1588 ArrayRef<uint8_t> SectionTable) {1656 ArrayRef<uint8_t> sectionTable) {
1589 // It's not entirely clear what this is, but the * Linker * module uses it.1657 // It's not entirely clear what this is, but the * Linker * module uses it.
1590 pdb::DbiStreamBuilder &DbiBuilder = Builder.getDbiBuilder();1658 pdb::DbiStreamBuilder &dbiBuilder = builder.getDbiBuilder();
1591 NativePath = Config->PDBPath;1659 nativePath = config->pdbPath;
1592 pdbMakeAbsolute(NativePath);1660 pdbMakeAbsolute(nativePath);
1593 uint32_t PdbFilePathNI = DbiBuilder.addECName(NativePath);1661 uint32_t pdbFilePathNI = dbiBuilder.addECName(nativePath);
1594 auto &LinkerModule = ExitOnErr(DbiBuilder.addModuleInfo("* Linker *"));1662 auto &linkerModule = exitOnErr(dbiBuilder.addModuleInfo("* Linker *"));
1595 LinkerModule.setPdbFilePathNI(PdbFilePathNI);1663 linkerModule.setPdbFilePathNI(pdbFilePathNI);
1596 addCommonLinkerModuleSymbols(NativePath, LinkerModule, Alloc);1664 addCommonLinkerModuleSymbols(nativePath, linkerModule, alloc);
15971665
1598 // Add section contributions. They must be ordered by ascending RVA.1666 // Add section contributions. They must be ordered by ascending RVA.
1599 for (OutputSection *OS : OutputSections) {1667 for (OutputSection *os : outputSections) {
1600 addLinkerModuleSectionSymbol(LinkerModule, *OS, Alloc);1668 addLinkerModuleSectionSymbol(linkerModule, *os, alloc);
1601 for (Chunk *C : OS->Chunks) {1669 for (Chunk *c : os->chunks) {
1602 pdb::SectionContrib SC =1670 pdb::SectionContrib sc =
1603 createSectionContrib(C, LinkerModule.getModuleIndex());1671 createSectionContrib(c, linkerModule.getModuleIndex());
1604 Builder.getDbiBuilder().addSectionContrib(SC);1672 builder.getDbiBuilder().addSectionContrib(sc);
1605 }1673 }
1606 }1674 }
16071675
1676 // The * Linker * first section contrib is only used along with /INCREMENTAL,
1677 // to provide trampolines thunks for incremental function patching. Set this
1678 // as "unused" because LLD doesn't support /INCREMENTAL link.
1679 pdb::SectionContrib sc =
1680 createSectionContrib(nullptr, llvm::pdb::kInvalidStreamIndex);
1681 linkerModule.setFirstSectionContrib(sc);
1682
1608 // Add Section Map stream.1683 // Add Section Map stream.
1609 ArrayRef<object::coff_section> Sections = {1684 ArrayRef<object::coff_section> sections = {
1610 (const object::coff_section *)SectionTable.data(),1685 (const object::coff_section *)sectionTable.data(),
1611 SectionTable.size() / sizeof(object::coff_section)};1686 sectionTable.size() / sizeof(object::coff_section)};
1612 SectionMap = pdb::DbiStreamBuilder::createSectionMap(Sections);1687 sectionMap = pdb::DbiStreamBuilder::createSectionMap(sections);
1613 DbiBuilder.setSectionMap(SectionMap);1688 dbiBuilder.setSectionMap(sectionMap);
16141689
1615 // Add COFF section header stream.1690 // Add COFF section header stream.
1616 ExitOnErr(1691 exitOnErr(
1617 DbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, SectionTable));1692 dbiBuilder.addDbgStream(pdb::DbgHeaderType::SectionHdr, sectionTable));
1618}1693}
16191694
1620void PDBLinker::commit(codeview::GUID *Guid) {1695void PDBLinker::commit(codeview::GUID *guid) {
1621 // Write to a file.1696 // Write to a file.
1622 ExitOnErr(Builder.commit(Config->PDBPath, Guid));1697 exitOnErr(builder.commit(config->pdbPath, guid));
1623}
1624
1625static Expected<StringRef>
1626getFileName(const DebugStringTableSubsectionRef &Strings,
1627 const DebugChecksumsSubsectionRef &Checksums, uint32_t FileID) {
1628 auto Iter = Checksums.getArray().at(FileID);
1629 if (Iter == Checksums.getArray().end())
1630 return make_error<CodeViewError>(cv_error_code::no_records);
1631 uint32_t Offset = Iter->FileNameOffset;
1632 return Strings.getString(Offset);
1633}1698}
16341699
1635static uint32_t getSecrelReloc() {1700static uint32_t getSecrelReloc() {
1636 switch (Config->Machine) {1701 switch (config->machine) {
1637 case AMD64:1702 case AMD64:
1638 return COFF::IMAGE_REL_AMD64_SECREL;1703 return COFF::IMAGE_REL_AMD64_SECREL;
1639 case I386:1704 case I386:
...@@ -1652,78 +1717,78 @@ static uint32_t getSecrelReloc() {...@@ -1652,78 +1717,78 @@ static uint32_t getSecrelReloc() {
1652// that are used to interpret the line table, and the offset of Addr in the line1717// that are used to interpret the line table, and the offset of Addr in the line
1653// table are stored in the output arguments. Returns whether a line table was1718// table are stored in the output arguments. Returns whether a line table was
1654// found.1719// found.
1655static bool findLineTable(const SectionChunk *C, uint32_t Addr,1720static bool findLineTable(const SectionChunk *c, uint32_t addr,
1656 DebugStringTableSubsectionRef &CVStrTab,1721 DebugStringTableSubsectionRef &cVStrTab,
1657 DebugChecksumsSubsectionRef &Checksums,1722 DebugChecksumsSubsectionRef &checksums,
1658 DebugLinesSubsectionRef &Lines,1723 DebugLinesSubsectionRef &lines,
1659 uint32_t &OffsetInLinetable) {1724 uint32_t &offsetInLinetable) {
1660 ExitOnError ExitOnErr;1725 ExitOnError exitOnErr;
1661 uint32_t SecrelReloc = getSecrelReloc();1726 uint32_t secrelReloc = getSecrelReloc();
16621727
1663 for (SectionChunk *DbgC : C->File->getDebugChunks()) {1728 for (SectionChunk *dbgC : c->file->getDebugChunks()) {
1664 if (DbgC->getSectionName() != ".debug$S")1729 if (dbgC->getSectionName() != ".debug$S")
1665 continue;1730 continue;
16661731
1667 // Build a mapping of SECREL relocations in DbgC that refer to C.1732 // Build a mapping of SECREL relocations in dbgC that refer to `c`.
1668 DenseMap<uint32_t, uint32_t> Secrels;1733 DenseMap<uint32_t, uint32_t> secrels;
1669 for (const coff_relocation &R : DbgC->Relocs) {1734 for (const coff_relocation &r : dbgC->getRelocs()) {
1670 if (R.Type != SecrelReloc)1735 if (r.Type != secrelReloc)
1671 continue;1736 continue;
16721737
1673 if (auto *S = dyn_cast_or_null<DefinedRegular>(1738 if (auto *s = dyn_cast_or_null<DefinedRegular>(
1674 C->File->getSymbols()[R.SymbolTableIndex]))1739 c->file->getSymbols()[r.SymbolTableIndex]))
1675 if (S->getChunk() == C)1740 if (s->getChunk() == c)
1676 Secrels[R.VirtualAddress] = S->getValue();1741 secrels[r.VirtualAddress] = s->getValue();
1677 }1742 }
16781743
1679 ArrayRef<uint8_t> Contents =1744 ArrayRef<uint8_t> contents =
1680 consumeDebugMagic(DbgC->getContents(), ".debug$S");1745 SectionChunk::consumeDebugMagic(dbgC->getContents(), ".debug$S");
1681 DebugSubsectionArray Subsections;1746 DebugSubsectionArray subsections;
1682 BinaryStreamReader Reader(Contents, support::little);1747 BinaryStreamReader reader(contents, support::little);
1683 ExitOnErr(Reader.readArray(Subsections, Contents.size()));1748 exitOnErr(reader.readArray(subsections, contents.size()));
16841749
1685 for (const DebugSubsectionRecord &SS : Subsections) {1750 for (const DebugSubsectionRecord &ss : subsections) {
1686 switch (SS.kind()) {1751 switch (ss.kind()) {
1687 case DebugSubsectionKind::StringTable: {1752 case DebugSubsectionKind::StringTable: {
1688 assert(!CVStrTab.valid() &&1753 assert(!cVStrTab.valid() &&
1689 "Encountered multiple string table subsections!");1754 "Encountered multiple string table subsections!");
1690 ExitOnErr(CVStrTab.initialize(SS.getRecordData()));1755 exitOnErr(cVStrTab.initialize(ss.getRecordData()));
1691 break;1756 break;
1692 }1757 }
1693 case DebugSubsectionKind::FileChecksums:1758 case DebugSubsectionKind::FileChecksums:
1694 assert(!Checksums.valid() &&1759 assert(!checksums.valid() &&
1695 "Encountered multiple checksum subsections!");1760 "Encountered multiple checksum subsections!");
1696 ExitOnErr(Checksums.initialize(SS.getRecordData()));1761 exitOnErr(checksums.initialize(ss.getRecordData()));
1697 break;1762 break;
1698 case DebugSubsectionKind::Lines: {1763 case DebugSubsectionKind::Lines: {
1699 ArrayRef<uint8_t> Bytes;1764 ArrayRef<uint8_t> bytes;
1700 auto Ref = SS.getRecordData();1765 auto ref = ss.getRecordData();
1701 ExitOnErr(Ref.readLongestContiguousChunk(0, Bytes));1766 exitOnErr(ref.readLongestContiguousChunk(0, bytes));
1702 size_t OffsetInDbgC = Bytes.data() - DbgC->getContents().data();1767 size_t offsetInDbgC = bytes.data() - dbgC->getContents().data();
17031768
1704 // Check whether this line table refers to C.1769 // Check whether this line table refers to C.
1705 auto I = Secrels.find(OffsetInDbgC);1770 auto i = secrels.find(offsetInDbgC);
1706 if (I == Secrels.end())1771 if (i == secrels.end())
1707 break;1772 break;
17081773
1709 // Check whether this line table covers Addr in C.1774 // Check whether this line table covers Addr in C.
1710 DebugLinesSubsectionRef LinesTmp;1775 DebugLinesSubsectionRef linesTmp;
1711 ExitOnErr(LinesTmp.initialize(BinaryStreamReader(Ref)));1776 exitOnErr(linesTmp.initialize(BinaryStreamReader(ref)));
1712 uint32_t OffsetInC = I->second + LinesTmp.header()->RelocOffset;1777 uint32_t offsetInC = i->second + linesTmp.header()->RelocOffset;
1713 if (Addr < OffsetInC || Addr >= OffsetInC + LinesTmp.header()->CodeSize)1778 if (addr < offsetInC || addr >= offsetInC + linesTmp.header()->CodeSize)
1714 break;1779 break;
17151780
1716 assert(!Lines.header() &&1781 assert(!lines.header() &&
1717 "Encountered multiple line tables for function!");1782 "Encountered multiple line tables for function!");
1718 ExitOnErr(Lines.initialize(BinaryStreamReader(Ref)));1783 exitOnErr(lines.initialize(BinaryStreamReader(ref)));
1719 OffsetInLinetable = Addr - OffsetInC;1784 offsetInLinetable = addr - offsetInC;
1720 break;1785 break;
1721 }1786 }
1722 default:1787 default:
1723 break;1788 break;
1724 }1789 }
17251790
1726 if (CVStrTab.valid() && Checksums.valid() && Lines.header())1791 if (cVStrTab.valid() && checksums.valid() && lines.header())
1727 return true;1792 return true;
1728 }1793 }
1729 }1794 }
...@@ -1734,38 +1799,38 @@ static bool findLineTable(const SectionChunk *C, uint32_t Addr,...@@ -1734,38 +1799,38 @@ static bool findLineTable(const SectionChunk *C, uint32_t Addr,
1734// Use CodeView line tables to resolve a file and line number for the given1799// Use CodeView line tables to resolve a file and line number for the given
1735// offset into the given chunk and return them, or {"", 0} if a line table was1800// offset into the given chunk and return them, or {"", 0} if a line table was
1736// not found.1801// not found.
1737std::pair<StringRef, uint32_t> coff::getFileLine(const SectionChunk *C,1802std::pair<StringRef, uint32_t> coff::getFileLine(const SectionChunk *c,
1738 uint32_t Addr) {1803 uint32_t addr) {
1739 ExitOnError ExitOnErr;1804 ExitOnError exitOnErr;
17401805
1741 DebugStringTableSubsectionRef CVStrTab;1806 DebugStringTableSubsectionRef cVStrTab;
1742 DebugChecksumsSubsectionRef Checksums;1807 DebugChecksumsSubsectionRef checksums;
1743 DebugLinesSubsectionRef Lines;1808 DebugLinesSubsectionRef lines;
1744 uint32_t OffsetInLinetable;1809 uint32_t offsetInLinetable;
17451810
1746 if (!findLineTable(C, Addr, CVStrTab, Checksums, Lines, OffsetInLinetable))1811 if (!findLineTable(c, addr, cVStrTab, checksums, lines, offsetInLinetable))
1747 return {"", 0};1812 return {"", 0};
17481813
1749 Optional<uint32_t> NameIndex;1814 Optional<uint32_t> nameIndex;
1750 Optional<uint32_t> LineNumber;1815 Optional<uint32_t> lineNumber;
1751 for (LineColumnEntry &Entry : Lines) {1816 for (LineColumnEntry &entry : lines) {
1752 for (const LineNumberEntry &LN : Entry.LineNumbers) {1817 for (const LineNumberEntry &ln : entry.LineNumbers) {
1753 LineInfo LI(LN.Flags);1818 LineInfo li(ln.Flags);
1754 if (LN.Offset > OffsetInLinetable) {1819 if (ln.Offset > offsetInLinetable) {
1755 if (!NameIndex) {1820 if (!nameIndex) {
1756 NameIndex = Entry.NameIndex;1821 nameIndex = entry.NameIndex;
1757 LineNumber = LI.getStartLine();1822 lineNumber = li.getStartLine();
1758 }1823 }
1759 StringRef Filename =1824 StringRef filename =
1760 ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex));1825 exitOnErr(getFileName(cVStrTab, checksums, *nameIndex));
1761 return {Filename, *LineNumber};1826 return {filename, *lineNumber};
1762 }1827 }
1763 NameIndex = Entry.NameIndex;1828 nameIndex = entry.NameIndex;
1764 LineNumber = LI.getStartLine();1829 lineNumber = li.getStartLine();
1765 }1830 }
1766 }1831 }
1767 if (!NameIndex)1832 if (!nameIndex)
1768 return {"", 0};1833 return {"", 0};
1769 StringRef Filename = ExitOnErr(getFileName(CVStrTab, Checksums, *NameIndex));1834 StringRef filename = exitOnErr(getFileName(cVStrTab, checksums, *nameIndex));
1770 return {Filename, *LineNumber};1835 return {filename, *lineNumber};
1771}1836}
deps/lld/COFF/PDB.h+9-10
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- PDB.h ----------------------------------------------------*- C++ -*-===//1//===- PDB.h ----------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -25,13 +24,13 @@ class OutputSection;...@@ -25,13 +24,13 @@ class OutputSection;
25class SectionChunk;24class SectionChunk;
26class SymbolTable;25class SymbolTable;
2726
28void createPDB(SymbolTable *Symtab,27void createPDB(SymbolTable *symtab,
29 llvm::ArrayRef<OutputSection *> OutputSections,28 llvm::ArrayRef<OutputSection *> outputSections,
30 llvm::ArrayRef<uint8_t> SectionTable,29 llvm::ArrayRef<uint8_t> sectionTable,
31 llvm::codeview::DebugInfo *BuildId);30 llvm::codeview::DebugInfo *buildId);
3231
33std::pair<llvm::StringRef, uint32_t> getFileLine(const SectionChunk *C,32std::pair<llvm::StringRef, uint32_t> getFileLine(const SectionChunk *c,
34 uint32_t Addr);33 uint32_t addr);
35}34}
36}35}
3736
deps/lld/COFF/SymbolTable.cpp+392-337
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- SymbolTable.cpp ----------------------------------------------------===//1//===- SymbolTable.cpp ----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -17,6 +16,7 @@...@@ -17,6 +16,7 @@
17#include "lld/Common/Memory.h"16#include "lld/Common/Memory.h"
18#include "lld/Common/Timer.h"17#include "lld/Common/Timer.h"
19#include "llvm/IR/LLVMContext.h"18#include "llvm/IR/LLVMContext.h"
19#include "llvm/Object/WindowsMachineFlag.h"
20#include "llvm/Support/Debug.h"20#include "llvm/Support/Debug.h"
21#include "llvm/Support/raw_ostream.h"21#include "llvm/Support/raw_ostream.h"
22#include <utility>22#include <utility>
...@@ -26,521 +26,576 @@ using namespace llvm;...@@ -26,521 +26,576 @@ using namespace llvm;
26namespace lld {26namespace lld {
27namespace coff {27namespace coff {
2828
29static Timer LTOTimer("LTO", Timer::root());29static Timer ltoTimer("LTO", Timer::root());
3030
31SymbolTable *Symtab;31SymbolTable *symtab;
3232
33void SymbolTable::addFile(InputFile *File) {33void SymbolTable::addFile(InputFile *file) {
34 log("Reading " + toString(File));34 log("Reading " + toString(file));
35 File->parse();35 file->parse();
3636
37 MachineTypes MT = File->getMachineType();37 MachineTypes mt = file->getMachineType();
38 if (Config->Machine == IMAGE_FILE_MACHINE_UNKNOWN) {38 if (config->machine == IMAGE_FILE_MACHINE_UNKNOWN) {
39 Config->Machine = MT;39 config->machine = mt;
40 } else if (MT != IMAGE_FILE_MACHINE_UNKNOWN && Config->Machine != MT) {40 } else if (mt != IMAGE_FILE_MACHINE_UNKNOWN && config->machine != mt) {
41 error(toString(File) + ": machine type " + machineToStr(MT) +41 error(toString(file) + ": machine type " + machineToStr(mt) +
42 " conflicts with " + machineToStr(Config->Machine));42 " conflicts with " + machineToStr(config->machine));
43 return;43 return;
44 }44 }
4545
46 if (auto *F = dyn_cast<ObjFile>(File)) {46 if (auto *f = dyn_cast<ObjFile>(file)) {
47 ObjFile::Instances.push_back(F);47 ObjFile::instances.push_back(f);
48 } else if (auto *F = dyn_cast<BitcodeFile>(File)) {48 } else if (auto *f = dyn_cast<BitcodeFile>(file)) {
49 BitcodeFile::Instances.push_back(F);49 BitcodeFile::instances.push_back(f);
50 } else if (auto *F = dyn_cast<ImportFile>(File)) {50 } else if (auto *f = dyn_cast<ImportFile>(file)) {
51 ImportFile::Instances.push_back(F);51 ImportFile::instances.push_back(f);
52 }52 }
5353
54 StringRef S = File->getDirectives();54 driver->parseDirectives(file);
55 if (S.empty())
56 return;
57
58 log("Directives: " + toString(File) + ": " + S);
59 Driver->parseDirectives(S);
60}55}
6156
62static void errorOrWarn(const Twine &S) {57static void errorOrWarn(const Twine &s) {
63 if (Config->ForceUnresolved)58 if (config->forceUnresolved)
64 warn(S);59 warn(s);
65 else60 else
66 error(S);61 error(s);
67}62}
6863
69// Returns the symbol in SC whose value is <= Addr that is closest to Addr.64// 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 contains65// This is generally the global variable or function whose definition contains
71// Addr.66// Addr.
72static Symbol *getSymbol(SectionChunk *SC, uint32_t Addr) {67static Symbol *getSymbol(SectionChunk *sc, uint32_t addr) {
73 DefinedRegular *Candidate = nullptr;68 DefinedRegular *candidate = nullptr;
7469
75 for (Symbol *S : SC->File->getSymbols()) {70 for (Symbol *s : sc->file->getSymbols()) {
76 auto *D = dyn_cast_or_null<DefinedRegular>(S);71 auto *d = dyn_cast_or_null<DefinedRegular>(s);
77 if (!D || D->getChunk() != SC || D->getValue() > Addr ||72 if (!d || !d->data || d->getChunk() != sc || d->getValue() > addr ||
78 (Candidate && D->getValue() < Candidate->getValue()))73 (candidate && d->getValue() < candidate->getValue()))
79 continue;74 continue;
8075
81 Candidate = D;76 candidate = d;
82 }77 }
8378
84 return Candidate;79 return candidate;
85}80}
8681
87std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex) {82// Given a file and the index of a symbol in that file, returns a description
83// of all references to that symbol from that file. If no debug information is
84// available, returns just the name of the file, else one string per actual
85// reference as described in the debug info.
86std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex) {
88 struct Location {87 struct Location {
89 Symbol *Sym;88 Symbol *sym;
90 std::pair<StringRef, uint32_t> FileLine;89 std::pair<StringRef, uint32_t> fileLine;
91 };90 };
92 std::vector<Location> Locations;91 std::vector<Location> locations;
9392
94 for (Chunk *C : File->getChunks()) {93 for (Chunk *c : file->getChunks()) {
95 auto *SC = dyn_cast<SectionChunk>(C);94 auto *sc = dyn_cast<SectionChunk>(c);
96 if (!SC)95 if (!sc)
97 continue;96 continue;
98 for (const coff_relocation &R : SC->Relocs) {97 for (const coff_relocation &r : sc->getRelocs()) {
99 if (R.SymbolTableIndex != SymIndex)98 if (r.SymbolTableIndex != symIndex)
100 continue;99 continue;
101 std::pair<StringRef, uint32_t> FileLine =100 std::pair<StringRef, uint32_t> fileLine =
102 getFileLine(SC, R.VirtualAddress);101 getFileLine(sc, r.VirtualAddress);
103 Symbol *Sym = getSymbol(SC, R.VirtualAddress);102 Symbol *sym = getSymbol(sc, r.VirtualAddress);
104 if (!FileLine.first.empty() || Sym)103 if (!fileLine.first.empty() || sym)
105 Locations.push_back({Sym, FileLine});104 locations.push_back({sym, fileLine});
106 }105 }
107 }106 }
108107
109 if (Locations.empty())108 if (locations.empty())
110 return "\n>>> referenced by " + toString(File);109 return std::vector<std::string>({"\n>>> referenced by " + toString(file)});
111110
112 std::string Out;111 std::vector<std::string> symbolLocations(locations.size());
113 llvm::raw_string_ostream OS(Out);112 size_t i = 0;
114 for (Location Loc : Locations) {113 for (Location loc : locations) {
115 OS << "\n>>> referenced by ";114 llvm::raw_string_ostream os(symbolLocations[i++]);
116 if (!Loc.FileLine.first.empty())115 os << "\n>>> referenced by ";
117 OS << Loc.FileLine.first << ":" << Loc.FileLine.second116 if (!loc.fileLine.first.empty())
117 os << loc.fileLine.first << ":" << loc.fileLine.second
118 << "\n>>> ";118 << "\n>>> ";
119 OS << toString(File);119 os << toString(file);
120 if (Loc.Sym)120 if (loc.sym)
121 OS << ":(" << toString(*Loc.Sym) << ')';121 os << ":(" << toString(*loc.sym) << ')';
122 }
123 return symbolLocations;
124}
125
126// For an undefined symbol, stores all files referencing it and the index of
127// the undefined symbol in each file.
128struct UndefinedDiag {
129 Symbol *sym;
130 struct File {
131 ObjFile *oFile;
132 uint64_t symIndex;
133 };
134 std::vector<File> files;
135};
136
137static void reportUndefinedSymbol(const UndefinedDiag &undefDiag) {
138 std::string out;
139 llvm::raw_string_ostream os(out);
140 os << "undefined symbol: " << toString(*undefDiag.sym);
141
142 const size_t maxUndefReferences = 10;
143 size_t i = 0, numRefs = 0;
144 for (const UndefinedDiag::File &ref : undefDiag.files) {
145 std::vector<std::string> symbolLocations =
146 getSymbolLocations(ref.oFile, ref.symIndex);
147 numRefs += symbolLocations.size();
148 for (const std::string &s : symbolLocations) {
149 if (i >= maxUndefReferences)
150 break;
151 os << s;
152 i++;
153 }
122 }154 }
123 return OS.str();155 if (i < numRefs)
156 os << "\n>>> referenced " << numRefs - i << " more times";
157 errorOrWarn(os.str());
124}158}
125159
126void SymbolTable::loadMinGWAutomaticImports() {160void SymbolTable::loadMinGWAutomaticImports() {
127 for (auto &I : SymMap) {161 for (auto &i : symMap) {
128 Symbol *Sym = I.second;162 Symbol *sym = i.second;
129 auto *Undef = dyn_cast<Undefined>(Sym);163 auto *undef = dyn_cast<Undefined>(sym);
130 if (!Undef)164 if (!undef)
131 continue;165 continue;
132 if (!Sym->IsUsedInRegularObj)166 if (!sym->isUsedInRegularObj)
133 continue;167 continue;
134168
135 StringRef Name = Undef->getName();169 StringRef name = undef->getName();
136170
137 if (Name.startswith("__imp_"))171 if (name.startswith("__imp_"))
138 continue;172 continue;
139 // If we have an undefined symbol, but we have a Lazy representing a173 // 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.174 // symbol we could load from file, make sure to load that.
141 Lazy *L = dyn_cast_or_null<Lazy>(find(("__imp_" + Name).str()));175 Lazy *l = dyn_cast_or_null<Lazy>(find(("__imp_" + name).str()));
142 if (!L || L->PendingArchiveLoad)176 if (!l || l->pendingArchiveLoad)
143 continue;177 continue;
144178
145 log("Loading lazy " + L->getName() + " from " + L->File->getName() +179 log("Loading lazy " + l->getName() + " from " + l->file->getName() +
146 " for automatic import");180 " for automatic import");
147 L->PendingArchiveLoad = true;181 l->pendingArchiveLoad = true;
148 L->File->addMember(&L->Sym);182 l->file->addMember(&l->sym);
149 }183 }
150}184}
151185
152bool SymbolTable::handleMinGWAutomaticImport(Symbol *Sym, StringRef Name) {186bool SymbolTable::handleMinGWAutomaticImport(Symbol *sym, StringRef name) {
153 if (Name.startswith("__imp_"))187 if (name.startswith("__imp_"))
154 return false;188 return false;
155 Defined *Imp = dyn_cast_or_null<Defined>(find(("__imp_" + Name).str()));189 Defined *imp = dyn_cast_or_null<Defined>(find(("__imp_" + name).str()));
156 if (!Imp)190 if (!imp)
157 return false;191 return false;
158192
159 // Replace the reference directly to a variable with a reference193 // Replace the reference directly to a variable with a reference
160 // to the import address table instead. This obviously isn't right,194 // to the import address table instead. This obviously isn't right,
161 // but we mark the symbol as IsRuntimePseudoReloc, and a later pass195 // but we mark the symbol as isRuntimePseudoReloc, and a later pass
162 // will add runtime pseudo relocations for every relocation against196 // will add runtime pseudo relocations for every relocation against
163 // this Symbol. The runtime pseudo relocation framework expects the197 // this Symbol. The runtime pseudo relocation framework expects the
164 // reference itself to point at the IAT entry.198 // reference itself to point at the IAT entry.
165 size_t ImpSize = 0;199 size_t impSize = 0;
166 if (isa<DefinedImportData>(Imp)) {200 if (isa<DefinedImportData>(imp)) {
167 log("Automatically importing " + Name + " from " +201 log("Automatically importing " + name + " from " +
168 cast<DefinedImportData>(Imp)->getDLLName());202 cast<DefinedImportData>(imp)->getDLLName());
169 ImpSize = sizeof(DefinedImportData);203 impSize = sizeof(DefinedImportData);
170 } else if (isa<DefinedRegular>(Imp)) {204 } else if (isa<DefinedRegular>(imp)) {
171 log("Automatically importing " + Name + " from " +205 log("Automatically importing " + name + " from " +
172 toString(cast<DefinedRegular>(Imp)->File));206 toString(cast<DefinedRegular>(imp)->file));
173 ImpSize = sizeof(DefinedRegular);207 impSize = sizeof(DefinedRegular);
174 } else {208 } else {
175 warn("unable to automatically import " + Name + " from " + Imp->getName() +209 warn("unable to automatically import " + name + " from " + imp->getName() +
176 " from " + toString(cast<DefinedRegular>(Imp)->File) +210 " from " + toString(cast<DefinedRegular>(imp)->file) +
177 "; unexpected symbol type");211 "; unexpected symbol type");
178 return false;212 return false;
179 }213 }
180 Sym->replaceKeepingName(Imp, ImpSize);214 sym->replaceKeepingName(imp, impSize);
181 Sym->IsRuntimePseudoReloc = true;215 sym->isRuntimePseudoReloc = true;
182216
183 // There may exist symbols named .refptr.<name> which only consist217 // There may exist symbols named .refptr.<name> which only consist
184 // of a single pointer to <name>. If it turns out <name> is218 // of a single pointer to <name>. If it turns out <name> is
185 // automatically imported, we don't need to keep the .refptr.<name>219 // automatically imported, we don't need to keep the .refptr.<name>
186 // pointer at all, but redirect all accesses to it to the IAT entry220 // 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.221 // for __imp_<name> instead, and drop the whole .refptr.<name> chunk.
188 DefinedRegular *Refptr =222 DefinedRegular *refptr =
189 dyn_cast_or_null<DefinedRegular>(find((".refptr." + Name).str()));223 dyn_cast_or_null<DefinedRegular>(find((".refptr." + name).str()));
190 if (Refptr && Refptr->getChunk()->getSize() == Config->Wordsize) {224 if (refptr && refptr->getChunk()->getSize() == config->wordsize) {
191 SectionChunk *SC = dyn_cast_or_null<SectionChunk>(Refptr->getChunk());225 SectionChunk *sc = dyn_cast_or_null<SectionChunk>(refptr->getChunk());
192 if (SC && SC->Relocs.size() == 1 && *SC->symbols().begin() == Sym) {226 if (sc && sc->getRelocs().size() == 1 && *sc->symbols().begin() == sym) {
193 log("Replacing .refptr." + Name + " with " + Imp->getName());227 log("Replacing .refptr." + name + " with " + imp->getName());
194 Refptr->getChunk()->Live = false;228 refptr->getChunk()->live = false;
195 Refptr->replaceKeepingName(Imp, ImpSize);229 refptr->replaceKeepingName(imp, impSize);
196 }230 }
197 }231 }
198 return true;232 return true;
199}233}
200234
201void SymbolTable::reportRemainingUndefines() {235void SymbolTable::reportRemainingUndefines() {
202 SmallPtrSet<Symbol *, 8> Undefs;236 SmallPtrSet<Symbol *, 8> undefs;
203 DenseMap<Symbol *, Symbol *> LocalImports;237 DenseMap<Symbol *, Symbol *> localImports;
204238
205 for (auto &I : SymMap) {239 for (auto &i : symMap) {
206 Symbol *Sym = I.second;240 Symbol *sym = i.second;
207 auto *Undef = dyn_cast<Undefined>(Sym);241 auto *undef = dyn_cast<Undefined>(sym);
208 if (!Undef)242 if (!undef)
209 continue;243 continue;
210 if (!Sym->IsUsedInRegularObj)244 if (!sym->isUsedInRegularObj)
211 continue;245 continue;
212246
213 StringRef Name = Undef->getName();247 StringRef name = undef->getName();
214248
215 // A weak alias may have been resolved, so check for that.249 // A weak alias may have been resolved, so check for that.
216 if (Defined *D = Undef->getWeakAlias()) {250 if (Defined *d = undef->getWeakAlias()) {
217 // We want to replace Sym with D. However, we can't just blindly251 // We want to replace Sym with D. However, we can't just blindly
218 // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an252 // copy sizeof(SymbolUnion) bytes from D to Sym because D may be an
219 // internal symbol, and internal symbols are stored as "unparented"253 // internal symbol, and internal symbols are stored as "unparented"
220 // Symbols. For that reason we need to check which type of symbol we254 // Symbols. For that reason we need to check which type of symbol we
221 // are dealing with and copy the correct number of bytes.255 // are dealing with and copy the correct number of bytes.
222 if (isa<DefinedRegular>(D))256 if (isa<DefinedRegular>(d))
223 memcpy(Sym, D, sizeof(DefinedRegular));257 memcpy(sym, d, sizeof(DefinedRegular));
224 else if (isa<DefinedAbsolute>(D))258 else if (isa<DefinedAbsolute>(d))
225 memcpy(Sym, D, sizeof(DefinedAbsolute));259 memcpy(sym, d, sizeof(DefinedAbsolute));
226 else260 else
227 memcpy(Sym, D, sizeof(SymbolUnion));261 memcpy(sym, d, sizeof(SymbolUnion));
228 continue;262 continue;
229 }263 }
230264
231 // If we can resolve a symbol by removing __imp_ prefix, do that.265 // If we can resolve a symbol by removing __imp_ prefix, do that.
232 // This odd rule is for compatibility with MSVC linker.266 // This odd rule is for compatibility with MSVC linker.
233 if (Name.startswith("__imp_")) {267 if (name.startswith("__imp_")) {
234 Symbol *Imp = find(Name.substr(strlen("__imp_")));268 Symbol *imp = find(name.substr(strlen("__imp_")));
235 if (Imp && isa<Defined>(Imp)) {269 if (imp && isa<Defined>(imp)) {
236 auto *D = cast<Defined>(Imp);270 auto *d = cast<Defined>(imp);
237 replaceSymbol<DefinedLocalImport>(Sym, Name, D);271 replaceSymbol<DefinedLocalImport>(sym, name, d);
238 LocalImportChunks.push_back(cast<DefinedLocalImport>(Sym)->getChunk());272 localImportChunks.push_back(cast<DefinedLocalImport>(sym)->getChunk());
239 LocalImports[Sym] = D;273 localImports[sym] = d;
240 continue;274 continue;
241 }275 }
242 }276 }
243277
244 // We don't want to report missing Microsoft precompiled headers symbols.278 // We don't want to report missing Microsoft precompiled headers symbols.
245 // A proper message will be emitted instead in PDBLinker::aquirePrecompObj279 // A proper message will be emitted instead in PDBLinker::aquirePrecompObj
246 if (Name.contains("_PchSym_"))280 if (name.contains("_PchSym_"))
247 continue;281 continue;
248282
249 if (Config->MinGW && handleMinGWAutomaticImport(Sym, Name))283 if (config->mingw && handleMinGWAutomaticImport(sym, name))
250 continue;284 continue;
251285
252 // Remaining undefined symbols are not fatal if /force is specified.286 // Remaining undefined symbols are not fatal if /force is specified.
253 // They are replaced with dummy defined symbols.287 // They are replaced with dummy defined symbols.
254 if (Config->ForceUnresolved)288 if (config->forceUnresolved)
255 replaceSymbol<DefinedAbsolute>(Sym, Name, 0);289 replaceSymbol<DefinedAbsolute>(sym, name, 0);
256 Undefs.insert(Sym);290 undefs.insert(sym);
257 }291 }
258292
259 if (Undefs.empty() && LocalImports.empty())293 if (undefs.empty() && localImports.empty())
260 return;294 return;
261295
262 for (Symbol *B : Config->GCRoot) {296 for (Symbol *b : config->gcroot) {
263 if (Undefs.count(B))297 if (undefs.count(b))
264 errorOrWarn("<root>: undefined symbol: " + toString(*B));298 errorOrWarn("<root>: undefined symbol: " + toString(*b));
265 if (Config->WarnLocallyDefinedImported)299 if (config->warnLocallyDefinedImported)
266 if (Symbol *Imp = LocalImports.lookup(B))300 if (Symbol *imp = localImports.lookup(b))
267 warn("<root>: locally defined symbol imported: " + toString(*Imp) +301 warn("<root>: locally defined symbol imported: " + toString(*imp) +
268 " (defined in " + toString(Imp->getFile()) + ") [LNK4217]");302 " (defined in " + toString(imp->getFile()) + ") [LNK4217]");
269 }303 }
270304
271 for (ObjFile *File : ObjFile::Instances) {305 std::vector<UndefinedDiag> undefDiags;
272 size_t SymIndex = (size_t)-1;306 DenseMap<Symbol *, int> firstDiag;
273 for (Symbol *Sym : File->getSymbols()) {307
274 ++SymIndex;308 for (ObjFile *file : ObjFile::instances) {
275 if (!Sym)309 size_t symIndex = (size_t)-1;
310 for (Symbol *sym : file->getSymbols()) {
311 ++symIndex;
312 if (!sym)
276 continue;313 continue;
277 if (Undefs.count(Sym))314 if (undefs.count(sym)) {
278 errorOrWarn("undefined symbol: " + toString(*Sym) +315 auto it = firstDiag.find(sym);
279 getSymbolLocations(File, SymIndex));316 if (it == firstDiag.end()) {
280 if (Config->WarnLocallyDefinedImported)317 firstDiag[sym] = undefDiags.size();
281 if (Symbol *Imp = LocalImports.lookup(Sym))318 undefDiags.push_back({sym, {{file, symIndex}}});
282 warn(toString(File) +319 } else {
283 ": locally defined symbol imported: " + toString(*Imp) +320 undefDiags[it->second].files.push_back({file, symIndex});
284 " (defined in " + toString(Imp->getFile()) + ") [LNK4217]");321 }
322 }
323 if (config->warnLocallyDefinedImported)
324 if (Symbol *imp = localImports.lookup(sym))
325 warn(toString(file) +
326 ": locally defined symbol imported: " + toString(*imp) +
327 " (defined in " + toString(imp->getFile()) + ") [LNK4217]");
285 }328 }
286 }329 }
330
331 for (const UndefinedDiag& undefDiag : undefDiags)
332 reportUndefinedSymbol(undefDiag);
287}333}
288334
289std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name) {335std::pair<Symbol *, bool> SymbolTable::insert(StringRef name) {
290 bool Inserted = false;336 bool inserted = false;
291 Symbol *&Sym = SymMap[CachedHashStringRef(Name)];337 Symbol *&sym = symMap[CachedHashStringRef(name)];
292 if (!Sym) {338 if (!sym) {
293 Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());339 sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
294 Sym->IsUsedInRegularObj = false;340 sym->isUsedInRegularObj = false;
295 Sym->PendingArchiveLoad = false;341 sym->pendingArchiveLoad = false;
296 Inserted = true;342 inserted = true;
297 }343 }
298 return {Sym, Inserted};344 return {sym, inserted};
299}345}
300346
301std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) {347std::pair<Symbol *, bool> SymbolTable::insert(StringRef name, InputFile *file) {
302 std::pair<Symbol *, bool> Result = insert(Name);348 std::pair<Symbol *, bool> result = insert(name);
303 if (!File || !isa<BitcodeFile>(File))349 if (!file || !isa<BitcodeFile>(file))
304 Result.first->IsUsedInRegularObj = true;350 result.first->isUsedInRegularObj = true;
305 return Result;351 return result;
306}352}
307353
308Symbol *SymbolTable::addUndefined(StringRef Name, InputFile *F,354Symbol *SymbolTable::addUndefined(StringRef name, InputFile *f,
309 bool IsWeakAlias) {355 bool isWeakAlias) {
310 Symbol *S;356 Symbol *s;
311 bool WasInserted;357 bool wasInserted;
312 std::tie(S, WasInserted) = insert(Name, F);358 std::tie(s, wasInserted) = insert(name, f);
313 if (WasInserted || (isa<Lazy>(S) && IsWeakAlias)) {359 if (wasInserted || (isa<Lazy>(s) && isWeakAlias)) {
314 replaceSymbol<Undefined>(S, Name);360 replaceSymbol<Undefined>(s, name);
315 return S;361 return s;
316 }362 }
317 if (auto *L = dyn_cast<Lazy>(S)) {363 if (auto *l = dyn_cast<Lazy>(s)) {
318 if (!S->PendingArchiveLoad) {364 if (!s->pendingArchiveLoad) {
319 S->PendingArchiveLoad = true;365 s->pendingArchiveLoad = true;
320 L->File->addMember(&L->Sym);366 l->file->addMember(&l->sym);
321 }367 }
322 }368 }
323 return S;369 return s;
324}370}
325371
326void SymbolTable::addLazy(ArchiveFile *F, const Archive::Symbol Sym) {372void SymbolTable::addLazy(ArchiveFile *f, const Archive::Symbol sym) {
327 StringRef Name = Sym.getName();373 StringRef name = sym.getName();
328 Symbol *S;374 Symbol *s;
329 bool WasInserted;375 bool wasInserted;
330 std::tie(S, WasInserted) = insert(Name);376 std::tie(s, wasInserted) = insert(name);
331 if (WasInserted) {377 if (wasInserted) {
332 replaceSymbol<Lazy>(S, F, Sym);378 replaceSymbol<Lazy>(s, f, sym);
333 return;379 return;
334 }380 }
335 auto *U = dyn_cast<Undefined>(S);381 auto *u = dyn_cast<Undefined>(s);
336 if (!U || U->WeakAlias || S->PendingArchiveLoad)382 if (!u || u->weakAlias || s->pendingArchiveLoad)
337 return;383 return;
338 S->PendingArchiveLoad = true;384 s->pendingArchiveLoad = true;
339 F->addMember(&Sym);385 f->addMember(&sym);
340}386}
341387
342void SymbolTable::reportDuplicate(Symbol *Existing, InputFile *NewFile) {388void SymbolTable::reportDuplicate(Symbol *existing, InputFile *newFile) {
343 std::string Msg = "duplicate symbol: " + toString(*Existing) + " in " +389 std::string msg = "duplicate symbol: " + toString(*existing) + " in " +
344 toString(Existing->getFile()) + " and in " +390 toString(existing->getFile()) + " and in " +
345 toString(NewFile);391 toString(newFile);
346392
347 if (Config->ForceMultiple)393 if (config->forceMultiple)
348 warn(Msg);394 warn(msg);
349 else395 else
350 error(Msg);396 error(msg);
351}397}
352398
353Symbol *SymbolTable::addAbsolute(StringRef N, COFFSymbolRef Sym) {399Symbol *SymbolTable::addAbsolute(StringRef n, COFFSymbolRef sym) {
354 Symbol *S;400 Symbol *s;
355 bool WasInserted;401 bool wasInserted;
356 std::tie(S, WasInserted) = insert(N, nullptr);402 std::tie(s, wasInserted) = insert(n, nullptr);
357 S->IsUsedInRegularObj = true;403 s->isUsedInRegularObj = true;
358 if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))404 if (wasInserted || isa<Undefined>(s) || isa<Lazy>(s))
359 replaceSymbol<DefinedAbsolute>(S, N, Sym);405 replaceSymbol<DefinedAbsolute>(s, n, sym);
360 else if (!isa<DefinedCOFF>(S))406 else if (!isa<DefinedCOFF>(s))
361 reportDuplicate(S, nullptr);407 reportDuplicate(s, nullptr);
362 return S;408 return s;
363}409}
364410
365Symbol *SymbolTable::addAbsolute(StringRef N, uint64_t VA) {411Symbol *SymbolTable::addAbsolute(StringRef n, uint64_t va) {
366 Symbol *S;412 Symbol *s;
367 bool WasInserted;413 bool wasInserted;
368 std::tie(S, WasInserted) = insert(N, nullptr);414 std::tie(s, wasInserted) = insert(n, nullptr);
369 S->IsUsedInRegularObj = true;415 s->isUsedInRegularObj = true;
370 if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))416 if (wasInserted || isa<Undefined>(s) || isa<Lazy>(s))
371 replaceSymbol<DefinedAbsolute>(S, N, VA);417 replaceSymbol<DefinedAbsolute>(s, n, va);
372 else if (!isa<DefinedCOFF>(S))418 else if (!isa<DefinedCOFF>(s))
373 reportDuplicate(S, nullptr);419 reportDuplicate(s, nullptr);
374 return S;420 return s;
375}421}
376422
377Symbol *SymbolTable::addSynthetic(StringRef N, Chunk *C) {423Symbol *SymbolTable::addSynthetic(StringRef n, Chunk *c) {
378 Symbol *S;424 Symbol *s;
379 bool WasInserted;425 bool wasInserted;
380 std::tie(S, WasInserted) = insert(N, nullptr);426 std::tie(s, wasInserted) = insert(n, nullptr);
381 S->IsUsedInRegularObj = true;427 s->isUsedInRegularObj = true;
382 if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S))428 if (wasInserted || isa<Undefined>(s) || isa<Lazy>(s))
383 replaceSymbol<DefinedSynthetic>(S, N, C);429 replaceSymbol<DefinedSynthetic>(s, n, c);
384 else if (!isa<DefinedCOFF>(S))430 else if (!isa<DefinedCOFF>(s))
385 reportDuplicate(S, nullptr);431 reportDuplicate(s, nullptr);
386 return S;432 return s;
387}433}
388434
389Symbol *SymbolTable::addRegular(InputFile *F, StringRef N,435Symbol *SymbolTable::addRegular(InputFile *f, StringRef n,
390 const coff_symbol_generic *Sym,436 const coff_symbol_generic *sym,
391 SectionChunk *C) {437 SectionChunk *c) {
392 Symbol *S;438 Symbol *s;
393 bool WasInserted;439 bool wasInserted;
394 std::tie(S, WasInserted) = insert(N, F);440 std::tie(s, wasInserted) = insert(n, f);
395 if (WasInserted || !isa<DefinedRegular>(S))441 if (wasInserted || !isa<DefinedRegular>(s))
396 replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ false,442 replaceSymbol<DefinedRegular>(s, f, n, /*IsCOMDAT*/ false,
397 /*IsExternal*/ true, Sym, C);443 /*IsExternal*/ true, sym, c);
398 else444 else
399 reportDuplicate(S, F);445 reportDuplicate(s, f);
400 return S;446 return s;
401}447}
402448
403std::pair<Symbol *, bool>449std::pair<DefinedRegular *, bool>
404SymbolTable::addComdat(InputFile *F, StringRef N,450SymbolTable::addComdat(InputFile *f, StringRef n,
405 const coff_symbol_generic *Sym) {451 const coff_symbol_generic *sym) {
406 Symbol *S;452 Symbol *s;
407 bool WasInserted;453 bool wasInserted;
408 std::tie(S, WasInserted) = insert(N, F);454 std::tie(s, wasInserted) = insert(n, f);
409 if (WasInserted || !isa<DefinedRegular>(S)) {455 if (wasInserted || !isa<DefinedRegular>(s)) {
410 replaceSymbol<DefinedRegular>(S, F, N, /*IsCOMDAT*/ true,456 replaceSymbol<DefinedRegular>(s, f, n, /*IsCOMDAT*/ true,
411 /*IsExternal*/ true, Sym, nullptr);457 /*IsExternal*/ true, sym, nullptr);
412 return {S, true};458 return {cast<DefinedRegular>(s), true};
413 }459 }
414 if (!cast<DefinedRegular>(S)->isCOMDAT())460 auto *existingSymbol = cast<DefinedRegular>(s);
415 reportDuplicate(S, F);461 if (!existingSymbol->isCOMDAT)
416 return {S, false};462 reportDuplicate(s, f);
463 return {existingSymbol, false};
417}464}
418465
419Symbol *SymbolTable::addCommon(InputFile *F, StringRef N, uint64_t Size,466Symbol *SymbolTable::addCommon(InputFile *f, StringRef n, uint64_t size,
420 const coff_symbol_generic *Sym, CommonChunk *C) {467 const coff_symbol_generic *sym, CommonChunk *c) {
421 Symbol *S;468 Symbol *s;
422 bool WasInserted;469 bool wasInserted;
423 std::tie(S, WasInserted) = insert(N, F);470 std::tie(s, wasInserted) = insert(n, f);
424 if (WasInserted || !isa<DefinedCOFF>(S))471 if (wasInserted || !isa<DefinedCOFF>(s))
425 replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C);472 replaceSymbol<DefinedCommon>(s, f, n, size, sym, c);
426 else if (auto *DC = dyn_cast<DefinedCommon>(S))473 else if (auto *dc = dyn_cast<DefinedCommon>(s))
427 if (Size > DC->getSize())474 if (size > dc->getSize())
428 replaceSymbol<DefinedCommon>(S, F, N, Size, Sym, C);475 replaceSymbol<DefinedCommon>(s, f, n, size, sym, c);
429 return S;476 return s;
430}477}
431478
432Symbol *SymbolTable::addImportData(StringRef N, ImportFile *F) {479Symbol *SymbolTable::addImportData(StringRef n, ImportFile *f) {
433 Symbol *S;480 Symbol *s;
434 bool WasInserted;481 bool wasInserted;
435 std::tie(S, WasInserted) = insert(N, nullptr);482 std::tie(s, wasInserted) = insert(n, nullptr);
436 S->IsUsedInRegularObj = true;483 s->isUsedInRegularObj = true;
437 if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {484 if (wasInserted || isa<Undefined>(s) || isa<Lazy>(s)) {
438 replaceSymbol<DefinedImportData>(S, N, F);485 replaceSymbol<DefinedImportData>(s, n, f);
439 return S;486 return s;
440 }487 }
441488
442 reportDuplicate(S, F);489 reportDuplicate(s, f);
443 return nullptr;490 return nullptr;
444}491}
445492
446Symbol *SymbolTable::addImportThunk(StringRef Name, DefinedImportData *ID,493Symbol *SymbolTable::addImportThunk(StringRef name, DefinedImportData *id,
447 uint16_t Machine) {494 uint16_t machine) {
448 Symbol *S;495 Symbol *s;
449 bool WasInserted;496 bool wasInserted;
450 std::tie(S, WasInserted) = insert(Name, nullptr);497 std::tie(s, wasInserted) = insert(name, nullptr);
451 S->IsUsedInRegularObj = true;498 s->isUsedInRegularObj = true;
452 if (WasInserted || isa<Undefined>(S) || isa<Lazy>(S)) {499 if (wasInserted || isa<Undefined>(s) || isa<Lazy>(s)) {
453 replaceSymbol<DefinedImportThunk>(S, Name, ID, Machine);500 replaceSymbol<DefinedImportThunk>(s, name, id, machine);
454 return S;501 return s;
455 }502 }
456503
457 reportDuplicate(S, ID->File);504 reportDuplicate(s, id->file);
458 return nullptr;505 return nullptr;
459}506}
460507
461std::vector<Chunk *> SymbolTable::getChunks() {508std::vector<Chunk *> SymbolTable::getChunks() {
462 std::vector<Chunk *> Res;509 std::vector<Chunk *> res;
463 for (ObjFile *File : ObjFile::Instances) {510 for (ObjFile *file : ObjFile::instances) {
464 ArrayRef<Chunk *> V = File->getChunks();511 ArrayRef<Chunk *> v = file->getChunks();
465 Res.insert(Res.end(), V.begin(), V.end());512 res.insert(res.end(), v.begin(), v.end());
466 }513 }
467 return Res;514 return res;
468}515}
469516
470Symbol *SymbolTable::find(StringRef Name) {517Symbol *SymbolTable::find(StringRef name) {
471 return SymMap.lookup(CachedHashStringRef(Name));518 return symMap.lookup(CachedHashStringRef(name));
472}519}
473520
474Symbol *SymbolTable::findUnderscore(StringRef Name) {521Symbol *SymbolTable::findUnderscore(StringRef name) {
475 if (Config->Machine == I386)522 if (config->machine == I386)
476 return find(("_" + Name).str());523 return find(("_" + name).str());
477 return find(Name);524 return find(name);
478}525}
479526
480StringRef SymbolTable::findByPrefix(StringRef Prefix) {527// Return all symbols that start with Prefix, possibly ignoring the first
481 for (auto Pair : SymMap) {528// character of Prefix or the first character symbol.
482 StringRef Name = Pair.first.val();529std::vector<Symbol *> SymbolTable::getSymsWithPrefix(StringRef prefix) {
483 if (Name.startswith(Prefix))530 std::vector<Symbol *> syms;
484 return Name;531 for (auto pair : symMap) {
532 StringRef name = pair.first.val();
533 if (name.startswith(prefix) || name.startswith(prefix.drop_front()) ||
534 name.drop_front().startswith(prefix) ||
535 name.drop_front().startswith(prefix.drop_front())) {
536 syms.push_back(pair.second);
537 }
485 }538 }
486 return "";539 return syms;
487}540}
488541
489StringRef SymbolTable::findMangle(StringRef Name) {542Symbol *SymbolTable::findMangle(StringRef name) {
490 if (Symbol *Sym = find(Name))543 if (Symbol *sym = find(name))
491 if (!isa<Undefined>(Sym))544 if (!isa<Undefined>(sym))
492 return Name;545 return sym;
493 if (Config->Machine != I386)546
494 return findByPrefix(("?" + Name + "@@Y").str());547 // Efficient fuzzy string lookup is impossible with a hash table, so iterate
495 if (!Name.startswith("_"))548 // the symbol table once and collect all possibly matching symbols into this
496 return "";549 // vector. Then compare each possibly matching symbol with each possible
550 // mangling.
551 std::vector<Symbol *> syms = getSymsWithPrefix(name);
552 auto findByPrefix = [&syms](const Twine &t) -> Symbol * {
553 std::string prefix = t.str();
554 for (auto *s : syms)
555 if (s->getName().startswith(prefix))
556 return s;
557 return nullptr;
558 };
559
560 // For non-x86, just look for C++ functions.
561 if (config->machine != I386)
562 return findByPrefix("?" + name + "@@Y");
563
564 if (!name.startswith("_"))
565 return nullptr;
497 // Search for x86 stdcall function.566 // Search for x86 stdcall function.
498 StringRef S = findByPrefix((Name + "@").str());567 if (Symbol *s = findByPrefix(name + "@"))
499 if (!S.empty())568 return s;
500 return S;
501 // Search for x86 fastcall function.569 // Search for x86 fastcall function.
502 S = findByPrefix(("@" + Name.substr(1) + "@").str());570 if (Symbol *s = findByPrefix("@" + name.substr(1) + "@"))
503 if (!S.empty())571 return s;
504 return S;
505 // Search for x86 vectorcall function.572 // Search for x86 vectorcall function.
506 S = findByPrefix((Name.substr(1) + "@@").str());573 if (Symbol *s = findByPrefix(name.substr(1) + "@@"))
507 if (!S.empty())574 return s;
508 return S;
509 // Search for x86 C++ non-member function.575 // Search for x86 C++ non-member function.
510 return findByPrefix(("?" + Name.substr(1) + "@@Y").str());576 return findByPrefix("?" + name.substr(1) + "@@Y");
511}
512
513void SymbolTable::mangleMaybe(Symbol *B) {
514 auto *U = dyn_cast<Undefined>(B);
515 if (!U || U->WeakAlias)
516 return;
517 StringRef Alias = findMangle(U->getName());
518 if (!Alias.empty()) {
519 log(U->getName() + " aliased to " + Alias);
520 U->WeakAlias = addUndefined(Alias);
521 }
522}577}
523578
524Symbol *SymbolTable::addUndefined(StringRef Name) {579Symbol *SymbolTable::addUndefined(StringRef name) {
525 return addUndefined(Name, nullptr, false);580 return addUndefined(name, nullptr, false);
526}581}
527582
528std::vector<StringRef> SymbolTable::compileBitcodeFiles() {583std::vector<StringRef> SymbolTable::compileBitcodeFiles() {
529 LTO.reset(new BitcodeCompiler);584 lto.reset(new BitcodeCompiler);
530 for (BitcodeFile *F : BitcodeFile::Instances)585 for (BitcodeFile *f : BitcodeFile::instances)
531 LTO->add(*F);586 lto->add(*f);
532 return LTO->compile();587 return lto->compile();
533}588}
534589
535void SymbolTable::addCombinedLTOObjects() {590void SymbolTable::addCombinedLTOObjects() {
536 if (BitcodeFile::Instances.empty())591 if (BitcodeFile::instances.empty())
537 return;592 return;
538593
539 ScopedTimer T(LTOTimer);594 ScopedTimer t(ltoTimer);
540 for (StringRef Object : compileBitcodeFiles()) {595 for (StringRef object : compileBitcodeFiles()) {
541 auto *Obj = make<ObjFile>(MemoryBufferRef(Object, "lto.tmp"));596 auto *obj = make<ObjFile>(MemoryBufferRef(object, "lto.tmp"));
542 Obj->parse();597 obj->parse();
543 ObjFile::Instances.push_back(Obj);598 ObjFile::instances.push_back(obj);
544 }599 }
545}600}
546601
deps/lld/COFF/SymbolTable.h+44-44
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- SymbolTable.h --------------------------------------------*- C++ -*-===//1//===- SymbolTable.h --------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -28,6 +27,7 @@ class Chunk;...@@ -28,6 +27,7 @@ class Chunk;
28class CommonChunk;27class CommonChunk;
29class Defined;28class Defined;
30class DefinedAbsolute;29class DefinedAbsolute;
30class DefinedRegular;
31class DefinedRelative;31class DefinedRelative;
32class Lazy;32class Lazy;
33class SectionChunk;33class SectionChunk;
...@@ -47,7 +47,7 @@ class Symbol;...@@ -47,7 +47,7 @@ class Symbol;
47// There is one add* function per symbol type.47// There is one add* function per symbol type.
48class SymbolTable {48class SymbolTable {
49public:49public:
50 void addFile(InputFile *File);50 void addFile(InputFile *file);
5151
52 // Try to resolve any undefined symbols and update the symbol table52 // Try to resolve any undefined symbols and update the symbol table
53 // accordingly, then print an error message for any remaining undefined53 // accordingly, then print an error message for any remaining undefined
...@@ -55,21 +55,20 @@ public:...@@ -55,21 +55,20 @@ public:
55 void reportRemainingUndefines();55 void reportRemainingUndefines();
5656
57 void loadMinGWAutomaticImports();57 void loadMinGWAutomaticImports();
58 bool handleMinGWAutomaticImport(Symbol *Sym, StringRef Name);58 bool handleMinGWAutomaticImport(Symbol *sym, StringRef name);
5959
60 // Returns a list of chunks of selected symbols.60 // Returns a list of chunks of selected symbols.
61 std::vector<Chunk *> getChunks();61 std::vector<Chunk *> getChunks();
6262
63 // Returns a symbol for a given name. Returns a nullptr if not found.63 // Returns a symbol for a given name. Returns a nullptr if not found.
64 Symbol *find(StringRef Name);64 Symbol *find(StringRef name);
65 Symbol *findUnderscore(StringRef Name);65 Symbol *findUnderscore(StringRef name);
6666
67 // Occasionally we have to resolve an undefined symbol to its67 // Occasionally we have to resolve an undefined symbol to its
68 // mangled symbol. This function tries to find a mangled name68 // mangled symbol. This function tries to find a mangled name
69 // for U from the symbol table, and if found, set the symbol as69 // for U from the symbol table, and if found, set the symbol as
70 // a weak alias for U.70 // a weak alias for U.
71 void mangleMaybe(Symbol *B);71 Symbol *findMangle(StringRef name);
72 StringRef findMangle(StringRef Name);
7372
74 // Build a set of COFF objects representing the combined contents of73 // Build a set of COFF objects representing the combined contents of
75 // BitcodeFiles and add them to the symbol table. Called after all files are74 // BitcodeFiles and add them to the symbol table. Called after all files are
...@@ -78,52 +77,53 @@ public:...@@ -78,52 +77,53 @@ public:
78 std::vector<StringRef> compileBitcodeFiles();77 std::vector<StringRef> compileBitcodeFiles();
7978
80 // Creates an Undefined symbol for a given name.79 // Creates an Undefined symbol for a given name.
81 Symbol *addUndefined(StringRef Name);80 Symbol *addUndefined(StringRef name);
8281
83 Symbol *addSynthetic(StringRef N, Chunk *C);82 Symbol *addSynthetic(StringRef n, Chunk *c);
84 Symbol *addAbsolute(StringRef N, uint64_t VA);83 Symbol *addAbsolute(StringRef n, uint64_t va);
8584
86 Symbol *addUndefined(StringRef Name, InputFile *F, bool IsWeakAlias);85 Symbol *addUndefined(StringRef name, InputFile *f, bool isWeakAlias);
87 void addLazy(ArchiveFile *F, const Archive::Symbol Sym);86 void addLazy(ArchiveFile *f, const Archive::Symbol sym);
88 Symbol *addAbsolute(StringRef N, COFFSymbolRef S);87 Symbol *addAbsolute(StringRef n, COFFSymbolRef s);
89 Symbol *addRegular(InputFile *F, StringRef N,88 Symbol *addRegular(InputFile *f, StringRef n,
90 const llvm::object::coff_symbol_generic *S = nullptr,89 const llvm::object::coff_symbol_generic *s = nullptr,
91 SectionChunk *C = nullptr);90 SectionChunk *c = nullptr);
92 std::pair<Symbol *, bool>91 std::pair<DefinedRegular *, bool>
93 addComdat(InputFile *F, StringRef N,92 addComdat(InputFile *f, StringRef n,
94 const llvm::object::coff_symbol_generic *S = nullptr);93 const llvm::object::coff_symbol_generic *s = nullptr);
95 Symbol *addCommon(InputFile *F, StringRef N, uint64_t Size,94 Symbol *addCommon(InputFile *f, StringRef n, uint64_t size,
96 const llvm::object::coff_symbol_generic *S = nullptr,95 const llvm::object::coff_symbol_generic *s = nullptr,
97 CommonChunk *C = nullptr);96 CommonChunk *c = nullptr);
98 Symbol *addImportData(StringRef N, ImportFile *F);97 Symbol *addImportData(StringRef n, ImportFile *f);
99 Symbol *addImportThunk(StringRef Name, DefinedImportData *S,98 Symbol *addImportThunk(StringRef name, DefinedImportData *s,
100 uint16_t Machine);99 uint16_t machine);
101100
102 void reportDuplicate(Symbol *Existing, InputFile *NewFile);101 void reportDuplicate(Symbol *existing, InputFile *newFile);
103102
104 // A list of chunks which to be added to .rdata.103 // A list of chunks which to be added to .rdata.
105 std::vector<Chunk *> LocalImportChunks;104 std::vector<Chunk *> localImportChunks;
106105
107 // Iterates symbols in non-determinstic hash table order.106 // Iterates symbols in non-determinstic hash table order.
108 template <typename T> void forEachSymbol(T Callback) {107 template <typename T> void forEachSymbol(T callback) {
109 for (auto &Pair : SymMap)108 for (auto &pair : symMap)
110 Callback(Pair.second);109 callback(pair.second);
111 }110 }
112111
113private:112private:
114 /// Inserts symbol if not already present.113 /// Inserts symbol if not already present.
115 std::pair<Symbol *, bool> insert(StringRef Name);114 std::pair<Symbol *, bool> insert(StringRef name);
116 /// Same as insert(Name), but also sets IsUsedInRegularObj.115 /// Same as insert(Name), but also sets isUsedInRegularObj.
117 std::pair<Symbol *, bool> insert(StringRef Name, InputFile *F);116 std::pair<Symbol *, bool> insert(StringRef name, InputFile *f);
118 StringRef findByPrefix(StringRef Prefix);117
118 std::vector<Symbol *> getSymsWithPrefix(StringRef prefix);
119119
120 llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> SymMap;120 llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> symMap;
121 std::unique_ptr<BitcodeCompiler> LTO;121 std::unique_ptr<BitcodeCompiler> lto;
122};122};
123123
124extern SymbolTable *Symtab;124extern SymbolTable *symtab;
125125
126std::string getSymbolLocations(ObjFile *File, uint32_t SymIndex);126std::vector<std::string> getSymbolLocations(ObjFile *file, uint32_t symIndex);
127127
128} // namespace coff128} // namespace coff
129} // namespace lld129} // namespace lld
deps/lld/COFF/Symbols.cpp+58-48
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Symbols.cpp --------------------------------------------------------===//1//===- Symbols.cpp --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -19,11 +18,17 @@...@@ -19,11 +18,17 @@
19using namespace llvm;18using namespace llvm;
20using namespace llvm::object;19using namespace llvm::object;
2120
21using namespace lld::coff;
22
23static_assert(sizeof(SymbolUnion) <= 48,
24 "symbols should be optimized for memory usage");
25
22// Returns a symbol name for an error message.26// Returns a symbol name for an error message.
23std::string lld::toString(coff::Symbol &B) {27std::string lld::toString(coff::Symbol &b) {
24 if (Optional<std::string> S = lld::demangleMSVC(B.getName()))28 if (config->demangle)
25 return ("\"" + *S + "\" (" + B.getName() + ")").str();29 if (Optional<std::string> s = lld::demangleMSVC(b.getName()))
26 return B.getName();30 return *s;
31 return b.getName();
27}32}
2833
29namespace lld {34namespace lld {
...@@ -37,70 +42,75 @@ StringRef Symbol::getName() {...@@ -37,70 +42,75 @@ StringRef Symbol::getName() {
37 // name. Object files contain lots of non-external symbols, and creating42 // name. Object files contain lots of non-external symbols, and creating
38 // StringRefs for them (which involves lots of strlen() on the string table)43 // StringRefs for them (which involves lots of strlen() on the string table)
39 // is a waste of time.44 // is a waste of time.
40 if (Name.empty()) {45 if (nameData == nullptr) {
41 auto *D = cast<DefinedCOFF>(this);46 auto *d = cast<DefinedCOFF>(this);
42 cast<ObjFile>(D->File)->getCOFFObj()->getSymbolName(D->Sym, Name);47 StringRef nameStr;
48 cast<ObjFile>(d->file)->getCOFFObj()->getSymbolName(d->sym, nameStr);
49 nameData = nameStr.data();
50 nameSize = nameStr.size();
51 assert(nameSize == nameStr.size() && "name length truncated");
43 }52 }
44 return Name;53 return StringRef(nameData, nameSize);
45}54}
4655
47InputFile *Symbol::getFile() {56InputFile *Symbol::getFile() {
48 if (auto *Sym = dyn_cast<DefinedCOFF>(this))57 if (auto *sym = dyn_cast<DefinedCOFF>(this))
49 return Sym->File;58 return sym->file;
50 if (auto *Sym = dyn_cast<Lazy>(this))59 if (auto *sym = dyn_cast<Lazy>(this))
51 return Sym->File;60 return sym->file;
52 return nullptr;61 return nullptr;
53}62}
5463
55bool Symbol::isLive() const {64bool Symbol::isLive() const {
56 if (auto *R = dyn_cast<DefinedRegular>(this))65 if (auto *r = dyn_cast<DefinedRegular>(this))
57 return R->getChunk()->Live;66 return r->getChunk()->live;
58 if (auto *Imp = dyn_cast<DefinedImportData>(this))67 if (auto *imp = dyn_cast<DefinedImportData>(this))
59 return Imp->File->Live;68 return imp->file->live;
60 if (auto *Imp = dyn_cast<DefinedImportThunk>(this))69 if (auto *imp = dyn_cast<DefinedImportThunk>(this))
61 return Imp->WrappedSym->File->ThunkLive;70 return imp->wrappedSym->file->thunkLive;
62 // Assume any other kind of symbol is live.71 // Assume any other kind of symbol is live.
63 return true;72 return true;
64}73}
6574
66// MinGW specific.75// MinGW specific.
67void Symbol::replaceKeepingName(Symbol *Other, size_t Size) {76void Symbol::replaceKeepingName(Symbol *other, size_t size) {
68 StringRef OrigName = Name;77 StringRef origName = getName();
69 memcpy(this, Other, Size);78 memcpy(this, other, size);
70 Name = OrigName;79 nameData = origName.data();
80 nameSize = origName.size();
71}81}
7282
73COFFSymbolRef DefinedCOFF::getCOFFSymbol() {83COFFSymbolRef DefinedCOFF::getCOFFSymbol() {
74 size_t SymSize = cast<ObjFile>(File)->getCOFFObj()->getSymbolTableEntrySize();84 size_t symSize = cast<ObjFile>(file)->getCOFFObj()->getSymbolTableEntrySize();
75 if (SymSize == sizeof(coff_symbol16))85 if (symSize == sizeof(coff_symbol16))
76 return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(Sym));86 return COFFSymbolRef(reinterpret_cast<const coff_symbol16 *>(sym));
77 assert(SymSize == sizeof(coff_symbol32));87 assert(symSize == sizeof(coff_symbol32));
78 return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(Sym));88 return COFFSymbolRef(reinterpret_cast<const coff_symbol32 *>(sym));
79}89}
8090
81uint16_t DefinedAbsolute::NumOutputSections;91uint16_t DefinedAbsolute::numOutputSections;
8292
83static Chunk *makeImportThunk(DefinedImportData *S, uint16_t Machine) {93static Chunk *makeImportThunk(DefinedImportData *s, uint16_t machine) {
84 if (Machine == AMD64)94 if (machine == AMD64)
85 return make<ImportThunkChunkX64>(S);95 return make<ImportThunkChunkX64>(s);
86 if (Machine == I386)96 if (machine == I386)
87 return make<ImportThunkChunkX86>(S);97 return make<ImportThunkChunkX86>(s);
88 if (Machine == ARM64)98 if (machine == ARM64)
89 return make<ImportThunkChunkARM64>(S);99 return make<ImportThunkChunkARM64>(s);
90 assert(Machine == ARMNT);100 assert(machine == ARMNT);
91 return make<ImportThunkChunkARM>(S);101 return make<ImportThunkChunkARM>(s);
92}102}
93103
94DefinedImportThunk::DefinedImportThunk(StringRef Name, DefinedImportData *S,104DefinedImportThunk::DefinedImportThunk(StringRef name, DefinedImportData *s,
95 uint16_t Machine)105 uint16_t machine)
96 : Defined(DefinedImportThunkKind, Name), WrappedSym(S),106 : Defined(DefinedImportThunkKind, name), wrappedSym(s),
97 Data(makeImportThunk(S, Machine)) {}107 data(makeImportThunk(s, machine)) {}
98108
99Defined *Undefined::getWeakAlias() {109Defined *Undefined::getWeakAlias() {
100 // A weak alias may be a weak alias to another symbol, so check recursively.110 // A weak alias may be a weak alias to another symbol, so check recursively.
101 for (Symbol *A = WeakAlias; A; A = cast<Undefined>(A)->WeakAlias)111 for (Symbol *a = weakAlias; a; a = cast<Undefined>(a)->weakAlias)
102 if (auto *D = dyn_cast<Defined>(A))112 if (auto *d = dyn_cast<Defined>(a))
103 return D;113 return d;
104 return nullptr;114 return nullptr;
105}115}
106} // namespace coff116} // namespace coff
deps/lld/COFF/Symbols.h+121-122
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Symbols.h ------------------------------------------------*- C++ -*-===//1//===- Symbols.h ------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -58,15 +57,12 @@ public:...@@ -58,15 +57,12 @@ public:
58 LastDefinedKind = DefinedSyntheticKind,57 LastDefinedKind = DefinedSyntheticKind,
59 };58 };
6059
61 Kind kind() const { return static_cast<Kind>(SymbolKind); }60 Kind kind() const { return static_cast<Kind>(symbolKind); }
62
63 // Returns true if this is an external symbol.
64 bool isExternal() { return IsExternal; }
6561
66 // Returns the symbol name.62 // Returns the symbol name.
67 StringRef getName();63 StringRef getName();
6864
69 void replaceKeepingName(Symbol *Other, size_t Size);65 void replaceKeepingName(Symbol *other, size_t size);
7066
71 // Returns the file from which this symbol was created.67 // Returns the file from which this symbol was created.
72 InputFile *getFile();68 InputFile *getFile();
...@@ -77,46 +73,50 @@ public:...@@ -77,46 +73,50 @@ public:
7773
78protected:74protected:
79 friend SymbolTable;75 friend SymbolTable;
80 explicit Symbol(Kind K, StringRef N = "")76 explicit Symbol(Kind k, StringRef n = "")
81 : SymbolKind(K), IsExternal(true), IsCOMDAT(false),77 : symbolKind(k), isExternal(true), isCOMDAT(false),
82 WrittenToSymtab(false), PendingArchiveLoad(false), IsGCRoot(false),78 writtenToSymtab(false), pendingArchiveLoad(false), isGCRoot(false),
83 IsRuntimePseudoReloc(false), Name(N) {}79 isRuntimePseudoReloc(false), nameSize(n.size()),
80 nameData(n.empty() ? nullptr : n.data()) {}
8481
85 const unsigned SymbolKind : 8;82 const unsigned symbolKind : 8;
86 unsigned IsExternal : 1;83 unsigned isExternal : 1;
8784
85public:
88 // This bit is used by the \c DefinedRegular subclass.86 // This bit is used by the \c DefinedRegular subclass.
89 unsigned IsCOMDAT : 1;87 unsigned isCOMDAT : 1;
9088
91public:
92 // This bit is used by Writer::createSymbolAndStringTable() to prevent89 // This bit is used by Writer::createSymbolAndStringTable() to prevent
93 // symbols from being written to the symbol table more than once.90 // symbols from being written to the symbol table more than once.
94 unsigned WrittenToSymtab : 1;91 unsigned writtenToSymtab : 1;
9592
96 // True if this symbol was referenced by a regular (non-bitcode) object.93 // True if this symbol was referenced by a regular (non-bitcode) object.
97 unsigned IsUsedInRegularObj : 1;94 unsigned isUsedInRegularObj : 1;
9895
99 // True if we've seen both a lazy and an undefined symbol with this symbol96 // True if we've seen both a lazy and an undefined symbol with this symbol
100 // name, which means that we have enqueued an archive member load and should97 // name, which means that we have enqueued an archive member load and should
101 // not load any more archive members to resolve the same symbol.98 // not load any more archive members to resolve the same symbol.
102 unsigned PendingArchiveLoad : 1;99 unsigned pendingArchiveLoad : 1;
103100
104 /// True if we've already added this symbol to the list of GC roots.101 /// True if we've already added this symbol to the list of GC roots.
105 unsigned IsGCRoot : 1;102 unsigned isGCRoot : 1;
106103
107 unsigned IsRuntimePseudoReloc : 1;104 unsigned isRuntimePseudoReloc : 1;
108105
109protected:106protected:
110 StringRef Name;107 // Symbol name length. Assume symbol lengths fit in a 32-bit integer.
108 uint32_t nameSize;
109
110 const char *nameData;
111};111};
112112
113// The base class for any defined symbols, including absolute symbols,113// The base class for any defined symbols, including absolute symbols,
114// etc.114// etc.
115class Defined : public Symbol {115class Defined : public Symbol {
116public:116public:
117 Defined(Kind K, StringRef N) : Symbol(K, N) {}117 Defined(Kind k, StringRef n) : Symbol(k, n) {}
118118
119 static bool classof(const Symbol *S) { return S->kind() <= LastDefinedKind; }119 static bool classof(const Symbol *s) { return s->kind() <= LastDefinedKind; }
120120
121 // Returns the RVA (relative virtual address) of this symbol. The121 // Returns the RVA (relative virtual address) of this symbol. The
122 // writer sets and uses RVAs.122 // writer sets and uses RVAs.
...@@ -130,120 +130,119 @@ public:...@@ -130,120 +130,119 @@ public:
130// Symbols defined via a COFF object file or bitcode file. For COFF files, this130// Symbols defined via a COFF object file or bitcode file. For COFF files, this
131// stores a coff_symbol_generic*, and names of internal symbols are lazily131// stores a coff_symbol_generic*, and names of internal symbols are lazily
132// loaded through that. For bitcode files, Sym is nullptr and the name is stored132// loaded through that. For bitcode files, Sym is nullptr and the name is stored
133// as a StringRef.133// as a decomposed StringRef.
134class DefinedCOFF : public Defined {134class DefinedCOFF : public Defined {
135 friend Symbol;135 friend Symbol;
136136
137public:137public:
138 DefinedCOFF(Kind K, InputFile *F, StringRef N, const coff_symbol_generic *S)138 DefinedCOFF(Kind k, InputFile *f, StringRef n, const coff_symbol_generic *s)
139 : Defined(K, N), File(F), Sym(S) {}139 : Defined(k, n), file(f), sym(s) {}
140140
141 static bool classof(const Symbol *S) {141 static bool classof(const Symbol *s) {
142 return S->kind() <= LastDefinedCOFFKind;142 return s->kind() <= LastDefinedCOFFKind;
143 }143 }
144144
145 InputFile *getFile() { return File; }145 InputFile *getFile() { return file; }
146146
147 COFFSymbolRef getCOFFSymbol();147 COFFSymbolRef getCOFFSymbol();
148148
149 InputFile *File;149 InputFile *file;
150150
151protected:151protected:
152 const coff_symbol_generic *Sym;152 const coff_symbol_generic *sym;
153};153};
154154
155// Regular defined symbols read from object file symbol tables.155// Regular defined symbols read from object file symbol tables.
156class DefinedRegular : public DefinedCOFF {156class DefinedRegular : public DefinedCOFF {
157public:157public:
158 DefinedRegular(InputFile *F, StringRef N, bool IsCOMDAT,158 DefinedRegular(InputFile *f, StringRef n, bool isCOMDAT,
159 bool IsExternal = false,159 bool isExternal = false,
160 const coff_symbol_generic *S = nullptr,160 const coff_symbol_generic *s = nullptr,
161 SectionChunk *C = nullptr)161 SectionChunk *c = nullptr)
162 : DefinedCOFF(DefinedRegularKind, F, N, S), Data(C ? &C->Repl : nullptr) {162 : DefinedCOFF(DefinedRegularKind, f, n, s), data(c ? &c->repl : nullptr) {
163 this->IsExternal = IsExternal;163 this->isExternal = isExternal;
164 this->IsCOMDAT = IsCOMDAT;164 this->isCOMDAT = isCOMDAT;
165 }165 }
166166
167 static bool classof(const Symbol *S) {167 static bool classof(const Symbol *s) {
168 return S->kind() == DefinedRegularKind;168 return s->kind() == DefinedRegularKind;
169 }169 }
170170
171 uint64_t getRVA() const { return (*Data)->getRVA() + Sym->Value; }171 uint64_t getRVA() const { return (*data)->getRVA() + sym->Value; }
172 bool isCOMDAT() const { return IsCOMDAT; }172 SectionChunk *getChunk() const { return *data; }
173 SectionChunk *getChunk() const { return *Data; }173 uint32_t getValue() const { return sym->Value; }
174 uint32_t getValue() const { return Sym->Value; }
175174
176 SectionChunk **Data;175 SectionChunk **data;
177};176};
178177
179class DefinedCommon : public DefinedCOFF {178class DefinedCommon : public DefinedCOFF {
180public:179public:
181 DefinedCommon(InputFile *F, StringRef N, uint64_t Size,180 DefinedCommon(InputFile *f, StringRef n, uint64_t size,
182 const coff_symbol_generic *S = nullptr,181 const coff_symbol_generic *s = nullptr,
183 CommonChunk *C = nullptr)182 CommonChunk *c = nullptr)
184 : DefinedCOFF(DefinedCommonKind, F, N, S), Data(C), Size(Size) {183 : DefinedCOFF(DefinedCommonKind, f, n, s), data(c), size(size) {
185 this->IsExternal = true;184 this->isExternal = true;
186 }185 }
187186
188 static bool classof(const Symbol *S) {187 static bool classof(const Symbol *s) {
189 return S->kind() == DefinedCommonKind;188 return s->kind() == DefinedCommonKind;
190 }189 }
191190
192 uint64_t getRVA() { return Data->getRVA(); }191 uint64_t getRVA() { return data->getRVA(); }
193 CommonChunk *getChunk() { return Data; }192 CommonChunk *getChunk() { return data; }
194193
195private:194private:
196 friend SymbolTable;195 friend SymbolTable;
197 uint64_t getSize() const { return Size; }196 uint64_t getSize() const { return size; }
198 CommonChunk *Data;197 CommonChunk *data;
199 uint64_t Size;198 uint64_t size;
200};199};
201200
202// Absolute symbols.201// Absolute symbols.
203class DefinedAbsolute : public Defined {202class DefinedAbsolute : public Defined {
204public:203public:
205 DefinedAbsolute(StringRef N, COFFSymbolRef S)204 DefinedAbsolute(StringRef n, COFFSymbolRef s)
206 : Defined(DefinedAbsoluteKind, N), VA(S.getValue()) {205 : Defined(DefinedAbsoluteKind, n), va(s.getValue()) {
207 IsExternal = S.isExternal();206 isExternal = s.isExternal();
208 }207 }
209208
210 DefinedAbsolute(StringRef N, uint64_t V)209 DefinedAbsolute(StringRef n, uint64_t v)
211 : Defined(DefinedAbsoluteKind, N), VA(V) {}210 : Defined(DefinedAbsoluteKind, n), va(v) {}
212211
213 static bool classof(const Symbol *S) {212 static bool classof(const Symbol *s) {
214 return S->kind() == DefinedAbsoluteKind;213 return s->kind() == DefinedAbsoluteKind;
215 }214 }
216215
217 uint64_t getRVA() { return VA - Config->ImageBase; }216 uint64_t getRVA() { return va - config->imageBase; }
218 void setVA(uint64_t V) { VA = V; }217 void setVA(uint64_t v) { va = v; }
219218
220 // Section index relocations against absolute symbols resolve to219 // Section index relocations against absolute symbols resolve to
221 // this 16 bit number, and it is the largest valid section index220 // this 16 bit number, and it is the largest valid section index
222 // plus one. This variable keeps it.221 // plus one. This variable keeps it.
223 static uint16_t NumOutputSections;222 static uint16_t numOutputSections;
224223
225private:224private:
226 uint64_t VA;225 uint64_t va;
227};226};
228227
229// This symbol is used for linker-synthesized symbols like __ImageBase and228// This symbol is used for linker-synthesized symbols like __ImageBase and
230// __safe_se_handler_table.229// __safe_se_handler_table.
231class DefinedSynthetic : public Defined {230class DefinedSynthetic : public Defined {
232public:231public:
233 explicit DefinedSynthetic(StringRef Name, Chunk *C)232 explicit DefinedSynthetic(StringRef name, Chunk *c)
234 : Defined(DefinedSyntheticKind, Name), C(C) {}233 : Defined(DefinedSyntheticKind, name), c(c) {}
235234
236 static bool classof(const Symbol *S) {235 static bool classof(const Symbol *s) {
237 return S->kind() == DefinedSyntheticKind;236 return s->kind() == DefinedSyntheticKind;
238 }237 }
239238
240 // A null chunk indicates that this is __ImageBase. Otherwise, this is some239 // A null chunk indicates that this is __ImageBase. Otherwise, this is some
241 // other synthesized chunk, like SEHTableChunk.240 // other synthesized chunk, like SEHTableChunk.
242 uint32_t getRVA() { return C ? C->getRVA() : 0; }241 uint32_t getRVA() { return c ? c->getRVA() : 0; }
243 Chunk *getChunk() { return C; }242 Chunk *getChunk() { return c; }
244243
245private:244private:
246 Chunk *C;245 Chunk *c;
247};246};
248247
249// This class represents a symbol defined in an archive file. It is248// This class represents a symbol defined in an archive file. It is
...@@ -253,32 +252,32 @@ private:...@@ -253,32 +252,32 @@ private:
253// the same name, it will ask the Lazy to load a file.252// the same name, it will ask the Lazy to load a file.
254class Lazy : public Symbol {253class Lazy : public Symbol {
255public:254public:
256 Lazy(ArchiveFile *F, const Archive::Symbol S)255 Lazy(ArchiveFile *f, const Archive::Symbol s)
257 : Symbol(LazyKind, S.getName()), File(F), Sym(S) {}256 : Symbol(LazyKind, s.getName()), file(f), sym(s) {}
258257
259 static bool classof(const Symbol *S) { return S->kind() == LazyKind; }258 static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
260259
261 ArchiveFile *File;260 ArchiveFile *file;
262261
263private:262private:
264 friend SymbolTable;263 friend SymbolTable;
265264
266private:265private:
267 const Archive::Symbol Sym;266 const Archive::Symbol sym;
268};267};
269268
270// Undefined symbols.269// Undefined symbols.
271class Undefined : public Symbol {270class Undefined : public Symbol {
272public:271public:
273 explicit Undefined(StringRef N) : Symbol(UndefinedKind, N) {}272 explicit Undefined(StringRef n) : Symbol(UndefinedKind, n) {}
274273
275 static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; }274 static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; }
276275
277 // An undefined symbol can have a fallback symbol which gives an276 // An undefined symbol can have a fallback symbol which gives an
278 // undefined symbol a second chance if it would remain undefined.277 // undefined symbol a second chance if it would remain undefined.
279 // If it remains undefined, it'll be replaced with whatever the278 // If it remains undefined, it'll be replaced with whatever the
280 // Alias pointer points to.279 // Alias pointer points to.
281 Symbol *WeakAlias = nullptr;280 Symbol *weakAlias = nullptr;
282281
283 // If this symbol is external weak, try to resolve it to a defined282 // If this symbol is external weak, try to resolve it to a defined
284 // symbol by searching the chain of fallback symbols. Returns the symbol if283 // symbol by searching the chain of fallback symbols. Returns the symbol if
...@@ -294,23 +293,23 @@ public:...@@ -294,23 +293,23 @@ public:
294// table in an output. The former has "__imp_" prefix.293// table in an output. The former has "__imp_" prefix.
295class DefinedImportData : public Defined {294class DefinedImportData : public Defined {
296public:295public:
297 DefinedImportData(StringRef N, ImportFile *F)296 DefinedImportData(StringRef n, ImportFile *f)
298 : Defined(DefinedImportDataKind, N), File(F) {297 : Defined(DefinedImportDataKind, n), file(f) {
299 }298 }
300299
301 static bool classof(const Symbol *S) {300 static bool classof(const Symbol *s) {
302 return S->kind() == DefinedImportDataKind;301 return s->kind() == DefinedImportDataKind;
303 }302 }
304303
305 uint64_t getRVA() { return File->Location->getRVA(); }304 uint64_t getRVA() { return file->location->getRVA(); }
306 Chunk *getChunk() { return File->Location; }305 Chunk *getChunk() { return file->location; }
307 void setLocation(Chunk *AddressTable) { File->Location = AddressTable; }306 void setLocation(Chunk *addressTable) { file->location = addressTable; }
308307
309 StringRef getDLLName() { return File->DLLName; }308 StringRef getDLLName() { return file->dllName; }
310 StringRef getExternalName() { return File->ExternalName; }309 StringRef getExternalName() { return file->externalName; }
311 uint16_t getOrdinal() { return File->Hdr->OrdinalHint; }310 uint16_t getOrdinal() { return file->hdr->OrdinalHint; }
312311
313 ImportFile *File;312 ImportFile *file;
314};313};
315314
316// This class represents a symbol for a jump table entry which jumps315// This class represents a symbol for a jump table entry which jumps
...@@ -320,19 +319,19 @@ public:...@@ -320,19 +319,19 @@ public:
320// a regular name. A function pointer is given as a DefinedImportData.319// a regular name. A function pointer is given as a DefinedImportData.
321class DefinedImportThunk : public Defined {320class DefinedImportThunk : public Defined {
322public:321public:
323 DefinedImportThunk(StringRef Name, DefinedImportData *S, uint16_t Machine);322 DefinedImportThunk(StringRef name, DefinedImportData *s, uint16_t machine);
324323
325 static bool classof(const Symbol *S) {324 static bool classof(const Symbol *s) {
326 return S->kind() == DefinedImportThunkKind;325 return s->kind() == DefinedImportThunkKind;
327 }326 }
328327
329 uint64_t getRVA() { return Data->getRVA(); }328 uint64_t getRVA() { return data->getRVA(); }
330 Chunk *getChunk() { return Data; }329 Chunk *getChunk() { return data; }
331330
332 DefinedImportData *WrappedSym;331 DefinedImportData *wrappedSym;
333332
334private:333private:
335 Chunk *Data;334 Chunk *data;
336};335};
337336
338// If you have a symbol "foo" in your object file, a symbol name337// If you have a symbol "foo" in your object file, a symbol name
...@@ -342,18 +341,18 @@ private:...@@ -342,18 +341,18 @@ private:
342// This is here just for compatibility with MSVC.341// This is here just for compatibility with MSVC.
343class DefinedLocalImport : public Defined {342class DefinedLocalImport : public Defined {
344public:343public:
345 DefinedLocalImport(StringRef N, Defined *S)344 DefinedLocalImport(StringRef n, Defined *s)
346 : Defined(DefinedLocalImportKind, N), Data(make<LocalImportChunk>(S)) {}345 : Defined(DefinedLocalImportKind, n), data(make<LocalImportChunk>(s)) {}
347346
348 static bool classof(const Symbol *S) {347 static bool classof(const Symbol *s) {
349 return S->kind() == DefinedLocalImportKind;348 return s->kind() == DefinedLocalImportKind;
350 }349 }
351350
352 uint64_t getRVA() { return Data->getRVA(); }351 uint64_t getRVA() { return data->getRVA(); }
353 Chunk *getChunk() { return Data; }352 Chunk *getChunk() { return data; }
354353
355private:354private:
356 LocalImportChunk *Data;355 LocalImportChunk *data;
357};356};
358357
359inline uint64_t Defined::getRVA() {358inline uint64_t Defined::getRVA() {
...@@ -406,19 +405,19 @@ inline Chunk *Defined::getChunk() {...@@ -406,19 +405,19 @@ inline Chunk *Defined::getChunk() {
406// object. We allocate memory using this class and instantiate a symbol405// object. We allocate memory using this class and instantiate a symbol
407// using the placement new.406// using the placement new.
408union SymbolUnion {407union SymbolUnion {
409 alignas(DefinedRegular) char A[sizeof(DefinedRegular)];408 alignas(DefinedRegular) char a[sizeof(DefinedRegular)];
410 alignas(DefinedCommon) char B[sizeof(DefinedCommon)];409 alignas(DefinedCommon) char b[sizeof(DefinedCommon)];
411 alignas(DefinedAbsolute) char C[sizeof(DefinedAbsolute)];410 alignas(DefinedAbsolute) char c[sizeof(DefinedAbsolute)];
412 alignas(DefinedSynthetic) char D[sizeof(DefinedSynthetic)];411 alignas(DefinedSynthetic) char d[sizeof(DefinedSynthetic)];
413 alignas(Lazy) char E[sizeof(Lazy)];412 alignas(Lazy) char e[sizeof(Lazy)];
414 alignas(Undefined) char F[sizeof(Undefined)];413 alignas(Undefined) char f[sizeof(Undefined)];
415 alignas(DefinedImportData) char G[sizeof(DefinedImportData)];414 alignas(DefinedImportData) char g[sizeof(DefinedImportData)];
416 alignas(DefinedImportThunk) char H[sizeof(DefinedImportThunk)];415 alignas(DefinedImportThunk) char h[sizeof(DefinedImportThunk)];
417 alignas(DefinedLocalImport) char I[sizeof(DefinedLocalImport)];416 alignas(DefinedLocalImport) char i[sizeof(DefinedLocalImport)];
418};417};
419418
420template <typename T, typename... ArgT>419template <typename T, typename... ArgT>
421void replaceSymbol(Symbol *S, ArgT &&... Arg) {420void replaceSymbol(Symbol *s, ArgT &&... arg) {
422 static_assert(std::is_trivially_destructible<T>(),421 static_assert(std::is_trivially_destructible<T>(),
423 "Symbol types must be trivially destructible");422 "Symbol types must be trivially destructible");
424 static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");423 static_assert(sizeof(T) <= sizeof(SymbolUnion), "Symbol too small");
...@@ -426,11 +425,11 @@ void replaceSymbol(Symbol *S, ArgT &&... Arg) {...@@ -426,11 +425,11 @@ void replaceSymbol(Symbol *S, ArgT &&... Arg) {
426 "SymbolUnion not aligned enough");425 "SymbolUnion not aligned enough");
427 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&426 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
428 "Not a Symbol");427 "Not a Symbol");
429 new (S) T(std::forward<ArgT>(Arg)...);428 new (s) T(std::forward<ArgT>(arg)...);
430}429}
431} // namespace coff430} // namespace coff
432431
433std::string toString(coff::Symbol &B);432std::string toString(coff::Symbol &b);
434} // namespace lld433} // namespace lld
435434
436#endif435#endif
deps/lld/COFF/TypeMerger.h created+65
...@@ -0,0 +1,65 @@
1//===- TypeMerger.h ---------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_COFF_TYPEMERGER_H
10#define LLD_COFF_TYPEMERGER_H
11
12#include "Config.h"
13#include "llvm/DebugInfo/CodeView/GlobalTypeTableBuilder.h"
14#include "llvm/DebugInfo/CodeView/MergingTypeTableBuilder.h"
15#include "llvm/Support/Allocator.h"
16
17namespace lld {
18namespace coff {
19
20class TypeMerger {
21public:
22 TypeMerger(llvm::BumpPtrAllocator &alloc)
23 : typeTable(alloc), iDTable(alloc), globalTypeTable(alloc),
24 globalIDTable(alloc) {}
25
26 /// Get the type table or the global type table if /DEBUG:GHASH is enabled.
27 inline llvm::codeview::TypeCollection &getTypeTable() {
28 if (config->debugGHashes)
29 return globalTypeTable;
30 return typeTable;
31 }
32
33 /// Get the ID table or the global ID table if /DEBUG:GHASH is enabled.
34 inline llvm::codeview::TypeCollection &getIDTable() {
35 if (config->debugGHashes)
36 return globalIDTable;
37 return iDTable;
38 }
39
40 /// Type records that will go into the PDB TPI stream.
41 llvm::codeview::MergingTypeTableBuilder typeTable;
42
43 /// Item records that will go into the PDB IPI stream.
44 llvm::codeview::MergingTypeTableBuilder iDTable;
45
46 /// Type records that will go into the PDB TPI stream (for /DEBUG:GHASH)
47 llvm::codeview::GlobalTypeTableBuilder globalTypeTable;
48
49 /// Item records that will go into the PDB IPI stream (for /DEBUG:GHASH)
50 llvm::codeview::GlobalTypeTableBuilder globalIDTable;
51};
52
53/// Map from type index and item index in a type server PDB to the
54/// corresponding index in the destination PDB.
55struct CVIndexMap {
56 llvm::SmallVector<llvm::codeview::TypeIndex, 0> tpiMap;
57 llvm::SmallVector<llvm::codeview::TypeIndex, 0> ipiMap;
58 bool isTypeServerMap = false;
59 bool isPrecompiledTypeMap = false;
60};
61
62} // namespace coff
63} // namespace lld
64
65#endif
\ No newline at end of file
deps/lld/COFF/Writer.cpp+1111-936
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Writer.cpp ---------------------------------------------------------===//1//===- Writer.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -17,6 +16,7 @@...@@ -17,6 +16,7 @@
17#include "Symbols.h"16#include "Symbols.h"
18#include "lld/Common/ErrorHandler.h"17#include "lld/Common/ErrorHandler.h"
19#include "lld/Common/Memory.h"18#include "lld/Common/Memory.h"
19#include "lld/Common/Threads.h"
20#include "lld/Common/Timer.h"20#include "lld/Common/Timer.h"
21#include "llvm/ADT/DenseMap.h"21#include "llvm/ADT/DenseMap.h"
22#include "llvm/ADT/STLExtras.h"22#include "llvm/ADT/STLExtras.h"
...@@ -63,104 +63,129 @@ align 8, db 0...@@ -63,104 +63,129 @@ align 8, db 0
63$ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin63$ nasm -fbin /tmp/DOSProgram.asm -o /tmp/DOSProgram.bin
64$ xxd -i /tmp/DOSProgram.bin64$ xxd -i /tmp/DOSProgram.bin
65*/65*/
66static unsigned char DOSProgram[] = {66static unsigned char dosProgram[] = {
67 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c,67 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 0x21, 0xb8, 0x01, 0x4c,
68 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,68 0xcd, 0x21, 0x54, 0x68, 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72,
69 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,69 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 0x74, 0x20, 0x62, 0x65,
70 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,70 0x20, 0x72, 0x75, 0x6e, 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20,
71 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x0071 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x24, 0x00, 0x00
72};72};
73static_assert(sizeof(DOSProgram) % 8 == 0,73static_assert(sizeof(dosProgram) % 8 == 0,
74 "DOSProgram size must be multiple of 8");74 "DOSProgram size must be multiple of 8");
7575
76static const int SectorSize = 512;76static const int dosStubSize = sizeof(dos_header) + sizeof(dosProgram);
77static const int DOSStubSize = sizeof(dos_header) + sizeof(DOSProgram);77static_assert(dosStubSize % 8 == 0, "DOSStub size must be multiple of 8");
78static_assert(DOSStubSize % 8 == 0, "DOSStub size must be multiple of 8");78
79static const int numberOfDataDirectory = 16;
7980
80static const int NumberOfDataDirectory = 16;81// Global vector of all output sections. After output sections are finalized,
82// this can be indexed by Chunk::getOutputSection.
83static std::vector<OutputSection *> outputSections;
84
85OutputSection *Chunk::getOutputSection() const {
86 return osidx == 0 ? nullptr : outputSections[osidx - 1];
87}
8188
82namespace {89namespace {
8390
84class DebugDirectoryChunk : public Chunk {91class DebugDirectoryChunk : public NonSectionChunk {
85public:92public:
86 DebugDirectoryChunk(const std::vector<Chunk *> &R, bool WriteRepro)93 DebugDirectoryChunk(const std::vector<Chunk *> &r, bool writeRepro)
87 : Records(R), WriteRepro(WriteRepro) {}94 : records(r), writeRepro(writeRepro) {}
8895
89 size_t getSize() const override {96 size_t getSize() const override {
90 return (Records.size() + int(WriteRepro)) * sizeof(debug_directory);97 return (records.size() + int(writeRepro)) * sizeof(debug_directory);
91 }98 }
9299
93 void writeTo(uint8_t *B) const override {100 void writeTo(uint8_t *b) const override {
94 auto *D = reinterpret_cast<debug_directory *>(B + OutputSectionOff);101 auto *d = reinterpret_cast<debug_directory *>(b);
95102
96 for (const Chunk *Record : Records) {103 for (const Chunk *record : records) {
97 OutputSection *OS = Record->getOutputSection();104 OutputSection *os = record->getOutputSection();
98 uint64_t Offs = OS->getFileOff() + (Record->getRVA() - OS->getRVA());105 uint64_t offs = os->getFileOff() + (record->getRVA() - os->getRVA());
99 fillEntry(D, COFF::IMAGE_DEBUG_TYPE_CODEVIEW, Record->getSize(),106 fillEntry(d, COFF::IMAGE_DEBUG_TYPE_CODEVIEW, record->getSize(),
100 Record->getRVA(), Offs);107 record->getRVA(), offs);
101 ++D;108 ++d;
102 }109 }
103110
104 if (WriteRepro) {111 if (writeRepro) {
105 // FIXME: The COFF spec allows either a 0-sized entry to just say112 // 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 field113 // "the timestamp field is really a hash", or a 4-byte size field
107 // followed by that many bytes containing a longer hash (with the114 // followed by that many bytes containing a longer hash (with the
108 // lowest 4 bytes usually being the timestamp in little-endian order).115 // lowest 4 bytes usually being the timestamp in little-endian order).
109 // Consider storing the full 8 bytes computed by xxHash64 here.116 // Consider storing the full 8 bytes computed by xxHash64 here.
110 fillEntry(D, COFF::IMAGE_DEBUG_TYPE_REPRO, 0, 0, 0);117 fillEntry(d, COFF::IMAGE_DEBUG_TYPE_REPRO, 0, 0, 0);
111 }118 }
112 }119 }
113120
114 void setTimeDateStamp(uint32_t TimeDateStamp) {121 void setTimeDateStamp(uint32_t timeDateStamp) {
115 for (support::ulittle32_t *TDS : TimeDateStamps)122 for (support::ulittle32_t *tds : timeDateStamps)
116 *TDS = TimeDateStamp;123 *tds = timeDateStamp;
117 }124 }
118125
119private:126private:
120 void fillEntry(debug_directory *D, COFF::DebugType DebugType, size_t Size,127 void fillEntry(debug_directory *d, COFF::DebugType debugType, size_t size,
121 uint64_t RVA, uint64_t Offs) const {128 uint64_t rva, uint64_t offs) const {
122 D->Characteristics = 0;129 d->Characteristics = 0;
123 D->TimeDateStamp = 0;130 d->TimeDateStamp = 0;
124 D->MajorVersion = 0;131 d->MajorVersion = 0;
125 D->MinorVersion = 0;132 d->MinorVersion = 0;
126 D->Type = DebugType;133 d->Type = debugType;
127 D->SizeOfData = Size;134 d->SizeOfData = size;
128 D->AddressOfRawData = RVA;135 d->AddressOfRawData = rva;
129 D->PointerToRawData = Offs;136 d->PointerToRawData = offs;
130137
131 TimeDateStamps.push_back(&D->TimeDateStamp);138 timeDateStamps.push_back(&d->TimeDateStamp);
132 }139 }
133140
134 mutable std::vector<support::ulittle32_t *> TimeDateStamps;141 mutable std::vector<support::ulittle32_t *> timeDateStamps;
135 const std::vector<Chunk *> &Records;142 const std::vector<Chunk *> &records;
136 bool WriteRepro;143 bool writeRepro;
137};144};
138145
139class CVDebugRecordChunk : public Chunk {146class CVDebugRecordChunk : public NonSectionChunk {
140public:147public:
141 size_t getSize() const override {148 size_t getSize() const override {
142 return sizeof(codeview::DebugInfo) + Config->PDBAltPath.size() + 1;149 return sizeof(codeview::DebugInfo) + config->pdbAltPath.size() + 1;
143 }150 }
144151
145 void writeTo(uint8_t *B) const override {152 void writeTo(uint8_t *b) const override {
146 // Save off the DebugInfo entry to backfill the file signature (build id)153 // Save off the DebugInfo entry to backfill the file signature (build id)
147 // in Writer::writeBuildId154 // in Writer::writeBuildId
148 BuildId = reinterpret_cast<codeview::DebugInfo *>(B + OutputSectionOff);155 buildId = reinterpret_cast<codeview::DebugInfo *>(b);
149156
150 // variable sized field (PDB Path)157 // variable sized field (PDB Path)
151 char *P = reinterpret_cast<char *>(B + OutputSectionOff + sizeof(*BuildId));158 char *p = reinterpret_cast<char *>(b + sizeof(*buildId));
152 if (!Config->PDBAltPath.empty())159 if (!config->pdbAltPath.empty())
153 memcpy(P, Config->PDBAltPath.data(), Config->PDBAltPath.size());160 memcpy(p, config->pdbAltPath.data(), config->pdbAltPath.size());
154 P[Config->PDBAltPath.size()] = '\0';161 p[config->pdbAltPath.size()] = '\0';
155 }162 }
156163
157 mutable codeview::DebugInfo *BuildId = nullptr;164 mutable codeview::DebugInfo *buildId = nullptr;
165};
166
167// PartialSection represents a group of chunks that contribute to an
168// OutputSection. Collating a collection of PartialSections of same name and
169// characteristics constitutes the OutputSection.
170class PartialSectionKey {
171public:
172 StringRef name;
173 unsigned characteristics;
174
175 bool operator<(const PartialSectionKey &other) const {
176 int c = name.compare(other.name);
177 if (c == 1)
178 return false;
179 if (c == 0)
180 return characteristics < other.characteristics;
181 return true;
182 }
158};183};
159184
160// The writer writes a SymbolTable result to a file.185// The writer writes a SymbolTable result to a file.
161class Writer {186class Writer {
162public:187public:
163 Writer() : Buffer(errorHandler().OutputBuffer) {}188 Writer() : buffer(errorHandler().outputBuffer) {}
164 void run();189 void run();
165190
166private:191private:
...@@ -168,78 +193,81 @@ private:...@@ -168,78 +193,81 @@ private:
168 void createMiscChunks();193 void createMiscChunks();
169 void createImportTables();194 void createImportTables();
170 void appendImportThunks();195 void appendImportThunks();
171 void locateImportTables(196 void locateImportTables();
172 std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map);
173 void createExportTable();197 void createExportTable();
174 void mergeSections();198 void mergeSections();
175 void readRelocTargets();
176 void removeUnusedSections();199 void removeUnusedSections();
177 void assignAddresses();200 void assignAddresses();
178 void finalizeAddresses();201 void finalizeAddresses();
179 void removeEmptySections();202 void removeEmptySections();
203 void assignOutputSectionIndices();
180 void createSymbolAndStringTable();204 void createSymbolAndStringTable();
181 void openFile(StringRef OutputPath);205 void openFile(StringRef outputPath);
182 template <typename PEHeaderTy> void writeHeader();206 template <typename PEHeaderTy> void writeHeader();
183 void createSEHTable();207 void createSEHTable();
184 void createRuntimePseudoRelocs();208 void createRuntimePseudoRelocs();
185 void insertCtorDtorSymbols();209 void insertCtorDtorSymbols();
186 void createGuardCFTables();210 void createGuardCFTables();
187 void markSymbolsForRVATable(ObjFile *File,211 void markSymbolsForRVATable(ObjFile *file,
188 ArrayRef<SectionChunk *> SymIdxChunks,212 ArrayRef<SectionChunk *> symIdxChunks,
189 SymbolRVASet &TableSymbols);213 SymbolRVASet &tableSymbols);
190 void maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym,214 void maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
191 StringRef CountSym);215 StringRef countSym);
192 void setSectionPermissions();216 void setSectionPermissions();
193 void writeSections();217 void writeSections();
194 void writeBuildId();218 void writeBuildId();
195 void sortExceptionTable();219 void sortExceptionTable();
196 void sortCRTSectionChunks(std::vector<Chunk *> &Chunks);220 void sortCRTSectionChunks(std::vector<Chunk *> &chunks);
221 void addSyntheticIdata();
222 void fixPartialSectionChars(StringRef name, uint32_t chars);
223 bool fixGnuImportChunks();
224 PartialSection *createPartialSection(StringRef name, uint32_t outChars);
225 PartialSection *findPartialSection(StringRef name, uint32_t outChars);
197226
198 llvm::Optional<coff_symbol16> createSymbol(Defined *D);227 llvm::Optional<coff_symbol16> createSymbol(Defined *d);
199 size_t addEntryToStringTable(StringRef Str);228 size_t addEntryToStringTable(StringRef str);
200229
201 OutputSection *findSection(StringRef Name);230 OutputSection *findSection(StringRef name);
202 void addBaserels();231 void addBaserels();
203 void addBaserelBlocks(std::vector<Baserel> &V);232 void addBaserelBlocks(std::vector<Baserel> &v);
204233
205 uint32_t getSizeOfInitializedData();234 uint32_t getSizeOfInitializedData();
206 std::map<StringRef, std::vector<DefinedImportData *>> binImports();235
207236 std::unique_ptr<FileOutputBuffer> &buffer;
208 std::unique_ptr<FileOutputBuffer> &Buffer;237 std::map<PartialSectionKey, PartialSection *> partialSections;
209 std::vector<OutputSection *> OutputSections;238 std::vector<char> strtab;
210 std::vector<char> Strtab;239 std::vector<llvm::object::coff_symbol16> outputSymtab;
211 std::vector<llvm::object::coff_symbol16> OutputSymtab;240 IdataContents idata;
212 IdataContents Idata;241 Chunk *importTableStart = nullptr;
213 Chunk *ImportTableStart = nullptr;242 uint64_t importTableSize = 0;
214 uint64_t ImportTableSize = 0;243 Chunk *iatStart = nullptr;
215 Chunk *IATStart = nullptr;244 uint64_t iatSize = 0;
216 uint64_t IATSize = 0;245 DelayLoadContents delayIdata;
217 DelayLoadContents DelayIdata;246 EdataContents edata;
218 EdataContents Edata;247 bool setNoSEHCharacteristic = false;
219 bool SetNoSEHCharacteristic = false;248
220249 DebugDirectoryChunk *debugDirectory = nullptr;
221 DebugDirectoryChunk *DebugDirectory = nullptr;250 std::vector<Chunk *> debugRecords;
222 std::vector<Chunk *> DebugRecords;251 CVDebugRecordChunk *buildId = nullptr;
223 CVDebugRecordChunk *BuildId = nullptr;252 ArrayRef<uint8_t> sectionTable;
224 ArrayRef<uint8_t> SectionTable;253
225254 uint64_t fileSize;
226 uint64_t FileSize;255 uint32_t pointerToSymbolTable = 0;
227 uint32_t PointerToSymbolTable = 0;256 uint64_t sizeOfImage;
228 uint64_t SizeOfImage;257 uint64_t sizeOfHeaders;
229 uint64_t SizeOfHeaders;258
230259 OutputSection *textSec;
231 OutputSection *TextSec;260 OutputSection *rdataSec;
232 OutputSection *RdataSec;261 OutputSection *buildidSec;
233 OutputSection *BuildidSec;262 OutputSection *dataSec;
234 OutputSection *DataSec;263 OutputSection *pdataSec;
235 OutputSection *PdataSec;264 OutputSection *idataSec;
236 OutputSection *IdataSec;265 OutputSection *edataSec;
237 OutputSection *EdataSec;266 OutputSection *didatSec;
238 OutputSection *DidatSec;267 OutputSection *rsrcSec;
239 OutputSection *RsrcSec;268 OutputSection *relocSec;
240 OutputSection *RelocSec;269 OutputSection *ctorsSec;
241 OutputSection *CtorsSec;270 OutputSection *dtorsSec;
242 OutputSection *DtorsSec;
243271
244 // The first and last .pdata sections in the output file.272 // The first and last .pdata sections in the output file.
245 //273 //
...@@ -250,82 +278,85 @@ private:...@@ -250,82 +278,85 @@ private:
250 // are entirely linker-generated we can keep track of their locations using278 // are entirely linker-generated we can keep track of their locations using
251 // the chunks that the linker creates. All .pdata chunks come from input279 // the chunks that the linker creates. All .pdata chunks come from input
252 // files, so we need to keep track of them separately.280 // files, so we need to keep track of them separately.
253 Chunk *FirstPdata = nullptr;281 Chunk *firstPdata = nullptr;
254 Chunk *LastPdata;282 Chunk *lastPdata;
255};283};
256} // anonymous namespace284} // anonymous namespace
257285
258namespace lld {286namespace lld {
259namespace coff {287namespace coff {
260288
261static Timer CodeLayoutTimer("Code Layout", Timer::root());289static Timer codeLayoutTimer("Code Layout", Timer::root());
262static Timer DiskCommitTimer("Commit Output File", Timer::root());290static Timer diskCommitTimer("Commit Output File", Timer::root());
263291
264void writeResult() { Writer().run(); }292void writeResult() { Writer().run(); }
265293
266void OutputSection::addChunk(Chunk *C) {294void OutputSection::addChunk(Chunk *c) {
267 Chunks.push_back(C);295 chunks.push_back(c);
268 C->setOutputSection(this);
269}296}
270297
271void OutputSection::insertChunkAtStart(Chunk *C) {298void OutputSection::insertChunkAtStart(Chunk *c) {
272 Chunks.insert(Chunks.begin(), C);299 chunks.insert(chunks.begin(), c);
273 C->setOutputSection(this);
274}300}
275301
276void OutputSection::setPermissions(uint32_t C) {302void OutputSection::setPermissions(uint32_t c) {
277 Header.Characteristics &= ~PermMask;303 header.Characteristics &= ~permMask;
278 Header.Characteristics |= C;304 header.Characteristics |= c;
279}305}
280306
281void OutputSection::merge(OutputSection *Other) {307void OutputSection::merge(OutputSection *other) {
282 for (Chunk *C : Other->Chunks)308 chunks.insert(chunks.end(), other->chunks.begin(), other->chunks.end());
283 C->setOutputSection(this);309 other->chunks.clear();
284 Chunks.insert(Chunks.end(), Other->Chunks.begin(), Other->Chunks.end());310 contribSections.insert(contribSections.end(), other->contribSections.begin(),
285 Other->Chunks.clear();311 other->contribSections.end());
312 other->contribSections.clear();
286}313}
287314
288// Write the section header to a given buffer.315// Write the section header to a given buffer.
289void OutputSection::writeHeaderTo(uint8_t *Buf) {316void OutputSection::writeHeaderTo(uint8_t *buf) {
290 auto *Hdr = reinterpret_cast<coff_section *>(Buf);317 auto *hdr = reinterpret_cast<coff_section *>(buf);
291 *Hdr = Header;318 *hdr = header;
292 if (StringTableOff) {319 if (stringTableOff) {
293 // If name is too long, write offset into the string table as a name.320 // If name is too long, write offset into the string table as a name.
294 sprintf(Hdr->Name, "/%d", StringTableOff);321 sprintf(hdr->Name, "/%d", stringTableOff);
295 } else {322 } else {
296 assert(!Config->Debug || Name.size() <= COFF::NameSize ||323 assert(!config->debug || name.size() <= COFF::NameSize ||
297 (Hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0);324 (hdr->Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0);
298 strncpy(Hdr->Name, Name.data(),325 strncpy(hdr->Name, name.data(),
299 std::min(Name.size(), (size_t)COFF::NameSize));326 std::min(name.size(), (size_t)COFF::NameSize));
300 }327 }
301}328}
302329
330void OutputSection::addContributingPartialSection(PartialSection *sec) {
331 contribSections.push_back(sec);
332}
333
303} // namespace coff334} // namespace coff
304} // namespace lld335} // namespace lld
305336
306// Check whether the target address S is in range from a relocation337// Check whether the target address S is in range from a relocation
307// of type RelType at address P.338// of type relType at address P.
308static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) {339static bool isInRange(uint16_t relType, uint64_t s, uint64_t p, int margin) {
309 if (Config->Machine == ARMNT) {340 if (config->machine == ARMNT) {
310 int64_t Diff = AbsoluteDifference(S, P + 4) + Margin;341 int64_t diff = AbsoluteDifference(s, p + 4) + margin;
311 switch (RelType) {342 switch (relType) {
312 case IMAGE_REL_ARM_BRANCH20T:343 case IMAGE_REL_ARM_BRANCH20T:
313 return isInt<21>(Diff);344 return isInt<21>(diff);
314 case IMAGE_REL_ARM_BRANCH24T:345 case IMAGE_REL_ARM_BRANCH24T:
315 case IMAGE_REL_ARM_BLX23T:346 case IMAGE_REL_ARM_BLX23T:
316 return isInt<25>(Diff);347 return isInt<25>(diff);
317 default:348 default:
318 return true;349 return true;
319 }350 }
320 } else if (Config->Machine == ARM64) {351 } else if (config->machine == ARM64) {
321 int64_t Diff = AbsoluteDifference(S, P) + Margin;352 int64_t diff = AbsoluteDifference(s, p) + margin;
322 switch (RelType) {353 switch (relType) {
323 case IMAGE_REL_ARM64_BRANCH26:354 case IMAGE_REL_ARM64_BRANCH26:
324 return isInt<28>(Diff);355 return isInt<28>(diff);
325 case IMAGE_REL_ARM64_BRANCH19:356 case IMAGE_REL_ARM64_BRANCH19:
326 return isInt<21>(Diff);357 return isInt<21>(diff);
327 case IMAGE_REL_ARM64_BRANCH14:358 case IMAGE_REL_ARM64_BRANCH14:
328 return isInt<16>(Diff);359 return isInt<16>(diff);
329 default:360 default:
330 return true;361 return true;
331 }362 }
...@@ -337,25 +368,25 @@ static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) {...@@ -337,25 +368,25 @@ static bool isInRange(uint16_t RelType, uint64_t S, uint64_t P, int Margin) {
337// Return the last thunk for the given target if it is in range,368// Return the last thunk for the given target if it is in range,
338// or create a new one.369// or create a new one.
339static std::pair<Defined *, bool>370static std::pair<Defined *, bool>
340getThunk(DenseMap<uint64_t, Defined *> &LastThunks, Defined *Target, uint64_t P,371getThunk(DenseMap<uint64_t, Defined *> &lastThunks, Defined *target, uint64_t p,
341 uint16_t Type, int Margin) {372 uint16_t type, int margin) {
342 Defined *&LastThunk = LastThunks[Target->getRVA()];373 Defined *&lastThunk = lastThunks[target->getRVA()];
343 if (LastThunk && isInRange(Type, LastThunk->getRVA(), P, Margin))374 if (lastThunk && isInRange(type, lastThunk->getRVA(), p, margin))
344 return {LastThunk, false};375 return {lastThunk, false};
345 Chunk *C;376 Chunk *c;
346 switch (Config->Machine) {377 switch (config->machine) {
347 case ARMNT:378 case ARMNT:
348 C = make<RangeExtensionThunkARM>(Target);379 c = make<RangeExtensionThunkARM>(target);
349 break;380 break;
350 case ARM64:381 case ARM64:
351 C = make<RangeExtensionThunkARM64>(Target);382 c = make<RangeExtensionThunkARM64>(target);
352 break;383 break;
353 default:384 default:
354 llvm_unreachable("Unexpected architecture");385 llvm_unreachable("Unexpected architecture");
355 }386 }
356 Defined *D = make<DefinedSynthetic>("", C);387 Defined *d = make<DefinedSynthetic>("", c);
357 LastThunk = D;388 lastThunk = d;
358 return {D, true};389 return {d, true};
359}390}
360391
361// This checks all relocations, and for any relocation which isn't in range392// This checks all relocations, and for any relocation which isn't in range
...@@ -369,82 +400,124 @@ getThunk(DenseMap<uint64_t, Defined *> &LastThunks, Defined *Target, uint64_t P,...@@ -369,82 +400,124 @@ getThunk(DenseMap<uint64_t, Defined *> &LastThunks, Defined *Target, uint64_t P,
369// After adding thunks, we verify that all relocations are in range (with400// After adding thunks, we verify that all relocations are in range (with
370// no extra margin requirements). If this failed, we restart (throwing away401// no extra margin requirements). If this failed, we restart (throwing away
371// the previously created thunks) and retry with a wider margin.402// the previously created thunks) and retry with a wider margin.
372static bool createThunks(OutputSection *OS, int Margin) {403static bool createThunks(OutputSection *os, int margin) {
373 bool AddressesChanged = false;404 bool addressesChanged = false;
374 DenseMap<uint64_t, Defined *> LastThunks;405 DenseMap<uint64_t, Defined *> lastThunks;
375 size_t ThunksSize = 0;406 DenseMap<std::pair<ObjFile *, Defined *>, uint32_t> thunkSymtabIndices;
407 size_t thunksSize = 0;
376 // Recheck Chunks.size() each iteration, since we can insert more408 // Recheck Chunks.size() each iteration, since we can insert more
377 // elements into it.409 // elements into it.
378 for (size_t I = 0; I != OS->Chunks.size(); ++I) {410 for (size_t i = 0; i != os->chunks.size(); ++i) {
379 SectionChunk *SC = dyn_cast_or_null<SectionChunk>(OS->Chunks[I]);411 SectionChunk *sc = dyn_cast_or_null<SectionChunk>(os->chunks[i]);
380 if (!SC)412 if (!sc)
381 continue;413 continue;
382 size_t ThunkInsertionSpot = I + 1;414 size_t thunkInsertionSpot = i + 1;
383415
384 // Try to get a good enough estimate of where new thunks will be placed.416 // 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 the417 // Offset this by the size of the new thunks added so far, to make the
386 // estimate slightly better.418 // estimate slightly better.
387 size_t ThunkInsertionRVA = SC->getRVA() + SC->getSize() + ThunksSize;419 size_t thunkInsertionRVA = sc->getRVA() + sc->getSize() + thunksSize;
388 for (size_t J = 0, E = SC->Relocs.size(); J < E; ++J) {420 ObjFile *file = sc->file;
389 const coff_relocation &Rel = SC->Relocs[J];421 std::vector<std::pair<uint32_t, uint32_t>> relocReplacements;
390 Symbol *&RelocTarget = SC->RelocTargets[J];422 ArrayRef<coff_relocation> originalRelocs =
423 file->getCOFFObj()->getRelocations(sc->header);
424 for (size_t j = 0, e = originalRelocs.size(); j < e; ++j) {
425 const coff_relocation &rel = originalRelocs[j];
426 Symbol *relocTarget = file->getSymbol(rel.SymbolTableIndex);
391427
392 // The estimate of the source address P should be pretty accurate,428 // The estimate of the source address P should be pretty accurate,
393 // but we don't know whether the target Symbol address should be429 // 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 of430 // offset by thunksSize or not (or by some of thunksSize but not all of
395 // it), giving us some uncertainty once we have added one thunk.431 // it), giving us some uncertainty once we have added one thunk.
396 uint64_t P = SC->getRVA() + Rel.VirtualAddress + ThunksSize;432 uint64_t p = sc->getRVA() + rel.VirtualAddress + thunksSize;
397433
398 Defined *Sym = dyn_cast_or_null<Defined>(RelocTarget);434 Defined *sym = dyn_cast_or_null<Defined>(relocTarget);
399 if (!Sym)435 if (!sym)
400 continue;436 continue;
401437
402 uint64_t S = Sym->getRVA();438 uint64_t s = sym->getRVA();
403439
404 if (isInRange(Rel.Type, S, P, Margin))440 if (isInRange(rel.Type, s, p, margin))
405 continue;441 continue;
406442
407 // If the target isn't in range, hook it up to an existing or new443 // If the target isn't in range, hook it up to an existing or new
408 // thunk.444 // thunk.
409 Defined *Thunk;445 Defined *thunk;
410 bool WasNew;446 bool wasNew;
411 std::tie(Thunk, WasNew) = getThunk(LastThunks, Sym, P, Rel.Type, Margin);447 std::tie(thunk, wasNew) = getThunk(lastThunks, sym, p, rel.Type, margin);
412 if (WasNew) {448 if (wasNew) {
413 Chunk *ThunkChunk = Thunk->getChunk();449 Chunk *thunkChunk = thunk->getChunk();
414 ThunkChunk->setRVA(450 thunkChunk->setRVA(
415 ThunkInsertionRVA); // Estimate of where it will be located.451 thunkInsertionRVA); // Estimate of where it will be located.
416 ThunkChunk->setOutputSection(OS);452 os->chunks.insert(os->chunks.begin() + thunkInsertionSpot, thunkChunk);
417 OS->Chunks.insert(OS->Chunks.begin() + ThunkInsertionSpot, ThunkChunk);453 thunkInsertionSpot++;
418 ThunkInsertionSpot++;454 thunksSize += thunkChunk->getSize();
419 ThunksSize += ThunkChunk->getSize();455 thunkInsertionRVA += thunkChunk->getSize();
420 ThunkInsertionRVA += ThunkChunk->getSize();456 addressesChanged = true;
421 AddressesChanged = true;457 }
458
459 // To redirect the relocation, add a symbol to the parent object file's
460 // symbol table, and replace the relocation symbol table index with the
461 // new index.
462 auto insertion = thunkSymtabIndices.insert({{file, thunk}, ~0U});
463 uint32_t &thunkSymbolIndex = insertion.first->second;
464 if (insertion.second)
465 thunkSymbolIndex = file->addRangeThunkSymbol(thunk);
466 relocReplacements.push_back({j, thunkSymbolIndex});
467 }
468
469 // Get a writable copy of this section's relocations so they can be
470 // modified. If the relocations point into the object file, allocate new
471 // memory. Otherwise, this must be previously allocated memory that can be
472 // modified in place.
473 ArrayRef<coff_relocation> curRelocs = sc->getRelocs();
474 MutableArrayRef<coff_relocation> newRelocs;
475 if (originalRelocs.data() == curRelocs.data()) {
476 newRelocs = makeMutableArrayRef(
477 bAlloc.Allocate<coff_relocation>(originalRelocs.size()),
478 originalRelocs.size());
479 } else {
480 newRelocs = makeMutableArrayRef(
481 const_cast<coff_relocation *>(curRelocs.data()), curRelocs.size());
482 }
483
484 // Copy each relocation, but replace the symbol table indices which need
485 // thunks.
486 auto nextReplacement = relocReplacements.begin();
487 auto endReplacement = relocReplacements.end();
488 for (size_t i = 0, e = originalRelocs.size(); i != e; ++i) {
489 newRelocs[i] = originalRelocs[i];
490 if (nextReplacement != endReplacement && nextReplacement->first == i) {
491 newRelocs[i].SymbolTableIndex = nextReplacement->second;
492 ++nextReplacement;
422 }493 }
423 RelocTarget = Thunk;
424 }494 }
495
496 sc->setRelocs(newRelocs);
425 }497 }
426 return AddressesChanged;498 return addressesChanged;
427}499}
428500
429// Verify that all relocations are in range, with no extra margin requirements.501// Verify that all relocations are in range, with no extra margin requirements.
430static bool verifyRanges(const std::vector<Chunk *> Chunks) {502static bool verifyRanges(const std::vector<Chunk *> chunks) {
431 for (Chunk *C : Chunks) {503 for (Chunk *c : chunks) {
432 SectionChunk *SC = dyn_cast_or_null<SectionChunk>(C);504 SectionChunk *sc = dyn_cast_or_null<SectionChunk>(c);
433 if (!SC)505 if (!sc)
434 continue;506 continue;
435507
436 for (size_t J = 0, E = SC->Relocs.size(); J < E; ++J) {508 ArrayRef<coff_relocation> relocs = sc->getRelocs();
437 const coff_relocation &Rel = SC->Relocs[J];509 for (size_t j = 0, e = relocs.size(); j < e; ++j) {
438 Symbol *RelocTarget = SC->RelocTargets[J];510 const coff_relocation &rel = relocs[j];
511 Symbol *relocTarget = sc->file->getSymbol(rel.SymbolTableIndex);
439512
440 Defined *Sym = dyn_cast_or_null<Defined>(RelocTarget);513 Defined *sym = dyn_cast_or_null<Defined>(relocTarget);
441 if (!Sym)514 if (!sym)
442 continue;515 continue;
443516
444 uint64_t P = SC->getRVA() + Rel.VirtualAddress;517 uint64_t p = sc->getRVA() + rel.VirtualAddress;
445 uint64_t S = Sym->getRVA();518 uint64_t s = sym->getRVA();
446519
447 if (!isInRange(Rel.Type, S, P, 0))520 if (!isInRange(rel.Type, s, p, 0))
448 return false;521 return false;
449 }522 }
450 }523 }
...@@ -454,71 +527,68 @@ static bool verifyRanges(const std::vector<Chunk *> Chunks) {...@@ -454,71 +527,68 @@ static bool verifyRanges(const std::vector<Chunk *> Chunks) {
454// Assign addresses and add thunks if necessary.527// Assign addresses and add thunks if necessary.
455void Writer::finalizeAddresses() {528void Writer::finalizeAddresses() {
456 assignAddresses();529 assignAddresses();
457 if (Config->Machine != ARMNT && Config->Machine != ARM64)530 if (config->machine != ARMNT && config->machine != ARM64)
458 return;531 return;
459532
460 size_t OrigNumChunks = 0;533 size_t origNumChunks = 0;
461 for (OutputSection *Sec : OutputSections) {534 for (OutputSection *sec : outputSections) {
462 Sec->OrigChunks = Sec->Chunks;535 sec->origChunks = sec->chunks;
463 OrigNumChunks += Sec->Chunks.size();536 origNumChunks += sec->chunks.size();
464 }537 }
465538
466 int Pass = 0;539 int pass = 0;
467 int Margin = 1024 * 100;540 int margin = 1024 * 100;
468 while (true) {541 while (true) {
469 // First check whether we need thunks at all, or if the previous pass of542 // First check whether we need thunks at all, or if the previous pass of
470 // adding them turned out ok.543 // adding them turned out ok.
471 bool RangesOk = true;544 bool rangesOk = true;
472 size_t NumChunks = 0;545 size_t numChunks = 0;
473 for (OutputSection *Sec : OutputSections) {546 for (OutputSection *sec : outputSections) {
474 if (!verifyRanges(Sec->Chunks)) {547 if (!verifyRanges(sec->chunks)) {
475 RangesOk = false;548 rangesOk = false;
476 break;549 break;
477 }550 }
478 NumChunks += Sec->Chunks.size();551 numChunks += sec->chunks.size();
479 }552 }
480 if (RangesOk) {553 if (rangesOk) {
481 if (Pass > 0)554 if (pass > 0)
482 log("Added " + Twine(NumChunks - OrigNumChunks) + " thunks with " +555 log("Added " + Twine(numChunks - origNumChunks) + " thunks with " +
483 "margin " + Twine(Margin) + " in " + Twine(Pass) + " passes");556 "margin " + Twine(margin) + " in " + Twine(pass) + " passes");
484 return;557 return;
485 }558 }
486559
487 if (Pass >= 10)560 if (pass >= 10)
488 fatal("adding thunks hasn't converged after " + Twine(Pass) + " passes");561 fatal("adding thunks hasn't converged after " + Twine(pass) + " passes");
489562
490 if (Pass > 0) {563 if (pass > 0) {
491 // If the previous pass didn't work out, reset everything back to the564 // If the previous pass didn't work out, reset everything back to the
492 // original conditions before retrying with a wider margin. This should565 // original conditions before retrying with a wider margin. This should
493 // ideally never happen under real circumstances.566 // ideally never happen under real circumstances.
494 for (OutputSection *Sec : OutputSections) {567 for (OutputSection *sec : outputSections)
495 Sec->Chunks = Sec->OrigChunks;568 sec->chunks = sec->origChunks;
496 for (Chunk *C : Sec->Chunks)569 margin *= 2;
497 C->resetRelocTargets();
498 }
499 Margin *= 2;
500 }570 }
501571
502 // Try adding thunks everywhere where it is needed, with a margin572 // Try adding thunks everywhere where it is needed, with a margin
503 // to avoid things going out of range due to the added thunks.573 // to avoid things going out of range due to the added thunks.
504 bool AddressesChanged = false;574 bool addressesChanged = false;
505 for (OutputSection *Sec : OutputSections)575 for (OutputSection *sec : outputSections)
506 AddressesChanged |= createThunks(Sec, Margin);576 addressesChanged |= createThunks(sec, margin);
507 // If the verification above thought we needed thunks, we should have577 // If the verification above thought we needed thunks, we should have
508 // added some.578 // added some.
509 assert(AddressesChanged);579 assert(addressesChanged);
510580
511 // Recalculate the layout for the whole image (and verify the ranges at581 // Recalculate the layout for the whole image (and verify the ranges at
512 // the start of the next round).582 // the start of the next round).
513 assignAddresses();583 assignAddresses();
514584
515 Pass++;585 pass++;
516 }586 }
517}587}
518588
519// The main function of the writer.589// The main function of the writer.
520void Writer::run() {590void Writer::run() {
521 ScopedTimer T1(CodeLayoutTimer);591 ScopedTimer t1(codeLayoutTimer);
522592
523 createImportTables();593 createImportTables();
524 createSections();594 createSections();
...@@ -526,19 +596,19 @@ void Writer::run() {...@@ -526,19 +596,19 @@ void Writer::run() {
526 appendImportThunks();596 appendImportThunks();
527 createExportTable();597 createExportTable();
528 mergeSections();598 mergeSections();
529 readRelocTargets();
530 removeUnusedSections();599 removeUnusedSections();
531 finalizeAddresses();600 finalizeAddresses();
532 removeEmptySections();601 removeEmptySections();
602 assignOutputSectionIndices();
533 setSectionPermissions();603 setSectionPermissions();
534 createSymbolAndStringTable();604 createSymbolAndStringTable();
535605
536 if (FileSize > UINT32_MAX)606 if (fileSize > UINT32_MAX)
537 fatal("image size (" + Twine(FileSize) + ") " +607 fatal("image size (" + Twine(fileSize) + ") " +
538 "exceeds maximum allowable size (" + Twine(UINT32_MAX) + ")");608 "exceeds maximum allowable size (" + Twine(UINT32_MAX) + ")");
539609
540 openFile(Config->OutputFile);610 openFile(config->outputFile);
541 if (Config->is64()) {611 if (config->is64()) {
542 writeHeader<pe32plus_header>();612 writeHeader<pe32plus_header>();
543 } else {613 } else {
544 writeHeader<pe32_header>();614 writeHeader<pe32_header>();
...@@ -546,42 +616,59 @@ void Writer::run() {...@@ -546,42 +616,59 @@ void Writer::run() {
546 writeSections();616 writeSections();
547 sortExceptionTable();617 sortExceptionTable();
548618
549 T1.stop();619 t1.stop();
550620
551 if (!Config->PDBPath.empty() && Config->Debug) {621 if (!config->pdbPath.empty() && config->debug) {
552 assert(BuildId);622 assert(buildId);
553 createPDB(Symtab, OutputSections, SectionTable, BuildId->BuildId);623 createPDB(symtab, outputSections, sectionTable, buildId->buildId);
554 }624 }
555 writeBuildId();625 writeBuildId();
556626
557 writeMapFile(OutputSections);627 writeMapFile(outputSections);
558628
559 ScopedTimer T2(DiskCommitTimer);629 ScopedTimer t2(diskCommitTimer);
560 if (auto E = Buffer->commit())630 if (auto e = buffer->commit())
561 fatal("failed to write the output file: " + toString(std::move(E)));631 fatal("failed to write the output file: " + toString(std::move(e)));
562}632}
563633
564static StringRef getOutputSectionName(StringRef Name) {634static StringRef getOutputSectionName(StringRef name) {
565 StringRef S = Name.split('$').first;635 StringRef s = name.split('$').first;
566636
567 // Treat a later period as a separator for MinGW, for sections like637 // Treat a later period as a separator for MinGW, for sections like
568 // ".ctors.01234".638 // ".ctors.01234".
569 return S.substr(0, S.find('.', 1));639 return s.substr(0, s.find('.', 1));
570}640}
571641
572// For /order.642// For /order.
573static void sortBySectionOrder(std::vector<Chunk *> &Chunks) {643static void sortBySectionOrder(std::vector<Chunk *> &chunks) {
574 auto GetPriority = [](const Chunk *C) {644 auto getPriority = [](const Chunk *c) {
575 if (auto *Sec = dyn_cast<SectionChunk>(C))645 if (auto *sec = dyn_cast<SectionChunk>(c))
576 if (Sec->Sym)646 if (sec->sym)
577 return Config->Order.lookup(Sec->Sym->getName());647 return config->order.lookup(sec->sym->getName());
578 return 0;648 return 0;
579 };649 };
580650
581 std::stable_sort(Chunks.begin(), Chunks.end(),651 llvm::stable_sort(chunks, [=](const Chunk *a, const Chunk *b) {
582 [=](const Chunk *A, const Chunk *B) {652 return getPriority(a) < getPriority(b);
583 return GetPriority(A) < GetPriority(B);653 });
584 });654}
655
656// Change the characteristics of existing PartialSections that belong to the
657// section Name to Chars.
658void Writer::fixPartialSectionChars(StringRef name, uint32_t chars) {
659 for (auto it : partialSections) {
660 PartialSection *pSec = it.second;
661 StringRef curName = pSec->name;
662 if (!curName.consume_front(name) ||
663 (!curName.empty() && !curName.startswith("$")))
664 continue;
665 if (pSec->characteristics == chars)
666 continue;
667 PartialSection *destSec = createPartialSection(pSec->name, chars);
668 destSec->chunks.insert(destSec->chunks.end(), pSec->chunks.begin(),
669 pSec->chunks.end());
670 pSec->chunks.clear();
671 }
585}672}
586673
587// Sort concrete section chunks from GNU import libraries.674// Sort concrete section chunks from GNU import libraries.
...@@ -594,249 +681,269 @@ static void sortBySectionOrder(std::vector<Chunk *> &Chunks) {...@@ -594,249 +681,269 @@ static void sortBySectionOrder(std::vector<Chunk *> &Chunks) {
594// be formed correctly, the section chunks within each .idata$* section need681// be formed correctly, the section chunks within each .idata$* section need
595// to be grouped by library, and sorted alphabetically within each library682// to be grouped by library, and sorted alphabetically within each library
596// (which makes sure the header comes first and the trailer last).683// (which makes sure the header comes first and the trailer last).
597static bool fixGnuImportChunks(684bool Writer::fixGnuImportChunks() {
598 std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map) {685 uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
599 uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
600686
601 // Make sure all .idata$* section chunks are mapped as RDATA in order to687 // 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.688 // be sorted into the same sections as our own synthesized .idata chunks.
603 for (auto &Pair : Map) {689 fixPartialSectionChars(".idata", rdata);
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 }
615690
616 bool HasIdata = false;691 bool hasIdata = false;
617 // Sort all .idata$* chunks, grouping chunks from the same library,692 // Sort all .idata$* chunks, grouping chunks from the same library,
618 // with alphabetical ordering of the object fils within a library.693 // with alphabetical ordering of the object fils within a library.
619 for (auto &Pair : Map) {694 for (auto it : partialSections) {
620 StringRef SectionName = Pair.first.first;695 PartialSection *pSec = it.second;
621 if (!SectionName.startswith(".idata"))696 if (!pSec->name.startswith(".idata"))
622 continue;697 continue;
623698
624 std::vector<Chunk *> &Chunks = Pair.second;699 if (!pSec->chunks.empty())
625 if (!Chunks.empty())700 hasIdata = true;
626 HasIdata = true;701 llvm::stable_sort(pSec->chunks, [&](Chunk *s, Chunk *t) {
627 std::stable_sort(Chunks.begin(), Chunks.end(), [&](Chunk *S, Chunk *T) {702 SectionChunk *sc1 = dyn_cast_or_null<SectionChunk>(s);
628 SectionChunk *SC1 = dyn_cast_or_null<SectionChunk>(S);703 SectionChunk *sc2 = dyn_cast_or_null<SectionChunk>(t);
629 SectionChunk *SC2 = dyn_cast_or_null<SectionChunk>(T);704 if (!sc1 || !sc2) {
630 if (!SC1 || !SC2) {
631 // if SC1, order them ascending. If SC2 or both null,705 // if SC1, order them ascending. If SC2 or both null,
632 // S is not less than T.706 // S is not less than T.
633 return SC1 != nullptr;707 return sc1 != nullptr;
634 }708 }
635 // Make a string with "libraryname/objectfile" for sorting, achieving709 // Make a string with "libraryname/objectfile" for sorting, achieving
636 // both grouping by library and sorting of objects within a library,710 // both grouping by library and sorting of objects within a library,
637 // at once.711 // at once.
638 std::string Key1 =712 std::string key1 =
639 (SC1->File->ParentName + "/" + SC1->File->getName()).str();713 (sc1->file->parentName + "/" + sc1->file->getName()).str();
640 std::string Key2 =714 std::string key2 =
641 (SC2->File->ParentName + "/" + SC2->File->getName()).str();715 (sc2->file->parentName + "/" + sc2->file->getName()).str();
642 return Key1 < Key2;716 return key1 < key2;
643 });717 });
644 }718 }
645 return HasIdata;719 return hasIdata;
646}720}
647721
648// Add generated idata chunks, for imported symbols and DLLs, and a722// Add generated idata chunks, for imported symbols and DLLs, and a
649// terminator in .idata$2.723// terminator in .idata$2.
650static void addSyntheticIdata(724void Writer::addSyntheticIdata() {
651 IdataContents &Idata,725 uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
652 std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map) {726 idata.create();
653 uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
654 Idata.create();
655727
656 // Add the .idata content in the right section groups, to allow728 // Add the .idata content in the right section groups, to allow
657 // chunks from other linked in object files to be grouped together.729 // chunks from other linked in object files to be grouped together.
658 // See Microsoft PE/COFF spec 5.4 for details.730 // See Microsoft PE/COFF spec 5.4 for details.
659 auto Add = [&](StringRef N, std::vector<Chunk *> &V) {731 auto add = [&](StringRef n, std::vector<Chunk *> &v) {
660 std::vector<Chunk *> &DestVect = Map[{N, RDATA}];732 PartialSection *pSec = createPartialSection(n, rdata);
661 DestVect.insert(DestVect.end(), V.begin(), V.end());733 pSec->chunks.insert(pSec->chunks.end(), v.begin(), v.end());
662 };734 };
663735
664 // The loader assumes a specific order of data.736 // The loader assumes a specific order of data.
665 // Add each type in the correct order.737 // Add each type in the correct order.
666 Add(".idata$2", Idata.Dirs);738 add(".idata$2", idata.dirs);
667 Add(".idata$4", Idata.Lookups);739 add(".idata$4", idata.lookups);
668 Add(".idata$5", Idata.Addresses);740 add(".idata$5", idata.addresses);
669 Add(".idata$6", Idata.Hints);741 add(".idata$6", idata.hints);
670 Add(".idata$7", Idata.DLLNames);742 add(".idata$7", idata.dllNames);
671}743}
672744
673// Locate the first Chunk and size of the import directory list and the745// Locate the first Chunk and size of the import directory list and the
674// IAT.746// IAT.
675void Writer::locateImportTables(747void Writer::locateImportTables() {
676 std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> &Map) {748 uint32_t rdata = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;
677 uint32_t RDATA = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ;749
678 std::vector<Chunk *> &ImportTables = Map[{".idata$2", RDATA}];750 if (PartialSection *importDirs = findPartialSection(".idata$2", rdata)) {
679 if (!ImportTables.empty())751 if (!importDirs->chunks.empty())
680 ImportTableStart = ImportTables.front();752 importTableStart = importDirs->chunks.front();
681 for (Chunk *C : ImportTables)753 for (Chunk *c : importDirs->chunks)
682 ImportTableSize += C->getSize();754 importTableSize += c->getSize();
683755 }
684 std::vector<Chunk *> &IAT = Map[{".idata$5", RDATA}];756
685 if (!IAT.empty())757 if (PartialSection *importAddresses = findPartialSection(".idata$5", rdata)) {
686 IATStart = IAT.front();758 if (!importAddresses->chunks.empty())
687 for (Chunk *C : IAT)759 iatStart = importAddresses->chunks.front();
688 IATSize += C->getSize();760 for (Chunk *c : importAddresses->chunks)
761 iatSize += c->getSize();
762 }
763}
764
765// Return whether a SectionChunk's suffix (the dollar and any trailing
766// suffix) should be removed and sorted into the main suffixless
767// PartialSection.
768static bool shouldStripSectionSuffix(SectionChunk *sc, StringRef name) {
769 // On MinGW, comdat groups are formed by putting the comdat group name
770 // after the '$' in the section name. For .eh_frame$<symbol>, that must
771 // still be sorted before the .eh_frame trailer from crtend.o, thus just
772 // strip the section name trailer. For other sections, such as
773 // .tls$$<symbol> (where non-comdat .tls symbols are otherwise stored in
774 // ".tls$"), they must be strictly sorted after .tls. And for the
775 // hypothetical case of comdat .CRT$XCU, we definitely need to keep the
776 // suffix for sorting. Thus, to play it safe, only strip the suffix for
777 // the standard sections.
778 if (!config->mingw)
779 return false;
780 if (!sc || !sc->isCOMDAT())
781 return false;
782 return name.startswith(".text$") || name.startswith(".data$") ||
783 name.startswith(".rdata$") || name.startswith(".pdata$") ||
784 name.startswith(".xdata$") || name.startswith(".eh_frame$");
689}785}
690786
691// Create output section objects and add them to OutputSections.787// Create output section objects and add them to OutputSections.
692void Writer::createSections() {788void Writer::createSections() {
693 // First, create the builtin sections.789 // First, create the builtin sections.
694 const uint32_t DATA = IMAGE_SCN_CNT_INITIALIZED_DATA;790 const uint32_t data = IMAGE_SCN_CNT_INITIALIZED_DATA;
695 const uint32_t BSS = IMAGE_SCN_CNT_UNINITIALIZED_DATA;791 const uint32_t bss = IMAGE_SCN_CNT_UNINITIALIZED_DATA;
696 const uint32_t CODE = IMAGE_SCN_CNT_CODE;792 const uint32_t code = IMAGE_SCN_CNT_CODE;
697 const uint32_t DISCARDABLE = IMAGE_SCN_MEM_DISCARDABLE;793 const uint32_t discardable = IMAGE_SCN_MEM_DISCARDABLE;
698 const uint32_t R = IMAGE_SCN_MEM_READ;794 const uint32_t r = IMAGE_SCN_MEM_READ;
699 const uint32_t W = IMAGE_SCN_MEM_WRITE;795 const uint32_t w = IMAGE_SCN_MEM_WRITE;
700 const uint32_t X = IMAGE_SCN_MEM_EXECUTE;796 const uint32_t x = IMAGE_SCN_MEM_EXECUTE;
701797
702 SmallDenseMap<std::pair<StringRef, uint32_t>, OutputSection *> Sections;798 SmallDenseMap<std::pair<StringRef, uint32_t>, OutputSection *> sections;
703 auto CreateSection = [&](StringRef Name, uint32_t OutChars) {799 auto createSection = [&](StringRef name, uint32_t outChars) {
704 OutputSection *&Sec = Sections[{Name, OutChars}];800 OutputSection *&sec = sections[{name, outChars}];
705 if (!Sec) {801 if (!sec) {
706 Sec = make<OutputSection>(Name, OutChars);802 sec = make<OutputSection>(name, outChars);
707 OutputSections.push_back(Sec);803 outputSections.push_back(sec);
708 }804 }
709 return Sec;805 return sec;
710 };806 };
711807
712 // Try to match the section order used by link.exe.808 // Try to match the section order used by link.exe.
713 TextSec = CreateSection(".text", CODE | R | X);809 textSec = createSection(".text", code | r | x);
714 CreateSection(".bss", BSS | R | W);810 createSection(".bss", bss | r | w);
715 RdataSec = CreateSection(".rdata", DATA | R);811 rdataSec = createSection(".rdata", data | r);
716 BuildidSec = CreateSection(".buildid", DATA | R);812 buildidSec = createSection(".buildid", data | r);
717 DataSec = CreateSection(".data", DATA | R | W);813 dataSec = createSection(".data", data | r | w);
718 PdataSec = CreateSection(".pdata", DATA | R);814 pdataSec = createSection(".pdata", data | r);
719 IdataSec = CreateSection(".idata", DATA | R);815 idataSec = createSection(".idata", data | r);
720 EdataSec = CreateSection(".edata", DATA | R);816 edataSec = createSection(".edata", data | r);
721 DidatSec = CreateSection(".didat", DATA | R);817 didatSec = createSection(".didat", data | r);
722 RsrcSec = CreateSection(".rsrc", DATA | R);818 rsrcSec = createSection(".rsrc", data | r);
723 RelocSec = CreateSection(".reloc", DATA | DISCARDABLE | R);819 relocSec = createSection(".reloc", data | discardable | r);
724 CtorsSec = CreateSection(".ctors", DATA | R | W);820 ctorsSec = createSection(".ctors", data | r | w);
725 DtorsSec = CreateSection(".dtors", DATA | R | W);821 dtorsSec = createSection(".dtors", data | r | w);
726822
727 // Then bin chunks by name and output characteristics.823 // Then bin chunks by name and output characteristics.
728 std::map<std::pair<StringRef, uint32_t>, std::vector<Chunk *>> Map;824 for (Chunk *c : symtab->getChunks()) {
729 for (Chunk *C : Symtab->getChunks()) {825 auto *sc = dyn_cast<SectionChunk>(c);
730 auto *SC = dyn_cast<SectionChunk>(C);826 if (sc && !sc->live) {
731 if (SC && !SC->Live) {827 if (config->verbose)
732 if (Config->Verbose)828 sc->printDiscardedMessage();
733 SC->printDiscardedMessage();
734 continue;829 continue;
735 }830 }
736 Map[{C->getSectionName(), C->getOutputCharacteristics()}].push_back(C);831 StringRef name = c->getSectionName();
832 if (shouldStripSectionSuffix(sc, name))
833 name = name.split('$').first;
834 PartialSection *pSec = createPartialSection(name,
835 c->getOutputCharacteristics());
836 pSec->chunks.push_back(c);
737 }837 }
738838
839 fixPartialSectionChars(".rsrc", data | r);
739 // Even in non MinGW cases, we might need to link against GNU import840 // Even in non MinGW cases, we might need to link against GNU import
740 // libraries.841 // libraries.
741 bool HasIdata = fixGnuImportChunks(Map);842 bool hasIdata = fixGnuImportChunks();
742 if (!Idata.empty())843 if (!idata.empty())
743 HasIdata = true;844 hasIdata = true;
744845
745 if (HasIdata)846 if (hasIdata)
746 addSyntheticIdata(Idata, Map);847 addSyntheticIdata();
747848
748 // Process an /order option.849 // Process an /order option.
749 if (!Config->Order.empty())850 if (!config->order.empty())
750 for (auto &Pair : Map)851 for (auto it : partialSections)
751 sortBySectionOrder(Pair.second);852 sortBySectionOrder(it.second->chunks);
752853
753 if (HasIdata)854 if (hasIdata)
754 locateImportTables(Map);855 locateImportTables();
755856
756 // Then create an OutputSection for each section.857 // Then create an OutputSection for each section.
757 // '$' and all following characters in input section names are858 // '$' and all following characters in input section names are
758 // discarded when determining output section. So, .text$foo859 // discarded when determining output section. So, .text$foo
759 // contributes to .text, for example. See PE/COFF spec 3.2.860 // contributes to .text, for example. See PE/COFF spec 3.2.
760 for (auto &Pair : Map) {861 for (auto it : partialSections) {
761 StringRef Name = getOutputSectionName(Pair.first.first);862 PartialSection *pSec = it.second;
762 uint32_t OutChars = Pair.first.second;863 StringRef name = getOutputSectionName(pSec->name);
864 uint32_t outChars = pSec->characteristics;
763865
764 if (Name == ".CRT") {866 if (name == ".CRT") {
765 // In link.exe, there is a special case for the I386 target where .CRT867 // 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 if868 // sections are treated as if they have output characteristics DATA | R if
767 // their characteristics are DATA | R | W. This implements the same869 // their characteristics are DATA | R | W. This implements the same
768 // special case for all architectures.870 // special case for all architectures.
769 OutChars = DATA | R;871 outChars = data | r;
770872
771 log("Processing section " + Pair.first.first + " -> " + Name);873 log("Processing section " + pSec->name + " -> " + name);
772874
773 sortCRTSectionChunks(Pair.second);875 sortCRTSectionChunks(pSec->chunks);
774 }876 }
775877
776 OutputSection *Sec = CreateSection(Name, OutChars);878 OutputSection *sec = createSection(name, outChars);
777 std::vector<Chunk *> &Chunks = Pair.second;879 for (Chunk *c : pSec->chunks)
778 for (Chunk *C : Chunks)880 sec->addChunk(c);
779 Sec->addChunk(C);881
882 sec->addContributingPartialSection(pSec);
780 }883 }
781884
782 // Finally, move some output sections to the end.885 // Finally, move some output sections to the end.
783 auto SectionOrder = [&](OutputSection *S) {886 auto sectionOrder = [&](const OutputSection *s) {
784 // Move DISCARDABLE (or non-memory-mapped) sections to the end of file because887 // Move DISCARDABLE (or non-memory-mapped) sections to the end of file
785 // the loader cannot handle holes. Stripping can remove other discardable ones888 // because the loader cannot handle holes. Stripping can remove other
786 // than .reloc, which is first of them (created early).889 // discardable ones than .reloc, which is first of them (created early).
787 if (S->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)890 if (s->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
788 return 2;891 return 2;
789 // .rsrc should come at the end of the non-discardable sections because its892 // .rsrc should come at the end of the non-discardable sections because its
790 // size may change by the Win32 UpdateResources() function, causing893 // size may change by the Win32 UpdateResources() function, causing
791 // subsequent sections to move (see https://crbug.com/827082).894 // subsequent sections to move (see https://crbug.com/827082).
792 if (S == RsrcSec)895 if (s == rsrcSec)
793 return 1;896 return 1;
794 return 0;897 return 0;
795 };898 };
796 std::stable_sort(OutputSections.begin(), OutputSections.end(),899 llvm::stable_sort(outputSections,
797 [&](OutputSection *S, OutputSection *T) {900 [&](const OutputSection *s, const OutputSection *t) {
798 return SectionOrder(S) < SectionOrder(T);901 return sectionOrder(s) < sectionOrder(t);
799 });902 });
800}903}
801904
802void Writer::createMiscChunks() {905void Writer::createMiscChunks() {
803 for (auto &P : MergeChunk::Instances)906 for (MergeChunk *p : MergeChunk::instances) {
804 RdataSec->addChunk(P.second);907 if (p) {
908 p->finalizeContents();
909 rdataSec->addChunk(p);
910 }
911 }
805912
806 // Create thunks for locally-dllimported symbols.913 // Create thunks for locally-dllimported symbols.
807 if (!Symtab->LocalImportChunks.empty()) {914 if (!symtab->localImportChunks.empty()) {
808 for (Chunk *C : Symtab->LocalImportChunks)915 for (Chunk *c : symtab->localImportChunks)
809 RdataSec->addChunk(C);916 rdataSec->addChunk(c);
810 }917 }
811918
812 // Create Debug Information Chunks919 // Create Debug Information Chunks
813 OutputSection *DebugInfoSec = Config->MinGW ? BuildidSec : RdataSec;920 OutputSection *debugInfoSec = config->mingw ? buildidSec : rdataSec;
814 if (Config->Debug || Config->Repro) {921 if (config->debug || config->repro) {
815 DebugDirectory = make<DebugDirectoryChunk>(DebugRecords, Config->Repro);922 debugDirectory = make<DebugDirectoryChunk>(debugRecords, config->repro);
816 DebugInfoSec->addChunk(DebugDirectory);923 debugInfoSec->addChunk(debugDirectory);
817 }924 }
818925
819 if (Config->Debug) {926 if (config->debug) {
820 // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified. We927 // Make a CVDebugRecordChunk even when /DEBUG:CV is not specified. We
821 // output a PDB no matter what, and this chunk provides the only means of928 // output a PDB no matter what, and this chunk provides the only means of
822 // allowing a debugger to match a PDB and an executable. So we need it even929 // allowing a debugger to match a PDB and an executable. So we need it even
823 // if we're ultimately not going to write CodeView data to the PDB.930 // if we're ultimately not going to write CodeView data to the PDB.
824 BuildId = make<CVDebugRecordChunk>();931 buildId = make<CVDebugRecordChunk>();
825 DebugRecords.push_back(BuildId);932 debugRecords.push_back(buildId);
826933
827 for (Chunk *C : DebugRecords)934 for (Chunk *c : debugRecords)
828 DebugInfoSec->addChunk(C);935 debugInfoSec->addChunk(c);
829 }936 }
830937
831 // Create SEH table. x86-only.938 // Create SEH table. x86-only.
832 if (Config->Machine == I386)939 if (config->safeSEH)
833 createSEHTable();940 createSEHTable();
834941
835 // Create /guard:cf tables if requested.942 // Create /guard:cf tables if requested.
836 if (Config->GuardCF != GuardCFLevel::Off)943 if (config->guardCF != GuardCFLevel::Off)
837 createGuardCFTables();944 createGuardCFTables();
838945
839 if (Config->MinGW) {946 if (config->mingw) {
840 createRuntimePseudoRelocs();947 createRuntimePseudoRelocs();
841948
842 insertCtorDtorSymbols();949 insertCtorDtorSymbols();
...@@ -851,106 +958,123 @@ void Writer::createImportTables() {...@@ -851,106 +958,123 @@ void Writer::createImportTables() {
851 // Initialize DLLOrder so that import entries are ordered in958 // Initialize DLLOrder so that import entries are ordered in
852 // the same order as in the command line. (That affects DLL959 // the same order as in the command line. (That affects DLL
853 // initialization order, and this ordering is MSVC-compatible.)960 // initialization order, and this ordering is MSVC-compatible.)
854 for (ImportFile *File : ImportFile::Instances) {961 for (ImportFile *file : ImportFile::instances) {
855 if (!File->Live)962 if (!file->live)
856 continue;963 continue;
857964
858 std::string DLL = StringRef(File->DLLName).lower();965 std::string dll = StringRef(file->dllName).lower();
859 if (Config->DLLOrder.count(DLL) == 0)966 if (config->dllOrder.count(dll) == 0)
860 Config->DLLOrder[DLL] = Config->DLLOrder.size();967 config->dllOrder[dll] = config->dllOrder.size();
861968
862 if (File->ImpSym && !isa<DefinedImportData>(File->ImpSym))969 if (file->impSym && !isa<DefinedImportData>(file->impSym))
863 fatal(toString(*File->ImpSym) + " was replaced");970 fatal(toString(*file->impSym) + " was replaced");
864 DefinedImportData *ImpSym = cast_or_null<DefinedImportData>(File->ImpSym);971 DefinedImportData *impSym = cast_or_null<DefinedImportData>(file->impSym);
865 if (Config->DelayLoads.count(StringRef(File->DLLName).lower())) {972 if (config->delayLoads.count(StringRef(file->dllName).lower())) {
866 if (!File->ThunkSym)973 if (!file->thunkSym)
867 fatal("cannot delay-load " + toString(File) +974 fatal("cannot delay-load " + toString(file) +
868 " due to import of data: " + toString(*ImpSym));975 " due to import of data: " + toString(*impSym));
869 DelayIdata.add(ImpSym);976 delayIdata.add(impSym);
870 } else {977 } else {
871 Idata.add(ImpSym);978 idata.add(impSym);
872 }979 }
873 }980 }
874}981}
875982
876void Writer::appendImportThunks() {983void Writer::appendImportThunks() {
877 if (ImportFile::Instances.empty())984 if (ImportFile::instances.empty())
878 return;985 return;
879986
880 for (ImportFile *File : ImportFile::Instances) {987 for (ImportFile *file : ImportFile::instances) {
881 if (!File->Live)988 if (!file->live)
882 continue;989 continue;
883990
884 if (!File->ThunkSym)991 if (!file->thunkSym)
885 continue;992 continue;
886993
887 if (!isa<DefinedImportThunk>(File->ThunkSym))994 if (!isa<DefinedImportThunk>(file->thunkSym))
888 fatal(toString(*File->ThunkSym) + " was replaced");995 fatal(toString(*file->thunkSym) + " was replaced");
889 DefinedImportThunk *Thunk = cast<DefinedImportThunk>(File->ThunkSym);996 DefinedImportThunk *thunk = cast<DefinedImportThunk>(file->thunkSym);
890 if (File->ThunkLive)997 if (file->thunkLive)
891 TextSec->addChunk(Thunk->getChunk());998 textSec->addChunk(thunk->getChunk());
892 }999 }
8931000
894 if (!DelayIdata.empty()) {1001 if (!delayIdata.empty()) {
895 Defined *Helper = cast<Defined>(Config->DelayLoadHelper);1002 Defined *helper = cast<Defined>(config->delayLoadHelper);
896 DelayIdata.create(Helper);1003 delayIdata.create(helper);
897 for (Chunk *C : DelayIdata.getChunks())1004 for (Chunk *c : delayIdata.getChunks())
898 DidatSec->addChunk(C);1005 didatSec->addChunk(c);
899 for (Chunk *C : DelayIdata.getDataChunks())1006 for (Chunk *c : delayIdata.getDataChunks())
900 DataSec->addChunk(C);1007 dataSec->addChunk(c);
901 for (Chunk *C : DelayIdata.getCodeChunks())1008 for (Chunk *c : delayIdata.getCodeChunks())
902 TextSec->addChunk(C);1009 textSec->addChunk(c);
903 }1010 }
904}1011}
9051012
906void Writer::createExportTable() {1013void Writer::createExportTable() {
907 if (Config->Exports.empty())1014 if (config->exports.empty())
908 return;1015 return;
909 for (Chunk *C : Edata.Chunks)1016 for (Chunk *c : edata.chunks)
910 EdataSec->addChunk(C);1017 edataSec->addChunk(c);
911}1018}
9121019
913void Writer::removeUnusedSections() {1020void Writer::removeUnusedSections() {
914 // Remove sections that we can be sure won't get content, to avoid1021 // Remove sections that we can be sure won't get content, to avoid
915 // allocating space for their section headers.1022 // allocating space for their section headers.
916 auto IsUnused = [this](OutputSection *S) {1023 auto isUnused = [this](OutputSection *s) {
917 if (S == RelocSec)1024 if (s == relocSec)
918 return false; // This section is populated later.1025 return false; // This section is populated later.
919 // MergeChunks have zero size at this point, as their size is finalized1026 // MergeChunks have zero size at this point, as their size is finalized
920 // later. Only remove sections that have no Chunks at all.1027 // later. Only remove sections that have no Chunks at all.
921 return S->Chunks.empty();1028 return s->chunks.empty();
922 };1029 };
923 OutputSections.erase(1030 outputSections.erase(
924 std::remove_if(OutputSections.begin(), OutputSections.end(), IsUnused),1031 std::remove_if(outputSections.begin(), outputSections.end(), isUnused),
925 OutputSections.end());1032 outputSections.end());
926}1033}
9271034
928// The Windows loader doesn't seem to like empty sections,1035// The Windows loader doesn't seem to like empty sections,
929// so we remove them if any.1036// so we remove them if any.
930void Writer::removeEmptySections() {1037void Writer::removeEmptySections() {
931 auto IsEmpty = [](OutputSection *S) { return S->getVirtualSize() == 0; };1038 auto isEmpty = [](OutputSection *s) { return s->getVirtualSize() == 0; };
932 OutputSections.erase(1039 outputSections.erase(
933 std::remove_if(OutputSections.begin(), OutputSections.end(), IsEmpty),1040 std::remove_if(outputSections.begin(), outputSections.end(), isEmpty),
934 OutputSections.end());1041 outputSections.end());
935 uint32_t Idx = 1;
936 for (OutputSection *Sec : OutputSections)
937 Sec->SectionIndex = Idx++;
938}1042}
9391043
940size_t Writer::addEntryToStringTable(StringRef Str) {1044void Writer::assignOutputSectionIndices() {
941 assert(Str.size() > COFF::NameSize);1045 // Assign final output section indices, and assign each chunk to its output
942 size_t OffsetOfEntry = Strtab.size() + 4; // +4 for the size field1046 // section.
943 Strtab.insert(Strtab.end(), Str.begin(), Str.end());1047 uint32_t idx = 1;
944 Strtab.push_back('\0');1048 for (OutputSection *os : outputSections) {
945 return OffsetOfEntry;1049 os->sectionIndex = idx;
1050 for (Chunk *c : os->chunks)
1051 c->setOutputSectionIdx(idx);
1052 ++idx;
1053 }
1054
1055 // Merge chunks are containers of chunks, so assign those an output section
1056 // too.
1057 for (MergeChunk *mc : MergeChunk::instances)
1058 if (mc)
1059 for (SectionChunk *sc : mc->sections)
1060 if (sc && sc->live)
1061 sc->setOutputSectionIdx(mc->getOutputSectionIdx());
946}1062}
9471063
948Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {1064size_t Writer::addEntryToStringTable(StringRef str) {
949 coff_symbol16 Sym;1065 assert(str.size() > COFF::NameSize);
950 switch (Def->kind()) {1066 size_t offsetOfEntry = strtab.size() + 4; // +4 for the size field
1067 strtab.insert(strtab.end(), str.begin(), str.end());
1068 strtab.push_back('\0');
1069 return offsetOfEntry;
1070}
1071
1072Optional<coff_symbol16> Writer::createSymbol(Defined *def) {
1073 coff_symbol16 sym;
1074 switch (def->kind()) {
951 case Symbol::DefinedAbsoluteKind:1075 case Symbol::DefinedAbsoluteKind:
952 Sym.Value = Def->getRVA();1076 sym.Value = def->getRVA();
953 Sym.SectionNumber = IMAGE_SYM_ABSOLUTE;1077 sym.SectionNumber = IMAGE_SYM_ABSOLUTE;
954 break;1078 break;
955 case Symbol::DefinedSyntheticKind:1079 case Symbol::DefinedSyntheticKind:
956 // Relative symbols are unrepresentable in a COFF symbol table.1080 // Relative symbols are unrepresentable in a COFF symbol table.
...@@ -958,38 +1082,38 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {...@@ -958,38 +1082,38 @@ Optional<coff_symbol16> Writer::createSymbol(Defined *Def) {
958 default: {1082 default: {
959 // Don't write symbols that won't be written to the output to the symbol1083 // Don't write symbols that won't be written to the output to the symbol
960 // table.1084 // table.
961 Chunk *C = Def->getChunk();1085 Chunk *c = def->getChunk();
962 if (!C)1086 if (!c)
963 return None;1087 return None;
964 OutputSection *OS = C->getOutputSection();1088 OutputSection *os = c->getOutputSection();
965 if (!OS)1089 if (!os)
966 return None;1090 return None;
9671091
968 Sym.Value = Def->getRVA() - OS->getRVA();1092 sym.Value = def->getRVA() - os->getRVA();
969 Sym.SectionNumber = OS->SectionIndex;1093 sym.SectionNumber = os->sectionIndex;
970 break;1094 break;
971 }1095 }
972 }1096 }
9731097
974 StringRef Name = Def->getName();1098 StringRef name = def->getName();
975 if (Name.size() > COFF::NameSize) {1099 if (name.size() > COFF::NameSize) {
976 Sym.Name.Offset.Zeroes = 0;1100 sym.Name.Offset.Zeroes = 0;
977 Sym.Name.Offset.Offset = addEntryToStringTable(Name);1101 sym.Name.Offset.Offset = addEntryToStringTable(name);
978 } else {1102 } else {
979 memset(Sym.Name.ShortName, 0, COFF::NameSize);1103 memset(sym.Name.ShortName, 0, COFF::NameSize);
980 memcpy(Sym.Name.ShortName, Name.data(), Name.size());1104 memcpy(sym.Name.ShortName, name.data(), name.size());
981 }1105 }
9821106
983 if (auto *D = dyn_cast<DefinedCOFF>(Def)) {1107 if (auto *d = dyn_cast<DefinedCOFF>(def)) {
984 COFFSymbolRef Ref = D->getCOFFSymbol();1108 COFFSymbolRef ref = d->getCOFFSymbol();
985 Sym.Type = Ref.getType();1109 sym.Type = ref.getType();
986 Sym.StorageClass = Ref.getStorageClass();1110 sym.StorageClass = ref.getStorageClass();
987 } else {1111 } else {
988 Sym.Type = IMAGE_SYM_TYPE_NULL;1112 sym.Type = IMAGE_SYM_TYPE_NULL;
989 Sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;1113 sym.StorageClass = IMAGE_SYM_CLASS_EXTERNAL;
990 }1114 }
991 Sym.NumberOfAuxSymbols = 0;1115 sym.NumberOfAuxSymbols = 0;
992 return Sym;1116 return sym;
993}1117}
9941118
995void Writer::createSymbolAndStringTable() {1119void Writer::createSymbolAndStringTable() {
...@@ -1001,113 +1125,120 @@ void Writer::createSymbolAndStringTable() {...@@ -1001,113 +1125,120 @@ void Writer::createSymbolAndStringTable() {
1001 // solution where discardable sections have long names preserved and1125 // solution where discardable sections have long names preserved and
1002 // non-discardable sections have their names truncated, to ensure that any1126 // non-discardable sections have their names truncated, to ensure that any
1003 // section which is mapped at runtime also has its name mapped at runtime.1127 // section which is mapped at runtime also has its name mapped at runtime.
1004 for (OutputSection *Sec : OutputSections) {1128 for (OutputSection *sec : outputSections) {
1005 if (Sec->Name.size() <= COFF::NameSize)1129 if (sec->name.size() <= COFF::NameSize)
1006 continue;1130 continue;
1007 if ((Sec->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0)1131 if ((sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE) == 0)
1008 continue;1132 continue;
1009 Sec->setStringTableOff(addEntryToStringTable(Sec->Name));1133 sec->setStringTableOff(addEntryToStringTable(sec->name));
1010 }1134 }
10111135
1012 if (Config->DebugDwarf || Config->DebugSymtab) {1136 if (config->debugDwarf || config->debugSymtab) {
1013 for (ObjFile *File : ObjFile::Instances) {1137 for (ObjFile *file : ObjFile::instances) {
1014 for (Symbol *B : File->getSymbols()) {1138 for (Symbol *b : file->getSymbols()) {
1015 auto *D = dyn_cast_or_null<Defined>(B);1139 auto *d = dyn_cast_or_null<Defined>(b);
1016 if (!D || D->WrittenToSymtab)1140 if (!d || d->writtenToSymtab)
1017 continue;1141 continue;
1018 D->WrittenToSymtab = true;1142 d->writtenToSymtab = true;
10191143
1020 if (Optional<coff_symbol16> Sym = createSymbol(D))1144 if (Optional<coff_symbol16> sym = createSymbol(d))
1021 OutputSymtab.push_back(*Sym);1145 outputSymtab.push_back(*sym);
1022 }1146 }
1023 }1147 }
1024 }1148 }
10251149
1026 if (OutputSymtab.empty() && Strtab.empty())1150 if (outputSymtab.empty() && strtab.empty())
1027 return;1151 return;
10281152
1029 // We position the symbol table to be adjacent to the end of the last section.1153 // We position the symbol table to be adjacent to the end of the last section.
1030 uint64_t FileOff = FileSize;1154 uint64_t fileOff = fileSize;
1031 PointerToSymbolTable = FileOff;1155 pointerToSymbolTable = fileOff;
1032 FileOff += OutputSymtab.size() * sizeof(coff_symbol16);1156 fileOff += outputSymtab.size() * sizeof(coff_symbol16);
1033 FileOff += 4 + Strtab.size();1157 fileOff += 4 + strtab.size();
1034 FileSize = alignTo(FileOff, SectorSize);1158 fileSize = alignTo(fileOff, config->fileAlign);
1035}1159}
10361160
1037void Writer::mergeSections() {1161void Writer::mergeSections() {
1038 if (!PdataSec->Chunks.empty()) {1162 if (!pdataSec->chunks.empty()) {
1039 FirstPdata = PdataSec->Chunks.front();1163 firstPdata = pdataSec->chunks.front();
1040 LastPdata = PdataSec->Chunks.back();1164 lastPdata = pdataSec->chunks.back();
1041 }1165 }
10421166
1043 for (auto &P : Config->Merge) {1167 for (auto &p : config->merge) {
1044 StringRef ToName = P.second;1168 StringRef toName = p.second;
1045 if (P.first == ToName)1169 if (p.first == toName)
1046 continue;1170 continue;
1047 StringSet<> Names;1171 StringSet<> names;
1048 while (1) {1172 while (1) {
1049 if (!Names.insert(ToName).second)1173 if (!names.insert(toName).second)
1050 fatal("/merge: cycle found for section '" + P.first + "'");1174 fatal("/merge: cycle found for section '" + p.first + "'");
1051 auto I = Config->Merge.find(ToName);1175 auto i = config->merge.find(toName);
1052 if (I == Config->Merge.end())1176 if (i == config->merge.end())
1053 break;1177 break;
1054 ToName = I->second;1178 toName = i->second;
1055 }1179 }
1056 OutputSection *From = findSection(P.first);1180 OutputSection *from = findSection(p.first);
1057 OutputSection *To = findSection(ToName);1181 OutputSection *to = findSection(toName);
1058 if (!From)1182 if (!from)
1059 continue;1183 continue;
1060 if (!To) {1184 if (!to) {
1061 From->Name = ToName;1185 from->name = toName;
1062 continue;1186 continue;
1063 }1187 }
1064 To->merge(From);1188 to->merge(from);
1065 }1189 }
1066}1190}
10671191
1068// Visits all sections to initialize their relocation targets.
1069void 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
1075// Visits all sections to assign incremental, non-overlapping RVAs and1192// Visits all sections to assign incremental, non-overlapping RVAs and
1076// file offsets.1193// file offsets.
1077void Writer::assignAddresses() {1194void Writer::assignAddresses() {
1078 SizeOfHeaders = DOSStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +1195 sizeOfHeaders = dosStubSize + sizeof(PEMagic) + sizeof(coff_file_header) +
1079 sizeof(data_directory) * NumberOfDataDirectory +1196 sizeof(data_directory) * numberOfDataDirectory +
1080 sizeof(coff_section) * OutputSections.size();1197 sizeof(coff_section) * outputSections.size();
1081 SizeOfHeaders +=1198 sizeOfHeaders +=
1082 Config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);1199 config->is64() ? sizeof(pe32plus_header) : sizeof(pe32_header);
1083 SizeOfHeaders = alignTo(SizeOfHeaders, SectorSize);1200 sizeOfHeaders = alignTo(sizeOfHeaders, config->fileAlign);
1084 uint64_t RVA = PageSize; // The first page is kept unmapped.1201 uint64_t rva = pageSize; // The first page is kept unmapped.
1085 FileSize = SizeOfHeaders;1202 fileSize = sizeOfHeaders;
10861203
1087 for (OutputSection *Sec : OutputSections) {1204 for (OutputSection *sec : outputSections) {
1088 if (Sec == RelocSec)1205 if (sec == relocSec)
1089 addBaserels();1206 addBaserels();
1090 uint64_t RawSize = 0, VirtualSize = 0;1207 uint64_t rawSize = 0, virtualSize = 0;
1091 Sec->Header.VirtualAddress = RVA;1208 sec->header.VirtualAddress = rva;
1092 for (Chunk *C : Sec->Chunks) {1209
1093 VirtualSize = alignTo(VirtualSize, C->Alignment);1210 // If /FUNCTIONPADMIN is used, functions are padded in order to create a
1094 C->setRVA(RVA + VirtualSize);1211 // hotpatchable image.
1095 C->OutputSectionOff = VirtualSize;1212 const bool isCodeSection =
1096 C->finalizeContents();1213 (sec->header.Characteristics & IMAGE_SCN_CNT_CODE) &&
1097 VirtualSize += C->getSize();1214 (sec->header.Characteristics & IMAGE_SCN_MEM_READ) &&
1098 if (C->hasData())1215 (sec->header.Characteristics & IMAGE_SCN_MEM_EXECUTE);
1099 RawSize = alignTo(VirtualSize, SectorSize);1216 uint32_t padding = isCodeSection ? config->functionPadMin : 0;
1217
1218 for (Chunk *c : sec->chunks) {
1219 if (padding && c->isHotPatchable())
1220 virtualSize += padding;
1221 virtualSize = alignTo(virtualSize, c->getAlignment());
1222 c->setRVA(rva + virtualSize);
1223 virtualSize += c->getSize();
1224 if (c->hasData)
1225 rawSize = alignTo(virtualSize, config->fileAlign);
1100 }1226 }
1101 if (VirtualSize > UINT32_MAX)1227 if (virtualSize > UINT32_MAX)
1102 error("section larger than 4 GiB: " + Sec->Name);1228 error("section larger than 4 GiB: " + sec->name);
1103 Sec->Header.VirtualSize = VirtualSize;1229 sec->header.VirtualSize = virtualSize;
1104 Sec->Header.SizeOfRawData = RawSize;1230 sec->header.SizeOfRawData = rawSize;
1105 if (RawSize != 0)1231 if (rawSize != 0)
1106 Sec->Header.PointerToRawData = FileSize;1232 sec->header.PointerToRawData = fileSize;
1107 RVA += alignTo(VirtualSize, PageSize);1233 rva += alignTo(virtualSize, pageSize);
1108 FileSize += alignTo(RawSize, SectorSize);1234 fileSize += alignTo(rawSize, config->fileAlign);
1109 }1235 }
1110 SizeOfImage = alignTo(RVA, PageSize);1236 sizeOfImage = alignTo(rva, pageSize);
1237
1238 // Assign addresses to sections in MergeChunks.
1239 for (MergeChunk *mc : MergeChunk::instances)
1240 if (mc)
1241 mc->assignSubsectionRVAs();
1111}1242}
11121243
1113template <typename PEHeaderTy> void Writer::writeHeader() {1244template <typename PEHeaderTy> void Writer::writeHeader() {
...@@ -1116,275 +1247,299 @@ template <typename PEHeaderTy> void Writer::writeHeader() {...@@ -1116,275 +1247,299 @@ template <typename PEHeaderTy> void Writer::writeHeader() {
1116 // under DOS, that program gets run (usually to just print an error message).1247 // under DOS, that program gets run (usually to just print an error message).
1117 // When run under Windows, the loader looks at AddressOfNewExeHeader and uses1248 // When run under Windows, the loader looks at AddressOfNewExeHeader and uses
1118 // the PE header instead.1249 // the PE header instead.
1119 uint8_t *Buf = Buffer->getBufferStart();1250 uint8_t *buf = buffer->getBufferStart();
1120 auto *DOS = reinterpret_cast<dos_header *>(Buf);1251 auto *dos = reinterpret_cast<dos_header *>(buf);
1121 Buf += sizeof(dos_header);1252 buf += sizeof(dos_header);
1122 DOS->Magic[0] = 'M';1253 dos->Magic[0] = 'M';
1123 DOS->Magic[1] = 'Z';1254 dos->Magic[1] = 'Z';
1124 DOS->UsedBytesInTheLastPage = DOSStubSize % 512;1255 dos->UsedBytesInTheLastPage = dosStubSize % 512;
1125 DOS->FileSizeInPages = divideCeil(DOSStubSize, 512);1256 dos->FileSizeInPages = divideCeil(dosStubSize, 512);
1126 DOS->HeaderSizeInParagraphs = sizeof(dos_header) / 16;1257 dos->HeaderSizeInParagraphs = sizeof(dos_header) / 16;
11271258
1128 DOS->AddressOfRelocationTable = sizeof(dos_header);1259 dos->AddressOfRelocationTable = sizeof(dos_header);
1129 DOS->AddressOfNewExeHeader = DOSStubSize;1260 dos->AddressOfNewExeHeader = dosStubSize;
11301261
1131 // Write DOS program.1262 // Write DOS program.
1132 memcpy(Buf, DOSProgram, sizeof(DOSProgram));1263 memcpy(buf, dosProgram, sizeof(dosProgram));
1133 Buf += sizeof(DOSProgram);1264 buf += sizeof(dosProgram);
11341265
1135 // Write PE magic1266 // Write PE magic
1136 memcpy(Buf, PEMagic, sizeof(PEMagic));1267 memcpy(buf, PEMagic, sizeof(PEMagic));
1137 Buf += sizeof(PEMagic);1268 buf += sizeof(PEMagic);
11381269
1139 // Write COFF header1270 // Write COFF header
1140 auto *COFF = reinterpret_cast<coff_file_header *>(Buf);1271 auto *coff = reinterpret_cast<coff_file_header *>(buf);
1141 Buf += sizeof(*COFF);1272 buf += sizeof(*coff);
1142 COFF->Machine = Config->Machine;1273 coff->Machine = config->machine;
1143 COFF->NumberOfSections = OutputSections.size();1274 coff->NumberOfSections = outputSections.size();
1144 COFF->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;1275 coff->Characteristics = IMAGE_FILE_EXECUTABLE_IMAGE;
1145 if (Config->LargeAddressAware)1276 if (config->largeAddressAware)
1146 COFF->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;1277 coff->Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE;
1147 if (!Config->is64())1278 if (!config->is64())
1148 COFF->Characteristics |= IMAGE_FILE_32BIT_MACHINE;1279 coff->Characteristics |= IMAGE_FILE_32BIT_MACHINE;
1149 if (Config->DLL)1280 if (config->dll)
1150 COFF->Characteristics |= IMAGE_FILE_DLL;1281 coff->Characteristics |= IMAGE_FILE_DLL;
1151 if (!Config->Relocatable)1282 if (!config->relocatable)
1152 COFF->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;1283 coff->Characteristics |= IMAGE_FILE_RELOCS_STRIPPED;
1153 COFF->SizeOfOptionalHeader =1284 if (config->swaprunCD)
1154 sizeof(PEHeaderTy) + sizeof(data_directory) * NumberOfDataDirectory;1285 coff->Characteristics |= IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP;
1286 if (config->swaprunNet)
1287 coff->Characteristics |= IMAGE_FILE_NET_RUN_FROM_SWAP;
1288 coff->SizeOfOptionalHeader =
1289 sizeof(PEHeaderTy) + sizeof(data_directory) * numberOfDataDirectory;
11551290
1156 // Write PE header1291 // Write PE header
1157 auto *PE = reinterpret_cast<PEHeaderTy *>(Buf);1292 auto *pe = reinterpret_cast<PEHeaderTy *>(buf);
1158 Buf += sizeof(*PE);1293 buf += sizeof(*pe);
1159 PE->Magic = Config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32;1294 pe->Magic = config->is64() ? PE32Header::PE32_PLUS : PE32Header::PE32;
11601295
1161 // If {Major,Minor}LinkerVersion is left at 0.0, then for some1296 // If {Major,Minor}LinkerVersion is left at 0.0, then for some
1162 // reason signing the resulting PE file with Authenticode produces a1297 // reason signing the resulting PE file with Authenticode produces a
1163 // signature that fails to validate on Windows 7 (but is OK on 10).1298 // signature that fails to validate on Windows 7 (but is OK on 10).
1164 // Set it to 14.0, which is what VS2015 outputs, and which avoids1299 // Set it to 14.0, which is what VS2015 outputs, and which avoids
1165 // that problem.1300 // that problem.
1166 PE->MajorLinkerVersion = 14;1301 pe->MajorLinkerVersion = 14;
1167 PE->MinorLinkerVersion = 0;1302 pe->MinorLinkerVersion = 0;
11681303
1169 PE->ImageBase = Config->ImageBase;1304 pe->ImageBase = config->imageBase;
1170 PE->SectionAlignment = PageSize;1305 pe->SectionAlignment = pageSize;
1171 PE->FileAlignment = SectorSize;1306 pe->FileAlignment = config->fileAlign;
1172 PE->MajorImageVersion = Config->MajorImageVersion;1307 pe->MajorImageVersion = config->majorImageVersion;
1173 PE->MinorImageVersion = Config->MinorImageVersion;1308 pe->MinorImageVersion = config->minorImageVersion;
1174 PE->MajorOperatingSystemVersion = Config->MajorOSVersion;1309 pe->MajorOperatingSystemVersion = config->majorOSVersion;
1175 PE->MinorOperatingSystemVersion = Config->MinorOSVersion;1310 pe->MinorOperatingSystemVersion = config->minorOSVersion;
1176 PE->MajorSubsystemVersion = Config->MajorOSVersion;1311 pe->MajorSubsystemVersion = config->majorOSVersion;
1177 PE->MinorSubsystemVersion = Config->MinorOSVersion;1312 pe->MinorSubsystemVersion = config->minorOSVersion;
1178 PE->Subsystem = Config->Subsystem;1313 pe->Subsystem = config->subsystem;
1179 PE->SizeOfImage = SizeOfImage;1314 pe->SizeOfImage = sizeOfImage;
1180 PE->SizeOfHeaders = SizeOfHeaders;1315 pe->SizeOfHeaders = sizeOfHeaders;
1181 if (!Config->NoEntry) {1316 if (!config->noEntry) {
1182 Defined *Entry = cast<Defined>(Config->Entry);1317 Defined *entry = cast<Defined>(config->entry);
1183 PE->AddressOfEntryPoint = Entry->getRVA();1318 pe->AddressOfEntryPoint = entry->getRVA();
1184 // Pointer to thumb code must have the LSB set, so adjust it.1319 // Pointer to thumb code must have the LSB set, so adjust it.
1185 if (Config->Machine == ARMNT)1320 if (config->machine == ARMNT)
1186 PE->AddressOfEntryPoint |= 1;1321 pe->AddressOfEntryPoint |= 1;
1187 }1322 }
1188 PE->SizeOfStackReserve = Config->StackReserve;1323 pe->SizeOfStackReserve = config->stackReserve;
1189 PE->SizeOfStackCommit = Config->StackCommit;1324 pe->SizeOfStackCommit = config->stackCommit;
1190 PE->SizeOfHeapReserve = Config->HeapReserve;1325 pe->SizeOfHeapReserve = config->heapReserve;
1191 PE->SizeOfHeapCommit = Config->HeapCommit;1326 pe->SizeOfHeapCommit = config->heapCommit;
1192 if (Config->AppContainer)1327 if (config->appContainer)
1193 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER;1328 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_APPCONTAINER;
1194 if (Config->DynamicBase)1329 if (config->dynamicBase)
1195 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;1330 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE;
1196 if (Config->HighEntropyVA)1331 if (config->highEntropyVA)
1197 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;1332 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA;
1198 if (!Config->AllowBind)1333 if (!config->allowBind)
1199 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND;1334 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_BIND;
1200 if (Config->NxCompat)1335 if (config->nxCompat)
1201 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;1336 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NX_COMPAT;
1202 if (!Config->AllowIsolation)1337 if (!config->allowIsolation)
1203 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;1338 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION;
1204 if (Config->GuardCF != GuardCFLevel::Off)1339 if (config->guardCF != GuardCFLevel::Off)
1205 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF;1340 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_GUARD_CF;
1206 if (Config->IntegrityCheck)1341 if (config->integrityCheck)
1207 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;1342 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY;
1208 if (SetNoSEHCharacteristic)1343 if (setNoSEHCharacteristic)
1209 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH;1344 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_NO_SEH;
1210 if (Config->TerminalServerAware)1345 if (config->terminalServerAware)
1211 PE->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;1346 pe->DLLCharacteristics |= IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE;
1212 PE->NumberOfRvaAndSize = NumberOfDataDirectory;1347 pe->NumberOfRvaAndSize = numberOfDataDirectory;
1213 if (TextSec->getVirtualSize()) {1348 if (textSec->getVirtualSize()) {
1214 PE->BaseOfCode = TextSec->getRVA();1349 pe->BaseOfCode = textSec->getRVA();
1215 PE->SizeOfCode = TextSec->getRawSize();1350 pe->SizeOfCode = textSec->getRawSize();
1216 }1351 }
1217 PE->SizeOfInitializedData = getSizeOfInitializedData();1352 pe->SizeOfInitializedData = getSizeOfInitializedData();
12181353
1219 // Write data directory1354 // Write data directory
1220 auto *Dir = reinterpret_cast<data_directory *>(Buf);1355 auto *dir = reinterpret_cast<data_directory *>(buf);
1221 Buf += sizeof(*Dir) * NumberOfDataDirectory;1356 buf += sizeof(*dir) * numberOfDataDirectory;
1222 if (!Config->Exports.empty()) {1357 if (!config->exports.empty()) {
1223 Dir[EXPORT_TABLE].RelativeVirtualAddress = Edata.getRVA();1358 dir[EXPORT_TABLE].RelativeVirtualAddress = edata.getRVA();
1224 Dir[EXPORT_TABLE].Size = Edata.getSize();1359 dir[EXPORT_TABLE].Size = edata.getSize();
1225 }1360 }
1226 if (ImportTableStart) {1361 if (importTableStart) {
1227 Dir[IMPORT_TABLE].RelativeVirtualAddress = ImportTableStart->getRVA();1362 dir[IMPORT_TABLE].RelativeVirtualAddress = importTableStart->getRVA();
1228 Dir[IMPORT_TABLE].Size = ImportTableSize;1363 dir[IMPORT_TABLE].Size = importTableSize;
1229 }1364 }
1230 if (IATStart) {1365 if (iatStart) {
1231 Dir[IAT].RelativeVirtualAddress = IATStart->getRVA();1366 dir[IAT].RelativeVirtualAddress = iatStart->getRVA();
1232 Dir[IAT].Size = IATSize;1367 dir[IAT].Size = iatSize;
1233 }1368 }
1234 if (RsrcSec->getVirtualSize()) {1369 if (rsrcSec->getVirtualSize()) {
1235 Dir[RESOURCE_TABLE].RelativeVirtualAddress = RsrcSec->getRVA();1370 dir[RESOURCE_TABLE].RelativeVirtualAddress = rsrcSec->getRVA();
1236 Dir[RESOURCE_TABLE].Size = RsrcSec->getVirtualSize();1371 dir[RESOURCE_TABLE].Size = rsrcSec->getVirtualSize();
1237 }1372 }
1238 if (FirstPdata) {1373 if (firstPdata) {
1239 Dir[EXCEPTION_TABLE].RelativeVirtualAddress = FirstPdata->getRVA();1374 dir[EXCEPTION_TABLE].RelativeVirtualAddress = firstPdata->getRVA();
1240 Dir[EXCEPTION_TABLE].Size =1375 dir[EXCEPTION_TABLE].Size =
1241 LastPdata->getRVA() + LastPdata->getSize() - FirstPdata->getRVA();1376 lastPdata->getRVA() + lastPdata->getSize() - firstPdata->getRVA();
1242 }1377 }
1243 if (RelocSec->getVirtualSize()) {1378 if (relocSec->getVirtualSize()) {
1244 Dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = RelocSec->getRVA();1379 dir[BASE_RELOCATION_TABLE].RelativeVirtualAddress = relocSec->getRVA();
1245 Dir[BASE_RELOCATION_TABLE].Size = RelocSec->getVirtualSize();1380 dir[BASE_RELOCATION_TABLE].Size = relocSec->getVirtualSize();
1246 }1381 }
1247 if (Symbol *Sym = Symtab->findUnderscore("_tls_used")) {1382 if (Symbol *sym = symtab->findUnderscore("_tls_used")) {
1248 if (Defined *B = dyn_cast<Defined>(Sym)) {1383 if (Defined *b = dyn_cast<Defined>(sym)) {
1249 Dir[TLS_TABLE].RelativeVirtualAddress = B->getRVA();1384 dir[TLS_TABLE].RelativeVirtualAddress = b->getRVA();
1250 Dir[TLS_TABLE].Size = Config->is64()1385 dir[TLS_TABLE].Size = config->is64()
1251 ? sizeof(object::coff_tls_directory64)1386 ? sizeof(object::coff_tls_directory64)
1252 : sizeof(object::coff_tls_directory32);1387 : sizeof(object::coff_tls_directory32);
1253 }1388 }
1254 }1389 }
1255 if (DebugDirectory) {1390 if (debugDirectory) {
1256 Dir[DEBUG_DIRECTORY].RelativeVirtualAddress = DebugDirectory->getRVA();1391 dir[DEBUG_DIRECTORY].RelativeVirtualAddress = debugDirectory->getRVA();
1257 Dir[DEBUG_DIRECTORY].Size = DebugDirectory->getSize();1392 dir[DEBUG_DIRECTORY].Size = debugDirectory->getSize();
1258 }1393 }
1259 if (Symbol *Sym = Symtab->findUnderscore("_load_config_used")) {1394 if (Symbol *sym = symtab->findUnderscore("_load_config_used")) {
1260 if (auto *B = dyn_cast<DefinedRegular>(Sym)) {1395 if (auto *b = dyn_cast<DefinedRegular>(sym)) {
1261 SectionChunk *SC = B->getChunk();1396 SectionChunk *sc = b->getChunk();
1262 assert(B->getRVA() >= SC->getRVA());1397 assert(b->getRVA() >= sc->getRVA());
1263 uint64_t OffsetInChunk = B->getRVA() - SC->getRVA();1398 uint64_t offsetInChunk = b->getRVA() - sc->getRVA();
1264 if (!SC->hasData() || OffsetInChunk + 4 > SC->getSize())1399 if (!sc->hasData || offsetInChunk + 4 > sc->getSize())
1265 fatal("_load_config_used is malformed");1400 fatal("_load_config_used is malformed");
12661401
1267 ArrayRef<uint8_t> SecContents = SC->getContents();1402 ArrayRef<uint8_t> secContents = sc->getContents();
1268 uint32_t LoadConfigSize =1403 uint32_t loadConfigSize =
1269 *reinterpret_cast<const ulittle32_t *>(&SecContents[OffsetInChunk]);1404 *reinterpret_cast<const ulittle32_t *>(&secContents[offsetInChunk]);
1270 if (OffsetInChunk + LoadConfigSize > SC->getSize())1405 if (offsetInChunk + loadConfigSize > sc->getSize())
1271 fatal("_load_config_used is too large");1406 fatal("_load_config_used is too large");
1272 Dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = B->getRVA();1407 dir[LOAD_CONFIG_TABLE].RelativeVirtualAddress = b->getRVA();
1273 Dir[LOAD_CONFIG_TABLE].Size = LoadConfigSize;1408 dir[LOAD_CONFIG_TABLE].Size = loadConfigSize;
1274 }1409 }
1275 }1410 }
1276 if (!DelayIdata.empty()) {1411 if (!delayIdata.empty()) {
1277 Dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =1412 dir[DELAY_IMPORT_DESCRIPTOR].RelativeVirtualAddress =
1278 DelayIdata.getDirRVA();1413 delayIdata.getDirRVA();
1279 Dir[DELAY_IMPORT_DESCRIPTOR].Size = DelayIdata.getDirSize();1414 dir[DELAY_IMPORT_DESCRIPTOR].Size = delayIdata.getDirSize();
1280 }1415 }
12811416
1282 // Write section table1417 // Write section table
1283 for (OutputSection *Sec : OutputSections) {1418 for (OutputSection *sec : outputSections) {
1284 Sec->writeHeaderTo(Buf);1419 sec->writeHeaderTo(buf);
1285 Buf += sizeof(coff_section);1420 buf += sizeof(coff_section);
1286 }1421 }
1287 SectionTable = ArrayRef<uint8_t>(1422 sectionTable = ArrayRef<uint8_t>(
1288 Buf - OutputSections.size() * sizeof(coff_section), Buf);1423 buf - outputSections.size() * sizeof(coff_section), buf);
12891424
1290 if (OutputSymtab.empty() && Strtab.empty())1425 if (outputSymtab.empty() && strtab.empty())
1291 return;1426 return;
12921427
1293 COFF->PointerToSymbolTable = PointerToSymbolTable;1428 coff->PointerToSymbolTable = pointerToSymbolTable;
1294 uint32_t NumberOfSymbols = OutputSymtab.size();1429 uint32_t numberOfSymbols = outputSymtab.size();
1295 COFF->NumberOfSymbols = NumberOfSymbols;1430 coff->NumberOfSymbols = numberOfSymbols;
1296 auto *SymbolTable = reinterpret_cast<coff_symbol16 *>(1431 auto *symbolTable = reinterpret_cast<coff_symbol16 *>(
1297 Buffer->getBufferStart() + COFF->PointerToSymbolTable);1432 buffer->getBufferStart() + coff->PointerToSymbolTable);
1298 for (size_t I = 0; I != NumberOfSymbols; ++I)1433 for (size_t i = 0; i != numberOfSymbols; ++i)
1299 SymbolTable[I] = OutputSymtab[I];1434 symbolTable[i] = outputSymtab[i];
1300 // Create the string table, it follows immediately after the symbol table.1435 // Create the string table, it follows immediately after the symbol table.
1301 // The first 4 bytes is length including itself.1436 // The first 4 bytes is length including itself.
1302 Buf = reinterpret_cast<uint8_t *>(&SymbolTable[NumberOfSymbols]);1437 buf = reinterpret_cast<uint8_t *>(&symbolTable[numberOfSymbols]);
1303 write32le(Buf, Strtab.size() + 4);1438 write32le(buf, strtab.size() + 4);
1304 if (!Strtab.empty())1439 if (!strtab.empty())
1305 memcpy(Buf + 4, Strtab.data(), Strtab.size());1440 memcpy(buf + 4, strtab.data(), strtab.size());
1306}1441}
13071442
1308void Writer::openFile(StringRef Path) {1443void Writer::openFile(StringRef path) {
1309 Buffer = CHECK(1444 buffer = CHECK(
1310 FileOutputBuffer::create(Path, FileSize, FileOutputBuffer::F_executable),1445 FileOutputBuffer::create(path, fileSize, FileOutputBuffer::F_executable),
1311 "failed to open " + Path);1446 "failed to open " + path);
1312}1447}
13131448
1314void Writer::createSEHTable() {1449void Writer::createSEHTable() {
1315 // Set the no SEH characteristic on x86 binaries unless we find exception1450 SymbolRVASet handlers;
1316 // handlers.1451 for (ObjFile *file : ObjFile::instances) {
1317 SetNoSEHCharacteristic = true;1452 if (!file->hasSafeSEH())
13181453 error("/safeseh: " + file->getName() + " is not compatible with SEH");
1319 SymbolRVASet Handlers;1454 markSymbolsForRVATable(file, file->getSXDataChunks(), handlers);
1320 for (ObjFile *File : ObjFile::Instances) {
1321 // FIXME: We should error here instead of earlier unless /safeseh:no was
1322 // passed.
1323 if (!File->hasSafeSEH())
1324 return;
1325
1326 markSymbolsForRVATable(File, File->getSXDataChunks(), Handlers);
1327 }1455 }
13281456
1329 // Remove the "no SEH" characteristic if all object files were built with1457 // Set the "no SEH" characteristic if there really were no handlers, or if
1330 // safeseh, we found some exception handlers, and there is a load config in1458 // there is no load config object to point to the table of handlers.
1331 // the object.1459 setNoSEHCharacteristic =
1332 SetNoSEHCharacteristic =1460 handlers.empty() || !symtab->findUnderscore("_load_config_used");
1333 Handlers.empty() || !Symtab->findUnderscore("_load_config_used");
13341461
1335 maybeAddRVATable(std::move(Handlers), "__safe_se_handler_table",1462 maybeAddRVATable(std::move(handlers), "__safe_se_handler_table",
1336 "__safe_se_handler_count");1463 "__safe_se_handler_count");
1337}1464}
13381465
1339// Add a symbol to an RVA set. Two symbols may have the same RVA, but an RVA set1466// Add a symbol to an RVA set. Two symbols may have the same RVA, but an RVA set
1340// cannot contain duplicates. Therefore, the set is uniqued by Chunk and the1467// cannot contain duplicates. Therefore, the set is uniqued by Chunk and the
1341// symbol's offset into that Chunk.1468// symbol's offset into that Chunk.
1342static void addSymbolToRVASet(SymbolRVASet &RVASet, Defined *S) {1469static void addSymbolToRVASet(SymbolRVASet &rvaSet, Defined *s) {
1343 Chunk *C = S->getChunk();1470 Chunk *c = s->getChunk();
1344 if (auto *SC = dyn_cast<SectionChunk>(C))1471 if (auto *sc = dyn_cast<SectionChunk>(c))
1345 C = SC->Repl; // Look through ICF replacement.1472 c = sc->repl; // Look through ICF replacement.
1346 uint32_t Off = S->getRVA() - (C ? C->getRVA() : 0);1473 uint32_t off = s->getRVA() - (c ? c->getRVA() : 0);
1347 RVASet.insert({C, Off});1474 rvaSet.insert({c, off});
1348}1475}
13491476
1350// Given a symbol, add it to the GFIDs table if it is a live, defined, function1477// Given a symbol, add it to the GFIDs table if it is a live, defined, function
1351// symbol in an executable section.1478// symbol in an executable section.
1352static void maybeAddAddressTakenFunction(SymbolRVASet &AddressTakenSyms,1479static void maybeAddAddressTakenFunction(SymbolRVASet &addressTakenSyms,
1353 Symbol *S) {1480 Symbol *s) {
1354 auto *D = dyn_cast_or_null<DefinedCOFF>(S);1481 if (!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;1482 return;
13611483
1362 // Mark the symbol as address taken if it's in an executable section.1484 switch (s->kind()) {
1363 Chunk *RefChunk = D->getChunk();1485 case Symbol::DefinedLocalImportKind:
1364 OutputSection *OS = RefChunk ? RefChunk->getOutputSection() : nullptr;1486 case Symbol::DefinedImportDataKind:
1365 if (OS && OS->Header.Characteristics & IMAGE_SCN_MEM_EXECUTE)1487 // Defines an __imp_ pointer, so it is data, so it is ignored.
1366 addSymbolToRVASet(AddressTakenSyms, D);1488 break;
1489 case Symbol::DefinedCommonKind:
1490 // Common is always data, so it is ignored.
1491 break;
1492 case Symbol::DefinedAbsoluteKind:
1493 case Symbol::DefinedSyntheticKind:
1494 // Absolute is never code, synthetic generally isn't and usually isn't
1495 // determinable.
1496 break;
1497 case Symbol::LazyKind:
1498 case Symbol::UndefinedKind:
1499 // Undefined symbols resolve to zero, so they don't have an RVA. Lazy
1500 // symbols shouldn't have relocations.
1501 break;
1502
1503 case Symbol::DefinedImportThunkKind:
1504 // Thunks are always code, include them.
1505 addSymbolToRVASet(addressTakenSyms, cast<Defined>(s));
1506 break;
1507
1508 case Symbol::DefinedRegularKind: {
1509 // This is a regular, defined, symbol from a COFF file. Mark the symbol as
1510 // address taken if the symbol type is function and it's in an executable
1511 // section.
1512 auto *d = cast<DefinedRegular>(s);
1513 if (d->getCOFFSymbol().getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION) {
1514 SectionChunk *sc = dyn_cast<SectionChunk>(d->getChunk());
1515 if (sc && sc->live &&
1516 sc->getOutputCharacteristics() & IMAGE_SCN_MEM_EXECUTE)
1517 addSymbolToRVASet(addressTakenSyms, d);
1518 }
1519 break;
1520 }
1521 }
1367}1522}
13681523
1369// Visit all relocations from all section contributions of this object file and1524// Visit all relocations from all section contributions of this object file and
1370// mark the relocation target as address-taken.1525// mark the relocation target as address-taken.
1371static void markSymbolsWithRelocations(ObjFile *File,1526static void markSymbolsWithRelocations(ObjFile *file,
1372 SymbolRVASet &UsedSymbols) {1527 SymbolRVASet &usedSymbols) {
1373 for (Chunk *C : File->getChunks()) {1528 for (Chunk *c : file->getChunks()) {
1374 // We only care about live section chunks. Common chunks and other chunks1529 // We only care about live section chunks. Common chunks and other chunks
1375 // don't generally contain relocations.1530 // don't generally contain relocations.
1376 SectionChunk *SC = dyn_cast<SectionChunk>(C);1531 SectionChunk *sc = dyn_cast<SectionChunk>(c);
1377 if (!SC || !SC->Live)1532 if (!sc || !sc->live)
1378 continue;1533 continue;
13791534
1380 for (const coff_relocation &Reloc : SC->Relocs) {1535 for (const coff_relocation &reloc : sc->getRelocs()) {
1381 if (Config->Machine == I386 && Reloc.Type == COFF::IMAGE_REL_I386_REL32)1536 if (config->machine == I386 && reloc.Type == COFF::IMAGE_REL_I386_REL32)
1382 // Ignore relative relocations on x86. On x86_64 they can't be ignored1537 // Ignore relative relocations on x86. On x86_64 they can't be ignored
1383 // since they're also used to compute absolute addresses.1538 // since they're also used to compute absolute addresses.
1384 continue;1539 continue;
13851540
1386 Symbol *Ref = SC->File->getSymbol(Reloc.SymbolTableIndex);1541 Symbol *ref = sc->file->getSymbol(reloc.SymbolTableIndex);
1387 maybeAddAddressTakenFunction(UsedSymbols, Ref);1542 maybeAddAddressTakenFunction(usedSymbols, ref);
1388 }1543 }
1389 }1544 }
1390}1545}
...@@ -1393,109 +1548,109 @@ static void markSymbolsWithRelocations(ObjFile *File,...@@ -1393,109 +1548,109 @@ static void markSymbolsWithRelocations(ObjFile *File,
1393// address-taken functions. It is sorted and uniqued, just like the safe SEH1548// address-taken functions. It is sorted and uniqued, just like the safe SEH
1394// table.1549// table.
1395void Writer::createGuardCFTables() {1550void Writer::createGuardCFTables() {
1396 SymbolRVASet AddressTakenSyms;1551 SymbolRVASet addressTakenSyms;
1397 SymbolRVASet LongJmpTargets;1552 SymbolRVASet longJmpTargets;
1398 for (ObjFile *File : ObjFile::Instances) {1553 for (ObjFile *file : ObjFile::instances) {
1399 // If the object was compiled with /guard:cf, the address taken symbols1554 // If the object was compiled with /guard:cf, the address taken symbols
1400 // are in .gfids$y sections, and the longjmp targets are in .gljmp$y1555 // are in .gfids$y sections, and the longjmp targets are in .gljmp$y
1401 // sections. If the object was not compiled with /guard:cf, we assume there1556 // sections. If the object was not compiled with /guard:cf, we assume there
1402 // were no setjmp targets, and that all code symbols with relocations are1557 // were no setjmp targets, and that all code symbols with relocations are
1403 // possibly address-taken.1558 // possibly address-taken.
1404 if (File->hasGuardCF()) {1559 if (file->hasGuardCF()) {
1405 markSymbolsForRVATable(File, File->getGuardFidChunks(), AddressTakenSyms);1560 markSymbolsForRVATable(file, file->getGuardFidChunks(), addressTakenSyms);
1406 markSymbolsForRVATable(File, File->getGuardLJmpChunks(), LongJmpTargets);1561 markSymbolsForRVATable(file, file->getGuardLJmpChunks(), longJmpTargets);
1407 } else {1562 } else {
1408 markSymbolsWithRelocations(File, AddressTakenSyms);1563 markSymbolsWithRelocations(file, addressTakenSyms);
1409 }1564 }
1410 }1565 }
14111566
1412 // Mark the image entry as address-taken.1567 // Mark the image entry as address-taken.
1413 if (Config->Entry)1568 if (config->entry)
1414 maybeAddAddressTakenFunction(AddressTakenSyms, Config->Entry);1569 maybeAddAddressTakenFunction(addressTakenSyms, config->entry);
14151570
1416 // Mark exported symbols in executable sections as address-taken.1571 // Mark exported symbols in executable sections as address-taken.
1417 for (Export &E : Config->Exports)1572 for (Export &e : config->exports)
1418 maybeAddAddressTakenFunction(AddressTakenSyms, E.Sym);1573 maybeAddAddressTakenFunction(addressTakenSyms, e.sym);
14191574
1420 // Ensure sections referenced in the gfid table are 16-byte aligned.1575 // Ensure sections referenced in the gfid table are 16-byte aligned.
1421 for (const ChunkAndOffset &C : AddressTakenSyms)1576 for (const ChunkAndOffset &c : addressTakenSyms)
1422 if (C.InputChunk->Alignment < 16)1577 if (c.inputChunk->getAlignment() < 16)
1423 C.InputChunk->Alignment = 16;1578 c.inputChunk->setAlignment(16);
14241579
1425 maybeAddRVATable(std::move(AddressTakenSyms), "__guard_fids_table",1580 maybeAddRVATable(std::move(addressTakenSyms), "__guard_fids_table",
1426 "__guard_fids_count");1581 "__guard_fids_count");
14271582
1428 // Add the longjmp target table unless the user told us not to.1583 // Add the longjmp target table unless the user told us not to.
1429 if (Config->GuardCF == GuardCFLevel::Full)1584 if (config->guardCF == GuardCFLevel::Full)
1430 maybeAddRVATable(std::move(LongJmpTargets), "__guard_longjmp_table",1585 maybeAddRVATable(std::move(longJmpTargets), "__guard_longjmp_table",
1431 "__guard_longjmp_count");1586 "__guard_longjmp_count");
14321587
1433 // Set __guard_flags, which will be used in the load config to indicate that1588 // Set __guard_flags, which will be used in the load config to indicate that
1434 // /guard:cf was enabled.1589 // /guard:cf was enabled.
1435 uint32_t GuardFlags = uint32_t(coff_guard_flags::CFInstrumented) |1590 uint32_t guardFlags = uint32_t(coff_guard_flags::CFInstrumented) |
1436 uint32_t(coff_guard_flags::HasFidTable);1591 uint32_t(coff_guard_flags::HasFidTable);
1437 if (Config->GuardCF == GuardCFLevel::Full)1592 if (config->guardCF == GuardCFLevel::Full)
1438 GuardFlags |= uint32_t(coff_guard_flags::HasLongJmpTable);1593 guardFlags |= uint32_t(coff_guard_flags::HasLongJmpTable);
1439 Symbol *FlagSym = Symtab->findUnderscore("__guard_flags");1594 Symbol *flagSym = symtab->findUnderscore("__guard_flags");
1440 cast<DefinedAbsolute>(FlagSym)->setVA(GuardFlags);1595 cast<DefinedAbsolute>(flagSym)->setVA(guardFlags);
1441}1596}
14421597
1443// Take a list of input sections containing symbol table indices and add those1598// Take a list of input sections containing symbol table indices and add those
1444// symbols to an RVA table. The challenge is that symbol RVAs are not known and1599// symbols to an RVA table. The challenge is that symbol RVAs are not known and
1445// depend on the table size, so we can't directly build a set of integers.1600// depend on the table size, so we can't directly build a set of integers.
1446void Writer::markSymbolsForRVATable(ObjFile *File,1601void Writer::markSymbolsForRVATable(ObjFile *file,
1447 ArrayRef<SectionChunk *> SymIdxChunks,1602 ArrayRef<SectionChunk *> symIdxChunks,
1448 SymbolRVASet &TableSymbols) {1603 SymbolRVASet &tableSymbols) {
1449 for (SectionChunk *C : SymIdxChunks) {1604 for (SectionChunk *c : symIdxChunks) {
1450 // Skip sections discarded by linker GC. This comes up when a .gfids section1605 // Skip sections discarded by linker GC. This comes up when a .gfids section
1451 // is associated with something like a vtable and the vtable is discarded.1606 // is associated with something like a vtable and the vtable is discarded.
1452 // In this case, the associated gfids section is discarded, and we don't1607 // In this case, the associated gfids section is discarded, and we don't
1453 // mark the virtual member functions as address-taken by the vtable.1608 // mark the virtual member functions as address-taken by the vtable.
1454 if (!C->Live)1609 if (!c->live)
1455 continue;1610 continue;
14561611
1457 // Validate that the contents look like symbol table indices.1612 // Validate that the contents look like symbol table indices.
1458 ArrayRef<uint8_t> Data = C->getContents();1613 ArrayRef<uint8_t> data = c->getContents();
1459 if (Data.size() % 4 != 0) {1614 if (data.size() % 4 != 0) {
1460 warn("ignoring " + C->getSectionName() +1615 warn("ignoring " + c->getSectionName() +
1461 " symbol table index section in object " + toString(File));1616 " symbol table index section in object " + toString(file));
1462 continue;1617 continue;
1463 }1618 }
14641619
1465 // Read each symbol table index and check if that symbol was included in the1620 // Read each symbol table index and check if that symbol was included in the
1466 // final link. If so, add it to the table symbol set.1621 // final link. If so, add it to the table symbol set.
1467 ArrayRef<ulittle32_t> SymIndices(1622 ArrayRef<ulittle32_t> symIndices(
1468 reinterpret_cast<const ulittle32_t *>(Data.data()), Data.size() / 4);1623 reinterpret_cast<const ulittle32_t *>(data.data()), data.size() / 4);
1469 ArrayRef<Symbol *> ObjSymbols = File->getSymbols();1624 ArrayRef<Symbol *> objSymbols = file->getSymbols();
1470 for (uint32_t SymIndex : SymIndices) {1625 for (uint32_t symIndex : symIndices) {
1471 if (SymIndex >= ObjSymbols.size()) {1626 if (symIndex >= objSymbols.size()) {
1472 warn("ignoring invalid symbol table index in section " +1627 warn("ignoring invalid symbol table index in section " +
1473 C->getSectionName() + " in object " + toString(File));1628 c->getSectionName() + " in object " + toString(file));
1474 continue;1629 continue;
1475 }1630 }
1476 if (Symbol *S = ObjSymbols[SymIndex]) {1631 if (Symbol *s = objSymbols[symIndex]) {
1477 if (S->isLive())1632 if (s->isLive())
1478 addSymbolToRVASet(TableSymbols, cast<Defined>(S));1633 addSymbolToRVASet(tableSymbols, cast<Defined>(s));
1479 }1634 }
1480 }1635 }
1481 }1636 }
1482}1637}
14831638
1484// Replace the absolute table symbol with a synthetic symbol pointing to1639// Replace the absolute table symbol with a synthetic symbol pointing to
1485// TableChunk so that we can emit base relocations for it and resolve section1640// tableChunk so that we can emit base relocations for it and resolve section
1486// relative relocations.1641// relative relocations.
1487void Writer::maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym,1642void Writer::maybeAddRVATable(SymbolRVASet tableSymbols, StringRef tableSym,
1488 StringRef CountSym) {1643 StringRef countSym) {
1489 if (TableSymbols.empty())1644 if (tableSymbols.empty())
1490 return;1645 return;
14911646
1492 RVATableChunk *TableChunk = make<RVATableChunk>(std::move(TableSymbols));1647 RVATableChunk *tableChunk = make<RVATableChunk>(std::move(tableSymbols));
1493 RdataSec->addChunk(TableChunk);1648 rdataSec->addChunk(tableChunk);
14941649
1495 Symbol *T = Symtab->findUnderscore(TableSym);1650 Symbol *t = symtab->findUnderscore(tableSym);
1496 Symbol *C = Symtab->findUnderscore(CountSym);1651 Symbol *c = symtab->findUnderscore(countSym);
1497 replaceSymbol<DefinedSynthetic>(T, T->getName(), TableChunk);1652 replaceSymbol<DefinedSynthetic>(t, t->getName(), tableChunk);
1498 cast<DefinedAbsolute>(C)->setVA(TableChunk->getSize() / 4);1653 cast<DefinedAbsolute>(c)->setVA(tableChunk->getSize() / 4);
1499}1654}
15001655
1501// MinGW specific. Gather all relocations that are imported from a DLL even1656// MinGW specific. Gather all relocations that are imported from a DLL even
...@@ -1503,26 +1658,26 @@ void Writer::maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym,...@@ -1503,26 +1658,26 @@ void Writer::maybeAddRVATable(SymbolRVASet TableSymbols, StringRef TableSym,
1503// uses for fixing them up, and provide the synthetic symbols that the1658// uses for fixing them up, and provide the synthetic symbols that the
1504// runtime uses for finding the table.1659// runtime uses for finding the table.
1505void Writer::createRuntimePseudoRelocs() {1660void Writer::createRuntimePseudoRelocs() {
1506 std::vector<RuntimePseudoReloc> Rels;1661 std::vector<RuntimePseudoReloc> rels;
15071662
1508 for (Chunk *C : Symtab->getChunks()) {1663 for (Chunk *c : symtab->getChunks()) {
1509 auto *SC = dyn_cast<SectionChunk>(C);1664 auto *sc = dyn_cast<SectionChunk>(c);
1510 if (!SC || !SC->Live)1665 if (!sc || !sc->live)
1511 continue;1666 continue;
1512 SC->getRuntimePseudoRelocs(Rels);1667 sc->getRuntimePseudoRelocs(rels);
1513 }1668 }
15141669
1515 if (!Rels.empty())1670 if (!rels.empty())
1516 log("Writing " + Twine(Rels.size()) + " runtime pseudo relocations");1671 log("Writing " + Twine(rels.size()) + " runtime pseudo relocations");
1517 PseudoRelocTableChunk *Table = make<PseudoRelocTableChunk>(Rels);1672 PseudoRelocTableChunk *table = make<PseudoRelocTableChunk>(rels);
1518 RdataSec->addChunk(Table);1673 rdataSec->addChunk(table);
1519 EmptyChunk *EndOfList = make<EmptyChunk>();1674 EmptyChunk *endOfList = make<EmptyChunk>();
1520 RdataSec->addChunk(EndOfList);1675 rdataSec->addChunk(endOfList);
15211676
1522 Symbol *HeadSym = Symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__");1677 Symbol *headSym = symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST__");
1523 Symbol *EndSym = Symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__");1678 Symbol *endSym = symtab->findUnderscore("__RUNTIME_PSEUDO_RELOC_LIST_END__");
1524 replaceSymbol<DefinedSynthetic>(HeadSym, HeadSym->getName(), Table);1679 replaceSymbol<DefinedSynthetic>(headSym, headSym->getName(), table);
1525 replaceSymbol<DefinedSynthetic>(EndSym, EndSym->getName(), EndOfList);1680 replaceSymbol<DefinedSynthetic>(endSym, endSym->getName(), endOfList);
1526}1681}
15271682
1528// MinGW specific.1683// MinGW specific.
...@@ -1531,32 +1686,32 @@ void Writer::createRuntimePseudoRelocs() {...@@ -1531,32 +1686,32 @@ void Writer::createRuntimePseudoRelocs() {
1531// There's a symbol pointing to the start sentinel pointer, __CTOR_LIST__1686// There's a symbol pointing to the start sentinel pointer, __CTOR_LIST__
1532// and __DTOR_LIST__ respectively.1687// and __DTOR_LIST__ respectively.
1533void Writer::insertCtorDtorSymbols() {1688void Writer::insertCtorDtorSymbols() {
1534 AbsolutePointerChunk *CtorListHead = make<AbsolutePointerChunk>(-1);1689 AbsolutePointerChunk *ctorListHead = make<AbsolutePointerChunk>(-1);
1535 AbsolutePointerChunk *CtorListEnd = make<AbsolutePointerChunk>(0);1690 AbsolutePointerChunk *ctorListEnd = make<AbsolutePointerChunk>(0);
1536 AbsolutePointerChunk *DtorListHead = make<AbsolutePointerChunk>(-1);1691 AbsolutePointerChunk *dtorListHead = make<AbsolutePointerChunk>(-1);
1537 AbsolutePointerChunk *DtorListEnd = make<AbsolutePointerChunk>(0);1692 AbsolutePointerChunk *dtorListEnd = make<AbsolutePointerChunk>(0);
1538 CtorsSec->insertChunkAtStart(CtorListHead);1693 ctorsSec->insertChunkAtStart(ctorListHead);
1539 CtorsSec->addChunk(CtorListEnd);1694 ctorsSec->addChunk(ctorListEnd);
1540 DtorsSec->insertChunkAtStart(DtorListHead);1695 dtorsSec->insertChunkAtStart(dtorListHead);
1541 DtorsSec->addChunk(DtorListEnd);1696 dtorsSec->addChunk(dtorListEnd);
15421697
1543 Symbol *CtorListSym = Symtab->findUnderscore("__CTOR_LIST__");1698 Symbol *ctorListSym = symtab->findUnderscore("__CTOR_LIST__");
1544 Symbol *DtorListSym = Symtab->findUnderscore("__DTOR_LIST__");1699 Symbol *dtorListSym = symtab->findUnderscore("__DTOR_LIST__");
1545 replaceSymbol<DefinedSynthetic>(CtorListSym, CtorListSym->getName(),1700 replaceSymbol<DefinedSynthetic>(ctorListSym, ctorListSym->getName(),
1546 CtorListHead);1701 ctorListHead);
1547 replaceSymbol<DefinedSynthetic>(DtorListSym, DtorListSym->getName(),1702 replaceSymbol<DefinedSynthetic>(dtorListSym, dtorListSym->getName(),
1548 DtorListHead);1703 dtorListHead);
1549}1704}
15501705
1551// Handles /section options to allow users to overwrite1706// Handles /section options to allow users to overwrite
1552// section attributes.1707// section attributes.
1553void Writer::setSectionPermissions() {1708void Writer::setSectionPermissions() {
1554 for (auto &P : Config->Section) {1709 for (auto &p : config->section) {
1555 StringRef Name = P.first;1710 StringRef name = p.first;
1556 uint32_t Perm = P.second;1711 uint32_t perm = p.second;
1557 for (OutputSection *Sec : OutputSections)1712 for (OutputSection *sec : outputSections)
1558 if (Sec->Name == Name)1713 if (sec->name == name)
1559 Sec->setPermissions(Perm);1714 sec->setPermissions(perm);
1560 }1715 }
1561}1716}
15621717
...@@ -1564,18 +1719,19 @@ void Writer::setSectionPermissions() {...@@ -1564,18 +1719,19 @@ void Writer::setSectionPermissions() {
1564void Writer::writeSections() {1719void Writer::writeSections() {
1565 // Record the number of sections to apply section index relocations1720 // Record the number of sections to apply section index relocations
1566 // against absolute symbols. See applySecIdx in Chunks.cpp..1721 // against absolute symbols. See applySecIdx in Chunks.cpp..
1567 DefinedAbsolute::NumOutputSections = OutputSections.size();1722 DefinedAbsolute::numOutputSections = outputSections.size();
15681723
1569 uint8_t *Buf = Buffer->getBufferStart();1724 uint8_t *buf = buffer->getBufferStart();
1570 for (OutputSection *Sec : OutputSections) {1725 for (OutputSection *sec : outputSections) {
1571 uint8_t *SecBuf = Buf + Sec->getFileOff();1726 uint8_t *secBuf = buf + sec->getFileOff();
1572 // Fill gaps between functions in .text with INT3 instructions1727 // Fill gaps between functions in .text with INT3 instructions
1573 // instead of leaving as NUL bytes (which can be interpreted as1728 // instead of leaving as NUL bytes (which can be interpreted as
1574 // ADD instructions).1729 // ADD instructions).
1575 if (Sec->Header.Characteristics & IMAGE_SCN_CNT_CODE)1730 if (sec->header.Characteristics & IMAGE_SCN_CNT_CODE)
1576 memset(SecBuf, 0xCC, Sec->getRawSize());1731 memset(secBuf, 0xCC, sec->getRawSize());
1577 for_each(parallel::par, Sec->Chunks.begin(), Sec->Chunks.end(),1732 parallelForEach(sec->chunks, [&](Chunk *c) {
1578 [&](Chunk *C) { C->writeTo(SecBuf); });1733 c->writeTo(secBuf + c->getRVA() - sec->getRVA());
1734 });
1579 }1735 }
1580}1736}
15811737
...@@ -1586,8 +1742,8 @@ void Writer::writeBuildId() {...@@ -1586,8 +1742,8 @@ void Writer::writeBuildId() {
1586 // 2) In all cases, the PE COFF file header also contains a timestamp.1742 // 2) In all cases, the PE COFF file header also contains a timestamp.
1587 // For reproducibility, instead of a timestamp we want to use a hash of the1743 // For reproducibility, instead of a timestamp we want to use a hash of the
1588 // PE contents.1744 // PE contents.
1589 if (Config->Debug) {1745 if (config->debug) {
1590 assert(BuildId && "BuildId is not set!");1746 assert(buildId && "BuildId is not set!");
1591 // BuildId->BuildId was filled in when the PDB was written.1747 // BuildId->BuildId was filled in when the PDB was written.
1592 }1748 }
15931749
...@@ -1595,62 +1751,65 @@ void Writer::writeBuildId() {...@@ -1595,62 +1751,65 @@ void Writer::writeBuildId() {
1595 // "timestamp" in the COFF file header, and the ones in the coff debug1751 // "timestamp" in the COFF file header, and the ones in the coff debug
1596 // directory. Now we can hash the file and write that hash to the various1752 // directory. Now we can hash the file and write that hash to the various
1597 // timestamp fields in the file.1753 // timestamp fields in the file.
1598 StringRef OutputFileData(1754 StringRef outputFileData(
1599 reinterpret_cast<const char *>(Buffer->getBufferStart()),1755 reinterpret_cast<const char *>(buffer->getBufferStart()),
1600 Buffer->getBufferSize());1756 buffer->getBufferSize());
16011757
1602 uint32_t Timestamp = Config->Timestamp;1758 uint32_t timestamp = config->timestamp;
1603 uint64_t Hash = 0;1759 uint64_t hash = 0;
1604 bool GenerateSyntheticBuildId =1760 bool generateSyntheticBuildId =
1605 Config->MinGW && Config->Debug && Config->PDBPath.empty();1761 config->mingw && config->debug && config->pdbPath.empty();
16061762
1607 if (Config->Repro || GenerateSyntheticBuildId)1763 if (config->repro || generateSyntheticBuildId)
1608 Hash = xxHash64(OutputFileData);1764 hash = xxHash64(outputFileData);
16091765
1610 if (Config->Repro)1766 if (config->repro)
1611 Timestamp = static_cast<uint32_t>(Hash);1767 timestamp = static_cast<uint32_t>(hash);
16121768
1613 if (GenerateSyntheticBuildId) {1769 if (generateSyntheticBuildId) {
1614 // For MinGW builds without a PDB file, we still generate a build id1770 // For MinGW builds without a PDB file, we still generate a build id
1615 // to allow associating a crash dump to the executable.1771 // to allow associating a crash dump to the executable.
1616 BuildId->BuildId->PDB70.CVSignature = OMF::Signature::PDB70;1772 buildId->buildId->PDB70.CVSignature = OMF::Signature::PDB70;
1617 BuildId->BuildId->PDB70.Age = 1;1773 buildId->buildId->PDB70.Age = 1;
1618 memcpy(BuildId->BuildId->PDB70.Signature, &Hash, 8);1774 memcpy(buildId->buildId->PDB70.Signature, &hash, 8);
1619 // xxhash only gives us 8 bytes, so put some fixed data in the other half.1775 // 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);1776 memcpy(&buildId->buildId->PDB70.Signature[8], "LLD PDB.", 8);
1621 }1777 }
16221778
1623 if (DebugDirectory)1779 if (debugDirectory)
1624 DebugDirectory->setTimeDateStamp(Timestamp);1780 debugDirectory->setTimeDateStamp(timestamp);
16251781
1626 uint8_t *Buf = Buffer->getBufferStart();1782 uint8_t *buf = buffer->getBufferStart();
1627 Buf += DOSStubSize + sizeof(PEMagic);1783 buf += dosStubSize + sizeof(PEMagic);
1628 object::coff_file_header *CoffHeader =1784 object::coff_file_header *coffHeader =
1629 reinterpret_cast<coff_file_header *>(Buf);1785 reinterpret_cast<coff_file_header *>(buf);
1630 CoffHeader->TimeDateStamp = Timestamp;1786 coffHeader->TimeDateStamp = timestamp;
1631}1787}
16321788
1633// Sort .pdata section contents according to PE/COFF spec 5.5.1789// Sort .pdata section contents according to PE/COFF spec 5.5.
1634void Writer::sortExceptionTable() {1790void Writer::sortExceptionTable() {
1635 if (!FirstPdata)1791 if (!firstPdata)
1636 return;1792 return;
1637 // We assume .pdata contains function table entries only.1793 // We assume .pdata contains function table entries only.
1638 auto BufAddr = [&](Chunk *C) {1794 auto bufAddr = [&](Chunk *c) {
1639 return Buffer->getBufferStart() + C->getOutputSection()->getFileOff() +1795 OutputSection *os = c->getOutputSection();
1640 C->getRVA() - C->getOutputSection()->getRVA();1796 return buffer->getBufferStart() + os->getFileOff() + c->getRVA() -
1797 os->getRVA();
1641 };1798 };
1642 uint8_t *Begin = BufAddr(FirstPdata);1799 uint8_t *begin = bufAddr(firstPdata);
1643 uint8_t *End = BufAddr(LastPdata) + LastPdata->getSize();1800 uint8_t *end = bufAddr(lastPdata) + lastPdata->getSize();
1644 if (Config->Machine == AMD64) {1801 if (config->machine == AMD64) {
1645 struct Entry { ulittle32_t Begin, End, Unwind; };1802 struct Entry { ulittle32_t begin, end, unwind; };
1646 sort(parallel::par, (Entry *)Begin, (Entry *)End,1803 parallelSort(
1647 [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });1804 MutableArrayRef<Entry>((Entry *)begin, (Entry *)end),
1805 [](const Entry &a, const Entry &b) { return a.begin < b.begin; });
1648 return;1806 return;
1649 }1807 }
1650 if (Config->Machine == ARMNT || Config->Machine == ARM64) {1808 if (config->machine == ARMNT || config->machine == ARM64) {
1651 struct Entry { ulittle32_t Begin, Unwind; };1809 struct Entry { ulittle32_t begin, unwind; };
1652 sort(parallel::par, (Entry *)Begin, (Entry *)End,1810 parallelSort(
1653 [](const Entry &A, const Entry &B) { return A.Begin < B.Begin; });1811 MutableArrayRef<Entry>((Entry *)begin, (Entry *)end),
1812 [](const Entry &a, const Entry &b) { return a.begin < b.begin; });
1654 return;1813 return;
1655 }1814 }
1656 errs() << "warning: don't know how to handle .pdata.\n";1815 errs() << "warning: don't know how to handle .pdata.\n";
...@@ -1670,76 +1829,92 @@ void Writer::sortExceptionTable() {...@@ -1670,76 +1829,92 @@ void Writer::sortExceptionTable() {
1670// pointers in the order that they are listed in the object file (top to1829// pointers in the order that they are listed in the object file (top to
1671// bottom), otherwise global objects might not be initialized in the1830// bottom), otherwise global objects might not be initialized in the
1672// correct order.1831// correct order.
1673void Writer::sortCRTSectionChunks(std::vector<Chunk *> &Chunks) {1832void Writer::sortCRTSectionChunks(std::vector<Chunk *> &chunks) {
1674 auto SectionChunkOrder = [](const Chunk *A, const Chunk *B) {1833 auto sectionChunkOrder = [](const Chunk *a, const Chunk *b) {
1675 auto SA = dyn_cast<SectionChunk>(A);1834 auto sa = dyn_cast<SectionChunk>(a);
1676 auto SB = dyn_cast<SectionChunk>(B);1835 auto sb = dyn_cast<SectionChunk>(b);
1677 assert(SA && SB && "Non-section chunks in CRT section!");1836 assert(sa && sb && "Non-section chunks in CRT section!");
16781837
1679 StringRef SAObj = SA->File->MB.getBufferIdentifier();1838 StringRef sAObj = sa->file->mb.getBufferIdentifier();
1680 StringRef SBObj = SB->File->MB.getBufferIdentifier();1839 StringRef sBObj = sb->file->mb.getBufferIdentifier();
16811840
1682 return SAObj == SBObj && SA->getSectionNumber() < SB->getSectionNumber();1841 return sAObj == sBObj && sa->getSectionNumber() < sb->getSectionNumber();
1683 };1842 };
1684 std::stable_sort(Chunks.begin(), Chunks.end(), SectionChunkOrder);1843 llvm::stable_sort(chunks, sectionChunkOrder);
16851844
1686 if (Config->Verbose) {1845 if (config->verbose) {
1687 for (auto &C : Chunks) {1846 for (auto &c : chunks) {
1688 auto SC = dyn_cast<SectionChunk>(C);1847 auto sc = dyn_cast<SectionChunk>(c);
1689 log(" " + SC->File->MB.getBufferIdentifier().str() +1848 log(" " + sc->file->mb.getBufferIdentifier().str() +
1690 ", SectionID: " + Twine(SC->getSectionNumber()));1849 ", SectionID: " + Twine(sc->getSectionNumber()));
1691 }1850 }
1692 }1851 }
1693}1852}
16941853
1695OutputSection *Writer::findSection(StringRef Name) {1854OutputSection *Writer::findSection(StringRef name) {
1696 for (OutputSection *Sec : OutputSections)1855 for (OutputSection *sec : outputSections)
1697 if (Sec->Name == Name)1856 if (sec->name == name)
1698 return Sec;1857 return sec;
1699 return nullptr;1858 return nullptr;
1700}1859}
17011860
1702uint32_t Writer::getSizeOfInitializedData() {1861uint32_t Writer::getSizeOfInitializedData() {
1703 uint32_t Res = 0;1862 uint32_t res = 0;
1704 for (OutputSection *S : OutputSections)1863 for (OutputSection *s : outputSections)
1705 if (S->Header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)1864 if (s->header.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA)
1706 Res += S->getRawSize();1865 res += s->getRawSize();
1707 return Res;1866 return res;
1708}1867}
17091868
1710// Add base relocations to .reloc section.1869// Add base relocations to .reloc section.
1711void Writer::addBaserels() {1870void Writer::addBaserels() {
1712 if (!Config->Relocatable)1871 if (!config->relocatable)
1713 return;1872 return;
1714 RelocSec->Chunks.clear();1873 relocSec->chunks.clear();
1715 std::vector<Baserel> V;1874 std::vector<Baserel> v;
1716 for (OutputSection *Sec : OutputSections) {1875 for (OutputSection *sec : outputSections) {
1717 if (Sec->Header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)1876 if (sec->header.Characteristics & IMAGE_SCN_MEM_DISCARDABLE)
1718 continue;1877 continue;
1719 // Collect all locations for base relocations.1878 // Collect all locations for base relocations.
1720 for (Chunk *C : Sec->Chunks)1879 for (Chunk *c : sec->chunks)
1721 C->getBaserels(&V);1880 c->getBaserels(&v);
1722 // Add the addresses to .reloc section.1881 // Add the addresses to .reloc section.
1723 if (!V.empty())1882 if (!v.empty())
1724 addBaserelBlocks(V);1883 addBaserelBlocks(v);
1725 V.clear();1884 v.clear();
1726 }1885 }
1727}1886}
17281887
1729// Add addresses to .reloc section. Note that addresses are grouped by page.1888// Add addresses to .reloc section. Note that addresses are grouped by page.
1730void Writer::addBaserelBlocks(std::vector<Baserel> &V) {1889void Writer::addBaserelBlocks(std::vector<Baserel> &v) {
1731 const uint32_t Mask = ~uint32_t(PageSize - 1);1890 const uint32_t mask = ~uint32_t(pageSize - 1);
1732 uint32_t Page = V[0].RVA & Mask;1891 uint32_t page = v[0].rva & mask;
1733 size_t I = 0, J = 1;1892 size_t i = 0, j = 1;
1734 for (size_t E = V.size(); J < E; ++J) {1893 for (size_t e = v.size(); j < e; ++j) {
1735 uint32_t P = V[J].RVA & Mask;1894 uint32_t p = v[j].rva & mask;
1736 if (P == Page)1895 if (p == page)
1737 continue;1896 continue;
1738 RelocSec->addChunk(make<BaserelChunk>(Page, &V[I], &V[0] + J));1897 relocSec->addChunk(make<BaserelChunk>(page, &v[i], &v[0] + j));
1739 I = J;1898 i = j;
1740 Page = P;1899 page = p;
1741 }1900 }
1742 if (I == J)1901 if (i == j)
1743 return;1902 return;
1744 RelocSec->addChunk(make<BaserelChunk>(Page, &V[I], &V[0] + J));1903 relocSec->addChunk(make<BaserelChunk>(page, &v[i], &v[0] + j));
1904}
1905
1906PartialSection *Writer::createPartialSection(StringRef name,
1907 uint32_t outChars) {
1908 PartialSection *&pSec = partialSections[{name, outChars}];
1909 if (pSec)
1910 return pSec;
1911 pSec = make<PartialSection>(name, outChars);
1912 return pSec;
1913}
1914
1915PartialSection *Writer::findPartialSection(StringRef name, uint32_t outChars) {
1916 auto it = partialSections.find({name, outChars});
1917 if (it != partialSections.end())
1918 return it->second;
1919 return nullptr;
1745}1920}
deps/lld/COFF/Writer.h+36-26
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Writer.h -------------------------------------------------*- C++ -*-===//1//===- Writer.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -19,10 +18,19 @@...@@ -19,10 +18,19 @@
1918
20namespace lld {19namespace lld {
21namespace coff {20namespace coff {
22static const int PageSize = 4096;21static const int pageSize = 4096;
2322
24void writeResult();23void writeResult();
2524
25class PartialSection {
26public:
27 PartialSection(StringRef n, uint32_t chars)
28 : name(n), characteristics(chars) {}
29 StringRef name;
30 unsigned characteristics;
31 std::vector<Chunk *> chunks;
32};
33
26// OutputSection represents a section in an output file. It's a34// OutputSection represents a section in an output file. It's a
27// container of chunks. OutputSection and Chunk are 1:N relationship.35// container of chunks. OutputSection and Chunk are 1:N relationship.
28// Chunks cannot belong to more than one OutputSections. The writer36// Chunks cannot belong to more than one OutputSections. The writer
...@@ -30,46 +38,48 @@ void writeResult();...@@ -30,46 +38,48 @@ void writeResult();
30// non-overlapping file offsets and RVAs.38// non-overlapping file offsets and RVAs.
31class OutputSection {39class OutputSection {
32public:40public:
33 OutputSection(llvm::StringRef N, uint32_t Chars) : Name(N) {41 OutputSection(llvm::StringRef n, uint32_t chars) : name(n) {
34 Header.Characteristics = Chars;42 header.Characteristics = chars;
35 }43 }
36 void addChunk(Chunk *C);44 void addChunk(Chunk *c);
37 void insertChunkAtStart(Chunk *C);45 void insertChunkAtStart(Chunk *c);
38 void merge(OutputSection *Other);46 void merge(OutputSection *other);
39 void addPermissions(uint32_t C);47 void setPermissions(uint32_t c);
40 void setPermissions(uint32_t C);48 uint64_t getRVA() { return header.VirtualAddress; }
41 uint64_t getRVA() { return Header.VirtualAddress; }49 uint64_t getFileOff() { return header.PointerToRawData; }
42 uint64_t getFileOff() { return Header.PointerToRawData; }50 void writeHeaderTo(uint8_t *buf);
43 void writeHeaderTo(uint8_t *Buf);51 void addContributingPartialSection(PartialSection *sec);
4452
45 // Returns the size of this section in an executable memory image.53 // Returns the size of this section in an executable memory image.
46 // This may be smaller than the raw size (the raw size is multiple54 // This may be smaller than the raw size (the raw size is multiple
47 // of disk sector size, so there may be padding at end), or may be55 // of disk sector size, so there may be padding at end), or may be
48 // larger (if that's the case, the loader reserves spaces after end56 // larger (if that's the case, the loader reserves spaces after end
49 // of raw data).57 // of raw data).
50 uint64_t getVirtualSize() { return Header.VirtualSize; }58 uint64_t getVirtualSize() { return header.VirtualSize; }
5159
52 // Returns the size of the section in the output file.60 // Returns the size of the section in the output file.
53 uint64_t getRawSize() { return Header.SizeOfRawData; }61 uint64_t getRawSize() { return header.SizeOfRawData; }
5462
55 // Set offset into the string table storing this section name.63 // Set offset into the string table storing this section name.
56 // Used only when the name is longer than 8 bytes.64 // Used only when the name is longer than 8 bytes.
57 void setStringTableOff(uint32_t V) { StringTableOff = V; }65 void setStringTableOff(uint32_t v) { stringTableOff = v; }
5866
59 // N.B. The section index is one based.67 // N.B. The section index is one based.
60 uint32_t SectionIndex = 0;68 uint32_t sectionIndex = 0;
69
70 llvm::StringRef name;
71 llvm::object::coff_section header = {};
6172
62 llvm::StringRef Name;73 std::vector<Chunk *> chunks;
63 llvm::object::coff_section Header = {};74 std::vector<Chunk *> origChunks;
6475
65 std::vector<Chunk *> Chunks;76 std::vector<PartialSection *> contribSections;
66 std::vector<Chunk *> OrigChunks;
6777
68private:78private:
69 uint32_t StringTableOff = 0;79 uint32_t stringTableOff = 0;
70};80};
7181
72}82} // namespace coff
73}83} // namespace lld
7484
75#endif85#endif
deps/lld/Common/Args.cpp+48-39
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Args.cpp -----------------------------------------------------------===//1//===- Args.cpp -----------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -18,56 +17,66 @@...@@ -18,56 +17,66 @@
18using namespace llvm;17using namespace llvm;
19using namespace lld;18using namespace lld;
2019
21int lld::args::getInteger(opt::InputArgList &Args, unsigned Key, int Default) {20// TODO(sbc): Remove this once CGOptLevel can be set completely based on bitcode
22 auto *A = Args.getLastArg(Key);21// function metadata.
23 if (!A)22CodeGenOpt::Level lld::args::getCGOptLevel(int optLevelLTO) {
23 if (optLevelLTO == 3)
24 return CodeGenOpt::Aggressive;
25 assert(optLevelLTO < 3);
26 return CodeGenOpt::Default;
27}
28
29int64_t lld::args::getInteger(opt::InputArgList &args, unsigned key,
30 int64_t Default) {
31 auto *a = args.getLastArg(key);
32 if (!a)
24 return Default;33 return Default;
2534
26 int V;35 int64_t v;
27 if (to_integer(A->getValue(), V, 10))36 if (to_integer(a->getValue(), v, 10))
28 return V;37 return v;
2938
30 StringRef Spelling = Args.getArgString(A->getIndex());39 StringRef spelling = args.getArgString(a->getIndex());
31 error(Spelling + ": number expected, but got '" + A->getValue() + "'");40 error(spelling + ": number expected, but got '" + a->getValue() + "'");
32 return 0;41 return 0;
33}42}
3443
35std::vector<StringRef> lld::args::getStrings(opt::InputArgList &Args, int Id) {44std::vector<StringRef> lld::args::getStrings(opt::InputArgList &args, int id) {
36 std::vector<StringRef> V;45 std::vector<StringRef> v;
37 for (auto *Arg : Args.filtered(Id))46 for (auto *arg : args.filtered(id))
38 V.push_back(Arg->getValue());47 v.push_back(arg->getValue());
39 return V;48 return v;
40}49}
4150
42uint64_t lld::args::getZOptionValue(opt::InputArgList &Args, int Id,51uint64_t lld::args::getZOptionValue(opt::InputArgList &args, int id,
43 StringRef Key, uint64_t Default) {52 StringRef key, uint64_t Default) {
44 for (auto *Arg : Args.filtered_reverse(Id)) {53 for (auto *arg : args.filtered_reverse(id)) {
45 std::pair<StringRef, StringRef> KV = StringRef(Arg->getValue()).split('=');54 std::pair<StringRef, StringRef> kv = StringRef(arg->getValue()).split('=');
46 if (KV.first == Key) {55 if (kv.first == key) {
47 uint64_t Result = Default;56 uint64_t result = Default;
48 if (!to_integer(KV.second, Result))57 if (!to_integer(kv.second, result))
49 error("invalid " + Key + ": " + KV.second);58 error("invalid " + key + ": " + kv.second);
50 return Result;59 return result;
51 }60 }
52 }61 }
53 return Default;62 return Default;
54}63}
5564
56std::vector<StringRef> lld::args::getLines(MemoryBufferRef MB) {65std::vector<StringRef> lld::args::getLines(MemoryBufferRef mb) {
57 SmallVector<StringRef, 0> Arr;66 SmallVector<StringRef, 0> arr;
58 MB.getBuffer().split(Arr, '\n');67 mb.getBuffer().split(arr, '\n');
5968
60 std::vector<StringRef> Ret;69 std::vector<StringRef> ret;
61 for (StringRef S : Arr) {70 for (StringRef s : arr) {
62 S = S.trim();71 s = s.trim();
63 if (!S.empty() && S[0] != '#')72 if (!s.empty() && s[0] != '#')
64 Ret.push_back(S);73 ret.push_back(s);
65 }74 }
66 return Ret;75 return ret;
67}76}
6877
69StringRef lld::args::getFilenameWithoutExe(StringRef Path) {78StringRef lld::args::getFilenameWithoutExe(StringRef path) {
70 if (Path.endswith_lower(".exe"))79 if (path.endswith_lower(".exe"))
71 return sys::path::stem(Path);80 return sys::path::stem(path);
72 return sys::path::filename(Path);81 return sys::path::filename(path);
73}82}
deps/lld/Common/CMakeLists.txt+27
...@@ -2,15 +2,42 @@ if(NOT LLD_BUILT_STANDALONE)...@@ -2,15 +2,42 @@ if(NOT LLD_BUILT_STANDALONE)
2 set(tablegen_deps intrinsics_gen)2 set(tablegen_deps intrinsics_gen)
3endif()3endif()
44
5find_first_existing_vc_file("${LLVM_MAIN_SRC_DIR}" llvm_vc)
6find_first_existing_vc_file("${LLD_SOURCE_DIR}" lld_vc)
7
8set(version_inc "${CMAKE_CURRENT_BINARY_DIR}/VCSVersion.inc")
9set(generate_vcs_version_script "${LLVM_CMAKE_PATH}/GenerateVersionFromVCS.cmake")
10
11if(lld_vc)
12 set(lld_source_dir ${LLD_SOURCE_DIR})
13endif()
14
15add_custom_command(OUTPUT "${version_inc}"
16 DEPENDS "${lld_vc}" "${generate_vcs_version_script}"
17 COMMAND ${CMAKE_COMMAND} "-DNAMES=LLD"
18 "-DLLD_SOURCE_DIR=${LLD_SOURCE_DIR}"
19 "-DHEADER_FILE=${version_inc}"
20 -P "${generate_vcs_version_script}")
21
22# Mark the generated header as being generated.
23set_source_files_properties("${version_inc}"
24 PROPERTIES GENERATED TRUE
25 HEADER_FILE_ONLY TRUE)
26
27set_property(SOURCE Version.cpp APPEND PROPERTY
28 COMPILE_DEFINITIONS "HAVE_VCS_VERSION_INC")
29
5add_lld_library(lldCommon30add_lld_library(lldCommon
6 Args.cpp31 Args.cpp
7 ErrorHandler.cpp32 ErrorHandler.cpp
33 Filesystem.cpp
8 Memory.cpp34 Memory.cpp
9 Reproduce.cpp35 Reproduce.cpp
10 Strings.cpp36 Strings.cpp
11 TargetOptionsCommandFlags.cpp37 TargetOptionsCommandFlags.cpp
12 Threads.cpp38 Threads.cpp
13 Timer.cpp39 Timer.cpp
40 VCSVersion.inc
14 Version.cpp41 Version.cpp
1542
16 ADDITIONAL_HEADER_DIRS43 ADDITIONAL_HEADER_DIRS
deps/lld/Common/ErrorHandler.cpp+97-63
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ErrorHandler.cpp ---------------------------------------------------===//1//===- ErrorHandler.cpp ---------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -17,6 +16,7 @@...@@ -17,6 +16,7 @@
17#include "llvm/Support/ManagedStatic.h"16#include "llvm/Support/ManagedStatic.h"
18#include "llvm/Support/raw_ostream.h"17#include "llvm/Support/raw_ostream.h"
19#include <mutex>18#include <mutex>
19#include <regex>
2020
21#if !defined(_MSC_VER) && !defined(__MINGW32__)21#if !defined(_MSC_VER) && !defined(__MINGW32__)
22#include <unistd.h>22#include <unistd.h>
...@@ -27,29 +27,29 @@ using namespace lld;...@@ -27,29 +27,29 @@ using namespace lld;
2727
28// The functions defined in this file can be called from multiple threads,28// The functions defined in this file can be called from multiple threads,
29// but outs() or errs() are not thread-safe. We protect them using a mutex.29// but outs() or errs() are not thread-safe. We protect them using a mutex.
30static std::mutex Mu;30static std::mutex mu;
3131
32// Prints "\n" or does nothing, depending on Msg contents of32// Prints "\n" or does nothing, depending on Msg contents of
33// the previous call of this function.33// the previous call of this function.
34static void newline(raw_ostream *ErrorOS, const Twine &Msg) {34static void newline(raw_ostream *errorOS, const Twine &msg) {
35 // True if the previous error message contained "\n".35 // True if the previous error message contained "\n".
36 // We want to separate multi-line error messages with a newline.36 // We want to separate multi-line error messages with a newline.
37 static bool Flag;37 static bool flag;
3838
39 if (Flag)39 if (flag)
40 *ErrorOS << "\n";40 *errorOS << "\n";
41 Flag = StringRef(Msg.str()).contains('\n');41 flag = StringRef(msg.str()).contains('\n');
42}42}
4343
44ErrorHandler &lld::errorHandler() {44ErrorHandler &lld::errorHandler() {
45 static ErrorHandler Handler;45 static ErrorHandler handler;
46 return Handler;46 return handler;
47}47}
4848
49void lld::exitLld(int Val) {49void lld::exitLld(int val) {
50 // Delete any temporary file, while keeping the memory mapping open.50 // Delete any temporary file, while keeping the memory mapping open.
51 if (errorHandler().OutputBuffer)51 if (errorHandler().outputBuffer)
52 errorHandler().OutputBuffer->discard();52 errorHandler().outputBuffer->discard();
5353
54 // Dealloc/destroy ManagedStatic variables before calling54 // Dealloc/destroy ManagedStatic variables before calling
55 // _exit(). In a non-LTO build, this is a nop. In an LTO55 // _exit(). In a non-LTO build, this is a nop. In an LTO
...@@ -58,87 +58,121 @@ void lld::exitLld(int Val) {...@@ -58,87 +58,121 @@ void lld::exitLld(int Val) {
5858
59 outs().flush();59 outs().flush();
60 errs().flush();60 errs().flush();
61 _exit(Val);61 _exit(val);
62}62}
6363
64void lld::diagnosticHandler(const DiagnosticInfo &DI) {64void lld::diagnosticHandler(const DiagnosticInfo &di) {
65 SmallString<128> S;65 SmallString<128> s;
66 raw_svector_ostream OS(S);66 raw_svector_ostream os(s);
67 DiagnosticPrinterRawOStream DP(OS);67 DiagnosticPrinterRawOStream dp(os);
68 DI.print(DP);68 di.print(dp);
69 switch (DI.getSeverity()) {69 switch (di.getSeverity()) {
70 case DS_Error:70 case DS_Error:
71 error(S);71 error(s);
72 break;72 break;
73 case DS_Warning:73 case DS_Warning:
74 warn(S);74 warn(s);
75 break;75 break;
76 case DS_Remark:76 case DS_Remark:
77 case DS_Note:77 case DS_Note:
78 message(S);78 message(s);
79 break;79 break;
80 }80 }
81}81}
8282
83void lld::checkError(Error E) {83void lld::checkError(Error e) {
84 handleAllErrors(std::move(E),84 handleAllErrors(std::move(e),
85 [&](ErrorInfoBase &EIB) { error(EIB.message()); });85 [&](ErrorInfoBase &eib) { error(eib.message()); });
86}
87
88static std::string getLocation(std::string msg, std::string defaultMsg) {
89 static std::vector<std::regex> Regexes{
90 std::regex(R"(^undefined symbol:.*\n>>> referenced by (\S+):(\d+)\n.*)"),
91 std::regex(R"(^undefined symbol:.*\n>>> referenced by (.*):)"),
92 std::regex(
93 R"(^duplicate symbol: .*\n>>> defined in (\S+)\n>>> defined in.*)"),
94 std::regex(
95 R"(^duplicate symbol: .*\n>>> defined at (\S+):(\d+).*)"),
96 std::regex(
97 R"(.*\n>>> defined in .*\n>>> referenced by (\S+):(\d+))"),
98 std::regex(
99 R"(^undefined (internal|hidden|protected) symbol: .*\n>>> referenced by (\S+):(\d+)\n.*)"),
100 std::regex(R"((\S+):(\d+): unclosed quote)"),
101 };
102
103 std::smatch Match;
104 for (std::regex &Re : Regexes) {
105 if (std::regex_search(msg, Match, Re)) {
106 return Match.size() > 2 ? Match.str(1) + "(" + Match.str(2) + ")"
107 : Match.str(1);
108 }
109 }
110 return defaultMsg;
86}111}
87112
88void ErrorHandler::print(StringRef S, raw_ostream::Colors C) {113void ErrorHandler::printHeader(StringRef s, raw_ostream::Colors c,
89 *ErrorOS << LogName << ": ";114 const Twine &msg) {
90 if (ColorDiagnostics) {115
91 ErrorOS->changeColor(C, true);116 if (vsDiagnostics) {
92 *ErrorOS << S;117 // A Visual Studio-style error message starts with an error location.
93 ErrorOS->resetColor();118 // If a location cannot be extracted then we default to LogName.
119 *errorOS << getLocation(msg.str(), logName) << ": ";
120 } else {
121 *errorOS << logName << ": ";
122 }
123
124 if (colorDiagnostics) {
125 errorOS->changeColor(c, true);
126 *errorOS << s;
127 errorOS->resetColor();
94 } else {128 } else {
95 *ErrorOS << S;129 *errorOS << s;
96 }130 }
97}131}
98132
99void ErrorHandler::log(const Twine &Msg) {133void ErrorHandler::log(const Twine &msg) {
100 if (Verbose) {134 if (verbose) {
101 std::lock_guard<std::mutex> Lock(Mu);135 std::lock_guard<std::mutex> lock(mu);
102 *ErrorOS << LogName << ": " << Msg << "\n";136 *errorOS << logName << ": " << msg << "\n";
103 }137 }
104}138}
105139
106void ErrorHandler::message(const Twine &Msg) {140void ErrorHandler::message(const Twine &msg) {
107 std::lock_guard<std::mutex> Lock(Mu);141 std::lock_guard<std::mutex> lock(mu);
108 outs() << Msg << "\n";142 outs() << msg << "\n";
109 outs().flush();143 outs().flush();
110}144}
111145
112void ErrorHandler::warn(const Twine &Msg) {146void ErrorHandler::warn(const Twine &msg) {
113 if (FatalWarnings) {147 if (fatalWarnings) {
114 error(Msg);148 error(msg);
115 return;149 return;
116 }150 }
117151
118 std::lock_guard<std::mutex> Lock(Mu);152 std::lock_guard<std::mutex> lock(mu);
119 newline(ErrorOS, Msg);153 newline(errorOS, msg);
120 print("warning: ", raw_ostream::MAGENTA);154 printHeader("warning: ", raw_ostream::MAGENTA, msg);
121 *ErrorOS << Msg << "\n";155 *errorOS << msg << "\n";
122}156}
123157
124void ErrorHandler::error(const Twine &Msg) {158void ErrorHandler::error(const Twine &msg) {
125 std::lock_guard<std::mutex> Lock(Mu);159 std::lock_guard<std::mutex> lock(mu);
126 newline(ErrorOS, Msg);160 newline(errorOS, msg);
127161
128 if (ErrorLimit == 0 || ErrorCount < ErrorLimit) {162 if (errorLimit == 0 || errorCount < errorLimit) {
129 print("error: ", raw_ostream::RED);163 printHeader("error: ", raw_ostream::RED, msg);
130 *ErrorOS << Msg << "\n";164 *errorOS << msg << "\n";
131 } else if (ErrorCount == ErrorLimit) {165 } else if (errorCount == errorLimit) {
132 print("error: ", raw_ostream::RED);166 printHeader("error: ", raw_ostream::RED, msg);
133 *ErrorOS << ErrorLimitExceededMsg << "\n";167 *errorOS << errorLimitExceededMsg << "\n";
134 if (ExitEarly)168 if (exitEarly)
135 exitLld(1);169 exitLld(1);
136 }170 }
137171
138 ++ErrorCount;172 ++errorCount;
139}173}
140174
141void ErrorHandler::fatal(const Twine &Msg) {175void ErrorHandler::fatal(const Twine &msg) {
142 error(Msg);176 error(msg);
143 exitLld(1);177 exitLld(1);
144}178}
deps/lld/Common/Filesystem.cpp created+99
...@@ -0,0 +1,99 @@
1//===- Filesystem.cpp -----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains a few utility functions to handle files.
10//
11//===----------------------------------------------------------------------===//
12
13#include "lld/Common/Filesystem.h"
14#include "lld/Common/Threads.h"
15#include "llvm/Config/llvm-config.h"
16#include "llvm/Support/FileOutputBuffer.h"
17#include "llvm/Support/FileSystem.h"
18#if LLVM_ON_UNIX
19#include <unistd.h>
20#endif
21#include <thread>
22
23using namespace llvm;
24using namespace lld;
25
26// Removes a given file asynchronously. This is a performance hack,
27// so remove this when operating systems are improved.
28//
29// On Linux (and probably on other Unix-like systems), unlink(2) is a
30// noticeably slow system call. As of 2016, unlink takes 250
31// milliseconds to remove a 1 GB file on ext4 filesystem on my machine.
32//
33// To create a new result file, we first remove existing file. So, if
34// you repeatedly link a 1 GB program in a regular compile-link-debug
35// cycle, every cycle wastes 250 milliseconds only to remove a file.
36// Since LLD can link a 1 GB binary in about 5 seconds, that waste
37// actually counts.
38//
39// This function spawns a background thread to remove the file.
40// The calling thread returns almost immediately.
41void lld::unlinkAsync(StringRef path) {
42// Removing a file is async on windows.
43#if defined(_WIN32)
44 sys::fs::remove(path);
45#else
46 if (!threadsEnabled || !sys::fs::exists(path) ||
47 !sys::fs::is_regular_file(path))
48 return;
49
50 // We cannot just remove path from a different thread because we are now going
51 // to create path as a new file.
52 // Instead we open the file and unlink it on this thread. The unlink is fast
53 // since the open fd guarantees that it is not removing the last reference.
54 int fd;
55 std::error_code ec = sys::fs::openFileForRead(path, fd);
56 sys::fs::remove(path);
57
58 if (ec)
59 return;
60
61 // close and therefore remove TempPath in background.
62 std::mutex m;
63 std::condition_variable cv;
64 bool started = false;
65 std::thread([&, fd] {
66 {
67 std::lock_guard<std::mutex> l(m);
68 started = true;
69 cv.notify_all();
70 }
71 ::close(fd);
72 }).detach();
73
74 // GLIBC 2.26 and earlier have race condition that crashes an entire process
75 // if the main thread calls exit(2) while other thread is starting up.
76 std::unique_lock<std::mutex> l(m);
77 cv.wait(l, [&] { return started; });
78#endif
79}
80
81// Simulate file creation to see if Path is writable.
82//
83// Determining whether a file is writable or not is amazingly hard,
84// and after all the only reliable way of doing that is to actually
85// create a file. But we don't want to do that in this function
86// because LLD shouldn't update any file if it will end in a failure.
87// We also don't want to reimplement heuristics to determine if a
88// file is writable. So we'll let FileOutputBuffer do the work.
89//
90// FileOutputBuffer doesn't touch a desitnation file until commit()
91// is called. We use that class without calling commit() to predict
92// if the given file is writable.
93std::error_code lld::tryCreateFile(StringRef path) {
94 if (path.empty())
95 return std::error_code();
96 if (path == "-")
97 return std::error_code();
98 return errorToErrorCode(FileOutputBuffer::create(path, 1).takeError());
99}
deps/lld/Common/Memory.cpp+9-10
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Memory.cpp ---------------------------------------------------------===//1//===- Memory.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -12,12 +11,12 @@...@@ -12,12 +11,12 @@
12using namespace llvm;11using namespace llvm;
13using namespace lld;12using namespace lld;
1413
15BumpPtrAllocator lld::BAlloc;14BumpPtrAllocator lld::bAlloc;
16StringSaver lld::Saver{BAlloc};15StringSaver lld::saver{bAlloc};
17std::vector<SpecificAllocBase *> lld::SpecificAllocBase::Instances;16std::vector<SpecificAllocBase *> lld::SpecificAllocBase::instances;
1817
19void lld::freeArena() {18void lld::freeArena() {
20 for (SpecificAllocBase *Alloc : SpecificAllocBase::Instances)19 for (SpecificAllocBase *alloc : SpecificAllocBase::instances)
21 Alloc->reset();20 alloc->reset();
22 BAlloc.Reset();21 bAlloc.Reset();
23}22}
deps/lld/Common/Reproduce.cpp+31-36
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Reproduce.cpp - Utilities for creating reproducers -----------------===//1//===- Reproduce.cpp - Utilities for creating reproducers -----------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -22,45 +21,41 @@ using namespace llvm::sys;...@@ -22,45 +21,41 @@ using namespace llvm::sys;
22// assuming that the current directory is "/home/john/bar".21// assuming that the current directory is "/home/john/bar".
23// Returned string is a forward slash separated path even on Windows to avoid22// Returned string is a forward slash separated path even on Windows to avoid
24// a mess with backslash-as-escape and backslash-as-path-separator.23// a mess with backslash-as-escape and backslash-as-path-separator.
25std::string lld::relativeToRoot(StringRef Path) {24std::string lld::relativeToRoot(StringRef path) {
26 SmallString<128> Abs = Path;25 SmallString<128> abs = path;
27 if (fs::make_absolute(Abs))26 if (fs::make_absolute(abs))
28 return Path;27 return path;
29 path::remove_dots(Abs, /*remove_dot_dot=*/true);28 path::remove_dots(abs, /*remove_dot_dot=*/true);
3029
31 // This is Windows specific. root_name() returns a drive letter30 // This is Windows specific. root_name() returns a drive letter
32 // (e.g. "c:") or a UNC name (//net). We want to keep it as part31 // (e.g. "c:") or a UNC name (//net). We want to keep it as part
33 // of the result.32 // of the result.
34 SmallString<128> Res;33 SmallString<128> res;
35 StringRef Root = path::root_name(Abs);34 StringRef root = path::root_name(abs);
36 if (Root.endswith(":"))35 if (root.endswith(":"))
37 Res = Root.drop_back();36 res = root.drop_back();
38 else if (Root.startswith("//"))37 else if (root.startswith("//"))
39 Res = Root.substr(2);38 res = root.substr(2);
4039
41 path::append(Res, path::relative_path(Abs));40 path::append(res, path::relative_path(abs));
42 return path::convert_to_slash(Res);41 return path::convert_to_slash(res);
43}42}
4443
45// Quote a given string if it contains a space character.44// Quote a given string if it contains a space character.
46std::string lld::quote(StringRef S) {45std::string lld::quote(StringRef s) {
47 if (S.contains(' '))46 if (s.contains(' '))
48 return ("\"" + S + "\"").str();47 return ("\"" + s + "\"").str();
49 return S;48 return s;
50}
51
52std::string lld::rewritePath(StringRef S) {
53 if (fs::exists(S))
54 return relativeToRoot(S);
55 return S;
56}49}
5750
58std::string lld::toString(const opt::Arg &Arg) {51// Converts an Arg to a string representation suitable for a response file.
59 std::string K = Arg.getSpelling();52// To show an Arg in a diagnostic, use Arg::getAsString() instead.
60 if (Arg.getNumValues() == 0)53std::string lld::toString(const opt::Arg &arg) {
61 return K;54 std::string k = arg.getSpelling();
62 std::string V = quote(Arg.getValue());55 if (arg.getNumValues() == 0)
63 if (Arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle)56 return k;
64 return K + V;57 std::string v = quote(arg.getValue());
65 return K + " " + V;58 if (arg.getOption().getRenderStyle() == opt::Option::RenderJoinedStyle)
59 return k + v;
60 return k + " " + v;
66}61}
deps/lld/Common/Strings.cpp+49-50
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Strings.cpp -------------------------------------------------------===//1//===- Strings.cpp -------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -20,85 +19,85 @@ using namespace llvm;...@@ -20,85 +19,85 @@ using namespace llvm;
20using namespace lld;19using namespace lld;
2120
22// Returns the demangled C++ symbol name for Name.21// Returns the demangled C++ symbol name for Name.
23Optional<std::string> lld::demangleItanium(StringRef Name) {22Optional<std::string> lld::demangleItanium(StringRef name) {
24 // itaniumDemangle can be used to demangle strings other than symbol23 // itaniumDemangle can be used to demangle strings other than symbol
25 // names which do not necessarily start with "_Z". Name can be24 // names which do not necessarily start with "_Z". Name can be
26 // either a C or C++ symbol. Don't call itaniumDemangle if the name25 // either a C or C++ symbol. Don't call itaniumDemangle if the name
27 // does not look like a C++ symbol name to avoid getting unexpected26 // does not look like a C++ symbol name to avoid getting unexpected
28 // result for a C symbol that happens to match a mangled type name.27 // result for a C symbol that happens to match a mangled type name.
29 if (!Name.startswith("_Z"))28 if (!name.startswith("_Z"))
30 return None;29 return None;
3130
32 char *Buf = itaniumDemangle(Name.str().c_str(), nullptr, nullptr, nullptr);31 char *buf = itaniumDemangle(name.str().c_str(), nullptr, nullptr, nullptr);
33 if (!Buf)32 if (!buf)
34 return None;33 return None;
35 std::string S(Buf);34 std::string s(buf);
36 free(Buf);35 free(buf);
37 return S;36 return s;
38}37}
3938
40Optional<std::string> lld::demangleMSVC(StringRef Name) {39Optional<std::string> lld::demangleMSVC(StringRef name) {
41 std::string Prefix;40 std::string prefix;
42 if (Name.consume_front("__imp_"))41 if (name.consume_front("__imp_"))
43 Prefix = "__declspec(dllimport) ";42 prefix = "__declspec(dllimport) ";
4443
45 // Demangle only C++ names.44 // Demangle only C++ names.
46 if (!Name.startswith("?"))45 if (!name.startswith("?"))
47 return None;46 return None;
4847
49 char *Buf = microsoftDemangle(Name.str().c_str(), nullptr, nullptr, nullptr);48 char *buf = microsoftDemangle(name.str().c_str(), nullptr, nullptr, nullptr);
50 if (!Buf)49 if (!buf)
51 return None;50 return None;
52 std::string S(Buf);51 std::string s(buf);
53 free(Buf);52 free(buf);
54 return Prefix + S;53 return prefix + s;
55}54}
5655
57StringMatcher::StringMatcher(ArrayRef<StringRef> Pat) {56StringMatcher::StringMatcher(ArrayRef<StringRef> pat) {
58 for (StringRef S : Pat) {57 for (StringRef s : pat) {
59 Expected<GlobPattern> Pat = GlobPattern::create(S);58 Expected<GlobPattern> pat = GlobPattern::create(s);
60 if (!Pat)59 if (!pat)
61 error(toString(Pat.takeError()));60 error(toString(pat.takeError()));
62 else61 else
63 Patterns.push_back(*Pat);62 patterns.push_back(*pat);
64 }63 }
65}64}
6665
67bool StringMatcher::match(StringRef S) const {66bool StringMatcher::match(StringRef s) const {
68 for (const GlobPattern &Pat : Patterns)67 for (const GlobPattern &pat : patterns)
69 if (Pat.match(S))68 if (pat.match(s))
70 return true;69 return true;
71 return false;70 return false;
72}71}
7372
74// Converts a hex string (e.g. "deadbeef") to a vector.73// Converts a hex string (e.g. "deadbeef") to a vector.
75std::vector<uint8_t> lld::parseHex(StringRef S) {74std::vector<uint8_t> lld::parseHex(StringRef s) {
76 std::vector<uint8_t> Hex;75 std::vector<uint8_t> hex;
77 while (!S.empty()) {76 while (!s.empty()) {
78 StringRef B = S.substr(0, 2);77 StringRef b = s.substr(0, 2);
79 S = S.substr(2);78 s = s.substr(2);
80 uint8_t H;79 uint8_t h;
81 if (!to_integer(B, H, 16)) {80 if (!to_integer(b, h, 16)) {
82 error("not a hexadecimal value: " + B);81 error("not a hexadecimal value: " + b);
83 return {};82 return {};
84 }83 }
85 Hex.push_back(H);84 hex.push_back(h);
86 }85 }
87 return Hex;86 return hex;
88}87}
8988
90// Returns true if S is valid as a C language identifier.89// Returns true if S is valid as a C language identifier.
91bool lld::isValidCIdentifier(StringRef S) {90bool lld::isValidCIdentifier(StringRef s) {
92 return !S.empty() && (isAlpha(S[0]) || S[0] == '_') &&91 return !s.empty() && (isAlpha(s[0]) || s[0] == '_') &&
93 std::all_of(S.begin() + 1, S.end(),92 std::all_of(s.begin() + 1, s.end(),
94 [](char C) { return C == '_' || isAlnum(C); });93 [](char c) { return c == '_' || isAlnum(c); });
95}94}
9695
97// Write the contents of the a buffer to a file96// Write the contents of the a buffer to a file
98void lld::saveBuffer(StringRef Buffer, const Twine &Path) {97void lld::saveBuffer(StringRef buffer, const Twine &path) {
99 std::error_code EC;98 std::error_code ec;
100 raw_fd_ostream OS(Path.str(), EC, sys::fs::OpenFlags::F_None);99 raw_fd_ostream os(path.str(), ec, sys::fs::OpenFlags::F_None);
101 if (EC)100 if (ec)
102 error("cannot create " + Path + ": " + EC.message());101 error("cannot create " + path + ": " + ec.message());
103 OS << Buffer;102 os << buffer;
104}103}
deps/lld/Common/TargetOptionsCommandFlags.cpp+9-9
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===-- TargetOptionsCommandFlags.cpp ---------------------------*- C++ -*-===//1//===-- TargetOptionsCommandFlags.cpp ---------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -20,16 +19,17 @@...@@ -20,16 +19,17 @@
20#include "llvm/Target/TargetOptions.h"19#include "llvm/Target/TargetOptions.h"
2120
22// Define an externally visible version of21// Define an externally visible version of
23// InitTargetOptionsFromCodeGenFlags, so that its functionality can be22// initTargetOptionsFromCodeGenFlags, so that its functionality can be
24// used without having to include llvm/CodeGen/CommandFlags.inc, which23// used without having to include llvm/CodeGen/CommandFlags.inc, which
25// would lead to multiple definitions of the command line flags.24// would lead to multiple definitions of the command line flags.
26llvm::TargetOptions lld::InitTargetOptionsFromCodeGenFlags() {25llvm::TargetOptions lld::initTargetOptionsFromCodeGenFlags() {
27 return ::InitTargetOptionsFromCodeGenFlags();26 return ::InitTargetOptionsFromCodeGenFlags();
28}27}
2928
30llvm::Optional<llvm::CodeModel::Model> lld::GetCodeModelFromCMModel() {29llvm::Optional<llvm::CodeModel::Model> lld::getCodeModelFromCMModel() {
31 return getCodeModel();30 return getCodeModel();
32}31}
3332
34std::string lld::GetCPUStr() { return ::getCPUStr(); }33std::string lld::getCPUStr() { return ::getCPUStr(); }
35std::vector<std::string> lld::GetMAttrs() { return ::MAttrs; }34
35std::vector<std::string> lld::getMAttrs() { return ::MAttrs; }
deps/lld/Common/Threads.cpp+4-5
...@@ -1,12 +1,11 @@...@@ -1,12 +1,11 @@
1//===- Threads.cpp --------------------------------------------------------===//1//===- Threads.cpp --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
10#include "lld/Common/Threads.h"9#include "lld/Common/Threads.h"
1110
12bool lld::ThreadsEnabled = true;11bool lld::threadsEnabled = true;
deps/lld/Common/Timer.cpp+30-31
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Timer.cpp ----------------------------------------------------------===//1//===- Timer.cpp ----------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -14,43 +13,43 @@...@@ -14,43 +13,43 @@
14using namespace lld;13using namespace lld;
15using namespace llvm;14using namespace llvm;
1615
17ScopedTimer::ScopedTimer(Timer &T) : T(&T) { T.start(); }16ScopedTimer::ScopedTimer(Timer &t) : t(&t) { t.start(); }
1817
19void ScopedTimer::stop() {18void ScopedTimer::stop() {
20 if (!T)19 if (!t)
21 return;20 return;
22 T->stop();21 t->stop();
23 T = nullptr;22 t = nullptr;
24}23}
2524
26ScopedTimer::~ScopedTimer() { stop(); }25ScopedTimer::~ScopedTimer() { stop(); }
2726
28Timer::Timer(llvm::StringRef Name) : Name(Name), Parent(nullptr) {}27Timer::Timer(llvm::StringRef name) : name(name), parent(nullptr) {}
29Timer::Timer(llvm::StringRef Name, Timer &Parent)28Timer::Timer(llvm::StringRef name, Timer &parent)
30 : Name(Name), Parent(&Parent) {}29 : name(name), parent(&parent) {}
3130
32void Timer::start() {31void Timer::start() {
33 if (Parent && Total.count() == 0)32 if (parent && total.count() == 0)
34 Parent->Children.push_back(this);33 parent->children.push_back(this);
35 StartTime = std::chrono::high_resolution_clock::now();34 startTime = std::chrono::high_resolution_clock::now();
36}35}
3736
38void Timer::stop() {37void Timer::stop() {
39 Total += (std::chrono::high_resolution_clock::now() - StartTime);38 total += (std::chrono::high_resolution_clock::now() - startTime);
40}39}
4140
42Timer &Timer::root() {41Timer &Timer::root() {
43 static Timer RootTimer("Total Link Time");42 static Timer rootTimer("Total Link Time");
44 return RootTimer;43 return rootTimer;
45}44}
4645
47void Timer::print() {46void Timer::print() {
48 double TotalDuration = static_cast<double>(root().millis());47 double totalDuration = static_cast<double>(root().millis());
4948
50 // We want to print the grand total under all the intermediate phases, so we49 // We want to print the grand total under all the intermediate phases, so we
51 // print all children first, then print the total under that.50 // print all children first, then print the total under that.
52 for (const auto &Child : Children)51 for (const auto &child : children)
53 Child->print(1, TotalDuration);52 child->print(1, totalDuration);
5453
55 message(std::string(49, '-'));54 message(std::string(49, '-'));
5655
...@@ -59,22 +58,22 @@ void Timer::print() {...@@ -59,22 +58,22 @@ void Timer::print() {
5958
60double Timer::millis() const {59double Timer::millis() const {
61 return std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(60 return std::chrono::duration_cast<std::chrono::duration<double, std::milli>>(
62 Total)61 total)
63 .count();62 .count();
64}63}
6564
66void Timer::print(int Depth, double TotalDuration, bool Recurse) const {65void Timer::print(int depth, double totalDuration, bool recurse) const {
67 double P = 100.0 * millis() / TotalDuration;66 double p = 100.0 * millis() / totalDuration;
6867
69 SmallString<32> Str;68 SmallString<32> str;
70 llvm::raw_svector_ostream Stream(Str);69 llvm::raw_svector_ostream stream(str);
71 std::string S = std::string(Depth * 2, ' ') + Name + std::string(":");70 std::string s = std::string(depth * 2, ' ') + name + std::string(":");
72 Stream << format("%-30s%5d ms (%5.1f%%)", S.c_str(), (int)millis(), P);71 stream << format("%-30s%5d ms (%5.1f%%)", s.c_str(), (int)millis(), p);
7372
74 message(Str);73 message(str);
7574
76 if (Recurse) {75 if (recurse) {
77 for (const auto &Child : Children)76 for (const auto &child : children)
78 Child->print(Depth + 1, TotalDuration);77 child->print(depth + 1, totalDuration);
79 }78 }
80}79}
deps/lld/Common/Version.cpp+13-29
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/Common/Version.cpp - LLD Version Number ---------------*- C++-=====//1//===- lib/Common/Version.cpp - LLD Version Number ---------------*- C++-=====//
2//2//
3// The LLVM Compiler Infrastructure3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -13,31 +12,16 @@...@@ -13,31 +12,16 @@
1312
14#include "lld/Common/Version.h"13#include "lld/Common/Version.h"
1514
16using namespace llvm;15#ifdef HAVE_VCS_VERSION_INC
1716#include "VCSVersion.inc"
18// Returns an SVN repository path, which is usually "trunk".17#endif
19static std::string getRepositoryPath() {
20 StringRef S = LLD_REPOSITORY_STRING;
21 size_t Pos = S.find("lld/");
22 if (Pos != StringRef::npos)
23 return S.substr(Pos + 4);
24 return S;
25}
26
27// Returns an SVN repository name, e.g., " (trunk 284614)"
28// or an empty string if no repository info is available.
29static std::string getRepository() {
30 std::string Repo = getRepositoryPath();
31 std::string Rev = LLD_REVISION_STRING;
32
33 if (Repo.empty() && Rev.empty())
34 return "";
35 if (!Repo.empty() && !Rev.empty())
36 return " (" + Repo + " " + Rev + ")";
37 return " (" + Repo + Rev + ")";
38}
3918
40// Returns a version string, e.g., "LLD 4.0 (lld/trunk 284614)".19// Returns a version string, e.g.:
20// lld 9.0.0 (https://github.com/llvm/llvm-project.git 9efdd7ac5e914d3c9fa1ef)
41std::string lld::getLLDVersion() {21std::string lld::getLLDVersion() {
42 return "LLD " + std::string(LLD_VERSION_STRING) + getRepository();22#if defined(LLD_REPOSITORY) && defined(LLD_REVISION)
23 return "LLD " LLD_VERSION_STRING " (" LLD_REPOSITORY " " LLD_REVISION ")";
24#else
25 return "LLD " LLD_VERSION_STRING;
26#endif
43}27}
deps/lld/ELF/AArch64ErrataFix.cpp+247-248
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- AArch64ErrataFix.cpp -----------------------------------------------===//1//===- AArch64ErrataFix.cpp -----------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9// This file implements Section Patching for the purpose of working around8// This file implements Section Patching for the purpose of working around
...@@ -57,8 +56,8 @@ using namespace lld::elf;...@@ -57,8 +56,8 @@ using namespace lld::elf;
5756
58// ADRP57// ADRP
59// | 1 | immlo (2) | 1 | 0 0 0 0 | immhi (19) | Rd (5) |58// | 1 | immlo (2) | 1 | 0 0 0 0 | immhi (19) | Rd (5) |
60static bool isADRP(uint32_t Instr) {59static bool isADRP(uint32_t instr) {
61 return (Instr & 0x9f000000) == 0x90000000;60 return (instr & 0x9f000000) == 0x90000000;
62}61}
6362
64// Load and store bit patterns from ARMv8-A ARM ARM.63// Load and store bit patterns from ARMv8-A ARM ARM.
...@@ -67,8 +66,8 @@ static bool isADRP(uint32_t Instr) {...@@ -67,8 +66,8 @@ static bool isADRP(uint32_t Instr) {
6766
68// All loads and stores have 1 (at bit postion 27), (0 at bit position 25).67// All loads and stores have 1 (at bit postion 27), (0 at bit position 25).
69// | op0 x op1 (2) | 1 op2 0 op3 (2) | x | op4 (5) | xxxx | op5 (2) | x (10) |68// | op0 x op1 (2) | 1 op2 0 op3 (2) | x | op4 (5) | xxxx | op5 (2) | x (10) |
70static bool isLoadStoreClass(uint32_t Instr) {69static bool isLoadStoreClass(uint32_t instr) {
71 return (Instr & 0x0a000000) == 0x08000000;70 return (instr & 0x0a000000) == 0x08000000;
72}71}
7372
74// LDN/STN multiple no offset73// LDN/STN multiple no offset
...@@ -83,20 +82,20 @@ static bool isLoadStoreClass(uint32_t Instr) {...@@ -83,20 +82,20 @@ static bool isLoadStoreClass(uint32_t Instr) {
83// opcode == 0110 ST1 3 registers.82// opcode == 0110 ST1 3 registers.
84// opcode == 0111 ST1 1 register.83// opcode == 0111 ST1 1 register.
85// opcode == 1010 ST1 2 registers.84// opcode == 1010 ST1 2 registers.
86static bool isST1MultipleOpcode(uint32_t Instr) {85static bool isST1MultipleOpcode(uint32_t instr) {
87 return (Instr & 0x0000f000) == 0x00002000 ||86 return (instr & 0x0000f000) == 0x00002000 ||
88 (Instr & 0x0000f000) == 0x00006000 ||87 (instr & 0x0000f000) == 0x00006000 ||
89 (Instr & 0x0000f000) == 0x00007000 ||88 (instr & 0x0000f000) == 0x00007000 ||
90 (Instr & 0x0000f000) == 0x0000a000;89 (instr & 0x0000f000) == 0x0000a000;
91}90}
9291
93static bool isST1Multiple(uint32_t Instr) {92static bool isST1Multiple(uint32_t instr) {
94 return (Instr & 0xbfff0000) == 0x0c000000 && isST1MultipleOpcode(Instr);93 return (instr & 0xbfff0000) == 0x0c000000 && isST1MultipleOpcode(instr);
95}94}
9695
97// Writes to Rn (writeback).96// Writes to Rn (writeback).
98static bool isST1MultiplePost(uint32_t Instr) {97static bool isST1MultiplePost(uint32_t instr) {
99 return (Instr & 0xbfe00000) == 0x0c800000 && isST1MultipleOpcode(Instr);98 return (instr & 0xbfe00000) == 0x0c800000 && isST1MultipleOpcode(instr);
100}99}
101100
102// LDN/STN single no offset101// LDN/STN single no offset
...@@ -111,41 +110,41 @@ static bool isST1MultiplePost(uint32_t Instr) {...@@ -111,41 +110,41 @@ static bool isST1MultiplePost(uint32_t Instr) {
111// opcode == 000 ST1 8-bit.110// opcode == 000 ST1 8-bit.
112// opcode == 010 ST1 16-bit.111// opcode == 010 ST1 16-bit.
113// opcode == 100 ST1 32 or 64-bit (Size determines which).112// opcode == 100 ST1 32 or 64-bit (Size determines which).
114static bool isST1SingleOpcode(uint32_t Instr) {113static bool isST1SingleOpcode(uint32_t instr) {
115 return (Instr & 0x0040e000) == 0x00000000 ||114 return (instr & 0x0040e000) == 0x00000000 ||
116 (Instr & 0x0040e000) == 0x00004000 ||115 (instr & 0x0040e000) == 0x00004000 ||
117 (Instr & 0x0040e000) == 0x00008000;116 (instr & 0x0040e000) == 0x00008000;
118}117}
119118
120static bool isST1Single(uint32_t Instr) {119static bool isST1Single(uint32_t instr) {
121 return (Instr & 0xbfff0000) == 0x0d000000 && isST1SingleOpcode(Instr);120 return (instr & 0xbfff0000) == 0x0d000000 && isST1SingleOpcode(instr);
122}121}
123122
124// Writes to Rn (writeback).123// Writes to Rn (writeback).
125static bool isST1SinglePost(uint32_t Instr) {124static bool isST1SinglePost(uint32_t instr) {
126 return (Instr & 0xbfe00000) == 0x0d800000 && isST1SingleOpcode(Instr);125 return (instr & 0xbfe00000) == 0x0d800000 && isST1SingleOpcode(instr);
127}126}
128127
129static bool isST1(uint32_t Instr) {128static bool isST1(uint32_t instr) {
130 return isST1Multiple(Instr) || isST1MultiplePost(Instr) ||129 return isST1Multiple(instr) || isST1MultiplePost(instr) ||
131 isST1Single(Instr) || isST1SinglePost(Instr);130 isST1Single(instr) || isST1SinglePost(instr);
132}131}
133132
134// Load/store exclusive133// Load/store exclusive
135// | size (2) 00 | 1000 | o2 L o1 | Rs (5) | o0 | Rt2 (5) | Rn (5) | Rt (5) |134// | size (2) 00 | 1000 | o2 L o1 | Rs (5) | o0 | Rt2 (5) | Rn (5) | Rt (5) |
136// L == 0 for Stores.135// L == 0 for Stores.
137static bool isLoadStoreExclusive(uint32_t Instr) {136static bool isLoadStoreExclusive(uint32_t instr) {
138 return (Instr & 0x3f000000) == 0x08000000;137 return (instr & 0x3f000000) == 0x08000000;
139}138}
140139
141static bool isLoadExclusive(uint32_t Instr) {140static bool isLoadExclusive(uint32_t instr) {
142 return (Instr & 0x3f400000) == 0x08400000;141 return (instr & 0x3f400000) == 0x08400000;
143}142}
144143
145// Load register literal144// Load register literal
146// | opc (2) 01 | 1 V 00 | imm19 | Rt (5) |145// | opc (2) 01 | 1 V 00 | imm19 | Rt (5) |
147static bool isLoadLiteral(uint32_t Instr) {146static bool isLoadLiteral(uint32_t instr) {
148 return (Instr & 0x3b000000) == 0x18000000;147 return (instr & 0x3b000000) == 0x18000000;
149}148}
150149
151// Load/store no-allocate pair150// Load/store no-allocate pair
...@@ -153,8 +152,8 @@ static bool isLoadLiteral(uint32_t Instr) {...@@ -153,8 +152,8 @@ static bool isLoadLiteral(uint32_t Instr) {
153// | opc (2) 10 | 1 V 00 | 0 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) |152// | opc (2) 10 | 1 V 00 | 0 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) |
154// L == 0 for stores.153// L == 0 for stores.
155// Never writes to register154// Never writes to register
156static bool isSTNP(uint32_t Instr) {155static bool isSTNP(uint32_t instr) {
157 return (Instr & 0x3bc00000) == 0x28000000;156 return (instr & 0x3bc00000) == 0x28000000;
158}157}
159158
160// Load/store register pair159// Load/store register pair
...@@ -162,69 +161,69 @@ static bool isSTNP(uint32_t Instr) {...@@ -162,69 +161,69 @@ static bool isSTNP(uint32_t Instr) {
162// | opc (2) 10 | 1 V 00 | 1 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) |161// | opc (2) 10 | 1 V 00 | 1 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) |
163// L == 0 for stores, V == 0 for Scalar, V == 1 for Simd/FP162// L == 0 for stores, V == 0 for Scalar, V == 1 for Simd/FP
164// Writes to Rn.163// Writes to Rn.
165static bool isSTPPost(uint32_t Instr) {164static bool isSTPPost(uint32_t instr) {
166 return (Instr & 0x3bc00000) == 0x28800000;165 return (instr & 0x3bc00000) == 0x28800000;
167}166}
168167
169// (offset)168// (offset)
170// | opc (2) 10 | 1 V 01 | 0 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) |169// | opc (2) 10 | 1 V 01 | 0 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) |
171static bool isSTPOffset(uint32_t Instr) {170static bool isSTPOffset(uint32_t instr) {
172 return (Instr & 0x3bc00000) == 0x29000000;171 return (instr & 0x3bc00000) == 0x29000000;
173}172}
174173
175// (pre-index)174// (pre-index)
176// | opc (2) 10 | 1 V 01 | 1 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) |175// | opc (2) 10 | 1 V 01 | 1 L | imm7 | Rt2 (5) | Rn (5) | Rt (5) |
177// Writes to Rn.176// Writes to Rn.
178static bool isSTPPre(uint32_t Instr) {177static bool isSTPPre(uint32_t instr) {
179 return (Instr & 0x3bc00000) == 0x29800000;178 return (instr & 0x3bc00000) == 0x29800000;
180}179}
181180
182static bool isSTP(uint32_t Instr) {181static bool isSTP(uint32_t instr) {
183 return isSTPPost(Instr) || isSTPOffset(Instr) || isSTPPre(Instr);182 return isSTPPost(instr) || isSTPOffset(instr) || isSTPPre(instr);
184}183}
185184
186// Load/store register (unscaled immediate)185// Load/store register (unscaled immediate)
187// | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 00 | Rn (5) | Rt (5) |186// | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 00 | Rn (5) | Rt (5) |
188// V == 0 for Scalar, V == 1 for Simd/FP.187// V == 0 for Scalar, V == 1 for Simd/FP.
189static bool isLoadStoreUnscaled(uint32_t Instr) {188static bool isLoadStoreUnscaled(uint32_t instr) {
190 return (Instr & 0x3b000c00) == 0x38000000;189 return (instr & 0x3b000c00) == 0x38000000;
191}190}
192191
193// Load/store register (immediate post-indexed)192// Load/store register (immediate post-indexed)
194// | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 01 | Rn (5) | Rt (5) |193// | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 01 | Rn (5) | Rt (5) |
195static bool isLoadStoreImmediatePost(uint32_t Instr) {194static bool isLoadStoreImmediatePost(uint32_t instr) {
196 return (Instr & 0x3b200c00) == 0x38000400;195 return (instr & 0x3b200c00) == 0x38000400;
197}196}
198197
199// Load/store register (unprivileged)198// Load/store register (unprivileged)
200// | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 10 | Rn (5) | Rt (5) |199// | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 10 | Rn (5) | Rt (5) |
201static bool isLoadStoreUnpriv(uint32_t Instr) {200static bool isLoadStoreUnpriv(uint32_t instr) {
202 return (Instr & 0x3b200c00) == 0x38000800;201 return (instr & 0x3b200c00) == 0x38000800;
203}202}
204203
205// Load/store register (immediate pre-indexed)204// Load/store register (immediate pre-indexed)
206// | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 11 | Rn (5) | Rt (5) |205// | size (2) 11 | 1 V 00 | opc (2) 0 | imm9 | 11 | Rn (5) | Rt (5) |
207static bool isLoadStoreImmediatePre(uint32_t Instr) {206static bool isLoadStoreImmediatePre(uint32_t instr) {
208 return (Instr & 0x3b200c00) == 0x38000c00;207 return (instr & 0x3b200c00) == 0x38000c00;
209}208}
210209
211// Load/store register (register offset)210// Load/store register (register offset)
212// | size (2) 11 | 1 V 00 | opc (2) 1 | Rm (5) | option (3) S | 10 | Rn | Rt |211// | size (2) 11 | 1 V 00 | opc (2) 1 | Rm (5) | option (3) S | 10 | Rn | Rt |
213static bool isLoadStoreRegisterOff(uint32_t Instr) {212static bool isLoadStoreRegisterOff(uint32_t instr) {
214 return (Instr & 0x3b200c00) == 0x38200800;213 return (instr & 0x3b200c00) == 0x38200800;
215}214}
216215
217// Load/store register (unsigned immediate)216// Load/store register (unsigned immediate)
218// | size (2) 11 | 1 V 01 | opc (2) | imm12 | Rn (5) | Rt (5) |217// | size (2) 11 | 1 V 01 | opc (2) | imm12 | Rn (5) | Rt (5) |
219static bool isLoadStoreRegisterUnsigned(uint32_t Instr) {218static bool isLoadStoreRegisterUnsigned(uint32_t instr) {
220 return (Instr & 0x3b000000) == 0x39000000;219 return (instr & 0x3b000000) == 0x39000000;
221}220}
222221
223// Rt is always in bit position 0 - 4.222// Rt is always in bit position 0 - 4.
224static uint32_t getRt(uint32_t Instr) { return (Instr & 0x1f); }223static uint32_t getRt(uint32_t instr) { return (instr & 0x1f); }
225224
226// Rn is always in bit position 5 - 9.225// Rn is always in bit position 5 - 9.
227static uint32_t getRn(uint32_t Instr) { return (Instr >> 5) & 0x1f; }226static uint32_t getRn(uint32_t instr) { return (instr >> 5) & 0x1f; }
228227
229// C4.1.2 Branches, Exception Generating and System instructions228// C4.1.2 Branches, Exception Generating and System instructions
230// | op0 (3) 1 | 01 op1 (4) | x (22) |229// | op0 (3) 1 | 01 op1 (4) | x (22) |
...@@ -233,41 +232,41 @@ static uint32_t getRn(uint32_t Instr) { return (Instr >> 5) & 0x1f; }...@@ -233,41 +232,41 @@ static uint32_t getRn(uint32_t Instr) { return (Instr >> 5) & 0x1f; }
233// op0 == x00 101 op1 == xxxx Unconditional Branch immediate.232// op0 == x00 101 op1 == xxxx Unconditional Branch immediate.
234// op0 == x01 101 op1 == 0xxx Compare and branch immediate.233// op0 == x01 101 op1 == 0xxx Compare and branch immediate.
235// op0 == x01 101 op1 == 1xxx Test and branch immediate.234// op0 == x01 101 op1 == 1xxx Test and branch immediate.
236static bool isBranch(uint32_t Instr) {235static bool isBranch(uint32_t instr) {
237 return ((Instr & 0xfe000000) == 0xd6000000) || // Cond branch.236 return ((instr & 0xfe000000) == 0xd6000000) || // Cond branch.
238 ((Instr & 0xfe000000) == 0x54000000) || // Uncond branch reg.237 ((instr & 0xfe000000) == 0x54000000) || // Uncond branch reg.
239 ((Instr & 0x7c000000) == 0x14000000) || // Uncond branch imm.238 ((instr & 0x7c000000) == 0x14000000) || // Uncond branch imm.
240 ((Instr & 0x7c000000) == 0x34000000); // Compare and test branch.239 ((instr & 0x7c000000) == 0x34000000); // Compare and test branch.
241}240}
242241
243static bool isV8SingleRegisterNonStructureLoadStore(uint32_t Instr) {242static bool isV8SingleRegisterNonStructureLoadStore(uint32_t instr) {
244 return isLoadStoreUnscaled(Instr) || isLoadStoreImmediatePost(Instr) ||243 return isLoadStoreUnscaled(instr) || isLoadStoreImmediatePost(instr) ||
245 isLoadStoreUnpriv(Instr) || isLoadStoreImmediatePre(Instr) ||244 isLoadStoreUnpriv(instr) || isLoadStoreImmediatePre(instr) ||
246 isLoadStoreRegisterOff(Instr) || isLoadStoreRegisterUnsigned(Instr);245 isLoadStoreRegisterOff(instr) || isLoadStoreRegisterUnsigned(instr);
247}246}
248247
249// Note that this function refers to v8.0 only and does not include the248// Note that this function refers to v8.0 only and does not include the
250// additional load and store instructions added for in later revisions of249// additional load and store instructions added for in later revisions of
251// the architecture such as the Atomic memory operations introduced250// the architecture such as the Atomic memory operations introduced
252// in v8.1.251// in v8.1.
253static bool isV8NonStructureLoad(uint32_t Instr) {252static bool isV8NonStructureLoad(uint32_t instr) {
254 if (isLoadExclusive(Instr))253 if (isLoadExclusive(instr))
255 return true;254 return true;
256 if (isLoadLiteral(Instr))255 if (isLoadLiteral(instr))
257 return true;256 return true;
258 else if (isV8SingleRegisterNonStructureLoadStore(Instr)) {257 else if (isV8SingleRegisterNonStructureLoadStore(instr)) {
259 // For Load and Store single register, Loads are derived from a258 // For Load and Store single register, Loads are derived from a
260 // combination of the Size, V and Opc fields.259 // combination of the Size, V and Opc fields.
261 uint32_t Size = (Instr >> 30) & 0xff;260 uint32_t size = (instr >> 30) & 0xff;
262 uint32_t V = (Instr >> 26) & 0x1;261 uint32_t v = (instr >> 26) & 0x1;
263 uint32_t Opc = (Instr >> 22) & 0x3;262 uint32_t opc = (instr >> 22) & 0x3;
264 // For the load and store instructions that we are decoding.263 // For the load and store instructions that we are decoding.
265 // Opc == 0 are all stores.264 // Opc == 0 are all stores.
266 // Opc == 1 with a couple of exceptions are loads. The exceptions are:265 // Opc == 1 with a couple of exceptions are loads. The exceptions are:
267 // Size == 00 (0), V == 1, Opc == 10 (2) which is a store and266 // Size == 00 (0), V == 1, Opc == 10 (2) which is a store and
268 // Size == 11 (3), V == 0, Opc == 10 (2) which is a prefetch.267 // Size == 11 (3), V == 0, Opc == 10 (2) which is a prefetch.
269 return Opc != 0 && !(Size == 0 && V == 1 && Opc == 2) &&268 return opc != 0 && !(size == 0 && v == 1 && opc == 2) &&
270 !(Size == 3 && V == 0 && Opc == 2);269 !(size == 3 && v == 0 && opc == 2);
271 }270 }
272 return false;271 return false;
273}272}
...@@ -276,18 +275,18 @@ static bool isV8NonStructureLoad(uint32_t Instr) {...@@ -276,18 +275,18 @@ static bool isV8NonStructureLoad(uint32_t Instr) {
276// needed for errata 843419.275// needed for errata 843419.
277276
278// Instruction with writeback updates the index register after the load/store.277// Instruction with writeback updates the index register after the load/store.
279static bool hasWriteback(uint32_t Instr) {278static bool hasWriteback(uint32_t instr) {
280 return isLoadStoreImmediatePre(Instr) || isLoadStoreImmediatePost(Instr) ||279 return isLoadStoreImmediatePre(instr) || isLoadStoreImmediatePost(instr) ||
281 isSTPPre(Instr) || isSTPPost(Instr) || isST1SinglePost(Instr) ||280 isSTPPre(instr) || isSTPPost(instr) || isST1SinglePost(instr) ||
282 isST1MultiplePost(Instr);281 isST1MultiplePost(instr);
283}282}
284283
285// For the load and store class of instructions, a load can write to the284// For the load and store class of instructions, a load can write to the
286// destination register, a load and a store can write to the base register when285// destination register, a load and a store can write to the base register when
287// the instruction has writeback.286// the instruction has writeback.
288static bool doesLoadStoreWriteToReg(uint32_t Instr, uint32_t Reg) {287static bool doesLoadStoreWriteToReg(uint32_t instr, uint32_t reg) {
289 return (isV8NonStructureLoad(Instr) && getRt(Instr) == Reg) ||288 return (isV8NonStructureLoad(instr) && getRt(instr) == reg) ||
290 (hasWriteback(Instr) && getRn(Instr) == Reg);289 (hasWriteback(instr) && getRn(instr) == reg);
291}290}
292291
293// Scanner for Cortex-A53 errata 843419292// Scanner for Cortex-A53 errata 843419
...@@ -319,18 +318,18 @@ static bool doesLoadStoreWriteToReg(uint32_t Instr, uint32_t Reg) {...@@ -319,18 +318,18 @@ static bool doesLoadStoreWriteToReg(uint32_t Instr, uint32_t Reg) {
319// Return true if the Instruction sequence Adrp, Instr2, and Instr4 match318// Return true if the Instruction sequence Adrp, Instr2, and Instr4 match
320// the erratum sequence. The Adrp, Instr2 and Instr4 correspond to 1.), 2.),319// the erratum sequence. The Adrp, Instr2 and Instr4 correspond to 1.), 2.),
321// and 4.) in the Scanner for Cortex-A53 errata comment above.320// and 4.) in the Scanner for Cortex-A53 errata comment above.
322static bool is843419ErratumSequence(uint32_t Instr1, uint32_t Instr2,321static bool is843419ErratumSequence(uint32_t instr1, uint32_t instr2,
323 uint32_t Instr4) {322 uint32_t instr4) {
324 if (!isADRP(Instr1))323 if (!isADRP(instr1))
325 return false;324 return false;
326325
327 uint32_t Rn = getRt(Instr1);326 uint32_t rn = getRt(instr1);
328 return isLoadStoreClass(Instr2) &&327 return isLoadStoreClass(instr2) &&
329 (isLoadStoreExclusive(Instr2) || isLoadLiteral(Instr2) ||328 (isLoadStoreExclusive(instr2) || isLoadLiteral(instr2) ||
330 isV8SingleRegisterNonStructureLoadStore(Instr2) || isSTP(Instr2) ||329 isV8SingleRegisterNonStructureLoadStore(instr2) || isSTP(instr2) ||
331 isSTNP(Instr2) || isST1(Instr2)) &&330 isSTNP(instr2) || isST1(instr2)) &&
332 !doesLoadStoreWriteToReg(Instr2, Rn) &&331 !doesLoadStoreWriteToReg(instr2, rn) &&
333 isLoadStoreRegisterUnsigned(Instr4) && getRn(Instr4) == Rn;332 isLoadStoreRegisterUnsigned(instr4) && getRn(instr4) == rn;
334}333}
335334
336// Scan the instruction sequence starting at Offset Off from the base of335// Scan the instruction sequence starting at Offset Off from the base of
...@@ -339,143 +338,143 @@ static bool is843419ErratumSequence(uint32_t Instr1, uint32_t Instr2,...@@ -339,143 +338,143 @@ static bool is843419ErratumSequence(uint32_t Instr1, uint32_t Instr2,
339// instructions we've scanned.338// instructions we've scanned.
340// Return the offset of the load or store instruction in IS that we want to339// Return the offset of the load or store instruction in IS that we want to
341// patch or 0 if no patch required.340// patch or 0 if no patch required.
342static uint64_t scanCortexA53Errata843419(InputSection *IS, uint64_t &Off,341static uint64_t scanCortexA53Errata843419(InputSection *isec, uint64_t &off,
343 uint64_t Limit) {342 uint64_t limit) {
344 uint64_t ISAddr = IS->getVA(0);343 uint64_t isecAddr = isec->getVA(0);
345344
346 // Advance Off so that (ISAddr + Off) modulo 0x1000 is at least 0xff8.345 // Advance Off so that (ISAddr + Off) modulo 0x1000 is at least 0xff8.
347 uint64_t InitialPageOff = (ISAddr + Off) & 0xfff;346 uint64_t initialPageOff = (isecAddr + off) & 0xfff;
348 if (InitialPageOff < 0xff8)347 if (initialPageOff < 0xff8)
349 Off += 0xff8 - InitialPageOff;348 off += 0xff8 - initialPageOff;
350349
351 bool OptionalAllowed = Limit - Off > 12;350 bool optionalAllowed = limit - off > 12;
352 if (Off >= Limit || Limit - Off < 12) {351 if (off >= limit || limit - off < 12) {
353 // Need at least 3 4-byte sized instructions to trigger erratum.352 // Need at least 3 4-byte sized instructions to trigger erratum.
354 Off = Limit;353 off = limit;
355 return 0;354 return 0;
356 }355 }
357356
358 uint64_t PatchOff = 0;357 uint64_t patchOff = 0;
359 const uint8_t *Buf = IS->data().begin();358 const uint8_t *buf = isec->data().begin();
360 const ulittle32_t *InstBuf = reinterpret_cast<const ulittle32_t *>(Buf + Off);359 const ulittle32_t *instBuf = reinterpret_cast<const ulittle32_t *>(buf + off);
361 uint32_t Instr1 = *InstBuf++;360 uint32_t instr1 = *instBuf++;
362 uint32_t Instr2 = *InstBuf++;361 uint32_t instr2 = *instBuf++;
363 uint32_t Instr3 = *InstBuf++;362 uint32_t instr3 = *instBuf++;
364 if (is843419ErratumSequence(Instr1, Instr2, Instr3)) {363 if (is843419ErratumSequence(instr1, instr2, instr3)) {
365 PatchOff = Off + 8;364 patchOff = off + 8;
366 } else if (OptionalAllowed && !isBranch(Instr3)) {365 } else if (optionalAllowed && !isBranch(instr3)) {
367 uint32_t Instr4 = *InstBuf++;366 uint32_t instr4 = *instBuf++;
368 if (is843419ErratumSequence(Instr1, Instr2, Instr4))367 if (is843419ErratumSequence(instr1, instr2, instr4))
369 PatchOff = Off + 12;368 patchOff = off + 12;
370 }369 }
371 if (((ISAddr + Off) & 0xfff) == 0xff8)370 if (((isecAddr + off) & 0xfff) == 0xff8)
372 Off += 4;371 off += 4;
373 else372 else
374 Off += 0xffc;373 off += 0xffc;
375 return PatchOff;374 return patchOff;
376}375}
377376
378class lld::elf::Patch843419Section : public SyntheticSection {377class lld::elf::Patch843419Section : public SyntheticSection {
379public:378public:
380 Patch843419Section(InputSection *P, uint64_t Off);379 Patch843419Section(InputSection *p, uint64_t off);
381380
382 void writeTo(uint8_t *Buf) override;381 void writeTo(uint8_t *buf) override;
383382
384 size_t getSize() const override { return 8; }383 size_t getSize() const override { return 8; }
385384
386 uint64_t getLDSTAddr() const;385 uint64_t getLDSTAddr() const;
387386
388 // The Section we are patching.387 // The Section we are patching.
389 const InputSection *Patchee;388 const InputSection *patchee;
390 // The offset of the instruction in the Patchee section we are patching.389 // The offset of the instruction in the Patchee section we are patching.
391 uint64_t PatcheeOffset;390 uint64_t patcheeOffset;
392 // A label for the start of the Patch that we can use as a relocation target.391 // A label for the start of the Patch that we can use as a relocation target.
393 Symbol *PatchSym;392 Symbol *patchSym;
394};393};
395394
396lld::elf::Patch843419Section::Patch843419Section(InputSection *P, uint64_t Off)395lld::elf::Patch843419Section::Patch843419Section(InputSection *p, uint64_t off)
397 : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 4,396 : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 4,
398 ".text.patch"),397 ".text.patch"),
399 Patchee(P), PatcheeOffset(Off) {398 patchee(p), patcheeOffset(off) {
400 this->Parent = P->getParent();399 this->parent = p->getParent();
401 PatchSym = addSyntheticLocal(400 patchSym = addSyntheticLocal(
402 Saver.save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, 0,401 saver.save("__CortexA53843419_" + utohexstr(getLDSTAddr())), STT_FUNC, 0,
403 getSize(), *this);402 getSize(), *this);
404 addSyntheticLocal(Saver.save("$x"), STT_NOTYPE, 0, 0, *this);403 addSyntheticLocal(saver.save("$x"), STT_NOTYPE, 0, 0, *this);
405}404}
406405
407uint64_t lld::elf::Patch843419Section::getLDSTAddr() const {406uint64_t lld::elf::Patch843419Section::getLDSTAddr() const {
408 return Patchee->getVA(PatcheeOffset);407 return patchee->getVA(patcheeOffset);
409}408}
410409
411void lld::elf::Patch843419Section::writeTo(uint8_t *Buf) {410void lld::elf::Patch843419Section::writeTo(uint8_t *buf) {
412 // Copy the instruction that we will be replacing with a branch in the411 // Copy the instruction that we will be replacing with a branch in the
413 // Patchee Section.412 // Patchee Section.
414 write32le(Buf, read32le(Patchee->data().begin() + PatcheeOffset));413 write32le(buf, read32le(patchee->data().begin() + patcheeOffset));
415414
416 // Apply any relocation transferred from the original PatcheeSection.415 // Apply any relocation transferred from the original PatcheeSection.
417 // For a SyntheticSection Buf already has OutSecOff added, but relocateAlloc416 // For a SyntheticSection Buf already has outSecOff added, but relocateAlloc
418 // also adds OutSecOff so we need to subtract to avoid double counting.417 // also adds outSecOff so we need to subtract to avoid double counting.
419 this->relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + getSize());418 this->relocateAlloc(buf - outSecOff, buf - outSecOff + getSize());
420419
421 // Return address is the next instruction after the one we have just copied.420 // Return address is the next instruction after the one we have just copied.
422 uint64_t S = getLDSTAddr() + 4;421 uint64_t s = getLDSTAddr() + 4;
423 uint64_t P = PatchSym->getVA() + 4;422 uint64_t p = patchSym->getVA() + 4;
424 Target->relocateOne(Buf + 4, R_AARCH64_JUMP26, S - P);423 target->relocateOne(buf + 4, R_AARCH64_JUMP26, s - p);
425}424}
426425
427void AArch64Err843419Patcher::init() {426void AArch64Err843419Patcher::init() {
428 // The AArch64 ABI permits data in executable sections. We must avoid scanning427 // The AArch64 ABI permits data in executable sections. We must avoid scanning
429 // this data as if it were instructions to avoid false matches. We use the428 // this data as if it were instructions to avoid false matches. We use the
430 // mapping symbols in the InputObjects to identify this data, caching the429 // mapping symbols in the InputObjects to identify this data, caching the
431 // results in SectionMap so we don't have to recalculate it each pass.430 // results in sectionMap so we don't have to recalculate it each pass.
432431
433 // The ABI Section 4.5.4 Mapping symbols; defines local symbols that describe432 // The ABI Section 4.5.4 Mapping symbols; defines local symbols that describe
434 // half open intervals [Symbol Value, Next Symbol Value) of code and data433 // half open intervals [Symbol Value, Next Symbol Value) of code and data
435 // within sections. If there is no next symbol then the half open interval is434 // within sections. If there is no next symbol then the half open interval is
436 // [Symbol Value, End of section). The type, code or data, is determined by435 // [Symbol Value, End of section). The type, code or data, is determined by
437 // the mapping symbol name, $x for code, $d for data.436 // the mapping symbol name, $x for code, $d for data.
438 auto IsCodeMapSymbol = [](const Symbol *B) {437 auto isCodeMapSymbol = [](const Symbol *b) {
439 return B->getName() == "$x" || B->getName().startswith("$x.");438 return b->getName() == "$x" || b->getName().startswith("$x.");
440 };439 };
441 auto IsDataMapSymbol = [](const Symbol *B) {440 auto isDataMapSymbol = [](const Symbol *b) {
442 return B->getName() == "$d" || B->getName().startswith("$d.");441 return b->getName() == "$d" || b->getName().startswith("$d.");
443 };442 };
444443
445 // Collect mapping symbols for every executable InputSection.444 // Collect mapping symbols for every executable InputSection.
446 for (InputFile *File : ObjectFiles) {445 for (InputFile *file : objectFiles) {
447 auto *F = cast<ObjFile<ELF64LE>>(File);446 auto *f = cast<ObjFile<ELF64LE>>(file);
448 for (Symbol *B : F->getLocalSymbols()) {447 for (Symbol *b : f->getLocalSymbols()) {
449 auto *Def = dyn_cast<Defined>(B);448 auto *def = dyn_cast<Defined>(b);
450 if (!Def)449 if (!def)
451 continue;450 continue;
452 if (!IsCodeMapSymbol(Def) && !IsDataMapSymbol(Def))451 if (!isCodeMapSymbol(def) && !isDataMapSymbol(def))
453 continue;452 continue;
454 if (auto *Sec = dyn_cast_or_null<InputSection>(Def->Section))453 if (auto *sec = dyn_cast_or_null<InputSection>(def->section))
455 if (Sec->Flags & SHF_EXECINSTR)454 if (sec->flags & SHF_EXECINSTR)
456 SectionMap[Sec].push_back(Def);455 sectionMap[sec].push_back(def);
457 }456 }
458 }457 }
459 // For each InputSection make sure the mapping symbols are in sorted in458 // For each InputSection make sure the mapping symbols are in sorted in
460 // ascending order and free from consecutive runs of mapping symbols with459 // ascending order and free from consecutive runs of mapping symbols with
461 // the same type. For example we must remove the redundant $d.1 from $x.0460 // the same type. For example we must remove the redundant $d.1 from $x.0
462 // $d.0 $d.1 $x.1.461 // $d.0 $d.1 $x.1.
463 for (auto &KV : SectionMap) {462 for (auto &kv : sectionMap) {
464 std::vector<const Defined *> &MapSyms = KV.second;463 std::vector<const Defined *> &mapSyms = kv.second;
465 if (MapSyms.size() <= 1)464 if (mapSyms.size() <= 1)
466 continue;465 continue;
467 std::stable_sort(466 llvm::stable_sort(mapSyms, [](const Defined *a, const Defined *b) {
468 MapSyms.begin(), MapSyms.end(),467 return a->value < b->value;
469 [](const Defined *A, const Defined *B) { return A->Value < B->Value; });468 });
470 MapSyms.erase(469 mapSyms.erase(
471 std::unique(MapSyms.begin(), MapSyms.end(),470 std::unique(mapSyms.begin(), mapSyms.end(),
472 [=](const Defined *A, const Defined *B) {471 [=](const Defined *a, const Defined *b) {
473 return (IsCodeMapSymbol(A) && IsCodeMapSymbol(B)) ||472 return (isCodeMapSymbol(a) && isCodeMapSymbol(b)) ||
474 (IsDataMapSymbol(A) && IsDataMapSymbol(B));473 (isDataMapSymbol(a) && isDataMapSymbol(b));
475 }),474 }),
476 MapSyms.end());475 mapSyms.end());
477 }476 }
478 Initialized = true;477 initialized = true;
479}478}
480479
481// Insert the PatchSections we have created back into the480// Insert the PatchSections we have created back into the
...@@ -484,60 +483,60 @@ void AArch64Err843419Patcher::init() {...@@ -484,60 +483,60 @@ void AArch64Err843419Patcher::init() {
484// executable sections, although we may need to insert them earlier if the483// executable sections, although we may need to insert them earlier if the
485// InputSectionDescription is larger than the maximum branch range.484// InputSectionDescription is larger than the maximum branch range.
486void AArch64Err843419Patcher::insertPatches(485void AArch64Err843419Patcher::insertPatches(
487 InputSectionDescription &ISD, std::vector<Patch843419Section *> &Patches) {486 InputSectionDescription &isd, std::vector<Patch843419Section *> &patches) {
488 uint64_t ISLimit;487 uint64_t isecLimit;
489 uint64_t PrevISLimit = ISD.Sections.front()->OutSecOff;488 uint64_t prevIsecLimit = isd.sections.front()->outSecOff;
490 uint64_t PatchUpperBound = PrevISLimit + Target->getThunkSectionSpacing();489 uint64_t patchUpperBound = prevIsecLimit + target->getThunkSectionSpacing();
491 uint64_t OutSecAddr = ISD.Sections.front()->getParent()->Addr;490 uint64_t outSecAddr = isd.sections.front()->getParent()->addr;
492491
493 // Set the OutSecOff of patches to the place where we want to insert them.492 // Set the outSecOff of patches to the place where we want to insert them.
494 // We use a similar strategy to Thunk placement. Place patches roughly493 // We use a similar strategy to Thunk placement. Place patches roughly
495 // every multiple of maximum branch range.494 // every multiple of maximum branch range.
496 auto PatchIt = Patches.begin();495 auto patchIt = patches.begin();
497 auto PatchEnd = Patches.end();496 auto patchEnd = patches.end();
498 for (const InputSection *IS : ISD.Sections) {497 for (const InputSection *isec : isd.sections) {
499 ISLimit = IS->OutSecOff + IS->getSize();498 isecLimit = isec->outSecOff + isec->getSize();
500 if (ISLimit > PatchUpperBound) {499 if (isecLimit > patchUpperBound) {
501 while (PatchIt != PatchEnd) {500 while (patchIt != patchEnd) {
502 if ((*PatchIt)->getLDSTAddr() - OutSecAddr >= PrevISLimit)501 if ((*patchIt)->getLDSTAddr() - outSecAddr >= prevIsecLimit)
503 break;502 break;
504 (*PatchIt)->OutSecOff = PrevISLimit;503 (*patchIt)->outSecOff = prevIsecLimit;
505 ++PatchIt;504 ++patchIt;
506 }505 }
507 PatchUpperBound = PrevISLimit + Target->getThunkSectionSpacing();506 patchUpperBound = prevIsecLimit + target->getThunkSectionSpacing();
508 }507 }
509 PrevISLimit = ISLimit;508 prevIsecLimit = isecLimit;
510 }509 }
511 for (; PatchIt != PatchEnd; ++PatchIt) {510 for (; patchIt != patchEnd; ++patchIt) {
512 (*PatchIt)->OutSecOff = ISLimit;511 (*patchIt)->outSecOff = isecLimit;
513 }512 }
514513
515 // merge all patch sections. We use the OutSecOff assigned above to514 // merge all patch sections. We use the outSecOff assigned above to
516 // determine the insertion point. This is ok as we only merge into an515 // determine the insertion point. This is ok as we only merge into an
517 // InputSectionDescription once per pass, and at the end of the pass516 // InputSectionDescription once per pass, and at the end of the pass
518 // assignAddresses() will recalculate all the OutSecOff values.517 // assignAddresses() will recalculate all the outSecOff values.
519 std::vector<InputSection *> Tmp;518 std::vector<InputSection *> tmp;
520 Tmp.reserve(ISD.Sections.size() + Patches.size());519 tmp.reserve(isd.sections.size() + patches.size());
521 auto MergeCmp = [](const InputSection *A, const InputSection *B) {520 auto mergeCmp = [](const InputSection *a, const InputSection *b) {
522 if (A->OutSecOff < B->OutSecOff)521 if (a->outSecOff < b->outSecOff)
523 return true;522 return true;
524 if (A->OutSecOff == B->OutSecOff && isa<Patch843419Section>(A) &&523 if (a->outSecOff == b->outSecOff && isa<Patch843419Section>(a) &&
525 !isa<Patch843419Section>(B))524 !isa<Patch843419Section>(b))
526 return true;525 return true;
527 return false;526 return false;
528 };527 };
529 std::merge(ISD.Sections.begin(), ISD.Sections.end(), Patches.begin(),528 std::merge(isd.sections.begin(), isd.sections.end(), patches.begin(),
530 Patches.end(), std::back_inserter(Tmp), MergeCmp);529 patches.end(), std::back_inserter(tmp), mergeCmp);
531 ISD.Sections = std::move(Tmp);530 isd.sections = std::move(tmp);
532}531}
533532
534// Given an erratum sequence that starts at address AdrpAddr, with an533// Given an erratum sequence that starts at address adrpAddr, with an
535// instruction that we need to patch at PatcheeOffset from the start of534// instruction that we need to patch at patcheeOffset from the start of
536// InputSection IS, create a Patch843419 Section and add it to the535// InputSection IS, create a Patch843419 Section and add it to the
537// Patches that we need to insert.536// Patches that we need to insert.
538static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset,537static void implementPatch(uint64_t adrpAddr, uint64_t patcheeOffset,
539 InputSection *IS,538 InputSection *isec,
540 std::vector<Patch843419Section *> &Patches) {539 std::vector<Patch843419Section *> &patches) {
541 // There may be a relocation at the same offset that we are patching. There540 // There may be a relocation at the same offset that we are patching. There
542 // are four cases that we need to consider.541 // are four cases that we need to consider.
543 // Case 1: R_AARCH64_JUMP26 branch relocation. We have already patched this542 // Case 1: R_AARCH64_JUMP26 branch relocation. We have already patched this
...@@ -552,29 +551,29 @@ static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset,...@@ -552,29 +551,29 @@ static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset,
552 // and replace the relocation with a R_AARCH_JUMP26 branch relocation.551 // and replace the relocation with a R_AARCH_JUMP26 branch relocation.
553 // Case 4: No relocation. We must create a new R_AARCH64_JUMP26 branch552 // Case 4: No relocation. We must create a new R_AARCH64_JUMP26 branch
554 // relocation at the offset.553 // relocation at the offset.
555 auto RelIt = std::find_if(554 auto relIt = llvm::find_if(isec->relocations, [=](const Relocation &r) {
556 IS->Relocations.begin(), IS->Relocations.end(),555 return r.offset == patcheeOffset;
557 [=](const Relocation &R) { return R.Offset == PatcheeOffset; });556 });
558 if (RelIt != IS->Relocations.end() &&557 if (relIt != isec->relocations.end() &&
559 (RelIt->Type == R_AARCH64_JUMP26 || RelIt->Expr == R_RELAX_TLS_IE_TO_LE))558 (relIt->type == R_AARCH64_JUMP26 || relIt->expr == R_RELAX_TLS_IE_TO_LE))
560 return;559 return;
561560
562 log("detected cortex-a53-843419 erratum sequence starting at " +561 log("detected cortex-a53-843419 erratum sequence starting at " +
563 utohexstr(AdrpAddr) + " in unpatched output.");562 utohexstr(adrpAddr) + " in unpatched output.");
564563
565 auto *PS = make<Patch843419Section>(IS, PatcheeOffset);564 auto *ps = make<Patch843419Section>(isec, patcheeOffset);
566 Patches.push_back(PS);565 patches.push_back(ps);
567566
568 auto MakeRelToPatch = [](uint64_t Offset, Symbol *PatchSym) {567 auto makeRelToPatch = [](uint64_t offset, Symbol *patchSym) {
569 return Relocation{R_PC, R_AARCH64_JUMP26, Offset, 0, PatchSym};568 return Relocation{R_PC, R_AARCH64_JUMP26, offset, 0, patchSym};
570 };569 };
571570
572 if (RelIt != IS->Relocations.end()) {571 if (relIt != isec->relocations.end()) {
573 PS->Relocations.push_back(572 ps->relocations.push_back(
574 {RelIt->Expr, RelIt->Type, 0, RelIt->Addend, RelIt->Sym});573 {relIt->expr, relIt->type, 0, relIt->addend, relIt->sym});
575 *RelIt = MakeRelToPatch(PatcheeOffset, PS->PatchSym);574 *relIt = makeRelToPatch(patcheeOffset, ps->patchSym);
576 } else575 } else
577 IS->Relocations.push_back(MakeRelToPatch(PatcheeOffset, PS->PatchSym));576 isec->relocations.push_back(makeRelToPatch(patcheeOffset, ps->patchSym));
578}577}
579578
580// Scan all the instructions in InputSectionDescription, for each instance of579// Scan all the instructions in InputSectionDescription, for each instance of
...@@ -582,40 +581,40 @@ static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset,...@@ -582,40 +581,40 @@ static void implementPatch(uint64_t AdrpAddr, uint64_t PatcheeOffset,
582// Patch843419Sections that need to be applied to ISD.581// Patch843419Sections that need to be applied to ISD.
583std::vector<Patch843419Section *>582std::vector<Patch843419Section *>
584AArch64Err843419Patcher::patchInputSectionDescription(583AArch64Err843419Patcher::patchInputSectionDescription(
585 InputSectionDescription &ISD) {584 InputSectionDescription &isd) {
586 std::vector<Patch843419Section *> Patches;585 std::vector<Patch843419Section *> patches;
587 for (InputSection *IS : ISD.Sections) {586 for (InputSection *isec : isd.sections) {
588 // LLD doesn't use the erratum sequence in SyntheticSections.587 // LLD doesn't use the erratum sequence in SyntheticSections.
589 if (isa<SyntheticSection>(IS))588 if (isa<SyntheticSection>(isec))
590 continue;589 continue;
591 // Use SectionMap to make sure we only scan code and not inline data.590 // Use sectionMap to make sure we only scan code and not inline data.
592 // We have already sorted MapSyms in ascending order and removed consecutive591 // We have already sorted MapSyms in ascending order and removed consecutive
593 // mapping symbols of the same type. Our range of executable instructions to592 // mapping symbols of the same type. Our range of executable instructions to
594 // scan is therefore [CodeSym->Value, DataSym->Value) or [CodeSym->Value,593 // scan is therefore [codeSym->value, dataSym->value) or [codeSym->value,
595 // section size).594 // section size).
596 std::vector<const Defined *> &MapSyms = SectionMap[IS];595 std::vector<const Defined *> &mapSyms = sectionMap[isec];
597596
598 auto CodeSym = llvm::find_if(MapSyms, [&](const Defined *MS) {597 auto codeSym = llvm::find_if(mapSyms, [&](const Defined *ms) {
599 return MS->getName().startswith("$x");598 return ms->getName().startswith("$x");
600 });599 });
601600
602 while (CodeSym != MapSyms.end()) {601 while (codeSym != mapSyms.end()) {
603 auto DataSym = std::next(CodeSym);602 auto dataSym = std::next(codeSym);
604 uint64_t Off = (*CodeSym)->Value;603 uint64_t off = (*codeSym)->value;
605 uint64_t Limit =604 uint64_t limit =
606 (DataSym == MapSyms.end()) ? IS->data().size() : (*DataSym)->Value;605 (dataSym == mapSyms.end()) ? isec->data().size() : (*dataSym)->value;
607606
608 while (Off < Limit) {607 while (off < limit) {
609 uint64_t StartAddr = IS->getVA(Off);608 uint64_t startAddr = isec->getVA(off);
610 if (uint64_t PatcheeOffset = scanCortexA53Errata843419(IS, Off, Limit))609 if (uint64_t patcheeOffset = scanCortexA53Errata843419(isec, off, limit))
611 implementPatch(StartAddr, PatcheeOffset, IS, Patches);610 implementPatch(startAddr, patcheeOffset, isec, patches);
612 }611 }
613 if (DataSym == MapSyms.end())612 if (dataSym == mapSyms.end())
614 break;613 break;
615 CodeSym = std::next(DataSym);614 codeSym = std::next(dataSym);
616 }615 }
617 }616 }
618 return Patches;617 return patches;
619}618}
620619
621// For each InputSectionDescription make one pass over the executable sections620// For each InputSectionDescription make one pass over the executable sections
...@@ -631,22 +630,22 @@ AArch64Err843419Patcher::patchInputSectionDescription(...@@ -631,22 +630,22 @@ AArch64Err843419Patcher::patchInputSectionDescription(
631// Ouptut and Input Sections may have been changed.630// Ouptut and Input Sections may have been changed.
632// Returns false if no patches were required and no changes were made.631// Returns false if no patches were required and no changes were made.
633bool AArch64Err843419Patcher::createFixes() {632bool AArch64Err843419Patcher::createFixes() {
634 if (Initialized == false)633 if (initialized == false)
635 init();634 init();
636635
637 bool AddressesChanged = false;636 bool addressesChanged = false;
638 for (OutputSection *OS : OutputSections) {637 for (OutputSection *os : outputSections) {
639 if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR))638 if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR))
640 continue;639 continue;
641 for (BaseCommand *BC : OS->SectionCommands)640 for (BaseCommand *bc : os->sectionCommands)
642 if (auto *ISD = dyn_cast<InputSectionDescription>(BC)) {641 if (auto *isd = dyn_cast<InputSectionDescription>(bc)) {
643 std::vector<Patch843419Section *> Patches =642 std::vector<Patch843419Section *> patches =
644 patchInputSectionDescription(*ISD);643 patchInputSectionDescription(*isd);
645 if (!Patches.empty()) {644 if (!patches.empty()) {
646 insertPatches(*ISD, Patches);645 insertPatches(*isd, patches);
647 AddressesChanged = true;646 addressesChanged = true;
648 }647 }
649 }648 }
650 }649 }
651 return AddressesChanged;650 return addressesChanged;
652}651}
deps/lld/ELF/AArch64ErrataFix.h+9-10
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- AArch64ErrataFix.h ---------------------------------------*- C++ -*-===//1//===- AArch64ErrataFix.h ---------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -30,19 +29,19 @@ public:...@@ -30,19 +29,19 @@ public:
3029
31private:30private:
32 std::vector<Patch843419Section *>31 std::vector<Patch843419Section *>
33 patchInputSectionDescription(InputSectionDescription &ISD);32 patchInputSectionDescription(InputSectionDescription &isd);
3433
35 void insertPatches(InputSectionDescription &ISD,34 void insertPatches(InputSectionDescription &isd,
36 std::vector<Patch843419Section *> &Patches);35 std::vector<Patch843419Section *> &patches);
3736
38 void init();37 void init();
3938
40 // A cache of the mapping symbols defined by the InputSecion sorted in order39 // A cache of the mapping symbols defined by the InputSection sorted in order
41 // of ascending value with redundant symbols removed. These describe40 // of ascending value with redundant symbols removed. These describe
42 // the ranges of code and data in an executable InputSection.41 // the ranges of code and data in an executable InputSection.
43 std::map<InputSection *, std::vector<const Defined *>> SectionMap;42 std::map<InputSection *, std::vector<const Defined *>> sectionMap;
4443
45 bool Initialized = false;44 bool initialized = false;
46};45};
4746
48} // namespace elf47} // namespace elf
deps/lld/ELF/Arch/AArch64.cpp+308-158
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- AArch64.cpp --------------------------------------------------------===//1//===- AArch64.cpp --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -24,60 +23,59 @@ using namespace lld::elf;...@@ -24,60 +23,59 @@ using namespace lld::elf;
24// Page(Expr) is the page address of the expression Expr, defined23// Page(Expr) is the page address of the expression Expr, defined
25// as (Expr & ~0xFFF). (This applies even if the machine page size24// as (Expr & ~0xFFF). (This applies even if the machine page size
26// supported by the platform has a different value.)25// supported by the platform has a different value.)
27uint64_t elf::getAArch64Page(uint64_t Expr) {26uint64_t elf::getAArch64Page(uint64_t expr) {
28 return Expr & ~static_cast<uint64_t>(0xFFF);27 return expr & ~static_cast<uint64_t>(0xFFF);
29}28}
3029
31namespace {30namespace {
32class AArch64 final : public TargetInfo {31class AArch64 : public TargetInfo {
33public:32public:
34 AArch64();33 AArch64();
35 RelExpr getRelExpr(RelType Type, const Symbol &S,34 RelExpr getRelExpr(RelType type, const Symbol &s,
36 const uint8_t *Loc) const override;35 const uint8_t *loc) const override;
37 RelType getDynRel(RelType Type) const override;36 RelType getDynRel(RelType type) const override;
38 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;37 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
39 void writePltHeader(uint8_t *Buf) const override;38 void writePltHeader(uint8_t *buf) const override;
40 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,39 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
41 int32_t Index, unsigned RelOff) const override;40 int32_t index, unsigned relOff) const override;
42 bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File,41 bool needsThunk(RelExpr expr, RelType type, const InputFile *file,
43 uint64_t BranchAddr, const Symbol &S) const override;42 uint64_t branchAddr, const Symbol &s) const override;
44 uint32_t getThunkSectionSpacing() const override;43 uint32_t getThunkSectionSpacing() const override;
45 bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override;44 bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
46 bool usesOnlyLowPageBits(RelType Type) const override;45 bool usesOnlyLowPageBits(RelType type) const override;
47 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;46 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
48 RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,47 RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
49 RelExpr Expr) const override;48 RelExpr expr) const override;
50 void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;49 void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
51 void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override;50 void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
52 void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;51 void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
53};52};
54} // namespace53} // namespace
5554
56AArch64::AArch64() {55AArch64::AArch64() {
57 CopyRel = R_AARCH64_COPY;56 copyRel = R_AARCH64_COPY;
58 RelativeRel = R_AARCH64_RELATIVE;57 relativeRel = R_AARCH64_RELATIVE;
59 IRelativeRel = R_AARCH64_IRELATIVE;58 iRelativeRel = R_AARCH64_IRELATIVE;
60 GotRel = R_AARCH64_GLOB_DAT;59 gotRel = R_AARCH64_GLOB_DAT;
61 NoneRel = R_AARCH64_NONE;60 noneRel = R_AARCH64_NONE;
62 PltRel = R_AARCH64_JUMP_SLOT;61 pltRel = R_AARCH64_JUMP_SLOT;
63 TlsDescRel = R_AARCH64_TLSDESC;62 symbolicRel = R_AARCH64_ABS64;
64 TlsGotRel = R_AARCH64_TLS_TPREL64;63 tlsDescRel = R_AARCH64_TLSDESC;
65 GotEntrySize = 8;64 tlsGotRel = R_AARCH64_TLS_TPREL64;
66 GotPltEntrySize = 8;65 pltEntrySize = 16;
67 PltEntrySize = 16;66 pltHeaderSize = 32;
68 PltHeaderSize = 32;67 defaultMaxPageSize = 65536;
69 DefaultMaxPageSize = 65536;
7068
71 // Align to the 2 MiB page size (known as a superpage or huge page).69 // Align to the 2 MiB page size (known as a superpage or huge page).
72 // FreeBSD automatically promotes 2 MiB-aligned allocations.70 // FreeBSD automatically promotes 2 MiB-aligned allocations.
73 DefaultImageBase = 0x200000;71 defaultImageBase = 0x200000;
7472
75 NeedsThunks = true;73 needsThunks = true;
76}74}
7775
78RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S,76RelExpr AArch64::getRelExpr(RelType type, const Symbol &s,
79 const uint8_t *Loc) const {77 const uint8_t *loc) const {
80 switch (Type) {78 switch (type) {
81 case R_AARCH64_TLSDESC_ADR_PAGE21:79 case R_AARCH64_TLSDESC_ADR_PAGE21:
82 return R_AARCH64_TLSDESC_PAGE;80 return R_AARCH64_TLSDESC_PAGE;
83 case R_AARCH64_TLSDESC_LD64_LO12:81 case R_AARCH64_TLSDESC_LD64_LO12:
...@@ -105,6 +103,7 @@ RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S,...@@ -105,6 +103,7 @@ RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S,
105 case R_AARCH64_LD_PREL_LO19:103 case R_AARCH64_LD_PREL_LO19:
106 return R_PC;104 return R_PC;
107 case R_AARCH64_ADR_PREL_PG_HI21:105 case R_AARCH64_ADR_PREL_PG_HI21:
106 case R_AARCH64_ADR_PREL_PG_HI21_NC:
108 return R_AARCH64_PAGE_PC;107 return R_AARCH64_PAGE_PC;
109 case R_AARCH64_LD64_GOT_LO12_NC:108 case R_AARCH64_LD64_GOT_LO12_NC:
110 case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:109 case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
...@@ -119,18 +118,18 @@ RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S,...@@ -119,18 +118,18 @@ RelExpr AArch64::getRelExpr(RelType Type, const Symbol &S,
119 }118 }
120}119}
121120
122RelExpr AArch64::adjustRelaxExpr(RelType Type, const uint8_t *Data,121RelExpr AArch64::adjustRelaxExpr(RelType type, const uint8_t *data,
123 RelExpr Expr) const {122 RelExpr expr) const {
124 if (Expr == R_RELAX_TLS_GD_TO_IE) {123 if (expr == R_RELAX_TLS_GD_TO_IE) {
125 if (Type == R_AARCH64_TLSDESC_ADR_PAGE21)124 if (type == R_AARCH64_TLSDESC_ADR_PAGE21)
126 return R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC;125 return R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC;
127 return R_RELAX_TLS_GD_TO_IE_ABS;126 return R_RELAX_TLS_GD_TO_IE_ABS;
128 }127 }
129 return Expr;128 return expr;
130}129}
131130
132bool AArch64::usesOnlyLowPageBits(RelType Type) const {131bool AArch64::usesOnlyLowPageBits(RelType type) const {
133 switch (Type) {132 switch (type) {
134 default:133 default:
135 return false;134 return false;
136 case R_AARCH64_ADD_ABS_LO12_NC:135 case R_AARCH64_ADD_ABS_LO12_NC:
...@@ -147,18 +146,18 @@ bool AArch64::usesOnlyLowPageBits(RelType Type) const {...@@ -147,18 +146,18 @@ bool AArch64::usesOnlyLowPageBits(RelType Type) const {
147 }146 }
148}147}
149148
150RelType AArch64::getDynRel(RelType Type) const {149RelType AArch64::getDynRel(RelType type) const {
151 if (Type == R_AARCH64_ABS32 || Type == R_AARCH64_ABS64)150 if (type == R_AARCH64_ABS64)
152 return Type;151 return type;
153 return R_AARCH64_NONE;152 return R_AARCH64_NONE;
154}153}
155154
156void AArch64::writeGotPlt(uint8_t *Buf, const Symbol &) const {155void AArch64::writeGotPlt(uint8_t *buf, const Symbol &) const {
157 write64le(Buf, In.Plt->getVA());156 write64le(buf, in.plt->getVA());
158}157}
159158
160void AArch64::writePltHeader(uint8_t *Buf) const {159void AArch64::writePltHeader(uint8_t *buf) const {
161 const uint8_t PltData[] = {160 const uint8_t pltData[] = {
162 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]!161 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]!
163 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2]))162 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2]))
164 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))]163 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))]
...@@ -168,42 +167,42 @@ void AArch64::writePltHeader(uint8_t *Buf) const {...@@ -168,42 +167,42 @@ void AArch64::writePltHeader(uint8_t *Buf) const {
168 0x1f, 0x20, 0x03, 0xd5, // nop167 0x1f, 0x20, 0x03, 0xd5, // nop
169 0x1f, 0x20, 0x03, 0xd5 // nop168 0x1f, 0x20, 0x03, 0xd5 // nop
170 };169 };
171 memcpy(Buf, PltData, sizeof(PltData));170 memcpy(buf, pltData, sizeof(pltData));
172171
173 uint64_t Got = In.GotPlt->getVA();172 uint64_t got = in.gotPlt->getVA();
174 uint64_t Plt = In.Plt->getVA();173 uint64_t plt = in.plt->getVA();
175 relocateOne(Buf + 4, R_AARCH64_ADR_PREL_PG_HI21,174 relocateOne(buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
176 getAArch64Page(Got + 16) - getAArch64Page(Plt + 4));175 getAArch64Page(got + 16) - getAArch64Page(plt + 4));
177 relocateOne(Buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, Got + 16);176 relocateOne(buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, got + 16);
178 relocateOne(Buf + 12, R_AARCH64_ADD_ABS_LO12_NC, Got + 16);177 relocateOne(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16);
179}178}
180179
181void AArch64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,180void AArch64::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
182 uint64_t PltEntryAddr, int32_t Index,181 uint64_t pltEntryAddr, int32_t index,
183 unsigned RelOff) const {182 unsigned relOff) const {
184 const uint8_t Inst[] = {183 const uint8_t inst[] = {
185 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n]))184 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n]))
186 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))]185 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))]
187 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[n]))186 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[n]))
188 0x20, 0x02, 0x1f, 0xd6 // br x17187 0x20, 0x02, 0x1f, 0xd6 // br x17
189 };188 };
190 memcpy(Buf, Inst, sizeof(Inst));189 memcpy(buf, inst, sizeof(inst));
191190
192 relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21,191 relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21,
193 getAArch64Page(GotPltEntryAddr) - getAArch64Page(PltEntryAddr));192 getAArch64Page(gotPltEntryAddr) - getAArch64Page(pltEntryAddr));
194 relocateOne(Buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, GotPltEntryAddr);193 relocateOne(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr);
195 relocateOne(Buf + 8, R_AARCH64_ADD_ABS_LO12_NC, GotPltEntryAddr);194 relocateOne(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr);
196}195}
197196
198bool AArch64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,197bool AArch64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
199 uint64_t BranchAddr, const Symbol &S) const {198 uint64_t branchAddr, const Symbol &s) const {
200 // ELF for the ARM 64-bit architecture, section Call and Jump relocations199 // ELF for the ARM 64-bit architecture, section Call and Jump relocations
201 // only permits range extension thunks for R_AARCH64_CALL26 and200 // only permits range extension thunks for R_AARCH64_CALL26 and
202 // R_AARCH64_JUMP26 relocation types.201 // R_AARCH64_JUMP26 relocation types.
203 if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26)202 if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26)
204 return false;203 return false;
205 uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA();204 uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA() : s.getVA();
206 return !inBranchRange(Type, BranchAddr, Dst);205 return !inBranchRange(type, branchAddr, dst);
207}206}
208207
209uint32_t AArch64::getThunkSectionSpacing() const {208uint32_t AArch64::getThunkSectionSpacing() const {
...@@ -213,71 +212,72 @@ uint32_t AArch64::getThunkSectionSpacing() const {...@@ -213,71 +212,72 @@ uint32_t AArch64::getThunkSectionSpacing() const {
213 return (128 * 1024 * 1024) - 0x30000;212 return (128 * 1024 * 1024) - 0x30000;
214}213}
215214
216bool AArch64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const {215bool AArch64::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
217 if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26)216 if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26)
218 return true;217 return true;
219 // The AArch64 call and unconditional branch instructions have a range of218 // The AArch64 call and unconditional branch instructions have a range of
220 // +/- 128 MiB.219 // +/- 128 MiB.
221 uint64_t Range = 128 * 1024 * 1024;220 uint64_t range = 128 * 1024 * 1024;
222 if (Dst > Src) {221 if (dst > src) {
223 // Immediate of branch is signed.222 // Immediate of branch is signed.
224 Range -= 4;223 range -= 4;
225 return Dst - Src <= Range;224 return dst - src <= range;
226 }225 }
227 return Src - Dst <= Range;226 return src - dst <= range;
228}227}
229228
230static void write32AArch64Addr(uint8_t *L, uint64_t Imm) {229static void write32AArch64Addr(uint8_t *l, uint64_t imm) {
231 uint32_t ImmLo = (Imm & 0x3) << 29;230 uint32_t immLo = (imm & 0x3) << 29;
232 uint32_t ImmHi = (Imm & 0x1FFFFC) << 3;231 uint32_t immHi = (imm & 0x1FFFFC) << 3;
233 uint64_t Mask = (0x3 << 29) | (0x1FFFFC << 3);232 uint64_t mask = (0x3 << 29) | (0x1FFFFC << 3);
234 write32le(L, (read32le(L) & ~Mask) | ImmLo | ImmHi);233 write32le(l, (read32le(l) & ~mask) | immLo | immHi);
235}234}
236235
237// Return the bits [Start, End] from Val shifted Start bits.236// Return the bits [Start, End] from Val shifted Start bits.
238// For instance, getBits(0xF0, 4, 8) returns 0xF.237// For instance, getBits(0xF0, 4, 8) returns 0xF.
239static uint64_t getBits(uint64_t Val, int Start, int End) {238static uint64_t getBits(uint64_t val, int start, int end) {
240 uint64_t Mask = ((uint64_t)1 << (End + 1 - Start)) - 1;239 uint64_t mask = ((uint64_t)1 << (end + 1 - start)) - 1;
241 return (Val >> Start) & Mask;240 return (val >> start) & mask;
242}241}
243242
244static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }243static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); }
245244
246// Update the immediate field in a AARCH64 ldr, str, and add instruction.245// Update the immediate field in a AARCH64 ldr, str, and add instruction.
247static void or32AArch64Imm(uint8_t *L, uint64_t Imm) {246static void or32AArch64Imm(uint8_t *l, uint64_t imm) {
248 or32le(L, (Imm & 0xFFF) << 10);247 or32le(l, (imm & 0xFFF) << 10);
249}248}
250249
251void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {250void AArch64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
252 switch (Type) {251 switch (type) {
253 case R_AARCH64_ABS16:252 case R_AARCH64_ABS16:
254 case R_AARCH64_PREL16:253 case R_AARCH64_PREL16:
255 checkIntUInt(Loc, Val, 16, Type);254 checkIntUInt(loc, val, 16, type);
256 write16le(Loc, Val);255 write16le(loc, val);
257 break;256 break;
258 case R_AARCH64_ABS32:257 case R_AARCH64_ABS32:
259 case R_AARCH64_PREL32:258 case R_AARCH64_PREL32:
260 checkIntUInt(Loc, Val, 32, Type);259 checkIntUInt(loc, val, 32, type);
261 write32le(Loc, Val);260 write32le(loc, val);
262 break;261 break;
263 case R_AARCH64_ABS64:262 case R_AARCH64_ABS64:
264 case R_AARCH64_GLOB_DAT:
265 case R_AARCH64_PREL64:263 case R_AARCH64_PREL64:
266 write64le(Loc, Val);264 write64le(loc, val);
267 break;265 break;
268 case R_AARCH64_ADD_ABS_LO12_NC:266 case R_AARCH64_ADD_ABS_LO12_NC:
269 or32AArch64Imm(Loc, Val);267 or32AArch64Imm(loc, val);
270 break;268 break;
271 case R_AARCH64_ADR_GOT_PAGE:269 case R_AARCH64_ADR_GOT_PAGE:
272 case R_AARCH64_ADR_PREL_PG_HI21:270 case R_AARCH64_ADR_PREL_PG_HI21:
273 case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:271 case R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21:
274 case R_AARCH64_TLSDESC_ADR_PAGE21:272 case R_AARCH64_TLSDESC_ADR_PAGE21:
275 checkInt(Loc, Val, 33, Type);273 checkInt(loc, val, 33, type);
276 write32AArch64Addr(Loc, Val >> 12);274 LLVM_FALLTHROUGH;
275 case R_AARCH64_ADR_PREL_PG_HI21_NC:
276 write32AArch64Addr(loc, val >> 12);
277 break;277 break;
278 case R_AARCH64_ADR_PREL_LO21:278 case R_AARCH64_ADR_PREL_LO21:
279 checkInt(Loc, Val, 21, Type);279 checkInt(loc, val, 21, type);
280 write32AArch64Addr(Loc, Val);280 write32AArch64Addr(loc, val);
281 break;281 break;
282 case R_AARCH64_JUMP26:282 case R_AARCH64_JUMP26:
283 // Normally we would just write the bits of the immediate field, however283 // Normally we would just write the bits of the immediate field, however
...@@ -287,75 +287,75 @@ void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -287,75 +287,75 @@ void AArch64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
287 // opcode and the immediate (0 001 | 01 imm26) we can do this287 // opcode and the immediate (0 001 | 01 imm26) we can do this
288 // transformation by placing a R_AARCH64_JUMP26 relocation at the offset of288 // transformation by placing a R_AARCH64_JUMP26 relocation at the offset of
289 // the instruction we want to patch.289 // the instruction we want to patch.
290 write32le(Loc, 0x14000000);290 write32le(loc, 0x14000000);
291 LLVM_FALLTHROUGH;291 LLVM_FALLTHROUGH;
292 case R_AARCH64_CALL26:292 case R_AARCH64_CALL26:
293 checkInt(Loc, Val, 28, Type);293 checkInt(loc, val, 28, type);
294 or32le(Loc, (Val & 0x0FFFFFFC) >> 2);294 or32le(loc, (val & 0x0FFFFFFC) >> 2);
295 break;295 break;
296 case R_AARCH64_CONDBR19:296 case R_AARCH64_CONDBR19:
297 case R_AARCH64_LD_PREL_LO19:297 case R_AARCH64_LD_PREL_LO19:
298 checkAlignment(Loc, Val, 4, Type);298 checkAlignment(loc, val, 4, type);
299 checkInt(Loc, Val, 21, Type);299 checkInt(loc, val, 21, type);
300 or32le(Loc, (Val & 0x1FFFFC) << 3);300 or32le(loc, (val & 0x1FFFFC) << 3);
301 break;301 break;
302 case R_AARCH64_LDST8_ABS_LO12_NC:302 case R_AARCH64_LDST8_ABS_LO12_NC:
303 case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:303 case R_AARCH64_TLSLE_LDST8_TPREL_LO12_NC:
304 or32AArch64Imm(Loc, getBits(Val, 0, 11));304 or32AArch64Imm(loc, getBits(val, 0, 11));
305 break;305 break;
306 case R_AARCH64_LDST16_ABS_LO12_NC:306 case R_AARCH64_LDST16_ABS_LO12_NC:
307 case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:307 case R_AARCH64_TLSLE_LDST16_TPREL_LO12_NC:
308 checkAlignment(Loc, Val, 2, Type);308 checkAlignment(loc, val, 2, type);
309 or32AArch64Imm(Loc, getBits(Val, 1, 11));309 or32AArch64Imm(loc, getBits(val, 1, 11));
310 break;310 break;
311 case R_AARCH64_LDST32_ABS_LO12_NC:311 case R_AARCH64_LDST32_ABS_LO12_NC:
312 case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:312 case R_AARCH64_TLSLE_LDST32_TPREL_LO12_NC:
313 checkAlignment(Loc, Val, 4, Type);313 checkAlignment(loc, val, 4, type);
314 or32AArch64Imm(Loc, getBits(Val, 2, 11));314 or32AArch64Imm(loc, getBits(val, 2, 11));
315 break;315 break;
316 case R_AARCH64_LDST64_ABS_LO12_NC:316 case R_AARCH64_LDST64_ABS_LO12_NC:
317 case R_AARCH64_LD64_GOT_LO12_NC:317 case R_AARCH64_LD64_GOT_LO12_NC:
318 case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:318 case R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC:
319 case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:319 case R_AARCH64_TLSLE_LDST64_TPREL_LO12_NC:
320 case R_AARCH64_TLSDESC_LD64_LO12:320 case R_AARCH64_TLSDESC_LD64_LO12:
321 checkAlignment(Loc, Val, 8, Type);321 checkAlignment(loc, val, 8, type);
322 or32AArch64Imm(Loc, getBits(Val, 3, 11));322 or32AArch64Imm(loc, getBits(val, 3, 11));
323 break;323 break;
324 case R_AARCH64_LDST128_ABS_LO12_NC:324 case R_AARCH64_LDST128_ABS_LO12_NC:
325 case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC:325 case R_AARCH64_TLSLE_LDST128_TPREL_LO12_NC:
326 checkAlignment(Loc, Val, 16, Type);326 checkAlignment(loc, val, 16, type);
327 or32AArch64Imm(Loc, getBits(Val, 4, 11));327 or32AArch64Imm(loc, getBits(val, 4, 11));
328 break;328 break;
329 case R_AARCH64_MOVW_UABS_G0_NC:329 case R_AARCH64_MOVW_UABS_G0_NC:
330 or32le(Loc, (Val & 0xFFFF) << 5);330 or32le(loc, (val & 0xFFFF) << 5);
331 break;331 break;
332 case R_AARCH64_MOVW_UABS_G1_NC:332 case R_AARCH64_MOVW_UABS_G1_NC:
333 or32le(Loc, (Val & 0xFFFF0000) >> 11);333 or32le(loc, (val & 0xFFFF0000) >> 11);
334 break;334 break;
335 case R_AARCH64_MOVW_UABS_G2_NC:335 case R_AARCH64_MOVW_UABS_G2_NC:
336 or32le(Loc, (Val & 0xFFFF00000000) >> 27);336 or32le(loc, (val & 0xFFFF00000000) >> 27);
337 break;337 break;
338 case R_AARCH64_MOVW_UABS_G3:338 case R_AARCH64_MOVW_UABS_G3:
339 or32le(Loc, (Val & 0xFFFF000000000000) >> 43);339 or32le(loc, (val & 0xFFFF000000000000) >> 43);
340 break;340 break;
341 case R_AARCH64_TSTBR14:341 case R_AARCH64_TSTBR14:
342 checkInt(Loc, Val, 16, Type);342 checkInt(loc, val, 16, type);
343 or32le(Loc, (Val & 0xFFFC) << 3);343 or32le(loc, (val & 0xFFFC) << 3);
344 break;344 break;
345 case R_AARCH64_TLSLE_ADD_TPREL_HI12:345 case R_AARCH64_TLSLE_ADD_TPREL_HI12:
346 checkUInt(Loc, Val, 24, Type);346 checkUInt(loc, val, 24, type);
347 or32AArch64Imm(Loc, Val >> 12);347 or32AArch64Imm(loc, val >> 12);
348 break;348 break;
349 case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:349 case R_AARCH64_TLSLE_ADD_TPREL_LO12_NC:
350 case R_AARCH64_TLSDESC_ADD_LO12:350 case R_AARCH64_TLSDESC_ADD_LO12:
351 or32AArch64Imm(Loc, Val);351 or32AArch64Imm(loc, val);
352 break;352 break;
353 default:353 default:
354 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));354 error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
355 }355 }
356}356}
357357
358void AArch64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {358void AArch64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
359 // TLSDESC Global-Dynamic relocation are in the form:359 // TLSDESC Global-Dynamic relocation are in the form:
360 // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]360 // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]
361 // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12]361 // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12]
...@@ -367,25 +367,25 @@ void AArch64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -367,25 +367,25 @@ void AArch64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
367 // movk x0, #0x10367 // movk x0, #0x10
368 // nop368 // nop
369 // nop369 // nop
370 checkUInt(Loc, Val, 32, Type);370 checkUInt(loc, val, 32, type);
371371
372 switch (Type) {372 switch (type) {
373 case R_AARCH64_TLSDESC_ADD_LO12:373 case R_AARCH64_TLSDESC_ADD_LO12:
374 case R_AARCH64_TLSDESC_CALL:374 case R_AARCH64_TLSDESC_CALL:
375 write32le(Loc, 0xd503201f); // nop375 write32le(loc, 0xd503201f); // nop
376 return;376 return;
377 case R_AARCH64_TLSDESC_ADR_PAGE21:377 case R_AARCH64_TLSDESC_ADR_PAGE21:
378 write32le(Loc, 0xd2a00000 | (((Val >> 16) & 0xffff) << 5)); // movz378 write32le(loc, 0xd2a00000 | (((val >> 16) & 0xffff) << 5)); // movz
379 return;379 return;
380 case R_AARCH64_TLSDESC_LD64_LO12:380 case R_AARCH64_TLSDESC_LD64_LO12:
381 write32le(Loc, 0xf2800000 | ((Val & 0xffff) << 5)); // movk381 write32le(loc, 0xf2800000 | ((val & 0xffff) << 5)); // movk
382 return;382 return;
383 default:383 default:
384 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");384 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
385 }385 }
386}386}
387387
388void AArch64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {388void AArch64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
389 // TLSDESC Global-Dynamic relocation are in the form:389 // TLSDESC Global-Dynamic relocation are in the form:
390 // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]390 // adrp x0, :tlsdesc:v [R_AARCH64_TLSDESC_ADR_PAGE21]
391 // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12]391 // ldr x1, [x0, #:tlsdesc_lo12:v [R_AARCH64_TLSDESC_LD64_LO12]
...@@ -398,43 +398,193 @@ void AArch64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -398,43 +398,193 @@ void AArch64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {
398 // nop398 // nop
399 // nop399 // nop
400400
401 switch (Type) {401 switch (type) {
402 case R_AARCH64_TLSDESC_ADD_LO12:402 case R_AARCH64_TLSDESC_ADD_LO12:
403 case R_AARCH64_TLSDESC_CALL:403 case R_AARCH64_TLSDESC_CALL:
404 write32le(Loc, 0xd503201f); // nop404 write32le(loc, 0xd503201f); // nop
405 break;405 break;
406 case R_AARCH64_TLSDESC_ADR_PAGE21:406 case R_AARCH64_TLSDESC_ADR_PAGE21:
407 write32le(Loc, 0x90000000); // adrp407 write32le(loc, 0x90000000); // adrp
408 relocateOne(Loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, Val);408 relocateOne(loc, R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21, val);
409 break;409 break;
410 case R_AARCH64_TLSDESC_LD64_LO12:410 case R_AARCH64_TLSDESC_LD64_LO12:
411 write32le(Loc, 0xf9400000); // ldr411 write32le(loc, 0xf9400000); // ldr
412 relocateOne(Loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, Val);412 relocateOne(loc, R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC, val);
413 break;413 break;
414 default:414 default:
415 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");415 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
416 }416 }
417}417}
418418
419void AArch64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {419void AArch64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
420 checkUInt(Loc, Val, 32, Type);420 checkUInt(loc, val, 32, type);
421421
422 if (Type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {422 if (type == R_AARCH64_TLSIE_ADR_GOTTPREL_PAGE21) {
423 // Generate MOVZ.423 // Generate MOVZ.
424 uint32_t RegNo = read32le(Loc) & 0x1f;424 uint32_t regNo = read32le(loc) & 0x1f;
425 write32le(Loc, (0xd2a00000 | RegNo) | (((Val >> 16) & 0xffff) << 5));425 write32le(loc, (0xd2a00000 | regNo) | (((val >> 16) & 0xffff) << 5));
426 return;426 return;
427 }427 }
428 if (Type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) {428 if (type == R_AARCH64_TLSIE_LD64_GOTTPREL_LO12_NC) {
429 // Generate MOVK.429 // Generate MOVK.
430 uint32_t RegNo = read32le(Loc) & 0x1f;430 uint32_t regNo = read32le(loc) & 0x1f;
431 write32le(Loc, (0xf2800000 | RegNo) | ((Val & 0xffff) << 5));431 write32le(loc, (0xf2800000 | regNo) | ((val & 0xffff) << 5));
432 return;432 return;
433 }433 }
434 llvm_unreachable("invalid relocation for TLS IE to LE relaxation");434 llvm_unreachable("invalid relocation for TLS IE to LE relaxation");
435}435}
436436
437TargetInfo *elf::getAArch64TargetInfo() {437// AArch64 may use security features in variant PLT sequences. These are:
438 static AArch64 Target;438// Pointer Authentication (PAC), introduced in armv8.3-a and Branch Target
439 return &Target;439// Indicator (BTI) introduced in armv8.5-a. The additional instructions used
440// in the variant Plt sequences are encoded in the Hint space so they can be
441// deployed on older architectures, which treat the instructions as a nop.
442// PAC and BTI can be combined leading to the following combinations:
443// writePltHeader
444// writePltHeaderBti (no PAC Header needed)
445// writePlt
446// writePltBti (BTI only)
447// writePltPac (PAC only)
448// writePltBtiPac (BTI and PAC)
449//
450// When PAC is enabled the dynamic loader encrypts the address that it places
451// in the .got.plt using the pacia1716 instruction which encrypts the value in
452// x17 using the modifier in x16. The static linker places autia1716 before the
453// indirect branch to x17 to authenticate the address in x17 with the modifier
454// in x16. This makes it more difficult for an attacker to modify the value in
455// the .got.plt.
456//
457// When BTI is enabled all indirect branches must land on a bti instruction.
458// The static linker must place a bti instruction at the start of any PLT entry
459// that may be the target of an indirect branch. As the PLT entries call the
460// lazy resolver indirectly this must have a bti instruction at start. In
461// general a bti instruction is not needed for a PLT entry as indirect calls
462// are resolved to the function address and not the PLT entry for the function.
463// There are a small number of cases where the PLT address can escape, such as
464// taking the address of a function or ifunc via a non got-generating
465// relocation, and a shared library refers to that symbol.
466//
467// We use the bti c variant of the instruction which permits indirect branches
468// (br) via x16/x17 and indirect function calls (blr) via any register. The ABI
469// guarantees that all indirect branches from code requiring BTI protection
470// will go via x16/x17
471
472namespace {
473class AArch64BtiPac final : public AArch64 {
474public:
475 AArch64BtiPac();
476 void writePltHeader(uint8_t *buf) const override;
477 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
478 int32_t index, unsigned relOff) const override;
479
480private:
481 bool btiHeader; // bti instruction needed in PLT Header
482 bool btiEntry; // bti instruction needed in PLT Entry
483 bool pacEntry; // autia1716 instruction needed in PLT Entry
484};
485} // namespace
486
487AArch64BtiPac::AArch64BtiPac() {
488 btiHeader = (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI);
489 // A BTI (Branch Target Indicator) Plt Entry is only required if the
490 // address of the PLT entry can be taken by the program, which permits an
491 // indirect jump to the PLT entry. This can happen when the address
492 // of the PLT entry for a function is canonicalised due to the address of
493 // the function in an executable being taken by a shared library.
494 // FIXME: There is a potential optimization to omit the BTI if we detect
495 // that the address of the PLT entry isn't taken.
496 btiEntry = btiHeader && !config->shared;
497 pacEntry = (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC);
498
499 if (btiEntry || pacEntry)
500 pltEntrySize = 24;
440}501}
502
503void AArch64BtiPac::writePltHeader(uint8_t *buf) const {
504 const uint8_t btiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c
505 const uint8_t pltData[] = {
506 0xf0, 0x7b, 0xbf, 0xa9, // stp x16, x30, [sp,#-16]!
507 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[2]))
508 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[2]))]
509 0x10, 0x02, 0x00, 0x91, // add x16, x16, Offset(&(.plt.got[2]))
510 0x20, 0x02, 0x1f, 0xd6, // br x17
511 0x1f, 0x20, 0x03, 0xd5, // nop
512 0x1f, 0x20, 0x03, 0xd5 // nop
513 };
514 const uint8_t nopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop
515
516 uint64_t got = in.gotPlt->getVA();
517 uint64_t plt = in.plt->getVA();
518
519 if (btiHeader) {
520 // PltHeader is called indirectly by plt[N]. Prefix pltData with a BTI C
521 // instruction.
522 memcpy(buf, btiData, sizeof(btiData));
523 buf += sizeof(btiData);
524 plt += sizeof(btiData);
525 }
526 memcpy(buf, pltData, sizeof(pltData));
527
528 relocateOne(buf + 4, R_AARCH64_ADR_PREL_PG_HI21,
529 getAArch64Page(got + 16) - getAArch64Page(plt + 8));
530 relocateOne(buf + 8, R_AARCH64_LDST64_ABS_LO12_NC, got + 16);
531 relocateOne(buf + 12, R_AARCH64_ADD_ABS_LO12_NC, got + 16);
532 if (!btiHeader)
533 // We didn't add the BTI c instruction so round out size with NOP.
534 memcpy(buf + sizeof(pltData), nopData, sizeof(nopData));
535}
536
537void AArch64BtiPac::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
538 uint64_t pltEntryAddr, int32_t index,
539 unsigned relOff) const {
540 // The PLT entry is of the form:
541 // [btiData] addrInst (pacBr | stdBr) [nopData]
542 const uint8_t btiData[] = { 0x5f, 0x24, 0x03, 0xd5 }; // bti c
543 const uint8_t addrInst[] = {
544 0x10, 0x00, 0x00, 0x90, // adrp x16, Page(&(.plt.got[n]))
545 0x11, 0x02, 0x40, 0xf9, // ldr x17, [x16, Offset(&(.plt.got[n]))]
546 0x10, 0x02, 0x00, 0x91 // add x16, x16, Offset(&(.plt.got[n]))
547 };
548 const uint8_t pacBr[] = {
549 0x9f, 0x21, 0x03, 0xd5, // autia1716
550 0x20, 0x02, 0x1f, 0xd6 // br x17
551 };
552 const uint8_t stdBr[] = {
553 0x20, 0x02, 0x1f, 0xd6, // br x17
554 0x1f, 0x20, 0x03, 0xd5 // nop
555 };
556 const uint8_t nopData[] = { 0x1f, 0x20, 0x03, 0xd5 }; // nop
557
558 if (btiEntry) {
559 memcpy(buf, btiData, sizeof(btiData));
560 buf += sizeof(btiData);
561 pltEntryAddr += sizeof(btiData);
562 }
563
564 memcpy(buf, addrInst, sizeof(addrInst));
565 relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21,
566 getAArch64Page(gotPltEntryAddr) -
567 getAArch64Page(pltEntryAddr));
568 relocateOne(buf + 4, R_AARCH64_LDST64_ABS_LO12_NC, gotPltEntryAddr);
569 relocateOne(buf + 8, R_AARCH64_ADD_ABS_LO12_NC, gotPltEntryAddr);
570
571 if (pacEntry)
572 memcpy(buf + sizeof(addrInst), pacBr, sizeof(pacBr));
573 else
574 memcpy(buf + sizeof(addrInst), stdBr, sizeof(stdBr));
575 if (!btiEntry)
576 // We didn't add the BTI c instruction so round out size with NOP.
577 memcpy(buf + sizeof(addrInst) + sizeof(stdBr), nopData, sizeof(nopData));
578}
579
580static TargetInfo *getTargetInfo() {
581 if (config->andFeatures & (GNU_PROPERTY_AARCH64_FEATURE_1_BTI |
582 GNU_PROPERTY_AARCH64_FEATURE_1_PAC)) {
583 static AArch64BtiPac t;
584 return &t;
585 }
586 static AArch64 t;
587 return &t;
588}
589
590TargetInfo *elf::getAArch64TargetInfo() { return getTargetInfo(); }
deps/lld/ELF/Arch/AMDGPU.cpp+39-31
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- AMDGPU.cpp ---------------------------------------------------------===//1//===- AMDGPU.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -26,62 +25,63 @@ class AMDGPU final : public TargetInfo {...@@ -26,62 +25,63 @@ class AMDGPU final : public TargetInfo {
26public:25public:
27 AMDGPU();26 AMDGPU();
28 uint32_t calcEFlags() const override;27 uint32_t calcEFlags() const override;
29 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;28 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
30 RelExpr getRelExpr(RelType Type, const Symbol &S,29 RelExpr getRelExpr(RelType type, const Symbol &s,
31 const uint8_t *Loc) const override;30 const uint8_t *loc) const override;
31 RelType getDynRel(RelType type) const override;
32};32};
33} // namespace33} // namespace
3434
35AMDGPU::AMDGPU() {35AMDGPU::AMDGPU() {
36 RelativeRel = R_AMDGPU_RELATIVE64;36 relativeRel = R_AMDGPU_RELATIVE64;
37 GotRel = R_AMDGPU_ABS64;37 gotRel = R_AMDGPU_ABS64;
38 NoneRel = R_AMDGPU_NONE;38 noneRel = R_AMDGPU_NONE;
39 GotEntrySize = 8;39 symbolicRel = R_AMDGPU_ABS64;
40}40}
4141
42static uint32_t getEFlags(InputFile *File) {42static uint32_t getEFlags(InputFile *file) {
43 return cast<ObjFile<ELF64LE>>(File)->getObj().getHeader()->e_flags;43 return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader()->e_flags;
44}44}
4545
46uint32_t AMDGPU::calcEFlags() const {46uint32_t AMDGPU::calcEFlags() const {
47 assert(!ObjectFiles.empty());47 assert(!objectFiles.empty());
48 uint32_t Ret = getEFlags(ObjectFiles[0]);48 uint32_t ret = getEFlags(objectFiles[0]);
4949
50 // Verify that all input files have the same e_flags.50 // Verify that all input files have the same e_flags.
51 for (InputFile *F : makeArrayRef(ObjectFiles).slice(1)) {51 for (InputFile *f : makeArrayRef(objectFiles).slice(1)) {
52 if (Ret == getEFlags(F))52 if (ret == getEFlags(f))
53 continue;53 continue;
54 error("incompatible e_flags: " + toString(F));54 error("incompatible e_flags: " + toString(f));
55 return 0;55 return 0;
56 }56 }
57 return Ret;57 return ret;
58}58}
5959
60void AMDGPU::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {60void AMDGPU::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
61 switch (Type) {61 switch (type) {
62 case R_AMDGPU_ABS32:62 case R_AMDGPU_ABS32:
63 case R_AMDGPU_GOTPCREL:63 case R_AMDGPU_GOTPCREL:
64 case R_AMDGPU_GOTPCREL32_LO:64 case R_AMDGPU_GOTPCREL32_LO:
65 case R_AMDGPU_REL32:65 case R_AMDGPU_REL32:
66 case R_AMDGPU_REL32_LO:66 case R_AMDGPU_REL32_LO:
67 write32le(Loc, Val);67 write32le(loc, val);
68 break;68 break;
69 case R_AMDGPU_ABS64:69 case R_AMDGPU_ABS64:
70 case R_AMDGPU_REL64:70 case R_AMDGPU_REL64:
71 write64le(Loc, Val);71 write64le(loc, val);
72 break;72 break;
73 case R_AMDGPU_GOTPCREL32_HI:73 case R_AMDGPU_GOTPCREL32_HI:
74 case R_AMDGPU_REL32_HI:74 case R_AMDGPU_REL32_HI:
75 write32le(Loc, Val >> 32);75 write32le(loc, val >> 32);
76 break;76 break;
77 default:77 default:
78 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));78 llvm_unreachable("unknown relocation");
79 }79 }
80}80}
8181
82RelExpr AMDGPU::getRelExpr(RelType Type, const Symbol &S,82RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s,
83 const uint8_t *Loc) const {83 const uint8_t *loc) const {
84 switch (Type) {84 switch (type) {
85 case R_AMDGPU_ABS32:85 case R_AMDGPU_ABS32:
86 case R_AMDGPU_ABS64:86 case R_AMDGPU_ABS64:
87 return R_ABS;87 return R_ABS;
...@@ -95,11 +95,19 @@ RelExpr AMDGPU::getRelExpr(RelType Type, const Symbol &S,...@@ -95,11 +95,19 @@ RelExpr AMDGPU::getRelExpr(RelType Type, const Symbol &S,
95 case R_AMDGPU_GOTPCREL32_HI:95 case R_AMDGPU_GOTPCREL32_HI:
96 return R_GOT_PC;96 return R_GOT_PC;
97 default:97 default:
98 return R_INVALID;98 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
99 ") against symbol " + toString(s));
100 return R_NONE;
99 }101 }
100}102}
101103
104RelType AMDGPU::getDynRel(RelType type) const {
105 if (type == R_AMDGPU_ABS64)
106 return type;
107 return R_AMDGPU_NONE;
108}
109
102TargetInfo *elf::getAMDGPUTargetInfo() {110TargetInfo *elf::getAMDGPUTargetInfo() {
103 static AMDGPU Target;111 static AMDGPU target;
104 return &Target;112 return &target;
105}113}
deps/lld/ELF/Arch/ARM.cpp+228-234
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ARM.cpp ------------------------------------------------------------===//1//===- ARM.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -27,63 +26,62 @@ class ARM final : public TargetInfo {...@@ -27,63 +26,62 @@ class ARM final : public TargetInfo {
27public:26public:
28 ARM();27 ARM();
29 uint32_t calcEFlags() const override;28 uint32_t calcEFlags() const override;
30 RelExpr getRelExpr(RelType Type, const Symbol &S,29 RelExpr getRelExpr(RelType type, const Symbol &s,
31 const uint8_t *Loc) const override;30 const uint8_t *loc) const override;
32 RelType getDynRel(RelType Type) const override;31 RelType getDynRel(RelType type) const override;
33 int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override;32 int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
34 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;33 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
35 void writeIgotPlt(uint8_t *Buf, const Symbol &S) const override;34 void writeIgotPlt(uint8_t *buf, const Symbol &s) const override;
36 void writePltHeader(uint8_t *Buf) const override;35 void writePltHeader(uint8_t *buf) const override;
37 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,36 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
38 int32_t Index, unsigned RelOff) const override;37 int32_t index, unsigned relOff) const override;
39 void addPltSymbols(InputSection &IS, uint64_t Off) const override;38 void addPltSymbols(InputSection &isec, uint64_t off) const override;
40 void addPltHeaderSymbols(InputSection &ISD) const override;39 void addPltHeaderSymbols(InputSection &isd) const override;
41 bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File,40 bool needsThunk(RelExpr expr, RelType type, const InputFile *file,
42 uint64_t BranchAddr, const Symbol &S) const override;41 uint64_t branchAddr, const Symbol &s) const override;
43 uint32_t getThunkSectionSpacing() const override;42 uint32_t getThunkSectionSpacing() const override;
44 bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override;43 bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
45 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;44 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
46};45};
47} // namespace46} // namespace
4847
49ARM::ARM() {48ARM::ARM() {
50 CopyRel = R_ARM_COPY;49 copyRel = R_ARM_COPY;
51 RelativeRel = R_ARM_RELATIVE;50 relativeRel = R_ARM_RELATIVE;
52 IRelativeRel = R_ARM_IRELATIVE;51 iRelativeRel = R_ARM_IRELATIVE;
53 GotRel = R_ARM_GLOB_DAT;52 gotRel = R_ARM_GLOB_DAT;
54 NoneRel = R_ARM_NONE;53 noneRel = R_ARM_NONE;
55 PltRel = R_ARM_JUMP_SLOT;54 pltRel = R_ARM_JUMP_SLOT;
56 TlsGotRel = R_ARM_TLS_TPOFF32;55 symbolicRel = R_ARM_ABS32;
57 TlsModuleIndexRel = R_ARM_TLS_DTPMOD32;56 tlsGotRel = R_ARM_TLS_TPOFF32;
58 TlsOffsetRel = R_ARM_TLS_DTPOFF32;57 tlsModuleIndexRel = R_ARM_TLS_DTPMOD32;
59 GotBaseSymInGotPlt = false;58 tlsOffsetRel = R_ARM_TLS_DTPOFF32;
60 GotEntrySize = 4;59 gotBaseSymInGotPlt = false;
61 GotPltEntrySize = 4;60 pltEntrySize = 16;
62 PltEntrySize = 16;61 pltHeaderSize = 32;
63 PltHeaderSize = 32;62 trapInstr = {0xd4, 0xd4, 0xd4, 0xd4};
64 TrapInstr = {0xd4, 0xd4, 0xd4, 0xd4};63 needsThunks = true;
65 NeedsThunks = true;
66}64}
6765
68uint32_t ARM::calcEFlags() const {66uint32_t ARM::calcEFlags() const {
69 // The ABIFloatType is used by loaders to detect the floating point calling67 // The ABIFloatType is used by loaders to detect the floating point calling
70 // convention.68 // convention.
71 uint32_t ABIFloatType = 0;69 uint32_t abiFloatType = 0;
72 if (Config->ARMVFPArgs == ARMVFPArgKind::Base ||70 if (config->armVFPArgs == ARMVFPArgKind::Base ||
73 Config->ARMVFPArgs == ARMVFPArgKind::Default)71 config->armVFPArgs == ARMVFPArgKind::Default)
74 ABIFloatType = EF_ARM_ABI_FLOAT_SOFT;72 abiFloatType = EF_ARM_ABI_FLOAT_SOFT;
75 else if (Config->ARMVFPArgs == ARMVFPArgKind::VFP)73 else if (config->armVFPArgs == ARMVFPArgKind::VFP)
76 ABIFloatType = EF_ARM_ABI_FLOAT_HARD;74 abiFloatType = EF_ARM_ABI_FLOAT_HARD;
7775
78 // We don't currently use any features incompatible with EF_ARM_EABI_VER5,76 // We don't currently use any features incompatible with EF_ARM_EABI_VER5,
79 // but we don't have any firm guarantees of conformance. Linux AArch6477 // but we don't have any firm guarantees of conformance. Linux AArch64
80 // kernels (as of 2016) require an EABI version to be set.78 // kernels (as of 2016) require an EABI version to be set.
81 return EF_ARM_EABI_VER5 | ABIFloatType;79 return EF_ARM_EABI_VER5 | abiFloatType;
82}80}
8381
84RelExpr ARM::getRelExpr(RelType Type, const Symbol &S,82RelExpr ARM::getRelExpr(RelType type, const Symbol &s,
85 const uint8_t *Loc) const {83 const uint8_t *loc) const {
86 switch (Type) {84 switch (type) {
87 case R_ARM_THM_JUMP11:85 case R_ARM_THM_JUMP11:
88 return R_PC;86 return R_PC;
89 case R_ARM_CALL:87 case R_ARM_CALL:
...@@ -108,11 +106,11 @@ RelExpr ARM::getRelExpr(RelType Type, const Symbol &S,...@@ -108,11 +106,11 @@ RelExpr ARM::getRelExpr(RelType Type, const Symbol &S,
108 case R_ARM_SBREL32:106 case R_ARM_SBREL32:
109 return R_ARM_SBREL;107 return R_ARM_SBREL;
110 case R_ARM_TARGET1:108 case R_ARM_TARGET1:
111 return Config->Target1Rel ? R_PC : R_ABS;109 return config->target1Rel ? R_PC : R_ABS;
112 case R_ARM_TARGET2:110 case R_ARM_TARGET2:
113 if (Config->Target2 == Target2Policy::Rel)111 if (config->target2 == Target2Policy::Rel)
114 return R_PC;112 return R_PC;
115 if (Config->Target2 == Target2Policy::Abs)113 if (config->target2 == Target2Policy::Abs)
116 return R_ABS;114 return R_ABS;
117 return R_GOT_PC;115 return R_GOT_PC;
118 case R_ARM_TLS_GD32:116 case R_ARM_TLS_GD32:
...@@ -145,25 +143,25 @@ RelExpr ARM::getRelExpr(RelType Type, const Symbol &S,...@@ -145,25 +143,25 @@ RelExpr ARM::getRelExpr(RelType Type, const Symbol &S,
145 }143 }
146}144}
147145
148RelType ARM::getDynRel(RelType Type) const {146RelType ARM::getDynRel(RelType type) const {
149 if ((Type == R_ARM_ABS32) || (Type == R_ARM_TARGET1 && !Config->Target1Rel))147 if ((type == R_ARM_ABS32) || (type == R_ARM_TARGET1 && !config->target1Rel))
150 return R_ARM_ABS32;148 return R_ARM_ABS32;
151 return R_ARM_NONE;149 return R_ARM_NONE;
152}150}
153151
154void ARM::writeGotPlt(uint8_t *Buf, const Symbol &) const {152void ARM::writeGotPlt(uint8_t *buf, const Symbol &) const {
155 write32le(Buf, In.Plt->getVA());153 write32le(buf, in.plt->getVA());
156}154}
157155
158void ARM::writeIgotPlt(uint8_t *Buf, const Symbol &S) const {156void ARM::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
159 // An ARM entry is the address of the ifunc resolver function.157 // An ARM entry is the address of the ifunc resolver function.
160 write32le(Buf, S.getVA());158 write32le(buf, s.getVA());
161}159}
162160
163// Long form PLT Header that does not have any restrictions on the displacement161// Long form PLT Header that does not have any restrictions on the displacement
164// of the .plt from the .plt.got.162// of the .plt from the .plt.got.
165static void writePltHeaderLong(uint8_t *Buf) {163static void writePltHeaderLong(uint8_t *buf) {
166 const uint8_t PltData[] = {164 const uint8_t pltData[] = {
167 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]!165 0x04, 0xe0, 0x2d, 0xe5, // str lr, [sp,#-4]!
168 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2166 0x04, 0xe0, 0x9f, 0xe5, // ldr lr, L2
169 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr167 0x0e, 0xe0, 0x8f, 0xe0, // L1: add lr, pc, lr
...@@ -172,128 +170,128 @@ static void writePltHeaderLong(uint8_t *Buf) {...@@ -172,128 +170,128 @@ static void writePltHeaderLong(uint8_t *Buf) {
172 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary170 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary
173 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary171 0xd4, 0xd4, 0xd4, 0xd4, // Pad to 32-byte boundary
174 0xd4, 0xd4, 0xd4, 0xd4};172 0xd4, 0xd4, 0xd4, 0xd4};
175 memcpy(Buf, PltData, sizeof(PltData));173 memcpy(buf, pltData, sizeof(pltData));
176 uint64_t GotPlt = In.GotPlt->getVA();174 uint64_t gotPlt = in.gotPlt->getVA();
177 uint64_t L1 = In.Plt->getVA() + 8;175 uint64_t l1 = in.plt->getVA() + 8;
178 write32le(Buf + 16, GotPlt - L1 - 8);176 write32le(buf + 16, gotPlt - l1 - 8);
179}177}
180178
181// The default PLT header requires the .plt.got to be within 128 Mb of the179// The default PLT header requires the .plt.got to be within 128 Mb of the
182// .plt in the positive direction.180// .plt in the positive direction.
183void ARM::writePltHeader(uint8_t *Buf) const {181void ARM::writePltHeader(uint8_t *buf) const {
184 // Use a similar sequence to that in writePlt(), the difference is the calling182 // Use a similar sequence to that in writePlt(), the difference is the calling
185 // conventions mean we use lr instead of ip. The PLT entry is responsible for183 // conventions mean we use lr instead of ip. The PLT entry is responsible for
186 // saving lr on the stack, the dynamic loader is responsible for reloading184 // saving lr on the stack, the dynamic loader is responsible for reloading
187 // it.185 // it.
188 const uint32_t PltData[] = {186 const uint32_t pltData[] = {
189 0xe52de004, // L1: str lr, [sp,#-4]!187 0xe52de004, // L1: str lr, [sp,#-4]!
190 0xe28fe600, // add lr, pc, #0x0NN00000 &(.got.plt - L1 - 4)188 0xe28fe600, // add lr, pc, #0x0NN00000 &(.got.plt - L1 - 4)
191 0xe28eea00, // add lr, lr, #0x000NN000 &(.got.plt - L1 - 4)189 0xe28eea00, // add lr, lr, #0x000NN000 &(.got.plt - L1 - 4)
192 0xe5bef000, // ldr pc, [lr, #0x00000NNN] &(.got.plt -L1 - 4)190 0xe5bef000, // ldr pc, [lr, #0x00000NNN] &(.got.plt -L1 - 4)
193 };191 };
194192
195 uint64_t Offset = In.GotPlt->getVA() - In.Plt->getVA() - 4;193 uint64_t offset = in.gotPlt->getVA() - in.plt->getVA() - 4;
196 if (!llvm::isUInt<27>(Offset)) {194 if (!llvm::isUInt<27>(offset)) {
197 // We cannot encode the Offset, use the long form.195 // We cannot encode the Offset, use the long form.
198 writePltHeaderLong(Buf);196 writePltHeaderLong(buf);
199 return;197 return;
200 }198 }
201 write32le(Buf + 0, PltData[0]);199 write32le(buf + 0, pltData[0]);
202 write32le(Buf + 4, PltData[1] | ((Offset >> 20) & 0xff));200 write32le(buf + 4, pltData[1] | ((offset >> 20) & 0xff));
203 write32le(Buf + 8, PltData[2] | ((Offset >> 12) & 0xff));201 write32le(buf + 8, pltData[2] | ((offset >> 12) & 0xff));
204 write32le(Buf + 12, PltData[3] | (Offset & 0xfff));202 write32le(buf + 12, pltData[3] | (offset & 0xfff));
205 memcpy(Buf + 16, TrapInstr.data(), 4); // Pad to 32-byte boundary203 memcpy(buf + 16, trapInstr.data(), 4); // Pad to 32-byte boundary
206 memcpy(Buf + 20, TrapInstr.data(), 4);204 memcpy(buf + 20, trapInstr.data(), 4);
207 memcpy(Buf + 24, TrapInstr.data(), 4);205 memcpy(buf + 24, trapInstr.data(), 4);
208 memcpy(Buf + 28, TrapInstr.data(), 4);206 memcpy(buf + 28, trapInstr.data(), 4);
209}207}
210208
211void ARM::addPltHeaderSymbols(InputSection &IS) const {209void ARM::addPltHeaderSymbols(InputSection &isec) const {
212 addSyntheticLocal("$a", STT_NOTYPE, 0, 0, IS);210 addSyntheticLocal("$a", STT_NOTYPE, 0, 0, isec);
213 addSyntheticLocal("$d", STT_NOTYPE, 16, 0, IS);211 addSyntheticLocal("$d", STT_NOTYPE, 16, 0, isec);
214}212}
215213
216// Long form PLT entries that do not have any restrictions on the displacement214// Long form PLT entries that do not have any restrictions on the displacement
217// of the .plt from the .plt.got.215// of the .plt from the .plt.got.
218static void writePltLong(uint8_t *Buf, uint64_t GotPltEntryAddr,216static void writePltLong(uint8_t *buf, uint64_t gotPltEntryAddr,
219 uint64_t PltEntryAddr, int32_t Index,217 uint64_t pltEntryAddr, int32_t index,
220 unsigned RelOff) {218 unsigned relOff) {
221 const uint8_t PltData[] = {219 const uint8_t pltData[] = {
222 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2220 0x04, 0xc0, 0x9f, 0xe5, // ldr ip, L2
223 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc221 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
224 0x00, 0xf0, 0x9c, 0xe5, // ldr pc, [ip]222 0x00, 0xf0, 0x9c, 0xe5, // ldr pc, [ip]
225 0x00, 0x00, 0x00, 0x00, // L2: .word Offset(&(.plt.got) - L1 - 8223 0x00, 0x00, 0x00, 0x00, // L2: .word Offset(&(.plt.got) - L1 - 8
226 };224 };
227 memcpy(Buf, PltData, sizeof(PltData));225 memcpy(buf, pltData, sizeof(pltData));
228 uint64_t L1 = PltEntryAddr + 4;226 uint64_t l1 = pltEntryAddr + 4;
229 write32le(Buf + 12, GotPltEntryAddr - L1 - 8);227 write32le(buf + 12, gotPltEntryAddr - l1 - 8);
230}228}
231229
232// The default PLT entries require the .plt.got to be within 128 Mb of the230// The default PLT entries require the .plt.got to be within 128 Mb of the
233// .plt in the positive direction.231// .plt in the positive direction.
234void ARM::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,232void ARM::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
235 uint64_t PltEntryAddr, int32_t Index,233 uint64_t pltEntryAddr, int32_t index,
236 unsigned RelOff) const {234 unsigned relOff) const {
237 // The PLT entry is similar to the example given in Appendix A of ELF for235 // The PLT entry is similar to the example given in Appendix A of ELF for
238 // the Arm Architecture. Instead of using the Group Relocations to find the236 // the Arm Architecture. Instead of using the Group Relocations to find the
239 // optimal rotation for the 8-bit immediate used in the add instructions we237 // optimal rotation for the 8-bit immediate used in the add instructions we
240 // hard code the most compact rotations for simplicity. This saves a load238 // hard code the most compact rotations for simplicity. This saves a load
241 // instruction over the long plt sequences.239 // instruction over the long plt sequences.
242 const uint32_t PltData[] = {240 const uint32_t pltData[] = {
243 0xe28fc600, // L1: add ip, pc, #0x0NN00000 Offset(&(.plt.got) - L1 - 8241 0xe28fc600, // L1: add ip, pc, #0x0NN00000 Offset(&(.plt.got) - L1 - 8
244 0xe28cca00, // add ip, ip, #0x000NN000 Offset(&(.plt.got) - L1 - 8242 0xe28cca00, // add ip, ip, #0x000NN000 Offset(&(.plt.got) - L1 - 8
245 0xe5bcf000, // ldr pc, [ip, #0x00000NNN] Offset(&(.plt.got) - L1 - 8243 0xe5bcf000, // ldr pc, [ip, #0x00000NNN] Offset(&(.plt.got) - L1 - 8
246 };244 };
247245
248 uint64_t Offset = GotPltEntryAddr - PltEntryAddr - 8;246 uint64_t offset = gotPltEntryAddr - pltEntryAddr - 8;
249 if (!llvm::isUInt<27>(Offset)) {247 if (!llvm::isUInt<27>(offset)) {
250 // We cannot encode the Offset, use the long form.248 // We cannot encode the Offset, use the long form.
251 writePltLong(Buf, GotPltEntryAddr, PltEntryAddr, Index, RelOff);249 writePltLong(buf, gotPltEntryAddr, pltEntryAddr, index, relOff);
252 return;250 return;
253 }251 }
254 write32le(Buf + 0, PltData[0] | ((Offset >> 20) & 0xff));252 write32le(buf + 0, pltData[0] | ((offset >> 20) & 0xff));
255 write32le(Buf + 4, PltData[1] | ((Offset >> 12) & 0xff));253 write32le(buf + 4, pltData[1] | ((offset >> 12) & 0xff));
256 write32le(Buf + 8, PltData[2] | (Offset & 0xfff));254 write32le(buf + 8, pltData[2] | (offset & 0xfff));
257 memcpy(Buf + 12, TrapInstr.data(), 4); // Pad to 16-byte boundary255 memcpy(buf + 12, trapInstr.data(), 4); // Pad to 16-byte boundary
258}256}
259257
260void ARM::addPltSymbols(InputSection &IS, uint64_t Off) const {258void ARM::addPltSymbols(InputSection &isec, uint64_t off) const {
261 addSyntheticLocal("$a", STT_NOTYPE, Off, 0, IS);259 addSyntheticLocal("$a", STT_NOTYPE, off, 0, isec);
262 addSyntheticLocal("$d", STT_NOTYPE, Off + 12, 0, IS);260 addSyntheticLocal("$d", STT_NOTYPE, off + 12, 0, isec);
263}261}
264262
265bool ARM::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,263bool ARM::needsThunk(RelExpr expr, RelType type, const InputFile *file,
266 uint64_t BranchAddr, const Symbol &S) const {264 uint64_t branchAddr, const Symbol &s) const {
267 // If S is an undefined weak symbol and does not have a PLT entry then it265 // If S is an undefined weak symbol and does not have a PLT entry then it
268 // will be resolved as a branch to the next instruction.266 // will be resolved as a branch to the next instruction.
269 if (S.isUndefWeak() && !S.isInPlt())267 if (s.isUndefWeak() && !s.isInPlt())
270 return false;268 return false;
271 // A state change from ARM to Thumb and vice versa must go through an269 // A state change from ARM to Thumb and vice versa must go through an
272 // interworking thunk if the relocation type is not R_ARM_CALL or270 // interworking thunk if the relocation type is not R_ARM_CALL or
273 // R_ARM_THM_CALL.271 // R_ARM_THM_CALL.
274 switch (Type) {272 switch (type) {
275 case R_ARM_PC24:273 case R_ARM_PC24:
276 case R_ARM_PLT32:274 case R_ARM_PLT32:
277 case R_ARM_JUMP24:275 case R_ARM_JUMP24:
278 // Source is ARM, all PLT entries are ARM so no interworking required.276 // Source is ARM, all PLT entries are ARM so no interworking required.
279 // Otherwise we need to interwork if Symbol has bit 0 set (Thumb).277 // Otherwise we need to interwork if Symbol has bit 0 set (Thumb).
280 if (Expr == R_PC && ((S.getVA() & 1) == 1))278 if (expr == R_PC && ((s.getVA() & 1) == 1))
281 return true;279 return true;
282 LLVM_FALLTHROUGH;280 LLVM_FALLTHROUGH;
283 case R_ARM_CALL: {281 case R_ARM_CALL: {
284 uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA();282 uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA() : s.getVA();
285 return !inBranchRange(Type, BranchAddr, Dst);283 return !inBranchRange(type, branchAddr, dst);
286 }284 }
287 case R_ARM_THM_JUMP19:285 case R_ARM_THM_JUMP19:
288 case R_ARM_THM_JUMP24:286 case R_ARM_THM_JUMP24:
289 // Source is Thumb, all PLT entries are ARM so interworking is required.287 // Source is Thumb, all PLT entries are ARM so interworking is required.
290 // Otherwise we need to interwork if Symbol has bit 0 clear (ARM).288 // Otherwise we need to interwork if Symbol has bit 0 clear (ARM).
291 if (Expr == R_PLT_PC || ((S.getVA() & 1) == 0))289 if (expr == R_PLT_PC || ((s.getVA() & 1) == 0))
292 return true;290 return true;
293 LLVM_FALLTHROUGH;291 LLVM_FALLTHROUGH;
294 case R_ARM_THM_CALL: {292 case R_ARM_THM_CALL: {
295 uint64_t Dst = (Expr == R_PLT_PC) ? S.getPltVA() : S.getVA();293 uint64_t dst = (expr == R_PLT_PC) ? s.getPltVA() : s.getVA();
296 return !inBranchRange(Type, BranchAddr, Dst);294 return !inBranchRange(type, branchAddr, dst);
297 }295 }
298 }296 }
299 return false;297 return false;
...@@ -301,13 +299,13 @@ bool ARM::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,...@@ -301,13 +299,13 @@ bool ARM::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,
301299
302uint32_t ARM::getThunkSectionSpacing() const {300uint32_t ARM::getThunkSectionSpacing() const {
303 // The placing of pre-created ThunkSections is controlled by the value301 // The placing of pre-created ThunkSections is controlled by the value
304 // ThunkSectionSpacing returned by getThunkSectionSpacing(). The aim is to302 // thunkSectionSpacing returned by getThunkSectionSpacing(). The aim is to
305 // place the ThunkSection such that all branches from the InputSections303 // place the ThunkSection such that all branches from the InputSections
306 // prior to the ThunkSection can reach a Thunk placed at the end of the304 // prior to the ThunkSection can reach a Thunk placed at the end of the
307 // ThunkSection. Graphically:305 // ThunkSection. Graphically:
308 // | up to ThunkSectionSpacing .text input sections |306 // | up to thunkSectionSpacing .text input sections |
309 // | ThunkSection |307 // | ThunkSection |
310 // | up to ThunkSectionSpacing .text input sections |308 // | up to thunkSectionSpacing .text input sections |
311 // | ThunkSection |309 // | ThunkSection |
312310
313 // Pre-created ThunkSections are spaced roughly 16MiB apart on ARMv7. This311 // Pre-created ThunkSections are spaced roughly 16MiB apart on ARMv7. This
...@@ -318,69 +316,68 @@ uint32_t ARM::getThunkSectionSpacing() const {...@@ -318,69 +316,68 @@ uint32_t ARM::getThunkSectionSpacing() const {
318 // Thumb B<cc>.W range +/- 1MiB316 // Thumb B<cc>.W range +/- 1MiB
319 // If a branch cannot reach a pre-created ThunkSection a new one will be317 // 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.318 // 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 maximum319 // 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 within320 // 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 shorten321 // 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,384322 // 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 to323 // 12 byte Thunks at any offset in a ThunkSection without risk of a branch to
326 // one of the Thunks going out of range.324 // one of the Thunks going out of range.
327325
328 // On Arm the ThunkSectionSpacing depends on the range of the Thumb Branch326 // On Arm the thunkSectionSpacing depends on the range of the Thumb Branch
329 // range. On earlier Architectures such as ARMv4, ARMv5 and ARMv6 (except327 // range. On earlier Architectures such as ARMv4, ARMv5 and ARMv6 (except
330 // ARMv6T2) the range is +/- 4MiB.328 // ARMv6T2) the range is +/- 4MiB.
331329
332 return (Config->ARMJ1J2BranchEncoding) ? 0x1000000 - 0x30000330 return (config->armJ1J2BranchEncoding) ? 0x1000000 - 0x30000
333 : 0x400000 - 0x7500;331 : 0x400000 - 0x7500;
334}332}
335333
336bool ARM::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const {334bool ARM::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
337 uint64_t Range;335 uint64_t range;
338 uint64_t InstrSize;336 uint64_t instrSize;
339337
340 switch (Type) {338 switch (type) {
341 case R_ARM_PC24:339 case R_ARM_PC24:
342 case R_ARM_PLT32:340 case R_ARM_PLT32:
343 case R_ARM_JUMP24:341 case R_ARM_JUMP24:
344 case R_ARM_CALL:342 case R_ARM_CALL:
345 Range = 0x2000000;343 range = 0x2000000;
346 InstrSize = 4;344 instrSize = 4;
347 break;345 break;
348 case R_ARM_THM_JUMP19:346 case R_ARM_THM_JUMP19:
349 Range = 0x100000;347 range = 0x100000;
350 InstrSize = 2;348 instrSize = 2;
351 break;349 break;
352 case R_ARM_THM_JUMP24:350 case R_ARM_THM_JUMP24:
353 case R_ARM_THM_CALL:351 case R_ARM_THM_CALL:
354 Range = Config->ARMJ1J2BranchEncoding ? 0x1000000 : 0x400000;352 range = config->armJ1J2BranchEncoding ? 0x1000000 : 0x400000;
355 InstrSize = 2;353 instrSize = 2;
356 break;354 break;
357 default:355 default:
358 return true;356 return true;
359 }357 }
360 // PC at Src is 2 instructions ahead, immediate of branch is signed358 // PC at Src is 2 instructions ahead, immediate of branch is signed
361 if (Src > Dst)359 if (src > dst)
362 Range -= 2 * InstrSize;360 range -= 2 * instrSize;
363 else361 else
364 Range += InstrSize;362 range += instrSize;
365363
366 if ((Dst & 0x1) == 0)364 if ((dst & 0x1) == 0)
367 // Destination is ARM, if ARM caller then Src is already 4-byte aligned.365 // Destination is ARM, if ARM caller then Src is already 4-byte aligned.
368 // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure366 // If Thumb Caller (BLX) the Src address has bottom 2 bits cleared to ensure
369 // destination will be 4 byte aligned.367 // destination will be 4 byte aligned.
370 Src &= ~0x3;368 src &= ~0x3;
371 else369 else
372 // Bit 0 == 1 denotes Thumb state, it is not part of the range370 // Bit 0 == 1 denotes Thumb state, it is not part of the range
373 Dst &= ~0x1;371 dst &= ~0x1;
374372
375 uint64_t Distance = (Src > Dst) ? Src - Dst : Dst - Src;373 uint64_t distance = (src > dst) ? src - dst : dst - src;
376 return Distance <= Range;374 return distance <= range;
377}375}
378376
379void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {377void ARM::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
380 switch (Type) {378 switch (type) {
381 case R_ARM_ABS32:379 case R_ARM_ABS32:
382 case R_ARM_BASE_PREL:380 case R_ARM_BASE_PREL:
383 case R_ARM_GLOB_DAT:
384 case R_ARM_GOTOFF32:381 case R_ARM_GOTOFF32:
385 case R_ARM_GOT_BREL:382 case R_ARM_GOT_BREL:
386 case R_ARM_GOT_PREL:383 case R_ARM_GOT_PREL:
...@@ -396,135 +393,132 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -396,135 +393,132 @@ void ARM::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
396 case R_ARM_TLS_LE32:393 case R_ARM_TLS_LE32:
397 case R_ARM_TLS_TPOFF32:394 case R_ARM_TLS_TPOFF32:
398 case R_ARM_TLS_DTPOFF32:395 case R_ARM_TLS_DTPOFF32:
399 write32le(Loc, Val);396 write32le(loc, val);
400 break;
401 case R_ARM_TLS_DTPMOD32:
402 write32le(Loc, 1);
403 break;397 break;
404 case R_ARM_PREL31:398 case R_ARM_PREL31:
405 checkInt(Loc, Val, 31, Type);399 checkInt(loc, val, 31, type);
406 write32le(Loc, (read32le(Loc) & 0x80000000) | (Val & ~0x80000000));400 write32le(loc, (read32le(loc) & 0x80000000) | (val & ~0x80000000));
407 break;401 break;
408 case R_ARM_CALL:402 case R_ARM_CALL:
409 // R_ARM_CALL is used for BL and BLX instructions, depending on the403 // R_ARM_CALL is used for BL and BLX instructions, depending on the
410 // value of bit 0 of Val, we must select a BL or BLX instruction404 // value of bit 0 of Val, we must select a BL or BLX instruction
411 if (Val & 1) {405 if (val & 1) {
412 // If bit 0 of Val is 1 the target is Thumb, we must select a BLX.406 // If bit 0 of Val is 1 the target is Thumb, we must select a BLX.
413 // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1'407 // The BLX encoding is 0xfa:H:imm24 where Val = imm24:H:'1'
414 checkInt(Loc, Val, 26, Type);408 checkInt(loc, val, 26, type);
415 write32le(Loc, 0xfa000000 | // opcode409 write32le(loc, 0xfa000000 | // opcode
416 ((Val & 2) << 23) | // H410 ((val & 2) << 23) | // H
417 ((Val >> 2) & 0x00ffffff)); // imm24411 ((val >> 2) & 0x00ffffff)); // imm24
418 break;412 break;
419 }413 }
420 if ((read32le(Loc) & 0xfe000000) == 0xfa000000)414 if ((read32le(loc) & 0xfe000000) == 0xfa000000)
421 // BLX (always unconditional) instruction to an ARM Target, select an415 // BLX (always unconditional) instruction to an ARM Target, select an
422 // unconditional BL.416 // unconditional BL.
423 write32le(Loc, 0xeb000000 | (read32le(Loc) & 0x00ffffff));417 write32le(loc, 0xeb000000 | (read32le(loc) & 0x00ffffff));
424 // fall through as BL encoding is shared with B418 // fall through as BL encoding is shared with B
425 LLVM_FALLTHROUGH;419 LLVM_FALLTHROUGH;
426 case R_ARM_JUMP24:420 case R_ARM_JUMP24:
427 case R_ARM_PC24:421 case R_ARM_PC24:
428 case R_ARM_PLT32:422 case R_ARM_PLT32:
429 checkInt(Loc, Val, 26, Type);423 checkInt(loc, val, 26, type);
430 write32le(Loc, (read32le(Loc) & ~0x00ffffff) | ((Val >> 2) & 0x00ffffff));424 write32le(loc, (read32le(loc) & ~0x00ffffff) | ((val >> 2) & 0x00ffffff));
431 break;425 break;
432 case R_ARM_THM_JUMP11:426 case R_ARM_THM_JUMP11:
433 checkInt(Loc, Val, 12, Type);427 checkInt(loc, val, 12, type);
434 write16le(Loc, (read32le(Loc) & 0xf800) | ((Val >> 1) & 0x07ff));428 write16le(loc, (read32le(loc) & 0xf800) | ((val >> 1) & 0x07ff));
435 break;429 break;
436 case R_ARM_THM_JUMP19:430 case R_ARM_THM_JUMP19:
437 // Encoding T3: Val = S:J2:J1:imm6:imm11:0431 // Encoding T3: Val = S:J2:J1:imm6:imm11:0
438 checkInt(Loc, Val, 21, Type);432 checkInt(loc, val, 21, type);
439 write16le(Loc,433 write16le(loc,
440 (read16le(Loc) & 0xfbc0) | // opcode cond434 (read16le(loc) & 0xfbc0) | // opcode cond
441 ((Val >> 10) & 0x0400) | // S435 ((val >> 10) & 0x0400) | // S
442 ((Val >> 12) & 0x003f)); // imm6436 ((val >> 12) & 0x003f)); // imm6
443 write16le(Loc + 2,437 write16le(loc + 2,
444 0x8000 | // opcode438 0x8000 | // opcode
445 ((Val >> 8) & 0x0800) | // J2439 ((val >> 8) & 0x0800) | // J2
446 ((Val >> 5) & 0x2000) | // J1440 ((val >> 5) & 0x2000) | // J1
447 ((Val >> 1) & 0x07ff)); // imm11441 ((val >> 1) & 0x07ff)); // imm11
448 break;442 break;
449 case R_ARM_THM_CALL:443 case R_ARM_THM_CALL:
450 // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the444 // R_ARM_THM_CALL is used for BL and BLX instructions, depending on the
451 // value of bit 0 of Val, we must select a BL or BLX instruction445 // value of bit 0 of Val, we must select a BL or BLX instruction
452 if ((Val & 1) == 0) {446 if ((val & 1) == 0) {
453 // Ensure BLX destination is 4-byte aligned. As BLX instruction may447 // Ensure BLX destination is 4-byte aligned. As BLX instruction may
454 // only be two byte aligned. This must be done before overflow check448 // only be two byte aligned. This must be done before overflow check
455 Val = alignTo(Val, 4);449 val = alignTo(val, 4);
456 }450 }
457 // Bit 12 is 0 for BLX, 1 for BL451 // Bit 12 is 0 for BLX, 1 for BL
458 write16le(Loc + 2, (read16le(Loc + 2) & ~0x1000) | (Val & 1) << 12);452 write16le(loc + 2, (read16le(loc + 2) & ~0x1000) | (val & 1) << 12);
459 if (!Config->ARMJ1J2BranchEncoding) {453 if (!config->armJ1J2BranchEncoding) {
460 // Older Arm architectures do not support R_ARM_THM_JUMP24 and have454 // 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.455 // different encoding rules and range due to J1 and J2 always being 1.
462 checkInt(Loc, Val, 23, Type);456 checkInt(loc, val, 23, type);
463 write16le(Loc,457 write16le(loc,
464 0xf000 | // opcode458 0xf000 | // opcode
465 ((Val >> 12) & 0x07ff)); // imm11459 ((val >> 12) & 0x07ff)); // imm11
466 write16le(Loc + 2,460 write16le(loc + 2,
467 (read16le(Loc + 2) & 0xd000) | // opcode461 (read16le(loc + 2) & 0xd000) | // opcode
468 0x2800 | // J1 == J2 == 1462 0x2800 | // J1 == J2 == 1
469 ((Val >> 1) & 0x07ff)); // imm11463 ((val >> 1) & 0x07ff)); // imm11
470 break;464 break;
471 }465 }
472 // Fall through as rest of encoding is the same as B.W466 // Fall through as rest of encoding is the same as B.W
473 LLVM_FALLTHROUGH;467 LLVM_FALLTHROUGH;
474 case R_ARM_THM_JUMP24:468 case R_ARM_THM_JUMP24:
475 // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0469 // Encoding B T4, BL T1, BLX T2: Val = S:I1:I2:imm10:imm11:0
476 checkInt(Loc, Val, 25, Type);470 checkInt(loc, val, 25, type);
477 write16le(Loc,471 write16le(loc,
478 0xf000 | // opcode472 0xf000 | // opcode
479 ((Val >> 14) & 0x0400) | // S473 ((val >> 14) & 0x0400) | // S
480 ((Val >> 12) & 0x03ff)); // imm10474 ((val >> 12) & 0x03ff)); // imm10
481 write16le(Loc + 2,475 write16le(loc + 2,
482 (read16le(Loc + 2) & 0xd000) | // opcode476 (read16le(loc + 2) & 0xd000) | // opcode
483 (((~(Val >> 10)) ^ (Val >> 11)) & 0x2000) | // J1477 (((~(val >> 10)) ^ (val >> 11)) & 0x2000) | // J1
484 (((~(Val >> 11)) ^ (Val >> 13)) & 0x0800) | // J2478 (((~(val >> 11)) ^ (val >> 13)) & 0x0800) | // J2
485 ((Val >> 1) & 0x07ff)); // imm11479 ((val >> 1) & 0x07ff)); // imm11
486 break;480 break;
487 case R_ARM_MOVW_ABS_NC:481 case R_ARM_MOVW_ABS_NC:
488 case R_ARM_MOVW_PREL_NC:482 case R_ARM_MOVW_PREL_NC:
489 write32le(Loc, (read32le(Loc) & ~0x000f0fff) | ((Val & 0xf000) << 4) |483 write32le(loc, (read32le(loc) & ~0x000f0fff) | ((val & 0xf000) << 4) |
490 (Val & 0x0fff));484 (val & 0x0fff));
491 break;485 break;
492 case R_ARM_MOVT_ABS:486 case R_ARM_MOVT_ABS:
493 case R_ARM_MOVT_PREL:487 case R_ARM_MOVT_PREL:
494 write32le(Loc, (read32le(Loc) & ~0x000f0fff) |488 write32le(loc, (read32le(loc) & ~0x000f0fff) |
495 (((Val >> 16) & 0xf000) << 4) | ((Val >> 16) & 0xfff));489 (((val >> 16) & 0xf000) << 4) | ((val >> 16) & 0xfff));
496 break;490 break;
497 case R_ARM_THM_MOVT_ABS:491 case R_ARM_THM_MOVT_ABS:
498 case R_ARM_THM_MOVT_PREL:492 case R_ARM_THM_MOVT_PREL:
499 // Encoding T1: A = imm4:i:imm3:imm8493 // Encoding T1: A = imm4:i:imm3:imm8
500 write16le(Loc,494 write16le(loc,
501 0xf2c0 | // opcode495 0xf2c0 | // opcode
502 ((Val >> 17) & 0x0400) | // i496 ((val >> 17) & 0x0400) | // i
503 ((Val >> 28) & 0x000f)); // imm4497 ((val >> 28) & 0x000f)); // imm4
504 write16le(Loc + 2,498 write16le(loc + 2,
505 (read16le(Loc + 2) & 0x8f00) | // opcode499 (read16le(loc + 2) & 0x8f00) | // opcode
506 ((Val >> 12) & 0x7000) | // imm3500 ((val >> 12) & 0x7000) | // imm3
507 ((Val >> 16) & 0x00ff)); // imm8501 ((val >> 16) & 0x00ff)); // imm8
508 break;502 break;
509 case R_ARM_THM_MOVW_ABS_NC:503 case R_ARM_THM_MOVW_ABS_NC:
510 case R_ARM_THM_MOVW_PREL_NC:504 case R_ARM_THM_MOVW_PREL_NC:
511 // Encoding T3: A = imm4:i:imm3:imm8505 // Encoding T3: A = imm4:i:imm3:imm8
512 write16le(Loc,506 write16le(loc,
513 0xf240 | // opcode507 0xf240 | // opcode
514 ((Val >> 1) & 0x0400) | // i508 ((val >> 1) & 0x0400) | // i
515 ((Val >> 12) & 0x000f)); // imm4509 ((val >> 12) & 0x000f)); // imm4
516 write16le(Loc + 2,510 write16le(loc + 2,
517 (read16le(Loc + 2) & 0x8f00) | // opcode511 (read16le(loc + 2) & 0x8f00) | // opcode
518 ((Val << 4) & 0x7000) | // imm3512 ((val << 4) & 0x7000) | // imm3
519 (Val & 0x00ff)); // imm8513 (val & 0x00ff)); // imm8
520 break;514 break;
521 default:515 default:
522 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));516 error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
523 }517 }
524}518}
525519
526int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const {520int64_t ARM::getImplicitAddend(const uint8_t *buf, RelType type) const {
527 switch (Type) {521 switch (type) {
528 default:522 default:
529 return 0;523 return 0;
530 case R_ARM_ABS32:524 case R_ARM_ABS32:
...@@ -540,47 +534,47 @@ int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const {...@@ -540,47 +534,47 @@ int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const {
540 case R_ARM_TLS_LDO32:534 case R_ARM_TLS_LDO32:
541 case R_ARM_TLS_IE32:535 case R_ARM_TLS_IE32:
542 case R_ARM_TLS_LE32:536 case R_ARM_TLS_LE32:
543 return SignExtend64<32>(read32le(Buf));537 return SignExtend64<32>(read32le(buf));
544 case R_ARM_PREL31:538 case R_ARM_PREL31:
545 return SignExtend64<31>(read32le(Buf));539 return SignExtend64<31>(read32le(buf));
546 case R_ARM_CALL:540 case R_ARM_CALL:
547 case R_ARM_JUMP24:541 case R_ARM_JUMP24:
548 case R_ARM_PC24:542 case R_ARM_PC24:
549 case R_ARM_PLT32:543 case R_ARM_PLT32:
550 return SignExtend64<26>(read32le(Buf) << 2);544 return SignExtend64<26>(read32le(buf) << 2);
551 case R_ARM_THM_JUMP11:545 case R_ARM_THM_JUMP11:
552 return SignExtend64<12>(read16le(Buf) << 1);546 return SignExtend64<12>(read16le(buf) << 1);
553 case R_ARM_THM_JUMP19: {547 case R_ARM_THM_JUMP19: {
554 // Encoding T3: A = S:J2:J1:imm10:imm6:0548 // Encoding T3: A = S:J2:J1:imm10:imm6:0
555 uint16_t Hi = read16le(Buf);549 uint16_t hi = read16le(buf);
556 uint16_t Lo = read16le(Buf + 2);550 uint16_t lo = read16le(buf + 2);
557 return SignExtend64<20>(((Hi & 0x0400) << 10) | // S551 return SignExtend64<20>(((hi & 0x0400) << 10) | // S
558 ((Lo & 0x0800) << 8) | // J2552 ((lo & 0x0800) << 8) | // J2
559 ((Lo & 0x2000) << 5) | // J1553 ((lo & 0x2000) << 5) | // J1
560 ((Hi & 0x003f) << 12) | // imm6554 ((hi & 0x003f) << 12) | // imm6
561 ((Lo & 0x07ff) << 1)); // imm11:0555 ((lo & 0x07ff) << 1)); // imm11:0
562 }556 }
563 case R_ARM_THM_CALL:557 case R_ARM_THM_CALL:
564 if (!Config->ARMJ1J2BranchEncoding) {558 if (!config->armJ1J2BranchEncoding) {
565 // Older Arm architectures do not support R_ARM_THM_JUMP24 and have559 // 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.560 // different encoding rules and range due to J1 and J2 always being 1.
567 uint16_t Hi = read16le(Buf);561 uint16_t hi = read16le(buf);
568 uint16_t Lo = read16le(Buf + 2);562 uint16_t lo = read16le(buf + 2);
569 return SignExtend64<22>(((Hi & 0x7ff) << 12) | // imm11563 return SignExtend64<22>(((hi & 0x7ff) << 12) | // imm11
570 ((Lo & 0x7ff) << 1)); // imm11:0564 ((lo & 0x7ff) << 1)); // imm11:0
571 break;565 break;
572 }566 }
573 LLVM_FALLTHROUGH;567 LLVM_FALLTHROUGH;
574 case R_ARM_THM_JUMP24: {568 case R_ARM_THM_JUMP24: {
575 // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0569 // Encoding B T4, BL T1, BLX T2: A = S:I1:I2:imm10:imm11:0
576 // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S)570 // I1 = NOT(J1 EOR S), I2 = NOT(J2 EOR S)
577 uint16_t Hi = read16le(Buf);571 uint16_t hi = read16le(buf);
578 uint16_t Lo = read16le(Buf + 2);572 uint16_t lo = read16le(buf + 2);
579 return SignExtend64<24>(((Hi & 0x0400) << 14) | // S573 return SignExtend64<24>(((hi & 0x0400) << 14) | // S
580 (~((Lo ^ (Hi << 3)) << 10) & 0x00800000) | // I1574 (~((lo ^ (hi << 3)) << 10) & 0x00800000) | // I1
581 (~((Lo ^ (Hi << 1)) << 11) & 0x00400000) | // I2575 (~((lo ^ (hi << 1)) << 11) & 0x00400000) | // I2
582 ((Hi & 0x003ff) << 12) | // imm0576 ((hi & 0x003ff) << 12) | // imm0
583 ((Lo & 0x007ff) << 1)); // imm11:0577 ((lo & 0x007ff) << 1)); // imm11:0
584 }578 }
585 // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and579 // ELF for the ARM Architecture 4.6.1.1 the implicit addend for MOVW and
586 // MOVT is in the range -32768 <= A < 32768580 // MOVT is in the range -32768 <= A < 32768
...@@ -588,25 +582,25 @@ int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const {...@@ -588,25 +582,25 @@ int64_t ARM::getImplicitAddend(const uint8_t *Buf, RelType Type) const {
588 case R_ARM_MOVT_ABS:582 case R_ARM_MOVT_ABS:
589 case R_ARM_MOVW_PREL_NC:583 case R_ARM_MOVW_PREL_NC:
590 case R_ARM_MOVT_PREL: {584 case R_ARM_MOVT_PREL: {
591 uint64_t Val = read32le(Buf) & 0x000f0fff;585 uint64_t val = read32le(buf) & 0x000f0fff;
592 return SignExtend64<16>(((Val & 0x000f0000) >> 4) | (Val & 0x00fff));586 return SignExtend64<16>(((val & 0x000f0000) >> 4) | (val & 0x00fff));
593 }587 }
594 case R_ARM_THM_MOVW_ABS_NC:588 case R_ARM_THM_MOVW_ABS_NC:
595 case R_ARM_THM_MOVT_ABS:589 case R_ARM_THM_MOVT_ABS:
596 case R_ARM_THM_MOVW_PREL_NC:590 case R_ARM_THM_MOVW_PREL_NC:
597 case R_ARM_THM_MOVT_PREL: {591 case R_ARM_THM_MOVT_PREL: {
598 // Encoding T3: A = imm4:i:imm3:imm8592 // Encoding T3: A = imm4:i:imm3:imm8
599 uint16_t Hi = read16le(Buf);593 uint16_t hi = read16le(buf);
600 uint16_t Lo = read16le(Buf + 2);594 uint16_t lo = read16le(buf + 2);
601 return SignExtend64<16>(((Hi & 0x000f) << 12) | // imm4595 return SignExtend64<16>(((hi & 0x000f) << 12) | // imm4
602 ((Hi & 0x0400) << 1) | // i596 ((hi & 0x0400) << 1) | // i
603 ((Lo & 0x7000) >> 4) | // imm3597 ((lo & 0x7000) >> 4) | // imm3
604 (Lo & 0x00ff)); // imm8598 (lo & 0x00ff)); // imm8
605 }599 }
606 }600 }
607}601}
608602
609TargetInfo *elf::getARMTargetInfo() {603TargetInfo *elf::getARMTargetInfo() {
610 static ARM Target;604 static ARM target;
611 return &Target;605 return &target;
612}606}
deps/lld/ELF/Arch/AVR.cpp+18-19
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- AVR.cpp ------------------------------------------------------------===//1//===- AVR.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -44,34 +43,34 @@ namespace {...@@ -44,34 +43,34 @@ namespace {
44class AVR final : public TargetInfo {43class AVR final : public TargetInfo {
45public:44public:
46 AVR();45 AVR();
47 RelExpr getRelExpr(RelType Type, const Symbol &S,46 RelExpr getRelExpr(RelType type, const Symbol &s,
48 const uint8_t *Loc) const override;47 const uint8_t *loc) const override;
49 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;48 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
50};49};
51} // namespace50} // namespace
5251
53AVR::AVR() { NoneRel = R_AVR_NONE; }52AVR::AVR() { noneRel = R_AVR_NONE; }
5453
55RelExpr AVR::getRelExpr(RelType Type, const Symbol &S,54RelExpr AVR::getRelExpr(RelType type, const Symbol &s,
56 const uint8_t *Loc) const {55 const uint8_t *loc) const {
57 return R_ABS;56 return R_ABS;
58}57}
5958
60void AVR::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {59void AVR::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
61 switch (Type) {60 switch (type) {
62 case R_AVR_CALL: {61 case R_AVR_CALL: {
63 uint16_t Hi = Val >> 17;62 uint16_t hi = val >> 17;
64 uint16_t Lo = Val >> 1;63 uint16_t lo = val >> 1;
65 write16le(Loc, read16le(Loc) | ((Hi >> 1) << 4) | (Hi & 1));64 write16le(loc, read16le(loc) | ((hi >> 1) << 4) | (hi & 1));
66 write16le(Loc + 2, Lo);65 write16le(loc + 2, lo);
67 break;66 break;
68 }67 }
69 default:68 default:
70 error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type));69 error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
71 }70 }
72}71}
7372
74TargetInfo *elf::getAVRTargetInfo() {73TargetInfo *elf::getAVRTargetInfo() {
75 static AVR Target;74 static AVR target;
76 return &Target;75 return &target;
77}76}
deps/lld/ELF/Arch/Hexagon.cpp+97-98
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===-- Hexagon.cpp -------------------------------------------------------===//1//===-- Hexagon.cpp -------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -28,65 +27,65 @@ class Hexagon final : public TargetInfo {...@@ -28,65 +27,65 @@ class Hexagon final : public TargetInfo {
28public:27public:
29 Hexagon();28 Hexagon();
30 uint32_t calcEFlags() const override;29 uint32_t calcEFlags() const override;
31 RelExpr getRelExpr(RelType Type, const Symbol &S,30 RelExpr getRelExpr(RelType type, const Symbol &s,
32 const uint8_t *Loc) const override;31 const uint8_t *loc) const override;
33 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;32 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
34 void writePltHeader(uint8_t *Buf) const override;33 void writePltHeader(uint8_t *buf) const override;
35 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,34 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
36 int32_t Index, unsigned RelOff) const override;35 int32_t index, unsigned relOff) const override;
37};36};
38} // namespace37} // namespace
3938
40Hexagon::Hexagon() {39Hexagon::Hexagon() {
41 PltRel = R_HEX_JMP_SLOT;40 pltRel = R_HEX_JMP_SLOT;
42 RelativeRel = R_HEX_RELATIVE;41 relativeRel = R_HEX_RELATIVE;
43 GotRel = R_HEX_GLOB_DAT;42 gotRel = R_HEX_GLOB_DAT;
44 GotEntrySize = 4;43 symbolicRel = R_HEX_32;
44
45 // The zero'th GOT entry is reserved for the address of _DYNAMIC. The45 // The zero'th GOT entry is reserved for the address of _DYNAMIC. The
46 // next 3 are reserved for the dynamic loader.46 // next 3 are reserved for the dynamic loader.
47 GotPltHeaderEntriesNum = 4;47 gotPltHeaderEntriesNum = 4;
48 GotPltEntrySize = 4;
4948
50 PltEntrySize = 16;49 pltEntrySize = 16;
51 PltHeaderSize = 32;50 pltHeaderSize = 32;
5251
53 // Hexagon Linux uses 64K pages by default.52 // Hexagon Linux uses 64K pages by default.
54 DefaultMaxPageSize = 0x10000;53 defaultMaxPageSize = 0x10000;
55 NoneRel = R_HEX_NONE;54 noneRel = R_HEX_NONE;
56}55}
5756
58uint32_t Hexagon::calcEFlags() const {57uint32_t Hexagon::calcEFlags() const {
59 assert(!ObjectFiles.empty());58 assert(!objectFiles.empty());
6059
61 // The architecture revision must always be equal to or greater than60 // The architecture revision must always be equal to or greater than
62 // greatest revision in the list of inputs.61 // greatest revision in the list of inputs.
63 uint32_t Ret = 0;62 uint32_t ret = 0;
64 for (InputFile *F : ObjectFiles) {63 for (InputFile *f : objectFiles) {
65 uint32_t EFlags = cast<ObjFile<ELF32LE>>(F)->getObj().getHeader()->e_flags;64 uint32_t eflags = cast<ObjFile<ELF32LE>>(f)->getObj().getHeader()->e_flags;
66 if (EFlags > Ret)65 if (eflags > ret)
67 Ret = EFlags;66 ret = eflags;
68 }67 }
69 return Ret;68 return ret;
70}69}
7170
72static uint32_t applyMask(uint32_t Mask, uint32_t Data) {71static uint32_t applyMask(uint32_t mask, uint32_t data) {
73 uint32_t Result = 0;72 uint32_t result = 0;
74 size_t Off = 0;73 size_t off = 0;
7574
76 for (size_t Bit = 0; Bit != 32; ++Bit) {75 for (size_t bit = 0; bit != 32; ++bit) {
77 uint32_t ValBit = (Data >> Off) & 1;76 uint32_t valBit = (data >> off) & 1;
78 uint32_t MaskBit = (Mask >> Bit) & 1;77 uint32_t maskBit = (mask >> bit) & 1;
79 if (MaskBit) {78 if (maskBit) {
80 Result |= (ValBit << Bit);79 result |= (valBit << bit);
81 ++Off;80 ++off;
82 }81 }
83 }82 }
84 return Result;83 return result;
85}84}
8685
87RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S,86RelExpr Hexagon::getRelExpr(RelType type, const Symbol &s,
88 const uint8_t *Loc) const {87 const uint8_t *loc) const {
89 switch (Type) {88 switch (type) {
90 case R_HEX_B9_PCREL:89 case R_HEX_B9_PCREL:
91 case R_HEX_B9_PCREL_X:90 case R_HEX_B9_PCREL_X:
92 case R_HEX_B13_PCREL:91 case R_HEX_B13_PCREL:
...@@ -109,16 +108,16 @@ RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S,...@@ -109,16 +108,16 @@ RelExpr Hexagon::getRelExpr(RelType Type, const Symbol &S,
109 }108 }
110}109}
111110
112static uint32_t findMaskR6(uint32_t Insn) {111static uint32_t findMaskR6(uint32_t insn) {
113 // There are (arguably too) many relocation masks for the DSP's112 // 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 mask113 // R_HEX_6_X type. The table below is used to select the correct mask
115 // for the given instruction.114 // for the given instruction.
116 struct InstructionMask {115 struct InstructionMask {
117 uint32_t CmpMask;116 uint32_t cmpMask;
118 uint32_t RelocMask;117 uint32_t relocMask;
119 };118 };
120119
121 static const InstructionMask R6[] = {120 static const InstructionMask r6[] = {
122 {0x38000000, 0x0000201f}, {0x39000000, 0x0000201f},121 {0x38000000, 0x0000201f}, {0x39000000, 0x0000201f},
123 {0x3e000000, 0x00001f80}, {0x3f000000, 0x00001f80},122 {0x3e000000, 0x00001f80}, {0x3f000000, 0x00001f80},
124 {0x40000000, 0x000020f8}, {0x41000000, 0x000007e0},123 {0x40000000, 0x000020f8}, {0x41000000, 0x000007e0},
...@@ -136,124 +135,124 @@ static uint32_t findMaskR6(uint32_t Insn) {...@@ -136,124 +135,124 @@ static uint32_t findMaskR6(uint32_t Insn) {
136 // Duplex forms have a fixed mask and parse bits 15:14 are always135 // 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 the136 // zero. Non-duplex insns will always have at least one bit set in the
138 // parse field.137 // parse field.
139 if ((0xC000 & Insn) == 0x0)138 if ((0xC000 & insn) == 0x0)
140 return 0x03f00000;139 return 0x03f00000;
141140
142 for (InstructionMask I : R6)141 for (InstructionMask i : r6)
143 if ((0xff000000 & Insn) == I.CmpMask)142 if ((0xff000000 & insn) == i.cmpMask)
144 return I.RelocMask;143 return i.relocMask;
145144
146 error("unrecognized instruction for R_HEX_6 relocation: 0x" +145 error("unrecognized instruction for R_HEX_6 relocation: 0x" +
147 utohexstr(Insn));146 utohexstr(insn));
148 return 0;147 return 0;
149}148}
150149
151static uint32_t findMaskR8(uint32_t Insn) {150static uint32_t findMaskR8(uint32_t insn) {
152 if ((0xff000000 & Insn) == 0xde000000)151 if ((0xff000000 & insn) == 0xde000000)
153 return 0x00e020e8;152 return 0x00e020e8;
154 if ((0xff000000 & Insn) == 0x3c000000)153 if ((0xff000000 & insn) == 0x3c000000)
155 return 0x0000207f;154 return 0x0000207f;
156 return 0x00001fe0;155 return 0x00001fe0;
157}156}
158157
159static uint32_t findMaskR11(uint32_t Insn) {158static uint32_t findMaskR11(uint32_t insn) {
160 if ((0xff000000 & Insn) == 0xa1000000)159 if ((0xff000000 & insn) == 0xa1000000)
161 return 0x060020ff;160 return 0x060020ff;
162 return 0x06003fe0;161 return 0x06003fe0;
163}162}
164163
165static uint32_t findMaskR16(uint32_t Insn) {164static uint32_t findMaskR16(uint32_t insn) {
166 if ((0xff000000 & Insn) == 0x48000000)165 if ((0xff000000 & insn) == 0x48000000)
167 return 0x061f20ff;166 return 0x061f20ff;
168 if ((0xff000000 & Insn) == 0x49000000)167 if ((0xff000000 & insn) == 0x49000000)
169 return 0x061f3fe0;168 return 0x061f3fe0;
170 if ((0xff000000 & Insn) == 0x78000000)169 if ((0xff000000 & insn) == 0x78000000)
171 return 0x00df3fe0;170 return 0x00df3fe0;
172 if ((0xff000000 & Insn) == 0xb0000000)171 if ((0xff000000 & insn) == 0xb0000000)
173 return 0x0fe03fe0;172 return 0x0fe03fe0;
174173
175 error("unrecognized instruction for R_HEX_16_X relocation: 0x" +174 error("unrecognized instruction for R_HEX_16_X relocation: 0x" +
176 utohexstr(Insn));175 utohexstr(insn));
177 return 0;176 return 0;
178}177}
179178
180static void or32le(uint8_t *P, int32_t V) { write32le(P, read32le(P) | V); }179static void or32le(uint8_t *p, int32_t v) { write32le(p, read32le(p) | v); }
181180
182void Hexagon::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {181void Hexagon::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
183 switch (Type) {182 switch (type) {
184 case R_HEX_NONE:183 case R_HEX_NONE:
185 break;184 break;
186 case R_HEX_6_PCREL_X:185 case R_HEX_6_PCREL_X:
187 case R_HEX_6_X:186 case R_HEX_6_X:
188 or32le(Loc, applyMask(findMaskR6(read32le(Loc)), Val));187 or32le(loc, applyMask(findMaskR6(read32le(loc)), val));
189 break;188 break;
190 case R_HEX_8_X:189 case R_HEX_8_X:
191 or32le(Loc, applyMask(findMaskR8(read32le(Loc)), Val));190 or32le(loc, applyMask(findMaskR8(read32le(loc)), val));
192 break;191 break;
193 case R_HEX_9_X:192 case R_HEX_9_X:
194 or32le(Loc, applyMask(0x00003fe0, Val & 0x3f));193 or32le(loc, applyMask(0x00003fe0, val & 0x3f));
195 break;194 break;
196 case R_HEX_10_X:195 case R_HEX_10_X:
197 or32le(Loc, applyMask(0x00203fe0, Val & 0x3f));196 or32le(loc, applyMask(0x00203fe0, val & 0x3f));
198 break;197 break;
199 case R_HEX_11_X:198 case R_HEX_11_X:
200 case R_HEX_GOT_11_X:199 case R_HEX_GOT_11_X:
201 or32le(Loc, applyMask(findMaskR11(read32le(Loc)), Val & 0x3f));200 or32le(loc, applyMask(findMaskR11(read32le(loc)), val & 0x3f));
202 break;201 break;
203 case R_HEX_12_X:202 case R_HEX_12_X:
204 or32le(Loc, applyMask(0x000007e0, Val));203 or32le(loc, applyMask(0x000007e0, val));
205 break;204 break;
206 case R_HEX_16_X: // These relocs only have 6 effective bits.205 case R_HEX_16_X: // These relocs only have 6 effective bits.
207 case R_HEX_GOT_16_X:206 case R_HEX_GOT_16_X:
208 or32le(Loc, applyMask(findMaskR16(read32le(Loc)), Val & 0x3f));207 or32le(loc, applyMask(findMaskR16(read32le(loc)), val & 0x3f));
209 break;208 break;
210 case R_HEX_32:209 case R_HEX_32:
211 case R_HEX_32_PCREL:210 case R_HEX_32_PCREL:
212 or32le(Loc, Val);211 or32le(loc, val);
213 break;212 break;
214 case R_HEX_32_6_X:213 case R_HEX_32_6_X:
215 case R_HEX_GOT_32_6_X:214 case R_HEX_GOT_32_6_X:
216 or32le(Loc, applyMask(0x0fff3fff, Val >> 6));215 or32le(loc, applyMask(0x0fff3fff, val >> 6));
217 break;216 break;
218 case R_HEX_B9_PCREL:217 case R_HEX_B9_PCREL:
219 or32le(Loc, applyMask(0x003000fe, Val >> 2));218 or32le(loc, applyMask(0x003000fe, val >> 2));
220 break;219 break;
221 case R_HEX_B9_PCREL_X:220 case R_HEX_B9_PCREL_X:
222 or32le(Loc, applyMask(0x003000fe, Val & 0x3f));221 or32le(loc, applyMask(0x003000fe, val & 0x3f));
223 break;222 break;
224 case R_HEX_B13_PCREL:223 case R_HEX_B13_PCREL:
225 or32le(Loc, applyMask(0x00202ffe, Val >> 2));224 or32le(loc, applyMask(0x00202ffe, val >> 2));
226 break;225 break;
227 case R_HEX_B15_PCREL:226 case R_HEX_B15_PCREL:
228 or32le(Loc, applyMask(0x00df20fe, Val >> 2));227 or32le(loc, applyMask(0x00df20fe, val >> 2));
229 break;228 break;
230 case R_HEX_B15_PCREL_X:229 case R_HEX_B15_PCREL_X:
231 or32le(Loc, applyMask(0x00df20fe, Val & 0x3f));230 or32le(loc, applyMask(0x00df20fe, val & 0x3f));
232 break;231 break;
233 case R_HEX_B22_PCREL:232 case R_HEX_B22_PCREL:
234 case R_HEX_PLT_B22_PCREL:233 case R_HEX_PLT_B22_PCREL:
235 or32le(Loc, applyMask(0x1ff3ffe, Val >> 2));234 or32le(loc, applyMask(0x1ff3ffe, val >> 2));
236 break;235 break;
237 case R_HEX_B22_PCREL_X:236 case R_HEX_B22_PCREL_X:
238 or32le(Loc, applyMask(0x1ff3ffe, Val & 0x3f));237 or32le(loc, applyMask(0x1ff3ffe, val & 0x3f));
239 break;238 break;
240 case R_HEX_B32_PCREL_X:239 case R_HEX_B32_PCREL_X:
241 or32le(Loc, applyMask(0x0fff3fff, Val >> 6));240 or32le(loc, applyMask(0x0fff3fff, val >> 6));
242 break;241 break;
243 case R_HEX_HI16:242 case R_HEX_HI16:
244 or32le(Loc, applyMask(0x00c03fff, Val >> 16));243 or32le(loc, applyMask(0x00c03fff, val >> 16));
245 break;244 break;
246 case R_HEX_LO16:245 case R_HEX_LO16:
247 or32le(Loc, applyMask(0x00c03fff, Val));246 or32le(loc, applyMask(0x00c03fff, val));
248 break;247 break;
249 default:248 default:
250 error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type));249 error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
251 break;250 break;
252 }251 }
253}252}
254253
255void Hexagon::writePltHeader(uint8_t *Buf) const {254void Hexagon::writePltHeader(uint8_t *buf) const {
256 const uint8_t PltData[] = {255 const uint8_t pltData[] = {
257 0x00, 0x40, 0x00, 0x00, // { immext (#0)256 0x00, 0x40, 0x00, 0x00, // { immext (#0)
258 0x1c, 0xc0, 0x49, 0x6a, // r28 = add (pc, ##GOT0@PCREL) } # @GOT0257 0x1c, 0xc0, 0x49, 0x6a, // r28 = add (pc, ##GOT0@PCREL) } # @GOT0
259 0x0e, 0x42, 0x9c, 0xe2, // { r14 -= add (r28, #16) # offset of GOTn258 0x0e, 0x42, 0x9c, 0xe2, // { r14 -= add (r28, #16) # offset of GOTn
...@@ -263,30 +262,30 @@ void Hexagon::writePltHeader(uint8_t *Buf) const {...@@ -263,30 +262,30 @@ void Hexagon::writePltHeader(uint8_t *Buf) const {
263 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 } # call dynamic linker262 0x00, 0xc0, 0x9c, 0x52, // jumpr r28 } # call dynamic linker
264 0x0c, 0xdb, 0x00, 0x54, // trap0(#0xdb) # bring plt0 into 16byte alignment263 0x0c, 0xdb, 0x00, 0x54, // trap0(#0xdb) # bring plt0 into 16byte alignment
265 };264 };
266 memcpy(Buf, PltData, sizeof(PltData));265 memcpy(buf, pltData, sizeof(pltData));
267266
268 // Offset from PLT0 to the GOT.267 // Offset from PLT0 to the GOT.
269 uint64_t Off = In.GotPlt->getVA() - In.Plt->getVA();268 uint64_t off = in.gotPlt->getVA() - in.plt->getVA();
270 relocateOne(Buf, R_HEX_B32_PCREL_X, Off);269 relocateOne(buf, R_HEX_B32_PCREL_X, off);
271 relocateOne(Buf + 4, R_HEX_6_PCREL_X, Off);270 relocateOne(buf + 4, R_HEX_6_PCREL_X, off);
272}271}
273272
274void Hexagon::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,273void Hexagon::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
275 uint64_t PltEntryAddr, int32_t Index,274 uint64_t pltEntryAddr, int32_t index,
276 unsigned RelOff) const {275 unsigned relOff) const {
277 const uint8_t Inst[] = {276 const uint8_t inst[] = {
278 0x00, 0x40, 0x00, 0x00, // { immext (#0)277 0x00, 0x40, 0x00, 0x00, // { immext (#0)
279 0x0e, 0xc0, 0x49, 0x6a, // r14 = add (pc, ##GOTn@PCREL) }278 0x0e, 0xc0, 0x49, 0x6a, // r14 = add (pc, ##GOTn@PCREL) }
280 0x1c, 0xc0, 0x8e, 0x91, // r28 = memw (r14)279 0x1c, 0xc0, 0x8e, 0x91, // r28 = memw (r14)
281 0x00, 0xc0, 0x9c, 0x52, // jumpr r28280 0x00, 0xc0, 0x9c, 0x52, // jumpr r28
282 };281 };
283 memcpy(Buf, Inst, sizeof(Inst));282 memcpy(buf, inst, sizeof(inst));
284283
285 relocateOne(Buf, R_HEX_B32_PCREL_X, GotPltEntryAddr - PltEntryAddr);284 relocateOne(buf, R_HEX_B32_PCREL_X, gotPltEntryAddr - pltEntryAddr);
286 relocateOne(Buf + 4, R_HEX_6_PCREL_X, GotPltEntryAddr - PltEntryAddr);285 relocateOne(buf + 4, R_HEX_6_PCREL_X, gotPltEntryAddr - pltEntryAddr);
287}286}
288287
289TargetInfo *elf::getHexagonTargetInfo() {288TargetInfo *elf::getHexagonTargetInfo() {
290 static Hexagon Target;289 static Hexagon target;
291 return &Target;290 return &target;
292}291}
deps/lld/ELF/Arch/MSP430.cpp+24-25
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MSP430.cpp ---------------------------------------------------------===//1//===- MSP430.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -34,20 +33,20 @@ namespace {...@@ -34,20 +33,20 @@ namespace {
34class MSP430 final : public TargetInfo {33class MSP430 final : public TargetInfo {
35public:34public:
36 MSP430();35 MSP430();
37 RelExpr getRelExpr(RelType Type, const Symbol &S,36 RelExpr getRelExpr(RelType type, const Symbol &s,
38 const uint8_t *Loc) const override;37 const uint8_t *loc) const override;
39 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;38 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
40};39};
41} // namespace40} // namespace
4241
43MSP430::MSP430() {42MSP430::MSP430() {
44 // mov.b #0, r343 // mov.b #0, r3
45 TrapInstr = {0x43, 0x43, 0x43, 0x43};44 trapInstr = {0x43, 0x43, 0x43, 0x43};
46}45}
4746
48RelExpr MSP430::getRelExpr(RelType Type, const Symbol &S,47RelExpr MSP430::getRelExpr(RelType type, const Symbol &s,
49 const uint8_t *Loc) const {48 const uint8_t *loc) const {
50 switch (Type) {49 switch (type) {
51 case R_MSP430_10_PCREL:50 case R_MSP430_10_PCREL:
52 case R_MSP430_16_PCREL:51 case R_MSP430_16_PCREL:
53 case R_MSP430_16_PCREL_BYTE:52 case R_MSP430_16_PCREL_BYTE:
...@@ -60,35 +59,35 @@ RelExpr MSP430::getRelExpr(RelType Type, const Symbol &S,...@@ -60,35 +59,35 @@ RelExpr MSP430::getRelExpr(RelType Type, const Symbol &S,
60 }59 }
61}60}
6261
63void MSP430::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {62void MSP430::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
64 switch (Type) {63 switch (type) {
65 case R_MSP430_8:64 case R_MSP430_8:
66 checkIntUInt(Loc, Val, 8, Type);65 checkIntUInt(loc, val, 8, type);
67 *Loc = Val;66 *loc = val;
68 break;67 break;
69 case R_MSP430_16:68 case R_MSP430_16:
70 case R_MSP430_16_PCREL:69 case R_MSP430_16_PCREL:
71 case R_MSP430_16_BYTE:70 case R_MSP430_16_BYTE:
72 case R_MSP430_16_PCREL_BYTE:71 case R_MSP430_16_PCREL_BYTE:
73 checkIntUInt(Loc, Val, 16, Type);72 checkIntUInt(loc, val, 16, type);
74 write16le(Loc, Val);73 write16le(loc, val);
75 break;74 break;
76 case R_MSP430_32:75 case R_MSP430_32:
77 checkIntUInt(Loc, Val, 32, Type);76 checkIntUInt(loc, val, 32, type);
78 write32le(Loc, Val);77 write32le(loc, val);
79 break;78 break;
80 case R_MSP430_10_PCREL: {79 case R_MSP430_10_PCREL: {
81 int16_t Offset = ((int16_t)Val >> 1) - 1;80 int16_t offset = ((int16_t)val >> 1) - 1;
82 checkInt(Loc, Offset, 10, Type);81 checkInt(loc, offset, 10, type);
83 write16le(Loc, (read16le(Loc) & 0xFC00) | (Offset & 0x3FF));82 write16le(loc, (read16le(loc) & 0xFC00) | (offset & 0x3FF));
84 break;83 break;
85 }84 }
86 default:85 default:
87 error(getErrorLocation(Loc) + "unrecognized reloc " + toString(Type));86 error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
88 }87 }
89}88}
9089
91TargetInfo *elf::getMSP430TargetInfo() {90TargetInfo *elf::getMSP430TargetInfo() {
92 static MSP430 Target;91 static MSP430 target;
93 return &Target;92 return &target;
94}93}
deps/lld/ELF/Arch/Mips.cpp+336-271
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MIPS.cpp -----------------------------------------------------------===//1//===- MIPS.cpp -----------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -29,47 +28,47 @@ template <class ELFT> class MIPS final : public TargetInfo {...@@ -29,47 +28,47 @@ template <class ELFT> class MIPS final : public TargetInfo {
29public:28public:
30 MIPS();29 MIPS();
31 uint32_t calcEFlags() const override;30 uint32_t calcEFlags() const override;
32 RelExpr getRelExpr(RelType Type, const Symbol &S,31 RelExpr getRelExpr(RelType type, const Symbol &s,
33 const uint8_t *Loc) const override;32 const uint8_t *loc) const override;
34 int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override;33 int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
35 RelType getDynRel(RelType Type) const override;34 RelType getDynRel(RelType type) const override;
36 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;35 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
37 void writePltHeader(uint8_t *Buf) const override;36 void writePltHeader(uint8_t *buf) const override;
38 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,37 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
39 int32_t Index, unsigned RelOff) const override;38 int32_t index, unsigned relOff) const override;
40 bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File,39 bool needsThunk(RelExpr expr, RelType type, const InputFile *file,
41 uint64_t BranchAddr, const Symbol &S) const override;40 uint64_t branchAddr, const Symbol &s) const override;
42 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;41 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
43 bool usesOnlyLowPageBits(RelType Type) const override;42 bool usesOnlyLowPageBits(RelType type) const override;
44};43};
45} // namespace44} // namespace
4645
47template <class ELFT> MIPS<ELFT>::MIPS() {46template <class ELFT> MIPS<ELFT>::MIPS() {
48 GotPltHeaderEntriesNum = 2;47 gotPltHeaderEntriesNum = 2;
49 DefaultMaxPageSize = 65536;48 defaultMaxPageSize = 65536;
50 GotEntrySize = sizeof(typename ELFT::uint);49 gotBaseSymInGotPlt = false;
51 GotPltEntrySize = sizeof(typename ELFT::uint);50 pltEntrySize = 16;
52 GotBaseSymInGotPlt = false;51 pltHeaderSize = 32;
53 PltEntrySize = 16;52 copyRel = R_MIPS_COPY;
54 PltHeaderSize = 32;53 noneRel = R_MIPS_NONE;
55 CopyRel = R_MIPS_COPY;54 pltRel = R_MIPS_JUMP_SLOT;
56 NoneRel = R_MIPS_NONE;55 needsThunks = true;
57 PltRel = R_MIPS_JUMP_SLOT;
58 NeedsThunks = true;
5956
60 // Set `sigrie 1` as a trap instruction.57 // Set `sigrie 1` as a trap instruction.
61 write32(TrapInstr.data(), 0x04170001);58 write32(trapInstr.data(), 0x04170001);
6259
63 if (ELFT::Is64Bits) {60 if (ELFT::Is64Bits) {
64 RelativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32;61 relativeRel = (R_MIPS_64 << 8) | R_MIPS_REL32;
65 TlsGotRel = R_MIPS_TLS_TPREL64;62 symbolicRel = R_MIPS_64;
66 TlsModuleIndexRel = R_MIPS_TLS_DTPMOD64;63 tlsGotRel = R_MIPS_TLS_TPREL64;
67 TlsOffsetRel = R_MIPS_TLS_DTPREL64;64 tlsModuleIndexRel = R_MIPS_TLS_DTPMOD64;
65 tlsOffsetRel = R_MIPS_TLS_DTPREL64;
68 } else {66 } else {
69 RelativeRel = R_MIPS_REL32;67 relativeRel = R_MIPS_REL32;
70 TlsGotRel = R_MIPS_TLS_TPREL32;68 symbolicRel = R_MIPS_32;
71 TlsModuleIndexRel = R_MIPS_TLS_DTPMOD32;69 tlsGotRel = R_MIPS_TLS_TPREL32;
72 TlsOffsetRel = R_MIPS_TLS_DTPREL32;70 tlsModuleIndexRel = R_MIPS_TLS_DTPMOD32;
71 tlsOffsetRel = R_MIPS_TLS_DTPREL32;
73 }72 }
74}73}
7574
...@@ -78,13 +77,13 @@ template <class ELFT> uint32_t MIPS<ELFT>::calcEFlags() const {...@@ -78,13 +77,13 @@ template <class ELFT> uint32_t MIPS<ELFT>::calcEFlags() const {
78}77}
7978
80template <class ELFT>79template <class ELFT>
81RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,80RelExpr MIPS<ELFT>::getRelExpr(RelType type, const Symbol &s,
82 const uint8_t *Loc) const {81 const uint8_t *loc) const {
83 // See comment in the calculateMipsRelChain.82 // See comment in the calculateMipsRelChain.
84 if (ELFT::Is64Bits || Config->MipsN32Abi)83 if (ELFT::Is64Bits || config->mipsN32Abi)
85 Type &= 0xff;84 type &= 0xff;
8685
87 switch (Type) {86 switch (type) {
88 case R_MIPS_JALR:87 case R_MIPS_JALR:
89 case R_MICROMIPS_JALR:88 case R_MICROMIPS_JALR:
90 return R_HINT;89 return R_HINT;
...@@ -108,9 +107,9 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,...@@ -108,9 +107,9 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,
108 // offset between start of function and 'gp' value which by default107 // offset between start of function and 'gp' value which by default
109 // equal to the start of .got section. In that case we consider these108 // equal to the start of .got section. In that case we consider these
110 // relocations as relative.109 // relocations as relative.
111 if (&S == ElfSym::MipsGpDisp)110 if (&s == ElfSym::mipsGpDisp)
112 return R_MIPS_GOT_GP_PC;111 return R_MIPS_GOT_GP_PC;
113 if (&S == ElfSym::MipsLocalGp)112 if (&s == ElfSym::mipsLocalGp)
114 return R_MIPS_GOT_GP;113 return R_MIPS_GOT_GP;
115 LLVM_FALLTHROUGH;114 LLVM_FALLTHROUGH;
116 case R_MIPS_32:115 case R_MIPS_32:
...@@ -147,7 +146,7 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,...@@ -147,7 +146,7 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,
147 return R_PC;146 return R_PC;
148 case R_MIPS_GOT16:147 case R_MIPS_GOT16:
149 case R_MICROMIPS_GOT16:148 case R_MICROMIPS_GOT16:
150 if (S.isLocal())149 if (s.isLocal())
151 return R_MIPS_GOT_LOCAL_PAGE;150 return R_MIPS_GOT_LOCAL_PAGE;
152 LLVM_FALLTHROUGH;151 LLVM_FALLTHROUGH;
153 case R_MIPS_CALL16:152 case R_MIPS_CALL16:
...@@ -176,209 +175,213 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,...@@ -176,209 +175,213 @@ RelExpr MIPS<ELFT>::getRelExpr(RelType Type, const Symbol &S,
176 case R_MIPS_NONE:175 case R_MIPS_NONE:
177 return R_NONE;176 return R_NONE;
178 default:177 default:
179 return R_INVALID;178 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
179 ") against symbol " + toString(s));
180 return R_NONE;
180 }181 }
181}182}
182183
183template <class ELFT> RelType MIPS<ELFT>::getDynRel(RelType Type) const {184template <class ELFT> RelType MIPS<ELFT>::getDynRel(RelType type) const {
184 if (Type == R_MIPS_32 || Type == R_MIPS_64)185 if (type == symbolicRel)
185 return RelativeRel;186 return type;
186 return R_MIPS_NONE;187 return R_MIPS_NONE;
187}188}
188189
189template <class ELFT>190template <class ELFT>
190void MIPS<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &) const {191void MIPS<ELFT>::writeGotPlt(uint8_t *buf, const Symbol &) const {
191 uint64_t VA = In.Plt->getVA();192 uint64_t va = in.plt->getVA();
192 if (isMicroMips())193 if (isMicroMips())
193 VA |= 1;194 va |= 1;
194 write32<ELFT::TargetEndianness>(Buf, VA);195 write32<ELFT::TargetEndianness>(buf, va);
195}196}
196197
197template <endianness E> static uint32_t readShuffle(const uint8_t *Loc) {198template <endianness E> static uint32_t readShuffle(const uint8_t *loc) {
198 // The major opcode of a microMIPS instruction needs to appear199 // The major opcode of a microMIPS instruction needs to appear
199 // in the first 16-bit word (lowest address) for efficient hardware200 // in the first 16-bit word (lowest address) for efficient hardware
200 // decode so that it knows if the instruction is 16-bit or 32-bit201 // decode so that it knows if the instruction is 16-bit or 32-bit
201 // as early as possible. To do so, little-endian binaries keep 16-bit202 // as early as possible. To do so, little-endian binaries keep 16-bit
202 // words in a big-endian order. That is why we have to swap these203 // words in a big-endian order. That is why we have to swap these
203 // words to get a correct value.204 // words to get a correct value.
204 uint32_t V = read32<E>(Loc);205 uint32_t v = read32<E>(loc);
205 if (E == support::little)206 if (E == support::little)
206 return (V << 16) | (V >> 16);207 return (v << 16) | (v >> 16);
207 return V;208 return v;
208}209}
209210
210template <endianness E>211template <endianness E>
211static void writeValue(uint8_t *Loc, uint64_t V, uint8_t BitsSize,212static void writeValue(uint8_t *loc, uint64_t v, uint8_t bitsSize,
212 uint8_t Shift) {213 uint8_t shift) {
213 uint32_t Instr = read32<E>(Loc);214 uint32_t instr = read32<E>(loc);
214 uint32_t Mask = 0xffffffff >> (32 - BitsSize);215 uint32_t mask = 0xffffffff >> (32 - bitsSize);
215 uint32_t Data = (Instr & ~Mask) | ((V >> Shift) & Mask);216 uint32_t data = (instr & ~mask) | ((v >> shift) & mask);
216 write32<E>(Loc, Data);217 write32<E>(loc, data);
217}218}
218219
219template <endianness E>220template <endianness E>
220static void writeShuffleValue(uint8_t *Loc, uint64_t V, uint8_t BitsSize,221static void writeShuffleValue(uint8_t *loc, uint64_t v, uint8_t bitsSize,
221 uint8_t Shift) {222 uint8_t shift) {
222 // See comments in readShuffle for purpose of this code.223 // See comments in readShuffle for purpose of this code.
223 uint16_t *Words = (uint16_t *)Loc;224 uint16_t *words = (uint16_t *)loc;
224 if (E == support::little)225 if (E == support::little)
225 std::swap(Words[0], Words[1]);226 std::swap(words[0], words[1]);
226227
227 writeValue<E>(Loc, V, BitsSize, Shift);228 writeValue<E>(loc, v, bitsSize, shift);
228229
229 if (E == support::little)230 if (E == support::little)
230 std::swap(Words[0], Words[1]);231 std::swap(words[0], words[1]);
231}232}
232233
233template <endianness E>234template <endianness E>
234static void writeMicroRelocation16(uint8_t *Loc, uint64_t V, uint8_t BitsSize,235static void writeMicroRelocation16(uint8_t *loc, uint64_t v, uint8_t bitsSize,
235 uint8_t Shift) {236 uint8_t shift) {
236 uint16_t Instr = read16<E>(Loc);237 uint16_t instr = read16<E>(loc);
237 uint16_t Mask = 0xffff >> (16 - BitsSize);238 uint16_t mask = 0xffff >> (16 - bitsSize);
238 uint16_t Data = (Instr & ~Mask) | ((V >> Shift) & Mask);239 uint16_t data = (instr & ~mask) | ((v >> shift) & mask);
239 write16<E>(Loc, Data);240 write16<E>(loc, data);
240}241}
241242
242template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *Buf) const {243template <class ELFT> void MIPS<ELFT>::writePltHeader(uint8_t *buf) const {
243 const endianness E = ELFT::TargetEndianness;244 const endianness e = ELFT::TargetEndianness;
244 if (isMicroMips()) {245 if (isMicroMips()) {
245 uint64_t GotPlt = In.GotPlt->getVA();246 uint64_t gotPlt = in.gotPlt->getVA();
246 uint64_t Plt = In.Plt->getVA();247 uint64_t plt = in.plt->getVA();
247 // Overwrite trap instructions written by Writer::writeTrapInstr.248 // Overwrite trap instructions written by Writer::writeTrapInstr.
248 memset(Buf, 0, PltHeaderSize);249 memset(buf, 0, pltHeaderSize);
249250
250 write16<E>(Buf, isMipsR6() ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - .251 write16<e>(buf, isMipsR6() ? 0x7860 : 0x7980); // addiupc v1, (GOTPLT) - .
251 write16<E>(Buf + 4, 0xff23); // lw $25, 0($3)252 write16<e>(buf + 4, 0xff23); // lw $25, 0($3)
252 write16<E>(Buf + 8, 0x0535); // subu16 $2, $2, $3253 write16<e>(buf + 8, 0x0535); // subu16 $2, $2, $3
253 write16<E>(Buf + 10, 0x2525); // srl16 $2, $2, 2254 write16<e>(buf + 10, 0x2525); // srl16 $2, $2, 2
254 write16<E>(Buf + 12, 0x3302); // addiu $24, $2, -2255 write16<e>(buf + 12, 0x3302); // addiu $24, $2, -2
255 write16<E>(Buf + 14, 0xfffe);256 write16<e>(buf + 14, 0xfffe);
256 write16<E>(Buf + 16, 0x0dff); // move $15, $31257 write16<e>(buf + 16, 0x0dff); // move $15, $31
257 if (isMipsR6()) {258 if (isMipsR6()) {
258 write16<E>(Buf + 18, 0x0f83); // move $28, $3259 write16<e>(buf + 18, 0x0f83); // move $28, $3
259 write16<E>(Buf + 20, 0x472b); // jalrc $25260 write16<e>(buf + 20, 0x472b); // jalrc $25
260 write16<E>(Buf + 22, 0x0c00); // nop261 write16<e>(buf + 22, 0x0c00); // nop
261 relocateOne(Buf, R_MICROMIPS_PC19_S2, GotPlt - Plt);262 relocateOne(buf, R_MICROMIPS_PC19_S2, gotPlt - plt);
262 } else {263 } else {
263 write16<E>(Buf + 18, 0x45f9); // jalrc $25264 write16<e>(buf + 18, 0x45f9); // jalrc $25
264 write16<E>(Buf + 20, 0x0f83); // move $28, $3265 write16<e>(buf + 20, 0x0f83); // move $28, $3
265 write16<E>(Buf + 22, 0x0c00); // nop266 write16<e>(buf + 22, 0x0c00); // nop
266 relocateOne(Buf, R_MICROMIPS_PC23_S2, GotPlt - Plt);267 relocateOne(buf, R_MICROMIPS_PC23_S2, gotPlt - plt);
267 }268 }
268 return;269 return;
269 }270 }
270271
271 if (Config->MipsN32Abi) {272 if (config->mipsN32Abi) {
272 write32<E>(Buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0])273 write32<e>(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0])
273 write32<E>(Buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14)274 write32<e>(buf + 4, 0x8dd90000); // lw $25, %lo(&GOTPLT[0])($14)
274 write32<E>(Buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0])275 write32<e>(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0])
275 write32<E>(Buf + 12, 0x030ec023); // subu $24, $24, $14276 write32<e>(buf + 12, 0x030ec023); // subu $24, $24, $14
276 write32<E>(Buf + 16, 0x03e07825); // move $15, $31277 write32<e>(buf + 16, 0x03e07825); // move $15, $31
277 write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2278 write32<e>(buf + 20, 0x0018c082); // srl $24, $24, 2
278 } else if (ELFT::Is64Bits) {279 } else if (ELFT::Is64Bits) {
279 write32<E>(Buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0])280 write32<e>(buf, 0x3c0e0000); // lui $14, %hi(&GOTPLT[0])
280 write32<E>(Buf + 4, 0xddd90000); // ld $25, %lo(&GOTPLT[0])($14)281 write32<e>(buf + 4, 0xddd90000); // ld $25, %lo(&GOTPLT[0])($14)
281 write32<E>(Buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0])282 write32<e>(buf + 8, 0x25ce0000); // addiu $14, $14, %lo(&GOTPLT[0])
282 write32<E>(Buf + 12, 0x030ec023); // subu $24, $24, $14283 write32<e>(buf + 12, 0x030ec023); // subu $24, $24, $14
283 write32<E>(Buf + 16, 0x03e07825); // move $15, $31284 write32<e>(buf + 16, 0x03e07825); // move $15, $31
284 write32<E>(Buf + 20, 0x0018c0c2); // srl $24, $24, 3285 write32<e>(buf + 20, 0x0018c0c2); // srl $24, $24, 3
285 } else {286 } else {
286 write32<E>(Buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0])287 write32<e>(buf, 0x3c1c0000); // lui $28, %hi(&GOTPLT[0])
287 write32<E>(Buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28)288 write32<e>(buf + 4, 0x8f990000); // lw $25, %lo(&GOTPLT[0])($28)
288 write32<E>(Buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0])289 write32<e>(buf + 8, 0x279c0000); // addiu $28, $28, %lo(&GOTPLT[0])
289 write32<E>(Buf + 12, 0x031cc023); // subu $24, $24, $28290 write32<e>(buf + 12, 0x031cc023); // subu $24, $24, $28
290 write32<E>(Buf + 16, 0x03e07825); // move $15, $31291 write32<e>(buf + 16, 0x03e07825); // move $15, $31
291 write32<E>(Buf + 20, 0x0018c082); // srl $24, $24, 2292 write32<e>(buf + 20, 0x0018c082); // srl $24, $24, 2
292 }293 }
293294
294 uint32_t JalrInst = Config->ZHazardplt ? 0x0320fc09 : 0x0320f809;295 uint32_t jalrInst = config->zHazardplt ? 0x0320fc09 : 0x0320f809;
295 write32<E>(Buf + 24, JalrInst); // jalr.hb $25 or jalr $25296 write32<e>(buf + 24, jalrInst); // jalr.hb $25 or jalr $25
296 write32<E>(Buf + 28, 0x2718fffe); // subu $24, $24, 2297 write32<e>(buf + 28, 0x2718fffe); // subu $24, $24, 2
297298
298 uint64_t GotPlt = In.GotPlt->getVA();299 uint64_t gotPlt = in.gotPlt->getVA();
299 writeValue<E>(Buf, GotPlt + 0x8000, 16, 16);300 writeValue<e>(buf, gotPlt + 0x8000, 16, 16);
300 writeValue<E>(Buf + 4, GotPlt, 16, 0);301 writeValue<e>(buf + 4, gotPlt, 16, 0);
301 writeValue<E>(Buf + 8, GotPlt, 16, 0);302 writeValue<e>(buf + 8, gotPlt, 16, 0);
302}303}
303304
304template <class ELFT>305template <class ELFT>
305void MIPS<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,306void MIPS<ELFT>::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
306 uint64_t PltEntryAddr, int32_t Index,307 uint64_t pltEntryAddr, int32_t index,
307 unsigned RelOff) const {308 unsigned relOff) const {
308 const endianness E = ELFT::TargetEndianness;309 const endianness e = ELFT::TargetEndianness;
309 if (isMicroMips()) {310 if (isMicroMips()) {
310 // Overwrite trap instructions written by Writer::writeTrapInstr.311 // Overwrite trap instructions written by Writer::writeTrapInstr.
311 memset(Buf, 0, PltEntrySize);312 memset(buf, 0, pltEntrySize);
312313
313 if (isMipsR6()) {314 if (isMipsR6()) {
314 write16<E>(Buf, 0x7840); // addiupc $2, (GOTPLT) - .315 write16<e>(buf, 0x7840); // addiupc $2, (GOTPLT) - .
315 write16<E>(Buf + 4, 0xff22); // lw $25, 0($2)316 write16<e>(buf + 4, 0xff22); // lw $25, 0($2)
316 write16<E>(Buf + 8, 0x0f02); // move $24, $2317 write16<e>(buf + 8, 0x0f02); // move $24, $2
317 write16<E>(Buf + 10, 0x4723); // jrc $25 / jr16 $25318 write16<e>(buf + 10, 0x4723); // jrc $25 / jr16 $25
318 relocateOne(Buf, R_MICROMIPS_PC19_S2, GotPltEntryAddr - PltEntryAddr);319 relocateOne(buf, R_MICROMIPS_PC19_S2, gotPltEntryAddr - pltEntryAddr);
319 } else {320 } else {
320 write16<E>(Buf, 0x7900); // addiupc $2, (GOTPLT) - .321 write16<e>(buf, 0x7900); // addiupc $2, (GOTPLT) - .
321 write16<E>(Buf + 4, 0xff22); // lw $25, 0($2)322 write16<e>(buf + 4, 0xff22); // lw $25, 0($2)
322 write16<E>(Buf + 8, 0x4599); // jrc $25 / jr16 $25323 write16<e>(buf + 8, 0x4599); // jrc $25 / jr16 $25
323 write16<E>(Buf + 10, 0x0f02); // move $24, $2324 write16<e>(buf + 10, 0x0f02); // move $24, $2
324 relocateOne(Buf, R_MICROMIPS_PC23_S2, GotPltEntryAddr - PltEntryAddr);325 relocateOne(buf, R_MICROMIPS_PC23_S2, gotPltEntryAddr - pltEntryAddr);
325 }326 }
326 return;327 return;
327 }328 }
328329
329 uint32_t JrInst = isMipsR6() ? (Config->ZHazardplt ? 0x03200409 : 0x03200009)330 uint32_t loadInst = ELFT::Is64Bits ? 0xddf90000 : 0x8df90000;
330 : (Config->ZHazardplt ? 0x03200408 : 0x03200008);331 uint32_t jrInst = isMipsR6() ? (config->zHazardplt ? 0x03200409 : 0x03200009)
331332 : (config->zHazardplt ? 0x03200408 : 0x03200008);
332 write32<E>(Buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry)333 uint32_t addInst = ELFT::Is64Bits ? 0x65f80000 : 0x25f80000;
333 write32<E>(Buf + 4, 0x8df90000); // l[wd] $25, %lo(.got.plt entry)($15)334
334 write32<E>(Buf + 8, JrInst); // jr $25 / jr.hb $25335 write32<e>(buf, 0x3c0f0000); // lui $15, %hi(.got.plt entry)
335 write32<E>(Buf + 12, 0x25f80000); // addiu $24, $15, %lo(.got.plt entry)336 write32<e>(buf + 4, loadInst); // l[wd] $25, %lo(.got.plt entry)($15)
336 writeValue<E>(Buf, GotPltEntryAddr + 0x8000, 16, 16);337 write32<e>(buf + 8, jrInst); // jr $25 / jr.hb $25
337 writeValue<E>(Buf + 4, GotPltEntryAddr, 16, 0);338 write32<e>(buf + 12, addInst); // [d]addiu $24, $15, %lo(.got.plt entry)
338 writeValue<E>(Buf + 12, GotPltEntryAddr, 16, 0);339 writeValue<e>(buf, gotPltEntryAddr + 0x8000, 16, 16);
340 writeValue<e>(buf + 4, gotPltEntryAddr, 16, 0);
341 writeValue<e>(buf + 12, gotPltEntryAddr, 16, 0);
339}342}
340343
341template <class ELFT>344template <class ELFT>
342bool MIPS<ELFT>::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,345bool MIPS<ELFT>::needsThunk(RelExpr expr, RelType type, const InputFile *file,
343 uint64_t BranchAddr, const Symbol &S) const {346 uint64_t branchAddr, const Symbol &s) const {
344 // Any MIPS PIC code function is invoked with its address in register $t9.347 // Any MIPS PIC code function is invoked with its address in register $t9.
345 // So if we have a branch instruction from non-PIC code to the PIC one348 // So if we have a branch instruction from non-PIC code to the PIC one
346 // we cannot make the jump directly and need to create a small stubs349 // we cannot make the jump directly and need to create a small stubs
347 // to save the target function address.350 // to save the target function address.
348 // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf351 // See page 3-38 ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
349 if (Type != R_MIPS_26 && Type != R_MICROMIPS_26_S1 &&352 if (type != R_MIPS_26 && type != R_MIPS_PC26_S2 &&
350 Type != R_MICROMIPS_PC26_S1)353 type != R_MICROMIPS_26_S1 && type != R_MICROMIPS_PC26_S1)
351 return false;354 return false;
352 auto *F = dyn_cast_or_null<ELFFileBase<ELFT>>(File);355 auto *f = dyn_cast_or_null<ObjFile<ELFT>>(file);
353 if (!F)356 if (!f)
354 return false;357 return false;
355 // If current file has PIC code, LA25 stub is not required.358 // If current file has PIC code, LA25 stub is not required.
356 if (F->getObj().getHeader()->e_flags & EF_MIPS_PIC)359 if (f->getObj().getHeader()->e_flags & EF_MIPS_PIC)
357 return false;360 return false;
358 auto *D = dyn_cast<Defined>(&S);361 auto *d = dyn_cast<Defined>(&s);
359 // LA25 is required if target file has PIC code362 // LA25 is required if target file has PIC code
360 // or target symbol is a PIC symbol.363 // or target symbol is a PIC symbol.
361 return D && isMipsPIC<ELFT>(D);364 return d && isMipsPIC<ELFT>(d);
362}365}
363366
364template <class ELFT>367template <class ELFT>
365int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, RelType Type) const {368int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *buf, RelType type) const {
366 const endianness E = ELFT::TargetEndianness;369 const endianness e = ELFT::TargetEndianness;
367 switch (Type) {370 switch (type) {
368 case R_MIPS_32:371 case R_MIPS_32:
369 case R_MIPS_GPREL32:372 case R_MIPS_GPREL32:
370 case R_MIPS_TLS_DTPREL32:373 case R_MIPS_TLS_DTPREL32:
371 case R_MIPS_TLS_TPREL32:374 case R_MIPS_TLS_TPREL32:
372 return SignExtend64<32>(read32<E>(Buf));375 return SignExtend64<32>(read32<e>(buf));
373 case R_MIPS_26:376 case R_MIPS_26:
374 // FIXME (simon): If the relocation target symbol is not a PLT entry377 // FIXME (simon): If the relocation target symbol is not a PLT entry
375 // we should use another expression for calculation:378 // we should use another expression for calculation:
376 // ((A << 2) | (P & 0xf0000000)) >> 2379 // ((A << 2) | (P & 0xf0000000)) >> 2
377 return SignExtend64<28>(read32<E>(Buf) << 2);380 return SignExtend64<28>(read32<e>(buf) << 2);
378 case R_MIPS_GOT16:381 case R_MIPS_GOT16:
379 case R_MIPS_HI16:382 case R_MIPS_HI16:
380 case R_MIPS_PCHI16:383 case R_MIPS_PCHI16:
381 return SignExtend64<16>(read32<E>(Buf)) << 16;384 return SignExtend64<16>(read32<e>(buf)) << 16;
382 case R_MIPS_GPREL16:385 case R_MIPS_GPREL16:
383 case R_MIPS_LO16:386 case R_MIPS_LO16:
384 case R_MIPS_PCLO16:387 case R_MIPS_PCLO16:
...@@ -386,54 +389,54 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, RelType Type) const {...@@ -386,54 +389,54 @@ int64_t MIPS<ELFT>::getImplicitAddend(const uint8_t *Buf, RelType Type) const {
386 case R_MIPS_TLS_DTPREL_LO16:389 case R_MIPS_TLS_DTPREL_LO16:
387 case R_MIPS_TLS_TPREL_HI16:390 case R_MIPS_TLS_TPREL_HI16:
388 case R_MIPS_TLS_TPREL_LO16:391 case R_MIPS_TLS_TPREL_LO16:
389 return SignExtend64<16>(read32<E>(Buf));392 return SignExtend64<16>(read32<e>(buf));
390 case R_MICROMIPS_GOT16:393 case R_MICROMIPS_GOT16:
391 case R_MICROMIPS_HI16:394 case R_MICROMIPS_HI16:
392 return SignExtend64<16>(readShuffle<E>(Buf)) << 16;395 return SignExtend64<16>(readShuffle<e>(buf)) << 16;
393 case R_MICROMIPS_GPREL16:396 case R_MICROMIPS_GPREL16:
394 case R_MICROMIPS_LO16:397 case R_MICROMIPS_LO16:
395 case R_MICROMIPS_TLS_DTPREL_HI16:398 case R_MICROMIPS_TLS_DTPREL_HI16:
396 case R_MICROMIPS_TLS_DTPREL_LO16:399 case R_MICROMIPS_TLS_DTPREL_LO16:
397 case R_MICROMIPS_TLS_TPREL_HI16:400 case R_MICROMIPS_TLS_TPREL_HI16:
398 case R_MICROMIPS_TLS_TPREL_LO16:401 case R_MICROMIPS_TLS_TPREL_LO16:
399 return SignExtend64<16>(readShuffle<E>(Buf));402 return SignExtend64<16>(readShuffle<e>(buf));
400 case R_MICROMIPS_GPREL7_S2:403 case R_MICROMIPS_GPREL7_S2:
401 return SignExtend64<9>(readShuffle<E>(Buf) << 2);404 return SignExtend64<9>(readShuffle<e>(buf) << 2);
402 case R_MIPS_PC16:405 case R_MIPS_PC16:
403 return SignExtend64<18>(read32<E>(Buf) << 2);406 return SignExtend64<18>(read32<e>(buf) << 2);
404 case R_MIPS_PC19_S2:407 case R_MIPS_PC19_S2:
405 return SignExtend64<21>(read32<E>(Buf) << 2);408 return SignExtend64<21>(read32<e>(buf) << 2);
406 case R_MIPS_PC21_S2:409 case R_MIPS_PC21_S2:
407 return SignExtend64<23>(read32<E>(Buf) << 2);410 return SignExtend64<23>(read32<e>(buf) << 2);
408 case R_MIPS_PC26_S2:411 case R_MIPS_PC26_S2:
409 return SignExtend64<28>(read32<E>(Buf) << 2);412 return SignExtend64<28>(read32<e>(buf) << 2);
410 case R_MIPS_PC32:413 case R_MIPS_PC32:
411 return SignExtend64<32>(read32<E>(Buf));414 return SignExtend64<32>(read32<e>(buf));
412 case R_MICROMIPS_26_S1:415 case R_MICROMIPS_26_S1:
413 return SignExtend64<27>(readShuffle<E>(Buf) << 1);416 return SignExtend64<27>(readShuffle<e>(buf) << 1);
414 case R_MICROMIPS_PC7_S1:417 case R_MICROMIPS_PC7_S1:
415 return SignExtend64<8>(read16<E>(Buf) << 1);418 return SignExtend64<8>(read16<e>(buf) << 1);
416 case R_MICROMIPS_PC10_S1:419 case R_MICROMIPS_PC10_S1:
417 return SignExtend64<11>(read16<E>(Buf) << 1);420 return SignExtend64<11>(read16<e>(buf) << 1);
418 case R_MICROMIPS_PC16_S1:421 case R_MICROMIPS_PC16_S1:
419 return SignExtend64<17>(readShuffle<E>(Buf) << 1);422 return SignExtend64<17>(readShuffle<e>(buf) << 1);
420 case R_MICROMIPS_PC18_S3:423 case R_MICROMIPS_PC18_S3:
421 return SignExtend64<21>(readShuffle<E>(Buf) << 3);424 return SignExtend64<21>(readShuffle<e>(buf) << 3);
422 case R_MICROMIPS_PC19_S2:425 case R_MICROMIPS_PC19_S2:
423 return SignExtend64<21>(readShuffle<E>(Buf) << 2);426 return SignExtend64<21>(readShuffle<e>(buf) << 2);
424 case R_MICROMIPS_PC21_S1:427 case R_MICROMIPS_PC21_S1:
425 return SignExtend64<22>(readShuffle<E>(Buf) << 1);428 return SignExtend64<22>(readShuffle<e>(buf) << 1);
426 case R_MICROMIPS_PC23_S2:429 case R_MICROMIPS_PC23_S2:
427 return SignExtend64<25>(readShuffle<E>(Buf) << 2);430 return SignExtend64<25>(readShuffle<e>(buf) << 2);
428 case R_MICROMIPS_PC26_S1:431 case R_MICROMIPS_PC26_S1:
429 return SignExtend64<27>(readShuffle<E>(Buf) << 1);432 return SignExtend64<27>(readShuffle<e>(buf) << 1);
430 default:433 default:
431 return 0;434 return 0;
432 }435 }
433}436}
434437
435static std::pair<uint32_t, uint64_t>438static std::pair<uint32_t, uint64_t>
436calculateMipsRelChain(uint8_t *Loc, RelType Type, uint64_t Val) {439calculateMipsRelChain(uint8_t *loc, RelType type, uint64_t val) {
437 // MIPS N64 ABI packs multiple relocations into the single relocation440 // MIPS N64 ABI packs multiple relocations into the single relocation
438 // record. In general, all up to three relocations can have arbitrary441 // record. In general, all up to three relocations can have arbitrary
439 // types. In fact, Clang and GCC uses only a few combinations. For now,442 // types. In fact, Clang and GCC uses only a few combinations. For now,
...@@ -446,72 +449,134 @@ calculateMipsRelChain(uint8_t *Loc, RelType Type, uint64_t Val) {...@@ -446,72 +449,134 @@ calculateMipsRelChain(uint8_t *Loc, RelType Type, uint64_t Val) {
446 // relocations used to modify result of the first one: extend it to449 // relocations used to modify result of the first one: extend it to
447 // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation450 // 64-bit, extract high or low part etc. For details, see part 2.9 Relocation
448 // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf451 // at the https://dmz-portal.mips.com/mw/images/8/82/007-4658-001.pdf
449 RelType Type2 = (Type >> 8) & 0xff;452 RelType type2 = (type >> 8) & 0xff;
450 RelType Type3 = (Type >> 16) & 0xff;453 RelType type3 = (type >> 16) & 0xff;
451 if (Type2 == R_MIPS_NONE && Type3 == R_MIPS_NONE)454 if (type2 == R_MIPS_NONE && type3 == R_MIPS_NONE)
452 return std::make_pair(Type, Val);455 return std::make_pair(type, val);
453 if (Type2 == R_MIPS_64 && Type3 == R_MIPS_NONE)456 if (type2 == R_MIPS_64 && type3 == R_MIPS_NONE)
454 return std::make_pair(Type2, Val);457 return std::make_pair(type2, val);
455 if (Type2 == R_MIPS_SUB && (Type3 == R_MIPS_HI16 || Type3 == R_MIPS_LO16))458 if (type2 == R_MIPS_SUB && (type3 == R_MIPS_HI16 || type3 == R_MIPS_LO16))
456 return std::make_pair(Type3, -Val);459 return std::make_pair(type3, -val);
457 error(getErrorLocation(Loc) + "unsupported relocations combination " +460 error(getErrorLocation(loc) + "unsupported relocations combination " +
458 Twine(Type));461 Twine(type));
459 return std::make_pair(Type & 0xff, Val);462 return std::make_pair(type & 0xff, val);
463}
464
465static bool isBranchReloc(RelType type) {
466 return type == R_MIPS_26 || type == R_MIPS_PC26_S2 ||
467 type == R_MIPS_PC21_S2 || type == R_MIPS_PC16;
468}
469
470static bool isMicroBranchReloc(RelType type) {
471 return type == R_MICROMIPS_26_S1 || type == R_MICROMIPS_PC16_S1 ||
472 type == R_MICROMIPS_PC10_S1 || type == R_MICROMIPS_PC7_S1;
460}473}
461474
462template <class ELFT>475template <class ELFT>
463void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {476static uint64_t fixupCrossModeJump(uint8_t *loc, RelType type, uint64_t val) {
464 const endianness E = ELFT::TargetEndianness;477 // Here we need to detect jump/branch from regular MIPS code
478 // to a microMIPS target and vice versa. In that cases jump
479 // instructions need to be replaced by their "cross-mode"
480 // equivalents.
481 const endianness e = ELFT::TargetEndianness;
482 bool isMicroTgt = val & 0x1;
483 bool isCrossJump = (isMicroTgt && isBranchReloc(type)) ||
484 (!isMicroTgt && isMicroBranchReloc(type));
485 if (!isCrossJump)
486 return val;
487
488 switch (type) {
489 case R_MIPS_26: {
490 uint32_t inst = read32<e>(loc) >> 26;
491 if (inst == 0x3 || inst == 0x1d) { // JAL or JALX
492 writeValue<e>(loc, 0x1d << 26, 32, 0);
493 return val;
494 }
495 break;
496 }
497 case R_MICROMIPS_26_S1: {
498 uint32_t inst = readShuffle<e>(loc) >> 26;
499 if (inst == 0x3d || inst == 0x3c) { // JAL32 or JALX32
500 val >>= 1;
501 writeShuffleValue<e>(loc, 0x3c << 26, 32, 0);
502 return val;
503 }
504 break;
505 }
506 case R_MIPS_PC26_S2:
507 case R_MIPS_PC21_S2:
508 case R_MIPS_PC16:
509 case R_MICROMIPS_PC16_S1:
510 case R_MICROMIPS_PC10_S1:
511 case R_MICROMIPS_PC7_S1:
512 // FIXME (simon): Support valid branch relocations.
513 break;
514 default:
515 llvm_unreachable("unexpected jump/branch relocation");
516 }
517
518 error(getErrorLocation(loc) +
519 "unsupported jump/branch instruction between ISA modes referenced by " +
520 toString(type) + " relocation");
521 return val;
522}
523
524template <class ELFT>
525void MIPS<ELFT>::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
526 const endianness e = ELFT::TargetEndianness;
527
528 if (ELFT::Is64Bits || config->mipsN32Abi)
529 std::tie(type, val) = calculateMipsRelChain(loc, type, val);
465530
466 if (ELFT::Is64Bits || Config->MipsN32Abi)531 // Detect cross-mode jump/branch and fix instruction.
467 std::tie(Type, Val) = calculateMipsRelChain(Loc, Type, Val);532 val = fixupCrossModeJump<ELFT>(loc, type, val);
468533
469 // Thread pointer and DRP offsets from the start of TLS data area.534 // Thread pointer and DRP offsets from the start of TLS data area.
470 // https://www.linux-mips.org/wiki/NPTL535 // https://www.linux-mips.org/wiki/NPTL
471 if (Type == R_MIPS_TLS_DTPREL_HI16 || Type == R_MIPS_TLS_DTPREL_LO16 ||536 if (type == R_MIPS_TLS_DTPREL_HI16 || type == R_MIPS_TLS_DTPREL_LO16 ||
472 Type == R_MIPS_TLS_DTPREL32 || Type == R_MIPS_TLS_DTPREL64 ||537 type == R_MIPS_TLS_DTPREL32 || type == R_MIPS_TLS_DTPREL64 ||
473 Type == R_MICROMIPS_TLS_DTPREL_HI16 ||538 type == R_MICROMIPS_TLS_DTPREL_HI16 ||
474 Type == R_MICROMIPS_TLS_DTPREL_LO16) {539 type == R_MICROMIPS_TLS_DTPREL_LO16) {
475 Val -= 0x8000;540 val -= 0x8000;
476 } else if (Type == R_MIPS_TLS_TPREL_HI16 || Type == R_MIPS_TLS_TPREL_LO16 ||541 } else if (type == R_MIPS_TLS_TPREL_HI16 || type == R_MIPS_TLS_TPREL_LO16 ||
477 Type == R_MIPS_TLS_TPREL32 || Type == R_MIPS_TLS_TPREL64 ||542 type == R_MIPS_TLS_TPREL32 || type == R_MIPS_TLS_TPREL64 ||
478 Type == R_MICROMIPS_TLS_TPREL_HI16 ||543 type == R_MICROMIPS_TLS_TPREL_HI16 ||
479 Type == R_MICROMIPS_TLS_TPREL_LO16) {544 type == R_MICROMIPS_TLS_TPREL_LO16) {
480 Val -= 0x7000;545 val -= 0x7000;
481 }546 }
482547
483 switch (Type) {548 switch (type) {
484 case R_MIPS_32:549 case R_MIPS_32:
485 case R_MIPS_GPREL32:550 case R_MIPS_GPREL32:
486 case R_MIPS_TLS_DTPREL32:551 case R_MIPS_TLS_DTPREL32:
487 case R_MIPS_TLS_TPREL32:552 case R_MIPS_TLS_TPREL32:
488 write32<E>(Loc, Val);553 write32<e>(loc, val);
489 break;554 break;
490 case R_MIPS_64:555 case R_MIPS_64:
491 case R_MIPS_TLS_DTPREL64:556 case R_MIPS_TLS_DTPREL64:
492 case R_MIPS_TLS_TPREL64:557 case R_MIPS_TLS_TPREL64:
493 write64<E>(Loc, Val);558 write64<e>(loc, val);
494 break;559 break;
495 case R_MIPS_26:560 case R_MIPS_26:
496 writeValue<E>(Loc, Val, 26, 2);561 writeValue<e>(loc, val, 26, 2);
497 break;562 break;
498 case R_MIPS_GOT16:563 case R_MIPS_GOT16:
499 // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode564 // The R_MIPS_GOT16 relocation's value in "relocatable" linking mode
500 // is updated addend (not a GOT index). In that case write high 16 bits565 // is updated addend (not a GOT index). In that case write high 16 bits
501 // to store a correct addend value.566 // to store a correct addend value.
502 if (Config->Relocatable) {567 if (config->relocatable) {
503 writeValue<E>(Loc, Val + 0x8000, 16, 16);568 writeValue<e>(loc, val + 0x8000, 16, 16);
504 } else {569 } else {
505 checkInt(Loc, Val, 16, Type);570 checkInt(loc, val, 16, type);
506 writeValue<E>(Loc, Val, 16, 0);571 writeValue<e>(loc, val, 16, 0);
507 }572 }
508 break;573 break;
509 case R_MICROMIPS_GOT16:574 case R_MICROMIPS_GOT16:
510 if (Config->Relocatable) {575 if (config->relocatable) {
511 writeShuffleValue<E>(Loc, Val + 0x8000, 16, 16);576 writeShuffleValue<e>(loc, val + 0x8000, 16, 16);
512 } else {577 } else {
513 checkInt(Loc, Val, 16, Type);578 checkInt(loc, val, 16, type);
514 writeShuffleValue<E>(Loc, Val, 16, 0);579 writeShuffleValue<e>(loc, val, 16, 0);
515 }580 }
516 break;581 break;
517 case R_MIPS_CALL16:582 case R_MIPS_CALL16:
...@@ -521,7 +586,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -521,7 +586,7 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
521 case R_MIPS_TLS_GD:586 case R_MIPS_TLS_GD:
522 case R_MIPS_TLS_GOTTPREL:587 case R_MIPS_TLS_GOTTPREL:
523 case R_MIPS_TLS_LDM:588 case R_MIPS_TLS_LDM:
524 checkInt(Loc, Val, 16, Type);589 checkInt(loc, val, 16, type);
525 LLVM_FALLTHROUGH;590 LLVM_FALLTHROUGH;
526 case R_MIPS_CALL_LO16:591 case R_MIPS_CALL_LO16:
527 case R_MIPS_GOT_LO16:592 case R_MIPS_GOT_LO16:
...@@ -530,13 +595,13 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -530,13 +595,13 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
530 case R_MIPS_PCLO16:595 case R_MIPS_PCLO16:
531 case R_MIPS_TLS_DTPREL_LO16:596 case R_MIPS_TLS_DTPREL_LO16:
532 case R_MIPS_TLS_TPREL_LO16:597 case R_MIPS_TLS_TPREL_LO16:
533 writeValue<E>(Loc, Val, 16, 0);598 writeValue<e>(loc, val, 16, 0);
534 break;599 break;
535 case R_MICROMIPS_GPREL16:600 case R_MICROMIPS_GPREL16:
536 case R_MICROMIPS_TLS_GD:601 case R_MICROMIPS_TLS_GD:
537 case R_MICROMIPS_TLS_LDM:602 case R_MICROMIPS_TLS_LDM:
538 checkInt(Loc, Val, 16, Type);603 checkInt(loc, val, 16, type);
539 writeShuffleValue<E>(Loc, Val, 16, 0);604 writeShuffleValue<e>(loc, val, 16, 0);
540 break;605 break;
541 case R_MICROMIPS_CALL16:606 case R_MICROMIPS_CALL16:
542 case R_MICROMIPS_CALL_LO16:607 case R_MICROMIPS_CALL_LO16:
...@@ -544,11 +609,11 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -544,11 +609,11 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
544 case R_MICROMIPS_TLS_DTPREL_LO16:609 case R_MICROMIPS_TLS_DTPREL_LO16:
545 case R_MICROMIPS_TLS_GOTTPREL:610 case R_MICROMIPS_TLS_GOTTPREL:
546 case R_MICROMIPS_TLS_TPREL_LO16:611 case R_MICROMIPS_TLS_TPREL_LO16:
547 writeShuffleValue<E>(Loc, Val, 16, 0);612 writeShuffleValue<e>(loc, val, 16, 0);
548 break;613 break;
549 case R_MICROMIPS_GPREL7_S2:614 case R_MICROMIPS_GPREL7_S2:
550 checkInt(Loc, Val, 7, Type);615 checkInt(loc, val, 7, type);
551 writeShuffleValue<E>(Loc, Val, 7, 2);616 writeShuffleValue<e>(loc, val, 7, 2);
552 break;617 break;
553 case R_MIPS_CALL_HI16:618 case R_MIPS_CALL_HI16:
554 case R_MIPS_GOT_HI16:619 case R_MIPS_GOT_HI16:
...@@ -556,113 +621,113 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -556,113 +621,113 @@ void MIPS<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
556 case R_MIPS_PCHI16:621 case R_MIPS_PCHI16:
557 case R_MIPS_TLS_DTPREL_HI16:622 case R_MIPS_TLS_DTPREL_HI16:
558 case R_MIPS_TLS_TPREL_HI16:623 case R_MIPS_TLS_TPREL_HI16:
559 writeValue<E>(Loc, Val + 0x8000, 16, 16);624 writeValue<e>(loc, val + 0x8000, 16, 16);
560 break;625 break;
561 case R_MICROMIPS_CALL_HI16:626 case R_MICROMIPS_CALL_HI16:
562 case R_MICROMIPS_GOT_HI16:627 case R_MICROMIPS_GOT_HI16:
563 case R_MICROMIPS_HI16:628 case R_MICROMIPS_HI16:
564 case R_MICROMIPS_TLS_DTPREL_HI16:629 case R_MICROMIPS_TLS_DTPREL_HI16:
565 case R_MICROMIPS_TLS_TPREL_HI16:630 case R_MICROMIPS_TLS_TPREL_HI16:
566 writeShuffleValue<E>(Loc, Val + 0x8000, 16, 16);631 writeShuffleValue<e>(loc, val + 0x8000, 16, 16);
567 break;632 break;
568 case R_MIPS_HIGHER:633 case R_MIPS_HIGHER:
569 writeValue<E>(Loc, Val + 0x80008000, 16, 32);634 writeValue<e>(loc, val + 0x80008000, 16, 32);
570 break;635 break;
571 case R_MIPS_HIGHEST:636 case R_MIPS_HIGHEST:
572 writeValue<E>(Loc, Val + 0x800080008000, 16, 48);637 writeValue<e>(loc, val + 0x800080008000, 16, 48);
573 break;638 break;
574 case R_MIPS_JALR:639 case R_MIPS_JALR:
575 case R_MICROMIPS_JALR:640 case R_MICROMIPS_JALR:
576 // Ignore this optimization relocation for now641 // Ignore this optimization relocation for now
577 break;642 break;
578 case R_MIPS_PC16:643 case R_MIPS_PC16:
579 checkAlignment(Loc, Val, 4, Type);644 checkAlignment(loc, val, 4, type);
580 checkInt(Loc, Val, 18, Type);645 checkInt(loc, val, 18, type);
581 writeValue<E>(Loc, Val, 16, 2);646 writeValue<e>(loc, val, 16, 2);
582 break;647 break;
583 case R_MIPS_PC19_S2:648 case R_MIPS_PC19_S2:
584 checkAlignment(Loc, Val, 4, Type);649 checkAlignment(loc, val, 4, type);
585 checkInt(Loc, Val, 21, Type);650 checkInt(loc, val, 21, type);
586 writeValue<E>(Loc, Val, 19, 2);651 writeValue<e>(loc, val, 19, 2);
587 break;652 break;
588 case R_MIPS_PC21_S2:653 case R_MIPS_PC21_S2:
589 checkAlignment(Loc, Val, 4, Type);654 checkAlignment(loc, val, 4, type);
590 checkInt(Loc, Val, 23, Type);655 checkInt(loc, val, 23, type);
591 writeValue<E>(Loc, Val, 21, 2);656 writeValue<e>(loc, val, 21, 2);
592 break;657 break;
593 case R_MIPS_PC26_S2:658 case R_MIPS_PC26_S2:
594 checkAlignment(Loc, Val, 4, Type);659 checkAlignment(loc, val, 4, type);
595 checkInt(Loc, Val, 28, Type);660 checkInt(loc, val, 28, type);
596 writeValue<E>(Loc, Val, 26, 2);661 writeValue<e>(loc, val, 26, 2);
597 break;662 break;
598 case R_MIPS_PC32:663 case R_MIPS_PC32:
599 writeValue<E>(Loc, Val, 32, 0);664 writeValue<e>(loc, val, 32, 0);
600 break;665 break;
601 case R_MICROMIPS_26_S1:666 case R_MICROMIPS_26_S1:
602 case R_MICROMIPS_PC26_S1:667 case R_MICROMIPS_PC26_S1:
603 checkInt(Loc, Val, 27, Type);668 checkInt(loc, val, 27, type);
604 writeShuffleValue<E>(Loc, Val, 26, 1);669 writeShuffleValue<e>(loc, val, 26, 1);
605 break;670 break;
606 case R_MICROMIPS_PC7_S1:671 case R_MICROMIPS_PC7_S1:
607 checkInt(Loc, Val, 8, Type);672 checkInt(loc, val, 8, type);
608 writeMicroRelocation16<E>(Loc, Val, 7, 1);673 writeMicroRelocation16<e>(loc, val, 7, 1);
609 break;674 break;
610 case R_MICROMIPS_PC10_S1:675 case R_MICROMIPS_PC10_S1:
611 checkInt(Loc, Val, 11, Type);676 checkInt(loc, val, 11, type);
612 writeMicroRelocation16<E>(Loc, Val, 10, 1);677 writeMicroRelocation16<e>(loc, val, 10, 1);
613 break;678 break;
614 case R_MICROMIPS_PC16_S1:679 case R_MICROMIPS_PC16_S1:
615 checkInt(Loc, Val, 17, Type);680 checkInt(loc, val, 17, type);
616 writeShuffleValue<E>(Loc, Val, 16, 1);681 writeShuffleValue<e>(loc, val, 16, 1);
617 break;682 break;
618 case R_MICROMIPS_PC18_S3:683 case R_MICROMIPS_PC18_S3:
619 checkInt(Loc, Val, 21, Type);684 checkInt(loc, val, 21, type);
620 writeShuffleValue<E>(Loc, Val, 18, 3);685 writeShuffleValue<e>(loc, val, 18, 3);
621 break;686 break;
622 case R_MICROMIPS_PC19_S2:687 case R_MICROMIPS_PC19_S2:
623 checkInt(Loc, Val, 21, Type);688 checkInt(loc, val, 21, type);
624 writeShuffleValue<E>(Loc, Val, 19, 2);689 writeShuffleValue<e>(loc, val, 19, 2);
625 break;690 break;
626 case R_MICROMIPS_PC21_S1:691 case R_MICROMIPS_PC21_S1:
627 checkInt(Loc, Val, 22, Type);692 checkInt(loc, val, 22, type);
628 writeShuffleValue<E>(Loc, Val, 21, 1);693 writeShuffleValue<e>(loc, val, 21, 1);
629 break;694 break;
630 case R_MICROMIPS_PC23_S2:695 case R_MICROMIPS_PC23_S2:
631 checkInt(Loc, Val, 25, Type);696 checkInt(loc, val, 25, type);
632 writeShuffleValue<E>(Loc, Val, 23, 2);697 writeShuffleValue<e>(loc, val, 23, 2);
633 break;698 break;
634 default:699 default:
635 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));700 llvm_unreachable("unknown relocation");
636 }701 }
637}702}
638703
639template <class ELFT> bool MIPS<ELFT>::usesOnlyLowPageBits(RelType Type) const {704template <class ELFT> bool MIPS<ELFT>::usesOnlyLowPageBits(RelType type) const {
640 return Type == R_MIPS_LO16 || Type == R_MIPS_GOT_OFST ||705 return type == R_MIPS_LO16 || type == R_MIPS_GOT_OFST ||
641 Type == R_MICROMIPS_LO16;706 type == R_MICROMIPS_LO16;
642}707}
643708
644// Return true if the symbol is a PIC function.709// Return true if the symbol is a PIC function.
645template <class ELFT> bool elf::isMipsPIC(const Defined *Sym) {710template <class ELFT> bool elf::isMipsPIC(const Defined *sym) {
646 if (!Sym->isFunc())711 if (!sym->isFunc())
647 return false;712 return false;
648713
649 if (Sym->StOther & STO_MIPS_PIC)714 if (sym->stOther & STO_MIPS_PIC)
650 return true;715 return true;
651716
652 if (!Sym->Section)717 if (!sym->section)
653 return false;718 return false;
654719
655 ObjFile<ELFT> *File =720 ObjFile<ELFT> *file =
656 cast<InputSectionBase>(Sym->Section)->template getFile<ELFT>();721 cast<InputSectionBase>(sym->section)->template getFile<ELFT>();
657 if (!File)722 if (!file)
658 return false;723 return false;
659724
660 return File->getObj().getHeader()->e_flags & EF_MIPS_PIC;725 return file->getObj().getHeader()->e_flags & EF_MIPS_PIC;
661}726}
662727
663template <class ELFT> TargetInfo *elf::getMipsTargetInfo() {728template <class ELFT> TargetInfo *elf::getMipsTargetInfo() {
664 static MIPS<ELFT> Target;729 static MIPS<ELFT> target;
665 return &Target;730 return &target;
666}731}
667732
668template TargetInfo *elf::getMipsTargetInfo<ELF32LE>();733template TargetInfo *elf::getMipsTargetInfo<ELF32LE>();
deps/lld/ELF/Arch/MipsArchTree.cpp+119-120
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MipsArchTree.cpp --------------------------------------------------===//1//===- MipsArchTree.cpp --------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===---------------------------------------------------------------------===//7//===---------------------------------------------------------------------===//
9//8//
...@@ -29,18 +28,18 @@ using namespace lld::elf;...@@ -29,18 +28,18 @@ using namespace lld::elf;
2928
30namespace {29namespace {
31struct ArchTreeEdge {30struct ArchTreeEdge {
32 uint32_t Child;31 uint32_t child;
33 uint32_t Parent;32 uint32_t parent;
34};33};
3534
36struct FileFlags {35struct FileFlags {
37 InputFile *File;36 InputFile *file;
38 uint32_t Flags;37 uint32_t flags;
39};38};
40} // namespace39} // namespace
4140
42static StringRef getAbiName(uint32_t Flags) {41static StringRef getAbiName(uint32_t flags) {
43 switch (Flags) {42 switch (flags) {
44 case 0:43 case 0:
45 return "n64";44 return "n64";
46 case EF_MIPS_ABI2:45 case EF_MIPS_ABI2:
...@@ -58,76 +57,76 @@ static StringRef getAbiName(uint32_t Flags) {...@@ -58,76 +57,76 @@ static StringRef getAbiName(uint32_t Flags) {
58 }57 }
59}58}
6059
61static StringRef getNanName(bool IsNan2008) {60static StringRef getNanName(bool isNan2008) {
62 return IsNan2008 ? "2008" : "legacy";61 return isNan2008 ? "2008" : "legacy";
63}62}
6463
65static StringRef getFpName(bool IsFp64) { return IsFp64 ? "64" : "32"; }64static StringRef getFpName(bool isFp64) { return isFp64 ? "64" : "32"; }
6665
67static void checkFlags(ArrayRef<FileFlags> Files) {66static void checkFlags(ArrayRef<FileFlags> files) {
68 assert(!Files.empty() && "expected non-empty file list");67 assert(!files.empty() && "expected non-empty file list");
6968
70 uint32_t ABI = Files[0].Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);69 uint32_t abi = files[0].flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
71 bool Nan = Files[0].Flags & EF_MIPS_NAN2008;70 bool nan = files[0].flags & EF_MIPS_NAN2008;
72 bool Fp = Files[0].Flags & EF_MIPS_FP64;71 bool fp = files[0].flags & EF_MIPS_FP64;
7372
74 for (const FileFlags &F : Files) {73 for (const FileFlags &f : files) {
75 if (Config->Is64 && F.Flags & EF_MIPS_MICROMIPS)74 if (config->is64 && f.flags & EF_MIPS_MICROMIPS)
76 error(toString(F.File) + ": microMIPS 64-bit is not supported");75 error(toString(f.file) + ": microMIPS 64-bit is not supported");
7776
78 uint32_t ABI2 = F.Flags & (EF_MIPS_ABI | EF_MIPS_ABI2);77 uint32_t abi2 = f.flags & (EF_MIPS_ABI | EF_MIPS_ABI2);
79 if (ABI != ABI2)78 if (abi != abi2)
80 error(toString(F.File) + ": ABI '" + getAbiName(ABI2) +79 error(toString(f.file) + ": ABI '" + getAbiName(abi2) +
81 "' is incompatible with target ABI '" + getAbiName(ABI) + "'");80 "' is incompatible with target ABI '" + getAbiName(abi) + "'");
8281
83 bool Nan2 = F.Flags & EF_MIPS_NAN2008;82 bool nan2 = f.flags & EF_MIPS_NAN2008;
84 if (Nan != Nan2)83 if (nan != nan2)
85 error(toString(F.File) + ": -mnan=" + getNanName(Nan2) +84 error(toString(f.file) + ": -mnan=" + getNanName(nan2) +
86 " is incompatible with target -mnan=" + getNanName(Nan));85 " is incompatible with target -mnan=" + getNanName(nan));
8786
88 bool Fp2 = F.Flags & EF_MIPS_FP64;87 bool fp2 = f.flags & EF_MIPS_FP64;
89 if (Fp != Fp2)88 if (fp != fp2)
90 error(toString(F.File) + ": -mfp" + getFpName(Fp2) +89 error(toString(f.file) + ": -mfp" + getFpName(fp2) +
91 " is incompatible with target -mfp" + getFpName(Fp));90 " is incompatible with target -mfp" + getFpName(fp));
92 }91 }
93}92}
9493
95static uint32_t getMiscFlags(ArrayRef<FileFlags> Files) {94static uint32_t getMiscFlags(ArrayRef<FileFlags> files) {
96 uint32_t Ret = 0;95 uint32_t ret = 0;
97 for (const FileFlags &F : Files)96 for (const FileFlags &f : files)
98 Ret |= F.Flags &97 ret |= f.flags &
99 (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |98 (EF_MIPS_ABI | EF_MIPS_ABI2 | EF_MIPS_ARCH_ASE | EF_MIPS_NOREORDER |
100 EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);99 EF_MIPS_MICROMIPS | EF_MIPS_NAN2008 | EF_MIPS_32BITMODE);
101 return Ret;100 return ret;
102}101}
103102
104static uint32_t getPicFlags(ArrayRef<FileFlags> Files) {103static uint32_t getPicFlags(ArrayRef<FileFlags> files) {
105 // Check PIC/non-PIC compatibility.104 // Check PIC/non-PIC compatibility.
106 bool IsPic = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);105 bool isPic = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
107 for (const FileFlags &F : Files.slice(1)) {106 for (const FileFlags &f : files.slice(1)) {
108 bool IsPic2 = F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);107 bool isPic2 = f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
109 if (IsPic && !IsPic2)108 if (isPic && !isPic2)
110 warn(toString(F.File) +109 warn(toString(f.file) +
111 ": linking non-abicalls code with abicalls code " +110 ": linking non-abicalls code with abicalls code " +
112 toString(Files[0].File));111 toString(files[0].file));
113 if (!IsPic && IsPic2)112 if (!isPic && isPic2)
114 warn(toString(F.File) +113 warn(toString(f.file) +
115 ": linking abicalls code with non-abicalls code " +114 ": linking abicalls code with non-abicalls code " +
116 toString(Files[0].File));115 toString(files[0].file));
117 }116 }
118117
119 // Compute the result PIC/non-PIC flag.118 // Compute the result PIC/non-PIC flag.
120 uint32_t Ret = Files[0].Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);119 uint32_t ret = files[0].flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
121 for (const FileFlags &F : Files.slice(1))120 for (const FileFlags &f : files.slice(1))
122 Ret &= F.Flags & (EF_MIPS_PIC | EF_MIPS_CPIC);121 ret &= f.flags & (EF_MIPS_PIC | EF_MIPS_CPIC);
123122
124 // PIC code is inherently CPIC and may not set CPIC flag explicitly.123 // PIC code is inherently CPIC and may not set CPIC flag explicitly.
125 if (Ret & EF_MIPS_PIC)124 if (ret & EF_MIPS_PIC)
126 Ret |= EF_MIPS_CPIC;125 ret |= EF_MIPS_CPIC;
127 return Ret;126 return ret;
128}127}
129128
130static ArchTreeEdge ArchTree[] = {129static ArchTreeEdge archTree[] = {
131 // MIPS32R6 and MIPS64R6 are not compatible with other extensions130 // MIPS32R6 and MIPS64R6 are not compatible with other extensions
132 // MIPS64R2 extensions.131 // MIPS64R2 extensions.
133 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},132 {EF_MIPS_ARCH_64R2 | EF_MIPS_MACH_OCTEON3, EF_MIPS_ARCH_64R2},
...@@ -167,25 +166,25 @@ static ArchTreeEdge ArchTree[] = {...@@ -167,25 +166,25 @@ static ArchTreeEdge ArchTree[] = {
167 {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},166 {EF_MIPS_ARCH_2, EF_MIPS_ARCH_1},
168};167};
169168
170static bool isArchMatched(uint32_t New, uint32_t Res) {169static bool isArchMatched(uint32_t New, uint32_t res) {
171 if (New == Res)170 if (New == res)
172 return true;171 return true;
173 if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, Res))172 if (New == EF_MIPS_ARCH_32 && isArchMatched(EF_MIPS_ARCH_64, res))
174 return true;173 return true;
175 if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, Res))174 if (New == EF_MIPS_ARCH_32R2 && isArchMatched(EF_MIPS_ARCH_64R2, res))
176 return true;175 return true;
177 for (const auto &Edge : ArchTree) {176 for (const auto &edge : archTree) {
178 if (Res == Edge.Child) {177 if (res == edge.child) {
179 Res = Edge.Parent;178 res = edge.parent;
180 if (Res == New)179 if (res == New)
181 return true;180 return true;
182 }181 }
183 }182 }
184 return false;183 return false;
185}184}
186185
187static StringRef getMachName(uint32_t Flags) {186static StringRef getMachName(uint32_t flags) {
188 switch (Flags & EF_MIPS_MACH) {187 switch (flags & EF_MIPS_MACH) {
189 case EF_MIPS_MACH_NONE:188 case EF_MIPS_MACH_NONE:
190 return "";189 return "";
191 case EF_MIPS_MACH_3900:190 case EF_MIPS_MACH_3900:
...@@ -229,8 +228,8 @@ static StringRef getMachName(uint32_t Flags) {...@@ -229,8 +228,8 @@ static StringRef getMachName(uint32_t Flags) {
229 }228 }
230}229}
231230
232static StringRef getArchName(uint32_t Flags) {231static StringRef getArchName(uint32_t flags) {
233 switch (Flags & EF_MIPS_ARCH) {232 switch (flags & EF_MIPS_ARCH) {
234 case EF_MIPS_ARCH_1:233 case EF_MIPS_ARCH_1:
235 return "mips1";234 return "mips1";
236 case EF_MIPS_ARCH_2:235 case EF_MIPS_ARCH_2:
...@@ -258,12 +257,12 @@ static StringRef getArchName(uint32_t Flags) {...@@ -258,12 +257,12 @@ static StringRef getArchName(uint32_t Flags) {
258 }257 }
259}258}
260259
261static std::string getFullArchName(uint32_t Flags) {260static std::string getFullArchName(uint32_t flags) {
262 StringRef Arch = getArchName(Flags);261 StringRef arch = getArchName(flags);
263 StringRef Mach = getMachName(Flags);262 StringRef mach = getMachName(flags);
264 if (Mach.empty())263 if (mach.empty())
265 return Arch.str();264 return arch.str();
266 return (Arch + " (" + Mach + ")").str();265 return (arch + " (" + mach + ")").str();
267}266}
268267
269// There are (arguably too) many MIPS ISAs out there. Their relationships268// There are (arguably too) many MIPS ISAs out there. Their relationships
...@@ -275,55 +274,55 @@ static std::string getFullArchName(uint32_t Flags) {...@@ -275,55 +274,55 @@ static std::string getFullArchName(uint32_t Flags) {
275// Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32274// Output file gets EF_MIPS_ARCH_2 flag. From the other side mips3 and mips32
276// are incompatible because nor mips3 is a parent for misp32, nor mips32275// are incompatible because nor mips3 is a parent for misp32, nor mips32
277// is a parent for mips3.276// is a parent for mips3.
278static uint32_t getArchFlags(ArrayRef<FileFlags> Files) {277static uint32_t getArchFlags(ArrayRef<FileFlags> files) {
279 uint32_t Ret = Files[0].Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);278 uint32_t ret = files[0].flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
280279
281 for (const FileFlags &F : Files.slice(1)) {280 for (const FileFlags &f : files.slice(1)) {
282 uint32_t New = F.Flags & (EF_MIPS_ARCH | EF_MIPS_MACH);281 uint32_t New = f.flags & (EF_MIPS_ARCH | EF_MIPS_MACH);
283282
284 // Check ISA compatibility.283 // Check ISA compatibility.
285 if (isArchMatched(New, Ret))284 if (isArchMatched(New, ret))
286 continue;285 continue;
287 if (!isArchMatched(Ret, New)) {286 if (!isArchMatched(ret, New)) {
288 error("incompatible target ISA:\n>>> " + toString(Files[0].File) + ": " +287 error("incompatible target ISA:\n>>> " + toString(files[0].file) + ": " +
289 getFullArchName(Ret) + "\n>>> " + toString(F.File) + ": " +288 getFullArchName(ret) + "\n>>> " + toString(f.file) + ": " +
290 getFullArchName(New));289 getFullArchName(New));
291 return 0;290 return 0;
292 }291 }
293 Ret = New;292 ret = New;
294 }293 }
295 return Ret;294 return ret;
296}295}
297296
298template <class ELFT> uint32_t elf::calcMipsEFlags() {297template <class ELFT> uint32_t elf::calcMipsEFlags() {
299 std::vector<FileFlags> V;298 std::vector<FileFlags> v;
300 for (InputFile *F : ObjectFiles)299 for (InputFile *f : objectFiles)
301 V.push_back({F, cast<ObjFile<ELFT>>(F)->getObj().getHeader()->e_flags});300 v.push_back({f, cast<ObjFile<ELFT>>(f)->getObj().getHeader()->e_flags});
302 if (V.empty())301 if (v.empty())
303 return 0;302 return 0;
304 checkFlags(V);303 checkFlags(v);
305 return getMiscFlags(V) | getPicFlags(V) | getArchFlags(V);304 return getMiscFlags(v) | getPicFlags(v) | getArchFlags(v);
306}305}
307306
308static int compareMipsFpAbi(uint8_t FpA, uint8_t FpB) {307static int compareMipsFpAbi(uint8_t fpA, uint8_t fpB) {
309 if (FpA == FpB)308 if (fpA == fpB)
310 return 0;309 return 0;
311 if (FpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)310 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_ANY)
312 return 1;311 return 1;
313 if (FpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&312 if (fpB == Mips::Val_GNU_MIPS_ABI_FP_64A &&
314 FpA == Mips::Val_GNU_MIPS_ABI_FP_64)313 fpA == Mips::Val_GNU_MIPS_ABI_FP_64)
315 return 1;314 return 1;
316 if (FpB != Mips::Val_GNU_MIPS_ABI_FP_XX)315 if (fpB != Mips::Val_GNU_MIPS_ABI_FP_XX)
317 return -1;316 return -1;
318 if (FpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||317 if (fpA == Mips::Val_GNU_MIPS_ABI_FP_DOUBLE ||
319 FpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||318 fpA == Mips::Val_GNU_MIPS_ABI_FP_64 ||
320 FpA == Mips::Val_GNU_MIPS_ABI_FP_64A)319 fpA == Mips::Val_GNU_MIPS_ABI_FP_64A)
321 return 1;320 return 1;
322 return -1;321 return -1;
323}322}
324323
325static StringRef getMipsFpAbiName(uint8_t FpAbi) {324static StringRef getMipsFpAbiName(uint8_t fpAbi) {
326 switch (FpAbi) {325 switch (fpAbi) {
327 case Mips::Val_GNU_MIPS_ABI_FP_ANY:326 case Mips::Val_GNU_MIPS_ABI_FP_ANY:
328 return "any";327 return "any";
329 case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:328 case Mips::Val_GNU_MIPS_ABI_FP_DOUBLE:
...@@ -345,43 +344,43 @@ static StringRef getMipsFpAbiName(uint8_t FpAbi) {...@@ -345,43 +344,43 @@ static StringRef getMipsFpAbiName(uint8_t FpAbi) {
345 }344 }
346}345}
347346
348uint8_t elf::getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,347uint8_t elf::getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
349 StringRef FileName) {348 StringRef fileName) {
350 if (compareMipsFpAbi(NewFlag, OldFlag) >= 0)349 if (compareMipsFpAbi(newFlag, oldFlag) >= 0)
351 return NewFlag;350 return newFlag;
352 if (compareMipsFpAbi(OldFlag, NewFlag) < 0)351 if (compareMipsFpAbi(oldFlag, newFlag) < 0)
353 error(FileName + ": floating point ABI '" + getMipsFpAbiName(NewFlag) +352 error(fileName + ": floating point ABI '" + getMipsFpAbiName(newFlag) +
354 "' is incompatible with target floating point ABI '" +353 "' is incompatible with target floating point ABI '" +
355 getMipsFpAbiName(OldFlag) + "'");354 getMipsFpAbiName(oldFlag) + "'");
356 return OldFlag;355 return oldFlag;
357}356}
358357
359template <class ELFT> static bool isN32Abi(const InputFile *F) {358template <class ELFT> static bool isN32Abi(const InputFile *f) {
360 if (auto *EF = dyn_cast<ELFFileBase<ELFT>>(F))359 if (auto *ef = dyn_cast<ELFFileBase>(f))
361 return EF->getObj().getHeader()->e_flags & EF_MIPS_ABI2;360 return ef->template getObj<ELFT>().getHeader()->e_flags & EF_MIPS_ABI2;
362 return false;361 return false;
363}362}
364363
365bool elf::isMipsN32Abi(const InputFile *F) {364bool elf::isMipsN32Abi(const InputFile *f) {
366 switch (Config->EKind) {365 switch (config->ekind) {
367 case ELF32LEKind:366 case ELF32LEKind:
368 return isN32Abi<ELF32LE>(F);367 return isN32Abi<ELF32LE>(f);
369 case ELF32BEKind:368 case ELF32BEKind:
370 return isN32Abi<ELF32BE>(F);369 return isN32Abi<ELF32BE>(f);
371 case ELF64LEKind:370 case ELF64LEKind:
372 return isN32Abi<ELF64LE>(F);371 return isN32Abi<ELF64LE>(f);
373 case ELF64BEKind:372 case ELF64BEKind:
374 return isN32Abi<ELF64BE>(F);373 return isN32Abi<ELF64BE>(f);
375 default:374 default:
376 llvm_unreachable("unknown Config->EKind");375 llvm_unreachable("unknown Config->EKind");
377 }376 }
378}377}
379378
380bool elf::isMicroMips() { return Config->EFlags & EF_MIPS_MICROMIPS; }379bool elf::isMicroMips() { return config->eflags & EF_MIPS_MICROMIPS; }
381380
382bool elf::isMipsR6() {381bool elf::isMipsR6() {
383 uint32_t Arch = Config->EFlags & EF_MIPS_ARCH;382 uint32_t arch = config->eflags & EF_MIPS_ARCH;
384 return Arch == EF_MIPS_ARCH_32R6 || Arch == EF_MIPS_ARCH_64R6;383 return arch == EF_MIPS_ARCH_32R6 || arch == EF_MIPS_ARCH_64R6;
385}384}
386385
387template uint32_t elf::calcMipsEFlags<ELF32LE>();386template uint32_t elf::calcMipsEFlags<ELF32LE>();
deps/lld/ELF/Arch/PPC.cpp+379-28
...@@ -1,13 +1,14 @@...@@ -1,13 +1,14 @@
1//===- PPC.cpp ------------------------------------------------------------===//1//===- PPC.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
9#include "OutputSections.h"
10#include "Symbols.h"10#include "Symbols.h"
11#include "SyntheticSections.h"
11#include "Target.h"12#include "Target.h"
12#include "lld/Common/ErrorHandler.h"13#include "lld/Common/ErrorHandler.h"
13#include "llvm/Support/Endian.h"14#include "llvm/Support/Endian.h"
...@@ -22,60 +23,410 @@ namespace {...@@ -22,60 +23,410 @@ namespace {
22class PPC final : public TargetInfo {23class PPC final : public TargetInfo {
23public:24public:
24 PPC();25 PPC();
25 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;26 RelExpr getRelExpr(RelType type, const Symbol &s,
26 RelExpr getRelExpr(RelType Type, const Symbol &S,27 const uint8_t *loc) const override;
27 const uint8_t *Loc) const override;28 RelType getDynRel(RelType type) const override;
29 void writeGotHeader(uint8_t *buf) const override;
30 void writePltHeader(uint8_t *buf) const override {
31 llvm_unreachable("should call writePPC32GlinkSection() instead");
32 }
33 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
34 int32_t index, unsigned relOff) const override {
35 llvm_unreachable("should call writePPC32GlinkSection() instead");
36 }
37 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
38 bool needsThunk(RelExpr expr, RelType relocType, const InputFile *file,
39 uint64_t branchAddr, const Symbol &s) const override;
40 uint32_t getThunkSectionSpacing() const override;
41 bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
42 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
43 RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
44 RelExpr expr) const override;
45 int getTlsGdRelaxSkip(RelType type) const override;
46 void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
47 void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
48 void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
49 void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
28};50};
29} // namespace51} // namespace
3052
53static uint16_t lo(uint32_t v) { return v; }
54static uint16_t ha(uint32_t v) { return (v + 0x8000) >> 16; }
55
56static uint32_t readFromHalf16(const uint8_t *loc) {
57 return read32(config->isLE ? loc : loc - 2);
58}
59
60static void writeFromHalf16(uint8_t *loc, uint32_t insn) {
61 write32(config->isLE ? loc : loc - 2, insn);
62}
63
64void elf::writePPC32GlinkSection(uint8_t *buf, size_t numEntries) {
65 // On PPC Secure PLT ABI, bl foo@plt jumps to a call stub, which loads an
66 // absolute address from a specific .plt slot (usually called .got.plt on
67 // other targets) and jumps there.
68 //
69 // a) With immediate binding (BIND_NOW), the .plt entry is resolved at load
70 // time. The .glink section is not used.
71 // b) With lazy binding, the .plt entry points to a `b PLTresolve`
72 // instruction in .glink, filled in by PPC::writeGotPlt().
73
74 // Write N `b PLTresolve` first.
75 for (size_t i = 0; i != numEntries; ++i)
76 write32(buf + 4 * i, 0x48000000 | 4 * (numEntries - i));
77 buf += 4 * numEntries;
78
79 // Then write PLTresolve(), which has two forms: PIC and non-PIC. PLTresolve()
80 // computes the PLT index (by computing the distance from the landing b to
81 // itself) and calls _dl_runtime_resolve() (in glibc).
82 uint32_t got = in.got->getVA();
83 uint32_t glink = in.plt->getVA(); // VA of .glink
84 const uint8_t *end = buf + 64;
85 if (config->isPic) {
86 uint32_t afterBcl = in.plt->getSize() - target->pltHeaderSize + 12;
87 uint32_t gotBcl = got + 4 - (glink + afterBcl);
88 write32(buf + 0, 0x3d6b0000 | ha(afterBcl)); // addis r11,r11,1f-glink@ha
89 write32(buf + 4, 0x7c0802a6); // mflr r0
90 write32(buf + 8, 0x429f0005); // bcl 20,30,.+4
91 write32(buf + 12, 0x396b0000 | lo(afterBcl)); // 1: addi r11,r11,1b-.glink@l
92 write32(buf + 16, 0x7d8802a6); // mflr r12
93 write32(buf + 20, 0x7c0803a6); // mtlr r0
94 write32(buf + 24, 0x7d6c5850); // sub r11,r11,r12
95 write32(buf + 28, 0x3d8c0000 | ha(gotBcl)); // addis 12,12,GOT+4-1b@ha
96 if (ha(gotBcl) == ha(gotBcl + 4)) {
97 write32(buf + 32, 0x800c0000 | lo(gotBcl)); // lwz r0,r12,GOT+4-1b@l(r12)
98 write32(buf + 36,
99 0x818c0000 | lo(gotBcl + 4)); // lwz r12,r12,GOT+8-1b@l(r12)
100 } else {
101 write32(buf + 32, 0x840c0000 | lo(gotBcl)); // lwzu r0,r12,GOT+4-1b@l(r12)
102 write32(buf + 36, 0x818c0000 | 4); // lwz r12,r12,4(r12)
103 }
104 write32(buf + 40, 0x7c0903a6); // mtctr 0
105 write32(buf + 44, 0x7c0b5a14); // add r0,11,11
106 write32(buf + 48, 0x7d605a14); // add r11,0,11
107 write32(buf + 52, 0x4e800420); // bctr
108 buf += 56;
109 } else {
110 write32(buf + 0, 0x3d800000 | ha(got + 4)); // lis r12,GOT+4@ha
111 write32(buf + 4, 0x3d6b0000 | ha(-glink)); // addis r11,r11,-Glink@ha
112 if (ha(got + 4) == ha(got + 8))
113 write32(buf + 8, 0x800c0000 | lo(got + 4)); // lwz r0,GOT+4@l(r12)
114 else
115 write32(buf + 8, 0x840c0000 | lo(got + 4)); // lwzu r0,GOT+4@l(r12)
116 write32(buf + 12, 0x396b0000 | lo(-glink)); // addi r11,r11,-Glink@l
117 write32(buf + 16, 0x7c0903a6); // mtctr r0
118 write32(buf + 20, 0x7c0b5a14); // add r0,r11,r11
119 if (ha(got + 4) == ha(got + 8))
120 write32(buf + 24, 0x818c0000 | lo(got + 8)); // lwz r12,GOT+8@ha(r12)
121 else
122 write32(buf + 24, 0x818c0000 | 4); // lwz r12,4(r12)
123 write32(buf + 28, 0x7d605a14); // add r11,r0,r11
124 write32(buf + 32, 0x4e800420); // bctr
125 buf += 36;
126 }
127
128 // Pad with nop. They should not be executed.
129 for (; buf < end; buf += 4)
130 write32(buf, 0x60000000);
131}
132
31PPC::PPC() {133PPC::PPC() {
32 NoneRel = R_PPC_NONE;134 gotRel = R_PPC_GLOB_DAT;
33 GotBaseSymOff = 0x8000;135 noneRel = R_PPC_NONE;
34 GotBaseSymInGotPlt = false;136 pltRel = R_PPC_JMP_SLOT;
137 relativeRel = R_PPC_RELATIVE;
138 iRelativeRel = R_PPC_IRELATIVE;
139 symbolicRel = R_PPC_ADDR32;
140 gotBaseSymInGotPlt = false;
141 gotHeaderEntriesNum = 3;
142 gotPltHeaderEntriesNum = 0;
143 pltHeaderSize = 64; // size of PLTresolve in .glink
144 pltEntrySize = 4;
145
146 needsThunks = true;
147
148 tlsModuleIndexRel = R_PPC_DTPMOD32;
149 tlsOffsetRel = R_PPC_DTPREL32;
150 tlsGotRel = R_PPC_TPREL32;
151
152 defaultMaxPageSize = 65536;
153 defaultImageBase = 0x10000000;
154
155 write32(trapInstr.data(), 0x7fe00008);
156}
157
158void PPC::writeGotHeader(uint8_t *buf) const {
159 // _GLOBAL_OFFSET_TABLE_[0] = _DYNAMIC
160 // glibc stores _dl_runtime_resolve in _GLOBAL_OFFSET_TABLE_[1],
161 // link_map in _GLOBAL_OFFSET_TABLE_[2].
162 write32(buf, mainPart->dynamic->getVA());
163}
164
165void PPC::writeGotPlt(uint8_t *buf, const Symbol &s) const {
166 // Address of the symbol resolver stub in .glink .
167 write32(buf, in.plt->getVA() + 4 * s.pltIndex);
168}
169
170bool PPC::needsThunk(RelExpr expr, RelType type, const InputFile *file,
171 uint64_t branchAddr, const Symbol &s) const {
172 if (type != R_PPC_REL24 && type != R_PPC_PLTREL24)
173 return false;
174 if (s.isInPlt())
175 return true;
176 if (s.isUndefWeak())
177 return false;
178 return !(expr == R_PC && PPC::inBranchRange(type, branchAddr, s.getVA()));
35}179}
36180
37RelExpr PPC::getRelExpr(RelType Type, const Symbol &S,181uint32_t PPC::getThunkSectionSpacing() const { return 0x2000000; }
38 const uint8_t *Loc) const {182
39 switch (Type) {183bool PPC::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
184 uint64_t offset = dst - src;
185 if (type == R_PPC_REL24 || type == R_PPC_PLTREL24)
186 return isInt<26>(offset);
187 llvm_unreachable("unsupported relocation type used in branch");
188}
189
190RelExpr PPC::getRelExpr(RelType type, const Symbol &s,
191 const uint8_t *loc) const {
192 switch (type) {
193 case R_PPC_DTPREL16:
194 case R_PPC_DTPREL16_HA:
195 case R_PPC_DTPREL16_HI:
196 case R_PPC_DTPREL16_LO:
197 case R_PPC_DTPREL32:
198 return R_DTPREL;
40 case R_PPC_REL14:199 case R_PPC_REL14:
41 case R_PPC_REL24:
42 case R_PPC_REL32:200 case R_PPC_REL32:
201 case R_PPC_LOCAL24PC:
202 case R_PPC_REL16_LO:
203 case R_PPC_REL16_HI:
204 case R_PPC_REL16_HA:
43 return R_PC;205 return R_PC;
44 case R_PPC_PLTREL24:206 case R_PPC_GOT16:
207 return R_GOT_OFF;
208 case R_PPC_REL24:
45 return R_PLT_PC;209 return R_PLT_PC;
210 case R_PPC_PLTREL24:
211 return R_PPC32_PLTREL;
212 case R_PPC_GOT_TLSGD16:
213 return R_TLSGD_GOT;
214 case R_PPC_GOT_TLSLD16:
215 return R_TLSLD_GOT;
216 case R_PPC_GOT_TPREL16:
217 return R_GOT_OFF;
218 case R_PPC_TLS:
219 return R_TLSIE_HINT;
220 case R_PPC_TLSGD:
221 return R_TLSDESC_CALL;
222 case R_PPC_TLSLD:
223 return R_TLSLD_HINT;
224 case R_PPC_TPREL16:
225 case R_PPC_TPREL16_HA:
226 case R_PPC_TPREL16_LO:
227 case R_PPC_TPREL16_HI:
228 return R_TLS;
46 default:229 default:
47 return R_ABS;230 return R_ABS;
48 }231 }
49}232}
50233
51void PPC::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {234RelType PPC::getDynRel(RelType type) const {
52 switch (Type) {235 if (type == R_PPC_ADDR32)
236 return type;
237 return R_PPC_NONE;
238}
239
240static std::pair<RelType, uint64_t> fromDTPREL(RelType type, uint64_t val) {
241 uint64_t dtpBiasedVal = val - 0x8000;
242 switch (type) {
243 case R_PPC_DTPREL16:
244 return {R_PPC64_ADDR16, dtpBiasedVal};
245 case R_PPC_DTPREL16_HA:
246 return {R_PPC_ADDR16_HA, dtpBiasedVal};
247 case R_PPC_DTPREL16_HI:
248 return {R_PPC_ADDR16_HI, dtpBiasedVal};
249 case R_PPC_DTPREL16_LO:
250 return {R_PPC_ADDR16_LO, dtpBiasedVal};
251 case R_PPC_DTPREL32:
252 return {R_PPC_ADDR32, dtpBiasedVal};
253 default:
254 return {type, val};
255 }
256}
257
258void PPC::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
259 RelType newType;
260 std::tie(newType, val) = fromDTPREL(type, val);
261 switch (newType) {
262 case R_PPC_ADDR16:
263 checkIntUInt(loc, val, 16, type);
264 write16(loc, val);
265 break;
266 case R_PPC_GOT16:
267 case R_PPC_GOT_TLSGD16:
268 case R_PPC_GOT_TLSLD16:
269 case R_PPC_GOT_TPREL16:
270 case R_PPC_TPREL16:
271 checkInt(loc, val, 16, type);
272 write16(loc, val);
273 break;
53 case R_PPC_ADDR16_HA:274 case R_PPC_ADDR16_HA:
54 write16be(Loc, (Val + 0x8000) >> 16);275 case R_PPC_DTPREL16_HA:
276 case R_PPC_GOT_TLSGD16_HA:
277 case R_PPC_GOT_TLSLD16_HA:
278 case R_PPC_GOT_TPREL16_HA:
279 case R_PPC_REL16_HA:
280 case R_PPC_TPREL16_HA:
281 write16(loc, ha(val));
55 break;282 break;
56 case R_PPC_ADDR16_HI:283 case R_PPC_ADDR16_HI:
57 write16be(Loc, Val >> 16);284 case R_PPC_DTPREL16_HI:
285 case R_PPC_GOT_TLSGD16_HI:
286 case R_PPC_GOT_TLSLD16_HI:
287 case R_PPC_GOT_TPREL16_HI:
288 case R_PPC_REL16_HI:
289 case R_PPC_TPREL16_HI:
290 write16(loc, val >> 16);
58 break;291 break;
59 case R_PPC_ADDR16_LO:292 case R_PPC_ADDR16_LO:
60 write16be(Loc, Val);293 case R_PPC_DTPREL16_LO:
294 case R_PPC_GOT_TLSGD16_LO:
295 case R_PPC_GOT_TLSLD16_LO:
296 case R_PPC_GOT_TPREL16_LO:
297 case R_PPC_REL16_LO:
298 case R_PPC_TPREL16_LO:
299 write16(loc, val);
61 break;300 break;
62 case R_PPC_ADDR32:301 case R_PPC_ADDR32:
63 case R_PPC_REL32:302 case R_PPC_REL32:
64 write32be(Loc, Val);303 write32(loc, val);
65 break;304 break;
66 case R_PPC_REL14:305 case R_PPC_REL14: {
67 write32be(Loc, read32be(Loc) | (Val & 0xFFFC));306 uint32_t mask = 0x0000FFFC;
307 checkInt(loc, val, 16, type);
308 checkAlignment(loc, val, 4, type);
309 write32(loc, (read32(loc) & ~mask) | (val & mask));
68 break;310 break;
69 case R_PPC_PLTREL24:311 }
70 case R_PPC_REL24:312 case R_PPC_REL24:
71 write32be(Loc, read32be(Loc) | (Val & 0x3FFFFFC));313 case R_PPC_LOCAL24PC:
314 case R_PPC_PLTREL24: {
315 uint32_t mask = 0x03FFFFFC;
316 checkInt(loc, val, 26, type);
317 checkAlignment(loc, val, 4, type);
318 write32(loc, (read32(loc) & ~mask) | (val & mask));
72 break;319 break;
320 }
321 default:
322 error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
323 }
324}
325
326RelExpr PPC::adjustRelaxExpr(RelType type, const uint8_t *data,
327 RelExpr expr) const {
328 if (expr == R_RELAX_TLS_GD_TO_IE)
329 return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
330 if (expr == R_RELAX_TLS_LD_TO_LE)
331 return R_RELAX_TLS_LD_TO_LE_ABS;
332 return expr;
333}
334
335int PPC::getTlsGdRelaxSkip(RelType type) const {
336 // A __tls_get_addr call instruction is marked with 2 relocations:
337 //
338 // R_PPC_TLSGD / R_PPC_TLSLD: marker relocation
339 // R_PPC_REL24: __tls_get_addr
340 //
341 // After the relaxation we no longer call __tls_get_addr and should skip both
342 // relocations to not create a false dependence on __tls_get_addr being
343 // defined.
344 if (type == R_PPC_TLSGD || type == R_PPC_TLSLD)
345 return 2;
346 return 1;
347}
348
349void PPC::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
350 switch (type) {
351 case R_PPC_GOT_TLSGD16: {
352 // addi rT, rA, x@got@tlsgd --> lwz rT, x@got@tprel(rA)
353 uint32_t insn = readFromHalf16(loc);
354 writeFromHalf16(loc, 0x80000000 | (insn & 0x03ff0000));
355 relocateOne(loc, R_PPC_GOT_TPREL16, val);
356 break;
357 }
358 case R_PPC_TLSGD:
359 // bl __tls_get_addr(x@tldgd) --> add r3, r3, r2
360 write32(loc, 0x7c631214);
361 break;
362 default:
363 llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
364 }
365}
366
367void PPC::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
368 switch (type) {
369 case R_PPC_GOT_TLSGD16:
370 // addi r3, r31, x@got@tlsgd --> addis r3, r2, x@tprel@ha
371 writeFromHalf16(loc, 0x3c620000 | ha(val));
372 break;
373 case R_PPC_TLSGD:
374 // bl __tls_get_addr(x@tldgd) --> add r3, r3, x@tprel@l
375 write32(loc, 0x38630000 | lo(val));
376 break;
377 default:
378 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
379 }
380}
381
382void PPC::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
383 switch (type) {
384 case R_PPC_GOT_TLSLD16:
385 // addi r3, rA, x@got@tlsgd --> addis r3, r2, 0
386 writeFromHalf16(loc, 0x3c620000);
387 break;
388 case R_PPC_TLSLD:
389 // r3+x@dtprel computes r3+x-0x8000, while we want it to compute r3+x@tprel
390 // = r3+x-0x7000, so add 4096 to r3.
391 // bl __tls_get_addr(x@tlsld) --> addi r3, r3, 4096
392 write32(loc, 0x38631000);
393 break;
394 case R_PPC_DTPREL16:
395 case R_PPC_DTPREL16_HA:
396 case R_PPC_DTPREL16_HI:
397 case R_PPC_DTPREL16_LO:
398 relocateOne(loc, type, val);
399 break;
400 default:
401 llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
402 }
403}
404
405void PPC::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
406 switch (type) {
407 case R_PPC_GOT_TPREL16: {
408 // lwz rT, x@got@tprel(rA) --> addis rT, r2, x@tprel@ha
409 uint32_t rt = readFromHalf16(loc) & 0x03e00000;
410 writeFromHalf16(loc, 0x3c020000 | rt | ha(val));
411 break;
412 }
413 case R_PPC_TLS: {
414 uint32_t insn = read32(loc);
415 if (insn >> 26 != 31)
416 error("unrecognized instruction for IE to LE R_PPC_TLS");
417 // addi rT, rT, x@tls --> addi rT, rT, x@tprel@l
418 uint32_t dFormOp = getPPCDFormOp((read32(loc) & 0x000007fe) >> 1);
419 if (dFormOp == 0)
420 error("unrecognized instruction for IE to LE R_PPC_TLS");
421 write32(loc, (dFormOp << 26) | (insn & 0x03ff0000) | lo(val));
422 break;
423 }
73 default:424 default:
74 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));425 llvm_unreachable("unsupported relocation for TLS IE to LE relaxation");
75 }426 }
76}427}
77428
78TargetInfo *elf::getPPCTargetInfo() {429TargetInfo *elf::getPPCTargetInfo() {
79 static PPC Target;430 static PPC target;
80 return &Target;431 return &target;
81}432}
deps/lld/ELF/Arch/PPC64.cpp+438-292
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- PPC64.cpp ----------------------------------------------------------===//1//===- PPC64.cpp ----------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -20,8 +19,8 @@ using namespace llvm::ELF;...@@ -20,8 +19,8 @@ using namespace llvm::ELF;
20using namespace lld;19using namespace lld;
21using namespace lld::elf;20using namespace lld::elf;
2221
23static uint64_t PPC64TocOffset = 0x8000;22static uint64_t ppc64TocOffset = 0x8000;
24static uint64_t DynamicThreadPointerOffset = 0x8000;23static uint64_t dynamicThreadPointerOffset = 0x8000;
2524
26// The instruction encoding of bits 21-30 from the ISA for the Xform and Dform25// 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.26// instructions that can be used as part of the initial exec TLS sequence.
...@@ -65,16 +64,16 @@ uint64_t elf::getPPC64TocBase() {...@@ -65,16 +64,16 @@ uint64_t elf::getPPC64TocBase() {
65 // TOC starts where the first of these sections starts. We always create a64 // TOC starts where the first of these sections starts. We always create a
66 // .got when we see a relocation that uses it, so for us the start is always65 // .got when we see a relocation that uses it, so for us the start is always
67 // the .got.66 // the .got.
68 uint64_t TocVA = In.Got->getVA();67 uint64_t tocVA = in.got->getVA();
6968
70 // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x800069 // Per the ppc64-elf-linux ABI, The TOC base is TOC value plus 0x8000
71 // thus permitting a full 64 Kbytes segment. Note that the glibc startup70 // thus permitting a full 64 Kbytes segment. Note that the glibc startup
72 // code (crt1.o) assumes that you can get from the TOC base to the71 // code (crt1.o) assumes that you can get from the TOC base to the
73 // start of the .toc section with only a single (signed) 16-bit relocation.72 // start of the .toc section with only a single (signed) 16-bit relocation.
74 return TocVA + PPC64TocOffset;73 return tocVA + ppc64TocOffset;
75}74}
7675
77unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther) {76unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther) {
78 // The offset is encoded into the 3 most significant bits of the st_other77 // 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:78 // 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 use79 // 0 --> Zero offset between the GEP and LEP, and the function does NOT use
...@@ -86,43 +85,134 @@ unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther) {...@@ -86,43 +85,134 @@ unsigned elf::getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther) {
86 // 2 --> 2^2 = 4 bytes --> 1 instruction.85 // 2 --> 2^2 = 4 bytes --> 1 instruction.
87 // 6 --> 2^6 = 64 bytes --> 16 instructions.86 // 6 --> 2^6 = 64 bytes --> 16 instructions.
88 // 7 --> Reserved.87 // 7 --> Reserved.
89 uint8_t GepToLep = (StOther >> 5) & 7;88 uint8_t gepToLep = (stOther >> 5) & 7;
90 if (GepToLep < 2)89 if (gepToLep < 2)
91 return 0;90 return 0;
9291
93 // The value encoded in the st_other bits is the92 // The value encoded in the st_other bits is the
94 // log-base-2(offset).93 // log-base-2(offset).
95 if (GepToLep < 7)94 if (gepToLep < 7)
96 return 1 << GepToLep;95 return 1 << gepToLep;
9796
98 error("reserved value of 7 in the 3 most-significant-bits of st_other");97 error("reserved value of 7 in the 3 most-significant-bits of st_other");
99 return 0;98 return 0;
100}99}
101100
101bool elf::isPPC64SmallCodeModelTocReloc(RelType type) {
102 // The only small code model relocations that access the .toc section.
103 return type == R_PPC64_TOC16 || type == R_PPC64_TOC16_DS;
104}
105
106// Find the R_PPC64_ADDR64 in .rela.toc with matching offset.
107template <typename ELFT>
108static std::pair<Defined *, int64_t>
109getRelaTocSymAndAddend(InputSectionBase *tocSec, uint64_t offset) {
110 if (tocSec->numRelocations == 0)
111 return {};
112
113 // .rela.toc contains exclusively R_PPC64_ADDR64 relocations sorted by
114 // r_offset: 0, 8, 16, etc. For a given Offset, Offset / 8 gives us the
115 // relocation index in most cases.
116 //
117 // In rare cases a TOC entry may store a constant that doesn't need an
118 // R_PPC64_ADDR64, the corresponding r_offset is therefore missing. Offset / 8
119 // points to a relocation with larger r_offset. Do a linear probe then.
120 // Constants are extremely uncommon in .toc and the extra number of array
121 // accesses can be seen as a small constant.
122 ArrayRef<typename ELFT::Rela> relas = tocSec->template relas<ELFT>();
123 uint64_t index = std::min<uint64_t>(offset / 8, relas.size() - 1);
124 for (;;) {
125 if (relas[index].r_offset == offset) {
126 Symbol &sym = tocSec->getFile<ELFT>()->getRelocTargetSym(relas[index]);
127 return {dyn_cast<Defined>(&sym), getAddend<ELFT>(relas[index])};
128 }
129 if (relas[index].r_offset < offset || index == 0)
130 break;
131 --index;
132 }
133 return {};
134}
135
136// When accessing a symbol defined in another translation unit, compilers
137// reserve a .toc entry, allocate a local label and generate toc-indirect
138// instuctions:
139//
140// addis 3, 2, .LC0@toc@ha # R_PPC64_TOC16_HA
141// ld 3, .LC0@toc@l(3) # R_PPC64_TOC16_LO_DS, load the address from a .toc entry
142// ld/lwa 3, 0(3) # load the value from the address
143//
144// .section .toc,"aw",@progbits
145// .LC0: .tc var[TC],var
146//
147// If var is defined, non-preemptable and addressable with a 32-bit signed
148// offset from the toc base, the address of var can be computed by adding an
149// offset to the toc base, saving a load.
150//
151// addis 3,2,var@toc@ha # this may be relaxed to a nop,
152// addi 3,3,var@toc@l # then this becomes addi 3,2,var@toc
153// ld/lwa 3, 0(3) # load the value from the address
154//
155// Returns true if the relaxation is performed.
156bool elf::tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel,
157 uint8_t *bufLoc) {
158 assert(config->tocOptimize);
159 if (rel.addend < 0)
160 return false;
161
162 // If the symbol is not the .toc section, this isn't a toc-indirection.
163 Defined *defSym = dyn_cast<Defined>(rel.sym);
164 if (!defSym || !defSym->isSection() || defSym->section->name != ".toc")
165 return false;
166
167 Defined *d;
168 int64_t addend;
169 auto *tocISB = cast<InputSectionBase>(defSym->section);
170 std::tie(d, addend) =
171 config->isLE ? getRelaTocSymAndAddend<ELF64LE>(tocISB, rel.addend)
172 : getRelaTocSymAndAddend<ELF64BE>(tocISB, rel.addend);
173
174 // Only non-preemptable defined symbols can be relaxed.
175 if (!d || d->isPreemptible)
176 return false;
177
178 // Two instructions can materialize a 32-bit signed offset from the toc base.
179 uint64_t tocRelative = d->getVA(addend) - getPPC64TocBase();
180 if (!isInt<32>(tocRelative))
181 return false;
182
183 // Add PPC64TocOffset that will be subtracted by relocateOne().
184 target->relaxGot(bufLoc, type, tocRelative + ppc64TocOffset);
185 return true;
186}
187
102namespace {188namespace {
103class PPC64 final : public TargetInfo {189class PPC64 final : public TargetInfo {
104public:190public:
105 PPC64();191 PPC64();
192 int getTlsGdRelaxSkip(RelType type) const override;
106 uint32_t calcEFlags() const override;193 uint32_t calcEFlags() const override;
107 RelExpr getRelExpr(RelType Type, const Symbol &S,194 RelExpr getRelExpr(RelType type, const Symbol &s,
108 const uint8_t *Loc) const override;195 const uint8_t *loc) const override;
109 void writePltHeader(uint8_t *Buf) const override;196 RelType getDynRel(RelType type) const override;
110 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,197 void writePltHeader(uint8_t *buf) const override;
111 int32_t Index, unsigned RelOff) const override;198 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
112 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;199 int32_t index, unsigned relOff) const override;
113 void writeGotHeader(uint8_t *Buf) const override;200 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
114 bool needsThunk(RelExpr Expr, RelType Type, const InputFile *File,201 void writeGotHeader(uint8_t *buf) const override;
115 uint64_t BranchAddr, const Symbol &S) const override;202 bool needsThunk(RelExpr expr, RelType type, const InputFile *file,
116 bool inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const override;203 uint64_t branchAddr, const Symbol &s) const override;
117 RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,204 uint32_t getThunkSectionSpacing() const override;
118 RelExpr Expr) const override;205 bool inBranchRange(RelType type, uint64_t src, uint64_t dst) const override;
119 void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override;206 RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
120 void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;207 RelExpr expr) const override;
121 void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;208 void relaxGot(uint8_t *loc, RelType type, uint64_t val) const override;
122 void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;209 void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
123210 void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
124 bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End,211 void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
125 uint8_t StOther) const override;212 void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
213
214 bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
215 uint8_t stOther) const override;
126};216};
127} // namespace217} // namespace
128218
...@@ -130,19 +220,19 @@ public:...@@ -130,19 +220,19 @@ public:
130// #higher(value), #highera(value), #highest(value), and #highesta(value)220// #higher(value), #highera(value), #highest(value), and #highesta(value)
131// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi221// macros defined in section 4.5.1. Relocation Types of the PPC-elf64abi
132// document.222// document.
133static uint16_t lo(uint64_t V) { return V; }223static uint16_t lo(uint64_t v) { return v; }
134static uint16_t hi(uint64_t V) { return V >> 16; }224static uint16_t hi(uint64_t v) { return v >> 16; }
135static uint16_t ha(uint64_t V) { return (V + 0x8000) >> 16; }225static uint16_t ha(uint64_t v) { return (v + 0x8000) >> 16; }
136static uint16_t higher(uint64_t V) { return V >> 32; }226static uint16_t higher(uint64_t v) { return v >> 32; }
137static uint16_t highera(uint64_t V) { return (V + 0x8000) >> 32; }227static uint16_t highera(uint64_t v) { return (v + 0x8000) >> 32; }
138static uint16_t highest(uint64_t V) { return V >> 48; }228static uint16_t highest(uint64_t v) { return v >> 48; }
139static uint16_t highesta(uint64_t V) { return (V + 0x8000) >> 48; }229static uint16_t highesta(uint64_t v) { return (v + 0x8000) >> 48; }
140230
141// Extracts the 'PO' field of an instruction encoding.231// Extracts the 'PO' field of an instruction encoding.
142static uint8_t getPrimaryOpCode(uint32_t Encoding) { return (Encoding >> 26); }232static uint8_t getPrimaryOpCode(uint32_t encoding) { return (encoding >> 26); }
143233
144static bool isDQFormInstruction(uint32_t Encoding) {234static bool isDQFormInstruction(uint32_t encoding) {
145 switch (getPrimaryOpCode(Encoding)) {235 switch (getPrimaryOpCode(encoding)) {
146 default:236 default:
147 return false;237 return false;
148 case 56:238 case 56:
...@@ -152,12 +242,12 @@ static bool isDQFormInstruction(uint32_t Encoding) {...@@ -152,12 +242,12 @@ static bool isDQFormInstruction(uint32_t Encoding) {
152 // There are both DS and DQ instruction forms with this primary opcode.242 // There are both DS and DQ instruction forms with this primary opcode.
153 // Namely `lxv` and `stxv` are the DQ-forms that use it.243 // 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.244 // The DS 'XO' bits being set to 01 is restricted to DQ form.
155 return (Encoding & 3) == 0x1;245 return (encoding & 3) == 0x1;
156 }246 }
157}247}
158248
159static bool isInstructionUpdateForm(uint32_t Encoding) {249static bool isInstructionUpdateForm(uint32_t encoding) {
160 switch (getPrimaryOpCode(Encoding)) {250 switch (getPrimaryOpCode(encoding)) {
161 default:251 default:
162 return false;252 return false;
163 case LBZU:253 case LBZU:
...@@ -176,7 +266,7 @@ static bool isInstructionUpdateForm(uint32_t Encoding) {...@@ -176,7 +266,7 @@ static bool isInstructionUpdateForm(uint32_t Encoding) {
176 // between LD/LDU/LWA266 // between LD/LDU/LWA
177 case LD:267 case LD:
178 case STD:268 case STD:
179 return (Encoding & 3) == 1;269 return (encoding & 3) == 1;
180 }270 }
181}271}
182272
...@@ -185,40 +275,38 @@ static bool isInstructionUpdateForm(uint32_t Encoding) {...@@ -185,40 +275,38 @@ static bool isInstructionUpdateForm(uint32_t Encoding) {
185// pointer is pointing into the middle of the word we want to extract, and on275// 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 to276// little-endian it is pointing to the start of the word. These 2 helpers are to
187// simplify reading and writing in that context.277// simplify reading and writing in that context.
188static void writeInstrFromHalf16(uint8_t *Loc, uint32_t Instr) {278static void writeFromHalf16(uint8_t *loc, uint32_t insn) {
189 write32(Loc - (Config->EKind == ELF64BEKind ? 2 : 0), Instr);279 write32(config->isLE ? loc : loc - 2, insn);
190}280}
191281
192static uint32_t readInstrFromHalf16(const uint8_t *Loc) {282static uint32_t readFromHalf16(const uint8_t *loc) {
193 return read32(Loc - (Config->EKind == ELF64BEKind ? 2 : 0));283 return read32(config->isLE ? loc : loc - 2);
194}284}
195285
196PPC64::PPC64() {286PPC64::PPC64() {
197 GotRel = R_PPC64_GLOB_DAT;287 gotRel = R_PPC64_GLOB_DAT;
198 NoneRel = R_PPC64_NONE;288 noneRel = R_PPC64_NONE;
199 PltRel = R_PPC64_JMP_SLOT;289 pltRel = R_PPC64_JMP_SLOT;
200 RelativeRel = R_PPC64_RELATIVE;290 relativeRel = R_PPC64_RELATIVE;
201 IRelativeRel = R_PPC64_IRELATIVE;291 iRelativeRel = R_PPC64_IRELATIVE;
202 GotEntrySize = 8;292 symbolicRel = R_PPC64_ADDR64;
203 PltEntrySize = 4;293 pltEntrySize = 4;
204 GotPltEntrySize = 8;294 gotBaseSymInGotPlt = false;
205 GotBaseSymInGotPlt = false;295 gotHeaderEntriesNum = 1;
206 GotBaseSymOff = 0x8000;296 gotPltHeaderEntriesNum = 2;
207 GotHeaderEntriesNum = 1;297 pltHeaderSize = 60;
208 GotPltHeaderEntriesNum = 2;298 needsThunks = true;
209 PltHeaderSize = 60;299
210 NeedsThunks = true;300 tlsModuleIndexRel = R_PPC64_DTPMOD64;
211301 tlsOffsetRel = R_PPC64_DTPREL64;
212 TlsModuleIndexRel = R_PPC64_DTPMOD64;302
213 TlsOffsetRel = R_PPC64_DTPREL64;303 tlsGotRel = R_PPC64_TPREL64;
214304
215 TlsGotRel = R_PPC64_TPREL64;305 needsMoreStackNonSplit = false;
216
217 NeedsMoreStackNonSplit = false;
218306
219 // We need 64K pages (at least under glibc/Linux, the loader won't307 // We need 64K pages (at least under glibc/Linux, the loader won't
220 // set different permissions on a finer granularity than that).308 // set different permissions on a finer granularity than that).
221 DefaultMaxPageSize = 65536;309 defaultMaxPageSize = 65536;
222310
223 // The PPC64 ELF ABI v1 spec, says:311 // The PPC64 ELF ABI v1 spec, says:
224 //312 //
...@@ -228,31 +316,66 @@ PPC64::PPC64() {...@@ -228,31 +316,66 @@ PPC64::PPC64() {
228 //316 //
229 // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers317 // And because the lowest non-zero 256M boundary is 0x10000000, PPC64 linkers
230 // use 0x10000000 as the starting address.318 // use 0x10000000 as the starting address.
231 DefaultImageBase = 0x10000000;319 defaultImageBase = 0x10000000;
232320
233 write32(TrapInstr.data(), 0x7fe00008);321 write32(trapInstr.data(), 0x7fe00008);
322}
323
324int PPC64::getTlsGdRelaxSkip(RelType type) const {
325 // A __tls_get_addr call instruction is marked with 2 relocations:
326 //
327 // R_PPC64_TLSGD / R_PPC64_TLSLD: marker relocation
328 // R_PPC64_REL24: __tls_get_addr
329 //
330 // After the relaxation we no longer call __tls_get_addr and should skip both
331 // relocations to not create a false dependence on __tls_get_addr being
332 // defined.
333 if (type == R_PPC64_TLSGD || type == R_PPC64_TLSLD)
334 return 2;
335 return 1;
234}336}
235337
236static uint32_t getEFlags(InputFile *File) {338static uint32_t getEFlags(InputFile *file) {
237 if (Config->EKind == ELF64BEKind)339 if (config->ekind == ELF64BEKind)
238 return cast<ObjFile<ELF64BE>>(File)->getObj().getHeader()->e_flags;340 return cast<ObjFile<ELF64BE>>(file)->getObj().getHeader()->e_flags;
239 return cast<ObjFile<ELF64LE>>(File)->getObj().getHeader()->e_flags;341 return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader()->e_flags;
240}342}
241343
242// This file implements v2 ABI. This function makes sure that all344// This file implements v2 ABI. This function makes sure that all
243// object files have v2 or an unspecified version as an ABI version.345// object files have v2 or an unspecified version as an ABI version.
244uint32_t PPC64::calcEFlags() const {346uint32_t PPC64::calcEFlags() const {
245 for (InputFile *F : ObjectFiles) {347 for (InputFile *f : objectFiles) {
246 uint32_t Flag = getEFlags(F);348 uint32_t flag = getEFlags(f);
247 if (Flag == 1)349 if (flag == 1)
248 error(toString(F) + ": ABI version 1 is not supported");350 error(toString(f) + ": ABI version 1 is not supported");
249 else if (Flag > 2)351 else if (flag > 2)
250 error(toString(F) + ": unrecognized e_flags: " + Twine(Flag));352 error(toString(f) + ": unrecognized e_flags: " + Twine(flag));
251 }353 }
252 return 2;354 return 2;
253}355}
254356
255void PPC64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {357void PPC64::relaxGot(uint8_t *loc, RelType type, uint64_t val) const {
358 switch (type) {
359 case R_PPC64_TOC16_HA:
360 // Convert "addis reg, 2, .LC0@toc@h" to "addis reg, 2, var@toc@h" or "nop".
361 relocateOne(loc, type, val);
362 break;
363 case R_PPC64_TOC16_LO_DS: {
364 // Convert "ld reg, .LC0@toc@l(reg)" to "addi reg, reg, var@toc@l" or
365 // "addi reg, 2, var@toc".
366 uint32_t insn = readFromHalf16(loc);
367 if (getPrimaryOpCode(insn) != LD)
368 error("expected a 'ld' for got-indirect to toc-relative relaxing");
369 writeFromHalf16(loc, (insn & 0x03ffffff) | 0x38000000);
370 relocateOne(loc, R_PPC64_TOC16_LO, val);
371 break;
372 }
373 default:
374 llvm_unreachable("unexpected relocation type");
375 }
376}
377
378void PPC64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
256 // Reference: 3.7.4.2 of the 64-bit ELF V2 abi supplement.379 // Reference: 3.7.4.2 of the 64-bit ELF V2 abi supplement.
257 // The general dynamic code sequence for a global `x` will look like:380 // The general dynamic code sequence for a global `x` will look like:
258 // Instruction Relocation Symbol381 // Instruction Relocation Symbol
...@@ -268,30 +391,30 @@ void PPC64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -268,30 +391,30 @@ void PPC64::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
268 // bl __tls_get_addr(x@tlsgd) into nop391 // bl __tls_get_addr(x@tlsgd) into nop
269 // nop into addi r3, r3, x@tprel@l392 // nop into addi r3, r3, x@tprel@l
270393
271 switch (Type) {394 switch (type) {
272 case R_PPC64_GOT_TLSGD16_HA:395 case R_PPC64_GOT_TLSGD16_HA:
273 writeInstrFromHalf16(Loc, 0x60000000); // nop396 writeFromHalf16(loc, 0x60000000); // nop
274 break;397 break;
275 case R_PPC64_GOT_TLSGD16:398 case R_PPC64_GOT_TLSGD16:
276 case R_PPC64_GOT_TLSGD16_LO:399 case R_PPC64_GOT_TLSGD16_LO:
277 writeInstrFromHalf16(Loc, 0x3c6d0000); // addis r3, r13400 writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13
278 relocateOne(Loc, R_PPC64_TPREL16_HA, Val);401 relocateOne(loc, R_PPC64_TPREL16_HA, val);
279 break;402 break;
280 case R_PPC64_TLSGD:403 case R_PPC64_TLSGD:
281 write32(Loc, 0x60000000); // nop404 write32(loc, 0x60000000); // nop
282 write32(Loc + 4, 0x38630000); // addi r3, r3405 write32(loc + 4, 0x38630000); // addi r3, r3
283 // Since we are relocating a half16 type relocation and Loc + 4 points to406 // 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 extra407 // the start of an instruction we need to advance the buffer by an extra
285 // 2 bytes on BE.408 // 2 bytes on BE.
286 relocateOne(Loc + 4 + (Config->EKind == ELF64BEKind ? 2 : 0),409 relocateOne(loc + 4 + (config->ekind == ELF64BEKind ? 2 : 0),
287 R_PPC64_TPREL16_LO, Val);410 R_PPC64_TPREL16_LO, val);
288 break;411 break;
289 default:412 default:
290 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");413 llvm_unreachable("unsupported relocation for TLS GD to LE relaxation");
291 }414 }
292}415}
293416
294void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {417void PPC64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
295 // Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement.418 // Reference: 3.7.4.3 of the 64-bit ELF V2 abi supplement.
296 // The local dynamic code sequence for a global `x` will look like:419 // The local dynamic code sequence for a global `x` will look like:
297 // Instruction Relocation Symbol420 // Instruction Relocation Symbol
...@@ -307,16 +430,16 @@ void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -307,16 +430,16 @@ void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
307 // bl __tls_get_addr(x@tlsgd) into nop430 // bl __tls_get_addr(x@tlsgd) into nop
308 // nop into addi r3, r3, 4096431 // nop into addi r3, r3, 4096
309432
310 switch (Type) {433 switch (type) {
311 case R_PPC64_GOT_TLSLD16_HA:434 case R_PPC64_GOT_TLSLD16_HA:
312 writeInstrFromHalf16(Loc, 0x60000000); // nop435 writeFromHalf16(loc, 0x60000000); // nop
313 break;436 break;
314 case R_PPC64_GOT_TLSLD16_LO:437 case R_PPC64_GOT_TLSLD16_LO:
315 writeInstrFromHalf16(Loc, 0x3c6d0000); // addis r3, r13, 0438 writeFromHalf16(loc, 0x3c6d0000); // addis r3, r13, 0
316 break;439 break;
317 case R_PPC64_TLSLD:440 case R_PPC64_TLSLD:
318 write32(Loc, 0x60000000); // nop441 write32(loc, 0x60000000); // nop
319 write32(Loc + 4, 0x38631000); // addi r3, r3, 4096442 write32(loc + 4, 0x38631000); // addi r3, r3, 4096
320 break;443 break;
321 case R_PPC64_DTPREL16:444 case R_PPC64_DTPREL16:
322 case R_PPC64_DTPREL16_HA:445 case R_PPC64_DTPREL16_HA:
...@@ -324,19 +447,15 @@ void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -324,19 +447,15 @@ void PPC64::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
324 case R_PPC64_DTPREL16_DS:447 case R_PPC64_DTPREL16_DS:
325 case R_PPC64_DTPREL16_LO:448 case R_PPC64_DTPREL16_LO:
326 case R_PPC64_DTPREL16_LO_DS:449 case R_PPC64_DTPREL16_LO_DS:
327 case R_PPC64_GOT_DTPREL16_HA:450 relocateOne(loc, type, val);
328 case R_PPC64_GOT_DTPREL16_LO_DS:
329 case R_PPC64_GOT_DTPREL16_DS:
330 case R_PPC64_GOT_DTPREL16_HI:
331 relocateOne(Loc, Type, Val);
332 break;451 break;
333 default:452 default:
334 llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");453 llvm_unreachable("unsupported relocation for TLS LD to LE relaxation");
335 }454 }
336}455}
337456
338static unsigned getDFormOp(unsigned SecondaryOp) {457unsigned elf::getPPCDFormOp(unsigned secondaryOp) {
339 switch (SecondaryOp) {458 switch (secondaryOp) {
340 case LBZX:459 case LBZX:
341 return LBZ;460 return LBZ;
342 case LHZX:461 case LHZX:
...@@ -356,12 +475,11 @@ static unsigned getDFormOp(unsigned SecondaryOp) {...@@ -356,12 +475,11 @@ static unsigned getDFormOp(unsigned SecondaryOp) {
356 case ADD:475 case ADD:
357 return ADDI;476 return ADDI;
358 default:477 default:
359 error("unrecognized instruction for IE to LE R_PPC64_TLS");
360 return 0;478 return 0;
361 }479 }
362}480}
363481
364void PPC64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {482void PPC64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
365 // The initial exec code sequence for a global `x` will look like:483 // The initial exec code sequence for a global `x` will look like:
366 // Instruction Relocation Symbol484 // Instruction Relocation Symbol
367 // addis r9, r2, x@got@tprel@ha R_PPC64_GOT_TPREL16_HA x485 // addis r9, r2, x@got@tprel@ha R_PPC64_GOT_TPREL16_HA x
...@@ -381,26 +499,28 @@ void PPC64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -381,26 +499,28 @@ void PPC64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
381 // instruction, if we are accessing memory it will use any of the X-form499 // instruction, if we are accessing memory it will use any of the X-form
382 // indexed load or store instructions.500 // indexed load or store instructions.
383501
384 unsigned Offset = (Config->EKind == ELF64BEKind) ? 2 : 0;502 unsigned offset = (config->ekind == ELF64BEKind) ? 2 : 0;
385 switch (Type) {503 switch (type) {
386 case R_PPC64_GOT_TPREL16_HA:504 case R_PPC64_GOT_TPREL16_HA:
387 write32(Loc - Offset, 0x60000000); // nop505 write32(loc - offset, 0x60000000); // nop
388 break;506 break;
389 case R_PPC64_GOT_TPREL16_LO_DS:507 case R_PPC64_GOT_TPREL16_LO_DS:
390 case R_PPC64_GOT_TPREL16_DS: {508 case R_PPC64_GOT_TPREL16_DS: {
391 uint32_t RegNo = read32(Loc - Offset) & 0x03E00000; // bits 6-10509 uint32_t regNo = read32(loc - offset) & 0x03E00000; // bits 6-10
392 write32(Loc - Offset, 0x3C0D0000 | RegNo); // addis RegNo, r13510 write32(loc - offset, 0x3C0D0000 | regNo); // addis RegNo, r13
393 relocateOne(Loc, R_PPC64_TPREL16_HA, Val);511 relocateOne(loc, R_PPC64_TPREL16_HA, val);
394 break;512 break;
395 }513 }
396 case R_PPC64_TLS: {514 case R_PPC64_TLS: {
397 uint32_t PrimaryOp = getPrimaryOpCode(read32(Loc));515 uint32_t primaryOp = getPrimaryOpCode(read32(loc));
398 if (PrimaryOp != 31)516 if (primaryOp != 31)
399 error("unrecognized instruction for IE to LE R_PPC64_TLS");517 error("unrecognized instruction for IE to LE R_PPC64_TLS");
400 uint32_t SecondaryOp = (read32(Loc) & 0x000007FE) >> 1; // bits 21-30518 uint32_t secondaryOp = (read32(loc) & 0x000007FE) >> 1; // bits 21-30
401 uint32_t DFormOp = getDFormOp(SecondaryOp);519 uint32_t dFormOp = getPPCDFormOp(secondaryOp);
402 write32(Loc, ((DFormOp << 26) | (read32(Loc) & 0x03FFFFFF)));520 if (dFormOp == 0)
403 relocateOne(Loc + Offset, R_PPC64_TPREL16_LO, Val);521 error("unrecognized instruction for IE to LE R_PPC64_TLS");
522 write32(loc, ((dFormOp << 26) | (read32(loc) & 0x03FFFFFF)));
523 relocateOne(loc + offset, R_PPC64_TPREL16_LO, val);
404 break;524 break;
405 }525 }
406 default:526 default:
...@@ -409,9 +529,9 @@ void PPC64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -409,9 +529,9 @@ void PPC64::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
409 }529 }
410}530}
411531
412RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,532RelExpr PPC64::getRelExpr(RelType type, const Symbol &s,
413 const uint8_t *Loc) const {533 const uint8_t *loc) const {
414 switch (Type) {534 switch (type) {
415 case R_PPC64_GOT16:535 case R_PPC64_GOT16:
416 case R_PPC64_GOT16_DS:536 case R_PPC64_GOT16_DS:
417 case R_PPC64_GOT16_HA:537 case R_PPC64_GOT16_HA:
...@@ -421,16 +541,17 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,...@@ -421,16 +541,17 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
421 return R_GOT_OFF;541 return R_GOT_OFF;
422 case R_PPC64_TOC16:542 case R_PPC64_TOC16:
423 case R_PPC64_TOC16_DS:543 case R_PPC64_TOC16_DS:
424 case R_PPC64_TOC16_HA:
425 case R_PPC64_TOC16_HI:544 case R_PPC64_TOC16_HI:
426 case R_PPC64_TOC16_LO:545 case R_PPC64_TOC16_LO:
427 case R_PPC64_TOC16_LO_DS:
428 return R_GOTREL;546 return R_GOTREL;
547 case R_PPC64_TOC16_HA:
548 case R_PPC64_TOC16_LO_DS:
549 return config->tocOptimize ? R_PPC64_RELAX_TOC : R_GOTREL;
429 case R_PPC64_TOC:550 case R_PPC64_TOC:
430 return R_PPC_TOC;551 return R_PPC64_TOCBASE;
431 case R_PPC64_REL14:552 case R_PPC64_REL14:
432 case R_PPC64_REL24:553 case R_PPC64_REL24:
433 return R_PPC_CALL_PLT;554 return R_PPC64_CALL_PLT;
434 case R_PPC64_REL16_LO:555 case R_PPC64_REL16_LO:
435 case R_PPC64_REL16_HA:556 case R_PPC64_REL16_HA:
436 case R_PPC64_REL32:557 case R_PPC64_REL32:
...@@ -478,7 +599,7 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,...@@ -478,7 +599,7 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
478 case R_PPC64_DTPREL16_LO:599 case R_PPC64_DTPREL16_LO:
479 case R_PPC64_DTPREL16_LO_DS:600 case R_PPC64_DTPREL16_LO_DS:
480 case R_PPC64_DTPREL64:601 case R_PPC64_DTPREL64:
481 return R_ABS;602 return R_DTPREL;
482 case R_PPC64_TLSGD:603 case R_PPC64_TLSGD:
483 return R_TLSDESC_CALL;604 return R_TLSDESC_CALL;
484 case R_PPC64_TLSLD:605 case R_PPC64_TLSLD:
...@@ -490,115 +611,121 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,...@@ -490,115 +611,121 @@ RelExpr PPC64::getRelExpr(RelType Type, const Symbol &S,
490 }611 }
491}612}
492613
493void PPC64::writeGotHeader(uint8_t *Buf) const {614RelType PPC64::getDynRel(RelType type) const {
494 write64(Buf, getPPC64TocBase());615 if (type == R_PPC64_ADDR64 || type == R_PPC64_TOC)
616 return R_PPC64_ADDR64;
617 return R_PPC64_NONE;
495}618}
496619
497void PPC64::writePltHeader(uint8_t *Buf) const {620void PPC64::writeGotHeader(uint8_t *buf) const {
621 write64(buf, getPPC64TocBase());
622}
623
624void PPC64::writePltHeader(uint8_t *buf) const {
498 // The generic resolver stub goes first.625 // The generic resolver stub goes first.
499 write32(Buf + 0, 0x7c0802a6); // mflr r0626 write32(buf + 0, 0x7c0802a6); // mflr r0
500 write32(Buf + 4, 0x429f0005); // bcl 20,4*cr7+so,8 <_glink+0x8>627 write32(buf + 4, 0x429f0005); // bcl 20,4*cr7+so,8 <_glink+0x8>
501 write32(Buf + 8, 0x7d6802a6); // mflr r11628 write32(buf + 8, 0x7d6802a6); // mflr r11
502 write32(Buf + 12, 0x7c0803a6); // mtlr r0629 write32(buf + 12, 0x7c0803a6); // mtlr r0
503 write32(Buf + 16, 0x7d8b6050); // subf r12, r11, r12630 write32(buf + 16, 0x7d8b6050); // subf r12, r11, r12
504 write32(Buf + 20, 0x380cffcc); // subi r0,r12,52631 write32(buf + 20, 0x380cffcc); // subi r0,r12,52
505 write32(Buf + 24, 0x7800f082); // srdi r0,r0,62,2632 write32(buf + 24, 0x7800f082); // srdi r0,r0,62,2
506 write32(Buf + 28, 0xe98b002c); // ld r12,44(r11)633 write32(buf + 28, 0xe98b002c); // ld r12,44(r11)
507 write32(Buf + 32, 0x7d6c5a14); // add r11,r12,r11634 write32(buf + 32, 0x7d6c5a14); // add r11,r12,r11
508 write32(Buf + 36, 0xe98b0000); // ld r12,0(r11)635 write32(buf + 36, 0xe98b0000); // ld r12,0(r11)
509 write32(Buf + 40, 0xe96b0008); // ld r11,8(r11)636 write32(buf + 40, 0xe96b0008); // ld r11,8(r11)
510 write32(Buf + 44, 0x7d8903a6); // mtctr r12637 write32(buf + 44, 0x7d8903a6); // mtctr r12
511 write32(Buf + 48, 0x4e800420); // bctr638 write32(buf + 48, 0x4e800420); // bctr
512639
513 // The 'bcl' instruction will set the link register to the address of the640 // The 'bcl' instruction will set the link register to the address of the
514 // following instruction ('mflr r11'). Here we store the offset from that641 // following instruction ('mflr r11'). Here we store the offset from that
515 // instruction to the first entry in the GotPlt section.642 // instruction to the first entry in the GotPlt section.
516 int64_t GotPltOffset = In.GotPlt->getVA() - (In.Plt->getVA() + 8);643 int64_t gotPltOffset = in.gotPlt->getVA() - (in.plt->getVA() + 8);
517 write64(Buf + 52, GotPltOffset);644 write64(buf + 52, gotPltOffset);
518}645}
519646
520void PPC64::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,647void PPC64::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
521 uint64_t PltEntryAddr, int32_t Index,648 uint64_t pltEntryAddr, int32_t index,
522 unsigned RelOff) const {649 unsigned relOff) const {
523 int32_t Offset = PltHeaderSize + Index * PltEntrySize;650 int32_t offset = pltHeaderSize + index * pltEntrySize;
524 // bl __glink_PLTresolve651 // bl __glink_PLTresolve
525 write32(Buf, 0x48000000 | ((-Offset) & 0x03FFFFFc));652 write32(buf, 0x48000000 | ((-offset) & 0x03FFFFFc));
526}653}
527654
528static std::pair<RelType, uint64_t> toAddr16Rel(RelType Type, uint64_t Val) {655static std::pair<RelType, uint64_t> toAddr16Rel(RelType type, uint64_t val) {
529 // Relocations relative to the toc-base need to be adjusted by the Toc offset.656 // Relocations relative to the toc-base need to be adjusted by the Toc offset.
530 uint64_t TocBiasedVal = Val - PPC64TocOffset;657 uint64_t tocBiasedVal = val - ppc64TocOffset;
531 // Relocations relative to dtv[dtpmod] need to be adjusted by the DTP offset.658 // Relocations relative to dtv[dtpmod] need to be adjusted by the DTP offset.
532 uint64_t DTPBiasedVal = Val - DynamicThreadPointerOffset;659 uint64_t dtpBiasedVal = val - dynamicThreadPointerOffset;
533660
534 switch (Type) {661 switch (type) {
535 // TOC biased relocation.662 // TOC biased relocation.
536 case R_PPC64_GOT16:663 case R_PPC64_GOT16:
537 case R_PPC64_GOT_TLSGD16:664 case R_PPC64_GOT_TLSGD16:
538 case R_PPC64_GOT_TLSLD16:665 case R_PPC64_GOT_TLSLD16:
539 case R_PPC64_TOC16:666 case R_PPC64_TOC16:
540 return {R_PPC64_ADDR16, TocBiasedVal};667 return {R_PPC64_ADDR16, tocBiasedVal};
541 case R_PPC64_GOT16_DS:668 case R_PPC64_GOT16_DS:
542 case R_PPC64_TOC16_DS:669 case R_PPC64_TOC16_DS:
543 case R_PPC64_GOT_TPREL16_DS:670 case R_PPC64_GOT_TPREL16_DS:
544 case R_PPC64_GOT_DTPREL16_DS:671 case R_PPC64_GOT_DTPREL16_DS:
545 return {R_PPC64_ADDR16_DS, TocBiasedVal};672 return {R_PPC64_ADDR16_DS, tocBiasedVal};
546 case R_PPC64_GOT16_HA:673 case R_PPC64_GOT16_HA:
547 case R_PPC64_GOT_TLSGD16_HA:674 case R_PPC64_GOT_TLSGD16_HA:
548 case R_PPC64_GOT_TLSLD16_HA:675 case R_PPC64_GOT_TLSLD16_HA:
549 case R_PPC64_GOT_TPREL16_HA:676 case R_PPC64_GOT_TPREL16_HA:
550 case R_PPC64_GOT_DTPREL16_HA:677 case R_PPC64_GOT_DTPREL16_HA:
551 case R_PPC64_TOC16_HA:678 case R_PPC64_TOC16_HA:
552 return {R_PPC64_ADDR16_HA, TocBiasedVal};679 return {R_PPC64_ADDR16_HA, tocBiasedVal};
553 case R_PPC64_GOT16_HI:680 case R_PPC64_GOT16_HI:
554 case R_PPC64_GOT_TLSGD16_HI:681 case R_PPC64_GOT_TLSGD16_HI:
555 case R_PPC64_GOT_TLSLD16_HI:682 case R_PPC64_GOT_TLSLD16_HI:
556 case R_PPC64_GOT_TPREL16_HI:683 case R_PPC64_GOT_TPREL16_HI:
557 case R_PPC64_GOT_DTPREL16_HI:684 case R_PPC64_GOT_DTPREL16_HI:
558 case R_PPC64_TOC16_HI:685 case R_PPC64_TOC16_HI:
559 return {R_PPC64_ADDR16_HI, TocBiasedVal};686 return {R_PPC64_ADDR16_HI, tocBiasedVal};
560 case R_PPC64_GOT16_LO:687 case R_PPC64_GOT16_LO:
561 case R_PPC64_GOT_TLSGD16_LO:688 case R_PPC64_GOT_TLSGD16_LO:
562 case R_PPC64_GOT_TLSLD16_LO:689 case R_PPC64_GOT_TLSLD16_LO:
563 case R_PPC64_TOC16_LO:690 case R_PPC64_TOC16_LO:
564 return {R_PPC64_ADDR16_LO, TocBiasedVal};691 return {R_PPC64_ADDR16_LO, tocBiasedVal};
565 case R_PPC64_GOT16_LO_DS:692 case R_PPC64_GOT16_LO_DS:
566 case R_PPC64_TOC16_LO_DS:693 case R_PPC64_TOC16_LO_DS:
567 case R_PPC64_GOT_TPREL16_LO_DS:694 case R_PPC64_GOT_TPREL16_LO_DS:
568 case R_PPC64_GOT_DTPREL16_LO_DS:695 case R_PPC64_GOT_DTPREL16_LO_DS:
569 return {R_PPC64_ADDR16_LO_DS, TocBiasedVal};696 return {R_PPC64_ADDR16_LO_DS, tocBiasedVal};
570697
571 // Dynamic Thread pointer biased relocation types.698 // Dynamic Thread pointer biased relocation types.
572 case R_PPC64_DTPREL16:699 case R_PPC64_DTPREL16:
573 return {R_PPC64_ADDR16, DTPBiasedVal};700 return {R_PPC64_ADDR16, dtpBiasedVal};
574 case R_PPC64_DTPREL16_DS:701 case R_PPC64_DTPREL16_DS:
575 return {R_PPC64_ADDR16_DS, DTPBiasedVal};702 return {R_PPC64_ADDR16_DS, dtpBiasedVal};
576 case R_PPC64_DTPREL16_HA:703 case R_PPC64_DTPREL16_HA:
577 return {R_PPC64_ADDR16_HA, DTPBiasedVal};704 return {R_PPC64_ADDR16_HA, dtpBiasedVal};
578 case R_PPC64_DTPREL16_HI:705 case R_PPC64_DTPREL16_HI:
579 return {R_PPC64_ADDR16_HI, DTPBiasedVal};706 return {R_PPC64_ADDR16_HI, dtpBiasedVal};
580 case R_PPC64_DTPREL16_HIGHER:707 case R_PPC64_DTPREL16_HIGHER:
581 return {R_PPC64_ADDR16_HIGHER, DTPBiasedVal};708 return {R_PPC64_ADDR16_HIGHER, dtpBiasedVal};
582 case R_PPC64_DTPREL16_HIGHERA:709 case R_PPC64_DTPREL16_HIGHERA:
583 return {R_PPC64_ADDR16_HIGHERA, DTPBiasedVal};710 return {R_PPC64_ADDR16_HIGHERA, dtpBiasedVal};
584 case R_PPC64_DTPREL16_HIGHEST:711 case R_PPC64_DTPREL16_HIGHEST:
585 return {R_PPC64_ADDR16_HIGHEST, DTPBiasedVal};712 return {R_PPC64_ADDR16_HIGHEST, dtpBiasedVal};
586 case R_PPC64_DTPREL16_HIGHESTA:713 case R_PPC64_DTPREL16_HIGHESTA:
587 return {R_PPC64_ADDR16_HIGHESTA, DTPBiasedVal};714 return {R_PPC64_ADDR16_HIGHESTA, dtpBiasedVal};
588 case R_PPC64_DTPREL16_LO:715 case R_PPC64_DTPREL16_LO:
589 return {R_PPC64_ADDR16_LO, DTPBiasedVal};716 return {R_PPC64_ADDR16_LO, dtpBiasedVal};
590 case R_PPC64_DTPREL16_LO_DS:717 case R_PPC64_DTPREL16_LO_DS:
591 return {R_PPC64_ADDR16_LO_DS, DTPBiasedVal};718 return {R_PPC64_ADDR16_LO_DS, dtpBiasedVal};
592 case R_PPC64_DTPREL64:719 case R_PPC64_DTPREL64:
593 return {R_PPC64_ADDR64, DTPBiasedVal};720 return {R_PPC64_ADDR64, dtpBiasedVal};
594721
595 default:722 default:
596 return {Type, Val};723 return {type, val};
597 }724 }
598}725}
599726
600static bool isTocOptType(RelType Type) {727static bool isTocOptType(RelType type) {
601 switch (Type) {728 switch (type) {
602 case R_PPC64_GOT16_HA:729 case R_PPC64_GOT16_HA:
603 case R_PPC64_GOT16_LO_DS:730 case R_PPC64_GOT16_LO_DS:
604 case R_PPC64_TOC16_HA:731 case R_PPC64_TOC16_HA:
...@@ -610,66 +737,69 @@ static bool isTocOptType(RelType Type) {...@@ -610,66 +737,69 @@ static bool isTocOptType(RelType Type) {
610 }737 }
611}738}
612739
613void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {740void PPC64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
614 // We need to save the original relocation type to use in diagnostics, and741 // 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 the742 // use the original type to determine if we should toc-optimize the
616 // instructions being relocated.743 // instructions being relocated.
617 RelType OriginalType = Type;744 RelType originalType = type;
618 bool ShouldTocOptimize = isTocOptType(Type);745 bool shouldTocOptimize = isTocOptType(type);
619 // For dynamic thread pointer relative, toc-relative, and got-indirect746 // For dynamic thread pointer relative, toc-relative, and got-indirect
620 // relocations, proceed in terms of the corresponding ADDR16 relocation type.747 // relocations, proceed in terms of the corresponding ADDR16 relocation type.
621 std::tie(Type, Val) = toAddr16Rel(Type, Val);748 std::tie(type, val) = toAddr16Rel(type, val);
622749
623 switch (Type) {750 switch (type) {
624 case R_PPC64_ADDR14: {751 case R_PPC64_ADDR14: {
625 checkAlignment(Loc, Val, 4, Type);752 checkAlignment(loc, val, 4, type);
626 // Preserve the AA/LK bits in the branch instruction753 // Preserve the AA/LK bits in the branch instruction
627 uint8_t AALK = Loc[3];754 uint8_t aalk = loc[3];
628 write16(Loc + 2, (AALK & 3) | (Val & 0xfffc));755 write16(loc + 2, (aalk & 3) | (val & 0xfffc));
629 break;756 break;
630 }757 }
631 case R_PPC64_ADDR16:758 case R_PPC64_ADDR16:
632 case R_PPC64_TPREL16:759 checkIntUInt(loc, val, 16, originalType);
633 checkInt(Loc, Val, 16, OriginalType);760 write16(loc, val);
634 write16(Loc, Val);761 break;
762 case R_PPC64_ADDR32:
763 checkIntUInt(loc, val, 32, originalType);
764 write32(loc, val);
635 break;765 break;
636 case R_PPC64_ADDR16_DS:766 case R_PPC64_ADDR16_DS:
637 case R_PPC64_TPREL16_DS: {767 case R_PPC64_TPREL16_DS: {
638 checkInt(Loc, Val, 16, OriginalType);768 checkInt(loc, val, 16, originalType);
639 // DQ-form instructions use bits 28-31 as part of the instruction encoding769 // DQ-form instructions use bits 28-31 as part of the instruction encoding
640 // DS-form instructions only use bits 30-31.770 // DS-form instructions only use bits 30-31.
641 uint16_t Mask = isDQFormInstruction(readInstrFromHalf16(Loc)) ? 0xF : 0x3;771 uint16_t mask = isDQFormInstruction(readFromHalf16(loc)) ? 0xf : 0x3;
642 checkAlignment(Loc, lo(Val), Mask + 1, OriginalType);772 checkAlignment(loc, lo(val), mask + 1, originalType);
643 write16(Loc, (read16(Loc) & Mask) | lo(Val));773 write16(loc, (read16(loc) & mask) | lo(val));
644 } break;774 } break;
645 case R_PPC64_ADDR16_HA:775 case R_PPC64_ADDR16_HA:
646 case R_PPC64_REL16_HA:776 case R_PPC64_REL16_HA:
647 case R_PPC64_TPREL16_HA:777 case R_PPC64_TPREL16_HA:
648 if (Config->TocOptimize && ShouldTocOptimize && ha(Val) == 0)778 if (config->tocOptimize && shouldTocOptimize && ha(val) == 0)
649 writeInstrFromHalf16(Loc, 0x60000000);779 writeFromHalf16(loc, 0x60000000);
650 else780 else
651 write16(Loc, ha(Val));781 write16(loc, ha(val));
652 break;782 break;
653 case R_PPC64_ADDR16_HI:783 case R_PPC64_ADDR16_HI:
654 case R_PPC64_REL16_HI:784 case R_PPC64_REL16_HI:
655 case R_PPC64_TPREL16_HI:785 case R_PPC64_TPREL16_HI:
656 write16(Loc, hi(Val));786 write16(loc, hi(val));
657 break;787 break;
658 case R_PPC64_ADDR16_HIGHER:788 case R_PPC64_ADDR16_HIGHER:
659 case R_PPC64_TPREL16_HIGHER:789 case R_PPC64_TPREL16_HIGHER:
660 write16(Loc, higher(Val));790 write16(loc, higher(val));
661 break;791 break;
662 case R_PPC64_ADDR16_HIGHERA:792 case R_PPC64_ADDR16_HIGHERA:
663 case R_PPC64_TPREL16_HIGHERA:793 case R_PPC64_TPREL16_HIGHERA:
664 write16(Loc, highera(Val));794 write16(loc, highera(val));
665 break;795 break;
666 case R_PPC64_ADDR16_HIGHEST:796 case R_PPC64_ADDR16_HIGHEST:
667 case R_PPC64_TPREL16_HIGHEST:797 case R_PPC64_TPREL16_HIGHEST:
668 write16(Loc, highest(Val));798 write16(loc, highest(val));
669 break;799 break;
670 case R_PPC64_ADDR16_HIGHESTA:800 case R_PPC64_ADDR16_HIGHESTA:
671 case R_PPC64_TPREL16_HIGHESTA:801 case R_PPC64_TPREL16_HIGHESTA:
672 write16(Loc, highesta(Val));802 write16(loc, highesta(val));
673 break;803 break;
674 case R_PPC64_ADDR16_LO:804 case R_PPC64_ADDR16_LO:
675 case R_PPC64_REL16_LO:805 case R_PPC64_REL16_LO:
...@@ -677,104 +807,119 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -677,104 +807,119 @@ void PPC64::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
677 // When the high-adjusted part of a toc relocation evalutes to 0, it is807 // 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 the808 // changed into a nop. The lo part then needs to be updated to use the
679 // toc-pointer register r2, as the base register.809 // toc-pointer register r2, as the base register.
680 if (Config->TocOptimize && ShouldTocOptimize && ha(Val) == 0) {810 if (config->tocOptimize && shouldTocOptimize && ha(val) == 0) {
681 uint32_t Instr = readInstrFromHalf16(Loc);811 uint32_t insn = readFromHalf16(loc);
682 if (isInstructionUpdateForm(Instr))812 if (isInstructionUpdateForm(insn))
683 error(getErrorLocation(Loc) +813 error(getErrorLocation(loc) +
684 "can't toc-optimize an update instruction: 0x" +814 "can't toc-optimize an update instruction: 0x" +
685 utohexstr(Instr));815 utohexstr(insn));
686 Instr = (Instr & 0xFFE00000) | 0x00020000;816 writeFromHalf16(loc, (insn & 0xffe00000) | 0x00020000 | lo(val));
687 writeInstrFromHalf16(Loc, Instr);817 } else {
818 write16(loc, lo(val));
688 }819 }
689 write16(Loc, lo(Val));
690 break;820 break;
691 case R_PPC64_ADDR16_LO_DS:821 case R_PPC64_ADDR16_LO_DS:
692 case R_PPC64_TPREL16_LO_DS: {822 case R_PPC64_TPREL16_LO_DS: {
693 // DQ-form instructions use bits 28-31 as part of the instruction encoding823 // DQ-form instructions use bits 28-31 as part of the instruction encoding
694 // DS-form instructions only use bits 30-31.824 // DS-form instructions only use bits 30-31.
695 uint32_t Inst = readInstrFromHalf16(Loc);825 uint32_t insn = readFromHalf16(loc);
696 uint16_t Mask = isDQFormInstruction(Inst) ? 0xF : 0x3;826 uint16_t mask = isDQFormInstruction(insn) ? 0xf : 0x3;
697 checkAlignment(Loc, lo(Val), Mask + 1, OriginalType);827 checkAlignment(loc, lo(val), mask + 1, originalType);
698 if (Config->TocOptimize && ShouldTocOptimize && ha(Val) == 0) {828 if (config->tocOptimize && shouldTocOptimize && ha(val) == 0) {
699 // When the high-adjusted part of a toc relocation evalutes to 0, it is829 // 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 toc830 // changed into a nop. The lo part then needs to be updated to use the toc
701 // pointer register r2, as the base register.831 // pointer register r2, as the base register.
702 if (isInstructionUpdateForm(Inst))832 if (isInstructionUpdateForm(insn))
703 error(getErrorLocation(Loc) +833 error(getErrorLocation(loc) +
704 "Can't toc-optimize an update instruction: 0x" +834 "Can't toc-optimize an update instruction: 0x" +
705 Twine::utohexstr(Inst));835 Twine::utohexstr(insn));
706 Inst = (Inst & 0xFFE0000F) | 0x00020000;836 insn &= 0xffe00000 | mask;
707 writeInstrFromHalf16(Loc, Inst);837 writeFromHalf16(loc, insn | 0x00020000 | lo(val));
838 } else {
839 write16(loc, (read16(loc) & mask) | lo(val));
708 }840 }
709 write16(Loc, (read16(Loc) & Mask) | lo(Val));
710 } break;841 } break;
711 case R_PPC64_ADDR32:842 case R_PPC64_TPREL16:
843 checkInt(loc, val, 16, originalType);
844 write16(loc, val);
845 break;
712 case R_PPC64_REL32:846 case R_PPC64_REL32:
713 checkInt(Loc, Val, 32, Type);847 checkInt(loc, val, 32, type);
714 write32(Loc, Val);848 write32(loc, val);
715 break;849 break;
716 case R_PPC64_ADDR64:850 case R_PPC64_ADDR64:
717 case R_PPC64_REL64:851 case R_PPC64_REL64:
718 case R_PPC64_TOC:852 case R_PPC64_TOC:
719 write64(Loc, Val);853 write64(loc, val);
720 break;854 break;
721 case R_PPC64_REL14: {855 case R_PPC64_REL14: {
722 uint32_t Mask = 0x0000FFFC;856 uint32_t mask = 0x0000FFFC;
723 checkInt(Loc, Val, 16, Type);857 checkInt(loc, val, 16, type);
724 checkAlignment(Loc, Val, 4, Type);858 checkAlignment(loc, val, 4, type);
725 write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));859 write32(loc, (read32(loc) & ~mask) | (val & mask));
726 break;860 break;
727 }861 }
728 case R_PPC64_REL24: {862 case R_PPC64_REL24: {
729 uint32_t Mask = 0x03FFFFFC;863 uint32_t mask = 0x03FFFFFC;
730 checkInt(Loc, Val, 26, Type);864 checkInt(loc, val, 26, type);
731 checkAlignment(Loc, Val, 4, Type);865 checkAlignment(loc, val, 4, type);
732 write32(Loc, (read32(Loc) & ~Mask) | (Val & Mask));866 write32(loc, (read32(loc) & ~mask) | (val & mask));
733 break;867 break;
734 }868 }
735 case R_PPC64_DTPREL64:869 case R_PPC64_DTPREL64:
736 write64(Loc, Val - DynamicThreadPointerOffset);870 write64(loc, val - dynamicThreadPointerOffset);
737 break;871 break;
738 default:872 default:
739 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));873 error(getErrorLocation(loc) + "unrecognized relocation " + toString(type));
740 }874 }
741}875}
742876
743bool PPC64::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,877bool PPC64::needsThunk(RelExpr expr, RelType type, const InputFile *file,
744 uint64_t BranchAddr, const Symbol &S) const {878 uint64_t branchAddr, const Symbol &s) const {
745 if (Type != R_PPC64_REL14 && Type != R_PPC64_REL24)879 if (type != R_PPC64_REL14 && type != R_PPC64_REL24)
746 return false;880 return false;
747881
748 // If a function is in the Plt it needs to be called with a call-stub.882 // If a function is in the Plt it needs to be called with a call-stub.
749 if (S.isInPlt())883 if (s.isInPlt())
750 return true;884 return true;
751885
752 // If a symbol is a weak undefined and we are compiling an executable886 // 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.887 // it doesn't need a range-extending thunk since it can't be called.
754 if (S.isUndefWeak() && !Config->Shared)888 if (s.isUndefWeak() && !config->shared)
755 return false;889 return false;
756890
757 // If the offset exceeds the range of the branch type then it will need891 // If the offset exceeds the range of the branch type then it will need
758 // a range-extending thunk.892 // a range-extending thunk.
759 return !inBranchRange(Type, BranchAddr, S.getVA());893 // See the comment in getRelocTargetVA() about R_PPC64_CALL.
894 return !inBranchRange(type, branchAddr,
895 s.getVA() +
896 getPPC64GlobalEntryToLocalEntryOffset(s.stOther));
760}897}
761898
762bool PPC64::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const {899uint32_t PPC64::getThunkSectionSpacing() const {
763 int64_t Offset = Dst - Src;900 // See comment in Arch/ARM.cpp for a more detailed explanation of
764 if (Type == R_PPC64_REL14)901 // getThunkSectionSpacing(). For PPC64 we pick the constant here based on
765 return isInt<16>(Offset);902 // R_PPC64_REL24, which is used by unconditional branch instructions.
766 if (Type == R_PPC64_REL24)903 // 0x2000000 = (1 << 24-1) * 4
767 return isInt<26>(Offset);904 return 0x2000000;
905}
906
907bool PPC64::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
908 int64_t offset = dst - src;
909 if (type == R_PPC64_REL14)
910 return isInt<16>(offset);
911 if (type == R_PPC64_REL24)
912 return isInt<26>(offset);
768 llvm_unreachable("unsupported relocation type used in branch");913 llvm_unreachable("unsupported relocation type used in branch");
769}914}
770915
771RelExpr PPC64::adjustRelaxExpr(RelType Type, const uint8_t *Data,916RelExpr PPC64::adjustRelaxExpr(RelType type, const uint8_t *data,
772 RelExpr Expr) const {917 RelExpr expr) const {
773 if (Expr == R_RELAX_TLS_GD_TO_IE)918 if (expr == R_RELAX_TLS_GD_TO_IE)
774 return R_RELAX_TLS_GD_TO_IE_GOT_OFF;919 return R_RELAX_TLS_GD_TO_IE_GOT_OFF;
775 if (Expr == R_RELAX_TLS_LD_TO_LE)920 if (expr == R_RELAX_TLS_LD_TO_LE)
776 return R_RELAX_TLS_LD_TO_LE_ABS;921 return R_RELAX_TLS_LD_TO_LE_ABS;
777 return Expr;922 return expr;
778}923}
779924
780// Reference: 3.7.4.1 of the 64-bit ELF V2 abi supplement.925// Reference: 3.7.4.1 of the 64-bit ELF V2 abi supplement.
...@@ -794,24 +939,25 @@ RelExpr PPC64::adjustRelaxExpr(RelType Type, const uint8_t *Data,...@@ -794,24 +939,25 @@ RelExpr PPC64::adjustRelaxExpr(RelType Type, const uint8_t *Data,
794// thread pointer.939// thread pointer.
795// Since the nop must directly follow the call, the R_PPC64_TLSGD relocation is940// Since the nop must directly follow the call, the R_PPC64_TLSGD relocation is
796// used as the relaxation hint for both steps 2 and 3.941// used as the relaxation hint for both steps 2 and 3.
797void PPC64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {942void PPC64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
798 switch (Type) {943 switch (type) {
799 case R_PPC64_GOT_TLSGD16_HA:944 case R_PPC64_GOT_TLSGD16_HA:
800 // This is relaxed from addis rT, r2, sym@got@tlsgd@ha to945 // This is relaxed from addis rT, r2, sym@got@tlsgd@ha to
801 // addis rT, r2, sym@got@tprel@ha.946 // addis rT, r2, sym@got@tprel@ha.
802 relocateOne(Loc, R_PPC64_GOT_TPREL16_HA, Val);947 relocateOne(loc, R_PPC64_GOT_TPREL16_HA, val);
803 return;948 return;
949 case R_PPC64_GOT_TLSGD16:
804 case R_PPC64_GOT_TLSGD16_LO: {950 case R_PPC64_GOT_TLSGD16_LO: {
805 // Relax from addi r3, rA, sym@got@tlsgd@l to951 // Relax from addi r3, rA, sym@got@tlsgd@l to
806 // ld r3, sym@got@tprel@l(rA)952 // ld r3, sym@got@tprel@l(rA)
807 uint32_t InputRegister = (readInstrFromHalf16(Loc) & (0x1f << 16));953 uint32_t ra = (readFromHalf16(loc) & (0x1f << 16));
808 writeInstrFromHalf16(Loc, 0xE8600000 | InputRegister);954 writeFromHalf16(loc, 0xe8600000 | ra);
809 relocateOne(Loc, R_PPC64_GOT_TPREL16_LO_DS, Val);955 relocateOne(loc, R_PPC64_GOT_TPREL16_LO_DS, val);
810 return;956 return;
811 }957 }
812 case R_PPC64_TLSGD:958 case R_PPC64_TLSGD:
813 write32(Loc, 0x60000000); // bl __tls_get_addr(sym@tlsgd) --> nop959 write32(loc, 0x60000000); // bl __tls_get_addr(sym@tlsgd) --> nop
814 write32(Loc + 4, 0x7c636A14); // nop --> add r3, r3, r13960 write32(loc + 4, 0x7c636A14); // nop --> add r3, r3, r13
815 return;961 return;
816 default:962 default:
817 llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");963 llvm_unreachable("unsupported relocation for TLS GD to IE relaxation");
...@@ -846,86 +992,86 @@ void PPC64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -846,86 +992,86 @@ void PPC64::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {
846// pair by split-stack-size-adjust.992// pair by split-stack-size-adjust.
847// addis r12, r1, ha(-stack-frame size - split-stack-adjust-size)993// addis r12, r1, ha(-stack-frame size - split-stack-adjust-size)
848// addi r12, r12, l(-stack-frame size - split-stack-adjust-size)994// addi r12, r12, l(-stack-frame size - split-stack-adjust-size)
849bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End,995bool PPC64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
850 uint8_t StOther) const {996 uint8_t stOther) const {
851 // If the caller has a global entry point adjust the buffer past it. The start997 // 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.998 // of the split-stack prologue will be at the local entry point.
853 Loc += getPPC64GlobalEntryToLocalEntryOffset(StOther);999 loc += getPPC64GlobalEntryToLocalEntryOffset(stOther);
8541000
855 // At the very least we expect to see a load of some split-stack data from the1001 // 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 this1002 // tcb, and 2 instructions that calculate the ending stack address this
857 // function will require. If there is not enough room for at least 31003 // function will require. If there is not enough room for at least 3
858 // instructions it can't be a split-stack prologue.1004 // instructions it can't be a split-stack prologue.
859 if (Loc + 12 >= End)1005 if (loc + 12 >= end)
860 return false;1006 return false;
8611007
862 // First instruction must be `ld r0, -0x7000-64(r13)`1008 // First instruction must be `ld r0, -0x7000-64(r13)`
863 if (read32(Loc) != 0xe80d8fc0)1009 if (read32(loc) != 0xe80d8fc0)
864 return false;1010 return false;
8651011
866 int16_t HiImm = 0;1012 int16_t hiImm = 0;
867 int16_t LoImm = 0;1013 int16_t loImm = 0;
868 // First instruction can be either an addis if the frame size is larger then1014 // 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.1015 // 32K, or an addi if the size is less then 32K.
870 int32_t FirstInstr = read32(Loc + 4);1016 int32_t firstInstr = read32(loc + 4);
871 if (getPrimaryOpCode(FirstInstr) == 15) {1017 if (getPrimaryOpCode(firstInstr) == 15) {
872 HiImm = FirstInstr & 0xFFFF;1018 hiImm = firstInstr & 0xFFFF;
873 } else if (getPrimaryOpCode(FirstInstr) == 14) {1019 } else if (getPrimaryOpCode(firstInstr) == 14) {
874 LoImm = FirstInstr & 0xFFFF;1020 loImm = firstInstr & 0xFFFF;
875 } else {1021 } else {
876 return false;1022 return false;
877 }1023 }
8781024
879 // Second instruction is either an addi or a nop. If the first instruction was1025 // 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.1026 // an addi then LoImm is set and the second instruction must be a nop.
881 uint32_t SecondInstr = read32(Loc + 8);1027 uint32_t secondInstr = read32(loc + 8);
882 if (!LoImm && getPrimaryOpCode(SecondInstr) == 14) {1028 if (!loImm && getPrimaryOpCode(secondInstr) == 14) {
883 LoImm = SecondInstr & 0xFFFF;1029 loImm = secondInstr & 0xFFFF;
884 } else if (SecondInstr != 0x60000000) {1030 } else if (secondInstr != 0x60000000) {
885 return false;1031 return false;
886 }1032 }
8871033
888 // The register operands of the first instruction should be the stack-pointer1034 // 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 second1035 // (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.1036 // instruction is not a nop, then it should use r12 as both input and output.
891 auto CheckRegOperands = [](uint32_t Instr, uint8_t ExpectedRT,1037 auto checkRegOperands = [](uint32_t instr, uint8_t expectedRT,
892 uint8_t ExpectedRA) {1038 uint8_t expectedRA) {
893 return ((Instr & 0x3E00000) >> 21 == ExpectedRT) &&1039 return ((instr & 0x3E00000) >> 21 == expectedRT) &&
894 ((Instr & 0x1F0000) >> 16 == ExpectedRA);1040 ((instr & 0x1F0000) >> 16 == expectedRA);
895 };1041 };
896 if (!CheckRegOperands(FirstInstr, 12, 1))1042 if (!checkRegOperands(firstInstr, 12, 1))
897 return false;1043 return false;
898 if (SecondInstr != 0x60000000 && !CheckRegOperands(SecondInstr, 12, 12))1044 if (secondInstr != 0x60000000 && !checkRegOperands(secondInstr, 12, 12))
899 return false;1045 return false;
9001046
901 int32_t StackFrameSize = (HiImm * 65536) + LoImm;1047 int32_t stackFrameSize = (hiImm * 65536) + loImm;
902 // Check that the adjusted size doesn't overflow what we can represent with 21048 // Check that the adjusted size doesn't overflow what we can represent with 2
903 // instructions.1049 // instructions.
904 if (StackFrameSize < Config->SplitStackAdjustSize + INT32_MIN) {1050 if (stackFrameSize < config->splitStackAdjustSize + INT32_MIN) {
905 error(getErrorLocation(Loc) + "split-stack prologue adjustment overflows");1051 error(getErrorLocation(loc) + "split-stack prologue adjustment overflows");
906 return false;1052 return false;
907 }1053 }
9081054
909 int32_t AdjustedStackFrameSize =1055 int32_t adjustedStackFrameSize =
910 StackFrameSize - Config->SplitStackAdjustSize;1056 stackFrameSize - config->splitStackAdjustSize;
9111057
912 LoImm = AdjustedStackFrameSize & 0xFFFF;1058 loImm = adjustedStackFrameSize & 0xFFFF;
913 HiImm = (AdjustedStackFrameSize + 0x8000) >> 16;1059 hiImm = (adjustedStackFrameSize + 0x8000) >> 16;
914 if (HiImm) {1060 if (hiImm) {
915 write32(Loc + 4, 0x3D810000 | (uint16_t)HiImm);1061 write32(loc + 4, 0x3D810000 | (uint16_t)hiImm);
916 // If the low immediate is zero the second instruction will be a nop.1062 // If the low immediate is zero the second instruction will be a nop.
917 SecondInstr = LoImm ? 0x398C0000 | (uint16_t)LoImm : 0x60000000;1063 secondInstr = loImm ? 0x398C0000 | (uint16_t)loImm : 0x60000000;
918 write32(Loc + 8, SecondInstr);1064 write32(loc + 8, secondInstr);
919 } else {1065 } else {
920 // addi r12, r1, imm1066 // addi r12, r1, imm
921 write32(Loc + 4, (0x39810000) | (uint16_t)LoImm);1067 write32(loc + 4, (0x39810000) | (uint16_t)loImm);
922 write32(Loc + 8, 0x60000000);1068 write32(loc + 8, 0x60000000);
923 }1069 }
9241070
925 return true;1071 return true;
926}1072}
9271073
928TargetInfo *elf::getPPC64TargetInfo() {1074TargetInfo *elf::getPPC64TargetInfo() {
929 static PPC64 Target;1075 static PPC64 target;
930 return &Target;1076 return &target;
931}1077}
deps/lld/ELF/Arch/RISCV.cpp+282-119
...@@ -1,13 +1,13 @@...@@ -1,13 +1,13 @@
1//===- RISCV.cpp ----------------------------------------------------------===//1//===- RISCV.cpp ----------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
10#include "InputFiles.h"9#include "InputFiles.h"
10#include "SyntheticSections.h"
11#include "Target.h"11#include "Target.h"
1212
13using namespace llvm;13using namespace llvm;
...@@ -23,59 +23,207 @@ class RISCV final : public TargetInfo {...@@ -23,59 +23,207 @@ class RISCV final : public TargetInfo {
23public:23public:
24 RISCV();24 RISCV();
25 uint32_t calcEFlags() const override;25 uint32_t calcEFlags() const override;
26 RelExpr getRelExpr(RelType Type, const Symbol &S,26 void writeGotHeader(uint8_t *buf) const override;
27 const uint8_t *Loc) const override;27 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
28 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;28 void writePltHeader(uint8_t *buf) const override;
29 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
30 int32_t index, unsigned relOff) const override;
31 RelType getDynRel(RelType type) const override;
32 RelExpr getRelExpr(RelType type, const Symbol &s,
33 const uint8_t *loc) const override;
34 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
29};35};
3036
31} // end anonymous namespace37} // end anonymous namespace
3238
33RISCV::RISCV() { NoneRel = R_RISCV_NONE; }39const uint64_t dtpOffset = 0x800;
40
41enum Op {
42 ADDI = 0x13,
43 AUIPC = 0x17,
44 JALR = 0x67,
45 LD = 0x3003,
46 LW = 0x2003,
47 SRLI = 0x5013,
48 SUB = 0x40000033,
49};
50
51enum Reg {
52 X_RA = 1,
53 X_T0 = 5,
54 X_T1 = 6,
55 X_T2 = 7,
56 X_T3 = 28,
57};
58
59static uint32_t hi20(uint32_t val) { return (val + 0x800) >> 12; }
60static uint32_t lo12(uint32_t val) { return val & 4095; }
61
62static uint32_t itype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t imm) {
63 return op | (rd << 7) | (rs1 << 15) | (imm << 20);
64}
65static uint32_t rtype(uint32_t op, uint32_t rd, uint32_t rs1, uint32_t rs2) {
66 return op | (rd << 7) | (rs1 << 15) | (rs2 << 20);
67}
68static uint32_t utype(uint32_t op, uint32_t rd, uint32_t imm) {
69 return op | (rd << 7) | (imm << 12);
70}
71
72RISCV::RISCV() {
73 copyRel = R_RISCV_COPY;
74 noneRel = R_RISCV_NONE;
75 pltRel = R_RISCV_JUMP_SLOT;
76 relativeRel = R_RISCV_RELATIVE;
77 if (config->is64) {
78 symbolicRel = R_RISCV_64;
79 tlsModuleIndexRel = R_RISCV_TLS_DTPMOD64;
80 tlsOffsetRel = R_RISCV_TLS_DTPREL64;
81 tlsGotRel = R_RISCV_TLS_TPREL64;
82 } else {
83 symbolicRel = R_RISCV_32;
84 tlsModuleIndexRel = R_RISCV_TLS_DTPMOD32;
85 tlsOffsetRel = R_RISCV_TLS_DTPREL32;
86 tlsGotRel = R_RISCV_TLS_TPREL32;
87 }
88 gotRel = symbolicRel;
89
90 // .got[0] = _DYNAMIC
91 gotBaseSymInGotPlt = false;
92 gotHeaderEntriesNum = 1;
93
94 // .got.plt[0] = _dl_runtime_resolve, .got.plt[1] = link_map
95 gotPltHeaderEntriesNum = 2;
3496
35static uint32_t getEFlags(InputFile *F) {97 pltEntrySize = 16;
36 if (Config->Is64)98 pltHeaderSize = 32;
37 return cast<ObjFile<ELF64LE>>(F)->getObj().getHeader()->e_flags;99}
38 return cast<ObjFile<ELF32LE>>(F)->getObj().getHeader()->e_flags;100
101static uint32_t getEFlags(InputFile *f) {
102 if (config->is64)
103 return cast<ObjFile<ELF64LE>>(f)->getObj().getHeader()->e_flags;
104 return cast<ObjFile<ELF32LE>>(f)->getObj().getHeader()->e_flags;
39}105}
40106
41uint32_t RISCV::calcEFlags() const {107uint32_t RISCV::calcEFlags() const {
42 assert(!ObjectFiles.empty());108 assert(!objectFiles.empty());
43109
44 uint32_t Target = getEFlags(ObjectFiles.front());110 uint32_t target = getEFlags(objectFiles.front());
45111
46 for (InputFile *F : ObjectFiles) {112 for (InputFile *f : objectFiles) {
47 uint32_t EFlags = getEFlags(F);113 uint32_t eflags = getEFlags(f);
48 if (EFlags & EF_RISCV_RVC)114 if (eflags & EF_RISCV_RVC)
49 Target |= EF_RISCV_RVC;115 target |= EF_RISCV_RVC;
50116
51 if ((EFlags & EF_RISCV_FLOAT_ABI) != (Target & EF_RISCV_FLOAT_ABI))117 if ((eflags & EF_RISCV_FLOAT_ABI) != (target & EF_RISCV_FLOAT_ABI))
52 error(toString(F) +118 error(toString(f) +
53 ": cannot link object files with different floating-point ABI");119 ": cannot link object files with different floating-point ABI");
54120
55 if ((EFlags & EF_RISCV_RVE) != (Target & EF_RISCV_RVE))121 if ((eflags & EF_RISCV_RVE) != (target & EF_RISCV_RVE))
56 error(toString(F) +122 error(toString(f) +
57 ": cannot link object files with different EF_RISCV_RVE");123 ": cannot link object files with different EF_RISCV_RVE");
58 }124 }
59125
60 return Target;126 return target;
127}
128
129void RISCV::writeGotHeader(uint8_t *buf) const {
130 if (config->is64)
131 write64le(buf, mainPart->dynamic->getVA());
132 else
133 write32le(buf, mainPart->dynamic->getVA());
134}
135
136void RISCV::writeGotPlt(uint8_t *buf, const Symbol &s) const {
137 if (config->is64)
138 write64le(buf, in.plt->getVA());
139 else
140 write32le(buf, in.plt->getVA());
141}
142
143void RISCV::writePltHeader(uint8_t *buf) const {
144 // 1: auipc t2, %pcrel_hi(.got.plt)
145 // sub t1, t1, t3
146 // l[wd] t3, %pcrel_lo(1b)(t2); t3 = _dl_runtime_resolve
147 // addi t1, t1, -pltHeaderSize-12; t1 = &.plt[i] - &.plt[0]
148 // addi t0, t2, %pcrel_lo(1b)
149 // srli t1, t1, (rv64?1:2); t1 = &.got.plt[i] - &.got.plt[0]
150 // l[wd] t0, Wordsize(t0); t0 = link_map
151 // jr t3
152 uint32_t offset = in.gotPlt->getVA() - in.plt->getVA();
153 uint32_t load = config->is64 ? LD : LW;
154 write32le(buf + 0, utype(AUIPC, X_T2, hi20(offset)));
155 write32le(buf + 4, rtype(SUB, X_T1, X_T1, X_T3));
156 write32le(buf + 8, itype(load, X_T3, X_T2, lo12(offset)));
157 write32le(buf + 12, itype(ADDI, X_T1, X_T1, -target->pltHeaderSize - 12));
158 write32le(buf + 16, itype(ADDI, X_T0, X_T2, lo12(offset)));
159 write32le(buf + 20, itype(SRLI, X_T1, X_T1, config->is64 ? 1 : 2));
160 write32le(buf + 24, itype(load, X_T0, X_T0, config->wordsize));
161 write32le(buf + 28, itype(JALR, 0, X_T3, 0));
61}162}
62163
63RelExpr RISCV::getRelExpr(const RelType Type, const Symbol &S,164void RISCV::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
64 const uint8_t *Loc) const {165 uint64_t pltEntryAddr, int32_t index,
65 switch (Type) {166 unsigned relOff) const {
167 // 1: auipc t3, %pcrel_hi(f@.got.plt)
168 // l[wd] t3, %pcrel_lo(1b)(t3)
169 // jalr t1, t3
170 // nop
171 uint32_t offset = gotPltEntryAddr - pltEntryAddr;
172 write32le(buf + 0, utype(AUIPC, X_T3, hi20(offset)));
173 write32le(buf + 4, itype(config->is64 ? LD : LW, X_T3, X_T3, lo12(offset)));
174 write32le(buf + 8, itype(JALR, X_T1, X_T3, 0));
175 write32le(buf + 12, itype(ADDI, 0, 0, 0));
176}
177
178RelType RISCV::getDynRel(RelType type) const {
179 return type == target->symbolicRel ? type
180 : static_cast<RelType>(R_RISCV_NONE);
181}
182
183RelExpr RISCV::getRelExpr(const RelType type, const Symbol &s,
184 const uint8_t *loc) const {
185 switch (type) {
186 case R_RISCV_ADD8:
187 case R_RISCV_ADD16:
188 case R_RISCV_ADD32:
189 case R_RISCV_ADD64:
190 case R_RISCV_SET6:
191 case R_RISCV_SET8:
192 case R_RISCV_SET16:
193 case R_RISCV_SET32:
194 case R_RISCV_SUB6:
195 case R_RISCV_SUB8:
196 case R_RISCV_SUB16:
197 case R_RISCV_SUB32:
198 case R_RISCV_SUB64:
199 return R_RISCV_ADD;
66 case R_RISCV_JAL:200 case R_RISCV_JAL:
67 case R_RISCV_BRANCH:201 case R_RISCV_BRANCH:
68 case R_RISCV_CALL:
69 case R_RISCV_PCREL_HI20:202 case R_RISCV_PCREL_HI20:
70 case R_RISCV_RVC_BRANCH:203 case R_RISCV_RVC_BRANCH:
71 case R_RISCV_RVC_JUMP:204 case R_RISCV_RVC_JUMP:
72 case R_RISCV_32_PCREL:205 case R_RISCV_32_PCREL:
73 return R_PC;206 return R_PC;
207 case R_RISCV_CALL:
208 case R_RISCV_CALL_PLT:
209 return R_PLT_PC;
210 case R_RISCV_GOT_HI20:
211 return R_GOT_PC;
74 case R_RISCV_PCREL_LO12_I:212 case R_RISCV_PCREL_LO12_I:
75 case R_RISCV_PCREL_LO12_S:213 case R_RISCV_PCREL_LO12_S:
76 return R_RISCV_PC_INDIRECT;214 return R_RISCV_PC_INDIRECT;
215 case R_RISCV_TLS_GD_HI20:
216 return R_TLSGD_PC;
217 case R_RISCV_TLS_GOT_HI20:
218 config->hasStaticTlsModel = true;
219 return R_GOT_PC;
220 case R_RISCV_TPREL_HI20:
221 case R_RISCV_TPREL_LO12_I:
222 case R_RISCV_TPREL_LO12_S:
223 return R_TLS;
77 case R_RISCV_RELAX:224 case R_RISCV_RELAX:
78 case R_RISCV_ALIGN:225 case R_RISCV_ALIGN:
226 case R_RISCV_TPREL_ADD:
79 return R_HINT;227 return R_HINT;
80 default:228 default:
81 return R_ABS;229 return R_ABS;
...@@ -83,175 +231,190 @@ RelExpr RISCV::getRelExpr(const RelType Type, const Symbol &S,...@@ -83,175 +231,190 @@ RelExpr RISCV::getRelExpr(const RelType Type, const Symbol &S,
83}231}
84232
85// Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63.233// Extract bits V[Begin:End], where range is inclusive, and Begin must be < 63.
86static uint32_t extractBits(uint64_t V, uint32_t Begin, uint32_t End) {234static uint32_t extractBits(uint64_t v, uint32_t begin, uint32_t end) {
87 return (V & ((1ULL << (Begin + 1)) - 1)) >> End;235 return (v & ((1ULL << (begin + 1)) - 1)) >> end;
88}236}
89237
90void RISCV::relocateOne(uint8_t *Loc, const RelType Type,238void RISCV::relocateOne(uint8_t *loc, const RelType type,
91 const uint64_t Val) const {239 const uint64_t val) const {
92 switch (Type) {240 const unsigned bits = config->wordsize * 8;
241
242 switch (type) {
93 case R_RISCV_32:243 case R_RISCV_32:
94 write32le(Loc, Val);244 write32le(loc, val);
95 return;245 return;
96 case R_RISCV_64:246 case R_RISCV_64:
97 write64le(Loc, Val);247 write64le(loc, val);
98 return;248 return;
99249
100 case R_RISCV_RVC_BRANCH: {250 case R_RISCV_RVC_BRANCH: {
101 checkInt(Loc, static_cast<int64_t>(Val) >> 1, 8, Type);251 checkInt(loc, static_cast<int64_t>(val) >> 1, 8, type);
102 checkAlignment(Loc, Val, 2, Type);252 checkAlignment(loc, val, 2, type);
103 uint16_t Insn = read16le(Loc) & 0xE383;253 uint16_t insn = read16le(loc) & 0xE383;
104 uint16_t Imm8 = extractBits(Val, 8, 8) << 12;254 uint16_t imm8 = extractBits(val, 8, 8) << 12;
105 uint16_t Imm4_3 = extractBits(Val, 4, 3) << 10;255 uint16_t imm4_3 = extractBits(val, 4, 3) << 10;
106 uint16_t Imm7_6 = extractBits(Val, 7, 6) << 5;256 uint16_t imm7_6 = extractBits(val, 7, 6) << 5;
107 uint16_t Imm2_1 = extractBits(Val, 2, 1) << 3;257 uint16_t imm2_1 = extractBits(val, 2, 1) << 3;
108 uint16_t Imm5 = extractBits(Val, 5, 5) << 2;258 uint16_t imm5 = extractBits(val, 5, 5) << 2;
109 Insn |= Imm8 | Imm4_3 | Imm7_6 | Imm2_1 | Imm5;259 insn |= imm8 | imm4_3 | imm7_6 | imm2_1 | imm5;
110260
111 write16le(Loc, Insn);261 write16le(loc, insn);
112 return;262 return;
113 }263 }
114264
115 case R_RISCV_RVC_JUMP: {265 case R_RISCV_RVC_JUMP: {
116 checkInt(Loc, static_cast<int64_t>(Val) >> 1, 11, Type);266 checkInt(loc, static_cast<int64_t>(val) >> 1, 11, type);
117 checkAlignment(Loc, Val, 2, Type);267 checkAlignment(loc, val, 2, type);
118 uint16_t Insn = read16le(Loc) & 0xE003;268 uint16_t insn = read16le(loc) & 0xE003;
119 uint16_t Imm11 = extractBits(Val, 11, 11) << 12;269 uint16_t imm11 = extractBits(val, 11, 11) << 12;
120 uint16_t Imm4 = extractBits(Val, 4, 4) << 11;270 uint16_t imm4 = extractBits(val, 4, 4) << 11;
121 uint16_t Imm9_8 = extractBits(Val, 9, 8) << 9;271 uint16_t imm9_8 = extractBits(val, 9, 8) << 9;
122 uint16_t Imm10 = extractBits(Val, 10, 10) << 8;272 uint16_t imm10 = extractBits(val, 10, 10) << 8;
123 uint16_t Imm6 = extractBits(Val, 6, 6) << 7;273 uint16_t imm6 = extractBits(val, 6, 6) << 7;
124 uint16_t Imm7 = extractBits(Val, 7, 7) << 6;274 uint16_t imm7 = extractBits(val, 7, 7) << 6;
125 uint16_t Imm3_1 = extractBits(Val, 3, 1) << 3;275 uint16_t imm3_1 = extractBits(val, 3, 1) << 3;
126 uint16_t Imm5 = extractBits(Val, 5, 5) << 2;276 uint16_t imm5 = extractBits(val, 5, 5) << 2;
127 Insn |= Imm11 | Imm4 | Imm9_8 | Imm10 | Imm6 | Imm7 | Imm3_1 | Imm5;277 insn |= imm11 | imm4 | imm9_8 | imm10 | imm6 | imm7 | imm3_1 | imm5;
128278
129 write16le(Loc, Insn);279 write16le(loc, insn);
130 return;280 return;
131 }281 }
132282
133 case R_RISCV_RVC_LUI: {283 case R_RISCV_RVC_LUI: {
134 int32_t Imm = ((Val + 0x800) >> 12);284 int64_t imm = SignExtend64(val + 0x800, bits) >> 12;
135 checkUInt(Loc, Imm, 6, Type);285 checkInt(loc, imm, 6, type);
136 if (Imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0`286 if (imm == 0) { // `c.lui rd, 0` is illegal, convert to `c.li rd, 0`
137 write16le(Loc, (read16le(Loc) & 0x0F83) | 0x4000);287 write16le(loc, (read16le(loc) & 0x0F83) | 0x4000);
138 } else {288 } else {
139 uint16_t Imm17 = extractBits(Val + 0x800, 17, 17) << 12;289 uint16_t imm17 = extractBits(val + 0x800, 17, 17) << 12;
140 uint16_t Imm16_12 = extractBits(Val + 0x800, 16, 12) << 2;290 uint16_t imm16_12 = extractBits(val + 0x800, 16, 12) << 2;
141 write16le(Loc, (read16le(Loc) & 0xEF83) | Imm17 | Imm16_12);291 write16le(loc, (read16le(loc) & 0xEF83) | imm17 | imm16_12);
142 }292 }
143 return;293 return;
144 }294 }
145295
146 case R_RISCV_JAL: {296 case R_RISCV_JAL: {
147 checkInt(Loc, static_cast<int64_t>(Val) >> 1, 20, Type);297 checkInt(loc, static_cast<int64_t>(val) >> 1, 20, type);
148 checkAlignment(Loc, Val, 2, Type);298 checkAlignment(loc, val, 2, type);
149299
150 uint32_t Insn = read32le(Loc) & 0xFFF;300 uint32_t insn = read32le(loc) & 0xFFF;
151 uint32_t Imm20 = extractBits(Val, 20, 20) << 31;301 uint32_t imm20 = extractBits(val, 20, 20) << 31;
152 uint32_t Imm10_1 = extractBits(Val, 10, 1) << 21;302 uint32_t imm10_1 = extractBits(val, 10, 1) << 21;
153 uint32_t Imm11 = extractBits(Val, 11, 11) << 20;303 uint32_t imm11 = extractBits(val, 11, 11) << 20;
154 uint32_t Imm19_12 = extractBits(Val, 19, 12) << 12;304 uint32_t imm19_12 = extractBits(val, 19, 12) << 12;
155 Insn |= Imm20 | Imm10_1 | Imm11 | Imm19_12;305 insn |= imm20 | imm10_1 | imm11 | imm19_12;
156306
157 write32le(Loc, Insn);307 write32le(loc, insn);
158 return;308 return;
159 }309 }
160310
161 case R_RISCV_BRANCH: {311 case R_RISCV_BRANCH: {
162 checkInt(Loc, static_cast<int64_t>(Val) >> 1, 12, Type);312 checkInt(loc, static_cast<int64_t>(val) >> 1, 12, type);
163 checkAlignment(Loc, Val, 2, Type);313 checkAlignment(loc, val, 2, type);
164314
165 uint32_t Insn = read32le(Loc) & 0x1FFF07F;315 uint32_t insn = read32le(loc) & 0x1FFF07F;
166 uint32_t Imm12 = extractBits(Val, 12, 12) << 31;316 uint32_t imm12 = extractBits(val, 12, 12) << 31;
167 uint32_t Imm10_5 = extractBits(Val, 10, 5) << 25;317 uint32_t imm10_5 = extractBits(val, 10, 5) << 25;
168 uint32_t Imm4_1 = extractBits(Val, 4, 1) << 8;318 uint32_t imm4_1 = extractBits(val, 4, 1) << 8;
169 uint32_t Imm11 = extractBits(Val, 11, 11) << 7;319 uint32_t imm11 = extractBits(val, 11, 11) << 7;
170 Insn |= Imm12 | Imm10_5 | Imm4_1 | Imm11;320 insn |= imm12 | imm10_5 | imm4_1 | imm11;
171321
172 write32le(Loc, Insn);322 write32le(loc, insn);
173 return;323 return;
174 }324 }
175325
176 // auipc + jalr pair326 // auipc + jalr pair
177 case R_RISCV_CALL: {327 case R_RISCV_CALL:
178 checkInt(Loc, Val, 32, Type);328 case R_RISCV_CALL_PLT: {
179 if (isInt<32>(Val)) {329 int64_t hi = SignExtend64(val + 0x800, bits) >> 12;
180 relocateOne(Loc, R_RISCV_PCREL_HI20, Val);330 checkInt(loc, hi, 20, type);
181 relocateOne(Loc + 4, R_RISCV_PCREL_LO12_I, Val);331 if (isInt<20>(hi)) {
332 relocateOne(loc, R_RISCV_PCREL_HI20, val);
333 relocateOne(loc + 4, R_RISCV_PCREL_LO12_I, val);
182 }334 }
183 return;335 return;
184 }336 }
185337
338 case R_RISCV_GOT_HI20:
186 case R_RISCV_PCREL_HI20:339 case R_RISCV_PCREL_HI20:
340 case R_RISCV_TLS_GD_HI20:
341 case R_RISCV_TLS_GOT_HI20:
342 case R_RISCV_TPREL_HI20:
187 case R_RISCV_HI20: {343 case R_RISCV_HI20: {
188 checkInt(Loc, Val, 32, Type);344 uint64_t hi = val + 0x800;
189 uint32_t Hi = Val + 0x800;345 checkInt(loc, SignExtend64(hi, bits) >> 12, 20, type);
190 write32le(Loc, (read32le(Loc) & 0xFFF) | (Hi & 0xFFFFF000));346 write32le(loc, (read32le(loc) & 0xFFF) | (hi & 0xFFFFF000));
191 return;347 return;
192 }348 }
193349
194 case R_RISCV_PCREL_LO12_I:350 case R_RISCV_PCREL_LO12_I:
351 case R_RISCV_TPREL_LO12_I:
195 case R_RISCV_LO12_I: {352 case R_RISCV_LO12_I: {
196 checkInt(Loc, Val, 32, Type);353 uint64_t hi = (val + 0x800) >> 12;
197 uint32_t Hi = Val + 0x800;354 uint64_t lo = val - (hi << 12);
198 uint32_t Lo = Val - (Hi & 0xFFFFF000);355 write32le(loc, (read32le(loc) & 0xFFFFF) | ((lo & 0xFFF) << 20));
199 write32le(Loc, (read32le(Loc) & 0xFFFFF) | ((Lo & 0xFFF) << 20));
200 return;356 return;
201 }357 }
202358
203 case R_RISCV_PCREL_LO12_S:359 case R_RISCV_PCREL_LO12_S:
360 case R_RISCV_TPREL_LO12_S:
204 case R_RISCV_LO12_S: {361 case R_RISCV_LO12_S: {
205 checkInt(Loc, Val, 32, Type);362 uint64_t hi = (val + 0x800) >> 12;
206 uint32_t Hi = Val + 0x800;363 uint64_t lo = val - (hi << 12);
207 uint32_t Lo = Val - (Hi & 0xFFFFF000);364 uint32_t imm11_5 = extractBits(lo, 11, 5) << 25;
208 uint32_t Imm11_5 = extractBits(Lo, 11, 5) << 25;365 uint32_t imm4_0 = extractBits(lo, 4, 0) << 7;
209 uint32_t Imm4_0 = extractBits(Lo, 4, 0) << 7;366 write32le(loc, (read32le(loc) & 0x1FFF07F) | imm11_5 | imm4_0);
210 write32le(Loc, (read32le(Loc) & 0x1FFF07F) | Imm11_5 | Imm4_0);
211 return;367 return;
212 }368 }
213369
214 case R_RISCV_ADD8:370 case R_RISCV_ADD8:
215 *Loc += Val;371 *loc += val;
216 return;372 return;
217 case R_RISCV_ADD16:373 case R_RISCV_ADD16:
218 write16le(Loc, read16le(Loc) + Val);374 write16le(loc, read16le(loc) + val);
219 return;375 return;
220 case R_RISCV_ADD32:376 case R_RISCV_ADD32:
221 write32le(Loc, read32le(Loc) + Val);377 write32le(loc, read32le(loc) + val);
222 return;378 return;
223 case R_RISCV_ADD64:379 case R_RISCV_ADD64:
224 write64le(Loc, read64le(Loc) + Val);380 write64le(loc, read64le(loc) + val);
225 return;381 return;
226 case R_RISCV_SUB6:382 case R_RISCV_SUB6:
227 *Loc = (*Loc & 0xc0) | (((*Loc & 0x3f) - Val) & 0x3f);383 *loc = (*loc & 0xc0) | (((*loc & 0x3f) - val) & 0x3f);
228 return;384 return;
229 case R_RISCV_SUB8:385 case R_RISCV_SUB8:
230 *Loc -= Val;386 *loc -= val;
231 return;387 return;
232 case R_RISCV_SUB16:388 case R_RISCV_SUB16:
233 write16le(Loc, read16le(Loc) - Val);389 write16le(loc, read16le(loc) - val);
234 return;390 return;
235 case R_RISCV_SUB32:391 case R_RISCV_SUB32:
236 write32le(Loc, read32le(Loc) - Val);392 write32le(loc, read32le(loc) - val);
237 return;393 return;
238 case R_RISCV_SUB64:394 case R_RISCV_SUB64:
239 write64le(Loc, read64le(Loc) - Val);395 write64le(loc, read64le(loc) - val);
240 return;396 return;
241 case R_RISCV_SET6:397 case R_RISCV_SET6:
242 *Loc = (*Loc & 0xc0) | (Val & 0x3f);398 *loc = (*loc & 0xc0) | (val & 0x3f);
243 return;399 return;
244 case R_RISCV_SET8:400 case R_RISCV_SET8:
245 *Loc = Val;401 *loc = val;
246 return;402 return;
247 case R_RISCV_SET16:403 case R_RISCV_SET16:
248 write16le(Loc, Val);404 write16le(loc, val);
249 return;405 return;
250 case R_RISCV_SET32:406 case R_RISCV_SET32:
251 case R_RISCV_32_PCREL:407 case R_RISCV_32_PCREL:
252 write32le(Loc, Val);408 write32le(loc, val);
253 return;409 return;
254410
411 case R_RISCV_TLS_DTPREL32:
412 write32le(loc, val - dtpOffset);
413 break;
414 case R_RISCV_TLS_DTPREL64:
415 write64le(loc, val - dtpOffset);
416 break;
417
255 case R_RISCV_ALIGN:418 case R_RISCV_ALIGN:
256 case R_RISCV_RELAX:419 case R_RISCV_RELAX:
257 return; // Ignored (for now)420 return; // Ignored (for now)
...@@ -267,13 +430,13 @@ void RISCV::relocateOne(uint8_t *Loc, const RelType Type,...@@ -267,13 +430,13 @@ void RISCV::relocateOne(uint8_t *Loc, const RelType Type,
267 case R_RISCV_GPREL_I:430 case R_RISCV_GPREL_I:
268 case R_RISCV_GPREL_S:431 case R_RISCV_GPREL_S:
269 default:432 default:
270 error(getErrorLocation(Loc) +433 error(getErrorLocation(loc) +
271 "unimplemented relocation: " + toString(Type));434 "unimplemented relocation: " + toString(type));
272 return;435 return;
273 }436 }
274}437}
275438
276TargetInfo *elf::getRISCVTargetInfo() {439TargetInfo *elf::getRISCVTargetInfo() {
277 static RISCV Target;440 static RISCV target;
278 return &Target;441 return &target;
279}442}
deps/lld/ELF/Arch/SPARCV9.cpp+51-51
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- SPARCV9.cpp --------------------------------------------------------===//1//===- SPARCV9.cpp --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -24,32 +23,32 @@ namespace {...@@ -24,32 +23,32 @@ namespace {
24class SPARCV9 final : public TargetInfo {23class SPARCV9 final : public TargetInfo {
25public:24public:
26 SPARCV9();25 SPARCV9();
27 RelExpr getRelExpr(RelType Type, const Symbol &S,26 RelExpr getRelExpr(RelType type, const Symbol &s,
28 const uint8_t *Loc) const override;27 const uint8_t *loc) const override;
29 void writePlt(uint8_t *Buf, uint64_t GotEntryAddr, uint64_t PltEntryAddr,28 void writePlt(uint8_t *buf, uint64_t gotEntryAddr, uint64_t pltEntryAddr,
30 int32_t Index, unsigned RelOff) const override;29 int32_t index, unsigned relOff) const override;
31 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;30 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
32};31};
33} // namespace32} // namespace
3433
35SPARCV9::SPARCV9() {34SPARCV9::SPARCV9() {
36 CopyRel = R_SPARC_COPY;35 copyRel = R_SPARC_COPY;
37 GotRel = R_SPARC_GLOB_DAT;36 gotRel = R_SPARC_GLOB_DAT;
38 NoneRel = R_SPARC_NONE;37 noneRel = R_SPARC_NONE;
39 PltRel = R_SPARC_JMP_SLOT;38 pltRel = R_SPARC_JMP_SLOT;
40 RelativeRel = R_SPARC_RELATIVE;39 relativeRel = R_SPARC_RELATIVE;
41 GotEntrySize = 8;40 symbolicRel = R_SPARC_64;
42 PltEntrySize = 32;41 pltEntrySize = 32;
43 PltHeaderSize = 4 * PltEntrySize;42 pltHeaderSize = 4 * pltEntrySize;
4443
45 PageSize = 8192;44 defaultCommonPageSize = 8192;
46 DefaultMaxPageSize = 0x100000;45 defaultMaxPageSize = 0x100000;
47 DefaultImageBase = 0x100000;46 defaultImageBase = 0x100000;
48}47}
4948
50RelExpr SPARCV9::getRelExpr(RelType Type, const Symbol &S,49RelExpr SPARCV9::getRelExpr(RelType type, const Symbol &s,
51 const uint8_t *Loc) const {50 const uint8_t *loc) const {
52 switch (Type) {51 switch (type) {
53 case R_SPARC_32:52 case R_SPARC_32:
54 case R_SPARC_UA32:53 case R_SPARC_UA32:
55 case R_SPARC_64:54 case R_SPARC_64:
...@@ -69,64 +68,65 @@ RelExpr SPARCV9::getRelExpr(RelType Type, const Symbol &S,...@@ -69,64 +68,65 @@ RelExpr SPARCV9::getRelExpr(RelType Type, const Symbol &S,
69 case R_SPARC_NONE:68 case R_SPARC_NONE:
70 return R_NONE;69 return R_NONE;
71 default:70 default:
72 return R_INVALID;71 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
72 ") against symbol " + toString(s));
73 return R_NONE;
73 }74 }
74}75}
7576
76void SPARCV9::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {77void SPARCV9::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
77 switch (Type) {78 switch (type) {
78 case R_SPARC_32:79 case R_SPARC_32:
79 case R_SPARC_UA32:80 case R_SPARC_UA32:
80 // V-word3281 // V-word32
81 checkUInt(Loc, Val, 32, Type);82 checkUInt(loc, val, 32, type);
82 write32be(Loc, Val);83 write32be(loc, val);
83 break;84 break;
84 case R_SPARC_DISP32:85 case R_SPARC_DISP32:
85 // V-disp3286 // V-disp32
86 checkInt(Loc, Val, 32, Type);87 checkInt(loc, val, 32, type);
87 write32be(Loc, Val);88 write32be(loc, val);
88 break;89 break;
89 case R_SPARC_WDISP30:90 case R_SPARC_WDISP30:
90 case R_SPARC_WPLT30:91 case R_SPARC_WPLT30:
91 // V-disp3092 // V-disp30
92 checkInt(Loc, Val, 32, Type);93 checkInt(loc, val, 32, type);
93 write32be(Loc, (read32be(Loc) & ~0x3fffffff) | ((Val >> 2) & 0x3fffffff));94 write32be(loc, (read32be(loc) & ~0x3fffffff) | ((val >> 2) & 0x3fffffff));
94 break;95 break;
95 case R_SPARC_22:96 case R_SPARC_22:
96 // V-imm2297 // V-imm22
97 checkUInt(Loc, Val, 22, Type);98 checkUInt(loc, val, 22, type);
98 write32be(Loc, (read32be(Loc) & ~0x003fffff) | (Val & 0x003fffff));99 write32be(loc, (read32be(loc) & ~0x003fffff) | (val & 0x003fffff));
99 break;100 break;
100 case R_SPARC_GOT22:101 case R_SPARC_GOT22:
101 case R_SPARC_PC22:102 case R_SPARC_PC22:
102 // T-imm22103 // T-imm22
103 write32be(Loc, (read32be(Loc) & ~0x003fffff) | ((Val >> 10) & 0x003fffff));104 write32be(loc, (read32be(loc) & ~0x003fffff) | ((val >> 10) & 0x003fffff));
104 break;105 break;
105 case R_SPARC_WDISP19:106 case R_SPARC_WDISP19:
106 // V-disp19107 // V-disp19
107 checkInt(Loc, Val, 21, Type);108 checkInt(loc, val, 21, type);
108 write32be(Loc, (read32be(Loc) & ~0x0007ffff) | ((Val >> 2) & 0x0007ffff));109 write32be(loc, (read32be(loc) & ~0x0007ffff) | ((val >> 2) & 0x0007ffff));
109 break;110 break;
110 case R_SPARC_GOT10:111 case R_SPARC_GOT10:
111 case R_SPARC_PC10:112 case R_SPARC_PC10:
112 // T-simm10113 // T-simm10
113 write32be(Loc, (read32be(Loc) & ~0x000003ff) | (Val & 0x000003ff));114 write32be(loc, (read32be(loc) & ~0x000003ff) | (val & 0x000003ff));
114 break;115 break;
115 case R_SPARC_64:116 case R_SPARC_64:
116 case R_SPARC_UA64:117 case R_SPARC_UA64:
117 case R_SPARC_GLOB_DAT:
118 // V-xword64118 // V-xword64
119 write64be(Loc, Val);119 write64be(loc, val);
120 break;120 break;
121 default:121 default:
122 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));122 llvm_unreachable("unknown relocation");
123 }123 }
124}124}
125125
126void SPARCV9::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,126void SPARCV9::writePlt(uint8_t *buf, uint64_t gotEntryAddr,
127 uint64_t PltEntryAddr, int32_t Index,127 uint64_t pltEntryAddr, int32_t index,
128 unsigned RelOff) const {128 unsigned relOff) const {
129 const uint8_t PltData[] = {129 const uint8_t pltData[] = {
130 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1130 0x03, 0x00, 0x00, 0x00, // sethi (. - .PLT0), %g1
131 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1131 0x30, 0x68, 0x00, 0x00, // ba,a %xcc, .PLT1
132 0x01, 0x00, 0x00, 0x00, // nop132 0x01, 0x00, 0x00, 0x00, // nop
...@@ -136,14 +136,14 @@ void SPARCV9::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,...@@ -136,14 +136,14 @@ void SPARCV9::writePlt(uint8_t *Buf, uint64_t GotEntryAddr,
136 0x01, 0x00, 0x00, 0x00, // nop136 0x01, 0x00, 0x00, 0x00, // nop
137 0x01, 0x00, 0x00, 0x00 // nop137 0x01, 0x00, 0x00, 0x00 // nop
138 };138 };
139 memcpy(Buf, PltData, sizeof(PltData));139 memcpy(buf, pltData, sizeof(pltData));
140140
141 uint64_t Off = getPltEntryOffset(Index);141 uint64_t off = pltHeaderSize + pltEntrySize * index;
142 relocateOne(Buf, R_SPARC_22, Off);142 relocateOne(buf, R_SPARC_22, off);
143 relocateOne(Buf + 4, R_SPARC_WDISP19, -(Off + 4 - PltEntrySize));143 relocateOne(buf + 4, R_SPARC_WDISP19, -(off + 4 - pltEntrySize));
144}144}
145145
146TargetInfo *elf::getSPARCV9TargetInfo() {146TargetInfo *elf::getSPARCV9TargetInfo() {
147 static SPARCV9 Target;147 static SPARCV9 target;
148 return &Target;148 return &target;
149}149}
deps/lld/ELF/Arch/X86.cpp+221-221
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- X86.cpp ------------------------------------------------------------===//1//===- X86.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -24,63 +23,73 @@ namespace {...@@ -24,63 +23,73 @@ namespace {
24class X86 : public TargetInfo {23class X86 : public TargetInfo {
25public:24public:
26 X86();25 X86();
27 RelExpr getRelExpr(RelType Type, const Symbol &S,26 int getTlsGdRelaxSkip(RelType type) const override;
28 const uint8_t *Loc) const override;27 RelExpr getRelExpr(RelType type, const Symbol &s,
29 int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const override;28 const uint8_t *loc) const override;
30 void writeGotPltHeader(uint8_t *Buf) const override;29 int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
31 RelType getDynRel(RelType Type) const override;30 void writeGotPltHeader(uint8_t *buf) const override;
32 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;31 RelType getDynRel(RelType type) const override;
33 void writeIgotPlt(uint8_t *Buf, const Symbol &S) const override;32 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
34 void writePltHeader(uint8_t *Buf) const override;33 void writeIgotPlt(uint8_t *buf, const Symbol &s) const override;
35 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,34 void writePltHeader(uint8_t *buf) const override;
36 int32_t Index, unsigned RelOff) const override;35 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
37 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;36 int32_t index, unsigned relOff) const override;
3837 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
39 RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,38
40 RelExpr Expr) const override;39 RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
41 void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override;40 RelExpr expr) const override;
42 void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;41 void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
43 void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;42 void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
44 void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;43 void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
44 void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
45};45};
46} // namespace46} // namespace
4747
48X86::X86() {48X86::X86() {
49 CopyRel = R_386_COPY;49 copyRel = R_386_COPY;
50 GotRel = R_386_GLOB_DAT;50 gotRel = R_386_GLOB_DAT;
51 NoneRel = R_386_NONE;51 noneRel = R_386_NONE;
52 PltRel = R_386_JUMP_SLOT;52 pltRel = R_386_JUMP_SLOT;
53 IRelativeRel = R_386_IRELATIVE;53 iRelativeRel = R_386_IRELATIVE;
54 RelativeRel = R_386_RELATIVE;54 relativeRel = R_386_RELATIVE;
55 TlsGotRel = R_386_TLS_TPOFF;55 symbolicRel = R_386_32;
56 TlsModuleIndexRel = R_386_TLS_DTPMOD32;56 tlsGotRel = R_386_TLS_TPOFF;
57 TlsOffsetRel = R_386_TLS_DTPOFF32;57 tlsModuleIndexRel = R_386_TLS_DTPMOD32;
58 GotEntrySize = 4;58 tlsOffsetRel = R_386_TLS_DTPOFF32;
59 GotPltEntrySize = 4;59 pltEntrySize = 16;
60 PltEntrySize = 16;60 pltHeaderSize = 16;
61 PltHeaderSize = 16;61 trapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3
62 TlsGdRelaxSkip = 2;
63 TrapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3
6462
65 // Align to the non-PAE large page size (known as a superpage or huge page).63 // Align to the non-PAE large page size (known as a superpage or huge page).
66 // FreeBSD automatically promotes large, superpage-aligned allocations.64 // FreeBSD automatically promotes large, superpage-aligned allocations.
67 DefaultImageBase = 0x400000;65 defaultImageBase = 0x400000;
68}66}
6967
70static bool hasBaseReg(uint8_t ModRM) { return (ModRM & 0xc7) != 0x5; }68int X86::getTlsGdRelaxSkip(RelType type) const {
69 return 2;
70}
7171
72RelExpr X86::getRelExpr(RelType Type, const Symbol &S,72RelExpr X86::getRelExpr(RelType type, const Symbol &s,
73 const uint8_t *Loc) const {73 const uint8_t *loc) const {
74 switch (Type) {74 // There are 4 different TLS variable models with varying degrees of
75 // flexibility and performance. LocalExec and InitialExec models are fast but
76 // less-flexible models. If they are in use, we set DF_STATIC_TLS flag in the
77 // dynamic section to let runtime know about that.
78 if (type == R_386_TLS_LE || type == R_386_TLS_LE_32 || type == R_386_TLS_IE ||
79 type == R_386_TLS_GOTIE)
80 config->hasStaticTlsModel = true;
81
82 switch (type) {
75 case R_386_8:83 case R_386_8:
76 case R_386_16:84 case R_386_16:
77 case R_386_32:85 case R_386_32:
78 case R_386_TLS_LDO_32:
79 return R_ABS;86 return R_ABS;
87 case R_386_TLS_LDO_32:
88 return R_DTPREL;
80 case R_386_TLS_GD:89 case R_386_TLS_GD:
81 return R_TLSGD_GOT_FROM_END;90 return R_TLSGD_GOTPLT;
82 case R_386_TLS_LDM:91 case R_386_TLS_LDM:
83 return R_TLSLD_GOT_FROM_END;92 return R_TLSLD_GOTPLT;
84 case R_386_PLT32:93 case R_386_PLT32:
85 return R_PLT_PC;94 return R_PLT_PC;
86 case R_386_PC8:95 case R_386_PC8:
...@@ -88,7 +97,7 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,...@@ -88,7 +97,7 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,
88 case R_386_PC32:97 case R_386_PC32:
89 return R_PC;98 return R_PC;
90 case R_386_GOTPC:99 case R_386_GOTPC:
91 return R_GOTONLY_PC_FROM_END;100 return R_GOTPLTONLY_PC;
92 case R_386_TLS_IE:101 case R_386_TLS_IE:
93 return R_GOT;102 return R_GOT;
94 case R_386_GOT32:103 case R_386_GOT32:
...@@ -108,14 +117,14 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,...@@ -108,14 +117,14 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,
108 // load an GOT address to a register, which is usually %ebx.117 // load an GOT address to a register, which is usually %ebx.
109 //118 //
110 // So, there are two ways to refer to symbol foo's GOT entry: foo@GOT or119 // So, there are two ways to refer to symbol foo's GOT entry: foo@GOT or
111 // foo@GOT(%reg).120 // foo@GOT(%ebx).
112 //121 //
113 // foo@GOT is not usable in PIC. If we are creating a PIC output and if we122 // foo@GOT is not usable in PIC. If we are creating a PIC output and if we
114 // find such relocation, we should report an error. foo@GOT is resolved to123 // find such relocation, we should report an error. foo@GOT is resolved to
115 // an *absolute* address of foo's GOT entry, because both GOT address and124 // an *absolute* address of foo's GOT entry, because both GOT address and
116 // foo's offset are known. In other words, it's G + A.125 // foo's offset are known. In other words, it's G + A.
117 //126 //
118 // foo@GOT(%reg) needs to be resolved to a *relative* offset from a GOT to127 // foo@GOT(%ebx) needs to be resolved to a *relative* offset from a GOT to
119 // foo's GOT entry in the table, because GOT address is not known but foo's128 // foo's GOT entry in the table, because GOT address is not known but foo's
120 // offset in the table is known. It's G + A - GOT.129 // offset in the table is known. It's G + A - GOT.
121 //130 //
...@@ -123,16 +132,16 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,...@@ -123,16 +132,16 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,
123 // different use cases. In order to distinguish them, we have to read a132 // different use cases. In order to distinguish them, we have to read a
124 // machine instruction.133 // machine instruction.
125 //134 //
126 // The following code implements it. We assume that Loc[0] is the first135 // The following code implements it. We assume that Loc[0] is the first byte
127 // byte of a displacement or an immediate field of a valid machine136 // of a displacement or an immediate field of a valid machine
128 // instruction. That means a ModRM byte is at Loc[-1]. By taking a look at137 // instruction. That means a ModRM byte is at Loc[-1]. By taking a look at
129 // the byte, we can determine whether the instruction is register-relative138 // the byte, we can determine whether the instruction uses the operand as an
130 // (i.e. it was generated for foo@GOT(%reg)) or absolute (i.e. foo@GOT).139 // absolute address (R_GOT) or a register-relative address (R_GOTPLT).
131 return hasBaseReg(Loc[-1]) ? R_GOT_FROM_END : R_GOT;140 return (loc[-1] & 0xc7) == 0x5 ? R_GOT : R_GOTPLT;
132 case R_386_TLS_GOTIE:141 case R_386_TLS_GOTIE:
133 return R_GOT_FROM_END;142 return R_GOTPLT;
134 case R_386_GOTOFF:143 case R_386_GOTOFF:
135 return R_GOTREL_FROM_END;144 return R_GOTPLTREL;
136 case R_386_TLS_LE:145 case R_386_TLS_LE:
137 return R_TLS;146 return R_TLS;
138 case R_386_TLS_LE_32:147 case R_386_TLS_LE_32:
...@@ -140,105 +149,102 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,...@@ -140,105 +149,102 @@ RelExpr X86::getRelExpr(RelType Type, const Symbol &S,
140 case R_386_NONE:149 case R_386_NONE:
141 return R_NONE;150 return R_NONE;
142 default:151 default:
143 return R_INVALID;152 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
153 ") against symbol " + toString(s));
154 return R_NONE;
144 }155 }
145}156}
146157
147RelExpr X86::adjustRelaxExpr(RelType Type, const uint8_t *Data,158RelExpr X86::adjustRelaxExpr(RelType type, const uint8_t *data,
148 RelExpr Expr) const {159 RelExpr expr) const {
149 switch (Expr) {160 switch (expr) {
150 default:161 default:
151 return Expr;162 return expr;
152 case R_RELAX_TLS_GD_TO_IE:163 case R_RELAX_TLS_GD_TO_IE:
153 return R_RELAX_TLS_GD_TO_IE_END;164 return R_RELAX_TLS_GD_TO_IE_GOTPLT;
154 case R_RELAX_TLS_GD_TO_LE:165 case R_RELAX_TLS_GD_TO_LE:
155 return R_RELAX_TLS_GD_TO_LE_NEG;166 return R_RELAX_TLS_GD_TO_LE_NEG;
156 }167 }
157}168}
158169
159void X86::writeGotPltHeader(uint8_t *Buf) const {170void X86::writeGotPltHeader(uint8_t *buf) const {
160 write32le(Buf, In.Dynamic->getVA());171 write32le(buf, mainPart->dynamic->getVA());
161}172}
162173
163void X86::writeGotPlt(uint8_t *Buf, const Symbol &S) const {174void X86::writeGotPlt(uint8_t *buf, const Symbol &s) const {
164 // Entries in .got.plt initially points back to the corresponding175 // Entries in .got.plt initially points back to the corresponding
165 // PLT entries with a fixed offset to skip the first instruction.176 // PLT entries with a fixed offset to skip the first instruction.
166 write32le(Buf, S.getPltVA() + 6);177 write32le(buf, s.getPltVA() + 6);
167}178}
168179
169void X86::writeIgotPlt(uint8_t *Buf, const Symbol &S) const {180void X86::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
170 // An x86 entry is the address of the ifunc resolver function.181 // An x86 entry is the address of the ifunc resolver function.
171 write32le(Buf, S.getVA());182 write32le(buf, s.getVA());
172}183}
173184
174RelType X86::getDynRel(RelType Type) const {185RelType X86::getDynRel(RelType type) const {
175 if (Type == R_386_TLS_LE)186 if (type == R_386_TLS_LE)
176 return R_386_TLS_TPOFF;187 return R_386_TLS_TPOFF;
177 if (Type == R_386_TLS_LE_32)188 if (type == R_386_TLS_LE_32)
178 return R_386_TLS_TPOFF32;189 return R_386_TLS_TPOFF32;
179 return Type;190 return type;
180}191}
181192
182void X86::writePltHeader(uint8_t *Buf) const {193void X86::writePltHeader(uint8_t *buf) const {
183 if (Config->Pic) {194 if (config->isPic) {
184 const uint8_t V[] = {195 const uint8_t v[] = {
185 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl GOTPLT+4(%ebx)196 0xff, 0xb3, 0x04, 0x00, 0x00, 0x00, // pushl 4(%ebx)
186 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *GOTPLT+8(%ebx)197 0xff, 0xa3, 0x08, 0x00, 0x00, 0x00, // jmp *8(%ebx)
187 0x90, 0x90, 0x90, 0x90 // nop198 0x90, 0x90, 0x90, 0x90 // nop
188 };199 };
189 memcpy(Buf, V, sizeof(V));200 memcpy(buf, v, sizeof(v));
190
191 uint32_t Ebx = In.Got->getVA() + In.Got->getSize();
192 uint32_t GotPlt = In.GotPlt->getVA() - Ebx;
193 write32le(Buf + 2, GotPlt + 4);
194 write32le(Buf + 8, GotPlt + 8);
195 return;201 return;
196 }202 }
197203
198 const uint8_t PltData[] = {204 const uint8_t pltData[] = {
199 0xff, 0x35, 0, 0, 0, 0, // pushl (GOTPLT+4)205 0xff, 0x35, 0, 0, 0, 0, // pushl (GOTPLT+4)
200 0xff, 0x25, 0, 0, 0, 0, // jmp *(GOTPLT+8)206 0xff, 0x25, 0, 0, 0, 0, // jmp *(GOTPLT+8)
201 0x90, 0x90, 0x90, 0x90, // nop207 0x90, 0x90, 0x90, 0x90, // nop
202 };208 };
203 memcpy(Buf, PltData, sizeof(PltData));209 memcpy(buf, pltData, sizeof(pltData));
204 uint32_t GotPlt = In.GotPlt->getVA();210 uint32_t gotPlt = in.gotPlt->getVA();
205 write32le(Buf + 2, GotPlt + 4);211 write32le(buf + 2, gotPlt + 4);
206 write32le(Buf + 8, GotPlt + 8);212 write32le(buf + 8, gotPlt + 8);
207}213}
208214
209void X86::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,215void X86::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
210 uint64_t PltEntryAddr, int32_t Index,216 uint64_t pltEntryAddr, int32_t index,
211 unsigned RelOff) const {217 unsigned relOff) const {
212 const uint8_t Inst[] = {218 if (config->isPic) {
213 0xff, 0x00, 0, 0, 0, 0, // jmp *foo_in_GOT or jmp *foo@GOT(%ebx)219 const uint8_t inst[] = {
214 0x68, 0, 0, 0, 0, // pushl $reloc_offset220 0xff, 0xa3, 0, 0, 0, 0, // jmp *foo@GOT(%ebx)
215 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC221 0x68, 0, 0, 0, 0, // pushl $reloc_offset
216 };222 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC
217 memcpy(Buf, Inst, sizeof(Inst));223 };
218224 memcpy(buf, inst, sizeof(inst));
219 if (Config->Pic) {225 write32le(buf + 2, gotPltEntryAddr - in.gotPlt->getVA());
220 // jmp *foo@GOT(%ebx)
221 uint32_t Ebx = In.Got->getVA() + In.Got->getSize();
222 Buf[1] = 0xa3;
223 write32le(Buf + 2, GotPltEntryAddr - Ebx);
224 } else {226 } else {
225 // jmp *foo_in_GOT227 const uint8_t inst[] = {
226 Buf[1] = 0x25;228 0xff, 0x25, 0, 0, 0, 0, // jmp *foo@GOT
227 write32le(Buf + 2, GotPltEntryAddr);229 0x68, 0, 0, 0, 0, // pushl $reloc_offset
230 0xe9, 0, 0, 0, 0, // jmp .PLT0@PC
231 };
232 memcpy(buf, inst, sizeof(inst));
233 write32le(buf + 2, gotPltEntryAddr);
228 }234 }
229235
230 write32le(Buf + 7, RelOff);236 write32le(buf + 7, relOff);
231 write32le(Buf + 12, -getPltEntryOffset(Index) - 16);237 write32le(buf + 12, -pltHeaderSize - pltEntrySize * index - 16);
232}238}
233239
234int64_t X86::getImplicitAddend(const uint8_t *Buf, RelType Type) const {240int64_t X86::getImplicitAddend(const uint8_t *buf, RelType type) const {
235 switch (Type) {241 switch (type) {
236 case R_386_8:242 case R_386_8:
237 case R_386_PC8:243 case R_386_PC8:
238 return SignExtend64<8>(*Buf);244 return SignExtend64<8>(*buf);
239 case R_386_16:245 case R_386_16:
240 case R_386_PC16:246 case R_386_PC16:
241 return SignExtend64<16>(read16le(Buf));247 return SignExtend64<16>(read16le(buf));
242 case R_386_32:248 case R_386_32:
243 case R_386_GOT32:249 case R_386_GOT32:
244 case R_386_GOT32X:250 case R_386_GOT32X:
...@@ -248,28 +254,28 @@ int64_t X86::getImplicitAddend(const uint8_t *Buf, RelType Type) const {...@@ -248,28 +254,28 @@ int64_t X86::getImplicitAddend(const uint8_t *Buf, RelType Type) const {
248 case R_386_PLT32:254 case R_386_PLT32:
249 case R_386_TLS_LDO_32:255 case R_386_TLS_LDO_32:
250 case R_386_TLS_LE:256 case R_386_TLS_LE:
251 return SignExtend64<32>(read32le(Buf));257 return SignExtend64<32>(read32le(buf));
252 default:258 default:
253 return 0;259 return 0;
254 }260 }
255}261}
256262
257void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {263void X86::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
258 switch (Type) {264 switch (type) {
259 case R_386_8:265 case R_386_8:
260 // R_386_{PC,}{8,16} are not part of the i386 psABI, but they are266 // R_386_{PC,}{8,16} are not part of the i386 psABI, but they are
261 // being used for some 16-bit programs such as boot loaders, so267 // being used for some 16-bit programs such as boot loaders, so
262 // we want to support them.268 // we want to support them.
263 checkIntUInt(Loc, Val, 8, Type);269 checkIntUInt(loc, val, 8, type);
264 *Loc = Val;270 *loc = val;
265 break;271 break;
266 case R_386_PC8:272 case R_386_PC8:
267 checkInt(Loc, Val, 8, Type);273 checkInt(loc, val, 8, type);
268 *Loc = Val;274 *loc = val;
269 break;275 break;
270 case R_386_16:276 case R_386_16:
271 checkIntUInt(Loc, Val, 16, Type);277 checkIntUInt(loc, val, 16, type);
272 write16le(Loc, Val);278 write16le(loc, val);
273 break;279 break;
274 case R_386_PC16:280 case R_386_PC16:
275 // R_386_PC16 is normally used with 16 bit code. In that situation281 // R_386_PC16 is normally used with 16 bit code. In that situation
...@@ -282,11 +288,10 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -282,11 +288,10 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
282 // current location subtracted from it.288 // current location subtracted from it.
283 // We just check that Val fits in 17 bits. This misses some cases, but289 // We just check that Val fits in 17 bits. This misses some cases, but
284 // should have no false positives.290 // should have no false positives.
285 checkInt(Loc, Val, 17, Type);291 checkInt(loc, val, 17, type);
286 write16le(Loc, Val);292 write16le(loc, val);
287 break;293 break;
288 case R_386_32:294 case R_386_32:
289 case R_386_GLOB_DAT:
290 case R_386_GOT32:295 case R_386_GOT32:
291 case R_386_GOT32X:296 case R_386_GOT32X:
292 case R_386_GOTOFF:297 case R_386_GOTOFF:
...@@ -305,86 +310,86 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -305,86 +310,86 @@ void X86::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
305 case R_386_TLS_LE_32:310 case R_386_TLS_LE_32:
306 case R_386_TLS_TPOFF:311 case R_386_TLS_TPOFF:
307 case R_386_TLS_TPOFF32:312 case R_386_TLS_TPOFF32:
308 checkInt(Loc, Val, 32, Type);313 checkInt(loc, val, 32, type);
309 write32le(Loc, Val);314 write32le(loc, val);
310 break;315 break;
311 default:316 default:
312 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));317 llvm_unreachable("unknown relocation");
313 }318 }
314}319}
315320
316void X86::relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {321void X86::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
317 // Convert322 // Convert
318 // leal x@tlsgd(, %ebx, 1),323 // leal x@tlsgd(, %ebx, 1),
319 // call __tls_get_addr@plt324 // call __tls_get_addr@plt
320 // to325 // to
321 // movl %gs:0,%eax326 // movl %gs:0,%eax
322 // subl $x@ntpoff,%eax327 // subl $x@ntpoff,%eax
323 const uint8_t Inst[] = {328 const uint8_t inst[] = {
324 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax329 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
325 0x81, 0xe8, 0, 0, 0, 0, // subl Val(%ebx), %eax330 0x81, 0xe8, 0, 0, 0, 0, // subl Val(%ebx), %eax
326 };331 };
327 memcpy(Loc - 3, Inst, sizeof(Inst));332 memcpy(loc - 3, inst, sizeof(inst));
328 write32le(Loc + 5, Val);333 write32le(loc + 5, val);
329}334}
330335
331void X86::relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const {336void X86::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
332 // Convert337 // Convert
333 // leal x@tlsgd(, %ebx, 1),338 // leal x@tlsgd(, %ebx, 1),
334 // call __tls_get_addr@plt339 // call __tls_get_addr@plt
335 // to340 // to
336 // movl %gs:0, %eax341 // movl %gs:0, %eax
337 // addl x@gotntpoff(%ebx), %eax342 // addl x@gotntpoff(%ebx), %eax
338 const uint8_t Inst[] = {343 const uint8_t inst[] = {
339 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax344 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0, %eax
340 0x03, 0x83, 0, 0, 0, 0, // addl Val(%ebx), %eax345 0x03, 0x83, 0, 0, 0, 0, // addl Val(%ebx), %eax
341 };346 };
342 memcpy(Loc - 3, Inst, sizeof(Inst));347 memcpy(loc - 3, inst, sizeof(inst));
343 write32le(Loc + 5, Val);348 write32le(loc + 5, val);
344}349}
345350
346// In some conditions, relocations can be optimized to avoid using GOT.351// In some conditions, relocations can be optimized to avoid using GOT.
347// This function does that for Initial Exec to Local Exec case.352// This function does that for Initial Exec to Local Exec case.
348void X86::relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {353void X86::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
349 // Ulrich's document section 6.2 says that @gotntpoff can354 // Ulrich's document section 6.2 says that @gotntpoff can
350 // be used with MOVL or ADDL instructions.355 // be used with MOVL or ADDL instructions.
351 // @indntpoff is similar to @gotntpoff, but for use in356 // @indntpoff is similar to @gotntpoff, but for use in
352 // position dependent code.357 // position dependent code.
353 uint8_t Reg = (Loc[-1] >> 3) & 7;358 uint8_t reg = (loc[-1] >> 3) & 7;
354359
355 if (Type == R_386_TLS_IE) {360 if (type == R_386_TLS_IE) {
356 if (Loc[-1] == 0xa1) {361 if (loc[-1] == 0xa1) {
357 // "movl foo@indntpoff,%eax" -> "movl $foo,%eax"362 // "movl foo@indntpoff,%eax" -> "movl $foo,%eax"
358 // This case is different from the generic case below because363 // This case is different from the generic case below because
359 // this is a 5 byte instruction while below is 6 bytes.364 // this is a 5 byte instruction while below is 6 bytes.
360 Loc[-1] = 0xb8;365 loc[-1] = 0xb8;
361 } else if (Loc[-2] == 0x8b) {366 } else if (loc[-2] == 0x8b) {
362 // "movl foo@indntpoff,%reg" -> "movl $foo,%reg"367 // "movl foo@indntpoff,%reg" -> "movl $foo,%reg"
363 Loc[-2] = 0xc7;368 loc[-2] = 0xc7;
364 Loc[-1] = 0xc0 | Reg;369 loc[-1] = 0xc0 | reg;
365 } else {370 } else {
366 // "addl foo@indntpoff,%reg" -> "addl $foo,%reg"371 // "addl foo@indntpoff,%reg" -> "addl $foo,%reg"
367 Loc[-2] = 0x81;372 loc[-2] = 0x81;
368 Loc[-1] = 0xc0 | Reg;373 loc[-1] = 0xc0 | reg;
369 }374 }
370 } else {375 } else {
371 assert(Type == R_386_TLS_GOTIE);376 assert(type == R_386_TLS_GOTIE);
372 if (Loc[-2] == 0x8b) {377 if (loc[-2] == 0x8b) {
373 // "movl foo@gottpoff(%rip),%reg" -> "movl $foo,%reg"378 // "movl foo@gottpoff(%rip),%reg" -> "movl $foo,%reg"
374 Loc[-2] = 0xc7;379 loc[-2] = 0xc7;
375 Loc[-1] = 0xc0 | Reg;380 loc[-1] = 0xc0 | reg;
376 } else {381 } else {
377 // "addl foo@gotntpoff(%rip),%reg" -> "leal foo(%reg),%reg"382 // "addl foo@gotntpoff(%rip),%reg" -> "leal foo(%reg),%reg"
378 Loc[-2] = 0x8d;383 loc[-2] = 0x8d;
379 Loc[-1] = 0x80 | (Reg << 3) | Reg;384 loc[-1] = 0x80 | (reg << 3) | reg;
380 }385 }
381 }386 }
382 write32le(Loc, Val);387 write32le(loc, val);
383}388}
384389
385void X86::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {390void X86::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
386 if (Type == R_386_TLS_LDO_32) {391 if (type == R_386_TLS_LDO_32) {
387 write32le(Loc, Val);392 write32le(loc, val);
388 return;393 return;
389 }394 }
390395
...@@ -395,48 +400,48 @@ void X86::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -395,48 +400,48 @@ void X86::relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const {
395 // movl %gs:0,%eax400 // movl %gs:0,%eax
396 // nop401 // nop
397 // leal 0(%esi,1),%esi402 // leal 0(%esi,1),%esi
398 const uint8_t Inst[] = {403 const uint8_t inst[] = {
399 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax404 0x65, 0xa1, 0x00, 0x00, 0x00, 0x00, // movl %gs:0,%eax
400 0x90, // nop405 0x90, // nop
401 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi406 0x8d, 0x74, 0x26, 0x00, // leal 0(%esi,1),%esi
402 };407 };
403 memcpy(Loc - 2, Inst, sizeof(Inst));408 memcpy(loc - 2, inst, sizeof(inst));
404}409}
405410
406namespace {411namespace {
407class RetpolinePic : public X86 {412class RetpolinePic : public X86 {
408public:413public:
409 RetpolinePic();414 RetpolinePic();
410 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;415 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
411 void writePltHeader(uint8_t *Buf) const override;416 void writePltHeader(uint8_t *buf) const override;
412 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,417 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
413 int32_t Index, unsigned RelOff) const override;418 int32_t index, unsigned relOff) const override;
414};419};
415420
416class RetpolineNoPic : public X86 {421class RetpolineNoPic : public X86 {
417public:422public:
418 RetpolineNoPic();423 RetpolineNoPic();
419 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;424 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
420 void writePltHeader(uint8_t *Buf) const override;425 void writePltHeader(uint8_t *buf) const override;
421 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,426 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
422 int32_t Index, unsigned RelOff) const override;427 int32_t index, unsigned relOff) const override;
423};428};
424} // namespace429} // namespace
425430
426RetpolinePic::RetpolinePic() {431RetpolinePic::RetpolinePic() {
427 PltHeaderSize = 48;432 pltHeaderSize = 48;
428 PltEntrySize = 32;433 pltEntrySize = 32;
429}434}
430435
431void RetpolinePic::writeGotPlt(uint8_t *Buf, const Symbol &S) const {436void RetpolinePic::writeGotPlt(uint8_t *buf, const Symbol &s) const {
432 write32le(Buf, S.getPltVA() + 17);437 write32le(buf, s.getPltVA() + 17);
433}438}
434439
435void RetpolinePic::writePltHeader(uint8_t *Buf) const {440void RetpolinePic::writePltHeader(uint8_t *buf) const {
436 const uint8_t Insn[] = {441 const uint8_t insn[] = {
437 0xff, 0xb3, 0, 0, 0, 0, // 0: pushl GOTPLT+4(%ebx)442 0xff, 0xb3, 4, 0, 0, 0, // 0: pushl 4(%ebx)
438 0x50, // 6: pushl %eax443 0x50, // 6: pushl %eax
439 0x8b, 0x83, 0, 0, 0, 0, // 7: mov GOTPLT+8(%ebx), %eax444 0x8b, 0x83, 8, 0, 0, 0, // 7: mov 8(%ebx), %eax
440 0xe8, 0x0e, 0x00, 0x00, 0x00, // d: call next445 0xe8, 0x0e, 0x00, 0x00, 0x00, // d: call next
441 0xf3, 0x90, // 12: loop: pause446 0xf3, 0x90, // 12: loop: pause
442 0x0f, 0xae, 0xe8, // 14: lfence447 0x0f, 0xae, 0xe8, // 14: lfence
...@@ -450,18 +455,13 @@ void RetpolinePic::writePltHeader(uint8_t *Buf) const {...@@ -450,18 +455,13 @@ void RetpolinePic::writePltHeader(uint8_t *Buf) const {
450 0xc3, // 2e: ret455 0xc3, // 2e: ret
451 0xcc, // 2f: int3; padding456 0xcc, // 2f: int3; padding
452 };457 };
453 memcpy(Buf, Insn, sizeof(Insn));458 memcpy(buf, insn, sizeof(insn));
454
455 uint32_t Ebx = In.Got->getVA() + In.Got->getSize();
456 uint32_t GotPlt = In.GotPlt->getVA() - Ebx;
457 write32le(Buf + 2, GotPlt + 4);
458 write32le(Buf + 9, GotPlt + 8);
459}459}
460460
461void RetpolinePic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,461void RetpolinePic::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
462 uint64_t PltEntryAddr, int32_t Index,462 uint64_t pltEntryAddr, int32_t index,
463 unsigned RelOff) const {463 unsigned relOff) const {
464 const uint8_t Insn[] = {464 const uint8_t insn[] = {
465 0x50, // pushl %eax465 0x50, // pushl %eax
466 0x8b, 0x83, 0, 0, 0, 0, // mov foo@GOT(%ebx), %eax466 0x8b, 0x83, 0, 0, 0, 0, // mov foo@GOT(%ebx), %eax
467 0xe8, 0, 0, 0, 0, // call plt+0x20467 0xe8, 0, 0, 0, 0, // call plt+0x20
...@@ -470,28 +470,28 @@ void RetpolinePic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,...@@ -470,28 +470,28 @@ void RetpolinePic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
470 0xe9, 0, 0, 0, 0, // jmp plt+0470 0xe9, 0, 0, 0, 0, // jmp plt+0
471 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding471 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding
472 };472 };
473 memcpy(Buf, Insn, sizeof(Insn));473 memcpy(buf, insn, sizeof(insn));
474474
475 uint32_t Ebx = In.Got->getVA() + In.Got->getSize();475 uint32_t ebx = in.gotPlt->getVA();
476 unsigned Off = getPltEntryOffset(Index);476 unsigned off = pltHeaderSize + pltEntrySize * index;
477 write32le(Buf + 3, GotPltEntryAddr - Ebx);477 write32le(buf + 3, gotPltEntryAddr - ebx);
478 write32le(Buf + 8, -Off - 12 + 32);478 write32le(buf + 8, -off - 12 + 32);
479 write32le(Buf + 13, -Off - 17 + 18);479 write32le(buf + 13, -off - 17 + 18);
480 write32le(Buf + 18, RelOff);480 write32le(buf + 18, relOff);
481 write32le(Buf + 23, -Off - 27);481 write32le(buf + 23, -off - 27);
482}482}
483483
484RetpolineNoPic::RetpolineNoPic() {484RetpolineNoPic::RetpolineNoPic() {
485 PltHeaderSize = 48;485 pltHeaderSize = 48;
486 PltEntrySize = 32;486 pltEntrySize = 32;
487}487}
488488
489void RetpolineNoPic::writeGotPlt(uint8_t *Buf, const Symbol &S) const {489void RetpolineNoPic::writeGotPlt(uint8_t *buf, const Symbol &s) const {
490 write32le(Buf, S.getPltVA() + 16);490 write32le(buf, s.getPltVA() + 16);
491}491}
492492
493void RetpolineNoPic::writePltHeader(uint8_t *Buf) const {493void RetpolineNoPic::writePltHeader(uint8_t *buf) const {
494 const uint8_t Insn[] = {494 const uint8_t insn[] = {
495 0xff, 0x35, 0, 0, 0, 0, // 0: pushl GOTPLT+4495 0xff, 0x35, 0, 0, 0, 0, // 0: pushl GOTPLT+4
496 0x50, // 6: pushl %eax496 0x50, // 6: pushl %eax
497 0xa1, 0, 0, 0, 0, // 7: mov GOTPLT+8, %eax497 0xa1, 0, 0, 0, 0, // 7: mov GOTPLT+8, %eax
...@@ -509,17 +509,17 @@ void RetpolineNoPic::writePltHeader(uint8_t *Buf) const {...@@ -509,17 +509,17 @@ void RetpolineNoPic::writePltHeader(uint8_t *Buf) const {
509 0xc3, // 2e: ret509 0xc3, // 2e: ret
510 0xcc, // 2f: int3; padding510 0xcc, // 2f: int3; padding
511 };511 };
512 memcpy(Buf, Insn, sizeof(Insn));512 memcpy(buf, insn, sizeof(insn));
513513
514 uint32_t GotPlt = In.GotPlt->getVA();514 uint32_t gotPlt = in.gotPlt->getVA();
515 write32le(Buf + 2, GotPlt + 4);515 write32le(buf + 2, gotPlt + 4);
516 write32le(Buf + 8, GotPlt + 8);516 write32le(buf + 8, gotPlt + 8);
517}517}
518518
519void RetpolineNoPic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,519void RetpolineNoPic::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
520 uint64_t PltEntryAddr, int32_t Index,520 uint64_t pltEntryAddr, int32_t index,
521 unsigned RelOff) const {521 unsigned relOff) const {
522 const uint8_t Insn[] = {522 const uint8_t insn[] = {
523 0x50, // 0: pushl %eax523 0x50, // 0: pushl %eax
524 0xa1, 0, 0, 0, 0, // 1: mov foo_in_GOT, %eax524 0xa1, 0, 0, 0, 0, // 1: mov foo_in_GOT, %eax
525 0xe8, 0, 0, 0, 0, // 6: call plt+0x20525 0xe8, 0, 0, 0, 0, // 6: call plt+0x20
...@@ -529,26 +529,26 @@ void RetpolineNoPic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,...@@ -529,26 +529,26 @@ void RetpolineNoPic::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
529 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding529 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding
530 0xcc, // 1f: int3; padding530 0xcc, // 1f: int3; padding
531 };531 };
532 memcpy(Buf, Insn, sizeof(Insn));532 memcpy(buf, insn, sizeof(insn));
533533
534 unsigned Off = getPltEntryOffset(Index);534 unsigned off = pltHeaderSize + pltEntrySize * index;
535 write32le(Buf + 2, GotPltEntryAddr);535 write32le(buf + 2, gotPltEntryAddr);
536 write32le(Buf + 7, -Off - 11 + 32);536 write32le(buf + 7, -off - 11 + 32);
537 write32le(Buf + 12, -Off - 16 + 17);537 write32le(buf + 12, -off - 16 + 17);
538 write32le(Buf + 17, RelOff);538 write32le(buf + 17, relOff);
539 write32le(Buf + 22, -Off - 26);539 write32le(buf + 22, -off - 26);
540}540}
541541
542TargetInfo *elf::getX86TargetInfo() {542TargetInfo *elf::getX86TargetInfo() {
543 if (Config->ZRetpolineplt) {543 if (config->zRetpolineplt) {
544 if (Config->Pic) {544 if (config->isPic) {
545 static RetpolinePic T;545 static RetpolinePic t;
546 return &T;546 return &t;
547 }547 }
548 static RetpolineNoPic T;548 static RetpolineNoPic t;
549 return &T;549 return &t;
550 }550 }
551551
552 static X86 T;552 static X86 t;
553 return &T;553 return &t;
554}554}
deps/lld/ELF/Arch/X86_64.cpp+323-299
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- X86_64.cpp ---------------------------------------------------------===//1//===- X86_64.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -23,71 +22,74 @@ using namespace lld;...@@ -23,71 +22,74 @@ using namespace lld;
23using namespace lld::elf;22using namespace lld::elf;
2423
25namespace {24namespace {
26template <class ELFT> class X86_64 : public TargetInfo {25class X86_64 : public TargetInfo {
27public:26public:
28 X86_64();27 X86_64();
29 RelExpr getRelExpr(RelType Type, const Symbol &S,28 int getTlsGdRelaxSkip(RelType type) const override;
30 const uint8_t *Loc) const override;29 RelExpr getRelExpr(RelType type, const Symbol &s,
31 RelType getDynRel(RelType Type) const override;30 const uint8_t *loc) const override;
32 void writeGotPltHeader(uint8_t *Buf) const override;31 RelType getDynRel(RelType type) const override;
33 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;32 void writeGotPltHeader(uint8_t *buf) const override;
34 void writePltHeader(uint8_t *Buf) const override;33 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
35 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,34 void writePltHeader(uint8_t *buf) const override;
36 int32_t Index, unsigned RelOff) const override;35 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
37 void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const override;36 int32_t index, unsigned relOff) const override;
3837 void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
39 RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,38
40 RelExpr Expr) const override;39 RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
41 void relaxGot(uint8_t *Loc, uint64_t Val) const override;40 RelExpr expr) const override;
42 void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const override;41 void relaxGot(uint8_t *loc, RelType type, uint64_t val) const override;
43 void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;42 void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const override;
44 void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;43 void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
45 void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const override;44 void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const override;
46 bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End,45 void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const override;
47 uint8_t StOther) const override;46 bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
4847 uint8_t stOther) const override;
49private:
50 void relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
51 uint8_t ModRm) const;
52};48};
53} // namespace49} // namespace
5450
55template <class ELFT> X86_64<ELFT>::X86_64() {51X86_64::X86_64() {
56 CopyRel = R_X86_64_COPY;52 copyRel = R_X86_64_COPY;
57 GotRel = R_X86_64_GLOB_DAT;53 gotRel = R_X86_64_GLOB_DAT;
58 NoneRel = R_X86_64_NONE;54 noneRel = R_X86_64_NONE;
59 PltRel = R_X86_64_JUMP_SLOT;55 pltRel = R_X86_64_JUMP_SLOT;
60 RelativeRel = R_X86_64_RELATIVE;56 relativeRel = R_X86_64_RELATIVE;
61 IRelativeRel = R_X86_64_IRELATIVE;57 iRelativeRel = R_X86_64_IRELATIVE;
62 TlsGotRel = R_X86_64_TPOFF64;58 symbolicRel = R_X86_64_64;
63 TlsModuleIndexRel = R_X86_64_DTPMOD64;59 tlsDescRel = R_X86_64_TLSDESC;
64 TlsOffsetRel = R_X86_64_DTPOFF64;60 tlsGotRel = R_X86_64_TPOFF64;
65 GotEntrySize = 8;61 tlsModuleIndexRel = R_X86_64_DTPMOD64;
66 GotPltEntrySize = 8;62 tlsOffsetRel = R_X86_64_DTPOFF64;
67 PltEntrySize = 16;63 pltEntrySize = 16;
68 PltHeaderSize = 16;64 pltHeaderSize = 16;
69 TlsGdRelaxSkip = 2;65 trapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3
70 TrapInstr = {0xcc, 0xcc, 0xcc, 0xcc}; // 0xcc = INT3
7166
72 // Align to the large page size (known as a superpage or huge page).67 // Align to the large page size (known as a superpage or huge page).
73 // FreeBSD automatically promotes large, superpage-aligned allocations.68 // FreeBSD automatically promotes large, superpage-aligned allocations.
74 DefaultImageBase = 0x200000;69 defaultImageBase = 0x200000;
75}70}
7671
77template <class ELFT>72int X86_64::getTlsGdRelaxSkip(RelType type) const { return 2; }
78RelExpr X86_64<ELFT>::getRelExpr(RelType Type, const Symbol &S,73
79 const uint8_t *Loc) const {74RelExpr X86_64::getRelExpr(RelType type, const Symbol &s,
80 switch (Type) {75 const uint8_t *loc) const {
76 if (type == R_X86_64_GOTTPOFF)
77 config->hasStaticTlsModel = true;
78
79 switch (type) {
81 case R_X86_64_8:80 case R_X86_64_8:
82 case R_X86_64_16:81 case R_X86_64_16:
83 case R_X86_64_32:82 case R_X86_64_32:
84 case R_X86_64_32S:83 case R_X86_64_32S:
85 case R_X86_64_64:84 case R_X86_64_64:
85 return R_ABS;
86 case R_X86_64_DTPOFF32:86 case R_X86_64_DTPOFF32:
87 case R_X86_64_DTPOFF64:87 case R_X86_64_DTPOFF64:
88 return R_ABS;88 return R_DTPREL;
89 case R_X86_64_TPOFF32:89 case R_X86_64_TPOFF32:
90 return R_TLS;90 return R_TLS;
91 case R_X86_64_TLSDESC_CALL:
92 return R_TLSDESC_CALL;
91 case R_X86_64_TLSLD:93 case R_X86_64_TLSLD:
92 return R_TLSLD_PC;94 return R_TLSLD_PC;
93 case R_X86_64_TLSGD:95 case R_X86_64_TLSGD:
...@@ -97,189 +99,222 @@ RelExpr X86_64<ELFT>::getRelExpr(RelType Type, const Symbol &S,...@@ -97,189 +99,222 @@ RelExpr X86_64<ELFT>::getRelExpr(RelType Type, const Symbol &S,
97 return R_SIZE;99 return R_SIZE;
98 case R_X86_64_PLT32:100 case R_X86_64_PLT32:
99 return R_PLT_PC;101 return R_PLT_PC;
102 case R_X86_64_PC8:
103 case R_X86_64_PC16:
100 case R_X86_64_PC32:104 case R_X86_64_PC32:
101 case R_X86_64_PC64:105 case R_X86_64_PC64:
102 return R_PC;106 return R_PC;
103 case R_X86_64_GOT32:107 case R_X86_64_GOT32:
104 case R_X86_64_GOT64:108 case R_X86_64_GOT64:
105 return R_GOT_FROM_END;109 return R_GOTPLT;
110 case R_X86_64_GOTPC32_TLSDESC:
111 return R_TLSDESC_PC;
106 case R_X86_64_GOTPCREL:112 case R_X86_64_GOTPCREL:
107 case R_X86_64_GOTPCRELX:113 case R_X86_64_GOTPCRELX:
108 case R_X86_64_REX_GOTPCRELX:114 case R_X86_64_REX_GOTPCRELX:
109 case R_X86_64_GOTTPOFF:115 case R_X86_64_GOTTPOFF:
110 return R_GOT_PC;116 return R_GOT_PC;
111 case R_X86_64_GOTOFF64:117 case R_X86_64_GOTOFF64:
112 return R_GOTREL_FROM_END;118 return R_GOTPLTREL;
113 case R_X86_64_GOTPC32:119 case R_X86_64_GOTPC32:
114 case R_X86_64_GOTPC64:120 case R_X86_64_GOTPC64:
115 return R_GOTONLY_PC_FROM_END;121 return R_GOTPLTONLY_PC;
116 case R_X86_64_NONE:122 case R_X86_64_NONE:
117 return R_NONE;123 return R_NONE;
118 default:124 default:
119 return R_INVALID;125 error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
126 ") against symbol " + toString(s));
127 return R_NONE;
120 }128 }
121}129}
122130
123template <class ELFT> void X86_64<ELFT>::writeGotPltHeader(uint8_t *Buf) const {131void X86_64::writeGotPltHeader(uint8_t *buf) const {
124 // The first entry holds the value of _DYNAMIC. It is not clear why that is132 // The first entry holds the value of _DYNAMIC. It is not clear why that is
125 // required, but it is documented in the psabi and the glibc dynamic linker133 // required, but it is documented in the psabi and the glibc dynamic linker
126 // seems to use it (note that this is relevant for linking ld.so, not any134 // seems to use it (note that this is relevant for linking ld.so, not any
127 // other program).135 // other program).
128 write64le(Buf, In.Dynamic->getVA());136 write64le(buf, mainPart->dynamic->getVA());
129}137}
130138
131template <class ELFT>139void X86_64::writeGotPlt(uint8_t *buf, const Symbol &s) const {
132void X86_64<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {
133 // See comments in X86::writeGotPlt.140 // See comments in X86::writeGotPlt.
134 write64le(Buf, S.getPltVA() + 6);141 write64le(buf, s.getPltVA() + 6);
135}142}
136143
137template <class ELFT> void X86_64<ELFT>::writePltHeader(uint8_t *Buf) const {144void X86_64::writePltHeader(uint8_t *buf) const {
138 const uint8_t PltData[] = {145 const uint8_t pltData[] = {
139 0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)146 0xff, 0x35, 0, 0, 0, 0, // pushq GOTPLT+8(%rip)
140 0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)147 0xff, 0x25, 0, 0, 0, 0, // jmp *GOTPLT+16(%rip)
141 0x0f, 0x1f, 0x40, 0x00, // nop148 0x0f, 0x1f, 0x40, 0x00, // nop
142 };149 };
143 memcpy(Buf, PltData, sizeof(PltData));150 memcpy(buf, pltData, sizeof(pltData));
144 uint64_t GotPlt = In.GotPlt->getVA();151 uint64_t gotPlt = in.gotPlt->getVA();
145 uint64_t Plt = In.Plt->getVA();152 uint64_t plt = in.plt->getVA();
146 write32le(Buf + 2, GotPlt - Plt + 2); // GOTPLT+8153 write32le(buf + 2, gotPlt - plt + 2); // GOTPLT+8
147 write32le(Buf + 8, GotPlt - Plt + 4); // GOTPLT+16154 write32le(buf + 8, gotPlt - plt + 4); // GOTPLT+16
148}155}
149156
150template <class ELFT>157void X86_64::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
151void X86_64<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,158 uint64_t pltEntryAddr, int32_t index,
152 uint64_t PltEntryAddr, int32_t Index,159 unsigned relOff) const {
153 unsigned RelOff) const {160 const uint8_t inst[] = {
154 const uint8_t Inst[] = {
155 0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)161 0xff, 0x25, 0, 0, 0, 0, // jmpq *got(%rip)
156 0x68, 0, 0, 0, 0, // pushq <relocation index>162 0x68, 0, 0, 0, 0, // pushq <relocation index>
157 0xe9, 0, 0, 0, 0, // jmpq plt[0]163 0xe9, 0, 0, 0, 0, // jmpq plt[0]
158 };164 };
159 memcpy(Buf, Inst, sizeof(Inst));165 memcpy(buf, inst, sizeof(inst));
160166
161 write32le(Buf + 2, GotPltEntryAddr - PltEntryAddr - 6);167 write32le(buf + 2, gotPltEntryAddr - pltEntryAddr - 6);
162 write32le(Buf + 7, Index);168 write32le(buf + 7, index);
163 write32le(Buf + 12, -getPltEntryOffset(Index) - 16);169 write32le(buf + 12, -pltHeaderSize - pltEntrySize * index - 16);
164}170}
165171
166template <class ELFT> RelType X86_64<ELFT>::getDynRel(RelType Type) const {172RelType X86_64::getDynRel(RelType type) const {
167 if (Type == R_X86_64_64 || Type == R_X86_64_PC64 || Type == R_X86_64_SIZE32 ||173 if (type == R_X86_64_64 || type == R_X86_64_PC64 || type == R_X86_64_SIZE32 ||
168 Type == R_X86_64_SIZE64)174 type == R_X86_64_SIZE64)
169 return Type;175 return type;
170 return R_X86_64_NONE;176 return R_X86_64_NONE;
171}177}
172178
173template <class ELFT>179void X86_64::relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const {
174void X86_64<ELFT>::relaxTlsGdToLe(uint8_t *Loc, RelType Type,180 if (type == R_X86_64_TLSGD) {
175 uint64_t Val) const {181 // Convert
176 // Convert182 // .byte 0x66
177 // .byte 0x66183 // leaq x@tlsgd(%rip), %rdi
178 // leaq x@tlsgd(%rip), %rdi184 // .word 0x6666
179 // .word 0x6666185 // rex64
180 // rex64186 // call __tls_get_addr@plt
181 // call __tls_get_addr@plt187 // to the following two instructions.
182 // to188 const uint8_t inst[] = {
183 // mov %fs:0x0,%rax189 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00,
184 // lea x@tpoff,%rax190 0x00, 0x00, // mov %fs:0x0,%rax
185 const uint8_t Inst[] = {191 0x48, 0x8d, 0x80, 0, 0, 0, 0, // lea x@tpoff,%rax
186 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax192 };
187 0x48, 0x8d, 0x80, 0, 0, 0, 0, // lea x@tpoff,%rax193 memcpy(loc - 4, inst, sizeof(inst));
188 };194
189 memcpy(Loc - 4, Inst, sizeof(Inst));195 // The original code used a pc relative relocation and so we have to
190196 // compensate for the -4 in had in the addend.
191 // The original code used a pc relative relocation and so we have to197 write32le(loc + 8, val + 4);
192 // compensate for the -4 in had in the addend.198 } else {
193 write32le(Loc + 8, Val + 4);199 // Convert
200 // lea x@tlsgd(%rip), %rax
201 // call *(%rax)
202 // to the following two instructions.
203 assert(type == R_X86_64_GOTPC32_TLSDESC);
204 if (memcmp(loc - 3, "\x48\x8d\x05", 3)) {
205 error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used "
206 "in callq *x@tlsdesc(%rip), %rax");
207 return;
208 }
209 // movq $x@tpoff(%rip),%rax
210 loc[-2] = 0xc7;
211 loc[-1] = 0xc0;
212 write32le(loc, val + 4);
213 // xchg ax,ax
214 loc[4] = 0x66;
215 loc[5] = 0x90;
216 }
194}217}
195218
196template <class ELFT>219void X86_64::relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const {
197void X86_64<ELFT>::relaxTlsGdToIe(uint8_t *Loc, RelType Type,220 if (type == R_X86_64_TLSGD) {
198 uint64_t Val) const {221 // Convert
199 // Convert222 // .byte 0x66
200 // .byte 0x66223 // leaq x@tlsgd(%rip), %rdi
201 // leaq x@tlsgd(%rip), %rdi224 // .word 0x6666
202 // .word 0x6666225 // rex64
203 // rex64226 // call __tls_get_addr@plt
204 // call __tls_get_addr@plt227 // to the following two instructions.
205 // to228 const uint8_t inst[] = {
206 // mov %fs:0x0,%rax229 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00,
207 // addq x@tpoff,%rax230 0x00, 0x00, // mov %fs:0x0,%rax
208 const uint8_t Inst[] = {231 0x48, 0x03, 0x05, 0, 0, 0, 0, // addq x@gottpoff(%rip),%rax
209 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0x0,%rax232 };
210 0x48, 0x03, 0x05, 0, 0, 0, 0, // addq x@tpoff,%rax233 memcpy(loc - 4, inst, sizeof(inst));
211 };234
212 memcpy(Loc - 4, Inst, sizeof(Inst));235 // Both code sequences are PC relatives, but since we are moving the
213236 // constant forward by 8 bytes we have to subtract the value by 8.
214 // Both code sequences are PC relatives, but since we are moving the constant237 write32le(loc + 8, val - 8);
215 // forward by 8 bytes we have to subtract the value by 8.238 } else {
216 write32le(Loc + 8, Val - 8);239 // Convert
240 // lea x@tlsgd(%rip), %rax
241 // call *(%rax)
242 // to the following two instructions.
243 assert(type == R_X86_64_GOTPC32_TLSDESC);
244 if (memcmp(loc - 3, "\x48\x8d\x05", 3)) {
245 error(getErrorLocation(loc - 3) + "R_X86_64_GOTPC32_TLSDESC must be used "
246 "in callq *x@tlsdesc(%rip), %rax");
247 return;
248 }
249 // movq x@gottpoff(%rip),%rax
250 loc[-2] = 0x8b;
251 write32le(loc, val);
252 // xchg ax,ax
253 loc[4] = 0x66;
254 loc[5] = 0x90;
255 }
217}256}
218257
219// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to258// In some conditions, R_X86_64_GOTTPOFF relocation can be optimized to
220// R_X86_64_TPOFF32 so that it does not use GOT.259// R_X86_64_TPOFF32 so that it does not use GOT.
221template <class ELFT>260void X86_64::relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const {
222void X86_64<ELFT>::relaxTlsIeToLe(uint8_t *Loc, RelType Type,261 uint8_t *inst = loc - 3;
223 uint64_t Val) const {262 uint8_t reg = loc[-1] >> 3;
224 uint8_t *Inst = Loc - 3;263 uint8_t *regSlot = loc - 1;
225 uint8_t Reg = Loc[-1] >> 3;
226 uint8_t *RegSlot = Loc - 1;
227264
228 // Note that ADD with RSP or R12 is converted to ADD instead of LEA265 // Note that ADD with RSP or R12 is converted to ADD instead of LEA
229 // because LEA with these registers needs 4 bytes to encode and thus266 // because LEA with these registers needs 4 bytes to encode and thus
230 // wouldn't fit the space.267 // wouldn't fit the space.
231268
232 if (memcmp(Inst, "\x48\x03\x25", 3) == 0) {269 if (memcmp(inst, "\x48\x03\x25", 3) == 0) {
233 // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp"270 // "addq foo@gottpoff(%rip),%rsp" -> "addq $foo,%rsp"
234 memcpy(Inst, "\x48\x81\xc4", 3);271 memcpy(inst, "\x48\x81\xc4", 3);
235 } else if (memcmp(Inst, "\x4c\x03\x25", 3) == 0) {272 } else if (memcmp(inst, "\x4c\x03\x25", 3) == 0) {
236 // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12"273 // "addq foo@gottpoff(%rip),%r12" -> "addq $foo,%r12"
237 memcpy(Inst, "\x49\x81\xc4", 3);274 memcpy(inst, "\x49\x81\xc4", 3);
238 } else if (memcmp(Inst, "\x4c\x03", 2) == 0) {275 } else if (memcmp(inst, "\x4c\x03", 2) == 0) {
239 // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]"276 // "addq foo@gottpoff(%rip),%r[8-15]" -> "leaq foo(%r[8-15]),%r[8-15]"
240 memcpy(Inst, "\x4d\x8d", 2);277 memcpy(inst, "\x4d\x8d", 2);
241 *RegSlot = 0x80 | (Reg << 3) | Reg;278 *regSlot = 0x80 | (reg << 3) | reg;
242 } else if (memcmp(Inst, "\x48\x03", 2) == 0) {279 } else if (memcmp(inst, "\x48\x03", 2) == 0) {
243 // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg"280 // "addq foo@gottpoff(%rip),%reg -> "leaq foo(%reg),%reg"
244 memcpy(Inst, "\x48\x8d", 2);281 memcpy(inst, "\x48\x8d", 2);
245 *RegSlot = 0x80 | (Reg << 3) | Reg;282 *regSlot = 0x80 | (reg << 3) | reg;
246 } else if (memcmp(Inst, "\x4c\x8b", 2) == 0) {283 } else if (memcmp(inst, "\x4c\x8b", 2) == 0) {
247 // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]"284 // "movq foo@gottpoff(%rip),%r[8-15]" -> "movq $foo,%r[8-15]"
248 memcpy(Inst, "\x49\xc7", 2);285 memcpy(inst, "\x49\xc7", 2);
249 *RegSlot = 0xc0 | Reg;286 *regSlot = 0xc0 | reg;
250 } else if (memcmp(Inst, "\x48\x8b", 2) == 0) {287 } else if (memcmp(inst, "\x48\x8b", 2) == 0) {
251 // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg"288 // "movq foo@gottpoff(%rip),%reg" -> "movq $foo,%reg"
252 memcpy(Inst, "\x48\xc7", 2);289 memcpy(inst, "\x48\xc7", 2);
253 *RegSlot = 0xc0 | Reg;290 *regSlot = 0xc0 | reg;
254 } else {291 } else {
255 error(getErrorLocation(Loc - 3) +292 error(getErrorLocation(loc - 3) +
256 "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only");293 "R_X86_64_GOTTPOFF must be used in MOVQ or ADDQ instructions only");
257 }294 }
258295
259 // The original code used a PC relative relocation.296 // The original code used a PC relative relocation.
260 // Need to compensate for the -4 it had in the addend.297 // Need to compensate for the -4 it had in the addend.
261 write32le(Loc, Val + 4);298 write32le(loc, val + 4);
262}299}
263300
264template <class ELFT>301void X86_64::relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const {
265void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type,302 if (type == R_X86_64_DTPOFF64) {
266 uint64_t Val) const {303 write64le(loc, val);
267 if (Type == R_X86_64_DTPOFF64) {
268 write64le(Loc, Val);
269 return;304 return;
270 }305 }
271 if (Type == R_X86_64_DTPOFF32) {306 if (type == R_X86_64_DTPOFF32) {
272 write32le(Loc, Val);307 write32le(loc, val);
273 return;308 return;
274 }309 }
275310
276 const uint8_t Inst[] = {311 const uint8_t inst[] = {
277 0x66, 0x66, // .word 0x6666312 0x66, 0x66, // .word 0x6666
278 0x66, // .byte 0x66313 0x66, // .byte 0x66
279 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax314 0x64, 0x48, 0x8b, 0x04, 0x25, 0x00, 0x00, 0x00, 0x00, // mov %fs:0,%rax
280 };315 };
281316
282 if (Loc[4] == 0xe8) {317 if (loc[4] == 0xe8) {
283 // Convert318 // Convert
284 // leaq bar@tlsld(%rip), %rdi # 48 8d 3d <Loc>319 // leaq bar@tlsld(%rip), %rdi # 48 8d 3d <Loc>
285 // callq __tls_get_addr@PLT # e8 <disp32>320 // callq __tls_get_addr@PLT # e8 <disp32>
...@@ -289,11 +324,11 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type,...@@ -289,11 +324,11 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type,
289 // .byte 0x66324 // .byte 0x66
290 // mov %fs:0,%rax325 // mov %fs:0,%rax
291 // leaq bar@tpoff(%rax), %rcx326 // leaq bar@tpoff(%rax), %rcx
292 memcpy(Loc - 3, Inst, sizeof(Inst));327 memcpy(loc - 3, inst, sizeof(inst));
293 return;328 return;
294 }329 }
295330
296 if (Loc[4] == 0xff && Loc[5] == 0x15) {331 if (loc[4] == 0xff && loc[5] == 0x15) {
297 // Convert332 // Convert
298 // leaq x@tlsld(%rip),%rdi # 48 8d 3d <Loc>333 // leaq x@tlsld(%rip),%rdi # 48 8d 3d <Loc>
299 // call *__tls_get_addr@GOTPCREL(%rip) # ff 15 <disp32>334 // call *__tls_get_addr@GOTPCREL(%rip) # ff 15 <disp32>
...@@ -302,34 +337,42 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type,...@@ -302,34 +337,42 @@ void X86_64<ELFT>::relaxTlsLdToLe(uint8_t *Loc, RelType Type,
302 // movq %fs:0,%rax337 // movq %fs:0,%rax
303 // See "Table 11.9: LD -> LE Code Transition (LP64)" in338 // 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.pdf339 // https://raw.githubusercontent.com/wiki/hjl-tools/x86-psABI/x86-64-psABI-1.0.pdf
305 Loc[-3] = 0x66;340 loc[-3] = 0x66;
306 memcpy(Loc - 2, Inst, sizeof(Inst));341 memcpy(loc - 2, inst, sizeof(inst));
307 return;342 return;
308 }343 }
309344
310 error(getErrorLocation(Loc - 3) +345 error(getErrorLocation(loc - 3) +
311 "expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD");346 "expected R_X86_64_PLT32 or R_X86_64_GOTPCRELX after R_X86_64_TLSLD");
312}347}
313348
314template <class ELFT>349void X86_64::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
315void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {350 switch (type) {
316 switch (Type) {
317 case R_X86_64_8:351 case R_X86_64_8:
318 checkUInt(Loc, Val, 8, Type);352 checkIntUInt(loc, val, 8, type);
319 *Loc = Val;353 *loc = val;
354 break;
355 case R_X86_64_PC8:
356 checkInt(loc, val, 8, type);
357 *loc = val;
320 break;358 break;
321 case R_X86_64_16:359 case R_X86_64_16:
322 checkUInt(Loc, Val, 16, Type);360 checkIntUInt(loc, val, 16, type);
323 write16le(Loc, Val);361 write16le(loc, val);
362 break;
363 case R_X86_64_PC16:
364 checkInt(loc, val, 16, type);
365 write16le(loc, val);
324 break;366 break;
325 case R_X86_64_32:367 case R_X86_64_32:
326 checkUInt(Loc, Val, 32, Type);368 checkUInt(loc, val, 32, type);
327 write32le(Loc, Val);369 write32le(loc, val);
328 break;370 break;
329 case R_X86_64_32S:371 case R_X86_64_32S:
330 case R_X86_64_TPOFF32:372 case R_X86_64_TPOFF32:
331 case R_X86_64_GOT32:373 case R_X86_64_GOT32:
332 case R_X86_64_GOTPC32:374 case R_X86_64_GOTPC32:
375 case R_X86_64_GOTPC32_TLSDESC:
333 case R_X86_64_GOTPCREL:376 case R_X86_64_GOTPCREL:
334 case R_X86_64_GOTPCRELX:377 case R_X86_64_GOTPCRELX:
335 case R_X86_64_REX_GOTPCRELX:378 case R_X86_64_REX_GOTPCRELX:
...@@ -340,49 +383,47 @@ void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {...@@ -340,49 +383,47 @@ void X86_64<ELFT>::relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const {
340 case R_X86_64_TLSLD:383 case R_X86_64_TLSLD:
341 case R_X86_64_DTPOFF32:384 case R_X86_64_DTPOFF32:
342 case R_X86_64_SIZE32:385 case R_X86_64_SIZE32:
343 checkInt(Loc, Val, 32, Type);386 checkInt(loc, val, 32, type);
344 write32le(Loc, Val);387 write32le(loc, val);
345 break;388 break;
346 case R_X86_64_64:389 case R_X86_64_64:
347 case R_X86_64_DTPOFF64:390 case R_X86_64_DTPOFF64:
348 case R_X86_64_GLOB_DAT:
349 case R_X86_64_PC64:391 case R_X86_64_PC64:
350 case R_X86_64_SIZE64:392 case R_X86_64_SIZE64:
351 case R_X86_64_GOT64:393 case R_X86_64_GOT64:
352 case R_X86_64_GOTOFF64:394 case R_X86_64_GOTOFF64:
353 case R_X86_64_GOTPC64:395 case R_X86_64_GOTPC64:
354 write64le(Loc, Val);396 write64le(loc, val);
355 break;397 break;
356 default:398 default:
357 error(getErrorLocation(Loc) + "unrecognized reloc " + Twine(Type));399 llvm_unreachable("unknown relocation");
358 }400 }
359}401}
360402
361template <class ELFT>403RelExpr X86_64::adjustRelaxExpr(RelType type, const uint8_t *data,
362RelExpr X86_64<ELFT>::adjustRelaxExpr(RelType Type, const uint8_t *Data,404 RelExpr relExpr) const {
363 RelExpr RelExpr) const {405 if (type != R_X86_64_GOTPCRELX && type != R_X86_64_REX_GOTPCRELX)
364 if (Type != R_X86_64_GOTPCRELX && Type != R_X86_64_REX_GOTPCRELX)406 return relExpr;
365 return RelExpr;407 const uint8_t op = data[-2];
366 const uint8_t Op = Data[-2];408 const uint8_t modRm = data[-1];
367 const uint8_t ModRm = Data[-1];
368409
369 // FIXME: When PIC is disabled and foo is defined locally in the410 // FIXME: When PIC is disabled and foo is defined locally in the
370 // lower 32 bit address space, memory operand in mov can be converted into411 // lower 32 bit address space, memory operand in mov can be converted into
371 // immediate operand. Otherwise, mov must be changed to lea. We support only412 // immediate operand. Otherwise, mov must be changed to lea. We support only
372 // latter relaxation at this moment.413 // latter relaxation at this moment.
373 if (Op == 0x8b)414 if (op == 0x8b)
374 return R_RELAX_GOT_PC;415 return R_RELAX_GOT_PC;
375416
376 // Relax call and jmp.417 // Relax call and jmp.
377 if (Op == 0xff && (ModRm == 0x15 || ModRm == 0x25))418 if (op == 0xff && (modRm == 0x15 || modRm == 0x25))
378 return R_RELAX_GOT_PC;419 return R_RELAX_GOT_PC;
379420
380 // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.421 // Relaxation of test, adc, add, and, cmp, or, sbb, sub, xor.
381 // If PIC then no relaxation is available.422 // If PIC then no relaxation is available.
382 // We also don't relax test/binop instructions without REX byte,423 // We also don't relax test/binop instructions without REX byte,
383 // they are 32bit operations and not common to have.424 // they are 32bit operations and not common to have.
384 assert(Type == R_X86_64_REX_GOTPCRELX);425 assert(type == R_X86_64_REX_GOTPCRELX);
385 return Config->Pic ? RelExpr : R_RELAX_GOT_PC_NOPIC;426 return config->isPic ? relExpr : R_RELAX_GOT_PC_NOPIC;
386}427}
387428
388// A subset of relaxations can only be applied for no-PIC. This method429// A subset of relaxations can only be applied for no-PIC. This method
...@@ -390,12 +431,11 @@ RelExpr X86_64<ELFT>::adjustRelaxExpr(RelType Type, const uint8_t *Data,...@@ -390,12 +431,11 @@ RelExpr X86_64<ELFT>::adjustRelaxExpr(RelType Type, const uint8_t *Data,
390// "Intel 64 and IA-32 Architectures Software Developer's Manual V2"431// "Intel 64 and IA-32 Architectures Software Developer's Manual V2"
391// (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/432// (http://www.intel.com/content/dam/www/public/us/en/documents/manuals/
392// 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf)433// 64-ia-32-architectures-software-developer-instruction-set-reference-manual-325383.pdf)
393template <class ELFT>434static void relaxGotNoPic(uint8_t *loc, uint64_t val, uint8_t op,
394void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,435 uint8_t modRm) {
395 uint8_t ModRm) const {436 const uint8_t rex = loc[-3];
396 const uint8_t Rex = Loc[-3];
397 // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg".437 // Convert "test %reg, foo@GOTPCREL(%rip)" to "test $foo, %reg".
398 if (Op == 0x85) {438 if (op == 0x85) {
399 // See "TEST-Logical Compare" (4-428 Vol. 2B),439 // See "TEST-Logical Compare" (4-428 Vol. 2B),
400 // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension).440 // TEST r/m64, r64 uses "full" ModR / M byte (no opcode extension).
401441
...@@ -412,11 +452,11 @@ void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,...@@ -412,11 +452,11 @@ void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
412 // 0x38 == 00 111 000 binary.452 // 0x38 == 00 111 000 binary.
413 // We transfer reg2 to reg1 here as operand.453 // We transfer reg2 to reg1 here as operand.
414 // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3).454 // See "2.1.3 ModR/M and SIB Bytes" (Vol. 2A 2-3).
415 Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3; // ModR/M byte.455 loc[-1] = 0xc0 | (modRm & 0x38) >> 3; // ModR/M byte.
416456
417 // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32457 // Change opcode from TEST r/m64, r64 to TEST r/m64, imm32
418 // See "TEST-Logical Compare" (4-428 Vol. 2B).458 // See "TEST-Logical Compare" (4-428 Vol. 2B).
419 Loc[-2] = 0xf7;459 loc[-2] = 0xf7;
420460
421 // Move R bit to the B bit in REX byte.461 // Move R bit to the B bit in REX byte.
422 // REX byte is encoded as 0100WRXB, where462 // REX byte is encoded as 0100WRXB, where
...@@ -429,8 +469,8 @@ void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,...@@ -429,8 +469,8 @@ void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
429 // REX.B This 1-bit value is an extension to the MODRM.rm field or the469 // REX.B This 1-bit value is an extension to the MODRM.rm field or the
430 // SIB.base field.470 // SIB.base field.
431 // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A).471 // See "2.2.1.2 More on REX Prefix Fields " (2-8 Vol. 2A).
432 Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;472 loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
433 write32le(Loc, Val);473 write32le(loc, val);
434 return;474 return;
435 }475 }
436476
...@@ -440,7 +480,7 @@ void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,...@@ -440,7 +480,7 @@ void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
440 // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg".480 // Convert "binop foo@GOTPCREL(%rip), %reg" to "binop $foo, %reg".
441 // Logic is close to one for test instruction above, but we also481 // Logic is close to one for test instruction above, but we also
442 // write opcode extension here, see below for details.482 // write opcode extension here, see below for details.
443 Loc[-1] = 0xc0 | (ModRm & 0x38) >> 3 | (Op & 0x3c); // ModR/M byte.483 loc[-1] = 0xc0 | (modRm & 0x38) >> 3 | (op & 0x3c); // ModR/M byte.
444484
445 // Primary opcode is 0x81, opcode extension is one of:485 // Primary opcode is 0x81, opcode extension is one of:
446 // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB,486 // 000b = ADD, 001b is OR, 010b is ADC, 011b is SBB,
...@@ -449,69 +489,67 @@ void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,...@@ -449,69 +489,67 @@ void X86_64<ELFT>::relaxGotNoPic(uint8_t *Loc, uint64_t Val, uint8_t Op,
449 // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15),489 // See "3.2 INSTRUCTIONS (A-M)" (Vol. 2A 3-15),
450 // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for490 // "INSTRUCTION SET REFERENCE, N-Z" (Vol. 2B 4-1) for
451 // descriptions about each operation.491 // descriptions about each operation.
452 Loc[-2] = 0x81;492 loc[-2] = 0x81;
453 Loc[-3] = (Rex & ~0x4) | (Rex & 0x4) >> 2;493 loc[-3] = (rex & ~0x4) | (rex & 0x4) >> 2;
454 write32le(Loc, Val);494 write32le(loc, val);
455}495}
456496
457template <class ELFT>497void X86_64::relaxGot(uint8_t *loc, RelType type, uint64_t val) const {
458void X86_64<ELFT>::relaxGot(uint8_t *Loc, uint64_t Val) const {498 const uint8_t op = loc[-2];
459 const uint8_t Op = Loc[-2];499 const uint8_t modRm = loc[-1];
460 const uint8_t ModRm = Loc[-1];
461500
462 // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg".501 // Convert "mov foo@GOTPCREL(%rip),%reg" to "lea foo(%rip),%reg".
463 if (Op == 0x8b) {502 if (op == 0x8b) {
464 Loc[-2] = 0x8d;503 loc[-2] = 0x8d;
465 write32le(Loc, Val);504 write32le(loc, val);
466 return;505 return;
467 }506 }
468507
469 if (Op != 0xff) {508 if (op != 0xff) {
470 // We are relaxing a rip relative to an absolute, so compensate509 // We are relaxing a rip relative to an absolute, so compensate
471 // for the old -4 addend.510 // for the old -4 addend.
472 assert(!Config->Pic);511 assert(!config->isPic);
473 relaxGotNoPic(Loc, Val + 4, Op, ModRm);512 relaxGotNoPic(loc, val + 4, op, modRm);
474 return;513 return;
475 }514 }
476515
477 // Convert call/jmp instructions.516 // Convert call/jmp instructions.
478 if (ModRm == 0x15) {517 if (modRm == 0x15) {
479 // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo".518 // ABI says we can convert "call *foo@GOTPCREL(%rip)" to "nop; call foo".
480 // Instead we convert to "addr32 call foo" where addr32 is an instruction519 // Instead we convert to "addr32 call foo" where addr32 is an instruction
481 // prefix. That makes result expression to be a single instruction.520 // prefix. That makes result expression to be a single instruction.
482 Loc[-2] = 0x67; // addr32 prefix521 loc[-2] = 0x67; // addr32 prefix
483 Loc[-1] = 0xe8; // call522 loc[-1] = 0xe8; // call
484 write32le(Loc, Val);523 write32le(loc, val);
485 return;524 return;
486 }525 }
487526
488 // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop".527 // Convert "jmp *foo@GOTPCREL(%rip)" to "jmp foo; nop".
489 // jmp doesn't return, so it is fine to use nop here, it is just a stub.528 // jmp doesn't return, so it is fine to use nop here, it is just a stub.
490 assert(ModRm == 0x25);529 assert(modRm == 0x25);
491 Loc[-2] = 0xe9; // jmp530 loc[-2] = 0xe9; // jmp
492 Loc[3] = 0x90; // nop531 loc[3] = 0x90; // nop
493 write32le(Loc - 1, Val + 1);532 write32le(loc - 1, val + 1);
494}533}
495534
496// This anonymous namespace works around a warning bug in
497// old versions of gcc. See https://gcc.gnu.org/bugzilla/show_bug.cgi?id=56480
498namespace {
499
500// A split-stack prologue starts by checking the amount of stack remaining535// A split-stack prologue starts by checking the amount of stack remaining
501// in one of two ways:536// in one of two ways:
502// A) Comparing of the stack pointer to a field in the tcb.537// A) Comparing of the stack pointer to a field in the tcb.
503// B) Or a load of a stack pointer offset with an lea to r10 or r11.538// B) Or a load of a stack pointer offset with an lea to r10 or r11.
504template <>539bool X86_64::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
505bool X86_64<ELF64LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,540 uint8_t stOther) const {
506 uint8_t *End,541 if (!config->is64) {
507 uint8_t StOther) const {542 error("Target doesn't support split stacks.");
508 if (Loc + 8 >= End)543 return false;
544 }
545
546 if (loc + 8 >= end)
509 return false;547 return false;
510548
511 // Replace "cmp %fs:0x70,%rsp" and subsequent branch549 // Replace "cmp %fs:0x70,%rsp" and subsequent branch
512 // with "stc, nopl 0x0(%rax,%rax,1)"550 // with "stc, nopl 0x0(%rax,%rax,1)"
513 if (memcmp(Loc, "\x64\x48\x3b\x24\x25", 5) == 0) {551 if (memcmp(loc, "\x64\x48\x3b\x24\x25", 5) == 0) {
514 memcpy(Loc, "\xf9\x0f\x1f\x84\x00\x00\x00\x00", 8);552 memcpy(loc, "\xf9\x0f\x1f\x84\x00\x00\x00\x00", 8);
515 return true;553 return true;
516 }554 }
517555
...@@ -519,25 +557,16 @@ bool X86_64<ELF64LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,...@@ -519,25 +557,16 @@ bool X86_64<ELF64LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,
519 // be r10 or r11. The lea instruction feeds a subsequent compare which checks557 // 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 reserves558 // 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.559 // that much additional space. The stack grows downward so subtract the value.
522 if (memcmp(Loc, "\x4c\x8d\x94\x24", 4) == 0 ||560 if (memcmp(loc, "\x4c\x8d\x94\x24", 4) == 0 ||
523 memcmp(Loc, "\x4c\x8d\x9c\x24", 4) == 0) {561 memcmp(loc, "\x4c\x8d\x9c\x24", 4) == 0) {
524 // The offset bytes are encoded four bytes after the start of the562 // The offset bytes are encoded four bytes after the start of the
525 // instruction.563 // instruction.
526 write32le(Loc + 4, read32le(Loc + 4) - 0x4000);564 write32le(loc + 4, read32le(loc + 4) - 0x4000);
527 return true;565 return true;
528 }566 }
529 return false;567 return false;
530}568}
531569
532template <>
533bool X86_64<ELF32LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,
534 uint8_t *End,
535 uint8_t StOther) const {
536 llvm_unreachable("Target doesn't support split stacks.");
537}
538
539} // namespace
540
541// These nonstandard PLT entries are to migtigate Spectre v2 security570// These nonstandard PLT entries are to migtigate Spectre v2 security
542// vulnerability. In order to mitigate Spectre v2, we want to avoid indirect571// vulnerability. In order to mitigate Spectre v2, we want to avoid indirect
543// branch instructions such as `jmp *GOTPLT(%rip)`. So, in the following PLT572// branch instructions such as `jmp *GOTPLT(%rip)`. So, in the following PLT
...@@ -548,37 +577,36 @@ bool X86_64<ELF32LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,...@@ -548,37 +577,36 @@ bool X86_64<ELF32LE>::adjustPrologueForCrossSplitStack(uint8_t *Loc,
548// is specified, all dynamic symbols are resolved at load-time. Thus, when577// is specified, all dynamic symbols are resolved at load-time. Thus, when
549// that option is given, we can omit code for symbol lazy resolution.578// that option is given, we can omit code for symbol lazy resolution.
550namespace {579namespace {
551template <class ELFT> class Retpoline : public X86_64<ELFT> {580class Retpoline : public X86_64 {
552public:581public:
553 Retpoline();582 Retpoline();
554 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override;583 void writeGotPlt(uint8_t *buf, const Symbol &s) const override;
555 void writePltHeader(uint8_t *Buf) const override;584 void writePltHeader(uint8_t *buf) const override;
556 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,585 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
557 int32_t Index, unsigned RelOff) const override;586 int32_t index, unsigned relOff) const override;
558};587};
559588
560template <class ELFT> class RetpolineZNow : public X86_64<ELFT> {589class RetpolineZNow : public X86_64 {
561public:590public:
562 RetpolineZNow();591 RetpolineZNow();
563 void writeGotPlt(uint8_t *Buf, const Symbol &S) const override {}592 void writeGotPlt(uint8_t *buf, const Symbol &s) const override {}
564 void writePltHeader(uint8_t *Buf) const override;593 void writePltHeader(uint8_t *buf) const override;
565 void writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr, uint64_t PltEntryAddr,594 void writePlt(uint8_t *buf, uint64_t gotPltEntryAddr, uint64_t pltEntryAddr,
566 int32_t Index, unsigned RelOff) const override;595 int32_t index, unsigned relOff) const override;
567};596};
568} // namespace597} // namespace
569598
570template <class ELFT> Retpoline<ELFT>::Retpoline() {599Retpoline::Retpoline() {
571 TargetInfo::PltHeaderSize = 48;600 pltHeaderSize = 48;
572 TargetInfo::PltEntrySize = 32;601 pltEntrySize = 32;
573}602}
574603
575template <class ELFT>604void Retpoline::writeGotPlt(uint8_t *buf, const Symbol &s) const {
576void Retpoline<ELFT>::writeGotPlt(uint8_t *Buf, const Symbol &S) const {605 write64le(buf, s.getPltVA() + 17);
577 write64le(Buf, S.getPltVA() + 17);
578}606}
579607
580template <class ELFT> void Retpoline<ELFT>::writePltHeader(uint8_t *Buf) const {608void Retpoline::writePltHeader(uint8_t *buf) const {
581 const uint8_t Insn[] = {609 const uint8_t insn[] = {
582 0xff, 0x35, 0, 0, 0, 0, // 0: pushq GOTPLT+8(%rip)610 0xff, 0x35, 0, 0, 0, 0, // 0: pushq GOTPLT+8(%rip)
583 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 6: mov GOTPLT+16(%rip), %r11611 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 6: mov GOTPLT+16(%rip), %r11
584 0xe8, 0x0e, 0x00, 0x00, 0x00, // d: callq next612 0xe8, 0x0e, 0x00, 0x00, 0x00, // d: callq next
...@@ -591,19 +619,18 @@ template <class ELFT> void Retpoline<ELFT>::writePltHeader(uint8_t *Buf) const {...@@ -591,19 +619,18 @@ template <class ELFT> void Retpoline<ELFT>::writePltHeader(uint8_t *Buf) const {
591 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 25: int3; padding619 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 25: int3; padding
592 0xcc, 0xcc, 0xcc, 0xcc, // 2c: int3; padding620 0xcc, 0xcc, 0xcc, 0xcc, // 2c: int3; padding
593 };621 };
594 memcpy(Buf, Insn, sizeof(Insn));622 memcpy(buf, insn, sizeof(insn));
595623
596 uint64_t GotPlt = In.GotPlt->getVA();624 uint64_t gotPlt = in.gotPlt->getVA();
597 uint64_t Plt = In.Plt->getVA();625 uint64_t plt = in.plt->getVA();
598 write32le(Buf + 2, GotPlt - Plt - 6 + 8);626 write32le(buf + 2, gotPlt - plt - 6 + 8);
599 write32le(Buf + 9, GotPlt - Plt - 13 + 16);627 write32le(buf + 9, gotPlt - plt - 13 + 16);
600}628}
601629
602template <class ELFT>630void Retpoline::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
603void Retpoline<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,631 uint64_t pltEntryAddr, int32_t index,
604 uint64_t PltEntryAddr, int32_t Index,632 unsigned relOff) const {
605 unsigned RelOff) const {633 const uint8_t insn[] = {
606 const uint8_t Insn[] = {
607 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 0: mov foo@GOTPLT(%rip), %r11634 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // 0: mov foo@GOTPLT(%rip), %r11
608 0xe8, 0, 0, 0, 0, // 7: callq plt+0x20635 0xe8, 0, 0, 0, 0, // 7: callq plt+0x20
609 0xe9, 0, 0, 0, 0, // c: jmp plt+0x12636 0xe9, 0, 0, 0, 0, // c: jmp plt+0x12
...@@ -611,25 +638,24 @@ void Retpoline<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,...@@ -611,25 +638,24 @@ void Retpoline<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,
611 0xe9, 0, 0, 0, 0, // 16: jmp plt+0638 0xe9, 0, 0, 0, 0, // 16: jmp plt+0
612 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1b: int3; padding639 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1b: int3; padding
613 };640 };
614 memcpy(Buf, Insn, sizeof(Insn));641 memcpy(buf, insn, sizeof(insn));
615642
616 uint64_t Off = getPltEntryOffset(Index);643 uint64_t off = pltHeaderSize + pltEntrySize * index;
617644
618 write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);645 write32le(buf + 3, gotPltEntryAddr - pltEntryAddr - 7);
619 write32le(Buf + 8, -Off - 12 + 32);646 write32le(buf + 8, -off - 12 + 32);
620 write32le(Buf + 13, -Off - 17 + 18);647 write32le(buf + 13, -off - 17 + 18);
621 write32le(Buf + 18, Index);648 write32le(buf + 18, index);
622 write32le(Buf + 23, -Off - 27);649 write32le(buf + 23, -off - 27);
623}650}
624651
625template <class ELFT> RetpolineZNow<ELFT>::RetpolineZNow() {652RetpolineZNow::RetpolineZNow() {
626 TargetInfo::PltHeaderSize = 32;653 pltHeaderSize = 32;
627 TargetInfo::PltEntrySize = 16;654 pltEntrySize = 16;
628}655}
629656
630template <class ELFT>657void RetpolineZNow::writePltHeader(uint8_t *buf) const {
631void RetpolineZNow<ELFT>::writePltHeader(uint8_t *Buf) const {658 const uint8_t insn[] = {
632 const uint8_t Insn[] = {
633 0xe8, 0x0b, 0x00, 0x00, 0x00, // 0: call next659 0xe8, 0x0b, 0x00, 0x00, 0x00, // 0: call next
634 0xf3, 0x90, // 5: loop: pause660 0xf3, 0x90, // 5: loop: pause
635 0x0f, 0xae, 0xe8, // 7: lfence661 0x0f, 0xae, 0xe8, // 7: lfence
...@@ -641,37 +667,35 @@ void RetpolineZNow<ELFT>::writePltHeader(uint8_t *Buf) const {...@@ -641,37 +667,35 @@ void RetpolineZNow<ELFT>::writePltHeader(uint8_t *Buf) const {
641 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding667 0xcc, 0xcc, 0xcc, 0xcc, 0xcc, // 1a: int3; padding
642 0xcc, // 1f: int3; padding668 0xcc, // 1f: int3; padding
643 };669 };
644 memcpy(Buf, Insn, sizeof(Insn));670 memcpy(buf, insn, sizeof(insn));
645}671}
646672
647template <class ELFT>673void RetpolineZNow::writePlt(uint8_t *buf, uint64_t gotPltEntryAddr,
648void RetpolineZNow<ELFT>::writePlt(uint8_t *Buf, uint64_t GotPltEntryAddr,674 uint64_t pltEntryAddr, int32_t index,
649 uint64_t PltEntryAddr, int32_t Index,675 unsigned relOff) const {
650 unsigned RelOff) const {676 const uint8_t insn[] = {
651 const uint8_t Insn[] = {
652 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // mov foo@GOTPLT(%rip), %r11677 0x4c, 0x8b, 0x1d, 0, 0, 0, 0, // mov foo@GOTPLT(%rip), %r11
653 0xe9, 0, 0, 0, 0, // jmp plt+0678 0xe9, 0, 0, 0, 0, // jmp plt+0
654 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding679 0xcc, 0xcc, 0xcc, 0xcc, // int3; padding
655 };680 };
656 memcpy(Buf, Insn, sizeof(Insn));681 memcpy(buf, insn, sizeof(insn));
657682
658 write32le(Buf + 3, GotPltEntryAddr - PltEntryAddr - 7);683 write32le(buf + 3, gotPltEntryAddr - pltEntryAddr - 7);
659 write32le(Buf + 8, -getPltEntryOffset(Index) - 12);684 write32le(buf + 8, -pltHeaderSize - pltEntrySize * index - 12);
660}685}
661686
662template <class ELFT> static TargetInfo *getTargetInfo() {687static TargetInfo *getTargetInfo() {
663 if (Config->ZRetpolineplt) {688 if (config->zRetpolineplt) {
664 if (Config->ZNow) {689 if (config->zNow) {
665 static RetpolineZNow<ELFT> T;690 static RetpolineZNow t;
666 return &T;691 return &t;
667 }692 }
668 static Retpoline<ELFT> T;693 static Retpoline t;
669 return &T;694 return &t;
670 }695 }
671696
672 static X86_64<ELFT> T;697 static X86_64 t;
673 return &T;698 return &t;
674}699}
675700
676TargetInfo *elf::getX32TargetInfo() { return getTargetInfo<ELF32LE>(); }701TargetInfo *elf::getX86_64TargetInfo() { return getTargetInfo(); }
677TargetInfo *elf::getX86_64TargetInfo() { return getTargetInfo<ELF64LE>(); }
deps/lld/ELF/Bits.h deleted-35
...@@ -1,35 +0,0 @@
1//===- Bits.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_BITS_H
11#define LLD_ELF_BITS_H
12
13#include "Config.h"
14#include "llvm/Support/Endian.h"
15
16namespace lld {
17namespace elf {
18
19inline uint64_t readUint(uint8_t *Buf) {
20 if (Config->Is64)
21 return llvm::support::endian::read64(Buf, Config->Endianness);
22 return llvm::support::endian::read32(Buf, Config->Endianness);
23}
24
25inline void writeUint(uint8_t *Buf, uint64_t Val) {
26 if (Config->Is64)
27 llvm::support::endian::write64(Buf, Val, Config->Endianness);
28 else
29 llvm::support::endian::write32(Buf, Val, Config->Endianness);
30}
31
32} // namespace elf
33} // namespace lld
34
35#endif
deps/lld/ELF/CMakeLists.txt-1
...@@ -27,7 +27,6 @@ add_lld_library(lldELF...@@ -27,7 +27,6 @@ add_lld_library(lldELF
27 Driver.cpp27 Driver.cpp
28 DriverUtils.cpp28 DriverUtils.cpp
29 EhFrame.cpp29 EhFrame.cpp
30 Filesystem.cpp
31 ICF.cpp30 ICF.cpp
32 InputFiles.cpp31 InputFiles.cpp
33 InputSection.cpp32 InputSection.cpp
deps/lld/ELF/CallGraphSort.cpp+102-83
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- CallGraphSort.cpp --------------------------------------------------===//1//===- CallGraphSort.cpp --------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9///8///
...@@ -52,24 +51,24 @@ using namespace lld::elf;...@@ -52,24 +51,24 @@ using namespace lld::elf;
5251
53namespace {52namespace {
54struct Edge {53struct Edge {
55 int From;54 int from;
56 uint64_t Weight;55 uint64_t weight;
57};56};
5857
59struct Cluster {58struct Cluster {
60 Cluster(int Sec, size_t S) : Sections{Sec}, Size(S) {}59 Cluster(int sec, size_t s) : sections{sec}, size(s) {}
6160
62 double getDensity() const {61 double getDensity() const {
63 if (Size == 0)62 if (size == 0)
64 return 0;63 return 0;
65 return double(Weight) / double(Size);64 return double(weight) / double(size);
66 }65 }
6766
68 std::vector<int> Sections;67 std::vector<int> sections;
69 size_t Size = 0;68 size_t size = 0;
70 uint64_t Weight = 0;69 uint64_t weight = 0;
71 uint64_t InitialWeight = 0;70 uint64_t initialWeight = 0;
72 Edge BestPred = {-1, 0};71 Edge bestPred = {-1, 0};
73};72};
7473
75class CallGraphSort {74class CallGraphSort {
...@@ -79,8 +78,8 @@ public:...@@ -79,8 +78,8 @@ public:
79 DenseMap<const InputSectionBase *, int> run();78 DenseMap<const InputSectionBase *, int> run();
8079
81private:80private:
82 std::vector<Cluster> Clusters;81 std::vector<Cluster> clusters;
83 std::vector<const InputSectionBase *> Sections;82 std::vector<const InputSectionBase *> sections;
8483
85 void groupClusters();84 void groupClusters();
86};85};
...@@ -93,30 +92,30 @@ constexpr int MAX_DENSITY_DEGRADATION = 8;...@@ -93,30 +92,30 @@ constexpr int MAX_DENSITY_DEGRADATION = 8;
93constexpr uint64_t MAX_CLUSTER_SIZE = 1024 * 1024;92constexpr uint64_t MAX_CLUSTER_SIZE = 1024 * 1024;
94} // end anonymous namespace93} // end anonymous namespace
9594
96typedef std::pair<const InputSectionBase *, const InputSectionBase *>95using SectionPair =
97 SectionPair;96 std::pair<const InputSectionBase *, const InputSectionBase *>;
9897
99// Take the edge list in Config->CallGraphProfile, resolve symbol names to98// Take the edge list in Config->CallGraphProfile, resolve symbol names to
100// Symbols, and generate a graph between InputSections with the provided99// Symbols, and generate a graph between InputSections with the provided
101// weights.100// weights.
102CallGraphSort::CallGraphSort() {101CallGraphSort::CallGraphSort() {
103 MapVector<SectionPair, uint64_t> &Profile = Config->CallGraphProfile;102 MapVector<SectionPair, uint64_t> &profile = config->callGraphProfile;
104 DenseMap<const InputSectionBase *, int> SecToCluster;103 DenseMap<const InputSectionBase *, int> secToCluster;
105104
106 auto GetOrCreateNode = [&](const InputSectionBase *IS) -> int {105 auto getOrCreateNode = [&](const InputSectionBase *isec) -> int {
107 auto Res = SecToCluster.insert(std::make_pair(IS, Clusters.size()));106 auto res = secToCluster.insert(std::make_pair(isec, clusters.size()));
108 if (Res.second) {107 if (res.second) {
109 Sections.push_back(IS);108 sections.push_back(isec);
110 Clusters.emplace_back(Clusters.size(), IS->getSize());109 clusters.emplace_back(clusters.size(), isec->getSize());
111 }110 }
112 return Res.first->second;111 return res.first->second;
113 };112 };
114113
115 // Create the graph.114 // Create the graph.
116 for (std::pair<SectionPair, uint64_t> &C : Profile) {115 for (std::pair<SectionPair, uint64_t> &c : profile) {
117 const auto *FromSB = cast<InputSectionBase>(C.first.first->Repl);116 const auto *fromSB = cast<InputSectionBase>(c.first.first->repl);
118 const auto *ToSB = cast<InputSectionBase>(C.first.second->Repl);117 const auto *toSB = cast<InputSectionBase>(c.first.second->repl);
119 uint64_t Weight = C.second;118 uint64_t weight = c.second;
120119
121 // Ignore edges between input sections belonging to different output120 // Ignore edges between input sections belonging to different output
122 // sections. This is done because otherwise we would end up with clusters121 // sections. This is done because otherwise we would end up with clusters
...@@ -124,110 +123,130 @@ CallGraphSort::CallGraphSort() {...@@ -124,110 +123,130 @@ CallGraphSort::CallGraphSort() {
124 // output. This messes with the cluster size and density calculations. We123 // output. This messes with the cluster size and density calculations. We
125 // would also end up moving input sections in other output sections without124 // would also end up moving input sections in other output sections without
126 // moving them closer to what calls them.125 // moving them closer to what calls them.
127 if (FromSB->getOutputSection() != ToSB->getOutputSection())126 if (fromSB->getOutputSection() != toSB->getOutputSection())
128 continue;127 continue;
129128
130 int From = GetOrCreateNode(FromSB);129 int from = getOrCreateNode(fromSB);
131 int To = GetOrCreateNode(ToSB);130 int to = getOrCreateNode(toSB);
132131
133 Clusters[To].Weight += Weight;132 clusters[to].weight += weight;
134133
135 if (From == To)134 if (from == to)
136 continue;135 continue;
137136
138 // Remember the best edge.137 // Remember the best edge.
139 Cluster &ToC = Clusters[To];138 Cluster &toC = clusters[to];
140 if (ToC.BestPred.From == -1 || ToC.BestPred.Weight < Weight) {139 if (toC.bestPred.from == -1 || toC.bestPred.weight < weight) {
141 ToC.BestPred.From = From;140 toC.bestPred.from = from;
142 ToC.BestPred.Weight = Weight;141 toC.bestPred.weight = weight;
143 }142 }
144 }143 }
145 for (Cluster &C : Clusters)144 for (Cluster &c : clusters)
146 C.InitialWeight = C.Weight;145 c.initialWeight = c.weight;
147}146}
148147
149// It's bad to merge clusters which would degrade the density too much.148// It's bad to merge clusters which would degrade the density too much.
150static bool isNewDensityBad(Cluster &A, Cluster &B) {149static bool isNewDensityBad(Cluster &a, Cluster &b) {
151 double NewDensity = double(A.Weight + B.Weight) / double(A.Size + B.Size);150 double newDensity = double(a.weight + b.weight) / double(a.size + b.size);
152 return NewDensity < A.getDensity() / MAX_DENSITY_DEGRADATION;151 return newDensity < a.getDensity() / MAX_DENSITY_DEGRADATION;
153}152}
154153
155static void mergeClusters(Cluster &Into, Cluster &From) {154static void mergeClusters(Cluster &into, Cluster &from) {
156 Into.Sections.insert(Into.Sections.end(), From.Sections.begin(),155 into.sections.insert(into.sections.end(), from.sections.begin(),
157 From.Sections.end());156 from.sections.end());
158 Into.Size += From.Size;157 into.size += from.size;
159 Into.Weight += From.Weight;158 into.weight += from.weight;
160 From.Sections.clear();159 from.sections.clear();
161 From.Size = 0;160 from.size = 0;
162 From.Weight = 0;161 from.weight = 0;
163}162}
164163
165// Group InputSections into clusters using the Call-Chain Clustering heuristic164// Group InputSections into clusters using the Call-Chain Clustering heuristic
166// then sort the clusters by density.165// then sort the clusters by density.
167void CallGraphSort::groupClusters() {166void CallGraphSort::groupClusters() {
168 std::vector<int> SortedSecs(Clusters.size());167 std::vector<int> sortedSecs(clusters.size());
169 std::vector<Cluster *> SecToCluster(Clusters.size());168 std::vector<Cluster *> secToCluster(clusters.size());
170169
171 for (size_t I = 0; I < Clusters.size(); ++I) {170 for (size_t i = 0; i < clusters.size(); ++i) {
172 SortedSecs[I] = I;171 sortedSecs[i] = i;
173 SecToCluster[I] = &Clusters[I];172 secToCluster[i] = &clusters[i];
174 }173 }
175174
176 std::stable_sort(SortedSecs.begin(), SortedSecs.end(), [&](int A, int B) {175 llvm::stable_sort(sortedSecs, [&](int a, int b) {
177 return Clusters[B].getDensity() < Clusters[A].getDensity();176 return clusters[a].getDensity() > clusters[b].getDensity();
178 });177 });
179178
180 for (int SI : SortedSecs) {179 for (int si : sortedSecs) {
181 // Clusters[SI] is the same as SecToClusters[SI] here because it has not180 // clusters[si] is the same as secToClusters[si] here because it has not
182 // been merged into another cluster yet.181 // been merged into another cluster yet.
183 Cluster &C = Clusters[SI];182 Cluster &c = clusters[si];
184183
185 // Don't consider merging if the edge is unlikely.184 // Don't consider merging if the edge is unlikely.
186 if (C.BestPred.From == -1 || C.BestPred.Weight * 10 <= C.InitialWeight)185 if (c.bestPred.from == -1 || c.bestPred.weight * 10 <= c.initialWeight)
187 continue;186 continue;
188187
189 Cluster *PredC = SecToCluster[C.BestPred.From];188 Cluster *predC = secToCluster[c.bestPred.from];
190 if (PredC == &C)189 if (predC == &c)
191 continue;190 continue;
192191
193 if (C.Size + PredC->Size > MAX_CLUSTER_SIZE)192 if (c.size + predC->size > MAX_CLUSTER_SIZE)
194 continue;193 continue;
195194
196 if (isNewDensityBad(*PredC, C))195 if (isNewDensityBad(*predC, c))
197 continue;196 continue;
198197
199 // NOTE: Consider using a disjoint-set to track section -> cluster mapping198 // NOTE: Consider using a disjoint-set to track section -> cluster mapping
200 // if this is ever slow.199 // if this is ever slow.
201 for (int SI : C.Sections)200 for (int si : c.sections)
202 SecToCluster[SI] = PredC;201 secToCluster[si] = predC;
203202
204 mergeClusters(*PredC, C);203 mergeClusters(*predC, c);
205 }204 }
206205
207 // Remove empty or dead nodes. Invalidates all cluster indices.206 // Remove empty or dead nodes. Invalidates all cluster indices.
208 llvm::erase_if(Clusters, [](const Cluster &C) {207 llvm::erase_if(clusters, [](const Cluster &c) {
209 return C.Size == 0 || C.Sections.empty();208 return c.size == 0 || c.sections.empty();
210 });209 });
211210
212 // Sort by density.211 // Sort by density.
213 std::stable_sort(Clusters.begin(), Clusters.end(),212 llvm::stable_sort(clusters, [](const Cluster &a, const Cluster &b) {
214 [](const Cluster &A, const Cluster &B) {213 return a.getDensity() > b.getDensity();
215 return A.getDensity() > B.getDensity();214 });
216 });
217}215}
218216
219DenseMap<const InputSectionBase *, int> CallGraphSort::run() {217DenseMap<const InputSectionBase *, int> CallGraphSort::run() {
220 groupClusters();218 groupClusters();
221219
222 // Generate order.220 // Generate order.
223 DenseMap<const InputSectionBase *, int> OrderMap;221 DenseMap<const InputSectionBase *, int> orderMap;
224 ssize_t CurOrder = 1;222 ssize_t curOrder = 1;
223
224 for (const Cluster &c : clusters)
225 for (int secIndex : c.sections)
226 orderMap[sections[secIndex]] = curOrder++;
227
228 if (!config->printSymbolOrder.empty()) {
229 std::error_code ec;
230 raw_fd_ostream os(config->printSymbolOrder, ec, sys::fs::F_None);
231 if (ec) {
232 error("cannot open " + config->printSymbolOrder + ": " + ec.message());
233 return orderMap;
234 }
225235
226 for (const Cluster &C : Clusters)236 // Print the symbols ordered by C3, in the order of increasing curOrder
227 for (int SecIndex : C.Sections)237 // Instead of sorting all the orderMap, just repeat the loops above.
228 OrderMap[Sections[SecIndex]] = CurOrder++;238 for (const Cluster &c : clusters)
239 for (int secIndex : c.sections)
240 // Search all the symbols in the file of the section
241 // and find out a Defined symbol with name that is within the section.
242 for (Symbol *sym: sections[secIndex]->file->getSymbols())
243 if (!sym->isSection()) // Filter out section-type symbols here.
244 if (auto *d = dyn_cast<Defined>(sym))
245 if (sections[secIndex] == d->section)
246 os << sym->getName() << "\n";
247 }
229248
230 return OrderMap;249 return orderMap;
231}250}
232251
233// Sort sections by the profile data provided by -callgraph-profile-file252// Sort sections by the profile data provided by -callgraph-profile-file
deps/lld/ELF/CallGraphSort.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- CallGraphSort.h ------------------------------------------*- C++ -*-===//1//===- CallGraphSort.h ------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/ELF/Config.h+192-165
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Config.h -------------------------------------------------*- C++ -*-===//1//===- Config.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -18,6 +17,7 @@...@@ -18,6 +17,7 @@
18#include "llvm/Support/CachePruning.h"17#include "llvm/Support/CachePruning.h"
19#include "llvm/Support/CodeGen.h"18#include "llvm/Support/CodeGen.h"
20#include "llvm/Support/Endian.h"19#include "llvm/Support/Endian.h"
20#include <atomic>
21#include <vector>21#include <vector>
2222
23namespace lld {23namespace lld {
...@@ -62,18 +62,17 @@ enum class Target2Policy { Abs, Rel, GotRel };...@@ -62,18 +62,17 @@ enum class Target2Policy { Abs, Rel, GotRel };
62enum class ARMVFPArgKind { Default, Base, VFP, ToolChain };62enum class ARMVFPArgKind { Default, Base, VFP, ToolChain };
6363
64struct SymbolVersion {64struct SymbolVersion {
65 llvm::StringRef Name;65 llvm::StringRef name;
66 bool IsExternCpp;66 bool isExternCpp;
67 bool HasWildcard;67 bool hasWildcard;
68};68};
6969
70// This struct contains symbols version definition that70// This struct contains symbols version definition that
71// can be found in version script if it is used for link.71// can be found in version script if it is used for link.
72struct VersionDefinition {72struct VersionDefinition {
73 llvm::StringRef Name;73 llvm::StringRef name;
74 uint16_t Id = 0;74 uint16_t id = 0;
75 std::vector<SymbolVersion> Globals;75 std::vector<SymbolVersion> globals;
76 size_t NameOff = 0; // Offset in the string table
77};76};
7877
79// This struct contains the global configuration for the linker.78// This struct contains the global configuration for the linker.
...@@ -81,163 +80,177 @@ struct VersionDefinition {...@@ -81,163 +80,177 @@ struct VersionDefinition {
81// and such fields have the same name as the corresponding options.80// and such fields have the same name as the corresponding options.
82// Most fields are initialized by the driver.81// Most fields are initialized by the driver.
83struct Configuration {82struct Configuration {
84 uint8_t OSABI = 0;83 uint8_t osabi = 0;
85 llvm::CachePruningPolicy ThinLTOCachePolicy;84 uint32_t andFeatures = 0;
86 llvm::StringMap<uint64_t> SectionStartMap;85 llvm::CachePruningPolicy thinLTOCachePolicy;
87 llvm::StringRef Chroot;86 llvm::StringMap<uint64_t> sectionStartMap;
88 llvm::StringRef DynamicLinker;87 llvm::StringRef chroot;
89 llvm::StringRef DwoDir;88 llvm::StringRef dynamicLinker;
90 llvm::StringRef Entry;89 llvm::StringRef dwoDir;
91 llvm::StringRef Emulation;90 llvm::StringRef entry;
92 llvm::StringRef Fini;91 llvm::StringRef emulation;
93 llvm::StringRef Init;92 llvm::StringRef fini;
94 llvm::StringRef LTOAAPipeline;93 llvm::StringRef init;
95 llvm::StringRef LTONewPmPasses;94 llvm::StringRef ltoAAPipeline;
96 llvm::StringRef LTOObjPath;95 llvm::StringRef ltoCSProfileFile;
97 llvm::StringRef LTOSampleProfile;96 llvm::StringRef ltoNewPmPasses;
98 llvm::StringRef MapFile;97 llvm::StringRef ltoObjPath;
99 llvm::StringRef OutputFile;98 llvm::StringRef ltoSampleProfile;
100 llvm::StringRef OptRemarksFilename;99 llvm::StringRef mapFile;
101 llvm::StringRef ProgName;100 llvm::StringRef outputFile;
102 llvm::StringRef SoName;101 llvm::StringRef optRemarksFilename;
103 llvm::StringRef Sysroot;102 llvm::StringRef optRemarksPasses;
104 llvm::StringRef ThinLTOCacheDir;103 llvm::StringRef optRemarksFormat;
105 llvm::StringRef ThinLTOIndexOnlyArg;104 llvm::StringRef progName;
106 std::pair<llvm::StringRef, llvm::StringRef> ThinLTOObjectSuffixReplace;105 llvm::StringRef printSymbolOrder;
107 std::pair<llvm::StringRef, llvm::StringRef> ThinLTOPrefixReplace;106 llvm::StringRef soName;
108 std::string Rpath;107 llvm::StringRef sysroot;
109 std::vector<VersionDefinition> VersionDefinitions;108 llvm::StringRef thinLTOCacheDir;
110 std::vector<llvm::StringRef> AuxiliaryList;109 llvm::StringRef thinLTOIndexOnlyArg;
111 std::vector<llvm::StringRef> FilterList;110 std::pair<llvm::StringRef, llvm::StringRef> thinLTOObjectSuffixReplace;
112 std::vector<llvm::StringRef> SearchPaths;111 std::pair<llvm::StringRef, llvm::StringRef> thinLTOPrefixReplace;
113 std::vector<llvm::StringRef> SymbolOrderingFile;112 std::string rpath;
114 std::vector<llvm::StringRef> Undefined;113 std::vector<VersionDefinition> versionDefinitions;
115 std::vector<SymbolVersion> DynamicList;114 std::vector<llvm::StringRef> auxiliaryList;
116 std::vector<SymbolVersion> VersionScriptGlobals;115 std::vector<llvm::StringRef> filterList;
117 std::vector<SymbolVersion> VersionScriptLocals;116 std::vector<llvm::StringRef> searchPaths;
118 std::vector<uint8_t> BuildIdVector;117 std::vector<llvm::StringRef> symbolOrderingFile;
118 std::vector<llvm::StringRef> undefined;
119 std::vector<SymbolVersion> dynamicList;
120 std::vector<SymbolVersion> versionScriptGlobals;
121 std::vector<SymbolVersion> versionScriptLocals;
122 std::vector<uint8_t> buildIdVector;
119 llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>,123 llvm::MapVector<std::pair<const InputSectionBase *, const InputSectionBase *>,
120 uint64_t>124 uint64_t>
121 CallGraphProfile;125 callGraphProfile;
122 bool AllowMultipleDefinition;126 bool allowMultipleDefinition;
123 bool AndroidPackDynRelocs;127 bool allowShlibUndefined;
124 bool ARMHasBlx = false;128 bool androidPackDynRelocs;
125 bool ARMHasMovtMovw = false;129 bool armHasBlx = false;
126 bool ARMJ1J2BranchEncoding = false;130 bool armHasMovtMovw = false;
127 bool AsNeeded = false;131 bool armJ1J2BranchEncoding = false;
128 bool Bsymbolic;132 bool asNeeded = false;
129 bool BsymbolicFunctions;133 bool bsymbolic;
130 bool CallGraphProfileSort;134 bool bsymbolicFunctions;
131 bool CheckSections;135 bool callGraphProfileSort;
132 bool CompressDebugSections;136 bool checkSections;
133 bool Cref;137 bool compressDebugSections;
134 bool DefineCommon;138 bool cref;
135 bool Demangle = true;139 bool defineCommon;
136 bool DisableVerify;140 bool demangle = true;
137 bool EhFrameHdr;141 bool dependentLibraries;
138 bool EmitLLVM;142 bool disableVerify;
139 bool EmitRelocs;143 bool ehFrameHdr;
140 bool EnableNewDtags;144 bool emitLLVM;
141 bool ExecuteOnly;145 bool emitRelocs;
142 bool ExportDynamic;146 bool enableNewDtags;
143 bool FixCortexA53Errata843419;147 bool executeOnly;
144 bool FormatBinary = false;148 bool exportDynamic;
145 bool GcSections;149 bool fixCortexA53Errata843419;
146 bool GdbIndex;150 bool forceBTI;
147 bool GnuHash = false;151 bool formatBinary = false;
148 bool GnuUnique;152 bool requireCET;
149 bool HasDynamicList = false;153 bool gcSections;
150 bool HasDynSymTab;154 bool gdbIndex;
151 bool IgnoreDataAddressEquality;155 bool gnuHash = false;
152 bool IgnoreFunctionAddressEquality;156 bool gnuUnique;
153 bool LTODebugPassManager;157 bool hasDynamicList = false;
154 bool LTONewPassManager;158 bool hasDynSymTab;
155 bool MergeArmExidx;159 bool ignoreDataAddressEquality;
156 bool MipsN32Abi = false;160 bool ignoreFunctionAddressEquality;
157 bool NoinhibitExec;161 bool ltoCSProfileGenerate;
158 bool Nostdlib;162 bool ltoDebugPassManager;
159 bool OFormatBinary;163 bool ltoNewPassManager;
160 bool Omagic;164 bool mergeArmExidx;
161 bool OptRemarksWithHotness;165 bool mipsN32Abi = false;
162 bool PicThunk;166 bool nmagic;
163 bool Pie;167 bool noinhibitExec;
164 bool PrintGcSections;168 bool nostdlib;
165 bool PrintIcfSections;169 bool oFormatBinary;
166 bool Relocatable;170 bool omagic;
167 bool RelrPackDynRelocs;171 bool optRemarksWithHotness;
168 bool SaveTemps;172 bool pacPlt;
169 bool SingleRoRx;173 bool picThunk;
170 bool Shared;174 bool pie;
171 bool Static = false;175 bool printGcSections;
172 bool SysvHash = false;176 bool printIcfSections;
173 bool Target1Rel;177 bool relocatable;
174 bool Trace;178 bool relrPackDynRelocs;
175 bool ThinLTOEmitImportsFiles;179 bool saveTemps;
176 bool ThinLTOIndexOnly;180 bool singleRoRx;
177 bool TocOptimize;181 bool shared;
178 bool UndefinedVersion;182 bool isStatic = false;
179 bool UseAndroidRelrTags = false;183 bool sysvHash = false;
180 bool WarnBackrefs;184 bool target1Rel;
181 bool WarnCommon;185 bool trace;
182 bool WarnIfuncTextrel;186 bool thinLTOEmitImportsFiles;
183 bool WarnMissingEntry;187 bool thinLTOIndexOnly;
184 bool WarnSymbolOrdering;188 bool tocOptimize;
185 bool WriteAddends;189 bool undefinedVersion;
186 bool ZCombreloc;190 bool useAndroidRelrTags = false;
187 bool ZCopyreloc;191 bool warnBackrefs;
188 bool ZExecstack;192 bool warnCommon;
189 bool ZGlobal;193 bool warnIfuncTextrel;
190 bool ZHazardplt;194 bool warnMissingEntry;
191 bool ZInitfirst;195 bool warnSymbolOrdering;
192 bool ZInterpose;196 bool writeAddends;
193 bool ZKeepTextSectionPrefix;197 bool zCombreloc;
194 bool ZNodefaultlib;198 bool zCopyreloc;
195 bool ZNodelete;199 bool zExecstack;
196 bool ZNodlopen;200 bool zGlobal;
197 bool ZNow;201 bool zHazardplt;
198 bool ZOrigin;202 bool zIfuncNoplt;
199 bool ZRelro;203 bool zInitfirst;
200 bool ZRodynamic;204 bool zInterpose;
201 bool ZText;205 bool zKeepTextSectionPrefix;
202 bool ZRetpolineplt;206 bool zNodefaultlib;
203 bool ZWxneeded;207 bool zNodelete;
204 DiscardPolicy Discard;208 bool zNodlopen;
205 ICFLevel ICF;209 bool zNow;
206 OrphanHandlingPolicy OrphanHandling;210 bool zOrigin;
207 SortSectionPolicy SortSection;211 bool zRelro;
208 StripPolicy Strip;212 bool zRodynamic;
209 UnresolvedPolicy UnresolvedSymbols;213 bool zText;
210 Target2Policy Target2;214 bool zRetpolineplt;
211 ARMVFPArgKind ARMVFPArgs = ARMVFPArgKind::Default;215 bool zWxneeded;
212 BuildIdKind BuildId = BuildIdKind::None;216 DiscardPolicy discard;
213 ELFKind EKind = ELFNoneKind;217 ICFLevel icf;
214 uint16_t DefaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;218 OrphanHandlingPolicy orphanHandling;
215 uint16_t EMachine = llvm::ELF::EM_NONE;219 SortSectionPolicy sortSection;
216 llvm::Optional<uint64_t> ImageBase;220 StripPolicy strip;
217 uint64_t MaxPageSize;221 UnresolvedPolicy unresolvedSymbols;
218 uint64_t MipsGotSize;222 Target2Policy target2;
219 uint64_t ZStackSize;223 ARMVFPArgKind armVFPArgs = ARMVFPArgKind::Default;
220 unsigned LTOPartitions;224 BuildIdKind buildId = BuildIdKind::None;
221 unsigned LTOO;225 ELFKind ekind = ELFNoneKind;
222 unsigned Optimize;226 uint16_t defaultSymbolVersion = llvm::ELF::VER_NDX_GLOBAL;
223 unsigned ThinLTOJobs;227 uint16_t emachine = llvm::ELF::EM_NONE;
224 int32_t SplitStackAdjustSize;228 llvm::Optional<uint64_t> imageBase;
229 uint64_t commonPageSize;
230 uint64_t maxPageSize;
231 uint64_t mipsGotSize;
232 uint64_t zStackSize;
233 unsigned ltoPartitions;
234 unsigned ltoo;
235 unsigned optimize;
236 unsigned thinLTOJobs;
237 int32_t splitStackAdjustSize;
225238
226 // The following config options do not directly correspond to any239 // The following config options do not directly correspond to any
227 // particualr command line options.240 // particualr command line options.
228241
229 // True if we need to pass through relocations in input files to the242 // True if we need to pass through relocations in input files to the
230 // output file. Usually false because we consume relocations.243 // output file. Usually false because we consume relocations.
231 bool CopyRelocs;244 bool copyRelocs;
232245
233 // True if the target is ELF64. False if ELF32.246 // True if the target is ELF64. False if ELF32.
234 bool Is64;247 bool is64;
235248
236 // True if the target is little-endian. False if big-endian.249 // True if the target is little-endian. False if big-endian.
237 bool IsLE;250 bool isLE;
238251
239 // endianness::little if IsLE is true. endianness::big otherwise.252 // endianness::little if isLE is true. endianness::big otherwise.
240 llvm::support::endianness Endianness;253 llvm::support::endianness endianness;
241254
242 // True if the target is the little-endian MIPS64.255 // True if the target is the little-endian MIPS64.
243 //256 //
...@@ -251,10 +264,24 @@ struct Configuration {...@@ -251,10 +264,24 @@ struct Configuration {
251 // name whatever that means. A fun hypothesis is that "EL" is short for264 // name whatever that means. A fun hypothesis is that "EL" is short for
252 // little-endian written in the little-endian order, but I don't know265 // little-endian written in the little-endian order, but I don't know
253 // if that's true.)266 // if that's true.)
254 bool IsMips64EL;267 bool isMips64EL;
268
269 // True if we need to set the DF_STATIC_TLS flag to an output file,
270 // which works as a hint to the dynamic loader that the file contains
271 // code compiled with the static TLS model. The thread-local variable
272 // compiled with the static TLS model is faster but less flexible, and
273 // it may not be loaded using dlopen().
274 //
275 // We set this flag to true when we see a relocation for the static TLS
276 // model. Once this becomes true, it will never become false.
277 //
278 // Since the flag is updated by multi-threaded code, we use std::atomic.
279 // (Writing to a variable is not considered thread-safe even if the
280 // variable is boolean and we always set the same value from all threads.)
281 std::atomic<bool> hasStaticTlsModel{false};
255282
256 // Holds set of ELF header flags for the target.283 // Holds set of ELF header flags for the target.
257 uint32_t EFlags = 0;284 uint32_t eflags = 0;
258285
259 // The ELF spec defines two types of relocation table entries, RELA and286 // The ELF spec defines two types of relocation table entries, RELA and
260 // REL. RELA is a triplet of (offset, info, addend) while REL is a287 // REL. RELA is a triplet of (offset, info, addend) while REL is a
...@@ -270,23 +297,23 @@ struct Configuration {...@@ -270,23 +297,23 @@ struct Configuration {
270 // Each ABI defines its relocation type. IsRela is true if target297 // Each ABI defines its relocation type. IsRela is true if target
271 // uses RELA. As far as we know, all 64-bit ABIs are using RELA. A298 // uses RELA. As far as we know, all 64-bit ABIs are using RELA. A
272 // few 32-bit ABIs are using RELA too.299 // few 32-bit ABIs are using RELA too.
273 bool IsRela;300 bool isRela;
274301
275 // True if we are creating position-independent code.302 // True if we are creating position-independent code.
276 bool Pic;303 bool isPic;
277304
278 // 4 for ELF32, 8 for ELF64.305 // 4 for ELF32, 8 for ELF64.
279 int Wordsize;306 int wordsize;
280};307};
281308
282// The only instance of Configuration struct.309// The only instance of Configuration struct.
283extern Configuration *Config;310extern Configuration *config;
284311
285static inline void errorOrWarn(const Twine &Msg) {312static inline void errorOrWarn(const Twine &msg) {
286 if (!Config->NoinhibitExec)313 if (!config->noinhibitExec)
287 error(Msg);314 error(msg);
288 else315 else
289 warn(Msg);316 warn(msg);
290}317}
291} // namespace elf318} // namespace elf
292} // namespace lld319} // namespace lld
deps/lld/ELF/DWARF.cpp+76-56
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- DWARF.cpp ----------------------------------------------------------===//1//===- DWARF.cpp ----------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -26,81 +25,102 @@ using namespace llvm::object;...@@ -26,81 +25,102 @@ using namespace llvm::object;
26using namespace lld;25using namespace lld;
27using namespace lld::elf;26using namespace lld::elf;
2827
29template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *Obj) {28template <class ELFT> LLDDwarfObj<ELFT>::LLDDwarfObj(ObjFile<ELFT> *obj) {
30 for (InputSectionBase *Sec : Obj->getSections()) {29 for (InputSectionBase *sec : obj->getSections()) {
31 if (!Sec)30 if (!sec)
32 continue;31 continue;
3332
34 if (LLDDWARFSection *M =33 if (LLDDWARFSection *m =
35 StringSwitch<LLDDWARFSection *>(Sec->Name)34 StringSwitch<LLDDWARFSection *>(sec->name)
36 .Case(".debug_addr", &AddrSection)35 .Case(".debug_addr", &addrSection)
37 .Case(".debug_gnu_pubnames", &GnuPubNamesSection)36 .Case(".debug_gnu_pubnames", &gnuPubNamesSection)
38 .Case(".debug_gnu_pubtypes", &GnuPubTypesSection)37 .Case(".debug_gnu_pubtypes", &gnuPubTypesSection)
39 .Case(".debug_info", &InfoSection)38 .Case(".debug_info", &infoSection)
40 .Case(".debug_ranges", &RangeSection)39 .Case(".debug_ranges", &rangeSection)
41 .Case(".debug_rnglists", &RngListsSection)40 .Case(".debug_rnglists", &rngListsSection)
42 .Case(".debug_line", &LineSection)41 .Case(".debug_line", &lineSection)
43 .Default(nullptr)) {42 .Default(nullptr)) {
44 M->Data = toStringRef(Sec->data());43 m->Data = toStringRef(sec->data());
45 M->Sec = Sec;44 m->sec = sec;
46 continue;45 continue;
47 }46 }
4847
49 if (Sec->Name == ".debug_abbrev")48 if (sec->name == ".debug_abbrev")
50 AbbrevSection = toStringRef(Sec->data());49 abbrevSection = toStringRef(sec->data());
51 else if (Sec->Name == ".debug_str")50 else if (sec->name == ".debug_str")
52 StrSection = toStringRef(Sec->data());51 strSection = toStringRef(sec->data());
53 else if (Sec->Name == ".debug_line_str")52 else if (sec->name == ".debug_line_str")
54 LineStringSection = toStringRef(Sec->data());53 lineStringSection = toStringRef(sec->data());
55 }54 }
56}55}
5756
57namespace {
58template <class RelTy> struct LLDRelocationResolver {
59 // In the ELF ABIs, S sepresents the value of the symbol in the relocation
60 // entry. For Rela, the addend is stored as part of the relocation entry.
61 static uint64_t resolve(object::RelocationRef ref, uint64_t s,
62 uint64_t /* A */) {
63 return s + ref.getRawDataRefImpl().p;
64 }
65};
66
67template <class ELFT> struct LLDRelocationResolver<Elf_Rel_Impl<ELFT, false>> {
68 // For Rel, the addend A is supplied by the caller.
69 static uint64_t resolve(object::RelocationRef /*Ref*/, uint64_t s,
70 uint64_t a) {
71 return s + a;
72 }
73};
74} // namespace
75
58// Find if there is a relocation at Pos in Sec. The code is a bit76// 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 index77// more complicated than usual because we need to pass a section index
60// to llvm since it has no idea about InputSection.78// to llvm since it has no idea about InputSection.
61template <class ELFT>79template <class ELFT>
62template <class RelTy>80template <class RelTy>
63Optional<RelocAddrEntry>81Optional<RelocAddrEntry>
64LLDDwarfObj<ELFT>::findAux(const InputSectionBase &Sec, uint64_t Pos,82LLDDwarfObj<ELFT>::findAux(const InputSectionBase &sec, uint64_t pos,
65 ArrayRef<RelTy> Rels) const {83 ArrayRef<RelTy> rels) const {
66 auto It = std::lower_bound(84 auto it =
67 Rels.begin(), Rels.end(), Pos,85 partition_point(rels, [=](const RelTy &a) { return a.r_offset < pos; });
68 [](const RelTy &A, uint64_t B) { return A.r_offset < B; });86 if (it == rels.end() || it->r_offset != pos)
69 if (It == Rels.end() || It->r_offset != Pos)
70 return None;87 return None;
71 const RelTy &Rel = *It;88 const RelTy &rel = *it;
7289
73 const ObjFile<ELFT> *File = Sec.getFile<ELFT>();90 const ObjFile<ELFT> *file = sec.getFile<ELFT>();
74 uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL);91 uint32_t symIndex = rel.getSymbol(config->isMips64EL);
75 const typename ELFT::Sym &Sym = File->getELFSyms()[SymIndex];92 const typename ELFT::Sym &sym = file->template getELFSyms<ELFT>()[symIndex];
76 uint32_t SecIndex = File->getSectionIndex(Sym);93 uint32_t secIndex = file->getSectionIndex(sym);
7794
78 // Broken debug info can point to a non-Defined symbol.95 // An undefined symbol may be a symbol defined in a discarded section. We
79 auto *DR = dyn_cast<Defined>(&File->getRelocTargetSym(Rel));96 // shall still resolve it. This is important for --gdb-index: the end address
80 if (!DR) {97 // offset of an entry in .debug_ranges is relocated. If it is not resolved,
81 RelType Type = Rel.getType(Config->IsMips64EL);98 // its zero value will terminate the decoding of .debug_ranges prematurely.
82 if (Type != Target->NoneRel)99 Symbol &s = file->getRelocTargetSym(rel);
83 error(toString(File) + ": relocation " + lld::toString(Type) + " at 0x" +100 uint64_t val = 0;
84 llvm::utohexstr(Rel.r_offset) + " has unsupported target");101 if (auto *dr = dyn_cast<Defined>(&s)) {
85 return None;102 val = dr->value;
86 }
87 uint64_t Val = DR->Value + getAddend<ELFT>(Rel);
88103
89 // FIXME: We should be consistent about always adding the file104 // FIXME: We should be consistent about always adding the file
90 // offset or not.105 // offset or not.
91 if (DR->Section->Flags & ELF::SHF_ALLOC)106 if (dr->section->flags & ELF::SHF_ALLOC)
92 Val += cast<InputSection>(DR->Section)->getOffsetInFile();107 val += cast<InputSection>(dr->section)->getOffsetInFile();
108 }
93109
94 return RelocAddrEntry{SecIndex, Val};110 DataRefImpl d;
111 d.p = getAddend<ELFT>(rel);
112 return RelocAddrEntry{secIndex, RelocationRef(d, nullptr),
113 val, Optional<object::RelocationRef>(),
114 0, LLDRelocationResolver<RelTy>::resolve};
95}115}
96116
97template <class ELFT>117template <class ELFT>
98Optional<RelocAddrEntry> LLDDwarfObj<ELFT>::find(const llvm::DWARFSection &S,118Optional<RelocAddrEntry> LLDDwarfObj<ELFT>::find(const llvm::DWARFSection &s,
99 uint64_t Pos) const {119 uint64_t pos) const {
100 auto &Sec = static_cast<const LLDDWARFSection &>(S);120 auto &sec = static_cast<const LLDDWARFSection &>(s);
101 if (Sec.Sec->AreRelocsRela)121 if (sec.sec->areRelocsRela)
102 return findAux(*Sec.Sec, Pos, Sec.Sec->template relas<ELFT>());122 return findAux(*sec.sec, pos, sec.sec->template relas<ELFT>());
103 return findAux(*Sec.Sec, Pos, Sec.Sec->template rels<ELFT>());123 return findAux(*sec.sec, pos, sec.sec->template rels<ELFT>());
104}124}
105125
106template class elf::LLDDwarfObj<ELF32LE>;126template class elf::LLDDwarfObj<ELF32LE>;
deps/lld/ELF/DWARF.h+32-33
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- DWARF.h -----------------------------------------------*- C++ -*-===//1//===- DWARF.h -----------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===-------------------------------------------------------------------===//7//===-------------------------------------------------------------------===//
98
...@@ -21,70 +20,70 @@ namespace elf {...@@ -21,70 +20,70 @@ namespace elf {
21class InputSection;20class InputSection;
2221
23struct LLDDWARFSection final : public llvm::DWARFSection {22struct LLDDWARFSection final : public llvm::DWARFSection {
24 InputSectionBase *Sec = nullptr;23 InputSectionBase *sec = nullptr;
25};24};
2625
27template <class ELFT> class LLDDwarfObj final : public llvm::DWARFObject {26template <class ELFT> class LLDDwarfObj final : public llvm::DWARFObject {
28public:27public:
29 explicit LLDDwarfObj(ObjFile<ELFT> *Obj);28 explicit LLDDwarfObj(ObjFile<ELFT> *obj);
3029
31 void forEachInfoSections(30 void forEachInfoSections(
32 llvm::function_ref<void(const llvm::DWARFSection &)> F) const override {31 llvm::function_ref<void(const llvm::DWARFSection &)> f) const override {
33 F(InfoSection);32 f(infoSection);
34 }33 }
3534
36 const llvm::DWARFSection &getRangeSection() const override {35 const llvm::DWARFSection &getRangeSection() const override {
37 return RangeSection;36 return rangeSection;
38 }37 }
3938
40 const llvm::DWARFSection &getRnglistsSection() const override {39 const llvm::DWARFSection &getRnglistsSection() const override {
41 return RngListsSection;40 return rngListsSection;
42 }41 }
4342
44 const llvm::DWARFSection &getLineSection() const override {43 const llvm::DWARFSection &getLineSection() const override {
45 return LineSection;44 return lineSection;
46 }45 }
4746
48 const llvm::DWARFSection &getAddrSection() const override {47 const llvm::DWARFSection &getAddrSection() const override {
49 return AddrSection;48 return addrSection;
50 }49 }
5150
52 const llvm::DWARFSection &getGnuPubNamesSection() const override {51 const llvm::DWARFSection &getGnuPubNamesSection() const override {
53 return GnuPubNamesSection;52 return gnuPubNamesSection;
54 }53 }
5554
56 const llvm::DWARFSection &getGnuPubTypesSection() const override {55 const llvm::DWARFSection &getGnuPubTypesSection() const override {
57 return GnuPubTypesSection;56 return gnuPubTypesSection;
58 }57 }
5958
60 StringRef getFileName() const override { return ""; }59 StringRef getFileName() const override { return ""; }
61 StringRef getAbbrevSection() const override { return AbbrevSection; }60 StringRef getAbbrevSection() const override { return abbrevSection; }
62 StringRef getStringSection() const override { return StrSection; }61 StringRef getStringSection() const override { return strSection; }
63 StringRef getLineStringSection() const override { return LineStringSection; }62 StringRef getLineStringSection() const override { return lineStringSection; }
6463
65 bool isLittleEndian() const override {64 bool isLittleEndian() const override {
66 return ELFT::TargetEndianness == llvm::support::little;65 return ELFT::TargetEndianness == llvm::support::little;
67 }66 }
6867
69 llvm::Optional<llvm::RelocAddrEntry> find(const llvm::DWARFSection &Sec,68 llvm::Optional<llvm::RelocAddrEntry> find(const llvm::DWARFSection &sec,
70 uint64_t Pos) const override;69 uint64_t pos) const override;
7170
72private:71private:
73 template <class RelTy>72 template <class RelTy>
74 llvm::Optional<llvm::RelocAddrEntry> findAux(const InputSectionBase &Sec,73 llvm::Optional<llvm::RelocAddrEntry> findAux(const InputSectionBase &sec,
75 uint64_t Pos,74 uint64_t pos,
76 ArrayRef<RelTy> Rels) const;75 ArrayRef<RelTy> rels) const;
7776
78 LLDDWARFSection GnuPubNamesSection;77 LLDDWARFSection gnuPubNamesSection;
79 LLDDWARFSection GnuPubTypesSection;78 LLDDWARFSection gnuPubTypesSection;
80 LLDDWARFSection InfoSection;79 LLDDWARFSection infoSection;
81 LLDDWARFSection RangeSection;80 LLDDWARFSection rangeSection;
82 LLDDWARFSection RngListsSection;81 LLDDWARFSection rngListsSection;
83 LLDDWARFSection LineSection;82 LLDDWARFSection lineSection;
84 LLDDWARFSection AddrSection;83 LLDDWARFSection addrSection;
85 StringRef AbbrevSection;84 StringRef abbrevSection;
86 StringRef StrSection;85 StringRef strSection;
87 StringRef LineStringSection;86 StringRef lineStringSection;
88};87};
8988
90} // namespace elf89} // namespace elf
deps/lld/ELF/Driver.cpp+1080-818
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Driver.cpp ---------------------------------------------------------===//1//===- Driver.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -25,7 +24,6 @@...@@ -25,7 +24,6 @@
2524
26#include "Driver.h"25#include "Driver.h"
27#include "Config.h"26#include "Config.h"
28#include "Filesystem.h"
29#include "ICF.h"27#include "ICF.h"
30#include "InputFiles.h"28#include "InputFiles.h"
31#include "InputSection.h"29#include "InputSection.h"
...@@ -41,6 +39,7 @@...@@ -41,6 +39,7 @@
41#include "lld/Common/Args.h"39#include "lld/Common/Args.h"
42#include "lld/Common/Driver.h"40#include "lld/Common/Driver.h"
43#include "lld/Common/ErrorHandler.h"41#include "lld/Common/ErrorHandler.h"
42#include "lld/Common/Filesystem.h"
44#include "lld/Common/Memory.h"43#include "lld/Common/Memory.h"
45#include "lld/Common/Strings.h"44#include "lld/Common/Strings.h"
46#include "lld/Common/TargetOptionsCommandFlags.h"45#include "lld/Common/TargetOptionsCommandFlags.h"
...@@ -51,6 +50,7 @@...@@ -51,6 +50,7 @@
51#include "llvm/ADT/StringSwitch.h"50#include "llvm/ADT/StringSwitch.h"
52#include "llvm/Support/CommandLine.h"51#include "llvm/Support/CommandLine.h"
53#include "llvm/Support/Compression.h"52#include "llvm/Support/Compression.h"
53#include "llvm/Support/GlobPattern.h"
54#include "llvm/Support/LEB128.h"54#include "llvm/Support/LEB128.h"
55#include "llvm/Support/Path.h"55#include "llvm/Support/Path.h"
56#include "llvm/Support/TarWriter.h"56#include "llvm/Support/TarWriter.h"
...@@ -68,44 +68,49 @@ using namespace llvm::support;...@@ -68,44 +68,49 @@ using namespace llvm::support;
68using namespace lld;68using namespace lld;
69using namespace lld::elf;69using namespace lld::elf;
7070
71Configuration *elf::Config;71Configuration *elf::config;
72LinkerDriver *elf::Driver;72LinkerDriver *elf::driver;
7373
74static void setConfigs(opt::InputArgList &Args);74static void setConfigs(opt::InputArgList &args);
75static void readConfigs(opt::InputArgList &args);
7576
76bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,77bool elf::link(ArrayRef<const char *> args, bool canExitEarly,
77 raw_ostream &Error) {78 raw_ostream &error) {
78 errorHandler().LogName = args::getFilenameWithoutExe(Args[0]);79 errorHandler().logName = args::getFilenameWithoutExe(args[0]);
79 errorHandler().ErrorLimitExceededMsg =80 errorHandler().errorLimitExceededMsg =
80 "too many errors emitted, stopping now (use "81 "too many errors emitted, stopping now (use "
81 "-error-limit=0 to see all errors)";82 "-error-limit=0 to see all errors)";
82 errorHandler().ErrorOS = &Error;83 errorHandler().errorOS = &error;
83 errorHandler().ExitEarly = CanExitEarly;84 errorHandler().exitEarly = canExitEarly;
84 errorHandler().ColorDiagnostics = Error.has_colors();85 errorHandler().colorDiagnostics = error.has_colors();
86
87 inputSections.clear();
88 outputSections.clear();
89 binaryFiles.clear();
90 bitcodeFiles.clear();
91 objectFiles.clear();
92 sharedFiles.clear();
93
94 config = make<Configuration>();
95 driver = make<LinkerDriver>();
96 script = make<LinkerScript>();
97 symtab = make<SymbolTable>();
8598
86 InputSections.clear();99 tar = nullptr;
87 OutputSections.clear();100 memset(&in, 0, sizeof(in));
88 BinaryFiles.clear();
89 BitcodeFiles.clear();
90 ObjectFiles.clear();
91 SharedFiles.clear();
92101
93 Config = make<Configuration>();102 partitions = {Partition()};
94 Driver = make<LinkerDriver>();
95 Script = make<LinkerScript>();
96 Symtab = make<SymbolTable>();
97103
98 Tar = nullptr;104 SharedFile::vernauxNum = 0;
99 memset(&In, 0, sizeof(In));
100105
101 Config->ProgName = Args[0];106 config->progName = args[0];
102107
103 Driver->main(Args);108 driver->main(args);
104109
105 // Exit immediately if we don't need to return to the caller.110 // Exit immediately if we don't need to return to the caller.
106 // This saves time because the overhead of calling destructors111 // This saves time because the overhead of calling destructors
107 // for all globally-allocated objects is not negligible.112 // for all globally-allocated objects is not negligible.
108 if (CanExitEarly)113 if (canExitEarly)
109 exitLld(errorCount() ? 1 : 0);114 exitLld(errorCount() ? 1 : 0);
110115
111 freeArena();116 freeArena();
...@@ -113,16 +118,16 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,...@@ -113,16 +118,16 @@ bool elf::link(ArrayRef<const char *> Args, bool CanExitEarly,
113}118}
114119
115// Parses a linker -m option.120// Parses a linker -m option.
116static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) {121static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef emul) {
117 uint8_t OSABI = 0;122 uint8_t osabi = 0;
118 StringRef S = Emul;123 StringRef s = emul;
119 if (S.endswith("_fbsd")) {124 if (s.endswith("_fbsd")) {
120 S = S.drop_back(5);125 s = s.drop_back(5);
121 OSABI = ELFOSABI_FREEBSD;126 osabi = ELFOSABI_FREEBSD;
122 }127 }
123128
124 std::pair<ELFKind, uint16_t> Ret =129 std::pair<ELFKind, uint16_t> ret =
125 StringSwitch<std::pair<ELFKind, uint16_t>>(S)130 StringSwitch<std::pair<ELFKind, uint16_t>>(s)
126 .Cases("aarch64elf", "aarch64linux", "aarch64_elf64_le_vec",131 .Cases("aarch64elf", "aarch64linux", "aarch64_elf64_le_vec",
127 {ELF64LEKind, EM_AARCH64})132 {ELF64LEKind, EM_AARCH64})
128 .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM})133 .Cases("armelf", "armelf_linux_eabi", {ELF32LEKind, EM_ARM})
...@@ -141,91 +146,101 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) {...@@ -141,91 +146,101 @@ static std::tuple<ELFKind, uint16_t, uint8_t> parseEmulation(StringRef Emul) {
141 .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU})146 .Case("elf_iamcu", {ELF32LEKind, EM_IAMCU})
142 .Default({ELFNoneKind, EM_NONE});147 .Default({ELFNoneKind, EM_NONE});
143148
144 if (Ret.first == ELFNoneKind)149 if (ret.first == ELFNoneKind)
145 error("unknown emulation: " + Emul);150 error("unknown emulation: " + emul);
146 return std::make_tuple(Ret.first, Ret.second, OSABI);151 return std::make_tuple(ret.first, ret.second, osabi);
147}152}
148153
149// Returns slices of MB by parsing MB as an archive file.154// Returns slices of MB by parsing MB as an archive file.
150// Each slice consists of a member file in the archive.155// Each slice consists of a member file in the archive.
151std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(156std::vector<std::pair<MemoryBufferRef, uint64_t>> static getArchiveMembers(
152 MemoryBufferRef MB) {157 MemoryBufferRef mb) {
153 std::unique_ptr<Archive> File =158 std::unique_ptr<Archive> file =
154 CHECK(Archive::create(MB),159 CHECK(Archive::create(mb),
155 MB.getBufferIdentifier() + ": failed to parse archive");160 mb.getBufferIdentifier() + ": failed to parse archive");
156161
157 std::vector<std::pair<MemoryBufferRef, uint64_t>> V;162 std::vector<std::pair<MemoryBufferRef, uint64_t>> v;
158 Error Err = Error::success();163 Error err = Error::success();
159 bool AddToTar = File->isThin() && Tar;164 bool addToTar = file->isThin() && tar;
160 for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {165 for (const ErrorOr<Archive::Child> &cOrErr : file->children(err)) {
161 Archive::Child C =166 Archive::Child c =
162 CHECK(COrErr, MB.getBufferIdentifier() +167 CHECK(cOrErr, mb.getBufferIdentifier() +
163 ": could not get the child of the archive");168 ": could not get the child of the archive");
164 MemoryBufferRef MBRef =169 MemoryBufferRef mbref =
165 CHECK(C.getMemoryBufferRef(),170 CHECK(c.getMemoryBufferRef(),
166 MB.getBufferIdentifier() +171 mb.getBufferIdentifier() +
167 ": could not get the buffer for a child of the archive");172 ": could not get the buffer for a child of the archive");
168 if (AddToTar)173 if (addToTar)
169 Tar->append(relativeToRoot(check(C.getFullName())), MBRef.getBuffer());174 tar->append(relativeToRoot(check(c.getFullName())), mbref.getBuffer());
170 V.push_back(std::make_pair(MBRef, C.getChildOffset()));175 v.push_back(std::make_pair(mbref, c.getChildOffset()));
171 }176 }
172 if (Err)177 if (err)
173 fatal(MB.getBufferIdentifier() + ": Archive::children failed: " +178 fatal(mb.getBufferIdentifier() + ": Archive::children failed: " +
174 toString(std::move(Err)));179 toString(std::move(err)));
175180
176 // Take ownership of memory buffers created for members of thin archives.181 // Take ownership of memory buffers created for members of thin archives.
177 for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers())182 for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers())
178 make<std::unique_ptr<MemoryBuffer>>(std::move(MB));183 make<std::unique_ptr<MemoryBuffer>>(std::move(mb));
179184
180 return V;185 return v;
181}186}
182187
183// Opens a file and create a file object. Path has to be resolved already.188// Opens a file and create a file object. Path has to be resolved already.
184void LinkerDriver::addFile(StringRef Path, bool WithLOption) {189void LinkerDriver::addFile(StringRef path, bool withLOption) {
185 using namespace sys::fs;190 using namespace sys::fs;
186191
187 Optional<MemoryBufferRef> Buffer = readFile(Path);192 Optional<MemoryBufferRef> buffer = readFile(path);
188 if (!Buffer.hasValue())193 if (!buffer.hasValue())
189 return;194 return;
190 MemoryBufferRef MBRef = *Buffer;195 MemoryBufferRef mbref = *buffer;
191196
192 if (Config->FormatBinary) {197 if (config->formatBinary) {
193 Files.push_back(make<BinaryFile>(MBRef));198 files.push_back(make<BinaryFile>(mbref));
194 return;199 return;
195 }200 }
196201
197 switch (identify_magic(MBRef.getBuffer())) {202 switch (identify_magic(mbref.getBuffer())) {
198 case file_magic::unknown:203 case file_magic::unknown:
199 readLinkerScript(MBRef);204 readLinkerScript(mbref);
200 return;205 return;
201 case file_magic::archive: {206 case file_magic::archive: {
202 // Handle -whole-archive.207 // Handle -whole-archive.
203 if (InWholeArchive) {208 if (inWholeArchive) {
204 for (const auto &P : getArchiveMembers(MBRef))209 for (const auto &p : getArchiveMembers(mbref))
205 Files.push_back(createObjectFile(P.first, Path, P.second));210 files.push_back(createObjectFile(p.first, path, p.second));
206 return;211 return;
207 }212 }
208213
209 std::unique_ptr<Archive> File =214 std::unique_ptr<Archive> file =
210 CHECK(Archive::create(MBRef), Path + ": failed to parse archive");215 CHECK(Archive::create(mbref), path + ": failed to parse archive");
211216
212 // If an archive file has no symbol table, it is likely that a user217 // If an archive file has no symbol table, it is likely that a user
213 // is attempting LTO and using a default ar command that doesn't218 // is attempting LTO and using a default ar command that doesn't
214 // understand the LLVM bitcode file. It is a pretty common error, so219 // understand the LLVM bitcode file. It is a pretty common error, so
215 // we'll handle it as if it had a symbol table.220 // we'll handle it as if it had a symbol table.
216 if (!File->isEmpty() && !File->hasSymbolTable()) {221 if (!file->isEmpty() && !file->hasSymbolTable()) {
217 for (const auto &P : getArchiveMembers(MBRef))222 // Check if all members are bitcode files. If not, ignore, which is the
218 Files.push_back(make<LazyObjFile>(P.first, Path, P.second));223 // default action without the LTO hack described above.
224 for (const std::pair<MemoryBufferRef, uint64_t> &p :
225 getArchiveMembers(mbref))
226 if (identify_magic(p.first.getBuffer()) != file_magic::bitcode) {
227 error(path + ": archive has no index; run ranlib to add one");
228 return;
229 }
230
231 for (const std::pair<MemoryBufferRef, uint64_t> &p :
232 getArchiveMembers(mbref))
233 files.push_back(make<LazyObjFile>(p.first, path, p.second));
219 return;234 return;
220 }235 }
221236
222 // Handle the regular case.237 // Handle the regular case.
223 Files.push_back(make<ArchiveFile>(std::move(File)));238 files.push_back(make<ArchiveFile>(std::move(file)));
224 return;239 return;
225 }240 }
226 case file_magic::elf_shared_object:241 case file_magic::elf_shared_object:
227 if (Config->Static || Config->Relocatable) {242 if (config->isStatic || config->relocatable) {
228 error("attempted static link of dynamic object " + Path);243 error("attempted static link of dynamic object " + path);
229 return;244 return;
230 }245 }
231246
...@@ -239,27 +254,27 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) {...@@ -239,27 +254,27 @@ void LinkerDriver::addFile(StringRef Path, bool WithLOption) {
239 // If a file was specified by -lfoo, the directory part is not254 // If a file was specified by -lfoo, the directory part is not
240 // significant, as a user did not specify it. This behavior is255 // significant, as a user did not specify it. This behavior is
241 // compatible with GNU.256 // compatible with GNU.
242 Files.push_back(257 files.push_back(
243 createSharedFile(MBRef, WithLOption ? path::filename(Path) : Path));258 make<SharedFile>(mbref, withLOption ? path::filename(path) : path));
244 return;259 return;
245 case file_magic::bitcode:260 case file_magic::bitcode:
246 case file_magic::elf_relocatable:261 case file_magic::elf_relocatable:
247 if (InLib)262 if (inLib)
248 Files.push_back(make<LazyObjFile>(MBRef, "", 0));263 files.push_back(make<LazyObjFile>(mbref, "", 0));
249 else264 else
250 Files.push_back(createObjectFile(MBRef));265 files.push_back(createObjectFile(mbref));
251 break;266 break;
252 default:267 default:
253 error(Path + ": unknown file type");268 error(path + ": unknown file type");
254 }269 }
255}270}
256271
257// Add a given library by searching it from input search paths.272// Add a given library by searching it from input search paths.
258void LinkerDriver::addLibrary(StringRef Name) {273void LinkerDriver::addLibrary(StringRef name) {
259 if (Optional<std::string> Path = searchLibrary(Name))274 if (Optional<std::string> path = searchLibrary(name))
260 addFile(*Path, /*WithLOption=*/true);275 addFile(*path, /*withLOption=*/true);
261 else276 else
262 error("unable to find library -l" + Name);277 error("unable to find library -l" + name);
263}278}
264279
265// This function is called on startup. We need this for LTO since280// This function is called on startup. We need this for LTO since
...@@ -278,102 +293,117 @@ static void initLLVM() {...@@ -278,102 +293,117 @@ static void initLLVM() {
278static void checkOptions() {293static void checkOptions() {
279 // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup294 // The MIPS ABI as of 2016 does not support the GNU-style symbol lookup
280 // table which is a relatively new feature.295 // table which is a relatively new feature.
281 if (Config->EMachine == EM_MIPS && Config->GnuHash)296 if (config->emachine == EM_MIPS && config->gnuHash)
282 error("the .gnu.hash section is not compatible with the MIPS target");297 error("the .gnu.hash section is not compatible with the MIPS target");
283298
284 if (Config->FixCortexA53Errata843419 && Config->EMachine != EM_AARCH64)299 if (config->fixCortexA53Errata843419 && config->emachine != EM_AARCH64)
285 error("--fix-cortex-a53-843419 is only supported on AArch64 targets");300 error("--fix-cortex-a53-843419 is only supported on AArch64 targets");
286301
287 if (Config->TocOptimize && Config->EMachine != EM_PPC64)302 if (config->tocOptimize && config->emachine != EM_PPC64)
288 error("--toc-optimize is only supported on the PowerPC64 target");303 error("--toc-optimize is only supported on the PowerPC64 target");
289304
290 if (Config->Pie && Config->Shared)305 if (config->pie && config->shared)
291 error("-shared and -pie may not be used together");306 error("-shared and -pie may not be used together");
292307
293 if (!Config->Shared && !Config->FilterList.empty())308 if (!config->shared && !config->filterList.empty())
294 error("-F may not be used without -shared");309 error("-F may not be used without -shared");
295310
296 if (!Config->Shared && !Config->AuxiliaryList.empty())311 if (!config->shared && !config->auxiliaryList.empty())
297 error("-f may not be used without -shared");312 error("-f may not be used without -shared");
298313
299 if (!Config->Relocatable && !Config->DefineCommon)314 if (!config->relocatable && !config->defineCommon)
300 error("-no-define-common not supported in non relocatable output");315 error("-no-define-common not supported in non relocatable output");
301316
302 if (Config->Relocatable) {317 if (config->zText && config->zIfuncNoplt)
303 if (Config->Shared)318 error("-z text and -z ifunc-noplt may not be used together");
319
320 if (config->relocatable) {
321 if (config->shared)
304 error("-r and -shared may not be used together");322 error("-r and -shared may not be used together");
305 if (Config->GcSections)323 if (config->gcSections)
306 error("-r and --gc-sections may not be used together");324 error("-r and --gc-sections may not be used together");
307 if (Config->GdbIndex)325 if (config->gdbIndex)
308 error("-r and --gdb-index may not be used together");326 error("-r and --gdb-index may not be used together");
309 if (Config->ICF != ICFLevel::None)327 if (config->icf != ICFLevel::None)
310 error("-r and --icf may not be used together");328 error("-r and --icf may not be used together");
311 if (Config->Pie)329 if (config->pie)
312 error("-r and -pie may not be used together");330 error("-r and -pie may not be used together");
313 }331 }
314332
315 if (Config->ExecuteOnly) {333 if (config->executeOnly) {
316 if (Config->EMachine != EM_AARCH64)334 if (config->emachine != EM_AARCH64)
317 error("-execute-only is only supported on AArch64 targets");335 error("-execute-only is only supported on AArch64 targets");
318336
319 if (Config->SingleRoRx && !Script->HasSectionsCommand)337 if (config->singleRoRx && !script->hasSectionsCommand)
320 error("-execute-only and -no-rosegment cannot be used together");338 error("-execute-only and -no-rosegment cannot be used together");
321 }339 }
340
341 if (config->zRetpolineplt && config->requireCET)
342 error("--require-cet may not be used with -z retpolineplt");
343
344 if (config->emachine != EM_AARCH64) {
345 if (config->pacPlt)
346 error("--pac-plt only supported on AArch64");
347 if (config->forceBTI)
348 error("--force-bti only supported on AArch64");
349 }
322}350}
323351
324static const char *getReproduceOption(opt::InputArgList &Args) {352static const char *getReproduceOption(opt::InputArgList &args) {
325 if (auto *Arg = Args.getLastArg(OPT_reproduce))353 if (auto *arg = args.getLastArg(OPT_reproduce))
326 return Arg->getValue();354 return arg->getValue();
327 return getenv("LLD_REPRODUCE");355 return getenv("LLD_REPRODUCE");
328}356}
329357
330static bool hasZOption(opt::InputArgList &Args, StringRef Key) {358static bool hasZOption(opt::InputArgList &args, StringRef key) {
331 for (auto *Arg : Args.filtered(OPT_z))359 for (auto *arg : args.filtered(OPT_z))
332 if (Key == Arg->getValue())360 if (key == arg->getValue())
333 return true;361 return true;
334 return false;362 return false;
335}363}
336364
337static bool getZFlag(opt::InputArgList &Args, StringRef K1, StringRef K2,365static bool getZFlag(opt::InputArgList &args, StringRef k1, StringRef k2,
338 bool Default) {366 bool Default) {
339 for (auto *Arg : Args.filtered_reverse(OPT_z)) {367 for (auto *arg : args.filtered_reverse(OPT_z)) {
340 if (K1 == Arg->getValue())368 if (k1 == arg->getValue())
341 return true;369 return true;
342 if (K2 == Arg->getValue())370 if (k2 == arg->getValue())
343 return false;371 return false;
344 }372 }
345 return Default;373 return Default;
346}374}
347375
348static bool isKnownZFlag(StringRef S) {376static bool isKnownZFlag(StringRef s) {
349 return S == "combreloc" || S == "copyreloc" || S == "defs" ||377 return s == "combreloc" || s == "copyreloc" || s == "defs" ||
350 S == "execstack" || S == "global" || S == "hazardplt" ||378 s == "execstack" || s == "global" || s == "hazardplt" ||
351 S == "initfirst" || S == "interpose" ||379 s == "ifunc-noplt" || s == "initfirst" || s == "interpose" ||
352 S == "keep-text-section-prefix" || S == "lazy" || S == "muldefs" ||380 s == "keep-text-section-prefix" || s == "lazy" || s == "muldefs" ||
353 S == "nocombreloc" || S == "nocopyreloc" || S == "nodefaultlib" ||381 s == "nocombreloc" || s == "nocopyreloc" || s == "nodefaultlib" ||
354 S == "nodelete" || S == "nodlopen" || S == "noexecstack" ||382 s == "nodelete" || s == "nodlopen" || s == "noexecstack" ||
355 S == "nokeep-text-section-prefix" || S == "norelro" || S == "notext" ||383 s == "nokeep-text-section-prefix" || s == "norelro" || s == "notext" ||
356 S == "now" || S == "origin" || S == "relro" || S == "retpolineplt" ||384 s == "now" || s == "origin" || s == "relro" || s == "retpolineplt" ||
357 S == "rodynamic" || S == "text" || S == "wxneeded" ||385 s == "rodynamic" || s == "text" || s == "wxneeded" ||
358 S.startswith("max-page-size=") || S.startswith("stack-size=");386 s.startswith("common-page-size") || s.startswith("max-page-size=") ||
387 s.startswith("stack-size=");
359}388}
360389
361// Report an error for an unknown -z option.390// Report an error for an unknown -z option.
362static void checkZOptions(opt::InputArgList &Args) {391static void checkZOptions(opt::InputArgList &args) {
363 for (auto *Arg : Args.filtered(OPT_z))392 for (auto *arg : args.filtered(OPT_z))
364 if (!isKnownZFlag(Arg->getValue()))393 if (!isKnownZFlag(arg->getValue()))
365 error("unknown -z value: " + StringRef(Arg->getValue()));394 error("unknown -z value: " + StringRef(arg->getValue()));
366}395}
367396
368void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {397void LinkerDriver::main(ArrayRef<const char *> argsArr) {
369 ELFOptTable Parser;398 ELFOptTable parser;
370 opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));399 opt::InputArgList args = parser.parse(argsArr.slice(1));
371400
372 // Interpret this flag early because error() depends on them.401 // Interpret this flag early because error() depends on them.
373 errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20);402 errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20);
403 checkZOptions(args);
374404
375 // Handle -help405 // Handle -help
376 if (Args.hasArg(OPT_help)) {406 if (args.hasArg(OPT_help)) {
377 printHelp();407 printHelp();
378 return;408 return;
379 }409 }
...@@ -393,213 +423,218 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {...@@ -393,213 +423,218 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) {
393 // lot of "configure" scripts out there that are generated by old version423 // lot of "configure" scripts out there that are generated by old version
394 // of Libtool. We cannot convince every software developer to migrate to424 // of Libtool. We cannot convince every software developer to migrate to
395 // the latest version and re-generate scripts. So we have this hack.425 // the latest version and re-generate scripts. So we have this hack.
396 if (Args.hasArg(OPT_v) || Args.hasArg(OPT_version))426 if (args.hasArg(OPT_v) || args.hasArg(OPT_version))
397 message(getLLDVersion() + " (compatible with GNU linkers)");427 message(getLLDVersion() + " (compatible with GNU linkers)");
398428
399 if (const char *Path = getReproduceOption(Args)) {429 if (const char *path = getReproduceOption(args)) {
400 // Note that --reproduce is a debug option so you can ignore it430 // Note that --reproduce is a debug option so you can ignore it
401 // if you are trying to understand the whole picture of the code.431 // if you are trying to understand the whole picture of the code.
402 Expected<std::unique_ptr<TarWriter>> ErrOrWriter =432 Expected<std::unique_ptr<TarWriter>> errOrWriter =
403 TarWriter::create(Path, path::stem(Path));433 TarWriter::create(path, path::stem(path));
404 if (ErrOrWriter) {434 if (errOrWriter) {
405 Tar = std::move(*ErrOrWriter);435 tar = std::move(*errOrWriter);
406 Tar->append("response.txt", createResponseFile(Args));436 tar->append("response.txt", createResponseFile(args));
407 Tar->append("version.txt", getLLDVersion() + "\n");437 tar->append("version.txt", getLLDVersion() + "\n");
408 } else {438 } else {
409 error("--reproduce: " + toString(ErrOrWriter.takeError()));439 error("--reproduce: " + toString(errOrWriter.takeError()));
410 }440 }
411 }441 }
412442
413 readConfigs(Args);443 readConfigs(args);
414 checkZOptions(Args);
415444
416 // The behavior of -v or --version is a bit strange, but this is445 // The behavior of -v or --version is a bit strange, but this is
417 // needed for compatibility with GNU linkers.446 // needed for compatibility with GNU linkers.
418 if (Args.hasArg(OPT_v) && !Args.hasArg(OPT_INPUT))447 if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT))
419 return;448 return;
420 if (Args.hasArg(OPT_version))449 if (args.hasArg(OPT_version))
421 return;450 return;
422451
423 initLLVM();452 initLLVM();
424 createFiles(Args);453 createFiles(args);
425 if (errorCount())454 if (errorCount())
426 return;455 return;
427456
428 inferMachineType();457 inferMachineType();
429 setConfigs(Args);458 setConfigs(args);
430 checkOptions();459 checkOptions();
431 if (errorCount())460 if (errorCount())
432 return;461 return;
433462
434 switch (Config->EKind) {463 // The Target instance handles target-specific stuff, such as applying
464 // relocations or writing a PLT section. It also contains target-dependent
465 // values such as a default image base address.
466 target = getTarget();
467
468 switch (config->ekind) {
435 case ELF32LEKind:469 case ELF32LEKind:
436 link<ELF32LE>(Args);470 link<ELF32LE>(args);
437 return;471 return;
438 case ELF32BEKind:472 case ELF32BEKind:
439 link<ELF32BE>(Args);473 link<ELF32BE>(args);
440 return;474 return;
441 case ELF64LEKind:475 case ELF64LEKind:
442 link<ELF64LE>(Args);476 link<ELF64LE>(args);
443 return;477 return;
444 case ELF64BEKind:478 case ELF64BEKind:
445 link<ELF64BE>(Args);479 link<ELF64BE>(args);
446 return;480 return;
447 default:481 default:
448 llvm_unreachable("unknown Config->EKind");482 llvm_unreachable("unknown Config->EKind");
449 }483 }
450}484}
451485
452static std::string getRpath(opt::InputArgList &Args) {486static std::string getRpath(opt::InputArgList &args) {
453 std::vector<StringRef> V = args::getStrings(Args, OPT_rpath);487 std::vector<StringRef> v = args::getStrings(args, OPT_rpath);
454 return llvm::join(V.begin(), V.end(), ":");488 return llvm::join(v.begin(), v.end(), ":");
455}489}
456490
457// Determines what we should do if there are remaining unresolved491// Determines what we should do if there are remaining unresolved
458// symbols after the name resolution.492// symbols after the name resolution.
459static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &Args) {493static UnresolvedPolicy getUnresolvedSymbolPolicy(opt::InputArgList &args) {
460 UnresolvedPolicy ErrorOrWarn = Args.hasFlag(OPT_error_unresolved_symbols,494 UnresolvedPolicy errorOrWarn = args.hasFlag(OPT_error_unresolved_symbols,
461 OPT_warn_unresolved_symbols, true)495 OPT_warn_unresolved_symbols, true)
462 ? UnresolvedPolicy::ReportError496 ? UnresolvedPolicy::ReportError
463 : UnresolvedPolicy::Warn;497 : UnresolvedPolicy::Warn;
464498
465 // Process the last of -unresolved-symbols, -no-undefined or -z defs.499 // Process the last of -unresolved-symbols, -no-undefined or -z defs.
466 for (auto *Arg : llvm::reverse(Args)) {500 for (auto *arg : llvm::reverse(args)) {
467 switch (Arg->getOption().getID()) {501 switch (arg->getOption().getID()) {
468 case OPT_unresolved_symbols: {502 case OPT_unresolved_symbols: {
469 StringRef S = Arg->getValue();503 StringRef s = arg->getValue();
470 if (S == "ignore-all" || S == "ignore-in-object-files")504 if (s == "ignore-all" || s == "ignore-in-object-files")
471 return UnresolvedPolicy::Ignore;505 return UnresolvedPolicy::Ignore;
472 if (S == "ignore-in-shared-libs" || S == "report-all")506 if (s == "ignore-in-shared-libs" || s == "report-all")
473 return ErrorOrWarn;507 return errorOrWarn;
474 error("unknown --unresolved-symbols value: " + S);508 error("unknown --unresolved-symbols value: " + s);
475 continue;509 continue;
476 }510 }
477 case OPT_no_undefined:511 case OPT_no_undefined:
478 return ErrorOrWarn;512 return errorOrWarn;
479 case OPT_z:513 case OPT_z:
480 if (StringRef(Arg->getValue()) == "defs")514 if (StringRef(arg->getValue()) == "defs")
481 return ErrorOrWarn;515 return errorOrWarn;
482 continue;516 continue;
483 }517 }
484 }518 }
485519
486 // -shared implies -unresolved-symbols=ignore-all because missing520 // -shared implies -unresolved-symbols=ignore-all because missing
487 // symbols are likely to be resolved at runtime using other DSOs.521 // symbols are likely to be resolved at runtime using other DSOs.
488 if (Config->Shared)522 if (config->shared)
489 return UnresolvedPolicy::Ignore;523 return UnresolvedPolicy::Ignore;
490 return ErrorOrWarn;524 return errorOrWarn;
491}525}
492526
493static Target2Policy getTarget2(opt::InputArgList &Args) {527static Target2Policy getTarget2(opt::InputArgList &args) {
494 StringRef S = Args.getLastArgValue(OPT_target2, "got-rel");528 StringRef s = args.getLastArgValue(OPT_target2, "got-rel");
495 if (S == "rel")529 if (s == "rel")
496 return Target2Policy::Rel;530 return Target2Policy::Rel;
497 if (S == "abs")531 if (s == "abs")
498 return Target2Policy::Abs;532 return Target2Policy::Abs;
499 if (S == "got-rel")533 if (s == "got-rel")
500 return Target2Policy::GotRel;534 return Target2Policy::GotRel;
501 error("unknown --target2 option: " + S);535 error("unknown --target2 option: " + s);
502 return Target2Policy::GotRel;536 return Target2Policy::GotRel;
503}537}
504538
505static bool isOutputFormatBinary(opt::InputArgList &Args) {539static bool isOutputFormatBinary(opt::InputArgList &args) {
506 StringRef S = Args.getLastArgValue(OPT_oformat, "elf");540 StringRef s = args.getLastArgValue(OPT_oformat, "elf");
507 if (S == "binary")541 if (s == "binary")
508 return true;542 return true;
509 if (!S.startswith("elf"))543 if (!s.startswith("elf"))
510 error("unknown --oformat value: " + S);544 error("unknown --oformat value: " + s);
511 return false;545 return false;
512}546}
513547
514static DiscardPolicy getDiscard(opt::InputArgList &Args) {548static DiscardPolicy getDiscard(opt::InputArgList &args) {
515 if (Args.hasArg(OPT_relocatable))549 if (args.hasArg(OPT_relocatable))
516 return DiscardPolicy::None;550 return DiscardPolicy::None;
517551
518 auto *Arg =552 auto *arg =
519 Args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none);553 args.getLastArg(OPT_discard_all, OPT_discard_locals, OPT_discard_none);
520 if (!Arg)554 if (!arg)
521 return DiscardPolicy::Default;555 return DiscardPolicy::Default;
522 if (Arg->getOption().getID() == OPT_discard_all)556 if (arg->getOption().getID() == OPT_discard_all)
523 return DiscardPolicy::All;557 return DiscardPolicy::All;
524 if (Arg->getOption().getID() == OPT_discard_locals)558 if (arg->getOption().getID() == OPT_discard_locals)
525 return DiscardPolicy::Locals;559 return DiscardPolicy::Locals;
526 return DiscardPolicy::None;560 return DiscardPolicy::None;
527}561}
528562
529static StringRef getDynamicLinker(opt::InputArgList &Args) {563static StringRef getDynamicLinker(opt::InputArgList &args) {
530 auto *Arg = Args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker);564 auto *arg = args.getLastArg(OPT_dynamic_linker, OPT_no_dynamic_linker);
531 if (!Arg || Arg->getOption().getID() == OPT_no_dynamic_linker)565 if (!arg || arg->getOption().getID() == OPT_no_dynamic_linker)
532 return "";566 return "";
533 return Arg->getValue();567 return arg->getValue();
534}568}
535569
536static ICFLevel getICF(opt::InputArgList &Args) {570static ICFLevel getICF(opt::InputArgList &args) {
537 auto *Arg = Args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all);571 auto *arg = args.getLastArg(OPT_icf_none, OPT_icf_safe, OPT_icf_all);
538 if (!Arg || Arg->getOption().getID() == OPT_icf_none)572 if (!arg || arg->getOption().getID() == OPT_icf_none)
539 return ICFLevel::None;573 return ICFLevel::None;
540 if (Arg->getOption().getID() == OPT_icf_safe)574 if (arg->getOption().getID() == OPT_icf_safe)
541 return ICFLevel::Safe;575 return ICFLevel::Safe;
542 return ICFLevel::All;576 return ICFLevel::All;
543}577}
544578
545static StripPolicy getStrip(opt::InputArgList &Args) {579static StripPolicy getStrip(opt::InputArgList &args) {
546 if (Args.hasArg(OPT_relocatable))580 if (args.hasArg(OPT_relocatable))
547 return StripPolicy::None;581 return StripPolicy::None;
548582
549 auto *Arg = Args.getLastArg(OPT_strip_all, OPT_strip_debug);583 auto *arg = args.getLastArg(OPT_strip_all, OPT_strip_debug);
550 if (!Arg)584 if (!arg)
551 return StripPolicy::None;585 return StripPolicy::None;
552 if (Arg->getOption().getID() == OPT_strip_all)586 if (arg->getOption().getID() == OPT_strip_all)
553 return StripPolicy::All;587 return StripPolicy::All;
554 return StripPolicy::Debug;588 return StripPolicy::Debug;
555}589}
556590
557static uint64_t parseSectionAddress(StringRef S, const opt::Arg &Arg) {591static uint64_t parseSectionAddress(StringRef s, opt::InputArgList &args,
558 uint64_t VA = 0;592 const opt::Arg &arg) {
559 if (S.startswith("0x"))593 uint64_t va = 0;
560 S = S.drop_front(2);594 if (s.startswith("0x"))
561 if (!to_integer(S, VA, 16))595 s = s.drop_front(2);
562 error("invalid argument: " + toString(Arg));596 if (!to_integer(s, va, 16))
563 return VA;597 error("invalid argument: " + arg.getAsString(args));
598 return va;
564}599}
565600
566static StringMap<uint64_t> getSectionStartMap(opt::InputArgList &Args) {601static StringMap<uint64_t> getSectionStartMap(opt::InputArgList &args) {
567 StringMap<uint64_t> Ret;602 StringMap<uint64_t> ret;
568 for (auto *Arg : Args.filtered(OPT_section_start)) {603 for (auto *arg : args.filtered(OPT_section_start)) {
569 StringRef Name;604 StringRef name;
570 StringRef Addr;605 StringRef addr;
571 std::tie(Name, Addr) = StringRef(Arg->getValue()).split('=');606 std::tie(name, addr) = StringRef(arg->getValue()).split('=');
572 Ret[Name] = parseSectionAddress(Addr, *Arg);607 ret[name] = parseSectionAddress(addr, args, *arg);
573 }608 }
574609
575 if (auto *Arg = Args.getLastArg(OPT_Ttext))610 if (auto *arg = args.getLastArg(OPT_Ttext))
576 Ret[".text"] = parseSectionAddress(Arg->getValue(), *Arg);611 ret[".text"] = parseSectionAddress(arg->getValue(), args, *arg);
577 if (auto *Arg = Args.getLastArg(OPT_Tdata))612 if (auto *arg = args.getLastArg(OPT_Tdata))
578 Ret[".data"] = parseSectionAddress(Arg->getValue(), *Arg);613 ret[".data"] = parseSectionAddress(arg->getValue(), args, *arg);
579 if (auto *Arg = Args.getLastArg(OPT_Tbss))614 if (auto *arg = args.getLastArg(OPT_Tbss))
580 Ret[".bss"] = parseSectionAddress(Arg->getValue(), *Arg);615 ret[".bss"] = parseSectionAddress(arg->getValue(), args, *arg);
581 return Ret;616 return ret;
582}617}
583618
584static SortSectionPolicy getSortSection(opt::InputArgList &Args) {619static SortSectionPolicy getSortSection(opt::InputArgList &args) {
585 StringRef S = Args.getLastArgValue(OPT_sort_section);620 StringRef s = args.getLastArgValue(OPT_sort_section);
586 if (S == "alignment")621 if (s == "alignment")
587 return SortSectionPolicy::Alignment;622 return SortSectionPolicy::Alignment;
588 if (S == "name")623 if (s == "name")
589 return SortSectionPolicy::Name;624 return SortSectionPolicy::Name;
590 if (!S.empty())625 if (!s.empty())
591 error("unknown --sort-section rule: " + S);626 error("unknown --sort-section rule: " + s);
592 return SortSectionPolicy::Default;627 return SortSectionPolicy::Default;
593}628}
594629
595static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &Args) {630static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &args) {
596 StringRef S = Args.getLastArgValue(OPT_orphan_handling, "place");631 StringRef s = args.getLastArgValue(OPT_orphan_handling, "place");
597 if (S == "warn")632 if (s == "warn")
598 return OrphanHandlingPolicy::Warn;633 return OrphanHandlingPolicy::Warn;
599 if (S == "error")634 if (s == "error")
600 return OrphanHandlingPolicy::Error;635 return OrphanHandlingPolicy::Error;
601 if (S != "place")636 if (s != "place")
602 error("unknown --orphan-handling mode: " + S);637 error("unknown --orphan-handling mode: " + s);
603 return OrphanHandlingPolicy::Place;638 return OrphanHandlingPolicy::Place;
604}639}
605640
...@@ -607,388 +642,412 @@ static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &Args) {...@@ -607,388 +642,412 @@ static OrphanHandlingPolicy getOrphanHandling(opt::InputArgList &Args) {
607// synonym for "sha1" because all our hash functions including642// synonym for "sha1" because all our hash functions including
608// -build-id=sha1 are actually tree hashes for performance reasons.643// -build-id=sha1 are actually tree hashes for performance reasons.
609static std::pair<BuildIdKind, std::vector<uint8_t>>644static std::pair<BuildIdKind, std::vector<uint8_t>>
610getBuildId(opt::InputArgList &Args) {645getBuildId(opt::InputArgList &args) {
611 auto *Arg = Args.getLastArg(OPT_build_id, OPT_build_id_eq);646 auto *arg = args.getLastArg(OPT_build_id, OPT_build_id_eq);
612 if (!Arg)647 if (!arg)
613 return {BuildIdKind::None, {}};648 return {BuildIdKind::None, {}};
614649
615 if (Arg->getOption().getID() == OPT_build_id)650 if (arg->getOption().getID() == OPT_build_id)
616 return {BuildIdKind::Fast, {}};651 return {BuildIdKind::Fast, {}};
617652
618 StringRef S = Arg->getValue();653 StringRef s = arg->getValue();
619 if (S == "fast")654 if (s == "fast")
620 return {BuildIdKind::Fast, {}};655 return {BuildIdKind::Fast, {}};
621 if (S == "md5")656 if (s == "md5")
622 return {BuildIdKind::Md5, {}};657 return {BuildIdKind::Md5, {}};
623 if (S == "sha1" || S == "tree")658 if (s == "sha1" || s == "tree")
624 return {BuildIdKind::Sha1, {}};659 return {BuildIdKind::Sha1, {}};
625 if (S == "uuid")660 if (s == "uuid")
626 return {BuildIdKind::Uuid, {}};661 return {BuildIdKind::Uuid, {}};
627 if (S.startswith("0x"))662 if (s.startswith("0x"))
628 return {BuildIdKind::Hexstring, parseHex(S.substr(2))};663 return {BuildIdKind::Hexstring, parseHex(s.substr(2))};
629664
630 if (S != "none")665 if (s != "none")
631 error("unknown --build-id style: " + S);666 error("unknown --build-id style: " + s);
632 return {BuildIdKind::None, {}};667 return {BuildIdKind::None, {}};
633}668}
634669
635static std::pair<bool, bool> getPackDynRelocs(opt::InputArgList &Args) {670static std::pair<bool, bool> getPackDynRelocs(opt::InputArgList &args) {
636 StringRef S = Args.getLastArgValue(OPT_pack_dyn_relocs, "none");671 StringRef s = args.getLastArgValue(OPT_pack_dyn_relocs, "none");
637 if (S == "android")672 if (s == "android")
638 return {true, false};673 return {true, false};
639 if (S == "relr")674 if (s == "relr")
640 return {false, true};675 return {false, true};
641 if (S == "android+relr")676 if (s == "android+relr")
642 return {true, true};677 return {true, true};
643678
644 if (S != "none")679 if (s != "none")
645 error("unknown -pack-dyn-relocs format: " + S);680 error("unknown -pack-dyn-relocs format: " + s);
646 return {false, false};681 return {false, false};
647}682}
648683
649static void readCallGraph(MemoryBufferRef MB) {684static void readCallGraph(MemoryBufferRef mb) {
650 // Build a map from symbol name to section685 // Build a map from symbol name to section
651 DenseMap<StringRef, Symbol *> Map;686 DenseMap<StringRef, Symbol *> map;
652 for (InputFile *File : ObjectFiles)687 for (InputFile *file : objectFiles)
653 for (Symbol *Sym : File->getSymbols())688 for (Symbol *sym : file->getSymbols())
654 Map[Sym->getName()] = Sym;689 map[sym->getName()] = sym;
655690
656 auto FindSection = [&](StringRef Name) -> InputSectionBase * {691 auto findSection = [&](StringRef name) -> InputSectionBase * {
657 Symbol *Sym = Map.lookup(Name);692 Symbol *sym = map.lookup(name);
658 if (!Sym) {693 if (!sym) {
659 if (Config->WarnSymbolOrdering)694 if (config->warnSymbolOrdering)
660 warn(MB.getBufferIdentifier() + ": no such symbol: " + Name);695 warn(mb.getBufferIdentifier() + ": no such symbol: " + name);
661 return nullptr;696 return nullptr;
662 }697 }
663 maybeWarnUnorderableSymbol(Sym);698 maybeWarnUnorderableSymbol(sym);
664699
665 if (Defined *DR = dyn_cast_or_null<Defined>(Sym))700 if (Defined *dr = dyn_cast_or_null<Defined>(sym))
666 return dyn_cast_or_null<InputSectionBase>(DR->Section);701 return dyn_cast_or_null<InputSectionBase>(dr->section);
667 return nullptr;702 return nullptr;
668 };703 };
669704
670 for (StringRef Line : args::getLines(MB)) {705 for (StringRef line : args::getLines(mb)) {
671 SmallVector<StringRef, 3> Fields;706 SmallVector<StringRef, 3> fields;
672 Line.split(Fields, ' ');707 line.split(fields, ' ');
673 uint64_t Count;708 uint64_t count;
674709
675 if (Fields.size() != 3 || !to_integer(Fields[2], Count)) {710 if (fields.size() != 3 || !to_integer(fields[2], count)) {
676 error(MB.getBufferIdentifier() + ": parse error");711 error(mb.getBufferIdentifier() + ": parse error");
677 return;712 return;
678 }713 }
679714
680 if (InputSectionBase *From = FindSection(Fields[0]))715 if (InputSectionBase *from = findSection(fields[0]))
681 if (InputSectionBase *To = FindSection(Fields[1]))716 if (InputSectionBase *to = findSection(fields[1]))
682 Config->CallGraphProfile[std::make_pair(From, To)] += Count;717 config->callGraphProfile[std::make_pair(from, to)] += count;
683 }718 }
684}719}
685720
686template <class ELFT> static void readCallGraphsFromObjectFiles() {721template <class ELFT> static void readCallGraphsFromObjectFiles() {
687 for (auto File : ObjectFiles) {722 for (auto file : objectFiles) {
688 auto *Obj = cast<ObjFile<ELFT>>(File);723 auto *obj = cast<ObjFile<ELFT>>(file);
689724
690 for (const Elf_CGProfile_Impl<ELFT> &CGPE : Obj->CGProfile) {725 for (const Elf_CGProfile_Impl<ELFT> &cgpe : obj->cgProfile) {
691 auto *FromSym = dyn_cast<Defined>(&Obj->getSymbol(CGPE.cgp_from));726 auto *fromSym = dyn_cast<Defined>(&obj->getSymbol(cgpe.cgp_from));
692 auto *ToSym = dyn_cast<Defined>(&Obj->getSymbol(CGPE.cgp_to));727 auto *toSym = dyn_cast<Defined>(&obj->getSymbol(cgpe.cgp_to));
693 if (!FromSym || !ToSym)728 if (!fromSym || !toSym)
694 continue;729 continue;
695730
696 auto *From = dyn_cast_or_null<InputSectionBase>(FromSym->Section);731 auto *from = dyn_cast_or_null<InputSectionBase>(fromSym->section);
697 auto *To = dyn_cast_or_null<InputSectionBase>(ToSym->Section);732 auto *to = dyn_cast_or_null<InputSectionBase>(toSym->section);
698 if (From && To)733 if (from && to)
699 Config->CallGraphProfile[{From, To}] += CGPE.cgp_weight;734 config->callGraphProfile[{from, to}] += cgpe.cgp_weight;
700 }735 }
701 }736 }
702}737}
703738
704static bool getCompressDebugSections(opt::InputArgList &Args) {739static bool getCompressDebugSections(opt::InputArgList &args) {
705 StringRef S = Args.getLastArgValue(OPT_compress_debug_sections, "none");740 StringRef s = args.getLastArgValue(OPT_compress_debug_sections, "none");
706 if (S == "none")741 if (s == "none")
707 return false;742 return false;
708 if (S != "zlib")743 if (s != "zlib")
709 error("unknown --compress-debug-sections value: " + S);744 error("unknown --compress-debug-sections value: " + s);
710 if (!zlib::isAvailable())745 if (!zlib::isAvailable())
711 error("--compress-debug-sections: zlib is not available");746 error("--compress-debug-sections: zlib is not available");
712 return true;747 return true;
713}748}
714749
715static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &Args,750static std::pair<StringRef, StringRef> getOldNewOptions(opt::InputArgList &args,
716 unsigned Id) {751 unsigned id) {
717 auto *Arg = Args.getLastArg(Id);752 auto *arg = args.getLastArg(id);
718 if (!Arg)753 if (!arg)
719 return {"", ""};754 return {"", ""};
720755
721 StringRef S = Arg->getValue();756 StringRef s = arg->getValue();
722 std::pair<StringRef, StringRef> Ret = S.split(';');757 std::pair<StringRef, StringRef> ret = s.split(';');
723 if (Ret.second.empty())758 if (ret.second.empty())
724 error(Arg->getSpelling() + " expects 'old;new' format, but got " + S);759 error(arg->getSpelling() + " expects 'old;new' format, but got " + s);
725 return Ret;760 return ret;
726}761}
727762
728// Parse the symbol ordering file and warn for any duplicate entries.763// Parse the symbol ordering file and warn for any duplicate entries.
729static std::vector<StringRef> getSymbolOrderingFile(MemoryBufferRef MB) {764static std::vector<StringRef> getSymbolOrderingFile(MemoryBufferRef mb) {
730 SetVector<StringRef> Names;765 SetVector<StringRef> names;
731 for (StringRef S : args::getLines(MB))766 for (StringRef s : args::getLines(mb))
732 if (!Names.insert(S) && Config->WarnSymbolOrdering)767 if (!names.insert(s) && config->warnSymbolOrdering)
733 warn(MB.getBufferIdentifier() + ": duplicate ordered symbol: " + S);768 warn(mb.getBufferIdentifier() + ": duplicate ordered symbol: " + s);
734769
735 return Names.takeVector();770 return names.takeVector();
736}771}
737772
738static void parseClangOption(StringRef Opt, const Twine &Msg) {773static void parseClangOption(StringRef opt, const Twine &msg) {
739 std::string Err;774 std::string err;
740 raw_string_ostream OS(Err);775 raw_string_ostream os(err);
741776
742 const char *Argv[] = {Config->ProgName.data(), Opt.data()};777 const char *argv[] = {config->progName.data(), opt.data()};
743 if (cl::ParseCommandLineOptions(2, Argv, "", &OS))778 if (cl::ParseCommandLineOptions(2, argv, "", &os))
744 return;779 return;
745 OS.flush();780 os.flush();
746 error(Msg + ": " + StringRef(Err).trim());781 error(msg + ": " + StringRef(err).trim());
747}782}
748783
749// Initializes Config members by the command line options.784// Initializes Config members by the command line options.
750void LinkerDriver::readConfigs(opt::InputArgList &Args) {785static void readConfigs(opt::InputArgList &args) {
751 errorHandler().Verbose = Args.hasArg(OPT_verbose);786 errorHandler().verbose = args.hasArg(OPT_verbose);
752 errorHandler().FatalWarnings =787 errorHandler().fatalWarnings =
753 Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);788 args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
754 ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true);789 errorHandler().vsDiagnostics =
755790 args.hasArg(OPT_visual_studio_diagnostics_format, false);
756 Config->AllowMultipleDefinition =791 threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true);
757 Args.hasFlag(OPT_allow_multiple_definition,792
793 config->allowMultipleDefinition =
794 args.hasFlag(OPT_allow_multiple_definition,
758 OPT_no_allow_multiple_definition, false) ||795 OPT_no_allow_multiple_definition, false) ||
759 hasZOption(Args, "muldefs");796 hasZOption(args, "muldefs");
760 Config->AuxiliaryList = args::getStrings(Args, OPT_auxiliary);797 config->allowShlibUndefined =
761 Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic);798 args.hasFlag(OPT_allow_shlib_undefined, OPT_no_allow_shlib_undefined,
762 Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions);799 args.hasArg(OPT_shared));
763 Config->CheckSections =800 config->auxiliaryList = args::getStrings(args, OPT_auxiliary);
764 Args.hasFlag(OPT_check_sections, OPT_no_check_sections, true);801 config->bsymbolic = args.hasArg(OPT_Bsymbolic);
765 Config->Chroot = Args.getLastArgValue(OPT_chroot);802 config->bsymbolicFunctions = args.hasArg(OPT_Bsymbolic_functions);
766 Config->CompressDebugSections = getCompressDebugSections(Args);803 config->checkSections =
767 Config->Cref = Args.hasFlag(OPT_cref, OPT_no_cref, false);804 args.hasFlag(OPT_check_sections, OPT_no_check_sections, true);
768 Config->DefineCommon = Args.hasFlag(OPT_define_common, OPT_no_define_common,805 config->chroot = args.getLastArgValue(OPT_chroot);
769 !Args.hasArg(OPT_relocatable));806 config->compressDebugSections = getCompressDebugSections(args);
770 Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);807 config->cref = args.hasFlag(OPT_cref, OPT_no_cref, false);
771 Config->DisableVerify = Args.hasArg(OPT_disable_verify);808 config->defineCommon = args.hasFlag(OPT_define_common, OPT_no_define_common,
772 Config->Discard = getDiscard(Args);809 !args.hasArg(OPT_relocatable));
773 Config->DwoDir = Args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq);810 config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
774 Config->DynamicLinker = getDynamicLinker(Args);811 config->dependentLibraries = args.hasFlag(OPT_dependent_libraries, OPT_no_dependent_libraries, true);
775 Config->EhFrameHdr =812 config->disableVerify = args.hasArg(OPT_disable_verify);
776 Args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false);813 config->discard = getDiscard(args);
777 Config->EmitLLVM = Args.hasArg(OPT_plugin_opt_emit_llvm, false);814 config->dwoDir = args.getLastArgValue(OPT_plugin_opt_dwo_dir_eq);
778 Config->EmitRelocs = Args.hasArg(OPT_emit_relocs);815 config->dynamicLinker = getDynamicLinker(args);
779 Config->CallGraphProfileSort = Args.hasFlag(816 config->ehFrameHdr =
817 args.hasFlag(OPT_eh_frame_hdr, OPT_no_eh_frame_hdr, false);
818 config->emitLLVM = args.hasArg(OPT_plugin_opt_emit_llvm, false);
819 config->emitRelocs = args.hasArg(OPT_emit_relocs);
820 config->callGraphProfileSort = args.hasFlag(
780 OPT_call_graph_profile_sort, OPT_no_call_graph_profile_sort, true);821 OPT_call_graph_profile_sort, OPT_no_call_graph_profile_sort, true);
781 Config->EnableNewDtags =822 config->enableNewDtags =
782 Args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true);823 args.hasFlag(OPT_enable_new_dtags, OPT_disable_new_dtags, true);
783 Config->Entry = Args.getLastArgValue(OPT_entry);824 config->entry = args.getLastArgValue(OPT_entry);
784 Config->ExecuteOnly =825 config->executeOnly =
785 Args.hasFlag(OPT_execute_only, OPT_no_execute_only, false);826 args.hasFlag(OPT_execute_only, OPT_no_execute_only, false);
786 Config->ExportDynamic =827 config->exportDynamic =
787 Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);828 args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);
788 Config->FilterList = args::getStrings(Args, OPT_filter);829 config->filterList = args::getStrings(args, OPT_filter);
789 Config->Fini = Args.getLastArgValue(OPT_fini, "_fini");830 config->fini = args.getLastArgValue(OPT_fini, "_fini");
790 Config->FixCortexA53Errata843419 = Args.hasArg(OPT_fix_cortex_a53_843419);831 config->fixCortexA53Errata843419 = args.hasArg(OPT_fix_cortex_a53_843419);
791 Config->GcSections = Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false);832 config->forceBTI = args.hasArg(OPT_force_bti);
792 Config->GnuUnique = Args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true);833 config->requireCET = args.hasArg(OPT_require_cet);
793 Config->GdbIndex = Args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false);834 config->gcSections = args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false);
794 Config->ICF = getICF(Args);835 config->gnuUnique = args.hasFlag(OPT_gnu_unique, OPT_no_gnu_unique, true);
795 Config->IgnoreDataAddressEquality =836 config->gdbIndex = args.hasFlag(OPT_gdb_index, OPT_no_gdb_index, false);
796 Args.hasArg(OPT_ignore_data_address_equality);837 config->icf = getICF(args);
797 Config->IgnoreFunctionAddressEquality =838 config->ignoreDataAddressEquality =
798 Args.hasArg(OPT_ignore_function_address_equality);839 args.hasArg(OPT_ignore_data_address_equality);
799 Config->Init = Args.getLastArgValue(OPT_init, "_init");840 config->ignoreFunctionAddressEquality =
800 Config->LTOAAPipeline = Args.getLastArgValue(OPT_lto_aa_pipeline);841 args.hasArg(OPT_ignore_function_address_equality);
801 Config->LTODebugPassManager = Args.hasArg(OPT_lto_debug_pass_manager);842 config->init = args.getLastArgValue(OPT_init, "_init");
802 Config->LTONewPassManager = Args.hasArg(OPT_lto_new_pass_manager);843 config->ltoAAPipeline = args.getLastArgValue(OPT_lto_aa_pipeline);
803 Config->LTONewPmPasses = Args.getLastArgValue(OPT_lto_newpm_passes);844 config->ltoCSProfileGenerate = args.hasArg(OPT_lto_cs_profile_generate);
804 Config->LTOO = args::getInteger(Args, OPT_lto_O, 2);845 config->ltoCSProfileFile = args.getLastArgValue(OPT_lto_cs_profile_file);
805 Config->LTOObjPath = Args.getLastArgValue(OPT_plugin_opt_obj_path_eq);846 config->ltoDebugPassManager = args.hasArg(OPT_lto_debug_pass_manager);
806 Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1);847 config->ltoNewPassManager = args.hasArg(OPT_lto_new_pass_manager);
807 Config->LTOSampleProfile = Args.getLastArgValue(OPT_lto_sample_profile);848 config->ltoNewPmPasses = args.getLastArgValue(OPT_lto_newpm_passes);
808 Config->MapFile = Args.getLastArgValue(OPT_Map);849 config->ltoo = args::getInteger(args, OPT_lto_O, 2);
809 Config->MipsGotSize = args::getInteger(Args, OPT_mips_got_size, 0xfff0);850 config->ltoObjPath = args.getLastArgValue(OPT_plugin_opt_obj_path_eq);
810 Config->MergeArmExidx =851 config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
811 Args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true);852 config->ltoSampleProfile = args.getLastArgValue(OPT_lto_sample_profile);
812 Config->NoinhibitExec = Args.hasArg(OPT_noinhibit_exec);853 config->mapFile = args.getLastArgValue(OPT_Map);
813 Config->Nostdlib = Args.hasArg(OPT_nostdlib);854 config->mipsGotSize = args::getInteger(args, OPT_mips_got_size, 0xfff0);
814 Config->OFormatBinary = isOutputFormatBinary(Args);855 config->mergeArmExidx =
815 Config->Omagic = Args.hasFlag(OPT_omagic, OPT_no_omagic, false);856 args.hasFlag(OPT_merge_exidx_entries, OPT_no_merge_exidx_entries, true);
816 Config->OptRemarksFilename = Args.getLastArgValue(OPT_opt_remarks_filename);857 config->nmagic = args.hasFlag(OPT_nmagic, OPT_no_nmagic, false);
817 Config->OptRemarksWithHotness = Args.hasArg(OPT_opt_remarks_with_hotness);858 config->noinhibitExec = args.hasArg(OPT_noinhibit_exec);
818 Config->Optimize = args::getInteger(Args, OPT_O, 1);859 config->nostdlib = args.hasArg(OPT_nostdlib);
819 Config->OrphanHandling = getOrphanHandling(Args);860 config->oFormatBinary = isOutputFormatBinary(args);
820 Config->OutputFile = Args.getLastArgValue(OPT_o);861 config->omagic = args.hasFlag(OPT_omagic, OPT_no_omagic, false);
821 Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false);862 config->optRemarksFilename = args.getLastArgValue(OPT_opt_remarks_filename);
822 Config->PrintIcfSections =863 config->optRemarksPasses = args.getLastArgValue(OPT_opt_remarks_passes);
823 Args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false);864 config->optRemarksWithHotness = args.hasArg(OPT_opt_remarks_with_hotness);
824 Config->PrintGcSections =865 config->optRemarksFormat = args.getLastArgValue(OPT_opt_remarks_format);
825 Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);866 config->optimize = args::getInteger(args, OPT_O, 1);
826 Config->Rpath = getRpath(Args);867 config->orphanHandling = getOrphanHandling(args);
827 Config->Relocatable = Args.hasArg(OPT_relocatable);868 config->outputFile = args.getLastArgValue(OPT_o);
828 Config->SaveTemps = Args.hasArg(OPT_save_temps);869 config->pacPlt = args.hasArg(OPT_pac_plt);
829 Config->SearchPaths = args::getStrings(Args, OPT_library_path);870 config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
830 Config->SectionStartMap = getSectionStartMap(Args);871 config->printIcfSections =
831 Config->Shared = Args.hasArg(OPT_shared);872 args.hasFlag(OPT_print_icf_sections, OPT_no_print_icf_sections, false);
832 Config->SingleRoRx = Args.hasArg(OPT_no_rosegment);873 config->printGcSections =
833 Config->SoName = Args.getLastArgValue(OPT_soname);874 args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
834 Config->SortSection = getSortSection(Args);875 config->printSymbolOrder =
835 Config->SplitStackAdjustSize = args::getInteger(Args, OPT_split_stack_adjust_size, 16384);876 args.getLastArgValue(OPT_print_symbol_order);
836 Config->Strip = getStrip(Args);877 config->rpath = getRpath(args);
837 Config->Sysroot = Args.getLastArgValue(OPT_sysroot);878 config->relocatable = args.hasArg(OPT_relocatable);
838 Config->Target1Rel = Args.hasFlag(OPT_target1_rel, OPT_target1_abs, false);879 config->saveTemps = args.hasArg(OPT_save_temps);
839 Config->Target2 = getTarget2(Args);880 config->searchPaths = args::getStrings(args, OPT_library_path);
840 Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir);881 config->sectionStartMap = getSectionStartMap(args);
841 Config->ThinLTOCachePolicy = CHECK(882 config->shared = args.hasArg(OPT_shared);
842 parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)),883 config->singleRoRx = args.hasArg(OPT_no_rosegment);
884 config->soName = args.getLastArgValue(OPT_soname);
885 config->sortSection = getSortSection(args);
886 config->splitStackAdjustSize = args::getInteger(args, OPT_split_stack_adjust_size, 16384);
887 config->strip = getStrip(args);
888 config->sysroot = args.getLastArgValue(OPT_sysroot);
889 config->target1Rel = args.hasFlag(OPT_target1_rel, OPT_target1_abs, false);
890 config->target2 = getTarget2(args);
891 config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
892 config->thinLTOCachePolicy = CHECK(
893 parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
843 "--thinlto-cache-policy: invalid cache policy");894 "--thinlto-cache-policy: invalid cache policy");
844 Config->ThinLTOEmitImportsFiles =895 config->thinLTOEmitImportsFiles =
845 Args.hasArg(OPT_plugin_opt_thinlto_emit_imports_files);896 args.hasArg(OPT_plugin_opt_thinlto_emit_imports_files);
846 Config->ThinLTOIndexOnly = Args.hasArg(OPT_plugin_opt_thinlto_index_only) ||897 config->thinLTOIndexOnly = args.hasArg(OPT_plugin_opt_thinlto_index_only) ||
847 Args.hasArg(OPT_plugin_opt_thinlto_index_only_eq);898 args.hasArg(OPT_plugin_opt_thinlto_index_only_eq);
848 Config->ThinLTOIndexOnlyArg =899 config->thinLTOIndexOnlyArg =
849 Args.getLastArgValue(OPT_plugin_opt_thinlto_index_only_eq);900 args.getLastArgValue(OPT_plugin_opt_thinlto_index_only_eq);
850 Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u);901 config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u);
851 Config->ThinLTOObjectSuffixReplace =902 config->thinLTOObjectSuffixReplace =
852 getOldNewOptions(Args, OPT_plugin_opt_thinlto_object_suffix_replace_eq);903 getOldNewOptions(args, OPT_plugin_opt_thinlto_object_suffix_replace_eq);
853 Config->ThinLTOPrefixReplace =904 config->thinLTOPrefixReplace =
854 getOldNewOptions(Args, OPT_plugin_opt_thinlto_prefix_replace_eq);905 getOldNewOptions(args, OPT_plugin_opt_thinlto_prefix_replace_eq);
855 Config->Trace = Args.hasArg(OPT_trace);906 config->trace = args.hasArg(OPT_trace);
856 Config->Undefined = args::getStrings(Args, OPT_undefined);907 config->undefined = args::getStrings(args, OPT_undefined);
857 Config->UndefinedVersion =908 config->undefinedVersion =
858 Args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true);909 args.hasFlag(OPT_undefined_version, OPT_no_undefined_version, true);
859 Config->UseAndroidRelrTags = Args.hasFlag(910 config->useAndroidRelrTags = args.hasFlag(
860 OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false);911 OPT_use_android_relr_tags, OPT_no_use_android_relr_tags, false);
861 Config->UnresolvedSymbols = getUnresolvedSymbolPolicy(Args);912 config->unresolvedSymbols = getUnresolvedSymbolPolicy(args);
862 Config->WarnBackrefs =913 config->warnBackrefs =
863 Args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false);914 args.hasFlag(OPT_warn_backrefs, OPT_no_warn_backrefs, false);
864 Config->WarnCommon = Args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);915 config->warnCommon = args.hasFlag(OPT_warn_common, OPT_no_warn_common, false);
865 Config->WarnIfuncTextrel =916 config->warnIfuncTextrel =
866 Args.hasFlag(OPT_warn_ifunc_textrel, OPT_no_warn_ifunc_textrel, false);917 args.hasFlag(OPT_warn_ifunc_textrel, OPT_no_warn_ifunc_textrel, false);
867 Config->WarnSymbolOrdering =918 config->warnSymbolOrdering =
868 Args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);919 args.hasFlag(OPT_warn_symbol_ordering, OPT_no_warn_symbol_ordering, true);
869 Config->ZCombreloc = getZFlag(Args, "combreloc", "nocombreloc", true);920 config->zCombreloc = getZFlag(args, "combreloc", "nocombreloc", true);
870 Config->ZCopyreloc = getZFlag(Args, "copyreloc", "nocopyreloc", true);921 config->zCopyreloc = getZFlag(args, "copyreloc", "nocopyreloc", true);
871 Config->ZExecstack = getZFlag(Args, "execstack", "noexecstack", false);922 config->zExecstack = getZFlag(args, "execstack", "noexecstack", false);
872 Config->ZGlobal = hasZOption(Args, "global");923 config->zGlobal = hasZOption(args, "global");
873 Config->ZHazardplt = hasZOption(Args, "hazardplt");924 config->zHazardplt = hasZOption(args, "hazardplt");
874 Config->ZInitfirst = hasZOption(Args, "initfirst");925 config->zIfuncNoplt = hasZOption(args, "ifunc-noplt");
875 Config->ZInterpose = hasZOption(Args, "interpose");926 config->zInitfirst = hasZOption(args, "initfirst");
876 Config->ZKeepTextSectionPrefix = getZFlag(927 config->zInterpose = hasZOption(args, "interpose");
877 Args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);928 config->zKeepTextSectionPrefix = getZFlag(
878 Config->ZNodefaultlib = hasZOption(Args, "nodefaultlib");929 args, "keep-text-section-prefix", "nokeep-text-section-prefix", false);
879 Config->ZNodelete = hasZOption(Args, "nodelete");930 config->zNodefaultlib = hasZOption(args, "nodefaultlib");
880 Config->ZNodlopen = hasZOption(Args, "nodlopen");931 config->zNodelete = hasZOption(args, "nodelete");
881 Config->ZNow = getZFlag(Args, "now", "lazy", false);932 config->zNodlopen = hasZOption(args, "nodlopen");
882 Config->ZOrigin = hasZOption(Args, "origin");933 config->zNow = getZFlag(args, "now", "lazy", false);
883 Config->ZRelro = getZFlag(Args, "relro", "norelro", true);934 config->zOrigin = hasZOption(args, "origin");
884 Config->ZRetpolineplt = hasZOption(Args, "retpolineplt");935 config->zRelro = getZFlag(args, "relro", "norelro", true);
885 Config->ZRodynamic = hasZOption(Args, "rodynamic");936 config->zRetpolineplt = hasZOption(args, "retpolineplt");
886 Config->ZStackSize = args::getZOptionValue(Args, OPT_z, "stack-size", 0);937 config->zRodynamic = hasZOption(args, "rodynamic");
887 Config->ZText = getZFlag(Args, "text", "notext", true);938 config->zStackSize = args::getZOptionValue(args, OPT_z, "stack-size", 0);
888 Config->ZWxneeded = hasZOption(Args, "wxneeded");939 config->zText = getZFlag(args, "text", "notext", true);
940 config->zWxneeded = hasZOption(args, "wxneeded");
889941
890 // Parse LTO options.942 // Parse LTO options.
891 if (auto *Arg = Args.getLastArg(OPT_plugin_opt_mcpu_eq))943 if (auto *arg = args.getLastArg(OPT_plugin_opt_mcpu_eq))
892 parseClangOption(Saver.save("-mcpu=" + StringRef(Arg->getValue())),944 parseClangOption(saver.save("-mcpu=" + StringRef(arg->getValue())),
893 Arg->getSpelling());945 arg->getSpelling());
894946
895 for (auto *Arg : Args.filtered(OPT_plugin_opt))947 for (auto *arg : args.filtered(OPT_plugin_opt))
896 parseClangOption(Arg->getValue(), Arg->getSpelling());948 parseClangOption(arg->getValue(), arg->getSpelling());
897949
898 // Parse -mllvm options.950 // Parse -mllvm options.
899 for (auto *Arg : Args.filtered(OPT_mllvm))951 for (auto *arg : args.filtered(OPT_mllvm))
900 parseClangOption(Arg->getValue(), Arg->getSpelling());952 parseClangOption(arg->getValue(), arg->getSpelling());
901953
902 if (Config->LTOO > 3)954 if (config->ltoo > 3)
903 error("invalid optimization level for LTO: " + Twine(Config->LTOO));955 error("invalid optimization level for LTO: " + Twine(config->ltoo));
904 if (Config->LTOPartitions == 0)956 if (config->ltoPartitions == 0)
905 error("--lto-partitions: number of threads must be > 0");957 error("--lto-partitions: number of threads must be > 0");
906 if (Config->ThinLTOJobs == 0)958 if (config->thinLTOJobs == 0)
907 error("--thinlto-jobs: number of threads must be > 0");959 error("--thinlto-jobs: number of threads must be > 0");
908960
909 if (Config->SplitStackAdjustSize < 0)961 if (config->splitStackAdjustSize < 0)
910 error("--split-stack-adjust-size: size must be >= 0");962 error("--split-stack-adjust-size: size must be >= 0");
911963
912 // Parse ELF{32,64}{LE,BE} and CPU type.964 // Parse ELF{32,64}{LE,BE} and CPU type.
913 if (auto *Arg = Args.getLastArg(OPT_m)) {965 if (auto *arg = args.getLastArg(OPT_m)) {
914 StringRef S = Arg->getValue();966 StringRef s = arg->getValue();
915 std::tie(Config->EKind, Config->EMachine, Config->OSABI) =967 std::tie(config->ekind, config->emachine, config->osabi) =
916 parseEmulation(S);968 parseEmulation(s);
917 Config->MipsN32Abi = (S == "elf32btsmipn32" || S == "elf32ltsmipn32");969 config->mipsN32Abi = (s == "elf32btsmipn32" || s == "elf32ltsmipn32");
918 Config->Emulation = S;970 config->emulation = s;
919 }971 }
920972
921 // Parse -hash-style={sysv,gnu,both}.973 // Parse -hash-style={sysv,gnu,both}.
922 if (auto *Arg = Args.getLastArg(OPT_hash_style)) {974 if (auto *arg = args.getLastArg(OPT_hash_style)) {
923 StringRef S = Arg->getValue();975 StringRef s = arg->getValue();
924 if (S == "sysv")976 if (s == "sysv")
925 Config->SysvHash = true;977 config->sysvHash = true;
926 else if (S == "gnu")978 else if (s == "gnu")
927 Config->GnuHash = true;979 config->gnuHash = true;
928 else if (S == "both")980 else if (s == "both")
929 Config->SysvHash = Config->GnuHash = true;981 config->sysvHash = config->gnuHash = true;
930 else982 else
931 error("unknown -hash-style: " + S);983 error("unknown -hash-style: " + s);
932 }984 }
933985
934 if (Args.hasArg(OPT_print_map))986 if (args.hasArg(OPT_print_map))
935 Config->MapFile = "-";987 config->mapFile = "-";
936988
937 // --omagic is an option to create old-fashioned executables in which989 // Page alignment can be disabled by the -n (--nmagic) and -N (--omagic).
938 // .text segments are writable. Today, the option is still in use to990 // As PT_GNU_RELRO relies on Paging, do not create it when we have disabled
939 // create special-purpose programs such as boot loaders. It doesn't991 // it.
940 // make sense to create PT_GNU_RELRO for such executables.992 if (config->nmagic || config->omagic)
941 if (Config->Omagic)993 config->zRelro = false;
942 Config->ZRelro = false;994
943995 std::tie(config->buildId, config->buildIdVector) = getBuildId(args);
944 std::tie(Config->BuildId, Config->BuildIdVector) = getBuildId(Args);996
945997 std::tie(config->androidPackDynRelocs, config->relrPackDynRelocs) =
946 std::tie(Config->AndroidPackDynRelocs, Config->RelrPackDynRelocs) =998 getPackDynRelocs(args);
947 getPackDynRelocs(Args);999
9481000 if (auto *arg = args.getLastArg(OPT_symbol_ordering_file)){
949 if (auto *Arg = Args.getLastArg(OPT_symbol_ordering_file))1001 if (args.hasArg(OPT_call_graph_ordering_file))
950 if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))1002 error("--symbol-ordering-file and --call-graph-order-file "
951 Config->SymbolOrderingFile = getSymbolOrderingFile(*Buffer);1003 "may not be used together");
1004 if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue())){
1005 config->symbolOrderingFile = getSymbolOrderingFile(*buffer);
1006 // Also need to disable CallGraphProfileSort to prevent
1007 // LLD order symbols with CGProfile
1008 config->callGraphProfileSort = false;
1009 }
1010 }
9521011
953 // If --retain-symbol-file is used, we'll keep only the symbols listed in1012 // If --retain-symbol-file is used, we'll keep only the symbols listed in
954 // the file and discard all others.1013 // the file and discard all others.
955 if (auto *Arg = Args.getLastArg(OPT_retain_symbols_file)) {1014 if (auto *arg = args.getLastArg(OPT_retain_symbols_file)) {
956 Config->DefaultSymbolVersion = VER_NDX_LOCAL;1015 config->defaultSymbolVersion = VER_NDX_LOCAL;
957 if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))1016 if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
958 for (StringRef S : args::getLines(*Buffer))1017 for (StringRef s : args::getLines(*buffer))
959 Config->VersionScriptGlobals.push_back(1018 config->versionScriptGlobals.push_back(
960 {S, /*IsExternCpp*/ false, /*HasWildcard*/ false});1019 {s, /*IsExternCpp*/ false, /*HasWildcard*/ false});
961 }1020 }
9621021
963 bool HasExportDynamic =1022 bool hasExportDynamic =
964 Args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);1023 args.hasFlag(OPT_export_dynamic, OPT_no_export_dynamic, false);
9651024
966 // Parses -dynamic-list and -export-dynamic-symbol. They make some1025 // Parses -dynamic-list and -export-dynamic-symbol. They make some
967 // symbols private. Note that -export-dynamic takes precedence over them1026 // symbols private. Note that -export-dynamic takes precedence over them
968 // as it says all symbols should be exported.1027 // as it says all symbols should be exported.
969 if (!HasExportDynamic) {1028 if (!hasExportDynamic) {
970 for (auto *Arg : Args.filtered(OPT_dynamic_list))1029 for (auto *arg : args.filtered(OPT_dynamic_list))
971 if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))1030 if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
972 readDynamicList(*Buffer);1031 readDynamicList(*buffer);
9731032
974 for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol))1033 for (auto *arg : args.filtered(OPT_export_dynamic_symbol))
975 Config->DynamicList.push_back(1034 config->dynamicList.push_back(
976 {Arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false});1035 {arg->getValue(), /*IsExternCpp*/ false, /*HasWildcard*/ false});
977 }1036 }
9781037
979 // If --export-dynamic-symbol=foo is given and symbol foo is defined in1038 // If --export-dynamic-symbol=foo is given and symbol foo is defined in
980 // an object file in an archive file, that object file should be pulled1039 // an object file in an archive file, that object file should be pulled
981 // out and linked. (It doesn't have to behave like that from technical1040 // out and linked. (It doesn't have to behave like that from technical
982 // point of view, but this is needed for compatibility with GNU.)1041 // point of view, but this is needed for compatibility with GNU.)
983 for (auto *Arg : Args.filtered(OPT_export_dynamic_symbol))1042 for (auto *arg : args.filtered(OPT_export_dynamic_symbol))
984 Config->Undefined.push_back(Arg->getValue());1043 config->undefined.push_back(arg->getValue());
9851044
986 for (auto *Arg : Args.filtered(OPT_version_script))1045 for (auto *arg : args.filtered(OPT_version_script))
987 if (Optional<std::string> Path = searchScript(Arg->getValue())) {1046 if (Optional<std::string> path = searchScript(arg->getValue())) {
988 if (Optional<MemoryBufferRef> Buffer = readFile(*Path))1047 if (Optional<MemoryBufferRef> buffer = readFile(*path))
989 readVersionScript(*Buffer);1048 readVersionScript(*buffer);
990 } else {1049 } else {
991 error(Twine("cannot find version script ") + Arg->getValue());1050 error(Twine("cannot find version script ") + arg->getValue());
992 }1051 }
993}1052}
9941053
...@@ -996,18 +1055,18 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {...@@ -996,18 +1055,18 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) {
996// command line options, but computed based on other Config values.1055// command line options, but computed based on other Config values.
997// This function initialize such members. See Config.h for the details1056// This function initialize such members. See Config.h for the details
998// of these values.1057// of these values.
999static void setConfigs(opt::InputArgList &Args) {1058static void setConfigs(opt::InputArgList &args) {
1000 ELFKind K = Config->EKind;1059 ELFKind k = config->ekind;
1001 uint16_t M = Config->EMachine;1060 uint16_t m = config->emachine;
10021061
1003 Config->CopyRelocs = (Config->Relocatable || Config->EmitRelocs);1062 config->copyRelocs = (config->relocatable || config->emitRelocs);
1004 Config->Is64 = (K == ELF64LEKind || K == ELF64BEKind);1063 config->is64 = (k == ELF64LEKind || k == ELF64BEKind);
1005 Config->IsLE = (K == ELF32LEKind || K == ELF64LEKind);1064 config->isLE = (k == ELF32LEKind || k == ELF64LEKind);
1006 Config->Endianness = Config->IsLE ? endianness::little : endianness::big;1065 config->endianness = config->isLE ? endianness::little : endianness::big;
1007 Config->IsMips64EL = (K == ELF64LEKind && M == EM_MIPS);1066 config->isMips64EL = (k == ELF64LEKind && m == EM_MIPS);
1008 Config->Pic = Config->Pie || Config->Shared;1067 config->isPic = config->pie || config->shared;
1009 Config->PicThunk = Args.hasArg(OPT_pic_veneer, Config->Pic);1068 config->picThunk = args.hasArg(OPT_pic_veneer, config->isPic);
1010 Config->Wordsize = Config->Is64 ? 8 : 4;1069 config->wordsize = config->is64 ? 8 : 4;
10111070
1012 // ELF defines two different ways to store relocation addends as shown below:1071 // ELF defines two different ways to store relocation addends as shown below:
1013 //1072 //
...@@ -1022,148 +1081,150 @@ static void setConfigs(opt::InputArgList &Args) {...@@ -1022,148 +1081,150 @@ static void setConfigs(opt::InputArgList &Args) {
1022 // You cannot choose which one, Rel or Rela, you want to use. Instead each1081 // You cannot choose which one, Rel or Rela, you want to use. Instead each
1023 // ABI defines which one you need to use. The following expression expresses1082 // ABI defines which one you need to use. The following expression expresses
1024 // that.1083 // that.
1025 Config->IsRela = M == EM_AARCH64 || M == EM_AMDGPU || M == EM_HEXAGON ||1084 config->isRela = m == EM_AARCH64 || m == EM_AMDGPU || m == EM_HEXAGON ||
1026 M == EM_PPC || M == EM_PPC64 || M == EM_RISCV ||1085 m == EM_PPC || m == EM_PPC64 || m == EM_RISCV ||
1027 M == EM_X86_64;1086 m == EM_X86_64;
10281087
1029 // If the output uses REL relocations we must store the dynamic relocation1088 // If the output uses REL relocations we must store the dynamic relocation
1030 // addends to the output sections. We also store addends for RELA relocations1089 // addends to the output sections. We also store addends for RELA relocations
1031 // if --apply-dynamic-relocs is used.1090 // if --apply-dynamic-relocs is used.
1032 // We default to not writing the addends when using RELA relocations since1091 // We default to not writing the addends when using RELA relocations since
1033 // any standard conforming tool can find it in r_addend.1092 // any standard conforming tool can find it in r_addend.
1034 Config->WriteAddends = Args.hasFlag(OPT_apply_dynamic_relocs,1093 config->writeAddends = args.hasFlag(OPT_apply_dynamic_relocs,
1035 OPT_no_apply_dynamic_relocs, false) ||1094 OPT_no_apply_dynamic_relocs, false) ||
1036 !Config->IsRela;1095 !config->isRela;
10371096
1038 Config->TocOptimize =1097 config->tocOptimize =
1039 Args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, M == EM_PPC64);1098 args.hasFlag(OPT_toc_optimize, OPT_no_toc_optimize, m == EM_PPC64);
1040}1099}
10411100
1042// Returns a value of "-format" option.1101// Returns a value of "-format" option.
1043static bool isFormatBinary(StringRef S) {1102static bool isFormatBinary(StringRef s) {
1044 if (S == "binary")1103 if (s == "binary")
1045 return true;1104 return true;
1046 if (S == "elf" || S == "default")1105 if (s == "elf" || s == "default")
1047 return false;1106 return false;
1048 error("unknown -format value: " + S +1107 error("unknown -format value: " + s +
1049 " (supported formats: elf, default, binary)");1108 " (supported formats: elf, default, binary)");
1050 return false;1109 return false;
1051}1110}
10521111
1053void LinkerDriver::createFiles(opt::InputArgList &Args) {1112void LinkerDriver::createFiles(opt::InputArgList &args) {
1054 // For --{push,pop}-state.1113 // For --{push,pop}-state.
1055 std::vector<std::tuple<bool, bool, bool>> Stack;1114 std::vector<std::tuple<bool, bool, bool>> stack;
10561115
1057 // Iterate over argv to process input files and positional arguments.1116 // Iterate over argv to process input files and positional arguments.
1058 for (auto *Arg : Args) {1117 for (auto *arg : args) {
1059 switch (Arg->getOption().getUnaliasedOption().getID()) {1118 switch (arg->getOption().getID()) {
1060 case OPT_library:1119 case OPT_library:
1061 addLibrary(Arg->getValue());1120 addLibrary(arg->getValue());
1062 break;1121 break;
1063 case OPT_INPUT:1122 case OPT_INPUT:
1064 addFile(Arg->getValue(), /*WithLOption=*/false);1123 addFile(arg->getValue(), /*withLOption=*/false);
1065 break;1124 break;
1066 case OPT_defsym: {1125 case OPT_defsym: {
1067 StringRef From;1126 StringRef from;
1068 StringRef To;1127 StringRef to;
1069 std::tie(From, To) = StringRef(Arg->getValue()).split('=');1128 std::tie(from, to) = StringRef(arg->getValue()).split('=');
1070 if (From.empty() || To.empty())1129 if (from.empty() || to.empty())
1071 error("-defsym: syntax error: " + StringRef(Arg->getValue()));1130 error("-defsym: syntax error: " + StringRef(arg->getValue()));
1072 else1131 else
1073 readDefsym(From, MemoryBufferRef(To, "-defsym"));1132 readDefsym(from, MemoryBufferRef(to, "-defsym"));
1074 break;1133 break;
1075 }1134 }
1076 case OPT_script:1135 case OPT_script:
1077 if (Optional<std::string> Path = searchScript(Arg->getValue())) {1136 if (Optional<std::string> path = searchScript(arg->getValue())) {
1078 if (Optional<MemoryBufferRef> MB = readFile(*Path))1137 if (Optional<MemoryBufferRef> mb = readFile(*path))
1079 readLinkerScript(*MB);1138 readLinkerScript(*mb);
1080 break;1139 break;
1081 }1140 }
1082 error(Twine("cannot find linker script ") + Arg->getValue());1141 error(Twine("cannot find linker script ") + arg->getValue());
1083 break;1142 break;
1084 case OPT_as_needed:1143 case OPT_as_needed:
1085 Config->AsNeeded = true;1144 config->asNeeded = true;
1086 break;1145 break;
1087 case OPT_format:1146 case OPT_format:
1088 Config->FormatBinary = isFormatBinary(Arg->getValue());1147 config->formatBinary = isFormatBinary(arg->getValue());
1089 break;1148 break;
1090 case OPT_no_as_needed:1149 case OPT_no_as_needed:
1091 Config->AsNeeded = false;1150 config->asNeeded = false;
1092 break;1151 break;
1093 case OPT_Bstatic:1152 case OPT_Bstatic:
1094 Config->Static = true;1153 case OPT_omagic:
1154 case OPT_nmagic:
1155 config->isStatic = true;
1095 break;1156 break;
1096 case OPT_Bdynamic:1157 case OPT_Bdynamic:
1097 Config->Static = false;1158 config->isStatic = false;
1098 break;1159 break;
1099 case OPT_whole_archive:1160 case OPT_whole_archive:
1100 InWholeArchive = true;1161 inWholeArchive = true;
1101 break;1162 break;
1102 case OPT_no_whole_archive:1163 case OPT_no_whole_archive:
1103 InWholeArchive = false;1164 inWholeArchive = false;
1104 break;1165 break;
1105 case OPT_just_symbols:1166 case OPT_just_symbols:
1106 if (Optional<MemoryBufferRef> MB = readFile(Arg->getValue())) {1167 if (Optional<MemoryBufferRef> mb = readFile(arg->getValue())) {
1107 Files.push_back(createObjectFile(*MB));1168 files.push_back(createObjectFile(*mb));
1108 Files.back()->JustSymbols = true;1169 files.back()->justSymbols = true;
1109 }1170 }
1110 break;1171 break;
1111 case OPT_start_group:1172 case OPT_start_group:
1112 if (InputFile::IsInGroup)1173 if (InputFile::isInGroup)
1113 error("nested --start-group");1174 error("nested --start-group");
1114 InputFile::IsInGroup = true;1175 InputFile::isInGroup = true;
1115 break;1176 break;
1116 case OPT_end_group:1177 case OPT_end_group:
1117 if (!InputFile::IsInGroup)1178 if (!InputFile::isInGroup)
1118 error("stray --end-group");1179 error("stray --end-group");
1119 InputFile::IsInGroup = false;1180 InputFile::isInGroup = false;
1120 ++InputFile::NextGroupId;1181 ++InputFile::nextGroupId;
1121 break;1182 break;
1122 case OPT_start_lib:1183 case OPT_start_lib:
1123 if (InLib)1184 if (inLib)
1124 error("nested --start-lib");1185 error("nested --start-lib");
1125 if (InputFile::IsInGroup)1186 if (InputFile::isInGroup)
1126 error("may not nest --start-lib in --start-group");1187 error("may not nest --start-lib in --start-group");
1127 InLib = true;1188 inLib = true;
1128 InputFile::IsInGroup = true;1189 InputFile::isInGroup = true;
1129 break;1190 break;
1130 case OPT_end_lib:1191 case OPT_end_lib:
1131 if (!InLib)1192 if (!inLib)
1132 error("stray --end-lib");1193 error("stray --end-lib");
1133 InLib = false;1194 inLib = false;
1134 InputFile::IsInGroup = false;1195 InputFile::isInGroup = false;
1135 ++InputFile::NextGroupId;1196 ++InputFile::nextGroupId;
1136 break;1197 break;
1137 case OPT_push_state:1198 case OPT_push_state:
1138 Stack.emplace_back(Config->AsNeeded, Config->Static, InWholeArchive);1199 stack.emplace_back(config->asNeeded, config->isStatic, inWholeArchive);
1139 break;1200 break;
1140 case OPT_pop_state:1201 case OPT_pop_state:
1141 if (Stack.empty()) {1202 if (stack.empty()) {
1142 error("unbalanced --push-state/--pop-state");1203 error("unbalanced --push-state/--pop-state");
1143 break;1204 break;
1144 }1205 }
1145 std::tie(Config->AsNeeded, Config->Static, InWholeArchive) = Stack.back();1206 std::tie(config->asNeeded, config->isStatic, inWholeArchive) = stack.back();
1146 Stack.pop_back();1207 stack.pop_back();
1147 break;1208 break;
1148 }1209 }
1149 }1210 }
11501211
1151 if (Files.empty() && errorCount() == 0)1212 if (files.empty() && errorCount() == 0)
1152 error("no input files");1213 error("no input files");
1153}1214}
11541215
1155// If -m <machine_type> was not given, infer it from object files.1216// If -m <machine_type> was not given, infer it from object files.
1156void LinkerDriver::inferMachineType() {1217void LinkerDriver::inferMachineType() {
1157 if (Config->EKind != ELFNoneKind)1218 if (config->ekind != ELFNoneKind)
1158 return;1219 return;
11591220
1160 for (InputFile *F : Files) {1221 for (InputFile *f : files) {
1161 if (F->EKind == ELFNoneKind)1222 if (f->ekind == ELFNoneKind)
1162 continue;1223 continue;
1163 Config->EKind = F->EKind;1224 config->ekind = f->ekind;
1164 Config->EMachine = F->EMachine;1225 config->emachine = f->emachine;
1165 Config->OSABI = F->OSABI;1226 config->osabi = f->osabi;
1166 Config->MipsN32Abi = Config->EMachine == EM_MIPS && isMipsN32Abi(F);1227 config->mipsN32Abi = config->emachine == EM_MIPS && isMipsN32Abi(f);
1167 return;1228 return;
1168 }1229 }
1169 error("target emulation unknown: -m or at least one .o file required");1230 error("target emulation unknown: -m or at least one .o file required");
...@@ -1171,49 +1232,72 @@ void LinkerDriver::inferMachineType() {...@@ -1171,49 +1232,72 @@ void LinkerDriver::inferMachineType() {
11711232
1172// Parse -z max-page-size=<value>. The default value is defined by1233// Parse -z max-page-size=<value>. The default value is defined by
1173// each target.1234// each target.
1174static uint64_t getMaxPageSize(opt::InputArgList &Args) {1235static uint64_t getMaxPageSize(opt::InputArgList &args) {
1175 uint64_t Val = args::getZOptionValue(Args, OPT_z, "max-page-size",1236 uint64_t val = args::getZOptionValue(args, OPT_z, "max-page-size",
1176 Target->DefaultMaxPageSize);1237 target->defaultMaxPageSize);
1177 if (!isPowerOf2_64(Val))1238 if (!isPowerOf2_64(val))
1178 error("max-page-size: value isn't a power of 2");1239 error("max-page-size: value isn't a power of 2");
1179 return Val;1240 if (config->nmagic || config->omagic) {
1241 if (val != target->defaultMaxPageSize)
1242 warn("-z max-page-size set, but paging disabled by omagic or nmagic");
1243 return 1;
1244 }
1245 return val;
1246}
1247
1248// Parse -z common-page-size=<value>. The default value is defined by
1249// each target.
1250static uint64_t getCommonPageSize(opt::InputArgList &args) {
1251 uint64_t val = args::getZOptionValue(args, OPT_z, "common-page-size",
1252 target->defaultCommonPageSize);
1253 if (!isPowerOf2_64(val))
1254 error("common-page-size: value isn't a power of 2");
1255 if (config->nmagic || config->omagic) {
1256 if (val != target->defaultCommonPageSize)
1257 warn("-z common-page-size set, but paging disabled by omagic or nmagic");
1258 return 1;
1259 }
1260 // commonPageSize can't be larger than maxPageSize.
1261 if (val > config->maxPageSize)
1262 val = config->maxPageSize;
1263 return val;
1180}1264}
11811265
1182// Parses -image-base option.1266// Parses -image-base option.
1183static Optional<uint64_t> getImageBase(opt::InputArgList &Args) {1267static Optional<uint64_t> getImageBase(opt::InputArgList &args) {
1184 // Because we are using "Config->MaxPageSize" here, this function has to be1268 // Because we are using "Config->maxPageSize" here, this function has to be
1185 // called after the variable is initialized.1269 // called after the variable is initialized.
1186 auto *Arg = Args.getLastArg(OPT_image_base);1270 auto *arg = args.getLastArg(OPT_image_base);
1187 if (!Arg)1271 if (!arg)
1188 return None;1272 return None;
11891273
1190 StringRef S = Arg->getValue();1274 StringRef s = arg->getValue();
1191 uint64_t V;1275 uint64_t v;
1192 if (!to_integer(S, V)) {1276 if (!to_integer(s, v)) {
1193 error("-image-base: number expected, but got " + S);1277 error("-image-base: number expected, but got " + s);
1194 return 0;1278 return 0;
1195 }1279 }
1196 if ((V % Config->MaxPageSize) != 0)1280 if ((v % config->maxPageSize) != 0)
1197 warn("-image-base: address isn't multiple of page size: " + S);1281 warn("-image-base: address isn't multiple of page size: " + s);
1198 return V;1282 return v;
1199}1283}
12001284
1201// Parses `--exclude-libs=lib,lib,...`.1285// Parses `--exclude-libs=lib,lib,...`.
1202// The library names may be delimited by commas or colons.1286// The library names may be delimited by commas or colons.
1203static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) {1287static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &args) {
1204 DenseSet<StringRef> Ret;1288 DenseSet<StringRef> ret;
1205 for (auto *Arg : Args.filtered(OPT_exclude_libs)) {1289 for (auto *arg : args.filtered(OPT_exclude_libs)) {
1206 StringRef S = Arg->getValue();1290 StringRef s = arg->getValue();
1207 for (;;) {1291 for (;;) {
1208 size_t Pos = S.find_first_of(",:");1292 size_t pos = s.find_first_of(",:");
1209 if (Pos == StringRef::npos)1293 if (pos == StringRef::npos)
1210 break;1294 break;
1211 Ret.insert(S.substr(0, Pos));1295 ret.insert(s.substr(0, pos));
1212 S = S.substr(Pos + 1);1296 s = s.substr(pos + 1);
1213 }1297 }
1214 Ret.insert(S);1298 ret.insert(s);
1215 }1299 }
1216 return Ret;1300 return ret;
1217}1301}
12181302
1219// Handles the -exclude-libs option. If a static library file is specified1303// Handles the -exclude-libs option. If a static library file is specified
...@@ -1222,139 +1306,247 @@ static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) {...@@ -1222,139 +1306,247 @@ static DenseSet<StringRef> getExcludeLibs(opt::InputArgList &Args) {
1222// A special library name "ALL" means all archive files.1306// A special library name "ALL" means all archive files.
1223//1307//
1224// This is not a popular option, but some programs such as bionic libc use it.1308// This is not a popular option, but some programs such as bionic libc use it.
1225template <class ELFT>1309static void excludeLibs(opt::InputArgList &args) {
1226static void excludeLibs(opt::InputArgList &Args) {1310 DenseSet<StringRef> libs = getExcludeLibs(args);
1227 DenseSet<StringRef> Libs = getExcludeLibs(Args);1311 bool all = libs.count("ALL");
1228 bool All = Libs.count("ALL");1312
12291313 auto visit = [&](InputFile *file) {
1230 auto Visit = [&](InputFile *File) {1314 if (!file->archiveName.empty())
1231 if (!File->ArchiveName.empty())1315 if (all || libs.count(path::filename(file->archiveName)))
1232 if (All || Libs.count(path::filename(File->ArchiveName)))1316 for (Symbol *sym : file->getSymbols())
1233 for (Symbol *Sym : File->getSymbols())1317 if (!sym->isLocal() && sym->file == file)
1234 if (!Sym->isLocal() && Sym->File == File)1318 sym->versionId = VER_NDX_LOCAL;
1235 Sym->VersionId = VER_NDX_LOCAL;
1236 };1319 };
12371320
1238 for (InputFile *File : ObjectFiles)1321 for (InputFile *file : objectFiles)
1239 Visit(File);1322 visit(file);
12401323
1241 for (BitcodeFile *File : BitcodeFiles)1324 for (BitcodeFile *file : bitcodeFiles)
1242 Visit(File);1325 visit(file);
1243}1326}
12441327
1245// Force Sym to be entered in the output. Used for -u or equivalent.1328// Force Sym to be entered in the output. Used for -u or equivalent.
1246template <class ELFT> static void handleUndefined(StringRef Name) {1329static void handleUndefined(Symbol *sym) {
1247 Symbol *Sym = Symtab->find(Name);1330 // Since a symbol may not be used inside the program, LTO may
1248 if (!Sym)1331 // eliminate it. Mark the symbol as "used" to prevent it.
1332 sym->isUsedInRegularObj = true;
1333
1334 if (sym->isLazy())
1335 sym->fetch();
1336}
1337
1338// As an extention to GNU linkers, lld supports a variant of `-u`
1339// which accepts wildcard patterns. All symbols that match a given
1340// pattern are handled as if they were given by `-u`.
1341static void handleUndefinedGlob(StringRef arg) {
1342 Expected<GlobPattern> pat = GlobPattern::create(arg);
1343 if (!pat) {
1344 error("--undefined-glob: " + toString(pat.takeError()));
1249 return;1345 return;
1346 }
12501347
1251 // Since symbol S may not be used inside the program, LTO may1348 std::vector<Symbol *> syms;
1252 // eliminate it. Mark the symbol as "used" to prevent it.1349 symtab->forEachSymbol([&](Symbol *sym) {
1253 Sym->IsUsedInRegularObj = true;1350 // Calling Sym->fetch() from here is not safe because it may
1351 // add new symbols to the symbol table, invalidating the
1352 // current iterator. So we just keep a note.
1353 if (pat->match(sym->getName()))
1354 syms.push_back(sym);
1355 });
12541356
1255 if (Sym->isLazy())1357 for (Symbol *sym : syms)
1256 Symtab->fetchLazy<ELFT>(Sym);1358 handleUndefined(sym);
1257}1359}
12581360
1259template <class ELFT> static void handleLibcall(StringRef Name) {1361static void handleLibcall(StringRef name) {
1260 Symbol *Sym = Symtab->find(Name);1362 Symbol *sym = symtab->find(name);
1261 if (!Sym || !Sym->isLazy())1363 if (!sym || !sym->isLazy())
1262 return;1364 return;
12631365
1264 MemoryBufferRef MB;1366 MemoryBufferRef mb;
1265 if (auto *LO = dyn_cast<LazyObject>(Sym))1367 if (auto *lo = dyn_cast<LazyObject>(sym))
1266 MB = LO->File->MB;1368 mb = lo->file->mb;
1267 else1369 else
1268 MB = cast<LazyArchive>(Sym)->getMemberBuffer();1370 mb = cast<LazyArchive>(sym)->getMemberBuffer();
12691371
1270 if (isBitcode(MB))1372 if (isBitcode(mb))
1271 Symtab->fetchLazy<ELFT>(Sym);1373 sym->fetch();
1374}
1375
1376// Replaces common symbols with defined symbols reside in .bss sections.
1377// This function is called after all symbol names are resolved. As a
1378// result, the passes after the symbol resolution won't see any
1379// symbols of type CommonSymbol.
1380static void replaceCommonSymbols() {
1381 symtab->forEachSymbol([](Symbol *sym) {
1382 auto *s = dyn_cast<CommonSymbol>(sym);
1383 if (!s)
1384 return;
1385
1386 auto *bss = make<BssSection>("COMMON", s->size, s->alignment);
1387 bss->file = s->file;
1388 bss->markDead();
1389 inputSections.push_back(bss);
1390 s->replace(Defined{s->file, s->getName(), s->binding, s->stOther, s->type,
1391 /*value=*/0, s->size, bss});
1392 });
1272}1393}
12731394
1274// If all references to a DSO happen to be weak, the DSO is not added1395// 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 symbols1396// to DT_NEEDED. If that happens, we need to eliminate shared symbols
1276// created from the DSO. Otherwise, they become dangling references1397// created from the DSO. Otherwise, they become dangling references
1277// that point to a non-existent DSO.1398// that point to a non-existent DSO.
1278template <class ELFT> static void demoteSharedSymbols() {1399static void demoteSharedSymbols() {
1279 for (Symbol *Sym : Symtab->getSymbols()) {1400 symtab->forEachSymbol([](Symbol *sym) {
1280 if (auto *S = dyn_cast<SharedSymbol>(Sym)) {1401 auto *s = dyn_cast<SharedSymbol>(sym);
1281 if (!S->getFile<ELFT>().IsNeeded) {1402 if (!s || s->getFile().isNeeded)
1282 bool Used = S->Used;1403 return;
1283 replaceSymbol<Undefined>(S, nullptr, S->getName(), STB_WEAK, S->StOther,1404
1284 S->Type);1405 bool used = s->used;
1285 S->Used = Used;1406 s->replace(Undefined{nullptr, s->getName(), STB_WEAK, s->stOther, s->type});
1286 }1407 s->used = used;
1287 }1408 });
1288 }
1289}1409}
12901410
1291// The section referred to by S is considered address-significant. Set the1411// The section referred to by `s` is considered address-significant. Set the
1292// KeepUnique flag on the section if appropriate.1412// keepUnique flag on the section if appropriate.
1293static void markAddrsig(Symbol *S) {1413static void markAddrsig(Symbol *s) {
1294 if (auto *D = dyn_cast_or_null<Defined>(S))1414 if (auto *d = dyn_cast_or_null<Defined>(s))
1295 if (D->Section)1415 if (d->section)
1296 // We don't need to keep text sections unique under --icf=all even if they1416 // We don't need to keep text sections unique under --icf=all even if they
1297 // are address-significant.1417 // are address-significant.
1298 if (Config->ICF == ICFLevel::Safe || !(D->Section->Flags & SHF_EXECINSTR))1418 if (config->icf == ICFLevel::Safe || !(d->section->flags & SHF_EXECINSTR))
1299 D->Section->KeepUnique = true;1419 d->section->keepUnique = true;
1300}1420}
13011421
1302// Record sections that define symbols mentioned in --keep-unique <symbol>1422// Record sections that define symbols mentioned in --keep-unique <symbol>
1303// and symbols referred to by address-significance tables. These sections are1423// and symbols referred to by address-significance tables. These sections are
1304// ineligible for ICF.1424// ineligible for ICF.
1305template <class ELFT>1425template <class ELFT>
1306static void findKeepUniqueSections(opt::InputArgList &Args) {1426static void findKeepUniqueSections(opt::InputArgList &args) {
1307 for (auto *Arg : Args.filtered(OPT_keep_unique)) {1427 for (auto *arg : args.filtered(OPT_keep_unique)) {
1308 StringRef Name = Arg->getValue();1428 StringRef name = arg->getValue();
1309 auto *D = dyn_cast_or_null<Defined>(Symtab->find(Name));1429 auto *d = dyn_cast_or_null<Defined>(symtab->find(name));
1310 if (!D || !D->Section) {1430 if (!d || !d->section) {
1311 warn("could not find symbol " + Name + " to keep unique");1431 warn("could not find symbol " + name + " to keep unique");
1312 continue;1432 continue;
1313 }1433 }
1314 D->Section->KeepUnique = true;1434 d->section->keepUnique = true;
1315 }1435 }
13161436
1317 // --icf=all --ignore-data-address-equality means that we can ignore1437 // --icf=all --ignore-data-address-equality means that we can ignore
1318 // the dynsym and address-significance tables entirely.1438 // the dynsym and address-significance tables entirely.
1319 if (Config->ICF == ICFLevel::All && Config->IgnoreDataAddressEquality)1439 if (config->icf == ICFLevel::All && config->ignoreDataAddressEquality)
1320 return;1440 return;
13211441
1322 // Symbols in the dynsym could be address-significant in other executables1442 // Symbols in the dynsym could be address-significant in other executables
1323 // or DSOs, so we conservatively mark them as address-significant.1443 // or DSOs, so we conservatively mark them as address-significant.
1324 for (Symbol *S : Symtab->getSymbols())1444 symtab->forEachSymbol([&](Symbol *sym) {
1325 if (S->includeInDynsym())1445 if (sym->includeInDynsym())
1326 markAddrsig(S);1446 markAddrsig(sym);
1447 });
13271448
1328 // Visit the address-significance table in each object file and mark each1449 // Visit the address-significance table in each object file and mark each
1329 // referenced symbol as address-significant.1450 // referenced symbol as address-significant.
1330 for (InputFile *F : ObjectFiles) {1451 for (InputFile *f : objectFiles) {
1331 auto *Obj = cast<ObjFile<ELFT>>(F);1452 auto *obj = cast<ObjFile<ELFT>>(f);
1332 ArrayRef<Symbol *> Syms = Obj->getSymbols();1453 ArrayRef<Symbol *> syms = obj->getSymbols();
1333 if (Obj->AddrsigSec) {1454 if (obj->addrsigSec) {
1334 ArrayRef<uint8_t> Contents =1455 ArrayRef<uint8_t> contents =
1335 check(Obj->getObj().getSectionContents(Obj->AddrsigSec));1456 check(obj->getObj().getSectionContents(obj->addrsigSec));
1336 const uint8_t *Cur = Contents.begin();1457 const uint8_t *cur = contents.begin();
1337 while (Cur != Contents.end()) {1458 while (cur != contents.end()) {
1338 unsigned Size;1459 unsigned size;
1339 const char *Err;1460 const char *err;
1340 uint64_t SymIndex = decodeULEB128(Cur, &Size, Contents.end(), &Err);1461 uint64_t symIndex = decodeULEB128(cur, &size, contents.end(), &err);
1341 if (Err)1462 if (err)
1342 fatal(toString(F) + ": could not decode addrsig section: " + Err);1463 fatal(toString(f) + ": could not decode addrsig section: " + err);
1343 markAddrsig(Syms[SymIndex]);1464 markAddrsig(syms[symIndex]);
1344 Cur += Size;1465 cur += size;
1345 }1466 }
1346 } else {1467 } else {
1347 // If an object file does not have an address-significance table,1468 // If an object file does not have an address-significance table,
1348 // conservatively mark all of its symbols as address-significant.1469 // conservatively mark all of its symbols as address-significant.
1349 for (Symbol *S : Syms)1470 for (Symbol *s : syms)
1350 markAddrsig(S);1471 markAddrsig(s);
1472 }
1473 }
1474}
1475
1476// This function reads a symbol partition specification section. These sections
1477// are used to control which partition a symbol is allocated to. See
1478// https://lld.llvm.org/Partitions.html for more details on partitions.
1479template <typename ELFT>
1480static void readSymbolPartitionSection(InputSectionBase *s) {
1481 // Read the relocation that refers to the partition's entry point symbol.
1482 Symbol *sym;
1483 if (s->areRelocsRela)
1484 sym = &s->getFile<ELFT>()->getRelocTargetSym(s->template relas<ELFT>()[0]);
1485 else
1486 sym = &s->getFile<ELFT>()->getRelocTargetSym(s->template rels<ELFT>()[0]);
1487 if (!isa<Defined>(sym) || !sym->includeInDynsym())
1488 return;
1489
1490 StringRef partName = reinterpret_cast<const char *>(s->data().data());
1491 for (Partition &part : partitions) {
1492 if (part.name == partName) {
1493 sym->partition = part.getNumber();
1494 return;
1351 }1495 }
1352 }1496 }
1497
1498 // Forbid partitions from being used on incompatible targets, and forbid them
1499 // from being used together with various linker features that assume a single
1500 // set of output sections.
1501 if (script->hasSectionsCommand)
1502 error(toString(s->file) +
1503 ": partitions cannot be used with the SECTIONS command");
1504 if (script->hasPhdrsCommands())
1505 error(toString(s->file) +
1506 ": partitions cannot be used with the PHDRS command");
1507 if (!config->sectionStartMap.empty())
1508 error(toString(s->file) + ": partitions cannot be used with "
1509 "--section-start, -Ttext, -Tdata or -Tbss");
1510 if (config->emachine == EM_MIPS)
1511 error(toString(s->file) + ": partitions cannot be used on this target");
1512
1513 // Impose a limit of no more than 254 partitions. This limit comes from the
1514 // sizes of the Partition fields in InputSectionBase and Symbol, as well as
1515 // the amount of space devoted to the partition number in RankFlags.
1516 if (partitions.size() == 254)
1517 fatal("may not have more than 254 partitions");
1518
1519 partitions.emplace_back();
1520 Partition &newPart = partitions.back();
1521 newPart.name = partName;
1522 sym->partition = newPart.getNumber();
1353}1523}
13541524
1355template <class ELFT> static Symbol *addUndefined(StringRef Name) {1525static Symbol *addUndefined(StringRef name) {
1356 return Symtab->addUndefined<ELFT>(Name, STB_GLOBAL, STV_DEFAULT, 0, false,1526 return symtab->addSymbol(
1357 nullptr);1527 Undefined{nullptr, name, STB_GLOBAL, STV_DEFAULT, 0});
1528}
1529
1530// This function is where all the optimizations of link-time
1531// optimization takes place. When LTO is in use, some input files are
1532// not in native object file format but in the LLVM bitcode format.
1533// This function compiles bitcode files into a few big native files
1534// using LLVM functions and replaces bitcode symbols with the results.
1535// Because all bitcode files that the program consists of are passed to
1536// the compiler at once, it can do a whole-program optimization.
1537template <class ELFT> void LinkerDriver::compileBitcodeFiles() {
1538 // Compile bitcode files and replace bitcode symbols.
1539 lto.reset(new BitcodeCompiler);
1540 for (BitcodeFile *file : bitcodeFiles)
1541 lto->add(*file);
1542
1543 for (InputFile *file : lto->compile()) {
1544 auto *obj = cast<ObjFile<ELFT>>(file);
1545 obj->parse(/*ignoreComdats=*/true);
1546 for (Symbol *sym : obj->getGlobalSymbols())
1547 sym->parseSymbolVersion();
1548 objectFiles.push_back(file);
1549 }
1358}1550}
13591551
1360// The --wrap option is a feature to rename symbols so that you can write1552// The --wrap option is a feature to rename symbols so that you can write
...@@ -1366,9 +1558,9 @@ template <class ELFT> static Symbol *addUndefined(StringRef Name) {...@@ -1366,9 +1558,9 @@ template <class ELFT> static Symbol *addUndefined(StringRef Name) {
1366//1558//
1367// This data structure is instantiated for each -wrap option.1559// This data structure is instantiated for each -wrap option.
1368struct WrappedSymbol {1560struct WrappedSymbol {
1369 Symbol *Sym;1561 Symbol *sym;
1370 Symbol *Real;1562 Symbol *real;
1371 Symbol *Wrap;1563 Symbol *wrap;
1372};1564};
13731565
1374// Handles -wrap option.1566// Handles -wrap option.
...@@ -1376,34 +1568,33 @@ struct WrappedSymbol {...@@ -1376,34 +1568,33 @@ struct WrappedSymbol {
1376// This function instantiates wrapper symbols. At this point, they seem1568// 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 so1569// like they are not being used at all, so we explicitly set some flags so
1378// that LTO won't eliminate them.1570// that LTO won't eliminate them.
1379template <class ELFT>1571static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
1380static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &Args) {1572 std::vector<WrappedSymbol> v;
1381 std::vector<WrappedSymbol> V;1573 DenseSet<StringRef> seen;
1382 DenseSet<StringRef> Seen;
13831574
1384 for (auto *Arg : Args.filtered(OPT_wrap)) {1575 for (auto *arg : args.filtered(OPT_wrap)) {
1385 StringRef Name = Arg->getValue();1576 StringRef name = arg->getValue();
1386 if (!Seen.insert(Name).second)1577 if (!seen.insert(name).second)
1387 continue;1578 continue;
13881579
1389 Symbol *Sym = Symtab->find(Name);1580 Symbol *sym = symtab->find(name);
1390 if (!Sym)1581 if (!sym)
1391 continue;1582 continue;
13921583
1393 Symbol *Real = addUndefined<ELFT>(Saver.save("__real_" + Name));1584 Symbol *real = addUndefined(saver.save("__real_" + name));
1394 Symbol *Wrap = addUndefined<ELFT>(Saver.save("__wrap_" + Name));1585 Symbol *wrap = addUndefined(saver.save("__wrap_" + name));
1395 V.push_back({Sym, Real, Wrap});1586 v.push_back({sym, real, wrap});
13961587
1397 // We want to tell LTO not to inline symbols to be overwritten1588 // We want to tell LTO not to inline symbols to be overwritten
1398 // because LTO doesn't know the final symbol contents after renaming.1589 // because LTO doesn't know the final symbol contents after renaming.
1399 Real->CanInline = false;1590 real->canInline = false;
1400 Sym->CanInline = false;1591 sym->canInline = false;
14011592
1402 // Tell LTO not to eliminate these symbols.1593 // Tell LTO not to eliminate these symbols.
1403 Sym->IsUsedInRegularObj = true;1594 sym->isUsedInRegularObj = true;
1404 Wrap->IsUsedInRegularObj = true;1595 wrap->isUsedInRegularObj = true;
1405 }1596 }
1406 return V;1597 return v;
1407}1598}
14081599
1409// Do renaming for -wrap by updating pointers to symbols.1600// Do renaming for -wrap by updating pointers to symbols.
...@@ -1411,27 +1602,63 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &Args) {...@@ -1411,27 +1602,63 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &Args) {
1411// When this function is executed, only InputFiles and symbol table1602// When this function is executed, only InputFiles and symbol table
1412// contain pointers to symbol objects. We visit them to replace pointers,1603// contain pointers to symbol objects. We visit them to replace pointers,
1413// so that wrapped symbols are swapped as instructed by the command line.1604// so that wrapped symbols are swapped as instructed by the command line.
1414template <class ELFT> static void wrapSymbols(ArrayRef<WrappedSymbol> Wrapped) {1605static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
1415 DenseMap<Symbol *, Symbol *> Map;1606 DenseMap<Symbol *, Symbol *> map;
1416 for (const WrappedSymbol &W : Wrapped) {1607 for (const WrappedSymbol &w : wrapped) {
1417 Map[W.Sym] = W.Wrap;1608 map[w.sym] = w.wrap;
1418 Map[W.Real] = W.Sym;1609 map[w.real] = w.sym;
1419 }1610 }
14201611
1421 // Update pointers in input files.1612 // Update pointers in input files.
1422 parallelForEach(ObjectFiles, [&](InputFile *File) {1613 parallelForEach(objectFiles, [&](InputFile *file) {
1423 std::vector<Symbol *> &Syms = File->getMutableSymbols();1614 MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
1424 for (size_t I = 0, E = Syms.size(); I != E; ++I)1615 for (size_t i = 0, e = syms.size(); i != e; ++i)
1425 if (Symbol *S = Map.lookup(Syms[I]))1616 if (Symbol *s = map.lookup(syms[i]))
1426 Syms[I] = S;1617 syms[i] = s;
1427 });1618 });
14281619
1429 // Update pointers in the symbol table.1620 // Update pointers in the symbol table.
1430 for (const WrappedSymbol &W : Wrapped)1621 for (const WrappedSymbol &w : wrapped)
1431 Symtab->wrap(W.Sym, W.Real, W.Wrap);1622 symtab->wrap(w.sym, w.real, w.wrap);
1432}1623}
14331624
1434static const char *LibcallRoutineNames[] = {1625// To enable CET (x86's hardware-assited control flow enforcement), each
1626// source file must be compiled with -fcf-protection. Object files compiled
1627// with the flag contain feature flags indicating that they are compatible
1628// with CET. We enable the feature only when all object files are compatible
1629// with CET.
1630//
1631// This function returns the merged feature flags. If 0, we cannot enable CET.
1632// This is also the case with AARCH64's BTI and PAC which use the similar
1633// GNU_PROPERTY_AARCH64_FEATURE_1_AND mechanism.
1634//
1635// Note that the CET-aware PLT is not implemented yet. We do error
1636// check only.
1637template <class ELFT> static uint32_t getAndFeatures() {
1638 if (config->emachine != EM_386 && config->emachine != EM_X86_64 &&
1639 config->emachine != EM_AARCH64)
1640 return 0;
1641
1642 uint32_t ret = -1;
1643 for (InputFile *f : objectFiles) {
1644 uint32_t features = cast<ObjFile<ELFT>>(f)->andFeatures;
1645 if (config->forceBTI && !(features & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)) {
1646 warn(toString(f) + ": --force-bti: file does not have BTI property");
1647 features |= GNU_PROPERTY_AARCH64_FEATURE_1_BTI;
1648 } else if (!features && config->requireCET)
1649 error(toString(f) + ": --require-cet: file is not compatible with CET");
1650 ret &= features;
1651 }
1652
1653 // Force enable pointer authentication Plt, we don't warn in this case as
1654 // this does not require support in the object for correctness.
1655 if (config->pacPlt)
1656 ret |= GNU_PROPERTY_AARCH64_FEATURE_1_PAC;
1657
1658 return ret;
1659}
1660
1661static const char *libcallRoutineNames[] = {
1435#define HANDLE_LIBCALL(code, name) name,1662#define HANDLE_LIBCALL(code, name) name,
1436#include "llvm/IR/RuntimeLibcalls.def"1663#include "llvm/IR/RuntimeLibcalls.def"
1437#undef HANDLE_LIBCALL1664#undef HANDLE_LIBCALL
...@@ -1439,53 +1666,48 @@ static const char *LibcallRoutineNames[] = {...@@ -1439,53 +1666,48 @@ static const char *LibcallRoutineNames[] = {
14391666
1440// Do actual linking. Note that when this function is called,1667// Do actual linking. Note that when this function is called,
1441// all linker scripts have already been parsed.1668// all linker scripts have already been parsed.
1442template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {1669template <class ELFT> void LinkerDriver::link(opt::InputArgList &args) {
1443 Target = getTarget();
1444 InX<ELFT>::VerSym = nullptr;
1445 InX<ELFT>::VerNeed = nullptr;
1446
1447 Config->MaxPageSize = getMaxPageSize(Args);
1448 Config->ImageBase = getImageBase(Args);
1449
1450 // If a -hash-style option was not given, set to a default value,1670 // If a -hash-style option was not given, set to a default value,
1451 // which varies depending on the target.1671 // which varies depending on the target.
1452 if (!Args.hasArg(OPT_hash_style)) {1672 if (!args.hasArg(OPT_hash_style)) {
1453 if (Config->EMachine == EM_MIPS)1673 if (config->emachine == EM_MIPS)
1454 Config->SysvHash = true;1674 config->sysvHash = true;
1455 else1675 else
1456 Config->SysvHash = Config->GnuHash = true;1676 config->sysvHash = config->gnuHash = true;
1457 }1677 }
14581678
1459 // Default output filename is "a.out" by the Unix tradition.1679 // Default output filename is "a.out" by the Unix tradition.
1460 if (Config->OutputFile.empty())1680 if (config->outputFile.empty())
1461 Config->OutputFile = "a.out";1681 config->outputFile = "a.out";
14621682
1463 // Fail early if the output file or map file is not writable. If a user has a1683 // Fail early if the output file or map file is not writable. If a user has a
1464 // long link, e.g. due to a large LTO link, they do not wish to run it and1684 // long link, e.g. due to a large LTO link, they do not wish to run it and
1465 // find that it failed because there was a mistake in their command-line.1685 // find that it failed because there was a mistake in their command-line.
1466 if (auto E = tryCreateFile(Config->OutputFile))1686 if (auto e = tryCreateFile(config->outputFile))
1467 error("cannot open output file " + Config->OutputFile + ": " + E.message());1687 error("cannot open output file " + config->outputFile + ": " + e.message());
1468 if (auto E = tryCreateFile(Config->MapFile))1688 if (auto e = tryCreateFile(config->mapFile))
1469 error("cannot open map file " + Config->MapFile + ": " + E.message());1689 error("cannot open map file " + config->mapFile + ": " + e.message());
1470 if (errorCount())1690 if (errorCount())
1471 return;1691 return;
14721692
1473 // Use default entry point name if no name was given via the command1693 // Use default entry point name if no name was given via the command
1474 // line nor linker scripts. For some reason, MIPS entry point name is1694 // line nor linker scripts. For some reason, MIPS entry point name is
1475 // different from others.1695 // different from others.
1476 Config->WarnMissingEntry =1696 config->warnMissingEntry =
1477 (!Config->Entry.empty() || (!Config->Shared && !Config->Relocatable));1697 (!config->entry.empty() || (!config->shared && !config->relocatable));
1478 if (Config->Entry.empty() && !Config->Relocatable)1698 if (config->entry.empty() && !config->relocatable)
1479 Config->Entry = (Config->EMachine == EM_MIPS) ? "__start" : "_start";1699 config->entry = (config->emachine == EM_MIPS) ? "__start" : "_start";
14801700
1481 // Handle --trace-symbol.1701 // Handle --trace-symbol.
1482 for (auto *Arg : Args.filtered(OPT_trace_symbol))1702 for (auto *arg : args.filtered(OPT_trace_symbol))
1483 Symtab->trace(Arg->getValue());1703 symtab->insert(arg->getValue())->traced = true;
14841704
1485 // Add all files to the symbol table. This will add almost all1705 // Add all files to the symbol table. This will add almost all
1486 // symbols that we need to the symbol table.1706 // symbols that we need to the symbol table. This process might
1487 for (InputFile *F : Files)1707 // add files to the link, via autolinking, these files are always
1488 Symtab->addFile<ELFT>(F);1708 // appended to the Files vector.
1709 for (size_t i = 0; i < files.size(); ++i)
1710 parseFile(files[i]);
14891711
1490 // Now that we have every file, we can decide if we will need a1712 // Now that we have every file, we can decide if we will need a
1491 // dynamic symbol table.1713 // dynamic symbol table.
...@@ -1493,20 +1715,26 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {...@@ -1493,20 +1715,26 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
1493 // producing a shared library.1715 // producing a shared library.
1494 // We also need one if any shared libraries are used and for pie executables1716 // We also need one if any shared libraries are used and for pie executables
1495 // (probably because the dynamic linker needs it).1717 // (probably because the dynamic linker needs it).
1496 Config->HasDynSymTab =1718 config->hasDynSymTab =
1497 !SharedFiles.empty() || Config->Pic || Config->ExportDynamic;1719 !sharedFiles.empty() || config->isPic || config->exportDynamic;
14981720
1499 // Some symbols (such as __ehdr_start) are defined lazily only when there1721 // Some symbols (such as __ehdr_start) are defined lazily only when there
1500 // are undefined symbols for them, so we add these to trigger that logic.1722 // are undefined symbols for them, so we add these to trigger that logic.
1501 for (StringRef Name : Script->ReferencedSymbols)1723 for (StringRef name : script->referencedSymbols)
1502 addUndefined<ELFT>(Name);1724 addUndefined(name);
15031725
1504 // Handle the `--undefined <sym>` options.1726 // Handle the `--undefined <sym>` options.
1505 for (StringRef S : Config->Undefined)1727 for (StringRef arg : config->undefined)
1506 handleUndefined<ELFT>(S);1728 if (Symbol *sym = symtab->find(arg))
1729 handleUndefined(sym);
15071730
1508 // If an entry symbol is in a static archive, pull out that file now.1731 // If an entry symbol is in a static archive, pull out that file now.
1509 handleUndefined<ELFT>(Config->Entry);1732 if (Symbol *sym = symtab->find(config->entry))
1733 handleUndefined(sym);
1734
1735 // Handle the `--undefined-glob <pattern>` options.
1736 for (StringRef pat : args::getStrings(args, OPT_undefined_glob))
1737 handleUndefinedGlob(pat);
15101738
1511 // If any of our inputs are bitcode files, the LTO code generator may create1739 // If any of our inputs are bitcode files, the LTO code generator may create
1512 // references to certain library functions that might not be explicit in the1740 // references to certain library functions that might not be explicit in the
...@@ -1525,9 +1753,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {...@@ -1525,9 +1753,9 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
1525 // to, i.e. if the symbol's definition is in bitcode. Any other required1753 // 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 LTO1754 // libcall symbols will be added to the link after LTO when we add the LTO
1527 // object file to the link.1755 // object file to the link.
1528 if (!BitcodeFiles.empty())1756 if (!bitcodeFiles.empty())
1529 for (const char *S : LibcallRoutineNames)1757 for (const char *s : libcallRoutineNames)
1530 handleLibcall<ELFT>(S);1758 handleLibcall(s);
15311759
1532 // Return if there were name resolution errors.1760 // Return if there were name resolution errors.
1533 if (errorCount())1761 if (errorCount())
...@@ -1535,27 +1763,27 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {...@@ -1535,27 +1763,27 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
15351763
1536 // Now when we read all script files, we want to finalize order of linker1764 // Now when we read all script files, we want to finalize order of linker
1537 // script commands, which can be not yet final because of INSERT commands.1765 // script commands, which can be not yet final because of INSERT commands.
1538 Script->processInsertCommands();1766 script->processInsertCommands();
15391767
1540 // We want to declare linker script's symbols early,1768 // We want to declare linker script's symbols early,
1541 // so that we can version them.1769 // so that we can version them.
1542 // They also might be exported if referenced by DSOs.1770 // They also might be exported if referenced by DSOs.
1543 Script->declareSymbols();1771 script->declareSymbols();
15441772
1545 // Handle the -exclude-libs option.1773 // Handle the -exclude-libs option.
1546 if (Args.hasArg(OPT_exclude_libs))1774 if (args.hasArg(OPT_exclude_libs))
1547 excludeLibs<ELFT>(Args);1775 excludeLibs(args);
15481776
1549 // Create ElfHeader early. We need a dummy section in1777 // Create elfHeader early. We need a dummy section in
1550 // addReservedSymbols to mark the created symbols as not absolute.1778 // addReservedSymbols to mark the created symbols as not absolute.
1551 Out::ElfHeader = make<OutputSection>("", 0, SHF_ALLOC);1779 Out::elfHeader = make<OutputSection>("", 0, SHF_ALLOC);
1552 Out::ElfHeader->Size = sizeof(typename ELFT::Ehdr);1780 Out::elfHeader->size = sizeof(typename ELFT::Ehdr);
15531781
1554 // Create wrapped symbols for -wrap option.1782 // Create wrapped symbols for -wrap option.
1555 std::vector<WrappedSymbol> Wrapped = addWrappedSymbols<ELFT>(Args);1783 std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
15561784
1557 // We need to create some reserved symbols such as _end. Create them.1785 // We need to create some reserved symbols such as _end. Create them.
1558 if (!Config->Relocatable)1786 if (!config->relocatable)
1559 addReservedSymbols();1787 addReservedSymbols();
15601788
1561 // Apply version scripts.1789 // Apply version scripts.
...@@ -1563,84 +1791,118 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {...@@ -1563,84 +1791,118 @@ template <class ELFT> void LinkerDriver::link(opt::InputArgList &Args) {
1563 // For a relocatable output, version scripts don't make sense, and1791 // For a relocatable output, version scripts don't make sense, and
1564 // parsing a symbol version string (e.g. dropping "@ver1" from a symbol1792 // parsing a symbol version string (e.g. dropping "@ver1" from a symbol
1565 // name "foo@ver1") rather do harm, so we don't call this if -r is given.1793 // name "foo@ver1") rather do harm, so we don't call this if -r is given.
1566 if (!Config->Relocatable)1794 if (!config->relocatable)
1567 Symtab->scanVersionScript();1795 symtab->scanVersionScript();
15681796
1569 // Do link-time optimization if given files are LLVM bitcode files.1797 // Do link-time optimization if given files are LLVM bitcode files.
1570 // This compiles bitcode files into real object files.1798 // This compiles bitcode files into real object files.
1571 //1799 //
1572 // With this the symbol table should be complete. After this, no new names1800 // 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.1801 // except a few linker-synthesized ones will be added to the symbol table.
1574 Symtab->addCombinedLTOObject<ELFT>();1802 compileBitcodeFiles<ELFT>();
1575 if (errorCount())1803 if (errorCount())
1576 return;1804 return;
15771805
1578 // If -thinlto-index-only is given, we should create only "index1806 // If -thinlto-index-only is given, we should create only "index
1579 // files" and not object files. Index file creation is already done1807 // files" and not object files. Index file creation is already done
1580 // in addCombinedLTOObject, so we are done if that's the case.1808 // in addCombinedLTOObject, so we are done if that's the case.
1581 if (Config->ThinLTOIndexOnly)1809 if (config->thinLTOIndexOnly)
1582 return;1810 return;
15831811
1584 // Likewise, --plugin-opt=emit-llvm is an option to make LTO create1812 // 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 a1813 // an output file in bitcode and exit, so that you can just get a
1586 // combined bitcode file.1814 // combined bitcode file.
1587 if (Config->EmitLLVM)1815 if (config->emitLLVM)
1588 return;1816 return;
15891817
1590 // Apply symbol renames for -wrap.1818 // Apply symbol renames for -wrap.
1591 if (!Wrapped.empty())1819 if (!wrapped.empty())
1592 wrapSymbols<ELFT>(Wrapped);1820 wrapSymbols(wrapped);
15931821
1594 // Now that we have a complete list of input files.1822 // Now that we have a complete list of input files.
1595 // Beyond this point, no new files are added.1823 // Beyond this point, no new files are added.
1596 // Aggregate all input sections into one place.1824 // Aggregate all input sections into one place.
1597 for (InputFile *F : ObjectFiles)1825 for (InputFile *f : objectFiles)
1598 for (InputSectionBase *S : F->getSections())1826 for (InputSectionBase *s : f->getSections())
1599 if (S && S != &InputSection::Discarded)1827 if (s && s != &InputSection::discarded)
1600 InputSections.push_back(S);1828 inputSections.push_back(s);
1601 for (BinaryFile *F : BinaryFiles)1829 for (BinaryFile *f : binaryFiles)
1602 for (InputSectionBase *S : F->getSections())1830 for (InputSectionBase *s : f->getSections())
1603 InputSections.push_back(cast<InputSection>(S));1831 inputSections.push_back(cast<InputSection>(s));
16041832
1605 // We do not want to emit debug sections if --strip-all1833 llvm::erase_if(inputSections, [](InputSectionBase *s) {
1606 // or -strip-debug are given.1834 if (s->type == SHT_LLVM_SYMPART) {
1607 if (Config->Strip != StripPolicy::None)1835 readSymbolPartitionSection<ELFT>(s);
1608 llvm::erase_if(InputSections, [](InputSectionBase *S) {1836 return true;
1609 return S->Name.startswith(".debug") || S->Name.startswith(".zdebug");1837 }
1610 });1838
16111839 // We do not want to emit debug sections if --strip-all
1612 Config->EFlags = Target->calcEFlags();1840 // or -strip-debug are given.
16131841 return config->strip != StripPolicy::None &&
1614 if (Config->EMachine == EM_ARM) {1842 (s->name.startswith(".debug") || s->name.startswith(".zdebug"));
1843 });
1844
1845 // Now that the number of partitions is fixed, save a pointer to the main
1846 // partition.
1847 mainPart = &partitions[0];
1848
1849 // Read .note.gnu.property sections from input object files which
1850 // contain a hint to tweak linker's and loader's behaviors.
1851 config->andFeatures = getAndFeatures<ELFT>();
1852
1853 // The Target instance handles target-specific stuff, such as applying
1854 // relocations or writing a PLT section. It also contains target-dependent
1855 // values such as a default image base address.
1856 target = getTarget();
1857
1858 config->eflags = target->calcEFlags();
1859 // maxPageSize (sometimes called abi page size) is the maximum page size that
1860 // the output can be run on. For example if the OS can use 4k or 64k page
1861 // sizes then maxPageSize must be 64k for the output to be useable on both.
1862 // All important alignment decisions must use this value.
1863 config->maxPageSize = getMaxPageSize(args);
1864 // commonPageSize is the most common page size that the output will be run on.
1865 // For example if an OS can use 4k or 64k page sizes and 4k is more common
1866 // than 64k then commonPageSize is set to 4k. commonPageSize can be used for
1867 // optimizations such as DATA_SEGMENT_ALIGN in linker scripts. LLD's use of it
1868 // is limited to writing trap instructions on the last executable segment.
1869 config->commonPageSize = getCommonPageSize(args);
1870
1871 config->imageBase = getImageBase(args);
1872
1873 if (config->emachine == EM_ARM) {
1615 // FIXME: These warnings can be removed when lld only uses these features1874 // FIXME: These warnings can be removed when lld only uses these features
1616 // when the input objects have been compiled with an architecture that1875 // when the input objects have been compiled with an architecture that
1617 // supports them.1876 // supports them.
1618 if (Config->ARMHasBlx == false)1877 if (config->armHasBlx == false)
1619 warn("lld uses blx instruction, no object with architecture supporting "1878 warn("lld uses blx instruction, no object with architecture supporting "
1620 "feature detected");1879 "feature detected");
1621 }1880 }
16221881
1623 // This adds a .comment section containing a version string. We have to add it1882 // This adds a .comment section containing a version string. We have to add it
1624 // before mergeSections because the .comment section is a mergeable section.1883 // before mergeSections because the .comment section is a mergeable section.
1625 if (!Config->Relocatable)1884 if (!config->relocatable)
1626 InputSections.push_back(createCommentSection());1885 inputSections.push_back(createCommentSection());
1886
1887 // Replace common symbols with regular symbols.
1888 replaceCommonSymbols();
16271889
1628 // Do size optimizations: garbage collection, merging of SHF_MERGE sections1890 // Do size optimizations: garbage collection, merging of SHF_MERGE sections
1629 // and identical code folding.1891 // and identical code folding.
1630 splitSections<ELFT>();1892 splitSections<ELFT>();
1631 markLive<ELFT>();1893 markLive<ELFT>();
1632 demoteSharedSymbols<ELFT>();1894 demoteSharedSymbols();
1633 mergeSections();1895 mergeSections();
1634 if (Config->ICF != ICFLevel::None) {1896 if (config->icf != ICFLevel::None) {
1635 findKeepUniqueSections<ELFT>(Args);1897 findKeepUniqueSections<ELFT>(args);
1636 doIcf<ELFT>();1898 doIcf<ELFT>();
1637 }1899 }
16381900
1639 // Read the callgraph now that we know what was gced or icfed1901 // Read the callgraph now that we know what was gced or icfed
1640 if (Config->CallGraphProfileSort) {1902 if (config->callGraphProfileSort) {
1641 if (auto *Arg = Args.getLastArg(OPT_call_graph_ordering_file))1903 if (auto *arg = args.getLastArg(OPT_call_graph_ordering_file))
1642 if (Optional<MemoryBufferRef> Buffer = readFile(Arg->getValue()))1904 if (Optional<MemoryBufferRef> buffer = readFile(arg->getValue()))
1643 readCallGraph(*Buffer);1905 readCallGraph(*buffer);
1644 readCallGraphsFromObjectFiles<ELFT>();1906 readCallGraphsFromObjectFiles<ELFT>();
1645 }1907 }
16461908
deps/lld/ELF/Driver.h+23-19
...@@ -1,15 +1,15 @@...@@ -1,15 +1,15 @@
1//===- Driver.h -------------------------------------------------*- C++ -*-===//1//===- Driver.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
10#ifndef LLD_ELF_DRIVER_H9#ifndef LLD_ELF_DRIVER_H
11#define LLD_ELF_DRIVER_H10#define LLD_ELF_DRIVER_H
1211
12#include "LTO.h"
13#include "SymbolTable.h"13#include "SymbolTable.h"
14#include "lld/Common/LLVM.h"14#include "lld/Common/LLVM.h"
15#include "lld/Common/Reproduce.h"15#include "lld/Common/Reproduce.h"
...@@ -22,34 +22,37 @@...@@ -22,34 +22,37 @@
22namespace lld {22namespace lld {
23namespace elf {23namespace elf {
2424
25extern class LinkerDriver *Driver;25extern class LinkerDriver *driver;
2626
27class LinkerDriver {27class LinkerDriver {
28public:28public:
29 void main(ArrayRef<const char *> Args);29 void main(ArrayRef<const char *> args);
30 void addFile(StringRef Path, bool WithLOption);30 void addFile(StringRef path, bool withLOption);
31 void addLibrary(StringRef Name);31 void addLibrary(StringRef name);
3232
33private:33private:
34 void readConfigs(llvm::opt::InputArgList &Args);34 void createFiles(llvm::opt::InputArgList &args);
35 void createFiles(llvm::opt::InputArgList &Args);
36 void inferMachineType();35 void inferMachineType();
37 template <class ELFT> void link(llvm::opt::InputArgList &Args);36 template <class ELFT> void link(llvm::opt::InputArgList &args);
37 template <class ELFT> void compileBitcodeFiles();
3838
39 // True if we are in --whole-archive and --no-whole-archive.39 // True if we are in --whole-archive and --no-whole-archive.
40 bool InWholeArchive = false;40 bool inWholeArchive = false;
4141
42 // True if we are in --start-lib and --end-lib.42 // True if we are in --start-lib and --end-lib.
43 bool InLib = false;43 bool inLib = false;
44
45 // For LTO.
46 std::unique_ptr<BitcodeCompiler> lto;
4447
45 std::vector<InputFile *> Files;48 std::vector<InputFile *> files;
46};49};
4750
48// Parses command line options.51// Parses command line options.
49class ELFOptTable : public llvm::opt::OptTable {52class ELFOptTable : public llvm::opt::OptTable {
50public:53public:
51 ELFOptTable();54 ELFOptTable();
52 llvm::opt::InputArgList parse(ArrayRef<const char *> Argv);55 llvm::opt::InputArgList parse(ArrayRef<const char *> argv);
53};56};
5457
55// Create enum with OPT_xxx values for each option in Options.td58// Create enum with OPT_xxx values for each option in Options.td
...@@ -61,11 +64,12 @@ enum {...@@ -61,11 +64,12 @@ enum {
61};64};
6265
63void printHelp();66void printHelp();
64std::string createResponseFile(const llvm::opt::InputArgList &Args);67std::string createResponseFile(const llvm::opt::InputArgList &args);
6568
66llvm::Optional<std::string> findFromSearchPaths(StringRef Path);69llvm::Optional<std::string> findFromSearchPaths(StringRef path);
67llvm::Optional<std::string> searchScript(StringRef Path);70llvm::Optional<std::string> searchScript(StringRef path);
68llvm::Optional<std::string> searchLibrary(StringRef Path);71llvm::Optional<std::string> searchLibraryBaseName(StringRef path);
72llvm::Optional<std::string> searchLibrary(StringRef path);
6973
70} // namespace elf74} // namespace elf
71} // namespace lld75} // namespace lld
deps/lld/ELF/DriverUtils.cpp+105-90
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- DriverUtils.cpp ----------------------------------------------------===//1//===- DriverUtils.cpp ----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -42,7 +41,7 @@ using namespace lld::elf;...@@ -42,7 +41,7 @@ using namespace lld::elf;
42#undef PREFIX41#undef PREFIX
4342
44// Create table mapping all options defined in Options.td43// Create table mapping all options defined in Options.td
45static const opt::OptTable::Info OptInfo[] = {44static const opt::OptTable::Info optInfo[] = {
46#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \45#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
47 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \46 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \
48 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},47 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
...@@ -50,36 +49,36 @@ static const opt::OptTable::Info OptInfo[] = {...@@ -50,36 +49,36 @@ static const opt::OptTable::Info OptInfo[] = {
50#undef OPTION49#undef OPTION
51};50};
5251
53ELFOptTable::ELFOptTable() : OptTable(OptInfo) {}52ELFOptTable::ELFOptTable() : OptTable(optInfo) {}
5453
55// Set color diagnostics according to -color-diagnostics={auto,always,never}54// Set color diagnostics according to -color-diagnostics={auto,always,never}
56// or -no-color-diagnostics flags.55// or -no-color-diagnostics flags.
57static void handleColorDiagnostics(opt::InputArgList &Args) {56static void handleColorDiagnostics(opt::InputArgList &args) {
58 auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,57 auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
59 OPT_no_color_diagnostics);58 OPT_no_color_diagnostics);
60 if (!Arg)59 if (!arg)
61 return;60 return;
62 if (Arg->getOption().getID() == OPT_color_diagnostics) {61 if (arg->getOption().getID() == OPT_color_diagnostics) {
63 errorHandler().ColorDiagnostics = true;62 errorHandler().colorDiagnostics = true;
64 } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) {63 } else if (arg->getOption().getID() == OPT_no_color_diagnostics) {
65 errorHandler().ColorDiagnostics = false;64 errorHandler().colorDiagnostics = false;
66 } else {65 } else {
67 StringRef S = Arg->getValue();66 StringRef s = arg->getValue();
68 if (S == "always")67 if (s == "always")
69 errorHandler().ColorDiagnostics = true;68 errorHandler().colorDiagnostics = true;
70 else if (S == "never")69 else if (s == "never")
71 errorHandler().ColorDiagnostics = false;70 errorHandler().colorDiagnostics = false;
72 else if (S != "auto")71 else if (s != "auto")
73 error("unknown option: --color-diagnostics=" + S);72 error("unknown option: --color-diagnostics=" + s);
74 }73 }
75}74}
7675
77static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {76static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &args) {
78 if (auto *Arg = Args.getLastArg(OPT_rsp_quoting)) {77 if (auto *arg = args.getLastArg(OPT_rsp_quoting)) {
79 StringRef S = Arg->getValue();78 StringRef s = arg->getValue();
80 if (S != "windows" && S != "posix")79 if (s != "windows" && s != "posix")
81 error("invalid response file quoting: " + S);80 error("invalid response file quoting: " + s);
82 if (S == "windows")81 if (s == "windows")
83 return cl::TokenizeWindowsCommandLine;82 return cl::TokenizeWindowsCommandLine;
84 return cl::TokenizeGNUCommandLine;83 return cl::TokenizeGNUCommandLine;
85 }84 }
...@@ -97,50 +96,56 @@ static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {...@@ -97,50 +96,56 @@ static cl::TokenizerCallback getQuotingStyle(opt::InputArgList &Args) {
97// `--plugin-opt <foo>` is converted to `--plugin-opt=<foo>`. This is a96// `--plugin-opt <foo>` is converted to `--plugin-opt=<foo>`. This is a
98// bit hacky, but looks like it is still better than handling --plugin-opt97// bit hacky, but looks like it is still better than handling --plugin-opt
99// options by hand.98// options by hand.
100static void concatLTOPluginOptions(SmallVectorImpl<const char *> &Args) {99static void concatLTOPluginOptions(SmallVectorImpl<const char *> &args) {
101 SmallVector<const char *, 256> V;100 SmallVector<const char *, 256> v;
102 for (size_t I = 0, E = Args.size(); I != E; ++I) {101 for (size_t i = 0, e = args.size(); i != e; ++i) {
103 StringRef S = Args[I];102 StringRef s = args[i];
104 if ((S == "-plugin-opt" || S == "--plugin-opt") && I + 1 != E) {103 if ((s == "-plugin-opt" || s == "--plugin-opt") && i + 1 != e) {
105 V.push_back(Saver.save(S + "=" + Args[I + 1]).data());104 v.push_back(saver.save(s + "=" + args[i + 1]).data());
106 ++I;105 ++i;
107 } else {106 } else {
108 V.push_back(Args[I]);107 v.push_back(args[i]);
109 }108 }
110 }109 }
111 Args = std::move(V);110 args = std::move(v);
112}111}
113112
114// Parses a given list of options.113// Parses a given list of options.
115opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> Argv) {114opt::InputArgList ELFOptTable::parse(ArrayRef<const char *> argv) {
116 // Make InputArgList from string vectors.115 // Make InputArgList from string vectors.
117 unsigned MissingIndex;116 unsigned missingIndex;
118 unsigned MissingCount;117 unsigned missingCount;
119 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());118 SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
120119
121 // We need to get the quoting style for response files before parsing all120 // We need to get the quoting style for response files before parsing all
122 // options so we parse here before and ignore all the options but121 // options so we parse here before and ignore all the options but
123 // --rsp-quoting.122 // --rsp-quoting.
124 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);123 opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount);
125124
126 // Expand response files (arguments in the form of @<filename>)125 // Expand response files (arguments in the form of @<filename>)
127 // and then parse the argument again.126 // and then parse the argument again.
128 cl::ExpandResponseFiles(Saver, getQuotingStyle(Args), Vec);127 cl::ExpandResponseFiles(saver, getQuotingStyle(args), vec);
129 concatLTOPluginOptions(Vec);128 concatLTOPluginOptions(vec);
130 Args = this->ParseArgs(Vec, MissingIndex, MissingCount);129 args = this->ParseArgs(vec, missingIndex, missingCount);
131130
132 handleColorDiagnostics(Args);131 handleColorDiagnostics(args);
133 if (MissingCount)132 if (missingCount)
134 error(Twine(Args.getArgString(MissingIndex)) + ": missing argument");133 error(Twine(args.getArgString(missingIndex)) + ": missing argument");
135134
136 for (auto *Arg : Args.filtered(OPT_UNKNOWN))135 for (auto *arg : args.filtered(OPT_UNKNOWN)) {
137 error("unknown argument: " + Arg->getSpelling());136 std::string nearest;
138 return Args;137 if (findNearest(arg->getAsString(args), nearest) > 1)
138 error("unknown argument '" + arg->getAsString(args) + "'");
139 else
140 error("unknown argument '" + arg->getAsString(args) +
141 "', did you mean '" + nearest + "'");
142 }
143 return args;
139}144}
140145
141void elf::printHelp() {146void elf::printHelp() {
142 ELFOptTable().PrintHelp(147 ELFOptTable().PrintHelp(
143 outs(), (Config->ProgName + " [options] file...").str().c_str(), "lld",148 outs(), (config->progName + " [options] file...").str().c_str(), "lld",
144 false /*ShowHidden*/, true /*ShowAllAliases*/);149 false /*ShowHidden*/, true /*ShowAllAliases*/);
145 outs() << "\n";150 outs() << "\n";
146151
...@@ -149,30 +154,36 @@ void elf::printHelp() {...@@ -149,30 +154,36 @@ void elf::printHelp() {
149 // in a message for the -help option. If it doesn't match, the scripts154 // in a message for the -help option. If it doesn't match, the scripts
150 // assume that the linker doesn't support very basic features such as155 // assume that the linker doesn't support very basic features such as
151 // shared libraries. Therefore, we need to print out at least "elf".156 // shared libraries. Therefore, we need to print out at least "elf".
152 outs() << Config->ProgName << ": supported targets: elf\n";157 outs() << config->progName << ": supported targets: elf\n";
158}
159
160static std::string rewritePath(StringRef s) {
161 if (fs::exists(s))
162 return relativeToRoot(s);
163 return s;
153}164}
154165
155// Reconstructs command line arguments so that so that you can re-run166// Reconstructs command line arguments so that so that you can re-run
156// the same command with the same inputs. This is for --reproduce.167// the same command with the same inputs. This is for --reproduce.
157std::string elf::createResponseFile(const opt::InputArgList &Args) {168std::string elf::createResponseFile(const opt::InputArgList &args) {
158 SmallString<0> Data;169 SmallString<0> data;
159 raw_svector_ostream OS(Data);170 raw_svector_ostream os(data);
160 OS << "--chroot .\n";171 os << "--chroot .\n";
161172
162 // Copy the command line to the output while rewriting paths.173 // Copy the command line to the output while rewriting paths.
163 for (auto *Arg : Args) {174 for (auto *arg : args) {
164 switch (Arg->getOption().getUnaliasedOption().getID()) {175 switch (arg->getOption().getID()) {
165 case OPT_reproduce:176 case OPT_reproduce:
166 break;177 break;
167 case OPT_INPUT:178 case OPT_INPUT:
168 OS << quote(rewritePath(Arg->getValue())) << "\n";179 os << quote(rewritePath(arg->getValue())) << "\n";
169 break;180 break;
170 case OPT_o:181 case OPT_o:
171 // If -o path contains directories, "lld @response.txt" will likely182 // If -o path contains directories, "lld @response.txt" will likely
172 // fail because the archive we are creating doesn't contain empty183 // fail because the archive we are creating doesn't contain empty
173 // directories for the output path (-o doesn't create directories).184 // directories for the output path (-o doesn't create directories).
174 // Strip directories to prevent the issue.185 // Strip directories to prevent the issue.
175 OS << "-o " << quote(sys::path::filename(Arg->getValue())) << "\n";186 os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n";
176 break;187 break;
177 case OPT_dynamic_list:188 case OPT_dynamic_list:
178 case OPT_library_path:189 case OPT_library_path:
...@@ -181,58 +192,62 @@ std::string elf::createResponseFile(const opt::InputArgList &Args) {...@@ -181,58 +192,62 @@ std::string elf::createResponseFile(const opt::InputArgList &Args) {
181 case OPT_symbol_ordering_file:192 case OPT_symbol_ordering_file:
182 case OPT_sysroot:193 case OPT_sysroot:
183 case OPT_version_script:194 case OPT_version_script:
184 OS << Arg->getSpelling() << " " << quote(rewritePath(Arg->getValue()))195 os << arg->getSpelling() << " " << quote(rewritePath(arg->getValue()))
185 << "\n";196 << "\n";
186 break;197 break;
187 default:198 default:
188 OS << toString(*Arg) << "\n";199 os << toString(*arg) << "\n";
189 }200 }
190 }201 }
191 return Data.str();202 return data.str();
192}203}
193204
194// Find a file by concatenating given paths. If a resulting path205// Find a file by concatenating given paths. If a resulting path
195// starts with "=", the character is replaced with a --sysroot value.206// starts with "=", the character is replaced with a --sysroot value.
196static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) {207static Optional<std::string> findFile(StringRef path1, const Twine &path2) {
197 SmallString<128> S;208 SmallString<128> s;
198 if (Path1.startswith("="))209 if (path1.startswith("="))
199 path::append(S, Config->Sysroot, Path1.substr(1), Path2);210 path::append(s, config->sysroot, path1.substr(1), path2);
200 else211 else
201 path::append(S, Path1, Path2);212 path::append(s, path1, path2);
202213
203 if (fs::exists(S))214 if (fs::exists(s))
204 return S.str().str();215 return s.str().str();
205 return None;216 return None;
206}217}
207218
208Optional<std::string> elf::findFromSearchPaths(StringRef Path) {219Optional<std::string> elf::findFromSearchPaths(StringRef path) {
209 for (StringRef Dir : Config->SearchPaths)220 for (StringRef dir : config->searchPaths)
210 if (Optional<std::string> S = findFile(Dir, Path))221 if (Optional<std::string> s = findFile(dir, path))
211 return S;222 return s;
212 return None;223 return None;
213}224}
214225
215// This is for -lfoo. We'll look for libfoo.so or libfoo.a from226// This is for -l<basename>. We'll look for lib<basename>.so or lib<basename>.a from
216// search paths.227// search paths.
217Optional<std::string> elf::searchLibrary(StringRef Name) {228Optional<std::string> elf::searchLibraryBaseName(StringRef name) {
218 if (Name.startswith(":"))229 for (StringRef dir : config->searchPaths) {
219 return findFromSearchPaths(Name.substr(1));230 if (!config->isStatic)
220231 if (Optional<std::string> s = findFile(dir, "lib" + name + ".so"))
221 for (StringRef Dir : Config->SearchPaths) {232 return s;
222 if (!Config->Static)233 if (Optional<std::string> s = findFile(dir, "lib" + name + ".a"))
223 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".so"))234 return s;
224 return S;
225 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a"))
226 return S;
227 }235 }
228 return None;236 return None;
229}237}
230238
239// This is for -l<namespec>.
240Optional<std::string> elf::searchLibrary(StringRef name) {
241 if (name.startswith(":"))
242 return findFromSearchPaths(name.substr(1));
243 return searchLibraryBaseName (name);
244}
245
231// If a linker/version script doesn't exist in the current directory, we also246// If a linker/version script doesn't exist in the current directory, we also
232// look for the script in the '-L' search paths. This matches the behaviour of247// look for the script in the '-L' search paths. This matches the behaviour of
233// '-T', --version-script=, and linker script INPUT() command in ld.bfd.248// '-T', --version-script=, and linker script INPUT() command in ld.bfd.
234Optional<std::string> elf::searchScript(StringRef Name) {249Optional<std::string> elf::searchScript(StringRef name) {
235 if (fs::exists(Name))250 if (fs::exists(name))
236 return Name.str();251 return name.str();
237 return findFromSearchPaths(Name);252 return findFromSearchPaths(name);
238}253}
deps/lld/ELF/EhFrame.cpp+68-69
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- EhFrame.cpp -------------------------------------------------------===//1//===- EhFrame.cpp -------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -37,72 +36,72 @@ using namespace lld::elf;...@@ -37,72 +36,72 @@ using namespace lld::elf;
37namespace {36namespace {
38class EhReader {37class EhReader {
39public:38public:
40 EhReader(InputSectionBase *S, ArrayRef<uint8_t> D) : IS(S), D(D) {}39 EhReader(InputSectionBase *s, ArrayRef<uint8_t> d) : isec(s), d(d) {}
41 size_t readEhRecordSize();40 size_t readEhRecordSize();
42 uint8_t getFdeEncoding();41 uint8_t getFdeEncoding();
4342
44private:43private:
45 template <class P> void failOn(const P *Loc, const Twine &Msg) {44 template <class P> void failOn(const P *loc, const Twine &msg) {
46 fatal("corrupted .eh_frame: " + Msg + "\n>>> defined in " +45 fatal("corrupted .eh_frame: " + msg + "\n>>> defined in " +
47 IS->getObjMsg((const uint8_t *)Loc - IS->data().data()));46 isec->getObjMsg((const uint8_t *)loc - isec->data().data()));
48 }47 }
4948
50 uint8_t readByte();49 uint8_t readByte();
51 void skipBytes(size_t Count);50 void skipBytes(size_t count);
52 StringRef readString();51 StringRef readString();
53 void skipLeb128();52 void skipLeb128();
54 void skipAugP();53 void skipAugP();
5554
56 InputSectionBase *IS;55 InputSectionBase *isec;
57 ArrayRef<uint8_t> D;56 ArrayRef<uint8_t> d;
58};57};
59}58}
6059
61size_t elf::readEhRecordSize(InputSectionBase *S, size_t Off) {60size_t elf::readEhRecordSize(InputSectionBase *s, size_t off) {
62 return EhReader(S, S->data().slice(Off)).readEhRecordSize();61 return EhReader(s, s->data().slice(off)).readEhRecordSize();
63}62}
6463
65// .eh_frame section is a sequence of records. Each record starts with64// .eh_frame section is a sequence of records. Each record starts with
66// a 4 byte length field. This function reads the length.65// a 4 byte length field. This function reads the length.
67size_t EhReader::readEhRecordSize() {66size_t EhReader::readEhRecordSize() {
68 if (D.size() < 4)67 if (d.size() < 4)
69 failOn(D.data(), "CIE/FDE too small");68 failOn(d.data(), "CIE/FDE too small");
7069
71 // First 4 bytes of CIE/FDE is the size of the record.70 // First 4 bytes of CIE/FDE is the size of the record.
72 // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead,71 // If it is 0xFFFFFFFF, the next 8 bytes contain the size instead,
73 // but we do not support that format yet.72 // but we do not support that format yet.
74 uint64_t V = read32(D.data());73 uint64_t v = read32(d.data());
75 if (V == UINT32_MAX)74 if (v == UINT32_MAX)
76 failOn(D.data(), "CIE/FDE too large");75 failOn(d.data(), "CIE/FDE too large");
77 uint64_t Size = V + 4;76 uint64_t size = v + 4;
78 if (Size > D.size())77 if (size > d.size())
79 failOn(D.data(), "CIE/FDE ends past the end of the section");78 failOn(d.data(), "CIE/FDE ends past the end of the section");
80 return Size;79 return size;
81}80}
8281
83// Read a byte and advance D by one byte.82// Read a byte and advance D by one byte.
84uint8_t EhReader::readByte() {83uint8_t EhReader::readByte() {
85 if (D.empty())84 if (d.empty())
86 failOn(D.data(), "unexpected end of CIE");85 failOn(d.data(), "unexpected end of CIE");
87 uint8_t B = D.front();86 uint8_t b = d.front();
88 D = D.slice(1);87 d = d.slice(1);
89 return B;88 return b;
90}89}
9190
92void EhReader::skipBytes(size_t Count) {91void EhReader::skipBytes(size_t count) {
93 if (D.size() < Count)92 if (d.size() < count)
94 failOn(D.data(), "CIE is too small");93 failOn(d.data(), "CIE is too small");
95 D = D.slice(Count);94 d = d.slice(count);
96}95}
9796
98// Read a null-terminated string.97// Read a null-terminated string.
99StringRef EhReader::readString() {98StringRef EhReader::readString() {
100 const uint8_t *End = std::find(D.begin(), D.end(), '\0');99 const uint8_t *end = llvm::find(d, '\0');
101 if (End == D.end())100 if (end == d.end())
102 failOn(D.data(), "corrupted CIE (failed to read string)");101 failOn(d.data(), "corrupted CIE (failed to read string)");
103 StringRef S = toStringRef(D.slice(0, End - D.begin()));102 StringRef s = toStringRef(d.slice(0, end - d.begin()));
104 D = D.slice(S.size() + 1);103 d = d.slice(s.size() + 1);
105 return S;104 return s;
106}105}
107106
108// Skip an integer encoded in the LEB128 format.107// Skip an integer encoded in the LEB128 format.
...@@ -110,21 +109,21 @@ StringRef EhReader::readString() {...@@ -110,21 +109,21 @@ StringRef EhReader::readString() {
110// But we need to be at least able to skip it so that we can read109// But we need to be at least able to skip it so that we can read
111// the field that follows a LEB128 number.110// the field that follows a LEB128 number.
112void EhReader::skipLeb128() {111void EhReader::skipLeb128() {
113 const uint8_t *ErrPos = D.data();112 const uint8_t *errPos = d.data();
114 while (!D.empty()) {113 while (!d.empty()) {
115 uint8_t Val = D.front();114 uint8_t val = d.front();
116 D = D.slice(1);115 d = d.slice(1);
117 if ((Val & 0x80) == 0)116 if ((val & 0x80) == 0)
118 return;117 return;
119 }118 }
120 failOn(ErrPos, "corrupted CIE (failed to read LEB128)");119 failOn(errPos, "corrupted CIE (failed to read LEB128)");
121}120}
122121
123static size_t getAugPSize(unsigned Enc) {122static size_t getAugPSize(unsigned enc) {
124 switch (Enc & 0x0f) {123 switch (enc & 0x0f) {
125 case DW_EH_PE_absptr:124 case DW_EH_PE_absptr:
126 case DW_EH_PE_signed:125 case DW_EH_PE_signed:
127 return Config->Wordsize;126 return config->wordsize;
128 case DW_EH_PE_udata2:127 case DW_EH_PE_udata2:
129 case DW_EH_PE_sdata2:128 case DW_EH_PE_sdata2:
130 return 2;129 return 2;
...@@ -139,29 +138,29 @@ static size_t getAugPSize(unsigned Enc) {...@@ -139,29 +138,29 @@ static size_t getAugPSize(unsigned Enc) {
139}138}
140139
141void EhReader::skipAugP() {140void EhReader::skipAugP() {
142 uint8_t Enc = readByte();141 uint8_t enc = readByte();
143 if ((Enc & 0xf0) == DW_EH_PE_aligned)142 if ((enc & 0xf0) == DW_EH_PE_aligned)
144 failOn(D.data() - 1, "DW_EH_PE_aligned encoding is not supported");143 failOn(d.data() - 1, "DW_EH_PE_aligned encoding is not supported");
145 size_t Size = getAugPSize(Enc);144 size_t size = getAugPSize(enc);
146 if (Size == 0)145 if (size == 0)
147 failOn(D.data() - 1, "unknown FDE encoding");146 failOn(d.data() - 1, "unknown FDE encoding");
148 if (Size >= D.size())147 if (size >= d.size())
149 failOn(D.data() - 1, "corrupted CIE");148 failOn(d.data() - 1, "corrupted CIE");
150 D = D.slice(Size);149 d = d.slice(size);
151}150}
152151
153uint8_t elf::getFdeEncoding(EhSectionPiece *P) {152uint8_t elf::getFdeEncoding(EhSectionPiece *p) {
154 return EhReader(P->Sec, P->data()).getFdeEncoding();153 return EhReader(p->sec, p->data()).getFdeEncoding();
155}154}
156155
157uint8_t EhReader::getFdeEncoding() {156uint8_t EhReader::getFdeEncoding() {
158 skipBytes(8);157 skipBytes(8);
159 int Version = readByte();158 int version = readByte();
160 if (Version != 1 && Version != 3)159 if (version != 1 && version != 3)
161 failOn(D.data() - 1,160 failOn(d.data() - 1,
162 "FDE version 1 or 3 expected, but got " + Twine(Version));161 "FDE version 1 or 3 expected, but got " + Twine(version));
163162
164 StringRef Aug = readString();163 StringRef aug = readString();
165164
166 // Skip code and data alignment factors.165 // Skip code and data alignment factors.
167 skipLeb128();166 skipLeb128();
...@@ -169,7 +168,7 @@ uint8_t EhReader::getFdeEncoding() {...@@ -169,7 +168,7 @@ uint8_t EhReader::getFdeEncoding() {
169168
170 // Skip the return address register. In CIE version 1 this is a single169 // Skip the return address register. In CIE version 1 this is a single
171 // byte. In CIE version 3 this is an unsigned LEB128.170 // byte. In CIE version 3 this is an unsigned LEB128.
172 if (Version == 1)171 if (version == 1)
173 readByte();172 readByte();
174 else173 else
175 skipLeb128();174 skipLeb128();
...@@ -177,22 +176,22 @@ uint8_t EhReader::getFdeEncoding() {...@@ -177,22 +176,22 @@ uint8_t EhReader::getFdeEncoding() {
177 // We only care about an 'R' value, but other records may precede an 'R'176 // We only care about an 'R' value, but other records may precede an 'R'
178 // record. Unfortunately records are not in TLV (type-length-value) format,177 // record. Unfortunately records are not in TLV (type-length-value) format,
179 // so we need to teach the linker how to skip records for each type.178 // so we need to teach the linker how to skip records for each type.
180 for (char C : Aug) {179 for (char c : aug) {
181 if (C == 'R')180 if (c == 'R')
182 return readByte();181 return readByte();
183 if (C == 'z') {182 if (c == 'z') {
184 skipLeb128();183 skipLeb128();
185 continue;184 continue;
186 }185 }
187 if (C == 'P') {186 if (c == 'P') {
188 skipAugP();187 skipAugP();
189 continue;188 continue;
190 }189 }
191 if (C == 'L') {190 if (c == 'L') {
192 readByte();191 readByte();
193 continue;192 continue;
194 }193 }
195 failOn(Aug.data(), "unknown .eh_frame augmentation string: " + Aug);194 failOn(aug.data(), "unknown .eh_frame augmentation string: " + aug);
196 }195 }
197 return DW_EH_PE_absptr;196 return DW_EH_PE_absptr;
198}197}
deps/lld/ELF/EhFrame.h+5-6
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- EhFrame.h ------------------------------------------------*- C++ -*-===//1//===- EhFrame.h ------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -17,8 +16,8 @@ namespace elf {...@@ -17,8 +16,8 @@ namespace elf {
17class InputSectionBase;16class InputSectionBase;
18struct EhSectionPiece;17struct EhSectionPiece;
1918
20size_t readEhRecordSize(InputSectionBase *S, size_t Off);19size_t readEhRecordSize(InputSectionBase *s, size_t off);
21uint8_t getFdeEncoding(EhSectionPiece *P);20uint8_t getFdeEncoding(EhSectionPiece *p);
22} // namespace elf21} // namespace elf
23} // namespace lld22} // namespace lld
2423
deps/lld/ELF/Filesystem.cpp deleted-86
...@@ -1,86 +0,0 @@
1//===- Filesystem.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// This file contains a few utility functions to handle files.
11//
12//===----------------------------------------------------------------------===//
13
14#include "Filesystem.h"
15#include "Config.h"
16#include "lld/Common/Threads.h"
17#include "llvm/Config/llvm-config.h"
18#include "llvm/Support/FileOutputBuffer.h"
19#include "llvm/Support/FileSystem.h"
20#if LLVM_ON_UNIX
21#include <unistd.h>
22#endif
23#include <thread>
24
25using namespace llvm;
26
27using namespace lld;
28using namespace lld::elf;
29
30// Removes a given file asynchronously. This is a performance hack,
31// so remove this when operating systems are improved.
32//
33// On Linux (and probably on other Unix-like systems), unlink(2) is a
34// noticeably slow system call. As of 2016, unlink takes 250
35// milliseconds to remove a 1 GB file on ext4 filesystem on my machine.
36//
37// To create a new result file, we first remove existing file. So, if
38// you repeatedly link a 1 GB program in a regular compile-link-debug
39// cycle, every cycle wastes 250 milliseconds only to remove a file.
40// Since LLD can link a 1 GB binary in about 5 seconds, that waste
41// actually counts.
42//
43// This function spawns a background thread to remove the file.
44// The calling thread returns almost immediately.
45void elf::unlinkAsync(StringRef Path) {
46// Removing a file is async on windows.
47#if defined(_WIN32)
48 sys::fs::remove(Path);
49#else
50 if (!ThreadsEnabled || !sys::fs::exists(Path) ||
51 !sys::fs::is_regular_file(Path))
52 return;
53
54 // We cannot just remove path from a different thread because we are now going
55 // to create path as a new file.
56 // Instead we open the file and unlink it on this thread. The unlink is fast
57 // since the open fd guarantees that it is not removing the last reference.
58 int FD;
59 std::error_code EC = sys::fs::openFileForRead(Path, FD);
60 sys::fs::remove(Path);
61
62 // close and therefore remove TempPath in background.
63 if (!EC)
64 std::thread([=] { ::close(FD); }).detach();
65#endif
66}
67
68// Simulate file creation to see if Path is writable.
69//
70// Determining whether a file is writable or not is amazingly hard,
71// and after all the only reliable way of doing that is to actually
72// create a file. But we don't want to do that in this function
73// because LLD shouldn't update any file if it will end in a failure.
74// We also don't want to reimplement heuristics to determine if a
75// file is writable. So we'll let FileOutputBuffer do the work.
76//
77// FileOutputBuffer doesn't touch a desitnation file until commit()
78// is called. We use that class without calling commit() to predict
79// if the given file is writable.
80std::error_code elf::tryCreateFile(StringRef Path) {
81 if (Path.empty())
82 return std::error_code();
83 if (Path == "-")
84 return std::error_code();
85 return errorToErrorCode(FileOutputBuffer::create(Path, 1).takeError());
86}
deps/lld/ELF/Filesystem.h deleted-23
...@@ -1,23 +0,0 @@
1//===- Filesystem.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_FILESYSTEM_H
11#define LLD_ELF_FILESYSTEM_H
12
13#include "lld/Common/LLVM.h"
14#include <system_error>
15
16namespace lld {
17namespace elf {
18void unlinkAsync(StringRef Path);
19std::error_code tryCreateFile(StringRef Path);
20} // namespace elf
21} // namespace lld
22
23#endif
deps/lld/ELF/ICF.cpp+166-168
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ICF.cpp ------------------------------------------------------------===//1//===- ICF.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -99,33 +98,33 @@ public:...@@ -99,33 +98,33 @@ public:
99 void run();98 void run();
10099
101private:100private:
102 void segregate(size_t Begin, size_t End, bool Constant);101 void segregate(size_t begin, size_t end, bool constant);
103102
104 template <class RelTy>103 template <class RelTy>
105 bool constantEq(const InputSection *A, ArrayRef<RelTy> RelsA,104 bool constantEq(const InputSection *a, ArrayRef<RelTy> relsA,
106 const InputSection *B, ArrayRef<RelTy> RelsB);105 const InputSection *b, ArrayRef<RelTy> relsB);
107106
108 template <class RelTy>107 template <class RelTy>
109 bool variableEq(const InputSection *A, ArrayRef<RelTy> RelsA,108 bool variableEq(const InputSection *a, ArrayRef<RelTy> relsA,
110 const InputSection *B, ArrayRef<RelTy> RelsB);109 const InputSection *b, ArrayRef<RelTy> relsB);
111110
112 bool equalsConstant(const InputSection *A, const InputSection *B);111 bool equalsConstant(const InputSection *a, const InputSection *b);
113 bool equalsVariable(const InputSection *A, const InputSection *B);112 bool equalsVariable(const InputSection *a, const InputSection *b);
114113
115 size_t findBoundary(size_t Begin, size_t End);114 size_t findBoundary(size_t begin, size_t end);
116115
117 void forEachClassRange(size_t Begin, size_t End,116 void forEachClassRange(size_t begin, size_t end,
118 llvm::function_ref<void(size_t, size_t)> Fn);117 llvm::function_ref<void(size_t, size_t)> fn);
119118
120 void forEachClass(llvm::function_ref<void(size_t, size_t)> Fn);119 void forEachClass(llvm::function_ref<void(size_t, size_t)> fn);
121120
122 std::vector<InputSection *> Sections;121 std::vector<InputSection *> sections;
123122
124 // We repeat the main loop while `Repeat` is true.123 // We repeat the main loop while `Repeat` is true.
125 std::atomic<bool> Repeat;124 std::atomic<bool> repeat;
126125
127 // The main loop counter.126 // The main loop counter.
128 int Cnt = 0;127 int cnt = 0;
129128
130 // We have two locations for equivalence classes. On the first iteration129 // We have two locations for equivalence classes. On the first iteration
131 // of the main loop, Class[0] has a valid value, and Class[1] contains130 // of the main loop, Class[0] has a valid value, and Class[1] contains
...@@ -151,42 +150,42 @@ private:...@@ -151,42 +150,42 @@ private:
151 // because we can safely read the next class without worrying about race150 // because we can safely read the next class without worrying about race
152 // conditions. Using the same location makes this algorithm converge151 // conditions. Using the same location makes this algorithm converge
153 // faster because it uses results of the same iteration earlier.152 // faster because it uses results of the same iteration earlier.
154 int Current = 0;153 int current = 0;
155 int Next = 0;154 int next = 0;
156};155};
157}156}
158157
159// Returns true if section S is subject of ICF.158// Returns true if section S is subject of ICF.
160static bool isEligible(InputSection *S) {159static bool isEligible(InputSection *s) {
161 if (!S->Live || S->KeepUnique || !(S->Flags & SHF_ALLOC))160 if (!s->isLive() || s->keepUnique || !(s->flags & SHF_ALLOC))
162 return false;161 return false;
163162
164 // Don't merge writable sections. .data.rel.ro sections are marked as writable163 // Don't merge writable sections. .data.rel.ro sections are marked as writable
165 // but are semantically read-only.164 // but are semantically read-only.
166 if ((S->Flags & SHF_WRITE) && S->Name != ".data.rel.ro" &&165 if ((s->flags & SHF_WRITE) && s->name != ".data.rel.ro" &&
167 !S->Name.startswith(".data.rel.ro."))166 !s->name.startswith(".data.rel.ro."))
168 return false;167 return false;
169168
170 // SHF_LINK_ORDER sections are ICF'd as a unit with their dependent sections,169 // SHF_LINK_ORDER sections are ICF'd as a unit with their dependent sections,
171 // so we don't consider them for ICF individually.170 // so we don't consider them for ICF individually.
172 if (S->Flags & SHF_LINK_ORDER)171 if (s->flags & SHF_LINK_ORDER)
173 return false;172 return false;
174173
175 // Don't merge synthetic sections as their Data member is not valid and empty.174 // Don't merge synthetic sections as their Data member is not valid and empty.
176 // The Data member needs to be valid for ICF as it is used by ICF to determine175 // The Data member needs to be valid for ICF as it is used by ICF to determine
177 // the equality of section contents.176 // the equality of section contents.
178 if (isa<SyntheticSection>(S))177 if (isa<SyntheticSection>(s))
179 return false;178 return false;
180179
181 // .init and .fini contains instructions that must be executed to initialize180 // .init and .fini contains instructions that must be executed to initialize
182 // and finalize the process. They cannot and should not be merged.181 // and finalize the process. They cannot and should not be merged.
183 if (S->Name == ".init" || S->Name == ".fini")182 if (s->name == ".init" || s->name == ".fini")
184 return false;183 return false;
185184
186 // A user program may enumerate sections named with a C identifier using185 // A user program may enumerate sections named with a C identifier using
187 // __start_* and __stop_* symbols. We cannot ICF any such sections because186 // __start_* and __stop_* symbols. We cannot ICF any such sections because
188 // that could change program semantics.187 // that could change program semantics.
189 if (isValidCIdentifier(S->Name))188 if (isValidCIdentifier(s->name))
190 return false;189 return false;
191190
192 return true;191 return true;
...@@ -194,7 +193,7 @@ static bool isEligible(InputSection *S) {...@@ -194,7 +193,7 @@ static bool isEligible(InputSection *S) {
194193
195// Split an equivalence class into smaller classes.194// Split an equivalence class into smaller classes.
196template <class ELFT>195template <class ELFT>
197void ICF<ELFT>::segregate(size_t Begin, size_t End, bool Constant) {196void ICF<ELFT>::segregate(size_t begin, size_t end, bool constant) {
198 // This loop rearranges sections in [Begin, End) so that all sections197 // This loop rearranges sections in [Begin, End) so that all sections
199 // that are equal in terms of equals{Constant,Variable} are contiguous198 // that are equal in terms of equals{Constant,Variable} are contiguous
200 // in [Begin, End).199 // in [Begin, End).
...@@ -203,93 +202,93 @@ void ICF<ELFT>::segregate(size_t Begin, size_t End, bool Constant) {...@@ -203,93 +202,93 @@ void ICF<ELFT>::segregate(size_t Begin, size_t End, bool Constant) {
203 // issue in practice because the number of the distinct sections in202 // issue in practice because the number of the distinct sections in
204 // each range is usually very small.203 // each range is usually very small.
205204
206 while (Begin < End) {205 while (begin < end) {
207 // Divide [Begin, End) into two. Let Mid be the start index of the206 // Divide [Begin, End) into two. Let Mid be the start index of the
208 // second group.207 // second group.
209 auto Bound =208 auto bound =
210 std::stable_partition(Sections.begin() + Begin + 1,209 std::stable_partition(sections.begin() + begin + 1,
211 Sections.begin() + End, [&](InputSection *S) {210 sections.begin() + end, [&](InputSection *s) {
212 if (Constant)211 if (constant)
213 return equalsConstant(Sections[Begin], S);212 return equalsConstant(sections[begin], s);
214 return equalsVariable(Sections[Begin], S);213 return equalsVariable(sections[begin], s);
215 });214 });
216 size_t Mid = Bound - Sections.begin();215 size_t mid = bound - sections.begin();
217216
218 // Now we split [Begin, End) into [Begin, Mid) and [Mid, End) by217 // Now we split [Begin, End) into [Begin, Mid) and [Mid, End) by
219 // updating the sections in [Begin, Mid). We use Mid as an equivalence218 // updating the sections in [Begin, Mid). We use Mid as an equivalence
220 // class ID because every group ends with a unique index.219 // class ID because every group ends with a unique index.
221 for (size_t I = Begin; I < Mid; ++I)220 for (size_t i = begin; i < mid; ++i)
222 Sections[I]->Class[Next] = Mid;221 sections[i]->eqClass[next] = mid;
223222
224 // If we created a group, we need to iterate the main loop again.223 // If we created a group, we need to iterate the main loop again.
225 if (Mid != End)224 if (mid != end)
226 Repeat = true;225 repeat = true;
227226
228 Begin = Mid;227 begin = mid;
229 }228 }
230}229}
231230
232// Compare two lists of relocations.231// Compare two lists of relocations.
233template <class ELFT>232template <class ELFT>
234template <class RelTy>233template <class RelTy>
235bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA,234bool ICF<ELFT>::constantEq(const InputSection *secA, ArrayRef<RelTy> ra,
236 const InputSection *SecB, ArrayRef<RelTy> RB) {235 const InputSection *secB, ArrayRef<RelTy> rb) {
237 for (size_t I = 0; I < RA.size(); ++I) {236 for (size_t i = 0; i < ra.size(); ++i) {
238 if (RA[I].r_offset != RB[I].r_offset ||237 if (ra[i].r_offset != rb[i].r_offset ||
239 RA[I].getType(Config->IsMips64EL) != RB[I].getType(Config->IsMips64EL))238 ra[i].getType(config->isMips64EL) != rb[i].getType(config->isMips64EL))
240 return false;239 return false;
241240
242 uint64_t AddA = getAddend<ELFT>(RA[I]);241 uint64_t addA = getAddend<ELFT>(ra[i]);
243 uint64_t AddB = getAddend<ELFT>(RB[I]);242 uint64_t addB = getAddend<ELFT>(rb[i]);
244243
245 Symbol &SA = SecA->template getFile<ELFT>()->getRelocTargetSym(RA[I]);244 Symbol &sa = secA->template getFile<ELFT>()->getRelocTargetSym(ra[i]);
246 Symbol &SB = SecB->template getFile<ELFT>()->getRelocTargetSym(RB[I]);245 Symbol &sb = secB->template getFile<ELFT>()->getRelocTargetSym(rb[i]);
247 if (&SA == &SB) {246 if (&sa == &sb) {
248 if (AddA == AddB)247 if (addA == addB)
249 continue;248 continue;
250 return false;249 return false;
251 }250 }
252251
253 auto *DA = dyn_cast<Defined>(&SA);252 auto *da = dyn_cast<Defined>(&sa);
254 auto *DB = dyn_cast<Defined>(&SB);253 auto *db = dyn_cast<Defined>(&sb);
255254
256 // Placeholder symbols generated by linker scripts look the same now but255 // Placeholder symbols generated by linker scripts look the same now but
257 // may have different values later.256 // may have different values later.
258 if (!DA || !DB || DA->ScriptDefined || DB->ScriptDefined)257 if (!da || !db || da->scriptDefined || db->scriptDefined)
259 return false;258 return false;
260259
261 // Relocations referring to absolute symbols are constant-equal if their260 // Relocations referring to absolute symbols are constant-equal if their
262 // values are equal.261 // values are equal.
263 if (!DA->Section && !DB->Section && DA->Value + AddA == DB->Value + AddB)262 if (!da->section && !db->section && da->value + addA == db->value + addB)
264 continue;263 continue;
265 if (!DA->Section || !DB->Section)264 if (!da->section || !db->section)
266 return false;265 return false;
267266
268 if (DA->Section->kind() != DB->Section->kind())267 if (da->section->kind() != db->section->kind())
269 return false;268 return false;
270269
271 // Relocations referring to InputSections are constant-equal if their270 // Relocations referring to InputSections are constant-equal if their
272 // section offsets are equal.271 // section offsets are equal.
273 if (isa<InputSection>(DA->Section)) {272 if (isa<InputSection>(da->section)) {
274 if (DA->Value + AddA == DB->Value + AddB)273 if (da->value + addA == db->value + addB)
275 continue;274 continue;
276 return false;275 return false;
277 }276 }
278277
279 // Relocations referring to MergeInputSections are constant-equal if their278 // Relocations referring to MergeInputSections are constant-equal if their
280 // offsets in the output section are equal.279 // offsets in the output section are equal.
281 auto *X = dyn_cast<MergeInputSection>(DA->Section);280 auto *x = dyn_cast<MergeInputSection>(da->section);
282 if (!X)281 if (!x)
283 return false;282 return false;
284 auto *Y = cast<MergeInputSection>(DB->Section);283 auto *y = cast<MergeInputSection>(db->section);
285 if (X->getParent() != Y->getParent())284 if (x->getParent() != y->getParent())
286 return false;285 return false;
287286
288 uint64_t OffsetA =287 uint64_t offsetA =
289 SA.isSection() ? X->getOffset(AddA) : X->getOffset(DA->Value) + AddA;288 sa.isSection() ? x->getOffset(addA) : x->getOffset(da->value) + addA;
290 uint64_t OffsetB =289 uint64_t offsetB =
291 SB.isSection() ? Y->getOffset(AddB) : Y->getOffset(DB->Value) + AddB;290 sb.isSection() ? y->getOffset(addB) : y->getOffset(db->value) + addB;
292 if (OffsetA != OffsetB)291 if (offsetA != offsetB)
293 return false;292 return false;
294 }293 }
295294
...@@ -299,57 +298,57 @@ bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA,...@@ -299,57 +298,57 @@ bool ICF<ELFT>::constantEq(const InputSection *SecA, ArrayRef<RelTy> RA,
299// Compare "non-moving" part of two InputSections, namely everything298// Compare "non-moving" part of two InputSections, namely everything
300// except relocation targets.299// except relocation targets.
301template <class ELFT>300template <class ELFT>
302bool ICF<ELFT>::equalsConstant(const InputSection *A, const InputSection *B) {301bool ICF<ELFT>::equalsConstant(const InputSection *a, const InputSection *b) {
303 if (A->NumRelocations != B->NumRelocations || A->Flags != B->Flags ||302 if (a->numRelocations != b->numRelocations || a->flags != b->flags ||
304 A->getSize() != B->getSize() || A->data() != B->data())303 a->getSize() != b->getSize() || a->data() != b->data())
305 return false;304 return false;
306305
307 // If two sections have different output sections, we cannot merge them.306 // If two sections have different output sections, we cannot merge them.
308 // FIXME: This doesn't do the right thing in the case where there is a linker307 // FIXME: This doesn't do the right thing in the case where there is a linker
309 // script. We probably need to move output section assignment before ICF to308 // script. We probably need to move output section assignment before ICF to
310 // get the correct behaviour here.309 // get the correct behaviour here.
311 if (getOutputSectionName(A) != getOutputSectionName(B))310 if (getOutputSectionName(a) != getOutputSectionName(b))
312 return false;311 return false;
313312
314 if (A->AreRelocsRela)313 if (a->areRelocsRela)
315 return constantEq(A, A->template relas<ELFT>(), B,314 return constantEq(a, a->template relas<ELFT>(), b,
316 B->template relas<ELFT>());315 b->template relas<ELFT>());
317 return constantEq(A, A->template rels<ELFT>(), B, B->template rels<ELFT>());316 return constantEq(a, a->template rels<ELFT>(), b, b->template rels<ELFT>());
318}317}
319318
320// Compare two lists of relocations. Returns true if all pairs of319// Compare two lists of relocations. Returns true if all pairs of
321// relocations point to the same section in terms of ICF.320// relocations point to the same section in terms of ICF.
322template <class ELFT>321template <class ELFT>
323template <class RelTy>322template <class RelTy>
324bool ICF<ELFT>::variableEq(const InputSection *SecA, ArrayRef<RelTy> RA,323bool ICF<ELFT>::variableEq(const InputSection *secA, ArrayRef<RelTy> ra,
325 const InputSection *SecB, ArrayRef<RelTy> RB) {324 const InputSection *secB, ArrayRef<RelTy> rb) {
326 assert(RA.size() == RB.size());325 assert(ra.size() == rb.size());
327326
328 for (size_t I = 0; I < RA.size(); ++I) {327 for (size_t i = 0; i < ra.size(); ++i) {
329 // The two sections must be identical.328 // The two sections must be identical.
330 Symbol &SA = SecA->template getFile<ELFT>()->getRelocTargetSym(RA[I]);329 Symbol &sa = secA->template getFile<ELFT>()->getRelocTargetSym(ra[i]);
331 Symbol &SB = SecB->template getFile<ELFT>()->getRelocTargetSym(RB[I]);330 Symbol &sb = secB->template getFile<ELFT>()->getRelocTargetSym(rb[i]);
332 if (&SA == &SB)331 if (&sa == &sb)
333 continue;332 continue;
334333
335 auto *DA = cast<Defined>(&SA);334 auto *da = cast<Defined>(&sa);
336 auto *DB = cast<Defined>(&SB);335 auto *db = cast<Defined>(&sb);
337336
338 // We already dealt with absolute and non-InputSection symbols in337 // We already dealt with absolute and non-InputSection symbols in
339 // constantEq, and for InputSections we have already checked everything338 // constantEq, and for InputSections we have already checked everything
340 // except the equivalence class.339 // except the equivalence class.
341 if (!DA->Section)340 if (!da->section)
342 continue;341 continue;
343 auto *X = dyn_cast<InputSection>(DA->Section);342 auto *x = dyn_cast<InputSection>(da->section);
344 if (!X)343 if (!x)
345 continue;344 continue;
346 auto *Y = cast<InputSection>(DB->Section);345 auto *y = cast<InputSection>(db->section);
347346
348 // Ineligible sections are in the special equivalence class 0.347 // Ineligible sections are in the special equivalence class 0.
349 // They can never be the same in terms of the equivalence class.348 // They can never be the same in terms of the equivalence class.
350 if (X->Class[Current] == 0)349 if (x->eqClass[current] == 0)
351 return false;350 return false;
352 if (X->Class[Current] != Y->Class[Current])351 if (x->eqClass[current] != y->eqClass[current])
353 return false;352 return false;
354 };353 };
355354
...@@ -358,19 +357,19 @@ bool ICF<ELFT>::variableEq(const InputSection *SecA, ArrayRef<RelTy> RA,...@@ -358,19 +357,19 @@ bool ICF<ELFT>::variableEq(const InputSection *SecA, ArrayRef<RelTy> RA,
358357
359// Compare "moving" part of two InputSections, namely relocation targets.358// Compare "moving" part of two InputSections, namely relocation targets.
360template <class ELFT>359template <class ELFT>
361bool ICF<ELFT>::equalsVariable(const InputSection *A, const InputSection *B) {360bool ICF<ELFT>::equalsVariable(const InputSection *a, const InputSection *b) {
362 if (A->AreRelocsRela)361 if (a->areRelocsRela)
363 return variableEq(A, A->template relas<ELFT>(), B,362 return variableEq(a, a->template relas<ELFT>(), b,
364 B->template relas<ELFT>());363 b->template relas<ELFT>());
365 return variableEq(A, A->template rels<ELFT>(), B, B->template rels<ELFT>());364 return variableEq(a, a->template rels<ELFT>(), b, b->template rels<ELFT>());
366}365}
367366
368template <class ELFT> size_t ICF<ELFT>::findBoundary(size_t Begin, size_t End) {367template <class ELFT> size_t ICF<ELFT>::findBoundary(size_t begin, size_t end) {
369 uint32_t Class = Sections[Begin]->Class[Current];368 uint32_t eqClass = sections[begin]->eqClass[current];
370 for (size_t I = Begin + 1; I < End; ++I)369 for (size_t i = begin + 1; i < end; ++i)
371 if (Class != Sections[I]->Class[Current])370 if (eqClass != sections[i]->eqClass[current])
372 return I;371 return i;
373 return End;372 return end;
374}373}
375374
376// Sections in the same equivalence class are contiguous in Sections375// Sections in the same equivalence class are contiguous in Sections
...@@ -379,126 +378,125 @@ template <class ELFT> size_t ICF<ELFT>::findBoundary(size_t Begin, size_t End) {...@@ -379,126 +378,125 @@ template <class ELFT> size_t ICF<ELFT>::findBoundary(size_t Begin, size_t End) {
379//378//
380// This function calls Fn on every group within [Begin, End).379// This function calls Fn on every group within [Begin, End).
381template <class ELFT>380template <class ELFT>
382void ICF<ELFT>::forEachClassRange(size_t Begin, size_t End,381void ICF<ELFT>::forEachClassRange(size_t begin, size_t end,
383 llvm::function_ref<void(size_t, size_t)> Fn) {382 llvm::function_ref<void(size_t, size_t)> fn) {
384 while (Begin < End) {383 while (begin < end) {
385 size_t Mid = findBoundary(Begin, End);384 size_t mid = findBoundary(begin, end);
386 Fn(Begin, Mid);385 fn(begin, mid);
387 Begin = Mid;386 begin = mid;
388 }387 }
389}388}
390389
391// Call Fn on each equivalence class.390// Call Fn on each equivalence class.
392template <class ELFT>391template <class ELFT>
393void ICF<ELFT>::forEachClass(llvm::function_ref<void(size_t, size_t)> Fn) {392void ICF<ELFT>::forEachClass(llvm::function_ref<void(size_t, size_t)> fn) {
394 // If threading is disabled or the number of sections are393 // If threading is disabled or the number of sections are
395 // too small to use threading, call Fn sequentially.394 // too small to use threading, call Fn sequentially.
396 if (!ThreadsEnabled || Sections.size() < 1024) {395 if (!threadsEnabled || sections.size() < 1024) {
397 forEachClassRange(0, Sections.size(), Fn);396 forEachClassRange(0, sections.size(), fn);
398 ++Cnt;397 ++cnt;
399 return;398 return;
400 }399 }
401400
402 Current = Cnt % 2;401 current = cnt % 2;
403 Next = (Cnt + 1) % 2;402 next = (cnt + 1) % 2;
404403
405 // Shard into non-overlapping intervals, and call Fn in parallel.404 // Shard into non-overlapping intervals, and call Fn in parallel.
406 // The sharding must be completed before any calls to Fn are made405 // The sharding must be completed before any calls to Fn are made
407 // so that Fn can modify the Chunks in its shard without causing data406 // so that Fn can modify the Chunks in its shard without causing data
408 // races.407 // races.
409 const size_t NumShards = 256;408 const size_t numShards = 256;
410 size_t Step = Sections.size() / NumShards;409 size_t step = sections.size() / numShards;
411 size_t Boundaries[NumShards + 1];410 size_t boundaries[numShards + 1];
412 Boundaries[0] = 0;411 boundaries[0] = 0;
413 Boundaries[NumShards] = Sections.size();412 boundaries[numShards] = sections.size();
414413
415 parallelForEachN(1, NumShards, [&](size_t I) {414 parallelForEachN(1, numShards, [&](size_t i) {
416 Boundaries[I] = findBoundary((I - 1) * Step, Sections.size());415 boundaries[i] = findBoundary((i - 1) * step, sections.size());
417 });416 });
418417
419 parallelForEachN(1, NumShards + 1, [&](size_t I) {418 parallelForEachN(1, numShards + 1, [&](size_t i) {
420 if (Boundaries[I - 1] < Boundaries[I])419 if (boundaries[i - 1] < boundaries[i])
421 forEachClassRange(Boundaries[I - 1], Boundaries[I], Fn);420 forEachClassRange(boundaries[i - 1], boundaries[i], fn);
422 });421 });
423 ++Cnt;422 ++cnt;
424}423}
425424
426// Combine the hashes of the sections referenced by the given section into its425// Combine the hashes of the sections referenced by the given section into its
427// hash.426// hash.
428template <class ELFT, class RelTy>427template <class ELFT, class RelTy>
429static void combineRelocHashes(unsigned Cnt, InputSection *IS,428static void combineRelocHashes(unsigned cnt, InputSection *isec,
430 ArrayRef<RelTy> Rels) {429 ArrayRef<RelTy> rels) {
431 uint32_t Hash = IS->Class[Cnt % 2];430 uint32_t hash = isec->eqClass[cnt % 2];
432 for (RelTy Rel : Rels) {431 for (RelTy rel : rels) {
433 Symbol &S = IS->template getFile<ELFT>()->getRelocTargetSym(Rel);432 Symbol &s = isec->template getFile<ELFT>()->getRelocTargetSym(rel);
434 if (auto *D = dyn_cast<Defined>(&S))433 if (auto *d = dyn_cast<Defined>(&s))
435 if (auto *RelSec = dyn_cast_or_null<InputSection>(D->Section))434 if (auto *relSec = dyn_cast_or_null<InputSection>(d->section))
436 Hash += RelSec->Class[Cnt % 2];435 hash += relSec->eqClass[cnt % 2];
437 }436 }
438 // Set MSB to 1 to avoid collisions with non-hash IDs.437 // Set MSB to 1 to avoid collisions with non-hash IDs.
439 IS->Class[(Cnt + 1) % 2] = Hash | (1U << 31);438 isec->eqClass[(cnt + 1) % 2] = hash | (1U << 31);
440}439}
441440
442static void print(const Twine &S) {441static void print(const Twine &s) {
443 if (Config->PrintIcfSections)442 if (config->printIcfSections)
444 message(S);443 message(s);
445}444}
446445
447// The main function of ICF.446// The main function of ICF.
448template <class ELFT> void ICF<ELFT>::run() {447template <class ELFT> void ICF<ELFT>::run() {
449 // Collect sections to merge.448 // Collect sections to merge.
450 for (InputSectionBase *Sec : InputSections)449 for (InputSectionBase *sec : inputSections)
451 if (auto *S = dyn_cast<InputSection>(Sec))450 if (auto *s = dyn_cast<InputSection>(sec))
452 if (isEligible(S))451 if (isEligible(s))
453 Sections.push_back(S);452 sections.push_back(s);
454453
455 // Initially, we use hash values to partition sections.454 // Initially, we use hash values to partition sections.
456 parallelForEach(Sections, [&](InputSection *S) {455 parallelForEach(sections, [&](InputSection *s) {
457 S->Class[0] = xxHash64(S->data());456 s->eqClass[0] = xxHash64(s->data());
458 });457 });
459458
460 for (unsigned Cnt = 0; Cnt != 2; ++Cnt) {459 for (unsigned cnt = 0; cnt != 2; ++cnt) {
461 parallelForEach(Sections, [&](InputSection *S) {460 parallelForEach(sections, [&](InputSection *s) {
462 if (S->AreRelocsRela)461 if (s->areRelocsRela)
463 combineRelocHashes<ELFT>(Cnt, S, S->template relas<ELFT>());462 combineRelocHashes<ELFT>(cnt, s, s->template relas<ELFT>());
464 else463 else
465 combineRelocHashes<ELFT>(Cnt, S, S->template rels<ELFT>());464 combineRelocHashes<ELFT>(cnt, s, s->template rels<ELFT>());
466 });465 });
467 }466 }
468467
469 // From now on, sections in Sections vector are ordered so that sections468 // From now on, sections in Sections vector are ordered so that sections
470 // in the same equivalence class are consecutive in the vector.469 // in the same equivalence class are consecutive in the vector.
471 std::stable_sort(Sections.begin(), Sections.end(),470 llvm::stable_sort(sections, [](const InputSection *a, const InputSection *b) {
472 [](InputSection *A, InputSection *B) {471 return a->eqClass[0] < b->eqClass[0];
473 return A->Class[0] < B->Class[0];472 });
474 });
475473
476 // Compare static contents and assign unique IDs for each static content.474 // Compare static contents and assign unique IDs for each static content.
477 forEachClass([&](size_t Begin, size_t End) { segregate(Begin, End, true); });475 forEachClass([&](size_t begin, size_t end) { segregate(begin, end, true); });
478476
479 // Split groups by comparing relocations until convergence is obtained.477 // Split groups by comparing relocations until convergence is obtained.
480 do {478 do {
481 Repeat = false;479 repeat = false;
482 forEachClass(480 forEachClass(
483 [&](size_t Begin, size_t End) { segregate(Begin, End, false); });481 [&](size_t begin, size_t end) { segregate(begin, end, false); });
484 } while (Repeat);482 } while (repeat);
485483
486 log("ICF needed " + Twine(Cnt) + " iterations");484 log("ICF needed " + Twine(cnt) + " iterations");
487485
488 // Merge sections by the equivalence class.486 // Merge sections by the equivalence class.
489 forEachClassRange(0, Sections.size(), [&](size_t Begin, size_t End) {487 forEachClassRange(0, sections.size(), [&](size_t begin, size_t end) {
490 if (End - Begin == 1)488 if (end - begin == 1)
491 return;489 return;
492 print("selected section " + toString(Sections[Begin]));490 print("selected section " + toString(sections[begin]));
493 for (size_t I = Begin + 1; I < End; ++I) {491 for (size_t i = begin + 1; i < end; ++i) {
494 print(" removing identical section " + toString(Sections[I]));492 print(" removing identical section " + toString(sections[i]));
495 Sections[Begin]->replace(Sections[I]);493 sections[begin]->replace(sections[i]);
496494
497 // At this point we know sections merged are fully identical and hence495 // At this point we know sections merged are fully identical and hence
498 // we want to remove duplicate implicit dependencies such as link order496 // we want to remove duplicate implicit dependencies such as link order
499 // and relocation sections.497 // and relocation sections.
500 for (InputSection *IS : Sections[I]->DependentSections)498 for (InputSection *isec : sections[i]->dependentSections)
501 IS->Live = false;499 isec->markDead();
502 }500 }
503 });501 });
504}502}
deps/lld/ELF/ICF.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ICF.h --------------------------------------------------------------===//1//===- ICF.h --------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/ELF/InputFiles.cpp+991-691
...@@ -1,13 +1,13 @@...@@ -1,13 +1,13 @@
1//===- InputFiles.cpp -----------------------------------------------------===//1//===- InputFiles.cpp -----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
10#include "InputFiles.h"9#include "InputFiles.h"
10#include "Driver.h"
11#include "InputSection.h"11#include "InputSection.h"
12#include "LinkerScript.h"12#include "LinkerScript.h"
13#include "SymbolTable.h"13#include "SymbolTable.h"
...@@ -25,6 +25,7 @@...@@ -25,6 +25,7 @@
25#include "llvm/Object/ELFObjectFile.h"25#include "llvm/Object/ELFObjectFile.h"
26#include "llvm/Support/ARMAttributeParser.h"26#include "llvm/Support/ARMAttributeParser.h"
27#include "llvm/Support/ARMBuildAttributes.h"27#include "llvm/Support/ARMBuildAttributes.h"
28#include "llvm/Support/Endian.h"
28#include "llvm/Support/Path.h"29#include "llvm/Support/Path.h"
29#include "llvm/Support/TarWriter.h"30#include "llvm/Support/TarWriter.h"
30#include "llvm/Support/raw_ostream.h"31#include "llvm/Support/raw_ostream.h"
...@@ -34,145 +35,272 @@ using namespace llvm::ELF;...@@ -34,145 +35,272 @@ using namespace llvm::ELF;
34using namespace llvm::object;35using namespace llvm::object;
35using namespace llvm::sys;36using namespace llvm::sys;
36using namespace llvm::sys::fs;37using namespace llvm::sys::fs;
38using namespace llvm::support::endian;
3739
38using namespace lld;40using namespace lld;
39using namespace lld::elf;41using namespace lld::elf;
4042
41bool InputFile::IsInGroup;43bool InputFile::isInGroup;
42uint32_t InputFile::NextGroupId;44uint32_t InputFile::nextGroupId;
43std::vector<BinaryFile *> elf::BinaryFiles;45std::vector<BinaryFile *> elf::binaryFiles;
44std::vector<BitcodeFile *> elf::BitcodeFiles;46std::vector<BitcodeFile *> elf::bitcodeFiles;
45std::vector<LazyObjFile *> elf::LazyObjFiles;47std::vector<LazyObjFile *> elf::lazyObjFiles;
46std::vector<InputFile *> elf::ObjectFiles;48std::vector<InputFile *> elf::objectFiles;
47std::vector<InputFile *> elf::SharedFiles;49std::vector<SharedFile *> elf::sharedFiles;
4850
49std::unique_ptr<TarWriter> elf::Tar;51std::unique_ptr<TarWriter> elf::tar;
52
53static ELFKind getELFKind(MemoryBufferRef mb, StringRef archiveName) {
54 unsigned char size;
55 unsigned char endian;
56 std::tie(size, endian) = getElfArchType(mb.getBuffer());
57
58 auto report = [&](StringRef msg) {
59 StringRef filename = mb.getBufferIdentifier();
60 if (archiveName.empty())
61 fatal(filename + ": " + msg);
62 else
63 fatal(archiveName + "(" + filename + "): " + msg);
64 };
65
66 if (!mb.getBuffer().startswith(ElfMagic))
67 report("not an ELF file");
68 if (endian != ELFDATA2LSB && endian != ELFDATA2MSB)
69 report("corrupted ELF file: invalid data encoding");
70 if (size != ELFCLASS32 && size != ELFCLASS64)
71 report("corrupted ELF file: invalid file class");
72
73 size_t bufSize = mb.getBuffer().size();
74 if ((size == ELFCLASS32 && bufSize < sizeof(Elf32_Ehdr)) ||
75 (size == ELFCLASS64 && bufSize < sizeof(Elf64_Ehdr)))
76 report("corrupted ELF file: file is too short");
77
78 if (size == ELFCLASS32)
79 return (endian == ELFDATA2LSB) ? ELF32LEKind : ELF32BEKind;
80 return (endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind;
81}
5082
51InputFile::InputFile(Kind K, MemoryBufferRef M)83InputFile::InputFile(Kind k, MemoryBufferRef m)
52 : MB(M), GroupId(NextGroupId), FileKind(K) {84 : mb(m), groupId(nextGroupId), fileKind(k) {
53 // All files within the same --{start,end}-group get the same group ID.85 // All files within the same --{start,end}-group get the same group ID.
54 // Otherwise, a new file will get a new group ID.86 // Otherwise, a new file will get a new group ID.
55 if (!IsInGroup)87 if (!isInGroup)
56 ++NextGroupId;88 ++nextGroupId;
57}89}
5890
59Optional<MemoryBufferRef> elf::readFile(StringRef Path) {91Optional<MemoryBufferRef> elf::readFile(StringRef path) {
60 // The --chroot option changes our virtual root directory.92 // The --chroot option changes our virtual root directory.
61 // This is useful when you are dealing with files created by --reproduce.93 // This is useful when you are dealing with files created by --reproduce.
62 if (!Config->Chroot.empty() && Path.startswith("/"))94 if (!config->chroot.empty() && path.startswith("/"))
63 Path = Saver.save(Config->Chroot + Path);95 path = saver.save(config->chroot + path);
6496
65 log(Path);97 log(path);
6698
67 auto MBOrErr = MemoryBuffer::getFile(Path, -1, false);99 auto mbOrErr = MemoryBuffer::getFile(path, -1, false);
68 if (auto EC = MBOrErr.getError()) {100 if (auto ec = mbOrErr.getError()) {
69 error("cannot open " + Path + ": " + EC.message());101 error("cannot open " + path + ": " + ec.message());
70 return None;102 return None;
71 }103 }
72104
73 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;105 std::unique_ptr<MemoryBuffer> &mb = *mbOrErr;
74 MemoryBufferRef MBRef = MB->getMemBufferRef();106 MemoryBufferRef mbref = mb->getMemBufferRef();
75 make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership107 make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take MB ownership
108
109 if (tar)
110 tar->append(relativeToRoot(path), mbref.getBuffer());
111 return mbref;
112}
113
114// All input object files must be for the same architecture
115// (e.g. it does not make sense to link x86 object files with
116// MIPS object files.) This function checks for that error.
117static bool isCompatible(InputFile *file) {
118 if (!file->isElf() && !isa<BitcodeFile>(file))
119 return true;
120
121 if (file->ekind == config->ekind && file->emachine == config->emachine) {
122 if (config->emachine != EM_MIPS)
123 return true;
124 if (isMipsN32Abi(file) == config->mipsN32Abi)
125 return true;
126 }
127
128 if (!config->emulation.empty()) {
129 error(toString(file) + " is incompatible with " + config->emulation);
130 } else {
131 InputFile *existing;
132 if (!objectFiles.empty())
133 existing = objectFiles[0];
134 else if (!sharedFiles.empty())
135 existing = sharedFiles[0];
136 else
137 existing = bitcodeFiles[0];
138
139 error(toString(file) + " is incompatible with " + toString(existing));
140 }
141
142 return false;
143}
144
145template <class ELFT> static void doParseFile(InputFile *file) {
146 if (!isCompatible(file))
147 return;
148
149 // Binary file
150 if (auto *f = dyn_cast<BinaryFile>(file)) {
151 binaryFiles.push_back(f);
152 f->parse();
153 return;
154 }
155
156 // .a file
157 if (auto *f = dyn_cast<ArchiveFile>(file)) {
158 f->parse();
159 return;
160 }
161
162 // Lazy object file
163 if (auto *f = dyn_cast<LazyObjFile>(file)) {
164 lazyObjFiles.push_back(f);
165 f->parse<ELFT>();
166 return;
167 }
168
169 if (config->trace)
170 message(toString(file));
76171
77 if (Tar)172 // .so file
78 Tar->append(relativeToRoot(Path), MBRef.getBuffer());173 if (auto *f = dyn_cast<SharedFile>(file)) {
79 return MBRef;174 f->parse<ELFT>();
175 return;
176 }
177
178 // LLVM bitcode file
179 if (auto *f = dyn_cast<BitcodeFile>(file)) {
180 bitcodeFiles.push_back(f);
181 f->parse<ELFT>();
182 return;
183 }
184
185 // Regular object file
186 objectFiles.push_back(file);
187 cast<ObjFile<ELFT>>(file)->parse();
188}
189
190// Add symbols in File to the symbol table.
191void elf::parseFile(InputFile *file) {
192 switch (config->ekind) {
193 case ELF32LEKind:
194 doParseFile<ELF32LE>(file);
195 return;
196 case ELF32BEKind:
197 doParseFile<ELF32BE>(file);
198 return;
199 case ELF64LEKind:
200 doParseFile<ELF64LE>(file);
201 return;
202 case ELF64BEKind:
203 doParseFile<ELF64BE>(file);
204 return;
205 default:
206 llvm_unreachable("unknown ELFT");
207 }
80}208}
81209
82// Concatenates arguments to construct a string representing an error location.210// Concatenates arguments to construct a string representing an error location.
83static std::string createFileLineMsg(StringRef Path, unsigned Line) {211static std::string createFileLineMsg(StringRef path, unsigned line) {
84 std::string Filename = path::filename(Path);212 std::string filename = path::filename(path);
85 std::string Lineno = ":" + std::to_string(Line);213 std::string lineno = ":" + std::to_string(line);
86 if (Filename == Path)214 if (filename == path)
87 return Filename + Lineno;215 return filename + lineno;
88 return Filename + Lineno + " (" + Path.str() + Lineno + ")";216 return filename + lineno + " (" + path.str() + lineno + ")";
89}217}
90218
91template <class ELFT>219template <class ELFT>
92static std::string getSrcMsgAux(ObjFile<ELFT> &File, const Symbol &Sym,220static std::string getSrcMsgAux(ObjFile<ELFT> &file, const Symbol &sym,
93 InputSectionBase &Sec, uint64_t Offset) {221 InputSectionBase &sec, uint64_t offset) {
94 // In DWARF, functions and variables are stored to different places.222 // In DWARF, functions and variables are stored to different places.
95 // First, lookup a function for a given offset.223 // First, lookup a function for a given offset.
96 if (Optional<DILineInfo> Info = File.getDILineInfo(&Sec, Offset))224 if (Optional<DILineInfo> info = file.getDILineInfo(&sec, offset))
97 return createFileLineMsg(Info->FileName, Info->Line);225 return createFileLineMsg(info->FileName, info->Line);
98226
99 // If it failed, lookup again as a variable.227 // If it failed, lookup again as a variable.
100 if (Optional<std::pair<std::string, unsigned>> FileLine =228 if (Optional<std::pair<std::string, unsigned>> fileLine =
101 File.getVariableLoc(Sym.getName()))229 file.getVariableLoc(sym.getName()))
102 return createFileLineMsg(FileLine->first, FileLine->second);230 return createFileLineMsg(fileLine->first, fileLine->second);
103231
104 // File.SourceFile contains STT_FILE symbol, and that is a last resort.232 // File.sourceFile contains STT_FILE symbol, and that is a last resort.
105 return File.SourceFile;233 return file.sourceFile;
106}234}
107235
108std::string InputFile::getSrcMsg(const Symbol &Sym, InputSectionBase &Sec,236std::string InputFile::getSrcMsg(const Symbol &sym, InputSectionBase &sec,
109 uint64_t Offset) {237 uint64_t offset) {
110 if (kind() != ObjKind)238 if (kind() != ObjKind)
111 return "";239 return "";
112 switch (Config->EKind) {240 switch (config->ekind) {
113 default:241 default:
114 llvm_unreachable("Invalid kind");242 llvm_unreachable("Invalid kind");
115 case ELF32LEKind:243 case ELF32LEKind:
116 return getSrcMsgAux(cast<ObjFile<ELF32LE>>(*this), Sym, Sec, Offset);244 return getSrcMsgAux(cast<ObjFile<ELF32LE>>(*this), sym, sec, offset);
117 case ELF32BEKind:245 case ELF32BEKind:
118 return getSrcMsgAux(cast<ObjFile<ELF32BE>>(*this), Sym, Sec, Offset);246 return getSrcMsgAux(cast<ObjFile<ELF32BE>>(*this), sym, sec, offset);
119 case ELF64LEKind:247 case ELF64LEKind:
120 return getSrcMsgAux(cast<ObjFile<ELF64LE>>(*this), Sym, Sec, Offset);248 return getSrcMsgAux(cast<ObjFile<ELF64LE>>(*this), sym, sec, offset);
121 case ELF64BEKind:249 case ELF64BEKind:
122 return getSrcMsgAux(cast<ObjFile<ELF64BE>>(*this), Sym, Sec, Offset);250 return getSrcMsgAux(cast<ObjFile<ELF64BE>>(*this), sym, sec, offset);
123 }251 }
124}252}
125253
126template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {254template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
127 Dwarf = llvm::make_unique<DWARFContext>(make_unique<LLDDwarfObj<ELFT>>(this));255 dwarf = llvm::make_unique<DWARFContext>(make_unique<LLDDwarfObj<ELFT>>(this));
128 for (std::unique_ptr<DWARFUnit> &CU : Dwarf->compile_units()) {256 for (std::unique_ptr<DWARFUnit> &cu : dwarf->compile_units()) {
129 auto Report = [](Error Err) {257 auto report = [](Error err) {
130 handleAllErrors(std::move(Err),258 handleAllErrors(std::move(err),
131 [](ErrorInfoBase &Info) { warn(Info.message()); });259 [](ErrorInfoBase &info) { warn(info.message()); });
132 };260 };
133 Expected<const DWARFDebugLine::LineTable *> ExpectedLT =261 Expected<const DWARFDebugLine::LineTable *> expectedLT =
134 Dwarf->getLineTableForUnit(CU.get(), Report);262 dwarf->getLineTableForUnit(cu.get(), report);
135 const DWARFDebugLine::LineTable *LT = nullptr;263 const DWARFDebugLine::LineTable *lt = nullptr;
136 if (ExpectedLT)264 if (expectedLT)
137 LT = *ExpectedLT;265 lt = *expectedLT;
138 else266 else
139 Report(ExpectedLT.takeError());267 report(expectedLT.takeError());
140 if (!LT)268 if (!lt)
141 continue;269 continue;
142 LineTables.push_back(LT);270 lineTables.push_back(lt);
143271
144 // Loop over variable records and insert them to VariableLoc.272 // Loop over variable records and insert them to variableLoc.
145 for (const auto &Entry : CU->dies()) {273 for (const auto &entry : cu->dies()) {
146 DWARFDie Die(CU.get(), &Entry);274 DWARFDie die(cu.get(), &entry);
147 // Skip all tags that are not variables.275 // Skip all tags that are not variables.
148 if (Die.getTag() != dwarf::DW_TAG_variable)276 if (die.getTag() != dwarf::DW_TAG_variable)
149 continue;277 continue;
150278
151 // Skip if a local variable because we don't need them for generating279 // Skip if a local variable because we don't need them for generating
152 // error messages. In general, only non-local symbols can fail to be280 // error messages. In general, only non-local symbols can fail to be
153 // linked.281 // linked.
154 if (!dwarf::toUnsigned(Die.find(dwarf::DW_AT_external), 0))282 if (!dwarf::toUnsigned(die.find(dwarf::DW_AT_external), 0))
155 continue;283 continue;
156284
157 // Get the source filename index for the variable.285 // Get the source filename index for the variable.
158 unsigned File = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_file), 0);286 unsigned file = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_file), 0);
159 if (!LT->hasFileAtIndex(File))287 if (!lt->hasFileAtIndex(file))
160 continue;288 continue;
161289
162 // Get the line number on which the variable is declared.290 // Get the line number on which the variable is declared.
163 unsigned Line = dwarf::toUnsigned(Die.find(dwarf::DW_AT_decl_line), 0);291 unsigned line = dwarf::toUnsigned(die.find(dwarf::DW_AT_decl_line), 0);
164292
165 // Here we want to take the variable name to add it into VariableLoc.293 // Here we want to take the variable name to add it into variableLoc.
166 // Variable can have regular and linkage name associated. At first, we try294 // Variable can have regular and linkage name associated. At first, we try
167 // to get linkage name as it can be different, for example when we have295 // to get linkage name as it can be different, for example when we have
168 // two variables in different namespaces of the same object. Use common296 // two variables in different namespaces of the same object. Use common
169 // name otherwise, but handle the case when it also absent in case if the297 // name otherwise, but handle the case when it also absent in case if the
170 // input object file lacks some debug info.298 // input object file lacks some debug info.
171 StringRef Name =299 StringRef name =
172 dwarf::toString(Die.find(dwarf::DW_AT_linkage_name),300 dwarf::toString(die.find(dwarf::DW_AT_linkage_name),
173 dwarf::toString(Die.find(dwarf::DW_AT_name), ""));301 dwarf::toString(die.find(dwarf::DW_AT_name), ""));
174 if (!Name.empty())302 if (!name.empty())
175 VariableLoc.insert({Name, {LT, File, Line}});303 variableLoc.insert({name, {lt, file, line}});
176 }304 }
177 }305 }
178}306}
...@@ -181,112 +309,152 @@ template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {...@@ -181,112 +309,152 @@ template <class ELFT> void ObjFile<ELFT>::initializeDwarf() {
181// object (variable, array, etc) definition.309// object (variable, array, etc) definition.
182template <class ELFT>310template <class ELFT>
183Optional<std::pair<std::string, unsigned>>311Optional<std::pair<std::string, unsigned>>
184ObjFile<ELFT>::getVariableLoc(StringRef Name) {312ObjFile<ELFT>::getVariableLoc(StringRef name) {
185 llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });313 llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); });
186314
187 // Return if we have no debug information about data object.315 // Return if we have no debug information about data object.
188 auto It = VariableLoc.find(Name);316 auto it = variableLoc.find(name);
189 if (It == VariableLoc.end())317 if (it == variableLoc.end())
190 return None;318 return None;
191319
192 // Take file name string from line table.320 // Take file name string from line table.
193 std::string FileName;321 std::string fileName;
194 if (!It->second.LT->getFileNameByIndex(322 if (!it->second.lt->getFileNameByIndex(
195 It->second.File, nullptr,323 it->second.file, {},
196 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, FileName))324 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, fileName))
197 return None;325 return None;
198326
199 return std::make_pair(FileName, It->second.Line);327 return std::make_pair(fileName, it->second.line);
200}328}
201329
202// Returns source line information for a given offset330// Returns source line information for a given offset
203// using DWARF debug info.331// using DWARF debug info.
204template <class ELFT>332template <class ELFT>
205Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *S,333Optional<DILineInfo> ObjFile<ELFT>::getDILineInfo(InputSectionBase *s,
206 uint64_t Offset) {334 uint64_t offset) {
207 llvm::call_once(InitDwarfLine, [this]() { initializeDwarf(); });335 llvm::call_once(initDwarfLine, [this]() { initializeDwarf(); });
336
337 // Detect SectionIndex for specified section.
338 uint64_t sectionIndex = object::SectionedAddress::UndefSection;
339 ArrayRef<InputSectionBase *> sections = s->file->getSections();
340 for (uint64_t curIndex = 0; curIndex < sections.size(); ++curIndex) {
341 if (s == sections[curIndex]) {
342 sectionIndex = curIndex;
343 break;
344 }
345 }
208346
209 // Use fake address calcuated by adding section file offset and offset in347 // Use fake address calcuated by adding section file offset and offset in
210 // section. See comments for ObjectInfo class.348 // section. See comments for ObjectInfo class.
211 DILineInfo Info;349 DILineInfo info;
212 for (const llvm::DWARFDebugLine::LineTable *LT : LineTables)350 for (const llvm::DWARFDebugLine::LineTable *lt : lineTables) {
213 if (LT->getFileLineInfoForAddress(351 if (lt->getFileLineInfoForAddress(
214 S->getOffsetInFile() + Offset, nullptr,352 {s->getOffsetInFile() + offset, sectionIndex}, nullptr,
215 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, Info))353 DILineInfoSpecifier::FileLineInfoKind::AbsoluteFilePath, info))
216 return Info;354 return info;
355 }
217 return None;356 return None;
218}357}
219358
220// Returns "<internal>", "foo.a(bar.o)" or "baz.o".359// Returns "<internal>", "foo.a(bar.o)" or "baz.o".
221std::string lld::toString(const InputFile *F) {360std::string lld::toString(const InputFile *f) {
222 if (!F)361 if (!f)
223 return "<internal>";362 return "<internal>";
224363
225 if (F->ToStringCache.empty()) {364 if (f->toStringCache.empty()) {
226 if (F->ArchiveName.empty())365 if (f->archiveName.empty())
227 F->ToStringCache = F->getName();366 f->toStringCache = f->getName();
228 else367 else
229 F->ToStringCache = (F->ArchiveName + "(" + F->getName() + ")").str();368 f->toStringCache = (f->archiveName + "(" + f->getName() + ")").str();
230 }369 }
231 return F->ToStringCache;370 return f->toStringCache;
232}371}
233372
234template <class ELFT>373ELFFileBase::ELFFileBase(Kind k, MemoryBufferRef mb) : InputFile(k, mb) {
235ELFFileBase<ELFT>::ELFFileBase(Kind K, MemoryBufferRef MB) : InputFile(K, MB) {374 ekind = getELFKind(mb, "");
236 if (ELFT::TargetEndianness == support::little)
237 EKind = ELFT::Is64Bits ? ELF64LEKind : ELF32LEKind;
238 else
239 EKind = ELFT::Is64Bits ? ELF64BEKind : ELF32BEKind;
240375
241 EMachine = getObj().getHeader()->e_machine;376 switch (ekind) {
242 OSABI = getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI];377 case ELF32LEKind:
378 init<ELF32LE>();
379 break;
380 case ELF32BEKind:
381 init<ELF32BE>();
382 break;
383 case ELF64LEKind:
384 init<ELF64LE>();
385 break;
386 case ELF64BEKind:
387 init<ELF64BE>();
388 break;
389 default:
390 llvm_unreachable("getELFKind");
391 }
243}392}
244393
245template <class ELFT>394template <typename Elf_Shdr>
246typename ELFT::SymRange ELFFileBase<ELFT>::getGlobalELFSyms() {395static const Elf_Shdr *findSection(ArrayRef<Elf_Shdr> sections, uint32_t type) {
247 return makeArrayRef(ELFSyms.begin() + FirstGlobal, ELFSyms.end());396 for (const Elf_Shdr &sec : sections)
397 if (sec.sh_type == type)
398 return &sec;
399 return nullptr;
248}400}
249401
250template <class ELFT>402template <class ELFT> void ELFFileBase::init() {
251uint32_t ELFFileBase<ELFT>::getSectionIndex(const Elf_Sym &Sym) const {403 using Elf_Shdr = typename ELFT::Shdr;
252 return CHECK(getObj().getSectionIndex(&Sym, ELFSyms, SymtabSHNDX), this);404 using Elf_Sym = typename ELFT::Sym;
253}
254405
255template <class ELFT>406 // Initialize trivial attributes.
256void ELFFileBase<ELFT>::initSymtab(ArrayRef<Elf_Shdr> Sections,407 const ELFFile<ELFT> &obj = getObj<ELFT>();
257 const Elf_Shdr *Symtab) {408 emachine = obj.getHeader()->e_machine;
258 FirstGlobal = Symtab->sh_info;409 osabi = obj.getHeader()->e_ident[llvm::ELF::EI_OSABI];
259 ELFSyms = CHECK(getObj().symbols(Symtab), this);410 abiVersion = obj.getHeader()->e_ident[llvm::ELF::EI_ABIVERSION];
260 if (FirstGlobal == 0 || FirstGlobal > ELFSyms.size())411
412 ArrayRef<Elf_Shdr> sections = CHECK(obj.sections(), this);
413
414 // Find a symbol table.
415 bool isDSO =
416 (identify_magic(mb.getBuffer()) == file_magic::elf_shared_object);
417 const Elf_Shdr *symtabSec =
418 findSection(sections, isDSO ? SHT_DYNSYM : SHT_SYMTAB);
419
420 if (!symtabSec)
421 return;
422
423 // Initialize members corresponding to a symbol table.
424 firstGlobal = symtabSec->sh_info;
425
426 ArrayRef<Elf_Sym> eSyms = CHECK(obj.symbols(symtabSec), this);
427 if (firstGlobal == 0 || firstGlobal > eSyms.size())
261 fatal(toString(this) + ": invalid sh_info in symbol table");428 fatal(toString(this) + ": invalid sh_info in symbol table");
262429
263 StringTable =430 elfSyms = reinterpret_cast<const void *>(eSyms.data());
264 CHECK(getObj().getStringTableForSymtab(*Symtab, Sections), this);431 numELFSyms = eSyms.size();
432 stringTable = CHECK(obj.getStringTableForSymtab(*symtabSec, sections), this);
265}433}
266434
267template <class ELFT>435template <class ELFT>
268ObjFile<ELFT>::ObjFile(MemoryBufferRef M, StringRef ArchiveName)436uint32_t ObjFile<ELFT>::getSectionIndex(const Elf_Sym &sym) const {
269 : ELFFileBase<ELFT>(Base::ObjKind, M) {437 return CHECK(
270 this->ArchiveName = ArchiveName;438 this->getObj().getSectionIndex(&sym, getELFSyms<ELFT>(), shndxTable),
439 this);
271}440}
272441
273template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getLocalSymbols() {442template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getLocalSymbols() {
274 if (this->Symbols.empty())443 if (this->symbols.empty())
275 return {};444 return {};
276 return makeArrayRef(this->Symbols).slice(1, this->FirstGlobal - 1);445 return makeArrayRef(this->symbols).slice(1, this->firstGlobal - 1);
277}446}
278447
279template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getGlobalSymbols() {448template <class ELFT> ArrayRef<Symbol *> ObjFile<ELFT>::getGlobalSymbols() {
280 return makeArrayRef(this->Symbols).slice(this->FirstGlobal);449 return makeArrayRef(this->symbols).slice(this->firstGlobal);
281}450}
282451
283template <class ELFT>452template <class ELFT> void ObjFile<ELFT>::parse(bool ignoreComdats) {
284void ObjFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {453 // Read a section table. justSymbols is usually false.
285 // Read a section table. JustSymbols is usually false.454 if (this->justSymbols)
286 if (this->JustSymbols)
287 initializeJustSymbols();455 initializeJustSymbols();
288 else456 else
289 initializeSections(ComdatGroups);457 initializeSections(ignoreComdats);
290458
291 // Read a symbol table.459 // Read a symbol table.
292 initializeSymbols();460 initializeSymbols();
...@@ -296,17 +464,13 @@ void ObjFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {...@@ -296,17 +464,13 @@ void ObjFile<ELFT>::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {
296// They are identified and deduplicated by group name. This function464// They are identified and deduplicated by group name. This function
297// returns a group name.465// returns a group name.
298template <class ELFT>466template <class ELFT>
299StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,467StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> sections,
300 const Elf_Shdr &Sec) {468 const Elf_Shdr &sec) {
301 // Group signatures are stored as symbol names in object files.469 typename ELFT::SymRange symbols = this->getELFSyms<ELFT>();
302 // sh_info contains a symbol index, so we fetch a symbol and read its name.470 if (sec.sh_info >= symbols.size())
303 if (this->ELFSyms.empty())471 fatal(toString(this) + ": invalid symbol index");
304 this->initSymtab(472 const typename ELFT::Sym &sym = symbols[sec.sh_info];
305 Sections, CHECK(object::getSection<ELFT>(Sections, Sec.sh_link), this));473 StringRef signature = CHECK(sym.getName(this->stringTable), this);
306
307 const Elf_Sym *Sym =
308 CHECK(object::getSymbol<ELFT>(this->ELFSyms, Sec.sh_info), this);
309 StringRef Signature = CHECK(Sym->getName(this->StringTable), this);
310474
311 // As a special case, if a symbol is a section symbol and has no name,475 // As a special case, if a symbol is a section symbol and has no name,
312 // we use a section name as a signature.476 // we use a section name as a signature.
...@@ -315,12 +479,12 @@ StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,...@@ -315,12 +479,12 @@ StringRef ObjFile<ELFT>::getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
315 // standard, but GNU gold 1.14 (the newest version as of July 2017) or479 // standard, but GNU gold 1.14 (the newest version as of July 2017) or
316 // older produce such sections as outputs for the -r option, so we need480 // older produce such sections as outputs for the -r option, so we need
317 // a bug-compatibility.481 // a bug-compatibility.
318 if (Signature.empty() && Sym->getType() == STT_SECTION)482 if (signature.empty() && sym.getType() == STT_SECTION)
319 return getSectionName(Sec);483 return getSectionName(sec);
320 return Signature;484 return signature;
321}485}
322486
323template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {487template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &sec) {
324 // On a regular link we don't merge sections if -O0 (default is -O1). This488 // On a regular link we don't merge sections if -O0 (default is -O1). This
325 // sometimes makes the linker significantly faster, although the output will489 // sometimes makes the linker significantly faster, although the output will
326 // be bigger.490 // be bigger.
...@@ -333,14 +497,14 @@ template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {...@@ -333,14 +497,14 @@ template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
333 // SHF_MERGE sections based both on their name and sh_entsize, but that seems497 // SHF_MERGE sections based both on their name and sh_entsize, but that seems
334 // to be more trouble than it is worth. Instead, we just use the regular (-O1)498 // to be more trouble than it is worth. Instead, we just use the regular (-O1)
335 // logic for -r.499 // logic for -r.
336 if (Config->Optimize == 0 && !Config->Relocatable)500 if (config->optimize == 0 && !config->relocatable)
337 return false;501 return false;
338502
339 // A mergeable section with size 0 is useless because they don't have503 // A mergeable section with size 0 is useless because they don't have
340 // any data to merge. A mergeable string section with size 0 can be504 // any data to merge. A mergeable string section with size 0 can be
341 // argued as invalid because it doesn't end with a null character.505 // argued as invalid because it doesn't end with a null character.
342 // We'll avoid a mess by handling them as if they were non-mergeable.506 // We'll avoid a mess by handling them as if they were non-mergeable.
343 if (Sec.sh_size == 0)507 if (sec.sh_size == 0)
344 return false;508 return false;
345509
346 // Check for sh_entsize. The ELF spec is not clear about the zero510 // Check for sh_entsize. The ELF spec is not clear about the zero
...@@ -348,17 +512,17 @@ template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {...@@ -348,17 +512,17 @@ template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
348 // the section does not hold a table of fixed-size entries". We know512 // the section does not hold a table of fixed-size entries". We know
349 // that Rust 1.13 produces a string mergeable section with a zero513 // that Rust 1.13 produces a string mergeable section with a zero
350 // sh_entsize. Here we just accept it rather than being picky about it.514 // sh_entsize. Here we just accept it rather than being picky about it.
351 uint64_t EntSize = Sec.sh_entsize;515 uint64_t entSize = sec.sh_entsize;
352 if (EntSize == 0)516 if (entSize == 0)
353 return false;517 return false;
354 if (Sec.sh_size % EntSize)518 if (sec.sh_size % entSize)
355 fatal(toString(this) +519 fatal(toString(this) +
356 ": SHF_MERGE section size must be a multiple of sh_entsize");520 ": SHF_MERGE section size must be a multiple of sh_entsize");
357521
358 uint64_t Flags = Sec.sh_flags;522 uint64_t flags = sec.sh_flags;
359 if (!(Flags & SHF_MERGE))523 if (!(flags & SHF_MERGE))
360 return false;524 return false;
361 if (Flags & SHF_WRITE)525 if (flags & SHF_WRITE)
362 fatal(toString(this) + ": writable SHF_MERGE section is not supported");526 fatal(toString(this) + ": writable SHF_MERGE section is not supported");
363527
364 return true;528 return true;
...@@ -374,126 +538,138 @@ template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {...@@ -374,126 +538,138 @@ template <class ELFT> bool ObjFile<ELFT>::shouldMerge(const Elf_Shdr &Sec) {
374// When the option is given, we link "just symbols". The section table is538// When the option is given, we link "just symbols". The section table is
375// initialized with null pointers.539// initialized with null pointers.
376template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {540template <class ELFT> void ObjFile<ELFT>::initializeJustSymbols() {
377 ArrayRef<Elf_Shdr> ObjSections = CHECK(this->getObj().sections(), this);541 ArrayRef<Elf_Shdr> sections = CHECK(this->getObj().sections(), this);
378 this->Sections.resize(ObjSections.size());542 this->sections.resize(sections.size());
543}
379544
380 for (const Elf_Shdr &Sec : ObjSections) {545// An ELF object file may contain a `.deplibs` section. If it exists, the
381 if (Sec.sh_type != SHT_SYMTAB)546// section contains a list of library specifiers such as `m` for libm. This
382 continue;547// function resolves a given name by finding the first matching library checking
383 this->initSymtab(ObjSections, &Sec);548// the various ways that a library can be specified to LLD. This ELF extension
549// is a form of autolinking and is called `dependent libraries`. It is currently
550// unique to LLVM and lld.
551static void addDependentLibrary(StringRef specifier, const InputFile *f) {
552 if (!config->dependentLibraries)
384 return;553 return;
385 }554 if (fs::exists(specifier))
555 driver->addFile(specifier, /*withLOption=*/false);
556 else if (Optional<std::string> s = findFromSearchPaths(specifier))
557 driver->addFile(*s, /*withLOption=*/true);
558 else if (Optional<std::string> s = searchLibraryBaseName(specifier))
559 driver->addFile(*s, /*withLOption=*/true);
560 else
561 error(toString(f) +
562 ": unable to find library from dependent library specifier: " +
563 specifier);
386}564}
387565
388template <class ELFT>566template <class ELFT>
389void ObjFile<ELFT>::initializeSections(567void ObjFile<ELFT>::initializeSections(bool ignoreComdats) {
390 DenseSet<CachedHashStringRef> &ComdatGroups) {568 const ELFFile<ELFT> &obj = this->getObj();
391 const ELFFile<ELFT> &Obj = this->getObj();569
392570 ArrayRef<Elf_Shdr> objSections = CHECK(obj.sections(), this);
393 ArrayRef<Elf_Shdr> ObjSections = CHECK(Obj.sections(), this);571 uint64_t size = objSections.size();
394 uint64_t Size = ObjSections.size();572 this->sections.resize(size);
395 this->Sections.resize(Size);573 this->sectionStringTable =
396 this->SectionStringTable =574 CHECK(obj.getSectionStringTable(objSections), this);
397 CHECK(Obj.getSectionStringTable(ObjSections), this);575
398576 for (size_t i = 0, e = objSections.size(); i < e; i++) {
399 for (size_t I = 0, E = ObjSections.size(); I < E; I++) {577 if (this->sections[i] == &InputSection::discarded)
400 if (this->Sections[I] == &InputSection::Discarded)
401 continue;578 continue;
402 const Elf_Shdr &Sec = ObjSections[I];579 const Elf_Shdr &sec = objSections[i];
403580
404 if (Sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)581 if (sec.sh_type == ELF::SHT_LLVM_CALL_GRAPH_PROFILE)
405 CGProfile = check(582 cgProfile =
406 this->getObj().template getSectionContentsAsArray<Elf_CGProfile>(583 check(obj.template getSectionContentsAsArray<Elf_CGProfile>(&sec));
407 &Sec));
408584
409 // SHF_EXCLUDE'ed sections are discarded by the linker. However,585 // SHF_EXCLUDE'ed sections are discarded by the linker. However,
410 // if -r is given, we'll let the final link discard such sections.586 // if -r is given, we'll let the final link discard such sections.
411 // This is compatible with GNU.587 // This is compatible with GNU.
412 if ((Sec.sh_flags & SHF_EXCLUDE) && !Config->Relocatable) {588 if ((sec.sh_flags & SHF_EXCLUDE) && !config->relocatable) {
413 if (Sec.sh_type == SHT_LLVM_ADDRSIG) {589 if (sec.sh_type == SHT_LLVM_ADDRSIG) {
414 // We ignore the address-significance table if we know that the object590 // We ignore the address-significance table if we know that the object
415 // file was created by objcopy or ld -r. This is because these tools591 // file was created by objcopy or ld -r. This is because these tools
416 // will reorder the symbols in the symbol table, invalidating the data592 // will reorder the symbols in the symbol table, invalidating the data
417 // in the address-significance table, which refers to symbols by index.593 // in the address-significance table, which refers to symbols by index.
418 if (Sec.sh_link != 0)594 if (sec.sh_link != 0)
419 this->AddrsigSec = &Sec;595 this->addrsigSec = &sec;
420 else if (Config->ICF == ICFLevel::Safe)596 else if (config->icf == ICFLevel::Safe)
421 warn(toString(this) + ": --icf=safe is incompatible with object "597 warn(toString(this) + ": --icf=safe is incompatible with object "
422 "files created using objcopy or ld -r");598 "files created using objcopy or ld -r");
423 }599 }
424 this->Sections[I] = &InputSection::Discarded;600 this->sections[i] = &InputSection::discarded;
425 continue;601 continue;
426 }602 }
427603
428 switch (Sec.sh_type) {604 switch (sec.sh_type) {
429 case SHT_GROUP: {605 case SHT_GROUP: {
430 // De-duplicate section groups by their signatures.606 // De-duplicate section groups by their signatures.
431 StringRef Signature = getShtGroupSignature(ObjSections, Sec);607 StringRef signature = getShtGroupSignature(objSections, sec);
432 this->Sections[I] = &InputSection::Discarded;608 this->sections[i] = &InputSection::discarded;
433609
434610
435 ArrayRef<Elf_Word> Entries =611 ArrayRef<Elf_Word> entries =
436 CHECK(Obj.template getSectionContentsAsArray<Elf_Word>(&Sec), this);612 CHECK(obj.template getSectionContentsAsArray<Elf_Word>(&sec), this);
437 if (Entries.empty())613 if (entries.empty())
438 fatal(toString(this) + ": empty SHT_GROUP");614 fatal(toString(this) + ": empty SHT_GROUP");
439615
440 // The first word of a SHT_GROUP section contains flags. Currently,616 // The first word of a SHT_GROUP section contains flags. Currently,
441 // the standard defines only "GRP_COMDAT" flag for the COMDAT group.617 // the standard defines only "GRP_COMDAT" flag for the COMDAT group.
442 // An group with the empty flag doesn't define anything; such sections618 // An group with the empty flag doesn't define anything; such sections
443 // are just skipped.619 // are just skipped.
444 if (Entries[0] == 0)620 if (entries[0] == 0)
445 continue;621 continue;
446622
447 if (Entries[0] != GRP_COMDAT)623 if (entries[0] != GRP_COMDAT)
448 fatal(toString(this) + ": unsupported SHT_GROUP format");624 fatal(toString(this) + ": unsupported SHT_GROUP format");
449625
450 bool IsNew = ComdatGroups.insert(CachedHashStringRef(Signature)).second;626 bool isNew =
451 if (IsNew) {627 ignoreComdats ||
452 if (Config->Relocatable)628 symtab->comdatGroups.try_emplace(CachedHashStringRef(signature), this)
453 this->Sections[I] = createInputSection(Sec);629 .second;
454 continue;630 if (isNew) {
631 if (config->relocatable)
632 this->sections[i] = createInputSection(sec);
633 continue;
455 }634 }
456635
457
458 // Otherwise, discard group members.636 // Otherwise, discard group members.
459 for (uint32_t SecIndex : Entries.slice(1)) {637 for (uint32_t secIndex : entries.slice(1)) {
460 if (SecIndex >= Size)638 if (secIndex >= size)
461 fatal(toString(this) +639 fatal(toString(this) +
462 ": invalid section index in group: " + Twine(SecIndex));640 ": invalid section index in group: " + Twine(secIndex));
463 this->Sections[SecIndex] = &InputSection::Discarded;641 this->sections[secIndex] = &InputSection::discarded;
464 }642 }
465 break;643 break;
466 }644 }
467 case SHT_SYMTAB:
468 this->initSymtab(ObjSections, &Sec);
469 break;
470 case SHT_SYMTAB_SHNDX:645 case SHT_SYMTAB_SHNDX:
471 this->SymtabSHNDX = CHECK(Obj.getSHNDXTable(Sec, ObjSections), this);646 shndxTable = CHECK(obj.getSHNDXTable(sec, objSections), this);
472 break;647 break;
648 case SHT_SYMTAB:
473 case SHT_STRTAB:649 case SHT_STRTAB:
474 case SHT_NULL:650 case SHT_NULL:
475 break;651 break;
476 default:652 default:
477 this->Sections[I] = createInputSection(Sec);653 this->sections[i] = createInputSection(sec);
478 }654 }
479655
480 // .ARM.exidx sections have a reverse dependency on the InputSection they656 // .ARM.exidx sections have a reverse dependency on the InputSection they
481 // have a SHF_LINK_ORDER dependency, this is identified by the sh_link.657 // have a SHF_LINK_ORDER dependency, this is identified by the sh_link.
482 if (Sec.sh_flags & SHF_LINK_ORDER) {658 if (sec.sh_flags & SHF_LINK_ORDER) {
483 InputSectionBase *LinkSec = nullptr;659 InputSectionBase *linkSec = nullptr;
484 if (Sec.sh_link < this->Sections.size())660 if (sec.sh_link < this->sections.size())
485 LinkSec = this->Sections[Sec.sh_link];661 linkSec = this->sections[sec.sh_link];
486 if (!LinkSec)662 if (!linkSec)
487 fatal(toString(this) +663 fatal(toString(this) +
488 ": invalid sh_link index: " + Twine(Sec.sh_link));664 ": invalid sh_link index: " + Twine(sec.sh_link));
489665
490 InputSection *IS = cast<InputSection>(this->Sections[I]);666 InputSection *isec = cast<InputSection>(this->sections[i]);
491 LinkSec->DependentSections.push_back(IS);667 linkSec->dependentSections.push_back(isec);
492 if (!isa<InputSection>(LinkSec))668 if (!isa<InputSection>(linkSec))
493 error("a section " + IS->Name +669 error("a section " + isec->name +
494 " with SHF_LINK_ORDER should not refer a non-regular "670 " with SHF_LINK_ORDER should not refer a non-regular "
495 "section: " +671 "section: " +
496 toString(LinkSec));672 toString(linkSec));
497 }673 }
498 }674 }
499}675}
...@@ -501,9 +677,9 @@ void ObjFile<ELFT>::initializeSections(...@@ -501,9 +677,9 @@ void ObjFile<ELFT>::initializeSections(
501// For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD677// For ARM only, to set the EF_ARM_ABI_FLOAT_SOFT or EF_ARM_ABI_FLOAT_HARD
502// flag in the ELF Header we need to look at Tag_ABI_VFP_args to find out how678// flag in the ELF Header we need to look at Tag_ABI_VFP_args to find out how
503// the input objects have been compiled.679// the input objects have been compiled.
504static void updateARMVFPArgs(const ARMAttributeParser &Attributes,680static void updateARMVFPArgs(const ARMAttributeParser &attributes,
505 const InputFile *F) {681 const InputFile *f) {
506 if (!Attributes.hasAttribute(ARMBuildAttrs::ABI_VFP_args))682 if (!attributes.hasAttribute(ARMBuildAttrs::ABI_VFP_args))
507 // If an ABI tag isn't present then it is implicitly given the value of 0683 // If an ABI tag isn't present then it is implicitly given the value of 0
508 // which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files,684 // which maps to ARMBuildAttrs::BaseAAPCS. However many assembler files,
509 // including some in glibc that don't use FP args (and should have value 3)685 // including some in glibc that don't use FP args (and should have value 3)
...@@ -511,31 +687,31 @@ static void updateARMVFPArgs(const ARMAttributeParser &Attributes,...@@ -511,31 +687,31 @@ static void updateARMVFPArgs(const ARMAttributeParser &Attributes,
511 // as a clash.687 // as a clash.
512 return;688 return;
513689
514 unsigned VFPArgs = Attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args);690 unsigned vfpArgs = attributes.getAttributeValue(ARMBuildAttrs::ABI_VFP_args);
515 ARMVFPArgKind Arg;691 ARMVFPArgKind arg;
516 switch (VFPArgs) {692 switch (vfpArgs) {
517 case ARMBuildAttrs::BaseAAPCS:693 case ARMBuildAttrs::BaseAAPCS:
518 Arg = ARMVFPArgKind::Base;694 arg = ARMVFPArgKind::Base;
519 break;695 break;
520 case ARMBuildAttrs::HardFPAAPCS:696 case ARMBuildAttrs::HardFPAAPCS:
521 Arg = ARMVFPArgKind::VFP;697 arg = ARMVFPArgKind::VFP;
522 break;698 break;
523 case ARMBuildAttrs::ToolChainFPPCS:699 case ARMBuildAttrs::ToolChainFPPCS:
524 // Tool chain specific convention that conforms to neither AAPCS variant.700 // Tool chain specific convention that conforms to neither AAPCS variant.
525 Arg = ARMVFPArgKind::ToolChain;701 arg = ARMVFPArgKind::ToolChain;
526 break;702 break;
527 case ARMBuildAttrs::CompatibleFPAAPCS:703 case ARMBuildAttrs::CompatibleFPAAPCS:
528 // Object compatible with all conventions.704 // Object compatible with all conventions.
529 return;705 return;
530 default:706 default:
531 error(toString(F) + ": unknown Tag_ABI_VFP_args value: " + Twine(VFPArgs));707 error(toString(f) + ": unknown Tag_ABI_VFP_args value: " + Twine(vfpArgs));
532 return;708 return;
533 }709 }
534 // Follow ld.bfd and error if there is a mix of calling conventions.710 // Follow ld.bfd and error if there is a mix of calling conventions.
535 if (Config->ARMVFPArgs != Arg && Config->ARMVFPArgs != ARMVFPArgKind::Default)711 if (config->armVFPArgs != arg && config->armVFPArgs != ARMVFPArgKind::Default)
536 error(toString(F) + ": incompatible Tag_ABI_VFP_args");712 error(toString(f) + ": incompatible Tag_ABI_VFP_args");
537 else713 else
538 Config->ARMVFPArgs = Arg;714 config->armVFPArgs = arg;
539}715}
540716
541// The ARM support in lld makes some use of instructions that are not available717// The ARM support in lld makes some use of instructions that are not available
...@@ -547,11 +723,11 @@ static void updateARMVFPArgs(const ARMAttributeParser &Attributes,...@@ -547,11 +723,11 @@ static void updateARMVFPArgs(const ARMAttributeParser &Attributes,
547// at compile time. We follow the convention that if at least one input object723// at compile time. We follow the convention that if at least one input object
548// is compiled with an architecture that supports these features then lld is724// is compiled with an architecture that supports these features then lld is
549// permitted to use them.725// permitted to use them.
550static void updateSupportedARMFeatures(const ARMAttributeParser &Attributes) {726static void updateSupportedARMFeatures(const ARMAttributeParser &attributes) {
551 if (!Attributes.hasAttribute(ARMBuildAttrs::CPU_arch))727 if (!attributes.hasAttribute(ARMBuildAttrs::CPU_arch))
552 return;728 return;
553 auto Arch = Attributes.getAttributeValue(ARMBuildAttrs::CPU_arch);729 auto arch = attributes.getAttributeValue(ARMBuildAttrs::CPU_arch);
554 switch (Arch) {730 switch (arch) {
555 case ARMBuildAttrs::Pre_v4:731 case ARMBuildAttrs::Pre_v4:
556 case ARMBuildAttrs::v4:732 case ARMBuildAttrs::v4:
557 case ARMBuildAttrs::v4T:733 case ARMBuildAttrs::v4T:
...@@ -563,70 +739,156 @@ static void updateSupportedARMFeatures(const ARMAttributeParser &Attributes) {...@@ -563,70 +739,156 @@ static void updateSupportedARMFeatures(const ARMAttributeParser &Attributes) {
563 case ARMBuildAttrs::v6:739 case ARMBuildAttrs::v6:
564 case ARMBuildAttrs::v6KZ:740 case ARMBuildAttrs::v6KZ:
565 case ARMBuildAttrs::v6K:741 case ARMBuildAttrs::v6K:
566 Config->ARMHasBlx = true;742 config->armHasBlx = true;
567 // Architectures used in pre-Cortex processors do not support743 // Architectures used in pre-Cortex processors do not support
568 // The J1 = 1 J2 = 1 Thumb branch range extension, with the exception744 // The J1 = 1 J2 = 1 Thumb branch range extension, with the exception
569 // of Architecture v6T2 (arm1156t2-s and arm1156t2f-s) that do.745 // of Architecture v6T2 (arm1156t2-s and arm1156t2f-s) that do.
570 break;746 break;
571 default:747 default:
572 // All other Architectures have BLX and extended branch encoding748 // All other Architectures have BLX and extended branch encoding
573 Config->ARMHasBlx = true;749 config->armHasBlx = true;
574 Config->ARMJ1J2BranchEncoding = true;750 config->armJ1J2BranchEncoding = true;
575 if (Arch != ARMBuildAttrs::v6_M && Arch != ARMBuildAttrs::v6S_M)751 if (arch != ARMBuildAttrs::v6_M && arch != ARMBuildAttrs::v6S_M)
576 // All Architectures used in Cortex processors with the exception752 // All Architectures used in Cortex processors with the exception
577 // of v6-M and v6S-M have the MOVT and MOVW instructions.753 // of v6-M and v6S-M have the MOVT and MOVW instructions.
578 Config->ARMHasMovtMovw = true;754 config->armHasMovtMovw = true;
579 break;755 break;
580 }756 }
581}757}
582758
759// If a source file is compiled with x86 hardware-assisted call flow control
760// enabled, the generated object file contains feature flags indicating that
761// fact. This function reads the feature flags and returns it.
762//
763// Essentially we want to read a single 32-bit value in this function, but this
764// function is rather complicated because the value is buried deep inside a
765// .note.gnu.property section.
766//
767// The section consists of one or more NOTE records. Each NOTE record consists
768// of zero or more type-length-value fields. We want to find a field of a
769// certain type. It seems a bit too much to just store a 32-bit value, perhaps
770// the ABI is unnecessarily complicated.
771template <class ELFT>
772static uint32_t readAndFeatures(ObjFile<ELFT> *obj, ArrayRef<uint8_t> data) {
773 using Elf_Nhdr = typename ELFT::Nhdr;
774 using Elf_Note = typename ELFT::Note;
775
776 uint32_t featuresSet = 0;
777 while (!data.empty()) {
778 // Read one NOTE record.
779 if (data.size() < sizeof(Elf_Nhdr))
780 fatal(toString(obj) + ": .note.gnu.property: section too short");
781
782 auto *nhdr = reinterpret_cast<const Elf_Nhdr *>(data.data());
783 if (data.size() < nhdr->getSize())
784 fatal(toString(obj) + ": .note.gnu.property: section too short");
785
786 Elf_Note note(*nhdr);
787 if (nhdr->n_type != NT_GNU_PROPERTY_TYPE_0 || note.getName() != "GNU") {
788 data = data.slice(nhdr->getSize());
789 continue;
790 }
791
792 uint32_t featureAndType = config->emachine == EM_AARCH64
793 ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
794 : GNU_PROPERTY_X86_FEATURE_1_AND;
795
796 // Read a body of a NOTE record, which consists of type-length-value fields.
797 ArrayRef<uint8_t> desc = note.getDesc();
798 while (!desc.empty()) {
799 if (desc.size() < 8)
800 fatal(toString(obj) + ": .note.gnu.property: section too short");
801
802 uint32_t type = read32le(desc.data());
803 uint32_t size = read32le(desc.data() + 4);
804
805 if (type == featureAndType) {
806 // We found a FEATURE_1_AND field. There may be more than one of these
807 // in a .note.gnu.propery section, for a relocatable object we
808 // accumulate the bits set.
809 featuresSet |= read32le(desc.data() + 8);
810 }
811
812 // On 64-bit, a payload may be followed by a 4-byte padding to make its
813 // size a multiple of 8.
814 if (ELFT::Is64Bits)
815 size = alignTo(size, 8);
816
817 desc = desc.slice(size + 8); // +8 for Type and Size
818 }
819
820 // Go to next NOTE record to look for more FEATURE_1_AND descriptions.
821 data = data.slice(nhdr->getSize());
822 }
823
824 return featuresSet;
825}
826
583template <class ELFT>827template <class ELFT>
584InputSectionBase *ObjFile<ELFT>::getRelocTarget(const Elf_Shdr &Sec) {828InputSectionBase *ObjFile<ELFT>::getRelocTarget(const Elf_Shdr &sec) {
585 uint32_t Idx = Sec.sh_info;829 uint32_t idx = sec.sh_info;
586 if (Idx >= this->Sections.size())830 if (idx >= this->sections.size())
587 fatal(toString(this) + ": invalid relocated section index: " + Twine(Idx));831 fatal(toString(this) + ": invalid relocated section index: " + Twine(idx));
588 InputSectionBase *Target = this->Sections[Idx];832 InputSectionBase *target = this->sections[idx];
589833
590 // Strictly speaking, a relocation section must be included in the834 // Strictly speaking, a relocation section must be included in the
591 // group of the section it relocates. However, LLVM 3.3 and earlier835 // group of the section it relocates. However, LLVM 3.3 and earlier
592 // would fail to do so, so we gracefully handle that case.836 // would fail to do so, so we gracefully handle that case.
593 if (Target == &InputSection::Discarded)837 if (target == &InputSection::discarded)
594 return nullptr;838 return nullptr;
595839
596 if (!Target)840 if (!target)
597 fatal(toString(this) + ": unsupported relocation reference");841 fatal(toString(this) + ": unsupported relocation reference");
598 return Target;842 return target;
599}843}
600844
601// Create a regular InputSection class that has the same contents845// Create a regular InputSection class that has the same contents
602// as a given section.846// as a given section.
603static InputSection *toRegularSection(MergeInputSection *Sec) {847static InputSection *toRegularSection(MergeInputSection *sec) {
604 return make<InputSection>(Sec->File, Sec->Flags, Sec->Type, Sec->Alignment,848 return make<InputSection>(sec->file, sec->flags, sec->type, sec->alignment,
605 Sec->data(), Sec->Name);849 sec->data(), sec->name);
606}850}
607851
608template <class ELFT>852template <class ELFT>
609InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {853InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &sec) {
610 StringRef Name = getSectionName(Sec);854 StringRef name = getSectionName(sec);
611855
612 switch (Sec.sh_type) {856 switch (sec.sh_type) {
613 case SHT_ARM_ATTRIBUTES: {857 case SHT_ARM_ATTRIBUTES: {
614 if (Config->EMachine != EM_ARM)858 if (config->emachine != EM_ARM)
615 break;859 break;
616 ARMAttributeParser Attributes;860 ARMAttributeParser attributes;
617 ArrayRef<uint8_t> Contents = check(this->getObj().getSectionContents(&Sec));861 ArrayRef<uint8_t> contents = check(this->getObj().getSectionContents(&sec));
618 Attributes.Parse(Contents, /*isLittle*/ Config->EKind == ELF32LEKind);862 attributes.Parse(contents, /*isLittle*/ config->ekind == ELF32LEKind);
619 updateSupportedARMFeatures(Attributes);863 updateSupportedARMFeatures(attributes);
620 updateARMVFPArgs(Attributes, this);864 updateARMVFPArgs(attributes, this);
621865
622 // FIXME: Retain the first attribute section we see. The eglibc ARM866 // FIXME: Retain the first attribute section we see. The eglibc ARM
623 // dynamic loaders require the presence of an attribute section for dlopen867 // dynamic loaders require the presence of an attribute section for dlopen
624 // to work. In a full implementation we would merge all attribute sections.868 // to work. In a full implementation we would merge all attribute sections.
625 if (In.ARMAttributes == nullptr) {869 if (in.armAttributes == nullptr) {
626 In.ARMAttributes = make<InputSection>(*this, Sec, Name);870 in.armAttributes = make<InputSection>(*this, sec, name);
627 return In.ARMAttributes;871 return in.armAttributes;
872 }
873 return &InputSection::discarded;
874 }
875 case SHT_LLVM_DEPENDENT_LIBRARIES: {
876 if (config->relocatable)
877 break;
878 ArrayRef<char> data =
879 CHECK(this->getObj().template getSectionContentsAsArray<char>(&sec), this);
880 if (!data.empty() && data.back() != '\0') {
881 error(toString(this) +
882 ": corrupted dependent libraries section (unterminated string): " +
883 name);
884 return &InputSection::discarded;
628 }885 }
629 return &InputSection::Discarded;886 for (const char *d = data.begin(), *e = data.end(); d < e;) {
887 StringRef s(d);
888 addDependentLibrary(s, this);
889 d += s.size() + 1;
890 }
891 return &InputSection::discarded;
630 }892 }
631 case SHT_RELA:893 case SHT_RELA:
632 case SHT_REL: {894 case SHT_REL: {
...@@ -635,25 +897,25 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {...@@ -635,25 +897,25 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
635 // and the group is discarded, even though it's a violation of the897 // and the group is discarded, even though it's a violation of the
636 // spec. We handle that situation gracefully by discarding dangling898 // spec. We handle that situation gracefully by discarding dangling
637 // relocation sections.899 // relocation sections.
638 InputSectionBase *Target = getRelocTarget(Sec);900 InputSectionBase *target = getRelocTarget(sec);
639 if (!Target)901 if (!target)
640 return nullptr;902 return nullptr;
641903
642 // This section contains relocation information.904 // This section contains relocation information.
643 // If -r is given, we do not interpret or apply relocation905 // If -r is given, we do not interpret or apply relocation
644 // but just copy relocation sections to output.906 // but just copy relocation sections to output.
645 if (Config->Relocatable) {907 if (config->relocatable) {
646 InputSection *RelocSec = make<InputSection>(*this, Sec, Name);908 InputSection *relocSec = make<InputSection>(*this, sec, name);
647 // We want to add a dependency to target, similar like we do for909 // 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 script910 // -emit-relocs below. This is useful for the case when linker script
649 // contains the "/DISCARD/". It is perhaps uncommon to use a script with911 // 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 case912 // -r, but we faced it in the Linux kernel and have to handle such case
651 // and not to crash.913 // and not to crash.
652 Target->DependentSections.push_back(RelocSec);914 target->dependentSections.push_back(relocSec);
653 return RelocSec;915 return relocSec;
654 }916 }
655917
656 if (Target->FirstRelocation)918 if (target->firstRelocation)
657 fatal(toString(this) +919 fatal(toString(this) +
658 ": multiple relocation sections to one section are not supported");920 ": multiple relocation sections to one section are not supported");
659921
...@@ -662,33 +924,33 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {...@@ -662,33 +924,33 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
662 // because applying relocations at end of linking changes section924 // because applying relocations at end of linking changes section
663 // contents. So, we simply handle such sections as non-mergeable ones.925 // contents. So, we simply handle such sections as non-mergeable ones.
664 // Degrading like this is acceptable because section merging is optional.926 // Degrading like this is acceptable because section merging is optional.
665 if (auto *MS = dyn_cast<MergeInputSection>(Target)) {927 if (auto *ms = dyn_cast<MergeInputSection>(target)) {
666 Target = toRegularSection(MS);928 target = toRegularSection(ms);
667 this->Sections[Sec.sh_info] = Target;929 this->sections[sec.sh_info] = target;
668 }930 }
669931
670 if (Sec.sh_type == SHT_RELA) {932 if (sec.sh_type == SHT_RELA) {
671 ArrayRef<Elf_Rela> Rels = CHECK(this->getObj().relas(&Sec), this);933 ArrayRef<Elf_Rela> rels = CHECK(getObj().relas(&sec), this);
672 Target->FirstRelocation = Rels.begin();934 target->firstRelocation = rels.begin();
673 Target->NumRelocations = Rels.size();935 target->numRelocations = rels.size();
674 Target->AreRelocsRela = true;936 target->areRelocsRela = true;
675 } else {937 } else {
676 ArrayRef<Elf_Rel> Rels = CHECK(this->getObj().rels(&Sec), this);938 ArrayRef<Elf_Rel> rels = CHECK(getObj().rels(&sec), this);
677 Target->FirstRelocation = Rels.begin();939 target->firstRelocation = rels.begin();
678 Target->NumRelocations = Rels.size();940 target->numRelocations = rels.size();
679 Target->AreRelocsRela = false;941 target->areRelocsRela = false;
680 }942 }
681 assert(isUInt<31>(Target->NumRelocations));943 assert(isUInt<31>(target->numRelocations));
682944
683 // Relocation sections processed by the linker are usually removed945 // Relocation sections processed by the linker are usually removed
684 // from the output, so returning `nullptr` for the normal case.946 // from the output, so returning `nullptr` for the normal case.
685 // However, if -emit-relocs is given, we need to leave them in the output.947 // However, if -emit-relocs is given, we need to leave them in the output.
686 // (Some post link analysis tools need this information.)948 // (Some post link analysis tools need this information.)
687 if (Config->EmitRelocs) {949 if (config->emitRelocs) {
688 InputSection *RelocSec = make<InputSection>(*this, Sec, Name);950 InputSection *relocSec = make<InputSection>(*this, sec, name);
689 // We will not emit relocation section if target was discarded.951 // We will not emit relocation section if target was discarded.
690 Target->DependentSections.push_back(RelocSec);952 target->dependentSections.push_back(relocSec);
691 return RelocSec;953 return relocSec;
692 }954 }
693 return nullptr;955 return nullptr;
694 }956 }
...@@ -707,28 +969,42 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {...@@ -707,28 +969,42 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
707 // explicitly told to do otherwise (by -z execstack). Because the stack969 // explicitly told to do otherwise (by -z execstack). Because the stack
708 // executable-ness is controlled solely by command line options,970 // executable-ness is controlled solely by command line options,
709 // .note.GNU-stack sections are simply ignored.971 // .note.GNU-stack sections are simply ignored.
710 if (Name == ".note.GNU-stack")972 if (name == ".note.GNU-stack")
711 return &InputSection::Discarded;973 return &InputSection::discarded;
974
975 // Object files that use processor features such as Intel Control-Flow
976 // Enforcement (CET) or AArch64 Branch Target Identification BTI, use a
977 // .note.gnu.property section containing a bitfield of feature bits like the
978 // GNU_PROPERTY_X86_FEATURE_1_IBT flag. Read a bitmap containing the flag.
979 //
980 // Since we merge bitmaps from multiple object files to create a new
981 // .note.gnu.property containing a single AND'ed bitmap, we discard an input
982 // file's .note.gnu.property section.
983 if (name == ".note.gnu.property") {
984 ArrayRef<uint8_t> contents = check(this->getObj().getSectionContents(&sec));
985 this->andFeatures = readAndFeatures(this, contents);
986 return &InputSection::discarded;
987 }
712988
713 // Split stacks is a feature to support a discontiguous stack,989 // Split stacks is a feature to support a discontiguous stack,
714 // commonly used in the programming language Go. For the details,990 // commonly used in the programming language Go. For the details,
715 // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled991 // see https://gcc.gnu.org/wiki/SplitStacks. An object file compiled
716 // for split stack will include a .note.GNU-split-stack section.992 // for split stack will include a .note.GNU-split-stack section.
717 if (Name == ".note.GNU-split-stack") {993 if (name == ".note.GNU-split-stack") {
718 if (Config->Relocatable) {994 if (config->relocatable) {
719 error("cannot mix split-stack and non-split-stack in a relocatable link");995 error("cannot mix split-stack and non-split-stack in a relocatable link");
720 return &InputSection::Discarded;996 return &InputSection::discarded;
721 }997 }
722 this->SplitStack = true;998 this->splitStack = true;
723 return &InputSection::Discarded;999 return &InputSection::discarded;
724 }1000 }
7251001
726 // An object file cmpiled for split stack, but where some of the1002 // An object file cmpiled for split stack, but where some of the
727 // functions were compiled with the no_split_stack_attribute will1003 // functions were compiled with the no_split_stack_attribute will
728 // include a .note.GNU-no-split-stack section.1004 // include a .note.GNU-no-split-stack section.
729 if (Name == ".note.GNU-no-split-stack") {1005 if (name == ".note.GNU-no-split-stack") {
730 this->SomeNoSplitStack = true;1006 this->someNoSplitStack = true;
731 return &InputSection::Discarded;1007 return &InputSection::discarded;
732 }1008 }
7331009
734 // The linkonce feature is a sort of proto-comdat. Some glibc i386 object1010 // The linkonce feature is a sort of proto-comdat. Some glibc i386 object
...@@ -736,246 +1012,205 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {...@@ -736,246 +1012,205 @@ InputSectionBase *ObjFile<ELFT>::createInputSection(const Elf_Shdr &Sec) {
736 // sections. Drop those sections to avoid duplicate symbol errors.1012 // sections. Drop those sections to avoid duplicate symbol errors.
737 // FIXME: This is glibc PR20543, we should remove this hack once that has been1013 // FIXME: This is glibc PR20543, we should remove this hack once that has been
738 // fixed for a while.1014 // fixed for a while.
739 if (Name == ".gnu.linkonce.t.__x86.get_pc_thunk.bx" ||1015 if (name == ".gnu.linkonce.t.__x86.get_pc_thunk.bx" ||
740 Name == ".gnu.linkonce.t.__i686.get_pc_thunk.bx")1016 name == ".gnu.linkonce.t.__i686.get_pc_thunk.bx")
741 return &InputSection::Discarded;1017 return &InputSection::discarded;
7421018
743 // If we are creating a new .build-id section, strip existing .build-id1019 // If we are creating a new .build-id section, strip existing .build-id
744 // sections so that the output won't have more than one .build-id.1020 // sections so that the output won't have more than one .build-id.
745 // This is not usually a problem because input object files normally don't1021 // This is not usually a problem because input object files normally don't
746 // have .build-id sections, but you can create such files by1022 // have .build-id sections, but you can create such files by
747 // "ld.{bfd,gold,lld} -r --build-id", and we want to guard against it.1023 // "ld.{bfd,gold,lld} -r --build-id", and we want to guard against it.
748 if (Name == ".note.gnu.build-id" && Config->BuildId != BuildIdKind::None)1024 if (name == ".note.gnu.build-id" && config->buildId != BuildIdKind::None)
749 return &InputSection::Discarded;1025 return &InputSection::discarded;
7501026
751 // The linker merges EH (exception handling) frames and creates a1027 // The linker merges EH (exception handling) frames and creates a
752 // .eh_frame_hdr section for runtime. So we handle them with a special1028 // .eh_frame_hdr section for runtime. So we handle them with a special
753 // class. For relocatable outputs, they are just passed through.1029 // class. For relocatable outputs, they are just passed through.
754 if (Name == ".eh_frame" && !Config->Relocatable)1030 if (name == ".eh_frame" && !config->relocatable)
755 return make<EhInputSection>(*this, Sec, Name);1031 return make<EhInputSection>(*this, sec, name);
7561032
757 if (shouldMerge(Sec))1033 if (shouldMerge(sec))
758 return make<MergeInputSection>(*this, Sec, Name);1034 return make<MergeInputSection>(*this, sec, name);
759 return make<InputSection>(*this, Sec, Name);1035 return make<InputSection>(*this, sec, name);
760}1036}
7611037
762template <class ELFT>1038template <class ELFT>
763StringRef ObjFile<ELFT>::getSectionName(const Elf_Shdr &Sec) {1039StringRef ObjFile<ELFT>::getSectionName(const Elf_Shdr &sec) {
764 return CHECK(this->getObj().getSectionName(&Sec, SectionStringTable), this);1040 return CHECK(getObj().getSectionName(&sec, sectionStringTable), this);
765}1041}
7661042
1043// Initialize this->Symbols. this->Symbols is a parallel array as
1044// its corresponding ELF symbol table.
767template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {1045template <class ELFT> void ObjFile<ELFT>::initializeSymbols() {
768 this->Symbols.reserve(this->ELFSyms.size());1046 ArrayRef<Elf_Sym> eSyms = this->getELFSyms<ELFT>();
769 for (const Elf_Sym &Sym : this->ELFSyms)1047 this->symbols.resize(eSyms.size());
770 this->Symbols.push_back(createSymbol(&Sym));1048
771}1049 // Our symbol table may have already been partially initialized
7721050 // because of LazyObjFile.
773template <class ELFT> Symbol *ObjFile<ELFT>::createSymbol(const Elf_Sym *Sym) {1051 for (size_t i = 0, end = eSyms.size(); i != end; ++i)
774 int Binding = Sym->getBinding();1052 if (!this->symbols[i] && eSyms[i].getBinding() != STB_LOCAL)
7751053 this->symbols[i] =
776 uint32_t SecIdx = this->getSectionIndex(*Sym);1054 symtab->insert(CHECK(eSyms[i].getName(this->stringTable), this));
777 if (SecIdx >= this->Sections.size())1055
778 fatal(toString(this) + ": invalid section index: " + Twine(SecIdx));1056 // Fill this->Symbols. A symbol is either local or global.
7791057 for (size_t i = 0, end = eSyms.size(); i != end; ++i) {
780 InputSectionBase *Sec = this->Sections[SecIdx];1058 const Elf_Sym &eSym = eSyms[i];
781 uint8_t StOther = Sym->st_other;1059
782 uint8_t Type = Sym->getType();1060 // Read symbol attributes.
783 uint64_t Value = Sym->st_value;1061 uint32_t secIdx = getSectionIndex(eSym);
784 uint64_t Size = Sym->st_size;1062 if (secIdx >= this->sections.size())
7851063 fatal(toString(this) + ": invalid section index: " + Twine(secIdx));
786 if (Binding == STB_LOCAL) {1064
787 if (Sym->getType() == STT_FILE)1065 InputSectionBase *sec = this->sections[secIdx];
788 SourceFile = CHECK(Sym->getName(this->StringTable), this);1066 uint8_t binding = eSym.getBinding();
1067 uint8_t stOther = eSym.st_other;
1068 uint8_t type = eSym.getType();
1069 uint64_t value = eSym.st_value;
1070 uint64_t size = eSym.st_size;
1071 StringRefZ name = this->stringTable.data() + eSym.st_name;
1072
1073 // Handle local symbols. Local symbols are not added to the symbol
1074 // table because they are not visible from other object files. We
1075 // allocate symbol instances and add their pointers to Symbols.
1076 if (binding == STB_LOCAL) {
1077 if (eSym.getType() == STT_FILE)
1078 sourceFile = CHECK(eSym.getName(this->stringTable), this);
1079
1080 if (this->stringTable.size() <= eSym.st_name)
1081 fatal(toString(this) + ": invalid symbol name offset");
1082
1083 if (eSym.st_shndx == SHN_UNDEF)
1084 this->symbols[i] = make<Undefined>(this, name, binding, stOther, type);
1085 else if (sec == &InputSection::discarded)
1086 this->symbols[i] = make<Undefined>(this, name, binding, stOther, type,
1087 /*DiscardedSecIdx=*/secIdx);
1088 else
1089 this->symbols[i] =
1090 make<Defined>(this, name, binding, stOther, type, value, size, sec);
1091 continue;
1092 }
7891093
790 if (this->StringTable.size() <= Sym->st_name)1094 // Handle global undefined symbols.
791 fatal(toString(this) + ": invalid symbol name offset");1095 if (eSym.st_shndx == SHN_UNDEF) {
1096 this->symbols[i]->resolve(Undefined{this, name, binding, stOther, type});
1097 continue;
1098 }
7921099
793 StringRefZ Name = this->StringTable.data() + Sym->st_name;1100 // Handle global common symbols.
794 if (Sym->st_shndx == SHN_UNDEF)1101 if (eSym.st_shndx == SHN_COMMON) {
795 return make<Undefined>(this, Name, Binding, StOther, Type);1102 if (value == 0 || value >= UINT32_MAX)
1103 fatal(toString(this) + ": common symbol '" + StringRef(name.data) +
1104 "' has invalid alignment: " + Twine(value));
1105 this->symbols[i]->resolve(
1106 CommonSymbol{this, name, binding, stOther, type, value, size});
1107 continue;
1108 }
7961109
797 return make<Defined>(this, Name, Binding, StOther, Type, Value, Size, Sec);1110 // If a defined symbol is in a discarded section, handle it as if it
798 }1111 // were an undefined symbol. Such symbol doesn't comply with the
1112 // standard, but in practice, a .eh_frame often directly refer
1113 // COMDAT member sections, and if a comdat group is discarded, some
1114 // defined symbol in a .eh_frame becomes dangling symbols.
1115 if (sec == &InputSection::discarded) {
1116 this->symbols[i]->resolve(
1117 Undefined{this, name, binding, stOther, type, secIdx});
1118 continue;
1119 }
7991120
800 StringRef Name = CHECK(Sym->getName(this->StringTable), this);1121 // Handle global defined symbols.
8011122 if (binding == STB_GLOBAL || binding == STB_WEAK ||
802 switch (Sym->st_shndx) {1123 binding == STB_GNU_UNIQUE) {
803 case SHN_UNDEF:1124 this->symbols[i]->resolve(
804 return Symtab->addUndefined<ELFT>(Name, Binding, StOther, Type,1125 Defined{this, name, binding, stOther, type, value, size, sec});
805 /*CanOmitFromDynSym=*/false, this);1126 continue;
806 case SHN_COMMON:1127 }
807 if (Value == 0 || Value >= UINT32_MAX)
808 fatal(toString(this) + ": common symbol '" + Name +
809 "' has invalid alignment: " + Twine(Value));
810 return Symtab->addCommon(Name, Size, Value, Binding, StOther, Type, *this);
811 }
8121128
813 switch (Binding) {1129 fatal(toString(this) + ": unexpected binding: " + Twine((int)binding));
814 default:
815 fatal(toString(this) + ": unexpected binding: " + Twine(Binding));
816 case STB_GLOBAL:
817 case STB_WEAK:
818 case STB_GNU_UNIQUE:
819 if (Sec == &InputSection::Discarded)
820 return Symtab->addUndefined<ELFT>(Name, Binding, StOther, Type,
821 /*CanOmitFromDynSym=*/false, this);
822 return Symtab->addDefined(Name, StOther, Type, Value, Size, Binding, Sec,
823 this);
824 }1130 }
825}1131}
8261132
827ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&File)1133ArchiveFile::ArchiveFile(std::unique_ptr<Archive> &&file)
828 : InputFile(ArchiveKind, File->getMemoryBufferRef()),1134 : InputFile(ArchiveKind, file->getMemoryBufferRef()),
829 File(std::move(File)) {}1135 file(std::move(file)) {}
8301136
831template <class ELFT> void ArchiveFile::parse() {1137void ArchiveFile::parse() {
832 for (const Archive::Symbol &Sym : File->symbols())1138 for (const Archive::Symbol &sym : file->symbols())
833 Symtab->addLazyArchive<ELFT>(Sym.getName(), *this, Sym);1139 symtab->addSymbol(LazyArchive{*this, sym});
834}1140}
8351141
836// Returns a buffer pointing to a member file containing a given symbol.1142// Returns a buffer pointing to a member file containing a given symbol.
837InputFile *ArchiveFile::fetch(const Archive::Symbol &Sym) {1143void ArchiveFile::fetch(const Archive::Symbol &sym) {
838 Archive::Child C =1144 Archive::Child c =
839 CHECK(Sym.getMember(), toString(this) +1145 CHECK(sym.getMember(), toString(this) +
840 ": could not get the member for symbol " +1146 ": could not get the member for symbol " +
841 Sym.getName());1147 sym.getName());
8421148
843 if (!Seen.insert(C.getChildOffset()).second)1149 if (!seen.insert(c.getChildOffset()).second)
844 return nullptr;1150 return;
8451151
846 MemoryBufferRef MB =1152 MemoryBufferRef mb =
847 CHECK(C.getMemoryBufferRef(),1153 CHECK(c.getMemoryBufferRef(),
848 toString(this) +1154 toString(this) +
849 ": could not get the buffer for the member defining symbol " +1155 ": could not get the buffer for the member defining symbol " +
850 Sym.getName());1156 sym.getName());
851
852 if (Tar && C.getParent()->isThin())
853 Tar->append(relativeToRoot(CHECK(C.getFullName(), this)), MB.getBuffer());
854
855 InputFile *File = createObjectFile(
856 MB, getName(), C.getParent()->isThin() ? 0 : C.getChildOffset());
857 File->GroupId = GroupId;
858 return File;
859}
860
861template <class ELFT>
862SharedFile<ELFT>::SharedFile(MemoryBufferRef M, StringRef DefaultSoName)
863 : ELFFileBase<ELFT>(Base::SharedKind, M), SoName(DefaultSoName),
864 IsNeeded(!Config->AsNeeded) {}
865
866// Partially parse the shared object file so that we can call
867// getSoName on this object.
868template <class ELFT> void SharedFile<ELFT>::parseSoName() {
869 const Elf_Shdr *DynamicSec = nullptr;
870 const ELFFile<ELFT> Obj = this->getObj();
871 ArrayRef<Elf_Shdr> Sections = CHECK(Obj.sections(), this);
872
873 // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d.
874 for (const Elf_Shdr &Sec : Sections) {
875 switch (Sec.sh_type) {
876 default:
877 continue;
878 case SHT_DYNSYM:
879 this->initSymtab(Sections, &Sec);
880 break;
881 case SHT_DYNAMIC:
882 DynamicSec = &Sec;
883 break;
884 case SHT_SYMTAB_SHNDX:
885 this->SymtabSHNDX = CHECK(Obj.getSHNDXTable(Sec, Sections), this);
886 break;
887 case SHT_GNU_versym:
888 this->VersymSec = &Sec;
889 break;
890 case SHT_GNU_verdef:
891 this->VerdefSec = &Sec;
892 break;
893 }
894 }
8951157
896 if (this->VersymSec && this->ELFSyms.empty())1158 if (tar && c.getParent()->isThin())
897 error("SHT_GNU_versym should be associated with symbol table");1159 tar->append(relativeToRoot(CHECK(c.getFullName(), this)), mb.getBuffer());
8981160
899 // Search for a DT_SONAME tag to initialize this->SoName.1161 InputFile *file = createObjectFile(
900 if (!DynamicSec)1162 mb, getName(), c.getParent()->isThin() ? 0 : c.getChildOffset());
901 return;1163 file->groupId = groupId;
902 ArrayRef<Elf_Dyn> Arr =1164 parseFile(file);
903 CHECK(Obj.template getSectionContentsAsArray<Elf_Dyn>(DynamicSec), this);
904 for (const Elf_Dyn &Dyn : Arr) {
905 if (Dyn.d_tag == DT_SONAME) {
906 uint64_t Val = Dyn.getVal();
907 if (Val >= this->StringTable.size())
908 fatal(toString(this) + ": invalid DT_SONAME entry");
909 SoName = this->StringTable.data() + Val;
910 return;
911 }
912 }
913}1165}
9141166
915// Parses ".gnu.version" section which is a parallel array for the symbol table.1167unsigned SharedFile::vernauxNum;
916// If a given file doesn't have ".gnu.version" section, returns VER_NDX_GLOBAL.
917template <class ELFT> std::vector<uint32_t> SharedFile<ELFT>::parseVersyms() {
918 size_t Size = this->ELFSyms.size() - this->FirstGlobal;
919 if (!VersymSec)
920 return std::vector<uint32_t>(Size, VER_NDX_GLOBAL);
921
922 const char *Base = this->MB.getBuffer().data();
923 const Elf_Versym *Versym =
924 reinterpret_cast<const Elf_Versym *>(Base + VersymSec->sh_offset) +
925 this->FirstGlobal;
926
927 std::vector<uint32_t> Ret(Size);
928 for (size_t I = 0; I < Size; ++I)
929 Ret[I] = Versym[I].vs_index;
930 return Ret;
931}
9321168
933// Parse the version definitions in the object file if present. Returns a vector1169// Parse the version definitions in the object file if present, and return a
934// whose nth element contains a pointer to the Elf_Verdef for version identifier1170// vector whose nth element contains a pointer to the Elf_Verdef for version
935// n. Version identifiers that are not definitions map to nullptr.1171// identifier n. Version identifiers that are not definitions map to nullptr.
936template <class ELFT>1172template <typename ELFT>
937std::vector<const typename ELFT::Verdef *> SharedFile<ELFT>::parseVerdefs() {1173static std::vector<const void *> parseVerdefs(const uint8_t *base,
938 if (!VerdefSec)1174 const typename ELFT::Shdr *sec) {
1175 if (!sec)
939 return {};1176 return {};
9401177
941 // We cannot determine the largest verdef identifier without inspecting1178 // We cannot determine the largest verdef identifier without inspecting
942 // every Elf_Verdef, but both bfd and gold assign verdef identifiers1179 // every Elf_Verdef, but both bfd and gold assign verdef identifiers
943 // sequentially starting from 1, so we predict that the largest identifier1180 // sequentially starting from 1, so we predict that the largest identifier
944 // will be VerdefCount.1181 // will be verdefCount.
945 unsigned VerdefCount = VerdefSec->sh_info;1182 unsigned verdefCount = sec->sh_info;
946 std::vector<const Elf_Verdef *> Verdefs(VerdefCount + 1);1183 std::vector<const void *> verdefs(verdefCount + 1);
9471184
948 // Build the Verdefs array by following the chain of Elf_Verdef objects1185 // Build the Verdefs array by following the chain of Elf_Verdef objects
949 // from the start of the .gnu.version_d section.1186 // from the start of the .gnu.version_d section.
950 const char *Base = this->MB.getBuffer().data();1187 const uint8_t *verdef = base + sec->sh_offset;
951 const char *Verdef = Base + VerdefSec->sh_offset;1188 for (unsigned i = 0; i != verdefCount; ++i) {
952 for (unsigned I = 0; I != VerdefCount; ++I) {1189 auto *curVerdef = reinterpret_cast<const typename ELFT::Verdef *>(verdef);
953 auto *CurVerdef = reinterpret_cast<const Elf_Verdef *>(Verdef);1190 verdef += curVerdef->vd_next;
954 Verdef += CurVerdef->vd_next;1191 unsigned verdefIndex = curVerdef->vd_ndx;
955 unsigned VerdefIndex = CurVerdef->vd_ndx;1192 verdefs.resize(verdefIndex + 1);
956 Verdefs.resize(VerdefIndex + 1);1193 verdefs[verdefIndex] = curVerdef;
957 Verdefs[VerdefIndex] = CurVerdef;
958 }1194 }
9591195 return verdefs;
960 return Verdefs;
961}1196}
9621197
963// We do not usually care about alignments of data in shared object1198// We do not usually care about alignments of data in shared object
964// files because the loader takes care of it. However, if we promote a1199// files because the loader takes care of it. However, if we promote a
965// DSO symbol to point to .bss due to copy relocation, we need to keep1200// DSO symbol to point to .bss due to copy relocation, we need to keep
966// the original alignment requirements. We infer it in this function.1201// the original alignment requirements. We infer it in this function.
967template <class ELFT>1202template <typename ELFT>
968uint32_t SharedFile<ELFT>::getAlignment(ArrayRef<Elf_Shdr> Sections,1203static uint64_t getAlignment(ArrayRef<typename ELFT::Shdr> sections,
969 const Elf_Sym &Sym) {1204 const typename ELFT::Sym &sym) {
970 uint64_t Ret = UINT64_MAX;1205 uint64_t ret = UINT64_MAX;
971 if (Sym.st_value)1206 if (sym.st_value)
972 Ret = 1ULL << countTrailingZeros((uint64_t)Sym.st_value);1207 ret = 1ULL << countTrailingZeros((uint64_t)sym.st_value);
973 if (0 < Sym.st_shndx && Sym.st_shndx < Sections.size())1208 if (0 < sym.st_shndx && sym.st_shndx < sections.size())
974 Ret = std::min<uint64_t>(Ret, Sections[Sym.st_shndx].sh_addralign);1209 ret = std::min<uint64_t>(ret, sections[sym.st_shndx].sh_addralign);
975 return (Ret > UINT32_MAX) ? 0 : Ret;1210 return (ret > UINT32_MAX) ? 0 : ret;
976}1211}
9771212
978// Fully parse the shared object file. This must be called after parseSoName().1213// Fully parse the shared object file.
979//1214//
980// This function parses symbol versions. If a DSO has version information,1215// This function parses symbol versions. If a DSO has version information,
981// the file has a ".gnu.version_d" section which contains symbol version1216// the file has a ".gnu.version_d" section which contains symbol version
...@@ -990,80 +1225,163 @@ uint32_t SharedFile<ELFT>::getAlignment(ArrayRef<Elf_Shdr> Sections,...@@ -990,80 +1225,163 @@ uint32_t SharedFile<ELFT>::getAlignment(ArrayRef<Elf_Shdr> Sections,
990// The file format for symbol versioning is perhaps a bit more complicated1225// The file format for symbol versioning is perhaps a bit more complicated
991// than necessary, but you can easily understand the code if you wrap your1226// than necessary, but you can easily understand the code if you wrap your
992// head around the data structure described above.1227// head around the data structure described above.
993template <class ELFT> void SharedFile<ELFT>::parseRest() {1228template <class ELFT> void SharedFile::parse() {
994 Verdefs = parseVerdefs(); // parse .gnu.version_d1229 using Elf_Dyn = typename ELFT::Dyn;
995 std::vector<uint32_t> Versyms = parseVersyms(); // parse .gnu.version1230 using Elf_Shdr = typename ELFT::Shdr;
996 ArrayRef<Elf_Shdr> Sections = CHECK(this->getObj().sections(), this);1231 using Elf_Sym = typename ELFT::Sym;
1232 using Elf_Verdef = typename ELFT::Verdef;
1233 using Elf_Versym = typename ELFT::Versym;
1234
1235 ArrayRef<Elf_Dyn> dynamicTags;
1236 const ELFFile<ELFT> obj = this->getObj<ELFT>();
1237 ArrayRef<Elf_Shdr> sections = CHECK(obj.sections(), this);
1238
1239 const Elf_Shdr *versymSec = nullptr;
1240 const Elf_Shdr *verdefSec = nullptr;
1241
1242 // Search for .dynsym, .dynamic, .symtab, .gnu.version and .gnu.version_d.
1243 for (const Elf_Shdr &sec : sections) {
1244 switch (sec.sh_type) {
1245 default:
1246 continue;
1247 case SHT_DYNAMIC:
1248 dynamicTags =
1249 CHECK(obj.template getSectionContentsAsArray<Elf_Dyn>(&sec), this);
1250 break;
1251 case SHT_GNU_versym:
1252 versymSec = &sec;
1253 break;
1254 case SHT_GNU_verdef:
1255 verdefSec = &sec;
1256 break;
1257 }
1258 }
1259
1260 if (versymSec && numELFSyms == 0) {
1261 error("SHT_GNU_versym should be associated with symbol table");
1262 return;
1263 }
1264
1265 // Search for a DT_SONAME tag to initialize this->soName.
1266 for (const Elf_Dyn &dyn : dynamicTags) {
1267 if (dyn.d_tag == DT_NEEDED) {
1268 uint64_t val = dyn.getVal();
1269 if (val >= this->stringTable.size())
1270 fatal(toString(this) + ": invalid DT_NEEDED entry");
1271 dtNeeded.push_back(this->stringTable.data() + val);
1272 } else if (dyn.d_tag == DT_SONAME) {
1273 uint64_t val = dyn.getVal();
1274 if (val >= this->stringTable.size())
1275 fatal(toString(this) + ": invalid DT_SONAME entry");
1276 soName = this->stringTable.data() + val;
1277 }
1278 }
1279
1280 // DSOs are uniquified not by filename but by soname.
1281 DenseMap<StringRef, SharedFile *>::iterator it;
1282 bool wasInserted;
1283 std::tie(it, wasInserted) = symtab->soNames.try_emplace(soName, this);
1284
1285 // If a DSO appears more than once on the command line with and without
1286 // --as-needed, --no-as-needed takes precedence over --as-needed because a
1287 // user can add an extra DSO with --no-as-needed to force it to be added to
1288 // the dependency list.
1289 it->second->isNeeded |= isNeeded;
1290 if (!wasInserted)
1291 return;
1292
1293 sharedFiles.push_back(this);
1294
1295 verdefs = parseVerdefs<ELFT>(obj.base(), verdefSec);
1296
1297 // Parse ".gnu.version" section which is a parallel array for the symbol
1298 // table. If a given file doesn't have a ".gnu.version" section, we use
1299 // VER_NDX_GLOBAL.
1300 size_t size = numELFSyms - firstGlobal;
1301 std::vector<uint32_t> versyms(size, VER_NDX_GLOBAL);
1302 if (versymSec) {
1303 ArrayRef<Elf_Versym> versym =
1304 CHECK(obj.template getSectionContentsAsArray<Elf_Versym>(versymSec),
1305 this)
1306 .slice(firstGlobal);
1307 for (size_t i = 0; i < size; ++i)
1308 versyms[i] = versym[i].vs_index;
1309 }
9971310
998 // System libraries can have a lot of symbols with versions. Using a1311 // System libraries can have a lot of symbols with versions. Using a
999 // fixed buffer for computing the versions name (foo@ver) can save a1312 // fixed buffer for computing the versions name (foo@ver) can save a
1000 // lot of allocations.1313 // lot of allocations.
1001 SmallString<0> VersionedNameBuffer;1314 SmallString<0> versionedNameBuffer;
10021315
1003 // Add symbols to the symbol table.1316 // Add symbols to the symbol table.
1004 ArrayRef<Elf_Sym> Syms = this->getGlobalELFSyms();1317 ArrayRef<Elf_Sym> syms = this->getGlobalELFSyms<ELFT>();
1005 for (size_t I = 0; I < Syms.size(); ++I) {1318 for (size_t i = 0; i < syms.size(); ++i) {
1006 const Elf_Sym &Sym = Syms[I];1319 const Elf_Sym &sym = syms[i];
10071320
1008 // ELF spec requires that all local symbols precede weak or global1321 // ELF spec requires that all local symbols precede weak or global
1009 // symbols in each symbol table, and the index of first non-local symbol1322 // symbols in each symbol table, and the index of first non-local symbol
1010 // is stored to sh_info. If a local symbol appears after some non-local1323 // is stored to sh_info. If a local symbol appears after some non-local
1011 // symbol, that's a violation of the spec.1324 // symbol, that's a violation of the spec.
1012 StringRef Name = CHECK(Sym.getName(this->StringTable), this);1325 StringRef name = CHECK(sym.getName(this->stringTable), this);
1013 if (Sym.getBinding() == STB_LOCAL) {1326 if (sym.getBinding() == STB_LOCAL) {
1014 warn("found local symbol '" + Name +1327 warn("found local symbol '" + name +
1015 "' in global part of symbol table in file " + toString(this));1328 "' in global part of symbol table in file " + toString(this));
1016 continue;1329 continue;
1017 }1330 }
10181331
1019 if (Sym.isUndefined()) {1332 if (sym.isUndefined()) {
1020 Symbol *S = Symtab->addUndefined<ELFT>(Name, Sym.getBinding(),1333 Symbol *s = symtab->addSymbol(
1021 Sym.st_other, Sym.getType(),1334 Undefined{this, name, sym.getBinding(), sym.st_other, sym.getType()});
1022 /*CanOmitFromDynSym=*/false, this);1335 s->exportDynamic = true;
1023 S->ExportDynamic = true;
1024 continue;1336 continue;
1025 }1337 }
10261338
1027 // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly1339 // MIPS BFD linker puts _gp_disp symbol into DSO files and incorrectly
1028 // assigns VER_NDX_LOCAL to this section global symbol. Here is a1340 // assigns VER_NDX_LOCAL to this section global symbol. Here is a
1029 // workaround for this bug.1341 // workaround for this bug.
1030 uint32_t Idx = Versyms[I] & ~VERSYM_HIDDEN;1342 uint32_t idx = versyms[i] & ~VERSYM_HIDDEN;
1031 if (Config->EMachine == EM_MIPS && Idx == VER_NDX_LOCAL &&1343 if (config->emachine == EM_MIPS && idx == VER_NDX_LOCAL &&
1032 Name == "_gp_disp")1344 name == "_gp_disp")
1033 continue;1345 continue;
10341346
1035 uint64_t Alignment = getAlignment(Sections, Sym);1347 uint32_t alignment = getAlignment<ELFT>(sections, sym);
1036 if (!(Versyms[I] & VERSYM_HIDDEN))1348 if (!(versyms[i] & VERSYM_HIDDEN)) {
1037 Symtab->addShared(Name, *this, Sym, Alignment, Idx);1349 symtab->addSymbol(SharedSymbol{*this, name, sym.getBinding(),
1350 sym.st_other, sym.getType(), sym.st_value,
1351 sym.st_size, alignment, idx});
1352 }
10381353
1039 // Also add the symbol with the versioned name to handle undefined symbols1354 // Also add the symbol with the versioned name to handle undefined symbols
1040 // with explicit versions.1355 // with explicit versions.
1041 if (Idx == VER_NDX_GLOBAL)1356 if (idx == VER_NDX_GLOBAL)
1042 continue;1357 continue;
10431358
1044 if (Idx >= Verdefs.size() || Idx == VER_NDX_LOCAL) {1359 if (idx >= verdefs.size() || idx == VER_NDX_LOCAL) {
1045 error("corrupt input file: version definition index " + Twine(Idx) +1360 error("corrupt input file: version definition index " + Twine(idx) +
1046 " for symbol " + Name + " is out of bounds\n>>> defined in " +1361 " for symbol " + name + " is out of bounds\n>>> defined in " +
1047 toString(this));1362 toString(this));
1048 continue;1363 continue;
1049 }1364 }
10501365
1051 StringRef VerName =1366 StringRef verName =
1052 this->StringTable.data() + Verdefs[Idx]->getAux()->vda_name;1367 this->stringTable.data() +
1053 VersionedNameBuffer.clear();1368 reinterpret_cast<const Elf_Verdef *>(verdefs[idx])->getAux()->vda_name;
1054 Name = (Name + "@" + VerName).toStringRef(VersionedNameBuffer);1369 versionedNameBuffer.clear();
1055 Symtab->addShared(Saver.save(Name), *this, Sym, Alignment, Idx);1370 name = (name + "@" + verName).toStringRef(versionedNameBuffer);
1371 symtab->addSymbol(SharedSymbol{*this, saver.save(name), sym.getBinding(),
1372 sym.st_other, sym.getType(), sym.st_value,
1373 sym.st_size, alignment, idx});
1056 }1374 }
1057}1375}
10581376
1059static ELFKind getBitcodeELFKind(const Triple &T) {1377static ELFKind getBitcodeELFKind(const Triple &t) {
1060 if (T.isLittleEndian())1378 if (t.isLittleEndian())
1061 return T.isArch64Bit() ? ELF64LEKind : ELF32LEKind;1379 return t.isArch64Bit() ? ELF64LEKind : ELF32LEKind;
1062 return T.isArch64Bit() ? ELF64BEKind : ELF32BEKind;1380 return t.isArch64Bit() ? ELF64BEKind : ELF32BEKind;
1063}1381}
10641382
1065static uint8_t getBitcodeMachineKind(StringRef Path, const Triple &T) {1383static uint8_t getBitcodeMachineKind(StringRef path, const Triple &t) {
1066 switch (T.getArch()) {1384 switch (t.getArch()) {
1067 case Triple::aarch64:1385 case Triple::aarch64:
1068 return EM_AARCH64;1386 return EM_AARCH64;
1069 case Triple::amdgcn:1387 case Triple::amdgcn:
...@@ -1086,25 +1404,28 @@ static uint8_t getBitcodeMachineKind(StringRef Path, const Triple &T) {...@@ -1086,25 +1404,28 @@ static uint8_t getBitcodeMachineKind(StringRef Path, const Triple &T) {
1086 case Triple::ppc64:1404 case Triple::ppc64:
1087 case Triple::ppc64le:1405 case Triple::ppc64le:
1088 return EM_PPC64;1406 return EM_PPC64;
1407 case Triple::riscv32:
1408 case Triple::riscv64:
1409 return EM_RISCV;
1089 case Triple::x86:1410 case Triple::x86:
1090 return T.isOSIAMCU() ? EM_IAMCU : EM_386;1411 return t.isOSIAMCU() ? EM_IAMCU : EM_386;
1091 case Triple::x86_64:1412 case Triple::x86_64:
1092 return EM_X86_64;1413 return EM_X86_64;
1093 default:1414 default:
1094 error(Path + ": could not infer e_machine from bitcode target triple " +1415 error(path + ": could not infer e_machine from bitcode target triple " +
1095 T.str());1416 t.str());
1096 return EM_NONE;1417 return EM_NONE;
1097 }1418 }
1098}1419}
10991420
1100BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName,1421BitcodeFile::BitcodeFile(MemoryBufferRef mb, StringRef archiveName,
1101 uint64_t OffsetInArchive)1422 uint64_t offsetInArchive)
1102 : InputFile(BitcodeKind, MB) {1423 : InputFile(BitcodeKind, mb) {
1103 this->ArchiveName = ArchiveName;1424 this->archiveName = archiveName;
11041425
1105 std::string Path = MB.getBufferIdentifier().str();1426 std::string path = mb.getBufferIdentifier().str();
1106 if (Config->ThinLTOIndexOnly)1427 if (config->thinLTOIndexOnly)
1107 Path = replaceThinLTOSuffix(MB.getBufferIdentifier());1428 path = replaceThinLTOSuffix(mb.getBufferIdentifier());
11081429
1109 // ThinLTO assumes that all MemoryBufferRefs given to it have a unique1430 // ThinLTO assumes that all MemoryBufferRefs given to it have a unique
1110 // name. If two archives define two members with the same name, this1431 // name. If two archives define two members with the same name, this
...@@ -1112,20 +1433,21 @@ BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName,...@@ -1112,20 +1433,21 @@ BitcodeFile::BitcodeFile(MemoryBufferRef MB, StringRef ArchiveName,
1112 // into consideration at LTO time (which very likely causes undefined1433 // into consideration at LTO time (which very likely causes undefined
1113 // symbols later in the link stage). So we append file offset to make1434 // symbols later in the link stage). So we append file offset to make
1114 // filename unique.1435 // filename unique.
1115 MemoryBufferRef MBRef(1436 StringRef name = archiveName.empty()
1116 MB.getBuffer(),1437 ? saver.save(path)
1117 Saver.save(ArchiveName + Path +1438 : saver.save(archiveName + "(" + path + " at " +
1118 (ArchiveName.empty() ? "" : utostr(OffsetInArchive))));1439 utostr(offsetInArchive) + ")");
1440 MemoryBufferRef mbref(mb.getBuffer(), name);
11191441
1120 Obj = CHECK(lto::InputFile::create(MBRef), this);1442 obj = CHECK(lto::InputFile::create(mbref), this);
11211443
1122 Triple T(Obj->getTargetTriple());1444 Triple t(obj->getTargetTriple());
1123 EKind = getBitcodeELFKind(T);1445 ekind = getBitcodeELFKind(t);
1124 EMachine = getBitcodeMachineKind(MB.getBufferIdentifier(), T);1446 emachine = getBitcodeMachineKind(mb.getBufferIdentifier(), t);
1125}1447}
11261448
1127static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {1449static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) {
1128 switch (GvVisibility) {1450 switch (gvVisibility) {
1129 case GlobalValue::DefaultVisibility:1451 case GlobalValue::DefaultVisibility:
1130 return STV_DEFAULT;1452 return STV_DEFAULT;
1131 case GlobalValue::HiddenVisibility:1453 case GlobalValue::HiddenVisibility:
...@@ -1137,209 +1459,187 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {...@@ -1137,209 +1459,187 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {
1137}1459}
11381460
1139template <class ELFT>1461template <class ELFT>
1140static Symbol *createBitcodeSymbol(const std::vector<bool> &KeptComdats,1462static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
1141 const lto::InputFile::Symbol &ObjSym,1463 const lto::InputFile::Symbol &objSym,
1142 BitcodeFile &F) {1464 BitcodeFile &f) {
1143 StringRef Name = Saver.save(ObjSym.getName());1465 StringRef name = saver.save(objSym.getName());
1144 uint32_t Binding = ObjSym.isWeak() ? STB_WEAK : STB_GLOBAL;1466 uint8_t binding = objSym.isWeak() ? STB_WEAK : STB_GLOBAL;
11451467 uint8_t type = objSym.isTLS() ? STT_TLS : STT_NOTYPE;
1146 uint8_t Type = ObjSym.isTLS() ? STT_TLS : STT_NOTYPE;1468 uint8_t visibility = mapVisibility(objSym.getVisibility());
1147 uint8_t Visibility = mapVisibility(ObjSym.getVisibility());1469 bool canOmitFromDynSym = objSym.canBeOmittedFromSymbolTable();
1148 bool CanOmitFromDynSym = ObjSym.canBeOmittedFromSymbolTable();1470
11491471 int c = objSym.getComdatIndex();
1150 int C = ObjSym.getComdatIndex();1472 if (objSym.isUndefined() || (c != -1 && !keptComdats[c])) {
1151 if (C != -1 && !KeptComdats[C])1473 Undefined New(&f, name, binding, visibility, type);
1152 return Symtab->addUndefined<ELFT>(Name, Binding, Visibility, Type,1474 if (canOmitFromDynSym)
1153 CanOmitFromDynSym, &F);1475 New.exportDynamic = false;
11541476 return symtab->addSymbol(New);
1155 if (ObjSym.isUndefined())1477 }
1156 return Symtab->addUndefined<ELFT>(Name, Binding, Visibility, Type,
1157 CanOmitFromDynSym, &F);
1158
1159 if (ObjSym.isCommon())
1160 return Symtab->addCommon(Name, ObjSym.getCommonSize(),
1161 ObjSym.getCommonAlignment(), Binding, Visibility,
1162 STT_OBJECT, F);
1163
1164 return Symtab->addBitcode(Name, Binding, Visibility, Type, CanOmitFromDynSym,
1165 F);
1166}
11671478
1168template <class ELFT>1479 if (objSym.isCommon())
1169void BitcodeFile::parse(DenseSet<CachedHashStringRef> &ComdatGroups) {1480 return symtab->addSymbol(
1170 std::vector<bool> KeptComdats;1481 CommonSymbol{&f, name, binding, visibility, STT_OBJECT,
1171 for (StringRef S : Obj->getComdatTable())1482 objSym.getCommonAlignment(), objSym.getCommonSize()});
1172 KeptComdats.push_back(ComdatGroups.insert(CachedHashStringRef(S)).second);
11731483
1174 for (const lto::InputFile::Symbol &ObjSym : Obj->symbols())1484 Defined New(&f, name, binding, visibility, type, 0, 0, nullptr);
1175 Symbols.push_back(createBitcodeSymbol<ELFT>(KeptComdats, ObjSym, *this));1485 if (canOmitFromDynSym)
1486 New.exportDynamic = false;
1487 return symtab->addSymbol(New);
1176}1488}
11771489
1178static ELFKind getELFKind(MemoryBufferRef MB) {1490template <class ELFT> void BitcodeFile::parse() {
1179 unsigned char Size;1491 std::vector<bool> keptComdats;
1180 unsigned char Endian;1492 for (StringRef s : obj->getComdatTable())
1181 std::tie(Size, Endian) = getElfArchType(MB.getBuffer());1493 keptComdats.push_back(
11821494 symtab->comdatGroups.try_emplace(CachedHashStringRef(s), this).second);
1183 if (Endian != ELFDATA2LSB && Endian != ELFDATA2MSB)
1184 fatal(MB.getBufferIdentifier() + ": invalid data encoding");
1185 if (Size != ELFCLASS32 && Size != ELFCLASS64)
1186 fatal(MB.getBufferIdentifier() + ": invalid file class");
11871495
1188 size_t BufSize = MB.getBuffer().size();1496 for (const lto::InputFile::Symbol &objSym : obj->symbols())
1189 if ((Size == ELFCLASS32 && BufSize < sizeof(Elf32_Ehdr)) ||1497 symbols.push_back(createBitcodeSymbol<ELFT>(keptComdats, objSym, *this));
1190 (Size == ELFCLASS64 && BufSize < sizeof(Elf64_Ehdr)))
1191 fatal(MB.getBufferIdentifier() + ": file is too short");
11921498
1193 if (Size == ELFCLASS32)1499 for (auto l : obj->getDependentLibraries())
1194 return (Endian == ELFDATA2LSB) ? ELF32LEKind : ELF32BEKind;1500 addDependentLibrary(l, this);
1195 return (Endian == ELFDATA2LSB) ? ELF64LEKind : ELF64BEKind;
1196}1501}
11971502
1198void BinaryFile::parse() {1503void BinaryFile::parse() {
1199 ArrayRef<uint8_t> Data = arrayRefFromStringRef(MB.getBuffer());1504 ArrayRef<uint8_t> data = arrayRefFromStringRef(mb.getBuffer());
1200 auto *Section = make<InputSection>(this, SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,1505 auto *section = make<InputSection>(this, SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,
1201 8, Data, ".data");1506 8, data, ".data");
1202 Sections.push_back(Section);1507 sections.push_back(section);
12031508
1204 // For each input file foo that is embedded to a result as a binary1509 // For each input file foo that is embedded to a result as a binary
1205 // blob, we define _binary_foo_{start,end,size} symbols, so that1510 // blob, we define _binary_foo_{start,end,size} symbols, so that
1206 // user programs can access blobs by name. Non-alphanumeric1511 // user programs can access blobs by name. Non-alphanumeric
1207 // characters in a filename are replaced with underscore.1512 // characters in a filename are replaced with underscore.
1208 std::string S = "_binary_" + MB.getBufferIdentifier().str();1513 std::string s = "_binary_" + mb.getBufferIdentifier().str();
1209 for (size_t I = 0; I < S.size(); ++I)1514 for (size_t i = 0; i < s.size(); ++i)
1210 if (!isAlnum(S[I]))1515 if (!isAlnum(s[i]))
1211 S[I] = '_';1516 s[i] = '_';
12121517
1213 Symtab->addDefined(Saver.save(S + "_start"), STV_DEFAULT, STT_OBJECT, 0, 0,1518 symtab->addSymbol(Defined{nullptr, saver.save(s + "_start"), STB_GLOBAL,
1214 STB_GLOBAL, Section, nullptr);1519 STV_DEFAULT, STT_OBJECT, 0, 0, section});
1215 Symtab->addDefined(Saver.save(S + "_end"), STV_DEFAULT, STT_OBJECT,1520 symtab->addSymbol(Defined{nullptr, saver.save(s + "_end"), STB_GLOBAL,
1216 Data.size(), 0, STB_GLOBAL, Section, nullptr);1521 STV_DEFAULT, STT_OBJECT, data.size(), 0, section});
1217 Symtab->addDefined(Saver.save(S + "_size"), STV_DEFAULT, STT_OBJECT,1522 symtab->addSymbol(Defined{nullptr, saver.save(s + "_size"), STB_GLOBAL,
1218 Data.size(), 0, STB_GLOBAL, nullptr, nullptr);1523 STV_DEFAULT, STT_OBJECT, data.size(), 0, nullptr});
1219}1524}
12201525
1221InputFile *elf::createObjectFile(MemoryBufferRef MB, StringRef ArchiveName,1526InputFile *elf::createObjectFile(MemoryBufferRef mb, StringRef archiveName,
1222 uint64_t OffsetInArchive) {1527 uint64_t offsetInArchive) {
1223 if (isBitcode(MB))1528 if (isBitcode(mb))
1224 return make<BitcodeFile>(MB, ArchiveName, OffsetInArchive);1529 return make<BitcodeFile>(mb, archiveName, offsetInArchive);
12251530
1226 switch (getELFKind(MB)) {1531 switch (getELFKind(mb, archiveName)) {
1227 case ELF32LEKind:1532 case ELF32LEKind:
1228 return make<ObjFile<ELF32LE>>(MB, ArchiveName);1533 return make<ObjFile<ELF32LE>>(mb, archiveName);
1229 case ELF32BEKind:1534 case ELF32BEKind:
1230 return make<ObjFile<ELF32BE>>(MB, ArchiveName);1535 return make<ObjFile<ELF32BE>>(mb, archiveName);
1231 case ELF64LEKind:1536 case ELF64LEKind:
1232 return make<ObjFile<ELF64LE>>(MB, ArchiveName);1537 return make<ObjFile<ELF64LE>>(mb, archiveName);
1233 case ELF64BEKind:1538 case ELF64BEKind:
1234 return make<ObjFile<ELF64BE>>(MB, ArchiveName);1539 return make<ObjFile<ELF64BE>>(mb, archiveName);
1235 default:1540 default:
1236 llvm_unreachable("getELFKind");1541 llvm_unreachable("getELFKind");
1237 }1542 }
1238}1543}
12391544
1240InputFile *elf::createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName) {1545void LazyObjFile::fetch() {
1241 switch (getELFKind(MB)) {1546 if (mb.getBuffer().empty())
1242 case ELF32LEKind:1547 return;
1243 return make<SharedFile<ELF32LE>>(MB, DefaultSoName);
1244 case ELF32BEKind:
1245 return make<SharedFile<ELF32BE>>(MB, DefaultSoName);
1246 case ELF64LEKind:
1247 return make<SharedFile<ELF64LE>>(MB, DefaultSoName);
1248 case ELF64BEKind:
1249 return make<SharedFile<ELF64BE>>(MB, DefaultSoName);
1250 default:
1251 llvm_unreachable("getELFKind");
1252 }
1253}
12541548
1255MemoryBufferRef LazyObjFile::getBuffer() {1549 InputFile *file = createObjectFile(mb, archiveName, offsetInArchive);
1256 if (AddedToLink)1550 file->groupId = groupId;
1257 return MemoryBufferRef();
1258 AddedToLink = true;
1259 return MB;
1260}
12611551
1262InputFile *LazyObjFile::fetch() {1552 mb = {};
1263 MemoryBufferRef MBRef = getBuffer();1553
1264 if (MBRef.getBuffer().empty())1554 // Copy symbol vector so that the new InputFile doesn't have to
1265 return nullptr;1555 // insert the same defined symbols to the symbol table again.
1556 file->symbols = std::move(symbols);
12661557
1267 InputFile *File = createObjectFile(MBRef, ArchiveName, OffsetInArchive);1558 parseFile(file);
1268 File->GroupId = GroupId;
1269 return File;
1270}1559}
12711560
1272template <class ELFT> void LazyObjFile::parse() {1561template <class ELFT> void LazyObjFile::parse() {
1562 using Elf_Sym = typename ELFT::Sym;
1563
1273 // A lazy object file wraps either a bitcode file or an ELF file.1564 // A lazy object file wraps either a bitcode file or an ELF file.
1274 if (isBitcode(this->MB)) {1565 if (isBitcode(this->mb)) {
1275 std::unique_ptr<lto::InputFile> Obj =1566 std::unique_ptr<lto::InputFile> obj =
1276 CHECK(lto::InputFile::create(this->MB), this);1567 CHECK(lto::InputFile::create(this->mb), this);
1277 for (const lto::InputFile::Symbol &Sym : Obj->symbols())1568 for (const lto::InputFile::Symbol &sym : obj->symbols()) {
1278 if (!Sym.isUndefined())1569 if (sym.isUndefined())
1279 Symtab->addLazyObject<ELFT>(Saver.save(Sym.getName()), *this);1570 continue;
1571 symtab->addSymbol(LazyObject{*this, saver.save(sym.getName())});
1572 }
1280 return;1573 return;
1281 }1574 }
12821575
1283 if (getELFKind(this->MB) != Config->EKind) {1576 if (getELFKind(this->mb, archiveName) != config->ekind) {
1284 error("incompatible file: " + this->MB.getBufferIdentifier());1577 error("incompatible file: " + this->mb.getBufferIdentifier());
1285 return;1578 return;
1286 }1579 }
12871580
1288 ELFFile<ELFT> Obj = check(ELFFile<ELFT>::create(MB.getBuffer()));1581 // Find a symbol table.
1289 ArrayRef<typename ELFT::Shdr> Sections = CHECK(Obj.sections(), this);1582 ELFFile<ELFT> obj = check(ELFFile<ELFT>::create(mb.getBuffer()));
1583 ArrayRef<typename ELFT::Shdr> sections = CHECK(obj.sections(), this);
12901584
1291 for (const typename ELFT::Shdr &Sec : Sections) {1585 for (const typename ELFT::Shdr &sec : sections) {
1292 if (Sec.sh_type != SHT_SYMTAB)1586 if (sec.sh_type != SHT_SYMTAB)
1293 continue;1587 continue;
12941588
1295 typename ELFT::SymRange Syms = CHECK(Obj.symbols(&Sec), this);1589 // A symbol table is found.
1296 uint32_t FirstGlobal = Sec.sh_info;1590 ArrayRef<Elf_Sym> eSyms = CHECK(obj.symbols(&sec), this);
1297 StringRef StringTable =1591 uint32_t firstGlobal = sec.sh_info;
1298 CHECK(Obj.getStringTableForSymtab(Sec, Sections), this);1592 StringRef strtab = CHECK(obj.getStringTableForSymtab(sec, sections), this);
1593 this->symbols.resize(eSyms.size());
1594
1595 // Get existing symbols or insert placeholder symbols.
1596 for (size_t i = firstGlobal, end = eSyms.size(); i != end; ++i)
1597 if (eSyms[i].st_shndx != SHN_UNDEF)
1598 this->symbols[i] = symtab->insert(CHECK(eSyms[i].getName(strtab), this));
1599
1600 // Replace existing symbols with LazyObject symbols.
1601 //
1602 // resolve() may trigger this->fetch() if an existing symbol is an
1603 // undefined symbol. If that happens, this LazyObjFile has served
1604 // its purpose, and we can exit from the loop early.
1605 for (Symbol *sym : this->symbols) {
1606 if (!sym)
1607 continue;
1608 sym->resolve(LazyObject{*this, sym->getName()});
12991609
1300 for (const typename ELFT::Sym &Sym : Syms.slice(FirstGlobal))1610 // MemoryBuffer is emptied if this file is instantiated as ObjFile.
1301 if (Sym.st_shndx != SHN_UNDEF)1611 if (mb.getBuffer().empty())
1302 Symtab->addLazyObject<ELFT>(CHECK(Sym.getName(StringTable), this),1612 return;
1303 *this);1613 }
1304 return;1614 return;
1305 }1615 }
1306}1616}
13071617
1308std::string elf::replaceThinLTOSuffix(StringRef Path) {1618std::string elf::replaceThinLTOSuffix(StringRef path) {
1309 StringRef Suffix = Config->ThinLTOObjectSuffixReplace.first;1619 StringRef suffix = config->thinLTOObjectSuffixReplace.first;
1310 StringRef Repl = Config->ThinLTOObjectSuffixReplace.second;1620 StringRef repl = config->thinLTOObjectSuffixReplace.second;
13111621
1312 if (Path.consume_back(Suffix))1622 if (path.consume_back(suffix))
1313 return (Path + Repl).str();1623 return (path + repl).str();
1314 return Path;1624 return path;
1315}1625}
13161626
1317template void ArchiveFile::parse<ELF32LE>();1627template void BitcodeFile::parse<ELF32LE>();
1318template void ArchiveFile::parse<ELF32BE>();1628template void BitcodeFile::parse<ELF32BE>();
1319template void ArchiveFile::parse<ELF64LE>();1629template void BitcodeFile::parse<ELF64LE>();
1320template void ArchiveFile::parse<ELF64BE>();1630template void BitcodeFile::parse<ELF64BE>();
1321
1322template void BitcodeFile::parse<ELF32LE>(DenseSet<CachedHashStringRef> &);
1323template void BitcodeFile::parse<ELF32BE>(DenseSet<CachedHashStringRef> &);
1324template void BitcodeFile::parse<ELF64LE>(DenseSet<CachedHashStringRef> &);
1325template void BitcodeFile::parse<ELF64BE>(DenseSet<CachedHashStringRef> &);
13261631
1327template void LazyObjFile::parse<ELF32LE>();1632template void LazyObjFile::parse<ELF32LE>();
1328template void LazyObjFile::parse<ELF32BE>();1633template void LazyObjFile::parse<ELF32BE>();
1329template void LazyObjFile::parse<ELF64LE>();1634template void LazyObjFile::parse<ELF64LE>();
1330template void LazyObjFile::parse<ELF64BE>();1635template void LazyObjFile::parse<ELF64BE>();
13311636
1332template class elf::ELFFileBase<ELF32LE>;
1333template class elf::ELFFileBase<ELF32BE>;
1334template class elf::ELFFileBase<ELF64LE>;
1335template class elf::ELFFileBase<ELF64BE>;
1336
1337template class elf::ObjFile<ELF32LE>;1637template class elf::ObjFile<ELF32LE>;
1338template class elf::ObjFile<ELF32BE>;1638template class elf::ObjFile<ELF32BE>;
1339template class elf::ObjFile<ELF64LE>;1639template class elf::ObjFile<ELF64LE>;
1340template class elf::ObjFile<ELF64BE>;1640template class elf::ObjFile<ELF64BE>;
13411641
1342template class elf::SharedFile<ELF32LE>;1642template void SharedFile::parse<ELF32LE>();
1343template class elf::SharedFile<ELF32BE>;1643template void SharedFile::parse<ELF32BE>();
1344template class elf::SharedFile<ELF64LE>;1644template void SharedFile::parse<ELF64LE>();
1345template class elf::SharedFile<ELF64BE>;1645template void SharedFile::parse<ELF64BE>();
deps/lld/ELF/InputFiles.h+190-167
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputFiles.h ---------------------------------------------*- C++ -*-===//1//===- InputFiles.h ---------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -40,7 +39,7 @@ class InputSectionBase;...@@ -40,7 +39,7 @@ class InputSectionBase;
40}39}
4140
42// Returns "<internal>", "foo.a(bar.o)" or "baz.o".41// Returns "<internal>", "foo.a(bar.o)" or "baz.o".
43std::string toString(const elf::InputFile *F);42std::string toString(const elf::InputFile *f);
4443
45namespace elf {44namespace elf {
4645
...@@ -50,10 +49,13 @@ class Symbol;...@@ -50,10 +49,13 @@ class Symbol;
5049
51// If -reproduce option is given, all input files are written50// If -reproduce option is given, all input files are written
52// to this tar archive.51// to this tar archive.
53extern std::unique_ptr<llvm::TarWriter> Tar;52extern std::unique_ptr<llvm::TarWriter> tar;
5453
55// Opens a given file.54// Opens a given file.
56llvm::Optional<MemoryBufferRef> readFile(StringRef Path);55llvm::Optional<MemoryBufferRef> readFile(StringRef path);
56
57// Add symbols in File to the symbol table.
58void parseFile(InputFile *file);
5759
58// The root class of input files.60// The root class of input files.
59class InputFile {61class InputFile {
...@@ -67,191 +69,230 @@ public:...@@ -67,191 +69,230 @@ public:
67 BinaryKind,69 BinaryKind,
68 };70 };
6971
70 Kind kind() const { return FileKind; }72 Kind kind() const { return fileKind; }
7173
72 bool isElf() const {74 bool isElf() const {
73 Kind K = kind();75 Kind k = kind();
74 return K == ObjKind || K == SharedKind;76 return k == ObjKind || k == SharedKind;
75 }77 }
7678
77 StringRef getName() const { return MB.getBufferIdentifier(); }79 StringRef getName() const { return mb.getBufferIdentifier(); }
78 MemoryBufferRef MB;80 MemoryBufferRef mb;
7981
80 // Returns sections. It is a runtime error to call this function82 // Returns sections. It is a runtime error to call this function
81 // on files that don't have the notion of sections.83 // on files that don't have the notion of sections.
82 ArrayRef<InputSectionBase *> getSections() const {84 ArrayRef<InputSectionBase *> getSections() const {
83 assert(FileKind == ObjKind || FileKind == BinaryKind);85 assert(fileKind == ObjKind || fileKind == BinaryKind);
84 return Sections;86 return sections;
85 }87 }
8688
87 // Returns object file symbols. It is a runtime error to call this89 // Returns object file symbols. It is a runtime error to call this
88 // function on files of other types.90 // function on files of other types.
89 ArrayRef<Symbol *> getSymbols() { return getMutableSymbols(); }91 ArrayRef<Symbol *> getSymbols() { return getMutableSymbols(); }
9092
91 std::vector<Symbol *> &getMutableSymbols() {93 MutableArrayRef<Symbol *> getMutableSymbols() {
92 assert(FileKind == BinaryKind || FileKind == ObjKind ||94 assert(fileKind == BinaryKind || fileKind == ObjKind ||
93 FileKind == BitcodeKind);95 fileKind == BitcodeKind);
94 return Symbols;96 return symbols;
95 }97 }
9698
97 // Filename of .a which contained this file. If this file was99 // Filename of .a which contained this file. If this file was
98 // not in an archive file, it is the empty string. We use this100 // not in an archive file, it is the empty string. We use this
99 // string for creating error messages.101 // string for creating error messages.
100 std::string ArchiveName;102 std::string archiveName;
101103
102 // If this is an architecture-specific file, the following members104 // If this is an architecture-specific file, the following members
103 // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.105 // have ELF type (i.e. ELF{32,64}{LE,BE}) and target machine type.
104 ELFKind EKind = ELFNoneKind;106 ELFKind ekind = ELFNoneKind;
105 uint16_t EMachine = llvm::ELF::EM_NONE;107 uint16_t emachine = llvm::ELF::EM_NONE;
106 uint8_t OSABI = 0;108 uint8_t osabi = 0;
109 uint8_t abiVersion = 0;
107110
108 // Cache for toString(). Only toString() should use this member.111 // Cache for toString(). Only toString() should use this member.
109 mutable std::string ToStringCache;112 mutable std::string toStringCache;
110113
111 std::string getSrcMsg(const Symbol &Sym, InputSectionBase &Sec,114 std::string getSrcMsg(const Symbol &sym, InputSectionBase &sec,
112 uint64_t Offset);115 uint64_t offset);
113116
114 // True if this is an argument for --just-symbols. Usually false.117 // True if this is an argument for --just-symbols. Usually false.
115 bool JustSymbols = false;118 bool justSymbols = false;
116119
117 // GroupId is used for --warn-backrefs which is an optional error120 // outSecOff of .got2 in the current file. This is used by PPC32 -fPIC/-fPIE
121 // to compute offsets in PLT call stubs.
122 uint32_t ppc32Got2OutSecOff = 0;
123
124 // On PPC64 we need to keep track of which files contain small code model
125 // relocations that access the .toc section. To minimize the chance of a
126 // relocation overflow, files that do contain said relocations should have
127 // their .toc sections sorted closer to the .got section than files that do
128 // not contain any small code model relocations. Thats because the toc-pointer
129 // is defined to point at .got + 0x8000 and the instructions used with small
130 // code model relocations support immediates in the range [-0x8000, 0x7FFC],
131 // making the addressable range relative to the toc pointer
132 // [.got, .got + 0xFFFC].
133 bool ppc64SmallCodeModelTocRelocs = false;
134
135 // groupId is used for --warn-backrefs which is an optional error
118 // checking feature. All files within the same --{start,end}-group or136 // checking feature. All files within the same --{start,end}-group or
119 // --{start,end}-lib get the same group ID. Otherwise, each file gets a new137 // --{start,end}-lib get the same group ID. Otherwise, each file gets a new
120 // group ID. For more info, see checkDependency() in SymbolTable.cpp.138 // group ID. For more info, see checkDependency() in SymbolTable.cpp.
121 uint32_t GroupId;139 uint32_t groupId;
122 static bool IsInGroup;140 static bool isInGroup;
123 static uint32_t NextGroupId;141 static uint32_t nextGroupId;
124142
125 // Index of MIPS GOT built for this file.143 // Index of MIPS GOT built for this file.
126 llvm::Optional<size_t> MipsGotIndex;144 llvm::Optional<size_t> mipsGotIndex;
145
146 std::vector<Symbol *> symbols;
127147
128protected:148protected:
129 InputFile(Kind K, MemoryBufferRef M);149 InputFile(Kind k, MemoryBufferRef m);
130 std::vector<InputSectionBase *> Sections;150 std::vector<InputSectionBase *> sections;
131 std::vector<Symbol *> Symbols;
132151
133private:152private:
134 const Kind FileKind;153 const Kind fileKind;
135};154};
136155
137template <typename ELFT> class ELFFileBase : public InputFile {156class ELFFileBase : public InputFile {
138public:157public:
139 typedef typename ELFT::Shdr Elf_Shdr;158 ELFFileBase(Kind k, MemoryBufferRef m);
140 typedef typename ELFT::Sym Elf_Sym;159 static bool classof(const InputFile *f) { return f->isElf(); }
141 typedef typename ELFT::Word Elf_Word;
142 typedef typename ELFT::SymRange Elf_Sym_Range;
143160
144 ELFFileBase(Kind K, MemoryBufferRef M);161 template <typename ELFT> llvm::object::ELFFile<ELFT> getObj() const {
145 static bool classof(const InputFile *F) { return F->isElf(); }162 return check(llvm::object::ELFFile<ELFT>::create(mb.getBuffer()));
146
147 llvm::object::ELFFile<ELFT> getObj() const {
148 return check(llvm::object::ELFFile<ELFT>::create(MB.getBuffer()));
149 }163 }
150164
151 StringRef getStringTable() const { return StringTable; }165 StringRef getStringTable() const { return stringTable; }
152
153 uint32_t getSectionIndex(const Elf_Sym &Sym) const;
154166
155 Elf_Sym_Range getGlobalELFSyms();167 template <typename ELFT> typename ELFT::SymRange getELFSyms() const {
156 Elf_Sym_Range getELFSyms() const { return ELFSyms; }168 return typename ELFT::SymRange(
169 reinterpret_cast<const typename ELFT::Sym *>(elfSyms), numELFSyms);
170 }
171 template <typename ELFT> typename ELFT::SymRange getGlobalELFSyms() const {
172 return getELFSyms<ELFT>().slice(firstGlobal);
173 }
157174
158protected:175protected:
159 ArrayRef<Elf_Sym> ELFSyms;176 // Initializes this class's member variables.
160 uint32_t FirstGlobal = 0;177 template <typename ELFT> void init();
161 ArrayRef<Elf_Word> SymtabSHNDX;178
162 StringRef StringTable;179 const void *elfSyms = nullptr;
163 void initSymtab(ArrayRef<Elf_Shdr> Sections, const Elf_Shdr *Symtab);180 size_t numELFSyms = 0;
181 uint32_t firstGlobal = 0;
182 StringRef stringTable;
164};183};
165184
166// .o file.185// .o file.
167template <class ELFT> class ObjFile : public ELFFileBase<ELFT> {186template <class ELFT> class ObjFile : public ELFFileBase {
168 typedef ELFFileBase<ELFT> Base;187 using Elf_Rel = typename ELFT::Rel;
169 typedef typename ELFT::Rel Elf_Rel;188 using Elf_Rela = typename ELFT::Rela;
170 typedef typename ELFT::Rela Elf_Rela;189 using Elf_Sym = typename ELFT::Sym;
171 typedef typename ELFT::Sym Elf_Sym;190 using Elf_Shdr = typename ELFT::Shdr;
172 typedef typename ELFT::Shdr Elf_Shdr;191 using Elf_Word = typename ELFT::Word;
173 typedef typename ELFT::Word Elf_Word;192 using Elf_CGProfile = typename ELFT::CGProfile;
174 typedef typename ELFT::CGProfile Elf_CGProfile;
175
176 StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> Sections,
177 const Elf_Shdr &Sec);
178193
179public:194public:
180 static bool classof(const InputFile *F) { return F->kind() == Base::ObjKind; }195 static bool classof(const InputFile *f) { return f->kind() == ObjKind; }
196
197 llvm::object::ELFFile<ELFT> getObj() const {
198 return this->ELFFileBase::getObj<ELFT>();
199 }
181200
182 ArrayRef<Symbol *> getLocalSymbols();201 ArrayRef<Symbol *> getLocalSymbols();
183 ArrayRef<Symbol *> getGlobalSymbols();202 ArrayRef<Symbol *> getGlobalSymbols();
184203
185 ObjFile(MemoryBufferRef M, StringRef ArchiveName);204 ObjFile(MemoryBufferRef m, StringRef archiveName) : ELFFileBase(ObjKind, m) {
186 void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);205 this->archiveName = archiveName;
206 }
207
208 void parse(bool ignoreComdats = false);
187209
188 Symbol &getSymbol(uint32_t SymbolIndex) const {210 StringRef getShtGroupSignature(ArrayRef<Elf_Shdr> sections,
189 if (SymbolIndex >= this->Symbols.size())211 const Elf_Shdr &sec);
212
213 Symbol &getSymbol(uint32_t symbolIndex) const {
214 if (symbolIndex >= this->symbols.size())
190 fatal(toString(this) + ": invalid symbol index");215 fatal(toString(this) + ": invalid symbol index");
191 return *this->Symbols[SymbolIndex];216 return *this->symbols[symbolIndex];
192 }217 }
193218
194 template <typename RelT> Symbol &getRelocTargetSym(const RelT &Rel) const {219 uint32_t getSectionIndex(const Elf_Sym &sym) const;
195 uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL);220
196 return getSymbol(SymIndex);221 template <typename RelT> Symbol &getRelocTargetSym(const RelT &rel) const {
222 uint32_t symIndex = rel.getSymbol(config->isMips64EL);
223 return getSymbol(symIndex);
197 }224 }
198225
199 llvm::Optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t);226 llvm::Optional<llvm::DILineInfo> getDILineInfo(InputSectionBase *, uint64_t);
200 llvm::Optional<std::pair<std::string, unsigned>> getVariableLoc(StringRef Name);227 llvm::Optional<std::pair<std::string, unsigned>> getVariableLoc(StringRef name);
201228
202 // MIPS GP0 value defined by this file. This value represents the gp value229 // MIPS GP0 value defined by this file. This value represents the gp value
203 // used to create the relocatable object and required to support230 // used to create the relocatable object and required to support
204 // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.231 // R_MIPS_GPREL16 / R_MIPS_GPREL32 relocations.
205 uint32_t MipsGp0 = 0;232 uint32_t mipsGp0 = 0;
233
234 uint32_t andFeatures = 0;
206235
207 // Name of source file obtained from STT_FILE symbol value,236 // Name of source file obtained from STT_FILE symbol value,
208 // or empty string if there is no such symbol in object file237 // or empty string if there is no such symbol in object file
209 // symbol table.238 // symbol table.
210 StringRef SourceFile;239 StringRef sourceFile;
211240
212 // True if the file defines functions compiled with241 // True if the file defines functions compiled with
213 // -fsplit-stack. Usually false.242 // -fsplit-stack. Usually false.
214 bool SplitStack = false;243 bool splitStack = false;
215244
216 // True if the file defines functions compiled with -fsplit-stack,245 // True if the file defines functions compiled with -fsplit-stack,
217 // but had one or more functions with the no_split_stack attribute.246 // but had one or more functions with the no_split_stack attribute.
218 bool SomeNoSplitStack = false;247 bool someNoSplitStack = false;
219248
220 // Pointer to this input file's .llvm_addrsig section, if it has one.249 // Pointer to this input file's .llvm_addrsig section, if it has one.
221 const Elf_Shdr *AddrsigSec = nullptr;250 const Elf_Shdr *addrsigSec = nullptr;
222251
223 // SHT_LLVM_CALL_GRAPH_PROFILE table252 // SHT_LLVM_CALL_GRAPH_PROFILE table
224 ArrayRef<Elf_CGProfile> CGProfile;253 ArrayRef<Elf_CGProfile> cgProfile;
225254
226private:255private:
227 void256 void initializeSections(bool ignoreComdats);
228 initializeSections(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);
229 void initializeSymbols();257 void initializeSymbols();
230 void initializeJustSymbols();258 void initializeJustSymbols();
231 void initializeDwarf();259 void initializeDwarf();
232 InputSectionBase *getRelocTarget(const Elf_Shdr &Sec);260 InputSectionBase *getRelocTarget(const Elf_Shdr &sec);
233 InputSectionBase *createInputSection(const Elf_Shdr &Sec);261 InputSectionBase *createInputSection(const Elf_Shdr &sec);
234 StringRef getSectionName(const Elf_Shdr &Sec);262 StringRef getSectionName(const Elf_Shdr &sec);
235263
236 bool shouldMerge(const Elf_Shdr &Sec);264 bool shouldMerge(const Elf_Shdr &sec);
237 Symbol *createSymbol(const Elf_Sym *Sym);265
266 // Each ELF symbol contains a section index which the symbol belongs to.
267 // However, because the number of bits dedicated for that is limited, a
268 // symbol can directly point to a section only when the section index is
269 // equal to or smaller than 65280.
270 //
271 // If an object file contains more than 65280 sections, the file must
272 // contain .symtab_shndx section. The section contains an array of
273 // 32-bit integers whose size is the same as the number of symbols.
274 // Nth symbol's section index is in the Nth entry of .symtab_shndx.
275 //
276 // The following variable contains the contents of .symtab_shndx.
277 // If the section does not exist (which is common), the array is empty.
278 ArrayRef<Elf_Word> shndxTable;
238279
239 // .shstrtab contents.280 // .shstrtab contents.
240 StringRef SectionStringTable;281 StringRef sectionStringTable;
241282
242 // Debugging information to retrieve source file and line for error283 // Debugging information to retrieve source file and line for error
243 // reporting. Linker may find reasonable number of errors in a284 // reporting. Linker may find reasonable number of errors in a
244 // single object file, so we cache debugging information in order to285 // single object file, so we cache debugging information in order to
245 // parse it only once for each object file we link.286 // parse it only once for each object file we link.
246 std::unique_ptr<llvm::DWARFContext> Dwarf;287 std::unique_ptr<llvm::DWARFContext> dwarf;
247 std::vector<const llvm::DWARFDebugLine::LineTable *> LineTables;288 std::vector<const llvm::DWARFDebugLine::LineTable *> lineTables;
248 struct VarLoc {289 struct VarLoc {
249 const llvm::DWARFDebugLine::LineTable *LT;290 const llvm::DWARFDebugLine::LineTable *lt;
250 unsigned File;291 unsigned file;
251 unsigned Line;292 unsigned line;
252 };293 };
253 llvm::DenseMap<StringRef, VarLoc> VariableLoc;294 llvm::DenseMap<StringRef, VarLoc> variableLoc;
254 llvm::once_flag InitDwarfLine;295 llvm::once_flag initDwarfLine;
255};296};
256297
257// LazyObjFile is analogous to ArchiveFile in the sense that298// LazyObjFile is analogous to ArchiveFile in the sense that
...@@ -263,118 +304,100 @@ private:...@@ -263,118 +304,100 @@ private:
263// archive file semantics.304// archive file semantics.
264class LazyObjFile : public InputFile {305class LazyObjFile : public InputFile {
265public:306public:
266 LazyObjFile(MemoryBufferRef M, StringRef ArchiveName,307 LazyObjFile(MemoryBufferRef m, StringRef archiveName,
267 uint64_t OffsetInArchive)308 uint64_t offsetInArchive)
268 : InputFile(LazyObjKind, M), OffsetInArchive(OffsetInArchive) {309 : InputFile(LazyObjKind, m), offsetInArchive(offsetInArchive) {
269 this->ArchiveName = ArchiveName;310 this->archiveName = archiveName;
270 }311 }
271312
272 static bool classof(const InputFile *F) { return F->kind() == LazyObjKind; }313 static bool classof(const InputFile *f) { return f->kind() == LazyObjKind; }
273314
274 template <class ELFT> void parse();315 template <class ELFT> void parse();
275 MemoryBufferRef getBuffer();316 void fetch();
276 InputFile *fetch();
277 bool AddedToLink = false;
278317
279private:318private:
280 uint64_t OffsetInArchive;319 uint64_t offsetInArchive;
281};320};
282321
283// An ArchiveFile object represents a .a file.322// An ArchiveFile object represents a .a file.
284class ArchiveFile : public InputFile {323class ArchiveFile : public InputFile {
285public:324public:
286 explicit ArchiveFile(std::unique_ptr<Archive> &&File);325 explicit ArchiveFile(std::unique_ptr<Archive> &&file);
287 static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }326 static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
288 template <class ELFT> void parse();327 void parse();
289328
290 // Pulls out an object file that contains a definition for Sym and329 // Pulls out an object file that contains a definition for Sym and
291 // returns it. If the same file was instantiated before, this330 // returns it. If the same file was instantiated before, this
292 // function returns a nullptr (so we don't instantiate the same file331 // function does nothing (so we don't instantiate the same file
293 // more than once.)332 // more than once.)
294 InputFile *fetch(const Archive::Symbol &Sym);333 void fetch(const Archive::Symbol &sym);
295334
296private:335private:
297 std::unique_ptr<Archive> File;336 std::unique_ptr<Archive> file;
298 llvm::DenseSet<uint64_t> Seen;337 llvm::DenseSet<uint64_t> seen;
299};338};
300339
301class BitcodeFile : public InputFile {340class BitcodeFile : public InputFile {
302public:341public:
303 BitcodeFile(MemoryBufferRef M, StringRef ArchiveName,342 BitcodeFile(MemoryBufferRef m, StringRef archiveName,
304 uint64_t OffsetInArchive);343 uint64_t offsetInArchive);
305 static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }344 static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
306 template <class ELFT>345 template <class ELFT> void parse();
307 void parse(llvm::DenseSet<llvm::CachedHashStringRef> &ComdatGroups);346 std::unique_ptr<llvm::lto::InputFile> obj;
308 std::unique_ptr<llvm::lto::InputFile> Obj;
309};347};
310348
311// .so file.349// .so file.
312template <class ELFT> class SharedFile : public ELFFileBase<ELFT> {350class SharedFile : public ELFFileBase {
313 typedef ELFFileBase<ELFT> Base;
314 typedef typename ELFT::Dyn Elf_Dyn;
315 typedef typename ELFT::Shdr Elf_Shdr;
316 typedef typename ELFT::Sym Elf_Sym;
317 typedef typename ELFT::SymRange Elf_Sym_Range;
318 typedef typename ELFT::Verdef Elf_Verdef;
319 typedef typename ELFT::Versym Elf_Versym;
320
321 const Elf_Shdr *VersymSec = nullptr;
322 const Elf_Shdr *VerdefSec = nullptr;
323
324public:351public:
325 std::vector<const Elf_Verdef *> Verdefs;352 SharedFile(MemoryBufferRef m, StringRef defaultSoName)
326 std::string SoName;353 : ELFFileBase(SharedKind, m), soName(defaultSoName),
354 isNeeded(!config->asNeeded) {}
327355
328 static bool classof(const InputFile *F) {356 // This is actually a vector of Elf_Verdef pointers.
329 return F->kind() == Base::SharedKind;357 std::vector<const void *> verdefs;
330 }
331358
332 SharedFile(MemoryBufferRef M, StringRef DefaultSoName);359 // If the output file needs Elf_Verneed data structures for this file, this is
360 // a vector of Elf_Vernaux version identifiers that map onto the entries in
361 // Verdefs, otherwise it is empty.
362 std::vector<unsigned> vernauxs;
333363
334 void parseSoName();364 static unsigned vernauxNum;
335 void parseRest();
336 uint32_t getAlignment(ArrayRef<Elf_Shdr> Sections, const Elf_Sym &Sym);
337 std::vector<const Elf_Verdef *> parseVerdefs();
338 std::vector<uint32_t> parseVersyms();
339365
340 struct NeededVer {366 std::vector<StringRef> dtNeeded;
341 // The string table offset of the version name in the output file.367 std::string soName;
342 size_t StrTab;
343368
344 // The version identifier for this version name.369 static bool classof(const InputFile *f) { return f->kind() == SharedKind; }
345 uint16_t Index;370
346 };371 template <typename ELFT> void parse();
347372
348 // Mapping from Elf_Verdef data structures to information about Elf_Vernaux373 // Used for --no-allow-shlib-undefined.
349 // data structures in the output file.374 bool allNeededIsKnown;
350 std::map<const Elf_Verdef *, NeededVer> VerdefMap;
351375
352 // Used for --as-needed376 // Used for --as-needed
353 bool IsNeeded;377 bool isNeeded;
354};378};
355379
356class BinaryFile : public InputFile {380class BinaryFile : public InputFile {
357public:381public:
358 explicit BinaryFile(MemoryBufferRef M) : InputFile(BinaryKind, M) {}382 explicit BinaryFile(MemoryBufferRef m) : InputFile(BinaryKind, m) {}
359 static bool classof(const InputFile *F) { return F->kind() == BinaryKind; }383 static bool classof(const InputFile *f) { return f->kind() == BinaryKind; }
360 void parse();384 void parse();
361};385};
362386
363InputFile *createObjectFile(MemoryBufferRef MB, StringRef ArchiveName = "",387InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "",
364 uint64_t OffsetInArchive = 0);388 uint64_t offsetInArchive = 0);
365InputFile *createSharedFile(MemoryBufferRef MB, StringRef DefaultSoName);
366389
367inline bool isBitcode(MemoryBufferRef MB) {390inline bool isBitcode(MemoryBufferRef mb) {
368 return identify_magic(MB.getBuffer()) == llvm::file_magic::bitcode;391 return identify_magic(mb.getBuffer()) == llvm::file_magic::bitcode;
369}392}
370393
371std::string replaceThinLTOSuffix(StringRef Path);394std::string replaceThinLTOSuffix(StringRef path);
372395
373extern std::vector<BinaryFile *> BinaryFiles;396extern std::vector<BinaryFile *> binaryFiles;
374extern std::vector<BitcodeFile *> BitcodeFiles;397extern std::vector<BitcodeFile *> bitcodeFiles;
375extern std::vector<LazyObjFile *> LazyObjFiles;398extern std::vector<LazyObjFile *> lazyObjFiles;
376extern std::vector<InputFile *> ObjectFiles;399extern std::vector<InputFile *> objectFiles;
377extern std::vector<InputFile *> SharedFiles;400extern std::vector<SharedFile *> sharedFiles;
378401
379} // namespace elf402} // namespace elf
380} // namespace lld403} // namespace lld
deps/lld/ELF/InputSection.cpp+583-530
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputSection.cpp ---------------------------------------------------===//1//===- InputSection.cpp ---------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -41,52 +40,52 @@ using namespace llvm::sys;...@@ -41,52 +40,52 @@ using namespace llvm::sys;
41using namespace lld;40using namespace lld;
42using namespace lld::elf;41using namespace lld::elf;
4342
44std::vector<InputSectionBase *> elf::InputSections;43std::vector<InputSectionBase *> elf::inputSections;
4544
46// Returns a string to construct an error message.45// Returns a string to construct an error message.
47std::string lld::toString(const InputSectionBase *Sec) {46std::string lld::toString(const InputSectionBase *sec) {
48 return (toString(Sec->File) + ":(" + Sec->Name + ")").str();47 return (toString(sec->file) + ":(" + sec->name + ")").str();
49}48}
5049
51template <class ELFT>50template <class ELFT>
52static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> &File,51static ArrayRef<uint8_t> getSectionContents(ObjFile<ELFT> &file,
53 const typename ELFT::Shdr &Hdr) {52 const typename ELFT::Shdr &hdr) {
54 if (Hdr.sh_type == SHT_NOBITS)53 if (hdr.sh_type == SHT_NOBITS)
55 return makeArrayRef<uint8_t>(nullptr, Hdr.sh_size);54 return makeArrayRef<uint8_t>(nullptr, hdr.sh_size);
56 return check(File.getObj().getSectionContents(&Hdr));55 return check(file.getObj().getSectionContents(&hdr));
57}56}
5857
59InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,58InputSectionBase::InputSectionBase(InputFile *file, uint64_t flags,
60 uint32_t Type, uint64_t Entsize,59 uint32_t type, uint64_t entsize,
61 uint32_t Link, uint32_t Info,60 uint32_t link, uint32_t info,
62 uint32_t Alignment, ArrayRef<uint8_t> Data,61 uint32_t alignment, ArrayRef<uint8_t> data,
63 StringRef Name, Kind SectionKind)62 StringRef name, Kind sectionKind)
64 : SectionBase(SectionKind, Name, Flags, Entsize, Alignment, Type, Info,63 : SectionBase(sectionKind, name, flags, entsize, alignment, type, info,
65 Link),64 link),
66 File(File), RawData(Data) {65 file(file), rawData(data) {
67 // In order to reduce memory allocation, we assume that mergeable66 // In order to reduce memory allocation, we assume that mergeable
68 // sections are smaller than 4 GiB, which is not an unreasonable67 // sections are smaller than 4 GiB, which is not an unreasonable
69 // assumption as of 2017.68 // assumption as of 2017.
70 if (SectionKind == SectionBase::Merge && RawData.size() > UINT32_MAX)69 if (sectionKind == SectionBase::Merge && rawData.size() > UINT32_MAX)
71 error(toString(this) + ": section too large");70 error(toString(this) + ": section too large");
7271
73 NumRelocations = 0;72 numRelocations = 0;
74 AreRelocsRela = false;73 areRelocsRela = false;
7574
76 // The ELF spec states that a value of 0 means the section has75 // The ELF spec states that a value of 0 means the section has
77 // no alignment constraits.76 // no alignment constraits.
78 uint32_t V = std::max<uint64_t>(Alignment, 1);77 uint32_t v = std::max<uint32_t>(alignment, 1);
79 if (!isPowerOf2_64(V))78 if (!isPowerOf2_64(v))
80 fatal(toString(File) + ": section sh_addralign is not a power of 2");79 fatal(toString(this) + ": sh_addralign is not a power of 2");
81 this->Alignment = V;80 this->alignment = v;
8281
83 // In ELF, each section can be compressed by zlib, and if compressed,82 // 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").83 // 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 a84 // If that's the case, demangle section name so that we can handle a
86 // section as if it weren't compressed.85 // section as if it weren't compressed.
87 if ((Flags & SHF_COMPRESSED) || Name.startswith(".zdebug")) {86 if ((flags & SHF_COMPRESSED) || name.startswith(".zdebug")) {
88 if (!zlib::isAvailable())87 if (!zlib::isAvailable())
89 error(toString(File) + ": contains a compressed section, " +88 error(toString(file) + ": contains a compressed section, " +
90 "but zlib is not available");89 "but zlib is not available");
91 parseCompressedHeader();90 parseCompressedHeader();
92 }91 }
...@@ -95,11 +94,11 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,...@@ -95,11 +94,11 @@ InputSectionBase::InputSectionBase(InputFile *File, uint64_t Flags,
95// Drop SHF_GROUP bit unless we are producing a re-linkable object file.94// Drop SHF_GROUP bit unless we are producing a re-linkable object file.
96// SHF_GROUP is a marker that a section belongs to some comdat group.95// SHF_GROUP is a marker that a section belongs to some comdat group.
97// That flag doesn't make sense in an executable.96// That flag doesn't make sense in an executable.
98static uint64_t getFlags(uint64_t Flags) {97static uint64_t getFlags(uint64_t flags) {
99 Flags &= ~(uint64_t)SHF_INFO_LINK;98 flags &= ~(uint64_t)SHF_INFO_LINK;
100 if (!Config->Relocatable)99 if (!config->relocatable)
101 Flags &= ~(uint64_t)SHF_GROUP;100 flags &= ~(uint64_t)SHF_GROUP;
102 return Flags;101 return flags;
103}102}
104103
105// GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of104// GNU assembler 2.24 and LLVM 4.0.0's MC (the newest release as of
...@@ -112,205 +111,212 @@ static uint64_t getFlags(uint64_t Flags) {...@@ -112,205 +111,212 @@ static uint64_t getFlags(uint64_t Flags) {
112//111//
113// This function forces SHT_{INIT,FINI}_ARRAY so that we can handle112// This function forces SHT_{INIT,FINI}_ARRAY so that we can handle
114// incorrect inputs as if they were correct from the beginning.113// incorrect inputs as if they were correct from the beginning.
115static uint64_t getType(uint64_t Type, StringRef Name) {114static uint64_t getType(uint64_t type, StringRef name) {
116 if (Type == SHT_PROGBITS && Name.startswith(".init_array."))115 if (type == SHT_PROGBITS && name.startswith(".init_array."))
117 return SHT_INIT_ARRAY;116 return SHT_INIT_ARRAY;
118 if (Type == SHT_PROGBITS && Name.startswith(".fini_array."))117 if (type == SHT_PROGBITS && name.startswith(".fini_array."))
119 return SHT_FINI_ARRAY;118 return SHT_FINI_ARRAY;
120 return Type;119 return type;
121}120}
122121
123template <class ELFT>122template <class ELFT>
124InputSectionBase::InputSectionBase(ObjFile<ELFT> &File,123InputSectionBase::InputSectionBase(ObjFile<ELFT> &file,
125 const typename ELFT::Shdr &Hdr,124 const typename ELFT::Shdr &hdr,
126 StringRef Name, Kind SectionKind)125 StringRef name, Kind sectionKind)
127 : InputSectionBase(&File, getFlags(Hdr.sh_flags),126 : InputSectionBase(&file, getFlags(hdr.sh_flags),
128 getType(Hdr.sh_type, Name), Hdr.sh_entsize, Hdr.sh_link,127 getType(hdr.sh_type, name), hdr.sh_entsize, hdr.sh_link,
129 Hdr.sh_info, Hdr.sh_addralign,128 hdr.sh_info, hdr.sh_addralign,
130 getSectionContents(File, Hdr), Name, SectionKind) {129 getSectionContents(file, hdr), name, sectionKind) {
131 // We reject object files having insanely large alignments even though130 // We reject object files having insanely large alignments even though
132 // they are allowed by the spec. I think 4GB is a reasonable limitation.131 // they are allowed by the spec. I think 4GB is a reasonable limitation.
133 // We might want to relax this in the future.132 // We might want to relax this in the future.
134 if (Hdr.sh_addralign > UINT32_MAX)133 if (hdr.sh_addralign > UINT32_MAX)
135 fatal(toString(&File) + ": section sh_addralign is too large");134 fatal(toString(&file) + ": section sh_addralign is too large");
136}135}
137136
138size_t InputSectionBase::getSize() const {137size_t InputSectionBase::getSize() const {
139 if (auto *S = dyn_cast<SyntheticSection>(this))138 if (auto *s = dyn_cast<SyntheticSection>(this))
140 return S->getSize();139 return s->getSize();
141 if (UncompressedSize >= 0)140 if (uncompressedSize >= 0)
142 return UncompressedSize;141 return uncompressedSize;
143 return RawData.size();142 return rawData.size();
144}143}
145144
146void InputSectionBase::uncompress() const {145void InputSectionBase::uncompress() const {
147 size_t Size = UncompressedSize;146 size_t size = uncompressedSize;
148 UncompressedBuf.reset(new char[Size]);147 char *uncompressedBuf;
148 {
149 static std::mutex mu;
150 std::lock_guard<std::mutex> lock(mu);
151 uncompressedBuf = bAlloc.Allocate<char>(size);
152 }
149153
150 if (Error E =154 if (Error e = zlib::uncompress(toStringRef(rawData), uncompressedBuf, size))
151 zlib::uncompress(toStringRef(RawData), UncompressedBuf.get(), Size))
152 fatal(toString(this) +155 fatal(toString(this) +
153 ": uncompress failed: " + llvm::toString(std::move(E)));156 ": uncompress failed: " + llvm::toString(std::move(e)));
154 RawData = makeArrayRef((uint8_t *)UncompressedBuf.get(), Size);157 rawData = makeArrayRef((uint8_t *)uncompressedBuf, size);
158 uncompressedSize = -1;
155}159}
156160
157uint64_t InputSectionBase::getOffsetInFile() const {161uint64_t InputSectionBase::getOffsetInFile() const {
158 const uint8_t *FileStart = (const uint8_t *)File->MB.getBufferStart();162 const uint8_t *fileStart = (const uint8_t *)file->mb.getBufferStart();
159 const uint8_t *SecStart = data().begin();163 const uint8_t *secStart = data().begin();
160 return SecStart - FileStart;164 return secStart - fileStart;
161}165}
162166
163uint64_t SectionBase::getOffset(uint64_t Offset) const {167uint64_t SectionBase::getOffset(uint64_t offset) const {
164 switch (kind()) {168 switch (kind()) {
165 case Output: {169 case Output: {
166 auto *OS = cast<OutputSection>(this);170 auto *os = cast<OutputSection>(this);
167 // For output sections we treat offset -1 as the end of the section.171 // For output sections we treat offset -1 as the end of the section.
168 return Offset == uint64_t(-1) ? OS->Size : Offset;172 return offset == uint64_t(-1) ? os->size : offset;
169 }173 }
170 case Regular:174 case Regular:
171 case Synthetic:175 case Synthetic:
172 return cast<InputSection>(this)->getOffset(Offset);176 return cast<InputSection>(this)->getOffset(offset);
173 case EHFrame:177 case EHFrame:
174 // The file crtbeginT.o has relocations pointing to the start of an empty178 // The file crtbeginT.o has relocations pointing to the start of an empty
175 // .eh_frame that is known to be the first in the link. It does that to179 // .eh_frame that is known to be the first in the link. It does that to
176 // identify the start of the output .eh_frame.180 // identify the start of the output .eh_frame.
177 return Offset;181 return offset;
178 case Merge:182 case Merge:
179 const MergeInputSection *MS = cast<MergeInputSection>(this);183 const MergeInputSection *ms = cast<MergeInputSection>(this);
180 if (InputSection *IS = MS->getParent())184 if (InputSection *isec = ms->getParent())
181 return IS->getOffset(MS->getParentOffset(Offset));185 return isec->getOffset(ms->getParentOffset(offset));
182 return MS->getParentOffset(Offset);186 return ms->getParentOffset(offset);
183 }187 }
184 llvm_unreachable("invalid section kind");188 llvm_unreachable("invalid section kind");
185}189}
186190
187uint64_t SectionBase::getVA(uint64_t Offset) const {191uint64_t SectionBase::getVA(uint64_t offset) const {
188 const OutputSection *Out = getOutputSection();192 const OutputSection *out = getOutputSection();
189 return (Out ? Out->Addr : 0) + getOffset(Offset);193 return (out ? out->addr : 0) + getOffset(offset);
190}194}
191195
192OutputSection *SectionBase::getOutputSection() {196OutputSection *SectionBase::getOutputSection() {
193 InputSection *Sec;197 InputSection *sec;
194 if (auto *IS = dyn_cast<InputSection>(this))198 if (auto *isec = dyn_cast<InputSection>(this))
195 Sec = IS;199 sec = isec;
196 else if (auto *MS = dyn_cast<MergeInputSection>(this))200 else if (auto *ms = dyn_cast<MergeInputSection>(this))
197 Sec = MS->getParent();201 sec = ms->getParent();
198 else if (auto *EH = dyn_cast<EhInputSection>(this))202 else if (auto *eh = dyn_cast<EhInputSection>(this))
199 Sec = EH->getParent();203 sec = eh->getParent();
200 else204 else
201 return cast<OutputSection>(this);205 return cast<OutputSection>(this);
202 return Sec ? Sec->getParent() : nullptr;206 return sec ? sec->getParent() : nullptr;
203}207}
204208
205// When a section is compressed, `RawData` consists with a header followed209// When a section is compressed, `rawData` consists with a header followed
206// by zlib-compressed data. This function parses a header to initialize210// by zlib-compressed data. This function parses a header to initialize
207// `UncompressedSize` member and remove the header from `RawData`.211// `uncompressedSize` member and remove the header from `rawData`.
208void InputSectionBase::parseCompressedHeader() {212void InputSectionBase::parseCompressedHeader() {
209 typedef typename ELF64LE::Chdr Chdr64;213 using Chdr64 = typename ELF64LE::Chdr;
210 typedef typename ELF32LE::Chdr Chdr32;214 using Chdr32 = typename ELF32LE::Chdr;
211215
212 // Old-style header216 // Old-style header
213 if (Name.startswith(".zdebug")) {217 if (name.startswith(".zdebug")) {
214 if (!toStringRef(RawData).startswith("ZLIB")) {218 if (!toStringRef(rawData).startswith("ZLIB")) {
215 error(toString(this) + ": corrupted compressed section header");219 error(toString(this) + ": corrupted compressed section header");
216 return;220 return;
217 }221 }
218 RawData = RawData.slice(4);222 rawData = rawData.slice(4);
219223
220 if (RawData.size() < 8) {224 if (rawData.size() < 8) {
221 error(toString(this) + ": corrupted compressed section header");225 error(toString(this) + ": corrupted compressed section header");
222 return;226 return;
223 }227 }
224228
225 UncompressedSize = read64be(RawData.data());229 uncompressedSize = read64be(rawData.data());
226 RawData = RawData.slice(8);230 rawData = rawData.slice(8);
227231
228 // Restore the original section name.232 // Restore the original section name.
229 // (e.g. ".zdebug_info" -> ".debug_info")233 // (e.g. ".zdebug_info" -> ".debug_info")
230 Name = Saver.save("." + Name.substr(2));234 name = saver.save("." + name.substr(2));
231 return;235 return;
232 }236 }
233237
234 assert(Flags & SHF_COMPRESSED);238 assert(flags & SHF_COMPRESSED);
235 Flags &= ~(uint64_t)SHF_COMPRESSED;239 flags &= ~(uint64_t)SHF_COMPRESSED;
236240
237 // New-style 64-bit header241 // New-style 64-bit header
238 if (Config->Is64) {242 if (config->is64) {
239 if (RawData.size() < sizeof(Chdr64)) {243 if (rawData.size() < sizeof(Chdr64)) {
240 error(toString(this) + ": corrupted compressed section");244 error(toString(this) + ": corrupted compressed section");
241 return;245 return;
242 }246 }
243247
244 auto *Hdr = reinterpret_cast<const Chdr64 *>(RawData.data());248 auto *hdr = reinterpret_cast<const Chdr64 *>(rawData.data());
245 if (Hdr->ch_type != ELFCOMPRESS_ZLIB) {249 if (hdr->ch_type != ELFCOMPRESS_ZLIB) {
246 error(toString(this) + ": unsupported compression type");250 error(toString(this) + ": unsupported compression type");
247 return;251 return;
248 }252 }
249253
250 UncompressedSize = Hdr->ch_size;254 uncompressedSize = hdr->ch_size;
251 RawData = RawData.slice(sizeof(*Hdr));255 alignment = std::max<uint32_t>(hdr->ch_addralign, 1);
256 rawData = rawData.slice(sizeof(*hdr));
252 return;257 return;
253 }258 }
254259
255 // New-style 32-bit header260 // New-style 32-bit header
256 if (RawData.size() < sizeof(Chdr32)) {261 if (rawData.size() < sizeof(Chdr32)) {
257 error(toString(this) + ": corrupted compressed section");262 error(toString(this) + ": corrupted compressed section");
258 return;263 return;
259 }264 }
260265
261 auto *Hdr = reinterpret_cast<const Chdr32 *>(RawData.data());266 auto *hdr = reinterpret_cast<const Chdr32 *>(rawData.data());
262 if (Hdr->ch_type != ELFCOMPRESS_ZLIB) {267 if (hdr->ch_type != ELFCOMPRESS_ZLIB) {
263 error(toString(this) + ": unsupported compression type");268 error(toString(this) + ": unsupported compression type");
264 return;269 return;
265 }270 }
266271
267 UncompressedSize = Hdr->ch_size;272 uncompressedSize = hdr->ch_size;
268 RawData = RawData.slice(sizeof(*Hdr));273 alignment = std::max<uint32_t>(hdr->ch_addralign, 1);
274 rawData = rawData.slice(sizeof(*hdr));
269}275}
270276
271InputSection *InputSectionBase::getLinkOrderDep() const {277InputSection *InputSectionBase::getLinkOrderDep() const {
272 assert(Link);278 assert(link);
273 assert(Flags & SHF_LINK_ORDER);279 assert(flags & SHF_LINK_ORDER);
274 return cast<InputSection>(File->getSections()[Link]);280 return cast<InputSection>(file->getSections()[link]);
275}281}
276282
277// Find a function symbol that encloses a given location.283// Find a function symbol that encloses a given location.
278template <class ELFT>284template <class ELFT>
279Defined *InputSectionBase::getEnclosingFunction(uint64_t Offset) {285Defined *InputSectionBase::getEnclosingFunction(uint64_t offset) {
280 for (Symbol *B : File->getSymbols())286 for (Symbol *b : file->getSymbols())
281 if (Defined *D = dyn_cast<Defined>(B))287 if (Defined *d = dyn_cast<Defined>(b))
282 if (D->Section == this && D->Type == STT_FUNC && D->Value <= Offset &&288 if (d->section == this && d->type == STT_FUNC && d->value <= offset &&
283 Offset < D->Value + D->Size)289 offset < d->value + d->size)
284 return D;290 return d;
285 return nullptr;291 return nullptr;
286}292}
287293
288// Returns a source location string. Used to construct an error message.294// Returns a source location string. Used to construct an error message.
289template <class ELFT>295template <class ELFT>
290std::string InputSectionBase::getLocation(uint64_t Offset) {296std::string InputSectionBase::getLocation(uint64_t offset) {
291 std::string SecAndOffset = (Name + "+0x" + utohexstr(Offset)).str();297 std::string secAndOffset = (name + "+0x" + utohexstr(offset)).str();
292298
293 // We don't have file for synthetic sections.299 // We don't have file for synthetic sections.
294 if (getFile<ELFT>() == nullptr)300 if (getFile<ELFT>() == nullptr)
295 return (Config->OutputFile + ":(" + SecAndOffset + ")")301 return (config->outputFile + ":(" + secAndOffset + ")")
296 .str();302 .str();
297303
298 // First check if we can get desired values from debugging information.304 // First check if we can get desired values from debugging information.
299 if (Optional<DILineInfo> Info = getFile<ELFT>()->getDILineInfo(this, Offset))305 if (Optional<DILineInfo> info = getFile<ELFT>()->getDILineInfo(this, offset))
300 return Info->FileName + ":" + std::to_string(Info->Line) + ":(" +306 return info->FileName + ":" + std::to_string(info->Line) + ":(" +
301 SecAndOffset + ")";307 secAndOffset + ")";
302308
303 // File->SourceFile contains STT_FILE symbol that contains a309 // File->sourceFile contains STT_FILE symbol that contains a
304 // source file name. If it's missing, we use an object file name.310 // source file name. If it's missing, we use an object file name.
305 std::string SrcFile = getFile<ELFT>()->SourceFile;311 std::string srcFile = getFile<ELFT>()->sourceFile;
306 if (SrcFile.empty())312 if (srcFile.empty())
307 SrcFile = toString(File);313 srcFile = toString(file);
308314
309 if (Defined *D = getEnclosingFunction<ELFT>(Offset))315 if (Defined *d = getEnclosingFunction<ELFT>(offset))
310 return SrcFile + ":(function " + toString(*D) + ": " + SecAndOffset + ")";316 return srcFile + ":(function " + toString(*d) + ": " + secAndOffset + ")";
311317
312 // If there's no symbol, print out the offset in the section.318 // If there's no symbol, print out the offset in the section.
313 return (SrcFile + ":(" + SecAndOffset + ")");319 return (srcFile + ":(" + secAndOffset + ")");
314}320}
315321
316// This function is intended to be used for constructing an error message.322// This function is intended to be used for constructing an error message.
...@@ -319,8 +325,8 @@ std::string InputSectionBase::getLocation(uint64_t Offset) {...@@ -319,8 +325,8 @@ std::string InputSectionBase::getLocation(uint64_t Offset) {
319// foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42)325// foo.c:42 (/home/alice/possibly/very/long/path/foo.c:42)
320//326//
321// Returns an empty string if there's no way to get line info.327// Returns an empty string if there's no way to get line info.
322std::string InputSectionBase::getSrcMsg(const Symbol &Sym, uint64_t Offset) {328std::string InputSectionBase::getSrcMsg(const Symbol &sym, uint64_t offset) {
323 return File->getSrcMsg(Sym, *this, Offset);329 return file->getSrcMsg(sym, *this, offset);
324}330}
325331
326// Returns a filename string along with an optional section name. This332// Returns a filename string along with an optional section name. This
...@@ -332,95 +338,96 @@ std::string InputSectionBase::getSrcMsg(const Symbol &Sym, uint64_t Offset) {...@@ -332,95 +338,96 @@ std::string InputSectionBase::getSrcMsg(const Symbol &Sym, uint64_t Offset) {
332// or338// or
333//339//
334// path/to/foo.o:(function bar) in archive path/to/bar.a340// path/to/foo.o:(function bar) in archive path/to/bar.a
335std::string InputSectionBase::getObjMsg(uint64_t Off) {341std::string InputSectionBase::getObjMsg(uint64_t off) {
336 std::string Filename = File->getName();342 std::string filename = file->getName();
337343
338 std::string Archive;344 std::string archive;
339 if (!File->ArchiveName.empty())345 if (!file->archiveName.empty())
340 Archive = " in archive " + File->ArchiveName;346 archive = " in archive " + file->archiveName;
341347
342 // Find a symbol that encloses a given location.348 // Find a symbol that encloses a given location.
343 for (Symbol *B : File->getSymbols())349 for (Symbol *b : file->getSymbols())
344 if (auto *D = dyn_cast<Defined>(B))350 if (auto *d = dyn_cast<Defined>(b))
345 if (D->Section == this && D->Value <= Off && Off < D->Value + D->Size)351 if (d->section == this && d->value <= off && off < d->value + d->size)
346 return Filename + ":(" + toString(*D) + ")" + Archive;352 return filename + ":(" + toString(*d) + ")" + archive;
347353
348 // If there's no symbol, print out the offset in the section.354 // If there's no symbol, print out the offset in the section.
349 return (Filename + ":(" + Name + "+0x" + utohexstr(Off) + ")" + Archive)355 return (filename + ":(" + name + "+0x" + utohexstr(off) + ")" + archive)
350 .str();356 .str();
351}357}
352358
353InputSection InputSection::Discarded(nullptr, 0, 0, 0, ArrayRef<uint8_t>(), "");359InputSection InputSection::discarded(nullptr, 0, 0, 0, ArrayRef<uint8_t>(), "");
354360
355InputSection::InputSection(InputFile *F, uint64_t Flags, uint32_t Type,361InputSection::InputSection(InputFile *f, uint64_t flags, uint32_t type,
356 uint32_t Alignment, ArrayRef<uint8_t> Data,362 uint32_t alignment, ArrayRef<uint8_t> data,
357 StringRef Name, Kind K)363 StringRef name, Kind k)
358 : InputSectionBase(F, Flags, Type,364 : InputSectionBase(f, flags, type,
359 /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, Alignment, Data,365 /*Entsize*/ 0, /*Link*/ 0, /*Info*/ 0, alignment, data,
360 Name, K) {}366 name, k) {}
361367
362template <class ELFT>368template <class ELFT>
363InputSection::InputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header,369InputSection::InputSection(ObjFile<ELFT> &f, const typename ELFT::Shdr &header,
364 StringRef Name)370 StringRef name)
365 : InputSectionBase(F, Header, Name, InputSectionBase::Regular) {}371 : InputSectionBase(f, header, name, InputSectionBase::Regular) {}
366372
367bool InputSection::classof(const SectionBase *S) {373bool InputSection::classof(const SectionBase *s) {
368 return S->kind() == SectionBase::Regular ||374 return s->kind() == SectionBase::Regular ||
369 S->kind() == SectionBase::Synthetic;375 s->kind() == SectionBase::Synthetic;
370}376}
371377
372OutputSection *InputSection::getParent() const {378OutputSection *InputSection::getParent() const {
373 return cast_or_null<OutputSection>(Parent);379 return cast_or_null<OutputSection>(parent);
374}380}
375381
376// Copy SHT_GROUP section contents. Used only for the -r option.382// Copy SHT_GROUP section contents. Used only for the -r option.
377template <class ELFT> void InputSection::copyShtGroup(uint8_t *Buf) {383template <class ELFT> void InputSection::copyShtGroup(uint8_t *buf) {
378 // ELFT::Word is the 32-bit integral type in the target endianness.384 // ELFT::Word is the 32-bit integral type in the target endianness.
379 typedef typename ELFT::Word u32;385 using u32 = typename ELFT::Word;
380 ArrayRef<u32> From = getDataAs<u32>();386 ArrayRef<u32> from = getDataAs<u32>();
381 auto *To = reinterpret_cast<u32 *>(Buf);387 auto *to = reinterpret_cast<u32 *>(buf);
382388
383 // The first entry is not a section number but a flag.389 // The first entry is not a section number but a flag.
384 *To++ = From[0];390 *to++ = from[0];
385391
386 // Adjust section numbers because section numbers in an input object392 // Adjust section numbers because section numbers in an input object
387 // files are different in the output.393 // files are different in the output.
388 ArrayRef<InputSectionBase *> Sections = File->getSections();394 ArrayRef<InputSectionBase *> sections = file->getSections();
389 for (uint32_t Idx : From.slice(1))395 for (uint32_t idx : from.slice(1))
390 *To++ = Sections[Idx]->getOutputSection()->SectionIndex;396 *to++ = sections[idx]->getOutputSection()->sectionIndex;
391}397}
392398
393InputSectionBase *InputSection::getRelocatedSection() const {399InputSectionBase *InputSection::getRelocatedSection() const {
394 if (!File || (Type != SHT_RELA && Type != SHT_REL))400 if (!file || (type != SHT_RELA && type != SHT_REL))
395 return nullptr;401 return nullptr;
396 ArrayRef<InputSectionBase *> Sections = File->getSections();402 ArrayRef<InputSectionBase *> sections = file->getSections();
397 return Sections[Info];403 return sections[info];
398}404}
399405
400// This is used for -r and --emit-relocs. We can't use memcpy to copy406// This is used for -r and --emit-relocs. We can't use memcpy to copy
401// relocations because we need to update symbol table offset and section index407// relocations because we need to update symbol table offset and section index
402// for each relocation. So we copy relocations one by one.408// for each relocation. So we copy relocations one by one.
403template <class ELFT, class RelTy>409template <class ELFT, class RelTy>
404void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {410void InputSection::copyRelocations(uint8_t *buf, ArrayRef<RelTy> rels) {
405 InputSectionBase *Sec = getRelocatedSection();411 InputSectionBase *sec = getRelocatedSection();
406412
407 for (const RelTy &Rel : Rels) {413 for (const RelTy &rel : rels) {
408 RelType Type = Rel.getType(Config->IsMips64EL);414 RelType type = rel.getType(config->isMips64EL);
409 Symbol &Sym = getFile<ELFT>()->getRelocTargetSym(Rel);415 const ObjFile<ELFT> *file = getFile<ELFT>();
416 Symbol &sym = file->getRelocTargetSym(rel);
410417
411 auto *P = reinterpret_cast<typename ELFT::Rela *>(Buf);418 auto *p = reinterpret_cast<typename ELFT::Rela *>(buf);
412 Buf += sizeof(RelTy);419 buf += sizeof(RelTy);
413420
414 if (RelTy::IsRela)421 if (RelTy::IsRela)
415 P->r_addend = getAddend<ELFT>(Rel);422 p->r_addend = getAddend<ELFT>(rel);
416423
417 // Output section VA is zero for -r, so r_offset is an offset within the424 // Output section VA is zero for -r, so r_offset is an offset within the
418 // section, but for --emit-relocs it is an virtual address.425 // section, but for --emit-relocs it is an virtual address.
419 P->r_offset = Sec->getVA(Rel.r_offset);426 p->r_offset = sec->getVA(rel.r_offset);
420 P->setSymbolAndType(In.SymTab->getSymbolIndex(&Sym), Type,427 p->setSymbolAndType(in.symTab->getSymbolIndex(&sym), type,
421 Config->IsMips64EL);428 config->isMips64EL);
422429
423 if (Sym.Type == STT_SECTION) {430 if (sym.type == STT_SECTION) {
424 // We combine multiple section symbols into only one per431 // We combine multiple section symbols into only one per
425 // section. This means we have to update the addend. That is432 // section. This means we have to update the addend. That is
426 // trivial for Elf_Rela, but for Elf_Rel we have to write to the433 // trivial for Elf_Rela, but for Elf_Rel we have to write to the
...@@ -429,25 +436,38 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {...@@ -429,25 +436,38 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
429 // .eh_frame is horribly special and can reference discarded sections. To436 // .eh_frame is horribly special and can reference discarded sections. To
430 // avoid having to parse and recreate .eh_frame, we just replace any437 // avoid having to parse and recreate .eh_frame, we just replace any
431 // relocation in it pointing to discarded sections with R_*_NONE, which438 // relocation in it pointing to discarded sections with R_*_NONE, which
432 // hopefully creates a frame that is ignored at runtime.439 // hopefully creates a frame that is ignored at runtime. Also, don't warn
433 auto *D = dyn_cast<Defined>(&Sym);440 // on .gcc_except_table and debug sections.
434 if (!D) {441 //
435 error("STT_SECTION symbol should be defined");442 // See the comment in maybeReportUndefined for PPC64 .toc .
443 auto *d = dyn_cast<Defined>(&sym);
444 if (!d) {
445 if (!sec->name.startswith(".debug") &&
446 !sec->name.startswith(".zdebug") && sec->name != ".eh_frame" &&
447 sec->name != ".gcc_except_table" && sec->name != ".toc") {
448 uint32_t secIdx = cast<Undefined>(sym).discardedSecIdx;
449 Elf_Shdr_Impl<ELFT> sec =
450 CHECK(file->getObj().sections(), file)[secIdx];
451 warn("relocation refers to a discarded section: " +
452 CHECK(file->getObj().getSectionName(&sec), file) +
453 "\n>>> referenced by " + getObjMsg(p->r_offset));
454 }
455 p->setSymbolAndType(0, 0, false);
436 continue;456 continue;
437 }457 }
438 SectionBase *Section = D->Section->Repl;458 SectionBase *section = d->section->repl;
439 if (!Section->Live) {459 if (!section->isLive()) {
440 P->setSymbolAndType(0, 0, false);460 p->setSymbolAndType(0, 0, false);
441 continue;461 continue;
442 }462 }
443463
444 int64_t Addend = getAddend<ELFT>(Rel);464 int64_t addend = getAddend<ELFT>(rel);
445 const uint8_t *BufLoc = Sec->data().begin() + Rel.r_offset;465 const uint8_t *bufLoc = sec->data().begin() + rel.r_offset;
446 if (!RelTy::IsRela)466 if (!RelTy::IsRela)
447 Addend = Target->getImplicitAddend(BufLoc, Type);467 addend = target->getImplicitAddend(bufLoc, type);
448468
449 if (Config->EMachine == EM_MIPS && Config->Relocatable &&469 if (config->emachine == EM_MIPS && config->relocatable &&
450 Target->getRelExpr(Type, Sym, BufLoc) == R_MIPS_GOTREL) {470 target->getRelExpr(type, sym, bufLoc) == R_MIPS_GOTREL) {
451 // Some MIPS relocations depend on "gp" value. By default,471 // Some MIPS relocations depend on "gp" value. By default,
452 // this value has 0x7ff0 offset from a .got section. But472 // this value has 0x7ff0 offset from a .got section. But
453 // relocatable files produced by a complier or a linker473 // relocatable files produced by a complier or a linker
...@@ -459,13 +479,13 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {...@@ -459,13 +479,13 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
459 // individual "gp" values used by each input object file.479 // individual "gp" values used by each input object file.
460 // As a workaround we add the "gp" value to the relocation480 // As a workaround we add the "gp" value to the relocation
461 // addend and save it back to the file.481 // addend and save it back to the file.
462 Addend += Sec->getFile<ELFT>()->MipsGp0;482 addend += sec->getFile<ELFT>()->mipsGp0;
463 }483 }
464484
465 if (RelTy::IsRela)485 if (RelTy::IsRela)
466 P->r_addend = Sym.getVA(Addend) - Section->getOutputSection()->Addr;486 p->r_addend = sym.getVA(addend) - section->getOutputSection()->addr;
467 else if (Config->Relocatable)487 else if (config->relocatable && type != target->noneRel)
468 Sec->Relocations.push_back({R_ABS, Type, Rel.r_offset, Addend, &Sym});488 sec->relocations.push_back({R_ABS, type, rel.r_offset, addend, &sym});
469 }489 }
470 }490 }
471}491}
...@@ -475,13 +495,13 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {...@@ -475,13 +495,13 @@ void InputSection::copyRelocations(uint8_t *Buf, ArrayRef<RelTy> Rels) {
475// this context is the address of the place P. A further special case is that495// this context is the address of the place P. A further special case is that
476// branch relocations to an undefined weak reference resolve to the next496// branch relocations to an undefined weak reference resolve to the next
477// instruction.497// instruction.
478static uint32_t getARMUndefinedRelativeWeakVA(RelType Type, uint32_t A,498static uint32_t getARMUndefinedRelativeWeakVA(RelType type, uint32_t a,
479 uint32_t P) {499 uint32_t p) {
480 switch (Type) {500 switch (type) {
481 // Unresolved branch relocations to weak references resolve to next501 // Unresolved branch relocations to weak references resolve to next
482 // instruction, this will be either 2 or 4 bytes on from P.502 // instruction, this will be either 2 or 4 bytes on from P.
483 case R_ARM_THM_JUMP11:503 case R_ARM_THM_JUMP11:
484 return P + 2 + A;504 return p + 2 + a;
485 case R_ARM_CALL:505 case R_ARM_CALL:
486 case R_ARM_JUMP24:506 case R_ARM_JUMP24:
487 case R_ARM_PC24:507 case R_ARM_PC24:
...@@ -489,10 +509,10 @@ static uint32_t getARMUndefinedRelativeWeakVA(RelType Type, uint32_t A,...@@ -489,10 +509,10 @@ static uint32_t getARMUndefinedRelativeWeakVA(RelType Type, uint32_t A,
489 case R_ARM_PREL31:509 case R_ARM_PREL31:
490 case R_ARM_THM_JUMP19:510 case R_ARM_THM_JUMP19:
491 case R_ARM_THM_JUMP24:511 case R_ARM_THM_JUMP24:
492 return P + 4 + A;512 return p + 4 + a;
493 case R_ARM_THM_CALL:513 case R_ARM_THM_CALL:
494 // We don't want an interworking BLX to ARM514 // We don't want an interworking BLX to ARM
495 return P + 5 + A;515 return p + 5 + a;
496 // Unresolved non branch pc-relative relocations516 // Unresolved non branch pc-relative relocations
497 // R_ARM_TARGET2 which can be resolved relatively is not present as it never517 // R_ARM_TARGET2 which can be resolved relatively is not present as it never
498 // targets a weak-reference.518 // targets a weak-reference.
...@@ -501,29 +521,29 @@ static uint32_t getARMUndefinedRelativeWeakVA(RelType Type, uint32_t A,...@@ -501,29 +521,29 @@ static uint32_t getARMUndefinedRelativeWeakVA(RelType Type, uint32_t A,
501 case R_ARM_REL32:521 case R_ARM_REL32:
502 case R_ARM_THM_MOVW_PREL_NC:522 case R_ARM_THM_MOVW_PREL_NC:
503 case R_ARM_THM_MOVT_PREL:523 case R_ARM_THM_MOVT_PREL:
504 return P + A;524 return p + a;
505 }525 }
506 llvm_unreachable("ARM pc-relative relocation expected\n");526 llvm_unreachable("ARM pc-relative relocation expected\n");
507}527}
508528
509// The comment above getARMUndefinedRelativeWeakVA applies to this function.529// The comment above getARMUndefinedRelativeWeakVA applies to this function.
510static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A,530static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t type, uint64_t a,
511 uint64_t P) {531 uint64_t p) {
512 switch (Type) {532 switch (type) {
513 // Unresolved branch relocations to weak references resolve to next533 // Unresolved branch relocations to weak references resolve to next
514 // instruction, this is 4 bytes on from P.534 // instruction, this is 4 bytes on from P.
515 case R_AARCH64_CALL26:535 case R_AARCH64_CALL26:
516 case R_AARCH64_CONDBR19:536 case R_AARCH64_CONDBR19:
517 case R_AARCH64_JUMP26:537 case R_AARCH64_JUMP26:
518 case R_AARCH64_TSTBR14:538 case R_AARCH64_TSTBR14:
519 return P + 4 + A;539 return p + 4 + a;
520 // Unresolved non branch pc-relative relocations540 // Unresolved non branch pc-relative relocations
521 case R_AARCH64_PREL16:541 case R_AARCH64_PREL16:
522 case R_AARCH64_PREL32:542 case R_AARCH64_PREL32:
523 case R_AARCH64_PREL64:543 case R_AARCH64_PREL64:
524 case R_AARCH64_ADR_PREL_LO21:544 case R_AARCH64_ADR_PREL_LO21:
525 case R_AARCH64_LD_PREL_LO19:545 case R_AARCH64_LD_PREL_LO19:
526 return P + A;546 return p + a;
527 }547 }
528 llvm_unreachable("AArch64 pc-relative relocation expected\n");548 llvm_unreachable("AArch64 pc-relative relocation expected\n");
529}549}
...@@ -535,11 +555,11 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A,...@@ -535,11 +555,11 @@ static uint64_t getAArch64UndefinedRelativeWeakVA(uint64_t Type, uint64_t A,
535// The procedure call standard only defines a Read Write Position Independent555// The procedure call standard only defines a Read Write Position Independent
536// RWPI variant so in practice we should expect the static base to be the base556// RWPI variant so in practice we should expect the static base to be the base
537// of the RW segment.557// of the RW segment.
538static uint64_t getARMStaticBase(const Symbol &Sym) {558static uint64_t getARMStaticBase(const Symbol &sym) {
539 OutputSection *OS = Sym.getOutputSection();559 OutputSection *os = sym.getOutputSection();
540 if (!OS || !OS->PtLoad || !OS->PtLoad->FirstSec)560 if (!os || !os->ptLoad || !os->ptLoad->firstSec)
541 fatal("SBREL relocation to " + Sym.getName() + " without static base");561 fatal("SBREL relocation to " + sym.getName() + " without static base");
542 return OS->PtLoad->FirstSec->Addr;562 return os->ptLoad->firstSec->addr;
543}563}
544564
545// For R_RISCV_PC_INDIRECT (R_RISCV_PCREL_LO12_{I,S}), the symbol actually565// For R_RISCV_PC_INDIRECT (R_RISCV_PCREL_LO12_{I,S}), the symbol actually
...@@ -548,101 +568,115 @@ static uint64_t getARMStaticBase(const Symbol &Sym) {...@@ -548,101 +568,115 @@ static uint64_t getARMStaticBase(const Symbol &Sym) {
548//568//
549// This function returns the R_RISCV_PCREL_HI20 relocation from569// This function returns the R_RISCV_PCREL_HI20 relocation from
550// R_RISCV_PCREL_LO12's symbol and addend.570// R_RISCV_PCREL_LO12's symbol and addend.
551static Relocation *getRISCVPCRelHi20(const Symbol *Sym, uint64_t Addend) {571static Relocation *getRISCVPCRelHi20(const Symbol *sym, uint64_t addend) {
552 const Defined *D = cast<Defined>(Sym);572 const Defined *d = cast<Defined>(sym);
553 InputSection *IS = cast<InputSection>(D->Section);573 if (!d->section) {
574 error("R_RISCV_PCREL_LO12 relocation points to an absolute symbol: " +
575 sym->getName());
576 return nullptr;
577 }
578 InputSection *isec = cast<InputSection>(d->section);
554579
555 if (Addend != 0)580 if (addend != 0)
556 warn("Non-zero addend in R_RISCV_PCREL_LO12 relocation to " +581 warn("Non-zero addend in R_RISCV_PCREL_LO12 relocation to " +
557 IS->getObjMsg(D->Value) + " is ignored");582 isec->getObjMsg(d->value) + " is ignored");
558583
559 // Relocations are sorted by offset, so we can use std::equal_range to do584 // Relocations are sorted by offset, so we can use std::equal_range to do
560 // binary search.585 // binary search.
561 auto Range = std::equal_range(IS->Relocations.begin(), IS->Relocations.end(),586 Relocation r;
562 D->Value, RelocationOffsetComparator{});587 r.offset = d->value;
563 for (auto It = std::get<0>(Range); It != std::get<1>(Range); ++It)588 auto range =
564 if (isRelExprOneOf<R_PC>(It->Expr))589 std::equal_range(isec->relocations.begin(), isec->relocations.end(), r,
565 return &*It;590 [](const Relocation &lhs, const Relocation &rhs) {
566591 return lhs.offset < rhs.offset;
567 error("R_RISCV_PCREL_LO12 relocation points to " + IS->getObjMsg(D->Value) +592 });
593
594 for (auto it = range.first; it != range.second; ++it)
595 if (it->type == R_RISCV_PCREL_HI20 || it->type == R_RISCV_GOT_HI20 ||
596 it->type == R_RISCV_TLS_GD_HI20 || it->type == R_RISCV_TLS_GOT_HI20)
597 return &*it;
598
599 error("R_RISCV_PCREL_LO12 relocation points to " + isec->getObjMsg(d->value) +
568 " without an associated R_RISCV_PCREL_HI20 relocation");600 " without an associated R_RISCV_PCREL_HI20 relocation");
569 return nullptr;601 return nullptr;
570}602}
571603
572// A TLS symbol's virtual address is relative to the TLS segment. Add a604// 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.605// target-specific adjustment to produce a thread-pointer-relative offset.
574static int64_t getTlsTpOffset() {606static int64_t getTlsTpOffset(const Symbol &s) {
575 switch (Config->EMachine) {607 // On targets that support TLSDESC, _TLS_MODULE_BASE_@tpoff = 0.
608 if (&s == ElfSym::tlsModuleBase)
609 return 0;
610
611 switch (config->emachine) {
576 case EM_ARM:612 case EM_ARM:
577 case EM_AARCH64:613 case EM_AARCH64:
578 // Variant 1. The thread pointer points to a TCB with a fixed 2-word size,614 // 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 TLS615 // followed by a variable amount of alignment padding, followed by the TLS
580 // segment.616 // segment.
581 //617 return s.getVA(0) + alignTo(config->wordsize * 2, Out::tlsPhdr->p_align);
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:618 case EM_386:
587 case EM_X86_64:619 case EM_X86_64:
588 // Variant 2. The TLS segment is located just before the thread pointer.620 // Variant 2. The TLS segment is located just before the thread pointer.
589 return -Out::TlsPhdr->p_memsz;621 return s.getVA(0) - alignTo(Out::tlsPhdr->p_memsz, Out::tlsPhdr->p_align);
622 case EM_PPC:
590 case EM_PPC64:623 case EM_PPC64:
591 // The thread pointer points to a fixed offset from the start of the624 // 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-bit625 // 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 the626 // offset to reach 0x1000 of TCB/thread-library data and 0xf000 of the
594 // program's TLS segment.627 // program's TLS segment.
595 return -0x7000;628 return s.getVA(0) - 0x7000;
629 case EM_RISCV:
630 return s.getVA(0);
596 default:631 default:
597 llvm_unreachable("unhandled Config->EMachine");632 llvm_unreachable("unhandled Config->EMachine");
598 }633 }
599}634}
600635
601static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,636static uint64_t getRelocTargetVA(const InputFile *file, RelType type, int64_t a,
602 uint64_t P, const Symbol &Sym, RelExpr Expr) {637 uint64_t p, const Symbol &sym, RelExpr expr) {
603 switch (Expr) {638 switch (expr) {
604 case R_INVALID:
605 return 0;
606 case R_ABS:639 case R_ABS:
640 case R_DTPREL:
607 case R_RELAX_TLS_LD_TO_LE_ABS:641 case R_RELAX_TLS_LD_TO_LE_ABS:
608 case R_RELAX_GOT_PC_NOPIC:642 case R_RELAX_GOT_PC_NOPIC:
609 return Sym.getVA(A);643 case R_RISCV_ADD:
644 return sym.getVA(a);
610 case R_ADDEND:645 case R_ADDEND:
611 return A;646 return a;
612 case R_ARM_SBREL:647 case R_ARM_SBREL:
613 return Sym.getVA(A) - getARMStaticBase(Sym);648 return sym.getVA(a) - getARMStaticBase(sym);
614 case R_GOT:649 case R_GOT:
615 case R_GOT_PLT:
616 case R_RELAX_TLS_GD_TO_IE_ABS:650 case R_RELAX_TLS_GD_TO_IE_ABS:
617 return Sym.getGotVA() + A;651 return sym.getGotVA() + a;
618 case R_GOTONLY_PC:652 case R_GOTONLY_PC:
619 return In.Got->getVA() + A - P;653 return in.got->getVA() + a - p;
620 case R_GOTONLY_PC_FROM_END:654 case R_GOTPLTONLY_PC:
621 return In.Got->getVA() + A - P + In.Got->getSize();655 return in.gotPlt->getVA() + a - p;
622 case R_GOTREL:656 case R_GOTREL:
623 return Sym.getVA(A) - In.Got->getVA();657 case R_PPC64_RELAX_TOC:
624 case R_GOTREL_FROM_END:658 return sym.getVA(a) - in.got->getVA();
625 return Sym.getVA(A) - In.Got->getVA() - In.Got->getSize();659 case R_GOTPLTREL:
626 case R_GOT_FROM_END:660 return sym.getVA(a) - in.gotPlt->getVA();
627 case R_RELAX_TLS_GD_TO_IE_END:661 case R_GOTPLT:
628 return Sym.getGotOffset() + A - In.Got->getSize();662 case R_RELAX_TLS_GD_TO_IE_GOTPLT:
663 return sym.getGotVA() + a - in.gotPlt->getVA();
629 case R_TLSLD_GOT_OFF:664 case R_TLSLD_GOT_OFF:
630 case R_GOT_OFF:665 case R_GOT_OFF:
631 case R_RELAX_TLS_GD_TO_IE_GOT_OFF:666 case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
632 return Sym.getGotOffset() + A;667 return sym.getGotOffset() + a;
633 case R_AARCH64_GOT_PAGE_PC:668 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:669 case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:
636 return getAArch64Page(Sym.getGotVA() + A) - getAArch64Page(P);670 return getAArch64Page(sym.getGotVA() + a) - getAArch64Page(p);
637 case R_GOT_PC:671 case R_GOT_PC:
638 case R_RELAX_TLS_GD_TO_IE:672 case R_RELAX_TLS_GD_TO_IE:
639 return Sym.getGotVA() + A - P;673 return sym.getGotVA() + a - p;
640 case R_HEXAGON_GOT:674 case R_HEXAGON_GOT:
641 return Sym.getGotVA() - In.GotPlt->getVA();675 return sym.getGotVA() - in.gotPlt->getVA();
642 case R_MIPS_GOTREL:676 case R_MIPS_GOTREL:
643 return Sym.getVA(A) - In.MipsGot->getGp(File);677 return sym.getVA(a) - in.mipsGot->getGp(file);
644 case R_MIPS_GOT_GP:678 case R_MIPS_GOT_GP:
645 return In.MipsGot->getGp(File) + A;679 return in.mipsGot->getGp(file) + a;
646 case R_MIPS_GOT_GP_PC: {680 case R_MIPS_GOT_GP_PC: {
647 // R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target681 // R_MIPS_LO16 expression has R_MIPS_GOT_GP_PC type iif the target
648 // is _gp_disp symbol. In that case we should use the following682 // is _gp_disp symbol. In that case we should use the following
...@@ -651,73 +685,76 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,...@@ -651,73 +685,76 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,
651 // microMIPS variants of these relocations use slightly different685 // microMIPS variants of these relocations use slightly different
652 // expressions: AHL + GP - P + 3 for %lo() and AHL + GP - P - 1 for %hi()686 // expressions: AHL + GP - P + 3 for %lo() and AHL + GP - P - 1 for %hi()
653 // to correctly handle less-sugnificant bit of the microMIPS symbol.687 // to correctly handle less-sugnificant bit of the microMIPS symbol.
654 uint64_t V = In.MipsGot->getGp(File) + A - P;688 uint64_t v = in.mipsGot->getGp(file) + a - p;
655 if (Type == R_MIPS_LO16 || Type == R_MICROMIPS_LO16)689 if (type == R_MIPS_LO16 || type == R_MICROMIPS_LO16)
656 V += 4;690 v += 4;
657 if (Type == R_MICROMIPS_LO16 || Type == R_MICROMIPS_HI16)691 if (type == R_MICROMIPS_LO16 || type == R_MICROMIPS_HI16)
658 V -= 1;692 v -= 1;
659 return V;693 return v;
660 }694 }
661 case R_MIPS_GOT_LOCAL_PAGE:695 case R_MIPS_GOT_LOCAL_PAGE:
662 // If relocation against MIPS local symbol requires GOT entry, this entry696 // If relocation against MIPS local symbol requires GOT entry, this entry
663 // should be initialized by 'page address'. This address is high 16-bits697 // should be initialized by 'page address'. This address is high 16-bits
664 // of sum the symbol's value and the addend.698 // of sum the symbol's value and the addend.
665 return In.MipsGot->getVA() + In.MipsGot->getPageEntryOffset(File, Sym, A) -699 return in.mipsGot->getVA() + in.mipsGot->getPageEntryOffset(file, sym, a) -
666 In.MipsGot->getGp(File);700 in.mipsGot->getGp(file);
667 case R_MIPS_GOT_OFF:701 case R_MIPS_GOT_OFF:
668 case R_MIPS_GOT_OFF32:702 case R_MIPS_GOT_OFF32:
669 // In case of MIPS if a GOT relocation has non-zero addend this addend703 // In case of MIPS if a GOT relocation has non-zero addend this addend
670 // should be applied to the GOT entry content not to the GOT entry offset.704 // should be applied to the GOT entry content not to the GOT entry offset.
671 // That is why we use separate expression type.705 // That is why we use separate expression type.
672 return In.MipsGot->getVA() + In.MipsGot->getSymEntryOffset(File, Sym, A) -706 return in.mipsGot->getVA() + in.mipsGot->getSymEntryOffset(file, sym, a) -
673 In.MipsGot->getGp(File);707 in.mipsGot->getGp(file);
674 case R_MIPS_TLSGD:708 case R_MIPS_TLSGD:
675 return In.MipsGot->getVA() + In.MipsGot->getGlobalDynOffset(File, Sym) -709 return in.mipsGot->getVA() + in.mipsGot->getGlobalDynOffset(file, sym) -
676 In.MipsGot->getGp(File);710 in.mipsGot->getGp(file);
677 case R_MIPS_TLSLD:711 case R_MIPS_TLSLD:
678 return In.MipsGot->getVA() + In.MipsGot->getTlsIndexOffset(File) -712 return in.mipsGot->getVA() + in.mipsGot->getTlsIndexOffset(file) -
679 In.MipsGot->getGp(File);713 in.mipsGot->getGp(file);
680 case R_AARCH64_PAGE_PC: {714 case R_AARCH64_PAGE_PC: {
681 uint64_t Val = Sym.isUndefWeak() ? P + A : Sym.getVA(A);715 uint64_t val = sym.isUndefWeak() ? p + a : sym.getVA(a);
682 return getAArch64Page(Val) - getAArch64Page(P);716 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 }717 }
688 case R_RISCV_PC_INDIRECT: {718 case R_RISCV_PC_INDIRECT: {
689 if (const Relocation *HiRel = getRISCVPCRelHi20(&Sym, A))719 if (const Relocation *hiRel = getRISCVPCRelHi20(&sym, a))
690 return getRelocTargetVA(File, HiRel->Type, HiRel->Addend, Sym.getVA(),720 return getRelocTargetVA(file, hiRel->type, hiRel->addend, sym.getVA(),
691 *HiRel->Sym, HiRel->Expr);721 *hiRel->sym, hiRel->expr);
692 return 0;722 return 0;
693 }723 }
694 case R_PC: {724 case R_PC: {
695 uint64_t Dest;725 uint64_t dest;
696 if (Sym.isUndefWeak()) {726 if (sym.isUndefWeak()) {
697 // On ARM and AArch64 a branch to an undefined weak resolves to the727 // On ARM and AArch64 a branch to an undefined weak resolves to the
698 // next instruction, otherwise the place.728 // next instruction, otherwise the place.
699 if (Config->EMachine == EM_ARM)729 if (config->emachine == EM_ARM)
700 Dest = getARMUndefinedRelativeWeakVA(Type, A, P);730 dest = getARMUndefinedRelativeWeakVA(type, a, p);
701 else if (Config->EMachine == EM_AARCH64)731 else if (config->emachine == EM_AARCH64)
702 Dest = getAArch64UndefinedRelativeWeakVA(Type, A, P);732 dest = getAArch64UndefinedRelativeWeakVA(type, a, p);
733 else if (config->emachine == EM_PPC)
734 dest = p;
703 else735 else
704 Dest = Sym.getVA(A);736 dest = sym.getVA(a);
705 } else {737 } else {
706 Dest = Sym.getVA(A);738 dest = sym.getVA(a);
707 }739 }
708 return Dest - P;740 return dest - p;
709 }741 }
710 case R_PLT:742 case R_PLT:
711 return Sym.getPltVA() + A;743 return sym.getPltVA() + a;
712 case R_PLT_PC:744 case R_PLT_PC:
713 case R_PPC_CALL_PLT:745 case R_PPC64_CALL_PLT:
714 return Sym.getPltVA() + A - P;746 return sym.getPltVA() + a - p;
715 case R_PPC_CALL: {747 case R_PPC32_PLTREL:
716 uint64_t SymVA = Sym.getVA(A);748 // R_PPC_PLTREL24 uses the addend (usually 0 or 0x8000) to indicate r30
749 // stores _GLOBAL_OFFSET_TABLE_ or .got2+0x8000. The addend is ignored for
750 // target VA compuation.
751 return sym.getPltVA() - p;
752 case R_PPC64_CALL: {
753 uint64_t symVA = sym.getVA(a);
717 // If we have an undefined weak symbol, we might get here with a symbol754 // If we have an undefined weak symbol, we might get here with a symbol
718 // address of zero. That could overflow, but the code must be unreachable,755 // address of zero. That could overflow, but the code must be unreachable,
719 // so don't bother doing anything at all.756 // so don't bother doing anything at all.
720 if (!SymVA)757 if (!symVA)
721 return 0;758 return 0;
722759
723 // PPC64 V2 ABI describes two entry points to a function. The global entry760 // PPC64 V2 ABI describes two entry points to a function. The global entry
...@@ -726,46 +763,49 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,...@@ -726,46 +763,49 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,
726 // the callee. For local calls the caller and callee share the same763 // 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 by764 // TOC base and so the TOC pointer initialization code should be skipped by
728 // branching to the local entry point.765 // branching to the local entry point.
729 return SymVA - P + getPPC64GlobalEntryToLocalEntryOffset(Sym.StOther);766 return symVA - p + getPPC64GlobalEntryToLocalEntryOffset(sym.stOther);
730 }767 }
731 case R_PPC_TOC:768 case R_PPC64_TOCBASE:
732 return getPPC64TocBase() + A;769 return getPPC64TocBase() + a;
733 case R_RELAX_GOT_PC:770 case R_RELAX_GOT_PC:
734 return Sym.getVA(A) - P;771 return sym.getVA(a) - p;
735 case R_RELAX_TLS_GD_TO_LE:772 case R_RELAX_TLS_GD_TO_LE:
736 case R_RELAX_TLS_IE_TO_LE:773 case R_RELAX_TLS_IE_TO_LE:
737 case R_RELAX_TLS_LD_TO_LE:774 case R_RELAX_TLS_LD_TO_LE:
738 case R_TLS:775 case R_TLS:
739 // A weak undefined TLS symbol resolves to the base of the TLS776 // It is not very clear what to return if the symbol is undefined. With
740 // block, i.e. gets a value of zero. If we pass --gc-sections to777 // --noinhibit-exec, even a non-weak undefined reference may reach here.
741 // lld and .tbss is not referenced, it gets reclaimed and we don't778 // Just return A, which matches R_ABS, and the behavior of some dynamic
742 // create a TLS program header. Therefore, we resolve this779 // loaders.
743 // statically to zero.780 if (sym.isUndefined())
744 if (Sym.isTls() && Sym.isUndefWeak())781 return a;
745 return 0;782 return getTlsTpOffset(sym) + a;
746 return Sym.getVA(A) + getTlsTpOffset();
747 case R_RELAX_TLS_GD_TO_LE_NEG:783 case R_RELAX_TLS_GD_TO_LE_NEG:
748 case R_NEG_TLS:784 case R_NEG_TLS:
749 return Out::TlsPhdr->p_memsz - Sym.getVA(A);785 if (sym.isUndefined())
786 return a;
787 return -getTlsTpOffset(sym) + a;
750 case R_SIZE:788 case R_SIZE:
751 return Sym.getSize() + A;789 return sym.getSize() + a;
752 case R_TLSDESC:790 case R_TLSDESC:
753 return In.Got->getGlobalDynAddr(Sym) + A;791 return in.got->getGlobalDynAddr(sym) + a;
792 case R_TLSDESC_PC:
793 return in.got->getGlobalDynAddr(sym) + a - p;
754 case R_AARCH64_TLSDESC_PAGE:794 case R_AARCH64_TLSDESC_PAGE:
755 return getAArch64Page(In.Got->getGlobalDynAddr(Sym) + A) -795 return getAArch64Page(in.got->getGlobalDynAddr(sym) + a) -
756 getAArch64Page(P);796 getAArch64Page(p);
757 case R_TLSGD_GOT:797 case R_TLSGD_GOT:
758 return In.Got->getGlobalDynOffset(Sym) + A;798 return in.got->getGlobalDynOffset(sym) + a;
759 case R_TLSGD_GOT_FROM_END:799 case R_TLSGD_GOTPLT:
760 return In.Got->getGlobalDynOffset(Sym) + A - In.Got->getSize();800 return in.got->getVA() + in.got->getGlobalDynOffset(sym) + a - in.gotPlt->getVA();
761 case R_TLSGD_PC:801 case R_TLSGD_PC:
762 return In.Got->getGlobalDynAddr(Sym) + A - P;802 return in.got->getGlobalDynAddr(sym) + a - p;
763 case R_TLSLD_GOT_FROM_END:803 case R_TLSLD_GOTPLT:
764 return In.Got->getTlsIndexOff() + A - In.Got->getSize();804 return in.got->getVA() + in.got->getTlsIndexOff() + a - in.gotPlt->getVA();
765 case R_TLSLD_GOT:805 case R_TLSLD_GOT:
766 return In.Got->getTlsIndexOff() + A;806 return in.got->getTlsIndexOff() + a;
767 case R_TLSLD_PC:807 case R_TLSLD_PC:
768 return In.Got->getTlsIndexVA() + A - P;808 return in.got->getTlsIndexVA() + a - p;
769 default:809 default:
770 llvm_unreachable("invalid expression");810 llvm_unreachable("invalid expression");
771 }811 }
...@@ -779,36 +819,36 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,...@@ -779,36 +819,36 @@ static uint64_t getRelocTargetVA(const InputFile *File, RelType Type, int64_t A,
779// So, we handle relocations for non-alloc sections directly in this819// So, we handle relocations for non-alloc sections directly in this
780// function as a performance optimization.820// function as a performance optimization.
781template <class ELFT, class RelTy>821template <class ELFT, class RelTy>
782void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {822void InputSection::relocateNonAlloc(uint8_t *buf, ArrayRef<RelTy> rels) {
783 const unsigned Bits = sizeof(typename ELFT::uint) * 8;823 const unsigned bits = sizeof(typename ELFT::uint) * 8;
784824
785 for (const RelTy &Rel : Rels) {825 for (const RelTy &rel : rels) {
786 RelType Type = Rel.getType(Config->IsMips64EL);826 RelType type = rel.getType(config->isMips64EL);
787827
788 // GCC 8.0 or earlier have a bug that they emit R_386_GOTPC relocations828 // GCC 8.0 or earlier have a bug that they emit R_386_GOTPC relocations
789 // against _GLOBAL_OFFSET_TABLE_ for .debug_info. The bug has been fixed829 // against _GLOBAL_OFFSET_TABLE_ for .debug_info. The bug has been fixed
790 // in 2017 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82630), but we830 // in 2017 (https://gcc.gnu.org/bugzilla/show_bug.cgi?id=82630), but we
791 // need to keep this bug-compatible code for a while.831 // need to keep this bug-compatible code for a while.
792 if (Config->EMachine == EM_386 && Type == R_386_GOTPC)832 if (config->emachine == EM_386 && type == R_386_GOTPC)
793 continue;833 continue;
794834
795 uint64_t Offset = getOffset(Rel.r_offset);835 uint64_t offset = getOffset(rel.r_offset);
796 uint8_t *BufLoc = Buf + Offset;836 uint8_t *bufLoc = buf + offset;
797 int64_t Addend = getAddend<ELFT>(Rel);837 int64_t addend = getAddend<ELFT>(rel);
798 if (!RelTy::IsRela)838 if (!RelTy::IsRela)
799 Addend += Target->getImplicitAddend(BufLoc, Type);839 addend += target->getImplicitAddend(bufLoc, type);
800840
801 Symbol &Sym = getFile<ELFT>()->getRelocTargetSym(Rel);841 Symbol &sym = getFile<ELFT>()->getRelocTargetSym(rel);
802 RelExpr Expr = Target->getRelExpr(Type, Sym, BufLoc);842 RelExpr expr = target->getRelExpr(type, sym, bufLoc);
803 if (Expr == R_NONE)843 if (expr == R_NONE)
804 continue;844 continue;
805845
806 if (Expr != R_ABS) {846 if (expr != R_ABS && expr != R_DTPREL && expr != R_RISCV_ADD) {
807 std::string Msg = getLocation<ELFT>(Offset) +847 std::string msg = getLocation<ELFT>(offset) +
808 ": has non-ABS relocation " + toString(Type) +848 ": has non-ABS relocation " + toString(type) +
809 " against symbol '" + toString(Sym) + "'";849 " against symbol '" + toString(sym) + "'";
810 if (Expr != R_PC) {850 if (expr != R_PC) {
811 error(Msg);851 error(msg);
812 return;852 return;
813 }853 }
814854
...@@ -819,16 +859,16 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {...@@ -819,16 +859,16 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
819 // relocations without any errors and relocate them as if they were at859 // relocations without any errors and relocate them as if they were at
820 // address 0. For bug-compatibilty, we accept them with warnings. We860 // address 0. For bug-compatibilty, we accept them with warnings. We
821 // know Steel Bank Common Lisp as of 2018 have this bug.861 // know Steel Bank Common Lisp as of 2018 have this bug.
822 warn(Msg);862 warn(msg);
823 Target->relocateOne(BufLoc, Type,863 target->relocateOne(bufLoc, type,
824 SignExtend64<Bits>(Sym.getVA(Addend - Offset)));864 SignExtend64<bits>(sym.getVA(addend - offset)));
825 continue;865 continue;
826 }866 }
827867
828 if (Sym.isTls() && !Out::TlsPhdr)868 if (sym.isTls() && !Out::tlsPhdr)
829 Target->relocateOne(BufLoc, Type, 0);869 target->relocateOne(bufLoc, type, 0);
830 else870 else
831 Target->relocateOne(BufLoc, Type, SignExtend64<Bits>(Sym.getVA(Addend)));871 target->relocateOne(bufLoc, type, SignExtend64<bits>(sym.getVA(addend)));
832 }872 }
833}873}
834874
...@@ -837,96 +877,100 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {...@@ -837,96 +877,100 @@ void InputSection::relocateNonAlloc(uint8_t *Buf, ArrayRef<RelTy> Rels) {
837// relocations aimed to update addends. They are handled in relocateAlloc()877// relocations aimed to update addends. They are handled in relocateAlloc()
838// for allocatable sections, and this function does the same for878// for allocatable sections, and this function does the same for
839// non-allocatable sections, such as sections with debug information.879// non-allocatable sections, such as sections with debug information.
840static void relocateNonAllocForRelocatable(InputSection *Sec, uint8_t *Buf) {880static void relocateNonAllocForRelocatable(InputSection *sec, uint8_t *buf) {
841 const unsigned Bits = Config->Is64 ? 64 : 32;881 const unsigned bits = config->is64 ? 64 : 32;
842882
843 for (const Relocation &Rel : Sec->Relocations) {883 for (const Relocation &rel : sec->relocations) {
844 // InputSection::copyRelocations() adds only R_ABS relocations.884 // InputSection::copyRelocations() adds only R_ABS relocations.
845 assert(Rel.Expr == R_ABS);885 assert(rel.expr == R_ABS);
846 uint8_t *BufLoc = Buf + Rel.Offset + Sec->OutSecOff;886 uint8_t *bufLoc = buf + rel.offset + sec->outSecOff;
847 uint64_t TargetVA = SignExtend64(Rel.Sym->getVA(Rel.Addend), Bits);887 uint64_t targetVA = SignExtend64(rel.sym->getVA(rel.addend), bits);
848 Target->relocateOne(BufLoc, Rel.Type, TargetVA);888 target->relocateOne(bufLoc, rel.type, targetVA);
849 }889 }
850}890}
851891
852template <class ELFT>892template <class ELFT>
853void InputSectionBase::relocate(uint8_t *Buf, uint8_t *BufEnd) {893void InputSectionBase::relocate(uint8_t *buf, uint8_t *bufEnd) {
854 if (Flags & SHF_EXECINSTR)894 if (flags & SHF_EXECINSTR)
855 adjustSplitStackFunctionPrologues<ELFT>(Buf, BufEnd);895 adjustSplitStackFunctionPrologues<ELFT>(buf, bufEnd);
856896
857 if (Flags & SHF_ALLOC) {897 if (flags & SHF_ALLOC) {
858 relocateAlloc(Buf, BufEnd);898 relocateAlloc(buf, bufEnd);
859 return;899 return;
860 }900 }
861901
862 auto *Sec = cast<InputSection>(this);902 auto *sec = cast<InputSection>(this);
863 if (Config->Relocatable)903 if (config->relocatable)
864 relocateNonAllocForRelocatable(Sec, Buf);904 relocateNonAllocForRelocatable(sec, buf);
865 else if (Sec->AreRelocsRela)905 else if (sec->areRelocsRela)
866 Sec->relocateNonAlloc<ELFT>(Buf, Sec->template relas<ELFT>());906 sec->relocateNonAlloc<ELFT>(buf, sec->template relas<ELFT>());
867 else907 else
868 Sec->relocateNonAlloc<ELFT>(Buf, Sec->template rels<ELFT>());908 sec->relocateNonAlloc<ELFT>(buf, sec->template rels<ELFT>());
869}909}
870910
871void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {911void InputSectionBase::relocateAlloc(uint8_t *buf, uint8_t *bufEnd) {
872 assert(Flags & SHF_ALLOC);912 assert(flags & SHF_ALLOC);
873 const unsigned Bits = Config->Wordsize * 8;913 const unsigned bits = config->wordsize * 8;
874914
875 for (const Relocation &Rel : Relocations) {915 for (const Relocation &rel : relocations) {
876 uint64_t Offset = Rel.Offset;916 uint64_t offset = rel.offset;
877 if (auto *Sec = dyn_cast<InputSection>(this))917 if (auto *sec = dyn_cast<InputSection>(this))
878 Offset += Sec->OutSecOff;918 offset += sec->outSecOff;
879 uint8_t *BufLoc = Buf + Offset;919 uint8_t *bufLoc = buf + offset;
880 RelType Type = Rel.Type;920 RelType type = rel.type;
881921
882 uint64_t AddrLoc = getOutputSection()->Addr + Offset;922 uint64_t addrLoc = getOutputSection()->addr + offset;
883 RelExpr Expr = Rel.Expr;923 RelExpr expr = rel.expr;
884 uint64_t TargetVA = SignExtend64(924 uint64_t targetVA = SignExtend64(
885 getRelocTargetVA(File, Type, Rel.Addend, AddrLoc, *Rel.Sym, Expr),925 getRelocTargetVA(file, type, rel.addend, addrLoc, *rel.sym, expr),
886 Bits);926 bits);
887927
888 switch (Expr) {928 switch (expr) {
889 case R_RELAX_GOT_PC:929 case R_RELAX_GOT_PC:
890 case R_RELAX_GOT_PC_NOPIC:930 case R_RELAX_GOT_PC_NOPIC:
891 Target->relaxGot(BufLoc, TargetVA);931 target->relaxGot(bufLoc, type, targetVA);
932 break;
933 case R_PPC64_RELAX_TOC:
934 if (!tryRelaxPPC64TocIndirection(type, rel, bufLoc))
935 target->relocateOne(bufLoc, type, targetVA);
892 break;936 break;
893 case R_RELAX_TLS_IE_TO_LE:937 case R_RELAX_TLS_IE_TO_LE:
894 Target->relaxTlsIeToLe(BufLoc, Type, TargetVA);938 target->relaxTlsIeToLe(bufLoc, type, targetVA);
895 break;939 break;
896 case R_RELAX_TLS_LD_TO_LE:940 case R_RELAX_TLS_LD_TO_LE:
897 case R_RELAX_TLS_LD_TO_LE_ABS:941 case R_RELAX_TLS_LD_TO_LE_ABS:
898 Target->relaxTlsLdToLe(BufLoc, Type, TargetVA);942 target->relaxTlsLdToLe(bufLoc, type, targetVA);
899 break;943 break;
900 case R_RELAX_TLS_GD_TO_LE:944 case R_RELAX_TLS_GD_TO_LE:
901 case R_RELAX_TLS_GD_TO_LE_NEG:945 case R_RELAX_TLS_GD_TO_LE_NEG:
902 Target->relaxTlsGdToLe(BufLoc, Type, TargetVA);946 target->relaxTlsGdToLe(bufLoc, type, targetVA);
903 break;947 break;
904 case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:948 case R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC:
905 case R_RELAX_TLS_GD_TO_IE:949 case R_RELAX_TLS_GD_TO_IE:
906 case R_RELAX_TLS_GD_TO_IE_ABS:950 case R_RELAX_TLS_GD_TO_IE_ABS:
907 case R_RELAX_TLS_GD_TO_IE_GOT_OFF:951 case R_RELAX_TLS_GD_TO_IE_GOT_OFF:
908 case R_RELAX_TLS_GD_TO_IE_END:952 case R_RELAX_TLS_GD_TO_IE_GOTPLT:
909 Target->relaxTlsGdToIe(BufLoc, Type, TargetVA);953 target->relaxTlsGdToIe(bufLoc, type, targetVA);
910 break;954 break;
911 case R_PPC_CALL:955 case R_PPC64_CALL:
912 // If this is a call to __tls_get_addr, it may be part of a TLS956 // If this is a call to __tls_get_addr, it may be part of a TLS
913 // sequence that has been relaxed and turned into a nop. In this957 // sequence that has been relaxed and turned into a nop. In this
914 // case, we don't want to handle it as a call.958 // case, we don't want to handle it as a call.
915 if (read32(BufLoc) == 0x60000000) // nop959 if (read32(bufLoc) == 0x60000000) // nop
916 break;960 break;
917961
918 // Patch a nop (0x60000000) to a ld.962 // Patch a nop (0x60000000) to a ld.
919 if (Rel.Sym->NeedsTocRestore) {963 if (rel.sym->needsTocRestore) {
920 if (BufLoc + 8 > BufEnd || read32(BufLoc + 4) != 0x60000000) {964 if (bufLoc + 8 > bufEnd || read32(bufLoc + 4) != 0x60000000) {
921 error(getErrorLocation(BufLoc) + "call lacks nop, can't restore toc");965 error(getErrorLocation(bufLoc) + "call lacks nop, can't restore toc");
922 break;966 break;
923 }967 }
924 write32(BufLoc + 4, 0xe8410018); // ld %r2, 24(%r1)968 write32(bufLoc + 4, 0xe8410018); // ld %r2, 24(%r1)
925 }969 }
926 Target->relocateOne(BufLoc, Type, TargetVA);970 target->relocateOne(bufLoc, type, targetVA);
927 break;971 break;
928 default:972 default:
929 Target->relocateOne(BufLoc, Type, TargetVA);973 target->relocateOne(bufLoc, type, targetVA);
930 break;974 break;
931 }975 }
932 }976 }
...@@ -935,44 +979,44 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {...@@ -935,44 +979,44 @@ void InputSectionBase::relocateAlloc(uint8_t *Buf, uint8_t *BufEnd) {
935// For each function-defining prologue, find any calls to __morestack,979// For each function-defining prologue, find any calls to __morestack,
936// and replace them with calls to __morestack_non_split.980// and replace them with calls to __morestack_non_split.
937static void switchMorestackCallsToMorestackNonSplit(981static void switchMorestackCallsToMorestackNonSplit(
938 DenseSet<Defined *> &Prologues, std::vector<Relocation *> &MorestackCalls) {982 DenseSet<Defined *> &prologues, std::vector<Relocation *> &morestackCalls) {
939983
940 // If the target adjusted a function's prologue, all calls to984 // If the target adjusted a function's prologue, all calls to
941 // __morestack inside that function should be switched to985 // __morestack inside that function should be switched to
942 // __morestack_non_split.986 // __morestack_non_split.
943 Symbol *MoreStackNonSplit = Symtab->find("__morestack_non_split");987 Symbol *moreStackNonSplit = symtab->find("__morestack_non_split");
944 if (!MoreStackNonSplit) {988 if (!moreStackNonSplit) {
945 error("Mixing split-stack objects requires a definition of "989 error("Mixing split-stack objects requires a definition of "
946 "__morestack_non_split");990 "__morestack_non_split");
947 return;991 return;
948 }992 }
949993
950 // Sort both collections to compare addresses efficiently.994 // Sort both collections to compare addresses efficiently.
951 llvm::sort(MorestackCalls, [](const Relocation *L, const Relocation *R) {995 llvm::sort(morestackCalls, [](const Relocation *l, const Relocation *r) {
952 return L->Offset < R->Offset;996 return l->offset < r->offset;
953 });997 });
954 std::vector<Defined *> Functions(Prologues.begin(), Prologues.end());998 std::vector<Defined *> functions(prologues.begin(), prologues.end());
955 llvm::sort(Functions, [](const Defined *L, const Defined *R) {999 llvm::sort(functions, [](const Defined *l, const Defined *r) {
956 return L->Value < R->Value;1000 return l->value < r->value;
957 });1001 });
9581002
959 auto It = MorestackCalls.begin();1003 auto it = morestackCalls.begin();
960 for (Defined *F : Functions) {1004 for (Defined *f : functions) {
961 // Find the first call to __morestack within the function.1005 // Find the first call to __morestack within the function.
962 while (It != MorestackCalls.end() && (*It)->Offset < F->Value)1006 while (it != morestackCalls.end() && (*it)->offset < f->value)
963 ++It;1007 ++it;
964 // Adjust all calls inside the function.1008 // Adjust all calls inside the function.
965 while (It != MorestackCalls.end() && (*It)->Offset < F->Value + F->Size) {1009 while (it != morestackCalls.end() && (*it)->offset < f->value + f->size) {
966 (*It)->Sym = MoreStackNonSplit;1010 (*it)->sym = moreStackNonSplit;
967 ++It;1011 ++it;
968 }1012 }
969 }1013 }
970}1014}
9711015
972static bool enclosingPrologueAttempted(uint64_t Offset,1016static bool enclosingPrologueAttempted(uint64_t offset,
973 const DenseSet<Defined *> &Prologues) {1017 const DenseSet<Defined *> &prologues) {
974 for (Defined *F : Prologues)1018 for (Defined *f : prologues)
975 if (F->Value <= Offset && Offset < F->Value + F->Size)1019 if (f->value <= offset && offset < f->value + f->size)
976 return true;1020 return true;
977 return false;1021 return false;
978}1022}
...@@ -982,30 +1026,30 @@ static bool enclosingPrologueAttempted(uint64_t Offset,...@@ -982,30 +1026,30 @@ static bool enclosingPrologueAttempted(uint64_t Offset,
982// adjusted to ensure that the called function will have enough stack1026// adjusted to ensure that the called function will have enough stack
983// available. Find those functions, and adjust their prologues.1027// available. Find those functions, and adjust their prologues.
984template <class ELFT>1028template <class ELFT>
985void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf,1029void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *buf,
986 uint8_t *End) {1030 uint8_t *end) {
987 if (!getFile<ELFT>()->SplitStack)1031 if (!getFile<ELFT>()->splitStack)
988 return;1032 return;
989 DenseSet<Defined *> Prologues;1033 DenseSet<Defined *> prologues;
990 std::vector<Relocation *> MorestackCalls;1034 std::vector<Relocation *> morestackCalls;
9911035
992 for (Relocation &Rel : Relocations) {1036 for (Relocation &rel : relocations) {
993 // Local symbols can't possibly be cross-calls, and should have been1037 // Local symbols can't possibly be cross-calls, and should have been
994 // resolved long before this line.1038 // resolved long before this line.
995 if (Rel.Sym->isLocal())1039 if (rel.sym->isLocal())
996 continue;1040 continue;
9971041
998 // Ignore calls into the split-stack api.1042 // Ignore calls into the split-stack api.
999 if (Rel.Sym->getName().startswith("__morestack")) {1043 if (rel.sym->getName().startswith("__morestack")) {
1000 if (Rel.Sym->getName().equals("__morestack"))1044 if (rel.sym->getName().equals("__morestack"))
1001 MorestackCalls.push_back(&Rel);1045 morestackCalls.push_back(&rel);
1002 continue;1046 continue;
1003 }1047 }
10041048
1005 // A relocation to non-function isn't relevant. Sometimes1049 // A relocation to non-function isn't relevant. Sometimes
1006 // __morestack is not marked as a function, so this check comes1050 // __morestack is not marked as a function, so this check comes
1007 // after the name check.1051 // after the name check.
1008 if (Rel.Sym->Type != STT_FUNC)1052 if (rel.sym->type != STT_FUNC)
1009 continue;1053 continue;
10101054
1011 // If the callee's-file was compiled with split stack, nothing to do. In1055 // If the callee's-file was compiled with split stack, nothing to do. In
...@@ -1013,106 +1057,117 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf,...@@ -1013,106 +1057,117 @@ void InputSectionBase::adjustSplitStackFunctionPrologues(uint8_t *Buf,
1013 // being produced". So an "undefined" symbol might be provided by a shared1057 // 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 be1058 // library. It is not possible to tell how such symbols were compiled, so be
1015 // conservative.1059 // conservative.
1016 if (Defined *D = dyn_cast<Defined>(Rel.Sym))1060 if (Defined *d = dyn_cast<Defined>(rel.sym))
1017 if (InputSection *IS = cast_or_null<InputSection>(D->Section))1061 if (InputSection *isec = cast_or_null<InputSection>(d->section))
1018 if (!IS || !IS->getFile<ELFT>() || IS->getFile<ELFT>()->SplitStack)1062 if (!isec || !isec->getFile<ELFT>() || isec->getFile<ELFT>()->splitStack)
1019 continue;1063 continue;
10201064
1021 if (enclosingPrologueAttempted(Rel.Offset, Prologues))1065 if (enclosingPrologueAttempted(rel.offset, prologues))
1022 continue;1066 continue;
10231067
1024 if (Defined *F = getEnclosingFunction<ELFT>(Rel.Offset)) {1068 if (Defined *f = getEnclosingFunction<ELFT>(rel.offset)) {
1025 Prologues.insert(F);1069 prologues.insert(f);
1026 if (Target->adjustPrologueForCrossSplitStack(Buf + getOffset(F->Value),1070 if (target->adjustPrologueForCrossSplitStack(buf + getOffset(f->value),
1027 End, F->StOther))1071 end, f->stOther))
1028 continue;1072 continue;
1029 if (!getFile<ELFT>()->SomeNoSplitStack)1073 if (!getFile<ELFT>()->someNoSplitStack)
1030 error(lld::toString(this) + ": " + F->getName() +1074 error(lld::toString(this) + ": " + f->getName() +
1031 " (with -fsplit-stack) calls " + Rel.Sym->getName() +1075 " (with -fsplit-stack) calls " + rel.sym->getName() +
1032 " (without -fsplit-stack), but couldn't adjust its prologue");1076 " (without -fsplit-stack), but couldn't adjust its prologue");
1033 }1077 }
1034 }1078 }
10351079
1036 if (Target->NeedsMoreStackNonSplit)1080 if (target->needsMoreStackNonSplit)
1037 switchMorestackCallsToMorestackNonSplit(Prologues, MorestackCalls);1081 switchMorestackCallsToMorestackNonSplit(prologues, morestackCalls);
1038}1082}
10391083
1040template <class ELFT> void InputSection::writeTo(uint8_t *Buf) {1084template <class ELFT> void InputSection::writeTo(uint8_t *buf) {
1041 if (Type == SHT_NOBITS)1085 if (type == SHT_NOBITS)
1042 return;1086 return;
10431087
1044 if (auto *S = dyn_cast<SyntheticSection>(this)) {1088 if (auto *s = dyn_cast<SyntheticSection>(this)) {
1045 S->writeTo(Buf + OutSecOff);1089 s->writeTo(buf + outSecOff);
1046 return;1090 return;
1047 }1091 }
10481092
1049 // If -r or --emit-relocs is given, then an InputSection1093 // If -r or --emit-relocs is given, then an InputSection
1050 // may be a relocation section.1094 // may be a relocation section.
1051 if (Type == SHT_RELA) {1095 if (type == SHT_RELA) {
1052 copyRelocations<ELFT>(Buf + OutSecOff, getDataAs<typename ELFT::Rela>());1096 copyRelocations<ELFT>(buf + outSecOff, getDataAs<typename ELFT::Rela>());
1053 return;1097 return;
1054 }1098 }
1055 if (Type == SHT_REL) {1099 if (type == SHT_REL) {
1056 copyRelocations<ELFT>(Buf + OutSecOff, getDataAs<typename ELFT::Rel>());1100 copyRelocations<ELFT>(buf + outSecOff, getDataAs<typename ELFT::Rel>());
1057 return;1101 return;
1058 }1102 }
10591103
1060 // If -r is given, we may have a SHT_GROUP section.1104 // If -r is given, we may have a SHT_GROUP section.
1061 if (Type == SHT_GROUP) {1105 if (type == SHT_GROUP) {
1062 copyShtGroup<ELFT>(Buf + OutSecOff);1106 copyShtGroup<ELFT>(buf + outSecOff);
1063 return;1107 return;
1064 }1108 }
10651109
1066 // If this is a compressed section, uncompress section contents directly1110 // If this is a compressed section, uncompress section contents directly
1067 // to the buffer.1111 // to the buffer.
1068 if (UncompressedSize >= 0 && !UncompressedBuf) {1112 if (uncompressedSize >= 0) {
1069 size_t Size = UncompressedSize;1113 size_t size = uncompressedSize;
1070 if (Error E = zlib::uncompress(toStringRef(RawData),1114 if (Error e = zlib::uncompress(toStringRef(rawData),
1071 (char *)(Buf + OutSecOff), Size))1115 (char *)(buf + outSecOff), size))
1072 fatal(toString(this) +1116 fatal(toString(this) +
1073 ": uncompress failed: " + llvm::toString(std::move(E)));1117 ": uncompress failed: " + llvm::toString(std::move(e)));
1074 uint8_t *BufEnd = Buf + OutSecOff + Size;1118 uint8_t *bufEnd = buf + outSecOff + size;
1075 relocate<ELFT>(Buf, BufEnd);1119 relocate<ELFT>(buf, bufEnd);
1076 return;1120 return;
1077 }1121 }
10781122
1079 // Copy section contents from source object file to output file1123 // Copy section contents from source object file to output file
1080 // and then apply relocations.1124 // and then apply relocations.
1081 memcpy(Buf + OutSecOff, data().data(), data().size());1125 memcpy(buf + outSecOff, data().data(), data().size());
1082 uint8_t *BufEnd = Buf + OutSecOff + data().size();1126 uint8_t *bufEnd = buf + outSecOff + data().size();
1083 relocate<ELFT>(Buf, BufEnd);1127 relocate<ELFT>(buf, bufEnd);
1084}1128}
10851129
1086void InputSection::replace(InputSection *Other) {1130void InputSection::replace(InputSection *other) {
1087 Alignment = std::max(Alignment, Other->Alignment);1131 alignment = std::max(alignment, other->alignment);
1088 Other->Repl = Repl;1132
1089 Other->Live = false;1133 // When a section is replaced with another section that was allocated to
1134 // another partition, the replacement section (and its associated sections)
1135 // need to be placed in the main partition so that both partitions will be
1136 // able to access it.
1137 if (partition != other->partition) {
1138 partition = 1;
1139 for (InputSection *isec : dependentSections)
1140 isec->partition = 1;
1141 }
1142
1143 other->repl = repl;
1144 other->markDead();
1090}1145}
10911146
1092template <class ELFT>1147template <class ELFT>
1093EhInputSection::EhInputSection(ObjFile<ELFT> &F,1148EhInputSection::EhInputSection(ObjFile<ELFT> &f,
1094 const typename ELFT::Shdr &Header,1149 const typename ELFT::Shdr &header,
1095 StringRef Name)1150 StringRef name)
1096 : InputSectionBase(F, Header, Name, InputSectionBase::EHFrame) {}1151 : InputSectionBase(f, header, name, InputSectionBase::EHFrame) {}
10971152
1098SyntheticSection *EhInputSection::getParent() const {1153SyntheticSection *EhInputSection::getParent() const {
1099 return cast_or_null<SyntheticSection>(Parent);1154 return cast_or_null<SyntheticSection>(parent);
1100}1155}
11011156
1102// Returns the index of the first relocation that points to a region between1157// Returns the index of the first relocation that points to a region between
1103// Begin and Begin+Size.1158// Begin and Begin+Size.
1104template <class IntTy, class RelTy>1159template <class IntTy, class RelTy>
1105static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef<RelTy> &Rels,1160static unsigned getReloc(IntTy begin, IntTy size, const ArrayRef<RelTy> &rels,
1106 unsigned &RelocI) {1161 unsigned &relocI) {
1107 // Start search from RelocI for fast access. That works because the1162 // Start search from RelocI for fast access. That works because the
1108 // relocations are sorted in .eh_frame.1163 // relocations are sorted in .eh_frame.
1109 for (unsigned N = Rels.size(); RelocI < N; ++RelocI) {1164 for (unsigned n = rels.size(); relocI < n; ++relocI) {
1110 const RelTy &Rel = Rels[RelocI];1165 const RelTy &rel = rels[relocI];
1111 if (Rel.r_offset < Begin)1166 if (rel.r_offset < begin)
1112 continue;1167 continue;
11131168
1114 if (Rel.r_offset < Begin + Size)1169 if (rel.r_offset < begin + size)
1115 return RelocI;1170 return relocI;
1116 return -1;1171 return -1;
1117 }1172 }
1118 return -1;1173 return -1;
...@@ -1121,84 +1176,84 @@ static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef<RelTy> &Rels,...@@ -1121,84 +1176,84 @@ static unsigned getReloc(IntTy Begin, IntTy Size, const ArrayRef<RelTy> &Rels,
1121// .eh_frame is a sequence of CIE or FDE records.1176// .eh_frame is a sequence of CIE or FDE records.
1122// This function splits an input section into records and returns them.1177// This function splits an input section into records and returns them.
1123template <class ELFT> void EhInputSection::split() {1178template <class ELFT> void EhInputSection::split() {
1124 if (AreRelocsRela)1179 if (areRelocsRela)
1125 split<ELFT>(relas<ELFT>());1180 split<ELFT>(relas<ELFT>());
1126 else1181 else
1127 split<ELFT>(rels<ELFT>());1182 split<ELFT>(rels<ELFT>());
1128}1183}
11291184
1130template <class ELFT, class RelTy>1185template <class ELFT, class RelTy>
1131void EhInputSection::split(ArrayRef<RelTy> Rels) {1186void EhInputSection::split(ArrayRef<RelTy> rels) {
1132 unsigned RelI = 0;1187 unsigned relI = 0;
1133 for (size_t Off = 0, End = data().size(); Off != End;) {1188 for (size_t off = 0, end = data().size(); off != end;) {
1134 size_t Size = readEhRecordSize(this, Off);1189 size_t size = readEhRecordSize(this, off);
1135 Pieces.emplace_back(Off, this, Size, getReloc(Off, Size, Rels, RelI));1190 pieces.emplace_back(off, this, size, getReloc(off, size, rels, relI));
1136 // The empty record is the end marker.1191 // The empty record is the end marker.
1137 if (Size == 4)1192 if (size == 4)
1138 break;1193 break;
1139 Off += Size;1194 off += size;
1140 }1195 }
1141}1196}
11421197
1143static size_t findNull(StringRef S, size_t EntSize) {1198static size_t findNull(StringRef s, size_t entSize) {
1144 // Optimize the common case.1199 // Optimize the common case.
1145 if (EntSize == 1)1200 if (entSize == 1)
1146 return S.find(0);1201 return s.find(0);
11471202
1148 for (unsigned I = 0, N = S.size(); I != N; I += EntSize) {1203 for (unsigned i = 0, n = s.size(); i != n; i += entSize) {
1149 const char *B = S.begin() + I;1204 const char *b = s.begin() + i;
1150 if (std::all_of(B, B + EntSize, [](char C) { return C == 0; }))1205 if (std::all_of(b, b + entSize, [](char c) { return c == 0; }))
1151 return I;1206 return i;
1152 }1207 }
1153 return StringRef::npos;1208 return StringRef::npos;
1154}1209}
11551210
1156SyntheticSection *MergeInputSection::getParent() const {1211SyntheticSection *MergeInputSection::getParent() const {
1157 return cast_or_null<SyntheticSection>(Parent);1212 return cast_or_null<SyntheticSection>(parent);
1158}1213}
11591214
1160// Split SHF_STRINGS section. Such section is a sequence of1215// Split SHF_STRINGS section. Such section is a sequence of
1161// null-terminated strings.1216// null-terminated strings.
1162void MergeInputSection::splitStrings(ArrayRef<uint8_t> Data, size_t EntSize) {1217void MergeInputSection::splitStrings(ArrayRef<uint8_t> data, size_t entSize) {
1163 size_t Off = 0;1218 size_t off = 0;
1164 bool IsAlloc = Flags & SHF_ALLOC;1219 bool isAlloc = flags & SHF_ALLOC;
1165 StringRef S = toStringRef(Data);1220 StringRef s = toStringRef(data);
11661221
1167 while (!S.empty()) {1222 while (!s.empty()) {
1168 size_t End = findNull(S, EntSize);1223 size_t end = findNull(s, entSize);
1169 if (End == StringRef::npos)1224 if (end == StringRef::npos)
1170 fatal(toString(this) + ": string is not null terminated");1225 fatal(toString(this) + ": string is not null terminated");
1171 size_t Size = End + EntSize;1226 size_t size = end + entSize;
11721227
1173 Pieces.emplace_back(Off, xxHash64(S.substr(0, Size)), !IsAlloc);1228 pieces.emplace_back(off, xxHash64(s.substr(0, size)), !isAlloc);
1174 S = S.substr(Size);1229 s = s.substr(size);
1175 Off += Size;1230 off += size;
1176 }1231 }
1177}1232}
11781233
1179// Split non-SHF_STRINGS section. Such section is a sequence of1234// Split non-SHF_STRINGS section. Such section is a sequence of
1180// fixed size records.1235// fixed size records.
1181void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> Data,1236void MergeInputSection::splitNonStrings(ArrayRef<uint8_t> data,
1182 size_t EntSize) {1237 size_t entSize) {
1183 size_t Size = Data.size();1238 size_t size = data.size();
1184 assert((Size % EntSize) == 0);1239 assert((size % entSize) == 0);
1185 bool IsAlloc = Flags & SHF_ALLOC;1240 bool isAlloc = flags & SHF_ALLOC;
11861241
1187 for (size_t I = 0; I != Size; I += EntSize)1242 for (size_t i = 0; i != size; i += entSize)
1188 Pieces.emplace_back(I, xxHash64(Data.slice(I, EntSize)), !IsAlloc);1243 pieces.emplace_back(i, xxHash64(data.slice(i, entSize)), !isAlloc);
1189}1244}
11901245
1191template <class ELFT>1246template <class ELFT>
1192MergeInputSection::MergeInputSection(ObjFile<ELFT> &F,1247MergeInputSection::MergeInputSection(ObjFile<ELFT> &f,
1193 const typename ELFT::Shdr &Header,1248 const typename ELFT::Shdr &header,
1194 StringRef Name)1249 StringRef name)
1195 : InputSectionBase(F, Header, Name, InputSectionBase::Merge) {}1250 : InputSectionBase(f, header, name, InputSectionBase::Merge) {}
11961251
1197MergeInputSection::MergeInputSection(uint64_t Flags, uint32_t Type,1252MergeInputSection::MergeInputSection(uint64_t flags, uint32_t type,
1198 uint64_t Entsize, ArrayRef<uint8_t> Data,1253 uint64_t entsize, ArrayRef<uint8_t> data,
1199 StringRef Name)1254 StringRef name)
1200 : InputSectionBase(nullptr, Flags, Type, Entsize, /*Link*/ 0, /*Info*/ 0,1255 : InputSectionBase(nullptr, flags, type, entsize, /*Link*/ 0, /*Info*/ 0,
1201 /*Alignment*/ Entsize, Data, Name, SectionBase::Merge) {}1256 /*Alignment*/ entsize, data, name, SectionBase::Merge) {}
12021257
1203// This function is called after we obtain a complete list of input sections1258// This function is called after we obtain a complete list of input sections
1204// that need to be linked. This is responsible to split section contents1259// that need to be linked. This is responsible to split section contents
...@@ -1207,37 +1262,35 @@ MergeInputSection::MergeInputSection(uint64_t Flags, uint32_t Type,...@@ -1207,37 +1262,35 @@ MergeInputSection::MergeInputSection(uint64_t Flags, uint32_t Type,
1207// Note that this function is called from parallelForEach. This must be1262// Note that this function is called from parallelForEach. This must be
1208// thread-safe (i.e. no memory allocation from the pools).1263// thread-safe (i.e. no memory allocation from the pools).
1209void MergeInputSection::splitIntoPieces() {1264void MergeInputSection::splitIntoPieces() {
1210 assert(Pieces.empty());1265 assert(pieces.empty());
12111266
1212 if (Flags & SHF_STRINGS)1267 if (flags & SHF_STRINGS)
1213 splitStrings(data(), Entsize);1268 splitStrings(data(), entsize);
1214 else1269 else
1215 splitNonStrings(data(), Entsize);1270 splitNonStrings(data(), entsize);
1216}1271}
12171272
1218SectionPiece *MergeInputSection::getSectionPiece(uint64_t Offset) {1273SectionPiece *MergeInputSection::getSectionPiece(uint64_t offset) {
1219 if (this->data().size() <= Offset)1274 if (this->data().size() <= offset)
1220 fatal(toString(this) + ": offset is outside the section");1275 fatal(toString(this) + ": offset is outside the section");
12211276
1222 // If Offset is not at beginning of a section piece, it is not in the map.1277 // If Offset is not at beginning of a section piece, it is not in the map.
1223 // In that case we need to do a binary search of the original section piece vector.1278 // In that case we need to do a binary search of the original section piece vector.
1224 auto It2 =1279 auto it = partition_point(
1225 llvm::upper_bound(Pieces, Offset, [](uint64_t Offset, SectionPiece P) {1280 pieces, [=](SectionPiece p) { return p.inputOff <= offset; });
1226 return Offset < P.InputOff;1281 return &it[-1];
1227 });
1228 return &It2[-1];
1229}1282}
12301283
1231// Returns the offset in an output section for a given input offset.1284// Returns the offset in an output section for a given input offset.
1232// Because contents of a mergeable section is not contiguous in output,1285// Because contents of a mergeable section is not contiguous in output,
1233// it is not just an addition to a base output offset.1286// it is not just an addition to a base output offset.
1234uint64_t MergeInputSection::getParentOffset(uint64_t Offset) const {1287uint64_t MergeInputSection::getParentOffset(uint64_t offset) const {
1235 // If Offset is not at beginning of a section piece, it is not in the map.1288 // If Offset is not at beginning of a section piece, it is not in the map.
1236 // In that case we need to search from the original section piece vector.1289 // In that case we need to search from the original section piece vector.
1237 const SectionPiece &Piece =1290 const SectionPiece &piece =
1238 *(const_cast<MergeInputSection *>(this)->getSectionPiece (Offset));1291 *(const_cast<MergeInputSection *>(this)->getSectionPiece (offset));
1239 uint64_t Addend = Offset - Piece.InputOff;1292 uint64_t addend = offset - piece.inputOff;
1240 return Piece.OutputOff + Addend;1293 return piece.outputOff + addend;
1241}1294}
12421295
1243template InputSection::InputSection(ObjFile<ELF32LE> &, const ELF32LE::Shdr &,1296template InputSection::InputSection(ObjFile<ELF32LE> &, const ELF32LE::Shdr &,
deps/lld/ELF/InputSection.h+143-135
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputSection.h -------------------------------------------*- C++ -*-===//1//===- InputSection.h -------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -26,11 +25,14 @@ class Symbol;...@@ -26,11 +25,14 @@ class Symbol;
26struct SectionPiece;25struct SectionPiece;
2726
28class Defined;27class Defined;
28struct Partition;
29class SyntheticSection;29class SyntheticSection;
30class MergeSyntheticSection;30class MergeSyntheticSection;
31template <class ELFT> class ObjFile;31template <class ELFT> class ObjFile;
32class OutputSection;32class OutputSection;
3333
34extern std::vector<Partition> partitions;
35
34// This is the base class of all sections that lld handles. Some are sections in36// This is the base class of all sections that lld handles. Some are sections in
35// input files, some are sections in the produced output file and some exist37// input files, some are sections in the produced output file and some exist
36// just as a convenience for implementing special ways of combining some38// just as a convenience for implementing special ways of combining some
...@@ -39,38 +41,53 @@ class SectionBase {...@@ -39,38 +41,53 @@ class SectionBase {
39public:41public:
40 enum Kind { Regular, EHFrame, Merge, Synthetic, Output };42 enum Kind { Regular, EHFrame, Merge, Synthetic, Output };
4143
42 Kind kind() const { return (Kind)SectionKind; }44 Kind kind() const { return (Kind)sectionKind; }
4345
44 StringRef Name;46 StringRef name;
4547
46 // This pointer points to the "real" instance of this instance.48 // This pointer points to the "real" instance of this instance.
47 // Usually Repl == this. However, if ICF merges two sections,49 // Usually Repl == this. However, if ICF merges two sections,
48 // Repl pointer of one section points to another section. So,50 // Repl pointer of one section points to another section. So,
49 // if you need to get a pointer to this instance, do not use51 // if you need to get a pointer to this instance, do not use
50 // this but instead this->Repl.52 // this but instead this->Repl.
51 SectionBase *Repl;53 SectionBase *repl;
5254
53 unsigned SectionKind : 3;55 unsigned sectionKind : 3;
5456
55 // The next two bit fields are only used by InputSectionBase, but we57 // The next three bit fields are only used by InputSectionBase, but we
56 // put them here so the struct packs better.58 // put them here so the struct packs better.
5759
58 // The garbage collector sets sections' Live bits.60 // True if this section has already been placed to a linker script
59 // If GC is disabled, all sections are considered live by default.61 // output section. This is needed because, in a linker script, you
60 unsigned Live : 1;62 // can refer to the same section more than once. For example, in
63 // the following linker script,
64 //
65 // .foo : { *(.text) }
66 // .bar : { *(.text) }
67 //
68 // .foo takes all .text sections, and .bar becomes empty. To achieve
69 // this, we need to memorize whether a section has been placed or
70 // not for each input section.
71 unsigned assigned : 1;
6172
62 unsigned Bss : 1;73 unsigned bss : 1;
6374
64 // Set for sections that should not be folded by ICF.75 // Set for sections that should not be folded by ICF.
65 unsigned KeepUnique : 1;76 unsigned keepUnique : 1;
77
78 // The 1-indexed partition that this section is assigned to by the garbage
79 // collector, or 0 if this section is dead. Normally there is only one
80 // partition, so this will either be 0 or 1.
81 uint8_t partition;
82 elf::Partition &getPartition() const;
6683
67 // These corresponds to the fields in Elf_Shdr.84 // These corresponds to the fields in Elf_Shdr.
68 uint32_t Alignment;85 uint32_t alignment;
69 uint64_t Flags;86 uint64_t flags;
70 uint64_t Entsize;87 uint64_t entsize;
71 uint32_t Type;88 uint32_t type;
72 uint32_t Link;89 uint32_t link;
73 uint32_t Info;90 uint32_t info;
7491
75 OutputSection *getOutputSection();92 OutputSection *getOutputSection();
76 const OutputSection *getOutputSection() const {93 const OutputSection *getOutputSection() const {
...@@ -79,90 +96,81 @@ public:...@@ -79,90 +96,81 @@ public:
7996
80 // Translate an offset in the input section to an offset in the output97 // Translate an offset in the input section to an offset in the output
81 // section.98 // section.
82 uint64_t getOffset(uint64_t Offset) const;99 uint64_t getOffset(uint64_t offset) const;
83100
84 uint64_t getVA(uint64_t Offset = 0) const;101 uint64_t getVA(uint64_t offset = 0) const;
102
103 bool isLive() const { return partition != 0; }
104 void markLive() { partition = 1; }
105 void markDead() { partition = 0; }
85106
86protected:107protected:
87 SectionBase(Kind SectionKind, StringRef Name, uint64_t Flags,108 SectionBase(Kind sectionKind, StringRef name, uint64_t flags,
88 uint64_t Entsize, uint64_t Alignment, uint32_t Type,109 uint64_t entsize, uint64_t alignment, uint32_t type,
89 uint32_t Info, uint32_t Link)110 uint32_t info, uint32_t link)
90 : Name(Name), Repl(this), SectionKind(SectionKind), Live(false),111 : name(name), repl(this), sectionKind(sectionKind), assigned(false),
91 Bss(false), KeepUnique(false), Alignment(Alignment), Flags(Flags),112 bss(false), keepUnique(false), partition(0), alignment(alignment),
92 Entsize(Entsize), Type(Type), Link(Link), Info(Info) {}113 flags(flags), entsize(entsize), type(type), link(link), info(info) {}
93};114};
94115
95// This corresponds to a section of an input file.116// This corresponds to a section of an input file.
96class InputSectionBase : public SectionBase {117class InputSectionBase : public SectionBase {
97public:118public:
98 template <class ELFT>119 template <class ELFT>
99 InputSectionBase(ObjFile<ELFT> &File, const typename ELFT::Shdr &Header,120 InputSectionBase(ObjFile<ELFT> &file, const typename ELFT::Shdr &header,
100 StringRef Name, Kind SectionKind);121 StringRef name, Kind sectionKind);
122
123 InputSectionBase(InputFile *file, uint64_t flags, uint32_t type,
124 uint64_t entsize, uint32_t link, uint32_t info,
125 uint32_t alignment, ArrayRef<uint8_t> data, StringRef name,
126 Kind sectionKind);
101127
102 InputSectionBase(InputFile *File, uint64_t Flags, uint32_t Type,128 static bool classof(const SectionBase *s) { return s->kind() != Output; }
103 uint64_t Entsize, uint32_t Link, uint32_t Info,
104 uint32_t Alignment, ArrayRef<uint8_t> Data, StringRef Name,
105 Kind SectionKind);
106129
107 static bool classof(const SectionBase *S) { return S->kind() != Output; }130 // Relocations that refer to this section.
131 unsigned numRelocations : 31;
132 unsigned areRelocsRela : 1;
133 const void *firstRelocation = nullptr;
108134
109 // The file which contains this section. Its dynamic type is always135 // The file which contains this section. Its dynamic type is always
110 // ObjFile<ELFT>, but in order to avoid ELFT, we use InputFile as136 // ObjFile<ELFT>, but in order to avoid ELFT, we use InputFile as
111 // its static type.137 // its static type.
112 InputFile *File;138 InputFile *file;
113139
114 template <class ELFT> ObjFile<ELFT> *getFile() const {140 template <class ELFT> ObjFile<ELFT> *getFile() const {
115 return cast_or_null<ObjFile<ELFT>>(File);141 return cast_or_null<ObjFile<ELFT>>(file);
116 }142 }
117143
118 ArrayRef<uint8_t> data() const {144 ArrayRef<uint8_t> data() const {
119 if (UncompressedSize >= 0 && !UncompressedBuf)145 if (uncompressedSize >= 0)
120 uncompress();146 uncompress();
121 return RawData;147 return rawData;
122 }148 }
123149
124 uint64_t getOffsetInFile() const;150 uint64_t getOffsetInFile() const;
125151
126 // True if this section has already been placed to a linker script
127 // output section. This is needed because, in a linker script, you
128 // can refer to the same section more than once. For example, in
129 // the following linker script,
130 //
131 // .foo : { *(.text) }
132 // .bar : { *(.text) }
133 //
134 // .foo takes all .text sections, and .bar becomes empty. To achieve
135 // this, we need to memorize whether a section has been placed or
136 // not for each input section.
137 bool Assigned = false;
138
139 // Input sections are part of an output section. Special sections152 // Input sections are part of an output section. Special sections
140 // like .eh_frame and merge sections are first combined into a153 // like .eh_frame and merge sections are first combined into a
141 // synthetic section that is then added to an output section. In all154 // synthetic section that is then added to an output section. In all
142 // cases this points one level up.155 // cases this points one level up.
143 SectionBase *Parent = nullptr;156 SectionBase *parent = nullptr;
144
145 // Relocations that refer to this section.
146 const void *FirstRelocation = nullptr;
147 unsigned NumRelocations : 31;
148 unsigned AreRelocsRela : 1;
149157
150 template <class ELFT> ArrayRef<typename ELFT::Rel> rels() const {158 template <class ELFT> ArrayRef<typename ELFT::Rel> rels() const {
151 assert(!AreRelocsRela);159 assert(!areRelocsRela);
152 return llvm::makeArrayRef(160 return llvm::makeArrayRef(
153 static_cast<const typename ELFT::Rel *>(FirstRelocation),161 static_cast<const typename ELFT::Rel *>(firstRelocation),
154 NumRelocations);162 numRelocations);
155 }163 }
156164
157 template <class ELFT> ArrayRef<typename ELFT::Rela> relas() const {165 template <class ELFT> ArrayRef<typename ELFT::Rela> relas() const {
158 assert(AreRelocsRela);166 assert(areRelocsRela);
159 return llvm::makeArrayRef(167 return llvm::makeArrayRef(
160 static_cast<const typename ELFT::Rela *>(FirstRelocation),168 static_cast<const typename ELFT::Rela *>(firstRelocation),
161 NumRelocations);169 numRelocations);
162 }170 }
163171
164 // InputSections that are dependent on us (reverse dependency for GC)172 // InputSections that are dependent on us (reverse dependency for GC)
165 llvm::TinyPtrVector<InputSection *> DependentSections;173 llvm::TinyPtrVector<InputSection *> dependentSections;
166174
167 // Returns the size of this section (even if this is a common or BSS.)175 // Returns the size of this section (even if this is a common or BSS.)
168 size_t getSize() const;176 size_t getSize() const;
...@@ -172,23 +180,23 @@ public:...@@ -172,23 +180,23 @@ public:
172 // Get the function symbol that encloses this offset from within the180 // Get the function symbol that encloses this offset from within the
173 // section.181 // section.
174 template <class ELFT>182 template <class ELFT>
175 Defined *getEnclosingFunction(uint64_t Offset);183 Defined *getEnclosingFunction(uint64_t offset);
176184
177 // Returns a source location string. Used to construct an error message.185 // Returns a source location string. Used to construct an error message.
178 template <class ELFT> std::string getLocation(uint64_t Offset);186 template <class ELFT> std::string getLocation(uint64_t offset);
179 std::string getSrcMsg(const Symbol &Sym, uint64_t Offset);187 std::string getSrcMsg(const Symbol &sym, uint64_t offset);
180 std::string getObjMsg(uint64_t Offset);188 std::string getObjMsg(uint64_t offset);
181189
182 // Each section knows how to relocate itself. These functions apply190 // Each section knows how to relocate itself. These functions apply
183 // relocations, assuming that Buf points to this section's copy in191 // relocations, assuming that Buf points to this section's copy in
184 // the mmap'ed output buffer.192 // the mmap'ed output buffer.
185 template <class ELFT> void relocate(uint8_t *Buf, uint8_t *BufEnd);193 template <class ELFT> void relocate(uint8_t *buf, uint8_t *bufEnd);
186 void relocateAlloc(uint8_t *Buf, uint8_t *BufEnd);194 void relocateAlloc(uint8_t *buf, uint8_t *bufEnd);
187195
188 // The native ELF reloc data type is not very convenient to handle.196 // The native ELF reloc data type is not very convenient to handle.
189 // So we convert ELF reloc records to our own records in Relocations.cpp.197 // So we convert ELF reloc records to our own records in Relocations.cpp.
190 // This vector contains such "cooked" relocations.198 // This vector contains such "cooked" relocations.
191 std::vector<Relocation> Relocations;199 std::vector<Relocation> relocations;
192200
193 // A function compiled with -fsplit-stack calling a function201 // A function compiled with -fsplit-stack calling a function
194 // compiled without -fsplit-stack needs its prologue adjusted. Find202 // compiled without -fsplit-stack needs its prologue adjusted. Find
...@@ -196,25 +204,26 @@ public:...@@ -196,25 +204,26 @@ public:
196 // to relocation. See https://gcc.gnu.org/wiki/SplitStacks for more204 // to relocation. See https://gcc.gnu.org/wiki/SplitStacks for more
197 // information.205 // information.
198 template <typename ELFT>206 template <typename ELFT>
199 void adjustSplitStackFunctionPrologues(uint8_t *Buf, uint8_t *End);207 void adjustSplitStackFunctionPrologues(uint8_t *buf, uint8_t *end);
200208
201209
202 template <typename T> llvm::ArrayRef<T> getDataAs() const {210 template <typename T> llvm::ArrayRef<T> getDataAs() const {
203 size_t S = data().size();211 size_t s = data().size();
204 assert(S % sizeof(T) == 0);212 assert(s % sizeof(T) == 0);
205 return llvm::makeArrayRef<T>((const T *)data().data(), S / sizeof(T));213 return llvm::makeArrayRef<T>((const T *)data().data(), s / sizeof(T));
206 }214 }
207215
208protected:216protected:
209 void parseCompressedHeader();217 void parseCompressedHeader();
210 void uncompress() const;218 void uncompress() const;
211219
212 mutable ArrayRef<uint8_t> RawData;220 mutable ArrayRef<uint8_t> rawData;
213221
214 // A pointer that owns uncompressed data if a section is compressed by zlib.222 // This field stores the uncompressed size of the compressed data in rawData,
215 // Since the feature is not used often, this is usually a nullptr.223 // or -1 if rawData is not compressed (either because the section wasn't
216 mutable std::unique_ptr<char[]> UncompressedBuf;224 // compressed in the first place, or because we ended up uncompressing it).
217 int64_t UncompressedSize = -1;225 // Since the feature is not used often, this is usually -1.
226 mutable int64_t uncompressedSize = -1;
218};227};
219228
220// SectionPiece represents a piece of splittable section contents.229// SectionPiece represents a piece of splittable section contents.
...@@ -222,14 +231,13 @@ protected:...@@ -222,14 +231,13 @@ protected:
222// have to be as compact as possible, which is why we don't store the size (can231// have to be as compact as possible, which is why we don't store the size (can
223// be found by looking at the next one).232// be found by looking at the next one).
224struct SectionPiece {233struct SectionPiece {
225 SectionPiece(size_t Off, uint32_t Hash, bool Live)234 SectionPiece(size_t off, uint32_t hash, bool live)
226 : InputOff(Off), Hash(Hash), OutputOff(0),235 : inputOff(off), live(live || !config->gcSections), hash(hash >> 1) {}
227 Live(Live || !Config->GcSections) {}236
228237 uint32_t inputOff;
229 uint32_t InputOff;238 uint32_t live : 1;
230 uint32_t Hash;239 uint32_t hash : 31;
231 int64_t OutputOff : 63;240 uint64_t outputOff = 0;
232 uint64_t Live : 1;
233};241};
234242
235static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big");243static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big");
...@@ -238,74 +246,74 @@ static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big");...@@ -238,74 +246,74 @@ static_assert(sizeof(SectionPiece) == 16, "SectionPiece is too big");
238class MergeInputSection : public InputSectionBase {246class MergeInputSection : public InputSectionBase {
239public:247public:
240 template <class ELFT>248 template <class ELFT>
241 MergeInputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header,249 MergeInputSection(ObjFile<ELFT> &f, const typename ELFT::Shdr &header,
242 StringRef Name);250 StringRef name);
243 MergeInputSection(uint64_t Flags, uint32_t Type, uint64_t Entsize,251 MergeInputSection(uint64_t flags, uint32_t type, uint64_t entsize,
244 ArrayRef<uint8_t> Data, StringRef Name);252 ArrayRef<uint8_t> data, StringRef name);
245253
246 static bool classof(const SectionBase *S) { return S->kind() == Merge; }254 static bool classof(const SectionBase *s) { return s->kind() == Merge; }
247 void splitIntoPieces();255 void splitIntoPieces();
248256
249 // Translate an offset in the input section to an offset in the parent257 // Translate an offset in the input section to an offset in the parent
250 // MergeSyntheticSection.258 // MergeSyntheticSection.
251 uint64_t getParentOffset(uint64_t Offset) const;259 uint64_t getParentOffset(uint64_t offset) const;
252260
253 // Splittable sections are handled as a sequence of data261 // Splittable sections are handled as a sequence of data
254 // rather than a single large blob of data.262 // rather than a single large blob of data.
255 std::vector<SectionPiece> Pieces;263 std::vector<SectionPiece> pieces;
256264
257 // Returns I'th piece's data. This function is very hot when265 // Returns I'th piece's data. This function is very hot when
258 // string merging is enabled, so we want to inline.266 // string merging is enabled, so we want to inline.
259 LLVM_ATTRIBUTE_ALWAYS_INLINE267 LLVM_ATTRIBUTE_ALWAYS_INLINE
260 llvm::CachedHashStringRef getData(size_t I) const {268 llvm::CachedHashStringRef getData(size_t i) const {
261 size_t Begin = Pieces[I].InputOff;269 size_t begin = pieces[i].inputOff;
262 size_t End =270 size_t end =
263 (Pieces.size() - 1 == I) ? data().size() : Pieces[I + 1].InputOff;271 (pieces.size() - 1 == i) ? data().size() : pieces[i + 1].inputOff;
264 return {toStringRef(data().slice(Begin, End - Begin)), Pieces[I].Hash};272 return {toStringRef(data().slice(begin, end - begin)), pieces[i].hash};
265 }273 }
266274
267 // Returns the SectionPiece at a given input section offset.275 // Returns the SectionPiece at a given input section offset.
268 SectionPiece *getSectionPiece(uint64_t Offset);276 SectionPiece *getSectionPiece(uint64_t offset);
269 const SectionPiece *getSectionPiece(uint64_t Offset) const {277 const SectionPiece *getSectionPiece(uint64_t offset) const {
270 return const_cast<MergeInputSection *>(this)->getSectionPiece(Offset);278 return const_cast<MergeInputSection *>(this)->getSectionPiece(offset);
271 }279 }
272280
273 SyntheticSection *getParent() const;281 SyntheticSection *getParent() const;
274282
275private:283private:
276 void splitStrings(ArrayRef<uint8_t> A, size_t Size);284 void splitStrings(ArrayRef<uint8_t> a, size_t size);
277 void splitNonStrings(ArrayRef<uint8_t> A, size_t Size);285 void splitNonStrings(ArrayRef<uint8_t> a, size_t size);
278};286};
279287
280struct EhSectionPiece {288struct EhSectionPiece {
281 EhSectionPiece(size_t Off, InputSectionBase *Sec, uint32_t Size,289 EhSectionPiece(size_t off, InputSectionBase *sec, uint32_t size,
282 unsigned FirstRelocation)290 unsigned firstRelocation)
283 : InputOff(Off), Sec(Sec), Size(Size), FirstRelocation(FirstRelocation) {}291 : inputOff(off), sec(sec), size(size), firstRelocation(firstRelocation) {}
284292
285 ArrayRef<uint8_t> data() {293 ArrayRef<uint8_t> data() {
286 return {Sec->data().data() + this->InputOff, Size};294 return {sec->data().data() + this->inputOff, size};
287 }295 }
288296
289 size_t InputOff;297 size_t inputOff;
290 ssize_t OutputOff = -1;298 ssize_t outputOff = -1;
291 InputSectionBase *Sec;299 InputSectionBase *sec;
292 uint32_t Size;300 uint32_t size;
293 unsigned FirstRelocation;301 unsigned firstRelocation;
294};302};
295303
296// This corresponds to a .eh_frame section of an input file.304// This corresponds to a .eh_frame section of an input file.
297class EhInputSection : public InputSectionBase {305class EhInputSection : public InputSectionBase {
298public:306public:
299 template <class ELFT>307 template <class ELFT>
300 EhInputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header,308 EhInputSection(ObjFile<ELFT> &f, const typename ELFT::Shdr &header,
301 StringRef Name);309 StringRef name);
302 static bool classof(const SectionBase *S) { return S->kind() == EHFrame; }310 static bool classof(const SectionBase *s) { return s->kind() == EHFrame; }
303 template <class ELFT> void split();311 template <class ELFT> void split();
304 template <class ELFT, class RelTy> void split(ArrayRef<RelTy> Rels);312 template <class ELFT, class RelTy> void split(ArrayRef<RelTy> rels);
305313
306 // Splittable sections are handled as a sequence of data314 // Splittable sections are handled as a sequence of data
307 // rather than a single large blob of data.315 // rather than a single large blob of data.
308 std::vector<EhSectionPiece> Pieces;316 std::vector<EhSectionPiece> pieces;
309317
310 SyntheticSection *getParent() const;318 SyntheticSection *getParent() const;
311};319};
...@@ -316,17 +324,17 @@ public:...@@ -316,17 +324,17 @@ public:
316// .eh_frame. It also includes the synthetic sections themselves.324// .eh_frame. It also includes the synthetic sections themselves.
317class InputSection : public InputSectionBase {325class InputSection : public InputSectionBase {
318public:326public:
319 InputSection(InputFile *F, uint64_t Flags, uint32_t Type, uint32_t Alignment,327 InputSection(InputFile *f, uint64_t flags, uint32_t type, uint32_t alignment,
320 ArrayRef<uint8_t> Data, StringRef Name, Kind K = Regular);328 ArrayRef<uint8_t> data, StringRef name, Kind k = Regular);
321 template <class ELFT>329 template <class ELFT>
322 InputSection(ObjFile<ELFT> &F, const typename ELFT::Shdr &Header,330 InputSection(ObjFile<ELFT> &f, const typename ELFT::Shdr &header,
323 StringRef Name);331 StringRef name);
324332
325 // Write this section to a mmap'ed file, assuming Buf is pointing to333 // Write this section to a mmap'ed file, assuming Buf is pointing to
326 // beginning of the output section.334 // beginning of the output section.
327 template <class ELFT> void writeTo(uint8_t *Buf);335 template <class ELFT> void writeTo(uint8_t *buf);
328336
329 uint64_t getOffset(uint64_t Offset) const { return OutSecOff + Offset; }337 uint64_t getOffset(uint64_t offset) const { return outSecOff + offset; }
330338
331 OutputSection *getParent() const;339 OutputSection *getParent() const;
332340
...@@ -334,32 +342,32 @@ public:...@@ -334,32 +342,32 @@ public:
334 // OutputSection's InputSection list, and is used when ordering SHF_LINK_ORDER342 // OutputSection's InputSection list, and is used when ordering SHF_LINK_ORDER
335 // sections. After assignAddresses is called, it represents the offset from343 // sections. After assignAddresses is called, it represents the offset from
336 // the beginning of the output section this section was assigned to.344 // the beginning of the output section this section was assigned to.
337 uint64_t OutSecOff = 0;345 uint64_t outSecOff = 0;
338346
339 static bool classof(const SectionBase *S);347 static bool classof(const SectionBase *s);
340348
341 InputSectionBase *getRelocatedSection() const;349 InputSectionBase *getRelocatedSection() const;
342350
343 template <class ELFT, class RelTy>351 template <class ELFT, class RelTy>
344 void relocateNonAlloc(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);352 void relocateNonAlloc(uint8_t *buf, llvm::ArrayRef<RelTy> rels);
345353
346 // Used by ICF.354 // Used by ICF.
347 uint32_t Class[2] = {0, 0};355 uint32_t eqClass[2] = {0, 0};
348356
349 // Called by ICF to merge two input sections.357 // Called by ICF to merge two input sections.
350 void replace(InputSection *Other);358 void replace(InputSection *other);
351359
352 static InputSection Discarded;360 static InputSection discarded;
353361
354private:362private:
355 template <class ELFT, class RelTy>363 template <class ELFT, class RelTy>
356 void copyRelocations(uint8_t *Buf, llvm::ArrayRef<RelTy> Rels);364 void copyRelocations(uint8_t *buf, llvm::ArrayRef<RelTy> rels);
357365
358 template <class ELFT> void copyShtGroup(uint8_t *Buf);366 template <class ELFT> void copyShtGroup(uint8_t *buf);
359};367};
360368
361// The list of all input sections.369// The list of all input sections.
362extern std::vector<InputSectionBase *> InputSections;370extern std::vector<InputSectionBase *> inputSections;
363371
364} // namespace elf372} // namespace elf
365373
deps/lld/ELF/LTO.cpp+167-160
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- LTO.cpp ------------------------------------------------------------===//1//===- LTO.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -13,6 +12,7 @@...@@ -13,6 +12,7 @@
13#include "LinkerScript.h"12#include "LinkerScript.h"
14#include "SymbolTable.h"13#include "SymbolTable.h"
15#include "Symbols.h"14#include "Symbols.h"
15#include "lld/Common/Args.h"
16#include "lld/Common/ErrorHandler.h"16#include "lld/Common/ErrorHandler.h"
17#include "lld/Common/TargetOptionsCommandFlags.h"17#include "lld/Common/TargetOptionsCommandFlags.h"
18#include "llvm/ADT/STLExtras.h"18#include "llvm/ADT/STLExtras.h"
...@@ -47,134 +47,135 @@ using namespace lld::elf;...@@ -47,134 +47,135 @@ using namespace lld::elf;
4747
48// Creates an empty file to store a list of object files for final48// Creates an empty file to store a list of object files for final
49// linking of distributed ThinLTO.49// linking of distributed ThinLTO.
50static std::unique_ptr<raw_fd_ostream> openFile(StringRef File) {50static std::unique_ptr<raw_fd_ostream> openFile(StringRef file) {
51 std::error_code EC;51 std::error_code ec;
52 auto Ret =52 auto ret =
53 llvm::make_unique<raw_fd_ostream>(File, EC, sys::fs::OpenFlags::F_None);53 llvm::make_unique<raw_fd_ostream>(file, ec, sys::fs::OpenFlags::F_None);
54 if (EC) {54 if (ec) {
55 error("cannot open " + File + ": " + EC.message());55 error("cannot open " + file + ": " + ec.message());
56 return nullptr;56 return nullptr;
57 }57 }
58 return Ret;58 return ret;
59}59}
6060
61static std::string getThinLTOOutputFile(StringRef ModulePath) {61static std::string getThinLTOOutputFile(StringRef modulePath) {
62 return lto::getThinLTOOutputFile(ModulePath,62 return lto::getThinLTOOutputFile(modulePath,
63 Config->ThinLTOPrefixReplace.first,63 config->thinLTOPrefixReplace.first,
64 Config->ThinLTOPrefixReplace.second);64 config->thinLTOPrefixReplace.second);
65}65}
6666
67static lto::Config createConfig() {67static lto::Config createConfig() {
68 lto::Config C;68 lto::Config c;
6969
70 // LLD supports the new relocations and address-significance tables.70 // LLD supports the new relocations and address-significance tables.
71 C.Options = InitTargetOptionsFromCodeGenFlags();71 c.Options = initTargetOptionsFromCodeGenFlags();
72 C.Options.RelaxELFRelocations = true;72 c.Options.RelaxELFRelocations = true;
73 C.Options.EmitAddrsig = true;73 c.Options.EmitAddrsig = true;
7474
75 // Always emit a section per function/datum with LTO.75 // Always emit a section per function/datum with LTO.
76 C.Options.FunctionSections = true;76 c.Options.FunctionSections = true;
77 C.Options.DataSections = true;77 c.Options.DataSections = true;
7878
79 if (Config->Relocatable)79 if (config->relocatable)
80 C.RelocModel = None;80 c.RelocModel = None;
81 else if (Config->Pic)81 else if (config->isPic)
82 C.RelocModel = Reloc::PIC_;82 c.RelocModel = Reloc::PIC_;
83 else83 else
84 C.RelocModel = Reloc::Static;84 c.RelocModel = Reloc::Static;
8585
86 C.CodeModel = GetCodeModelFromCMModel();86 c.CodeModel = getCodeModelFromCMModel();
87 C.DisableVerify = Config->DisableVerify;87 c.DisableVerify = config->disableVerify;
88 C.DiagHandler = diagnosticHandler;88 c.DiagHandler = diagnosticHandler;
89 C.OptLevel = Config->LTOO;89 c.OptLevel = config->ltoo;
90 C.CPU = GetCPUStr();90 c.CPU = getCPUStr();
91 C.MAttrs = GetMAttrs();91 c.MAttrs = getMAttrs();
92 c.CGOptLevel = args::getCGOptLevel(config->ltoo);
9293
93 // Set up a custom pipeline if we've been asked to.94 // Set up a custom pipeline if we've been asked to.
94 C.OptPipeline = Config->LTONewPmPasses;95 c.OptPipeline = config->ltoNewPmPasses;
95 C.AAPipeline = Config->LTOAAPipeline;96 c.AAPipeline = config->ltoAAPipeline;
9697
97 // Set up optimization remarks if we've been asked to.98 // Set up optimization remarks if we've been asked to.
98 C.RemarksFilename = Config->OptRemarksFilename;99 c.RemarksFilename = config->optRemarksFilename;
99 C.RemarksWithHotness = Config->OptRemarksWithHotness;100 c.RemarksPasses = config->optRemarksPasses;
100101 c.RemarksWithHotness = config->optRemarksWithHotness;
101 C.SampleProfile = Config->LTOSampleProfile;102 c.RemarksFormat = config->optRemarksFormat;
102 C.UseNewPM = Config->LTONewPassManager;103
103 C.DebugPassManager = Config->LTODebugPassManager;104 c.SampleProfile = config->ltoSampleProfile;
104 C.DwoDir = Config->DwoDir;105 c.UseNewPM = config->ltoNewPassManager;
105106 c.DebugPassManager = config->ltoDebugPassManager;
106 if (Config->EmitLLVM) {107 c.DwoDir = config->dwoDir;
107 C.PostInternalizeModuleHook = [](size_t Task, const Module &M) {108
108 if (std::unique_ptr<raw_fd_ostream> OS = openFile(Config->OutputFile))109 c.CSIRProfile = config->ltoCSProfileFile;
109 WriteBitcodeToFile(M, *OS, false);110 c.RunCSIRInstr = config->ltoCSProfileGenerate;
111
112 if (config->emitLLVM) {
113 c.PostInternalizeModuleHook = [](size_t task, const Module &m) {
114 if (std::unique_ptr<raw_fd_ostream> os = openFile(config->outputFile))
115 WriteBitcodeToFile(m, *os, false);
110 return false;116 return false;
111 };117 };
112 }118 }
113119
114 if (Config->SaveTemps)120 if (config->saveTemps)
115 checkError(C.addSaveTemps(Config->OutputFile.str() + ".",121 checkError(c.addSaveTemps(config->outputFile.str() + ".",
116 /*UseInputModulePath*/ true));122 /*UseInputModulePath*/ true));
117 return C;123 return c;
118}124}
119125
120BitcodeCompiler::BitcodeCompiler() {126BitcodeCompiler::BitcodeCompiler() {
121 // Initialize IndexFile.127 // Initialize indexFile.
122 if (!Config->ThinLTOIndexOnlyArg.empty())128 if (!config->thinLTOIndexOnlyArg.empty())
123 IndexFile = openFile(Config->ThinLTOIndexOnlyArg);129 indexFile = openFile(config->thinLTOIndexOnlyArg);
124130
125 // Initialize LTOObj.131 // Initialize ltoObj.
126 lto::ThinBackend Backend;132 lto::ThinBackend backend;
127 if (Config->ThinLTOIndexOnly) {133 if (config->thinLTOIndexOnly) {
128 auto OnIndexWrite = [&](StringRef S) { ThinIndices.erase(S); };134 auto onIndexWrite = [&](StringRef s) { thinIndices.erase(s); };
129 Backend = lto::createWriteIndexesThinBackend(135 backend = lto::createWriteIndexesThinBackend(
130 Config->ThinLTOPrefixReplace.first, Config->ThinLTOPrefixReplace.second,136 config->thinLTOPrefixReplace.first, config->thinLTOPrefixReplace.second,
131 Config->ThinLTOEmitImportsFiles, IndexFile.get(), OnIndexWrite);137 config->thinLTOEmitImportsFiles, indexFile.get(), onIndexWrite);
132 } else if (Config->ThinLTOJobs != -1U) {138 } else if (config->thinLTOJobs != -1U) {
133 Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs);139 backend = lto::createInProcessThinBackend(config->thinLTOJobs);
134 }140 }
135141
136 LTOObj = llvm::make_unique<lto::LTO>(createConfig(), Backend,142 ltoObj = llvm::make_unique<lto::LTO>(createConfig(), backend,
137 Config->LTOPartitions);143 config->ltoPartitions);
138144
139 // Initialize UsedStartStop.145 // Initialize usedStartStop.
140 for (Symbol *Sym : Symtab->getSymbols()) {146 symtab->forEachSymbol([&](Symbol *sym) {
141 StringRef S = Sym->getName();147 StringRef s = sym->getName();
142 for (StringRef Prefix : {"__start_", "__stop_"})148 for (StringRef prefix : {"__start_", "__stop_"})
143 if (S.startswith(Prefix))149 if (s.startswith(prefix))
144 UsedStartStop.insert(S.substr(Prefix.size()));150 usedStartStop.insert(s.substr(prefix.size()));
145 }151 });
146}152}
147153
148BitcodeCompiler::~BitcodeCompiler() = default;154BitcodeCompiler::~BitcodeCompiler() = default;
149155
150static void undefine(Symbol *S) {156void BitcodeCompiler::add(BitcodeFile &f) {
151 replaceSymbol<Undefined>(S, nullptr, S->getName(), STB_GLOBAL, STV_DEFAULT,157 lto::InputFile &obj = *f.obj;
152 S->Type);158 bool isExec = !config->shared && !config->relocatable;
153}
154
155void BitcodeCompiler::add(BitcodeFile &F) {
156 lto::InputFile &Obj = *F.Obj;
157 bool IsExec = !Config->Shared && !Config->Relocatable;
158159
159 if (Config->ThinLTOIndexOnly)160 if (config->thinLTOIndexOnly)
160 ThinIndices.insert(Obj.getName());161 thinIndices.insert(obj.getName());
161162
162 ArrayRef<Symbol *> Syms = F.getSymbols();163 ArrayRef<Symbol *> syms = f.getSymbols();
163 ArrayRef<lto::InputFile::Symbol> ObjSyms = Obj.symbols();164 ArrayRef<lto::InputFile::Symbol> objSyms = obj.symbols();
164 std::vector<lto::SymbolResolution> Resols(Syms.size());165 std::vector<lto::SymbolResolution> resols(syms.size());
165166
166 // Provide a resolution to the LTO API for each symbol.167 // Provide a resolution to the LTO API for each symbol.
167 for (size_t I = 0, E = Syms.size(); I != E; ++I) {168 for (size_t i = 0, e = syms.size(); i != e; ++i) {
168 Symbol *Sym = Syms[I];169 Symbol *sym = syms[i];
169 const lto::InputFile::Symbol &ObjSym = ObjSyms[I];170 const lto::InputFile::Symbol &objSym = objSyms[i];
170 lto::SymbolResolution &R = Resols[I];171 lto::SymbolResolution &r = resols[i];
171172
172 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile173 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
173 // reports two symbols for module ASM defined. Without this check, lld174 // reports two symbols for module ASM defined. Without this check, lld
174 // flags an undefined in IR with a definition in ASM as prevailing.175 // flags an undefined in IR with a definition in ASM as prevailing.
175 // Once IRObjectFile is fixed to report only one symbol this hack can176 // Once IRObjectFile is fixed to report only one symbol this hack can
176 // be removed.177 // be removed.
177 R.Prevailing = !ObjSym.isUndefined() && Sym->File == &F;178 r.Prevailing = !objSym.isUndefined() && sym->file == &f;
178179
179 // We ask LTO to preserve following global symbols:180 // We ask LTO to preserve following global symbols:
180 // 1) All symbols when doing relocatable link, so that them can be used181 // 1) All symbols when doing relocatable link, so that them can be used
...@@ -182,115 +183,121 @@ void BitcodeCompiler::add(BitcodeFile &F) {...@@ -182,115 +183,121 @@ void BitcodeCompiler::add(BitcodeFile &F) {
182 // 2) Symbols that are used in regular objects.183 // 2) Symbols that are used in regular objects.
183 // 3) C named sections if we have corresponding __start_/__stop_ symbol.184 // 3) C named sections if we have corresponding __start_/__stop_ symbol.
184 // 4) Symbols that are defined in bitcode files and used for dynamic linking.185 // 4) Symbols that are defined in bitcode files and used for dynamic linking.
185 R.VisibleToRegularObj = Config->Relocatable || Sym->IsUsedInRegularObj ||186 r.VisibleToRegularObj = config->relocatable || sym->isUsedInRegularObj ||
186 (R.Prevailing && Sym->includeInDynsym()) ||187 (r.Prevailing && sym->includeInDynsym()) ||
187 UsedStartStop.count(ObjSym.getSectionName());188 usedStartStop.count(objSym.getSectionName());
188 const auto *DR = dyn_cast<Defined>(Sym);189 const auto *dr = dyn_cast<Defined>(sym);
189 R.FinalDefinitionInLinkageUnit =190 r.FinalDefinitionInLinkageUnit =
190 (IsExec || Sym->Visibility != STV_DEFAULT) && DR &&191 (isExec || sym->visibility != STV_DEFAULT) && dr &&
191 // Skip absolute symbols from ELF objects, otherwise PC-rel relocations192 // Skip absolute symbols from ELF objects, otherwise PC-rel relocations
192 // will be generated by for them, triggering linker errors.193 // will be generated by for them, triggering linker errors.
193 // Symbol section is always null for bitcode symbols, hence the check194 // Symbol section is always null for bitcode symbols, hence the check
194 // for isElf(). Skip linker script defined symbols as well: they have195 // for isElf(). Skip linker script defined symbols as well: they have
195 // no File defined.196 // no File defined.
196 !(DR->Section == nullptr && (!Sym->File || Sym->File->isElf()));197 !(dr->section == nullptr && (!sym->file || sym->file->isElf()));
197198
198 if (R.Prevailing)199 if (r.Prevailing)
199 undefine(Sym);200 sym->replace(Undefined{nullptr, sym->getName(), STB_GLOBAL, STV_DEFAULT,
201 sym->type});
200202
201 // We tell LTO to not apply interprocedural optimization for wrapped203 // We tell LTO to not apply interprocedural optimization for wrapped
202 // (with --wrap) symbols because otherwise LTO would inline them while204 // (with --wrap) symbols because otherwise LTO would inline them while
203 // their values are still not final.205 // their values are still not final.
204 R.LinkerRedefined = !Sym->CanInline;206 r.LinkerRedefined = !sym->canInline;
205 }207 }
206 checkError(LTOObj->add(std::move(F.Obj), Resols));208 checkError(ltoObj->add(std::move(f.obj), resols));
207}209}
208210
209static void createEmptyIndex(StringRef ModulePath) {211// If LazyObjFile has not been added to link, emit empty index files.
210 std::string Path = replaceThinLTOSuffix(getThinLTOOutputFile(ModulePath));212// This is needed because this is what GNU gold plugin does and we have a
211 std::unique_ptr<raw_fd_ostream> OS = openFile(Path + ".thinlto.bc");213// distributed build system that depends on that behavior.
212 if (!OS)214static void thinLTOCreateEmptyIndexFiles() {
213 return;215 for (LazyObjFile *f : lazyObjFiles) {
214216 if (!isBitcode(f->mb))
215 ModuleSummaryIndex M(/*HaveGVs*/ false);217 continue;
216 M.setSkipModuleByDistributedBackend();218 std::string path = replaceThinLTOSuffix(getThinLTOOutputFile(f->getName()));
217 WriteIndexToFile(M, *OS);219 std::unique_ptr<raw_fd_ostream> os = openFile(path + ".thinlto.bc");
220 if (!os)
221 continue;
218222
219 if (Config->ThinLTOEmitImportsFiles)223 ModuleSummaryIndex m(/*HaveGVs*/ false);
220 openFile(Path + ".imports");224 m.setSkipModuleByDistributedBackend();
225 WriteIndexToFile(m, *os);
226 if (config->thinLTOEmitImportsFiles)
227 openFile(path + ".imports");
228 }
221}229}
222230
223// Merge all the bitcode files we have seen, codegen the result231// Merge all the bitcode files we have seen, codegen the result
224// and return the resulting ObjectFile(s).232// and return the resulting ObjectFile(s).
225std::vector<InputFile *> BitcodeCompiler::compile() {233std::vector<InputFile *> BitcodeCompiler::compile() {
226 unsigned MaxTasks = LTOObj->getMaxTasks();234 unsigned maxTasks = ltoObj->getMaxTasks();
227 Buf.resize(MaxTasks);235 buf.resize(maxTasks);
228 Files.resize(MaxTasks);236 files.resize(maxTasks);
229237
230 // The --thinlto-cache-dir option specifies the path to a directory in which238 // The --thinlto-cache-dir option specifies the path to a directory in which
231 // to cache native object files for ThinLTO incremental builds. If a path was239 // to cache native object files for ThinLTO incremental builds. If a path was
232 // specified, configure LTO to use it as the cache directory.240 // specified, configure LTO to use it as the cache directory.
233 lto::NativeObjectCache Cache;241 lto::NativeObjectCache cache;
234 if (!Config->ThinLTOCacheDir.empty())242 if (!config->thinLTOCacheDir.empty())
235 Cache = check(243 cache = check(
236 lto::localCache(Config->ThinLTOCacheDir,244 lto::localCache(config->thinLTOCacheDir,
237 [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {245 [&](size_t task, std::unique_ptr<MemoryBuffer> mb) {
238 Files[Task] = std::move(MB);246 files[task] = std::move(mb);
239 }));247 }));
240248
241 checkError(LTOObj->run(249 if (!bitcodeFiles.empty())
242 [&](size_t Task) {250 checkError(ltoObj->run(
243 return llvm::make_unique<lto::NativeObjectStream>(251 [&](size_t task) {
244 llvm::make_unique<raw_svector_ostream>(Buf[Task]));252 return llvm::make_unique<lto::NativeObjectStream>(
245 },253 llvm::make_unique<raw_svector_ostream>(buf[task]));
246 Cache));254 },
255 cache));
247256
248 // Emit empty index files for non-indexed files257 // Emit empty index files for non-indexed files
249 for (StringRef S : ThinIndices) {258 for (StringRef s : thinIndices) {
250 std::string Path = getThinLTOOutputFile(S);259 std::string path = getThinLTOOutputFile(s);
251 openFile(Path + ".thinlto.bc");260 openFile(path + ".thinlto.bc");
252 if (Config->ThinLTOEmitImportsFiles)261 if (config->thinLTOEmitImportsFiles)
253 openFile(Path + ".imports");262 openFile(path + ".imports");
254 }263 }
255264
256 // If LazyObjFile has not been added to link, emit empty index files.265 if (config->thinLTOIndexOnly) {
257 // This is needed because this is what GNU gold plugin does and we have a266 thinLTOCreateEmptyIndexFiles();
258 // distributed build system that depends on that behavior.
259 if (Config->ThinLTOIndexOnly) {
260 for (LazyObjFile *F : LazyObjFiles)
261 if (!F->AddedToLink && isBitcode(F->MB))
262 createEmptyIndex(F->getName());
263267
264 if (!Config->LTOObjPath.empty())268 if (!config->ltoObjPath.empty())
265 saveBuffer(Buf[0], Config->LTOObjPath);269 saveBuffer(buf[0], config->ltoObjPath);
266270
267 // ThinLTO with index only option is required to generate only the index271 // ThinLTO with index only option is required to generate only the index
268 // files. After that, we exit from linker and ThinLTO backend runs in a272 // files. After that, we exit from linker and ThinLTO backend runs in a
269 // distributed environment.273 // distributed environment.
270 if (IndexFile)274 if (indexFile)
271 IndexFile->close();275 indexFile->close();
272 return {};276 return {};
273 }277 }
274278
275 if (!Config->ThinLTOCacheDir.empty())279 if (!config->thinLTOCacheDir.empty())
276 pruneCache(Config->ThinLTOCacheDir, Config->ThinLTOCachePolicy);280 pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy);
277281
278 std::vector<InputFile *> Ret;282 if (!config->ltoObjPath.empty()) {
279 for (unsigned I = 0; I != MaxTasks; ++I) {283 saveBuffer(buf[0], config->ltoObjPath);
280 if (Buf[I].empty())284 for (unsigned i = 1; i != maxTasks; ++i)
281 continue;285 saveBuffer(buf[i], config->ltoObjPath + Twine(i));
282 if (Config->SaveTemps) {
283 if (I == 0)
284 saveBuffer(Buf[I], Config->OutputFile + ".lto.o");
285 else
286 saveBuffer(Buf[I], Config->OutputFile + Twine(I) + ".lto.o");
287 }
288 InputFile *Obj = createObjectFile(MemoryBufferRef(Buf[I], "lto.tmp"));
289 Ret.push_back(Obj);
290 }286 }
291287
292 for (std::unique_ptr<MemoryBuffer> &File : Files)288 if (config->saveTemps) {
293 if (File)289 saveBuffer(buf[0], config->outputFile + ".lto.o");
294 Ret.push_back(createObjectFile(*File));290 for (unsigned i = 1; i != maxTasks; ++i)
295 return Ret;291 saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o");
292 }
293
294 std::vector<InputFile *> ret;
295 for (unsigned i = 0; i != maxTasks; ++i)
296 if (!buf[i].empty())
297 ret.push_back(createObjectFile(MemoryBufferRef(buf[i], "lto.tmp")));
298
299 for (std::unique_ptr<MemoryBuffer> &file : files)
300 if (file)
301 ret.push_back(createObjectFile(*file));
302 return ret;
296}303}
deps/lld/ELF/LTO.h+10-11
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- LTO.h ----------------------------------------------------*- C++ -*-===//1//===- LTO.h ----------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -46,16 +45,16 @@ public:...@@ -46,16 +45,16 @@ public:
46 BitcodeCompiler();45 BitcodeCompiler();
47 ~BitcodeCompiler();46 ~BitcodeCompiler();
4847
49 void add(BitcodeFile &F);48 void add(BitcodeFile &f);
50 std::vector<InputFile *> compile();49 std::vector<InputFile *> compile();
5150
52private:51private:
53 std::unique_ptr<llvm::lto::LTO> LTOObj;52 std::unique_ptr<llvm::lto::LTO> ltoObj;
54 std::vector<SmallString<0>> Buf;53 std::vector<SmallString<0>> buf;
55 std::vector<std::unique_ptr<MemoryBuffer>> Files;54 std::vector<std::unique_ptr<MemoryBuffer>> files;
56 llvm::DenseSet<StringRef> UsedStartStop;55 llvm::DenseSet<StringRef> usedStartStop;
57 std::unique_ptr<llvm::raw_fd_ostream> IndexFile;56 std::unique_ptr<llvm::raw_fd_ostream> indexFile;
58 llvm::DenseSet<StringRef> ThinIndices;57 llvm::DenseSet<StringRef> thinIndices;
59};58};
60} // namespace elf59} // namespace elf
61} // namespace lld60} // namespace lld
deps/lld/ELF/LinkerScript.cpp+516-502
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- LinkerScript.cpp ---------------------------------------------------===//1//===- LinkerScript.cpp ---------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -47,26 +46,26 @@ using namespace llvm::support::endian;...@@ -47,26 +46,26 @@ using namespace llvm::support::endian;
47using namespace lld;46using namespace lld;
48using namespace lld::elf;47using namespace lld::elf;
4948
50LinkerScript *elf::Script;49LinkerScript *elf::script;
5150
52static uint64_t getOutputSectionVA(SectionBase *InputSec, StringRef Loc) {51static uint64_t getOutputSectionVA(SectionBase *inputSec, StringRef loc) {
53 if (OutputSection *OS = InputSec->getOutputSection())52 if (OutputSection *os = inputSec->getOutputSection())
54 return OS->Addr;53 return os->addr;
55 error(Loc + ": unable to evaluate expression: input section " +54 error(loc + ": unable to evaluate expression: input section " +
56 InputSec->Name + " has no output section assigned");55 inputSec->name + " has no output section assigned");
57 return 0;56 return 0;
58}57}
5958
60uint64_t ExprValue::getValue() const {59uint64_t ExprValue::getValue() const {
61 if (Sec)60 if (sec)
62 return alignTo(Sec->getOffset(Val) + getOutputSectionVA(Sec, Loc),61 return alignTo(sec->getOffset(val) + getOutputSectionVA(sec, loc),
63 Alignment);62 alignment);
64 return alignTo(Val, Alignment);63 return alignTo(val, alignment);
65}64}
6665
67uint64_t ExprValue::getSecAddr() const {66uint64_t ExprValue::getSecAddr() const {
68 if (Sec)67 if (sec)
69 return Sec->getOffset(0) + getOutputSectionVA(Sec, Loc);68 return sec->getOffset(0) + getOutputSectionVA(sec, loc);
70 return 0;69 return 0;
71}70}
7271
...@@ -74,106 +73,100 @@ uint64_t ExprValue::getSectionOffset() const {...@@ -74,106 +73,100 @@ uint64_t ExprValue::getSectionOffset() const {
74 // If the alignment is trivial, we don't have to compute the full73 // If the alignment is trivial, we don't have to compute the full
75 // value to know the offset. This allows this function to succeed in74 // value to know the offset. This allows this function to succeed in
76 // cases where the output section is not yet known.75 // cases where the output section is not yet known.
77 if (Alignment == 1 && (!Sec || !Sec->getOutputSection()))76 if (alignment == 1 && (!sec || !sec->getOutputSection()))
78 return Val;77 return val;
79 return getValue() - getSecAddr();78 return getValue() - getSecAddr();
80}79}
8180
82OutputSection *LinkerScript::createOutputSection(StringRef Name,81OutputSection *LinkerScript::createOutputSection(StringRef name,
83 StringRef Location) {82 StringRef location) {
84 OutputSection *&SecRef = NameToOutputSection[Name];83 OutputSection *&secRef = nameToOutputSection[name];
85 OutputSection *Sec;84 OutputSection *sec;
86 if (SecRef && SecRef->Location.empty()) {85 if (secRef && secRef->location.empty()) {
87 // There was a forward reference.86 // There was a forward reference.
88 Sec = SecRef;87 sec = secRef;
89 } else {88 } else {
90 Sec = make<OutputSection>(Name, SHT_NOBITS, 0);89 sec = make<OutputSection>(name, SHT_PROGBITS, 0);
91 if (!SecRef)90 if (!secRef)
92 SecRef = Sec;91 secRef = sec;
93 }92 }
94 Sec->Location = Location;93 sec->location = location;
95 return Sec;94 return sec;
96}95}
9796
98OutputSection *LinkerScript::getOrCreateOutputSection(StringRef Name) {97OutputSection *LinkerScript::getOrCreateOutputSection(StringRef name) {
99 OutputSection *&CmdRef = NameToOutputSection[Name];98 OutputSection *&cmdRef = nameToOutputSection[name];
100 if (!CmdRef)99 if (!cmdRef)
101 CmdRef = make<OutputSection>(Name, SHT_PROGBITS, 0);100 cmdRef = make<OutputSection>(name, SHT_PROGBITS, 0);
102 return CmdRef;101 return cmdRef;
103}102}
104103
105// Expands the memory region by the specified size.104// Expands the memory region by the specified size.
106static void expandMemoryRegion(MemoryRegion *MemRegion, uint64_t Size,105static void expandMemoryRegion(MemoryRegion *memRegion, uint64_t size,
107 StringRef RegionName, StringRef SecName) {106 StringRef regionName, StringRef secName) {
108 MemRegion->CurPos += Size;107 memRegion->curPos += size;
109 uint64_t NewSize = MemRegion->CurPos - MemRegion->Origin;108 uint64_t newSize = memRegion->curPos - memRegion->origin;
110 if (NewSize > MemRegion->Length)109 if (newSize > memRegion->length)
111 error("section '" + SecName + "' will not fit in region '" + RegionName +110 error("section '" + secName + "' will not fit in region '" + regionName +
112 "': overflowed by " + Twine(NewSize - MemRegion->Length) + " bytes");111 "': overflowed by " + Twine(newSize - memRegion->length) + " bytes");
113}112}
114113
115void LinkerScript::expandMemoryRegions(uint64_t Size) {114void LinkerScript::expandMemoryRegions(uint64_t size) {
116 if (Ctx->MemRegion)115 if (ctx->memRegion)
117 expandMemoryRegion(Ctx->MemRegion, Size, Ctx->MemRegion->Name,116 expandMemoryRegion(ctx->memRegion, size, ctx->memRegion->name,
118 Ctx->OutSec->Name);117 ctx->outSec->name);
119 // Only expand the LMARegion if it is different from MemRegion.118 // Only expand the LMARegion if it is different from memRegion.
120 if (Ctx->LMARegion && Ctx->MemRegion != Ctx->LMARegion)119 if (ctx->lmaRegion && ctx->memRegion != ctx->lmaRegion)
121 expandMemoryRegion(Ctx->LMARegion, Size, Ctx->LMARegion->Name,120 expandMemoryRegion(ctx->lmaRegion, size, ctx->lmaRegion->name,
122 Ctx->OutSec->Name);121 ctx->outSec->name);
123}122}
124123
125void LinkerScript::expandOutputSection(uint64_t Size) {124void LinkerScript::expandOutputSection(uint64_t size) {
126 Ctx->OutSec->Size += Size;125 ctx->outSec->size += size;
127 expandMemoryRegions(Size);126 expandMemoryRegions(size);
128}127}
129128
130void LinkerScript::setDot(Expr E, const Twine &Loc, bool InSec) {129void LinkerScript::setDot(Expr e, const Twine &loc, bool inSec) {
131 uint64_t Val = E().getValue();130 uint64_t val = e().getValue();
132 if (Val < Dot && InSec)131 if (val < dot && inSec)
133 error(Loc + ": unable to move location counter backward for: " +132 error(loc + ": unable to move location counter backward for: " +
134 Ctx->OutSec->Name);133 ctx->outSec->name);
135134
136 // Update to location counter means update to section size.135 // Update to location counter means update to section size.
137 if (InSec)136 if (inSec)
138 expandOutputSection(Val - Dot);137 expandOutputSection(val - dot);
139 else
140 expandMemoryRegions(Val - Dot);
141138
142 Dot = Val;139 dot = val;
143}140}
144141
145// Used for handling linker symbol assignments, for both finalizing142// Used for handling linker symbol assignments, for both finalizing
146// their values and doing early declarations. Returns true if symbol143// their values and doing early declarations. Returns true if symbol
147// should be defined from linker script.144// should be defined from linker script.
148static bool shouldDefineSym(SymbolAssignment *Cmd) {145static bool shouldDefineSym(SymbolAssignment *cmd) {
149 if (Cmd->Name == ".")146 if (cmd->name == ".")
150 return false;147 return false;
151148
152 if (!Cmd->Provide)149 if (!cmd->provide)
153 return true;150 return true;
154151
155 // If a symbol was in PROVIDE(), we need to define it only152 // If a symbol was in PROVIDE(), we need to define it only
156 // when it is a referenced undefined symbol.153 // when it is a referenced undefined symbol.
157 Symbol *B = Symtab->find(Cmd->Name);154 Symbol *b = symtab->find(cmd->name);
158 if (B && !B->isDefined())155 if (b && !b->isDefined())
159 return true;156 return true;
160 return false;157 return false;
161}158}
162159
163// This function is called from processSectionCommands,160// This function is called from processSectionCommands,
164// while we are fixing the output section layout.161// while we are fixing the output section layout.
165void LinkerScript::addSymbol(SymbolAssignment *Cmd) {162void LinkerScript::addSymbol(SymbolAssignment *cmd) {
166 if (!shouldDefineSym(Cmd))163 if (!shouldDefineSym(cmd))
167 return;164 return;
168165
169 // Define a symbol.166 // Define a symbol.
170 Symbol *Sym;167 ExprValue value = cmd->expression();
171 uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;168 SectionBase *sec = value.isAbsolute() ? nullptr : value.sec;
172 std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, Visibility,169 uint8_t visibility = cmd->hidden ? STV_HIDDEN : STV_DEFAULT;
173 /*CanOmitFromDynSym*/ false,
174 /*File*/ nullptr);
175 ExprValue Value = Cmd->Expression();
176 SectionBase *Sec = Value.isAbsolute() ? nullptr : Value.Sec;
177170
178 // When this function is called, section addresses have not been171 // When this function is called, section addresses have not been
179 // fixed yet. So, we may or may not know the value of the RHS172 // fixed yet. So, we may or may not know the value of the RHS
...@@ -186,68 +179,73 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) {...@@ -186,68 +179,73 @@ void LinkerScript::addSymbol(SymbolAssignment *Cmd) {
186 // We want to set symbol values early if we can. This allows us to179 // We want to set symbol values early if we can. This allows us to
187 // use symbols as variables in linker scripts. Doing so allows us to180 // use symbols as variables in linker scripts. Doing so allows us to
188 // write expressions like this: `alignment = 16; . = ALIGN(., alignment)`.181 // write expressions like this: `alignment = 16; . = ALIGN(., alignment)`.
189 uint64_t SymValue = Value.Sec ? 0 : Value.getValue();182 uint64_t symValue = value.sec ? 0 : value.getValue();
183
184 Defined New(nullptr, cmd->name, STB_GLOBAL, visibility, STT_NOTYPE, symValue,
185 0, sec);
190186
191 replaceSymbol<Defined>(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility,187 Symbol *sym = symtab->insert(cmd->name);
192 STT_NOTYPE, SymValue, 0, Sec);188 sym->mergeProperties(New);
193 Cmd->Sym = cast<Defined>(Sym);189 sym->replace(New);
190 cmd->sym = cast<Defined>(sym);
194}191}
195192
196// This function is called from LinkerScript::declareSymbols.193// This function is called from LinkerScript::declareSymbols.
197// It creates a placeholder symbol if needed.194// It creates a placeholder symbol if needed.
198static void declareSymbol(SymbolAssignment *Cmd) {195static void declareSymbol(SymbolAssignment *cmd) {
199 if (!shouldDefineSym(Cmd))196 if (!shouldDefineSym(cmd))
200 return;197 return;
201198
199 uint8_t visibility = cmd->hidden ? STV_HIDDEN : STV_DEFAULT;
200 Defined New(nullptr, cmd->name, STB_GLOBAL, visibility, STT_NOTYPE, 0, 0,
201 nullptr);
202
202 // We can't calculate final value right now.203 // We can't calculate final value right now.
203 Symbol *Sym;204 Symbol *sym = symtab->insert(cmd->name);
204 uint8_t Visibility = Cmd->Hidden ? STV_HIDDEN : STV_DEFAULT;205 sym->mergeProperties(New);
205 std::tie(Sym, std::ignore) = Symtab->insert(Cmd->Name, Visibility,206 sym->replace(New);
206 /*CanOmitFromDynSym*/ false,207
207 /*File*/ nullptr);208 cmd->sym = cast<Defined>(sym);
208 replaceSymbol<Defined>(Sym, nullptr, Cmd->Name, STB_GLOBAL, Visibility,209 cmd->provide = false;
209 STT_NOTYPE, 0, 0, nullptr);210 sym->scriptDefined = true;
210 Cmd->Sym = cast<Defined>(Sym);
211 Cmd->Provide = false;
212 Sym->ScriptDefined = true;
213}211}
214212
215// This method is used to handle INSERT AFTER statement. Here we rebuild213// This method is used to handle INSERT AFTER statement. Here we rebuild
216// the list of script commands to mix sections inserted into.214// the list of script commands to mix sections inserted into.
217void LinkerScript::processInsertCommands() {215void LinkerScript::processInsertCommands() {
218 std::vector<BaseCommand *> V;216 std::vector<BaseCommand *> v;
219 auto Insert = [&](std::vector<BaseCommand *> &From) {217 auto insert = [&](std::vector<BaseCommand *> &from) {
220 V.insert(V.end(), From.begin(), From.end());218 v.insert(v.end(), from.begin(), from.end());
221 From.clear();219 from.clear();
222 };220 };
223221
224 for (BaseCommand *Base : SectionCommands) {222 for (BaseCommand *base : sectionCommands) {
225 if (auto *OS = dyn_cast<OutputSection>(Base)) {223 if (auto *os = dyn_cast<OutputSection>(base)) {
226 Insert(InsertBeforeCommands[OS->Name]);224 insert(insertBeforeCommands[os->name]);
227 V.push_back(Base);225 v.push_back(base);
228 Insert(InsertAfterCommands[OS->Name]);226 insert(insertAfterCommands[os->name]);
229 continue;227 continue;
230 }228 }
231 V.push_back(Base);229 v.push_back(base);
232 }230 }
233231
234 for (auto &Cmds : {InsertBeforeCommands, InsertAfterCommands})232 for (auto &cmds : {insertBeforeCommands, insertAfterCommands})
235 for (const std::pair<StringRef, std::vector<BaseCommand *>> &P : Cmds)233 for (const std::pair<StringRef, std::vector<BaseCommand *>> &p : cmds)
236 if (!P.second.empty())234 if (!p.second.empty())
237 error("unable to INSERT AFTER/BEFORE " + P.first +235 error("unable to INSERT AFTER/BEFORE " + p.first +
238 ": section not defined");236 ": section not defined");
239237
240 SectionCommands = std::move(V);238 sectionCommands = std::move(v);
241}239}
242240
243// Symbols defined in script should not be inlined by LTO. At the same time241// Symbols defined in script should not be inlined by LTO. At the same time
244// we don't know their final values until late stages of link. Here we scan242// we don't know their final values until late stages of link. Here we scan
245// over symbol assignment commands and create placeholder symbols if needed.243// over symbol assignment commands and create placeholder symbols if needed.
246void LinkerScript::declareSymbols() {244void LinkerScript::declareSymbols() {
247 assert(!Ctx);245 assert(!ctx);
248 for (BaseCommand *Base : SectionCommands) {246 for (BaseCommand *base : sectionCommands) {
249 if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {247 if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
250 declareSymbol(Cmd);248 declareSymbol(cmd);
251 continue;249 continue;
252 }250 }
253251
...@@ -255,75 +253,75 @@ void LinkerScript::declareSymbols() {...@@ -255,75 +253,75 @@ void LinkerScript::declareSymbols() {
255 // we can't say for sure if it is going to be included or not.253 // we can't say for sure if it is going to be included or not.
256 // Skip such sections for now. Improve the checks if we ever254 // Skip such sections for now. Improve the checks if we ever
257 // need symbols from that sections to be declared early.255 // need symbols from that sections to be declared early.
258 auto *Sec = cast<OutputSection>(Base);256 auto *sec = cast<OutputSection>(base);
259 if (Sec->Constraint != ConstraintKind::NoConstraint)257 if (sec->constraint != ConstraintKind::NoConstraint)
260 continue;258 continue;
261 for (BaseCommand *Base2 : Sec->SectionCommands)259 for (BaseCommand *base2 : sec->sectionCommands)
262 if (auto *Cmd = dyn_cast<SymbolAssignment>(Base2))260 if (auto *cmd = dyn_cast<SymbolAssignment>(base2))
263 declareSymbol(Cmd);261 declareSymbol(cmd);
264 }262 }
265}263}
266264
267// This function is called from assignAddresses, while we are265// This function is called from assignAddresses, while we are
268// fixing the output section addresses. This function is supposed266// fixing the output section addresses. This function is supposed
269// to set the final value for a given symbol assignment.267// to set the final value for a given symbol assignment.
270void LinkerScript::assignSymbol(SymbolAssignment *Cmd, bool InSec) {268void LinkerScript::assignSymbol(SymbolAssignment *cmd, bool inSec) {
271 if (Cmd->Name == ".") {269 if (cmd->name == ".") {
272 setDot(Cmd->Expression, Cmd->Location, InSec);270 setDot(cmd->expression, cmd->location, inSec);
273 return;271 return;
274 }272 }
275273
276 if (!Cmd->Sym)274 if (!cmd->sym)
277 return;275 return;
278276
279 ExprValue V = Cmd->Expression();277 ExprValue v = cmd->expression();
280 if (V.isAbsolute()) {278 if (v.isAbsolute()) {
281 Cmd->Sym->Section = nullptr;279 cmd->sym->section = nullptr;
282 Cmd->Sym->Value = V.getValue();280 cmd->sym->value = v.getValue();
283 } else {281 } else {
284 Cmd->Sym->Section = V.Sec;282 cmd->sym->section = v.sec;
285 Cmd->Sym->Value = V.getSectionOffset();283 cmd->sym->value = v.getSectionOffset();
286 }284 }
287}285}
288286
289static std::string getFilename(InputFile *File) {287static std::string getFilename(InputFile *file) {
290 if (!File)288 if (!file)
291 return "";289 return "";
292 if (File->ArchiveName.empty())290 if (file->archiveName.empty())
293 return File->getName();291 return file->getName();
294 return (File->ArchiveName + "(" + File->getName() + ")").str();292 return (file->archiveName + "(" + file->getName() + ")").str();
295}293}
296294
297bool LinkerScript::shouldKeep(InputSectionBase *S) {295bool LinkerScript::shouldKeep(InputSectionBase *s) {
298 if (KeptSections.empty())296 if (keptSections.empty())
299 return false;297 return false;
300 std::string Filename = getFilename(S->File);298 std::string filename = getFilename(s->file);
301 for (InputSectionDescription *ID : KeptSections)299 for (InputSectionDescription *id : keptSections)
302 if (ID->FilePat.match(Filename))300 if (id->filePat.match(filename))
303 for (SectionPattern &P : ID->SectionPatterns)301 for (SectionPattern &p : id->sectionPatterns)
304 if (P.SectionPat.match(S->Name))302 if (p.sectionPat.match(s->name))
305 return true;303 return true;
306 return false;304 return false;
307}305}
308306
309// A helper function for the SORT() command.307// A helper function for the SORT() command.
310static std::function<bool(InputSectionBase *, InputSectionBase *)>308static std::function<bool(InputSectionBase *, InputSectionBase *)>
311getComparator(SortSectionPolicy K) {309getComparator(SortSectionPolicy k) {
312 switch (K) {310 switch (k) {
313 case SortSectionPolicy::Alignment:311 case SortSectionPolicy::Alignment:
314 return [](InputSectionBase *A, InputSectionBase *B) {312 return [](InputSectionBase *a, InputSectionBase *b) {
315 // ">" is not a mistake. Sections with larger alignments are placed313 // ">" is not a mistake. Sections with larger alignments are placed
316 // before sections with smaller alignments in order to reduce the314 // before sections with smaller alignments in order to reduce the
317 // amount of padding necessary. This is compatible with GNU.315 // amount of padding necessary. This is compatible with GNU.
318 return A->Alignment > B->Alignment;316 return a->alignment > b->alignment;
319 };317 };
320 case SortSectionPolicy::Name:318 case SortSectionPolicy::Name:
321 return [](InputSectionBase *A, InputSectionBase *B) {319 return [](InputSectionBase *a, InputSectionBase *b) {
322 return A->Name < B->Name;320 return a->name < b->name;
323 };321 };
324 case SortSectionPolicy::Priority:322 case SortSectionPolicy::Priority:
325 return [](InputSectionBase *A, InputSectionBase *B) {323 return [](InputSectionBase *a, InputSectionBase *b) {
326 return getPriority(A->Name) < getPriority(B->Name);324 return getPriority(a->name) < getPriority(b->name);
327 };325 };
328 default:326 default:
329 llvm_unreachable("unknown sort policy");327 llvm_unreachable("unknown sort policy");
...@@ -331,22 +329,22 @@ getComparator(SortSectionPolicy K) {...@@ -331,22 +329,22 @@ getComparator(SortSectionPolicy K) {
331}329}
332330
333// A helper function for the SORT() command.331// A helper function for the SORT() command.
334static bool matchConstraints(ArrayRef<InputSection *> Sections,332static bool matchConstraints(ArrayRef<InputSection *> sections,
335 ConstraintKind Kind) {333 ConstraintKind kind) {
336 if (Kind == ConstraintKind::NoConstraint)334 if (kind == ConstraintKind::NoConstraint)
337 return true;335 return true;
338336
339 bool IsRW = llvm::any_of(337 bool isRW = llvm::any_of(
340 Sections, [](InputSection *Sec) { return Sec->Flags & SHF_WRITE; });338 sections, [](InputSection *sec) { return sec->flags & SHF_WRITE; });
341339
342 return (IsRW && Kind == ConstraintKind::ReadWrite) ||340 return (isRW && kind == ConstraintKind::ReadWrite) ||
343 (!IsRW && Kind == ConstraintKind::ReadOnly);341 (!isRW && kind == ConstraintKind::ReadOnly);
344}342}
345343
346static void sortSections(MutableArrayRef<InputSection *> Vec,344static void sortSections(MutableArrayRef<InputSection *> vec,
347 SortSectionPolicy K) {345 SortSectionPolicy k) {
348 if (K != SortSectionPolicy::Default && K != SortSectionPolicy::None)346 if (k != SortSectionPolicy::Default && k != SortSectionPolicy::None)
349 std::stable_sort(Vec.begin(), Vec.end(), getComparator(K));347 llvm::stable_sort(vec, getComparator(k));
350}348}
351349
352// Sort sections as instructed by SORT-family commands and --sort-section350// Sort sections as instructed by SORT-family commands and --sort-section
...@@ -360,29 +358,29 @@ static void sortSections(MutableArrayRef<InputSection *> Vec,...@@ -360,29 +358,29 @@ static void sortSections(MutableArrayRef<InputSection *> Vec,
360// --sort-section is handled as an inner SORT command.358// --sort-section is handled as an inner SORT command.
361// 3. If one SORT command is given, and if it is SORT_NONE, don't sort.359// 3. If one SORT command is given, and if it is SORT_NONE, don't sort.
362// 4. If no SORT command is given, sort according to --sort-section.360// 4. If no SORT command is given, sort according to --sort-section.
363static void sortInputSections(MutableArrayRef<InputSection *> Vec,361static void sortInputSections(MutableArrayRef<InputSection *> vec,
364 const SectionPattern &Pat) {362 const SectionPattern &pat) {
365 if (Pat.SortOuter == SortSectionPolicy::None)363 if (pat.sortOuter == SortSectionPolicy::None)
366 return;364 return;
367365
368 if (Pat.SortInner == SortSectionPolicy::Default)366 if (pat.sortInner == SortSectionPolicy::Default)
369 sortSections(Vec, Config->SortSection);367 sortSections(vec, config->sortSection);
370 else368 else
371 sortSections(Vec, Pat.SortInner);369 sortSections(vec, pat.sortInner);
372 sortSections(Vec, Pat.SortOuter);370 sortSections(vec, pat.sortOuter);
373}371}
374372
375// Compute and remember which sections the InputSectionDescription matches.373// Compute and remember which sections the InputSectionDescription matches.
376std::vector<InputSection *>374std::vector<InputSection *>
377LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {375LinkerScript::computeInputSections(const InputSectionDescription *cmd) {
378 std::vector<InputSection *> Ret;376 std::vector<InputSection *> ret;
379377
380 // Collects all sections that satisfy constraints of Cmd.378 // Collects all sections that satisfy constraints of Cmd.
381 for (const SectionPattern &Pat : Cmd->SectionPatterns) {379 for (const SectionPattern &pat : cmd->sectionPatterns) {
382 size_t SizeBefore = Ret.size();380 size_t sizeBefore = ret.size();
383381
384 for (InputSectionBase *Sec : InputSections) {382 for (InputSectionBase *sec : inputSections) {
385 if (!Sec->Live || Sec->Assigned)383 if (!sec->isLive() || sec->assigned)
386 continue;384 continue;
387385
388 // For -emit-relocs we have to ignore entries like386 // For -emit-relocs we have to ignore entries like
...@@ -390,59 +388,59 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {...@@ -390,59 +388,59 @@ LinkerScript::computeInputSections(const InputSectionDescription *Cmd) {
390 // which are common because they are in the default bfd script.388 // which are common because they are in the default bfd script.
391 // We do not ignore SHT_REL[A] linker-synthesized sections here because389 // We do not ignore SHT_REL[A] linker-synthesized sections here because
392 // want to support scripts that do custom layout for them.390 // want to support scripts that do custom layout for them.
393 if (auto *IS = dyn_cast<InputSection>(Sec))391 if (auto *isec = dyn_cast<InputSection>(sec))
394 if (IS->getRelocatedSection())392 if (isec->getRelocatedSection())
395 continue;393 continue;
396394
397 std::string Filename = getFilename(Sec->File);395 std::string filename = getFilename(sec->file);
398 if (!Cmd->FilePat.match(Filename) ||396 if (!cmd->filePat.match(filename) ||
399 Pat.ExcludedFilePat.match(Filename) ||397 pat.excludedFilePat.match(filename) ||
400 !Pat.SectionPat.match(Sec->Name))398 !pat.sectionPat.match(sec->name))
401 continue;399 continue;
402400
403 // It is safe to assume that Sec is an InputSection401 // It is safe to assume that Sec is an InputSection
404 // because mergeable or EH input sections have already been402 // because mergeable or EH input sections have already been
405 // handled and eliminated.403 // handled and eliminated.
406 Ret.push_back(cast<InputSection>(Sec));404 ret.push_back(cast<InputSection>(sec));
407 Sec->Assigned = true;405 sec->assigned = true;
408 }406 }
409407
410 sortInputSections(MutableArrayRef<InputSection *>(Ret).slice(SizeBefore),408 sortInputSections(MutableArrayRef<InputSection *>(ret).slice(sizeBefore),
411 Pat);409 pat);
412 }410 }
413 return Ret;411 return ret;
414}412}
415413
416void LinkerScript::discard(ArrayRef<InputSection *> V) {414void LinkerScript::discard(ArrayRef<InputSection *> v) {
417 for (InputSection *S : V) {415 for (InputSection *s : v) {
418 if (S == In.ShStrTab || S == In.RelaDyn || S == In.RelrDyn)416 if (s == in.shStrTab || s == mainPart->relaDyn || s == mainPart->relrDyn)
419 error("discarding " + S->Name + " section is not allowed");417 error("discarding " + s->name + " section is not allowed");
420418
421 // You can discard .hash and .gnu.hash sections by linker scripts. Since419 // You can discard .hash and .gnu.hash sections by linker scripts. Since
422 // they are synthesized sections, we need to handle them differently than420 // they are synthesized sections, we need to handle them differently than
423 // other regular sections.421 // other regular sections.
424 if (S == In.GnuHashTab)422 if (s == mainPart->gnuHashTab)
425 In.GnuHashTab = nullptr;423 mainPart->gnuHashTab = nullptr;
426 if (S == In.HashTab)424 if (s == mainPart->hashTab)
427 In.HashTab = nullptr;425 mainPart->hashTab = nullptr;
428426
429 S->Assigned = false;427 s->assigned = false;
430 S->Live = false;428 s->markDead();
431 discard(S->DependentSections);429 discard(s->dependentSections);
432 }430 }
433}431}
434432
435std::vector<InputSection *>433std::vector<InputSection *>
436LinkerScript::createInputSectionList(OutputSection &OutCmd) {434LinkerScript::createInputSectionList(OutputSection &outCmd) {
437 std::vector<InputSection *> Ret;435 std::vector<InputSection *> ret;
438436
439 for (BaseCommand *Base : OutCmd.SectionCommands) {437 for (BaseCommand *base : outCmd.sectionCommands) {
440 if (auto *Cmd = dyn_cast<InputSectionDescription>(Base)) {438 if (auto *cmd = dyn_cast<InputSectionDescription>(base)) {
441 Cmd->Sections = computeInputSections(Cmd);439 cmd->sections = computeInputSections(cmd);
442 Ret.insert(Ret.end(), Cmd->Sections.begin(), Cmd->Sections.end());440 ret.insert(ret.end(), cmd->sections.begin(), cmd->sections.end());
443 }441 }
444 }442 }
445 return Ret;443 return ret;
446}444}
447445
448void LinkerScript::processSectionCommands() {446void LinkerScript::processSectionCommands() {
...@@ -455,34 +453,34 @@ void LinkerScript::processSectionCommands() {...@@ -455,34 +453,34 @@ void LinkerScript::processSectionCommands() {
455 // To handle that, create a dummy aether section that fills the void before453 // To handle that, create a dummy aether section that fills the void before
456 // the linker scripts switches to another section. It has an index of one454 // the linker scripts switches to another section. It has an index of one
457 // which will map to whatever the first actual section is.455 // which will map to whatever the first actual section is.
458 Aether = make<OutputSection>("", 0, SHF_ALLOC);456 aether = make<OutputSection>("", 0, SHF_ALLOC);
459 Aether->SectionIndex = 1;457 aether->sectionIndex = 1;
460458
461 // Ctx captures the local AddressState and makes it accessible deliberately.459 // Ctx captures the local AddressState and makes it accessible deliberately.
462 // This is needed as there are some cases where we cannot just460 // This is needed as there are some cases where we cannot just
463 // thread the current state through to a lambda function created by the461 // thread the current state through to a lambda function created by the
464 // script parser.462 // script parser.
465 auto Deleter = make_unique<AddressState>();463 auto deleter = make_unique<AddressState>();
466 Ctx = Deleter.get();464 ctx = deleter.get();
467 Ctx->OutSec = Aether;465 ctx->outSec = aether;
468466
469 size_t I = 0;467 size_t i = 0;
470 // Add input sections to output sections.468 // Add input sections to output sections.
471 for (BaseCommand *Base : SectionCommands) {469 for (BaseCommand *base : sectionCommands) {
472 // Handle symbol assignments outside of any output section.470 // Handle symbol assignments outside of any output section.
473 if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {471 if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
474 addSymbol(Cmd);472 addSymbol(cmd);
475 continue;473 continue;
476 }474 }
477475
478 if (auto *Sec = dyn_cast<OutputSection>(Base)) {476 if (auto *sec = dyn_cast<OutputSection>(base)) {
479 std::vector<InputSection *> V = createInputSectionList(*Sec);477 std::vector<InputSection *> v = createInputSectionList(*sec);
480478
481 // The output section name `/DISCARD/' is special.479 // The output section name `/DISCARD/' is special.
482 // Any input section assigned to it is discarded.480 // Any input section assigned to it is discarded.
483 if (Sec->Name == "/DISCARD/") {481 if (sec->name == "/DISCARD/") {
484 discard(V);482 discard(v);
485 Sec->SectionCommands.clear();483 sec->sectionCommands.clear();
486 continue;484 continue;
487 }485 }
488486
...@@ -493,60 +491,61 @@ void LinkerScript::processSectionCommands() {...@@ -493,60 +491,61 @@ void LinkerScript::processSectionCommands() {
493 //491 //
494 // Because we'll iterate over SectionCommands many more times, the easy492 // Because we'll iterate over SectionCommands many more times, the easy
495 // way to "make it as if it wasn't present" is to make it empty.493 // way to "make it as if it wasn't present" is to make it empty.
496 if (!matchConstraints(V, Sec->Constraint)) {494 if (!matchConstraints(v, sec->constraint)) {
497 for (InputSectionBase *S : V)495 for (InputSectionBase *s : v)
498 S->Assigned = false;496 s->assigned = false;
499 Sec->SectionCommands.clear();497 sec->sectionCommands.clear();
500 continue;498 continue;
501 }499 }
502500
503 // A directive may contain symbol definitions like this:501 // A directive may contain symbol definitions like this:
504 // ".foo : { ...; bar = .; }". Handle them.502 // ".foo : { ...; bar = .; }". Handle them.
505 for (BaseCommand *Base : Sec->SectionCommands)503 for (BaseCommand *base : sec->sectionCommands)
506 if (auto *OutCmd = dyn_cast<SymbolAssignment>(Base))504 if (auto *outCmd = dyn_cast<SymbolAssignment>(base))
507 addSymbol(OutCmd);505 addSymbol(outCmd);
508506
509 // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign507 // Handle subalign (e.g. ".foo : SUBALIGN(32) { ... }"). If subalign
510 // is given, input sections are aligned to that value, whether the508 // is given, input sections are aligned to that value, whether the
511 // given value is larger or smaller than the original section alignment.509 // given value is larger or smaller than the original section alignment.
512 if (Sec->SubalignExpr) {510 if (sec->subalignExpr) {
513 uint32_t Subalign = Sec->SubalignExpr().getValue();511 uint32_t subalign = sec->subalignExpr().getValue();
514 for (InputSectionBase *S : V)512 for (InputSectionBase *s : v)
515 S->Alignment = Subalign;513 s->alignment = subalign;
516 }514 }
517515
518 // Add input sections to an output section.516 // Add input sections to an output section.
519 for (InputSection *S : V)517 for (InputSection *s : v)
520 Sec->addSection(S);518 sec->addSection(s);
521519
522 Sec->SectionIndex = I++;520 sec->sectionIndex = i++;
523 if (Sec->Noload)521 if (sec->noload)
524 Sec->Type = SHT_NOBITS;522 sec->type = SHT_NOBITS;
525 if (Sec->NonAlloc)523 if (sec->nonAlloc)
526 Sec->Flags &= ~(uint64_t)SHF_ALLOC;524 sec->flags &= ~(uint64_t)SHF_ALLOC;
527 }525 }
528 }526 }
529 Ctx = nullptr;527 ctx = nullptr;
530}528}
531529
532static OutputSection *findByName(ArrayRef<BaseCommand *> Vec,530static OutputSection *findByName(ArrayRef<BaseCommand *> vec,
533 StringRef Name) {531 StringRef name) {
534 for (BaseCommand *Base : Vec)532 for (BaseCommand *base : vec)
535 if (auto *Sec = dyn_cast<OutputSection>(Base))533 if (auto *sec = dyn_cast<OutputSection>(base))
536 if (Sec->Name == Name)534 if (sec->name == name)
537 return Sec;535 return sec;
538 return nullptr;536 return nullptr;
539}537}
540538
541static OutputSection *createSection(InputSectionBase *IS,539static OutputSection *createSection(InputSectionBase *isec,
542 StringRef OutsecName) {540 StringRef outsecName) {
543 OutputSection *Sec = Script->createOutputSection(OutsecName, "<internal>");541 OutputSection *sec = script->createOutputSection(outsecName, "<internal>");
544 Sec->addSection(cast<InputSection>(IS));542 sec->addSection(cast<InputSection>(isec));
545 return Sec;543 return sec;
546}544}
547545
548static OutputSection *addInputSec(StringMap<OutputSection *> &Map,546static OutputSection *
549 InputSectionBase *IS, StringRef OutsecName) {547addInputSec(StringMap<TinyPtrVector<OutputSection *>> &map,
548 InputSectionBase *isec, StringRef outsecName) {
550 // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r549 // Sections with SHT_GROUP or SHF_GROUP attributes reach here only when the -r
551 // option is given. A section with SHT_GROUP defines a "section group", and550 // option is given. A section with SHT_GROUP defines a "section group", and
552 // its members have SHF_GROUP attribute. Usually these flags have already been551 // its members have SHF_GROUP attribute. Usually these flags have already been
...@@ -554,8 +553,8 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,...@@ -554,8 +553,8 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,
554 // However, for the -r option, we want to pass through all section groups553 // However, for the -r option, we want to pass through all section groups
555 // as-is because adding/removing members or merging them with other groups554 // as-is because adding/removing members or merging them with other groups
556 // change their semantics.555 // change their semantics.
557 if (IS->Type == SHT_GROUP || (IS->Flags & SHF_GROUP))556 if (isec->type == SHT_GROUP || (isec->flags & SHF_GROUP))
558 return createSection(IS, OutsecName);557 return createSection(isec, outsecName);
559558
560 // Imagine .zed : { *(.foo) *(.bar) } script. Both foo and bar may have559 // Imagine .zed : { *(.foo) *(.bar) } script. Both foo and bar may have
561 // relocation sections .rela.foo and .rela.bar for example. Most tools do560 // relocation sections .rela.foo and .rela.bar for example. Most tools do
...@@ -563,25 +562,25 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,...@@ -563,25 +562,25 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,
563 // should combine these relocation sections into single output.562 // should combine these relocation sections into single output.
564 // We skip synthetic sections because it can be .rela.dyn/.rela.plt or any563 // We skip synthetic sections because it can be .rela.dyn/.rela.plt or any
565 // other REL[A] sections created by linker itself.564 // other REL[A] sections created by linker itself.
566 if (!isa<SyntheticSection>(IS) &&565 if (!isa<SyntheticSection>(isec) &&
567 (IS->Type == SHT_REL || IS->Type == SHT_RELA)) {566 (isec->type == SHT_REL || isec->type == SHT_RELA)) {
568 auto *Sec = cast<InputSection>(IS);567 auto *sec = cast<InputSection>(isec);
569 OutputSection *Out = Sec->getRelocatedSection()->getOutputSection();568 OutputSection *out = sec->getRelocatedSection()->getOutputSection();
570569
571 if (Out->RelocationSection) {570 if (out->relocationSection) {
572 Out->RelocationSection->addSection(Sec);571 out->relocationSection->addSection(sec);
573 return nullptr;572 return nullptr;
574 }573 }
575574
576 Out->RelocationSection = createSection(IS, OutsecName);575 out->relocationSection = createSection(isec, outsecName);
577 return Out->RelocationSection;576 return out->relocationSection;
578 }577 }
579578
580 // When control reaches here, mergeable sections have already been merged into579 // When control reaches here, mergeable sections have already been merged into
581 // synthetic sections. For relocatable case we want to create one output580 // synthetic sections. For relocatable case we want to create one output
582 // section per syntetic section so that they have a valid sh_entsize.581 // section per syntetic section so that they have a valid sh_entsize.
583 if (Config->Relocatable && (IS->Flags & SHF_MERGE))582 if (config->relocatable && (isec->flags & SHF_MERGE))
584 return createSection(IS, OutsecName);583 return createSection(isec, outsecName);
585584
586 // The ELF spec just says585 // The ELF spec just says
587 // ----------------------------------------------------------------586 // ----------------------------------------------------------------
...@@ -625,159 +624,161 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,...@@ -625,159 +624,161 @@ static OutputSection *addInputSec(StringMap<OutputSection *> &Map,
625 //624 //
626 // Given the above issues, we instead merge sections by name and error on625 // Given the above issues, we instead merge sections by name and error on
627 // incompatible types and flags.626 // incompatible types and flags.
628 OutputSection *&Sec = Map[OutsecName];627 TinyPtrVector<OutputSection *> &v = map[outsecName];
629 if (Sec) {628 for (OutputSection *sec : v) {
630 Sec->addSection(cast<InputSection>(IS));629 if (sec->partition != isec->partition)
630 continue;
631 sec->addSection(cast<InputSection>(isec));
631 return nullptr;632 return nullptr;
632 }633 }
633634
634 Sec = createSection(IS, OutsecName);635 OutputSection *sec = createSection(isec, outsecName);
635 return Sec;636 v.push_back(sec);
637 return sec;
636}638}
637639
638// Add sections that didn't match any sections command.640// Add sections that didn't match any sections command.
639void LinkerScript::addOrphanSections() {641void LinkerScript::addOrphanSections() {
640 unsigned End = SectionCommands.size();642 StringMap<TinyPtrVector<OutputSection *>> map;
641 StringMap<OutputSection *> Map;643 std::vector<OutputSection *> v;
642 std::vector<OutputSection *> V;
643644
644 auto Add = [&](InputSectionBase *S) {645 auto add = [&](InputSectionBase *s) {
645 if (!S->Live || S->Parent)646 if (!s->isLive() || s->parent)
646 return;647 return;
647648
648 StringRef Name = getOutputSectionName(S);649 StringRef name = getOutputSectionName(s);
649650
650 if (Config->OrphanHandling == OrphanHandlingPolicy::Error)651 if (config->orphanHandling == OrphanHandlingPolicy::Error)
651 error(toString(S) + " is being placed in '" + Name + "'");652 error(toString(s) + " is being placed in '" + name + "'");
652 else if (Config->OrphanHandling == OrphanHandlingPolicy::Warn)653 else if (config->orphanHandling == OrphanHandlingPolicy::Warn)
653 warn(toString(S) + " is being placed in '" + Name + "'");654 warn(toString(s) + " is being placed in '" + name + "'");
654655
655 if (OutputSection *Sec =656 if (OutputSection *sec = findByName(sectionCommands, name)) {
656 findByName(makeArrayRef(SectionCommands).slice(0, End), Name)) {657 sec->addSection(cast<InputSection>(s));
657 Sec->addSection(cast<InputSection>(S));
658 return;658 return;
659 }659 }
660660
661 if (OutputSection *OS = addInputSec(Map, S, Name))661 if (OutputSection *os = addInputSec(map, s, name))
662 V.push_back(OS);662 v.push_back(os);
663 assert(S->getOutputSection()->SectionIndex == UINT32_MAX);663 assert(s->getOutputSection()->sectionIndex == UINT32_MAX);
664 };664 };
665665
666 // For futher --emit-reloc handling code we need target output section666 // For futher --emit-reloc handling code we need target output section
667 // to be created before we create relocation output section, so we want667 // to be created before we create relocation output section, so we want
668 // to create target sections first. We do not want priority handling668 // to create target sections first. We do not want priority handling
669 // for synthetic sections because them are special.669 // for synthetic sections because them are special.
670 for (InputSectionBase *IS : InputSections) {670 for (InputSectionBase *isec : inputSections) {
671 if (auto *Sec = dyn_cast<InputSection>(IS))671 if (auto *sec = dyn_cast<InputSection>(isec))
672 if (InputSectionBase *Rel = Sec->getRelocatedSection())672 if (InputSectionBase *rel = sec->getRelocatedSection())
673 if (auto *RelIS = dyn_cast_or_null<InputSectionBase>(Rel->Parent))673 if (auto *relIS = dyn_cast_or_null<InputSectionBase>(rel->parent))
674 Add(RelIS);674 add(relIS);
675 Add(IS);675 add(isec);
676 }676 }
677677
678 // If no SECTIONS command was given, we should insert sections commands678 // If no SECTIONS command was given, we should insert sections commands
679 // before others, so that we can handle scripts which refers them,679 // before others, so that we can handle scripts which refers them,
680 // for example: "foo = ABSOLUTE(ADDR(.text)));".680 // for example: "foo = ABSOLUTE(ADDR(.text)));".
681 // When SECTIONS command is present we just add all orphans to the end.681 // When SECTIONS command is present we just add all orphans to the end.
682 if (HasSectionsCommand)682 if (hasSectionsCommand)
683 SectionCommands.insert(SectionCommands.end(), V.begin(), V.end());683 sectionCommands.insert(sectionCommands.end(), v.begin(), v.end());
684 else684 else
685 SectionCommands.insert(SectionCommands.begin(), V.begin(), V.end());685 sectionCommands.insert(sectionCommands.begin(), v.begin(), v.end());
686}686}
687687
688uint64_t LinkerScript::advance(uint64_t Size, unsigned Alignment) {688uint64_t LinkerScript::advance(uint64_t size, unsigned alignment) {
689 bool IsTbss =689 bool isTbss =
690 (Ctx->OutSec->Flags & SHF_TLS) && Ctx->OutSec->Type == SHT_NOBITS;690 (ctx->outSec->flags & SHF_TLS) && ctx->outSec->type == SHT_NOBITS;
691 uint64_t Start = IsTbss ? Dot + Ctx->ThreadBssOffset : Dot;691 uint64_t start = isTbss ? dot + ctx->threadBssOffset : dot;
692 Start = alignTo(Start, Alignment);692 start = alignTo(start, alignment);
693 uint64_t End = Start + Size;693 uint64_t end = start + size;
694694
695 if (IsTbss)695 if (isTbss)
696 Ctx->ThreadBssOffset = End - Dot;696 ctx->threadBssOffset = end - dot;
697 else697 else
698 Dot = End;698 dot = end;
699 return End;699 return end;
700}700}
701701
702void LinkerScript::output(InputSection *S) {702void LinkerScript::output(InputSection *s) {
703 assert(Ctx->OutSec == S->getParent());703 assert(ctx->outSec == s->getParent());
704 uint64_t Before = advance(0, 1);704 uint64_t before = advance(0, 1);
705 uint64_t Pos = advance(S->getSize(), S->Alignment);705 uint64_t pos = advance(s->getSize(), s->alignment);
706 S->OutSecOff = Pos - S->getSize() - Ctx->OutSec->Addr;706 s->outSecOff = pos - s->getSize() - ctx->outSec->addr;
707707
708 // Update output section size after adding each section. This is so that708 // Update output section size after adding each section. This is so that
709 // SIZEOF works correctly in the case below:709 // SIZEOF works correctly in the case below:
710 // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }710 // .foo { *(.aaa) a = SIZEOF(.foo); *(.bbb) }
711 expandOutputSection(Pos - Before);711 expandOutputSection(pos - before);
712}712}
713713
714void LinkerScript::switchTo(OutputSection *Sec) {714void LinkerScript::switchTo(OutputSection *sec) {
715 Ctx->OutSec = Sec;715 ctx->outSec = sec;
716716
717 uint64_t Before = advance(0, 1);717 uint64_t before = advance(0, 1);
718 Ctx->OutSec->Addr = advance(0, Ctx->OutSec->Alignment);718 ctx->outSec->addr = advance(0, ctx->outSec->alignment);
719 expandMemoryRegions(Ctx->OutSec->Addr - Before);719 expandMemoryRegions(ctx->outSec->addr - before);
720}720}
721721
722// This function searches for a memory region to place the given output722// This function searches for a memory region to place the given output
723// section in. If found, a pointer to the appropriate memory region is723// section in. If found, a pointer to the appropriate memory region is
724// returned. Otherwise, a nullptr is returned.724// returned. Otherwise, a nullptr is returned.
725MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *Sec) {725MemoryRegion *LinkerScript::findMemoryRegion(OutputSection *sec) {
726 // If a memory region name was specified in the output section command,726 // If a memory region name was specified in the output section command,
727 // then try to find that region first.727 // then try to find that region first.
728 if (!Sec->MemoryRegionName.empty()) {728 if (!sec->memoryRegionName.empty()) {
729 if (MemoryRegion *M = MemoryRegions.lookup(Sec->MemoryRegionName))729 if (MemoryRegion *m = memoryRegions.lookup(sec->memoryRegionName))
730 return M;730 return m;
731 error("memory region '" + Sec->MemoryRegionName + "' not declared");731 error("memory region '" + sec->memoryRegionName + "' not declared");
732 return nullptr;732 return nullptr;
733 }733 }
734734
735 // If at least one memory region is defined, all sections must735 // If at least one memory region is defined, all sections must
736 // belong to some memory region. Otherwise, we don't need to do736 // belong to some memory region. Otherwise, we don't need to do
737 // anything for memory regions.737 // anything for memory regions.
738 if (MemoryRegions.empty())738 if (memoryRegions.empty())
739 return nullptr;739 return nullptr;
740740
741 // See if a region can be found by matching section flags.741 // See if a region can be found by matching section flags.
742 for (auto &Pair : MemoryRegions) {742 for (auto &pair : memoryRegions) {
743 MemoryRegion *M = Pair.second;743 MemoryRegion *m = pair.second;
744 if ((M->Flags & Sec->Flags) && (M->NegFlags & Sec->Flags) == 0)744 if ((m->flags & sec->flags) && (m->negFlags & sec->flags) == 0)
745 return M;745 return m;
746 }746 }
747747
748 // Otherwise, no suitable region was found.748 // Otherwise, no suitable region was found.
749 if (Sec->Flags & SHF_ALLOC)749 if (sec->flags & SHF_ALLOC)
750 error("no memory region specified for section '" + Sec->Name + "'");750 error("no memory region specified for section '" + sec->name + "'");
751 return nullptr;751 return nullptr;
752}752}
753753
754static OutputSection *findFirstSection(PhdrEntry *Load) {754static OutputSection *findFirstSection(PhdrEntry *load) {
755 for (OutputSection *Sec : OutputSections)755 for (OutputSection *sec : outputSections)
756 if (Sec->PtLoad == Load)756 if (sec->ptLoad == load)
757 return Sec;757 return sec;
758 return nullptr;758 return nullptr;
759}759}
760760
761// This function assigns offsets to input sections and an output section761// This function assigns offsets to input sections and an output section
762// for a single sections command (e.g. ".text { *(.text); }").762// for a single sections command (e.g. ".text { *(.text); }").
763void LinkerScript::assignOffsets(OutputSection *Sec) {763void LinkerScript::assignOffsets(OutputSection *sec) {
764 if (!(Sec->Flags & SHF_ALLOC))764 if (!(sec->flags & SHF_ALLOC))
765 Dot = 0;765 dot = 0;
766 else if (Sec->AddrExpr)
767 setDot(Sec->AddrExpr, Sec->Location, false);
768766
769 Ctx->MemRegion = Sec->MemRegion;767 ctx->memRegion = sec->memRegion;
770 Ctx->LMARegion = Sec->LMARegion;768 ctx->lmaRegion = sec->lmaRegion;
771 if (Ctx->MemRegion)769 if (ctx->memRegion)
772 Dot = Ctx->MemRegion->CurPos;770 dot = ctx->memRegion->curPos;
773771
774 switchTo(Sec);772 if ((sec->flags & SHF_ALLOC) && sec->addrExpr)
773 setDot(sec->addrExpr, sec->location, false);
775774
776 if (Sec->LMAExpr)775 switchTo(sec);
777 Ctx->LMAOffset = Sec->LMAExpr().getValue() - Dot;
778776
779 if (MemoryRegion *MR = Sec->LMARegion)777 if (sec->lmaExpr)
780 Ctx->LMAOffset = MR->CurPos - Dot;778 ctx->lmaOffset = sec->lmaExpr().getValue() - dot;
779
780 if (MemoryRegion *mr = sec->lmaRegion)
781 ctx->lmaOffset = mr->curPos - dot;
781782
782 // If neither AT nor AT> is specified for an allocatable section, the linker783 // If neither AT nor AT> is specified for an allocatable section, the linker
783 // will set the LMA such that the difference between VMA and LMA for the784 // will set the LMA such that the difference between VMA and LMA for the
...@@ -785,62 +786,71 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {...@@ -785,62 +786,71 @@ void LinkerScript::assignOffsets(OutputSection *Sec) {
785 // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html786 // https://sourceware.org/binutils/docs-2.20/ld/Output-Section-LMA.html
786 // This, however, should only be done by the first "non-header" section787 // This, however, should only be done by the first "non-header" section
787 // in the segment.788 // in the segment.
788 if (PhdrEntry *L = Ctx->OutSec->PtLoad)789 if (PhdrEntry *l = ctx->outSec->ptLoad)
789 if (Sec == findFirstSection(L))790 if (sec == findFirstSection(l))
790 L->LMAOffset = Ctx->LMAOffset;791 l->lmaOffset = ctx->lmaOffset;
791792
792 // We can call this method multiple times during the creation of793 // We can call this method multiple times during the creation of
793 // thunks and want to start over calculation each time.794 // thunks and want to start over calculation each time.
794 Sec->Size = 0;795 sec->size = 0;
795796
796 // We visited SectionsCommands from processSectionCommands to797 // We visited SectionsCommands from processSectionCommands to
797 // layout sections. Now, we visit SectionsCommands again to fix798 // layout sections. Now, we visit SectionsCommands again to fix
798 // section offsets.799 // section offsets.
799 for (BaseCommand *Base : Sec->SectionCommands) {800 for (BaseCommand *base : sec->sectionCommands) {
800 // This handles the assignments to symbol or to the dot.801 // This handles the assignments to symbol or to the dot.
801 if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {802 if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
802 Cmd->Addr = Dot;803 cmd->addr = dot;
803 assignSymbol(Cmd, true);804 assignSymbol(cmd, true);
804 Cmd->Size = Dot - Cmd->Addr;805 cmd->size = dot - cmd->addr;
805 continue;806 continue;
806 }807 }
807808
808 // Handle BYTE(), SHORT(), LONG(), or QUAD().809 // Handle BYTE(), SHORT(), LONG(), or QUAD().
809 if (auto *Cmd = dyn_cast<ByteCommand>(Base)) {810 if (auto *cmd = dyn_cast<ByteCommand>(base)) {
810 Cmd->Offset = Dot - Ctx->OutSec->Addr;811 cmd->offset = dot - ctx->outSec->addr;
811 Dot += Cmd->Size;812 dot += cmd->size;
812 expandOutputSection(Cmd->Size);813 expandOutputSection(cmd->size);
813 continue;814 continue;
814 }815 }
815816
816 // Handle a single input section description command.817 // Handle a single input section description command.
817 // It calculates and assigns the offsets for each section and also818 // It calculates and assigns the offsets for each section and also
818 // updates the output section size.819 // updates the output section size.
819 for (InputSection *Sec : cast<InputSectionDescription>(Base)->Sections)820 for (InputSection *sec : cast<InputSectionDescription>(base)->sections)
820 output(Sec);821 output(sec);
821 }822 }
822}823}
823824
824static bool isDiscardable(OutputSection &Sec) {825static bool isDiscardable(OutputSection &sec) {
826 if (sec.name == "/DISCARD/")
827 return true;
828
825 // We do not remove empty sections that are explicitly829 // We do not remove empty sections that are explicitly
826 // assigned to any segment.830 // assigned to any segment.
827 if (!Sec.Phdrs.empty())831 if (!sec.phdrs.empty())
828 return false;832 return false;
829833
830 // We do not want to remove sections that reference symbols in address and834 // We do not want to remove OutputSections with expressions that reference
831 // other expressions. We add script symbols as undefined, and want to ensure835 // symbols even if the OutputSection is empty. We want to ensure that the
832 // all of them are defined in the output, hence have to keep them.836 // expressions can be evaluated and report an error if they cannot.
833 if (Sec.ExpressionsUseSymbols)837 if (sec.expressionsUseSymbols)
834 return false;838 return false;
835839
836 for (BaseCommand *Base : Sec.SectionCommands) {840 // OutputSections may be referenced by name in ADDR and LOADADDR expressions,
837 if (auto Cmd = dyn_cast<SymbolAssignment>(Base))841 // as an empty Section can has a valid VMA and LMA we keep the OutputSection
842 // to maintain the integrity of the other Expression.
843 if (sec.usedInExpression)
844 return false;
845
846 for (BaseCommand *base : sec.sectionCommands) {
847 if (auto cmd = dyn_cast<SymbolAssignment>(base))
838 // Don't create empty output sections just for unreferenced PROVIDE848 // Don't create empty output sections just for unreferenced PROVIDE
839 // symbols.849 // symbols.
840 if (Cmd->Name != "." && !Cmd->Sym)850 if (cmd->name != "." && !cmd->sym)
841 continue;851 continue;
842852
843 if (!isa<InputSectionDescription>(*Base))853 if (!isa<InputSectionDescription>(*base))
844 return false;854 return false;
845 }855 }
846 return true;856 return true;
...@@ -867,33 +877,35 @@ void LinkerScript::adjustSectionsBeforeSorting() {...@@ -867,33 +877,35 @@ void LinkerScript::adjustSectionsBeforeSorting() {
867 // The other option is to pick flags that minimize the impact the section877 // The other option is to pick flags that minimize the impact the section
868 // will have on the rest of the linker. That is why we copy the flags from878 // will have on the rest of the linker. That is why we copy the flags from
869 // the previous sections. Only a few flags are needed to keep the impact low.879 // the previous sections. Only a few flags are needed to keep the impact low.
870 uint64_t Flags = SHF_ALLOC;880 uint64_t flags = SHF_ALLOC;
871881
872 for (BaseCommand *&Cmd : SectionCommands) {882 for (BaseCommand *&cmd : sectionCommands) {
873 auto *Sec = dyn_cast<OutputSection>(Cmd);883 auto *sec = dyn_cast<OutputSection>(cmd);
874 if (!Sec)884 if (!sec)
875 continue;885 continue;
876886
877 // Handle align (e.g. ".foo : ALIGN(16) { ... }").887 // Handle align (e.g. ".foo : ALIGN(16) { ... }").
878 if (Sec->AlignExpr)888 if (sec->alignExpr)
879 Sec->Alignment =889 sec->alignment =
880 std::max<uint32_t>(Sec->Alignment, Sec->AlignExpr().getValue());890 std::max<uint32_t>(sec->alignment, sec->alignExpr().getValue());
881891
882 // A live output section means that some input section was added to it. It892 // The input section might have been removed (if it was an empty synthetic
883 // might have been removed (if it was empty synthetic section), but we at893 // section), but we at least know the flags.
884 // least know the flags.894 if (sec->hasInputSections)
885 if (Sec->Live)895 flags = sec->flags;
886 Flags = Sec->Flags;
887896
888 // We do not want to keep any special flags for output section897 // We do not want to keep any special flags for output section
889 // in case it is empty.898 // in case it is empty.
890 bool IsEmpty = getInputSections(Sec).empty();899 bool isEmpty = getInputSections(sec).empty();
891 if (IsEmpty)900 if (isEmpty)
892 Sec->Flags = Flags & (SHF_ALLOC | SHF_WRITE | SHF_EXECINSTR);901 sec->flags = flags & ((sec->nonAlloc ? 0 : (uint64_t)SHF_ALLOC) |
893902 SHF_WRITE | SHF_EXECINSTR);
894 if (IsEmpty && isDiscardable(*Sec)) {903
895 Sec->Live = false;904 if (isEmpty && isDiscardable(*sec)) {
896 Cmd = nullptr;905 sec->markDead();
906 cmd = nullptr;
907 } else if (!sec->isLive()) {
908 sec->markLive();
897 }909 }
898 }910 }
899911
...@@ -903,20 +915,20 @@ void LinkerScript::adjustSectionsBeforeSorting() {...@@ -903,20 +915,20 @@ void LinkerScript::adjustSectionsBeforeSorting() {
903 // clutter the output.915 // clutter the output.
904 // We instead remove trivially empty sections. The bfd linker seems even916 // We instead remove trivially empty sections. The bfd linker seems even
905 // more aggressive at removing them.917 // more aggressive at removing them.
906 llvm::erase_if(SectionCommands, [&](BaseCommand *Base) { return !Base; });918 llvm::erase_if(sectionCommands, [&](BaseCommand *base) { return !base; });
907}919}
908920
909void LinkerScript::adjustSectionsAfterSorting() {921void LinkerScript::adjustSectionsAfterSorting() {
910 // Try and find an appropriate memory region to assign offsets in.922 // Try and find an appropriate memory region to assign offsets in.
911 for (BaseCommand *Base : SectionCommands) {923 for (BaseCommand *base : sectionCommands) {
912 if (auto *Sec = dyn_cast<OutputSection>(Base)) {924 if (auto *sec = dyn_cast<OutputSection>(base)) {
913 if (!Sec->LMARegionName.empty()) {925 if (!sec->lmaRegionName.empty()) {
914 if (MemoryRegion *M = MemoryRegions.lookup(Sec->LMARegionName))926 if (MemoryRegion *m = memoryRegions.lookup(sec->lmaRegionName))
915 Sec->LMARegion = M;927 sec->lmaRegion = m;
916 else928 else
917 error("memory region '" + Sec->LMARegionName + "' not declared");929 error("memory region '" + sec->lmaRegionName + "' not declared");
918 }930 }
919 Sec->MemRegion = findMemoryRegion(Sec);931 sec->memRegion = findMemoryRegion(sec);
920 }932 }
921 }933 }
922934
...@@ -926,38 +938,38 @@ void LinkerScript::adjustSectionsAfterSorting() {...@@ -926,38 +938,38 @@ void LinkerScript::adjustSectionsAfterSorting() {
926 // Below is an example of such linker script:938 // Below is an example of such linker script:
927 // PHDRS { seg PT_LOAD; }939 // PHDRS { seg PT_LOAD; }
928 // SECTIONS { .aaa : { *(.aaa) } }940 // SECTIONS { .aaa : { *(.aaa) } }
929 std::vector<StringRef> DefPhdrs;941 std::vector<StringRef> defPhdrs;
930 auto FirstPtLoad = llvm::find_if(PhdrsCommands, [](const PhdrsCommand &Cmd) {942 auto firstPtLoad = llvm::find_if(phdrsCommands, [](const PhdrsCommand &cmd) {
931 return Cmd.Type == PT_LOAD;943 return cmd.type == PT_LOAD;
932 });944 });
933 if (FirstPtLoad != PhdrsCommands.end())945 if (firstPtLoad != phdrsCommands.end())
934 DefPhdrs.push_back(FirstPtLoad->Name);946 defPhdrs.push_back(firstPtLoad->name);
935947
936 // Walk the commands and propagate the program headers to commands that don't948 // Walk the commands and propagate the program headers to commands that don't
937 // explicitly specify them.949 // explicitly specify them.
938 for (BaseCommand *Base : SectionCommands) {950 for (BaseCommand *base : sectionCommands) {
939 auto *Sec = dyn_cast<OutputSection>(Base);951 auto *sec = dyn_cast<OutputSection>(base);
940 if (!Sec)952 if (!sec)
941 continue;953 continue;
942954
943 if (Sec->Phdrs.empty()) {955 if (sec->phdrs.empty()) {
944 // To match the bfd linker script behaviour, only propagate program956 // To match the bfd linker script behaviour, only propagate program
945 // headers to sections that are allocated.957 // headers to sections that are allocated.
946 if (Sec->Flags & SHF_ALLOC)958 if (sec->flags & SHF_ALLOC)
947 Sec->Phdrs = DefPhdrs;959 sec->phdrs = defPhdrs;
948 } else {960 } else {
949 DefPhdrs = Sec->Phdrs;961 defPhdrs = sec->phdrs;
950 }962 }
951 }963 }
952}964}
953965
954static uint64_t computeBase(uint64_t Min, bool AllocateHeaders) {966static uint64_t computeBase(uint64_t min, bool allocateHeaders) {
955 // If there is no SECTIONS or if the linkerscript is explicit about program967 // If there is no SECTIONS or if the linkerscript is explicit about program
956 // headers, do our best to allocate them.968 // headers, do our best to allocate them.
957 if (!Script->HasSectionsCommand || AllocateHeaders)969 if (!script->hasSectionsCommand || allocateHeaders)
958 return 0;970 return 0;
959 // Otherwise only allocate program headers if that would not add a page.971 // Otherwise only allocate program headers if that would not add a page.
960 return alignDown(Min, Config->MaxPageSize);972 return alignDown(min, config->maxPageSize);
961}973}
962974
963// Try to find an address for the file and program headers output sections,975// Try to find an address for the file and program headers output sections,
...@@ -971,118 +983,120 @@ static uint64_t computeBase(uint64_t Min, bool AllocateHeaders) {...@@ -971,118 +983,120 @@ static uint64_t computeBase(uint64_t Min, bool AllocateHeaders) {
971//983//
972// If there isn't enough space for these sections, we'll remove them from the984// If there isn't enough space for these sections, we'll remove them from the
973// PT_LOAD segment, and we'll also remove the PT_PHDR segment.985// PT_LOAD segment, and we'll also remove the PT_PHDR segment.
974void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &Phdrs) {986void LinkerScript::allocateHeaders(std::vector<PhdrEntry *> &phdrs) {
975 uint64_t Min = std::numeric_limits<uint64_t>::max();987 uint64_t min = std::numeric_limits<uint64_t>::max();
976 for (OutputSection *Sec : OutputSections)988 for (OutputSection *sec : outputSections)
977 if (Sec->Flags & SHF_ALLOC)989 if (sec->flags & SHF_ALLOC)
978 Min = std::min<uint64_t>(Min, Sec->Addr);990 min = std::min<uint64_t>(min, sec->addr);
979991
980 auto It = llvm::find_if(992 auto it = llvm::find_if(
981 Phdrs, [](const PhdrEntry *E) { return E->p_type == PT_LOAD; });993 phdrs, [](const PhdrEntry *e) { return e->p_type == PT_LOAD; });
982 if (It == Phdrs.end())994 if (it == phdrs.end())
983 return;995 return;
984 PhdrEntry *FirstPTLoad = *It;996 PhdrEntry *firstPTLoad = *it;
985997
986 bool HasExplicitHeaders =998 bool hasExplicitHeaders =
987 llvm::any_of(PhdrsCommands, [](const PhdrsCommand &Cmd) {999 llvm::any_of(phdrsCommands, [](const PhdrsCommand &cmd) {
988 return Cmd.HasPhdrs || Cmd.HasFilehdr;1000 return cmd.hasPhdrs || cmd.hasFilehdr;
989 });1001 });
990 uint64_t HeaderSize = getHeaderSize();1002 bool paged = !config->omagic && !config->nmagic;
991 if (HeaderSize <= Min - computeBase(Min, HasExplicitHeaders)) {1003 uint64_t headerSize = getHeaderSize();
992 Min = alignDown(Min - HeaderSize, Config->MaxPageSize);1004 if ((paged || hasExplicitHeaders) &&
993 Out::ElfHeader->Addr = Min;1005 headerSize <= min - computeBase(min, hasExplicitHeaders)) {
994 Out::ProgramHeaders->Addr = Min + Out::ElfHeader->Size;1006 min = alignDown(min - headerSize, config->maxPageSize);
1007 Out::elfHeader->addr = min;
1008 Out::programHeaders->addr = min + Out::elfHeader->size;
995 return;1009 return;
996 }1010 }
9971011
998 // Error if we were explicitly asked to allocate headers.1012 // Error if we were explicitly asked to allocate headers.
999 if (HasExplicitHeaders)1013 if (hasExplicitHeaders)
1000 error("could not allocate headers");1014 error("could not allocate headers");
10011015
1002 Out::ElfHeader->PtLoad = nullptr;1016 Out::elfHeader->ptLoad = nullptr;
1003 Out::ProgramHeaders->PtLoad = nullptr;1017 Out::programHeaders->ptLoad = nullptr;
1004 FirstPTLoad->FirstSec = findFirstSection(FirstPTLoad);1018 firstPTLoad->firstSec = findFirstSection(firstPTLoad);
10051019
1006 llvm::erase_if(Phdrs,1020 llvm::erase_if(phdrs,
1007 [](const PhdrEntry *E) { return E->p_type == PT_PHDR; });1021 [](const PhdrEntry *e) { return e->p_type == PT_PHDR; });
1008}1022}
10091023
1010LinkerScript::AddressState::AddressState() {1024LinkerScript::AddressState::AddressState() {
1011 for (auto &MRI : Script->MemoryRegions) {1025 for (auto &mri : script->memoryRegions) {
1012 MemoryRegion *MR = MRI.second;1026 MemoryRegion *mr = mri.second;
1013 MR->CurPos = MR->Origin;1027 mr->curPos = mr->origin;
1014 }1028 }
1015}1029}
10161030
1017static uint64_t getInitialDot() {1031static uint64_t getInitialDot() {
1018 // By default linker scripts use an initial value of 0 for '.',1032 // By default linker scripts use an initial value of 0 for '.',
1019 // but prefer -image-base if set.1033 // but prefer -image-base if set.
1020 if (Script->HasSectionsCommand)1034 if (script->hasSectionsCommand)
1021 return Config->ImageBase ? *Config->ImageBase : 0;1035 return config->imageBase ? *config->imageBase : 0;
10221036
1023 uint64_t StartAddr = UINT64_MAX;1037 uint64_t startAddr = UINT64_MAX;
1024 // The Sections with -T<section> have been sorted in order of ascending1038 // The sections with -T<section> have been sorted in order of ascending
1025 // address. We must lower StartAddr if the lowest -T<section address> as1039 // address. We must lower startAddr if the lowest -T<section address> as
1026 // calls to setDot() must be monotonically increasing.1040 // calls to setDot() must be monotonically increasing.
1027 for (auto &KV : Config->SectionStartMap)1041 for (auto &kv : config->sectionStartMap)
1028 StartAddr = std::min(StartAddr, KV.second);1042 startAddr = std::min(startAddr, kv.second);
1029 return std::min(StartAddr, Target->getImageBase() + elf::getHeaderSize());1043 return std::min(startAddr, target->getImageBase() + elf::getHeaderSize());
1030}1044}
10311045
1032// Here we assign addresses as instructed by linker script SECTIONS1046// Here we assign addresses as instructed by linker script SECTIONS
1033// sub-commands. Doing that allows us to use final VA values, so here1047// sub-commands. Doing that allows us to use final VA values, so here
1034// we also handle rest commands like symbol assignments and ASSERTs.1048// we also handle rest commands like symbol assignments and ASSERTs.
1035void LinkerScript::assignAddresses() {1049void LinkerScript::assignAddresses() {
1036 Dot = getInitialDot();1050 dot = getInitialDot();
10371051
1038 auto Deleter = make_unique<AddressState>();1052 auto deleter = make_unique<AddressState>();
1039 Ctx = Deleter.get();1053 ctx = deleter.get();
1040 ErrorOnMissingSection = true;1054 errorOnMissingSection = true;
1041 switchTo(Aether);1055 switchTo(aether);
10421056
1043 for (BaseCommand *Base : SectionCommands) {1057 for (BaseCommand *base : sectionCommands) {
1044 if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {1058 if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
1045 Cmd->Addr = Dot;1059 cmd->addr = dot;
1046 assignSymbol(Cmd, false);1060 assignSymbol(cmd, false);
1047 Cmd->Size = Dot - Cmd->Addr;1061 cmd->size = dot - cmd->addr;
1048 continue;1062 continue;
1049 }1063 }
1050 assignOffsets(cast<OutputSection>(Base));1064 assignOffsets(cast<OutputSection>(base));
1051 }1065 }
1052 Ctx = nullptr;1066 ctx = nullptr;
1053}1067}
10541068
1055// Creates program headers as instructed by PHDRS linker script command.1069// Creates program headers as instructed by PHDRS linker script command.
1056std::vector<PhdrEntry *> LinkerScript::createPhdrs() {1070std::vector<PhdrEntry *> LinkerScript::createPhdrs() {
1057 std::vector<PhdrEntry *> Ret;1071 std::vector<PhdrEntry *> ret;
10581072
1059 // Process PHDRS and FILEHDR keywords because they are not1073 // Process PHDRS and FILEHDR keywords because they are not
1060 // real output sections and cannot be added in the following loop.1074 // real output sections and cannot be added in the following loop.
1061 for (const PhdrsCommand &Cmd : PhdrsCommands) {1075 for (const PhdrsCommand &cmd : phdrsCommands) {
1062 PhdrEntry *Phdr = make<PhdrEntry>(Cmd.Type, Cmd.Flags ? *Cmd.Flags : PF_R);1076 PhdrEntry *phdr = make<PhdrEntry>(cmd.type, cmd.flags ? *cmd.flags : PF_R);
10631077
1064 if (Cmd.HasFilehdr)1078 if (cmd.hasFilehdr)
1065 Phdr->add(Out::ElfHeader);1079 phdr->add(Out::elfHeader);
1066 if (Cmd.HasPhdrs)1080 if (cmd.hasPhdrs)
1067 Phdr->add(Out::ProgramHeaders);1081 phdr->add(Out::programHeaders);
10681082
1069 if (Cmd.LMAExpr) {1083 if (cmd.lmaExpr) {
1070 Phdr->p_paddr = Cmd.LMAExpr().getValue();1084 phdr->p_paddr = cmd.lmaExpr().getValue();
1071 Phdr->HasLMA = true;1085 phdr->hasLMA = true;
1072 }1086 }
1073 Ret.push_back(Phdr);1087 ret.push_back(phdr);
1074 }1088 }
10751089
1076 // Add output sections to program headers.1090 // Add output sections to program headers.
1077 for (OutputSection *Sec : OutputSections) {1091 for (OutputSection *sec : outputSections) {
1078 // Assign headers specified by linker script1092 // Assign headers specified by linker script
1079 for (size_t Id : getPhdrIndices(Sec)) {1093 for (size_t id : getPhdrIndices(sec)) {
1080 Ret[Id]->add(Sec);1094 ret[id]->add(sec);
1081 if (!PhdrsCommands[Id].Flags.hasValue())1095 if (!phdrsCommands[id].flags.hasValue())
1082 Ret[Id]->p_flags |= Sec->getPhdrFlags();1096 ret[id]->p_flags |= sec->getPhdrFlags();
1083 }1097 }
1084 }1098 }
1085 return Ret;1099 return ret;
1086}1100}
10871101
1088// Returns true if we should emit an .interp section.1102// Returns true if we should emit an .interp section.
...@@ -1091,54 +1105,54 @@ std::vector<PhdrEntry *> LinkerScript::createPhdrs() {...@@ -1091,54 +1105,54 @@ std::vector<PhdrEntry *> LinkerScript::createPhdrs() {
1091// no PT_INTERP is there, there's no place to emit an1105// no PT_INTERP is there, there's no place to emit an
1092// .interp, so we don't do that in that case.1106// .interp, so we don't do that in that case.
1093bool LinkerScript::needsInterpSection() {1107bool LinkerScript::needsInterpSection() {
1094 if (PhdrsCommands.empty())1108 if (phdrsCommands.empty())
1095 return true;1109 return true;
1096 for (PhdrsCommand &Cmd : PhdrsCommands)1110 for (PhdrsCommand &cmd : phdrsCommands)
1097 if (Cmd.Type == PT_INTERP)1111 if (cmd.type == PT_INTERP)
1098 return true;1112 return true;
1099 return false;1113 return false;
1100}1114}
11011115
1102ExprValue LinkerScript::getSymbolValue(StringRef Name, const Twine &Loc) {1116ExprValue LinkerScript::getSymbolValue(StringRef name, const Twine &loc) {
1103 if (Name == ".") {1117 if (name == ".") {
1104 if (Ctx)1118 if (ctx)
1105 return {Ctx->OutSec, false, Dot - Ctx->OutSec->Addr, Loc};1119 return {ctx->outSec, false, dot - ctx->outSec->addr, loc};
1106 error(Loc + ": unable to get location counter value");1120 error(loc + ": unable to get location counter value");
1107 return 0;1121 return 0;
1108 }1122 }
11091123
1110 if (Symbol *Sym = Symtab->find(Name)) {1124 if (Symbol *sym = symtab->find(name)) {
1111 if (auto *DS = dyn_cast<Defined>(Sym))1125 if (auto *ds = dyn_cast<Defined>(sym))
1112 return {DS->Section, false, DS->Value, Loc};1126 return {ds->section, false, ds->value, loc};
1113 if (isa<SharedSymbol>(Sym))1127 if (isa<SharedSymbol>(sym))
1114 if (!ErrorOnMissingSection)1128 if (!errorOnMissingSection)
1115 return {nullptr, false, 0, Loc};1129 return {nullptr, false, 0, loc};
1116 }1130 }
11171131
1118 error(Loc + ": symbol not found: " + Name);1132 error(loc + ": symbol not found: " + name);
1119 return 0;1133 return 0;
1120}1134}
11211135
1122// Returns the index of the segment named Name.1136// Returns the index of the segment named Name.
1123static Optional<size_t> getPhdrIndex(ArrayRef<PhdrsCommand> Vec,1137static Optional<size_t> getPhdrIndex(ArrayRef<PhdrsCommand> vec,
1124 StringRef Name) {1138 StringRef name) {
1125 for (size_t I = 0; I < Vec.size(); ++I)1139 for (size_t i = 0; i < vec.size(); ++i)
1126 if (Vec[I].Name == Name)1140 if (vec[i].name == name)
1127 return I;1141 return i;
1128 return None;1142 return None;
1129}1143}
11301144
1131// Returns indices of ELF headers containing specific section. Each index is a1145// Returns indices of ELF headers containing specific section. Each index is a
1132// zero based number of ELF header listed within PHDRS {} script block.1146// zero based number of ELF header listed within PHDRS {} script block.
1133std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *Cmd) {1147std::vector<size_t> LinkerScript::getPhdrIndices(OutputSection *cmd) {
1134 std::vector<size_t> Ret;1148 std::vector<size_t> ret;
11351149
1136 for (StringRef S : Cmd->Phdrs) {1150 for (StringRef s : cmd->phdrs) {
1137 if (Optional<size_t> Idx = getPhdrIndex(PhdrsCommands, S))1151 if (Optional<size_t> idx = getPhdrIndex(phdrsCommands, s))
1138 Ret.push_back(*Idx);1152 ret.push_back(*idx);
1139 else if (S != "NONE")1153 else if (s != "NONE")
1140 error(Cmd->Location + ": section header '" + S +1154 error(cmd->location + ": section header '" + s +
1141 "' is not listed in PHDRS");1155 "' is not listed in PHDRS");
1142 }1156 }
1143 return Ret;1157 return ret;
1144}1158}
deps/lld/ELF/LinkerScript.h+110-112
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- LinkerScript.h -------------------------------------------*- C++ -*-===//1//===- LinkerScript.h -------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -32,7 +31,6 @@ namespace elf {...@@ -32,7 +31,6 @@ namespace elf {
32class Defined;31class Defined;
33class InputSection;32class InputSection;
34class InputSectionBase;33class InputSectionBase;
35class InputSectionBase;
36class OutputSection;34class OutputSection;
37class SectionBase;35class SectionBase;
38class Symbol;36class Symbol;
...@@ -40,35 +38,35 @@ class ThunkSection;...@@ -40,35 +38,35 @@ class ThunkSection;
4038
41// This represents an r-value in the linker script.39// This represents an r-value in the linker script.
42struct ExprValue {40struct ExprValue {
43 ExprValue(SectionBase *Sec, bool ForceAbsolute, uint64_t Val,41 ExprValue(SectionBase *sec, bool forceAbsolute, uint64_t val,
44 const Twine &Loc)42 const Twine &loc)
45 : Sec(Sec), ForceAbsolute(ForceAbsolute), Val(Val), Loc(Loc.str()) {}43 : sec(sec), forceAbsolute(forceAbsolute), val(val), loc(loc.str()) {}
4644
47 ExprValue(uint64_t Val) : ExprValue(nullptr, false, Val, "") {}45 ExprValue(uint64_t val) : ExprValue(nullptr, false, val, "") {}
4846
49 bool isAbsolute() const { return ForceAbsolute || Sec == nullptr; }47 bool isAbsolute() const { return forceAbsolute || sec == nullptr; }
50 uint64_t getValue() const;48 uint64_t getValue() const;
51 uint64_t getSecAddr() const;49 uint64_t getSecAddr() const;
52 uint64_t getSectionOffset() const;50 uint64_t getSectionOffset() const;
5351
54 // If a value is relative to a section, it has a non-null Sec.52 // If a value is relative to a section, it has a non-null Sec.
55 SectionBase *Sec;53 SectionBase *sec;
5654
57 // True if this expression is enclosed in ABSOLUTE().55 // True if this expression is enclosed in ABSOLUTE().
58 // This flag affects the return value of getValue().56 // This flag affects the return value of getValue().
59 bool ForceAbsolute;57 bool forceAbsolute;
6058
61 uint64_t Val;59 uint64_t val;
62 uint64_t Alignment = 1;60 uint64_t alignment = 1;
6361
64 // Original source location. Used for error messages.62 // Original source location. Used for error messages.
65 std::string Loc;63 std::string loc;
66};64};
6765
68// This represents an expression in the linker script.66// This represents an expression in the linker script.
69// ScriptParser::readExpr reads an expression and returns an Expr.67// ScriptParser::readExpr reads an expression and returns an Expr.
70// Later, we evaluate the expression by calling the function.68// Later, we evaluate the expression by calling the function.
71typedef std::function<ExprValue()> Expr;69using Expr = std::function<ExprValue()>;
7270
73// This enum is used to implement linker script SECTIONS command.71// This enum is used to implement linker script SECTIONS command.
74// https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS72// https://sourceware.org/binutils/docs/ld/SECTIONS.html#SECTIONS
...@@ -80,42 +78,42 @@ enum SectionsCommandKind {...@@ -80,42 +78,42 @@ enum SectionsCommandKind {
80};78};
8179
82struct BaseCommand {80struct BaseCommand {
83 BaseCommand(int K) : Kind(K) {}81 BaseCommand(int k) : kind(k) {}
84 int Kind;82 int kind;
85};83};
8684
87// This represents ". = <expr>" or "<symbol> = <expr>".85// This represents ". = <expr>" or "<symbol> = <expr>".
88struct SymbolAssignment : BaseCommand {86struct SymbolAssignment : BaseCommand {
89 SymbolAssignment(StringRef Name, Expr E, std::string Loc)87 SymbolAssignment(StringRef name, Expr e, std::string loc)
90 : BaseCommand(AssignmentKind), Name(Name), Expression(E), Location(Loc) {}88 : BaseCommand(AssignmentKind), name(name), expression(e), location(loc) {}
9189
92 static bool classof(const BaseCommand *C) {90 static bool classof(const BaseCommand *c) {
93 return C->Kind == AssignmentKind;91 return c->kind == AssignmentKind;
94 }92 }
9593
96 // The LHS of an expression. Name is either a symbol name or ".".94 // The LHS of an expression. Name is either a symbol name or ".".
97 StringRef Name;95 StringRef name;
98 Defined *Sym = nullptr;96 Defined *sym = nullptr;
9997
100 // The RHS of an expression.98 // The RHS of an expression.
101 Expr Expression;99 Expr expression;
102100
103 // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.101 // Command attributes for PROVIDE, HIDDEN and PROVIDE_HIDDEN.
104 bool Provide = false;102 bool provide = false;
105 bool Hidden = false;103 bool hidden = false;
106104
107 // Holds file name and line number for error reporting.105 // Holds file name and line number for error reporting.
108 std::string Location;106 std::string location;
109107
110 // A string representation of this command. We use this for -Map.108 // A string representation of this command. We use this for -Map.
111 std::string CommandString;109 std::string commandString;
112110
113 // Address of this assignment command.111 // Address of this assignment command.
114 unsigned Addr;112 unsigned addr;
115113
116 // Size of this assignment command. This is usually 0, but if114 // Size of this assignment command. This is usually 0, but if
117 // you move '.' this may be greater than 0.115 // you move '.' this may be greater than 0.
118 unsigned Size;116 unsigned size;
119};117};
120118
121// Linker scripts allow additional constraints to be put on ouput sections.119// Linker scripts allow additional constraints to be put on ouput sections.
...@@ -128,83 +126,83 @@ enum class ConstraintKind { NoConstraint, ReadOnly, ReadWrite };...@@ -128,83 +126,83 @@ enum class ConstraintKind { NoConstraint, ReadOnly, ReadWrite };
128// target memory. Instances of the struct are created by parsing the126// target memory. Instances of the struct are created by parsing the
129// MEMORY command.127// MEMORY command.
130struct MemoryRegion {128struct MemoryRegion {
131 MemoryRegion(StringRef Name, uint64_t Origin, uint64_t Length, uint32_t Flags,129 MemoryRegion(StringRef name, uint64_t origin, uint64_t length, uint32_t flags,
132 uint32_t NegFlags)130 uint32_t negFlags)
133 : Name(Name), Origin(Origin), Length(Length), Flags(Flags),131 : name(name), origin(origin), length(length), flags(flags),
134 NegFlags(NegFlags) {}132 negFlags(negFlags) {}
135133
136 std::string Name;134 std::string name;
137 uint64_t Origin;135 uint64_t origin;
138 uint64_t Length;136 uint64_t length;
139 uint32_t Flags;137 uint32_t flags;
140 uint32_t NegFlags;138 uint32_t negFlags;
141 uint64_t CurPos = 0;139 uint64_t curPos = 0;
142};140};
143141
144// This struct represents one section match pattern in SECTIONS() command.142// This struct represents one section match pattern in SECTIONS() command.
145// It can optionally have negative match pattern for EXCLUDED_FILE command.143// It can optionally have negative match pattern for EXCLUDED_FILE command.
146// Also it may be surrounded with SORT() command, so contains sorting rules.144// Also it may be surrounded with SORT() command, so contains sorting rules.
147struct SectionPattern {145struct SectionPattern {
148 SectionPattern(StringMatcher &&Pat1, StringMatcher &&Pat2)146 SectionPattern(StringMatcher &&pat1, StringMatcher &&pat2)
149 : ExcludedFilePat(Pat1), SectionPat(Pat2),147 : excludedFilePat(pat1), sectionPat(pat2),
150 SortOuter(SortSectionPolicy::Default),148 sortOuter(SortSectionPolicy::Default),
151 SortInner(SortSectionPolicy::Default) {}149 sortInner(SortSectionPolicy::Default) {}
152150
153 StringMatcher ExcludedFilePat;151 StringMatcher excludedFilePat;
154 StringMatcher SectionPat;152 StringMatcher sectionPat;
155 SortSectionPolicy SortOuter;153 SortSectionPolicy sortOuter;
156 SortSectionPolicy SortInner;154 SortSectionPolicy sortInner;
157};155};
158156
159struct InputSectionDescription : BaseCommand {157struct InputSectionDescription : BaseCommand {
160 InputSectionDescription(StringRef FilePattern)158 InputSectionDescription(StringRef filePattern)
161 : BaseCommand(InputSectionKind), FilePat(FilePattern) {}159 : BaseCommand(InputSectionKind), filePat(filePattern) {}
162160
163 static bool classof(const BaseCommand *C) {161 static bool classof(const BaseCommand *c) {
164 return C->Kind == InputSectionKind;162 return c->kind == InputSectionKind;
165 }163 }
166164
167 StringMatcher FilePat;165 StringMatcher filePat;
168166
169 // Input sections that matches at least one of SectionPatterns167 // Input sections that matches at least one of SectionPatterns
170 // will be associated with this InputSectionDescription.168 // will be associated with this InputSectionDescription.
171 std::vector<SectionPattern> SectionPatterns;169 std::vector<SectionPattern> sectionPatterns;
172170
173 std::vector<InputSection *> Sections;171 std::vector<InputSection *> sections;
174172
175 // Temporary record of synthetic ThunkSection instances and the pass that173 // Temporary record of synthetic ThunkSection instances and the pass that
176 // they were created in. This is used to insert newly created ThunkSections174 // they were created in. This is used to insert newly created ThunkSections
177 // into Sections at the end of a createThunks() pass.175 // into Sections at the end of a createThunks() pass.
178 std::vector<std::pair<ThunkSection *, uint32_t>> ThunkSections;176 std::vector<std::pair<ThunkSection *, uint32_t>> thunkSections;
179};177};
180178
181// Represents BYTE(), SHORT(), LONG(), or QUAD().179// Represents BYTE(), SHORT(), LONG(), or QUAD().
182struct ByteCommand : BaseCommand {180struct ByteCommand : BaseCommand {
183 ByteCommand(Expr E, unsigned Size, std::string CommandString)181 ByteCommand(Expr e, unsigned size, std::string commandString)
184 : BaseCommand(ByteKind), CommandString(CommandString), Expression(E),182 : BaseCommand(ByteKind), commandString(commandString), expression(e),
185 Size(Size) {}183 size(size) {}
186184
187 static bool classof(const BaseCommand *C) { return C->Kind == ByteKind; }185 static bool classof(const BaseCommand *c) { return c->kind == ByteKind; }
188186
189 // Keeps string representing the command. Used for -Map" is perhaps better.187 // Keeps string representing the command. Used for -Map" is perhaps better.
190 std::string CommandString;188 std::string commandString;
191189
192 Expr Expression;190 Expr expression;
193191
194 // This is just an offset of this assignment command in the output section.192 // This is just an offset of this assignment command in the output section.
195 unsigned Offset;193 unsigned offset;
196194
197 // Size of this data command.195 // Size of this data command.
198 unsigned Size;196 unsigned size;
199};197};
200198
201struct PhdrsCommand {199struct PhdrsCommand {
202 StringRef Name;200 StringRef name;
203 unsigned Type = llvm::ELF::PT_NULL;201 unsigned type = llvm::ELF::PT_NULL;
204 bool HasFilehdr = false;202 bool hasFilehdr = false;
205 bool HasPhdrs = false;203 bool hasPhdrs = false;
206 llvm::Optional<unsigned> Flags;204 llvm::Optional<unsigned> flags;
207 Expr LMAExpr = nullptr;205 Expr lmaExpr = nullptr;
208};206};
209207
210class LinkerScript final {208class LinkerScript final {
...@@ -213,35 +211,35 @@ class LinkerScript final {...@@ -213,35 +211,35 @@ class LinkerScript final {
213 // not be used outside of the scope of a call to the above functions.211 // not be used outside of the scope of a call to the above functions.
214 struct AddressState {212 struct AddressState {
215 AddressState();213 AddressState();
216 uint64_t ThreadBssOffset = 0;214 uint64_t threadBssOffset = 0;
217 OutputSection *OutSec = nullptr;215 OutputSection *outSec = nullptr;
218 MemoryRegion *MemRegion = nullptr;216 MemoryRegion *memRegion = nullptr;
219 MemoryRegion *LMARegion = nullptr;217 MemoryRegion *lmaRegion = nullptr;
220 uint64_t LMAOffset = 0;218 uint64_t lmaOffset = 0;
221 };219 };
222220
223 llvm::DenseMap<StringRef, OutputSection *> NameToOutputSection;221 llvm::DenseMap<StringRef, OutputSection *> nameToOutputSection;
224222
225 void addSymbol(SymbolAssignment *Cmd);223 void addSymbol(SymbolAssignment *cmd);
226 void assignSymbol(SymbolAssignment *Cmd, bool InSec);224 void assignSymbol(SymbolAssignment *cmd, bool inSec);
227 void setDot(Expr E, const Twine &Loc, bool InSec);225 void setDot(Expr e, const Twine &loc, bool inSec);
228 void expandOutputSection(uint64_t Size);226 void expandOutputSection(uint64_t size);
229 void expandMemoryRegions(uint64_t Size);227 void expandMemoryRegions(uint64_t size);
230228
231 std::vector<InputSection *>229 std::vector<InputSection *>
232 computeInputSections(const InputSectionDescription *);230 computeInputSections(const InputSectionDescription *);
233231
234 std::vector<InputSection *> createInputSectionList(OutputSection &Cmd);232 std::vector<InputSection *> createInputSectionList(OutputSection &cmd);
235233
236 std::vector<size_t> getPhdrIndices(OutputSection *Sec);234 std::vector<size_t> getPhdrIndices(OutputSection *sec);
237235
238 MemoryRegion *findMemoryRegion(OutputSection *Sec);236 MemoryRegion *findMemoryRegion(OutputSection *sec);
239237
240 void switchTo(OutputSection *Sec);238 void switchTo(OutputSection *sec);
241 uint64_t advance(uint64_t Size, unsigned Align);239 uint64_t advance(uint64_t size, unsigned align);
242 void output(InputSection *Sec);240 void output(InputSection *sec);
243241
244 void assignOffsets(OutputSection *Sec);242 void assignOffsets(OutputSection *sec);
245243
246 // Ctx captures the local AddressState and makes it accessible244 // Ctx captures the local AddressState and makes it accessible
247 // deliberately. This is needed as there are some cases where we cannot just245 // deliberately. This is needed as there are some cases where we cannot just
...@@ -249,21 +247,21 @@ class LinkerScript final {...@@ -249,21 +247,21 @@ class LinkerScript final {
249 // script parser.247 // script parser.
250 // This should remain a plain pointer as its lifetime is smaller than248 // This should remain a plain pointer as its lifetime is smaller than
251 // LinkerScript.249 // LinkerScript.
252 AddressState *Ctx = nullptr;250 AddressState *ctx = nullptr;
253251
254 OutputSection *Aether;252 OutputSection *aether;
255253
256 uint64_t Dot;254 uint64_t dot;
257255
258public:256public:
259 OutputSection *createOutputSection(StringRef Name, StringRef Location);257 OutputSection *createOutputSection(StringRef name, StringRef location);
260 OutputSection *getOrCreateOutputSection(StringRef Name);258 OutputSection *getOrCreateOutputSection(StringRef name);
261259
262 bool hasPhdrsCommands() { return !PhdrsCommands.empty(); }260 bool hasPhdrsCommands() { return !phdrsCommands.empty(); }
263 uint64_t getDot() { return Dot; }261 uint64_t getDot() { return dot; }
264 void discard(ArrayRef<InputSection *> V);262 void discard(ArrayRef<InputSection *> v);
265263
266 ExprValue getSymbolValue(StringRef Name, const Twine &Loc);264 ExprValue getSymbolValue(StringRef name, const Twine &loc);
267265
268 void addOrphanSections();266 void addOrphanSections();
269 void adjustSectionsBeforeSorting();267 void adjustSectionsBeforeSorting();
...@@ -272,9 +270,9 @@ public:...@@ -272,9 +270,9 @@ public:
272 std::vector<PhdrEntry *> createPhdrs();270 std::vector<PhdrEntry *> createPhdrs();
273 bool needsInterpSection();271 bool needsInterpSection();
274272
275 bool shouldKeep(InputSectionBase *S);273 bool shouldKeep(InputSectionBase *s);
276 void assignAddresses();274 void assignAddresses();
277 void allocateHeaders(std::vector<PhdrEntry *> &Phdrs);275 void allocateHeaders(std::vector<PhdrEntry *> &phdrs);
278 void processSectionCommands();276 void processSectionCommands();
279 void declareSymbols();277 void declareSymbols();
280278
...@@ -282,31 +280,31 @@ public:...@@ -282,31 +280,31 @@ public:
282 void processInsertCommands();280 void processInsertCommands();
283281
284 // SECTIONS command list.282 // SECTIONS command list.
285 std::vector<BaseCommand *> SectionCommands;283 std::vector<BaseCommand *> sectionCommands;
286284
287 // PHDRS command list.285 // PHDRS command list.
288 std::vector<PhdrsCommand> PhdrsCommands;286 std::vector<PhdrsCommand> phdrsCommands;
289287
290 bool HasSectionsCommand = false;288 bool hasSectionsCommand = false;
291 bool ErrorOnMissingSection = false;289 bool errorOnMissingSection = false;
292290
293 // List of section patterns specified with KEEP commands. They will291 // List of section patterns specified with KEEP commands. They will
294 // be kept even if they are unused and --gc-sections is specified.292 // be kept even if they are unused and --gc-sections is specified.
295 std::vector<InputSectionDescription *> KeptSections;293 std::vector<InputSectionDescription *> keptSections;
296294
297 // A map from memory region name to a memory region descriptor.295 // A map from memory region name to a memory region descriptor.
298 llvm::MapVector<llvm::StringRef, MemoryRegion *> MemoryRegions;296 llvm::MapVector<llvm::StringRef, MemoryRegion *> memoryRegions;
299297
300 // A list of symbols referenced by the script.298 // A list of symbols referenced by the script.
301 std::vector<llvm::StringRef> ReferencedSymbols;299 std::vector<llvm::StringRef> referencedSymbols;
302300
303 // Used to implement INSERT [AFTER|BEFORE]. Contains commands that need301 // Used to implement INSERT [AFTER|BEFORE]. Contains commands that need
304 // to be inserted into SECTIONS commands list.302 // to be inserted into SECTIONS commands list.
305 llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertAfterCommands;303 llvm::DenseMap<StringRef, std::vector<BaseCommand *>> insertAfterCommands;
306 llvm::DenseMap<StringRef, std::vector<BaseCommand *>> InsertBeforeCommands;304 llvm::DenseMap<StringRef, std::vector<BaseCommand *>> insertBeforeCommands;
307};305};
308306
309extern LinkerScript *Script;307extern LinkerScript *script;
310308
311} // end namespace elf309} // end namespace elf
312} // end namespace lld310} // end namespace lld
deps/lld/ELF/MapFile.cpp+116-118
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MapFile.cpp --------------------------------------------------------===//1//===- MapFile.cpp --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -38,69 +37,67 @@ using namespace llvm::object;...@@ -38,69 +37,67 @@ using namespace llvm::object;
38using namespace lld;37using namespace lld;
39using namespace lld::elf;38using namespace lld::elf;
4039
41typedef DenseMap<const SectionBase *, SmallVector<Defined *, 4>> SymbolMapTy;40using SymbolMapTy = DenseMap<const SectionBase *, SmallVector<Defined *, 4>>;
4241
43static const std::string Indent8 = " "; // 8 spaces42static const std::string indent8 = " "; // 8 spaces
44static const std::string Indent16 = " "; // 16 spaces43static const std::string indent16 = " "; // 16 spaces
4544
46// Print out the first three columns of a line.45// Print out the first three columns of a line.
47static void writeHeader(raw_ostream &OS, uint64_t VMA, uint64_t LMA,46static void writeHeader(raw_ostream &os, uint64_t vma, uint64_t lma,
48 uint64_t Size, uint64_t Align) {47 uint64_t size, uint64_t align) {
49 if (Config->Is64)48 if (config->is64)
50 OS << format("%16llx %16llx %8llx %5lld ", VMA, LMA, Size, Align);49 os << format("%16llx %16llx %8llx %5lld ", vma, lma, size, align);
51 else50 else
52 OS << format("%8llx %8llx %8llx %5lld ", VMA, LMA, Size, Align);51 os << format("%8llx %8llx %8llx %5lld ", vma, lma, size, align);
53}52}
5453
55// Returns a list of all symbols that we want to print out.54// Returns a list of all symbols that we want to print out.
56static std::vector<Defined *> getSymbols() {55static std::vector<Defined *> getSymbols() {
57 std::vector<Defined *> V;56 std::vector<Defined *> v;
58 for (InputFile *File : ObjectFiles)57 for (InputFile *file : objectFiles)
59 for (Symbol *B : File->getSymbols())58 for (Symbol *b : file->getSymbols())
60 if (auto *DR = dyn_cast<Defined>(B))59 if (auto *dr = dyn_cast<Defined>(b))
61 if (!DR->isSection() && DR->Section && DR->Section->Live &&60 if (!dr->isSection() && dr->section && dr->section->isLive() &&
62 (DR->File == File || DR->NeedsPltAddr || DR->Section->Bss))61 (dr->file == file || dr->needsPltAddr || dr->section->bss))
63 V.push_back(DR);62 v.push_back(dr);
64 return V;63 return v;
65}64}
6665
67// Returns a map from sections to their symbols.66// Returns a map from sections to their symbols.
68static SymbolMapTy getSectionSyms(ArrayRef<Defined *> Syms) {67static SymbolMapTy getSectionSyms(ArrayRef<Defined *> syms) {
69 SymbolMapTy Ret;68 SymbolMapTy ret;
70 for (Defined *DR : Syms)69 for (Defined *dr : syms)
71 Ret[DR->Section].push_back(DR);70 ret[dr->section].push_back(dr);
7271
73 // Sort symbols by address. We want to print out symbols in the72 // Sort symbols by address. We want to print out symbols in the
74 // order in the output file rather than the order they appeared73 // order in the output file rather than the order they appeared
75 // in the input files.74 // in the input files.
76 for (auto &It : Ret) {75 for (auto &it : ret)
77 SmallVectorImpl<Defined *> &V = It.second;76 llvm::stable_sort(it.second, [](Defined *a, Defined *b) {
78 std::stable_sort(V.begin(), V.end(), [](Defined *A, Defined *B) {77 return a->getVA() < b->getVA();
79 return A->getVA() < B->getVA();
80 });78 });
81 }79 return ret;
82 return Ret;
83}80}
8481
85// Construct a map from symbols to their stringified representations.82// Construct a map from symbols to their stringified representations.
86// Demangling symbols (which is what toString() does) is slow, so83// Demangling symbols (which is what toString() does) is slow, so
87// we do that in batch using parallel-for.84// we do that in batch using parallel-for.
88static DenseMap<Symbol *, std::string>85static DenseMap<Symbol *, std::string>
89getSymbolStrings(ArrayRef<Defined *> Syms) {86getSymbolStrings(ArrayRef<Defined *> syms) {
90 std::vector<std::string> Str(Syms.size());87 std::vector<std::string> str(syms.size());
91 parallelForEachN(0, Syms.size(), [&](size_t I) {88 parallelForEachN(0, syms.size(), [&](size_t i) {
92 raw_string_ostream OS(Str[I]);89 raw_string_ostream os(str[i]);
93 OutputSection *OSec = Syms[I]->getOutputSection();90 OutputSection *osec = syms[i]->getOutputSection();
94 uint64_t VMA = Syms[I]->getVA();91 uint64_t vma = syms[i]->getVA();
95 uint64_t LMA = OSec ? OSec->getLMA() + VMA - OSec->getVA(0) : 0;92 uint64_t lma = osec ? osec->getLMA() + vma - osec->getVA(0) : 0;
96 writeHeader(OS, VMA, LMA, Syms[I]->getSize(), 1);93 writeHeader(os, vma, lma, syms[i]->getSize(), 1);
97 OS << Indent16 << toString(*Syms[I]);94 os << indent16 << toString(*syms[i]);
98 });95 });
9996
100 DenseMap<Symbol *, std::string> Ret;97 DenseMap<Symbol *, std::string> ret;
101 for (size_t I = 0, E = Syms.size(); I < E; ++I)98 for (size_t i = 0, e = syms.size(); i < e; ++i)
102 Ret[Syms[I]] = std::move(Str[I]);99 ret[syms[i]] = std::move(str[i]);
103 return Ret;100 return ret;
104}101}
105102
106// Print .eh_frame contents. Since the section consists of EhSectionPieces,103// Print .eh_frame contents. Since the section consists of EhSectionPieces,
...@@ -109,114 +106,115 @@ getSymbolStrings(ArrayRef<Defined *> Syms) {...@@ -109,114 +106,115 @@ getSymbolStrings(ArrayRef<Defined *> Syms) {
109// .eh_frame tend to contain a lot of section pieces that are contiguous106// .eh_frame tend to contain a lot of section pieces that are contiguous
110// both in input file and output file. Such pieces are squashed before107// both in input file and output file. Such pieces are squashed before
111// being displayed to make output compact.108// being displayed to make output compact.
112static void printEhFrame(raw_ostream &OS, OutputSection *OSec) {109static void printEhFrame(raw_ostream &os, const EhFrameSection *sec) {
113 std::vector<EhSectionPiece> Pieces;110 std::vector<EhSectionPiece> pieces;
114111
115 auto Add = [&](const EhSectionPiece &P) {112 auto add = [&](const EhSectionPiece &p) {
116 // If P is adjacent to Last, squash the two.113 // If P is adjacent to Last, squash the two.
117 if (!Pieces.empty()) {114 if (!pieces.empty()) {
118 EhSectionPiece &Last = Pieces.back();115 EhSectionPiece &last = pieces.back();
119 if (Last.Sec == P.Sec && Last.InputOff + Last.Size == P.InputOff &&116 if (last.sec == p.sec && last.inputOff + last.size == p.inputOff &&
120 Last.OutputOff + Last.Size == P.OutputOff) {117 last.outputOff + last.size == p.outputOff) {
121 Last.Size += P.Size;118 last.size += p.size;
122 return;119 return;
123 }120 }
124 }121 }
125 Pieces.push_back(P);122 pieces.push_back(p);
126 };123 };
127124
128 // Gather section pieces.125 // Gather section pieces.
129 for (const CieRecord *Rec : In.EhFrame->getCieRecords()) {126 for (const CieRecord *rec : sec->getCieRecords()) {
130 Add(*Rec->Cie);127 add(*rec->cie);
131 for (const EhSectionPiece *Fde : Rec->Fdes)128 for (const EhSectionPiece *fde : rec->fdes)
132 Add(*Fde);129 add(*fde);
133 }130 }
134131
135 // Print out section pieces.132 // Print out section pieces.
136 for (EhSectionPiece &P : Pieces) {133 const OutputSection *osec = sec->getOutputSection();
137 writeHeader(OS, OSec->Addr + P.OutputOff, OSec->getLMA() + P.OutputOff,134 for (EhSectionPiece &p : pieces) {
138 P.Size, 1);135 writeHeader(os, osec->addr + p.outputOff, osec->getLMA() + p.outputOff,
139 OS << Indent8 << toString(P.Sec->File) << ":(" << P.Sec->Name << "+0x"136 p.size, 1);
140 << Twine::utohexstr(P.InputOff) + ")\n";137 os << indent8 << toString(p.sec->file) << ":(" << p.sec->name << "+0x"
138 << Twine::utohexstr(p.inputOff) + ")\n";
141 }139 }
142}140}
143141
144void elf::writeMapFile() {142void elf::writeMapFile() {
145 if (Config->MapFile.empty())143 if (config->mapFile.empty())
146 return;144 return;
147145
148 // Open a map file for writing.146 // Open a map file for writing.
149 std::error_code EC;147 std::error_code ec;
150 raw_fd_ostream OS(Config->MapFile, EC, sys::fs::F_None);148 raw_fd_ostream os(config->mapFile, ec, sys::fs::F_None);
151 if (EC) {149 if (ec) {
152 error("cannot open " + Config->MapFile + ": " + EC.message());150 error("cannot open " + config->mapFile + ": " + ec.message());
153 return;151 return;
154 }152 }
155153
156 // Collect symbol info that we want to print out.154 // Collect symbol info that we want to print out.
157 std::vector<Defined *> Syms = getSymbols();155 std::vector<Defined *> syms = getSymbols();
158 SymbolMapTy SectionSyms = getSectionSyms(Syms);156 SymbolMapTy sectionSyms = getSectionSyms(syms);
159 DenseMap<Symbol *, std::string> SymStr = getSymbolStrings(Syms);157 DenseMap<Symbol *, std::string> symStr = getSymbolStrings(syms);
160158
161 // Print out the header line.159 // Print out the header line.
162 int W = Config->Is64 ? 16 : 8;160 int w = config->is64 ? 16 : 8;
163 OS << right_justify("VMA", W) << ' ' << right_justify("LMA", W)161 os << right_justify("VMA", w) << ' ' << right_justify("LMA", w)
164 << " Size Align Out In Symbol\n";162 << " Size Align Out In Symbol\n";
165163
166 OutputSection* OSec = nullptr;164 OutputSection* osec = nullptr;
167 for (BaseCommand *Base : Script->SectionCommands) {165 for (BaseCommand *base : script->sectionCommands) {
168 if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {166 if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
169 if (Cmd->Provide && !Cmd->Sym)167 if (cmd->provide && !cmd->sym)
170 continue;168 continue;
171 uint64_t LMA = OSec ? OSec->getLMA() + Cmd->Addr - OSec->getVA(0) : 0;169 uint64_t lma = osec ? osec->getLMA() + cmd->addr - osec->getVA(0) : 0;
172 writeHeader(OS, Cmd->Addr, LMA, Cmd->Size, 1);170 writeHeader(os, cmd->addr, lma, cmd->size, 1);
173 OS << Cmd->CommandString << '\n';171 os << cmd->commandString << '\n';
174 continue;172 continue;
175 }173 }
176174
177 OSec = cast<OutputSection>(Base);175 osec = cast<OutputSection>(base);
178 writeHeader(OS, OSec->Addr, OSec->getLMA(), OSec->Size, OSec->Alignment);176 writeHeader(os, osec->addr, osec->getLMA(), osec->size, osec->alignment);
179 OS << OSec->Name << '\n';177 os << osec->name << '\n';
180178
181 // Dump symbols for each input section.179 // Dump symbols for each input section.
182 for (BaseCommand *Base : OSec->SectionCommands) {180 for (BaseCommand *base : osec->sectionCommands) {
183 if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) {181 if (auto *isd = dyn_cast<InputSectionDescription>(base)) {
184 for (InputSection *IS : ISD->Sections) {182 for (InputSection *isec : isd->sections) {
185 if (IS == In.EhFrame) {183 if (auto *ehSec = dyn_cast<EhFrameSection>(isec)) {
186 printEhFrame(OS, OSec);184 printEhFrame(os, ehSec);
187 continue;185 continue;
188 }186 }
189187
190 writeHeader(OS, IS->getVA(0), OSec->getLMA() + IS->getOffset(0),188 writeHeader(os, isec->getVA(0), osec->getLMA() + isec->getOffset(0),
191 IS->getSize(), IS->Alignment);189 isec->getSize(), isec->alignment);
192 OS << Indent8 << toString(IS) << '\n';190 os << indent8 << toString(isec) << '\n';
193 for (Symbol *Sym : SectionSyms[IS])191 for (Symbol *sym : sectionSyms[isec])
194 OS << SymStr[Sym] << '\n';192 os << symStr[sym] << '\n';
195 }193 }
196 continue;194 continue;
197 }195 }
198196
199 if (auto *Cmd = dyn_cast<ByteCommand>(Base)) {197 if (auto *cmd = dyn_cast<ByteCommand>(base)) {
200 writeHeader(OS, OSec->Addr + Cmd->Offset, OSec->getLMA() + Cmd->Offset,198 writeHeader(os, osec->addr + cmd->offset, osec->getLMA() + cmd->offset,
201 Cmd->Size, 1);199 cmd->size, 1);
202 OS << Indent8 << Cmd->CommandString << '\n';200 os << indent8 << cmd->commandString << '\n';
203 continue;201 continue;
204 }202 }
205203
206 if (auto *Cmd = dyn_cast<SymbolAssignment>(Base)) {204 if (auto *cmd = dyn_cast<SymbolAssignment>(base)) {
207 if (Cmd->Provide && !Cmd->Sym)205 if (cmd->provide && !cmd->sym)
208 continue;206 continue;
209 writeHeader(OS, Cmd->Addr, OSec->getLMA() + Cmd->Addr - OSec->getVA(0),207 writeHeader(os, cmd->addr, osec->getLMA() + cmd->addr - osec->getVA(0),
210 Cmd->Size, 1);208 cmd->size, 1);
211 OS << Indent8 << Cmd->CommandString << '\n';209 os << indent8 << cmd->commandString << '\n';
212 continue;210 continue;
213 }211 }
214 }212 }
215 }213 }
216}214}
217215
218static void print(StringRef A, StringRef B) {216static void print(StringRef a, StringRef b) {
219 outs() << left_justify(A, 49) << " " << B << "\n";217 outs() << left_justify(a, 49) << " " << b << "\n";
220}218}
221219
222// Output a cross reference table to stdout. This is for --cref.220// Output a cross reference table to stdout. This is for --cref.
...@@ -231,18 +229,18 @@ static void print(StringRef A, StringRef B) {...@@ -231,18 +229,18 @@ static void print(StringRef A, StringRef B) {
231// In this case, strlen is defined by libc.so.6 and used by other two229// In this case, strlen is defined by libc.so.6 and used by other two
232// files.230// files.
233void elf::writeCrossReferenceTable() {231void elf::writeCrossReferenceTable() {
234 if (!Config->Cref)232 if (!config->cref)
235 return;233 return;
236234
237 // Collect symbols and files.235 // Collect symbols and files.
238 MapVector<Symbol *, SetVector<InputFile *>> Map;236 MapVector<Symbol *, SetVector<InputFile *>> map;
239 for (InputFile *File : ObjectFiles) {237 for (InputFile *file : objectFiles) {
240 for (Symbol *Sym : File->getSymbols()) {238 for (Symbol *sym : file->getSymbols()) {
241 if (isa<SharedSymbol>(Sym))239 if (isa<SharedSymbol>(sym))
242 Map[Sym].insert(File);240 map[sym].insert(file);
243 if (auto *D = dyn_cast<Defined>(Sym))241 if (auto *d = dyn_cast<Defined>(sym))
244 if (!D->isLocal() && (!D->Section || D->Section->Live))242 if (!d->isLocal() && (!d->section || d->section->isLive()))
245 Map[D].insert(File);243 map[d].insert(file);
246 }244 }
247 }245 }
248246
...@@ -251,13 +249,13 @@ void elf::writeCrossReferenceTable() {...@@ -251,13 +249,13 @@ void elf::writeCrossReferenceTable() {
251 print("Symbol", "File");249 print("Symbol", "File");
252250
253 // Print out a table.251 // Print out a table.
254 for (auto KV : Map) {252 for (auto kv : map) {
255 Symbol *Sym = KV.first;253 Symbol *sym = kv.first;
256 SetVector<InputFile *> &Files = KV.second;254 SetVector<InputFile *> &files = kv.second;
257255
258 print(toString(*Sym), toString(Sym->File));256 print(toString(*sym), toString(sym->file));
259 for (InputFile *File : Files)257 for (InputFile *file : files)
260 if (File != Sym->File)258 if (file != sym->file)
261 print("", toString(File));259 print("", toString(file));
262 }260 }
263}261}
deps/lld/ELF/MapFile.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MapFile.h ------------------------------------------------*- C++ -*-===//1//===- MapFile.h ------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/ELF/MarkLive.cpp+217-168
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MarkLive.cpp -------------------------------------------------------===//1//===- MarkLive.cpp -------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -26,6 +25,7 @@...@@ -26,6 +25,7 @@
26#include "OutputSections.h"25#include "OutputSections.h"
27#include "SymbolTable.h"26#include "SymbolTable.h"
28#include "Symbols.h"27#include "Symbols.h"
28#include "SyntheticSections.h"
29#include "Target.h"29#include "Target.h"
30#include "lld/Common/Memory.h"30#include "lld/Common/Memory.h"
31#include "lld/Common/Strings.h"31#include "lld/Common/Strings.h"
...@@ -42,66 +42,79 @@ using namespace llvm::support::endian;...@@ -42,66 +42,79 @@ using namespace llvm::support::endian;
42using namespace lld;42using namespace lld;
43using namespace lld::elf;43using namespace lld::elf;
4444
45namespace {
46template <class ELFT> class MarkLive {
47public:
48 MarkLive(unsigned partition) : partition(partition) {}
49
50 void run();
51 void moveToMain();
52
53private:
54 void enqueue(InputSectionBase *sec, uint64_t offset);
55 void markSymbol(Symbol *sym);
56 void mark();
57
58 template <class RelTy>
59 void resolveReloc(InputSectionBase &sec, RelTy &rel, bool isLSDA);
60
61 template <class RelTy>
62 void scanEhFrameSection(EhInputSection &eh, ArrayRef<RelTy> rels);
63
64 // The index of the partition that we are currently processing.
65 unsigned partition;
66
67 // A list of sections to visit.
68 SmallVector<InputSection *, 256> queue;
69
70 // There are normally few input sections whose names are valid C
71 // identifiers, so we just store a std::vector instead of a multimap.
72 DenseMap<StringRef, std::vector<InputSectionBase *>> cNamedSections;
73};
74} // namespace
75
45template <class ELFT>76template <class ELFT>
46static typename ELFT::uint getAddend(InputSectionBase &Sec,77static uint64_t getAddend(InputSectionBase &sec,
47 const typename ELFT::Rel &Rel) {78 const typename ELFT::Rel &rel) {
48 return Target->getImplicitAddend(Sec.data().begin() + Rel.r_offset,79 return target->getImplicitAddend(sec.data().begin() + rel.r_offset,
49 Rel.getType(Config->IsMips64EL));80 rel.getType(config->isMips64EL));
50}81}
5182
52template <class ELFT>83template <class ELFT>
53static typename ELFT::uint getAddend(InputSectionBase &Sec,84static uint64_t getAddend(InputSectionBase &sec,
54 const typename ELFT::Rela &Rel) {85 const typename ELFT::Rela &rel) {
55 return Rel.r_addend;86 return rel.r_addend;
56}87}
5788
58// There are normally few input sections whose names are valid C89template <class ELFT>
59// identifiers, so we just store a std::vector instead of a multimap.90template <class RelTy>
60static DenseMap<StringRef, std::vector<InputSectionBase *>> CNamedSections;91void MarkLive<ELFT>::resolveReloc(InputSectionBase &sec, RelTy &rel,
6192 bool isLSDA) {
62template <class ELFT, class RelT>93 Symbol &sym = sec.getFile<ELFT>()->getRelocTargetSym(rel);
63static void
64resolveReloc(InputSectionBase &Sec, RelT &Rel,
65 llvm::function_ref<void(InputSectionBase *, uint64_t)> Fn) {
66 Symbol &B = Sec.getFile<ELFT>()->getRelocTargetSym(Rel);
6794
68 // If a symbol is referenced in a live section, it is used.95 // If a symbol is referenced in a live section, it is used.
69 B.Used = true;96 sym.used = true;
70 if (auto *SS = dyn_cast<SharedSymbol>(&B))97
71 if (!SS->isWeak())98 if (auto *d = dyn_cast<Defined>(&sym)) {
72 SS->getFile<ELFT>().IsNeeded = true;99 auto *relSec = dyn_cast_or_null<InputSectionBase>(d->section);
73100 if (!relSec)
74 if (auto *D = dyn_cast<Defined>(&B)) {
75 auto *RelSec = dyn_cast_or_null<InputSectionBase>(D->Section);
76 if (!RelSec)
77 return;101 return;
78 uint64_t Offset = D->Value;
79 if (D->isSection())
80 Offset += getAddend<ELFT>(Sec, Rel);
81 Fn(RelSec, Offset);
82 return;
83 }
84102
85 if (!B.isDefined())103 uint64_t offset = d->value;
86 for (InputSectionBase *Sec : CNamedSections.lookup(B.getName()))104 if (d->isSection())
87 Fn(Sec, 0);105 offset += getAddend<ELFT>(sec, rel);
88}
89106
90// Calls Fn for each section that Sec refers to via relocations.107 if (!isLSDA || !(relSec->flags & SHF_EXECINSTR))
91template <class ELFT>108 enqueue(relSec, offset);
92static void109 return;
93forEachSuccessor(InputSection &Sec,
94 llvm::function_ref<void(InputSectionBase *, uint64_t)> Fn) {
95 if (Sec.AreRelocsRela) {
96 for (const typename ELFT::Rela &Rel : Sec.template relas<ELFT>())
97 resolveReloc<ELFT>(Sec, Rel, Fn);
98 } else {
99 for (const typename ELFT::Rel &Rel : Sec.template rels<ELFT>())
100 resolveReloc<ELFT>(Sec, Rel, Fn);
101 }110 }
102111
103 for (InputSectionBase *IS : Sec.DependentSections)112 if (auto *ss = dyn_cast<SharedSymbol>(&sym))
104 Fn(IS, 0);113 if (!ss->isWeak())
114 ss->getFile().isNeeded = true;
115
116 for (InputSectionBase *sec : cNamedSections.lookup(sym.getName()))
117 enqueue(sec, 0);
105}118}
106119
107// The .eh_frame section is an unfortunate special case.120// The .eh_frame section is an unfortunate special case.
...@@ -118,175 +131,203 @@ forEachSuccessor(InputSection &Sec,...@@ -118,175 +131,203 @@ forEachSuccessor(InputSection &Sec,
118// A possible improvement would be to fully process .eh_frame in the middle of131// A possible improvement would be to fully process .eh_frame in the middle of
119// the gc pass. With that we would be able to also gc some sections holding132// the gc pass. With that we would be able to also gc some sections holding
120// LSDAs and personality functions if we found that they were unused.133// LSDAs and personality functions if we found that they were unused.
121template <class ELFT, class RelTy>134template <class ELFT>
122static void135template <class RelTy>
123scanEhFrameSection(EhInputSection &EH, ArrayRef<RelTy> Rels,136void MarkLive<ELFT>::scanEhFrameSection(EhInputSection &eh,
124 llvm::function_ref<void(InputSectionBase *, uint64_t)> Fn) {137 ArrayRef<RelTy> rels) {
125 const endianness E = ELFT::TargetEndianness;138 for (size_t i = 0, end = eh.pieces.size(); i < end; ++i) {
126139 EhSectionPiece &piece = eh.pieces[i];
127 for (unsigned I = 0, N = EH.Pieces.size(); I < N; ++I) {140 size_t firstRelI = piece.firstRelocation;
128 EhSectionPiece &Piece = EH.Pieces[I];141 if (firstRelI == (unsigned)-1)
129 unsigned FirstRelI = Piece.FirstRelocation;
130 if (FirstRelI == (unsigned)-1)
131 continue;142 continue;
132 if (read32<E>(Piece.data().data() + 4) == 0) {143
144 if (read32<ELFT::TargetEndianness>(piece.data().data() + 4) == 0) {
133 // This is a CIE, we only need to worry about the first relocation. It is145 // This is a CIE, we only need to worry about the first relocation. It is
134 // known to point to the personality function.146 // known to point to the personality function.
135 resolveReloc<ELFT>(EH, Rels[FirstRelI], Fn);147 resolveReloc(eh, rels[firstRelI], false);
136 continue;148 continue;
137 }149 }
150
138 // This is a FDE. The relocations point to the described function or to151 // This is a FDE. The relocations point to the described function or to
139 // a LSDA. We only need to keep the LSDA alive, so ignore anything that152 // a LSDA. We only need to keep the LSDA alive, so ignore anything that
140 // points to executable sections.153 // points to executable sections.
141 typename ELFT::uint PieceEnd = Piece.InputOff + Piece.Size;154 uint64_t pieceEnd = piece.inputOff + piece.size;
142 for (unsigned I2 = FirstRelI, N2 = Rels.size(); I2 < N2; ++I2) {155 for (size_t j = firstRelI, end2 = rels.size(); j < end2; ++j)
143 const RelTy &Rel = Rels[I2];156 if (rels[j].r_offset < pieceEnd)
144 if (Rel.r_offset >= PieceEnd)157 resolveReloc(eh, rels[j], true);
145 break;
146 resolveReloc<ELFT>(EH, Rels[I2],
147 [&](InputSectionBase *Sec, uint64_t Offset) {
148 if (Sec && Sec != &InputSection::Discarded &&
149 !(Sec->Flags & SHF_EXECINSTR))
150 Fn(Sec, 0);
151 });
152 }
153 }158 }
154}159}
155160
156template <class ELFT>
157static void
158scanEhFrameSection(EhInputSection &EH,
159 llvm::function_ref<void(InputSectionBase *, uint64_t)> Fn) {
160 if (!EH.NumRelocations)
161 return;
162
163 if (EH.AreRelocsRela)
164 scanEhFrameSection<ELFT>(EH, EH.template relas<ELFT>(), Fn);
165 else
166 scanEhFrameSection<ELFT>(EH, EH.template rels<ELFT>(), Fn);
167}
168
169// Some sections are used directly by the loader, so they should never be161// Some sections are used directly by the loader, so they should never be
170// garbage-collected. This function returns true if a given section is such162// garbage-collected. This function returns true if a given section is such
171// section.163// section.
172template <class ELFT> static bool isReserved(InputSectionBase *Sec) {164static bool isReserved(InputSectionBase *sec) {
173 switch (Sec->Type) {165 switch (sec->type) {
174 case SHT_FINI_ARRAY:166 case SHT_FINI_ARRAY:
175 case SHT_INIT_ARRAY:167 case SHT_INIT_ARRAY:
176 case SHT_NOTE:168 case SHT_NOTE:
177 case SHT_PREINIT_ARRAY:169 case SHT_PREINIT_ARRAY:
178 return true;170 return true;
179 default:171 default:
180 StringRef S = Sec->Name;172 StringRef s = sec->name;
181 return S.startswith(".ctors") || S.startswith(".dtors") ||173 return s.startswith(".ctors") || s.startswith(".dtors") ||
182 S.startswith(".init") || S.startswith(".fini") ||174 s.startswith(".init") || s.startswith(".fini") ||
183 S.startswith(".jcr");175 s.startswith(".jcr");
184 }176 }
185}177}
186178
187// This is the main function of the garbage collector.179template <class ELFT>
188// Starting from GC-root sections, this function visits all reachable180void MarkLive<ELFT>::enqueue(InputSectionBase *sec, uint64_t offset) {
189// sections to set their "Live" bits.181 // Skip over discarded sections. This in theory shouldn't happen, because
190template <class ELFT> static void doGcSections() {182 // the ELF spec doesn't allow a relocation to point to a deduplicated
191 SmallVector<InputSection *, 256> Q;183 // COMDAT section directly. Unfortunately this happens in practice (e.g.
192 CNamedSections.clear();184 // .eh_frame) so we need to add a check.
193185 if (sec == &InputSection::discarded)
194 auto Enqueue = [&](InputSectionBase *Sec, uint64_t Offset) {186 return;
195 // Skip over discarded sections. This in theory shouldn't happen, because
196 // the ELF spec doesn't allow a relocation to point to a deduplicated
197 // COMDAT section directly. Unfortunately this happens in practice (e.g.
198 // .eh_frame) so we need to add a check.
199 if (Sec == &InputSection::Discarded)
200 return;
201
202187
203 // Usually, a whole section is marked as live or dead, but in mergeable188 // Usually, a whole section is marked as live or dead, but in mergeable
204 // (splittable) sections, each piece of data has independent liveness bit.189 // (splittable) sections, each piece of data has independent liveness bit.
205 // So we explicitly tell it which offset is in use.190 // So we explicitly tell it which offset is in use.
206 if (auto *MS = dyn_cast<MergeInputSection>(Sec))191 if (auto *ms = dyn_cast<MergeInputSection>(sec))
207 MS->getSectionPiece(Offset)->Live = true;192 ms->getSectionPiece(offset)->live = true;
208193
209 if (Sec->Live)194 // Set Sec->Partition to the meet (i.e. the "minimum") of Partition and
210 return;195 // Sec->Partition in the following lattice: 1 < other < 0. If Sec->Partition
211 Sec->Live = true;196 // doesn't change, we don't need to do anything.
197 if (sec->partition == 1 || sec->partition == partition)
198 return;
199 sec->partition = sec->partition ? 1 : partition;
212200
213 // Add input section to the queue.201 // Add input section to the queue.
214 if (InputSection *S = dyn_cast<InputSection>(Sec))202 if (InputSection *s = dyn_cast<InputSection>(sec))
215 Q.push_back(S);203 queue.push_back(s);
216 };204}
217205
218 auto MarkSymbol = [&](Symbol *Sym) {206template <class ELFT> void MarkLive<ELFT>::markSymbol(Symbol *sym) {
219 if (auto *D = dyn_cast_or_null<Defined>(Sym))207 if (auto *d = dyn_cast_or_null<Defined>(sym))
220 if (auto *IS = dyn_cast_or_null<InputSectionBase>(D->Section))208 if (auto *isec = dyn_cast_or_null<InputSectionBase>(d->section))
221 Enqueue(IS, D->Value);209 enqueue(isec, d->value);
222 };210}
223211
212// This is the main function of the garbage collector.
213// Starting from GC-root sections, this function visits all reachable
214// sections to set their "Live" bits.
215template <class ELFT> void MarkLive<ELFT>::run() {
224 // Add GC root symbols.216 // Add GC root symbols.
225 MarkSymbol(Symtab->find(Config->Entry));
226 MarkSymbol(Symtab->find(Config->Init));
227 MarkSymbol(Symtab->find(Config->Fini));
228 for (StringRef S : Config->Undefined)
229 MarkSymbol(Symtab->find(S));
230 for (StringRef S : Script->ReferencedSymbols)
231 MarkSymbol(Symtab->find(S));
232217
233 // Preserve externally-visible symbols if the symbols defined by this218 // Preserve externally-visible symbols if the symbols defined by this
234 // file can interrupt other ELF file's symbols at runtime.219 // file can interrupt other ELF file's symbols at runtime.
235 for (Symbol *S : Symtab->getSymbols())220 symtab->forEachSymbol([&](Symbol *sym) {
236 if (S->includeInDynsym())221 if (sym->includeInDynsym() && sym->partition == partition)
237 MarkSymbol(S);222 markSymbol(sym);
223 });
224
225 // If this isn't the main partition, that's all that we need to preserve.
226 if (partition != 1) {
227 mark();
228 return;
229 }
230
231 markSymbol(symtab->find(config->entry));
232 markSymbol(symtab->find(config->init));
233 markSymbol(symtab->find(config->fini));
234 for (StringRef s : config->undefined)
235 markSymbol(symtab->find(s));
236 for (StringRef s : script->referencedSymbols)
237 markSymbol(symtab->find(s));
238238
239 // Preserve special sections and those which are specified in linker239 // Preserve special sections and those which are specified in linker
240 // script KEEP command.240 // script KEEP command.
241 for (InputSectionBase *Sec : InputSections) {241 for (InputSectionBase *sec : inputSections) {
242 // Mark .eh_frame sections as live because there are usually no relocations242 // Mark .eh_frame sections as live because there are usually no relocations
243 // that point to .eh_frames. Otherwise, the garbage collector would drop243 // that point to .eh_frames. Otherwise, the garbage collector would drop
244 // all of them. We also want to preserve personality routines and LSDA244 // all of them. We also want to preserve personality routines and LSDA
245 // referenced by .eh_frame sections, so we scan them for that here.245 // referenced by .eh_frame sections, so we scan them for that here.
246 if (auto *EH = dyn_cast<EhInputSection>(Sec)) {246 if (auto *eh = dyn_cast<EhInputSection>(sec)) {
247 EH->Live = true;247 eh->markLive();
248 scanEhFrameSection<ELFT>(*EH, Enqueue);248 if (!eh->numRelocations)
249 continue;
250
251 if (eh->areRelocsRela)
252 scanEhFrameSection(*eh, eh->template relas<ELFT>());
253 else
254 scanEhFrameSection(*eh, eh->template rels<ELFT>());
249 }255 }
250256
251 if (Sec->Flags & SHF_LINK_ORDER)257 if (sec->flags & SHF_LINK_ORDER)
252 continue;258 continue;
253259
254 if (isReserved<ELFT>(Sec) || Script->shouldKeep(Sec)) {260 if (isReserved(sec) || script->shouldKeep(sec)) {
255 Enqueue(Sec, 0);261 enqueue(sec, 0);
256 } else if (isValidCIdentifier(Sec->Name)) {262 } else if (isValidCIdentifier(sec->name)) {
257 CNamedSections[Saver.save("__start_" + Sec->Name)].push_back(Sec);263 cNamedSections[saver.save("__start_" + sec->name)].push_back(sec);
258 CNamedSections[Saver.save("__stop_" + Sec->Name)].push_back(Sec);264 cNamedSections[saver.save("__stop_" + sec->name)].push_back(sec);
259 }265 }
260 }266 }
261267
268 mark();
269}
270
271template <class ELFT> void MarkLive<ELFT>::mark() {
262 // Mark all reachable sections.272 // Mark all reachable sections.
263 while (!Q.empty())273 while (!queue.empty()) {
264 forEachSuccessor<ELFT>(*Q.pop_back_val(), Enqueue);274 InputSectionBase &sec = *queue.pop_back_val();
275
276 if (sec.areRelocsRela) {
277 for (const typename ELFT::Rela &rel : sec.template relas<ELFT>())
278 resolveReloc(sec, rel, false);
279 } else {
280 for (const typename ELFT::Rel &rel : sec.template rels<ELFT>())
281 resolveReloc(sec, rel, false);
282 }
283
284 for (InputSectionBase *isec : sec.dependentSections)
285 enqueue(isec, 0);
286 }
287}
288
289// Move the sections for some symbols to the main partition, specifically ifuncs
290// (because they can result in an IRELATIVE being added to the main partition's
291// GOT, which means that the ifunc must be available when the main partition is
292// loaded) and TLS symbols (because we only know how to correctly process TLS
293// relocations for the main partition).
294template <class ELFT> void MarkLive<ELFT>::moveToMain() {
295 for (InputFile *file : objectFiles)
296 for (Symbol *s : file->getSymbols())
297 if (auto *d = dyn_cast<Defined>(s))
298 if ((d->type == STT_GNU_IFUNC || d->type == STT_TLS) && d->section &&
299 d->section->isLive())
300 markSymbol(s);
301
302 mark();
265}303}
266304
267// Before calling this function, Live bits are off for all305// Before calling this function, Live bits are off for all
268// input sections. This function make some or all of them on306// input sections. This function make some or all of them on
269// so that they are emitted to the output file.307// so that they are emitted to the output file.
270template <class ELFT> void elf::markLive() {308template <class ELFT> void elf::markLive() {
271 if (!Config->GcSections) {309 // If -gc-sections is not given, no sections are removed.
272 // If -gc-sections is missing, no sections are removed.310 if (!config->gcSections) {
273 for (InputSectionBase *Sec : InputSections)311 for (InputSectionBase *sec : inputSections)
274 Sec->Live = true;312 sec->markLive();
275313
276 // If a DSO defines a symbol referenced in a regular object, it is needed.314 // If a DSO defines a symbol referenced in a regular object, it is needed.
277 for (Symbol *Sym : Symtab->getSymbols())315 symtab->forEachSymbol([](Symbol *sym) {
278 if (auto *S = dyn_cast<SharedSymbol>(Sym))316 if (auto *s = dyn_cast<SharedSymbol>(sym))
279 if (S->IsUsedInRegularObj && !S->isWeak())317 if (s->isUsedInRegularObj && !s->isWeak())
280 S->getFile<ELFT>().IsNeeded = true;318 s->getFile().isNeeded = true;
319 });
281 return;320 return;
282 }321 }
283322
323 // Otheriwse, do mark-sweep GC.
324 //
284 // The -gc-sections option works only for SHF_ALLOC sections325 // The -gc-sections option works only for SHF_ALLOC sections
285 // (sections that are memory-mapped at runtime). So we can326 // (sections that are memory-mapped at runtime). So we can
286 // unconditionally make non-SHF_ALLOC sections alive except327 // unconditionally make non-SHF_ALLOC sections alive except
287 // SHF_LINK_ORDER and SHT_REL/SHT_RELA sections.328 // SHF_LINK_ORDER and SHT_REL/SHT_RELA sections.
288 //329 //
289 // Usually, SHF_ALLOC sections are not removed even if they are330 // Usually, non-SHF_ALLOC sections are not removed even if they are
290 // unreachable through relocations because reachability is not331 // unreachable through relocations because reachability is not
291 // a good signal whether they are garbage or not (e.g. there is332 // a good signal whether they are garbage or not (e.g. there is
292 // usually no section referring to a .comment section, but we333 // usually no section referring to a .comment section, but we
...@@ -300,22 +341,30 @@ template <class ELFT> void elf::markLive() {...@@ -300,22 +341,30 @@ template <class ELFT> void elf::markLive() {
300 // or -emit-reloc were given. And they are subject of garbage341 // or -emit-reloc were given. And they are subject of garbage
301 // collection because, if we remove a text section, we also342 // collection because, if we remove a text section, we also
302 // remove its relocation section.343 // remove its relocation section.
303 for (InputSectionBase *Sec : InputSections) {344 for (InputSectionBase *sec : inputSections) {
304 bool IsAlloc = (Sec->Flags & SHF_ALLOC);345 bool isAlloc = (sec->flags & SHF_ALLOC);
305 bool IsLinkOrder = (Sec->Flags & SHF_LINK_ORDER);346 bool isLinkOrder = (sec->flags & SHF_LINK_ORDER);
306 bool IsRel = (Sec->Type == SHT_REL || Sec->Type == SHT_RELA);347 bool isRel = (sec->type == SHT_REL || sec->type == SHT_RELA);
307 if (!IsAlloc && !IsLinkOrder && !IsRel)348
308 Sec->Live = true;349 if (!isAlloc && !isLinkOrder && !isRel)
350 sec->markLive();
309 }351 }
310352
311 // Follow the graph to mark all live sections.353 // Follow the graph to mark all live sections.
312 doGcSections<ELFT>();354 for (unsigned curPart = 1; curPart <= partitions.size(); ++curPart)
355 MarkLive<ELFT>(curPart).run();
356
357 // If we have multiple partitions, some sections need to live in the main
358 // partition even if they were allocated to a loadable partition. Move them
359 // there now.
360 if (partitions.size() != 1)
361 MarkLive<ELFT>(1).moveToMain();
313362
314 // Report garbage-collected sections.363 // Report garbage-collected sections.
315 if (Config->PrintGcSections)364 if (config->printGcSections)
316 for (InputSectionBase *Sec : InputSections)365 for (InputSectionBase *sec : inputSections)
317 if (!Sec->Live)366 if (!sec->isLive())
318 message("removing unused section " + toString(Sec));367 message("removing unused section " + toString(sec));
319}368}
320369
321template void elf::markLive<ELF32LE>();370template void elf::markLive<ELF32LE>();
deps/lld/ELF/MarkLive.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MarkLive.h -----------------------------------------------*- C++ -*-===//1//===- MarkLive.h -----------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/ELF/Options.td+51-4
...@@ -63,10 +63,18 @@ defm allow_multiple_definition: B<"allow-multiple-definition",...@@ -63,10 +63,18 @@ defm allow_multiple_definition: B<"allow-multiple-definition",
63 "Allow multiple definitions",63 "Allow multiple definitions",
64 "Do not allow multiple definitions (default)">;64 "Do not allow multiple definitions (default)">;
6565
66defm allow_shlib_undefined: B<"allow-shlib-undefined",
67 "Allow unresolved references in shared libraries (default when linking a shared library)",
68 "Do not allow unresolved references in shared libraries (default when linking an executable)">;
69
66defm apply_dynamic_relocs: B<"apply-dynamic-relocs",70defm apply_dynamic_relocs: B<"apply-dynamic-relocs",
67 "Apply link-time values for dynamic relocations",71 "Apply link-time values for dynamic relocations",
68 "Do not apply link-time values for dynamic relocations (default)">;72 "Do not apply link-time values for dynamic relocations (default)">;
6973
74defm dependent_libraries: B<"dependent-libraries",
75 "Process dependent library specifiers from input files (default)",
76 "Ignore dependent library specifiers from input files">;
77
70defm as_needed: B<"as-needed",78defm as_needed: B<"as-needed",
71 "Only set DT_NEEDED for shared libraries if used",79 "Only set DT_NEEDED for shared libraries if used",
72 "Always set DT_NEEDED for shared libraries (default)">;80 "Always set DT_NEEDED for shared libraries (default)">;
...@@ -163,6 +171,13 @@ defm fini: Eq<"fini", "Specify a finalizer function">, MetaVarName<"<symbol>">;...@@ -163,6 +171,13 @@ defm fini: Eq<"fini", "Specify a finalizer function">, MetaVarName<"<symbol>">;
163def fix_cortex_a53_843419: F<"fix-cortex-a53-843419">,171def fix_cortex_a53_843419: F<"fix-cortex-a53-843419">,
164 HelpText<"Apply fixes for AArch64 Cortex-A53 erratum 843419">;172 HelpText<"Apply fixes for AArch64 Cortex-A53 erratum 843419">;
165173
174// This option is intentionally hidden from the user as the implementation
175// is not complete.
176def require_cet: F<"require-cet">;
177
178def force_bti: F<"force-bti">,
179 HelpText<"Force enable AArch64 BTI in PLT, warn if Input ELF file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property">;
180
166defm format: Eq<"format", "Change the input format of the inputs following this option">,181defm format: Eq<"format", "Change the input format of the inputs following this option">,
167 MetaVarName<"[default,elf,binary]">;182 MetaVarName<"[default,elf,binary]">;
168183
...@@ -214,6 +229,9 @@ defm merge_exidx_entries: B<"merge-exidx-entries",...@@ -214,6 +229,9 @@ defm merge_exidx_entries: B<"merge-exidx-entries",
214 "Enable merging .ARM.exidx entries (default)",229 "Enable merging .ARM.exidx entries (default)",
215 "Disable merging .ARM.exidx entries">;230 "Disable merging .ARM.exidx entries">;
216231
232def nmagic: F<"nmagic">, MetaVarName<"<magic>">,
233 HelpText<"Do not page align sections, link against static libraries.">;
234
217def nostdlib: F<"nostdlib">,235def nostdlib: F<"nostdlib">,
218 HelpText<"Only search directories specified on the command line">;236 HelpText<"Only search directories specified on the command line">;
219237
...@@ -226,8 +244,11 @@ def no_dynamic_linker: F<"no-dynamic-linker">,...@@ -226,8 +244,11 @@ def no_dynamic_linker: F<"no-dynamic-linker">,
226def noinhibit_exec: F<"noinhibit-exec">,244def noinhibit_exec: F<"noinhibit-exec">,
227 HelpText<"Retain the executable output file whenever it is still usable">;245 HelpText<"Retain the executable output file whenever it is still usable">;
228246
247def no_nmagic: F<"no-nmagic">, MetaVarName<"<magic>">,
248 HelpText<"Page align sections (default)">;
249
229def no_omagic: F<"no-omagic">, MetaVarName<"<magic>">,250def no_omagic: F<"no-omagic">, MetaVarName<"<magic>">,
230 HelpText<"Do not set the text data sections to be writable">;251 HelpText<"Do not set the text data sections to be writable, page align sections (default)">;
231252
232def no_rosegment: F<"no-rosegment">,253def no_rosegment: F<"no-rosegment">,
233 HelpText<"Do not put read-only non-executable sections in their own segment">;254 HelpText<"Do not put read-only non-executable sections in their own segment">;
...@@ -242,7 +263,7 @@ def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">,...@@ -242,7 +263,7 @@ def oformat: Separate<["--"], "oformat">, MetaVarName<"<format>">,
242 HelpText<"Specify the binary format for the output object file">;263 HelpText<"Specify the binary format for the output object file">;
243264
244def omagic: Flag<["--"], "omagic">, MetaVarName<"<magic>">,265def omagic: Flag<["--"], "omagic">, MetaVarName<"<magic>">,
245 HelpText<"Set the text and data sections to be readable and writable">;266 HelpText<"Set the text and data sections to be readable and writable, do not page align sections, link against static libraries">;
246267
247defm orphan_handling:268defm orphan_handling:
248 Eq<"orphan-handling", "Control how orphan sections are handled when linker script used">;269 Eq<"orphan-handling", "Control how orphan sections are handled when linker script used">;
...@@ -251,6 +272,9 @@ defm pack_dyn_relocs:...@@ -251,6 +272,9 @@ defm pack_dyn_relocs:
251 Eq<"pack-dyn-relocs", "Pack dynamic relocations in the given format">,272 Eq<"pack-dyn-relocs", "Pack dynamic relocations in the given format">,
252 MetaVarName<"[none,android,relr,android+relr]">;273 MetaVarName<"[none,android,relr,android+relr]">;
253274
275def pac_plt: F<"pac-plt">,
276 HelpText<"AArch64 only, use pointer authentication in PLT">;
277
254defm use_android_relr_tags: B<"use-android-relr-tags",278defm use_android_relr_tags: B<"use-android-relr-tags",
255 "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",279 "Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*",
256 "Use SHT_RELR / DT_RELR* tags (default)">;280 "Use SHT_RELR / DT_RELR* tags (default)">;
...@@ -270,6 +294,9 @@ defm print_icf_sections: B<"print-icf-sections",...@@ -270,6 +294,9 @@ defm print_icf_sections: B<"print-icf-sections",
270 "List identical folded sections",294 "List identical folded sections",
271 "Do not list identical folded sections (default)">;295 "Do not list identical folded sections (default)">;
272296
297defm print_symbol_order: Eq<"print-symbol-order",
298 "Print a symbol order specified by --call-graph-ordering-file into the speficied file">;
299
273def pop_state: F<"pop-state">,300def pop_state: F<"pop-state">,
274 HelpText<"Undo the effect of -push-state">;301 HelpText<"Undo the effect of -push-state">;
275302
...@@ -339,6 +366,9 @@ defm trace_symbol: Eq<"trace-symbol", "Trace references to symbols">;...@@ -339,6 +366,9 @@ defm trace_symbol: Eq<"trace-symbol", "Trace references to symbols">;
339defm undefined: Eq<"undefined", "Force undefined symbol during linking">,366defm undefined: Eq<"undefined", "Force undefined symbol during linking">,
340 MetaVarName<"<symbol>">;367 MetaVarName<"<symbol>">;
341368
369defm undefined_glob: Eq<"undefined-glob", "Force undefined symbol during linking">,
370 MetaVarName<"<pattern>">;
371
342defm unresolved_symbols:372defm unresolved_symbols:
343 Eq<"unresolved-symbols", "Determine how to handle unresolved symbols">;373 Eq<"unresolved-symbols", "Determine how to handle unresolved symbols">;
344374
...@@ -386,6 +416,9 @@ defm wrap: Eq<"wrap", "Use wrapper functions for symbol">,...@@ -386,6 +416,9 @@ defm wrap: Eq<"wrap", "Use wrapper functions for symbol">,
386def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,416def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
387 HelpText<"Linker option extensions">;417 HelpText<"Linker option extensions">;
388418
419def visual_studio_diagnostics_format : F<"vs-diagnostics">,
420HelpText<"Format diagnostics for Visual Studio compatiblity">;
421
389// Aliases422// Aliases
390def: Separate<["-"], "f">, Alias<auxiliary>, HelpText<"Alias for --auxiliary">;423def: Separate<["-"], "f">, Alias<auxiliary>, HelpText<"Alias for --auxiliary">;
391def: F<"call_shared">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;424def: F<"call_shared">, Alias<Bdynamic>, HelpText<"Alias for --Bdynamic">;
...@@ -407,6 +440,7 @@ def: Separate<["-"], "b">, Alias<format>, HelpText<"Alias for --format">;...@@ -407,6 +440,7 @@ def: Separate<["-"], "b">, Alias<format>, HelpText<"Alias for --format">;
407def: JoinedOrSeparate<["-"], "l">, Alias<library>, HelpText<"Alias for --library">;440def: JoinedOrSeparate<["-"], "l">, Alias<library>, HelpText<"Alias for --library">;
408def: JoinedOrSeparate<["-"], "L">, Alias<library_path>, HelpText<"Alias for --library-path">;441def: JoinedOrSeparate<["-"], "L">, Alias<library_path>, HelpText<"Alias for --library-path">;
409def: F<"no-pic-executable">, Alias<no_pie>, HelpText<"Alias for --no-pie">;442def: F<"no-pic-executable">, Alias<no_pie>, HelpText<"Alias for --no-pie">;
443def: Flag<["-"], "n">, Alias<nmagic>, HelpText<"Alias for --nmagic">;
410def: Flag<["-"], "N">, Alias<omagic>, HelpText<"Alias for --omagic">;444def: Flag<["-"], "N">, Alias<omagic>, HelpText<"Alias for --omagic">;
411def: Joined<["--"], "output=">, Alias<o>, HelpText<"Alias for -o">;445def: Joined<["--"], "output=">, Alias<o>, HelpText<"Alias for -o">;
412def: Separate<["--"], "output">, Alias<o>, HelpText<"Alias for -o">;446def: Separate<["--"], "output">, Alias<o>, HelpText<"Alias for -o">;
...@@ -440,14 +474,22 @@ def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">,...@@ -440,14 +474,22 @@ def lto_O: J<"lto-O">, MetaVarName<"<opt-level>">,
440 HelpText<"Optimization level for LTO">;474 HelpText<"Optimization level for LTO">;
441def lto_partitions: J<"lto-partitions=">,475def lto_partitions: J<"lto-partitions=">,
442 HelpText<"Number of LTO codegen partitions">;476 HelpText<"Number of LTO codegen partitions">;
477def lto_cs_profile_generate: F<"lto-cs-profile-generate">,
478 HelpText<"Perform context senstive PGO instrumentation">;
479def lto_cs_profile_file: J<"lto-cs-profile-file=">,
480 HelpText<"Context sensitive profile file path">;
443def lto_sample_profile: J<"lto-sample-profile=">,481def lto_sample_profile: J<"lto-sample-profile=">,
444 HelpText<"Sample profile file path">;482 HelpText<"Sample profile file path">;
445def disable_verify: F<"disable-verify">;483def disable_verify: F<"disable-verify">;
446defm mllvm: Eq<"mllvm", "Additional arguments to forward to LLVM's option processing">;484defm mllvm: Eq<"mllvm", "Additional arguments to forward to LLVM's option processing">;
447def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">,485def opt_remarks_filename: Separate<["--"], "opt-remarks-filename">,
448 HelpText<"YAML output file for optimization remarks">;486 HelpText<"YAML output file for optimization remarks">;
487def opt_remarks_passes: Separate<["--"], "opt-remarks-passes">,
488 HelpText<"Regex for the passes that need to be serialized to the output file">;
449def opt_remarks_with_hotness: Flag<["--"], "opt-remarks-with-hotness">,489def opt_remarks_with_hotness: Flag<["--"], "opt-remarks-with-hotness">,
450 HelpText<"Include hotness information in the optimization remarks file">;490 HelpText<"Include hotness information in the optimization remarks file">;
491def opt_remarks_format: Separate<["--"], "opt-remarks-format">,
492 HelpText<"The format used for serializing remarks (default: YAML)">;
451defm plugin_opt: Eq<"plugin-opt", "specifies LTO options for compatibility with GNU linkers">;493defm plugin_opt: Eq<"plugin-opt", "specifies LTO options for compatibility with GNU linkers">;
452def save_temps: F<"save-temps">;494def save_temps: F<"save-temps">;
453def thinlto_cache_dir: J<"thinlto-cache-dir=">,495def thinlto_cache_dir: J<"thinlto-cache-dir=">,
...@@ -468,6 +510,10 @@ def plugin_opt_mcpu_eq: J<"plugin-opt=mcpu=">;...@@ -468,6 +510,10 @@ def plugin_opt_mcpu_eq: J<"plugin-opt=mcpu=">;
468def: F<"plugin-opt=new-pass-manager">,510def: F<"plugin-opt=new-pass-manager">,
469 Alias<lto_new_pass_manager>, HelpText<"Alias for -lto-new-pass-manager">;511 Alias<lto_new_pass_manager>, HelpText<"Alias for -lto-new-pass-manager">;
470def plugin_opt_obj_path_eq: J<"plugin-opt=obj-path=">;512def plugin_opt_obj_path_eq: J<"plugin-opt=obj-path=">;
513def: F<"plugin-opt=cs-profile-generate">,
514 Alias<lto_cs_profile_generate>, HelpText<"Alias for -lto-cs-profile-generate">;
515def: J<"plugin-opt=cs-profile-path=">,
516 Alias<lto_cs_profile_file>, HelpText<"Alias for -lto-cs-profile-file">;
471def: J<"plugin-opt=sample-profile=">,517def: J<"plugin-opt=sample-profile=">,
472 Alias<lto_sample_profile>, HelpText<"Alias for -lto-sample-profile">;518 Alias<lto_sample_profile>, HelpText<"Alias for -lto-sample-profile">;
473def: F<"plugin-opt=save-temps">, Alias<save_temps>, HelpText<"Alias for -save-temps">;519def: F<"plugin-opt=save-temps">, Alias<save_temps>, HelpText<"Alias for -save-temps">;
...@@ -492,19 +538,20 @@ def plugin_opt_thinlto: J<"plugin-opt=thinlto">;...@@ -492,19 +538,20 @@ def plugin_opt_thinlto: J<"plugin-opt=thinlto">;
492def plugin_opt_slash: J<"plugin-opt=/">;538def plugin_opt_slash: J<"plugin-opt=/">;
493539
494// Options listed below are silently ignored for now for compatibility.540// Options listed below are silently ignored for now for compatibility.
495def: F<"allow-shlib-undefined">;
496def: F<"detect-odr-violations">;541def: F<"detect-odr-violations">;
497def: Flag<["-"], "g">;542def: Flag<["-"], "g">;
498def: F<"long-plt">;543def: F<"long-plt">;
499def: F<"no-add-needed">;544def: F<"no-add-needed">;
500def: F<"no-allow-shlib-undefined">;
501def: F<"no-copy-dt-needed-entries">;545def: F<"no-copy-dt-needed-entries">;
502def: F<"no-ctors-in-init-array">;546def: F<"no-ctors-in-init-array">;
503def: F<"no-keep-memory">;547def: F<"no-keep-memory">;
504def: F<"no-mmap-output-file">;548def: F<"no-mmap-output-file">;
549def: F<"no-pipeline-knowledge">;
505def: F<"no-warn-mismatch">;550def: F<"no-warn-mismatch">;
551def: Flag<["-"], "p">;
506def: Separate<["--", "-"], "rpath-link">;552def: Separate<["--", "-"], "rpath-link">;
507def: J<"rpath-link=">;553def: J<"rpath-link=">;
554def: F<"secure-plt">;
508def: F<"sort-common">;555def: F<"sort-common">;
509def: F<"stats">;556def: F<"stats">;
510def: F<"warn-execstack">;557def: F<"warn-execstack">;
deps/lld/ELF/OutputSections.cpp+213-229
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- OutputSections.cpp -------------------------------------------------===//1//===- OutputSections.cpp -------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -31,47 +30,46 @@ using namespace llvm::ELF;...@@ -31,47 +30,46 @@ using namespace llvm::ELF;
31using namespace lld;30using namespace lld;
32using namespace lld::elf;31using namespace lld::elf;
3332
34uint8_t Out::First;33uint8_t *Out::bufferStart;
35PhdrEntry *Out::TlsPhdr;34uint8_t Out::first;
36OutputSection *Out::ElfHeader;35PhdrEntry *Out::tlsPhdr;
37OutputSection *Out::ProgramHeaders;36OutputSection *Out::elfHeader;
38OutputSection *Out::PreinitArray;37OutputSection *Out::programHeaders;
39OutputSection *Out::InitArray;38OutputSection *Out::preinitArray;
40OutputSection *Out::FiniArray;39OutputSection *Out::initArray;
40OutputSection *Out::finiArray;
4141
42std::vector<OutputSection *> elf::OutputSections;42std::vector<OutputSection *> elf::outputSections;
4343
44uint32_t OutputSection::getPhdrFlags() const {44uint32_t OutputSection::getPhdrFlags() const {
45 uint32_t Ret = 0;45 uint32_t ret = 0;
46 if (Config->EMachine != EM_ARM || !(Flags & SHF_ARM_PURECODE))46 if (config->emachine != EM_ARM || !(flags & SHF_ARM_PURECODE))
47 Ret |= PF_R;47 ret |= PF_R;
48 if (Flags & SHF_WRITE)48 if (flags & SHF_WRITE)
49 Ret |= PF_W;49 ret |= PF_W;
50 if (Flags & SHF_EXECINSTR)50 if (flags & SHF_EXECINSTR)
51 Ret |= PF_X;51 ret |= PF_X;
52 return Ret;52 return ret;
53}53}
5454
55template <class ELFT>55template <class ELFT>
56void OutputSection::writeHeaderTo(typename ELFT::Shdr *Shdr) {56void OutputSection::writeHeaderTo(typename ELFT::Shdr *shdr) {
57 Shdr->sh_entsize = Entsize;57 shdr->sh_entsize = entsize;
58 Shdr->sh_addralign = Alignment;58 shdr->sh_addralign = alignment;
59 Shdr->sh_type = Type;59 shdr->sh_type = type;
60 Shdr->sh_offset = Offset;60 shdr->sh_offset = offset;
61 Shdr->sh_flags = Flags;61 shdr->sh_flags = flags;
62 Shdr->sh_info = Info;62 shdr->sh_info = info;
63 Shdr->sh_link = Link;63 shdr->sh_link = link;
64 Shdr->sh_addr = Addr;64 shdr->sh_addr = addr;
65 Shdr->sh_size = Size;65 shdr->sh_size = size;
66 Shdr->sh_name = ShName;66 shdr->sh_name = shName;
67}67}
6868
69OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)69OutputSection::OutputSection(StringRef name, uint32_t type, uint64_t flags)
70 : BaseCommand(OutputSectionKind),70 : BaseCommand(OutputSectionKind),
71 SectionBase(Output, Name, Flags, /*Entsize*/ 0, /*Alignment*/ 1, Type,71 SectionBase(Output, name, flags, /*Entsize*/ 0, /*Alignment*/ 1, type,
72 /*Info*/ 0, /*Link*/ 0) {72 /*Info*/ 0, /*Link*/ 0) {}
73 Live = false;
74}
7573
76// We allow sections of types listed below to merged into a74// We allow sections of types listed below to merged into a
77// single progbits section. This is typically done by linker75// single progbits section. This is typically done by linker
...@@ -79,257 +77,248 @@ OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)...@@ -79,257 +77,248 @@ OutputSection::OutputSection(StringRef Name, uint32_t Type, uint64_t Flags)
79// to be allocated for nobits sections. Other ones don't require77// to be allocated for nobits sections. Other ones don't require
80// any special treatment on top of progbits, so there doesn't78// any special treatment on top of progbits, so there doesn't
81// seem to be a harm in merging them.79// seem to be a harm in merging them.
82static bool canMergeToProgbits(unsigned Type) {80static bool canMergeToProgbits(unsigned type) {
83 return Type == SHT_NOBITS || Type == SHT_PROGBITS || Type == SHT_INIT_ARRAY ||81 return type == SHT_NOBITS || type == SHT_PROGBITS || type == SHT_INIT_ARRAY ||
84 Type == SHT_PREINIT_ARRAY || Type == SHT_FINI_ARRAY ||82 type == SHT_PREINIT_ARRAY || type == SHT_FINI_ARRAY ||
85 Type == SHT_NOTE;83 type == SHT_NOTE;
86}84}
8785
88void OutputSection::addSection(InputSection *IS) {86void OutputSection::addSection(InputSection *isec) {
89 if (!Live) {87 if (!hasInputSections) {
90 // If IS is the first section to be added to this section,88 // If IS is the first section to be added to this section,
91 // initialize Type, Entsize and flags from IS.89 // initialize Partition, Type, Entsize and flags from IS.
92 Live = true;90 hasInputSections = true;
93 Type = IS->Type;91 partition = isec->partition;
94 Entsize = IS->Entsize;92 type = isec->type;
95 Flags = IS->Flags;93 entsize = isec->entsize;
94 flags = isec->flags;
96 } else {95 } else {
97 // Otherwise, check if new type or flags are compatible with existing ones.96 // Otherwise, check if new type or flags are compatible with existing ones.
98 unsigned Mask = SHF_TLS | SHF_LINK_ORDER;97 unsigned mask = SHF_TLS | SHF_LINK_ORDER;
99 if ((Flags & Mask) != (IS->Flags & Mask))98 if ((flags & mask) != (isec->flags & mask))
100 error("incompatible section flags for " + Name + "\n>>> " + toString(IS) +99 error("incompatible section flags for " + name + "\n>>> " + toString(isec) +
101 ": 0x" + utohexstr(IS->Flags) + "\n>>> output section " + Name +100 ": 0x" + utohexstr(isec->flags) + "\n>>> output section " + name +
102 ": 0x" + utohexstr(Flags));101 ": 0x" + utohexstr(flags));
103102
104 if (Type != IS->Type) {103 if (type != isec->type) {
105 if (!canMergeToProgbits(Type) || !canMergeToProgbits(IS->Type))104 if (!canMergeToProgbits(type) || !canMergeToProgbits(isec->type))
106 error("section type mismatch for " + IS->Name + "\n>>> " +105 error("section type mismatch for " + isec->name + "\n>>> " +
107 toString(IS) + ": " +106 toString(isec) + ": " +
108 getELFSectionTypeName(Config->EMachine, IS->Type) +107 getELFSectionTypeName(config->emachine, isec->type) +
109 "\n>>> output section " + Name + ": " +108 "\n>>> output section " + name + ": " +
110 getELFSectionTypeName(Config->EMachine, Type));109 getELFSectionTypeName(config->emachine, type));
111 Type = SHT_PROGBITS;110 type = SHT_PROGBITS;
112 }111 }
113 }112 }
114113
115 IS->Parent = this;114 isec->parent = this;
116 uint64_t AndMask =115 uint64_t andMask =
117 Config->EMachine == EM_ARM ? (uint64_t)SHF_ARM_PURECODE : 0;116 config->emachine == EM_ARM ? (uint64_t)SHF_ARM_PURECODE : 0;
118 uint64_t OrMask = ~AndMask;117 uint64_t orMask = ~andMask;
119 uint64_t AndFlags = (Flags & IS->Flags) & AndMask;118 uint64_t andFlags = (flags & isec->flags) & andMask;
120 uint64_t OrFlags = (Flags | IS->Flags) & OrMask;119 uint64_t orFlags = (flags | isec->flags) & orMask;
121 Flags = AndFlags | OrFlags;120 flags = andFlags | orFlags;
122121
123 Alignment = std::max(Alignment, IS->Alignment);122 alignment = std::max(alignment, isec->alignment);
124123
125 // If this section contains a table of fixed-size entries, sh_entsize124 // If this section contains a table of fixed-size entries, sh_entsize
126 // holds the element size. If it contains elements of different size we125 // holds the element size. If it contains elements of different size we
127 // set sh_entsize to 0.126 // set sh_entsize to 0.
128 if (Entsize != IS->Entsize)127 if (entsize != isec->entsize)
129 Entsize = 0;128 entsize = 0;
130129
131 if (!IS->Assigned) {130 if (!isec->assigned) {
132 IS->Assigned = true;131 isec->assigned = true;
133 if (SectionCommands.empty() ||132 if (sectionCommands.empty() ||
134 !isa<InputSectionDescription>(SectionCommands.back()))133 !isa<InputSectionDescription>(sectionCommands.back()))
135 SectionCommands.push_back(make<InputSectionDescription>(""));134 sectionCommands.push_back(make<InputSectionDescription>(""));
136 auto *ISD = cast<InputSectionDescription>(SectionCommands.back());135 auto *isd = cast<InputSectionDescription>(sectionCommands.back());
137 ISD->Sections.push_back(IS);136 isd->sections.push_back(isec);
138 }137 }
139}138}
140139
141static void sortByOrder(MutableArrayRef<InputSection *> In,140static void sortByOrder(MutableArrayRef<InputSection *> in,
142 llvm::function_ref<int(InputSectionBase *S)> Order) {141 llvm::function_ref<int(InputSectionBase *s)> order) {
143 typedef std::pair<int, InputSection *> Pair;142 std::vector<std::pair<int, InputSection *>> v;
144 auto Comp = [](const Pair &A, const Pair &B) { return A.first < B.first; };143 for (InputSection *s : in)
144 v.push_back({order(s), s});
145 llvm::stable_sort(v, less_first());
145146
146 std::vector<Pair> V;147 for (size_t i = 0; i < v.size(); ++i)
147 for (InputSection *S : In)148 in[i] = v[i].second;
148 V.push_back({Order(S), S});
149 std::stable_sort(V.begin(), V.end(), Comp);
150
151 for (size_t I = 0; I < V.size(); ++I)
152 In[I] = V[I].second;
153}149}
154150
155uint64_t elf::getHeaderSize() {151uint64_t elf::getHeaderSize() {
156 if (Config->OFormatBinary)152 if (config->oFormatBinary)
157 return 0;153 return 0;
158 return Out::ElfHeader->Size + Out::ProgramHeaders->Size;154 return Out::elfHeader->size + Out::programHeaders->size;
159}155}
160156
161bool OutputSection::classof(const BaseCommand *C) {157bool OutputSection::classof(const BaseCommand *c) {
162 return C->Kind == OutputSectionKind;158 return c->kind == OutputSectionKind;
163}159}
164160
165void OutputSection::sort(llvm::function_ref<int(InputSectionBase *S)> Order) {161void OutputSection::sort(llvm::function_ref<int(InputSectionBase *s)> order) {
166 assert(Live);162 assert(isLive());
167 for (BaseCommand *B : SectionCommands)163 for (BaseCommand *b : sectionCommands)
168 if (auto *ISD = dyn_cast<InputSectionDescription>(B))164 if (auto *isd = dyn_cast<InputSectionDescription>(b))
169 sortByOrder(ISD->Sections, Order);165 sortByOrder(isd->sections, order);
170}166}
171167
172// Fill [Buf, Buf + Size) with Filler.168// Fill [Buf, Buf + Size) with Filler.
173// This is used for linker script "=fillexp" command.169// This is used for linker script "=fillexp" command.
174static void fill(uint8_t *Buf, size_t Size,170static void fill(uint8_t *buf, size_t size,
175 const std::array<uint8_t, 4> &Filler) {171 const std::array<uint8_t, 4> &filler) {
176 size_t I = 0;172 size_t i = 0;
177 for (; I + 4 < Size; I += 4)173 for (; i + 4 < size; i += 4)
178 memcpy(Buf + I, Filler.data(), 4);174 memcpy(buf + i, filler.data(), 4);
179 memcpy(Buf + I, Filler.data(), Size - I);175 memcpy(buf + i, filler.data(), size - i);
180}176}
181177
182// Compress section contents if this section contains debug info.178// Compress section contents if this section contains debug info.
183template <class ELFT> void OutputSection::maybeCompress() {179template <class ELFT> void OutputSection::maybeCompress() {
184 typedef typename ELFT::Chdr Elf_Chdr;180 using Elf_Chdr = typename ELFT::Chdr;
185181
186 // Compress only DWARF debug sections.182 // Compress only DWARF debug sections.
187 if (!Config->CompressDebugSections || (Flags & SHF_ALLOC) ||183 if (!config->compressDebugSections || (flags & SHF_ALLOC) ||
188 !Name.startswith(".debug_"))184 !name.startswith(".debug_"))
189 return;185 return;
190186
191 // Create a section header.187 // Create a section header.
192 ZDebugHeader.resize(sizeof(Elf_Chdr));188 zDebugHeader.resize(sizeof(Elf_Chdr));
193 auto *Hdr = reinterpret_cast<Elf_Chdr *>(ZDebugHeader.data());189 auto *hdr = reinterpret_cast<Elf_Chdr *>(zDebugHeader.data());
194 Hdr->ch_type = ELFCOMPRESS_ZLIB;190 hdr->ch_type = ELFCOMPRESS_ZLIB;
195 Hdr->ch_size = Size;191 hdr->ch_size = size;
196 Hdr->ch_addralign = Alignment;192 hdr->ch_addralign = alignment;
197193
198 // Write section contents to a temporary buffer and compress it.194 // Write section contents to a temporary buffer and compress it.
199 std::vector<uint8_t> Buf(Size);195 std::vector<uint8_t> buf(size);
200 writeTo<ELFT>(Buf.data());196 writeTo<ELFT>(buf.data());
201 if (Error E = zlib::compress(toStringRef(Buf), CompressedData))197 if (Error e = zlib::compress(toStringRef(buf), compressedData))
202 fatal("compress failed: " + llvm::toString(std::move(E)));198 fatal("compress failed: " + llvm::toString(std::move(e)));
203199
204 // Update section headers.200 // Update section headers.
205 Size = sizeof(Elf_Chdr) + CompressedData.size();201 size = sizeof(Elf_Chdr) + compressedData.size();
206 Flags |= SHF_COMPRESSED;202 flags |= SHF_COMPRESSED;
207}203}
208204
209static void writeInt(uint8_t *Buf, uint64_t Data, uint64_t Size) {205static void writeInt(uint8_t *buf, uint64_t data, uint64_t size) {
210 if (Size == 1)206 if (size == 1)
211 *Buf = Data;207 *buf = data;
212 else if (Size == 2)208 else if (size == 2)
213 write16(Buf, Data);209 write16(buf, data);
214 else if (Size == 4)210 else if (size == 4)
215 write32(Buf, Data);211 write32(buf, data);
216 else if (Size == 8)212 else if (size == 8)
217 write64(Buf, Data);213 write64(buf, data);
218 else214 else
219 llvm_unreachable("unsupported Size argument");215 llvm_unreachable("unsupported Size argument");
220}216}
221217
222template <class ELFT> void OutputSection::writeTo(uint8_t *Buf) {218template <class ELFT> void OutputSection::writeTo(uint8_t *buf) {
223 if (Type == SHT_NOBITS)219 if (type == SHT_NOBITS)
224 return;220 return;
225221
226 Loc = Buf;
227
228 // If -compress-debug-section is specified and if this is a debug seciton,222 // If -compress-debug-section is specified and if this is a debug seciton,
229 // we've already compressed section contents. If that's the case,223 // we've already compressed section contents. If that's the case,
230 // just write it down.224 // just write it down.
231 if (!CompressedData.empty()) {225 if (!compressedData.empty()) {
232 memcpy(Buf, ZDebugHeader.data(), ZDebugHeader.size());226 memcpy(buf, zDebugHeader.data(), zDebugHeader.size());
233 memcpy(Buf + ZDebugHeader.size(), CompressedData.data(),227 memcpy(buf + zDebugHeader.size(), compressedData.data(),
234 CompressedData.size());228 compressedData.size());
235 return;229 return;
236 }230 }
237231
238 // Write leading padding.232 // Write leading padding.
239 std::vector<InputSection *> Sections = getInputSections(this);233 std::vector<InputSection *> sections = getInputSections(this);
240 std::array<uint8_t, 4> Filler = getFiller();234 std::array<uint8_t, 4> filler = getFiller();
241 bool NonZeroFiller = read32(Filler.data()) != 0;235 bool nonZeroFiller = read32(filler.data()) != 0;
242 if (NonZeroFiller)236 if (nonZeroFiller)
243 fill(Buf, Sections.empty() ? Size : Sections[0]->OutSecOff, Filler);237 fill(buf, sections.empty() ? size : sections[0]->outSecOff, filler);
244238
245 parallelForEachN(0, Sections.size(), [&](size_t I) {239 parallelForEachN(0, sections.size(), [&](size_t i) {
246 InputSection *IS = Sections[I];240 InputSection *isec = sections[i];
247 IS->writeTo<ELFT>(Buf);241 isec->writeTo<ELFT>(buf);
248242
249 // Fill gaps between sections.243 // Fill gaps between sections.
250 if (NonZeroFiller) {244 if (nonZeroFiller) {
251 uint8_t *Start = Buf + IS->OutSecOff + IS->getSize();245 uint8_t *start = buf + isec->outSecOff + isec->getSize();
252 uint8_t *End;246 uint8_t *end;
253 if (I + 1 == Sections.size())247 if (i + 1 == sections.size())
254 End = Buf + Size;248 end = buf + size;
255 else249 else
256 End = Buf + Sections[I + 1]->OutSecOff;250 end = buf + sections[i + 1]->outSecOff;
257 fill(Start, End - Start, Filler);251 fill(start, end - start, filler);
258 }252 }
259 });253 });
260254
261 // Linker scripts may have BYTE()-family commands with which you255 // Linker scripts may have BYTE()-family commands with which you
262 // can write arbitrary bytes to the output. Process them if any.256 // can write arbitrary bytes to the output. Process them if any.
263 for (BaseCommand *Base : SectionCommands)257 for (BaseCommand *base : sectionCommands)
264 if (auto *Data = dyn_cast<ByteCommand>(Base))258 if (auto *data = dyn_cast<ByteCommand>(base))
265 writeInt(Buf + Data->Offset, Data->Expression().getValue(), Data->Size);259 writeInt(buf + data->offset, data->expression().getValue(), data->size);
266}260}
267261
268template <class ELFT>262static void finalizeShtGroup(OutputSection *os,
269static void finalizeShtGroup(OutputSection *OS,263 InputSection *section) {
270 InputSection *Section) {264 assert(config->relocatable);
271 assert(Config->Relocatable);
272265
273 // sh_link field for SHT_GROUP sections should contain the section index of266 // sh_link field for SHT_GROUP sections should contain the section index of
274 // the symbol table.267 // the symbol table.
275 OS->Link = In.SymTab->getParent()->SectionIndex;268 os->link = in.symTab->getParent()->sectionIndex;
276269
277 // sh_info then contain index of an entry in symbol table section which270 // sh_info then contain index of an entry in symbol table section which
278 // provides signature of the section group.271 // provides signature of the section group.
279 ObjFile<ELFT> *Obj = Section->getFile<ELFT>();272 ArrayRef<Symbol *> symbols = section->file->getSymbols();
280 ArrayRef<Symbol *> Symbols = Obj->getSymbols();273 os->info = in.symTab->getSymbolIndex(symbols[section->info]);
281 OS->Info = In.SymTab->getSymbolIndex(Symbols[Section->Info]);
282}274}
283275
284template <class ELFT> void OutputSection::finalize() {276void OutputSection::finalize() {
285 if (Type == SHT_NOBITS)277 std::vector<InputSection *> v = getInputSections(this);
286 for (BaseCommand *Base : SectionCommands)278 InputSection *first = v.empty() ? nullptr : v[0];
287 if (isa<ByteCommand>(Base))
288 Type = SHT_PROGBITS;
289
290 std::vector<InputSection *> V = getInputSections(this);
291 InputSection *First = V.empty() ? nullptr : V[0];
292279
293 if (Flags & SHF_LINK_ORDER) {280 if (flags & SHF_LINK_ORDER) {
294 // We must preserve the link order dependency of sections with the281 // We must preserve the link order dependency of sections with the
295 // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We282 // SHF_LINK_ORDER flag. The dependency is indicated by the sh_link field. We
296 // need to translate the InputSection sh_link to the OutputSection sh_link,283 // need to translate the InputSection sh_link to the OutputSection sh_link,
297 // all InputSections in the OutputSection have the same dependency.284 // all InputSections in the OutputSection have the same dependency.
298 if (auto *D = First->getLinkOrderDep())285 if (auto *ex = dyn_cast<ARMExidxSyntheticSection>(first))
299 Link = D->getParent()->SectionIndex;286 link = ex->getLinkOrderDep()->getParent()->sectionIndex;
287 else if (auto *d = first->getLinkOrderDep())
288 link = d->getParent()->sectionIndex;
300 }289 }
301290
302 if (Type == SHT_GROUP) {291 if (type == SHT_GROUP) {
303 finalizeShtGroup<ELFT>(this, First);292 finalizeShtGroup(this, first);
304 return;293 return;
305 }294 }
306295
307 if (!Config->CopyRelocs || (Type != SHT_RELA && Type != SHT_REL))296 if (!config->copyRelocs || (type != SHT_RELA && type != SHT_REL))
308 return;297 return;
309298
310 if (isa<SyntheticSection>(First))299 if (isa<SyntheticSection>(first))
311 return;300 return;
312301
313 Link = In.SymTab->getParent()->SectionIndex;302 link = in.symTab->getParent()->sectionIndex;
314 // sh_info for SHT_REL[A] sections should contain the section header index of303 // sh_info for SHT_REL[A] sections should contain the section header index of
315 // the section to which the relocation applies.304 // the section to which the relocation applies.
316 InputSectionBase *S = First->getRelocatedSection();305 InputSectionBase *s = first->getRelocatedSection();
317 Info = S->getOutputSection()->SectionIndex;306 info = s->getOutputSection()->sectionIndex;
318 Flags |= SHF_INFO_LINK;307 flags |= SHF_INFO_LINK;
319}308}
320309
321// Returns true if S matches /Filename.?\.o$/.310// Returns true if S matches /Filename.?\.o$/.
322static bool isCrtBeginEnd(StringRef S, StringRef Filename) {311static bool isCrtBeginEnd(StringRef s, StringRef filename) {
323 if (!S.endswith(".o"))312 if (!s.endswith(".o"))
324 return false;313 return false;
325 S = S.drop_back(2);314 s = s.drop_back(2);
326 if (S.endswith(Filename))315 if (s.endswith(filename))
327 return true;316 return true;
328 return !S.empty() && S.drop_back().endswith(Filename);317 return !s.empty() && s.drop_back().endswith(filename);
329}318}
330319
331static bool isCrtbegin(StringRef S) { return isCrtBeginEnd(S, "crtbegin"); }320static bool isCrtbegin(StringRef s) { return isCrtBeginEnd(s, "crtbegin"); }
332static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); }321static bool isCrtend(StringRef s) { return isCrtBeginEnd(s, "crtend"); }
333322
334// .ctors and .dtors are sorted by this priority from highest to lowest.323// .ctors and .dtors are sorted by this priority from highest to lowest.
335//324//
...@@ -349,52 +338,52 @@ static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); }...@@ -349,52 +338,52 @@ static bool isCrtend(StringRef S) { return isCrtBeginEnd(S, "crtend"); }
349// .ctors are duplicate features (and .init_array is newer.) However, there338// .ctors are duplicate features (and .init_array is newer.) However, there
350// are too many real-world use cases of .ctors, so we had no choice to339// are too many real-world use cases of .ctors, so we had no choice to
351// support that with this rather ad-hoc semantics.340// support that with this rather ad-hoc semantics.
352static bool compCtors(const InputSection *A, const InputSection *B) {341static bool compCtors(const InputSection *a, const InputSection *b) {
353 bool BeginA = isCrtbegin(A->File->getName());342 bool beginA = isCrtbegin(a->file->getName());
354 bool BeginB = isCrtbegin(B->File->getName());343 bool beginB = isCrtbegin(b->file->getName());
355 if (BeginA != BeginB)344 if (beginA != beginB)
356 return BeginA;345 return beginA;
357 bool EndA = isCrtend(A->File->getName());346 bool endA = isCrtend(a->file->getName());
358 bool EndB = isCrtend(B->File->getName());347 bool endB = isCrtend(b->file->getName());
359 if (EndA != EndB)348 if (endA != endB)
360 return EndB;349 return endB;
361 StringRef X = A->Name;350 StringRef x = a->name;
362 StringRef Y = B->Name;351 StringRef y = b->name;
363 assert(X.startswith(".ctors") || X.startswith(".dtors"));352 assert(x.startswith(".ctors") || x.startswith(".dtors"));
364 assert(Y.startswith(".ctors") || Y.startswith(".dtors"));353 assert(y.startswith(".ctors") || y.startswith(".dtors"));
365 X = X.substr(6);354 x = x.substr(6);
366 Y = Y.substr(6);355 y = y.substr(6);
367 return X < Y;356 return x < y;
368}357}
369358
370// Sorts input sections by the special rules for .ctors and .dtors.359// Sorts input sections by the special rules for .ctors and .dtors.
371// Unfortunately, the rules are different from the one for .{init,fini}_array.360// Unfortunately, the rules are different from the one for .{init,fini}_array.
372// Read the comment above.361// Read the comment above.
373void OutputSection::sortCtorsDtors() {362void OutputSection::sortCtorsDtors() {
374 assert(SectionCommands.size() == 1);363 assert(sectionCommands.size() == 1);
375 auto *ISD = cast<InputSectionDescription>(SectionCommands[0]);364 auto *isd = cast<InputSectionDescription>(sectionCommands[0]);
376 std::stable_sort(ISD->Sections.begin(), ISD->Sections.end(), compCtors);365 llvm::stable_sort(isd->sections, compCtors);
377}366}
378367
379// If an input string is in the form of "foo.N" where N is a number,368// If an input string is in the form of "foo.N" where N is a number,
380// return N. Otherwise, returns 65536, which is one greater than the369// return N. Otherwise, returns 65536, which is one greater than the
381// lowest priority.370// lowest priority.
382int elf::getPriority(StringRef S) {371int elf::getPriority(StringRef s) {
383 size_t Pos = S.rfind('.');372 size_t pos = s.rfind('.');
384 if (Pos == StringRef::npos)373 if (pos == StringRef::npos)
385 return 65536;374 return 65536;
386 int V;375 int v;
387 if (!to_integer(S.substr(Pos + 1), V, 10))376 if (!to_integer(s.substr(pos + 1), v, 10))
388 return 65536;377 return 65536;
389 return V;378 return v;
390}379}
391380
392std::vector<InputSection *> elf::getInputSections(OutputSection *OS) {381std::vector<InputSection *> elf::getInputSections(OutputSection *os) {
393 std::vector<InputSection *> Ret;382 std::vector<InputSection *> ret;
394 for (BaseCommand *Base : OS->SectionCommands)383 for (BaseCommand *base : os->sectionCommands)
395 if (auto *ISD = dyn_cast<InputSectionDescription>(Base))384 if (auto *isd = dyn_cast<InputSectionDescription>(base))
396 Ret.insert(Ret.end(), ISD->Sections.begin(), ISD->Sections.end());385 ret.insert(ret.end(), isd->sections.begin(), isd->sections.end());
397 return Ret;386 return ret;
398}387}
399388
400// Sorts input sections by section name suffixes, so that .foo.N comes389// Sorts input sections by section name suffixes, so that .foo.N comes
...@@ -405,14 +394,14 @@ std::vector<InputSection *> elf::getInputSections(OutputSection *OS) {...@@ -405,14 +394,14 @@ std::vector<InputSection *> elf::getInputSections(OutputSection *OS) {
405// For more detail, read the section of the GCC's manual about init_priority.394// For more detail, read the section of the GCC's manual about init_priority.
406void OutputSection::sortInitFini() {395void OutputSection::sortInitFini() {
407 // Sort sections by priority.396 // Sort sections by priority.
408 sort([](InputSectionBase *S) { return getPriority(S->Name); });397 sort([](InputSectionBase *s) { return getPriority(s->name); });
409}398}
410399
411std::array<uint8_t, 4> OutputSection::getFiller() {400std::array<uint8_t, 4> OutputSection::getFiller() {
412 if (Filler)401 if (filler)
413 return *Filler;402 return *filler;
414 if (Flags & SHF_EXECINSTR)403 if (flags & SHF_EXECINSTR)
415 return Target->TrapInstr;404 return target->trapInstr;
416 return {0, 0, 0, 0};405 return {0, 0, 0, 0};
417}406}
418407
...@@ -430,8 +419,3 @@ template void OutputSection::maybeCompress<ELF32LE>();...@@ -430,8 +419,3 @@ template void OutputSection::maybeCompress<ELF32LE>();
430template void OutputSection::maybeCompress<ELF32BE>();419template void OutputSection::maybeCompress<ELF32BE>();
431template void OutputSection::maybeCompress<ELF64LE>();420template void OutputSection::maybeCompress<ELF64LE>();
432template void OutputSection::maybeCompress<ELF64BE>();421template void OutputSection::maybeCompress<ELF64BE>();
433
434template void OutputSection::finalize<ELF32LE>();
435template void OutputSection::finalize<ELF32BE>();
436template void OutputSection::finalize<ELF64LE>();
437template void OutputSection::finalize<ELF64BE>();
deps/lld/ELF/OutputSections.h+58-64
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- OutputSections.h -----------------------------------------*- C++ -*-===//1//===- OutputSections.h -----------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -23,17 +22,8 @@ namespace lld {...@@ -23,17 +22,8 @@ namespace lld {
23namespace elf {22namespace elf {
2423
25struct PhdrEntry;24struct PhdrEntry;
26class Symbol;
27struct EhSectionPiece;
28class EhInputSection;
29class InputSection;25class InputSection;
30class InputSectionBase;26class InputSectionBase;
31class MergeInputSection;
32class OutputSection;
33template <class ELFT> class ObjFile;
34template <class ELFT> class SharedFile;
35class SharedSymbol;
36class Defined;
3727
38// This represents a section in an output file.28// This represents a section in an output file.
39// It is composed of multiple InputSections.29// It is composed of multiple InputSections.
...@@ -41,19 +31,19 @@ class Defined;...@@ -41,19 +31,19 @@ class Defined;
41// non-overlapping file offsets and VAs.31// non-overlapping file offsets and VAs.
42class OutputSection final : public BaseCommand, public SectionBase {32class OutputSection final : public BaseCommand, public SectionBase {
43public:33public:
44 OutputSection(StringRef Name, uint32_t Type, uint64_t Flags);34 OutputSection(StringRef name, uint32_t type, uint64_t flags);
4535
46 static bool classof(const SectionBase *S) {36 static bool classof(const SectionBase *s) {
47 return S->kind() == SectionBase::Output;37 return s->kind() == SectionBase::Output;
48 }38 }
4939
50 static bool classof(const BaseCommand *C);40 static bool classof(const BaseCommand *c);
5141
52 uint64_t getLMA() const { return PtLoad ? Addr + PtLoad->LMAOffset : Addr; }42 uint64_t getLMA() const { return ptLoad ? addr + ptLoad->lmaOffset : addr; }
53 template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *SHdr);43 template <typename ELFT> void writeHeaderTo(typename ELFT::Shdr *sHdr);
5444
55 uint32_t SectionIndex = UINT32_MAX;45 uint32_t sectionIndex = UINT32_MAX;
56 unsigned SortRank;46 unsigned sortRank;
5747
58 uint32_t getPhdrFlags() const;48 uint32_t getPhdrFlags() const;
5949
...@@ -64,78 +54,82 @@ public:...@@ -64,78 +54,82 @@ public:
64 // section offset we use the following formula: Off = Off_first + VA -54 // section offset we use the following formula: Off = Off_first + VA -
65 // VA_first, where Off_first and VA_first is file offset and VA of first55 // VA_first, where Off_first and VA_first is file offset and VA of first
66 // section in PT_LOAD.56 // section in PT_LOAD.
67 PhdrEntry *PtLoad = nullptr;57 PhdrEntry *ptLoad = nullptr;
6858
69 // Pointer to a relocation section for this section. Usually nullptr because59 // Pointer to a relocation section for this section. Usually nullptr because
70 // we consume relocations, but if --emit-relocs is specified (which is rare),60 // we consume relocations, but if --emit-relocs is specified (which is rare),
71 // it may have a non-null value.61 // it may have a non-null value.
72 OutputSection *RelocationSection = nullptr;62 OutputSection *relocationSection = nullptr;
7363
74 // Initially this field is the number of InputSections that have been added to64 // Initially this field is the number of InputSections that have been added to
75 // the OutputSection so far. Later on, after a call to assignAddresses, it65 // the OutputSection so far. Later on, after a call to assignAddresses, it
76 // corresponds to the Elf_Shdr member.66 // corresponds to the Elf_Shdr member.
77 uint64_t Size = 0;67 uint64_t size = 0;
7868
79 // The following fields correspond to Elf_Shdr members.69 // The following fields correspond to Elf_Shdr members.
80 uint64_t Offset = 0;70 uint64_t offset = 0;
81 uint64_t Addr = 0;71 uint64_t addr = 0;
82 uint32_t ShName = 0;72 uint32_t shName = 0;
83
84 void addSection(InputSection *IS);
8573
86 // Location in the output buffer.74 void addSection(InputSection *isec);
87 uint8_t *Loc = nullptr;
8875
89 // The following members are normally only used in linker scripts.76 // The following members are normally only used in linker scripts.
90 MemoryRegion *MemRegion = nullptr;77 MemoryRegion *memRegion = nullptr;
91 MemoryRegion *LMARegion = nullptr;78 MemoryRegion *lmaRegion = nullptr;
92 Expr AddrExpr;79 Expr addrExpr;
93 Expr AlignExpr;80 Expr alignExpr;
94 Expr LMAExpr;81 Expr lmaExpr;
95 Expr SubalignExpr;82 Expr subalignExpr;
96 std::vector<BaseCommand *> SectionCommands;83 std::vector<BaseCommand *> sectionCommands;
97 std::vector<StringRef> Phdrs;84 std::vector<StringRef> phdrs;
98 llvm::Optional<std::array<uint8_t, 4>> Filler;85 llvm::Optional<std::array<uint8_t, 4>> filler;
99 ConstraintKind Constraint = ConstraintKind::NoConstraint;86 ConstraintKind constraint = ConstraintKind::NoConstraint;
100 std::string Location;87 std::string location;
101 std::string MemoryRegionName;88 std::string memoryRegionName;
102 std::string LMARegionName;89 std::string lmaRegionName;
103 bool NonAlloc = false;90 bool nonAlloc = false;
104 bool Noload = false;91 bool noload = false;
105 bool ExpressionsUseSymbols = false;92 bool expressionsUseSymbols = false;
106 bool InOverlay = false;93 bool usedInExpression = false;
10794 bool inOverlay = false;
108 template <class ELFT> void finalize();95
109 template <class ELFT> void writeTo(uint8_t *Buf);96 // Tracks whether the section has ever had an input section added to it, even
97 // if the section was later removed (e.g. because it is a synthetic section
98 // that wasn't needed). This is needed for orphan placement.
99 bool hasInputSections = false;
100
101 void finalize();
102 template <class ELFT> void writeTo(uint8_t *buf);
110 template <class ELFT> void maybeCompress();103 template <class ELFT> void maybeCompress();
111104
112 void sort(llvm::function_ref<int(InputSectionBase *S)> Order);105 void sort(llvm::function_ref<int(InputSectionBase *s)> order);
113 void sortInitFini();106 void sortInitFini();
114 void sortCtorsDtors();107 void sortCtorsDtors();
115108
116private:109private:
117 // Used for implementation of --compress-debug-sections option.110 // Used for implementation of --compress-debug-sections option.
118 std::vector<uint8_t> ZDebugHeader;111 std::vector<uint8_t> zDebugHeader;
119 llvm::SmallVector<char, 1> CompressedData;112 llvm::SmallVector<char, 1> compressedData;
120113
121 std::array<uint8_t, 4> getFiller();114 std::array<uint8_t, 4> getFiller();
122};115};
123116
124int getPriority(StringRef S);117int getPriority(StringRef s);
125118
126std::vector<InputSection *> getInputSections(OutputSection* OS);119std::vector<InputSection *> getInputSections(OutputSection* os);
127120
128// All output sections that are handled by the linker specially are121// All output sections that are handled by the linker specially are
129// globally accessible. Writer initializes them, so don't use them122// globally accessible. Writer initializes them, so don't use them
130// until Writer is initialized.123// until Writer is initialized.
131struct Out {124struct Out {
132 static uint8_t First;125 static uint8_t *bufferStart;
133 static PhdrEntry *TlsPhdr;126 static uint8_t first;
134 static OutputSection *ElfHeader;127 static PhdrEntry *tlsPhdr;
135 static OutputSection *ProgramHeaders;128 static OutputSection *elfHeader;
136 static OutputSection *PreinitArray;129 static OutputSection *programHeaders;
137 static OutputSection *InitArray;130 static OutputSection *preinitArray;
138 static OutputSection *FiniArray;131 static OutputSection *initArray;
132 static OutputSection *finiArray;
139};133};
140134
141} // namespace elf135} // namespace elf
...@@ -146,7 +140,7 @@ namespace elf {...@@ -146,7 +140,7 @@ namespace elf {
146140
147uint64_t getHeaderSize();141uint64_t getHeaderSize();
148142
149extern std::vector<OutputSection *> OutputSections;143extern std::vector<OutputSection *> outputSections;
150} // namespace elf144} // namespace elf
151} // namespace lld145} // namespace lld
152146
deps/lld/ELF/Relocations.cpp+985-678
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Relocations.cpp ----------------------------------------------------===//1//===- Relocations.cpp ----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -66,11 +65,11 @@ using namespace llvm::support::endian;...@@ -66,11 +65,11 @@ using namespace llvm::support::endian;
66using namespace lld;65using namespace lld;
67using namespace lld::elf;66using namespace lld::elf;
6867
69static Optional<std::string> getLinkerScriptLocation(const Symbol &Sym) {68static Optional<std::string> getLinkerScriptLocation(const Symbol &sym) {
70 for (BaseCommand *Base : Script->SectionCommands)69 for (BaseCommand *base : script->sectionCommands)
71 if (auto *Cmd = dyn_cast<SymbolAssignment>(Base))70 if (auto *cmd = dyn_cast<SymbolAssignment>(base))
72 if (Cmd->Sym == &Sym)71 if (cmd->sym == &sym)
73 return Cmd->Location;72 return cmd->location;
74 return None;73 return None;
75}74}
7675
...@@ -79,19 +78,51 @@ static Optional<std::string> getLinkerScriptLocation(const Symbol &Sym) {...@@ -79,19 +78,51 @@ static Optional<std::string> getLinkerScriptLocation(const Symbol &Sym) {
79// >>> defined in /home/alice/src/foo.o78// >>> defined in /home/alice/src/foo.o
80// >>> referenced by bar.c:12 (/home/alice/src/bar.c:12)79// >>> referenced by bar.c:12 (/home/alice/src/bar.c:12)
81// >>> /home/alice/src/bar.o:(.text+0x1)80// >>> /home/alice/src/bar.o:(.text+0x1)
82static std::string getLocation(InputSectionBase &S, const Symbol &Sym,81static std::string getLocation(InputSectionBase &s, const Symbol &sym,
83 uint64_t Off) {82 uint64_t off) {
84 std::string Msg = "\n>>> defined in ";83 std::string msg = "\n>>> defined in ";
85 if (Sym.File)84 if (sym.file)
86 Msg += toString(Sym.File);85 msg += toString(sym.file);
87 else if (Optional<std::string> Loc = getLinkerScriptLocation(Sym))86 else if (Optional<std::string> loc = getLinkerScriptLocation(sym))
88 Msg += *Loc;87 msg += *loc;
8988
90 Msg += "\n>>> referenced by ";89 msg += "\n>>> referenced by ";
91 std::string Src = S.getSrcMsg(Sym, Off);90 std::string src = s.getSrcMsg(sym, off);
92 if (!Src.empty())91 if (!src.empty())
93 Msg += Src + "\n>>> ";92 msg += src + "\n>>> ";
94 return Msg + S.getObjMsg(Off);93 return msg + s.getObjMsg(off);
94}
95
96namespace {
97// Build a bitmask with one bit set for each RelExpr.
98//
99// Constexpr function arguments can't be used in static asserts, so we
100// use template arguments to build the mask.
101// But function template partial specializations don't exist (needed
102// for base case of the recursion), so we need a dummy struct.
103template <RelExpr... Exprs> struct RelExprMaskBuilder {
104 static inline uint64_t build() { return 0; }
105};
106
107// Specialization for recursive case.
108template <RelExpr Head, RelExpr... Tail>
109struct RelExprMaskBuilder<Head, Tail...> {
110 static inline uint64_t build() {
111 static_assert(0 <= Head && Head < 64,
112 "RelExpr is too large for 64-bit mask!");
113 return (uint64_t(1) << Head) | RelExprMaskBuilder<Tail...>::build();
114 }
115};
116} // namespace
117
118// Return true if `Expr` is one of `Exprs`.
119// There are fewer than 64 RelExpr's, so we can represent any set of
120// RelExpr's as a constant bit mask and test for membership with a
121// couple cheap bitwise operations.
122template <RelExpr... Exprs> bool oneof(RelExpr expr) {
123 assert(0 <= expr && (int)expr < 64 &&
124 "RelExpr is too large for 64-bit mask!");
125 return (uint64_t(1) << expr) & RelExprMaskBuilder<Exprs...>::build();
95}126}
96127
97// This function is similar to the `handleTlsRelocation`. MIPS does not128// This function is similar to the `handleTlsRelocation`. MIPS does not
...@@ -100,204 +131,173 @@ static std::string getLocation(InputSectionBase &S, const Symbol &Sym,...@@ -100,204 +131,173 @@ static std::string getLocation(InputSectionBase &S, const Symbol &Sym,
100// pollute other `handleTlsRelocation` by MIPS `ifs` statements.131// pollute other `handleTlsRelocation` by MIPS `ifs` statements.
101// Mips has a custom MipsGotSection that handles the writing of GOT entries132// Mips has a custom MipsGotSection that handles the writing of GOT entries
102// without dynamic relocations.133// without dynamic relocations.
103static unsigned handleMipsTlsRelocation(RelType Type, Symbol &Sym,134static unsigned handleMipsTlsRelocation(RelType type, Symbol &sym,
104 InputSectionBase &C, uint64_t Offset,135 InputSectionBase &c, uint64_t offset,
105 int64_t Addend, RelExpr Expr) {136 int64_t addend, RelExpr expr) {
106 if (Expr == R_MIPS_TLSLD) {137 if (expr == R_MIPS_TLSLD) {
107 In.MipsGot->addTlsIndex(*C.File);138 in.mipsGot->addTlsIndex(*c.file);
108 C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});139 c.relocations.push_back({expr, type, offset, addend, &sym});
109 return 1;140 return 1;
110 }141 }
111 if (Expr == R_MIPS_TLSGD) {142 if (expr == R_MIPS_TLSGD) {
112 In.MipsGot->addDynTlsEntry(*C.File, Sym);143 in.mipsGot->addDynTlsEntry(*c.file, sym);
113 C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});144 c.relocations.push_back({expr, type, offset, addend, &sym});
114 return 1;145 return 1;
115 }146 }
116 return 0;147 return 0;
117}148}
118149
119// This function is similar to the `handleMipsTlsRelocation`. ARM also does not150// Notes about General Dynamic and Local Dynamic TLS models below. They may
120// support any relaxations for TLS relocations. ARM is logically similar to Mips151// require the generation of a pair of GOT entries that have associated dynamic
121// in how it handles TLS, but Mips uses its own custom GOT which handles some152// relocations. The pair of GOT entries created are of the form GOT[e0] Module
122// of the cases that ARM uses GOT relocations for.153// Index (Used to find pointer to TLS block at run-time) GOT[e1] Offset of
123//154// symbol in TLS block.
124// We look for TLS global dynamic and local dynamic relocations, these may
125// require the generation of a pair of GOT entries that have associated
126// dynamic relocations. When the results of the dynamic relocations can be
127// resolved at static link time we do so. This is necessary for static linking
128// as there will be no dynamic loader to resolve them at load-time.
129//155//
130// The pair of GOT entries created are of the form
131// GOT[e0] Module Index (Used to find pointer to TLS block at run-time)
132// GOT[e1] Offset of symbol in TLS block
133template <class ELFT>
134static unsigned handleARMTlsRelocation(RelType Type, Symbol &Sym,
135 InputSectionBase &C, uint64_t Offset,
136 int64_t Addend, RelExpr Expr) {
137 // The Dynamic TLS Module Index Relocation for a symbol defined in an
138 // executable is always 1. If the target Symbol is not preemptible then
139 // we know the offset into the TLS block at static link time.
140 bool NeedDynId = Sym.IsPreemptible || Config->Shared;
141 bool NeedDynOff = Sym.IsPreemptible;
142
143 auto AddTlsReloc = [&](uint64_t Off, RelType Type, Symbol *Dest, bool Dyn) {
144 if (Dyn)
145 In.RelaDyn->addReloc(Type, In.Got, Off, Dest);
146 else
147 In.Got->Relocations.push_back({R_ABS, Type, Off, 0, Dest});
148 };
149
150 // Local Dynamic is for access to module local TLS variables, while still
151 // being suitable for being dynamically loaded via dlopen.
152 // GOT[e0] is the module index, with a special value of 0 for the current
153 // module. GOT[e1] is unused. There only needs to be one module index entry.
154 if (Expr == R_TLSLD_PC && In.Got->addTlsIndex()) {
155 AddTlsReloc(In.Got->getTlsIndexOff(), Target->TlsModuleIndexRel,
156 NeedDynId ? nullptr : &Sym, NeedDynId);
157 C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
158 return 1;
159 }
160
161 // Global Dynamic is the most general purpose access model. When we know
162 // the module index and offset of symbol in TLS block we can fill these in
163 // using static GOT relocations.
164 if (Expr == R_TLSGD_PC) {
165 if (In.Got->addDynTlsEntry(Sym)) {
166 uint64_t Off = In.Got->getGlobalDynOffset(Sym);
167 AddTlsReloc(Off, Target->TlsModuleIndexRel, &Sym, NeedDynId);
168 AddTlsReloc(Off + Config->Wordsize, Target->TlsOffsetRel, &Sym,
169 NeedDynOff);
170 }
171 C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
172 return 1;
173 }
174 return 0;
175}
176
177// Returns the number of relocations processed.156// Returns the number of relocations processed.
178template <class ELFT>157template <class ELFT>
179static unsigned158static unsigned
180handleTlsRelocation(RelType Type, Symbol &Sym, InputSectionBase &C,159handleTlsRelocation(RelType type, Symbol &sym, InputSectionBase &c,
181 typename ELFT::uint Offset, int64_t Addend, RelExpr Expr) {160 typename ELFT::uint offset, int64_t addend, RelExpr expr) {
182 if (!Sym.isTls())161 if (!sym.isTls())
183 return 0;162 return 0;
184163
185 if (Config->EMachine == EM_ARM)164 if (config->emachine == EM_MIPS)
186 return handleARMTlsRelocation<ELFT>(Type, Sym, C, Offset, Addend, Expr);165 return handleMipsTlsRelocation(type, sym, c, offset, addend, expr);
187 if (Config->EMachine == EM_MIPS)166
188 return handleMipsTlsRelocation(Type, Sym, C, Offset, Addend, Expr);167 if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC>(
189168 expr) &&
190 if (isRelExprOneOf<R_TLSDESC, R_AARCH64_TLSDESC_PAGE, R_TLSDESC_CALL>(Expr) &&169 config->shared) {
191 Config->Shared) {170 if (in.got->addDynTlsEntry(sym)) {
192 if (In.Got->addDynTlsEntry(Sym)) {171 uint64_t off = in.got->getGlobalDynOffset(sym);
193 uint64_t Off = In.Got->getGlobalDynOffset(Sym);172 mainPart->relaDyn->addReloc(
194 In.RelaDyn->addReloc(173 {target->tlsDescRel, in.got, off, !sym.isPreemptible, &sym, 0});
195 {Target->TlsDescRel, In.Got, Off, !Sym.IsPreemptible, &Sym, 0});
196 }174 }
197 if (Expr != R_TLSDESC_CALL)175 if (expr != R_TLSDESC_CALL)
198 C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});176 c.relocations.push_back({expr, type, offset, addend, &sym});
199 return 1;177 return 1;
200 }178 }
201179
202 if (isRelExprOneOf<R_TLSLD_GOT, R_TLSLD_GOT_FROM_END, R_TLSLD_PC,180 bool canRelax = config->emachine != EM_ARM && config->emachine != EM_RISCV;
203 R_TLSLD_HINT>(Expr)) {181
182 // If we are producing an executable and the symbol is non-preemptable, it
183 // must be defined and the code sequence can be relaxed to use Local-Exec.
184 //
185 // ARM and RISC-V do not support any relaxations for TLS relocations, however,
186 // we can omit the DTPMOD dynamic relocations and resolve them at link time
187 // because them are always 1. This may be necessary for static linking as
188 // DTPMOD may not be expected at load time.
189 bool isLocalInExecutable = !sym.isPreemptible && !config->shared;
190
191 // Local Dynamic is for access to module local TLS variables, while still
192 // being suitable for being dynamically loaded via dlopen. GOT[e0] is the
193 // module index, with a special value of 0 for the current module. GOT[e1] is
194 // unused. There only needs to be one module index entry.
195 if (oneof<R_TLSLD_GOT, R_TLSLD_GOTPLT, R_TLSLD_PC, R_TLSLD_HINT>(
196 expr)) {
204 // Local-Dynamic relocs can be relaxed to Local-Exec.197 // Local-Dynamic relocs can be relaxed to Local-Exec.
205 if (!Config->Shared) {198 if (canRelax && !config->shared) {
206 C.Relocations.push_back(199 c.relocations.push_back(
207 {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,200 {target->adjustRelaxExpr(type, nullptr, R_RELAX_TLS_LD_TO_LE), type,
208 Offset, Addend, &Sym});201 offset, addend, &sym});
209 return Target->TlsGdRelaxSkip;202 return target->getTlsGdRelaxSkip(type);
210 }203 }
211 if (Expr == R_TLSLD_HINT)204 if (expr == R_TLSLD_HINT)
212 return 1;205 return 1;
213 if (In.Got->addTlsIndex())206 if (in.got->addTlsIndex()) {
214 In.RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got,207 if (isLocalInExecutable)
215 In.Got->getTlsIndexOff(), nullptr);208 in.got->relocations.push_back(
216 C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});209 {R_ADDEND, target->symbolicRel, in.got->getTlsIndexOff(), 1, &sym});
210 else
211 mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, in.got,
212 in.got->getTlsIndexOff(), nullptr);
213 }
214 c.relocations.push_back({expr, type, offset, addend, &sym});
217 return 1;215 return 1;
218 }216 }
219217
220 // Local-Dynamic relocs can be relaxed to Local-Exec.218 // Local-Dynamic relocs can be relaxed to Local-Exec.
221 if (Expr == R_ABS && !Config->Shared) {219 if (expr == R_DTPREL && !config->shared) {
222 C.Relocations.push_back(220 c.relocations.push_back(
223 {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_LD_TO_LE), Type,221 {target->adjustRelaxExpr(type, nullptr, R_RELAX_TLS_LD_TO_LE), type,
224 Offset, Addend, &Sym});222 offset, addend, &sym});
225 return 1;223 return 1;
226 }224 }
227225
228 // Local-Dynamic sequence where offset of tls variable relative to dynamic226 // Local-Dynamic sequence where offset of tls variable relative to dynamic
229 // thread pointer is stored in the got.227 // thread pointer is stored in the got. This cannot be relaxed to Local-Exec.
230 if (Expr == R_TLSLD_GOT_OFF) {228 if (expr == R_TLSLD_GOT_OFF) {
231 // Local-Dynamic relocs can be relaxed to local-exec229 if (!sym.isInGot()) {
232 if (!Config->Shared) {230 in.got->addEntry(sym);
233 C.Relocations.push_back({R_RELAX_TLS_LD_TO_LE, Type, Offset, Addend, &Sym});231 uint64_t off = sym.getGotOffset();
234 return 1;232 in.got->relocations.push_back(
233 {R_ABS, target->tlsOffsetRel, off, 0, &sym});
235 }234 }
236 if (!Sym.isInGot()) {235 c.relocations.push_back({expr, type, offset, addend, &sym});
237 In.Got->addEntry(Sym);
238 uint64_t Off = Sym.getGotOffset();
239 In.Got->Relocations.push_back(
240 {R_ABS, Target->TlsOffsetRel, Off, 0, &Sym});
241 }
242 C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
243 return 1;236 return 1;
244 }237 }
245238
246 if (isRelExprOneOf<R_TLSDESC, R_AARCH64_TLSDESC_PAGE, R_TLSDESC_CALL,239 if (oneof<R_AARCH64_TLSDESC_PAGE, R_TLSDESC, R_TLSDESC_CALL, R_TLSDESC_PC,
247 R_TLSGD_GOT, R_TLSGD_GOT_FROM_END, R_TLSGD_PC>(Expr)) {240 R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC>(expr)) {
248 if (Config->Shared) {241 if (!canRelax || config->shared) {
249 if (In.Got->addDynTlsEntry(Sym)) {242 if (in.got->addDynTlsEntry(sym)) {
250 uint64_t Off = In.Got->getGlobalDynOffset(Sym);243 uint64_t off = in.got->getGlobalDynOffset(sym);
251 In.RelaDyn->addReloc(Target->TlsModuleIndexRel, In.Got, Off, &Sym);244
245 if (isLocalInExecutable)
246 // Write one to the GOT slot.
247 in.got->relocations.push_back(
248 {R_ADDEND, target->symbolicRel, off, 1, &sym});
249 else
250 mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, in.got, off, &sym);
252251
253 // If the symbol is preemptible we need the dynamic linker to write252 // If the symbol is preemptible we need the dynamic linker to write
254 // the offset too.253 // the offset too.
255 uint64_t OffsetOff = Off + Config->Wordsize;254 uint64_t offsetOff = off + config->wordsize;
256 if (Sym.IsPreemptible)255 if (sym.isPreemptible)
257 In.RelaDyn->addReloc(Target->TlsOffsetRel, In.Got, OffsetOff, &Sym);256 mainPart->relaDyn->addReloc(target->tlsOffsetRel, in.got, offsetOff,
257 &sym);
258 else258 else
259 In.Got->Relocations.push_back(259 in.got->relocations.push_back(
260 {R_ABS, Target->TlsOffsetRel, OffsetOff, 0, &Sym});260 {R_ABS, target->tlsOffsetRel, offsetOff, 0, &sym});
261 }261 }
262 C.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});262 c.relocations.push_back({expr, type, offset, addend, &sym});
263 return 1;263 return 1;
264 }264 }
265265
266 // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec266 // Global-Dynamic relocs can be relaxed to Initial-Exec or Local-Exec
267 // depending on the symbol being locally defined or not.267 // depending on the symbol being locally defined or not.
268 if (Sym.IsPreemptible) {268 if (sym.isPreemptible) {
269 C.Relocations.push_back(269 c.relocations.push_back(
270 {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_IE), Type,270 {target->adjustRelaxExpr(type, nullptr, R_RELAX_TLS_GD_TO_IE), type,
271 Offset, Addend, &Sym});271 offset, addend, &sym});
272 if (!Sym.isInGot()) {272 if (!sym.isInGot()) {
273 In.Got->addEntry(Sym);273 in.got->addEntry(sym);
274 In.RelaDyn->addReloc(Target->TlsGotRel, In.Got, Sym.getGotOffset(),274 mainPart->relaDyn->addReloc(target->tlsGotRel, in.got, sym.getGotOffset(),
275 &Sym);275 &sym);
276 }276 }
277 } else {277 } else {
278 C.Relocations.push_back(278 c.relocations.push_back(
279 {Target->adjustRelaxExpr(Type, nullptr, R_RELAX_TLS_GD_TO_LE), Type,279 {target->adjustRelaxExpr(type, nullptr, R_RELAX_TLS_GD_TO_LE), type,
280 Offset, Addend, &Sym});280 offset, addend, &sym});
281 }281 }
282 return Target->TlsGdRelaxSkip;282 return target->getTlsGdRelaxSkip(type);
283 }283 }
284284
285 // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally285 // Initial-Exec relocs can be relaxed to Local-Exec if the symbol is locally
286 // defined.286 // defined.
287 if (isRelExprOneOf<R_GOT, R_GOT_FROM_END, R_GOT_PC, R_AARCH64_GOT_PAGE_PC,287 if (oneof<R_GOT, R_GOTPLT, R_GOT_PC, R_AARCH64_GOT_PAGE_PC, R_GOT_OFF,
288 R_GOT_OFF, R_TLSIE_HINT>(Expr) &&288 R_TLSIE_HINT>(expr) &&
289 !Config->Shared && !Sym.IsPreemptible) {289 canRelax && isLocalInExecutable) {
290 C.Relocations.push_back({R_RELAX_TLS_IE_TO_LE, Type, Offset, Addend, &Sym});290 c.relocations.push_back({R_RELAX_TLS_IE_TO_LE, type, offset, addend, &sym});
291 return 1;291 return 1;
292 }292 }
293293
294 if (Expr == R_TLSIE_HINT)294 if (expr == R_TLSIE_HINT)
295 return 1;295 return 1;
296 return 0;296 return 0;
297}297}
298298
299static RelType getMipsPairType(RelType Type, bool IsLocal) {299static RelType getMipsPairType(RelType type, bool isLocal) {
300 switch (Type) {300 switch (type) {
301 case R_MIPS_HI16:301 case R_MIPS_HI16:
302 return R_MIPS_LO16;302 return R_MIPS_LO16;
303 case R_MIPS_GOT16:303 case R_MIPS_GOT16:
...@@ -309,9 +309,9 @@ static RelType getMipsPairType(RelType Type, bool IsLocal) {...@@ -309,9 +309,9 @@ static RelType getMipsPairType(RelType Type, bool IsLocal) {
309 // the high 16 bits of the symbol's value. A paired R_MIPS_LO16309 // the high 16 bits of the symbol's value. A paired R_MIPS_LO16
310 // relocations handle low 16 bits of the address. That allows310 // relocations handle low 16 bits of the address. That allows
311 // to allocate only one GOT entry for every 64 KBytes of local data.311 // to allocate only one GOT entry for every 64 KBytes of local data.
312 return IsLocal ? R_MIPS_LO16 : R_MIPS_NONE;312 return isLocal ? R_MIPS_LO16 : R_MIPS_NONE;
313 case R_MICROMIPS_GOT16:313 case R_MICROMIPS_GOT16:
314 return IsLocal ? R_MICROMIPS_LO16 : R_MIPS_NONE;314 return isLocal ? R_MICROMIPS_LO16 : R_MIPS_NONE;
315 case R_MIPS_PCHI16:315 case R_MIPS_PCHI16:
316 return R_MIPS_PCLO16;316 return R_MIPS_PCLO16;
317 case R_MICROMIPS_HI16:317 case R_MICROMIPS_HI16:
...@@ -323,40 +323,38 @@ static RelType getMipsPairType(RelType Type, bool IsLocal) {...@@ -323,40 +323,38 @@ static RelType getMipsPairType(RelType Type, bool IsLocal) {
323323
324// True if non-preemptable symbol always has the same value regardless of where324// True if non-preemptable symbol always has the same value regardless of where
325// the DSO is loaded.325// the DSO is loaded.
326static bool isAbsolute(const Symbol &Sym) {326static bool isAbsolute(const Symbol &sym) {
327 if (Sym.isUndefWeak())327 if (sym.isUndefWeak())
328 return true;328 return true;
329 if (const auto *DR = dyn_cast<Defined>(&Sym))329 if (const auto *dr = dyn_cast<Defined>(&sym))
330 return DR->Section == nullptr; // Absolute symbol.330 return dr->section == nullptr; // Absolute symbol.
331 return false;331 return false;
332}332}
333333
334static bool isAbsoluteValue(const Symbol &Sym) {334static bool isAbsoluteValue(const Symbol &sym) {
335 return isAbsolute(Sym) || Sym.isTls();335 return isAbsolute(sym) || sym.isTls();
336}336}
337337
338// Returns true if Expr refers a PLT entry.338// Returns true if Expr refers a PLT entry.
339static bool needsPlt(RelExpr Expr) {339static bool needsPlt(RelExpr expr) {
340 return isRelExprOneOf<R_PLT_PC, R_PPC_CALL_PLT, R_PLT, R_AARCH64_PLT_PAGE_PC,340 return oneof<R_PLT_PC, R_PPC32_PLTREL, R_PPC64_CALL_PLT, R_PLT>(expr);
341 R_GOT_PLT, R_AARCH64_GOT_PAGE_PC_PLT>(Expr);
342}341}
343342
344// Returns true if Expr refers a GOT entry. Note that this function343// Returns true if Expr refers a GOT entry. Note that this function
345// returns false for TLS variables even though they need GOT, because344// returns false for TLS variables even though they need GOT, because
346// TLS variables uses GOT differently than the regular variables.345// TLS variables uses GOT differently than the regular variables.
347static bool needsGot(RelExpr Expr) {346static bool needsGot(RelExpr expr) {
348 return isRelExprOneOf<R_GOT, R_GOT_OFF, R_HEXAGON_GOT, R_MIPS_GOT_LOCAL_PAGE,347 return oneof<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,348 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,349 R_GOT_PC, R_GOTPLT>(expr);
351 R_GOT_PLT>(Expr);
352}350}
353351
354// True if this expression is of the form Sym - X, where X is a position in the352// True if this expression is of the form Sym - X, where X is a position in the
355// file (PC, or GOT for example).353// file (PC, or GOT for example).
356static bool isRelExpr(RelExpr Expr) {354static bool isRelExpr(RelExpr expr) {
357 return isRelExprOneOf<R_PC, R_GOTREL, R_GOTREL_FROM_END, R_MIPS_GOTREL,355 return oneof<R_PC, R_GOTREL, R_GOTPLTREL, R_MIPS_GOTREL, R_PPC64_CALL,
358 R_PPC_CALL, R_PPC_CALL_PLT, R_AARCH64_PAGE_PC,356 R_PPC64_RELAX_TOC, R_AARCH64_PAGE_PC, R_RELAX_GOT_PC,
359 R_AARCH64_PLT_PAGE_PC, R_RELAX_GOT_PC>(Expr);357 R_RISCV_PC_INDIRECT>(expr);
360}358}
361359
362// Returns true if a given relocation can be computed at link-time.360// Returns true if a given relocation can be computed at link-time.
...@@ -368,43 +366,43 @@ static bool isRelExpr(RelExpr Expr) {...@@ -368,43 +366,43 @@ static bool isRelExpr(RelExpr Expr) {
368//366//
369// If this function returns false, that means we need to emit a367// If this function returns false, that means we need to emit a
370// dynamic relocation so that the relocation will be fixed at load-time.368// dynamic relocation so that the relocation will be fixed at load-time.
371static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,369static bool isStaticLinkTimeConstant(RelExpr e, RelType type, const Symbol &sym,
372 InputSectionBase &S, uint64_t RelOff) {370 InputSectionBase &s, uint64_t relOff) {
373 // These expressions always compute a constant371 // These expressions always compute a constant
374 if (isRelExprOneOf<R_GOT_FROM_END, R_GOT_OFF, R_HEXAGON_GOT, R_TLSLD_GOT_OFF,372 if (oneof<R_DTPREL, R_GOTPLT, R_GOT_OFF, R_HEXAGON_GOT, R_TLSLD_GOT_OFF,
375 R_MIPS_GOT_LOCAL_PAGE, R_MIPS_GOTREL, R_MIPS_GOT_OFF,373 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,374 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,375 R_AARCH64_GOT_PAGE_PC, R_GOT_PC, R_GOTONLY_PC, R_GOTPLTONLY_PC,
378 R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_PLT_PC, R_TLSGD_GOT,376 R_PLT_PC, R_TLSGD_GOT, R_TLSGD_GOTPLT, R_TLSGD_PC, R_PPC32_PLTREL,
379 R_TLSGD_GOT_FROM_END, R_TLSGD_PC, R_PPC_CALL_PLT,377 R_PPC64_CALL_PLT, R_PPC64_RELAX_TOC, R_RISCV_ADD, R_TLSDESC_CALL,
380 R_TLSDESC_CALL, R_AARCH64_TLSDESC_PAGE, R_HINT,378 R_TLSDESC_PC, R_AARCH64_TLSDESC_PAGE, R_HINT, R_TLSLD_HINT,
381 R_TLSLD_HINT, R_TLSIE_HINT>(E))379 R_TLSIE_HINT>(e))
382 return true;380 return true;
383381
384 // These never do, except if the entire file is position dependent or if382 // These never do, except if the entire file is position dependent or if
385 // only the low bits are used.383 // only the low bits are used.
386 if (E == R_GOT || E == R_GOT_PLT || E == R_PLT || E == R_TLSDESC)384 if (e == R_GOT || e == R_PLT || e == R_TLSDESC)
387 return Target->usesOnlyLowPageBits(Type) || !Config->Pic;385 return target->usesOnlyLowPageBits(type) || !config->isPic;
388386
389 if (Sym.IsPreemptible)387 if (sym.isPreemptible)
390 return false;388 return false;
391 if (!Config->Pic)389 if (!config->isPic)
392 return true;390 return true;
393391
394 // The size of a non preemptible symbol is a constant.392 // The size of a non preemptible symbol is a constant.
395 if (E == R_SIZE)393 if (e == R_SIZE)
396 return true;394 return true;
397395
398 // For the target and the relocation, we want to know if they are396 // For the target and the relocation, we want to know if they are
399 // absolute or relative.397 // absolute or relative.
400 bool AbsVal = isAbsoluteValue(Sym);398 bool absVal = isAbsoluteValue(sym);
401 bool RelE = isRelExpr(E);399 bool relE = isRelExpr(e);
402 if (AbsVal && !RelE)400 if (absVal && !relE)
403 return true;401 return true;
404 if (!AbsVal && RelE)402 if (!absVal && relE)
405 return true;403 return true;
406 if (!AbsVal && !RelE)404 if (!absVal && !relE)
407 return Target->usesOnlyLowPageBits(Type);405 return target->usesOnlyLowPageBits(type);
408406
409 // Relative relocation to an absolute value. This is normally unrepresentable,407 // Relative relocation to an absolute value. This is normally unrepresentable,
410 // but if the relocation refers to a weak undefined symbol, we allow it to408 // but if the relocation refers to a weak undefined symbol, we allow it to
...@@ -414,59 +412,60 @@ static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,...@@ -414,59 +412,60 @@ static bool isStaticLinkTimeConstant(RelExpr E, RelType Type, const Symbol &Sym,
414 // Another special case is MIPS _gp_disp symbol which represents offset412 // Another special case is MIPS _gp_disp symbol which represents offset
415 // between start of a function and '_gp' value and defined as absolute just413 // between start of a function and '_gp' value and defined as absolute just
416 // to simplify the code.414 // to simplify the code.
417 assert(AbsVal && RelE);415 assert(absVal && relE);
418 if (Sym.isUndefWeak())416 if (sym.isUndefWeak())
419 return true;417 return true;
420418
421 error("relocation " + toString(Type) + " cannot refer to absolute symbol: " +419 // We set the final symbols values for linker script defined symbols later.
422 toString(Sym) + getLocation(S, Sym, RelOff));420 // They always can be computed as a link time constant.
421 if (sym.scriptDefined)
422 return true;
423
424 error("relocation " + toString(type) + " cannot refer to absolute symbol: " +
425 toString(sym) + getLocation(s, sym, relOff));
423 return true;426 return true;
424}427}
425428
426static RelExpr toPlt(RelExpr Expr) {429static RelExpr toPlt(RelExpr expr) {
427 switch (Expr) {430 switch (expr) {
428 case R_PPC_CALL:431 case R_PPC64_CALL:
429 return R_PPC_CALL_PLT;432 return R_PPC64_CALL_PLT;
430 case R_PC:433 case R_PC:
431 return R_PLT_PC;434 return R_PLT_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;
436 case R_ABS:435 case R_ABS:
437 return R_PLT;436 return R_PLT;
438 case R_GOT:
439 return R_GOT_PLT;
440 default:437 default:
441 return Expr;438 return expr;
442 }439 }
443}440}
444441
445static RelExpr fromPlt(RelExpr Expr) {442static RelExpr fromPlt(RelExpr expr) {
446 // We decided not to use a plt. Optimize a reference to the plt to a443 // We decided not to use a plt. Optimize a reference to the plt to a
447 // reference to the symbol itself.444 // reference to the symbol itself.
448 switch (Expr) {445 switch (expr) {
449 case R_PLT_PC:446 case R_PLT_PC:
447 case R_PPC32_PLTREL:
450 return R_PC;448 return R_PC;
451 case R_PPC_CALL_PLT:449 case R_PPC64_CALL_PLT:
452 return R_PPC_CALL;450 return R_PPC64_CALL;
453 case R_PLT:451 case R_PLT:
454 return R_ABS;452 return R_ABS;
455 default:453 default:
456 return Expr;454 return expr;
457 }455 }
458}456}
459457
460// Returns true if a given shared symbol is in a read-only segment in a DSO.458// Returns true if a given shared symbol is in a read-only segment in a DSO.
461template <class ELFT> static bool isReadOnly(SharedSymbol &SS) {459template <class ELFT> static bool isReadOnly(SharedSymbol &ss) {
462 typedef typename ELFT::Phdr Elf_Phdr;460 using Elf_Phdr = typename ELFT::Phdr;
463461
464 // Determine if the symbol is read-only by scanning the DSO's program headers.462 // Determine if the symbol is read-only by scanning the DSO's program headers.
465 const SharedFile<ELFT> &File = SS.getFile<ELFT>();463 const SharedFile &file = ss.getFile();
466 for (const Elf_Phdr &Phdr : check(File.getObj().program_headers()))464 for (const Elf_Phdr &phdr :
467 if ((Phdr.p_type == ELF::PT_LOAD || Phdr.p_type == ELF::PT_GNU_RELRO) &&465 check(file.template getObj<ELFT>().program_headers()))
468 !(Phdr.p_flags & ELF::PF_W) && SS.Value >= Phdr.p_vaddr &&466 if ((phdr.p_type == ELF::PT_LOAD || phdr.p_type == ELF::PT_GNU_RELRO) &&
469 SS.Value < Phdr.p_vaddr + Phdr.p_memsz)467 !(phdr.p_flags & ELF::PF_W) && ss.value >= phdr.p_vaddr &&
468 ss.value < phdr.p_vaddr + phdr.p_memsz)
470 return true;469 return true;
471 return false;470 return false;
472}471}
...@@ -477,22 +476,22 @@ template <class ELFT> static bool isReadOnly(SharedSymbol &SS) {...@@ -477,22 +476,22 @@ template <class ELFT> static bool isReadOnly(SharedSymbol &SS) {
477// them are copied by a copy relocation, all of them need to be copied.476// them are copied by a copy relocation, all of them need to be copied.
478// Otherwise, they would refer to different places at runtime.477// Otherwise, they would refer to different places at runtime.
479template <class ELFT>478template <class ELFT>
480static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &SS) {479static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &ss) {
481 typedef typename ELFT::Sym Elf_Sym;480 using Elf_Sym = typename ELFT::Sym;
482481
483 SharedFile<ELFT> &File = SS.getFile<ELFT>();482 SharedFile &file = ss.getFile();
484483
485 SmallSet<SharedSymbol *, 4> Ret;484 SmallSet<SharedSymbol *, 4> ret;
486 for (const Elf_Sym &S : File.getGlobalELFSyms()) {485 for (const Elf_Sym &s : file.template getGlobalELFSyms<ELFT>()) {
487 if (S.st_shndx == SHN_UNDEF || S.st_shndx == SHN_ABS ||486 if (s.st_shndx == SHN_UNDEF || s.st_shndx == SHN_ABS ||
488 S.getType() == STT_TLS || S.st_value != SS.Value)487 s.getType() == STT_TLS || s.st_value != ss.value)
489 continue;488 continue;
490 StringRef Name = check(S.getName(File.getStringTable()));489 StringRef name = check(s.getName(file.getStringTable()));
491 Symbol *Sym = Symtab->find(Name);490 Symbol *sym = symtab->find(name);
492 if (auto *Alias = dyn_cast_or_null<SharedSymbol>(Sym))491 if (auto *alias = dyn_cast_or_null<SharedSymbol>(sym))
493 Ret.insert(Alias);492 ret.insert(alias);
494 }493 }
495 return Ret;494 return ret;
496}495}
497496
498// When a symbol is copy relocated or we create a canonical plt entry, it is497// When a symbol is copy relocated or we create a canonical plt entry, it is
...@@ -500,19 +499,21 @@ static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &SS) {...@@ -500,19 +499,21 @@ static SmallSet<SharedSymbol *, 4> getSymbolsAt(SharedSymbol &SS) {
500// in .bss and in the case of a canonical plt entry it is in .plt. This function499// in .bss and in the case of a canonical plt entry it is in .plt. This function
501// replaces the existing symbol with a Defined pointing to the appropriate500// replaces the existing symbol with a Defined pointing to the appropriate
502// location.501// location.
503static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value,502static void replaceWithDefined(Symbol &sym, SectionBase *sec, uint64_t value,
504 uint64_t Size) {503 uint64_t size) {
505 Symbol Old = Sym;504 Symbol old = sym;
506 replaceSymbol<Defined>(&Sym, Sym.File, Sym.getName(), Sym.Binding,505
507 Sym.StOther, Sym.Type, Value, Size, Sec);506 sym.replace(Defined{sym.file, sym.getName(), sym.binding, sym.stOther,
508 Sym.PltIndex = Old.PltIndex;507 sym.type, value, size, sec});
509 Sym.GotIndex = Old.GotIndex;508
510 Sym.VerdefIndex = Old.VerdefIndex;509 sym.pltIndex = old.pltIndex;
511 Sym.PPC64BranchltIndex = Old.PPC64BranchltIndex;510 sym.gotIndex = old.gotIndex;
512 Sym.IsPreemptible = true;511 sym.verdefIndex = old.verdefIndex;
513 Sym.ExportDynamic = true;512 sym.ppc64BranchltIndex = old.ppc64BranchltIndex;
514 Sym.IsUsedInRegularObj = true;513 sym.isPreemptible = true;
515 Sym.Used = true;514 sym.exportDynamic = true;
515 sym.isUsedInRegularObj = true;
516 sym.used = true;
516}517}
517518
518// Reserve space in .bss or .bss.rel.ro for copy relocation.519// Reserve space in .bss or .bss.rel.ro for copy relocation.
...@@ -557,29 +558,29 @@ static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value,...@@ -557,29 +558,29 @@ static void replaceWithDefined(Symbol &Sym, SectionBase *Sec, uint64_t Value,
557// to the variable in .bss. This kind of issue is sometimes very hard to558// to the variable in .bss. This kind of issue is sometimes very hard to
558// debug. What's a solution? Instead of exporting a varaible V from a DSO,559// debug. What's a solution? Instead of exporting a varaible V from a DSO,
559// define an accessor getV().560// define an accessor getV().
560template <class ELFT> static void addCopyRelSymbol(SharedSymbol &SS) {561template <class ELFT> static void addCopyRelSymbol(SharedSymbol &ss) {
561 // Copy relocation against zero-sized symbol doesn't make sense.562 // Copy relocation against zero-sized symbol doesn't make sense.
562 uint64_t SymSize = SS.getSize();563 uint64_t symSize = ss.getSize();
563 if (SymSize == 0 || SS.Alignment == 0)564 if (symSize == 0 || ss.alignment == 0)
564 fatal("cannot create a copy relocation for symbol " + toString(SS));565 fatal("cannot create a copy relocation for symbol " + toString(ss));
565566
566 // See if this symbol is in a read-only segment. If so, preserve the symbol's567 // See if this symbol is in a read-only segment. If so, preserve the symbol's
567 // memory protection by reserving space in the .bss.rel.ro section.568 // memory protection by reserving space in the .bss.rel.ro section.
568 bool IsReadOnly = isReadOnly<ELFT>(SS);569 bool isRO = isReadOnly<ELFT>(ss);
569 BssSection *Sec = make<BssSection>(IsReadOnly ? ".bss.rel.ro" : ".bss",570 BssSection *sec =
570 SymSize, SS.Alignment);571 make<BssSection>(isRO ? ".bss.rel.ro" : ".bss", symSize, ss.alignment);
571 if (IsReadOnly)572 if (isRO)
572 In.BssRelRo->getParent()->addSection(Sec);573 in.bssRelRo->getParent()->addSection(sec);
573 else574 else
574 In.Bss->getParent()->addSection(Sec);575 in.bss->getParent()->addSection(sec);
575576
576 // Look through the DSO's dynamic symbol table for aliases and create a577 // Look through the DSO's dynamic symbol table for aliases and create a
577 // dynamic symbol for each one. This causes the copy relocation to correctly578 // dynamic symbol for each one. This causes the copy relocation to correctly
578 // interpose any aliases.579 // interpose any aliases.
579 for (SharedSymbol *Sym : getSymbolsAt<ELFT>(SS))580 for (SharedSymbol *sym : getSymbolsAt<ELFT>(ss))
580 replaceWithDefined(*Sym, Sec, 0, Sym->Size);581 replaceWithDefined(*sym, sec, 0, sym->size);
581582
582 In.RelaDyn->addReloc(Target->CopyRel, Sec, 0, &SS);583 mainPart->relaDyn->addReloc(target->copyRel, sec, 0, &ss);
583}584}
584585
585// MIPS has an odd notion of "paired" relocations to calculate addends.586// MIPS has an odd notion of "paired" relocations to calculate addends.
...@@ -587,34 +588,34 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol &SS) {...@@ -587,34 +588,34 @@ template <class ELFT> static void addCopyRelSymbol(SharedSymbol &SS) {
587// R_MIPS_LO16 relocation after that, and an addend is calculated using588// R_MIPS_LO16 relocation after that, and an addend is calculated using
588// the two relocations.589// the two relocations.
589template <class ELFT, class RelTy>590template <class ELFT, class RelTy>
590static int64_t computeMipsAddend(const RelTy &Rel, const RelTy *End,591static int64_t computeMipsAddend(const RelTy &rel, const RelTy *end,
591 InputSectionBase &Sec, RelExpr Expr,592 InputSectionBase &sec, RelExpr expr,
592 bool IsLocal) {593 bool isLocal) {
593 if (Expr == R_MIPS_GOTREL && IsLocal)594 if (expr == R_MIPS_GOTREL && isLocal)
594 return Sec.getFile<ELFT>()->MipsGp0;595 return sec.getFile<ELFT>()->mipsGp0;
595596
596 // The ABI says that the paired relocation is used only for REL.597 // The ABI says that the paired relocation is used only for REL.
597 // See p. 4-17 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf598 // See p. 4-17 at ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
598 if (RelTy::IsRela)599 if (RelTy::IsRela)
599 return 0;600 return 0;
600601
601 RelType Type = Rel.getType(Config->IsMips64EL);602 RelType type = rel.getType(config->isMips64EL);
602 uint32_t PairTy = getMipsPairType(Type, IsLocal);603 uint32_t pairTy = getMipsPairType(type, isLocal);
603 if (PairTy == R_MIPS_NONE)604 if (pairTy == R_MIPS_NONE)
604 return 0;605 return 0;
605606
606 const uint8_t *Buf = Sec.data().data();607 const uint8_t *buf = sec.data().data();
607 uint32_t SymIndex = Rel.getSymbol(Config->IsMips64EL);608 uint32_t symIndex = rel.getSymbol(config->isMips64EL);
608609
609 // To make things worse, paired relocations might not be contiguous in610 // To make things worse, paired relocations might not be contiguous in
610 // the relocation table, so we need to do linear search. *sigh*611 // the relocation table, so we need to do linear search. *sigh*
611 for (const RelTy *RI = &Rel; RI != End; ++RI)612 for (const RelTy *ri = &rel; ri != end; ++ri)
612 if (RI->getType(Config->IsMips64EL) == PairTy &&613 if (ri->getType(config->isMips64EL) == pairTy &&
613 RI->getSymbol(Config->IsMips64EL) == SymIndex)614 ri->getSymbol(config->isMips64EL) == symIndex)
614 return Target->getImplicitAddend(Buf + RI->r_offset, PairTy);615 return target->getImplicitAddend(buf + ri->r_offset, pairTy);
615616
616 warn("can't find matching " + toString(PairTy) + " relocation for " +617 warn("can't find matching " + toString(pairTy) + " relocation for " +
617 toString(Type));618 toString(type));
618 return 0;619 return 0;
619}620}
620621
...@@ -622,59 +623,174 @@ static int64_t computeMipsAddend(const RelTy &Rel, const RelTy *End,...@@ -622,59 +623,174 @@ static int64_t computeMipsAddend(const RelTy &Rel, const RelTy *End,
622// is in a relocation itself. If it is REL, we need to read it from an623// is in a relocation itself. If it is REL, we need to read it from an
623// input section.624// input section.
624template <class ELFT, class RelTy>625template <class ELFT, class RelTy>
625static int64_t computeAddend(const RelTy &Rel, const RelTy *End,626static int64_t computeAddend(const RelTy &rel, const RelTy *end,
626 InputSectionBase &Sec, RelExpr Expr,627 InputSectionBase &sec, RelExpr expr,
627 bool IsLocal) {628 bool isLocal) {
628 int64_t Addend;629 int64_t addend;
629 RelType Type = Rel.getType(Config->IsMips64EL);630 RelType type = rel.getType(config->isMips64EL);
630631
631 if (RelTy::IsRela) {632 if (RelTy::IsRela) {
632 Addend = getAddend<ELFT>(Rel);633 addend = getAddend<ELFT>(rel);
633 } else {634 } else {
634 const uint8_t *Buf = Sec.data().data();635 const uint8_t *buf = sec.data().data();
635 Addend = Target->getImplicitAddend(Buf + Rel.r_offset, Type);636 addend = target->getImplicitAddend(buf + rel.r_offset, type);
636 }637 }
637638
638 if (Config->EMachine == EM_PPC64 && Config->Pic && Type == R_PPC64_TOC)639 if (config->emachine == EM_PPC64 && config->isPic && type == R_PPC64_TOC)
639 Addend += getPPC64TocBase();640 addend += getPPC64TocBase();
640 if (Config->EMachine == EM_MIPS)641 if (config->emachine == EM_MIPS)
641 Addend += computeMipsAddend<ELFT>(Rel, End, Sec, Expr, IsLocal);642 addend += computeMipsAddend<ELFT>(rel, end, sec, expr, isLocal);
642643
643 return Addend;644 return addend;
644}645}
645646
646// Report an undefined symbol if necessary.647// Custom error message if Sym is defined in a discarded section.
647// Returns true if this function printed out an error message.648template <class ELFT>
648static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec,649static std::string maybeReportDiscarded(Undefined &sym) {
649 uint64_t Offset) {650 auto *file = dyn_cast_or_null<ObjFile<ELFT>>(sym.file);
650 if (Sym.isLocal() || !Sym.isUndefined() || Sym.isWeak())651 if (!file || !sym.discardedSecIdx ||
651 return false;652 file->getSections()[sym.discardedSecIdx] != &InputSection::discarded)
653 return "";
654 ArrayRef<Elf_Shdr_Impl<ELFT>> objSections =
655 CHECK(file->getObj().sections(), file);
656
657 std::string msg;
658 if (sym.type == ELF::STT_SECTION) {
659 msg = "relocation refers to a discarded section: ";
660 msg += CHECK(
661 file->getObj().getSectionName(&objSections[sym.discardedSecIdx]), file);
662 } else {
663 msg = "relocation refers to a symbol in a discarded section: " +
664 toString(sym);
665 }
666 msg += "\n>>> defined in " + toString(file);
667
668 Elf_Shdr_Impl<ELFT> elfSec = objSections[sym.discardedSecIdx - 1];
669 if (elfSec.sh_type != SHT_GROUP)
670 return msg;
671
672 // If the discarded section is a COMDAT.
673 StringRef signature = file->getShtGroupSignature(objSections, elfSec);
674 if (const InputFile *prevailing =
675 symtab->comdatGroups.lookup(CachedHashStringRef(signature)))
676 msg += "\n>>> section group signature: " + signature.str() +
677 "\n>>> prevailing definition is in " + toString(prevailing);
678 return msg;
679}
652680
653 bool CanBeExternal =681// Undefined diagnostics are collected in a vector and emitted once all of
654 Sym.computeBinding() != STB_LOCAL && Sym.Visibility == STV_DEFAULT;682// them are known, so that some postprocessing on the list of undefined symbols
655 if (Config->UnresolvedSymbols == UnresolvedPolicy::Ignore && CanBeExternal)683// can happen before lld emits diagnostics.
656 return false;684struct UndefinedDiag {
685 Symbol *sym;
686 struct Loc {
687 InputSectionBase *sec;
688 uint64_t offset;
689 };
690 std::vector<Loc> locs;
691 bool isWarning;
692};
693
694static std::vector<UndefinedDiag> undefs;
695
696template <class ELFT>
697static void reportUndefinedSymbol(const UndefinedDiag &undef) {
698 Symbol &sym = *undef.sym;
699
700 auto visibility = [&]() -> std::string {
701 switch (sym.visibility) {
702 case STV_INTERNAL:
703 return "internal ";
704 case STV_HIDDEN:
705 return "hidden ";
706 case STV_PROTECTED:
707 return "protected ";
708 default:
709 return "";
710 }
711 };
657712
658 std::string Msg =713 std::string msg = maybeReportDiscarded<ELFT>(cast<Undefined>(sym));
659 "undefined symbol: " + toString(Sym) + "\n>>> referenced by ";714 if (msg.empty())
715 msg = "undefined " + visibility() + "symbol: " + toString(sym);
716
717 const size_t maxUndefReferences = 10;
718 size_t i = 0;
719 for (UndefinedDiag::Loc l : undef.locs) {
720 if (i >= maxUndefReferences)
721 break;
722 InputSectionBase &sec = *l.sec;
723 uint64_t offset = l.offset;
724
725 msg += "\n>>> referenced by ";
726 std::string src = sec.getSrcMsg(sym, offset);
727 if (!src.empty())
728 msg += src + "\n>>> ";
729 msg += sec.getObjMsg(offset);
730 i++;
731 }
660732
661 std::string Src = Sec.getSrcMsg(Sym, Offset);733 if (i < undef.locs.size())
662 if (!Src.empty())734 msg += ("\n>>> referenced " + Twine(undef.locs.size() - i) + " more times")
663 Msg += Src + "\n>>> ";735 .str();
664 Msg += Sec.getObjMsg(Offset);
665736
666 if (Sym.getName().startswith("_ZTV"))737 if (sym.getName().startswith("_ZTV"))
667 Msg += "\nthe vtable symbol may be undefined because the class is missing "738 msg += "\nthe vtable symbol may be undefined because the class is missing "
668 "its key function (see https://lld.llvm.org/missingkeyfunction)";739 "its key function (see https://lld.llvm.org/missingkeyfunction)";
669740
670 if ((Config->UnresolvedSymbols == UnresolvedPolicy::Warn && CanBeExternal) ||741 if (undef.isWarning)
671 Config->NoinhibitExec) {742 warn(msg);
672 warn(Msg);743 else
673 return false;744 error(msg);
745}
746
747template <class ELFT> void elf::reportUndefinedSymbols() {
748 // Find the first "undefined symbol" diagnostic for each diagnostic, and
749 // collect all "referenced from" lines at the first diagnostic.
750 DenseMap<Symbol *, UndefinedDiag *> firstRef;
751 for (UndefinedDiag &undef : undefs) {
752 assert(undef.locs.size() == 1);
753 if (UndefinedDiag *canon = firstRef.lookup(undef.sym)) {
754 canon->locs.push_back(undef.locs[0]);
755 undef.locs.clear();
756 } else
757 firstRef[undef.sym] = &undef;
674 }758 }
675759
676 error(Msg);760 for (const UndefinedDiag &undef : undefs) {
677 return true;761 if (!undef.locs.empty())
762 reportUndefinedSymbol<ELFT>(undef);
763 }
764 undefs.clear();
765}
766
767// Report an undefined symbol if necessary.
768// Returns true if the undefined symbol will produce an error message.
769template <class ELFT>
770static bool maybeReportUndefined(Symbol &sym, InputSectionBase &sec,
771 uint64_t offset) {
772 if (!sym.isUndefined() || sym.isWeak())
773 return false;
774
775 bool canBeExternal = !sym.isLocal() && sym.computeBinding() != STB_LOCAL &&
776 sym.visibility == STV_DEFAULT;
777 if (config->unresolvedSymbols == UnresolvedPolicy::Ignore && canBeExternal)
778 return false;
779
780 // clang (as of 2019-06-12) / gcc (as of 8.2.1) PPC64 may emit a .rela.toc
781 // which references a switch table in a discarded .rodata/.text section. The
782 // .toc and the .rela.toc are incorrectly not placed in the comdat. The ELF
783 // spec says references from outside the group to a STB_LOCAL symbol are not
784 // allowed. Work around the bug.
785 if (config->emachine == EM_PPC64 &&
786 cast<Undefined>(sym).discardedSecIdx != 0 && sec.name == ".toc")
787 return false;
788
789 bool isWarning =
790 (config->unresolvedSymbols == UnresolvedPolicy::Warn && canBeExternal) ||
791 config->noinhibitExec;
792 undefs.push_back({&sym, {{&sec, offset}}, isWarning});
793 return !isWarning;
678}794}
679795
680// MIPS N32 ABI treats series of successive relocations with the same offset796// MIPS N32 ABI treats series of successive relocations with the same offset
...@@ -682,14 +798,14 @@ static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec,...@@ -682,14 +798,14 @@ static bool maybeReportUndefined(Symbol &Sym, InputSectionBase &Sec,
682// packs all relocations into the single relocation record. Here we emulate798// packs all relocations into the single relocation record. Here we emulate
683// this for the N32 ABI. Iterate over relocation with the same offset and put799// this for the N32 ABI. Iterate over relocation with the same offset and put
684// theirs types into the single bit-set.800// theirs types into the single bit-set.
685template <class RelTy> static RelType getMipsN32RelType(RelTy *&Rel, RelTy *End) {801template <class RelTy> static RelType getMipsN32RelType(RelTy *&rel, RelTy *end) {
686 RelType Type = 0;802 RelType type = 0;
687 uint64_t Offset = Rel->r_offset;803 uint64_t offset = rel->r_offset;
688804
689 int N = 0;805 int n = 0;
690 while (Rel != End && Rel->r_offset == Offset)806 while (rel != end && rel->r_offset == offset)
691 Type |= (Rel++)->getType(Config->IsMips64EL) << (8 * N++);807 type |= (rel++)->getType(config->isMips64EL) << (8 * n++);
692 return Type;808 return type;
693}809}
694810
695// .eh_frame sections are mergeable input sections, so their input811// .eh_frame sections are mergeable input sections, so their input
...@@ -706,77 +822,72 @@ template <class RelTy> static RelType getMipsN32RelType(RelTy *&Rel, RelTy *End)...@@ -706,77 +822,72 @@ template <class RelTy> static RelType getMipsN32RelType(RelTy *&Rel, RelTy *End)
706namespace {822namespace {
707class OffsetGetter {823class OffsetGetter {
708public:824public:
709 explicit OffsetGetter(InputSectionBase &Sec) {825 explicit OffsetGetter(InputSectionBase &sec) {
710 if (auto *Eh = dyn_cast<EhInputSection>(&Sec))826 if (auto *eh = dyn_cast<EhInputSection>(&sec))
711 Pieces = Eh->Pieces;827 pieces = eh->pieces;
712 }828 }
713829
714 // Translates offsets in input sections to offsets in output sections.830 // Translates offsets in input sections to offsets in output sections.
715 // Given offset must increase monotonically. We assume that Piece is831 // Given offset must increase monotonically. We assume that Piece is
716 // sorted by InputOff.832 // sorted by inputOff.
717 uint64_t get(uint64_t Off) {833 uint64_t get(uint64_t off) {
718 if (Pieces.empty())834 if (pieces.empty())
719 return Off;835 return off;
720836
721 while (I != Pieces.size() && Pieces[I].InputOff + Pieces[I].Size <= Off)837 while (i != pieces.size() && pieces[i].inputOff + pieces[i].size <= off)
722 ++I;838 ++i;
723 if (I == Pieces.size())839 if (i == pieces.size())
724 fatal(".eh_frame: relocation is not in any piece");840 fatal(".eh_frame: relocation is not in any piece");
725841
726 // Pieces must be contiguous, so there must be no holes in between.842 // Pieces must be contiguous, so there must be no holes in between.
727 assert(Pieces[I].InputOff <= Off && "Relocation not in any piece");843 assert(pieces[i].inputOff <= off && "Relocation not in any piece");
728844
729 // Offset -1 means that the piece is dead (i.e. garbage collected).845 // Offset -1 means that the piece is dead (i.e. garbage collected).
730 if (Pieces[I].OutputOff == -1)846 if (pieces[i].outputOff == -1)
731 return -1;847 return -1;
732 return Pieces[I].OutputOff + Off - Pieces[I].InputOff;848 return pieces[i].outputOff + off - pieces[i].inputOff;
733 }849 }
734850
735private:851private:
736 ArrayRef<EhSectionPiece> Pieces;852 ArrayRef<EhSectionPiece> pieces;
737 size_t I = 0;853 size_t i = 0;
738};854};
739} // namespace855} // namespace
740856
741static void addRelativeReloc(InputSectionBase *IS, uint64_t OffsetInSec,857static void addRelativeReloc(InputSectionBase *isec, uint64_t offsetInSec,
742 Symbol *Sym, int64_t Addend, RelExpr Expr,858 Symbol *sym, int64_t addend, RelExpr expr,
743 RelType Type) {859 RelType type) {
744 // Add a relative relocation. If RelrDyn section is enabled, and the860 Partition &part = isec->getPartition();
861
862 // Add a relative relocation. If relrDyn section is enabled, and the
745 // relocation offset is guaranteed to be even, add the relocation to863 // relocation offset is guaranteed to be even, add the relocation to
746 // the RelrDyn section, otherwise add it to the RelaDyn section.864 // the relrDyn section, otherwise add it to the relaDyn section.
747 // RelrDyn sections don't support odd offsets. Also, RelrDyn sections865 // relrDyn sections don't support odd offsets. Also, relrDyn sections
748 // don't store the addend values, so we must write it to the relocated866 // don't store the addend values, so we must write it to the relocated
749 // address.867 // address.
750 if (In.RelrDyn && IS->Alignment >= 2 && OffsetInSec % 2 == 0) {868 if (part.relrDyn && isec->alignment >= 2 && offsetInSec % 2 == 0) {
751 IS->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym});869 isec->relocations.push_back({expr, type, offsetInSec, addend, sym});
752 In.RelrDyn->Relocs.push_back({IS, OffsetInSec});870 part.relrDyn->relocs.push_back({isec, offsetInSec});
753 return;871 return;
754 }872 }
755 In.RelaDyn->addReloc(Target->RelativeRel, IS, OffsetInSec, Sym, Addend, Expr,873 part.relaDyn->addReloc(target->relativeRel, isec, offsetInSec, sym, addend,
756 Type);874 expr, type);
757}875}
758876
759template <class ELFT, class GotPltSection>877template <class ELFT, class GotPltSection>
760static void addPltEntry(PltSection *Plt, GotPltSection *GotPlt,878static void addPltEntry(PltSection *plt, GotPltSection *gotPlt,
761 RelocationBaseSection *Rel, RelType Type, Symbol &Sym) {879 RelocationBaseSection *rel, RelType type, Symbol &sym) {
762 Plt->addEntry<ELFT>(Sym);880 plt->addEntry<ELFT>(sym);
763 GotPlt->addEntry(Sym);881 gotPlt->addEntry(sym);
764 Rel->addReloc(882 rel->addReloc(
765 {Type, GotPlt, Sym.getGotPltOffset(), !Sym.IsPreemptible, &Sym, 0});883 {type, gotPlt, sym.getGotPltOffset(), !sym.isPreemptible, &sym, 0});
766}884}
767885
768template <class ELFT> static void addGotEntry(Symbol &Sym) {886static void addGotEntry(Symbol &sym) {
769 In.Got->addEntry(Sym);887 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;
778888
779 uint64_t Off = Sym.getGotOffset();889 RelExpr expr = sym.isTls() ? R_TLS : R_ABS;
890 uint64_t off = sym.getGotOffset();
780891
781 // If a GOT slot value can be calculated at link-time, which is now,892 // If a GOT slot value can be calculated at link-time, which is now,
782 // we can just fill that out.893 // we can just fill that out.
...@@ -785,42 +896,42 @@ template <class ELFT> static void addGotEntry(Symbol &Sym) {...@@ -785,42 +896,42 @@ template <class ELFT> static void addGotEntry(Symbol &Sym) {
785 // add a static relocation to a Relocations vector so that896 // add a static relocation to a Relocations vector so that
786 // InputSection::relocate will do the work for us. We may be able897 // InputSection::relocate will do the work for us. We may be able
787 // to just write a value now, but it is a TODO.)898 // to just write a value now, but it is a TODO.)
788 bool IsLinkTimeConstant =899 bool isLinkTimeConstant =
789 !Sym.IsPreemptible && (!Config->Pic || isAbsolute(Sym));900 !sym.isPreemptible && (!config->isPic || isAbsolute(sym));
790 if (IsLinkTimeConstant) {901 if (isLinkTimeConstant) {
791 In.Got->Relocations.push_back({Expr, Target->GotRel, Off, 0, &Sym});902 in.got->relocations.push_back({expr, target->symbolicRel, off, 0, &sym});
792 return;903 return;
793 }904 }
794905
795 // Otherwise, we emit a dynamic relocation to .rel[a].dyn so that906 // Otherwise, we emit a dynamic relocation to .rel[a].dyn so that
796 // the GOT slot will be fixed at load-time.907 // the GOT slot will be fixed at load-time.
797 if (!Sym.isTls() && !Sym.IsPreemptible && Config->Pic && !isAbsolute(Sym)) {908 if (!sym.isTls() && !sym.isPreemptible && config->isPic && !isAbsolute(sym)) {
798 addRelativeReloc(In.Got, Off, &Sym, 0, R_ABS, Target->GotRel);909 addRelativeReloc(in.got, off, &sym, 0, R_ABS, target->symbolicRel);
799 return;910 return;
800 }911 }
801 In.RelaDyn->addReloc(Sym.isTls() ? Target->TlsGotRel : Target->GotRel, In.Got,912 mainPart->relaDyn->addReloc(
802 Off, &Sym, 0, Sym.IsPreemptible ? R_ADDEND : R_ABS,913 sym.isTls() ? target->tlsGotRel : target->gotRel, in.got, off, &sym, 0,
803 Target->GotRel);914 sym.isPreemptible ? R_ADDEND : R_ABS, target->symbolicRel);
804}915}
805916
806// Return true if we can define a symbol in the executable that917// Return true if we can define a symbol in the executable that
807// contains the value/function of a symbol defined in a shared918// contains the value/function of a symbol defined in a shared
808// library.919// library.
809static bool canDefineSymbolInExecutable(Symbol &Sym) {920static bool canDefineSymbolInExecutable(Symbol &sym) {
810 // If the symbol has default visibility the symbol defined in the921 // If the symbol has default visibility the symbol defined in the
811 // executable will preempt it.922 // executable will preempt it.
812 // Note that we want the visibility of the shared symbol itself, not923 // Note that we want the visibility of the shared symbol itself, not
813 // the visibility of the symbol in the output file we are producing. That is924 // the visibility of the symbol in the output file we are producing. That is
814 // why we use Sym.StOther.925 // why we use Sym.stOther.
815 if ((Sym.StOther & 0x3) == STV_DEFAULT)926 if ((sym.stOther & 0x3) == STV_DEFAULT)
816 return true;927 return true;
817928
818 // If we are allowed to break address equality of functions, defining929 // If we are allowed to break address equality of functions, defining
819 // a plt entry will allow the program to call the function in the930 // a plt entry will allow the program to call the function in the
820 // .so, but the .so and the executable will no agree on the address931 // .so, but the .so and the executable will no agree on the address
821 // of the function. Similar logic for objects.932 // of the function. Similar logic for objects.
822 return ((Sym.isFunc() && Config->IgnoreFunctionAddressEquality) ||933 return ((sym.isFunc() && config->ignoreFunctionAddressEquality) ||
823 (Sym.isObject() && Config->IgnoreDataAddressEquality));934 (sym.isObject() && config->ignoreDataAddressEquality));
824}935}
825936
826// The reason we have to do this early scan is as follows937// The reason we have to do this early scan is as follows
...@@ -837,23 +948,33 @@ static bool canDefineSymbolInExecutable(Symbol &Sym) {...@@ -837,23 +948,33 @@ static bool canDefineSymbolInExecutable(Symbol &Sym) {
837// complicates things for the dynamic linker and means we would have to reserve948// complicates things for the dynamic linker and means we would have to reserve
838// space for the extra PT_LOAD even if we end up not using it.949// space for the extra PT_LOAD even if we end up not using it.
839template <class ELFT, class RelTy>950template <class ELFT, class RelTy>
840static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type,951static void processRelocAux(InputSectionBase &sec, RelExpr expr, RelType type,
841 uint64_t Offset, Symbol &Sym, const RelTy &Rel,952 uint64_t offset, Symbol &sym, const RelTy &rel,
842 int64_t Addend) {953 int64_t addend) {
843 if (isStaticLinkTimeConstant(Expr, Type, Sym, Sec, Offset)) {954 // If the relocation is known to be a link-time constant, we know no dynamic
844 Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});955 // relocation will be created, pass the control to relocateAlloc() or
956 // relocateNonAlloc() to resolve it.
957 //
958 // The behavior of an undefined weak reference is implementation defined. If
959 // the relocation is to a weak undef, and we are producing an executable, let
960 // relocate{,Non}Alloc() resolve it.
961 if (isStaticLinkTimeConstant(expr, type, sym, sec, offset) ||
962 (!config->shared && sym.isUndefWeak())) {
963 sec.relocations.push_back({expr, type, offset, addend, &sym});
845 return;964 return;
846 }965 }
847 bool CanWrite = (Sec.Flags & SHF_WRITE) || !Config->ZText;
848 if (CanWrite) {
849 // R_GOT refers to a position in the got, even if the symbol is preemptible.
850 bool IsPreemptibleValue = Sym.IsPreemptible && Expr != R_GOT;
851966
852 if (!IsPreemptibleValue) {967 bool canWrite = (sec.flags & SHF_WRITE) || !config->zText;
853 addRelativeReloc(&Sec, Offset, &Sym, Addend, Expr, Type);968 if (canWrite) {
969 RelType rel = target->getDynRel(type);
970 if (expr == R_GOT || (rel == target->symbolicRel && !sym.isPreemptible)) {
971 addRelativeReloc(&sec, offset, &sym, addend, expr, type);
854 return;972 return;
855 } else if (RelType Rel = Target->getDynRel(Type)) {973 } else if (rel != 0) {
856 In.RelaDyn->addReloc(Rel, &Sec, Offset, &Sym, Addend, R_ADDEND, Type);974 if (config->emachine == EM_MIPS && rel == target->symbolicRel)
975 rel = target->relativeRel;
976 sec.getPartition().relaDyn->addReloc(rel, &sec, offset, &sym, addend,
977 R_ADDEND, type);
857978
858 // MIPS ABI turns using of GOT and dynamic relocations inside out.979 // MIPS ABI turns using of GOT and dynamic relocations inside out.
859 // While regular ABI uses dynamic relocations to fill up GOT entries980 // While regular ABI uses dynamic relocations to fill up GOT entries
...@@ -870,62 +991,62 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type,...@@ -870,62 +991,62 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type,
870 // to the GOT entry and reads the GOT entry when it needs to perform991 // to the GOT entry and reads the GOT entry when it needs to perform
871 // a dynamic relocation.992 // a dynamic relocation.
872 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19993 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf p.4-19
873 if (Config->EMachine == EM_MIPS)994 if (config->emachine == EM_MIPS)
874 In.MipsGot->addEntry(*Sec.File, Sym, Addend, Expr);995 in.mipsGot->addEntry(*sec.file, sym, addend, expr);
875 return;996 return;
876 }997 }
877 }998 }
878999
879 // If the relocation is to a weak undef, and we are producing1000 if (!canWrite && (config->isPic && !isRelExpr(expr))) {
880 // executable, give up on it and produce a non preemptible 0.
881 if (!Config->Shared && Sym.isUndefWeak()) {
882 Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});
883 return;
884 }
885
886 if (!CanWrite && (Config->Pic && !isRelExpr(Expr))) {
887 error(1001 error(
888 "can't create dynamic relocation " + toString(Type) + " against " +1002 "can't create dynamic relocation " + toString(type) + " against " +
889 (Sym.getName().empty() ? "local symbol" : "symbol: " + toString(Sym)) +1003 (sym.getName().empty() ? "local symbol" : "symbol: " + toString(sym)) +
890 " in readonly segment; recompile object files with -fPIC "1004 " in readonly segment; recompile object files with -fPIC "
891 "or pass '-Wl,-z,notext' to allow text relocations in the output" +1005 "or pass '-Wl,-z,notext' to allow text relocations in the output" +
892 getLocation(Sec, Sym, Offset));1006 getLocation(sec, sym, offset));
893 return;1007 return;
894 }1008 }
8951009
896 // Copy relocations are only possible if we are creating an executable.1010 // Copy relocations (for STT_OBJECT) and canonical PLT (for STT_FUNC) are only
897 if (Config->Shared) {1011 // possible in an executable.
898 errorOrWarn("relocation " + toString(Type) +1012 //
899 " cannot be used against symbol " + toString(Sym) +1013 // Among R_ABS relocatoin types, symbolicRel has the same size as the word
900 "; recompile with -fPIC" + getLocation(Sec, Sym, Offset));1014 // size. Others have fewer bits and may cause runtime overflow in -pie/-shared
1015 // mode. Disallow them.
1016 if (config->shared ||
1017 (config->pie && expr == R_ABS && type != target->symbolicRel)) {
1018 errorOrWarn(
1019 "relocation " + toString(type) + " cannot be used against " +
1020 (sym.getName().empty() ? "local symbol" : "symbol " + toString(sym)) +
1021 "; recompile with -fPIC" + getLocation(sec, sym, offset));
901 return;1022 return;
902 }1023 }
9031024
904 // If the symbol is undefined we already reported any relevant errors.1025 // If the symbol is undefined we already reported any relevant errors.
905 if (Sym.isUndefined())1026 if (sym.isUndefined())
906 return;1027 return;
9071028
908 if (!canDefineSymbolInExecutable(Sym)) {1029 if (!canDefineSymbolInExecutable(sym)) {
909 error("cannot preempt symbol: " + toString(Sym) +1030 error("cannot preempt symbol: " + toString(sym) +
910 getLocation(Sec, Sym, Offset));1031 getLocation(sec, sym, offset));
911 return;1032 return;
912 }1033 }
9131034
914 if (Sym.isObject()) {1035 if (sym.isObject()) {
915 // Produce a copy relocation.1036 // Produce a copy relocation.
916 if (auto *SS = dyn_cast<SharedSymbol>(&Sym)) {1037 if (auto *ss = dyn_cast<SharedSymbol>(&sym)) {
917 if (!Config->ZCopyreloc)1038 if (!config->zCopyreloc)
918 error("unresolvable relocation " + toString(Type) +1039 error("unresolvable relocation " + toString(type) +
919 " against symbol '" + toString(*SS) +1040 " against symbol '" + toString(*ss) +
920 "'; recompile with -fPIC or remove '-z nocopyreloc'" +1041 "'; recompile with -fPIC or remove '-z nocopyreloc'" +
921 getLocation(Sec, Sym, Offset));1042 getLocation(sec, sym, offset));
922 addCopyRelSymbol<ELFT>(*SS);1043 addCopyRelSymbol<ELFT>(*ss);
923 }1044 }
924 Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});1045 sec.relocations.push_back({expr, type, offset, addend, &sym});
925 return;1046 return;
926 }1047 }
9271048
928 if (Sym.isFunc()) {1049 if (sym.isFunc()) {
929 // This handles a non PIC program call to function in a shared library. In1050 // This handles a non PIC program call to function in a shared library. In
930 // an ideal world, we could just report an error saying the relocation can1051 // an ideal world, we could just report an error saying the relocation can
931 // overflow at runtime. In the real world with glibc, crt1.o has a1052 // overflow at runtime. In the real world with glibc, crt1.o has a
...@@ -953,167 +1074,333 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type,...@@ -953,167 +1074,333 @@ static void processRelocAux(InputSectionBase &Sec, RelExpr Expr, RelType Type,
953 // compiled without -fPIE/-fPIC and doesn't maintain ebx.1074 // compiled without -fPIE/-fPIC and doesn't maintain ebx.
954 // * If a library definition gets preempted to the executable, it will have1075 // * If a library definition gets preempted to the executable, it will have
955 // the wrong ebx value.1076 // the wrong ebx value.
956 if (Config->Pie && Config->EMachine == EM_386)1077 if (config->pie && config->emachine == EM_386)
957 errorOrWarn("symbol '" + toString(Sym) +1078 errorOrWarn("symbol '" + toString(sym) +
958 "' cannot be preempted; recompile with -fPIE" +1079 "' cannot be preempted; recompile with -fPIE" +
959 getLocation(Sec, Sym, Offset));1080 getLocation(sec, sym, offset));
960 if (!Sym.isInPlt())1081 if (!sym.isInPlt())
961 addPltEntry<ELFT>(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym);1082 addPltEntry<ELFT>(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
962 if (!Sym.isDefined())1083 if (!sym.isDefined())
963 replaceWithDefined(Sym, In.Plt, getPltEntryOffset(Sym.PltIndex), 0);1084 replaceWithDefined(
964 Sym.NeedsPltAddr = true;1085 sym, in.plt,
965 Sec.Relocations.push_back({Expr, Type, Offset, Addend, &Sym});1086 target->pltHeaderSize + target->pltEntrySize * sym.pltIndex, 0);
1087 sym.needsPltAddr = true;
1088 sec.relocations.push_back({expr, type, offset, addend, &sym});
966 return;1089 return;
967 }1090 }
9681091
969 errorOrWarn("symbol '" + toString(Sym) + "' has no type" +1092 errorOrWarn("symbol '" + toString(sym) + "' has no type" +
970 getLocation(Sec, Sym, Offset));1093 getLocation(sec, sym, offset));
971}1094}
9721095
1096struct IRelativeReloc {
1097 RelType type;
1098 InputSectionBase *sec;
1099 uint64_t offset;
1100 Symbol *sym;
1101};
1102
1103static std::vector<IRelativeReloc> iRelativeRelocs;
1104
973template <class ELFT, class RelTy>1105template <class ELFT, class RelTy>
974static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I,1106static void scanReloc(InputSectionBase &sec, OffsetGetter &getOffset, RelTy *&i,
975 RelTy *End) {1107 RelTy *end) {
976 const RelTy &Rel = *I;1108 const RelTy &rel = *i;
977 Symbol &Sym = Sec.getFile<ELFT>()->getRelocTargetSym(Rel);1109 uint32_t symIndex = rel.getSymbol(config->isMips64EL);
978 RelType Type;1110 Symbol &sym = sec.getFile<ELFT>()->getSymbol(symIndex);
1111 RelType type;
9791112
980 // Deal with MIPS oddity.1113 // Deal with MIPS oddity.
981 if (Config->MipsN32Abi) {1114 if (config->mipsN32Abi) {
982 Type = getMipsN32RelType(I, End);1115 type = getMipsN32RelType(i, end);
983 } else {1116 } else {
984 Type = Rel.getType(Config->IsMips64EL);1117 type = rel.getType(config->isMips64EL);
985 ++I;1118 ++i;
986 }1119 }
9871120
988 // Get an offset in an output section this relocation is applied to.1121 // Get an offset in an output section this relocation is applied to.
989 uint64_t Offset = GetOffset.get(Rel.r_offset);1122 uint64_t offset = getOffset.get(rel.r_offset);
990 if (Offset == uint64_t(-1))1123 if (offset == uint64_t(-1))
991 return;1124 return;
9921125
993 // Skip if the target symbol is an erroneous undefined symbol.1126 // Error if the target symbol is undefined. Symbol index 0 may be used by
994 if (maybeReportUndefined(Sym, Sec, Rel.r_offset))1127 // marker relocations, e.g. R_*_NONE and R_ARM_V4BX. Don't error on them.
1128 if (symIndex != 0 && maybeReportUndefined<ELFT>(sym, sec, rel.r_offset))
995 return;1129 return;
9961130
997 const uint8_t *RelocatedAddr = Sec.data().begin() + Rel.r_offset;1131 const uint8_t *relocatedAddr = sec.data().begin() + rel.r_offset;
998 RelExpr Expr = Target->getRelExpr(Type, Sym, RelocatedAddr);1132 RelExpr expr = target->getRelExpr(type, sym, relocatedAddr);
9991133
1000 // Ignore "hint" relocations because they are only markers for relaxation.1134 // Ignore "hint" relocations because they are only markers for relaxation.
1001 if (isRelExprOneOf<R_HINT, R_NONE>(Expr))1135 if (oneof<R_HINT, R_NONE>(expr))
1002 return;1136 return;
10031137
1004 // Strenghten or relax relocations.1138 // We can separate the small code model relocations into 2 categories:
1005 //1139 // 1) Those that access the compiler generated .toc sections.
1006 // GNU ifunc symbols must be accessed via PLT because their addresses1140 // 2) Those that access the linker allocated got entries.
1007 // are determined by runtime.1141 // lld allocates got entries to symbols on demand. Since we don't try to sort
1142 // the got entries in any way, we don't have to track which objects have
1143 // got-based small code model relocs. The .toc sections get placed after the
1144 // end of the linker allocated .got section and we do sort those so sections
1145 // addressed with small code model relocations come first.
1146 if (config->emachine == EM_PPC64 && isPPC64SmallCodeModelTocReloc(type))
1147 sec.file->ppc64SmallCodeModelTocRelocs = true;
1148
1149 if (sym.isGnuIFunc() && !config->zText && config->warnIfuncTextrel) {
1150 warn("using ifunc symbols when text relocations are allowed may produce "
1151 "a binary that will segfault, if the object file is linked with "
1152 "old version of glibc (glibc 2.28 and earlier). If this applies to "
1153 "you, consider recompiling the object files without -fPIC and "
1154 "without -Wl,-z,notext option. Use -no-warn-ifunc-textrel to "
1155 "turn off this warning." +
1156 getLocation(sec, sym, offset));
1157 }
1158
1159 // Read an addend.
1160 int64_t addend = computeAddend<ELFT>(rel, end, sec, expr, sym.isLocal());
1161
1162 // Relax relocations.
1008 //1163 //
1009 // On the other hand, if we know that a PLT entry will be resolved within1164 // If we know that a PLT entry will be resolved within the same ELF module, we
1010 // the same ELF module, we can skip PLT access and directly jump to the1165 // can skip PLT access and directly jump to the destination function. For
1011 // destination function. For example, if we are linking a main exectuable,1166 // example, if we are linking a main exectuable, all dynamic symbols that can
1012 // all dynamic symbols that can be resolved within the executable will1167 // be resolved within the executable will actually be resolved that way at
1013 // actually be resolved that way at runtime, because the main exectuable1168 // runtime, because the main exectuable is always at the beginning of a search
1014 // is always at the beginning of a search list. We can leverage that fact.1169 // list. We can leverage that fact.
1015 if (Sym.isGnuIFunc()) {1170 if (!sym.isPreemptible && (!sym.isGnuIFunc() || config->zIfuncNoplt)) {
1016 if (!Config->ZText && Config->WarnIfuncTextrel) {1171 if (expr == R_GOT_PC && !isAbsoluteValue(sym)) {
1017 warn("using ifunc symbols when text relocations are allowed may produce "1172 expr = target->adjustRelaxExpr(type, relocatedAddr, expr);
1018 "a binary that will segfault, if the object file is linked with "1173 } else {
1019 "old version of glibc (glibc 2.28 and earlier). If this applies to "1174 // Addend of R_PPC_PLTREL24 is used to choose call stub type. It should be
1020 "you, consider recompiling the object files without -fPIC and "1175 // ignored if optimized to R_PC.
1021 "without -Wl,-z,notext option. Use -no-warn-ifunc-textrel to "1176 if (config->emachine == EM_PPC && expr == R_PPC32_PLTREL)
1022 "turn off this warning." +1177 addend = 0;
1023 getLocation(Sec, Sym, Offset));1178 expr = fromPlt(expr);
1024 }1179 }
1025 Expr = toPlt(Expr);
1026 } else if (!Sym.IsPreemptible && Expr == R_GOT_PC && !isAbsoluteValue(Sym)) {
1027 Expr = Target->adjustRelaxExpr(Type, RelocatedAddr, Expr);
1028 } else if (!Sym.IsPreemptible) {
1029 Expr = fromPlt(Expr);
1030 }1180 }
10311181
1032 // This relocation does not require got entry, but it is relative to got and1182 // If the relocation does not emit a GOT or GOTPLT entry but its computation
1033 // needs it to be created. Here we request for that.1183 // uses their addresses, we need GOT or GOTPLT to be created.
1034 if (isRelExprOneOf<R_GOTONLY_PC, R_GOTONLY_PC_FROM_END, R_GOTREL,1184 //
1035 R_GOTREL_FROM_END, R_PPC_TOC>(Expr))1185 // The 4 types that relative GOTPLT are all x86 and x86-64 specific.
1036 In.Got->HasGotOffRel = true;1186 if (oneof<R_GOTPLTONLY_PC, R_GOTPLTREL, R_GOTPLT, R_TLSGD_GOTPLT>(expr)) {
10371187 in.gotPlt->hasGotPltOffRel = true;
1038 // Read an addend.1188 } else if (oneof<R_GOTONLY_PC, R_GOTREL, R_PPC64_TOCBASE, R_PPC64_RELAX_TOC>(
1039 int64_t Addend = computeAddend<ELFT>(Rel, End, Sec, Expr, Sym.isLocal());1189 expr)) {
1190 in.got->hasGotOffRel = true;
1191 }
10401192
1041 // Process some TLS relocations, including relaxing TLS relocations.1193 // Process some TLS relocations, including relaxing TLS relocations.
1042 // Note that this function does not handle all TLS relocations.1194 // Note that this function does not handle all TLS relocations.
1043 if (unsigned Processed =1195 if (unsigned processed =
1044 handleTlsRelocation<ELFT>(Type, Sym, Sec, Offset, Addend, Expr)) {1196 handleTlsRelocation<ELFT>(type, sym, sec, offset, addend, expr)) {
1045 I += (Processed - 1);1197 i += (processed - 1);
1046 return;1198 return;
1047 }1199 }
10481200
1049 // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol.1201 // We were asked not to generate PLT entries for ifuncs. Instead, pass the
1050 if (needsPlt(Expr) && !Sym.isInPlt()) {1202 // direct relocation on through.
1051 if (Sym.isGnuIFunc() && !Sym.IsPreemptible)1203 if (sym.isGnuIFunc() && config->zIfuncNoplt) {
1052 addPltEntry<ELFT>(In.Iplt, In.IgotPlt, In.RelaIplt, Target->IRelativeRel,1204 sym.exportDynamic = true;
1053 Sym);1205 mainPart->relaDyn->addReloc(type, &sec, offset, &sym, addend, R_ADDEND, type);
1054 else1206 return;
1055 addPltEntry<ELFT>(In.Plt, In.GotPlt, In.RelaPlt, Target->PltRel, Sym);
1056 }1207 }
10571208
1058 // Create a GOT slot if a relocation needs GOT.1209 // Non-preemptible ifuncs require special handling. First, handle the usual
1059 if (needsGot(Expr)) {1210 // case where the symbol isn't one of these.
1060 if (Config->EMachine == EM_MIPS) {1211 if (!sym.isGnuIFunc() || sym.isPreemptible) {
1061 // MIPS ABI has special rules to process GOT entries and doesn't1212 // If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol.
1062 // require relocation entries for them. A special case is TLS1213 if (needsPlt(expr) && !sym.isInPlt())
1063 // relocations. In that case dynamic loader applies dynamic1214 addPltEntry<ELFT>(in.plt, in.gotPlt, in.relaPlt, target->pltRel, sym);
1064 // relocations to initialize TLS GOT entries.1215
1065 // See "Global Offset Table" in Chapter 5 in the following document1216 // Create a GOT slot if a relocation needs GOT.
1066 // for detailed description:1217 if (needsGot(expr)) {
1067 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf1218 if (config->emachine == EM_MIPS) {
1068 In.MipsGot->addEntry(*Sec.File, Sym, Addend, Expr);1219 // MIPS ABI has special rules to process GOT entries and doesn't
1069 } else if (!Sym.isInGot()) {1220 // require relocation entries for them. A special case is TLS
1070 addGotEntry<ELFT>(Sym);1221 // relocations. In that case dynamic loader applies dynamic
1222 // relocations to initialize TLS GOT entries.
1223 // See "Global Offset Table" in Chapter 5 in the following document
1224 // for detailed description:
1225 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1226 in.mipsGot->addEntry(*sec.file, sym, addend, expr);
1227 } else if (!sym.isInGot()) {
1228 addGotEntry(sym);
1229 }
1230 }
1231 } else {
1232 // Handle a reference to a non-preemptible ifunc. These are special in a
1233 // few ways:
1234 //
1235 // - Unlike most non-preemptible symbols, non-preemptible ifuncs do not have
1236 // a fixed value. But assuming that all references to the ifunc are
1237 // GOT-generating or PLT-generating, the handling of an ifunc is
1238 // relatively straightforward. We create a PLT entry in Iplt, which is
1239 // usually at the end of .plt, which makes an indirect call using a
1240 // matching GOT entry in igotPlt, which is usually at the end of .got.plt.
1241 // The GOT entry is relocated using an IRELATIVE relocation in relaIplt,
1242 // which is usually at the end of .rela.plt. Unlike most relocations in
1243 // .rela.plt, which may be evaluated lazily without -z now, dynamic
1244 // loaders evaluate IRELATIVE relocs eagerly, which means that for
1245 // IRELATIVE relocs only, GOT-generating relocations can point directly to
1246 // .got.plt without requiring a separate GOT entry.
1247 //
1248 // - Despite the fact that an ifunc does not have a fixed value, compilers
1249 // that are not passed -fPIC will assume that they do, and will emit
1250 // direct (non-GOT-generating, non-PLT-generating) relocations to the
1251 // symbol. This means that if a direct relocation to the symbol is
1252 // seen, the linker must set a value for the symbol, and this value must
1253 // be consistent no matter what type of reference is made to the symbol.
1254 // This can be done by creating a PLT entry for the symbol in the way
1255 // described above and making it canonical, that is, making all references
1256 // point to the PLT entry instead of the resolver. In lld we also store
1257 // the address of the PLT entry in the dynamic symbol table, which means
1258 // that the symbol will also have the same value in other modules.
1259 // Because the value loaded from the GOT needs to be consistent with
1260 // the value computed using a direct relocation, a non-preemptible ifunc
1261 // may end up with two GOT entries, one in .got.plt that points to the
1262 // address returned by the resolver and is used only by the PLT entry,
1263 // and another in .got that points to the PLT entry and is used by
1264 // GOT-generating relocations.
1265 //
1266 // - The fact that these symbols do not have a fixed value makes them an
1267 // exception to the general rule that a statically linked executable does
1268 // not require any form of dynamic relocation. To handle these relocations
1269 // correctly, the IRELATIVE relocations are stored in an array which a
1270 // statically linked executable's startup code must enumerate using the
1271 // linker-defined symbols __rela?_iplt_{start,end}.
1272 //
1273 // - An absolute relocation to a non-preemptible ifunc (such as a global
1274 // variable containing a pointer to the ifunc) needs to be relocated in
1275 // the exact same way as a GOT entry, so we can avoid needing to make the
1276 // PLT entry canonical by translating such relocations into IRELATIVE
1277 // relocations in the relaIplt.
1278 if (!sym.isInPlt()) {
1279 // Create PLT and GOTPLT slots for the symbol.
1280 sym.isInIplt = true;
1281
1282 // Create a copy of the symbol to use as the target of the IRELATIVE
1283 // relocation in the igotPlt. This is in case we make the PLT canonical
1284 // later, which would overwrite the original symbol.
1285 //
1286 // FIXME: Creating a copy of the symbol here is a bit of a hack. All
1287 // that's really needed to create the IRELATIVE is the section and value,
1288 // so ideally we should just need to copy those.
1289 auto *directSym = make<Defined>(cast<Defined>(sym));
1290 addPltEntry<ELFT>(in.iplt, in.igotPlt, in.relaIplt, target->iRelativeRel,
1291 *directSym);
1292 sym.pltIndex = directSym->pltIndex;
1293 }
1294 if (expr == R_ABS && addend == 0 && (sec.flags & SHF_WRITE)) {
1295 // We might be able to represent this as an IRELATIVE. But we don't know
1296 // yet whether some later relocation will make the symbol point to a
1297 // canonical PLT, which would make this either a dynamic RELATIVE (PIC) or
1298 // static (non-PIC) relocation. So we keep a record of the information
1299 // required to process the relocation, and after scanRelocs() has been
1300 // called on all relocations, the relocation is resolved by
1301 // addIRelativeRelocs().
1302 iRelativeRelocs.push_back({type, &sec, offset, &sym});
1303 return;
1304 }
1305 if (needsGot(expr)) {
1306 // Redirect GOT accesses to point to the Igot.
1307 //
1308 // This field is also used to keep track of whether we ever needed a GOT
1309 // entry. If we did and we make the PLT canonical later, we'll need to
1310 // create a GOT entry pointing to the PLT entry for Sym.
1311 sym.gotInIgot = true;
1312 } else if (!needsPlt(expr)) {
1313 // Make the ifunc's PLT entry canonical by changing the value of its
1314 // symbol to redirect all references to point to it.
1315 unsigned entryOffset = sym.pltIndex * target->pltEntrySize;
1316 if (config->zRetpolineplt)
1317 entryOffset += target->pltHeaderSize;
1318
1319 auto &d = cast<Defined>(sym);
1320 d.section = in.iplt;
1321 d.value = entryOffset;
1322 d.size = 0;
1323 // It's important to set the symbol type here so that dynamic loaders
1324 // don't try to call the PLT as if it were an ifunc resolver.
1325 d.type = STT_FUNC;
1326
1327 if (sym.gotInIgot) {
1328 // We previously encountered a GOT generating reference that we
1329 // redirected to the Igot. Now that the PLT entry is canonical we must
1330 // clear the redirection to the Igot and add a GOT entry. As we've
1331 // changed the symbol type to STT_FUNC future GOT generating references
1332 // will naturally use this GOT entry.
1333 //
1334 // We don't need to worry about creating a MIPS GOT here because ifuncs
1335 // aren't a thing on MIPS.
1336 sym.gotInIgot = false;
1337 addGotEntry(sym);
1338 }
1071 }1339 }
1072 }1340 }
10731341
1074 processRelocAux<ELFT>(Sec, Expr, Type, Offset, Sym, Rel, Addend);1342 processRelocAux<ELFT>(sec, expr, type, offset, sym, rel, addend);
1075}1343}
10761344
1077template <class ELFT, class RelTy>1345template <class ELFT, class RelTy>
1078static void scanRelocs(InputSectionBase &Sec, ArrayRef<RelTy> Rels) {1346static void scanRelocs(InputSectionBase &sec, ArrayRef<RelTy> rels) {
1079 OffsetGetter GetOffset(Sec);1347 OffsetGetter getOffset(sec);
10801348
1081 // Not all relocations end up in Sec.Relocations, but a lot do.1349 // Not all relocations end up in Sec.Relocations, but a lot do.
1082 Sec.Relocations.reserve(Rels.size());1350 sec.relocations.reserve(rels.size());
10831351
1084 for (auto I = Rels.begin(), End = Rels.end(); I != End;)1352 for (auto i = rels.begin(), end = rels.end(); i != end;)
1085 scanReloc<ELFT>(Sec, GetOffset, I, End);1353 scanReloc<ELFT>(sec, getOffset, i, end);
10861354
1087 // Sort relocations by offset to binary search for R_RISCV_PCREL_HI201355 // Sort relocations by offset for more efficient searching for
1088 if (Config->EMachine == EM_RISCV)1356 // R_RISCV_PCREL_HI20 and R_PPC64_ADDR64.
1089 std::stable_sort(Sec.Relocations.begin(), Sec.Relocations.end(),1357 if (config->emachine == EM_RISCV ||
1090 RelocationOffsetComparator{});1358 (config->emachine == EM_PPC64 && sec.name == ".toc"))
1359 llvm::stable_sort(sec.relocations,
1360 [](const Relocation &lhs, const Relocation &rhs) {
1361 return lhs.offset < rhs.offset;
1362 });
1091}1363}
10921364
1093template <class ELFT> void elf::scanRelocations(InputSectionBase &S) {1365template <class ELFT> void elf::scanRelocations(InputSectionBase &s) {
1094 if (S.AreRelocsRela)1366 if (s.areRelocsRela)
1095 scanRelocs<ELFT>(S, S.relas<ELFT>());1367 scanRelocs<ELFT>(s, s.relas<ELFT>());
1096 else1368 else
1097 scanRelocs<ELFT>(S, S.rels<ELFT>());1369 scanRelocs<ELFT>(s, s.rels<ELFT>());
1370}
1371
1372// Figure out which representation to use for any absolute relocs to
1373// non-preemptible ifuncs that we visited during scanRelocs().
1374void elf::addIRelativeRelocs() {
1375 for (IRelativeReloc &r : iRelativeRelocs) {
1376 if (r.sym->type == STT_GNU_IFUNC)
1377 in.relaIplt->addReloc(
1378 {target->iRelativeRel, r.sec, r.offset, true, r.sym, 0});
1379 else if (config->isPic)
1380 addRelativeReloc(r.sec, r.offset, r.sym, 0, R_ABS, r.type);
1381 else
1382 r.sec->relocations.push_back({R_ABS, r.type, r.offset, 0, r.sym});
1383 }
1384 iRelativeRelocs.clear();
1098}1385}
10991386
1100static bool mergeCmp(const InputSection *A, const InputSection *B) {1387static bool mergeCmp(const InputSection *a, const InputSection *b) {
1101 // std::merge requires a strict weak ordering.1388 // std::merge requires a strict weak ordering.
1102 if (A->OutSecOff < B->OutSecOff)1389 if (a->outSecOff < b->outSecOff)
1103 return true;1390 return true;
11041391
1105 if (A->OutSecOff == B->OutSecOff) {1392 if (a->outSecOff == b->outSecOff) {
1106 auto *TA = dyn_cast<ThunkSection>(A);1393 auto *ta = dyn_cast<ThunkSection>(a);
1107 auto *TB = dyn_cast<ThunkSection>(B);1394 auto *tb = dyn_cast<ThunkSection>(b);
11081395
1109 // Check if Thunk is immediately before any specific Target1396 // Check if Thunk is immediately before any specific Target
1110 // InputSection for example Mips LA25 Thunks.1397 // InputSection for example Mips LA25 Thunks.
1111 if (TA && TA->getTargetInputSection() == B)1398 if (ta && ta->getTargetInputSection() == b)
1112 return true;1399 return true;
11131400
1114 // Place Thunk Sections without specific targets before1401 // Place Thunk Sections without specific targets before
1115 // non-Thunk Sections.1402 // non-Thunk Sections.
1116 if (TA && !TB && !TA->getTargetInputSection())1403 if (ta && !tb && !ta->getTargetInputSection())
1117 return true;1404 return true;
1118 }1405 }
11191406
...@@ -1123,14 +1410,14 @@ static bool mergeCmp(const InputSection *A, const InputSection *B) {...@@ -1123,14 +1410,14 @@ static bool mergeCmp(const InputSection *A, const InputSection *B) {
1123// Call Fn on every executable InputSection accessed via the linker script1410// Call Fn on every executable InputSection accessed via the linker script
1124// InputSectionDescription::Sections.1411// InputSectionDescription::Sections.
1125static void forEachInputSectionDescription(1412static void forEachInputSectionDescription(
1126 ArrayRef<OutputSection *> OutputSections,1413 ArrayRef<OutputSection *> outputSections,
1127 llvm::function_ref<void(OutputSection *, InputSectionDescription *)> Fn) {1414 llvm::function_ref<void(OutputSection *, InputSectionDescription *)> fn) {
1128 for (OutputSection *OS : OutputSections) {1415 for (OutputSection *os : outputSections) {
1129 if (!(OS->Flags & SHF_ALLOC) || !(OS->Flags & SHF_EXECINSTR))1416 if (!(os->flags & SHF_ALLOC) || !(os->flags & SHF_EXECINSTR))
1130 continue;1417 continue;
1131 for (BaseCommand *BC : OS->SectionCommands)1418 for (BaseCommand *bc : os->sectionCommands)
1132 if (auto *ISD = dyn_cast<InputSectionDescription>(BC))1419 if (auto *isd = dyn_cast<InputSectionDescription>(bc))
1133 Fn(OS, ISD);1420 fn(os, isd);
1134 }1421 }
1135}1422}
11361423
...@@ -1225,54 +1512,54 @@ static void forEachInputSectionDescription(...@@ -1225,54 +1512,54 @@ static void forEachInputSectionDescription(
1225// in the Sections vector, and recalculate the InputSection output section1512// in the Sections vector, and recalculate the InputSection output section
1226// offsets.1513// offsets.
1227// This may invalidate any output section offsets stored outside of InputSection1514// This may invalidate any output section offsets stored outside of InputSection
1228void ThunkCreator::mergeThunks(ArrayRef<OutputSection *> OutputSections) {1515void ThunkCreator::mergeThunks(ArrayRef<OutputSection *> outputSections) {
1229 forEachInputSectionDescription(1516 forEachInputSectionDescription(
1230 OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) {1517 outputSections, [&](OutputSection *os, InputSectionDescription *isd) {
1231 if (ISD->ThunkSections.empty())1518 if (isd->thunkSections.empty())
1232 return;1519 return;
12331520
1234 // Remove any zero sized precreated Thunks.1521 // Remove any zero sized precreated Thunks.
1235 llvm::erase_if(ISD->ThunkSections,1522 llvm::erase_if(isd->thunkSections,
1236 [](const std::pair<ThunkSection *, uint32_t> &TS) {1523 [](const std::pair<ThunkSection *, uint32_t> &ts) {
1237 return TS.first->getSize() == 0;1524 return ts.first->getSize() == 0;
1238 });1525 });
12391526
1240 // ISD->ThunkSections contains all created ThunkSections, including1527 // ISD->ThunkSections contains all created ThunkSections, including
1241 // those inserted in previous passes. Extract the Thunks created this1528 // those inserted in previous passes. Extract the Thunks created this
1242 // pass and order them in ascending OutSecOff.1529 // pass and order them in ascending outSecOff.
1243 std::vector<ThunkSection *> NewThunks;1530 std::vector<ThunkSection *> newThunks;
1244 for (const std::pair<ThunkSection *, uint32_t> TS : ISD->ThunkSections)1531 for (const std::pair<ThunkSection *, uint32_t> ts : isd->thunkSections)
1245 if (TS.second == Pass)1532 if (ts.second == pass)
1246 NewThunks.push_back(TS.first);1533 newThunks.push_back(ts.first);
1247 std::stable_sort(NewThunks.begin(), NewThunks.end(),1534 llvm::stable_sort(newThunks,
1248 [](const ThunkSection *A, const ThunkSection *B) {1535 [](const ThunkSection *a, const ThunkSection *b) {
1249 return A->OutSecOff < B->OutSecOff;1536 return a->outSecOff < b->outSecOff;
1250 });1537 });
12511538
1252 // Merge sorted vectors of Thunks and InputSections by OutSecOff1539 // Merge sorted vectors of Thunks and InputSections by outSecOff
1253 std::vector<InputSection *> Tmp;1540 std::vector<InputSection *> tmp;
1254 Tmp.reserve(ISD->Sections.size() + NewThunks.size());1541 tmp.reserve(isd->sections.size() + newThunks.size());
12551542
1256 std::merge(ISD->Sections.begin(), ISD->Sections.end(),1543 std::merge(isd->sections.begin(), isd->sections.end(),
1257 NewThunks.begin(), NewThunks.end(), std::back_inserter(Tmp),1544 newThunks.begin(), newThunks.end(), std::back_inserter(tmp),
1258 mergeCmp);1545 mergeCmp);
12591546
1260 ISD->Sections = std::move(Tmp);1547 isd->sections = std::move(tmp);
1261 });1548 });
1262}1549}
12631550
1264// Find or create a ThunkSection within the InputSectionDescription (ISD) that1551// Find or create a ThunkSection within the InputSectionDescription (ISD) that
1265// is in range of Src. An ISD maps to a range of InputSections described by a1552// is in range of Src. An ISD maps to a range of InputSections described by a
1266// linker script section pattern such as { .text .text.* }.1553// linker script section pattern such as { .text .text.* }.
1267ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *OS, InputSection *IS,1554ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *os, InputSection *isec,
1268 InputSectionDescription *ISD,1555 InputSectionDescription *isd,
1269 uint32_t Type, uint64_t Src) {1556 uint32_t type, uint64_t src) {
1270 for (std::pair<ThunkSection *, uint32_t> TP : ISD->ThunkSections) {1557 for (std::pair<ThunkSection *, uint32_t> tp : isd->thunkSections) {
1271 ThunkSection *TS = TP.first;1558 ThunkSection *ts = tp.first;
1272 uint64_t TSBase = OS->Addr + TS->OutSecOff;1559 uint64_t tsBase = os->addr + ts->outSecOff;
1273 uint64_t TSLimit = TSBase + TS->getSize();1560 uint64_t tsLimit = tsBase + ts->getSize();
1274 if (Target->inBranchRange(Type, Src, (Src > TSLimit) ? TSBase : TSLimit))1561 if (target->inBranchRange(type, src, (src > tsLimit) ? tsBase : tsLimit))
1275 return TS;1562 return ts;
1276 }1563 }
12771564
1278 // No suitable ThunkSection exists. This can happen when there is a branch1565 // No suitable ThunkSection exists. This can happen when there is a branch
...@@ -1280,40 +1567,40 @@ ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *OS, InputSection *IS,...@@ -1280,40 +1567,40 @@ ThunkSection *ThunkCreator::getISDThunkSec(OutputSection *OS, InputSection *IS,
1280 // many Thunks. Create a new ThunkSection as close to the InputSection as1567 // many Thunks. Create a new ThunkSection as close to the InputSection as
1281 // possible. Error if InputSection is so large we cannot place ThunkSection1568 // possible. Error if InputSection is so large we cannot place ThunkSection
1282 // anywhere in Range.1569 // anywhere in Range.
1283 uint64_t ThunkSecOff = IS->OutSecOff;1570 uint64_t thunkSecOff = isec->outSecOff;
1284 if (!Target->inBranchRange(Type, Src, OS->Addr + ThunkSecOff)) {1571 if (!target->inBranchRange(type, src, os->addr + thunkSecOff)) {
1285 ThunkSecOff = IS->OutSecOff + IS->getSize();1572 thunkSecOff = isec->outSecOff + isec->getSize();
1286 if (!Target->inBranchRange(Type, Src, OS->Addr + ThunkSecOff))1573 if (!target->inBranchRange(type, src, os->addr + thunkSecOff))
1287 fatal("InputSection too large for range extension thunk " +1574 fatal("InputSection too large for range extension thunk " +
1288 IS->getObjMsg(Src - (OS->Addr + IS->OutSecOff)));1575 isec->getObjMsg(src - (os->addr + isec->outSecOff)));
1289 }1576 }
1290 return addThunkSection(OS, ISD, ThunkSecOff);1577 return addThunkSection(os, isd, thunkSecOff);
1291}1578}
12921579
1293// Add a Thunk that needs to be placed in a ThunkSection that immediately1580// Add a Thunk that needs to be placed in a ThunkSection that immediately
1294// precedes its Target.1581// precedes its Target.
1295ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) {1582ThunkSection *ThunkCreator::getISThunkSec(InputSection *isec) {
1296 ThunkSection *TS = ThunkedSections.lookup(IS);1583 ThunkSection *ts = thunkedSections.lookup(isec);
1297 if (TS)1584 if (ts)
1298 return TS;1585 return ts;
12991586
1300 // Find InputSectionRange within Target Output Section (TOS) that the1587 // Find InputSectionRange within Target Output Section (TOS) that the
1301 // InputSection (IS) that we need to precede is in.1588 // InputSection (IS) that we need to precede is in.
1302 OutputSection *TOS = IS->getParent();1589 OutputSection *tos = isec->getParent();
1303 for (BaseCommand *BC : TOS->SectionCommands) {1590 for (BaseCommand *bc : tos->sectionCommands) {
1304 auto *ISD = dyn_cast<InputSectionDescription>(BC);1591 auto *isd = dyn_cast<InputSectionDescription>(bc);
1305 if (!ISD || ISD->Sections.empty())1592 if (!isd || isd->sections.empty())
1306 continue;1593 continue;
13071594
1308 InputSection *First = ISD->Sections.front();1595 InputSection *first = isd->sections.front();
1309 InputSection *Last = ISD->Sections.back();1596 InputSection *last = isd->sections.back();
13101597
1311 if (IS->OutSecOff < First->OutSecOff || Last->OutSecOff < IS->OutSecOff)1598 if (isec->outSecOff < first->outSecOff || last->outSecOff < isec->outSecOff)
1312 continue;1599 continue;
13131600
1314 TS = addThunkSection(TOS, ISD, IS->OutSecOff);1601 ts = addThunkSection(tos, isd, isec->outSecOff);
1315 ThunkedSections[IS] = TS;1602 thunkedSections[isec] = ts;
1316 return TS;1603 return ts;
1317 }1604 }
13181605
1319 return nullptr;1606 return nullptr;
...@@ -1336,82 +1623,93 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) {...@@ -1336,82 +1623,93 @@ ThunkSection *ThunkCreator::getISThunkSec(InputSection *IS) {
1336// distance from a thunk to its target will be sufficiently small to1623// distance from a thunk to its target will be sufficiently small to
1337// allow for the creation of a short thunk.1624// allow for the creation of a short thunk.
1338void ThunkCreator::createInitialThunkSections(1625void ThunkCreator::createInitialThunkSections(
1339 ArrayRef<OutputSection *> OutputSections) {1626 ArrayRef<OutputSection *> outputSections) {
1340 uint32_t ThunkSectionSpacing = Target->getThunkSectionSpacing();1627 uint32_t thunkSectionSpacing = target->getThunkSectionSpacing();
13411628
1342 forEachInputSectionDescription(1629 forEachInputSectionDescription(
1343 OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) {1630 outputSections, [&](OutputSection *os, InputSectionDescription *isd) {
1344 if (ISD->Sections.empty())1631 if (isd->sections.empty())
1345 return;1632 return;
13461633
1347 uint32_t ISDBegin = ISD->Sections.front()->OutSecOff;1634 uint32_t isdBegin = isd->sections.front()->outSecOff;
1348 uint32_t ISDEnd =1635 uint32_t isdEnd =
1349 ISD->Sections.back()->OutSecOff + ISD->Sections.back()->getSize();1636 isd->sections.back()->outSecOff + isd->sections.back()->getSize();
1350 uint32_t LastThunkLowerBound = -1;1637 uint32_t lastThunkLowerBound = -1;
1351 if (ISDEnd - ISDBegin > ThunkSectionSpacing * 2)1638 if (isdEnd - isdBegin > thunkSectionSpacing * 2)
1352 LastThunkLowerBound = ISDEnd - ThunkSectionSpacing;1639 lastThunkLowerBound = isdEnd - thunkSectionSpacing;
13531640
1354 uint32_t ISLimit;1641 uint32_t isecLimit;
1355 uint32_t PrevISLimit = ISDBegin;1642 uint32_t prevIsecLimit = isdBegin;
1356 uint32_t ThunkUpperBound = ISDBegin + ThunkSectionSpacing;1643 uint32_t thunkUpperBound = isdBegin + thunkSectionSpacing;
13571644
1358 for (const InputSection *IS : ISD->Sections) {1645 for (const InputSection *isec : isd->sections) {
1359 ISLimit = IS->OutSecOff + IS->getSize();1646 isecLimit = isec->outSecOff + isec->getSize();
1360 if (ISLimit > ThunkUpperBound) {1647 if (isecLimit > thunkUpperBound) {
1361 addThunkSection(OS, ISD, PrevISLimit);1648 addThunkSection(os, isd, prevIsecLimit);
1362 ThunkUpperBound = PrevISLimit + ThunkSectionSpacing;1649 thunkUpperBound = prevIsecLimit + thunkSectionSpacing;
1363 }1650 }
1364 if (ISLimit > LastThunkLowerBound)1651 if (isecLimit > lastThunkLowerBound)
1365 break;1652 break;
1366 PrevISLimit = ISLimit;1653 prevIsecLimit = isecLimit;
1367 }1654 }
1368 addThunkSection(OS, ISD, ISLimit);1655 addThunkSection(os, isd, isecLimit);
1369 });1656 });
1370}1657}
13711658
1372ThunkSection *ThunkCreator::addThunkSection(OutputSection *OS,1659ThunkSection *ThunkCreator::addThunkSection(OutputSection *os,
1373 InputSectionDescription *ISD,1660 InputSectionDescription *isd,
1374 uint64_t Off) {1661 uint64_t off) {
1375 auto *TS = make<ThunkSection>(OS, Off);1662 auto *ts = make<ThunkSection>(os, off);
1376 ISD->ThunkSections.push_back({TS, Pass});1663 ts->partition = os->partition;
1377 return TS;1664 isd->thunkSections.push_back({ts, pass});
1665 return ts;
1378}1666}
13791667
1380std::pair<Thunk *, bool> ThunkCreator::getThunk(Symbol &Sym, RelType Type,1668static bool isThunkSectionCompatible(InputSection *source,
1381 uint64_t Src) {1669 SectionBase *target) {
1382 std::vector<Thunk *> *ThunkVec = nullptr;1670 // We can't reuse thunks in different loadable partitions because they might
1671 // not be loaded. But partition 1 (the main partition) will always be loaded.
1672 if (source->partition != target->partition)
1673 return target->partition == 1;
1674 return true;
1675}
1676
1677std::pair<Thunk *, bool> ThunkCreator::getThunk(InputSection *isec,
1678 Relocation &rel, uint64_t src) {
1679 std::vector<Thunk *> *thunkVec = nullptr;
13831680
1384 // We use (section, offset) pair to find the thunk position if possible so1681 // We use (section, offset) pair to find the thunk position if possible so
1385 // that we create only one thunk for aliased symbols or ICFed sections.1682 // that we create only one thunk for aliased symbols or ICFed sections.
1386 if (auto *D = dyn_cast<Defined>(&Sym))1683 if (auto *d = dyn_cast<Defined>(rel.sym))
1387 if (!D->isInPlt() && D->Section)1684 if (!d->isInPlt() && d->section)
1388 ThunkVec = &ThunkedSymbolsBySection[{D->Section->Repl, D->Value}];1685 thunkVec = &thunkedSymbolsBySection[{d->section->repl, d->value}];
1389 if (!ThunkVec)1686 if (!thunkVec)
1390 ThunkVec = &ThunkedSymbols[&Sym];1687 thunkVec = &thunkedSymbols[rel.sym];
13911688
1392 // Check existing Thunks for Sym to see if they can be reused1689 // Check existing Thunks for Sym to see if they can be reused
1393 for (Thunk *T : *ThunkVec)1690 for (Thunk *t : *thunkVec)
1394 if (T->isCompatibleWith(Type) &&1691 if (isThunkSectionCompatible(isec, t->getThunkTargetSym()->section) &&
1395 Target->inBranchRange(Type, Src, T->getThunkTargetSym()->getVA()))1692 t->isCompatibleWith(*isec, rel) &&
1396 return std::make_pair(T, false);1693 target->inBranchRange(rel.type, src, t->getThunkTargetSym()->getVA()))
1694 return std::make_pair(t, false);
13971695
1398 // No existing compatible Thunk in range, create a new one1696 // No existing compatible Thunk in range, create a new one
1399 Thunk *T = addThunk(Type, Sym);1697 Thunk *t = addThunk(*isec, rel);
1400 ThunkVec->push_back(T);1698 thunkVec->push_back(t);
1401 return std::make_pair(T, true);1699 return std::make_pair(t, true);
1402}1700}
14031701
1404// Return true if the relocation target is an in range Thunk.1702// Return true if the relocation target is an in range Thunk.
1405// Return false if the relocation is not to a Thunk. If the relocation target1703// Return false if the relocation is not to a Thunk. If the relocation target
1406// was originally to a Thunk, but is no longer in range we revert the1704// was originally to a Thunk, but is no longer in range we revert the
1407// relocation back to its original non-Thunk target.1705// relocation back to its original non-Thunk target.
1408bool ThunkCreator::normalizeExistingThunk(Relocation &Rel, uint64_t Src) {1706bool ThunkCreator::normalizeExistingThunk(Relocation &rel, uint64_t src) {
1409 if (Thunk *T = Thunks.lookup(Rel.Sym)) {1707 if (Thunk *t = thunks.lookup(rel.sym)) {
1410 if (Target->inBranchRange(Rel.Type, Src, Rel.Sym->getVA()))1708 if (target->inBranchRange(rel.type, src, rel.sym->getVA()))
1411 return true;1709 return true;
1412 Rel.Sym = &T->Destination;1710 rel.sym = &t->destination;
1413 if (Rel.Sym->isInPlt())1711 if (rel.sym->isInPlt())
1414 Rel.Expr = toPlt(Rel.Expr);1712 rel.expr = toPlt(rel.expr);
1415 }1713 }
1416 return false;1714 return false;
1417}1715}
...@@ -1441,15 +1739,15 @@ bool ThunkCreator::normalizeExistingThunk(Relocation &Rel, uint64_t Src) {...@@ -1441,15 +1739,15 @@ bool ThunkCreator::normalizeExistingThunk(Relocation &Rel, uint64_t Src) {
1441// made no changes. If the target requires range extension thunks, currently1739// made no changes. If the target requires range extension thunks, currently
1442// ARM, then any future change in offset between caller and callee risks a1740// ARM, then any future change in offset between caller and callee risks a
1443// relocation out of range error.1741// relocation out of range error.
1444bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {1742bool ThunkCreator::createThunks(ArrayRef<OutputSection *> outputSections) {
1445 bool AddressesChanged = false;1743 bool addressesChanged = false;
14461744
1447 if (Pass == 0 && Target->getThunkSectionSpacing())1745 if (pass == 0 && target->getThunkSectionSpacing())
1448 createInitialThunkSections(OutputSections);1746 createInitialThunkSections(outputSections);
14491747
1450 // With Thunk Size much smaller than branch range we expect to1748 // With Thunk Size much smaller than branch range we expect to
1451 // converge quickly; if we get to 10 something has gone wrong.1749 // converge quickly; if we get to 10 something has gone wrong.
1452 if (Pass == 10)1750 if (pass == 10)
1453 fatal("thunk creation not converged");1751 fatal("thunk creation not converged");
14541752
1455 // Create all the Thunks and insert them into synthetic ThunkSections. The1753 // Create all the Thunks and insert them into synthetic ThunkSections. The
...@@ -1458,55 +1756,64 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {...@@ -1458,55 +1756,64 @@ bool ThunkCreator::createThunks(ArrayRef<OutputSection *> OutputSections) {
1458 // ThunkSections as ThunkSections are not always inserted into the same1756 // ThunkSections as ThunkSections are not always inserted into the same
1459 // InputSectionDescription as the caller.1757 // InputSectionDescription as the caller.
1460 forEachInputSectionDescription(1758 forEachInputSectionDescription(
1461 OutputSections, [&](OutputSection *OS, InputSectionDescription *ISD) {1759 outputSections, [&](OutputSection *os, InputSectionDescription *isd) {
1462 for (InputSection *IS : ISD->Sections)1760 for (InputSection *isec : isd->sections)
1463 for (Relocation &Rel : IS->Relocations) {1761 for (Relocation &rel : isec->relocations) {
1464 uint64_t Src = IS->getVA(Rel.Offset);1762 uint64_t src = isec->getVA(rel.offset);
14651763
1466 // If we are a relocation to an existing Thunk, check if it is1764 // If we are a relocation to an existing Thunk, check if it is
1467 // still in range. If not then Rel will be altered to point to its1765 // still in range. If not then Rel will be altered to point to its
1468 // original target so another Thunk can be generated.1766 // original target so another Thunk can be generated.
1469 if (Pass > 0 && normalizeExistingThunk(Rel, Src))1767 if (pass > 0 && normalizeExistingThunk(rel, src))
1470 continue;1768 continue;
14711769
1472 if (!Target->needsThunk(Rel.Expr, Rel.Type, IS->File, Src,1770 if (!target->needsThunk(rel.expr, rel.type, isec->file, src,
1473 *Rel.Sym))1771 *rel.sym))
1474 continue;1772 continue;
14751773
1476 Thunk *T;1774 Thunk *t;
1477 bool IsNew;1775 bool isNew;
1478 std::tie(T, IsNew) = getThunk(*Rel.Sym, Rel.Type, Src);1776 std::tie(t, isNew) = getThunk(isec, rel, src);
14791777
1480 if (IsNew) {1778 if (isNew) {
1481 // Find or create a ThunkSection for the new Thunk1779 // Find or create a ThunkSection for the new Thunk
1482 ThunkSection *TS;1780 ThunkSection *ts;
1483 if (auto *TIS = T->getTargetInputSection())1781 if (auto *tis = t->getTargetInputSection())
1484 TS = getISThunkSec(TIS);1782 ts = getISThunkSec(tis);
1485 else1783 else
1486 TS = getISDThunkSec(OS, IS, ISD, Rel.Type, Src);1784 ts = getISDThunkSec(os, isec, isd, rel.type, src);
1487 TS->addThunk(T);1785 ts->addThunk(t);
1488 Thunks[T->getThunkTargetSym()] = T;1786 thunks[t->getThunkTargetSym()] = t;
1489 }1787 }
14901788
1491 // Redirect relocation to Thunk, we never go via the PLT to a Thunk1789 // Redirect relocation to Thunk, we never go via the PLT to a Thunk
1492 Rel.Sym = T->getThunkTargetSym();1790 rel.sym = t->getThunkTargetSym();
1493 Rel.Expr = fromPlt(Rel.Expr);1791 rel.expr = fromPlt(rel.expr);
1792
1793 // The addend of R_PPC_PLTREL24 should be ignored after changing to
1794 // R_PC.
1795 if (config->emachine == EM_PPC && rel.type == R_PPC_PLTREL24)
1796 rel.addend = 0;
1494 }1797 }
14951798
1496 for (auto &P : ISD->ThunkSections)1799 for (auto &p : isd->thunkSections)
1497 AddressesChanged |= P.first->assignOffsets();1800 addressesChanged |= p.first->assignOffsets();
1498 });1801 });
14991802
1500 for (auto &P : ThunkedSections)1803 for (auto &p : thunkedSections)
1501 AddressesChanged |= P.second->assignOffsets();1804 addressesChanged |= p.second->assignOffsets();
15021805
1503 // Merge all created synthetic ThunkSections back into OutputSection1806 // Merge all created synthetic ThunkSections back into OutputSection
1504 mergeThunks(OutputSections);1807 mergeThunks(outputSections);
1505 ++Pass;1808 ++pass;
1506 return AddressesChanged;1809 return addressesChanged;
1507}1810}
15081811
1509template void elf::scanRelocations<ELF32LE>(InputSectionBase &);1812template void elf::scanRelocations<ELF32LE>(InputSectionBase &);
1510template void elf::scanRelocations<ELF32BE>(InputSectionBase &);1813template void elf::scanRelocations<ELF32BE>(InputSectionBase &);
1511template void elf::scanRelocations<ELF64LE>(InputSectionBase &);1814template void elf::scanRelocations<ELF64LE>(InputSectionBase &);
1512template void elf::scanRelocations<ELF64BE>(InputSectionBase &);1815template void elf::scanRelocations<ELF64BE>(InputSectionBase &);
1816template void elf::reportUndefinedSymbols<ELF32LE>();
1817template void elf::reportUndefinedSymbols<ELF32BE>();
1818template void elf::reportUndefinedSymbols<ELF64LE>();
1819template void elf::reportUndefinedSymbols<ELF64BE>();
deps/lld/ELF/Relocations.h+71-107
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Relocations.h -------------------------------------------*- C++ -*-===//1//===- Relocations.h -------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -24,136 +23,100 @@ class OutputSection;...@@ -24,136 +23,100 @@ class OutputSection;
24class SectionBase;23class SectionBase;
2524
26// Represents a relocation type, such as R_X86_64_PC32 or R_ARM_THM_CALL.25// Represents a relocation type, such as R_X86_64_PC32 or R_ARM_THM_CALL.
27typedef uint32_t RelType;26using RelType = uint32_t;
2827
29// List of target-independent relocation types. Relocations read28// List of target-independent relocation types. Relocations read
30// from files are converted to these types so that the main code29// from files are converted to these types so that the main code
31// doesn't have to know about architecture-specific details.30// doesn't have to know about architecture-specific details.
32enum RelExpr {31enum RelExpr {
33 R_INVALID,
34 R_ABS,32 R_ABS,
35 R_ADDEND,33 R_ADDEND,
36 R_AARCH64_GOT_PAGE_PC,34 R_DTPREL,
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,
45 R_ARM_SBREL,
46 R_GOT,35 R_GOT,
47 // The expression is used for IFUNC support. Evaluates to GOT entry,
48 // containing redirection to the IPLT.
49 R_GOT_PLT,
50 R_GOTONLY_PC,
51 R_GOTONLY_PC_FROM_END,
52 R_GOTREL,
53 R_GOTREL_FROM_END,
54 R_GOT_FROM_END,
55 R_GOT_OFF,36 R_GOT_OFF,
56 R_GOT_PC,37 R_GOT_PC,
57 R_HEXAGON_GOT,38 R_GOTONLY_PC,
39 R_GOTPLTONLY_PC,
40 R_GOTPLT,
41 R_GOTPLTREL,
42 R_GOTREL,
58 R_HINT,43 R_HINT,
59 R_MIPS_GOTREL,
60 R_MIPS_GOT_GP,
61 R_MIPS_GOT_GP_PC,
62 R_MIPS_GOT_LOCAL_PAGE,
63 R_MIPS_GOT_OFF,
64 R_MIPS_GOT_OFF32,
65 R_MIPS_TLSGD,
66 R_MIPS_TLSLD,
67 R_NEG_TLS,44 R_NEG_TLS,
68 R_NONE,45 R_NONE,
69 R_PC,46 R_PC,
70 R_PLT,47 R_PLT,
71 R_PLT_PC,48 R_PLT_PC,
72 R_PPC_CALL,
73 R_PPC_CALL_PLT,
74 R_PPC_TOC,
75 R_RELAX_GOT_PC,49 R_RELAX_GOT_PC,
76 R_RELAX_GOT_PC_NOPIC,50 R_RELAX_GOT_PC_NOPIC,
77 R_RELAX_TLS_GD_TO_IE,51 R_RELAX_TLS_GD_TO_IE,
78 R_RELAX_TLS_GD_TO_IE_ABS,52 R_RELAX_TLS_GD_TO_IE_ABS,
79 R_RELAX_TLS_GD_TO_IE_END,
80 R_RELAX_TLS_GD_TO_IE_GOT_OFF,53 R_RELAX_TLS_GD_TO_IE_GOT_OFF,
54 R_RELAX_TLS_GD_TO_IE_GOTPLT,
81 R_RELAX_TLS_GD_TO_LE,55 R_RELAX_TLS_GD_TO_LE,
82 R_RELAX_TLS_GD_TO_LE_NEG,56 R_RELAX_TLS_GD_TO_LE_NEG,
83 R_RELAX_TLS_IE_TO_LE,57 R_RELAX_TLS_IE_TO_LE,
84 R_RELAX_TLS_LD_TO_LE,58 R_RELAX_TLS_LD_TO_LE,
85 R_RELAX_TLS_LD_TO_LE_ABS,59 R_RELAX_TLS_LD_TO_LE_ABS,
86 R_RISCV_PC_INDIRECT,
87 R_SIZE,60 R_SIZE,
88 R_TLS,61 R_TLS,
89 R_TLSDESC,62 R_TLSDESC,
90 R_TLSDESC_CALL,63 R_TLSDESC_CALL,
64 R_TLSDESC_PC,
91 R_TLSGD_GOT,65 R_TLSGD_GOT,
92 R_TLSGD_GOT_FROM_END,66 R_TLSGD_GOTPLT,
93 R_TLSGD_PC,67 R_TLSGD_PC,
94 R_TLSIE_HINT,68 R_TLSIE_HINT,
95 R_TLSLD_GOT,69 R_TLSLD_GOT,
96 R_TLSLD_GOT_FROM_END,70 R_TLSLD_GOTPLT,
97 R_TLSLD_GOT_OFF,71 R_TLSLD_GOT_OFF,
98 R_TLSLD_HINT,72 R_TLSLD_HINT,
99 R_TLSLD_PC,73 R_TLSLD_PC,
100};
10174
102// Build a bitmask with one bit set for each RelExpr.75 // The following is abstract relocation types used for only one target.
103//76 //
104// Constexpr function arguments can't be used in static asserts, so we77 // Even though RelExpr is intended to be a target-neutral representation
105// use template arguments to build the mask.78 // of a relocation type, there are some relocations whose semantics are
106// But function template partial specializations don't exist (needed79 // unique to a target. Such relocation are marked with R_<TARGET_NAME>.
107// for base case of the recursion), so we need a dummy struct.80 R_AARCH64_GOT_PAGE_PC,
108template <RelExpr... Exprs> struct RelExprMaskBuilder {81 R_AARCH64_PAGE_PC,
109 static inline uint64_t build() { return 0; }82 R_AARCH64_RELAX_TLS_GD_TO_IE_PAGE_PC,
110};83 R_AARCH64_TLSDESC_PAGE,
11184 R_ARM_SBREL,
112// Specialization for recursive case.85 R_HEXAGON_GOT,
113template <RelExpr Head, RelExpr... Tail>86 R_MIPS_GOTREL,
114struct RelExprMaskBuilder<Head, Tail...> {87 R_MIPS_GOT_GP,
115 static inline uint64_t build() {88 R_MIPS_GOT_GP_PC,
116 static_assert(0 <= Head && Head < 64,89 R_MIPS_GOT_LOCAL_PAGE,
117 "RelExpr is too large for 64-bit mask!");90 R_MIPS_GOT_OFF,
118 return (uint64_t(1) << Head) | RelExprMaskBuilder<Tail...>::build();91 R_MIPS_GOT_OFF32,
119 }92 R_MIPS_TLSGD,
93 R_MIPS_TLSLD,
94 R_PPC32_PLTREL,
95 R_PPC64_CALL,
96 R_PPC64_CALL_PLT,
97 R_PPC64_RELAX_TOC,
98 R_PPC64_TOCBASE,
99 R_RISCV_ADD,
100 R_RISCV_PC_INDIRECT,
120};101};
121102
122// Return true if `Expr` is one of `Exprs`.
123// There are fewer than 64 RelExpr's, so we can represent any set of
124// RelExpr's as a constant bit mask and test for membership with a
125// couple cheap bitwise operations.
126template <RelExpr... Exprs> bool isRelExprOneOf(RelExpr Expr) {
127 assert(0 <= Expr && (int)Expr < 64 &&
128 "RelExpr is too large for 64-bit mask!");
129 return (uint64_t(1) << Expr) & RelExprMaskBuilder<Exprs...>::build();
130}
131
132// Architecture-neutral representation of relocation.103// Architecture-neutral representation of relocation.
133struct Relocation {104struct Relocation {
134 RelExpr Expr;105 RelExpr expr;
135 RelType Type;106 RelType type;
136 uint64_t Offset;107 uint64_t offset;
137 int64_t Addend;108 int64_t addend;
138 Symbol *Sym;109 Symbol *sym;
139};110};
140111
141struct RelocationOffsetComparator {112// This function writes undefined symbol diagnostics to an internal buffer.
142 bool operator()(const Relocation &Lhs, const Relocation &Rhs) {113// Call reportUndefinedSymbols() after calling scanRelocations() to emit
143 return Lhs.Offset < Rhs.Offset;114// the diagnostics.
144 }115template <class ELFT> void scanRelocations(InputSectionBase &);
145116
146 // For std::lower_bound, std::upper_bound, std::equal_range.117template <class ELFT> void reportUndefinedSymbols();
147 bool operator()(const Relocation &Rel, uint64_t Val) {
148 return Rel.Offset < Val;
149 }
150118
151 bool operator()(uint64_t Val, const Relocation &Rel) {119void addIRelativeRelocs();
152 return Val < Rel.Offset;
153 }
154};
155
156template <class ELFT> void scanRelocations(InputSectionBase &);
157120
158class ThunkSection;121class ThunkSection;
159class Thunk;122class Thunk;
...@@ -162,56 +125,57 @@ struct InputSectionDescription;...@@ -162,56 +125,57 @@ struct InputSectionDescription;
162class ThunkCreator {125class ThunkCreator {
163public:126public:
164 // Return true if Thunks have been added to OutputSections127 // Return true if Thunks have been added to OutputSections
165 bool createThunks(ArrayRef<OutputSection *> OutputSections);128 bool createThunks(ArrayRef<OutputSection *> outputSections);
166129
167 // The number of completed passes of createThunks this permits us130 // The number of completed passes of createThunks this permits us
168 // to do one time initialization on Pass 0 and put a limit on the131 // to do one time initialization on Pass 0 and put a limit on the
169 // number of times it can be called to prevent infinite loops.132 // number of times it can be called to prevent infinite loops.
170 uint32_t Pass = 0;133 uint32_t pass = 0;
171134
172private:135private:
173 void mergeThunks(ArrayRef<OutputSection *> OutputSections);136 void mergeThunks(ArrayRef<OutputSection *> outputSections);
174137
175 ThunkSection *getISDThunkSec(OutputSection *OS, InputSection *IS,138 ThunkSection *getISDThunkSec(OutputSection *os, InputSection *isec,
176 InputSectionDescription *ISD, uint32_t Type,139 InputSectionDescription *isd, uint32_t type,
177 uint64_t Src);140 uint64_t src);
178141
179 ThunkSection *getISThunkSec(InputSection *IS);142 ThunkSection *getISThunkSec(InputSection *isec);
180143
181 void createInitialThunkSections(ArrayRef<OutputSection *> OutputSections);144 void createInitialThunkSections(ArrayRef<OutputSection *> outputSections);
182145
183 std::pair<Thunk *, bool> getThunk(Symbol &Sym, RelType Type, uint64_t Src);146 std::pair<Thunk *, bool> getThunk(InputSection *isec, Relocation &rel,
147 uint64_t src);
184148
185 ThunkSection *addThunkSection(OutputSection *OS, InputSectionDescription *,149 ThunkSection *addThunkSection(OutputSection *os, InputSectionDescription *,
186 uint64_t Off);150 uint64_t off);
187151
188 bool normalizeExistingThunk(Relocation &Rel, uint64_t Src);152 bool normalizeExistingThunk(Relocation &rel, uint64_t src);
189153
190 // Record all the available Thunks for a Symbol154 // Record all the available Thunks for a Symbol
191 llvm::DenseMap<std::pair<SectionBase *, uint64_t>, std::vector<Thunk *>>155 llvm::DenseMap<std::pair<SectionBase *, uint64_t>, std::vector<Thunk *>>
192 ThunkedSymbolsBySection;156 thunkedSymbolsBySection;
193 llvm::DenseMap<Symbol *, std::vector<Thunk *>> ThunkedSymbols;157 llvm::DenseMap<Symbol *, std::vector<Thunk *>> thunkedSymbols;
194158
195 // Find a Thunk from the Thunks symbol definition, we can use this to find159 // Find a Thunk from the Thunks symbol definition, we can use this to find
196 // the Thunk from a relocation to the Thunks symbol definition.160 // the Thunk from a relocation to the Thunks symbol definition.
197 llvm::DenseMap<Symbol *, Thunk *> Thunks;161 llvm::DenseMap<Symbol *, Thunk *> thunks;
198162
199 // Track InputSections that have an inline ThunkSection placed in front163 // Track InputSections that have an inline ThunkSection placed in front
200 // an inline ThunkSection may have control fall through to the section below164 // an inline ThunkSection may have control fall through to the section below
201 // so we need to make sure that there is only one of them.165 // so we need to make sure that there is only one of them.
202 // The Mips LA25 Thunk is an example of an inline ThunkSection.166 // The Mips LA25 Thunk is an example of an inline ThunkSection.
203 llvm::DenseMap<InputSection *, ThunkSection *> ThunkedSections;167 llvm::DenseMap<InputSection *, ThunkSection *> thunkedSections;
204};168};
205169
206// Return a int64_t to make sure we get the sign extension out of the way as170// Return a int64_t to make sure we get the sign extension out of the way as
207// early as possible.171// early as possible.
208template <class ELFT>172template <class ELFT>
209static inline int64_t getAddend(const typename ELFT::Rel &Rel) {173static inline int64_t getAddend(const typename ELFT::Rel &rel) {
210 return 0;174 return 0;
211}175}
212template <class ELFT>176template <class ELFT>
213static inline int64_t getAddend(const typename ELFT::Rela &Rel) {177static inline int64_t getAddend(const typename ELFT::Rela &rel) {
214 return Rel.r_addend;178 return rel.r_addend;
215}179}
216} // namespace elf180} // namespace elf
217} // namespace lld181} // namespace lld
deps/lld/ELF/ScriptLexer.cpp+113-111
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ScriptLexer.cpp ----------------------------------------------------===//1//===- ScriptLexer.cpp ----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -42,166 +41,169 @@ using namespace lld::elf;...@@ -42,166 +41,169 @@ using namespace lld::elf;
4241
43// Returns a whole line containing the current token.42// Returns a whole line containing the current token.
44StringRef ScriptLexer::getLine() {43StringRef ScriptLexer::getLine() {
45 StringRef S = getCurrentMB().getBuffer();44 StringRef s = getCurrentMB().getBuffer();
46 StringRef Tok = Tokens[Pos - 1];45 StringRef tok = tokens[pos - 1];
4746
48 size_t Pos = S.rfind('\n', Tok.data() - S.data());47 size_t pos = s.rfind('\n', tok.data() - s.data());
49 if (Pos != StringRef::npos)48 if (pos != StringRef::npos)
50 S = S.substr(Pos + 1);49 s = s.substr(pos + 1);
51 return S.substr(0, S.find_first_of("\r\n"));50 return s.substr(0, s.find_first_of("\r\n"));
52}51}
5352
54// Returns 1-based line number of the current token.53// Returns 1-based line number of the current token.
55size_t ScriptLexer::getLineNumber() {54size_t ScriptLexer::getLineNumber() {
56 StringRef S = getCurrentMB().getBuffer();55 StringRef s = getCurrentMB().getBuffer();
57 StringRef Tok = Tokens[Pos - 1];56 StringRef tok = tokens[pos - 1];
58 return S.substr(0, Tok.data() - S.data()).count('\n') + 1;57 return s.substr(0, tok.data() - s.data()).count('\n') + 1;
59}58}
6059
61// Returns 0-based column number of the current token.60// Returns 0-based column number of the current token.
62size_t ScriptLexer::getColumnNumber() {61size_t ScriptLexer::getColumnNumber() {
63 StringRef Tok = Tokens[Pos - 1];62 StringRef tok = tokens[pos - 1];
64 return Tok.data() - getLine().data();63 return tok.data() - getLine().data();
65}64}
6665
67std::string ScriptLexer::getCurrentLocation() {66std::string ScriptLexer::getCurrentLocation() {
68 std::string Filename = getCurrentMB().getBufferIdentifier();67 std::string filename = getCurrentMB().getBufferIdentifier();
69 return (Filename + ":" + Twine(getLineNumber())).str();68 return (filename + ":" + Twine(getLineNumber())).str();
70}69}
7170
72ScriptLexer::ScriptLexer(MemoryBufferRef MB) { tokenize(MB); }71ScriptLexer::ScriptLexer(MemoryBufferRef mb) { tokenize(mb); }
7372
74// We don't want to record cascading errors. Keep only the first one.73// We don't want to record cascading errors. Keep only the first one.
75void ScriptLexer::setError(const Twine &Msg) {74void ScriptLexer::setError(const Twine &msg) {
76 if (errorCount())75 if (errorCount())
77 return;76 return;
7877
79 std::string S = (getCurrentLocation() + ": " + Msg).str();78 std::string s = (getCurrentLocation() + ": " + msg).str();
80 if (Pos)79 if (pos)
81 S += "\n>>> " + getLine().str() + "\n>>> " +80 s += "\n>>> " + getLine().str() + "\n>>> " +
82 std::string(getColumnNumber(), ' ') + "^";81 std::string(getColumnNumber(), ' ') + "^";
83 error(S);82 error(s);
84}83}
8584
86// Split S into linker script tokens.85// Split S into linker script tokens.
87void ScriptLexer::tokenize(MemoryBufferRef MB) {86void ScriptLexer::tokenize(MemoryBufferRef mb) {
88 std::vector<StringRef> Vec;87 std::vector<StringRef> vec;
89 MBs.push_back(MB);88 mbs.push_back(mb);
90 StringRef S = MB.getBuffer();89 StringRef s = mb.getBuffer();
91 StringRef Begin = S;90 StringRef begin = s;
9291
93 for (;;) {92 for (;;) {
94 S = skipSpace(S);93 s = skipSpace(s);
95 if (S.empty())94 if (s.empty())
96 break;95 break;
9796
98 // Quoted token. Note that double-quote characters are parts of a token97 // Quoted token. Note that double-quote characters are parts of a token
99 // because, in a glob match context, only unquoted tokens are interpreted98 // because, in a glob match context, only unquoted tokens are interpreted
100 // as glob patterns. Double-quoted tokens are literal patterns in that99 // as glob patterns. Double-quoted tokens are literal patterns in that
101 // context.100 // context.
102 if (S.startswith("\"")) {101 if (s.startswith("\"")) {
103 size_t E = S.find("\"", 1);102 size_t e = s.find("\"", 1);
104 if (E == StringRef::npos) {103 if (e == StringRef::npos) {
105 StringRef Filename = MB.getBufferIdentifier();104 StringRef filename = mb.getBufferIdentifier();
106 size_t Lineno = Begin.substr(0, S.data() - Begin.data()).count('\n');105 size_t lineno = begin.substr(0, s.data() - begin.data()).count('\n');
107 error(Filename + ":" + Twine(Lineno + 1) + ": unclosed quote");106 error(filename + ":" + Twine(lineno + 1) + ": unclosed quote");
108 return;107 return;
109 }108 }
110109
111 Vec.push_back(S.take_front(E + 1));110 vec.push_back(s.take_front(e + 1));
112 S = S.substr(E + 1);111 s = s.substr(e + 1);
113 continue;112 continue;
114 }113 }
115114
116 // ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>".115 // ">foo" is parsed to ">" and "foo", but ">>" is parsed to ">>".
117 // "|", "||", "&" and "&&" are different operators.116 // "|", "||", "&" and "&&" are different operators.
118 if (S.startswith("<<") || S.startswith("<=") || S.startswith(">>") ||117 if (s.startswith("<<") || s.startswith("<=") || s.startswith(">>") ||
119 S.startswith(">=") || S.startswith("||") || S.startswith("&&")) {118 s.startswith(">=") || s.startswith("||") || s.startswith("&&")) {
120 Vec.push_back(S.substr(0, 2));119 vec.push_back(s.substr(0, 2));
121 S = S.substr(2);120 s = s.substr(2);
122 continue;121 continue;
123 }122 }
124123
125 // Unquoted token. This is more relaxed than tokens in C-like language,124 // Unquoted token. This is more relaxed than tokens in C-like language,
126 // so that you can write "file-name.cpp" as one bare token, for example.125 // so that you can write "file-name.cpp" as one bare token, for example.
127 size_t Pos = S.find_first_not_of(126 size_t pos = s.find_first_not_of(
128 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"127 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
129 "0123456789_.$/\\~=+[]*?-!^:");128 "0123456789_.$/\\~=+[]*?-!^:");
130129
131 // A character that cannot start a word (which is usually a130 // A character that cannot start a word (which is usually a
132 // punctuation) forms a single character token.131 // punctuation) forms a single character token.
133 if (Pos == 0)132 if (pos == 0)
134 Pos = 1;133 pos = 1;
135 Vec.push_back(S.substr(0, Pos));134 vec.push_back(s.substr(0, pos));
136 S = S.substr(Pos);135 s = s.substr(pos);
137 }136 }
138137
139 Tokens.insert(Tokens.begin() + Pos, Vec.begin(), Vec.end());138 tokens.insert(tokens.begin() + pos, vec.begin(), vec.end());
140}139}
141140
142// Skip leading whitespace characters or comments.141// Skip leading whitespace characters or comments.
143StringRef ScriptLexer::skipSpace(StringRef S) {142StringRef ScriptLexer::skipSpace(StringRef s) {
144 for (;;) {143 for (;;) {
145 if (S.startswith("/*")) {144 if (s.startswith("/*")) {
146 size_t E = S.find("*/", 2);145 size_t e = s.find("*/", 2);
147 if (E == StringRef::npos) {146 if (e == StringRef::npos) {
148 error("unclosed comment in a linker script");147 error("unclosed comment in a linker script");
149 return "";148 return "";
150 }149 }
151 S = S.substr(E + 2);150 s = s.substr(e + 2);
152 continue;151 continue;
153 }152 }
154 if (S.startswith("#")) {153 if (s.startswith("#")) {
155 size_t E = S.find('\n', 1);154 size_t e = s.find('\n', 1);
156 if (E == StringRef::npos)155 if (e == StringRef::npos)
157 E = S.size() - 1;156 e = s.size() - 1;
158 S = S.substr(E + 1);157 s = s.substr(e + 1);
159 continue;158 continue;
160 }159 }
161 size_t Size = S.size();160 size_t size = s.size();
162 S = S.ltrim();161 s = s.ltrim();
163 if (S.size() == Size)162 if (s.size() == size)
164 return S;163 return s;
165 }164 }
166}165}
167166
168// An erroneous token is handled as if it were the last token before EOF.167// An erroneous token is handled as if it were the last token before EOF.
169bool ScriptLexer::atEOF() { return errorCount() || Tokens.size() == Pos; }168bool ScriptLexer::atEOF() { return errorCount() || tokens.size() == pos; }
170169
171// Split a given string as an expression.170// Split a given string as an expression.
172// This function returns "3", "*" and "5" for "3*5" for example.171// This function returns "3", "*" and "5" for "3*5" for example.
173static std::vector<StringRef> tokenizeExpr(StringRef S) {172static std::vector<StringRef> tokenizeExpr(StringRef s) {
174 StringRef Ops = "+-*/:!~"; // List of operators173 StringRef ops = "+-*/:!~=<>"; // List of operators
175174
176 // Quoted strings are literal strings, so we don't want to split it.175 // Quoted strings are literal strings, so we don't want to split it.
177 if (S.startswith("\""))176 if (s.startswith("\""))
178 return {S};177 return {s};
179178
180 // Split S with operators as separators.179 // Split S with operators as separators.
181 std::vector<StringRef> Ret;180 std::vector<StringRef> ret;
182 while (!S.empty()) {181 while (!s.empty()) {
183 size_t E = S.find_first_of(Ops);182 size_t e = s.find_first_of(ops);
184183
185 // No need to split if there is no operator.184 // No need to split if there is no operator.
186 if (E == StringRef::npos) {185 if (e == StringRef::npos) {
187 Ret.push_back(S);186 ret.push_back(s);
188 break;187 break;
189 }188 }
190189
191 // Get a token before the opreator.190 // Get a token before the opreator.
192 if (E != 0)191 if (e != 0)
193 Ret.push_back(S.substr(0, E));192 ret.push_back(s.substr(0, e));
194193
195 // Get the operator as a token. Keep != as one token.194 // Get the operator as a token.
196 if (S.substr(E).startswith("!=")) {195 // Keep !=, ==, >=, <=, << and >> operators as a single tokens.
197 Ret.push_back(S.substr(E, 2));196 if (s.substr(e).startswith("!=") || s.substr(e).startswith("==") ||
198 S = S.substr(E + 2);197 s.substr(e).startswith(">=") || s.substr(e).startswith("<=") ||
198 s.substr(e).startswith("<<") || s.substr(e).startswith(">>")) {
199 ret.push_back(s.substr(e, 2));
200 s = s.substr(e + 2);
199 } else {201 } else {
200 Ret.push_back(S.substr(E, 1));202 ret.push_back(s.substr(e, 1));
201 S = S.substr(E + 1);203 s = s.substr(e + 1);
202 }204 }
203 }205 }
204 return Ret;206 return ret;
205}207}
206208
207// In contexts where expressions are expected, the lexer should apply209// In contexts where expressions are expected, the lexer should apply
...@@ -214,14 +216,14 @@ static std::vector<StringRef> tokenizeExpr(StringRef S) {...@@ -214,14 +216,14 @@ static std::vector<StringRef> tokenizeExpr(StringRef S) {
214//216//
215// This function may split the current token into multiple tokens.217// This function may split the current token into multiple tokens.
216void ScriptLexer::maybeSplitExpr() {218void ScriptLexer::maybeSplitExpr() {
217 if (!InExpr || errorCount() || atEOF())219 if (!inExpr || errorCount() || atEOF())
218 return;220 return;
219221
220 std::vector<StringRef> V = tokenizeExpr(Tokens[Pos]);222 std::vector<StringRef> v = tokenizeExpr(tokens[pos]);
221 if (V.size() == 1)223 if (v.size() == 1)
222 return;224 return;
223 Tokens.erase(Tokens.begin() + Pos);225 tokens.erase(tokens.begin() + pos);
224 Tokens.insert(Tokens.begin() + Pos, V.begin(), V.end());226 tokens.insert(tokens.begin() + pos, v.begin(), v.end());
225}227}
226228
227StringRef ScriptLexer::next() {229StringRef ScriptLexer::next() {
...@@ -233,28 +235,28 @@ StringRef ScriptLexer::next() {...@@ -233,28 +235,28 @@ StringRef ScriptLexer::next() {
233 setError("unexpected EOF");235 setError("unexpected EOF");
234 return "";236 return "";
235 }237 }
236 return Tokens[Pos++];238 return tokens[pos++];
237}239}
238240
239StringRef ScriptLexer::peek() {241StringRef ScriptLexer::peek() {
240 StringRef Tok = next();242 StringRef tok = next();
241 if (errorCount())243 if (errorCount())
242 return "";244 return "";
243 Pos = Pos - 1;245 pos = pos - 1;
244 return Tok;246 return tok;
245}247}
246248
247StringRef ScriptLexer::peek2() {249StringRef ScriptLexer::peek2() {
248 skip();250 skip();
249 StringRef Tok = next();251 StringRef tok = next();
250 if (errorCount())252 if (errorCount())
251 return "";253 return "";
252 Pos = Pos - 2;254 pos = pos - 2;
253 return Tok;255 return tok;
254}256}
255257
256bool ScriptLexer::consume(StringRef Tok) {258bool ScriptLexer::consume(StringRef tok) {
257 if (peek() == Tok) {259 if (peek() == tok) {
258 skip();260 skip();
259 return true;261 return true;
260 }262 }
...@@ -262,12 +264,12 @@ bool ScriptLexer::consume(StringRef Tok) {...@@ -262,12 +264,12 @@ bool ScriptLexer::consume(StringRef Tok) {
262}264}
263265
264// Consumes Tok followed by ":". Space is allowed between Tok and ":".266// Consumes Tok followed by ":". Space is allowed between Tok and ":".
265bool ScriptLexer::consumeLabel(StringRef Tok) {267bool ScriptLexer::consumeLabel(StringRef tok) {
266 if (consume((Tok + ":").str()))268 if (consume((tok + ":").str()))
267 return true;269 return true;
268 if (Tokens.size() >= Pos + 2 && Tokens[Pos] == Tok &&270 if (tokens.size() >= pos + 2 && tokens[pos] == tok &&
269 Tokens[Pos + 1] == ":") {271 tokens[pos + 1] == ":") {
270 Pos += 2;272 pos += 2;
271 return true;273 return true;
272 }274 }
273 return false;275 return false;
...@@ -275,24 +277,24 @@ bool ScriptLexer::consumeLabel(StringRef Tok) {...@@ -275,24 +277,24 @@ bool ScriptLexer::consumeLabel(StringRef Tok) {
275277
276void ScriptLexer::skip() { (void)next(); }278void ScriptLexer::skip() { (void)next(); }
277279
278void ScriptLexer::expect(StringRef Expect) {280void ScriptLexer::expect(StringRef expect) {
279 if (errorCount())281 if (errorCount())
280 return;282 return;
281 StringRef Tok = next();283 StringRef tok = next();
282 if (Tok != Expect)284 if (tok != expect)
283 setError(Expect + " expected, but got " + Tok);285 setError(expect + " expected, but got " + tok);
284}286}
285287
286// Returns true if S encloses T.288// Returns true if S encloses T.
287static bool encloses(StringRef S, StringRef T) {289static bool encloses(StringRef s, StringRef t) {
288 return S.bytes_begin() <= T.bytes_begin() && T.bytes_end() <= S.bytes_end();290 return s.bytes_begin() <= t.bytes_begin() && t.bytes_end() <= s.bytes_end();
289}291}
290292
291MemoryBufferRef ScriptLexer::getCurrentMB() {293MemoryBufferRef ScriptLexer::getCurrentMB() {
292 // Find input buffer containing the current token.294 // Find input buffer containing the current token.
293 assert(!MBs.empty() && Pos > 0);295 assert(!mbs.empty() && pos > 0);
294 for (MemoryBufferRef MB : MBs)296 for (MemoryBufferRef mb : mbs)
295 if (encloses(MB.getBuffer(), Tokens[Pos - 1]))297 if (encloses(mb.getBuffer(), tokens[pos - 1]))
296 return MB;298 return mb;
297 llvm_unreachable("getCurrentMB: failed to find a token");299 llvm_unreachable("getCurrentMB: failed to find a token");
298}300}
deps/lld/ELF/ScriptLexer.h+14-15
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ScriptLexer.h --------------------------------------------*- C++ -*-===//1//===- ScriptLexer.h --------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -21,25 +20,25 @@ namespace elf {...@@ -21,25 +20,25 @@ namespace elf {
2120
22class ScriptLexer {21class ScriptLexer {
23public:22public:
24 explicit ScriptLexer(MemoryBufferRef MB);23 explicit ScriptLexer(MemoryBufferRef mb);
2524
26 void setError(const Twine &Msg);25 void setError(const Twine &msg);
27 void tokenize(MemoryBufferRef MB);26 void tokenize(MemoryBufferRef mb);
28 static StringRef skipSpace(StringRef S);27 static StringRef skipSpace(StringRef s);
29 bool atEOF();28 bool atEOF();
30 StringRef next();29 StringRef next();
31 StringRef peek();30 StringRef peek();
32 StringRef peek2();31 StringRef peek2();
33 void skip();32 void skip();
34 bool consume(StringRef Tok);33 bool consume(StringRef tok);
35 void expect(StringRef Expect);34 void expect(StringRef expect);
36 bool consumeLabel(StringRef Tok);35 bool consumeLabel(StringRef tok);
37 std::string getCurrentLocation();36 std::string getCurrentLocation();
3837
39 std::vector<MemoryBufferRef> MBs;38 std::vector<MemoryBufferRef> mbs;
40 std::vector<StringRef> Tokens;39 std::vector<StringRef> tokens;
41 bool InExpr = false;40 bool inExpr = false;
42 size_t Pos = 0;41 size_t pos = 0;
4342
44private:43private:
45 void maybeSplitExpr();44 void maybeSplitExpr();
deps/lld/ELF/ScriptParser.cpp+633-636
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ScriptParser.cpp ---------------------------------------------------===//1//===- ScriptParser.cpp ---------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -41,22 +40,29 @@ using namespace llvm::support::endian;...@@ -41,22 +40,29 @@ using namespace llvm::support::endian;
41using namespace lld;40using namespace lld;
42using namespace lld::elf;41using namespace lld::elf;
4342
44static bool isUnderSysroot(StringRef Path);
45
46namespace {43namespace {
47class ScriptParser final : ScriptLexer {44class ScriptParser final : ScriptLexer {
48public:45public:
49 ScriptParser(MemoryBufferRef MB)46 ScriptParser(MemoryBufferRef mb) : ScriptLexer(mb) {
50 : ScriptLexer(MB),47 // Initialize IsUnderSysroot
51 IsUnderSysroot(isUnderSysroot(MB.getBufferIdentifier())) {}48 if (config->sysroot == "")
49 return;
50 StringRef path = mb.getBufferIdentifier();
51 for (; !path.empty(); path = sys::path::parent_path(path)) {
52 if (!sys::fs::equivalent(config->sysroot, path))
53 continue;
54 isUnderSysroot = true;
55 return;
56 }
57 }
5258
53 void readLinkerScript();59 void readLinkerScript();
54 void readVersionScript();60 void readVersionScript();
55 void readDynamicList();61 void readDynamicList();
56 void readDefsym(StringRef Name);62 void readDefsym(StringRef name);
5763
58private:64private:
59 void addFile(StringRef Path);65 void addFile(StringRef path);
6066
61 void readAsNeeded();67 void readAsNeeded();
62 void readEntry();68 void readEntry();
...@@ -76,24 +82,23 @@ private:...@@ -76,24 +82,23 @@ private:
76 void readVersion();82 void readVersion();
77 void readVersionScriptCommand();83 void readVersionScriptCommand();
7884
79 SymbolAssignment *readSymbolAssignment(StringRef Name);85 SymbolAssignment *readSymbolAssignment(StringRef name);
80 ByteCommand *readByteCommand(StringRef Tok);86 ByteCommand *readByteCommand(StringRef tok);
81 std::array<uint8_t, 4> readFill();87 std::array<uint8_t, 4> readFill();
82 std::array<uint8_t, 4> parseFill(StringRef Tok);88 bool readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2);
83 bool readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2);89 void readSectionAddressType(OutputSection *cmd);
84 void readSectionAddressType(OutputSection *Cmd);
85 OutputSection *readOverlaySectionDescription();90 OutputSection *readOverlaySectionDescription();
86 OutputSection *readOutputSectionDescription(StringRef OutSec);91 OutputSection *readOutputSectionDescription(StringRef outSec);
87 std::vector<BaseCommand *> readOverlay();92 std::vector<BaseCommand *> readOverlay();
88 std::vector<StringRef> readOutputSectionPhdrs();93 std::vector<StringRef> readOutputSectionPhdrs();
89 InputSectionDescription *readInputSectionDescription(StringRef Tok);94 InputSectionDescription *readInputSectionDescription(StringRef tok);
90 StringMatcher readFilePatterns();95 StringMatcher readFilePatterns();
91 std::vector<SectionPattern> readInputSectionsList();96 std::vector<SectionPattern> readInputSectionsList();
92 InputSectionDescription *readInputSectionRules(StringRef FilePattern);97 InputSectionDescription *readInputSectionRules(StringRef filePattern);
93 unsigned readPhdrType();98 unsigned readPhdrType();
94 SortSectionPolicy readSortKind();99 SortSectionPolicy readSortKind();
95 SymbolAssignment *readProvideHidden(bool Provide, bool Hidden);100 SymbolAssignment *readProvideHidden(bool provide, bool hidden);
96 SymbolAssignment *readAssignment(StringRef Tok);101 SymbolAssignment *readAssignment(StringRef tok);
97 void readSort();102 void readSort();
98 Expr readAssert();103 Expr readAssert();
99 Expr readConstant();104 Expr readConstant();
...@@ -102,97 +107,88 @@ private:...@@ -102,97 +107,88 @@ private:
102 uint64_t readMemoryAssignment(StringRef, StringRef, StringRef);107 uint64_t readMemoryAssignment(StringRef, StringRef, StringRef);
103 std::pair<uint32_t, uint32_t> readMemoryAttributes();108 std::pair<uint32_t, uint32_t> readMemoryAttributes();
104109
105 Expr combine(StringRef Op, Expr L, Expr R);110 Expr combine(StringRef op, Expr l, Expr r);
106 Expr readExpr();111 Expr readExpr();
107 Expr readExpr1(Expr Lhs, int MinPrec);112 Expr readExpr1(Expr lhs, int minPrec);
108 StringRef readParenLiteral();113 StringRef readParenLiteral();
109 Expr readPrimary();114 Expr readPrimary();
110 Expr readTernary(Expr Cond);115 Expr readTernary(Expr cond);
111 Expr readParenExpr();116 Expr readParenExpr();
112117
113 // For parsing version script.118 // For parsing version script.
114 std::vector<SymbolVersion> readVersionExtern();119 std::vector<SymbolVersion> readVersionExtern();
115 void readAnonymousDeclaration();120 void readAnonymousDeclaration();
116 void readVersionDeclaration(StringRef VerStr);121 void readVersionDeclaration(StringRef verStr);
117122
118 std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>123 std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
119 readSymbols();124 readSymbols();
120125
121 // True if a script being read is in a subdirectory specified by -sysroot.126 // True if a script being read is in a subdirectory specified by -sysroot.
122 bool IsUnderSysroot;127 bool isUnderSysroot = false;
123128
124 // A set to detect an INCLUDE() cycle.129 // A set to detect an INCLUDE() cycle.
125 StringSet<> Seen;130 StringSet<> seen;
126};131};
127} // namespace132} // namespace
128133
129static StringRef unquote(StringRef S) {134static StringRef unquote(StringRef s) {
130 if (S.startswith("\""))135 if (s.startswith("\""))
131 return S.substr(1, S.size() - 2);136 return s.substr(1, s.size() - 2);
132 return S;137 return s;
133}
134
135static bool isUnderSysroot(StringRef Path) {
136 if (Config->Sysroot == "")
137 return false;
138 for (; !Path.empty(); Path = sys::path::parent_path(Path))
139 if (sys::fs::equivalent(Config->Sysroot, Path))
140 return true;
141 return false;
142}138}
143139
144// Some operations only support one non absolute value. Move the140// Some operations only support one non absolute value. Move the
145// absolute one to the right hand side for convenience.141// absolute one to the right hand side for convenience.
146static void moveAbsRight(ExprValue &A, ExprValue &B) {142static void moveAbsRight(ExprValue &a, ExprValue &b) {
147 if (A.Sec == nullptr || (A.ForceAbsolute && !B.isAbsolute()))143 if (a.sec == nullptr || (a.forceAbsolute && !b.isAbsolute()))
148 std::swap(A, B);144 std::swap(a, b);
149 if (!B.isAbsolute())145 if (!b.isAbsolute())
150 error(A.Loc + ": at least one side of the expression must be absolute");146 error(a.loc + ": at least one side of the expression must be absolute");
151}147}
152148
153static ExprValue add(ExprValue A, ExprValue B) {149static ExprValue add(ExprValue a, ExprValue b) {
154 moveAbsRight(A, B);150 moveAbsRight(a, b);
155 return {A.Sec, A.ForceAbsolute, A.getSectionOffset() + B.getValue(), A.Loc};151 return {a.sec, a.forceAbsolute, a.getSectionOffset() + b.getValue(), a.loc};
156}152}
157153
158static ExprValue sub(ExprValue A, ExprValue B) {154static ExprValue sub(ExprValue a, ExprValue b) {
159 // The distance between two symbols in sections is absolute.155 // The distance between two symbols in sections is absolute.
160 if (!A.isAbsolute() && !B.isAbsolute())156 if (!a.isAbsolute() && !b.isAbsolute())
161 return A.getValue() - B.getValue();157 return a.getValue() - b.getValue();
162 return {A.Sec, false, A.getSectionOffset() - B.getValue(), A.Loc};158 return {a.sec, false, a.getSectionOffset() - b.getValue(), a.loc};
163}159}
164160
165static ExprValue bitAnd(ExprValue A, ExprValue B) {161static ExprValue bitAnd(ExprValue a, ExprValue b) {
166 moveAbsRight(A, B);162 moveAbsRight(a, b);
167 return {A.Sec, A.ForceAbsolute,163 return {a.sec, a.forceAbsolute,
168 (A.getValue() & B.getValue()) - A.getSecAddr(), A.Loc};164 (a.getValue() & b.getValue()) - a.getSecAddr(), a.loc};
169}165}
170166
171static ExprValue bitOr(ExprValue A, ExprValue B) {167static ExprValue bitOr(ExprValue a, ExprValue b) {
172 moveAbsRight(A, B);168 moveAbsRight(a, b);
173 return {A.Sec, A.ForceAbsolute,169 return {a.sec, a.forceAbsolute,
174 (A.getValue() | B.getValue()) - A.getSecAddr(), A.Loc};170 (a.getValue() | b.getValue()) - a.getSecAddr(), a.loc};
175}171}
176172
177void ScriptParser::readDynamicList() {173void ScriptParser::readDynamicList() {
178 Config->HasDynamicList = true;174 config->hasDynamicList = true;
179 expect("{");175 expect("{");
180 std::vector<SymbolVersion> Locals;176 std::vector<SymbolVersion> locals;
181 std::vector<SymbolVersion> Globals;177 std::vector<SymbolVersion> globals;
182 std::tie(Locals, Globals) = readSymbols();178 std::tie(locals, globals) = readSymbols();
183 expect(";");179 expect(";");
184180
185 if (!atEOF()) {181 if (!atEOF()) {
186 setError("EOF expected, but got " + next());182 setError("EOF expected, but got " + next());
187 return;183 return;
188 }184 }
189 if (!Locals.empty()) {185 if (!locals.empty()) {
190 setError("\"local:\" scope not supported in --dynamic-list");186 setError("\"local:\" scope not supported in --dynamic-list");
191 return;187 return;
192 }188 }
193189
194 for (SymbolVersion V : Globals)190 for (SymbolVersion v : globals)
195 Config->DynamicList.push_back(V);191 config->dynamicList.push_back(v);
196}192}
197193
198void ScriptParser::readVersionScript() {194void ScriptParser::readVersionScript() {
...@@ -208,14 +204,14 @@ void ScriptParser::readVersionScriptCommand() {...@@ -208,14 +204,14 @@ void ScriptParser::readVersionScriptCommand() {
208 }204 }
209205
210 while (!atEOF() && !errorCount() && peek() != "}") {206 while (!atEOF() && !errorCount() && peek() != "}") {
211 StringRef VerStr = next();207 StringRef verStr = next();
212 if (VerStr == "{") {208 if (verStr == "{") {
213 setError("anonymous version definition is used in "209 setError("anonymous version definition is used in "
214 "combination with other version definitions");210 "combination with other version definitions");
215 return;211 return;
216 }212 }
217 expect("{");213 expect("{");
218 readVersionDeclaration(VerStr);214 readVersionDeclaration(verStr);
219 }215 }
220}216}
221217
...@@ -227,135 +223,135 @@ void ScriptParser::readVersion() {...@@ -227,135 +223,135 @@ void ScriptParser::readVersion() {
227223
228void ScriptParser::readLinkerScript() {224void ScriptParser::readLinkerScript() {
229 while (!atEOF()) {225 while (!atEOF()) {
230 StringRef Tok = next();226 StringRef tok = next();
231 if (Tok == ";")227 if (tok == ";")
232 continue;228 continue;
233229
234 if (Tok == "ENTRY") {230 if (tok == "ENTRY") {
235 readEntry();231 readEntry();
236 } else if (Tok == "EXTERN") {232 } else if (tok == "EXTERN") {
237 readExtern();233 readExtern();
238 } else if (Tok == "GROUP") {234 } else if (tok == "GROUP") {
239 readGroup();235 readGroup();
240 } else if (Tok == "INCLUDE") {236 } else if (tok == "INCLUDE") {
241 readInclude();237 readInclude();
242 } else if (Tok == "INPUT") {238 } else if (tok == "INPUT") {
243 readInput();239 readInput();
244 } else if (Tok == "MEMORY") {240 } else if (tok == "MEMORY") {
245 readMemory();241 readMemory();
246 } else if (Tok == "OUTPUT") {242 } else if (tok == "OUTPUT") {
247 readOutput();243 readOutput();
248 } else if (Tok == "OUTPUT_ARCH") {244 } else if (tok == "OUTPUT_ARCH") {
249 readOutputArch();245 readOutputArch();
250 } else if (Tok == "OUTPUT_FORMAT") {246 } else if (tok == "OUTPUT_FORMAT") {
251 readOutputFormat();247 readOutputFormat();
252 } else if (Tok == "PHDRS") {248 } else if (tok == "PHDRS") {
253 readPhdrs();249 readPhdrs();
254 } else if (Tok == "REGION_ALIAS") {250 } else if (tok == "REGION_ALIAS") {
255 readRegionAlias();251 readRegionAlias();
256 } else if (Tok == "SEARCH_DIR") {252 } else if (tok == "SEARCH_DIR") {
257 readSearchDir();253 readSearchDir();
258 } else if (Tok == "SECTIONS") {254 } else if (tok == "SECTIONS") {
259 readSections();255 readSections();
260 } else if (Tok == "TARGET") {256 } else if (tok == "TARGET") {
261 readTarget();257 readTarget();
262 } else if (Tok == "VERSION") {258 } else if (tok == "VERSION") {
263 readVersion();259 readVersion();
264 } else if (SymbolAssignment *Cmd = readAssignment(Tok)) {260 } else if (SymbolAssignment *cmd = readAssignment(tok)) {
265 Script->SectionCommands.push_back(Cmd);261 script->sectionCommands.push_back(cmd);
266 } else {262 } else {
267 setError("unknown directive: " + Tok);263 setError("unknown directive: " + tok);
268 }264 }
269 }265 }
270}266}
271267
272void ScriptParser::readDefsym(StringRef Name) {268void ScriptParser::readDefsym(StringRef name) {
273 if (errorCount())269 if (errorCount())
274 return;270 return;
275 Expr E = readExpr();271 Expr e = readExpr();
276 if (!atEOF())272 if (!atEOF())
277 setError("EOF expected, but got " + next());273 setError("EOF expected, but got " + next());
278 SymbolAssignment *Cmd = make<SymbolAssignment>(Name, E, getCurrentLocation());274 SymbolAssignment *cmd = make<SymbolAssignment>(name, e, getCurrentLocation());
279 Script->SectionCommands.push_back(Cmd);275 script->sectionCommands.push_back(cmd);
280}276}
281277
282void ScriptParser::addFile(StringRef S) {278void ScriptParser::addFile(StringRef s) {
283 if (IsUnderSysroot && S.startswith("/")) {279 if (isUnderSysroot && s.startswith("/")) {
284 SmallString<128> PathData;280 SmallString<128> pathData;
285 StringRef Path = (Config->Sysroot + S).toStringRef(PathData);281 StringRef path = (config->sysroot + s).toStringRef(pathData);
286 if (sys::fs::exists(Path)) {282 if (sys::fs::exists(path)) {
287 Driver->addFile(Saver.save(Path), /*WithLOption=*/false);283 driver->addFile(saver.save(path), /*withLOption=*/false);
288 return;284 return;
289 }285 }
290 }286 }
291287
292 if (S.startswith("/")) {288 if (s.startswith("/")) {
293 Driver->addFile(S, /*WithLOption=*/false);289 driver->addFile(s, /*withLOption=*/false);
294 } else if (S.startswith("=")) {290 } else if (s.startswith("=")) {
295 if (Config->Sysroot.empty())291 if (config->sysroot.empty())
296 Driver->addFile(S.substr(1), /*WithLOption=*/false);292 driver->addFile(s.substr(1), /*withLOption=*/false);
297 else293 else
298 Driver->addFile(Saver.save(Config->Sysroot + "/" + S.substr(1)),294 driver->addFile(saver.save(config->sysroot + "/" + s.substr(1)),
299 /*WithLOption=*/false);295 /*withLOption=*/false);
300 } else if (S.startswith("-l")) {296 } else if (s.startswith("-l")) {
301 Driver->addLibrary(S.substr(2));297 driver->addLibrary(s.substr(2));
302 } else if (sys::fs::exists(S)) {298 } else if (sys::fs::exists(s)) {
303 Driver->addFile(S, /*WithLOption=*/false);299 driver->addFile(s, /*withLOption=*/false);
304 } else {300 } else {
305 if (Optional<std::string> Path = findFromSearchPaths(S))301 if (Optional<std::string> path = findFromSearchPaths(s))
306 Driver->addFile(Saver.save(*Path), /*WithLOption=*/true);302 driver->addFile(saver.save(*path), /*withLOption=*/true);
307 else303 else
308 setError("unable to find " + S);304 setError("unable to find " + s);
309 }305 }
310}306}
311307
312void ScriptParser::readAsNeeded() {308void ScriptParser::readAsNeeded() {
313 expect("(");309 expect("(");
314 bool Orig = Config->AsNeeded;310 bool orig = config->asNeeded;
315 Config->AsNeeded = true;311 config->asNeeded = true;
316 while (!errorCount() && !consume(")"))312 while (!errorCount() && !consume(")"))
317 addFile(unquote(next()));313 addFile(unquote(next()));
318 Config->AsNeeded = Orig;314 config->asNeeded = orig;
319}315}
320316
321void ScriptParser::readEntry() {317void ScriptParser::readEntry() {
322 // -e <symbol> takes predecence over ENTRY(<symbol>).318 // -e <symbol> takes predecence over ENTRY(<symbol>).
323 expect("(");319 expect("(");
324 StringRef Tok = next();320 StringRef tok = next();
325 if (Config->Entry.empty())321 if (config->entry.empty())
326 Config->Entry = Tok;322 config->entry = tok;
327 expect(")");323 expect(")");
328}324}
329325
330void ScriptParser::readExtern() {326void ScriptParser::readExtern() {
331 expect("(");327 expect("(");
332 while (!errorCount() && !consume(")"))328 while (!errorCount() && !consume(")"))
333 Config->Undefined.push_back(next());329 config->undefined.push_back(unquote(next()));
334}330}
335331
336void ScriptParser::readGroup() {332void ScriptParser::readGroup() {
337 bool Orig = InputFile::IsInGroup;333 bool orig = InputFile::isInGroup;
338 InputFile::IsInGroup = true;334 InputFile::isInGroup = true;
339 readInput();335 readInput();
340 InputFile::IsInGroup = Orig;336 InputFile::isInGroup = orig;
341 if (!Orig)337 if (!orig)
342 ++InputFile::NextGroupId;338 ++InputFile::nextGroupId;
343}339}
344340
345void ScriptParser::readInclude() {341void ScriptParser::readInclude() {
346 StringRef Tok = unquote(next());342 StringRef tok = unquote(next());
347343
348 if (!Seen.insert(Tok).second) {344 if (!seen.insert(tok).second) {
349 setError("there is a cycle in linker script INCLUDEs");345 setError("there is a cycle in linker script INCLUDEs");
350 return;346 return;
351 }347 }
352348
353 if (Optional<std::string> Path = searchScript(Tok)) {349 if (Optional<std::string> path = searchScript(tok)) {
354 if (Optional<MemoryBufferRef> MB = readFile(*Path))350 if (Optional<MemoryBufferRef> mb = readFile(*path))
355 tokenize(*MB);351 tokenize(*mb);
356 return;352 return;
357 }353 }
358 setError("cannot find linker script " + Tok);354 setError("cannot find linker script " + tok);
359}355}
360356
361void ScriptParser::readInput() {357void ScriptParser::readInput() {
...@@ -371,9 +367,9 @@ void ScriptParser::readInput() {...@@ -371,9 +367,9 @@ void ScriptParser::readInput() {
371void ScriptParser::readOutput() {367void ScriptParser::readOutput() {
372 // -o <file> takes predecence over OUTPUT(<file>).368 // -o <file> takes predecence over OUTPUT(<file>).
373 expect("(");369 expect("(");
374 StringRef Tok = next();370 StringRef tok = next();
375 if (Config->OutputFile.empty())371 if (config->outputFile.empty())
376 Config->OutputFile = unquote(Tok);372 config->outputFile = unquote(tok);
377 expect(")");373 expect(")");
378}374}
379375
...@@ -384,8 +380,8 @@ void ScriptParser::readOutputArch() {...@@ -384,8 +380,8 @@ void ScriptParser::readOutputArch() {
384 skip();380 skip();
385}381}
386382
387static std::pair<ELFKind, uint16_t> parseBfdName(StringRef S) {383static std::pair<ELFKind, uint16_t> parseBfdName(StringRef s) {
388 return StringSwitch<std::pair<ELFKind, uint16_t>>(S)384 return StringSwitch<std::pair<ELFKind, uint16_t>>(s)
389 .Case("elf32-i386", {ELF32LEKind, EM_386})385 .Case("elf32-i386", {ELF32LEKind, EM_386})
390 .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU})386 .Case("elf32-iamcu", {ELF32LEKind, EM_IAMCU})
391 .Case("elf32-littlearm", {ELF32LEKind, EM_ARM})387 .Case("elf32-littlearm", {ELF32LEKind, EM_ARM})
...@@ -402,6 +398,8 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef S) {...@@ -402,6 +398,8 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef S) {
402 .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS})398 .Case("elf32-ntradlittlemips", {ELF32LEKind, EM_MIPS})
403 .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS})399 .Case("elf64-tradbigmips", {ELF64BEKind, EM_MIPS})
404 .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS})400 .Case("elf64-tradlittlemips", {ELF64LEKind, EM_MIPS})
401 .Case("elf32-littleriscv", {ELF32LEKind, EM_RISCV})
402 .Case("elf64-littleriscv", {ELF64LEKind, EM_RISCV})
405 .Default({ELFNoneKind, EM_NONE});403 .Default({ELFNoneKind, EM_NONE});
406}404}
407405
...@@ -410,16 +408,16 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef S) {...@@ -410,16 +408,16 @@ static std::pair<ELFKind, uint16_t> parseBfdName(StringRef S) {
410void ScriptParser::readOutputFormat() {408void ScriptParser::readOutputFormat() {
411 expect("(");409 expect("(");
412410
413 StringRef Name = unquote(next());411 StringRef name = unquote(next());
414 StringRef S = Name;412 StringRef s = name;
415 if (S.consume_back("-freebsd"))413 if (s.consume_back("-freebsd"))
416 Config->OSABI = ELFOSABI_FREEBSD;414 config->osabi = ELFOSABI_FREEBSD;
417415
418 std::tie(Config->EKind, Config->EMachine) = parseBfdName(S);416 std::tie(config->ekind, config->emachine) = parseBfdName(s);
419 if (Config->EMachine == EM_NONE)417 if (config->emachine == EM_NONE)
420 setError("unknown output format name: " + Name);418 setError("unknown output format name: " + name);
421 if (S == "elf32-ntradlittlemips" || S == "elf32-ntradbigmips")419 if (s == "elf32-ntradlittlemips" || s == "elf32-ntradbigmips")
422 Config->MipsN32Abi = true;420 config->mipsN32Abi = true;
423421
424 if (consume(")"))422 if (consume(")"))
425 return;423 return;
...@@ -434,46 +432,46 @@ void ScriptParser::readPhdrs() {...@@ -434,46 +432,46 @@ void ScriptParser::readPhdrs() {
434 expect("{");432 expect("{");
435433
436 while (!errorCount() && !consume("}")) {434 while (!errorCount() && !consume("}")) {
437 PhdrsCommand Cmd;435 PhdrsCommand cmd;
438 Cmd.Name = next();436 cmd.name = next();
439 Cmd.Type = readPhdrType();437 cmd.type = readPhdrType();
440438
441 while (!errorCount() && !consume(";")) {439 while (!errorCount() && !consume(";")) {
442 if (consume("FILEHDR"))440 if (consume("FILEHDR"))
443 Cmd.HasFilehdr = true;441 cmd.hasFilehdr = true;
444 else if (consume("PHDRS"))442 else if (consume("PHDRS"))
445 Cmd.HasPhdrs = true;443 cmd.hasPhdrs = true;
446 else if (consume("AT"))444 else if (consume("AT"))
447 Cmd.LMAExpr = readParenExpr();445 cmd.lmaExpr = readParenExpr();
448 else if (consume("FLAGS"))446 else if (consume("FLAGS"))
449 Cmd.Flags = readParenExpr()().getValue();447 cmd.flags = readParenExpr()().getValue();
450 else448 else
451 setError("unexpected header attribute: " + next());449 setError("unexpected header attribute: " + next());
452 }450 }
453451
454 Script->PhdrsCommands.push_back(Cmd);452 script->phdrsCommands.push_back(cmd);
455 }453 }
456}454}
457455
458void ScriptParser::readRegionAlias() {456void ScriptParser::readRegionAlias() {
459 expect("(");457 expect("(");
460 StringRef Alias = unquote(next());458 StringRef alias = unquote(next());
461 expect(",");459 expect(",");
462 StringRef Name = next();460 StringRef name = next();
463 expect(")");461 expect(")");
464462
465 if (Script->MemoryRegions.count(Alias))463 if (script->memoryRegions.count(alias))
466 setError("redefinition of memory region '" + Alias + "'");464 setError("redefinition of memory region '" + alias + "'");
467 if (!Script->MemoryRegions.count(Name))465 if (!script->memoryRegions.count(name))
468 setError("memory region '" + Name + "' is not defined");466 setError("memory region '" + name + "' is not defined");
469 Script->MemoryRegions.insert({Alias, Script->MemoryRegions[Name]});467 script->memoryRegions.insert({alias, script->memoryRegions[name]});
470}468}
471469
472void ScriptParser::readSearchDir() {470void ScriptParser::readSearchDir() {
473 expect("(");471 expect("(");
474 StringRef Tok = next();472 StringRef tok = next();
475 if (!Config->Nostdlib)473 if (!config->nostdlib)
476 Config->SearchPaths.push_back(unquote(Tok));474 config->searchPaths.push_back(unquote(tok));
477 expect(")");475 expect(")");
478}476}
479477
...@@ -485,83 +483,83 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() {...@@ -485,83 +483,83 @@ std::vector<BaseCommand *> ScriptParser::readOverlay() {
485 // VA and LMA expressions are optional, though for simplicity of483 // VA and LMA expressions are optional, though for simplicity of
486 // implementation we assume they are not. That is what OVERLAY was designed484 // implementation we assume they are not. That is what OVERLAY was designed
487 // for first of all: to allow sections with overlapping VAs at different LMAs.485 // for first of all: to allow sections with overlapping VAs at different LMAs.
488 Expr AddrExpr = readExpr();486 Expr addrExpr = readExpr();
489 expect(":");487 expect(":");
490 expect("AT");488 expect("AT");
491 Expr LMAExpr = readParenExpr();489 Expr lmaExpr = readParenExpr();
492 expect("{");490 expect("{");
493491
494 std::vector<BaseCommand *> V;492 std::vector<BaseCommand *> v;
495 OutputSection *Prev = nullptr;493 OutputSection *prev = nullptr;
496 while (!errorCount() && !consume("}")) {494 while (!errorCount() && !consume("}")) {
497 // VA is the same for all sections. The LMAs are consecutive in memory495 // VA is the same for all sections. The LMAs are consecutive in memory
498 // starting from the base load address specified.496 // starting from the base load address specified.
499 OutputSection *OS = readOverlaySectionDescription();497 OutputSection *os = readOverlaySectionDescription();
500 OS->AddrExpr = AddrExpr;498 os->addrExpr = addrExpr;
501 if (Prev)499 if (prev)
502 OS->LMAExpr = [=] { return Prev->getLMA() + Prev->Size; };500 os->lmaExpr = [=] { return prev->getLMA() + prev->size; };
503 else501 else
504 OS->LMAExpr = LMAExpr;502 os->lmaExpr = lmaExpr;
505 V.push_back(OS);503 v.push_back(os);
506 Prev = OS;504 prev = os;
507 }505 }
508506
509 // According to the specification, at the end of the overlay, the location507 // According to the specification, at the end of the overlay, the location
510 // counter should be equal to the overlay base address plus size of the508 // counter should be equal to the overlay base address plus size of the
511 // largest section seen in the overlay.509 // largest section seen in the overlay.
512 // Here we want to create the Dot assignment command to achieve that.510 // Here we want to create the Dot assignment command to achieve that.
513 Expr MoveDot = [=] {511 Expr moveDot = [=] {
514 uint64_t Max = 0;512 uint64_t max = 0;
515 for (BaseCommand *Cmd : V)513 for (BaseCommand *cmd : v)
516 Max = std::max(Max, cast<OutputSection>(Cmd)->Size);514 max = std::max(max, cast<OutputSection>(cmd)->size);
517 return AddrExpr().getValue() + Max;515 return addrExpr().getValue() + max;
518 };516 };
519 V.push_back(make<SymbolAssignment>(".", MoveDot, getCurrentLocation()));517 v.push_back(make<SymbolAssignment>(".", moveDot, getCurrentLocation()));
520 return V;518 return v;
521}519}
522520
523void ScriptParser::readSections() {521void ScriptParser::readSections() {
524 Script->HasSectionsCommand = true;522 script->hasSectionsCommand = true;
525523
526 // -no-rosegment is used to avoid placing read only non-executable sections in524 // -no-rosegment is used to avoid placing read only non-executable sections in
527 // their own segment. We do the same if SECTIONS command is present in linker525 // their own segment. We do the same if SECTIONS command is present in linker
528 // script. See comment for computeFlags().526 // script. See comment for computeFlags().
529 Config->SingleRoRx = true;527 config->singleRoRx = true;
530528
531 expect("{");529 expect("{");
532 std::vector<BaseCommand *> V;530 std::vector<BaseCommand *> v;
533 while (!errorCount() && !consume("}")) {531 while (!errorCount() && !consume("}")) {
534 StringRef Tok = next();532 StringRef tok = next();
535 if (Tok == "OVERLAY") {533 if (tok == "OVERLAY") {
536 for (BaseCommand *Cmd : readOverlay())534 for (BaseCommand *cmd : readOverlay())
537 V.push_back(Cmd);535 v.push_back(cmd);
538 continue;536 continue;
539 } else if (Tok == "INCLUDE") {537 } else if (tok == "INCLUDE") {
540 readInclude();538 readInclude();
541 continue;539 continue;
542 }540 }
543541
544 if (BaseCommand *Cmd = readAssignment(Tok))542 if (BaseCommand *cmd = readAssignment(tok))
545 V.push_back(Cmd);543 v.push_back(cmd);
546 else544 else
547 V.push_back(readOutputSectionDescription(Tok));545 v.push_back(readOutputSectionDescription(tok));
548 }546 }
549547
550 if (!atEOF() && consume("INSERT")) {548 if (!atEOF() && consume("INSERT")) {
551 std::vector<BaseCommand *> *Dest = nullptr;549 std::vector<BaseCommand *> *dest = nullptr;
552 if (consume("AFTER"))550 if (consume("AFTER"))
553 Dest = &Script->InsertAfterCommands[next()];551 dest = &script->insertAfterCommands[next()];
554 else if (consume("BEFORE"))552 else if (consume("BEFORE"))
555 Dest = &Script->InsertBeforeCommands[next()];553 dest = &script->insertBeforeCommands[next()];
556 else554 else
557 setError("expected AFTER/BEFORE, but got '" + next() + "'");555 setError("expected AFTER/BEFORE, but got '" + next() + "'");
558 if (Dest)556 if (dest)
559 Dest->insert(Dest->end(), V.begin(), V.end());557 dest->insert(dest->end(), v.begin(), v.end());
560 return;558 return;
561 }559 }
562560
563 Script->SectionCommands.insert(Script->SectionCommands.end(), V.begin(),561 script->sectionCommands.insert(script->sectionCommands.end(), v.begin(),
564 V.end());562 v.end());
565}563}
566564
567void ScriptParser::readTarget() {565void ScriptParser::readTarget() {
...@@ -570,19 +568,19 @@ void ScriptParser::readTarget() {...@@ -570,19 +568,19 @@ void ScriptParser::readTarget() {
570 // for --format. We recognize only /^elf/ and "binary" in the linker568 // for --format. We recognize only /^elf/ and "binary" in the linker
571 // script as well.569 // script as well.
572 expect("(");570 expect("(");
573 StringRef Tok = next();571 StringRef tok = next();
574 expect(")");572 expect(")");
575573
576 if (Tok.startswith("elf"))574 if (tok.startswith("elf"))
577 Config->FormatBinary = false;575 config->formatBinary = false;
578 else if (Tok == "binary")576 else if (tok == "binary")
579 Config->FormatBinary = true;577 config->formatBinary = true;
580 else578 else
581 setError("unknown target: " + Tok);579 setError("unknown target: " + tok);
582}580}
583581
584static int precedence(StringRef Op) {582static int precedence(StringRef op) {
585 return StringSwitch<int>(Op)583 return StringSwitch<int>(op)
586 .Cases("*", "/", "%", 8)584 .Cases("*", "/", "%", 8)
587 .Cases("+", "-", 7)585 .Cases("+", "-", 7)
588 .Cases("<<", ">>", 6)586 .Cases("<<", ">>", 6)
...@@ -595,10 +593,10 @@ static int precedence(StringRef Op) {...@@ -595,10 +593,10 @@ static int precedence(StringRef Op) {
595}593}
596594
597StringMatcher ScriptParser::readFilePatterns() {595StringMatcher ScriptParser::readFilePatterns() {
598 std::vector<StringRef> V;596 std::vector<StringRef> v;
599 while (!errorCount() && !consume(")"))597 while (!errorCount() && !consume(")"))
600 V.push_back(next());598 v.push_back(next());
601 return StringMatcher(V);599 return StringMatcher(v);
602}600}
603601
604SortSectionPolicy ScriptParser::readSortKind() {602SortSectionPolicy ScriptParser::readSortKind() {
...@@ -627,24 +625,24 @@ SortSectionPolicy ScriptParser::readSortKind() {...@@ -627,24 +625,24 @@ SortSectionPolicy ScriptParser::readSortKind() {
627// The semantics of that is section .foo in any file, section .bar in625// The semantics of that is section .foo in any file, section .bar in
628// any file but a.o, and section .baz in any file but b.o.626// any file but a.o, and section .baz in any file but b.o.
629std::vector<SectionPattern> ScriptParser::readInputSectionsList() {627std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
630 std::vector<SectionPattern> Ret;628 std::vector<SectionPattern> ret;
631 while (!errorCount() && peek() != ")") {629 while (!errorCount() && peek() != ")") {
632 StringMatcher ExcludeFilePat;630 StringMatcher excludeFilePat;
633 if (consume("EXCLUDE_FILE")) {631 if (consume("EXCLUDE_FILE")) {
634 expect("(");632 expect("(");
635 ExcludeFilePat = readFilePatterns();633 excludeFilePat = readFilePatterns();
636 }634 }
637635
638 std::vector<StringRef> V;636 std::vector<StringRef> v;
639 while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE")637 while (!errorCount() && peek() != ")" && peek() != "EXCLUDE_FILE")
640 V.push_back(next());638 v.push_back(unquote(next()));
641639
642 if (!V.empty())640 if (!v.empty())
643 Ret.push_back({std::move(ExcludeFilePat), StringMatcher(V)});641 ret.push_back({std::move(excludeFilePat), StringMatcher(v)});
644 else642 else
645 setError("section pattern is expected");643 setError("section pattern is expected");
646 }644 }
647 return Ret;645 return ret;
648}646}
649647
650// Reads contents of "SECTIONS" directive. That directive contains a648// Reads contents of "SECTIONS" directive. That directive contains a
...@@ -659,52 +657,52 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() {...@@ -659,52 +657,52 @@ std::vector<SectionPattern> ScriptParser::readInputSectionsList() {
659//657//
660// <section-list> is parsed by readInputSectionsList().658// <section-list> is parsed by readInputSectionsList().
661InputSectionDescription *659InputSectionDescription *
662ScriptParser::readInputSectionRules(StringRef FilePattern) {660ScriptParser::readInputSectionRules(StringRef filePattern) {
663 auto *Cmd = make<InputSectionDescription>(FilePattern);661 auto *cmd = make<InputSectionDescription>(filePattern);
664 expect("(");662 expect("(");
665663
666 while (!errorCount() && !consume(")")) {664 while (!errorCount() && !consume(")")) {
667 SortSectionPolicy Outer = readSortKind();665 SortSectionPolicy outer = readSortKind();
668 SortSectionPolicy Inner = SortSectionPolicy::Default;666 SortSectionPolicy inner = SortSectionPolicy::Default;
669 std::vector<SectionPattern> V;667 std::vector<SectionPattern> v;
670 if (Outer != SortSectionPolicy::Default) {668 if (outer != SortSectionPolicy::Default) {
671 expect("(");669 expect("(");
672 Inner = readSortKind();670 inner = readSortKind();
673 if (Inner != SortSectionPolicy::Default) {671 if (inner != SortSectionPolicy::Default) {
674 expect("(");672 expect("(");
675 V = readInputSectionsList();673 v = readInputSectionsList();
676 expect(")");674 expect(")");
677 } else {675 } else {
678 V = readInputSectionsList();676 v = readInputSectionsList();
679 }677 }
680 expect(")");678 expect(")");
681 } else {679 } else {
682 V = readInputSectionsList();680 v = readInputSectionsList();
683 }681 }
684682
685 for (SectionPattern &Pat : V) {683 for (SectionPattern &pat : v) {
686 Pat.SortInner = Inner;684 pat.sortInner = inner;
687 Pat.SortOuter = Outer;685 pat.sortOuter = outer;
688 }686 }
689687
690 std::move(V.begin(), V.end(), std::back_inserter(Cmd->SectionPatterns));688 std::move(v.begin(), v.end(), std::back_inserter(cmd->sectionPatterns));
691 }689 }
692 return Cmd;690 return cmd;
693}691}
694692
695InputSectionDescription *693InputSectionDescription *
696ScriptParser::readInputSectionDescription(StringRef Tok) {694ScriptParser::readInputSectionDescription(StringRef tok) {
697 // Input section wildcard can be surrounded by KEEP.695 // Input section wildcard can be surrounded by KEEP.
698 // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep696 // https://sourceware.org/binutils/docs/ld/Input-Section-Keep.html#Input-Section-Keep
699 if (Tok == "KEEP") {697 if (tok == "KEEP") {
700 expect("(");698 expect("(");
701 StringRef FilePattern = next();699 StringRef filePattern = next();
702 InputSectionDescription *Cmd = readInputSectionRules(FilePattern);700 InputSectionDescription *cmd = readInputSectionRules(filePattern);
703 expect(")");701 expect(")");
704 Script->KeptSections.push_back(Cmd);702 script->keptSections.push_back(cmd);
705 return Cmd;703 return cmd;
706 }704 }
707 return readInputSectionRules(Tok);705 return readInputSectionRules(tok);
708}706}
709707
710void ScriptParser::readSort() {708void ScriptParser::readSort() {
...@@ -715,44 +713,33 @@ void ScriptParser::readSort() {...@@ -715,44 +713,33 @@ void ScriptParser::readSort() {
715713
716Expr ScriptParser::readAssert() {714Expr ScriptParser::readAssert() {
717 expect("(");715 expect("(");
718 Expr E = readExpr();716 Expr e = readExpr();
719 expect(",");717 expect(",");
720 StringRef Msg = unquote(next());718 StringRef msg = unquote(next());
721 expect(")");719 expect(")");
722720
723 return [=] {721 return [=] {
724 if (!E().getValue())722 if (!e().getValue())
725 error(Msg);723 error(msg);
726 return Script->getDot();724 return script->getDot();
727 };725 };
728}726}
729727
730// Reads a FILL(expr) command. We handle the FILL command as an
731// alias for =fillexp section attribute, which is different from
732// what GNU linkers do.
733// https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
734std::array<uint8_t, 4> ScriptParser::readFill() {
735 expect("(");
736 std::array<uint8_t, 4> V = parseFill(next());
737 expect(")");
738 return V;
739}
740
741// Tries to read the special directive for an output section definition which728// Tries to read the special directive for an output section definition which
742// can be one of following: "(NOLOAD)", "(COPY)", "(INFO)" or "(OVERLAY)".729// can be one of following: "(NOLOAD)", "(COPY)", "(INFO)" or "(OVERLAY)".
743// Tok1 and Tok2 are next 2 tokens peeked. See comment for readSectionAddressType below.730// Tok1 and Tok2 are next 2 tokens peeked. See comment for readSectionAddressType below.
744bool ScriptParser::readSectionDirective(OutputSection *Cmd, StringRef Tok1, StringRef Tok2) {731bool ScriptParser::readSectionDirective(OutputSection *cmd, StringRef tok1, StringRef tok2) {
745 if (Tok1 != "(")732 if (tok1 != "(")
746 return false;733 return false;
747 if (Tok2 != "NOLOAD" && Tok2 != "COPY" && Tok2 != "INFO" && Tok2 != "OVERLAY")734 if (tok2 != "NOLOAD" && tok2 != "COPY" && tok2 != "INFO" && tok2 != "OVERLAY")
748 return false;735 return false;
749736
750 expect("(");737 expect("(");
751 if (consume("NOLOAD")) {738 if (consume("NOLOAD")) {
752 Cmd->Noload = true;739 cmd->noload = true;
753 } else {740 } else {
754 skip(); // This is "COPY", "INFO" or "OVERLAY".741 skip(); // This is "COPY", "INFO" or "OVERLAY".
755 Cmd->NonAlloc = true;742 cmd->nonAlloc = true;
756 }743 }
757 expect(")");744 expect(")");
758 return true;745 return true;
...@@ -769,178 +756,186 @@ bool ScriptParser::readSectionDirective(OutputSection *Cmd, StringRef Tok1, Stri...@@ -769,178 +756,186 @@ bool ScriptParser::readSectionDirective(OutputSection *Cmd, StringRef Tok1, Stri
769//756//
770// https://sourceware.org/binutils/docs/ld/Output-Section-Address.html757// https://sourceware.org/binutils/docs/ld/Output-Section-Address.html
771// https://sourceware.org/binutils/docs/ld/Output-Section-Type.html758// https://sourceware.org/binutils/docs/ld/Output-Section-Type.html
772void ScriptParser::readSectionAddressType(OutputSection *Cmd) {759void ScriptParser::readSectionAddressType(OutputSection *cmd) {
773 if (readSectionDirective(Cmd, peek(), peek2()))760 if (readSectionDirective(cmd, peek(), peek2()))
774 return;761 return;
775762
776 Cmd->AddrExpr = readExpr();763 cmd->addrExpr = readExpr();
777 if (peek() == "(" && !readSectionDirective(Cmd, "(", peek2()))764 if (peek() == "(" && !readSectionDirective(cmd, "(", peek2()))
778 setError("unknown section directive: " + peek2());765 setError("unknown section directive: " + peek2());
779}766}
780767
781static Expr checkAlignment(Expr E, std::string &Loc) {768static Expr checkAlignment(Expr e, std::string &loc) {
782 return [=] {769 return [=] {
783 uint64_t Alignment = std::max((uint64_t)1, E().getValue());770 uint64_t alignment = std::max((uint64_t)1, e().getValue());
784 if (!isPowerOf2_64(Alignment)) {771 if (!isPowerOf2_64(alignment)) {
785 error(Loc + ": alignment must be power of 2");772 error(loc + ": alignment must be power of 2");
786 return (uint64_t)1; // Return a dummy value.773 return (uint64_t)1; // Return a dummy value.
787 }774 }
788 return Alignment;775 return alignment;
789 };776 };
790}777}
791778
792OutputSection *ScriptParser::readOverlaySectionDescription() {779OutputSection *ScriptParser::readOverlaySectionDescription() {
793 OutputSection *Cmd =780 OutputSection *cmd =
794 Script->createOutputSection(next(), getCurrentLocation());781 script->createOutputSection(next(), getCurrentLocation());
795 Cmd->InOverlay = true;782 cmd->inOverlay = true;
796 expect("{");783 expect("{");
797 while (!errorCount() && !consume("}"))784 while (!errorCount() && !consume("}"))
798 Cmd->SectionCommands.push_back(readInputSectionRules(next()));785 cmd->sectionCommands.push_back(readInputSectionRules(next()));
799 Cmd->Phdrs = readOutputSectionPhdrs();786 cmd->phdrs = readOutputSectionPhdrs();
800 return Cmd;787 return cmd;
801}788}
802789
803OutputSection *ScriptParser::readOutputSectionDescription(StringRef OutSec) {790OutputSection *ScriptParser::readOutputSectionDescription(StringRef outSec) {
804 OutputSection *Cmd =791 OutputSection *cmd =
805 Script->createOutputSection(OutSec, getCurrentLocation());792 script->createOutputSection(outSec, getCurrentLocation());
806793
807 size_t SymbolsReferenced = Script->ReferencedSymbols.size();794 size_t symbolsReferenced = script->referencedSymbols.size();
808795
809 if (peek() != ":")796 if (peek() != ":")
810 readSectionAddressType(Cmd);797 readSectionAddressType(cmd);
811 expect(":");798 expect(":");
812799
813 std::string Location = getCurrentLocation();800 std::string location = getCurrentLocation();
814 if (consume("AT"))801 if (consume("AT"))
815 Cmd->LMAExpr = readParenExpr();802 cmd->lmaExpr = readParenExpr();
816 if (consume("ALIGN"))803 if (consume("ALIGN"))
817 Cmd->AlignExpr = checkAlignment(readParenExpr(), Location);804 cmd->alignExpr = checkAlignment(readParenExpr(), location);
818 if (consume("SUBALIGN"))805 if (consume("SUBALIGN"))
819 Cmd->SubalignExpr = checkAlignment(readParenExpr(), Location);806 cmd->subalignExpr = checkAlignment(readParenExpr(), location);
820807
821 // Parse constraints.808 // Parse constraints.
822 if (consume("ONLY_IF_RO"))809 if (consume("ONLY_IF_RO"))
823 Cmd->Constraint = ConstraintKind::ReadOnly;810 cmd->constraint = ConstraintKind::ReadOnly;
824 if (consume("ONLY_IF_RW"))811 if (consume("ONLY_IF_RW"))
825 Cmd->Constraint = ConstraintKind::ReadWrite;812 cmd->constraint = ConstraintKind::ReadWrite;
826 expect("{");813 expect("{");
827814
828 while (!errorCount() && !consume("}")) {815 while (!errorCount() && !consume("}")) {
829 StringRef Tok = next();816 StringRef tok = next();
830 if (Tok == ";") {817 if (tok == ";") {
831 // Empty commands are allowed. Do nothing here.818 // Empty commands are allowed. Do nothing here.
832 } else if (SymbolAssignment *Assign = readAssignment(Tok)) {819 } else if (SymbolAssignment *assign = readAssignment(tok)) {
833 Cmd->SectionCommands.push_back(Assign);820 cmd->sectionCommands.push_back(assign);
834 } else if (ByteCommand *Data = readByteCommand(Tok)) {821 } else if (ByteCommand *data = readByteCommand(tok)) {
835 Cmd->SectionCommands.push_back(Data);822 cmd->sectionCommands.push_back(data);
836 } else if (Tok == "CONSTRUCTORS") {823 } else if (tok == "CONSTRUCTORS") {
837 // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors824 // CONSTRUCTORS is a keyword to make the linker recognize C++ ctors/dtors
838 // by name. This is for very old file formats such as ECOFF/XCOFF.825 // by name. This is for very old file formats such as ECOFF/XCOFF.
839 // For ELF, we should ignore.826 // For ELF, we should ignore.
840 } else if (Tok == "FILL") {827 } else if (tok == "FILL") {
841 Cmd->Filler = readFill();828 // We handle the FILL command as an alias for =fillexp section attribute,
842 } else if (Tok == "SORT") {829 // which is different from what GNU linkers do.
830 // https://sourceware.org/binutils/docs/ld/Output-Section-Data.html
831 expect("(");
832 cmd->filler = readFill();
833 expect(")");
834 } else if (tok == "SORT") {
843 readSort();835 readSort();
844 } else if (Tok == "INCLUDE") {836 } else if (tok == "INCLUDE") {
845 readInclude();837 readInclude();
846 } else if (peek() == "(") {838 } else if (peek() == "(") {
847 Cmd->SectionCommands.push_back(readInputSectionDescription(Tok));839 cmd->sectionCommands.push_back(readInputSectionDescription(tok));
848 } else {840 } else {
849 // We have a file name and no input sections description. It is not a841 // We have a file name and no input sections description. It is not a
850 // commonly used syntax, but still acceptable. In that case, all sections842 // commonly used syntax, but still acceptable. In that case, all sections
851 // from the file will be included.843 // from the file will be included.
852 auto *ISD = make<InputSectionDescription>(Tok);844 auto *isd = make<InputSectionDescription>(tok);
853 ISD->SectionPatterns.push_back({{}, StringMatcher({"*"})});845 isd->sectionPatterns.push_back({{}, StringMatcher({"*"})});
854 Cmd->SectionCommands.push_back(ISD);846 cmd->sectionCommands.push_back(isd);
855 }847 }
856 }848 }
857849
858 if (consume(">"))850 if (consume(">"))
859 Cmd->MemoryRegionName = next();851 cmd->memoryRegionName = next();
860852
861 if (consume("AT")) {853 if (consume("AT")) {
862 expect(">");854 expect(">");
863 Cmd->LMARegionName = next();855 cmd->lmaRegionName = next();
864 }856 }
865857
866 if (Cmd->LMAExpr && !Cmd->LMARegionName.empty())858 if (cmd->lmaExpr && !cmd->lmaRegionName.empty())
867 error("section can't have both LMA and a load region");859 error("section can't have both LMA and a load region");
868860
869 Cmd->Phdrs = readOutputSectionPhdrs();861 cmd->phdrs = readOutputSectionPhdrs();
870862
871 if (consume("="))863 if (peek() == "=" || peek().startswith("=")) {
872 Cmd->Filler = parseFill(next());864 inExpr = true;
873 else if (peek().startswith("="))865 consume("=");
874 Cmd->Filler = parseFill(next().drop_front());866 cmd->filler = readFill();
867 inExpr = false;
868 }
875869
876 // Consume optional comma following output section command.870 // Consume optional comma following output section command.
877 consume(",");871 consume(",");
878872
879 if (Script->ReferencedSymbols.size() > SymbolsReferenced)873 if (script->referencedSymbols.size() > symbolsReferenced)
880 Cmd->ExpressionsUseSymbols = true;874 cmd->expressionsUseSymbols = true;
881 return Cmd;875 return cmd;
882}876}
883877
884// Parses a given string as a octal/decimal/hexadecimal number and878// Reads a `=<fillexp>` expression and returns its value as a big-endian number.
885// returns it as a big-endian number. Used for `=<fillexp>`.
886// https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html879// https://sourceware.org/binutils/docs/ld/Output-Section-Fill.html
880// We do not support using symbols in such expressions.
887//881//
888// When reading a hexstring, ld.bfd handles it as a blob of arbitrary882// When reading a hexstring, ld.bfd handles it as a blob of arbitrary
889// size, while ld.gold always handles it as a 32-bit big-endian number.883// size, while ld.gold always handles it as a 32-bit big-endian number.
890// We are compatible with ld.gold because it's easier to implement.884// We are compatible with ld.gold because it's easier to implement.
891std::array<uint8_t, 4> ScriptParser::parseFill(StringRef Tok) {885std::array<uint8_t, 4> ScriptParser::readFill() {
892 uint32_t V = 0;886 uint64_t value = readExpr()().val;
893 if (!to_integer(Tok, V))887 if (value > UINT32_MAX)
894 setError("invalid filler expression: " + Tok);888 setError("filler expression result does not fit 32-bit: 0x" +
889 Twine::utohexstr(value));
895890
896 std::array<uint8_t, 4> Buf;891 std::array<uint8_t, 4> buf;
897 write32be(Buf.data(), V);892 write32be(buf.data(), (uint32_t)value);
898 return Buf;893 return buf;
899}894}
900895
901SymbolAssignment *ScriptParser::readProvideHidden(bool Provide, bool Hidden) {896SymbolAssignment *ScriptParser::readProvideHidden(bool provide, bool hidden) {
902 expect("(");897 expect("(");
903 SymbolAssignment *Cmd = readSymbolAssignment(next());898 SymbolAssignment *cmd = readSymbolAssignment(next());
904 Cmd->Provide = Provide;899 cmd->provide = provide;
905 Cmd->Hidden = Hidden;900 cmd->hidden = hidden;
906 expect(")");901 expect(")");
907 return Cmd;902 return cmd;
908}903}
909904
910SymbolAssignment *ScriptParser::readAssignment(StringRef Tok) {905SymbolAssignment *ScriptParser::readAssignment(StringRef tok) {
911 // Assert expression returns Dot, so this is equal to ".=."906 // Assert expression returns Dot, so this is equal to ".=."
912 if (Tok == "ASSERT")907 if (tok == "ASSERT")
913 return make<SymbolAssignment>(".", readAssert(), getCurrentLocation());908 return make<SymbolAssignment>(".", readAssert(), getCurrentLocation());
914909
915 size_t OldPos = Pos;910 size_t oldPos = pos;
916 SymbolAssignment *Cmd = nullptr;911 SymbolAssignment *cmd = nullptr;
917 if (peek() == "=" || peek() == "+=")912 if (peek() == "=" || peek() == "+=")
918 Cmd = readSymbolAssignment(Tok);913 cmd = readSymbolAssignment(tok);
919 else if (Tok == "PROVIDE")914 else if (tok == "PROVIDE")
920 Cmd = readProvideHidden(true, false);915 cmd = readProvideHidden(true, false);
921 else if (Tok == "HIDDEN")916 else if (tok == "HIDDEN")
922 Cmd = readProvideHidden(false, true);917 cmd = readProvideHidden(false, true);
923 else if (Tok == "PROVIDE_HIDDEN")918 else if (tok == "PROVIDE_HIDDEN")
924 Cmd = readProvideHidden(true, true);919 cmd = readProvideHidden(true, true);
925920
926 if (Cmd) {921 if (cmd) {
927 Cmd->CommandString =922 cmd->commandString =
928 Tok.str() + " " +923 tok.str() + " " +
929 llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " ");924 llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
930 expect(";");925 expect(";");
931 }926 }
932 return Cmd;927 return cmd;
933}928}
934929
935SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) {930SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef name) {
936 StringRef Op = next();931 StringRef op = next();
937 assert(Op == "=" || Op == "+=");932 assert(op == "=" || op == "+=");
938 Expr E = readExpr();933 Expr e = readExpr();
939 if (Op == "+=") {934 if (op == "+=") {
940 std::string Loc = getCurrentLocation();935 std::string loc = getCurrentLocation();
941 E = [=] { return add(Script->getSymbolValue(Name, Loc), E()); };936 e = [=] { return add(script->getSymbolValue(name, loc), e()); };
942 }937 }
943 return make<SymbolAssignment>(Name, E, getCurrentLocation());938 return make<SymbolAssignment>(name, e, getCurrentLocation());
944}939}
945940
946// This is an operator-precedence parser to parse a linker941// This is an operator-precedence parser to parse a linker
...@@ -948,178 +943,178 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) {...@@ -948,178 +943,178 @@ SymbolAssignment *ScriptParser::readSymbolAssignment(StringRef Name) {
948Expr ScriptParser::readExpr() {943Expr ScriptParser::readExpr() {
949 // Our lexer is context-aware. Set the in-expression bit so that944 // Our lexer is context-aware. Set the in-expression bit so that
950 // they apply different tokenization rules.945 // they apply different tokenization rules.
951 bool Orig = InExpr;946 bool orig = inExpr;
952 InExpr = true;947 inExpr = true;
953 Expr E = readExpr1(readPrimary(), 0);948 Expr e = readExpr1(readPrimary(), 0);
954 InExpr = Orig;949 inExpr = orig;
955 return E;950 return e;
956}951}
957952
958Expr ScriptParser::combine(StringRef Op, Expr L, Expr R) {953Expr ScriptParser::combine(StringRef op, Expr l, Expr r) {
959 if (Op == "+")954 if (op == "+")
960 return [=] { return add(L(), R()); };955 return [=] { return add(l(), r()); };
961 if (Op == "-")956 if (op == "-")
962 return [=] { return sub(L(), R()); };957 return [=] { return sub(l(), r()); };
963 if (Op == "*")958 if (op == "*")
964 return [=] { return L().getValue() * R().getValue(); };959 return [=] { return l().getValue() * r().getValue(); };
965 if (Op == "/") {960 if (op == "/") {
966 std::string Loc = getCurrentLocation();961 std::string loc = getCurrentLocation();
967 return [=]() -> uint64_t {962 return [=]() -> uint64_t {
968 if (uint64_t RV = R().getValue())963 if (uint64_t rv = r().getValue())
969 return L().getValue() / RV;964 return l().getValue() / rv;
970 error(Loc + ": division by zero");965 error(loc + ": division by zero");
971 return 0;966 return 0;
972 };967 };
973 }968 }
974 if (Op == "%") {969 if (op == "%") {
975 std::string Loc = getCurrentLocation();970 std::string loc = getCurrentLocation();
976 return [=]() -> uint64_t {971 return [=]() -> uint64_t {
977 if (uint64_t RV = R().getValue())972 if (uint64_t rv = r().getValue())
978 return L().getValue() % RV;973 return l().getValue() % rv;
979 error(Loc + ": modulo by zero");974 error(loc + ": modulo by zero");
980 return 0;975 return 0;
981 };976 };
982 }977 }
983 if (Op == "<<")978 if (op == "<<")
984 return [=] { return L().getValue() << R().getValue(); };979 return [=] { return l().getValue() << r().getValue(); };
985 if (Op == ">>")980 if (op == ">>")
986 return [=] { return L().getValue() >> R().getValue(); };981 return [=] { return l().getValue() >> r().getValue(); };
987 if (Op == "<")982 if (op == "<")
988 return [=] { return L().getValue() < R().getValue(); };983 return [=] { return l().getValue() < r().getValue(); };
989 if (Op == ">")984 if (op == ">")
990 return [=] { return L().getValue() > R().getValue(); };985 return [=] { return l().getValue() > r().getValue(); };
991 if (Op == ">=")986 if (op == ">=")
992 return [=] { return L().getValue() >= R().getValue(); };987 return [=] { return l().getValue() >= r().getValue(); };
993 if (Op == "<=")988 if (op == "<=")
994 return [=] { return L().getValue() <= R().getValue(); };989 return [=] { return l().getValue() <= r().getValue(); };
995 if (Op == "==")990 if (op == "==")
996 return [=] { return L().getValue() == R().getValue(); };991 return [=] { return l().getValue() == r().getValue(); };
997 if (Op == "!=")992 if (op == "!=")
998 return [=] { return L().getValue() != R().getValue(); };993 return [=] { return l().getValue() != r().getValue(); };
999 if (Op == "||")994 if (op == "||")
1000 return [=] { return L().getValue() || R().getValue(); };995 return [=] { return l().getValue() || r().getValue(); };
1001 if (Op == "&&")996 if (op == "&&")
1002 return [=] { return L().getValue() && R().getValue(); };997 return [=] { return l().getValue() && r().getValue(); };
1003 if (Op == "&")998 if (op == "&")
1004 return [=] { return bitAnd(L(), R()); };999 return [=] { return bitAnd(l(), r()); };
1005 if (Op == "|")1000 if (op == "|")
1006 return [=] { return bitOr(L(), R()); };1001 return [=] { return bitOr(l(), r()); };
1007 llvm_unreachable("invalid operator");1002 llvm_unreachable("invalid operator");
1008}1003}
10091004
1010// This is a part of the operator-precedence parser. This function1005// This is a part of the operator-precedence parser. This function
1011// assumes that the remaining token stream starts with an operator.1006// assumes that the remaining token stream starts with an operator.
1012Expr ScriptParser::readExpr1(Expr Lhs, int MinPrec) {1007Expr ScriptParser::readExpr1(Expr lhs, int minPrec) {
1013 while (!atEOF() && !errorCount()) {1008 while (!atEOF() && !errorCount()) {
1014 // Read an operator and an expression.1009 // Read an operator and an expression.
1015 if (consume("?"))1010 if (consume("?"))
1016 return readTernary(Lhs);1011 return readTernary(lhs);
1017 StringRef Op1 = peek();1012 StringRef op1 = peek();
1018 if (precedence(Op1) < MinPrec)1013 if (precedence(op1) < minPrec)
1019 break;1014 break;
1020 skip();1015 skip();
1021 Expr Rhs = readPrimary();1016 Expr rhs = readPrimary();
10221017
1023 // Evaluate the remaining part of the expression first if the1018 // Evaluate the remaining part of the expression first if the
1024 // next operator has greater precedence than the previous one.1019 // next operator has greater precedence than the previous one.
1025 // For example, if we have read "+" and "3", and if the next1020 // For example, if we have read "+" and "3", and if the next
1026 // operator is "*", then we'll evaluate 3 * ... part first.1021 // operator is "*", then we'll evaluate 3 * ... part first.
1027 while (!atEOF()) {1022 while (!atEOF()) {
1028 StringRef Op2 = peek();1023 StringRef op2 = peek();
1029 if (precedence(Op2) <= precedence(Op1))1024 if (precedence(op2) <= precedence(op1))
1030 break;1025 break;
1031 Rhs = readExpr1(Rhs, precedence(Op2));1026 rhs = readExpr1(rhs, precedence(op2));
1032 }1027 }
10331028
1034 Lhs = combine(Op1, Lhs, Rhs);1029 lhs = combine(op1, lhs, rhs);
1035 }1030 }
1036 return Lhs;1031 return lhs;
1037}1032}
10381033
1039Expr ScriptParser::getPageSize() {1034Expr ScriptParser::getPageSize() {
1040 std::string Location = getCurrentLocation();1035 std::string location = getCurrentLocation();
1041 return [=]() -> uint64_t {1036 return [=]() -> uint64_t {
1042 if (Target)1037 if (target)
1043 return Target->PageSize;1038 return config->commonPageSize;
1044 error(Location + ": unable to calculate page size");1039 error(location + ": unable to calculate page size");
1045 return 4096; // Return a dummy value.1040 return 4096; // Return a dummy value.
1046 };1041 };
1047}1042}
10481043
1049Expr ScriptParser::readConstant() {1044Expr ScriptParser::readConstant() {
1050 StringRef S = readParenLiteral();1045 StringRef s = readParenLiteral();
1051 if (S == "COMMONPAGESIZE")1046 if (s == "COMMONPAGESIZE")
1052 return getPageSize();1047 return getPageSize();
1053 if (S == "MAXPAGESIZE")1048 if (s == "MAXPAGESIZE")
1054 return [] { return Config->MaxPageSize; };1049 return [] { return config->maxPageSize; };
1055 setError("unknown constant: " + S);1050 setError("unknown constant: " + s);
1056 return [] { return 0; };1051 return [] { return 0; };
1057}1052}
10581053
1059// Parses Tok as an integer. It recognizes hexadecimal (prefixed with1054// Parses Tok as an integer. It recognizes hexadecimal (prefixed with
1060// "0x" or suffixed with "H") and decimal numbers. Decimal numbers may1055// "0x" or suffixed with "H") and decimal numbers. Decimal numbers may
1061// have "K" (Ki) or "M" (Mi) suffixes.1056// have "K" (Ki) or "M" (Mi) suffixes.
1062static Optional<uint64_t> parseInt(StringRef Tok) {1057static Optional<uint64_t> parseInt(StringRef tok) {
1063 // Hexadecimal1058 // Hexadecimal
1064 uint64_t Val;1059 uint64_t val;
1065 if (Tok.startswith_lower("0x")) {1060 if (tok.startswith_lower("0x")) {
1066 if (!to_integer(Tok.substr(2), Val, 16))1061 if (!to_integer(tok.substr(2), val, 16))
1067 return None;1062 return None;
1068 return Val;1063 return val;
1069 }1064 }
1070 if (Tok.endswith_lower("H")) {1065 if (tok.endswith_lower("H")) {
1071 if (!to_integer(Tok.drop_back(), Val, 16))1066 if (!to_integer(tok.drop_back(), val, 16))
1072 return None;1067 return None;
1073 return Val;1068 return val;
1074 }1069 }
10751070
1076 // Decimal1071 // Decimal
1077 if (Tok.endswith_lower("K")) {1072 if (tok.endswith_lower("K")) {
1078 if (!to_integer(Tok.drop_back(), Val, 10))1073 if (!to_integer(tok.drop_back(), val, 10))
1079 return None;1074 return None;
1080 return Val * 1024;1075 return val * 1024;
1081 }1076 }
1082 if (Tok.endswith_lower("M")) {1077 if (tok.endswith_lower("M")) {
1083 if (!to_integer(Tok.drop_back(), Val, 10))1078 if (!to_integer(tok.drop_back(), val, 10))
1084 return None;1079 return None;
1085 return Val * 1024 * 1024;1080 return val * 1024 * 1024;
1086 }1081 }
1087 if (!to_integer(Tok, Val, 10))1082 if (!to_integer(tok, val, 10))
1088 return None;1083 return None;
1089 return Val;1084 return val;
1090}1085}
10911086
1092ByteCommand *ScriptParser::readByteCommand(StringRef Tok) {1087ByteCommand *ScriptParser::readByteCommand(StringRef tok) {
1093 int Size = StringSwitch<int>(Tok)1088 int size = StringSwitch<int>(tok)
1094 .Case("BYTE", 1)1089 .Case("BYTE", 1)
1095 .Case("SHORT", 2)1090 .Case("SHORT", 2)
1096 .Case("LONG", 4)1091 .Case("LONG", 4)
1097 .Case("QUAD", 8)1092 .Case("QUAD", 8)
1098 .Default(-1);1093 .Default(-1);
1099 if (Size == -1)1094 if (size == -1)
1100 return nullptr;1095 return nullptr;
11011096
1102 size_t OldPos = Pos;1097 size_t oldPos = pos;
1103 Expr E = readParenExpr();1098 Expr e = readParenExpr();
1104 std::string CommandString =1099 std::string commandString =
1105 Tok.str() + " " +1100 tok.str() + " " +
1106 llvm::join(Tokens.begin() + OldPos, Tokens.begin() + Pos, " ");1101 llvm::join(tokens.begin() + oldPos, tokens.begin() + pos, " ");
1107 return make<ByteCommand>(E, Size, CommandString);1102 return make<ByteCommand>(e, size, commandString);
1108}1103}
11091104
1110StringRef ScriptParser::readParenLiteral() {1105StringRef ScriptParser::readParenLiteral() {
1111 expect("(");1106 expect("(");
1112 bool Orig = InExpr;1107 bool orig = inExpr;
1113 InExpr = false;1108 inExpr = false;
1114 StringRef Tok = next();1109 StringRef tok = next();
1115 InExpr = Orig;1110 inExpr = orig;
1116 expect(")");1111 expect(")");
1117 return Tok;1112 return tok;
1118}1113}
11191114
1120static void checkIfExists(OutputSection *Cmd, StringRef Location) {1115static void checkIfExists(OutputSection *cmd, StringRef location) {
1121 if (Cmd->Location.empty() && Script->ErrorOnMissingSection)1116 if (cmd->location.empty() && script->errorOnMissingSection)
1122 error(Location + ": undefined section " + Cmd->Name);1117 error(location + ": undefined section " + cmd->name);
1123}1118}
11241119
1125Expr ScriptParser::readPrimary() {1120Expr ScriptParser::readPrimary() {
...@@ -1127,84 +1122,85 @@ Expr ScriptParser::readPrimary() {...@@ -1127,84 +1122,85 @@ Expr ScriptParser::readPrimary() {
1127 return readParenExpr();1122 return readParenExpr();
11281123
1129 if (consume("~")) {1124 if (consume("~")) {
1130 Expr E = readPrimary();1125 Expr e = readPrimary();
1131 return [=] { return ~E().getValue(); };1126 return [=] { return ~e().getValue(); };
1132 }1127 }
1133 if (consume("!")) {1128 if (consume("!")) {
1134 Expr E = readPrimary();1129 Expr e = readPrimary();
1135 return [=] { return !E().getValue(); };1130 return [=] { return !e().getValue(); };
1136 }1131 }
1137 if (consume("-")) {1132 if (consume("-")) {
1138 Expr E = readPrimary();1133 Expr e = readPrimary();
1139 return [=] { return -E().getValue(); };1134 return [=] { return -e().getValue(); };
1140 }1135 }
11411136
1142 StringRef Tok = next();1137 StringRef tok = next();
1143 std::string Location = getCurrentLocation();1138 std::string location = getCurrentLocation();
11441139
1145 // Built-in functions are parsed here.1140 // Built-in functions are parsed here.
1146 // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.1141 // https://sourceware.org/binutils/docs/ld/Builtin-Functions.html.
1147 if (Tok == "ABSOLUTE") {1142 if (tok == "ABSOLUTE") {
1148 Expr Inner = readParenExpr();1143 Expr inner = readParenExpr();
1149 return [=] {1144 return [=] {
1150 ExprValue I = Inner();1145 ExprValue i = inner();
1151 I.ForceAbsolute = true;1146 i.forceAbsolute = true;
1152 return I;1147 return i;
1153 };1148 };
1154 }1149 }
1155 if (Tok == "ADDR") {1150 if (tok == "ADDR") {
1156 StringRef Name = readParenLiteral();1151 StringRef name = readParenLiteral();
1157 OutputSection *Sec = Script->getOrCreateOutputSection(Name);1152 OutputSection *sec = script->getOrCreateOutputSection(name);
1153 sec->usedInExpression = true;
1158 return [=]() -> ExprValue {1154 return [=]() -> ExprValue {
1159 checkIfExists(Sec, Location);1155 checkIfExists(sec, location);
1160 return {Sec, false, 0, Location};1156 return {sec, false, 0, location};
1161 };1157 };
1162 }1158 }
1163 if (Tok == "ALIGN") {1159 if (tok == "ALIGN") {
1164 expect("(");1160 expect("(");
1165 Expr E = readExpr();1161 Expr e = readExpr();
1166 if (consume(")")) {1162 if (consume(")")) {
1167 E = checkAlignment(E, Location);1163 e = checkAlignment(e, location);
1168 return [=] { return alignTo(Script->getDot(), E().getValue()); };1164 return [=] { return alignTo(script->getDot(), e().getValue()); };
1169 }1165 }
1170 expect(",");1166 expect(",");
1171 Expr E2 = checkAlignment(readExpr(), Location);1167 Expr e2 = checkAlignment(readExpr(), location);
1172 expect(")");1168 expect(")");
1173 return [=] {1169 return [=] {
1174 ExprValue V = E();1170 ExprValue v = e();
1175 V.Alignment = E2().getValue();1171 v.alignment = e2().getValue();
1176 return V;1172 return v;
1177 };1173 };
1178 }1174 }
1179 if (Tok == "ALIGNOF") {1175 if (tok == "ALIGNOF") {
1180 StringRef Name = readParenLiteral();1176 StringRef name = readParenLiteral();
1181 OutputSection *Cmd = Script->getOrCreateOutputSection(Name);1177 OutputSection *cmd = script->getOrCreateOutputSection(name);
1182 return [=] {1178 return [=] {
1183 checkIfExists(Cmd, Location);1179 checkIfExists(cmd, location);
1184 return Cmd->Alignment;1180 return cmd->alignment;
1185 };1181 };
1186 }1182 }
1187 if (Tok == "ASSERT")1183 if (tok == "ASSERT")
1188 return readAssert();1184 return readAssert();
1189 if (Tok == "CONSTANT")1185 if (tok == "CONSTANT")
1190 return readConstant();1186 return readConstant();
1191 if (Tok == "DATA_SEGMENT_ALIGN") {1187 if (tok == "DATA_SEGMENT_ALIGN") {
1192 expect("(");1188 expect("(");
1193 Expr E = readExpr();1189 Expr e = readExpr();
1194 expect(",");1190 expect(",");
1195 readExpr();1191 readExpr();
1196 expect(")");1192 expect(")");
1197 return [=] {1193 return [=] {
1198 return alignTo(Script->getDot(), std::max((uint64_t)1, E().getValue()));1194 return alignTo(script->getDot(), std::max((uint64_t)1, e().getValue()));
1199 };1195 };
1200 }1196 }
1201 if (Tok == "DATA_SEGMENT_END") {1197 if (tok == "DATA_SEGMENT_END") {
1202 expect("(");1198 expect("(");
1203 expect(".");1199 expect(".");
1204 expect(")");1200 expect(")");
1205 return [] { return Script->getDot(); };1201 return [] { return script->getDot(); };
1206 }1202 }
1207 if (Tok == "DATA_SEGMENT_RELRO_END") {1203 if (tok == "DATA_SEGMENT_RELRO_END") {
1208 // GNU linkers implements more complicated logic to handle1204 // GNU linkers implements more complicated logic to handle
1209 // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and1205 // DATA_SEGMENT_RELRO_END. We instead ignore the arguments and
1210 // just align to the next page boundary for simplicity.1206 // just align to the next page boundary for simplicity.
...@@ -1213,112 +1209,113 @@ Expr ScriptParser::readPrimary() {...@@ -1213,112 +1209,113 @@ Expr ScriptParser::readPrimary() {
1213 expect(",");1209 expect(",");
1214 readExpr();1210 readExpr();
1215 expect(")");1211 expect(")");
1216 Expr E = getPageSize();1212 Expr e = getPageSize();
1217 return [=] { return alignTo(Script->getDot(), E().getValue()); };1213 return [=] { return alignTo(script->getDot(), e().getValue()); };
1218 }1214 }
1219 if (Tok == "DEFINED") {1215 if (tok == "DEFINED") {
1220 StringRef Name = readParenLiteral();1216 StringRef name = readParenLiteral();
1221 return [=] { return Symtab->find(Name) ? 1 : 0; };1217 return [=] { return symtab->find(name) ? 1 : 0; };
1222 }1218 }
1223 if (Tok == "LENGTH") {1219 if (tok == "LENGTH") {
1224 StringRef Name = readParenLiteral();1220 StringRef name = readParenLiteral();
1225 if (Script->MemoryRegions.count(Name) == 0) {1221 if (script->memoryRegions.count(name) == 0) {
1226 setError("memory region not defined: " + Name);1222 setError("memory region not defined: " + name);
1227 return [] { return 0; };1223 return [] { return 0; };
1228 }1224 }
1229 return [=] { return Script->MemoryRegions[Name]->Length; };1225 return [=] { return script->memoryRegions[name]->length; };
1230 }1226 }
1231 if (Tok == "LOADADDR") {1227 if (tok == "LOADADDR") {
1232 StringRef Name = readParenLiteral();1228 StringRef name = readParenLiteral();
1233 OutputSection *Cmd = Script->getOrCreateOutputSection(Name);1229 OutputSection *cmd = script->getOrCreateOutputSection(name);
1230 cmd->usedInExpression = true;
1234 return [=] {1231 return [=] {
1235 checkIfExists(Cmd, Location);1232 checkIfExists(cmd, location);
1236 return Cmd->getLMA();1233 return cmd->getLMA();
1237 };1234 };
1238 }1235 }
1239 if (Tok == "MAX" || Tok == "MIN") {1236 if (tok == "MAX" || tok == "MIN") {
1240 expect("(");1237 expect("(");
1241 Expr A = readExpr();1238 Expr a = readExpr();
1242 expect(",");1239 expect(",");
1243 Expr B = readExpr();1240 Expr b = readExpr();
1244 expect(")");1241 expect(")");
1245 if (Tok == "MIN")1242 if (tok == "MIN")
1246 return [=] { return std::min(A().getValue(), B().getValue()); };1243 return [=] { return std::min(a().getValue(), b().getValue()); };
1247 return [=] { return std::max(A().getValue(), B().getValue()); };1244 return [=] { return std::max(a().getValue(), b().getValue()); };
1248 }1245 }
1249 if (Tok == "ORIGIN") {1246 if (tok == "ORIGIN") {
1250 StringRef Name = readParenLiteral();1247 StringRef name = readParenLiteral();
1251 if (Script->MemoryRegions.count(Name) == 0) {1248 if (script->memoryRegions.count(name) == 0) {
1252 setError("memory region not defined: " + Name);1249 setError("memory region not defined: " + name);
1253 return [] { return 0; };1250 return [] { return 0; };
1254 }1251 }
1255 return [=] { return Script->MemoryRegions[Name]->Origin; };1252 return [=] { return script->memoryRegions[name]->origin; };
1256 }1253 }
1257 if (Tok == "SEGMENT_START") {1254 if (tok == "SEGMENT_START") {
1258 expect("(");1255 expect("(");
1259 skip();1256 skip();
1260 expect(",");1257 expect(",");
1261 Expr E = readExpr();1258 Expr e = readExpr();
1262 expect(")");1259 expect(")");
1263 return [=] { return E(); };1260 return [=] { return e(); };
1264 }1261 }
1265 if (Tok == "SIZEOF") {1262 if (tok == "SIZEOF") {
1266 StringRef Name = readParenLiteral();1263 StringRef name = readParenLiteral();
1267 OutputSection *Cmd = Script->getOrCreateOutputSection(Name);1264 OutputSection *cmd = script->getOrCreateOutputSection(name);
1268 // Linker script does not create an output section if its content is empty.1265 // Linker script does not create an output section if its content is empty.
1269 // We want to allow SIZEOF(.foo) where .foo is a section which happened to1266 // We want to allow SIZEOF(.foo) where .foo is a section which happened to
1270 // be empty.1267 // be empty.
1271 return [=] { return Cmd->Size; };1268 return [=] { return cmd->size; };
1272 }1269 }
1273 if (Tok == "SIZEOF_HEADERS")1270 if (tok == "SIZEOF_HEADERS")
1274 return [=] { return elf::getHeaderSize(); };1271 return [=] { return elf::getHeaderSize(); };
12751272
1276 // Tok is the dot.1273 // Tok is the dot.
1277 if (Tok == ".")1274 if (tok == ".")
1278 return [=] { return Script->getSymbolValue(Tok, Location); };1275 return [=] { return script->getSymbolValue(tok, location); };
12791276
1280 // Tok is a literal number.1277 // Tok is a literal number.
1281 if (Optional<uint64_t> Val = parseInt(Tok))1278 if (Optional<uint64_t> val = parseInt(tok))
1282 return [=] { return *Val; };1279 return [=] { return *val; };
12831280
1284 // Tok is a symbol name.1281 // Tok is a symbol name.
1285 if (!isValidCIdentifier(Tok))1282 if (!isValidCIdentifier(tok))
1286 setError("malformed number: " + Tok);1283 setError("malformed number: " + tok);
1287 Script->ReferencedSymbols.push_back(Tok);1284 script->referencedSymbols.push_back(tok);
1288 return [=] { return Script->getSymbolValue(Tok, Location); };1285 return [=] { return script->getSymbolValue(tok, location); };
1289}1286}
12901287
1291Expr ScriptParser::readTernary(Expr Cond) {1288Expr ScriptParser::readTernary(Expr cond) {
1292 Expr L = readExpr();1289 Expr l = readExpr();
1293 expect(":");1290 expect(":");
1294 Expr R = readExpr();1291 Expr r = readExpr();
1295 return [=] { return Cond().getValue() ? L() : R(); };1292 return [=] { return cond().getValue() ? l() : r(); };
1296}1293}
12971294
1298Expr ScriptParser::readParenExpr() {1295Expr ScriptParser::readParenExpr() {
1299 expect("(");1296 expect("(");
1300 Expr E = readExpr();1297 Expr e = readExpr();
1301 expect(")");1298 expect(")");
1302 return E;1299 return e;
1303}1300}
13041301
1305std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() {1302std::vector<StringRef> ScriptParser::readOutputSectionPhdrs() {
1306 std::vector<StringRef> Phdrs;1303 std::vector<StringRef> phdrs;
1307 while (!errorCount() && peek().startswith(":")) {1304 while (!errorCount() && peek().startswith(":")) {
1308 StringRef Tok = next();1305 StringRef tok = next();
1309 Phdrs.push_back((Tok.size() == 1) ? next() : Tok.substr(1));1306 phdrs.push_back((tok.size() == 1) ? next() : tok.substr(1));
1310 }1307 }
1311 return Phdrs;1308 return phdrs;
1312}1309}
13131310
1314// Read a program header type name. The next token must be a1311// Read a program header type name. The next token must be a
1315// name of a program header type or a constant (e.g. "0x3").1312// name of a program header type or a constant (e.g. "0x3").
1316unsigned ScriptParser::readPhdrType() {1313unsigned ScriptParser::readPhdrType() {
1317 StringRef Tok = next();1314 StringRef tok = next();
1318 if (Optional<uint64_t> Val = parseInt(Tok))1315 if (Optional<uint64_t> val = parseInt(tok))
1319 return *Val;1316 return *val;
13201317
1321 unsigned Ret = StringSwitch<unsigned>(Tok)1318 unsigned ret = StringSwitch<unsigned>(tok)
1322 .Case("PT_NULL", PT_NULL)1319 .Case("PT_NULL", PT_NULL)
1323 .Case("PT_LOAD", PT_LOAD)1320 .Case("PT_LOAD", PT_LOAD)
1324 .Case("PT_DYNAMIC", PT_DYNAMIC)1321 .Case("PT_DYNAMIC", PT_DYNAMIC)
...@@ -1335,56 +1332,56 @@ unsigned ScriptParser::readPhdrType() {...@@ -1335,56 +1332,56 @@ unsigned ScriptParser::readPhdrType() {
1335 .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA)1332 .Case("PT_OPENBSD_BOOTDATA", PT_OPENBSD_BOOTDATA)
1336 .Default(-1);1333 .Default(-1);
13371334
1338 if (Ret == (unsigned)-1) {1335 if (ret == (unsigned)-1) {
1339 setError("invalid program header type: " + Tok);1336 setError("invalid program header type: " + tok);
1340 return PT_NULL;1337 return PT_NULL;
1341 }1338 }
1342 return Ret;1339 return ret;
1343}1340}
13441341
1345// Reads an anonymous version declaration.1342// Reads an anonymous version declaration.
1346void ScriptParser::readAnonymousDeclaration() {1343void ScriptParser::readAnonymousDeclaration() {
1347 std::vector<SymbolVersion> Locals;1344 std::vector<SymbolVersion> locals;
1348 std::vector<SymbolVersion> Globals;1345 std::vector<SymbolVersion> globals;
1349 std::tie(Locals, Globals) = readSymbols();1346 std::tie(locals, globals) = readSymbols();
13501347
1351 for (SymbolVersion V : Locals) {1348 for (SymbolVersion v : locals) {
1352 if (V.Name == "*")1349 if (v.name == "*")
1353 Config->DefaultSymbolVersion = VER_NDX_LOCAL;1350 config->defaultSymbolVersion = VER_NDX_LOCAL;
1354 else1351 else
1355 Config->VersionScriptLocals.push_back(V);1352 config->versionScriptLocals.push_back(v);
1356 }1353 }
13571354
1358 for (SymbolVersion V : Globals)1355 for (SymbolVersion v : globals)
1359 Config->VersionScriptGlobals.push_back(V);1356 config->versionScriptGlobals.push_back(v);
13601357
1361 expect(";");1358 expect(";");
1362}1359}
13631360
1364// Reads a non-anonymous version definition,1361// Reads a non-anonymous version definition,
1365// e.g. "VerStr { global: foo; bar; local: *; };".1362// e.g. "VerStr { global: foo; bar; local: *; };".
1366void ScriptParser::readVersionDeclaration(StringRef VerStr) {1363void ScriptParser::readVersionDeclaration(StringRef verStr) {
1367 // Read a symbol list.1364 // Read a symbol list.
1368 std::vector<SymbolVersion> Locals;1365 std::vector<SymbolVersion> locals;
1369 std::vector<SymbolVersion> Globals;1366 std::vector<SymbolVersion> globals;
1370 std::tie(Locals, Globals) = readSymbols();1367 std::tie(locals, globals) = readSymbols();
13711368
1372 for (SymbolVersion V : Locals) {1369 for (SymbolVersion v : locals) {
1373 if (V.Name == "*")1370 if (v.name == "*")
1374 Config->DefaultSymbolVersion = VER_NDX_LOCAL;1371 config->defaultSymbolVersion = VER_NDX_LOCAL;
1375 else1372 else
1376 Config->VersionScriptLocals.push_back(V);1373 config->versionScriptLocals.push_back(v);
1377 }1374 }
13781375
1379 // Create a new version definition and add that to the global symbols.1376 // Create a new version definition and add that to the global symbols.
1380 VersionDefinition Ver;1377 VersionDefinition ver;
1381 Ver.Name = VerStr;1378 ver.name = verStr;
1382 Ver.Globals = Globals;1379 ver.globals = globals;
13831380
1384 // User-defined version number starts from 2 because 0 and 1 are1381 // User-defined version number starts from 2 because 0 and 1 are
1385 // reserved for VER_NDX_LOCAL and VER_NDX_GLOBAL, respectively.1382 // reserved for VER_NDX_LOCAL and VER_NDX_GLOBAL, respectively.
1386 Ver.Id = Config->VersionDefinitions.size() + 2;1383 ver.id = config->versionDefinitions.size() + 2;
1387 Config->VersionDefinitions.push_back(Ver);1384 config->versionDefinitions.push_back(ver);
13881385
1389 // Each version may have a parent version. For example, "Ver2"1386 // Each version may have a parent version. For example, "Ver2"
1390 // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1"1387 // defined as "Ver2 { global: foo; local: *; } Ver1;" has "Ver1"
...@@ -1396,39 +1393,39 @@ void ScriptParser::readVersionDeclaration(StringRef VerStr) {...@@ -1396,39 +1393,39 @@ void ScriptParser::readVersionDeclaration(StringRef VerStr) {
1396 expect(";");1393 expect(";");
1397}1394}
13981395
1399static bool hasWildcard(StringRef S) {1396static bool hasWildcard(StringRef s) {
1400 return S.find_first_of("?*[") != StringRef::npos;1397 return s.find_first_of("?*[") != StringRef::npos;
1401}1398}
14021399
1403// Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".1400// Reads a list of symbols, e.g. "{ global: foo; bar; local: *; };".
1404std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>1401std::pair<std::vector<SymbolVersion>, std::vector<SymbolVersion>>
1405ScriptParser::readSymbols() {1402ScriptParser::readSymbols() {
1406 std::vector<SymbolVersion> Locals;1403 std::vector<SymbolVersion> locals;
1407 std::vector<SymbolVersion> Globals;1404 std::vector<SymbolVersion> globals;
1408 std::vector<SymbolVersion> *V = &Globals;1405 std::vector<SymbolVersion> *v = &globals;
14091406
1410 while (!errorCount()) {1407 while (!errorCount()) {
1411 if (consume("}"))1408 if (consume("}"))
1412 break;1409 break;
1413 if (consumeLabel("local")) {1410 if (consumeLabel("local")) {
1414 V = &Locals;1411 v = &locals;
1415 continue;1412 continue;
1416 }1413 }
1417 if (consumeLabel("global")) {1414 if (consumeLabel("global")) {
1418 V = &Globals;1415 v = &globals;
1419 continue;1416 continue;
1420 }1417 }
14211418
1422 if (consume("extern")) {1419 if (consume("extern")) {
1423 std::vector<SymbolVersion> Ext = readVersionExtern();1420 std::vector<SymbolVersion> ext = readVersionExtern();
1424 V->insert(V->end(), Ext.begin(), Ext.end());1421 v->insert(v->end(), ext.begin(), ext.end());
1425 } else {1422 } else {
1426 StringRef Tok = next();1423 StringRef tok = next();
1427 V->push_back({unquote(Tok), false, hasWildcard(Tok)});1424 v->push_back({unquote(tok), false, hasWildcard(tok)});
1428 }1425 }
1429 expect(";");1426 expect(";");
1430 }1427 }
1431 return {Locals, Globals};1428 return {locals, globals};
1432}1429}
14331430
1434// Reads an "extern C++" directive, e.g.,1431// Reads an "extern C++" directive, e.g.,
...@@ -1437,30 +1434,30 @@ ScriptParser::readSymbols() {...@@ -1437,30 +1434,30 @@ ScriptParser::readSymbols() {
1437// The last semicolon is optional. E.g. this is OK:1434// The last semicolon is optional. E.g. this is OK:
1438// "extern "C++" { ns::*; "f(int, double)" };"1435// "extern "C++" { ns::*; "f(int, double)" };"
1439std::vector<SymbolVersion> ScriptParser::readVersionExtern() {1436std::vector<SymbolVersion> ScriptParser::readVersionExtern() {
1440 StringRef Tok = next();1437 StringRef tok = next();
1441 bool IsCXX = Tok == "\"C++\"";1438 bool isCXX = tok == "\"C++\"";
1442 if (!IsCXX && Tok != "\"C\"")1439 if (!isCXX && tok != "\"C\"")
1443 setError("Unknown language");1440 setError("Unknown language");
1444 expect("{");1441 expect("{");
14451442
1446 std::vector<SymbolVersion> Ret;1443 std::vector<SymbolVersion> ret;
1447 while (!errorCount() && peek() != "}") {1444 while (!errorCount() && peek() != "}") {
1448 StringRef Tok = next();1445 StringRef tok = next();
1449 bool HasWildcard = !Tok.startswith("\"") && hasWildcard(Tok);1446 ret.push_back(
1450 Ret.push_back({unquote(Tok), IsCXX, HasWildcard});1447 {unquote(tok), isCXX, !tok.startswith("\"") && hasWildcard(tok)});
1451 if (consume("}"))1448 if (consume("}"))
1452 return Ret;1449 return ret;
1453 expect(";");1450 expect(";");
1454 }1451 }
14551452
1456 expect("}");1453 expect("}");
1457 return Ret;1454 return ret;
1458}1455}
14591456
1460uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2,1457uint64_t ScriptParser::readMemoryAssignment(StringRef s1, StringRef s2,
1461 StringRef S3) {1458 StringRef s3) {
1462 if (!consume(S1) && !consume(S2) && !consume(S3)) {1459 if (!consume(s1) && !consume(s2) && !consume(s3)) {
1463 setError("expected one of: " + S1 + ", " + S2 + ", or " + S3);1460 setError("expected one of: " + s1 + ", " + s2 + ", or " + s3);
1464 return 0;1461 return 0;
1465 }1462 }
1466 expect("=");1463 expect("=");
...@@ -1474,28 +1471,28 @@ uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2,...@@ -1474,28 +1471,28 @@ uint64_t ScriptParser::readMemoryAssignment(StringRef S1, StringRef S2,
1474void ScriptParser::readMemory() {1471void ScriptParser::readMemory() {
1475 expect("{");1472 expect("{");
1476 while (!errorCount() && !consume("}")) {1473 while (!errorCount() && !consume("}")) {
1477 StringRef Tok = next();1474 StringRef tok = next();
1478 if (Tok == "INCLUDE") {1475 if (tok == "INCLUDE") {
1479 readInclude();1476 readInclude();
1480 continue;1477 continue;
1481 }1478 }
14821479
1483 uint32_t Flags = 0;1480 uint32_t flags = 0;
1484 uint32_t NegFlags = 0;1481 uint32_t negFlags = 0;
1485 if (consume("(")) {1482 if (consume("(")) {
1486 std::tie(Flags, NegFlags) = readMemoryAttributes();1483 std::tie(flags, negFlags) = readMemoryAttributes();
1487 expect(")");1484 expect(")");
1488 }1485 }
1489 expect(":");1486 expect(":");
14901487
1491 uint64_t Origin = readMemoryAssignment("ORIGIN", "org", "o");1488 uint64_t origin = readMemoryAssignment("ORIGIN", "org", "o");
1492 expect(",");1489 expect(",");
1493 uint64_t Length = readMemoryAssignment("LENGTH", "len", "l");1490 uint64_t length = readMemoryAssignment("LENGTH", "len", "l");
14941491
1495 // Add the memory region to the region map.1492 // Add the memory region to the region map.
1496 MemoryRegion *MR = make<MemoryRegion>(Tok, Origin, Length, Flags, NegFlags);1493 MemoryRegion *mr = make<MemoryRegion>(tok, origin, length, flags, negFlags);
1497 if (!Script->MemoryRegions.insert({Tok, MR}).second)1494 if (!script->memoryRegions.insert({tok, mr}).second)
1498 setError("region '" + Tok + "' already defined");1495 setError("region '" + tok + "' already defined");
1499 }1496 }
1500}1497}
15011498
...@@ -1503,43 +1500,43 @@ void ScriptParser::readMemory() {...@@ -1503,43 +1500,43 @@ void ScriptParser::readMemory() {
1503// flags when placing output sections in a memory region. These flags1500// flags when placing output sections in a memory region. These flags
1504// are only used when an explicit memory region name is not used.1501// are only used when an explicit memory region name is not used.
1505std::pair<uint32_t, uint32_t> ScriptParser::readMemoryAttributes() {1502std::pair<uint32_t, uint32_t> ScriptParser::readMemoryAttributes() {
1506 uint32_t Flags = 0;1503 uint32_t flags = 0;
1507 uint32_t NegFlags = 0;1504 uint32_t negFlags = 0;
1508 bool Invert = false;1505 bool invert = false;
15091506
1510 for (char C : next().lower()) {1507 for (char c : next().lower()) {
1511 uint32_t Flag = 0;1508 uint32_t flag = 0;
1512 if (C == '!')1509 if (c == '!')
1513 Invert = !Invert;1510 invert = !invert;
1514 else if (C == 'w')1511 else if (c == 'w')
1515 Flag = SHF_WRITE;1512 flag = SHF_WRITE;
1516 else if (C == 'x')1513 else if (c == 'x')
1517 Flag = SHF_EXECINSTR;1514 flag = SHF_EXECINSTR;
1518 else if (C == 'a')1515 else if (c == 'a')
1519 Flag = SHF_ALLOC;1516 flag = SHF_ALLOC;
1520 else if (C != 'r')1517 else if (c != 'r')
1521 setError("invalid memory region attribute");1518 setError("invalid memory region attribute");
15221519
1523 if (Invert)1520 if (invert)
1524 NegFlags |= Flag;1521 negFlags |= flag;
1525 else1522 else
1526 Flags |= Flag;1523 flags |= flag;
1527 }1524 }
1528 return {Flags, NegFlags};1525 return {flags, negFlags};
1529}1526}
15301527
1531void elf::readLinkerScript(MemoryBufferRef MB) {1528void elf::readLinkerScript(MemoryBufferRef mb) {
1532 ScriptParser(MB).readLinkerScript();1529 ScriptParser(mb).readLinkerScript();
1533}1530}
15341531
1535void elf::readVersionScript(MemoryBufferRef MB) {1532void elf::readVersionScript(MemoryBufferRef mb) {
1536 ScriptParser(MB).readVersionScript();1533 ScriptParser(mb).readVersionScript();
1537}1534}
15381535
1539void elf::readDynamicList(MemoryBufferRef MB) {1536void elf::readDynamicList(MemoryBufferRef mb) {
1540 ScriptParser(MB).readDynamicList();1537 ScriptParser(mb).readDynamicList();
1541}1538}
15421539
1543void elf::readDefsym(StringRef Name, MemoryBufferRef MB) {1540void elf::readDefsym(StringRef name, MemoryBufferRef mb) {
1544 ScriptParser(MB).readDefsym(Name);1541 ScriptParser(mb).readDefsym(name);
1545}1542}
deps/lld/ELF/ScriptParser.h+8-9
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ScriptParser.h -------------------------------------------*- C++ -*-===//1//===- ScriptParser.h -------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -17,16 +16,16 @@ namespace lld {...@@ -17,16 +16,16 @@ namespace lld {
17namespace elf {16namespace elf {
1817
19// Parses a linker script. Calling this function updates18// Parses a linker script. Calling this function updates
20// Config and ScriptConfig.19// lld::elf::config and lld::elf::script.
21void readLinkerScript(MemoryBufferRef MB);20void readLinkerScript(MemoryBufferRef mb);
2221
23// Parses a version script.22// Parses a version script.
24void readVersionScript(MemoryBufferRef MB);23void readVersionScript(MemoryBufferRef mb);
2524
26void readDynamicList(MemoryBufferRef MB);25void readDynamicList(MemoryBufferRef mb);
2726
28// Parses the defsym expression.27// Parses the defsym expression.
29void readDefsym(StringRef Name, MemoryBufferRef MB);28void readDefsym(StringRef name, MemoryBufferRef mb);
3029
31} // namespace elf30} // namespace elf
32} // namespace lld31} // namespace lld
deps/lld/ELF/SymbolTable.cpp+143-692
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- SymbolTable.cpp ----------------------------------------------------===//1//===- SymbolTable.cpp ----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -31,576 +30,76 @@ using namespace llvm::ELF;...@@ -31,576 +30,76 @@ using namespace llvm::ELF;
31using namespace lld;30using namespace lld;
32using namespace lld::elf;31using namespace lld::elf;
3332
34SymbolTable *elf::Symtab;33SymbolTable *elf::symtab;
35
36static InputFile *getFirstElf() {
37 if (!ObjectFiles.empty())
38 return ObjectFiles[0];
39 if (!SharedFiles.empty())
40 return SharedFiles[0];
41 return BitcodeFiles[0];
42}
43
44// All input object files must be for the same architecture
45// (e.g. it does not make sense to link x86 object files with
46// MIPS object files.) This function checks for that error.
47static bool isCompatible(InputFile *F) {
48 if (!F->isElf() && !isa<BitcodeFile>(F))
49 return true;
50
51 if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) {
52 if (Config->EMachine != EM_MIPS)
53 return true;
54 if (isMipsN32Abi(F) == Config->MipsN32Abi)
55 return true;
56 }
57
58 if (!Config->Emulation.empty())
59 error(toString(F) + " is incompatible with " + Config->Emulation);
60 else
61 error(toString(F) + " is incompatible with " + toString(getFirstElf()));
62 return false;
63}
64
65// Add symbols in File to the symbol table.
66template <class ELFT> void SymbolTable::addFile(InputFile *File) {
67 if (!isCompatible(File))
68 return;
69
70 // Binary file
71 if (auto *F = dyn_cast<BinaryFile>(File)) {
72 BinaryFiles.push_back(F);
73 F->parse();
74 return;
75 }
76
77 // .a file
78 if (auto *F = dyn_cast<ArchiveFile>(File)) {
79 F->parse<ELFT>();
80 return;
81 }
82
83 // Lazy object file
84 if (auto *F = dyn_cast<LazyObjFile>(File)) {
85 LazyObjFiles.push_back(F);
86 F->parse<ELFT>();
87 return;
88 }
89
90 if (Config->Trace)
91 message(toString(File));
92
93 // .so file
94 if (auto *F = dyn_cast<SharedFile<ELFT>>(File)) {
95 // DSOs are uniquified not by filename but by soname.
96 F->parseSoName();
97 if (errorCount())
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
111 SharedFiles.push_back(F);
112 F->parseRest();
113 return;
114 }
115
116 // LLVM bitcode file
117 if (auto *F = dyn_cast<BitcodeFile>(File)) {
118 BitcodeFiles.push_back(F);
119 F->parse<ELFT>(ComdatGroups);
120 return;
121 }
122
123 // Regular object file
124 ObjectFiles.push_back(File);
125 cast<ObjFile<ELFT>>(File)->parse(ComdatGroups);
126}
127
128// This function is where all the optimizations of link-time
129// optimization happens. When LTO is in use, some input files are
130// not in native object file format but in the LLVM bitcode format.
131// This function compiles bitcode files into a few big native files
132// using LLVM functions and replaces bitcode symbols with the results.
133// Because all bitcode files that the program consists of are passed
134// to the compiler at once, it can do whole-program optimization.
135template <class ELFT> void SymbolTable::addCombinedLTOObject() {
136 if (BitcodeFiles.empty())
137 return;
138
139 // Compile bitcode files and replace bitcode symbols.
140 LTO.reset(new BitcodeCompiler);
141 for (BitcodeFile *F : BitcodeFiles)
142 LTO->add(*F);
143
144 for (InputFile *File : LTO->compile()) {
145 DenseSet<CachedHashStringRef> DummyGroups;
146 auto *Obj = cast<ObjFile<ELFT>>(File);
147 Obj->parse(DummyGroups);
148 for (Symbol *Sym : Obj->getGlobalSymbols())
149 Sym->parseSymbolVersion();
150 ObjectFiles.push_back(File);
151 }
152}
153
154// Set a flag for --trace-symbol so that we can print out a log message
155// if a new symbol with the same name is inserted into the symbol table.
156void SymbolTable::trace(StringRef Name) {
157 SymMap.insert({CachedHashStringRef(Name), -1});
158}
15934
160void SymbolTable::wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap) {35void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
161 // Swap symbols as instructed by -wrap.36 // Swap symbols as instructed by -wrap.
162 int &Idx1 = SymMap[CachedHashStringRef(Sym->getName())];37 int &idx1 = symMap[CachedHashStringRef(sym->getName())];
163 int &Idx2 = SymMap[CachedHashStringRef(Real->getName())];38 int &idx2 = symMap[CachedHashStringRef(real->getName())];
164 int &Idx3 = SymMap[CachedHashStringRef(Wrap->getName())];39 int &idx3 = symMap[CachedHashStringRef(wrap->getName())];
16540
166 Idx2 = Idx1;41 idx2 = idx1;
167 Idx1 = Idx3;42 idx1 = idx3;
16843
169 // Now renaming is complete. No one refers Real symbol. We could leave44 // 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 may45 // 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.46 // contain irrelevant values. So, we copy all values from Sym to Real.
172 StringRef S = Real->getName();47 StringRef s = real->getName();
173 memcpy(Real, Sym, sizeof(SymbolUnion));48 memcpy(real, sym, sizeof(SymbolUnion));
174 Real->setName(S);49 real->setName(s);
175}
176
177static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
178 if (VA == STV_DEFAULT)
179 return VB;
180 if (VB == STV_DEFAULT)
181 return VA;
182 return std::min(VA, VB);
183}50}
18451
185// Find an existing symbol or create and insert a new one.52// Find an existing symbol or create a new one.
186std::pair<Symbol *, bool> SymbolTable::insertName(StringRef Name) {53Symbol *SymbolTable::insert(StringRef name) {
187 // <name>@@<version> means the symbol is the default version. In that54 // <name>@@<version> means the symbol is the default version. In that
188 // case <name>@@<version> will be used to resolve references to <name>.55 // case <name>@@<version> will be used to resolve references to <name>.
189 //56 //
190 // Since this is a hot path, the following string search code is57 // Since this is a hot path, the following string search code is
191 // optimized for speed. StringRef::find(char) is much faster than58 // optimized for speed. StringRef::find(char) is much faster than
192 // StringRef::find(StringRef).59 // StringRef::find(StringRef).
193 size_t Pos = Name.find('@');60 size_t pos = name.find('@');
194 if (Pos != StringRef::npos && Pos + 1 < Name.size() && Name[Pos + 1] == '@')61 if (pos != StringRef::npos && pos + 1 < name.size() && name[pos + 1] == '@')
195 Name = Name.take_front(Pos);62 name = name.take_front(pos);
19663
197 auto P = SymMap.insert({CachedHashStringRef(Name), (int)SymVector.size()});64 auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
198 int &SymIndex = P.first->second;65 int &symIndex = p.first->second;
199 bool IsNew = P.second;66 bool isNew = p.second;
200 bool Traced = false;67
20168 if (!isNew)
202 if (SymIndex == -1) {69 return symVector[symIndex];
203 SymIndex = SymVector.size();70
204 IsNew = true;71 Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
205 Traced = true;72 symVector.push_back(sym);
206 }73
20774 sym->setName(name);
208 if (!IsNew)75 sym->symbolKind = Symbol::PlaceholderKind;
209 return {SymVector[SymIndex], false};76 sym->versionId = config->defaultSymbolVersion;
21077 sym->visibility = STV_DEFAULT;
211 auto *Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());78 sym->isUsedInRegularObj = false;
212 Sym->SymbolKind = Symbol::PlaceholderKind;79 sym->exportDynamic = false;
213 Sym->Visibility = STV_DEFAULT;80 sym->canInline = true;
214 Sym->IsUsedInRegularObj = false;81 sym->scriptDefined = false;
215 Sym->ExportDynamic = false;82 sym->partition = 1;
216 Sym->CanInline = true;83 return sym;
217 Sym->Traced = Traced;
218 Sym->VersionId = Config->DefaultSymbolVersion;
219 SymVector.push_back(Sym);
220 return {Sym, true};
221}84}
22285
223// Find an existing symbol or create and insert a new one, then apply the given86Symbol *SymbolTable::addSymbol(const Symbol &New) {
224// attributes.87 Symbol *sym = symtab->insert(New.getName());
225std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name,88 sym->resolve(New);
226 uint8_t Visibility,89 return sym;
227 bool CanOmitFromDynSym,
228 InputFile *File) {
229 Symbol *S;
230 bool WasInserted;
231 std::tie(S, WasInserted) = insertName(Name);
232
233 // Merge in the new symbol's visibility.
234 S->Visibility = getMinVisibility(S->Visibility, Visibility);
235
236 if (!CanOmitFromDynSym && (Config->Shared || Config->ExportDynamic))
237 S->ExportDynamic = true;
238
239 if (!File || File->kind() == InputFile::ObjKind)
240 S->IsUsedInRegularObj = true;
241
242 return {S, WasInserted};
243}90}
24491
245static uint8_t getVisibility(uint8_t StOther) { return StOther & 3; }92Symbol *SymbolTable::find(StringRef name) {
24693 auto it = symMap.find(CachedHashStringRef(name));
247template <class ELFT>94 if (it == symMap.end())
248Symbol *SymbolTable::addUndefined(StringRef Name, uint8_t Binding,
249 uint8_t StOther, uint8_t Type,
250 bool CanOmitFromDynSym, InputFile *File) {
251 Symbol *S;
252 bool WasInserted;
253 uint8_t Visibility = getVisibility(StOther);
254 std::tie(S, WasInserted) = insert(Name, Visibility, CanOmitFromDynSym, File);
255
256 // An undefined symbol with non default visibility must be satisfied
257 // in the same DSO.
258 if (WasInserted || (isa<SharedSymbol>(S) && Visibility != STV_DEFAULT)) {
259 replaceSymbol<Undefined>(S, File, Name, Binding, StOther, Type);
260 return S;
261 }
262
263 if (S->isShared() || S->isLazy() || (S->isUndefined() && Binding != STB_WEAK))
264 S->Binding = Binding;
265
266 if (S->isLazy()) {
267 // An undefined weak will not fetch archive members. See comment on Lazy in
268 // Symbols.h for the details.
269 if (Binding == STB_WEAK) {
270 S->Type = Type;
271 return S;
272 }
273
274 // Do extra check for --warn-backrefs.
275 //
276 // --warn-backrefs is an option to prevent an undefined reference from
277 // fetching an archive member written earlier in the command line. It can be
278 // used to keep compatibility with GNU linkers to some degree.
279 // I'll explain the feature and why you may find it useful in this comment.
280 //
281 // lld's symbol resolution semantics is more relaxed than traditional Unix
282 // linkers. For example,
283 //
284 // ld.lld foo.a bar.o
285 //
286 // succeeds even if bar.o contains an undefined symbol that has to be
287 // resolved by some object file in foo.a. Traditional Unix linkers don't
288 // allow this kind of backward reference, as they visit each file only once
289 // from left to right in the command line while resolving all undefined
290 // symbols at the moment of visiting.
291 //
292 // In the above case, since there's no undefined symbol when a linker visits
293 // foo.a, no files are pulled out from foo.a, and because the linker forgets
294 // about foo.a after visiting, it can't resolve undefined symbols in bar.o
295 // that could have been resolved otherwise.
296 //
297 // That lld accepts more relaxed form means that (besides it'd make more
298 // sense) you can accidentally write a command line or a build file that
299 // works only with lld, even if you have a plan to distribute it to wider
300 // users who may be using GNU linkers. With --warn-backrefs, you can detect
301 // a library order that doesn't work with other Unix linkers.
302 //
303 // The option is also useful to detect cyclic dependencies between static
304 // archives. Again, lld accepts
305 //
306 // ld.lld foo.a bar.a
307 //
308 // even if foo.a and bar.a depend on each other. With --warn-backrefs, it is
309 // handled as an error.
310 //
311 // Here is how the option works. We assign a group ID to each file. A file
312 // with a smaller group ID can pull out object files from an archive file
313 // with an equal or greater group ID. Otherwise, it is a reverse dependency
314 // and an error.
315 //
316 // A file outside --{start,end}-group gets a fresh ID when instantiated. All
317 // files within the same --{start,end}-group get the same group ID. E.g.
318 //
319 // ld.lld A B --start-group C D --end-group E
320 //
321 // A forms group 0. B form group 1. C and D (including their member object
322 // files) form group 2. E forms group 3. I think that you can see how this
323 // group assignment rule simulates the traditional linker's semantics.
324 bool Backref =
325 Config->WarnBackrefs && File && S->File->GroupId < File->GroupId;
326 fetchLazy<ELFT>(S);
327
328 // We don't report backward references to weak symbols as they can be
329 // overridden later.
330 if (Backref && S->Binding != STB_WEAK)
331 warn("backward reference detected: " + Name + " in " + toString(File) +
332 " refers to " + toString(S->File));
333 }
334 return S;
335}
336
337// Using .symver foo,foo@@VER unfortunately creates two symbols: foo and
338// foo@@VER. We want to effectively ignore foo, so give precedence to
339// foo@@VER.
340// FIXME: If users can transition to using
341// .symver foo,foo@@@VER
342// we can delete this hack.
343static int compareVersion(Symbol *S, StringRef Name) {
344 bool A = Name.contains("@@");
345 bool B = S->getName().contains("@@");
346 if (A && !B)
347 return 1;
348 if (!A && B)
349 return -1;
350 return 0;
351}
352
353// We have a new defined symbol with the specified binding. Return 1 if the new
354// symbol should win, -1 if the new symbol should lose, or 0 if both symbols are
355// strong defined symbols.
356static int compareDefined(Symbol *S, bool WasInserted, uint8_t Binding,
357 StringRef Name) {
358 if (WasInserted)
359 return 1;
360 if (!S->isDefined())
361 return 1;
362 if (int R = compareVersion(S, Name))
363 return R;
364 if (Binding == STB_WEAK)
365 return -1;
366 if (S->isWeak())
367 return 1;
368 return 0;
369}
370
371// We have a new non-common defined symbol with the specified binding. Return 1
372// if the new symbol should win, -1 if the new symbol should lose, or 0 if there
373// is a conflict. If the new symbol wins, also update the binding.
374static int compareDefinedNonCommon(Symbol *S, bool WasInserted, uint8_t Binding,
375 bool IsAbsolute, uint64_t Value,
376 StringRef Name) {
377 if (int Cmp = compareDefined(S, WasInserted, Binding, Name))
378 return Cmp;
379 if (auto *R = dyn_cast<Defined>(S)) {
380 if (R->Section && isa<BssSection>(R->Section)) {
381 // Non-common symbols take precedence over common symbols.
382 if (Config->WarnCommon)
383 warn("common " + S->getName() + " is overridden");
384 return 1;
385 }
386 if (R->Section == nullptr && Binding == STB_GLOBAL && IsAbsolute &&
387 R->Value == Value)
388 return -1;
389 }
390 return 0;
391}
392
393Symbol *SymbolTable::addCommon(StringRef N, uint64_t Size, uint32_t Alignment,
394 uint8_t Binding, uint8_t StOther, uint8_t Type,
395 InputFile &File) {
396 Symbol *S;
397 bool WasInserted;
398 std::tie(S, WasInserted) = insert(N, getVisibility(StOther),
399 /*CanOmitFromDynSym*/ false, &File);
400
401 int Cmp = compareDefined(S, WasInserted, Binding, N);
402 if (Cmp < 0)
403 return S;
404
405 if (Cmp > 0) {
406 auto *Bss = make<BssSection>("COMMON", Size, Alignment);
407 Bss->File = &File;
408 Bss->Live = !Config->GcSections;
409 InputSections.push_back(Bss);
410
411 replaceSymbol<Defined>(S, &File, N, Binding, StOther, Type, 0, Size, Bss);
412 return S;
413 }
414
415 auto *D = cast<Defined>(S);
416 auto *Bss = dyn_cast_or_null<BssSection>(D->Section);
417 if (!Bss) {
418 // Non-common symbols take precedence over common symbols.
419 if (Config->WarnCommon)
420 warn("common " + S->getName() + " is overridden");
421 return S;
422 }
423
424 if (Config->WarnCommon)
425 warn("multiple common of " + D->getName());
426
427 Bss->Alignment = std::max(Bss->Alignment, Alignment);
428 if (Size > Bss->Size) {
429 D->File = Bss->File = &File;
430 D->Size = Bss->Size = Size;
431 }
432 return S;
433}
434
435static void reportDuplicate(Symbol *Sym, InputFile *NewFile,
436 InputSectionBase *ErrSec, uint64_t ErrOffset) {
437 if (Config->AllowMultipleDefinition)
438 return;
439
440 Defined *D = cast<Defined>(Sym);
441 if (!D->Section || !ErrSec) {
442 error("duplicate symbol: " + toString(*Sym) + "\n>>> defined in " +
443 toString(Sym->File) + "\n>>> defined in " + toString(NewFile));
444 return;
445 }
446
447 // Construct and print an error message in the form of:
448 //
449 // ld.lld: error: duplicate symbol: foo
450 // >>> defined at bar.c:30
451 // >>> bar.o (/home/alice/src/bar.o)
452 // >>> defined at baz.c:563
453 // >>> baz.o in archive libbaz.a
454 auto *Sec1 = cast<InputSectionBase>(D->Section);
455 std::string Src1 = Sec1->getSrcMsg(*Sym, D->Value);
456 std::string Obj1 = Sec1->getObjMsg(D->Value);
457 std::string Src2 = ErrSec->getSrcMsg(*Sym, ErrOffset);
458 std::string Obj2 = ErrSec->getObjMsg(ErrOffset);
459
460 std::string Msg = "duplicate symbol: " + toString(*Sym) + "\n>>> defined at ";
461 if (!Src1.empty())
462 Msg += Src1 + "\n>>> ";
463 Msg += Obj1 + "\n>>> defined at ";
464 if (!Src2.empty())
465 Msg += Src2 + "\n>>> ";
466 Msg += Obj2;
467 error(Msg);
468}
469
470Defined *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) {
473 Symbol *S;
474 bool WasInserted;
475 std::tie(S, WasInserted) = insert(Name, getVisibility(StOther),
476 /*CanOmitFromDynSym*/ false, File);
477 int Cmp = compareDefinedNonCommon(S, WasInserted, Binding, Section == nullptr,
478 Value, Name);
479 if (Cmp > 0)
480 replaceSymbol<Defined>(S, File, Name, Binding, StOther, Type, Value, Size,
481 Section);
482 else if (Cmp == 0)
483 reportDuplicate(S, File, dyn_cast_or_null<InputSectionBase>(Section),
484 Value);
485 return cast<Defined>(S);
486}
487
488template <typename ELFT>
489void SymbolTable::addShared(StringRef Name, SharedFile<ELFT> &File,
490 const typename ELFT::Sym &Sym, uint32_t Alignment,
491 uint32_t VerdefIndex) {
492 // DSO symbols do not affect visibility in the output, so we pass STV_DEFAULT
493 // as the visibility, which will leave the visibility in the symbol table
494 // unchanged.
495 Symbol *S;
496 bool WasInserted;
497 std::tie(S, WasInserted) = insert(Name, STV_DEFAULT,
498 /*CanOmitFromDynSym*/ true, &File);
499 // Make sure we preempt DSO symbols with default visibility.
500 if (Sym.getVisibility() == STV_DEFAULT)
501 S->ExportDynamic = true;
502
503 // An undefined symbol with non default visibility must be satisfied
504 // in the same DSO.
505 auto Replace = [&](uint8_t Binding) {
506 replaceSymbol<SharedSymbol>(S, File, Name, Binding, Sym.st_other,
507 Sym.getType(), Sym.st_value, Sym.st_size,
508 Alignment, VerdefIndex);
509 };
510
511 if (WasInserted)
512 Replace(Sym.getBinding());
513 else if (S->Visibility == STV_DEFAULT && (S->isUndefined() || S->isLazy()))
514 Replace(S->Binding);
515}
516
517Symbol *SymbolTable::addBitcode(StringRef Name, uint8_t Binding,
518 uint8_t StOther, uint8_t Type,
519 bool CanOmitFromDynSym, BitcodeFile &F) {
520 Symbol *S;
521 bool WasInserted;
522 std::tie(S, WasInserted) =
523 insert(Name, getVisibility(StOther), CanOmitFromDynSym, &F);
524 int Cmp = compareDefinedNonCommon(S, WasInserted, Binding,
525 /*IsAbs*/ false, /*Value*/ 0, Name);
526 if (Cmp > 0)
527 replaceSymbol<Defined>(S, &F, Name, Binding, StOther, Type, 0, 0, nullptr);
528 else if (Cmp == 0)
529 reportDuplicate(S, &F, nullptr, 0);
530 return S;
531}
532
533Symbol *SymbolTable::find(StringRef Name) {
534 auto It = SymMap.find(CachedHashStringRef(Name));
535 if (It == SymMap.end())
536 return nullptr;95 return nullptr;
537 if (It->second == -1)96 Symbol *sym = symVector[it->second];
97 if (sym->isPlaceholder())
538 return nullptr;98 return nullptr;
539 return SymVector[It->second];99 return sym;
540}100}
541101
542template <class ELFT>102// Initialize demangledSyms with a map from demangled symbols to symbol
543void SymbolTable::addLazyArchive(StringRef Name, ArchiveFile &File,
544 const object::Archive::Symbol Sym) {
545 Symbol *S;
546 bool WasInserted;
547 std::tie(S, WasInserted) = insertName(Name);
548 if (WasInserted) {
549 replaceSymbol<LazyArchive>(S, File, STT_NOTYPE, Sym);
550 return;
551 }
552 if (!S->isUndefined())
553 return;
554
555 // An undefined weak will not fetch archive members. See comment on Lazy in
556 // Symbols.h for the details.
557 if (S->isWeak()) {
558 replaceSymbol<LazyArchive>(S, File, S->Type, Sym);
559 S->Binding = STB_WEAK;
560 return;
561 }
562
563 if (InputFile *F = File.fetch(Sym))
564 addFile<ELFT>(F);
565}
566
567template <class ELFT>
568void 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;
578
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);
589}
590
591template <class ELFT> void SymbolTable::fetchLazy(Symbol *Sym) {
592 if (auto *S = dyn_cast<LazyArchive>(Sym)) {
593 if (InputFile *File = S->fetch())
594 addFile<ELFT>(File);
595 return;
596 }
597
598 auto *S = cast<LazyObject>(Sym);
599 if (InputFile *File = cast<LazyObjFile>(S->File)->fetch())
600 addFile<ELFT>(File);
601}
602
603// Initialize DemangledSyms with a map from demangled symbols to symbol
604// objects. Used to handle "extern C++" directive in version scripts.103// objects. Used to handle "extern C++" directive in version scripts.
605//104//
606// The map will contain all demangled symbols. That can be very large,105// The map will contain all demangled symbols. That can be very large,
...@@ -614,204 +113,156 @@ template <class ELFT> void SymbolTable::fetchLazy(Symbol *Sym) {...@@ -614,204 +113,156 @@ template <class ELFT> void SymbolTable::fetchLazy(Symbol *Sym) {
614// So, if "extern C++" feature is used, we need to demangle all known113// So, if "extern C++" feature is used, we need to demangle all known
615// symbols.114// symbols.
616StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {115StringMap<std::vector<Symbol *>> &SymbolTable::getDemangledSyms() {
617 if (!DemangledSyms) {116 if (!demangledSyms) {
618 DemangledSyms.emplace();117 demangledSyms.emplace();
619 for (Symbol *Sym : SymVector) {118 for (Symbol *sym : symVector) {
620 if (!Sym->isDefined())119 if (!sym->isDefined() && !sym->isCommon())
621 continue;120 continue;
622 if (Optional<std::string> S = demangleItanium(Sym->getName()))121 if (Optional<std::string> s = demangleItanium(sym->getName()))
623 (*DemangledSyms)[*S].push_back(Sym);122 (*demangledSyms)[*s].push_back(sym);
624 else123 else
625 (*DemangledSyms)[Sym->getName()].push_back(Sym);124 (*demangledSyms)[sym->getName()].push_back(sym);
626 }125 }
627 }126 }
628 return *DemangledSyms;127 return *demangledSyms;
629}128}
630129
631std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion Ver) {130std::vector<Symbol *> SymbolTable::findByVersion(SymbolVersion ver) {
632 if (Ver.IsExternCpp)131 if (ver.isExternCpp)
633 return getDemangledSyms().lookup(Ver.Name);132 return getDemangledSyms().lookup(ver.name);
634 if (Symbol *B = find(Ver.Name))133 if (Symbol *b = find(ver.name))
635 if (B->isDefined())134 if (b->isDefined() || b->isCommon())
636 return {B};135 return {b};
637 return {};136 return {};
638}137}
639138
640std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion Ver) {139std::vector<Symbol *> SymbolTable::findAllByVersion(SymbolVersion ver) {
641 std::vector<Symbol *> Res;140 std::vector<Symbol *> res;
642 StringMatcher M(Ver.Name);141 StringMatcher m(ver.name);
643142
644 if (Ver.IsExternCpp) {143 if (ver.isExternCpp) {
645 for (auto &P : getDemangledSyms())144 for (auto &p : getDemangledSyms())
646 if (M.match(P.first()))145 if (m.match(p.first()))
647 Res.insert(Res.end(), P.second.begin(), P.second.end());146 res.insert(res.end(), p.second.begin(), p.second.end());
648 return Res;147 return res;
649 }148 }
650149
651 for (Symbol *Sym : SymVector)150 for (Symbol *sym : symVector)
652 if (Sym->isDefined() && M.match(Sym->getName()))151 if ((sym->isDefined() || sym->isCommon()) && m.match(sym->getName()))
653 Res.push_back(Sym);152 res.push_back(sym);
654 return Res;153 return res;
655}
656
657// If there's only one anonymous version definition in a version
658// script file, the script does not actually define any symbol version,
659// but just specifies symbols visibilities.
660void SymbolTable::handleAnonymousVersion() {
661 for (SymbolVersion &Ver : Config->VersionScriptGlobals)
662 assignExactVersion(Ver, VER_NDX_GLOBAL, "global");
663 for (SymbolVersion &Ver : Config->VersionScriptGlobals)
664 assignWildcardVersion(Ver, VER_NDX_GLOBAL);
665 for (SymbolVersion &Ver : Config->VersionScriptLocals)
666 assignExactVersion(Ver, VER_NDX_LOCAL, "local");
667 for (SymbolVersion &Ver : Config->VersionScriptLocals)
668 assignWildcardVersion(Ver, VER_NDX_LOCAL);
669}154}
670155
671// Handles -dynamic-list.156// Handles -dynamic-list.
672void SymbolTable::handleDynamicList() {157void SymbolTable::handleDynamicList() {
673 for (SymbolVersion &Ver : Config->DynamicList) {158 for (SymbolVersion &ver : config->dynamicList) {
674 std::vector<Symbol *> Syms;159 std::vector<Symbol *> syms;
675 if (Ver.HasWildcard)160 if (ver.hasWildcard)
676 Syms = findAllByVersion(Ver);161 syms = findAllByVersion(ver);
677 else162 else
678 Syms = findByVersion(Ver);163 syms = findByVersion(ver);
679164
680 for (Symbol *B : Syms) {165 for (Symbol *b : syms) {
681 if (!Config->Shared)166 if (!config->shared)
682 B->ExportDynamic = true;167 b->exportDynamic = true;
683 else if (B->includeInDynsym())168 else if (b->includeInDynsym())
684 B->IsPreemptible = true;169 b->isPreemptible = true;
685 }170 }
686 }171 }
687}172}
688173
689// Set symbol versions to symbols. This function handles patterns174// Set symbol versions to symbols. This function handles patterns
690// containing no wildcard characters.175// containing no wildcard characters.
691void SymbolTable::assignExactVersion(SymbolVersion Ver, uint16_t VersionId,176void SymbolTable::assignExactVersion(SymbolVersion ver, uint16_t versionId,
692 StringRef VersionName) {177 StringRef versionName) {
693 if (Ver.HasWildcard)178 if (ver.hasWildcard)
694 return;179 return;
695180
696 // Get a list of symbols which we need to assign the version to.181 // Get a list of symbols which we need to assign the version to.
697 std::vector<Symbol *> Syms = findByVersion(Ver);182 std::vector<Symbol *> syms = findByVersion(ver);
698 if (Syms.empty()) {183 if (syms.empty()) {
699 if (!Config->UndefinedVersion)184 if (!config->undefinedVersion)
700 error("version script assignment of '" + VersionName + "' to symbol '" +185 error("version script assignment of '" + versionName + "' to symbol '" +
701 Ver.Name + "' failed: symbol not defined");186 ver.name + "' failed: symbol not defined");
702 return;187 return;
703 }188 }
704189
190 auto getName = [](uint16_t ver) -> std::string {
191 if (ver == VER_NDX_LOCAL)
192 return "VER_NDX_LOCAL";
193 if (ver == VER_NDX_GLOBAL)
194 return "VER_NDX_GLOBAL";
195 return ("version '" + config->versionDefinitions[ver - 2].name + "'").str();
196 };
197
705 // Assign the version.198 // Assign the version.
706 for (Symbol *Sym : Syms) {199 for (Symbol *sym : syms) {
707 // Skip symbols containing version info because symbol versions200 // Skip symbols containing version info because symbol versions
708 // specified by symbol names take precedence over version scripts.201 // specified by symbol names take precedence over version scripts.
709 // See parseSymbolVersion().202 // See parseSymbolVersion().
710 if (Sym->getName().contains('@'))203 if (sym->getName().contains('@'))
204 continue;
205
206 if (sym->versionId == config->defaultSymbolVersion)
207 sym->versionId = versionId;
208 if (sym->versionId == versionId)
711 continue;209 continue;
712210
713 if (Sym->VersionId != Config->DefaultSymbolVersion &&211 warn("attempt to reassign symbol '" + ver.name + "' of " +
714 Sym->VersionId != VersionId)212 getName(sym->versionId) + " to " + getName(versionId));
715 error("duplicate symbol '" + Ver.Name + "' in version script");
716 Sym->VersionId = VersionId;
717 }213 }
718}214}
719215
720void SymbolTable::assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId) {216void SymbolTable::assignWildcardVersion(SymbolVersion ver, uint16_t versionId) {
721 if (!Ver.HasWildcard)217 if (!ver.hasWildcard)
722 return;218 return;
723219
724 // Exact matching takes precendence over fuzzy matching,220 // Exact matching takes precendence over fuzzy matching,
725 // so we set a version to a symbol only if no version has been assigned221 // so we set a version to a symbol only if no version has been assigned
726 // to the symbol. This behavior is compatible with GNU.222 // to the symbol. This behavior is compatible with GNU.
727 for (Symbol *B : findAllByVersion(Ver))223 for (Symbol *b : findAllByVersion(ver))
728 if (B->VersionId == Config->DefaultSymbolVersion)224 if (b->versionId == config->defaultSymbolVersion)
729 B->VersionId = VersionId;225 b->versionId = versionId;
730}226}
731227
732// This function processes version scripts by updating VersionId228// This function processes version scripts by updating the versionId
733// member of symbols.229// member of symbols.
230// If there's only one anonymous version definition in a version
231// script file, the script does not actually define any symbol version,
232// but just specifies symbols visibilities.
734void SymbolTable::scanVersionScript() {233void SymbolTable::scanVersionScript() {
735 // Handle edge cases first.
736 handleAnonymousVersion();
737 handleDynamicList();
738
739 // Now we have version definitions, so we need to set version ids to symbols.
740 // Each version definition has a glob pattern, and all symbols that match
741 // with the pattern get that version.
742
743 // First, we assign versions to exact matching symbols,234 // First, we assign versions to exact matching symbols,
744 // i.e. version definitions not containing any glob meta-characters.235 // i.e. version definitions not containing any glob meta-characters.
745 for (VersionDefinition &V : Config->VersionDefinitions)236 for (SymbolVersion &ver : config->versionScriptGlobals)
746 for (SymbolVersion &Ver : V.Globals)237 assignExactVersion(ver, VER_NDX_GLOBAL, "global");
747 assignExactVersion(Ver, V.Id, V.Name);238 for (SymbolVersion &ver : config->versionScriptLocals)
239 assignExactVersion(ver, VER_NDX_LOCAL, "local");
240 for (VersionDefinition &v : config->versionDefinitions)
241 for (SymbolVersion &ver : v.globals)
242 assignExactVersion(ver, v.id, v.name);
748243
749 // Next, we assign versions to fuzzy matching symbols,244 // Next, we assign versions to fuzzy matching symbols,
750 // i.e. version definitions containing glob meta-characters.245 // i.e. version definitions containing glob meta-characters.
246 for (SymbolVersion &ver : config->versionScriptGlobals)
247 assignWildcardVersion(ver, VER_NDX_GLOBAL);
248 for (SymbolVersion &ver : config->versionScriptLocals)
249 assignWildcardVersion(ver, VER_NDX_LOCAL);
250
751 // Note that because the last match takes precedence over previous matches,251 // Note that because the last match takes precedence over previous matches,
752 // we iterate over the definitions in the reverse order.252 // we iterate over the definitions in the reverse order.
753 for (VersionDefinition &V : llvm::reverse(Config->VersionDefinitions))253 for (VersionDefinition &v : llvm::reverse(config->versionDefinitions))
754 for (SymbolVersion &Ver : V.Globals)254 for (SymbolVersion &ver : v.globals)
755 assignWildcardVersion(Ver, V.Id);255 assignWildcardVersion(ver, v.id);
756256
757 // Symbol themselves might know their versions because symbols257 // Symbol themselves might know their versions because symbols
758 // can contain versions in the form of <name>@<version>.258 // can contain versions in the form of <name>@<version>.
759 // Let them parse and update their names to exclude version suffix.259 // Let them parse and update their names to exclude version suffix.
760 for (Symbol *Sym : SymVector)260 for (Symbol *sym : symVector)
761 Sym->parseSymbolVersion();261 sym->parseSymbolVersion();
762}
763262
764template void SymbolTable::addFile<ELF32LE>(InputFile *);263 // isPreemptible is false at this point. To correctly compute the binding of a
765template void SymbolTable::addFile<ELF32BE>(InputFile *);264 // Defined (which is used by includeInDynsym()), we need to know if it is
766template void SymbolTable::addFile<ELF64LE>(InputFile *);265 // VER_NDX_LOCAL or not. If defaultSymbolVersion is VER_NDX_LOCAL, we should
767template void SymbolTable::addFile<ELF64BE>(InputFile *);266 // compute symbol versions before handling --dynamic-list.
768267 handleDynamicList();
769template Symbol *SymbolTable::addUndefined<ELF32LE>(StringRef, uint8_t, uint8_t,268}
770 uint8_t, bool, InputFile *);
771template Symbol *SymbolTable::addUndefined<ELF32BE>(StringRef, uint8_t, uint8_t,
772 uint8_t, bool, InputFile *);
773template Symbol *SymbolTable::addUndefined<ELF64LE>(StringRef, uint8_t, uint8_t,
774 uint8_t, bool, InputFile *);
775template Symbol *SymbolTable::addUndefined<ELF64BE>(StringRef, uint8_t, uint8_t,
776 uint8_t, bool, InputFile *);
777
778template void SymbolTable::addCombinedLTOObject<ELF32LE>();
779template void SymbolTable::addCombinedLTOObject<ELF32BE>();
780template void SymbolTable::addCombinedLTOObject<ELF64LE>();
781template void SymbolTable::addCombinedLTOObject<ELF64BE>();
782
783template void
784SymbolTable::addLazyArchive<ELF32LE>(StringRef, ArchiveFile &,
785 const object::Archive::Symbol);
786template void
787SymbolTable::addLazyArchive<ELF32BE>(StringRef, ArchiveFile &,
788 const object::Archive::Symbol);
789template void
790SymbolTable::addLazyArchive<ELF64LE>(StringRef, ArchiveFile &,
791 const object::Archive::Symbol);
792template void
793SymbolTable::addLazyArchive<ELF64BE>(StringRef, ArchiveFile &,
794 const object::Archive::Symbol);
795
796template void SymbolTable::addLazyObject<ELF32LE>(StringRef, LazyObjFile &);
797template void SymbolTable::addLazyObject<ELF32BE>(StringRef, LazyObjFile &);
798template void SymbolTable::addLazyObject<ELF64LE>(StringRef, LazyObjFile &);
799template void SymbolTable::addLazyObject<ELF64BE>(StringRef, LazyObjFile &);
800
801template void SymbolTable::fetchLazy<ELF32LE>(Symbol *);
802template void SymbolTable::fetchLazy<ELF32BE>(Symbol *);
803template void SymbolTable::fetchLazy<ELF64LE>(Symbol *);
804template void SymbolTable::fetchLazy<ELF64BE>(Symbol *);
805
806template void SymbolTable::addShared<ELF32LE>(StringRef, SharedFile<ELF32LE> &,
807 const typename ELF32LE::Sym &,
808 uint32_t Alignment, uint32_t);
809template void SymbolTable::addShared<ELF32BE>(StringRef, SharedFile<ELF32BE> &,
810 const typename ELF32BE::Sym &,
811 uint32_t Alignment, uint32_t);
812template void SymbolTable::addShared<ELF64LE>(StringRef, SharedFile<ELF64LE> &,
813 const typename ELF64LE::Sym &,
814 uint32_t Alignment, uint32_t);
815template void SymbolTable::addShared<ELF64BE>(StringRef, SharedFile<ELF64BE> &,
816 const typename ELF64BE::Sym &,
817 uint32_t Alignment, uint32_t);
deps/lld/ELF/SymbolTable.h+32-66
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- SymbolTable.h --------------------------------------------*- C++ -*-===//1//===- SymbolTable.h --------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -11,15 +10,14 @@...@@ -11,15 +10,14 @@
11#define LLD_ELF_SYMBOL_TABLE_H10#define LLD_ELF_SYMBOL_TABLE_H
1211
13#include "InputFiles.h"12#include "InputFiles.h"
14#include "LTO.h"13#include "Symbols.h"
15#include "lld/Common/Strings.h"14#include "lld/Common/Strings.h"
16#include "llvm/ADT/CachedHashString.h"15#include "llvm/ADT/CachedHashString.h"
17#include "llvm/ADT/DenseMap.h"16#include "llvm/ADT/DenseMap.h"
17#include "llvm/ADT/STLExtras.h"
1818
19namespace lld {19namespace lld {
20namespace elf {20namespace elf {
21class Defined;
22class SectionBase;
2321
24// SymbolTable is a bucket of all known symbols, including defined,22// SymbolTable is a bucket of all known symbols, including defined,
25// undefined, or lazy symbols (the last one is symbols in archive23// undefined, or lazy symbols (the last one is symbols in archive
...@@ -35,62 +33,40 @@ class SectionBase;...@@ -35,62 +33,40 @@ class SectionBase;
35// is one add* function per symbol type.33// is one add* function per symbol type.
36class SymbolTable {34class SymbolTable {
37public:35public:
38 template <class ELFT> void addFile(InputFile *File);36 void wrap(Symbol *sym, Symbol *real, Symbol *wrap);
39 template <class ELFT> void addCombinedLTOObject();
40 void wrap(Symbol *Sym, Symbol *Real, Symbol *Wrap);
41
42 ArrayRef<Symbol *> getSymbols() const { return SymVector; }
43
44 template <class ELFT>
45 Symbol *addUndefined(StringRef Name, uint8_t Binding, uint8_t StOther,
46 uint8_t Type, bool CanOmitFromDynSym, 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);
51
52 template <class ELFT>
53 void addShared(StringRef Name, SharedFile<ELFT> &F,
54 const typename ELFT::Sym &Sym, uint32_t Alignment,
55 uint32_t VerdefIndex);
56
57 template <class ELFT>
58 void addLazyArchive(StringRef Name, ArchiveFile &F,
59 const llvm::object::Archive::Symbol S);
6037
61 template <class ELFT> void addLazyObject(StringRef Name, LazyObjFile &Obj);38 void forEachSymbol(llvm::function_ref<void(Symbol *)> fn) {
39 for (Symbol *sym : symVector)
40 if (!sym->isPlaceholder())
41 fn(sym);
42 }
6243
63 Symbol *addBitcode(StringRef Name, uint8_t Binding, uint8_t StOther,44 Symbol *insert(StringRef name);
64 uint8_t Type, bool CanOmitFromDynSym, BitcodeFile &File);
6545
66 Symbol *addCommon(StringRef Name, uint64_t Size, uint32_t Alignment,46 Symbol *addSymbol(const Symbol &New);
67 uint8_t Binding, uint8_t StOther, uint8_t Type,
68 InputFile &File);
69
70 std::pair<Symbol *, bool> insert(StringRef Name, uint8_t Visibility,
71 bool CanOmitFromDynSym, InputFile *File);
72
73 template <class ELFT> void fetchLazy(Symbol *Sym);
7447
75 void scanVersionScript();48 void scanVersionScript();
7649
77 Symbol *find(StringRef Name);50 Symbol *find(StringRef name);
78
79 void trace(StringRef Name);
8051
81 void handleDynamicList();52 void handleDynamicList();
8253
83private:54 // Set of .so files to not link the same shared object file more than once.
84 std::pair<Symbol *, bool> insertName(StringRef Name);55 llvm::DenseMap<StringRef, SharedFile *> soNames;
8556
86 std::vector<Symbol *> findByVersion(SymbolVersion Ver);57 // Comdat groups define "link once" sections. If two comdat groups have the
87 std::vector<Symbol *> findAllByVersion(SymbolVersion Ver);58 // same name, only one of them is linked, and the other is ignored. This map
59 // is used to uniquify them.
60 llvm::DenseMap<llvm::CachedHashStringRef, const InputFile *> comdatGroups;
61
62private:
63 std::vector<Symbol *> findByVersion(SymbolVersion ver);
64 std::vector<Symbol *> findAllByVersion(SymbolVersion ver);
8865
89 llvm::StringMap<std::vector<Symbol *>> &getDemangledSyms();66 llvm::StringMap<std::vector<Symbol *>> &getDemangledSyms();
90 void handleAnonymousVersion();67 void assignExactVersion(SymbolVersion ver, uint16_t versionId,
91 void assignExactVersion(SymbolVersion Ver, uint16_t VersionId,68 StringRef versionName);
92 StringRef VersionName);69 void assignWildcardVersion(SymbolVersion ver, uint16_t versionId);
93 void assignWildcardVersion(SymbolVersion Ver, uint16_t VersionId);
9470
95 // The order the global symbols are in is not defined. We can use an arbitrary71 // The order the global symbols are in is not defined. We can use an arbitrary
96 // order, but it has to be reproducible. That is true even when cross linking.72 // order, but it has to be reproducible. That is true even when cross linking.
...@@ -99,28 +75,18 @@ private:...@@ -99,28 +75,18 @@ private:
99 // but a bit inefficient.75 // but a bit inefficient.
100 // FIXME: Experiment with passing in a custom hashing or sorting the symbols76 // FIXME: Experiment with passing in a custom hashing or sorting the symbols
101 // once symbol resolution is finished.77 // once symbol resolution is finished.
102 llvm::DenseMap<llvm::CachedHashStringRef, int> SymMap;78 llvm::DenseMap<llvm::CachedHashStringRef, int> symMap;
103 std::vector<Symbol *> SymVector;79 std::vector<Symbol *> symVector;
104
105 // Comdat groups define "link once" sections. If two comdat groups have the
106 // same name, only one of them is linked, and the other is ignored. This set
107 // is used to uniquify them.
108 llvm::DenseSet<llvm::CachedHashStringRef> ComdatGroups;
109
110 // Set of .so files to not link the same shared object file more than once.
111 llvm::DenseMap<StringRef, InputFile *> SoNames;
11280
113 // A map from demangled symbol names to their symbol objects.81 // A map from demangled symbol names to their symbol objects.
114 // This mapping is 1:N because two symbols with different versions82 // This mapping is 1:N because two symbols with different versions
115 // can have the same name. We use this map to handle "extern C++ {}"83 // can have the same name. We use this map to handle "extern C++ {}"
116 // directive in version scripts.84 // directive in version scripts.
117 llvm::Optional<llvm::StringMap<std::vector<Symbol *>>> DemangledSyms;85 llvm::Optional<llvm::StringMap<std::vector<Symbol *>>> demangledSyms;
118
119 // For LTO.
120 std::unique_ptr<BitcodeCompiler> LTO;
121};86};
12287
123extern SymbolTable *Symtab;88extern SymbolTable *symtab;
89
124} // namespace elf90} // namespace elf
125} // namespace lld91} // namespace lld
12692
deps/lld/ELF/Symbols.cpp+489-138
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Symbols.cpp --------------------------------------------------------===//1//===- Symbols.cpp --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -27,40 +26,36 @@ using namespace llvm::ELF;...@@ -27,40 +26,36 @@ using namespace llvm::ELF;
27using namespace lld;26using namespace lld;
28using namespace lld::elf;27using namespace lld::elf;
2928
30Defined *ElfSym::Bss;29Defined *ElfSym::bss;
31Defined *ElfSym::Etext1;30Defined *ElfSym::etext1;
32Defined *ElfSym::Etext2;31Defined *ElfSym::etext2;
33Defined *ElfSym::Edata1;32Defined *ElfSym::edata1;
34Defined *ElfSym::Edata2;33Defined *ElfSym::edata2;
35Defined *ElfSym::End1;34Defined *ElfSym::end1;
36Defined *ElfSym::End2;35Defined *ElfSym::end2;
37Defined *ElfSym::GlobalOffsetTable;36Defined *ElfSym::globalOffsetTable;
38Defined *ElfSym::MipsGp;37Defined *ElfSym::mipsGp;
39Defined *ElfSym::MipsGpDisp;38Defined *ElfSym::mipsGpDisp;
40Defined *ElfSym::MipsLocalGp;39Defined *ElfSym::mipsLocalGp;
41Defined *ElfSym::RelaIpltStart;40Defined *ElfSym::relaIpltStart;
42Defined *ElfSym::RelaIpltEnd;41Defined *ElfSym::relaIpltEnd;
4342Defined *ElfSym::riscvGlobalPointer;
44static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {43Defined *ElfSym::tlsModuleBase;
45 switch (Sym.kind()) {44
45static uint64_t getSymVA(const Symbol &sym, int64_t &addend) {
46 switch (sym.kind()) {
46 case Symbol::DefinedKind: {47 case Symbol::DefinedKind: {
47 auto &D = cast<Defined>(Sym);48 auto &d = cast<Defined>(sym);
48 SectionBase *IS = D.Section;49 SectionBase *isec = d.section;
49
50 // According to the ELF spec reference to a local symbol from outside
51 // the group are not allowed. Unfortunately .eh_frame breaks that rule
52 // and must be treated specially. For now we just replace the symbol with
53 // 0.
54 if (IS == &InputSection::Discarded)
55 return 0;
5650
57 // This is an absolute symbol.51 // This is an absolute symbol.
58 if (!IS)52 if (!isec)
59 return D.Value;53 return d.value;
6054
61 IS = IS->Repl;55 assert(isec != &InputSection::discarded);
56 isec = isec->repl;
6257
63 uint64_t Offset = D.Value;58 uint64_t offset = d.value;
6459
65 // An object in an SHF_MERGE section might be referenced via a60 // An object in an SHF_MERGE section might be referenced via a
66 // section symbol (as a hack for reducing the number of local61 // section symbol (as a hack for reducing the number of local
...@@ -73,9 +68,9 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {...@@ -73,9 +68,9 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
73 // To make this work, we incorporate the addend into the section68 // To make this work, we incorporate the addend into the section
74 // offset (and zero out the addend for later processing) so that69 // offset (and zero out the addend for later processing) so that
75 // we find the right object in the section.70 // we find the right object in the section.
76 if (D.isSection()) {71 if (d.isSection()) {
77 Offset += Addend;72 offset += addend;
78 Addend = 0;73 addend = 0;
79 }74 }
8075
81 // In the typical case, this is actually very simple and boils76 // In the typical case, this is actually very simple and boils
...@@ -88,83 +83,107 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {...@@ -88,83 +83,107 @@ static uint64_t getSymVA(const Symbol &Sym, int64_t &Addend) {
88 // If you understand the data structures involved with this next83 // If you understand the data structures involved with this next
89 // line (and how they get built), then you have a pretty good84 // line (and how they get built), then you have a pretty good
90 // understanding of the linker.85 // understanding of the linker.
91 uint64_t VA = IS->getVA(Offset);86 uint64_t va = isec->getVA(offset);
9287
93 if (D.isTls() && !Config->Relocatable) {88 // MIPS relocatable files can mix regular and microMIPS code.
89 // Linker needs to distinguish such code. To do so microMIPS
90 // symbols has the `STO_MIPS_MICROMIPS` flag in the `st_other`
91 // field. Unfortunately, the `MIPS::relocateOne()` method has
92 // a symbol value only. To pass type of the symbol (regular/microMIPS)
93 // to that routine as well as other places where we write
94 // a symbol value as-is (.dynamic section, `Elf_Ehdr::e_entry`
95 // field etc) do the same trick as compiler uses to mark microMIPS
96 // for CPU - set the less-significant bit.
97 if (config->emachine == EM_MIPS && isMicroMips() &&
98 ((sym.stOther & STO_MIPS_MICROMIPS) || sym.needsPltAddr))
99 va |= 1;
100
101 if (d.isTls() && !config->relocatable) {
94 // Use the address of the TLS segment's first section rather than the102 // Use the address of the TLS segment's first section rather than the
95 // segment's address, because segment addresses aren't initialized until103 // segment's address, because segment addresses aren't initialized until
96 // after sections are finalized. (e.g. Measuring the size of .rela.dyn104 // after sections are finalized. (e.g. Measuring the size of .rela.dyn
97 // for Android relocation packing requires knowing TLS symbol addresses105 // for Android relocation packing requires knowing TLS symbol addresses
98 // during section finalization.)106 // during section finalization.)
99 if (!Out::TlsPhdr || !Out::TlsPhdr->FirstSec)107 if (!Out::tlsPhdr || !Out::tlsPhdr->firstSec)
100 fatal(toString(D.File) +108 fatal(toString(d.file) +
101 " has an STT_TLS symbol but doesn't have an SHF_TLS section");109 " has an STT_TLS symbol but doesn't have an SHF_TLS section");
102 return VA - Out::TlsPhdr->FirstSec->Addr;110 return va - Out::tlsPhdr->firstSec->addr;
103 }111 }
104 return VA;112 return va;
105 }113 }
106 case Symbol::SharedKind:114 case Symbol::SharedKind:
107 case Symbol::UndefinedKind:115 case Symbol::UndefinedKind:
108 return 0;116 return 0;
109 case Symbol::LazyArchiveKind:117 case Symbol::LazyArchiveKind:
110 case Symbol::LazyObjectKind:118 case Symbol::LazyObjectKind:
111 assert(Sym.IsUsedInRegularObj && "lazy symbol reached writer");119 assert(sym.isUsedInRegularObj && "lazy symbol reached writer");
112 return 0;120 return 0;
121 case Symbol::CommonKind:
122 llvm_unreachable("common symbol reached writer");
113 case Symbol::PlaceholderKind:123 case Symbol::PlaceholderKind:
114 llvm_unreachable("placeholder symbol reached writer");124 llvm_unreachable("placeholder symbol reached writer");
115 }125 }
116 llvm_unreachable("invalid symbol kind");126 llvm_unreachable("invalid symbol kind");
117}127}
118128
119uint64_t Symbol::getVA(int64_t Addend) const {129uint64_t Symbol::getVA(int64_t addend) const {
120 uint64_t OutVA = getSymVA(*this, Addend);130 uint64_t outVA = getSymVA(*this, addend);
121 return OutVA + Addend;131 return outVA + addend;
122}132}
123133
124uint64_t Symbol::getGotVA() const { return In.Got->getVA() + getGotOffset(); }134uint64_t Symbol::getGotVA() const {
125135 if (gotInIgot)
126uint64_t Symbol::getGotOffset() const {136 return in.igotPlt->getVA() + getGotPltOffset();
127 return GotIndex * Target->GotEntrySize;137 return in.got->getVA() + getGotOffset();
128}138}
129139
140uint64_t Symbol::getGotOffset() const { return gotIndex * config->wordsize; }
141
130uint64_t Symbol::getGotPltVA() const {142uint64_t Symbol::getGotPltVA() const {
131 if (this->IsInIgot)143 if (isInIplt)
132 return In.IgotPlt->getVA() + getGotPltOffset();144 return in.igotPlt->getVA() + getGotPltOffset();
133 return In.GotPlt->getVA() + getGotPltOffset();145 return in.gotPlt->getVA() + getGotPltOffset();
134}146}
135147
136uint64_t Symbol::getGotPltOffset() const {148uint64_t Symbol::getGotPltOffset() const {
137 if (IsInIgot)149 if (isInIplt)
138 return PltIndex * Target->GotPltEntrySize;150 return pltIndex * config->wordsize;
139 return (PltIndex + Target->GotPltHeaderEntriesNum) * Target->GotPltEntrySize;151 return (pltIndex + target->gotPltHeaderEntriesNum) * config->wordsize;
140}152}
141153
142uint64_t Symbol::getPPC64LongBranchOffset() const {154uint64_t Symbol::getPPC64LongBranchOffset() const {
143 assert(PPC64BranchltIndex != 0xffff);155 assert(ppc64BranchltIndex != 0xffff);
144 return PPC64BranchltIndex * Target->GotPltEntrySize;156 return ppc64BranchltIndex * config->wordsize;
145}157}
146158
147uint64_t Symbol::getPltVA() const {159uint64_t Symbol::getPltVA() const {
148 PltSection *Plt = IsInIplt ? In.Iplt : In.Plt;160 PltSection *plt = isInIplt ? in.iplt : in.plt;
149 return Plt->getVA() + Plt->HeaderSize + PltIndex * Target->PltEntrySize;161 uint64_t outVA =
162 plt->getVA() + plt->headerSize + pltIndex * target->pltEntrySize;
163 // While linking microMIPS code PLT code are always microMIPS
164 // code. Set the less-significant bit to track that fact.
165 // See detailed comment in the `getSymVA` function.
166 if (config->emachine == EM_MIPS && isMicroMips())
167 outVA |= 1;
168 return outVA;
150}169}
151170
152uint64_t Symbol::getPPC64LongBranchTableVA() const {171uint64_t Symbol::getPPC64LongBranchTableVA() const {
153 assert(PPC64BranchltIndex != 0xffff);172 assert(ppc64BranchltIndex != 0xffff);
154 return In.PPC64LongBranchTarget->getVA() +173 return in.ppc64LongBranchTarget->getVA() +
155 PPC64BranchltIndex * Target->GotPltEntrySize;174 ppc64BranchltIndex * config->wordsize;
156}175}
157176
158uint64_t Symbol::getSize() const {177uint64_t Symbol::getSize() const {
159 if (const auto *DR = dyn_cast<Defined>(this))178 if (const auto *dr = dyn_cast<Defined>(this))
160 return DR->Size;179 return dr->size;
161 return cast<SharedSymbol>(this)->Size;180 return cast<SharedSymbol>(this)->size;
162}181}
163182
164OutputSection *Symbol::getOutputSection() const {183OutputSection *Symbol::getOutputSection() const {
165 if (auto *S = dyn_cast<Defined>(this)) {184 if (auto *s = dyn_cast<Defined>(this)) {
166 if (auto *Sec = S->Section)185 if (auto *sec = s->section)
167 return Sec->Repl->getOutputSection();186 return sec->repl->getOutputSection();
168 return nullptr;187 return nullptr;
169 }188 }
170 return nullptr;189 return nullptr;
...@@ -173,16 +192,16 @@ OutputSection *Symbol::getOutputSection() const {...@@ -173,16 +192,16 @@ OutputSection *Symbol::getOutputSection() const {
173// If a symbol name contains '@', the characters after that is192// If a symbol name contains '@', the characters after that is
174// a symbol version name. This function parses that.193// a symbol version name. This function parses that.
175void Symbol::parseSymbolVersion() {194void Symbol::parseSymbolVersion() {
176 StringRef S = getName();195 StringRef s = getName();
177 size_t Pos = S.find('@');196 size_t pos = s.find('@');
178 if (Pos == 0 || Pos == StringRef::npos)197 if (pos == 0 || pos == StringRef::npos)
179 return;198 return;
180 StringRef Verstr = S.substr(Pos + 1);199 StringRef verstr = s.substr(pos + 1);
181 if (Verstr.empty())200 if (verstr.empty())
182 return;201 return;
183202
184 // Truncate the symbol name so that it doesn't include the version string.203 // Truncate the symbol name so that it doesn't include the version string.
185 NameSize = Pos;204 nameSize = pos;
186205
187 // If this is not in this DSO, it is not a definition.206 // If this is not in this DSO, it is not a definition.
188 if (!isDefined())207 if (!isDefined())
...@@ -190,18 +209,18 @@ void Symbol::parseSymbolVersion() {...@@ -190,18 +209,18 @@ void Symbol::parseSymbolVersion() {
190209
191 // '@@' in a symbol name means the default version.210 // '@@' in a symbol name means the default version.
192 // It is usually the most recent one.211 // It is usually the most recent one.
193 bool IsDefault = (Verstr[0] == '@');212 bool isDefault = (verstr[0] == '@');
194 if (IsDefault)213 if (isDefault)
195 Verstr = Verstr.substr(1);214 verstr = verstr.substr(1);
196215
197 for (VersionDefinition &Ver : Config->VersionDefinitions) {216 for (VersionDefinition &ver : config->versionDefinitions) {
198 if (Ver.Name != Verstr)217 if (ver.name != verstr)
199 continue;218 continue;
200219
201 if (IsDefault)220 if (isDefault)
202 VersionId = Ver.Id;221 versionId = ver.id;
203 else222 else
204 VersionId = Ver.Id | VERSYM_HIDDEN;223 versionId = ver.id | VERSYM_HIDDEN;
205 return;224 return;
206 }225 }
207226
...@@ -211,63 +230,79 @@ void Symbol::parseSymbolVersion() {...@@ -211,63 +230,79 @@ void Symbol::parseSymbolVersion() {
211 // so we do not report error in this case. We also do not error230 // so we do not report error in this case. We also do not error
212 // if the symbol has a local version as it won't be in the dynamic231 // if the symbol has a local version as it won't be in the dynamic
213 // symbol table.232 // symbol table.
214 if (Config->Shared && VersionId != VER_NDX_LOCAL)233 if (config->shared && versionId != VER_NDX_LOCAL)
215 error(toString(File) + ": symbol " + S + " has undefined version " +234 error(toString(file) + ": symbol " + s + " has undefined version " +
216 Verstr);235 verstr);
217}236}
218237
219InputFile *LazyArchive::fetch() { return cast<ArchiveFile>(File)->fetch(Sym); }238void Symbol::fetch() const {
239 if (auto *sym = dyn_cast<LazyArchive>(this)) {
240 cast<ArchiveFile>(sym->file)->fetch(sym->sym);
241 return;
242 }
243
244 if (auto *sym = dyn_cast<LazyObject>(this)) {
245 dyn_cast<LazyObjFile>(sym->file)->fetch();
246 return;
247 }
248
249 llvm_unreachable("Symbol::fetch() is called on a non-lazy symbol");
250}
220251
221MemoryBufferRef LazyArchive::getMemberBuffer() {252MemoryBufferRef LazyArchive::getMemberBuffer() {
222 Archive::Child C = CHECK(253 Archive::Child c = CHECK(
223 Sym.getMember(), "could not get the member for symbol " + Sym.getName());254 sym.getMember(), "could not get the member for symbol " + sym.getName());
224255
225 return CHECK(C.getMemoryBufferRef(),256 return CHECK(c.getMemoryBufferRef(),
226 "could not get the buffer for the member defining symbol " +257 "could not get the buffer for the member defining symbol " +
227 Sym.getName());258 sym.getName());
228}259}
229260
230uint8_t Symbol::computeBinding() const {261uint8_t Symbol::computeBinding() const {
231 if (Config->Relocatable)262 if (config->relocatable)
232 return Binding;263 return binding;
233 if (Visibility != STV_DEFAULT && Visibility != STV_PROTECTED)264 if (visibility != STV_DEFAULT && visibility != STV_PROTECTED)
234 return STB_LOCAL;265 return STB_LOCAL;
235 if (VersionId == VER_NDX_LOCAL && isDefined() && !IsPreemptible)266 if (versionId == VER_NDX_LOCAL && isDefined() && !isPreemptible)
236 return STB_LOCAL;267 return STB_LOCAL;
237 if (!Config->GnuUnique && Binding == STB_GNU_UNIQUE)268 if (!config->gnuUnique && binding == STB_GNU_UNIQUE)
238 return STB_GLOBAL;269 return STB_GLOBAL;
239 return Binding;270 return binding;
240}271}
241272
242bool Symbol::includeInDynsym() const {273bool Symbol::includeInDynsym() const {
243 if (!Config->HasDynSymTab)274 if (!config->hasDynSymTab)
244 return false;275 return false;
245 if (computeBinding() == STB_LOCAL)276 if (computeBinding() == STB_LOCAL)
246 return false;277 return false;
247 if (!isDefined())278
248 return true;279 // If a PIE binary was not linked against any shared libraries, then we can
249 return ExportDynamic;280 // safely drop weak undef symbols from .dynsym.
281 if (isUndefWeak() && config->pie && sharedFiles.empty())
282 return false;
283
284 return isUndefined() || isShared() || exportDynamic;
250}285}
251286
252// Print out a log message for --trace-symbol.287// Print out a log message for --trace-symbol.
253void elf::printTraceSymbol(Symbol *Sym) {288void elf::printTraceSymbol(const Symbol *sym) {
254 std::string S;289 std::string s;
255 if (Sym->isUndefined())290 if (sym->isUndefined())
256 S = ": reference to ";291 s = ": reference to ";
257 else if (Sym->isLazy())292 else if (sym->isLazy())
258 S = ": lazy definition of ";293 s = ": lazy definition of ";
259 else if (Sym->isShared())294 else if (sym->isShared())
260 S = ": shared definition of ";295 s = ": shared definition of ";
261 else if (dyn_cast_or_null<BssSection>(cast<Defined>(Sym)->Section))296 else if (sym->isCommon())
262 S = ": common definition of ";297 s = ": common definition of ";
263 else298 else
264 S = ": definition of ";299 s = ": definition of ";
265300
266 message(toString(Sym->File) + S + Sym->getName());301 message(toString(sym->file) + s + sym->getName());
267}302}
268303
269void elf::maybeWarnUnorderableSymbol(const Symbol *Sym) {304void elf::maybeWarnUnorderableSymbol(const Symbol *sym) {
270 if (!Config->WarnSymbolOrdering)305 if (!config->warnSymbolOrdering)
271 return;306 return;
272307
273 // If UnresolvedPolicy::Ignore is used, no "undefined symbol" error/warning308 // If UnresolvedPolicy::Ignore is used, no "undefined symbol" error/warning
...@@ -275,31 +310,347 @@ void elf::maybeWarnUnorderableSymbol(const Symbol *Sym) {...@@ -275,31 +310,347 @@ void elf::maybeWarnUnorderableSymbol(const Symbol *Sym) {
275 //310 //
276 // Note, ld.bfd --symbol-ordering-file= does not warn on undefined symbols,311 // Note, ld.bfd --symbol-ordering-file= does not warn on undefined symbols,
277 // but we don't have to be compatible here.312 // but we don't have to be compatible here.
278 if (Sym->isUndefined() &&313 if (sym->isUndefined() &&
279 Config->UnresolvedSymbols == UnresolvedPolicy::Ignore)314 config->unresolvedSymbols == UnresolvedPolicy::Ignore)
280 return;315 return;
281316
282 const InputFile *File = Sym->File;317 const InputFile *file = sym->file;
283 auto *D = dyn_cast<Defined>(Sym);318 auto *d = dyn_cast<Defined>(sym);
284319
285 auto Warn = [&](StringRef S) { warn(toString(File) + S + Sym->getName()); };320 auto report = [&](StringRef s) { warn(toString(file) + s + sym->getName()); };
286321
287 if (Sym->isUndefined())322 if (sym->isUndefined())
288 Warn(": unable to order undefined symbol: ");323 report(": unable to order undefined symbol: ");
289 else if (Sym->isShared())324 else if (sym->isShared())
290 Warn(": unable to order shared symbol: ");325 report(": unable to order shared symbol: ");
291 else if (D && !D->Section)326 else if (d && !d->section)
292 Warn(": unable to order absolute symbol: ");327 report(": unable to order absolute symbol: ");
293 else if (D && isa<OutputSection>(D->Section))328 else if (d && isa<OutputSection>(d->section))
294 Warn(": unable to order synthetic symbol: ");329 report(": unable to order synthetic symbol: ");
295 else if (D && !D->Section->Repl->Live)330 else if (d && !d->section->repl->isLive())
296 Warn(": unable to order discarded symbol: ");331 report(": unable to order discarded symbol: ");
297}332}
298333
299// Returns a symbol for an error message.334// Returns a symbol for an error message.
300std::string lld::toString(const Symbol &B) {335std::string lld::toString(const Symbol &b) {
301 if (Config->Demangle)336 if (config->demangle)
302 if (Optional<std::string> S = demangleItanium(B.getName()))337 if (Optional<std::string> s = demangleItanium(b.getName()))
303 return *S;338 return *s;
304 return B.getName();339 return b.getName();
340}
341
342static uint8_t getMinVisibility(uint8_t va, uint8_t vb) {
343 if (va == STV_DEFAULT)
344 return vb;
345 if (vb == STV_DEFAULT)
346 return va;
347 return std::min(va, vb);
348}
349
350// Merge symbol properties.
351//
352// When we have many symbols of the same name, we choose one of them,
353// and that's the result of symbol resolution. However, symbols that
354// were not chosen still affect some symbol properties.
355void Symbol::mergeProperties(const Symbol &other) {
356 if (other.exportDynamic)
357 exportDynamic = true;
358 if (other.isUsedInRegularObj)
359 isUsedInRegularObj = true;
360
361 // DSO symbols do not affect visibility in the output.
362 if (!other.isShared())
363 visibility = getMinVisibility(visibility, other.visibility);
364}
365
366void Symbol::resolve(const Symbol &other) {
367 mergeProperties(other);
368
369 if (isPlaceholder()) {
370 replace(other);
371 return;
372 }
373
374 switch (other.kind()) {
375 case Symbol::UndefinedKind:
376 resolveUndefined(cast<Undefined>(other));
377 break;
378 case Symbol::CommonKind:
379 resolveCommon(cast<CommonSymbol>(other));
380 break;
381 case Symbol::DefinedKind:
382 resolveDefined(cast<Defined>(other));
383 break;
384 case Symbol::LazyArchiveKind:
385 resolveLazy(cast<LazyArchive>(other));
386 break;
387 case Symbol::LazyObjectKind:
388 resolveLazy(cast<LazyObject>(other));
389 break;
390 case Symbol::SharedKind:
391 resolveShared(cast<SharedSymbol>(other));
392 break;
393 case Symbol::PlaceholderKind:
394 llvm_unreachable("bad symbol kind");
395 }
396}
397
398void Symbol::resolveUndefined(const Undefined &other) {
399 // An undefined symbol with non default visibility must be satisfied
400 // in the same DSO.
401 //
402 // If this is a non-weak defined symbol in a discarded section, override the
403 // existing undefined symbol for better error message later.
404 if ((isShared() && other.visibility != STV_DEFAULT) ||
405 (isUndefined() && other.binding != STB_WEAK && other.discardedSecIdx)) {
406 replace(other);
407 return;
408 }
409
410 if (traced)
411 printTraceSymbol(&other);
412
413 if (isLazy()) {
414 // An undefined weak will not fetch archive members. See comment on Lazy in
415 // Symbols.h for the details.
416 if (other.binding == STB_WEAK) {
417 binding = STB_WEAK;
418 type = other.type;
419 return;
420 }
421
422 // Do extra check for --warn-backrefs.
423 //
424 // --warn-backrefs is an option to prevent an undefined reference from
425 // fetching an archive member written earlier in the command line. It can be
426 // used to keep compatibility with GNU linkers to some degree.
427 // I'll explain the feature and why you may find it useful in this comment.
428 //
429 // lld's symbol resolution semantics is more relaxed than traditional Unix
430 // linkers. For example,
431 //
432 // ld.lld foo.a bar.o
433 //
434 // succeeds even if bar.o contains an undefined symbol that has to be
435 // resolved by some object file in foo.a. Traditional Unix linkers don't
436 // allow this kind of backward reference, as they visit each file only once
437 // from left to right in the command line while resolving all undefined
438 // symbols at the moment of visiting.
439 //
440 // In the above case, since there's no undefined symbol when a linker visits
441 // foo.a, no files are pulled out from foo.a, and because the linker forgets
442 // about foo.a after visiting, it can't resolve undefined symbols in bar.o
443 // that could have been resolved otherwise.
444 //
445 // That lld accepts more relaxed form means that (besides it'd make more
446 // sense) you can accidentally write a command line or a build file that
447 // works only with lld, even if you have a plan to distribute it to wider
448 // users who may be using GNU linkers. With --warn-backrefs, you can detect
449 // a library order that doesn't work with other Unix linkers.
450 //
451 // The option is also useful to detect cyclic dependencies between static
452 // archives. Again, lld accepts
453 //
454 // ld.lld foo.a bar.a
455 //
456 // even if foo.a and bar.a depend on each other. With --warn-backrefs, it is
457 // handled as an error.
458 //
459 // Here is how the option works. We assign a group ID to each file. A file
460 // with a smaller group ID can pull out object files from an archive file
461 // with an equal or greater group ID. Otherwise, it is a reverse dependency
462 // and an error.
463 //
464 // A file outside --{start,end}-group gets a fresh ID when instantiated. All
465 // files within the same --{start,end}-group get the same group ID. E.g.
466 //
467 // ld.lld A B --start-group C D --end-group E
468 //
469 // A forms group 0. B form group 1. C and D (including their member object
470 // files) form group 2. E forms group 3. I think that you can see how this
471 // group assignment rule simulates the traditional linker's semantics.
472 bool backref = config->warnBackrefs && other.file &&
473 file->groupId < other.file->groupId;
474 fetch();
475
476 // We don't report backward references to weak symbols as they can be
477 // overridden later.
478 if (backref && !isWeak())
479 warn("backward reference detected: " + other.getName() + " in " +
480 toString(other.file) + " refers to " + toString(file));
481 return;
482 }
483
484 // Undefined symbols in a SharedFile do not change the binding.
485 if (dyn_cast_or_null<SharedFile>(other.file))
486 return;
487
488 if (isUndefined()) {
489 // The binding may "upgrade" from weak to non-weak.
490 if (other.binding != STB_WEAK)
491 binding = other.binding;
492 } else if (auto *s = dyn_cast<SharedSymbol>(this)) {
493 // The binding of a SharedSymbol will be weak if there is at least one
494 // reference and all are weak. The binding has one opportunity to change to
495 // weak: if the first reference is weak.
496 if (other.binding != STB_WEAK || !s->referenced)
497 binding = other.binding;
498 s->referenced = true;
499 }
500}
501
502// Using .symver foo,foo@@VER unfortunately creates two symbols: foo and
503// foo@@VER. We want to effectively ignore foo, so give precedence to
504// foo@@VER.
505// FIXME: If users can transition to using
506// .symver foo,foo@@@VER
507// we can delete this hack.
508static int compareVersion(StringRef a, StringRef b) {
509 bool x = a.contains("@@");
510 bool y = b.contains("@@");
511 if (!x && y)
512 return 1;
513 if (x && !y)
514 return -1;
515 return 0;
516}
517
518// Compare two symbols. Return 1 if the new symbol should win, -1 if
519// the new symbol should lose, or 0 if there is a conflict.
520int Symbol::compare(const Symbol *other) const {
521 assert(other->isDefined() || other->isCommon());
522
523 if (!isDefined() && !isCommon())
524 return 1;
525
526 if (int cmp = compareVersion(getName(), other->getName()))
527 return cmp;
528
529 if (other->isWeak())
530 return -1;
531
532 if (isWeak())
533 return 1;
534
535 if (isCommon() && other->isCommon()) {
536 if (config->warnCommon)
537 warn("multiple common of " + getName());
538 return 0;
539 }
540
541 if (isCommon()) {
542 if (config->warnCommon)
543 warn("common " + getName() + " is overridden");
544 return 1;
545 }
546
547 if (other->isCommon()) {
548 if (config->warnCommon)
549 warn("common " + getName() + " is overridden");
550 return -1;
551 }
552
553 auto *oldSym = cast<Defined>(this);
554 auto *newSym = cast<Defined>(other);
555
556 if (other->file && isa<BitcodeFile>(other->file))
557 return 0;
558
559 if (!oldSym->section && !newSym->section && oldSym->value == newSym->value &&
560 newSym->binding == STB_GLOBAL)
561 return -1;
562
563 return 0;
564}
565
566static void reportDuplicate(Symbol *sym, InputFile *newFile,
567 InputSectionBase *errSec, uint64_t errOffset) {
568 if (config->allowMultipleDefinition)
569 return;
570
571 Defined *d = cast<Defined>(sym);
572 if (!d->section || !errSec) {
573 error("duplicate symbol: " + toString(*sym) + "\n>>> defined in " +
574 toString(sym->file) + "\n>>> defined in " + toString(newFile));
575 return;
576 }
577
578 // Construct and print an error message in the form of:
579 //
580 // ld.lld: error: duplicate symbol: foo
581 // >>> defined at bar.c:30
582 // >>> bar.o (/home/alice/src/bar.o)
583 // >>> defined at baz.c:563
584 // >>> baz.o in archive libbaz.a
585 auto *sec1 = cast<InputSectionBase>(d->section);
586 std::string src1 = sec1->getSrcMsg(*sym, d->value);
587 std::string obj1 = sec1->getObjMsg(d->value);
588 std::string src2 = errSec->getSrcMsg(*sym, errOffset);
589 std::string obj2 = errSec->getObjMsg(errOffset);
590
591 std::string msg = "duplicate symbol: " + toString(*sym) + "\n>>> defined at ";
592 if (!src1.empty())
593 msg += src1 + "\n>>> ";
594 msg += obj1 + "\n>>> defined at ";
595 if (!src2.empty())
596 msg += src2 + "\n>>> ";
597 msg += obj2;
598 error(msg);
599}
600
601void Symbol::resolveCommon(const CommonSymbol &other) {
602 int cmp = compare(&other);
603 if (cmp < 0)
604 return;
605
606 if (cmp > 0) {
607 replace(other);
608 return;
609 }
610
611 CommonSymbol *oldSym = cast<CommonSymbol>(this);
612
613 oldSym->alignment = std::max(oldSym->alignment, other.alignment);
614 if (oldSym->size < other.size) {
615 oldSym->file = other.file;
616 oldSym->size = other.size;
617 }
618}
619
620void Symbol::resolveDefined(const Defined &other) {
621 int cmp = compare(&other);
622 if (cmp > 0)
623 replace(other);
624 else if (cmp == 0)
625 reportDuplicate(this, other.file,
626 dyn_cast_or_null<InputSectionBase>(other.section),
627 other.value);
628}
629
630template <class LazyT> void Symbol::resolveLazy(const LazyT &other) {
631 if (!isUndefined())
632 return;
633
634 // An undefined weak will not fetch archive members. See comment on Lazy in
635 // Symbols.h for the details.
636 if (isWeak()) {
637 uint8_t ty = type;
638 replace(other);
639 type = ty;
640 binding = STB_WEAK;
641 return;
642 }
643
644 other.fetch();
645}
646
647void Symbol::resolveShared(const SharedSymbol &other) {
648 if (visibility == STV_DEFAULT && (isUndefined() || isLazy())) {
649 // An undefined symbol with non default visibility must be satisfied
650 // in the same DSO.
651 uint8_t bind = binding;
652 replace(other);
653 binding = bind;
654 cast<SharedSymbol>(this)->referenced = true;
655 }
305}656}
deps/lld/ELF/Symbols.h+298-163
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Symbols.h ------------------------------------------------*- C++ -*-===//1//===- Symbols.h ------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -14,6 +13,7 @@...@@ -14,6 +13,7 @@
14#ifndef LLD_ELF_SYMBOLS_H13#ifndef LLD_ELF_SYMBOLS_H
15#define LLD_ELF_SYMBOLS_H14#define LLD_ELF_SYMBOLS_H
1615
16#include "InputFiles.h"
17#include "InputSection.h"17#include "InputSection.h"
18#include "lld/Common/LLVM.h"18#include "lld/Common/LLVM.h"
19#include "lld/Common/Strings.h"19#include "lld/Common/Strings.h"
...@@ -22,8 +22,14 @@...@@ -22,8 +22,14 @@
2222
23namespace lld {23namespace lld {
24namespace elf {24namespace elf {
25class Symbol;25class CommonSymbol;
26class Defined;
26class InputFile;27class InputFile;
28class LazyArchive;
29class LazyObject;
30class SharedSymbol;
31class Symbol;
32class Undefined;
27} // namespace elf33} // namespace elf
2834
29std::string toString(const elf::Symbol &);35std::string toString(const elf::Symbol &);
...@@ -31,15 +37,6 @@ std::string toString(const elf::InputFile *);...@@ -31,15 +37,6 @@ std::string toString(const elf::InputFile *);
3137
32namespace elf {38namespace elf {
3339
34class ArchiveFile;
35class BitcodeFile;
36class BssSection;
37class InputFile;
38class LazyObjFile;
39template <class ELFT> class ObjFile;
40class OutputSection;
41template <class ELFT> class SharedFile;
42
43// This is a StringRef-like container that doesn't run strlen().40// This is a StringRef-like container that doesn't run strlen().
44//41//
45// ELF string tables contain a lot of null-terminated strings. Most of them42// ELF string tables contain a lot of null-terminated strings. Most of them
...@@ -47,11 +44,11 @@ template <class ELFT> class SharedFile;...@@ -47,11 +44,11 @@ template <class ELFT> class SharedFile;
47// and the linker doesn't use local symbol names for name resolution. So, we44// and the linker doesn't use local symbol names for name resolution. So, we
48// use this class to represents strings read from string tables.45// use this class to represents strings read from string tables.
49struct StringRefZ {46struct StringRefZ {
50 StringRefZ(const char *S) : Data(S), Size(-1) {}47 StringRefZ(const char *s) : data(s), size(-1) {}
51 StringRefZ(StringRef S) : Data(S.data()), Size(S.size()) {}48 StringRefZ(StringRef s) : data(s.data()), size(s.size()) {}
5249
53 const char *Data;50 const char *data;
54 const uint32_t Size;51 const uint32_t size;
55};52};
5653
57// The base class for real symbol classes.54// The base class for real symbol classes.
...@@ -60,85 +57,91 @@ public:...@@ -60,85 +57,91 @@ public:
60 enum Kind {57 enum Kind {
61 PlaceholderKind,58 PlaceholderKind,
62 DefinedKind,59 DefinedKind,
60 CommonKind,
63 SharedKind,61 SharedKind,
64 UndefinedKind,62 UndefinedKind,
65 LazyArchiveKind,63 LazyArchiveKind,
66 LazyObjectKind,64 LazyObjectKind,
67 };65 };
6866
69 Kind kind() const { return static_cast<Kind>(SymbolKind); }67 Kind kind() const { return static_cast<Kind>(symbolKind); }
7068
71 // The file from which this symbol was created.69 // The file from which this symbol was created.
72 InputFile *File;70 InputFile *file;
7371
74protected:72protected:
75 const char *NameData;73 const char *nameData;
76 mutable uint32_t NameSize;74 mutable uint32_t nameSize;
7775
78public:76public:
79 uint32_t DynsymIndex = 0;77 uint32_t dynsymIndex = 0;
80 uint32_t GotIndex = -1;78 uint32_t gotIndex = -1;
81 uint32_t PltIndex = -1;79 uint32_t pltIndex = -1;
8280
83 uint32_t GlobalDynIndex = -1;81 uint32_t globalDynIndex = -1;
8482
85 // This field is a index to the symbol's version definition.83 // This field is a index to the symbol's version definition.
86 uint32_t VerdefIndex = -1;84 uint32_t verdefIndex = -1;
8785
88 // Version definition index.86 // Version definition index.
89 uint16_t VersionId;87 uint16_t versionId;
9088
91 // An index into the .branch_lt section on PPC64.89 // An index into the .branch_lt section on PPC64.
92 uint16_t PPC64BranchltIndex = -1;90 uint16_t ppc64BranchltIndex = -1;
9391
94 // Symbol binding. This is not overwritten by replaceSymbol to track92 // Symbol binding. This is not overwritten by replace() to track
95 // changes during resolution. In particular:93 // changes during resolution. In particular:
96 // - An undefined weak is still weak when it resolves to a shared library.94 // - An undefined weak is still weak when it resolves to a shared library.
97 // - An undefined weak will not fetch archive members, but we have to95 // - An undefined weak will not fetch archive members, but we have to
98 // remember it is weak.96 // remember it is weak.
99 uint8_t Binding;97 uint8_t binding;
10098
101 // The following fields have the same meaning as the ELF symbol attributes.99 // The following fields have the same meaning as the ELF symbol attributes.
102 uint8_t Type; // symbol type100 uint8_t type; // symbol type
103 uint8_t StOther; // st_other field value101 uint8_t stOther; // st_other field value
104102
105 uint8_t SymbolKind;103 uint8_t symbolKind;
106104
107 // Symbol visibility. This is the computed minimum visibility of all105 // Symbol visibility. This is the computed minimum visibility of all
108 // observed non-DSO symbols.106 // observed non-DSO symbols.
109 unsigned Visibility : 2;107 unsigned visibility : 2;
110108
111 // True if the symbol was used for linking and thus need to be added to the109 // True if the symbol was used for linking and thus need to be added to the
112 // output file's symbol table. This is true for all symbols except for110 // output file's symbol table. This is true for all symbols except for
113 // unreferenced DSO symbols and bitcode symbols that are unreferenced except111 // unreferenced DSO symbols, lazy (archive) symbols, and bitcode symbols that
114 // by other bitcode objects.112 // are unreferenced except by other bitcode objects.
115 unsigned IsUsedInRegularObj : 1;113 unsigned isUsedInRegularObj : 1;
116114
117 // If this flag is true and the symbol has protected or default visibility, it115 // If this flag is true and the symbol has protected or default visibility, it
118 // will appear in .dynsym. This flag is set by interposable DSO symbols in116 // will appear in .dynsym. This flag is set by interposable DSO symbols in
119 // executables, by most symbols in DSOs and executables built with117 // executables, by most symbols in DSOs and executables built with
120 // --export-dynamic, and by dynamic lists.118 // --export-dynamic, and by dynamic lists.
121 unsigned ExportDynamic : 1;119 unsigned exportDynamic : 1;
122120
123 // False if LTO shouldn't inline whatever this symbol points to. If a symbol121 // False if LTO shouldn't inline whatever this symbol points to. If a symbol
124 // is overwritten after LTO, LTO shouldn't inline the symbol because it122 // is overwritten after LTO, LTO shouldn't inline the symbol because it
125 // doesn't know the final contents of the symbol.123 // doesn't know the final contents of the symbol.
126 unsigned CanInline : 1;124 unsigned canInline : 1;
127125
128 // True if this symbol is specified by --trace-symbol option.126 // True if this symbol is specified by --trace-symbol option.
129 unsigned Traced : 1;127 unsigned traced : 1;
128
129 inline void replace(const Symbol &New);
130130
131 bool includeInDynsym() const;131 bool includeInDynsym() const;
132 uint8_t computeBinding() const;132 uint8_t computeBinding() const;
133 bool isWeak() const { return Binding == llvm::ELF::STB_WEAK; }133 bool isWeak() const { return binding == llvm::ELF::STB_WEAK; }
134
135 bool isUndefined() const { return symbolKind == UndefinedKind; }
136 bool isCommon() const { return symbolKind == CommonKind; }
137 bool isDefined() const { return symbolKind == DefinedKind; }
138 bool isShared() const { return symbolKind == SharedKind; }
139 bool isPlaceholder() const { return symbolKind == PlaceholderKind; }
134140
135 bool isUndefined() const { return SymbolKind == UndefinedKind; }141 bool isLocal() const { return binding == llvm::ELF::STB_LOCAL; }
136 bool isDefined() const { return SymbolKind == DefinedKind; }
137 bool isShared() const { return SymbolKind == SharedKind; }
138 bool isLocal() const { return Binding == llvm::ELF::STB_LOCAL; }
139142
140 bool isLazy() const {143 bool isLazy() const {
141 return SymbolKind == LazyArchiveKind || SymbolKind == LazyObjectKind;144 return symbolKind == LazyArchiveKind || symbolKind == LazyObjectKind;
142 }145 }
143146
144 // True if this is an undefined weak symbol. This only works once147 // True if this is an undefined weak symbol. This only works once
...@@ -149,23 +152,23 @@ public:...@@ -149,23 +152,23 @@ public:
149 }152 }
150153
151 StringRef getName() const {154 StringRef getName() const {
152 if (NameSize == (uint32_t)-1)155 if (nameSize == (uint32_t)-1)
153 NameSize = strlen(NameData);156 nameSize = strlen(nameData);
154 return {NameData, NameSize};157 return {nameData, nameSize};
155 }158 }
156159
157 void setName(StringRef S) {160 void setName(StringRef s) {
158 NameData = S.data();161 nameData = s.data();
159 NameSize = S.size();162 nameSize = s.size();
160 }163 }
161164
162 void parseSymbolVersion();165 void parseSymbolVersion();
163166
164 bool isInGot() const { return GotIndex != -1U; }167 bool isInGot() const { return gotIndex != -1U; }
165 bool isInPlt() const { return PltIndex != -1U; }168 bool isInPlt() const { return pltIndex != -1U; }
166 bool isInPPC64Branchlt() const { return PPC64BranchltIndex != 0xffff; }169 bool isInPPC64Branchlt() const { return ppc64BranchltIndex != 0xffff; }
167170
168 uint64_t getVA(int64_t Addend = 0) const;171 uint64_t getVA(int64_t addend = 0) const;
169172
170 uint64_t getGotOffset() const;173 uint64_t getGotOffset() const;
171 uint64_t getGotVA() const;174 uint64_t getGotVA() const;
...@@ -177,81 +180,164 @@ public:...@@ -177,81 +180,164 @@ public:
177 uint64_t getSize() const;180 uint64_t getSize() const;
178 OutputSection *getOutputSection() const;181 OutputSection *getOutputSection() const;
179182
183 // The following two functions are used for symbol resolution.
184 //
185 // You are expected to call mergeProperties for all symbols in input
186 // files so that attributes that are attached to names rather than
187 // indivisual symbol (such as visibility) are merged together.
188 //
189 // Every time you read a new symbol from an input, you are supposed
190 // to call resolve() with the new symbol. That function replaces
191 // "this" object as a result of name resolution if the new symbol is
192 // more appropriate to be included in the output.
193 //
194 // For example, if "this" is an undefined symbol and a new symbol is
195 // a defined symbol, "this" is replaced with the new symbol.
196 void mergeProperties(const Symbol &other);
197 void resolve(const Symbol &other);
198
199 // If this is a lazy symbol, fetch an input file and add the symbol
200 // in the file to the symbol table. Calling this function on
201 // non-lazy object causes a runtime error.
202 void fetch() const;
203
204private:
205 static bool isExportDynamic(Kind k, uint8_t visibility) {
206 if (k == SharedKind)
207 return visibility == llvm::ELF::STV_DEFAULT;
208 return config->shared || config->exportDynamic;
209 }
210
211 void resolveUndefined(const Undefined &other);
212 void resolveCommon(const CommonSymbol &other);
213 void resolveDefined(const Defined &other);
214 template <class LazyT> void resolveLazy(const LazyT &other);
215 void resolveShared(const SharedSymbol &other);
216
217 int compare(const Symbol *other) const;
218
219 inline size_t getSymbolSize() const;
220
180protected:221protected:
181 Symbol(Kind K, InputFile *File, StringRefZ Name, uint8_t Binding,222 Symbol(Kind k, InputFile *file, StringRefZ name, uint8_t binding,
182 uint8_t StOther, uint8_t Type)223 uint8_t stOther, uint8_t type)
183 : File(File), NameData(Name.Data), NameSize(Name.Size), Binding(Binding),224 : file(file), nameData(name.data), nameSize(name.size), binding(binding),
184 Type(Type), StOther(StOther), SymbolKind(K), NeedsPltAddr(false),225 type(type), stOther(stOther), symbolKind(k), visibility(stOther & 3),
185 IsInIplt(false), IsInIgot(false), IsPreemptible(false),226 isUsedInRegularObj(!file || file->kind() == InputFile::ObjKind),
186 Used(!Config->GcSections), NeedsTocRestore(false),227 exportDynamic(isExportDynamic(k, visibility)), canInline(false),
187 ScriptDefined(false) {}228 traced(false), needsPltAddr(false), isInIplt(false), gotInIgot(false),
229 isPreemptible(false), used(!config->gcSections), needsTocRestore(false),
230 scriptDefined(false) {}
188231
189public:232public:
190 // True the symbol should point to its PLT entry.233 // True the symbol should point to its PLT entry.
191 // For SharedSymbol only.234 // For SharedSymbol only.
192 unsigned NeedsPltAddr : 1;235 unsigned needsPltAddr : 1;
193236
194 // True if this symbol is in the Iplt sub-section of the Plt.237 // True if this symbol is in the Iplt sub-section of the Plt and the Igot
195 unsigned IsInIplt : 1;238 // sub-section of the .got.plt or .got.
239 unsigned isInIplt : 1;
196240
197 // True if this symbol is in the Igot sub-section of the .got.plt or .got.241 // True if this symbol needs a GOT entry and its GOT entry is actually in
198 unsigned IsInIgot : 1;242 // Igot. This will be true only for certain non-preemptible ifuncs.
243 unsigned gotInIgot : 1;
199244
200 // True if this symbol is preemptible at load time.245 // True if this symbol is preemptible at load time.
201 unsigned IsPreemptible : 1;246 unsigned isPreemptible : 1;
202247
203 // True if an undefined or shared symbol is used from a live section.248 // True if an undefined or shared symbol is used from a live section.
204 unsigned Used : 1;249 unsigned used : 1;
205250
206 // True if a call to this symbol needs to be followed by a restore of the251 // True if a call to this symbol needs to be followed by a restore of the
207 // PPC64 toc pointer.252 // PPC64 toc pointer.
208 unsigned NeedsTocRestore : 1;253 unsigned needsTocRestore : 1;
209254
210 // True if this symbol is defined by a linker script.255 // True if this symbol is defined by a linker script.
211 unsigned ScriptDefined : 1;256 unsigned scriptDefined : 1;
212257
213 bool isSection() const { return Type == llvm::ELF::STT_SECTION; }258 // The partition whose dynamic symbol table contains this symbol's definition.
214 bool isTls() const { return Type == llvm::ELF::STT_TLS; }259 uint8_t partition = 1;
215 bool isFunc() const { return Type == llvm::ELF::STT_FUNC; }260
216 bool isGnuIFunc() const { return Type == llvm::ELF::STT_GNU_IFUNC; }261 bool isSection() const { return type == llvm::ELF::STT_SECTION; }
217 bool isObject() const { return Type == llvm::ELF::STT_OBJECT; }262 bool isTls() const { return type == llvm::ELF::STT_TLS; }
218 bool isFile() const { return Type == llvm::ELF::STT_FILE; }263 bool isFunc() const { return type == llvm::ELF::STT_FUNC; }
264 bool isGnuIFunc() const { return type == llvm::ELF::STT_GNU_IFUNC; }
265 bool isObject() const { return type == llvm::ELF::STT_OBJECT; }
266 bool isFile() const { return type == llvm::ELF::STT_FILE; }
219};267};
220268
221// Represents a symbol that is defined in the current output file.269// Represents a symbol that is defined in the current output file.
222class Defined : public Symbol {270class Defined : public Symbol {
223public:271public:
224 Defined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther,272 Defined(InputFile *file, StringRefZ name, uint8_t binding, uint8_t stOther,
225 uint8_t Type, uint64_t Value, uint64_t Size, SectionBase *Section)273 uint8_t type, uint64_t value, uint64_t size, SectionBase *section)
226 : Symbol(DefinedKind, File, Name, Binding, StOther, Type), Value(Value),274 : Symbol(DefinedKind, file, name, binding, stOther, type), value(value),
227 Size(Size), Section(Section) {}275 size(size), section(section) {}
276
277 static bool classof(const Symbol *s) { return s->isDefined(); }
278
279 uint64_t value;
280 uint64_t size;
281 SectionBase *section;
282};
283
284// Represents a common symbol.
285//
286// On Unix, it is traditionally allowed to write variable definitions
287// without initialization expressions (such as "int foo;") to header
288// files. Such definition is called "tentative definition".
289//
290// Using tentative definition is usually considered a bad practice
291// because you should write only declarations (such as "extern int
292// foo;") to header files. Nevertheless, the linker and the compiler
293// have to do something to support bad code by allowing duplicate
294// definitions for this particular case.
295//
296// Common symbols represent variable definitions without initializations.
297// The compiler creates common symbols when it sees varaible definitions
298// without initialization (you can suppress this behavior and let the
299// compiler create a regular defined symbol by -fno-common).
300//
301// The linker allows common symbols to be replaced by regular defined
302// symbols. If there are remaining common symbols after name resolution is
303// complete, they are converted to regular defined symbols in a .bss
304// section. (Therefore, the later passes don't see any CommonSymbols.)
305class CommonSymbol : public Symbol {
306public:
307 CommonSymbol(InputFile *file, StringRefZ name, uint8_t binding,
308 uint8_t stOther, uint8_t type, uint64_t alignment, uint64_t size)
309 : Symbol(CommonKind, file, name, binding, stOther, type),
310 alignment(alignment), size(size) {}
228311
229 static bool classof(const Symbol *S) { return S->isDefined(); }312 static bool classof(const Symbol *s) { return s->isCommon(); }
230313
231 uint64_t Value;314 uint32_t alignment;
232 uint64_t Size;315 uint64_t size;
233 SectionBase *Section;
234};316};
235317
236class Undefined : public Symbol {318class Undefined : public Symbol {
237public:319public:
238 Undefined(InputFile *File, StringRefZ Name, uint8_t Binding, uint8_t StOther,320 Undefined(InputFile *file, StringRefZ name, uint8_t binding, uint8_t stOther,
239 uint8_t Type)321 uint8_t type, uint32_t discardedSecIdx = 0)
240 : Symbol(UndefinedKind, File, Name, Binding, StOther, Type) {}322 : Symbol(UndefinedKind, file, name, binding, stOther, type),
323 discardedSecIdx(discardedSecIdx) {}
241324
242 static bool classof(const Symbol *S) { return S->kind() == UndefinedKind; }325 static bool classof(const Symbol *s) { return s->kind() == UndefinedKind; }
326
327 // The section index if in a discarded section, 0 otherwise.
328 uint32_t discardedSecIdx;
243};329};
244330
245class SharedSymbol : public Symbol {331class SharedSymbol : public Symbol {
246public:332public:
247 static bool classof(const Symbol *S) { return S->kind() == SharedKind; }333 static bool classof(const Symbol *s) { return s->kind() == SharedKind; }
248334
249 SharedSymbol(InputFile &File, StringRef Name, uint8_t Binding,335 SharedSymbol(InputFile &file, StringRef name, uint8_t binding,
250 uint8_t StOther, uint8_t Type, uint64_t Value, uint64_t Size,336 uint8_t stOther, uint8_t type, uint64_t value, uint64_t size,
251 uint32_t Alignment, uint32_t VerdefIndex)337 uint32_t alignment, uint32_t verdefIndex)
252 : Symbol(SharedKind, &File, Name, Binding, StOther, Type),338 : Symbol(SharedKind, &file, name, binding, stOther, type), value(value),
253 Alignment(Alignment), Value(Value), Size(Size) {339 size(size), alignment(alignment) {
254 this->VerdefIndex = VerdefIndex;340 this->verdefIndex = verdefIndex;
255 // GNU ifunc is a mechanism to allow user-supplied functions to341 // GNU ifunc is a mechanism to allow user-supplied functions to
256 // resolve PLT slot values at load-time. This is contrary to the342 // resolve PLT slot values at load-time. This is contrary to the
257 // regular symbol resolution scheme in which symbols are resolved just343 // regular symbol resolution scheme in which symbols are resolved just
...@@ -268,18 +354,20 @@ public:...@@ -268,18 +354,20 @@ public:
268 // For DSO symbols, we always call them through PLT slots anyway.354 // For DSO symbols, we always call them through PLT slots anyway.
269 // So there's no difference between GNU ifunc and regular function355 // So there's no difference between GNU ifunc and regular function
270 // symbols if they are in DSOs. So we can handle GNU_IFUNC as FUNC.356 // symbols if they are in DSOs. So we can handle GNU_IFUNC as FUNC.
271 if (this->Type == llvm::ELF::STT_GNU_IFUNC)357 if (this->type == llvm::ELF::STT_GNU_IFUNC)
272 this->Type = llvm::ELF::STT_FUNC;358 this->type = llvm::ELF::STT_FUNC;
273 }359 }
274360
275 template <class ELFT> SharedFile<ELFT> &getFile() const {361 SharedFile &getFile() const { return *cast<SharedFile>(file); }
276 return *cast<SharedFile<ELFT>>(File);
277 }
278362
279 uint32_t Alignment;363 uint64_t value; // st_value
364 uint64_t size; // st_size
365 uint32_t alignment;
280366
281 uint64_t Value; // st_value367 // This is true if there has been at least one undefined reference to the
282 uint64_t Size; // st_size368 // symbol. The binding may change to STB_WEAK if the first undefined reference
369 // is weak.
370 bool referenced = false;
283};371};
284372
285// LazyArchive and LazyObject represent a symbols that is not yet in the link,373// LazyArchive and LazyObject represent a symbols that is not yet in the link,
...@@ -298,121 +386,168 @@ public:...@@ -298,121 +386,168 @@ public:
298// symbol.386// symbol.
299class LazyArchive : public Symbol {387class LazyArchive : public Symbol {
300public:388public:
301 LazyArchive(InputFile &File, uint8_t Type,389 LazyArchive(InputFile &file, const llvm::object::Archive::Symbol s)
302 const llvm::object::Archive::Symbol S)390 : Symbol(LazyArchiveKind, &file, s.getName(), llvm::ELF::STB_GLOBAL,
303 : Symbol(LazyArchiveKind, &File, S.getName(), llvm::ELF::STB_GLOBAL,391 llvm::ELF::STV_DEFAULT, llvm::ELF::STT_NOTYPE),
304 llvm::ELF::STV_DEFAULT, Type),392 sym(s) {}
305 Sym(S) {}
306393
307 static bool classof(const Symbol *S) { return S->kind() == LazyArchiveKind; }394 static bool classof(const Symbol *s) { return s->kind() == LazyArchiveKind; }
308395
309 InputFile *fetch();
310 MemoryBufferRef getMemberBuffer();396 MemoryBufferRef getMemberBuffer();
311397
312private:398 const llvm::object::Archive::Symbol sym;
313 const llvm::object::Archive::Symbol Sym;
314};399};
315400
316// LazyObject symbols represents symbols in object files between401// LazyObject symbols represents symbols in object files between
317// --start-lib and --end-lib options.402// --start-lib and --end-lib options.
318class LazyObject : public Symbol {403class LazyObject : public Symbol {
319public:404public:
320 LazyObject(InputFile &File, uint8_t Type, StringRef Name)405 LazyObject(InputFile &file, StringRef name)
321 : Symbol(LazyObjectKind, &File, Name, llvm::ELF::STB_GLOBAL,406 : Symbol(LazyObjectKind, &file, name, llvm::ELF::STB_GLOBAL,
322 llvm::ELF::STV_DEFAULT, Type) {}407 llvm::ELF::STV_DEFAULT, llvm::ELF::STT_NOTYPE) {}
323408
324 static bool classof(const Symbol *S) { return S->kind() == LazyObjectKind; }409 static bool classof(const Symbol *s) { return s->kind() == LazyObjectKind; }
325};410};
326411
327// Some linker-generated symbols need to be created as412// Some linker-generated symbols need to be created as
328// Defined symbols.413// Defined symbols.
329struct ElfSym {414struct ElfSym {
330 // __bss_start415 // __bss_start
331 static Defined *Bss;416 static Defined *bss;
332417
333 // etext and _etext418 // etext and _etext
334 static Defined *Etext1;419 static Defined *etext1;
335 static Defined *Etext2;420 static Defined *etext2;
336421
337 // edata and _edata422 // edata and _edata
338 static Defined *Edata1;423 static Defined *edata1;
339 static Defined *Edata2;424 static Defined *edata2;
340425
341 // end and _end426 // end and _end
342 static Defined *End1;427 static Defined *end1;
343 static Defined *End2;428 static Defined *end2;
344429
345 // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to430 // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention to
346 // be at some offset from the base of the .got section, usually 0 or431 // be at some offset from the base of the .got section, usually 0 or
347 // the end of the .got.432 // the end of the .got.
348 static Defined *GlobalOffsetTable;433 static Defined *globalOffsetTable;
349434
350 // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS.435 // _gp, _gp_disp and __gnu_local_gp symbols. Only for MIPS.
351 static Defined *MipsGp;436 static Defined *mipsGp;
352 static Defined *MipsGpDisp;437 static Defined *mipsGpDisp;
353 static Defined *MipsLocalGp;438 static Defined *mipsLocalGp;
354439
355 // __rel{,a}_iplt_{start,end} symbols.440 // __rel{,a}_iplt_{start,end} symbols.
356 static Defined *RelaIpltStart;441 static Defined *relaIpltStart;
357 static Defined *RelaIpltEnd;442 static Defined *relaIpltEnd;
443
444 // __global_pointer$ for RISC-V.
445 static Defined *riscvGlobalPointer;
446
447 // _TLS_MODULE_BASE_ on targets that support TLSDESC.
448 static Defined *tlsModuleBase;
358};449};
359450
360// A buffer class that is large enough to hold any Symbol-derived451// A buffer class that is large enough to hold any Symbol-derived
361// object. We allocate memory using this class and instantiate a symbol452// object. We allocate memory using this class and instantiate a symbol
362// using the placement new.453// using the placement new.
363union SymbolUnion {454union SymbolUnion {
364 alignas(Defined) char A[sizeof(Defined)];455 alignas(Defined) char a[sizeof(Defined)];
365 alignas(Undefined) char C[sizeof(Undefined)];456 alignas(CommonSymbol) char b[sizeof(CommonSymbol)];
366 alignas(SharedSymbol) char D[sizeof(SharedSymbol)];457 alignas(Undefined) char c[sizeof(Undefined)];
367 alignas(LazyArchive) char E[sizeof(LazyArchive)];458 alignas(SharedSymbol) char d[sizeof(SharedSymbol)];
368 alignas(LazyObject) char F[sizeof(LazyObject)];459 alignas(LazyArchive) char e[sizeof(LazyArchive)];
460 alignas(LazyObject) char f[sizeof(LazyObject)];
369};461};
370462
371void printTraceSymbol(Symbol *Sym);463// It is important to keep the size of SymbolUnion small for performance and
372464// memory usage reasons. 80 bytes is a soft limit based on the size of Defined
373template <typename T, typename... ArgT>465// on a 64-bit system.
374void replaceSymbol(Symbol *S, ArgT &&... Arg) {466static_assert(sizeof(SymbolUnion) <= 80, "SymbolUnion too large");
375 using llvm::ELF::STT_TLS;
376467
468template <typename T> struct AssertSymbol {
377 static_assert(std::is_trivially_destructible<T>(),469 static_assert(std::is_trivially_destructible<T>(),
378 "Symbol types must be trivially destructible");470 "Symbol types must be trivially destructible");
379 static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");471 static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
380 static_assert(alignof(T) <= alignof(SymbolUnion),472 static_assert(alignof(T) <= alignof(SymbolUnion),
381 "SymbolUnion not aligned enough");473 "SymbolUnion not aligned enough");
382 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&474};
383 "Not a Symbol");
384475
385 Symbol Sym = *S;476static inline void assertSymbols() {
477 AssertSymbol<Defined>();
478 AssertSymbol<CommonSymbol>();
479 AssertSymbol<Undefined>();
480 AssertSymbol<SharedSymbol>();
481 AssertSymbol<LazyArchive>();
482 AssertSymbol<LazyObject>();
483}
386484
387 new (S) T(std::forward<ArgT>(Arg)...);485void printTraceSymbol(const Symbol *sym);
486
487size_t Symbol::getSymbolSize() const {
488 switch (kind()) {
489 case CommonKind:
490 return sizeof(CommonSymbol);
491 case DefinedKind:
492 return sizeof(Defined);
493 case LazyArchiveKind:
494 return sizeof(LazyArchive);
495 case LazyObjectKind:
496 return sizeof(LazyObject);
497 case SharedKind:
498 return sizeof(SharedSymbol);
499 case UndefinedKind:
500 return sizeof(Undefined);
501 case PlaceholderKind:
502 return sizeof(Symbol);
503 }
504 llvm_unreachable("unknown symbol kind");
505}
388506
389 S->VersionId = Sym.VersionId;507// replace() replaces "this" object with a given symbol by memcpy'ing
390 S->Visibility = Sym.Visibility;508// it over to "this". This function is called as a result of name
391 S->IsUsedInRegularObj = Sym.IsUsedInRegularObj;509// resolution, e.g. to replace an undefind symbol with a defined symbol.
392 S->ExportDynamic = Sym.ExportDynamic;510void Symbol::replace(const Symbol &New) {
393 S->CanInline = Sym.CanInline;511 using llvm::ELF::STT_TLS;
394 S->Traced = Sym.Traced;
395 S->ScriptDefined = Sym.ScriptDefined;
396512
397 // Symbols representing thread-local variables must be referenced by513 // Symbols representing thread-local variables must be referenced by
398 // TLS-aware relocations, and non-TLS symbols must be reference by514 // TLS-aware relocations, and non-TLS symbols must be reference by
399 // non-TLS relocations, so there's a clear distinction between TLS515 // 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 defined516 // 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.517 // 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) ||518 if (symbolKind != PlaceholderKind && !isLazy() && !New.isLazy()) {
403 (Sym.Type != STT_TLS && S->Type == STT_TLS);519 bool tlsMismatch = (type == STT_TLS && New.type != STT_TLS) ||
520 (type != STT_TLS && New.type == STT_TLS);
521 if (tlsMismatch)
522 error("TLS attribute mismatch: " + toString(*this) + "\n>>> defined in " +
523 toString(New.file) + "\n>>> defined in " + toString(file));
524 }
525
526 Symbol old = *this;
527 memcpy(this, &New, New.getSymbolSize());
528
529 versionId = old.versionId;
530 visibility = old.visibility;
531 isUsedInRegularObj = old.isUsedInRegularObj;
532 exportDynamic = old.exportDynamic;
533 canInline = old.canInline;
534 traced = old.traced;
535 isPreemptible = old.isPreemptible;
536 scriptDefined = old.scriptDefined;
537 partition = old.partition;
404538
405 if (Sym.SymbolKind != Symbol::PlaceholderKind && TlsMismatch && !Sym.isLazy())539 // Symbol length is computed lazily. If we already know a symbol length,
406 error("TLS attribute mismatch: " + toString(Sym) + "\n>>> defined in " +540 // propagate it.
407 toString(Sym.File) + "\n>>> defined in " + toString(S->File));541 if (nameData == old.nameData && nameSize == 0 && old.nameSize != 0)
542 nameSize = old.nameSize;
408543
409 // Print out a log message if --trace-symbol was specified.544 // Print out a log message if --trace-symbol was specified.
410 // This is for debugging.545 // This is for debugging.
411 if (S->Traced)546 if (traced)
412 printTraceSymbol(S);547 printTraceSymbol(this);
413}548}
414549
415void maybeWarnUnorderableSymbol(const Symbol *Sym);550void maybeWarnUnorderableSymbol(const Symbol *sym);
416} // namespace elf551} // namespace elf
417} // namespace lld552} // namespace lld
418553
deps/lld/ELF/SyntheticSections.cpp+2046-1654
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- SyntheticSections.cpp ----------------------------------------------===//1//===- SyntheticSections.cpp ----------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -15,7 +14,6 @@...@@ -15,7 +14,6 @@
15//===----------------------------------------------------------------------===//14//===----------------------------------------------------------------------===//
1615
17#include "SyntheticSections.h"16#include "SyntheticSections.h"
18#include "Bits.h"
19#include "Config.h"17#include "Config.h"
20#include "InputFiles.h"18#include "InputFiles.h"
21#include "LinkerScript.h"19#include "LinkerScript.h"
...@@ -38,9 +36,6 @@...@@ -38,9 +36,6 @@
38#include "llvm/Support/Endian.h"36#include "llvm/Support/Endian.h"
39#include "llvm/Support/LEB128.h"37#include "llvm/Support/LEB128.h"
40#include "llvm/Support/MD5.h"38#include "llvm/Support/MD5.h"
41#include "llvm/Support/RandomNumberGenerator.h"
42#include "llvm/Support/SHA1.h"
43#include "llvm/Support/xxhash.h"
44#include <cstdlib>39#include <cstdlib>
45#include <thread>40#include <thread>
4641
...@@ -57,19 +52,30 @@ using llvm::support::endian::read32le;...@@ -57,19 +52,30 @@ using llvm::support::endian::read32le;
57using llvm::support::endian::write32le;52using llvm::support::endian::write32le;
58using llvm::support::endian::write64le;53using llvm::support::endian::write64le;
5954
60constexpr size_t MergeNoTailSection::NumShards;55constexpr size_t MergeNoTailSection::numShards;
56
57static uint64_t readUint(uint8_t *buf) {
58 return config->is64 ? read64(buf) : read32(buf);
59}
60
61static void writeUint(uint8_t *buf, uint64_t val) {
62 if (config->is64)
63 write64(buf, val);
64 else
65 write32(buf, val);
66}
6167
62// Returns an LLD version string.68// Returns an LLD version string.
63static ArrayRef<uint8_t> getVersion() {69static ArrayRef<uint8_t> getVersion() {
64 // Check LLD_VERSION first for ease of testing.70 // Check LLD_VERSION first for ease of testing.
65 // You can get consistent output by using the environment variable.71 // You can get consistent output by using the environment variable.
66 // This is only for testing.72 // This is only for testing.
67 StringRef S = getenv("LLD_VERSION");73 StringRef s = getenv("LLD_VERSION");
68 if (S.empty())74 if (s.empty())
69 S = Saver.save(Twine("Linker: ") + getLLDVersion());75 s = saver.save(Twine("Linker: ") + getLLDVersion());
7076
71 // +1 to include the terminating '\0'.77 // +1 to include the terminating '\0'.
72 return {(const uint8_t *)S.data(), S.size() + 1};78 return {(const uint8_t *)s.data(), s.size() + 1};
73}79}
7480
75// Creates a .comment section containing LLD version info.81// Creates a .comment section containing LLD version info.
...@@ -83,79 +89,79 @@ MergeInputSection *elf::createCommentSection() {...@@ -83,79 +89,79 @@ MergeInputSection *elf::createCommentSection() {
8389
84// .MIPS.abiflags section.90// .MIPS.abiflags section.
85template <class ELFT>91template <class ELFT>
86MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(Elf_Mips_ABIFlags Flags)92MipsAbiFlagsSection<ELFT>::MipsAbiFlagsSection(Elf_Mips_ABIFlags flags)
87 : SyntheticSection(SHF_ALLOC, SHT_MIPS_ABIFLAGS, 8, ".MIPS.abiflags"),93 : SyntheticSection(SHF_ALLOC, SHT_MIPS_ABIFLAGS, 8, ".MIPS.abiflags"),
88 Flags(Flags) {94 flags(flags) {
89 this->Entsize = sizeof(Elf_Mips_ABIFlags);95 this->entsize = sizeof(Elf_Mips_ABIFlags);
90}96}
9197
92template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *Buf) {98template <class ELFT> void MipsAbiFlagsSection<ELFT>::writeTo(uint8_t *buf) {
93 memcpy(Buf, &Flags, sizeof(Flags));99 memcpy(buf, &flags, sizeof(flags));
94}100}
95101
96template <class ELFT>102template <class ELFT>
97MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {103MipsAbiFlagsSection<ELFT> *MipsAbiFlagsSection<ELFT>::create() {
98 Elf_Mips_ABIFlags Flags = {};104 Elf_Mips_ABIFlags flags = {};
99 bool Create = false;105 bool create = false;
100106
101 for (InputSectionBase *Sec : InputSections) {107 for (InputSectionBase *sec : inputSections) {
102 if (Sec->Type != SHT_MIPS_ABIFLAGS)108 if (sec->type != SHT_MIPS_ABIFLAGS)
103 continue;109 continue;
104 Sec->Live = false;110 sec->markDead();
105 Create = true;111 create = true;
106112
107 std::string Filename = toString(Sec->File);113 std::string filename = toString(sec->file);
108 const size_t Size = Sec->data().size();114 const size_t size = sec->data().size();
109 // Older version of BFD (such as the default FreeBSD linker) concatenate115 // Older version of BFD (such as the default FreeBSD linker) concatenate
110 // .MIPS.abiflags instead of merging. To allow for this case (or potential116 // .MIPS.abiflags instead of merging. To allow for this case (or potential
111 // zero padding) we ignore everything after the first Elf_Mips_ABIFlags117 // zero padding) we ignore everything after the first Elf_Mips_ABIFlags
112 if (Size < sizeof(Elf_Mips_ABIFlags)) {118 if (size < sizeof(Elf_Mips_ABIFlags)) {
113 error(Filename + ": invalid size of .MIPS.abiflags section: got " +119 error(filename + ": invalid size of .MIPS.abiflags section: got " +
114 Twine(Size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags)));120 Twine(size) + " instead of " + Twine(sizeof(Elf_Mips_ABIFlags)));
115 return nullptr;121 return nullptr;
116 }122 }
117 auto *S = reinterpret_cast<const Elf_Mips_ABIFlags *>(Sec->data().data());123 auto *s = reinterpret_cast<const Elf_Mips_ABIFlags *>(sec->data().data());
118 if (S->version != 0) {124 if (s->version != 0) {
119 error(Filename + ": unexpected .MIPS.abiflags version " +125 error(filename + ": unexpected .MIPS.abiflags version " +
120 Twine(S->version));126 Twine(s->version));
121 return nullptr;127 return nullptr;
122 }128 }
123129
124 // LLD checks ISA compatibility in calcMipsEFlags(). Here we just130 // LLD checks ISA compatibility in calcMipsEFlags(). Here we just
125 // select the highest number of ISA/Rev/Ext.131 // select the highest number of ISA/Rev/Ext.
126 Flags.isa_level = std::max(Flags.isa_level, S->isa_level);132 flags.isa_level = std::max(flags.isa_level, s->isa_level);
127 Flags.isa_rev = std::max(Flags.isa_rev, S->isa_rev);133 flags.isa_rev = std::max(flags.isa_rev, s->isa_rev);
128 Flags.isa_ext = std::max(Flags.isa_ext, S->isa_ext);134 flags.isa_ext = std::max(flags.isa_ext, s->isa_ext);
129 Flags.gpr_size = std::max(Flags.gpr_size, S->gpr_size);135 flags.gpr_size = std::max(flags.gpr_size, s->gpr_size);
130 Flags.cpr1_size = std::max(Flags.cpr1_size, S->cpr1_size);136 flags.cpr1_size = std::max(flags.cpr1_size, s->cpr1_size);
131 Flags.cpr2_size = std::max(Flags.cpr2_size, S->cpr2_size);137 flags.cpr2_size = std::max(flags.cpr2_size, s->cpr2_size);
132 Flags.ases |= S->ases;138 flags.ases |= s->ases;
133 Flags.flags1 |= S->flags1;139 flags.flags1 |= s->flags1;
134 Flags.flags2 |= S->flags2;140 flags.flags2 |= s->flags2;
135 Flags.fp_abi = elf::getMipsFpAbiFlag(Flags.fp_abi, S->fp_abi, Filename);141 flags.fp_abi = elf::getMipsFpAbiFlag(flags.fp_abi, s->fp_abi, filename);
136 };142 };
137143
138 if (Create)144 if (create)
139 return make<MipsAbiFlagsSection<ELFT>>(Flags);145 return make<MipsAbiFlagsSection<ELFT>>(flags);
140 return nullptr;146 return nullptr;
141}147}
142148
143// .MIPS.options section.149// .MIPS.options section.
144template <class ELFT>150template <class ELFT>
145MipsOptionsSection<ELFT>::MipsOptionsSection(Elf_Mips_RegInfo Reginfo)151MipsOptionsSection<ELFT>::MipsOptionsSection(Elf_Mips_RegInfo reginfo)
146 : SyntheticSection(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ".MIPS.options"),152 : SyntheticSection(SHF_ALLOC, SHT_MIPS_OPTIONS, 8, ".MIPS.options"),
147 Reginfo(Reginfo) {153 reginfo(reginfo) {
148 this->Entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);154 this->entsize = sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
149}155}
150156
151template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *Buf) {157template <class ELFT> void MipsOptionsSection<ELFT>::writeTo(uint8_t *buf) {
152 auto *Options = reinterpret_cast<Elf_Mips_Options *>(Buf);158 auto *options = reinterpret_cast<Elf_Mips_Options *>(buf);
153 Options->kind = ODK_REGINFO;159 options->kind = ODK_REGINFO;
154 Options->size = getSize();160 options->size = getSize();
155161
156 if (!Config->Relocatable)162 if (!config->relocatable)
157 Reginfo.ri_gp_value = In.MipsGot->getGp();163 reginfo.ri_gp_value = in.mipsGot->getGp();
158 memcpy(Buf + sizeof(Elf_Mips_Options), &Reginfo, sizeof(Reginfo));164 memcpy(buf + sizeof(Elf_Mips_Options), &reginfo, sizeof(reginfo));
159}165}
160166
161template <class ELFT>167template <class ELFT>
...@@ -164,55 +170,55 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {...@@ -164,55 +170,55 @@ MipsOptionsSection<ELFT> *MipsOptionsSection<ELFT>::create() {
164 if (!ELFT::Is64Bits)170 if (!ELFT::Is64Bits)
165 return nullptr;171 return nullptr;
166172
167 std::vector<InputSectionBase *> Sections;173 std::vector<InputSectionBase *> sections;
168 for (InputSectionBase *Sec : InputSections)174 for (InputSectionBase *sec : inputSections)
169 if (Sec->Type == SHT_MIPS_OPTIONS)175 if (sec->type == SHT_MIPS_OPTIONS)
170 Sections.push_back(Sec);176 sections.push_back(sec);
171177
172 if (Sections.empty())178 if (sections.empty())
173 return nullptr;179 return nullptr;
174180
175 Elf_Mips_RegInfo Reginfo = {};181 Elf_Mips_RegInfo reginfo = {};
176 for (InputSectionBase *Sec : Sections) {182 for (InputSectionBase *sec : sections) {
177 Sec->Live = false;183 sec->markDead();
178184
179 std::string Filename = toString(Sec->File);185 std::string filename = toString(sec->file);
180 ArrayRef<uint8_t> D = Sec->data();186 ArrayRef<uint8_t> d = sec->data();
181187
182 while (!D.empty()) {188 while (!d.empty()) {
183 if (D.size() < sizeof(Elf_Mips_Options)) {189 if (d.size() < sizeof(Elf_Mips_Options)) {
184 error(Filename + ": invalid size of .MIPS.options section");190 error(filename + ": invalid size of .MIPS.options section");
185 break;191 break;
186 }192 }
187193
188 auto *Opt = reinterpret_cast<const Elf_Mips_Options *>(D.data());194 auto *opt = reinterpret_cast<const Elf_Mips_Options *>(d.data());
189 if (Opt->kind == ODK_REGINFO) {195 if (opt->kind == ODK_REGINFO) {
190 Reginfo.ri_gprmask |= Opt->getRegInfo().ri_gprmask;196 reginfo.ri_gprmask |= opt->getRegInfo().ri_gprmask;
191 Sec->getFile<ELFT>()->MipsGp0 = Opt->getRegInfo().ri_gp_value;197 sec->getFile<ELFT>()->mipsGp0 = opt->getRegInfo().ri_gp_value;
192 break;198 break;
193 }199 }
194200
195 if (!Opt->size)201 if (!opt->size)
196 fatal(Filename + ": zero option descriptor size");202 fatal(filename + ": zero option descriptor size");
197 D = D.slice(Opt->size);203 d = d.slice(opt->size);
198 }204 }
199 };205 };
200206
201 return make<MipsOptionsSection<ELFT>>(Reginfo);207 return make<MipsOptionsSection<ELFT>>(reginfo);
202}208}
203209
204// MIPS .reginfo section.210// MIPS .reginfo section.
205template <class ELFT>211template <class ELFT>
206MipsReginfoSection<ELFT>::MipsReginfoSection(Elf_Mips_RegInfo Reginfo)212MipsReginfoSection<ELFT>::MipsReginfoSection(Elf_Mips_RegInfo reginfo)
207 : SyntheticSection(SHF_ALLOC, SHT_MIPS_REGINFO, 4, ".reginfo"),213 : SyntheticSection(SHF_ALLOC, SHT_MIPS_REGINFO, 4, ".reginfo"),
208 Reginfo(Reginfo) {214 reginfo(reginfo) {
209 this->Entsize = sizeof(Elf_Mips_RegInfo);215 this->entsize = sizeof(Elf_Mips_RegInfo);
210}216}
211217
212template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *Buf) {218template <class ELFT> void MipsReginfoSection<ELFT>::writeTo(uint8_t *buf) {
213 if (!Config->Relocatable)219 if (!config->relocatable)
214 Reginfo.ri_gp_value = In.MipsGot->getGp();220 reginfo.ri_gp_value = in.mipsGot->getGp();
215 memcpy(Buf, &Reginfo, sizeof(Reginfo));221 memcpy(buf, &reginfo, sizeof(reginfo));
216}222}
217223
218template <class ELFT>224template <class ELFT>
...@@ -221,53 +227,53 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {...@@ -221,53 +227,53 @@ MipsReginfoSection<ELFT> *MipsReginfoSection<ELFT>::create() {
221 if (ELFT::Is64Bits)227 if (ELFT::Is64Bits)
222 return nullptr;228 return nullptr;
223229
224 std::vector<InputSectionBase *> Sections;230 std::vector<InputSectionBase *> sections;
225 for (InputSectionBase *Sec : InputSections)231 for (InputSectionBase *sec : inputSections)
226 if (Sec->Type == SHT_MIPS_REGINFO)232 if (sec->type == SHT_MIPS_REGINFO)
227 Sections.push_back(Sec);233 sections.push_back(sec);
228234
229 if (Sections.empty())235 if (sections.empty())
230 return nullptr;236 return nullptr;
231237
232 Elf_Mips_RegInfo Reginfo = {};238 Elf_Mips_RegInfo reginfo = {};
233 for (InputSectionBase *Sec : Sections) {239 for (InputSectionBase *sec : sections) {
234 Sec->Live = false;240 sec->markDead();
235241
236 if (Sec->data().size() != sizeof(Elf_Mips_RegInfo)) {242 if (sec->data().size() != sizeof(Elf_Mips_RegInfo)) {
237 error(toString(Sec->File) + ": invalid size of .reginfo section");243 error(toString(sec->file) + ": invalid size of .reginfo section");
238 return nullptr;244 return nullptr;
239 }245 }
240246
241 auto *R = reinterpret_cast<const Elf_Mips_RegInfo *>(Sec->data().data());247 auto *r = reinterpret_cast<const Elf_Mips_RegInfo *>(sec->data().data());
242 Reginfo.ri_gprmask |= R->ri_gprmask;248 reginfo.ri_gprmask |= r->ri_gprmask;
243 Sec->getFile<ELFT>()->MipsGp0 = R->ri_gp_value;249 sec->getFile<ELFT>()->mipsGp0 = r->ri_gp_value;
244 };250 };
245251
246 return make<MipsReginfoSection<ELFT>>(Reginfo);252 return make<MipsReginfoSection<ELFT>>(reginfo);
247}253}
248254
249InputSection *elf::createInterpSection() {255InputSection *elf::createInterpSection() {
250 // StringSaver guarantees that the returned string ends with '\0'.256 // StringSaver guarantees that the returned string ends with '\0'.
251 StringRef S = Saver.save(Config->DynamicLinker);257 StringRef s = saver.save(config->dynamicLinker);
252 ArrayRef<uint8_t> Contents = {(const uint8_t *)S.data(), S.size() + 1};258 ArrayRef<uint8_t> contents = {(const uint8_t *)s.data(), s.size() + 1};
253259
254 auto *Sec = make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, Contents,260 auto *sec = make<InputSection>(nullptr, SHF_ALLOC, SHT_PROGBITS, 1, contents,
255 ".interp");261 ".interp");
256 Sec->Live = true;262 sec->markLive();
257 return Sec;263 return sec;
258}264}
259265
260Defined *elf::addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,266Defined *elf::addSyntheticLocal(StringRef name, uint8_t type, uint64_t value,
261 uint64_t Size, InputSectionBase &Section) {267 uint64_t size, InputSectionBase &section) {
262 auto *S = make<Defined>(Section.File, Name, STB_LOCAL, STV_DEFAULT, Type,268 auto *s = make<Defined>(section.file, name, STB_LOCAL, STV_DEFAULT, type,
263 Value, Size, &Section);269 value, size, &section);
264 if (In.SymTab)270 if (in.symTab)
265 In.SymTab->addSymbol(S);271 in.symTab->addSymbol(s);
266 return S;272 return s;
267}273}
268274
269static size_t getHashSize() {275static size_t getHashSize() {
270 switch (Config->BuildId) {276 switch (config->buildId) {
271 case BuildIdKind::Fast:277 case BuildIdKind::Fast:
272 return 8;278 return 8;
273 case BuildIdKind::Md5:279 case BuildIdKind::Md5:
...@@ -276,89 +282,67 @@ static size_t getHashSize() {...@@ -276,89 +282,67 @@ static size_t getHashSize() {
276 case BuildIdKind::Sha1:282 case BuildIdKind::Sha1:
277 return 20;283 return 20;
278 case BuildIdKind::Hexstring:284 case BuildIdKind::Hexstring:
279 return Config->BuildIdVector.size();285 return config->buildIdVector.size();
280 default:286 default:
281 llvm_unreachable("unknown BuildIdKind");287 llvm_unreachable("unknown BuildIdKind");
282 }288 }
283}289}
284290
291// This class represents a linker-synthesized .note.gnu.property section.
292//
293// In x86 and AArch64, object files may contain feature flags indicating the
294// features that they have used. The flags are stored in a .note.gnu.property
295// section.
296//
297// lld reads the sections from input files and merges them by computing AND of
298// the flags. The result is written as a new .note.gnu.property section.
299//
300// If the flag is zero (which indicates that the intersection of the feature
301// sets is empty, or some input files didn't have .note.gnu.property sections),
302// we don't create this section.
303GnuPropertySection::GnuPropertySection()
304 : SyntheticSection(llvm::ELF::SHF_ALLOC, llvm::ELF::SHT_NOTE, 4,
305 ".note.gnu.property") {}
306
307void GnuPropertySection::writeTo(uint8_t *buf) {
308 uint32_t featureAndType = config->emachine == EM_AARCH64
309 ? GNU_PROPERTY_AARCH64_FEATURE_1_AND
310 : GNU_PROPERTY_X86_FEATURE_1_AND;
311
312 write32(buf, 4); // Name size
313 write32(buf + 4, config->is64 ? 16 : 12); // Content size
314 write32(buf + 8, NT_GNU_PROPERTY_TYPE_0); // Type
315 memcpy(buf + 12, "GNU", 4); // Name string
316 write32(buf + 16, featureAndType); // Feature type
317 write32(buf + 20, 4); // Feature size
318 write32(buf + 24, config->andFeatures); // Feature flags
319 if (config->is64)
320 write32(buf + 28, 0); // Padding
321}
322
323size_t GnuPropertySection::getSize() const { return config->is64 ? 32 : 28; }
324
285BuildIdSection::BuildIdSection()325BuildIdSection::BuildIdSection()
286 : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"),326 : SyntheticSection(SHF_ALLOC, SHT_NOTE, 4, ".note.gnu.build-id"),
287 HashSize(getHashSize()) {}327 hashSize(getHashSize()) {}
288
289void BuildIdSection::writeTo(uint8_t *Buf) {
290 write32(Buf, 4); // Name size
291 write32(Buf + 4, HashSize); // Content size
292 write32(Buf + 8, NT_GNU_BUILD_ID); // Type
293 memcpy(Buf + 12, "GNU", 4); // Name string
294 HashBuf = Buf + 16;
295}
296
297// Split one uint8 array into small pieces of uint8 arrays.
298static std::vector<ArrayRef<uint8_t>> split(ArrayRef<uint8_t> Arr,
299 size_t ChunkSize) {
300 std::vector<ArrayRef<uint8_t>> Ret;
301 while (Arr.size() > ChunkSize) {
302 Ret.push_back(Arr.take_front(ChunkSize));
303 Arr = Arr.drop_front(ChunkSize);
304 }
305 if (!Arr.empty())
306 Ret.push_back(Arr);
307 return Ret;
308}
309
310// Computes a hash value of Data using a given hash function.
311// In order to utilize multiple cores, we first split data into 1MB
312// chunks, compute a hash for each chunk, and then compute a hash value
313// of the hash values.
314void BuildIdSection::computeHash(
315 llvm::ArrayRef<uint8_t> Data,
316 std::function<void(uint8_t *Dest, ArrayRef<uint8_t> Arr)> HashFn) {
317 std::vector<ArrayRef<uint8_t>> Chunks = split(Data, 1024 * 1024);
318 std::vector<uint8_t> Hashes(Chunks.size() * HashSize);
319
320 // Compute hash values.
321 parallelForEachN(0, Chunks.size(), [&](size_t I) {
322 HashFn(Hashes.data() + I * HashSize, Chunks[I]);
323 });
324328
325 // Write to the final output buffer.329void BuildIdSection::writeTo(uint8_t *buf) {
326 HashFn(HashBuf, Hashes);330 write32(buf, 4); // Name size
331 write32(buf + 4, hashSize); // Content size
332 write32(buf + 8, NT_GNU_BUILD_ID); // Type
333 memcpy(buf + 12, "GNU", 4); // Name string
334 hashBuf = buf + 16;
327}335}
328336
329BssSection::BssSection(StringRef Name, uint64_t Size, uint32_t Alignment)337void BuildIdSection::writeBuildId(ArrayRef<uint8_t> buf) {
330 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, Alignment, Name) {338 assert(buf.size() == hashSize);
331 this->Bss = true;339 memcpy(hashBuf, buf.data(), hashSize);
332 this->Size = Size;
333}340}
334341
335void BuildIdSection::writeBuildId(ArrayRef<uint8_t> Buf) {342BssSection::BssSection(StringRef name, uint64_t size, uint32_t alignment)
336 switch (Config->BuildId) {343 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_NOBITS, alignment, name) {
337 case BuildIdKind::Fast:344 this->bss = true;
338 computeHash(Buf, [](uint8_t *Dest, ArrayRef<uint8_t> Arr) {345 this->size = size;
339 write64le(Dest, xxHash64(Arr));
340 });
341 break;
342 case BuildIdKind::Md5:
343 computeHash(Buf, [](uint8_t *Dest, ArrayRef<uint8_t> Arr) {
344 memcpy(Dest, MD5::hash(Arr).data(), 16);
345 });
346 break;
347 case BuildIdKind::Sha1:
348 computeHash(Buf, [](uint8_t *Dest, ArrayRef<uint8_t> Arr) {
349 memcpy(Dest, SHA1::hash(Arr).data(), 20);
350 });
351 break;
352 case BuildIdKind::Uuid:
353 if (auto EC = getRandomBytes(HashBuf, HashSize))
354 error("entropy source failure: " + EC.message());
355 break;
356 case BuildIdKind::Hexstring:
357 memcpy(HashBuf, Config->BuildIdVector.data(), Config->BuildIdVector.size());
358 break;
359 default:
360 llvm_unreachable("unknown BuildIdKind");
361 }
362}346}
363347
364EhFrameSection::EhFrameSection()348EhFrameSection::EhFrameSection()
...@@ -368,47 +352,48 @@ EhFrameSection::EhFrameSection()...@@ -368,47 +352,48 @@ EhFrameSection::EhFrameSection()
368// CIE records from input object files are uniquified by their contents352// CIE records from input object files are uniquified by their contents
369// and where their relocations point to.353// and where their relocations point to.
370template <class ELFT, class RelTy>354template <class ELFT, class RelTy>
371CieRecord *EhFrameSection::addCie(EhSectionPiece &Cie, ArrayRef<RelTy> Rels) {355CieRecord *EhFrameSection::addCie(EhSectionPiece &cie, ArrayRef<RelTy> rels) {
372 Symbol *Personality = nullptr;356 Symbol *personality = nullptr;
373 unsigned FirstRelI = Cie.FirstRelocation;357 unsigned firstRelI = cie.firstRelocation;
374 if (FirstRelI != (unsigned)-1)358 if (firstRelI != (unsigned)-1)
375 Personality =359 personality =
376 &Cie.Sec->template getFile<ELFT>()->getRelocTargetSym(Rels[FirstRelI]);360 &cie.sec->template getFile<ELFT>()->getRelocTargetSym(rels[firstRelI]);
377361
378 // Search for an existing CIE by CIE contents/relocation target pair.362 // Search for an existing CIE by CIE contents/relocation target pair.
379 CieRecord *&Rec = CieMap[{Cie.data(), Personality}];363 CieRecord *&rec = cieMap[{cie.data(), personality}];
380364
381 // If not found, create a new one.365 // If not found, create a new one.
382 if (!Rec) {366 if (!rec) {
383 Rec = make<CieRecord>();367 rec = make<CieRecord>();
384 Rec->Cie = &Cie;368 rec->cie = &cie;
385 CieRecords.push_back(Rec);369 cieRecords.push_back(rec);
386 }370 }
387 return Rec;371 return rec;
388}372}
389373
390// There is one FDE per function. Returns true if a given FDE374// There is one FDE per function. Returns true if a given FDE
391// points to a live function.375// points to a live function.
392template <class ELFT, class RelTy>376template <class ELFT, class RelTy>
393bool EhFrameSection::isFdeLive(EhSectionPiece &Fde, ArrayRef<RelTy> Rels) {377bool EhFrameSection::isFdeLive(EhSectionPiece &fde, ArrayRef<RelTy> rels) {
394 auto *Sec = cast<EhInputSection>(Fde.Sec);378 auto *sec = cast<EhInputSection>(fde.sec);
395 unsigned FirstRelI = Fde.FirstRelocation;379 unsigned firstRelI = fde.firstRelocation;
396380
397 // An FDE should point to some function because FDEs are to describe381 // An FDE should point to some function because FDEs are to describe
398 // functions. That's however not always the case due to an issue of382 // functions. That's however not always the case due to an issue of
399 // ld.gold with -r. ld.gold may discard only functions and leave their383 // ld.gold with -r. ld.gold may discard only functions and leave their
400 // corresponding FDEs, which results in creating bad .eh_frame sections.384 // corresponding FDEs, which results in creating bad .eh_frame sections.
401 // To deal with that, we ignore such FDEs.385 // To deal with that, we ignore such FDEs.
402 if (FirstRelI == (unsigned)-1)386 if (firstRelI == (unsigned)-1)
403 return false;387 return false;
404388
405 const RelTy &Rel = Rels[FirstRelI];389 const RelTy &rel = rels[firstRelI];
406 Symbol &B = Sec->template getFile<ELFT>()->getRelocTargetSym(Rel);390 Symbol &b = sec->template getFile<ELFT>()->getRelocTargetSym(rel);
407391
408 // FDEs for garbage-collected or merged-by-ICF sections are dead.392 // FDEs for garbage-collected or merged-by-ICF sections, or sections in
409 if (auto *D = dyn_cast<Defined>(&B))393 // another partition, are dead.
410 if (SectionBase *Sec = D->Section)394 if (auto *d = dyn_cast<Defined>(&b))
411 return Sec->Live;395 if (SectionBase *sec = d->section)
396 return sec->partition == partition;
412 return false;397 return false;
413}398}
414399
...@@ -417,73 +402,73 @@ bool EhFrameSection::isFdeLive(EhSectionPiece &Fde, ArrayRef<RelTy> Rels) {...@@ -417,73 +402,73 @@ bool EhFrameSection::isFdeLive(EhSectionPiece &Fde, ArrayRef<RelTy> Rels) {
417// a list of FDEs. This function searches an existing CIE or create a new402// a list of FDEs. This function searches an existing CIE or create a new
418// one and associates FDEs to the CIE.403// one and associates FDEs to the CIE.
419template <class ELFT, class RelTy>404template <class ELFT, class RelTy>
420void EhFrameSection::addSectionAux(EhInputSection *Sec, ArrayRef<RelTy> Rels) {405void EhFrameSection::addSectionAux(EhInputSection *sec, ArrayRef<RelTy> rels) {
421 OffsetToCie.clear();406 offsetToCie.clear();
422 for (EhSectionPiece &Piece : Sec->Pieces) {407 for (EhSectionPiece &piece : sec->pieces) {
423 // The empty record is the end marker.408 // The empty record is the end marker.
424 if (Piece.Size == 4)409 if (piece.size == 4)
425 return;410 return;
426411
427 size_t Offset = Piece.InputOff;412 size_t offset = piece.inputOff;
428 uint32_t ID = read32(Piece.data().data() + 4);413 uint32_t id = read32(piece.data().data() + 4);
429 if (ID == 0) {414 if (id == 0) {
430 OffsetToCie[Offset] = addCie<ELFT>(Piece, Rels);415 offsetToCie[offset] = addCie<ELFT>(piece, rels);
431 continue;416 continue;
432 }417 }
433418
434 uint32_t CieOffset = Offset + 4 - ID;419 uint32_t cieOffset = offset + 4 - id;
435 CieRecord *Rec = OffsetToCie[CieOffset];420 CieRecord *rec = offsetToCie[cieOffset];
436 if (!Rec)421 if (!rec)
437 fatal(toString(Sec) + ": invalid CIE reference");422 fatal(toString(sec) + ": invalid CIE reference");
438423
439 if (!isFdeLive<ELFT>(Piece, Rels))424 if (!isFdeLive<ELFT>(piece, rels))
440 continue;425 continue;
441 Rec->Fdes.push_back(&Piece);426 rec->fdes.push_back(&piece);
442 NumFdes++;427 numFdes++;
443 }428 }
444}429}
445430
446template <class ELFT> void EhFrameSection::addSection(InputSectionBase *C) {431template <class ELFT> void EhFrameSection::addSection(InputSectionBase *c) {
447 auto *Sec = cast<EhInputSection>(C);432 auto *sec = cast<EhInputSection>(c);
448 Sec->Parent = this;433 sec->parent = this;
449434
450 Alignment = std::max(Alignment, Sec->Alignment);435 alignment = std::max(alignment, sec->alignment);
451 Sections.push_back(Sec);436 sections.push_back(sec);
452437
453 for (auto *DS : Sec->DependentSections)438 for (auto *ds : sec->dependentSections)
454 DependentSections.push_back(DS);439 dependentSections.push_back(ds);
455440
456 if (Sec->Pieces.empty())441 if (sec->pieces.empty())
457 return;442 return;
458443
459 if (Sec->AreRelocsRela)444 if (sec->areRelocsRela)
460 addSectionAux<ELFT>(Sec, Sec->template relas<ELFT>());445 addSectionAux<ELFT>(sec, sec->template relas<ELFT>());
461 else446 else
462 addSectionAux<ELFT>(Sec, Sec->template rels<ELFT>());447 addSectionAux<ELFT>(sec, sec->template rels<ELFT>());
463}448}
464449
465static void writeCieFde(uint8_t *Buf, ArrayRef<uint8_t> D) {450static void writeCieFde(uint8_t *buf, ArrayRef<uint8_t> d) {
466 memcpy(Buf, D.data(), D.size());451 memcpy(buf, d.data(), d.size());
467452
468 size_t Aligned = alignTo(D.size(), Config->Wordsize);453 size_t aligned = alignTo(d.size(), config->wordsize);
469454
470 // Zero-clear trailing padding if it exists.455 // Zero-clear trailing padding if it exists.
471 memset(Buf + D.size(), 0, Aligned - D.size());456 memset(buf + d.size(), 0, aligned - d.size());
472457
473 // Fix the size field. -4 since size does not include the size field itself.458 // Fix the size field. -4 since size does not include the size field itself.
474 write32(Buf, Aligned - 4);459 write32(buf, aligned - 4);
475}460}
476461
477void EhFrameSection::finalizeContents() {462void EhFrameSection::finalizeContents() {
478 assert(!this->Size); // Not finalized.463 assert(!this->size); // Not finalized.
479 size_t Off = 0;464 size_t off = 0;
480 for (CieRecord *Rec : CieRecords) {465 for (CieRecord *rec : cieRecords) {
481 Rec->Cie->OutputOff = Off;466 rec->cie->outputOff = off;
482 Off += alignTo(Rec->Cie->Size, Config->Wordsize);467 off += alignTo(rec->cie->size, config->wordsize);
483468
484 for (EhSectionPiece *Fde : Rec->Fdes) {469 for (EhSectionPiece *fde : rec->fdes) {
485 Fde->OutputOff = Off;470 fde->outputOff = off;
486 Off += alignTo(Fde->Size, Config->Wordsize);471 off += alignTo(fde->size, config->wordsize);
487 }472 }
488 }473 }
489474
...@@ -491,375 +476,374 @@ void EhFrameSection::finalizeContents() {...@@ -491,375 +476,374 @@ void EhFrameSection::finalizeContents() {
491 // Call Frame Information records. glibc unwind-dw2-fde.c476 // Call Frame Information records. glibc unwind-dw2-fde.c
492 // classify_object_over_fdes expects there is a CIE record length 0 as a477 // classify_object_over_fdes expects there is a CIE record length 0 as a
493 // terminator. Thus we add one unconditionally.478 // terminator. Thus we add one unconditionally.
494 Off += 4;479 off += 4;
495480
496 this->Size = Off;481 this->size = off;
497}482}
498483
499// Returns data for .eh_frame_hdr. .eh_frame_hdr is a binary search table484// Returns data for .eh_frame_hdr. .eh_frame_hdr is a binary search table
500// to get an FDE from an address to which FDE is applied. This function485// to get an FDE from an address to which FDE is applied. This function
501// returns a list of such pairs.486// returns a list of such pairs.
502std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const {487std::vector<EhFrameSection::FdeData> EhFrameSection::getFdeData() const {
503 uint8_t *Buf = getParent()->Loc + OutSecOff;488 uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff;
504 std::vector<FdeData> Ret;489 std::vector<FdeData> ret;
505490
506 uint64_t VA = In.EhFrameHdr->getVA();491 uint64_t va = getPartition().ehFrameHdr->getVA();
507 for (CieRecord *Rec : CieRecords) {492 for (CieRecord *rec : cieRecords) {
508 uint8_t Enc = getFdeEncoding(Rec->Cie);493 uint8_t enc = getFdeEncoding(rec->cie);
509 for (EhSectionPiece *Fde : Rec->Fdes) {494 for (EhSectionPiece *fde : rec->fdes) {
510 uint64_t Pc = getFdePc(Buf, Fde->OutputOff, Enc);495 uint64_t pc = getFdePc(buf, fde->outputOff, enc);
511 uint64_t FdeVA = getParent()->Addr + Fde->OutputOff;496 uint64_t fdeVA = getParent()->addr + fde->outputOff;
512 if (!isInt<32>(Pc - VA))497 if (!isInt<32>(pc - va))
513 fatal(toString(Fde->Sec) + ": PC offset is too large: 0x" +498 fatal(toString(fde->sec) + ": PC offset is too large: 0x" +
514 Twine::utohexstr(Pc - VA));499 Twine::utohexstr(pc - va));
515 Ret.push_back({uint32_t(Pc - VA), uint32_t(FdeVA - VA)});500 ret.push_back({uint32_t(pc - va), uint32_t(fdeVA - va)});
516 }501 }
517 }502 }
518503
519 // Sort the FDE list by their PC and uniqueify. Usually there is only504 // Sort the FDE list by their PC and uniqueify. Usually there is only
520 // one FDE for a PC (i.e. function), but if ICF merges two functions505 // one FDE for a PC (i.e. function), but if ICF merges two functions
521 // into one, there can be more than one FDEs pointing to the address.506 // into one, there can be more than one FDEs pointing to the address.
522 auto Less = [](const FdeData &A, const FdeData &B) {507 auto less = [](const FdeData &a, const FdeData &b) {
523 return A.PcRel < B.PcRel;508 return a.pcRel < b.pcRel;
524 };509 };
525 std::stable_sort(Ret.begin(), Ret.end(), Less);510 llvm::stable_sort(ret, less);
526 auto Eq = [](const FdeData &A, const FdeData &B) {511 auto eq = [](const FdeData &a, const FdeData &b) {
527 return A.PcRel == B.PcRel;512 return a.pcRel == b.pcRel;
528 };513 };
529 Ret.erase(std::unique(Ret.begin(), Ret.end(), Eq), Ret.end());514 ret.erase(std::unique(ret.begin(), ret.end(), eq), ret.end());
530515
531 return Ret;516 return ret;
532}517}
533518
534static uint64_t readFdeAddr(uint8_t *Buf, int Size) {519static uint64_t readFdeAddr(uint8_t *buf, int size) {
535 switch (Size) {520 switch (size) {
536 case DW_EH_PE_udata2:521 case DW_EH_PE_udata2:
537 return read16(Buf);522 return read16(buf);
538 case DW_EH_PE_sdata2:523 case DW_EH_PE_sdata2:
539 return (int16_t)read16(Buf);524 return (int16_t)read16(buf);
540 case DW_EH_PE_udata4:525 case DW_EH_PE_udata4:
541 return read32(Buf);526 return read32(buf);
542 case DW_EH_PE_sdata4:527 case DW_EH_PE_sdata4:
543 return (int32_t)read32(Buf);528 return (int32_t)read32(buf);
544 case DW_EH_PE_udata8:529 case DW_EH_PE_udata8:
545 case DW_EH_PE_sdata8:530 case DW_EH_PE_sdata8:
546 return read64(Buf);531 return read64(buf);
547 case DW_EH_PE_absptr:532 case DW_EH_PE_absptr:
548 return readUint(Buf);533 return readUint(buf);
549 }534 }
550 fatal("unknown FDE size encoding");535 fatal("unknown FDE size encoding");
551}536}
552537
553// Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to.538// Returns the VA to which a given FDE (on a mmap'ed buffer) is applied to.
554// We need it to create .eh_frame_hdr section.539// We need it to create .eh_frame_hdr section.
555uint64_t EhFrameSection::getFdePc(uint8_t *Buf, size_t FdeOff,540uint64_t EhFrameSection::getFdePc(uint8_t *buf, size_t fdeOff,
556 uint8_t Enc) const {541 uint8_t enc) const {
557 // The starting address to which this FDE applies is542 // The starting address to which this FDE applies is
558 // stored at FDE + 8 byte.543 // stored at FDE + 8 byte.
559 size_t Off = FdeOff + 8;544 size_t off = fdeOff + 8;
560 uint64_t Addr = readFdeAddr(Buf + Off, Enc & 0xf);545 uint64_t addr = readFdeAddr(buf + off, enc & 0xf);
561 if ((Enc & 0x70) == DW_EH_PE_absptr)546 if ((enc & 0x70) == DW_EH_PE_absptr)
562 return Addr;547 return addr;
563 if ((Enc & 0x70) == DW_EH_PE_pcrel)548 if ((enc & 0x70) == DW_EH_PE_pcrel)
564 return Addr + getParent()->Addr + Off;549 return addr + getParent()->addr + off;
565 fatal("unknown FDE size relative encoding");550 fatal("unknown FDE size relative encoding");
566}551}
567552
568void EhFrameSection::writeTo(uint8_t *Buf) {553void EhFrameSection::writeTo(uint8_t *buf) {
569 // Write CIE and FDE records.554 // Write CIE and FDE records.
570 for (CieRecord *Rec : CieRecords) {555 for (CieRecord *rec : cieRecords) {
571 size_t CieOffset = Rec->Cie->OutputOff;556 size_t cieOffset = rec->cie->outputOff;
572 writeCieFde(Buf + CieOffset, Rec->Cie->data());557 writeCieFde(buf + cieOffset, rec->cie->data());
573558
574 for (EhSectionPiece *Fde : Rec->Fdes) {559 for (EhSectionPiece *fde : rec->fdes) {
575 size_t Off = Fde->OutputOff;560 size_t off = fde->outputOff;
576 writeCieFde(Buf + Off, Fde->data());561 writeCieFde(buf + off, fde->data());
577562
578 // FDE's second word should have the offset to an associated CIE.563 // FDE's second word should have the offset to an associated CIE.
579 // Write it.564 // Write it.
580 write32(Buf + Off + 4, Off + 4 - CieOffset);565 write32(buf + off + 4, off + 4 - cieOffset);
581 }566 }
582 }567 }
583568
584 // Apply relocations. .eh_frame section contents are not contiguous569 // Apply relocations. .eh_frame section contents are not contiguous
585 // in the output buffer, but relocateAlloc() still works because570 // in the output buffer, but relocateAlloc() still works because
586 // getOffset() takes care of discontiguous section pieces.571 // getOffset() takes care of discontiguous section pieces.
587 for (EhInputSection *S : Sections)572 for (EhInputSection *s : sections)
588 S->relocateAlloc(Buf, nullptr);573 s->relocateAlloc(buf, nullptr);
574
575 if (getPartition().ehFrameHdr && getPartition().ehFrameHdr->getParent())
576 getPartition().ehFrameHdr->write();
589}577}
590578
591GotSection::GotSection()579GotSection::GotSection()
592 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS,580 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
593 Target->GotEntrySize, ".got") {581 ".got") {
594 // PPC64 saves the ElfSym::GlobalOffsetTable .TOC. as the first entry in the582 // If ElfSym::globalOffsetTable is relative to .got and is referenced,
595 // .got. If there are no references to .TOC. in the symbol table,583 // increase numEntries by the number of entries used to emit
596 // ElfSym::GlobalOffsetTable will not be defined and we won't need to save584 // ElfSym::globalOffsetTable.
597 // .TOC. in the .got. When it is defined, we increase NumEntries by the number585 if (ElfSym::globalOffsetTable && !target->gotBaseSymInGotPlt)
598 // of entries used to emit ElfSym::GlobalOffsetTable.586 numEntries += target->gotHeaderEntriesNum;
599 if (ElfSym::GlobalOffsetTable && !Target->GotBaseSymInGotPlt)
600 NumEntries += Target->GotHeaderEntriesNum;
601}587}
602588
603void GotSection::addEntry(Symbol &Sym) {589void GotSection::addEntry(Symbol &sym) {
604 Sym.GotIndex = NumEntries;590 sym.gotIndex = numEntries;
605 ++NumEntries;591 ++numEntries;
606}592}
607593
608bool GotSection::addDynTlsEntry(Symbol &Sym) {594bool GotSection::addDynTlsEntry(Symbol &sym) {
609 if (Sym.GlobalDynIndex != -1U)595 if (sym.globalDynIndex != -1U)
610 return false;596 return false;
611 Sym.GlobalDynIndex = NumEntries;597 sym.globalDynIndex = numEntries;
612 // Global Dynamic TLS entries take two GOT slots.598 // Global Dynamic TLS entries take two GOT slots.
613 NumEntries += 2;599 numEntries += 2;
614 return true;600 return true;
615}601}
616602
617// Reserves TLS entries for a TLS module ID and a TLS block offset.603// Reserves TLS entries for a TLS module ID and a TLS block offset.
618// In total it takes two GOT slots.604// In total it takes two GOT slots.
619bool GotSection::addTlsIndex() {605bool GotSection::addTlsIndex() {
620 if (TlsIndexOff != uint32_t(-1))606 if (tlsIndexOff != uint32_t(-1))
621 return false;607 return false;
622 TlsIndexOff = NumEntries * Config->Wordsize;608 tlsIndexOff = numEntries * config->wordsize;
623 NumEntries += 2;609 numEntries += 2;
624 return true;610 return true;
625}611}
626612
627uint64_t GotSection::getGlobalDynAddr(const Symbol &B) const {613uint64_t GotSection::getGlobalDynAddr(const Symbol &b) const {
628 return this->getVA() + B.GlobalDynIndex * Config->Wordsize;614 return this->getVA() + b.globalDynIndex * config->wordsize;
629}615}
630616
631uint64_t GotSection::getGlobalDynOffset(const Symbol &B) const {617uint64_t GotSection::getGlobalDynOffset(const Symbol &b) const {
632 return B.GlobalDynIndex * Config->Wordsize;618 return b.globalDynIndex * config->wordsize;
633}619}
634620
635void GotSection::finalizeContents() {621void GotSection::finalizeContents() {
636 Size = NumEntries * Config->Wordsize;622 size = numEntries * config->wordsize;
637}623}
638624
639bool GotSection::empty() const {625bool GotSection::isNeeded() const {
640 // We need to emit a GOT even if it's empty if there's a relocation that is626 // We need to emit a GOT even if it's empty if there's a relocation that is
641 // relative to GOT(such as GOTOFFREL) or there's a symbol that points to a GOT627 // relative to GOT(such as GOTOFFREL).
642 // (i.e. _GLOBAL_OFFSET_TABLE_) that the target defines relative to the .got.628 return numEntries || hasGotOffRel;
643 return NumEntries == 0 && !HasGotOffRel &&
644 !(ElfSym::GlobalOffsetTable && !Target->GotBaseSymInGotPlt);
645}629}
646630
647void GotSection::writeTo(uint8_t *Buf) {631void GotSection::writeTo(uint8_t *buf) {
648 // Buf points to the start of this section's buffer,632 // Buf points to the start of this section's buffer,
649 // whereas InputSectionBase::relocateAlloc() expects its argument633 // whereas InputSectionBase::relocateAlloc() expects its argument
650 // to point to the start of the output section.634 // to point to the start of the output section.
651 Target->writeGotHeader(Buf);635 target->writeGotHeader(buf);
652 relocateAlloc(Buf - OutSecOff, Buf - OutSecOff + Size);636 relocateAlloc(buf - outSecOff, buf - outSecOff + size);
653}637}
654638
655static uint64_t getMipsPageAddr(uint64_t Addr) {639static uint64_t getMipsPageAddr(uint64_t addr) {
656 return (Addr + 0x8000) & ~0xffff;640 return (addr + 0x8000) & ~0xffff;
657}641}
658642
659static uint64_t getMipsPageCount(uint64_t Size) {643static uint64_t getMipsPageCount(uint64_t size) {
660 return (Size + 0xfffe) / 0xffff + 1;644 return (size + 0xfffe) / 0xffff + 1;
661}645}
662646
663MipsGotSection::MipsGotSection()647MipsGotSection::MipsGotSection()
664 : SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16,648 : SyntheticSection(SHF_ALLOC | SHF_WRITE | SHF_MIPS_GPREL, SHT_PROGBITS, 16,
665 ".got") {}649 ".got") {}
666650
667void MipsGotSection::addEntry(InputFile &File, Symbol &Sym, int64_t Addend,651void MipsGotSection::addEntry(InputFile &file, Symbol &sym, int64_t addend,
668 RelExpr Expr) {652 RelExpr expr) {
669 FileGot &G = getGot(File);653 FileGot &g = getGot(file);
670 if (Expr == R_MIPS_GOT_LOCAL_PAGE) {654 if (expr == R_MIPS_GOT_LOCAL_PAGE) {
671 if (const OutputSection *OS = Sym.getOutputSection())655 if (const OutputSection *os = sym.getOutputSection())
672 G.PagesMap.insert({OS, {}});656 g.pagesMap.insert({os, {}});
673 else657 else
674 G.Local16.insert({{nullptr, getMipsPageAddr(Sym.getVA(Addend))}, 0});658 g.local16.insert({{nullptr, getMipsPageAddr(sym.getVA(addend))}, 0});
675 } else if (Sym.isTls())659 } else if (sym.isTls())
676 G.Tls.insert({&Sym, 0});660 g.tls.insert({&sym, 0});
677 else if (Sym.IsPreemptible && Expr == R_ABS)661 else if (sym.isPreemptible && expr == R_ABS)
678 G.Relocs.insert({&Sym, 0});662 g.relocs.insert({&sym, 0});
679 else if (Sym.IsPreemptible)663 else if (sym.isPreemptible)
680 G.Global.insert({&Sym, 0});664 g.global.insert({&sym, 0});
681 else if (Expr == R_MIPS_GOT_OFF32)665 else if (expr == R_MIPS_GOT_OFF32)
682 G.Local32.insert({{&Sym, Addend}, 0});666 g.local32.insert({{&sym, addend}, 0});
683 else667 else
684 G.Local16.insert({{&Sym, Addend}, 0});668 g.local16.insert({{&sym, addend}, 0});
685}669}
686670
687void MipsGotSection::addDynTlsEntry(InputFile &File, Symbol &Sym) {671void MipsGotSection::addDynTlsEntry(InputFile &file, Symbol &sym) {
688 getGot(File).DynTlsSymbols.insert({&Sym, 0});672 getGot(file).dynTlsSymbols.insert({&sym, 0});
689}673}
690674
691void MipsGotSection::addTlsIndex(InputFile &File) {675void MipsGotSection::addTlsIndex(InputFile &file) {
692 getGot(File).DynTlsSymbols.insert({nullptr, 0});676 getGot(file).dynTlsSymbols.insert({nullptr, 0});
693}677}
694678
695size_t MipsGotSection::FileGot::getEntriesNum() const {679size_t MipsGotSection::FileGot::getEntriesNum() const {
696 return getPageEntriesNum() + Local16.size() + Global.size() + Relocs.size() +680 return getPageEntriesNum() + local16.size() + global.size() + relocs.size() +
697 Tls.size() + DynTlsSymbols.size() * 2;681 tls.size() + dynTlsSymbols.size() * 2;
698}682}
699683
700size_t MipsGotSection::FileGot::getPageEntriesNum() const {684size_t MipsGotSection::FileGot::getPageEntriesNum() const {
701 size_t Num = 0;685 size_t num = 0;
702 for (const std::pair<const OutputSection *, FileGot::PageBlock> &P : PagesMap)686 for (const std::pair<const OutputSection *, FileGot::PageBlock> &p : pagesMap)
703 Num += P.second.Count;687 num += p.second.count;
704 return Num;688 return num;
705}689}
706690
707size_t MipsGotSection::FileGot::getIndexedEntriesNum() const {691size_t MipsGotSection::FileGot::getIndexedEntriesNum() const {
708 size_t Count = getPageEntriesNum() + Local16.size() + Global.size();692 size_t count = getPageEntriesNum() + local16.size() + global.size();
709 // If there are relocation-only entries in the GOT, TLS entries693 // If there are relocation-only entries in the GOT, TLS entries
710 // are allocated after them. TLS entries should be addressable694 // are allocated after them. TLS entries should be addressable
711 // by 16-bit index so count both reloc-only and TLS entries.695 // by 16-bit index so count both reloc-only and TLS entries.
712 if (!Tls.empty() || !DynTlsSymbols.empty())696 if (!tls.empty() || !dynTlsSymbols.empty())
713 Count += Relocs.size() + Tls.size() + DynTlsSymbols.size() * 2;697 count += relocs.size() + tls.size() + dynTlsSymbols.size() * 2;
714 return Count;698 return count;
715}699}
716700
717MipsGotSection::FileGot &MipsGotSection::getGot(InputFile &F) {701MipsGotSection::FileGot &MipsGotSection::getGot(InputFile &f) {
718 if (!F.MipsGotIndex.hasValue()) {702 if (!f.mipsGotIndex.hasValue()) {
719 Gots.emplace_back();703 gots.emplace_back();
720 Gots.back().File = &F;704 gots.back().file = &f;
721 F.MipsGotIndex = Gots.size() - 1;705 f.mipsGotIndex = gots.size() - 1;
722 }706 }
723 return Gots[*F.MipsGotIndex];707 return gots[*f.mipsGotIndex];
724}708}
725709
726uint64_t MipsGotSection::getPageEntryOffset(const InputFile *F,710uint64_t MipsGotSection::getPageEntryOffset(const InputFile *f,
727 const Symbol &Sym,711 const Symbol &sym,
728 int64_t Addend) const {712 int64_t addend) const {
729 const FileGot &G = Gots[*F->MipsGotIndex];713 const FileGot &g = gots[*f->mipsGotIndex];
730 uint64_t Index = 0;714 uint64_t index = 0;
731 if (const OutputSection *OutSec = Sym.getOutputSection()) {715 if (const OutputSection *outSec = sym.getOutputSection()) {
732 uint64_t SecAddr = getMipsPageAddr(OutSec->Addr);716 uint64_t secAddr = getMipsPageAddr(outSec->addr);
733 uint64_t SymAddr = getMipsPageAddr(Sym.getVA(Addend));717 uint64_t symAddr = getMipsPageAddr(sym.getVA(addend));
734 Index = G.PagesMap.lookup(OutSec).FirstIndex + (SymAddr - SecAddr) / 0xffff;718 index = g.pagesMap.lookup(outSec).firstIndex + (symAddr - secAddr) / 0xffff;
735 } else {719 } else {
736 Index = G.Local16.lookup({nullptr, getMipsPageAddr(Sym.getVA(Addend))});720 index = g.local16.lookup({nullptr, getMipsPageAddr(sym.getVA(addend))});
737 }721 }
738 return Index * Config->Wordsize;722 return index * config->wordsize;
739}723}
740724
741uint64_t MipsGotSection::getSymEntryOffset(const InputFile *F, const Symbol &S,725uint64_t MipsGotSection::getSymEntryOffset(const InputFile *f, const Symbol &s,
742 int64_t Addend) const {726 int64_t addend) const {
743 const FileGot &G = Gots[*F->MipsGotIndex];727 const FileGot &g = gots[*f->mipsGotIndex];
744 Symbol *Sym = const_cast<Symbol *>(&S);728 Symbol *sym = const_cast<Symbol *>(&s);
745 if (Sym->isTls())729 if (sym->isTls())
746 return G.Tls.lookup(Sym) * Config->Wordsize;730 return g.tls.lookup(sym) * config->wordsize;
747 if (Sym->IsPreemptible)731 if (sym->isPreemptible)
748 return G.Global.lookup(Sym) * Config->Wordsize;732 return g.global.lookup(sym) * config->wordsize;
749 return G.Local16.lookup({Sym, Addend}) * Config->Wordsize;733 return g.local16.lookup({sym, addend}) * config->wordsize;
750}734}
751735
752uint64_t MipsGotSection::getTlsIndexOffset(const InputFile *F) const {736uint64_t MipsGotSection::getTlsIndexOffset(const InputFile *f) const {
753 const FileGot &G = Gots[*F->MipsGotIndex];737 const FileGot &g = gots[*f->mipsGotIndex];
754 return G.DynTlsSymbols.lookup(nullptr) * Config->Wordsize;738 return g.dynTlsSymbols.lookup(nullptr) * config->wordsize;
755}739}
756740
757uint64_t MipsGotSection::getGlobalDynOffset(const InputFile *F,741uint64_t MipsGotSection::getGlobalDynOffset(const InputFile *f,
758 const Symbol &S) const {742 const Symbol &s) const {
759 const FileGot &G = Gots[*F->MipsGotIndex];743 const FileGot &g = gots[*f->mipsGotIndex];
760 Symbol *Sym = const_cast<Symbol *>(&S);744 Symbol *sym = const_cast<Symbol *>(&s);
761 return G.DynTlsSymbols.lookup(Sym) * Config->Wordsize;745 return g.dynTlsSymbols.lookup(sym) * config->wordsize;
762}746}
763747
764const Symbol *MipsGotSection::getFirstGlobalEntry() const {748const Symbol *MipsGotSection::getFirstGlobalEntry() const {
765 if (Gots.empty())749 if (gots.empty())
766 return nullptr;750 return nullptr;
767 const FileGot &PrimGot = Gots.front();751 const FileGot &primGot = gots.front();
768 if (!PrimGot.Global.empty())752 if (!primGot.global.empty())
769 return PrimGot.Global.front().first;753 return primGot.global.front().first;
770 if (!PrimGot.Relocs.empty())754 if (!primGot.relocs.empty())
771 return PrimGot.Relocs.front().first;755 return primGot.relocs.front().first;
772 return nullptr;756 return nullptr;
773}757}
774758
775unsigned MipsGotSection::getLocalEntriesNum() const {759unsigned MipsGotSection::getLocalEntriesNum() const {
776 if (Gots.empty())760 if (gots.empty())
777 return HeaderEntriesNum;761 return headerEntriesNum;
778 return HeaderEntriesNum + Gots.front().getPageEntriesNum() +762 return headerEntriesNum + gots.front().getPageEntriesNum() +
779 Gots.front().Local16.size();763 gots.front().local16.size();
780}764}
781765
782bool MipsGotSection::tryMergeGots(FileGot &Dst, FileGot &Src, bool IsPrimary) {766bool MipsGotSection::tryMergeGots(FileGot &dst, FileGot &src, bool isPrimary) {
783 FileGot Tmp = Dst;767 FileGot tmp = dst;
784 set_union(Tmp.PagesMap, Src.PagesMap);768 set_union(tmp.pagesMap, src.pagesMap);
785 set_union(Tmp.Local16, Src.Local16);769 set_union(tmp.local16, src.local16);
786 set_union(Tmp.Global, Src.Global);770 set_union(tmp.global, src.global);
787 set_union(Tmp.Relocs, Src.Relocs);771 set_union(tmp.relocs, src.relocs);
788 set_union(Tmp.Tls, Src.Tls);772 set_union(tmp.tls, src.tls);
789 set_union(Tmp.DynTlsSymbols, Src.DynTlsSymbols);773 set_union(tmp.dynTlsSymbols, src.dynTlsSymbols);
790774
791 size_t Count = IsPrimary ? HeaderEntriesNum : 0;775 size_t count = isPrimary ? headerEntriesNum : 0;
792 Count += Tmp.getIndexedEntriesNum();776 count += tmp.getIndexedEntriesNum();
793777
794 if (Count * Config->Wordsize > Config->MipsGotSize)778 if (count * config->wordsize > config->mipsGotSize)
795 return false;779 return false;
796780
797 std::swap(Tmp, Dst);781 std::swap(tmp, dst);
798 return true;782 return true;
799}783}
800784
801void MipsGotSection::finalizeContents() { updateAllocSize(); }785void MipsGotSection::finalizeContents() { updateAllocSize(); }
802786
803bool MipsGotSection::updateAllocSize() {787bool MipsGotSection::updateAllocSize() {
804 Size = HeaderEntriesNum * Config->Wordsize;788 size = headerEntriesNum * config->wordsize;
805 for (const FileGot &G : Gots)789 for (const FileGot &g : gots)
806 Size += G.getEntriesNum() * Config->Wordsize;790 size += g.getEntriesNum() * config->wordsize;
807 return false;791 return false;
808}792}
809793
810template <class ELFT> void MipsGotSection::build() {794void MipsGotSection::build() {
811 if (Gots.empty())795 if (gots.empty())
812 return;796 return;
813797
814 std::vector<FileGot> MergedGots(1);798 std::vector<FileGot> mergedGots(1);
815799
816 // For each GOT move non-preemptible symbols from the `Global`800 // For each GOT move non-preemptible symbols from the `Global`
817 // to `Local16` list. Preemptible symbol might become non-preemptible801 // to `Local16` list. Preemptible symbol might become non-preemptible
818 // one if, for example, it gets a related copy relocation.802 // one if, for example, it gets a related copy relocation.
819 for (FileGot &Got : Gots) {803 for (FileGot &got : gots) {
820 for (auto &P: Got.Global)804 for (auto &p: got.global)
821 if (!P.first->IsPreemptible)805 if (!p.first->isPreemptible)
822 Got.Local16.insert({{P.first, 0}, 0});806 got.local16.insert({{p.first, 0}, 0});
823 Got.Global.remove_if([&](const std::pair<Symbol *, size_t> &P) {807 got.global.remove_if([&](const std::pair<Symbol *, size_t> &p) {
824 return !P.first->IsPreemptible;808 return !p.first->isPreemptible;
825 });809 });
826 }810 }
827811
828 // For each GOT remove "reloc-only" entry if there is "global"812 // For each GOT remove "reloc-only" entry if there is "global"
829 // entry for the same symbol. And add local entries which indexed813 // entry for the same symbol. And add local entries which indexed
830 // using 32-bit value at the end of 16-bit entries.814 // using 32-bit value at the end of 16-bit entries.
831 for (FileGot &Got : Gots) {815 for (FileGot &got : gots) {
832 Got.Relocs.remove_if([&](const std::pair<Symbol *, size_t> &P) {816 got.relocs.remove_if([&](const std::pair<Symbol *, size_t> &p) {
833 return Got.Global.count(P.first);817 return got.global.count(p.first);
834 });818 });
835 set_union(Got.Local16, Got.Local32);819 set_union(got.local16, got.local32);
836 Got.Local32.clear();820 got.local32.clear();
837 }821 }
838822
839 // Evaluate number of "reloc-only" entries in the resulting GOT.823 // Evaluate number of "reloc-only" entries in the resulting GOT.
840 // To do that put all unique "reloc-only" and "global" entries824 // To do that put all unique "reloc-only" and "global" entries
841 // from all GOTs to the future primary GOT.825 // from all GOTs to the future primary GOT.
842 FileGot *PrimGot = &MergedGots.front();826 FileGot *primGot = &mergedGots.front();
843 for (FileGot &Got : Gots) {827 for (FileGot &got : gots) {
844 set_union(PrimGot->Relocs, Got.Global);828 set_union(primGot->relocs, got.global);
845 set_union(PrimGot->Relocs, Got.Relocs);829 set_union(primGot->relocs, got.relocs);
846 Got.Relocs.clear();830 got.relocs.clear();
847 }831 }
848832
849 // Evaluate number of "page" entries in each GOT.833 // Evaluate number of "page" entries in each GOT.
850 for (FileGot &Got : Gots) {834 for (FileGot &got : gots) {
851 for (std::pair<const OutputSection *, FileGot::PageBlock> &P :835 for (std::pair<const OutputSection *, FileGot::PageBlock> &p :
852 Got.PagesMap) {836 got.pagesMap) {
853 const OutputSection *OS = P.first;837 const OutputSection *os = p.first;
854 uint64_t SecSize = 0;838 uint64_t secSize = 0;
855 for (BaseCommand *Cmd : OS->SectionCommands) {839 for (BaseCommand *cmd : os->sectionCommands) {
856 if (auto *ISD = dyn_cast<InputSectionDescription>(Cmd))840 if (auto *isd = dyn_cast<InputSectionDescription>(cmd))
857 for (InputSection *IS : ISD->Sections) {841 for (InputSection *isec : isd->sections) {
858 uint64_t Off = alignTo(SecSize, IS->Alignment);842 uint64_t off = alignTo(secSize, isec->alignment);
859 SecSize = Off + IS->getSize();843 secSize = off + isec->getSize();
860 }844 }
861 }845 }
862 P.second.Count = getMipsPageCount(SecSize);846 p.second.count = getMipsPageCount(secSize);
863 }847 }
864 }848 }
865849
...@@ -868,149 +852,149 @@ template <class ELFT> void MipsGotSection::build() {...@@ -868,149 +852,149 @@ template <class ELFT> void MipsGotSection::build() {
868 // the primary GOT can be accessed in the most effective way. If it852 // the primary GOT can be accessed in the most effective way. If it
869 // is not possible, try to fill the last GOT in the list, and finally853 // is not possible, try to fill the last GOT in the list, and finally
870 // create a new GOT if both attempts failed.854 // create a new GOT if both attempts failed.
871 for (FileGot &SrcGot : Gots) {855 for (FileGot &srcGot : gots) {
872 InputFile *File = SrcGot.File;856 InputFile *file = srcGot.file;
873 if (tryMergeGots(MergedGots.front(), SrcGot, true)) {857 if (tryMergeGots(mergedGots.front(), srcGot, true)) {
874 File->MipsGotIndex = 0;858 file->mipsGotIndex = 0;
875 } else {859 } else {
876 // If this is the first time we failed to merge with the primary GOT,860 // If this is the first time we failed to merge with the primary GOT,
877 // MergedGots.back() will also be the primary GOT. We must make sure not861 // MergedGots.back() will also be the primary GOT. We must make sure not
878 // to try to merge again with IsPrimary=false, as otherwise, if the862 // to try to merge again with isPrimary=false, as otherwise, if the
879 // inputs are just right, we could allow the primary GOT to become 1 or 2863 // inputs are just right, we could allow the primary GOT to become 1 or 2
880 // words too big due to ignoring the header size.864 // words bigger due to ignoring the header size.
881 if (MergedGots.size() == 1 ||865 if (mergedGots.size() == 1 ||
882 !tryMergeGots(MergedGots.back(), SrcGot, false)) {866 !tryMergeGots(mergedGots.back(), srcGot, false)) {
883 MergedGots.emplace_back();867 mergedGots.emplace_back();
884 std::swap(MergedGots.back(), SrcGot);868 std::swap(mergedGots.back(), srcGot);
885 }869 }
886 File->MipsGotIndex = MergedGots.size() - 1;870 file->mipsGotIndex = mergedGots.size() - 1;
887 }871 }
888 }872 }
889 std::swap(Gots, MergedGots);873 std::swap(gots, mergedGots);
890874
891 // Reduce number of "reloc-only" entries in the primary GOT875 // Reduce number of "reloc-only" entries in the primary GOT
892 // by substracting "global" entries exist in the primary GOT.876 // by substracting "global" entries exist in the primary GOT.
893 PrimGot = &Gots.front();877 primGot = &gots.front();
894 PrimGot->Relocs.remove_if([&](const std::pair<Symbol *, size_t> &P) {878 primGot->relocs.remove_if([&](const std::pair<Symbol *, size_t> &p) {
895 return PrimGot->Global.count(P.first);879 return primGot->global.count(p.first);
896 });880 });
897881
898 // Calculate indexes for each GOT entry.882 // Calculate indexes for each GOT entry.
899 size_t Index = HeaderEntriesNum;883 size_t index = headerEntriesNum;
900 for (FileGot &Got : Gots) {884 for (FileGot &got : gots) {
901 Got.StartIndex = &Got == PrimGot ? 0 : Index;885 got.startIndex = &got == primGot ? 0 : index;
902 for (std::pair<const OutputSection *, FileGot::PageBlock> &P :886 for (std::pair<const OutputSection *, FileGot::PageBlock> &p :
903 Got.PagesMap) {887 got.pagesMap) {
904 // For each output section referenced by GOT page relocations calculate888 // For each output section referenced by GOT page relocations calculate
905 // and save into PagesMap an upper bound of MIPS GOT entries required889 // and save into pagesMap an upper bound of MIPS GOT entries required
906 // to store page addresses of local symbols. We assume the worst case -890 // to store page addresses of local symbols. We assume the worst case -
907 // each 64kb page of the output section has at least one GOT relocation891 // each 64kb page of the output section has at least one GOT relocation
908 // against it. And take in account the case when the section intersects892 // against it. And take in account the case when the section intersects
909 // page boundaries.893 // page boundaries.
910 P.second.FirstIndex = Index;894 p.second.firstIndex = index;
911 Index += P.second.Count;895 index += p.second.count;
912 }896 }
913 for (auto &P: Got.Local16)897 for (auto &p: got.local16)
914 P.second = Index++;898 p.second = index++;
915 for (auto &P: Got.Global)899 for (auto &p: got.global)
916 P.second = Index++;900 p.second = index++;
917 for (auto &P: Got.Relocs)901 for (auto &p: got.relocs)
918 P.second = Index++;902 p.second = index++;
919 for (auto &P: Got.Tls)903 for (auto &p: got.tls)
920 P.second = Index++;904 p.second = index++;
921 for (auto &P: Got.DynTlsSymbols) {905 for (auto &p: got.dynTlsSymbols) {
922 P.second = Index;906 p.second = index;
923 Index += 2;907 index += 2;
924 }908 }
925 }909 }
926910
927 // Update Symbol::GotIndex field to use this911 // Update Symbol::gotIndex field to use this
928 // value later in the `sortMipsSymbols` function.912 // value later in the `sortMipsSymbols` function.
929 for (auto &P : PrimGot->Global)913 for (auto &p : primGot->global)
930 P.first->GotIndex = P.second;914 p.first->gotIndex = p.second;
931 for (auto &P : PrimGot->Relocs)915 for (auto &p : primGot->relocs)
932 P.first->GotIndex = P.second;916 p.first->gotIndex = p.second;
933917
934 // Create dynamic relocations.918 // Create dynamic relocations.
935 for (FileGot &Got : Gots) {919 for (FileGot &got : gots) {
936 // Create dynamic relocations for TLS entries.920 // Create dynamic relocations for TLS entries.
937 for (std::pair<Symbol *, size_t> &P : Got.Tls) {921 for (std::pair<Symbol *, size_t> &p : got.tls) {
938 Symbol *S = P.first;922 Symbol *s = p.first;
939 uint64_t Offset = P.second * Config->Wordsize;923 uint64_t offset = p.second * config->wordsize;
940 if (S->IsPreemptible)924 if (s->isPreemptible)
941 In.RelaDyn->addReloc(Target->TlsGotRel, this, Offset, S);925 mainPart->relaDyn->addReloc(target->tlsGotRel, this, offset, s);
942 }926 }
943 for (std::pair<Symbol *, size_t> &P : Got.DynTlsSymbols) {927 for (std::pair<Symbol *, size_t> &p : got.dynTlsSymbols) {
944 Symbol *S = P.first;928 Symbol *s = p.first;
945 uint64_t Offset = P.second * Config->Wordsize;929 uint64_t offset = p.second * config->wordsize;
946 if (S == nullptr) {930 if (s == nullptr) {
947 if (!Config->Pic)931 if (!config->isPic)
948 continue;932 continue;
949 In.RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);933 mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, this, offset, s);
950 } else {934 } else {
951 // When building a shared library we still need a dynamic relocation935 // When building a shared library we still need a dynamic relocation
952 // for the module index. Therefore only checking for936 // for the module index. Therefore only checking for
953 // S->IsPreemptible is not sufficient (this happens e.g. for937 // S->isPreemptible is not sufficient (this happens e.g. for
954 // thread-locals that have been marked as local through a linker script)938 // thread-locals that have been marked as local through a linker script)
955 if (!S->IsPreemptible && !Config->Pic)939 if (!s->isPreemptible && !config->isPic)
956 continue;940 continue;
957 In.RelaDyn->addReloc(Target->TlsModuleIndexRel, this, Offset, S);941 mainPart->relaDyn->addReloc(target->tlsModuleIndexRel, this, offset, s);
958 // However, we can skip writing the TLS offset reloc for non-preemptible942 // However, we can skip writing the TLS offset reloc for non-preemptible
959 // symbols since it is known even in shared libraries943 // symbols since it is known even in shared libraries
960 if (!S->IsPreemptible)944 if (!s->isPreemptible)
961 continue;945 continue;
962 Offset += Config->Wordsize;946 offset += config->wordsize;
963 In.RelaDyn->addReloc(Target->TlsOffsetRel, this, Offset, S);947 mainPart->relaDyn->addReloc(target->tlsOffsetRel, this, offset, s);
964 }948 }
965 }949 }
966950
967 // Do not create dynamic relocations for non-TLS951 // Do not create dynamic relocations for non-TLS
968 // entries in the primary GOT.952 // entries in the primary GOT.
969 if (&Got == PrimGot)953 if (&got == primGot)
970 continue;954 continue;
971955
972 // Dynamic relocations for "global" entries.956 // Dynamic relocations for "global" entries.
973 for (const std::pair<Symbol *, size_t> &P : Got.Global) {957 for (const std::pair<Symbol *, size_t> &p : got.global) {
974 uint64_t Offset = P.second * Config->Wordsize;958 uint64_t offset = p.second * config->wordsize;
975 In.RelaDyn->addReloc(Target->RelativeRel, this, Offset, P.first);959 mainPart->relaDyn->addReloc(target->relativeRel, this, offset, p.first);
976 }960 }
977 if (!Config->Pic)961 if (!config->isPic)
978 continue;962 continue;
979 // Dynamic relocations for "local" entries in case of PIC.963 // Dynamic relocations for "local" entries in case of PIC.
980 for (const std::pair<const OutputSection *, FileGot::PageBlock> &L :964 for (const std::pair<const OutputSection *, FileGot::PageBlock> &l :
981 Got.PagesMap) {965 got.pagesMap) {
982 size_t PageCount = L.second.Count;966 size_t pageCount = l.second.count;
983 for (size_t PI = 0; PI < PageCount; ++PI) {967 for (size_t pi = 0; pi < pageCount; ++pi) {
984 uint64_t Offset = (L.second.FirstIndex + PI) * Config->Wordsize;968 uint64_t offset = (l.second.firstIndex + pi) * config->wordsize;
985 In.RelaDyn->addReloc({Target->RelativeRel, this, Offset, L.first,969 mainPart->relaDyn->addReloc({target->relativeRel, this, offset, l.first,
986 int64_t(PI * 0x10000)});970 int64_t(pi * 0x10000)});
987 }971 }
988 }972 }
989 for (const std::pair<GotEntry, size_t> &P : Got.Local16) {973 for (const std::pair<GotEntry, size_t> &p : got.local16) {
990 uint64_t Offset = P.second * Config->Wordsize;974 uint64_t offset = p.second * config->wordsize;
991 In.RelaDyn->addReloc({Target->RelativeRel, this, Offset, true,975 mainPart->relaDyn->addReloc({target->relativeRel, this, offset, true,
992 P.first.first, P.first.second});976 p.first.first, p.first.second});
993 }977 }
994 }978 }
995}979}
996980
997bool MipsGotSection::empty() const {981bool MipsGotSection::isNeeded() const {
998 // We add the .got section to the result for dynamic MIPS target because982 // We add the .got section to the result for dynamic MIPS target because
999 // its address and properties are mentioned in the .dynamic section.983 // its address and properties are mentioned in the .dynamic section.
1000 return Config->Relocatable;984 return !config->relocatable;
1001}985}
1002986
1003uint64_t MipsGotSection::getGp(const InputFile *F) const {987uint64_t MipsGotSection::getGp(const InputFile *f) const {
1004 // For files without related GOT or files refer a primary GOT988 // For files without related GOT or files refer a primary GOT
1005 // returns "common" _gp value. For secondary GOTs calculate989 // returns "common" _gp value. For secondary GOTs calculate
1006 // individual _gp values.990 // individual _gp values.
1007 if (!F || !F->MipsGotIndex.hasValue() || *F->MipsGotIndex == 0)991 if (!f || !f->mipsGotIndex.hasValue() || *f->mipsGotIndex == 0)
1008 return ElfSym::MipsGp->getVA(0);992 return ElfSym::mipsGp->getVA(0);
1009 return getVA() + Gots[*F->MipsGotIndex].StartIndex * Config->Wordsize +993 return getVA() + gots[*f->mipsGotIndex].startIndex * config->wordsize +
1010 0x7ff0;994 0x7ff0;
1011}995}
1012996
1013void MipsGotSection::writeTo(uint8_t *Buf) {997void MipsGotSection::writeTo(uint8_t *buf) {
1014 // Set the MSB of the second GOT slot. This is not required by any998 // Set the MSB of the second GOT slot. This is not required by any
1015 // MIPS ABI documentation, though.999 // MIPS ABI documentation, though.
1016 //1000 //
...@@ -1025,51 +1009,48 @@ void MipsGotSection::writeTo(uint8_t *Buf) {...@@ -1025,51 +1009,48 @@ void MipsGotSection::writeTo(uint8_t *Buf) {
1025 // we've been doing this for years, it is probably a safe bet to1009 // we've been doing this for years, it is probably a safe bet to
1026 // keep doing this for now. We really need to revisit this to see1010 // keep doing this for now. We really need to revisit this to see
1027 // if we had to do this.1011 // if we had to do this.
1028 writeUint(Buf + Config->Wordsize, (uint64_t)1 << (Config->Wordsize * 8 - 1));1012 writeUint(buf + config->wordsize, (uint64_t)1 << (config->wordsize * 8 - 1));
1029 for (const FileGot &G : Gots) {1013 for (const FileGot &g : gots) {
1030 auto Write = [&](size_t I, const Symbol *S, int64_t A) {1014 auto write = [&](size_t i, const Symbol *s, int64_t a) {
1031 uint64_t VA = A;1015 uint64_t va = a;
1032 if (S) {1016 if (s)
1033 VA = S->getVA(A);1017 va = s->getVA(a);
1034 if (S->StOther & STO_MIPS_MICROMIPS)1018 writeUint(buf + i * config->wordsize, va);
1035 VA |= 1;
1036 }
1037 writeUint(Buf + I * Config->Wordsize, VA);
1038 };1019 };
1039 // Write 'page address' entries to the local part of the GOT.1020 // Write 'page address' entries to the local part of the GOT.
1040 for (const std::pair<const OutputSection *, FileGot::PageBlock> &L :1021 for (const std::pair<const OutputSection *, FileGot::PageBlock> &l :
1041 G.PagesMap) {1022 g.pagesMap) {
1042 size_t PageCount = L.second.Count;1023 size_t pageCount = l.second.count;
1043 uint64_t FirstPageAddr = getMipsPageAddr(L.first->Addr);1024 uint64_t firstPageAddr = getMipsPageAddr(l.first->addr);
1044 for (size_t PI = 0; PI < PageCount; ++PI)1025 for (size_t pi = 0; pi < pageCount; ++pi)
1045 Write(L.second.FirstIndex + PI, nullptr, FirstPageAddr + PI * 0x10000);1026 write(l.second.firstIndex + pi, nullptr, firstPageAddr + pi * 0x10000);
1046 }1027 }
1047 // Local, global, TLS, reloc-only entries.1028 // Local, global, TLS, reloc-only entries.
1048 // If TLS entry has a corresponding dynamic relocations, leave it1029 // If TLS entry has a corresponding dynamic relocations, leave it
1049 // initialized by zero. Write down adjusted TLS symbol's values otherwise.1030 // initialized by zero. Write down adjusted TLS symbol's values otherwise.
1050 // To calculate the adjustments use offsets for thread-local storage.1031 // To calculate the adjustments use offsets for thread-local storage.
1051 // https://www.linux-mips.org/wiki/NPTL1032 // https://www.linux-mips.org/wiki/NPTL
1052 for (const std::pair<GotEntry, size_t> &P : G.Local16)1033 for (const std::pair<GotEntry, size_t> &p : g.local16)
1053 Write(P.second, P.first.first, P.first.second);1034 write(p.second, p.first.first, p.first.second);
1054 // Write VA to the primary GOT only. For secondary GOTs that1035 // Write VA to the primary GOT only. For secondary GOTs that
1055 // will be done by REL32 dynamic relocations.1036 // will be done by REL32 dynamic relocations.
1056 if (&G == &Gots.front())1037 if (&g == &gots.front())
1057 for (const std::pair<const Symbol *, size_t> &P : G.Global)1038 for (const std::pair<const Symbol *, size_t> &p : g.global)
1058 Write(P.second, P.first, 0);1039 write(p.second, p.first, 0);
1059 for (const std::pair<Symbol *, size_t> &P : G.Relocs)1040 for (const std::pair<Symbol *, size_t> &p : g.relocs)
1060 Write(P.second, P.first, 0);1041 write(p.second, p.first, 0);
1061 for (const std::pair<Symbol *, size_t> &P : G.Tls)1042 for (const std::pair<Symbol *, size_t> &p : g.tls)
1062 Write(P.second, P.first, P.first->IsPreemptible ? 0 : -0x7000);1043 write(p.second, p.first, p.first->isPreemptible ? 0 : -0x7000);
1063 for (const std::pair<Symbol *, size_t> &P : G.DynTlsSymbols) {1044 for (const std::pair<Symbol *, size_t> &p : g.dynTlsSymbols) {
1064 if (P.first == nullptr && !Config->Pic)1045 if (p.first == nullptr && !config->isPic)
1065 Write(P.second, nullptr, 1);1046 write(p.second, nullptr, 1);
1066 else if (P.first && !P.first->IsPreemptible) {1047 else if (p.first && !p.first->isPreemptible) {
1067 // If we are emitting PIC code with relocations we mustn't write1048 // If we are emitting PIC code with relocations we mustn't write
1068 // anything to the GOT here. When using Elf_Rel relocations the value1049 // anything to the GOT here. When using Elf_Rel relocations the value
1069 // one will be treated as an addend and will cause crashes at runtime1050 // one will be treated as an addend and will cause crashes at runtime
1070 if (!Config->Pic)1051 if (!config->isPic)
1071 Write(P.second, nullptr, 1);1052 write(p.second, nullptr, 1);
1072 Write(P.second + 1, P.first, -0x8000);1053 write(p.second + 1, p.first, -0x8000);
1073 }1054 }
1074 }1055 }
1075 }1056 }
...@@ -1080,46 +1061,48 @@ void MipsGotSection::writeTo(uint8_t *Buf) {...@@ -1080,46 +1061,48 @@ void MipsGotSection::writeTo(uint8_t *Buf) {
1080// section. I don't know why we have a BSS style type for the section but it is1061// section. I don't know why we have a BSS style type for the section but it is
1081// consitent across both 64-bit PowerPC ABIs as well as the 32-bit PowerPC ABI.1062// consitent across both 64-bit PowerPC ABIs as well as the 32-bit PowerPC ABI.
1082GotPltSection::GotPltSection()1063GotPltSection::GotPltSection()
1083 : SyntheticSection(SHF_ALLOC | SHF_WRITE,1064 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
1084 Config->EMachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS,1065 ".got.plt") {
1085 Target->GotPltEntrySize,1066 if (config->emachine == EM_PPC) {
1086 Config->EMachine == EM_PPC64 ? ".plt" : ".got.plt") {}1067 name = ".plt";
1068 } else if (config->emachine == EM_PPC64) {
1069 type = SHT_NOBITS;
1070 name = ".plt";
1071 }
1072}
10871073
1088void GotPltSection::addEntry(Symbol &Sym) {1074void GotPltSection::addEntry(Symbol &sym) {
1089 assert(Sym.PltIndex == Entries.size());1075 assert(sym.pltIndex == entries.size());
1090 Entries.push_back(&Sym);1076 entries.push_back(&sym);
1091}1077}
10921078
1093size_t GotPltSection::getSize() const {1079size_t GotPltSection::getSize() const {
1094 return (Target->GotPltHeaderEntriesNum + Entries.size()) *1080 return (target->gotPltHeaderEntriesNum + entries.size()) * config->wordsize;
1095 Target->GotPltEntrySize;
1096}1081}
10971082
1098void GotPltSection::writeTo(uint8_t *Buf) {1083void GotPltSection::writeTo(uint8_t *buf) {
1099 Target->writeGotPltHeader(Buf);1084 target->writeGotPltHeader(buf);
1100 Buf += Target->GotPltHeaderEntriesNum * Target->GotPltEntrySize;1085 buf += target->gotPltHeaderEntriesNum * config->wordsize;
1101 for (const Symbol *B : Entries) {1086 for (const Symbol *b : entries) {
1102 Target->writeGotPlt(Buf, *B);1087 target->writeGotPlt(buf, *b);
1103 Buf += Config->Wordsize;1088 buf += config->wordsize;
1104 }1089 }
1105}1090}
11061091
1107bool GotPltSection::empty() const {1092bool GotPltSection::isNeeded() const {
1108 // We need to emit a GOT.PLT even if it's empty if there's a symbol that1093 // We need to emit GOTPLT even if it's empty if there's a relocation relative
1109 // references the _GLOBAL_OFFSET_TABLE_ and the Target defines the symbol1094 // to it.
1110 // relative to the .got.plt section.1095 return !entries.empty() || hasGotPltOffRel;
1111 return Entries.empty() &&
1112 !(ElfSym::GlobalOffsetTable && Target->GotBaseSymInGotPlt);
1113}1096}
11141097
1115static StringRef getIgotPltName() {1098static StringRef getIgotPltName() {
1116 // On ARM the IgotPltSection is part of the GotSection.1099 // On ARM the IgotPltSection is part of the GotSection.
1117 if (Config->EMachine == EM_ARM)1100 if (config->emachine == EM_ARM)
1118 return ".got";1101 return ".got";
11191102
1120 // On PowerPC64 the GotPltSection is renamed to '.plt' so the IgotPltSection1103 // On PowerPC64 the GotPltSection is renamed to '.plt' so the IgotPltSection
1121 // needs to be named the same.1104 // needs to be named the same.
1122 if (Config->EMachine == EM_PPC64)1105 if (config->emachine == EM_PPC64)
1123 return ".plt";1106 return ".plt";
11241107
1125 return ".got.plt";1108 return ".got.plt";
...@@ -1129,130 +1112,110 @@ static StringRef getIgotPltName() {...@@ -1129,130 +1112,110 @@ static StringRef getIgotPltName() {
1129// with the IgotPltSection.1112// with the IgotPltSection.
1130IgotPltSection::IgotPltSection()1113IgotPltSection::IgotPltSection()
1131 : SyntheticSection(SHF_ALLOC | SHF_WRITE,1114 : SyntheticSection(SHF_ALLOC | SHF_WRITE,
1132 Config->EMachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS,1115 config->emachine == EM_PPC64 ? SHT_NOBITS : SHT_PROGBITS,
1133 Target->GotPltEntrySize, getIgotPltName()) {}1116 config->wordsize, getIgotPltName()) {}
11341117
1135void IgotPltSection::addEntry(Symbol &Sym) {1118void IgotPltSection::addEntry(Symbol &sym) {
1136 Sym.IsInIgot = true;1119 assert(sym.pltIndex == entries.size());
1137 assert(Sym.PltIndex == Entries.size());1120 entries.push_back(&sym);
1138 Entries.push_back(&Sym);
1139}1121}
11401122
1141size_t IgotPltSection::getSize() const {1123size_t IgotPltSection::getSize() const {
1142 return Entries.size() * Target->GotPltEntrySize;1124 return entries.size() * config->wordsize;
1143}1125}
11441126
1145void IgotPltSection::writeTo(uint8_t *Buf) {1127void IgotPltSection::writeTo(uint8_t *buf) {
1146 for (const Symbol *B : Entries) {1128 for (const Symbol *b : entries) {
1147 Target->writeIgotPlt(Buf, *B);1129 target->writeIgotPlt(buf, *b);
1148 Buf += Config->Wordsize;1130 buf += config->wordsize;
1149 }1131 }
1150}1132}
11511133
1152StringTableSection::StringTableSection(StringRef Name, bool Dynamic)1134StringTableSection::StringTableSection(StringRef name, bool dynamic)
1153 : SyntheticSection(Dynamic ? (uint64_t)SHF_ALLOC : 0, SHT_STRTAB, 1, Name),1135 : SyntheticSection(dynamic ? (uint64_t)SHF_ALLOC : 0, SHT_STRTAB, 1, name),
1154 Dynamic(Dynamic) {1136 dynamic(dynamic) {
1155 // ELF string tables start with a NUL byte.1137 // ELF string tables start with a NUL byte.
1156 addString("");1138 addString("");
1157}1139}
11581140
1159// Adds a string to the string table. If HashIt is true we hash and check for1141// Adds a string to the string table. If `hashIt` is true we hash and check for
1160// duplicates. It is optional because the name of global symbols are already1142// duplicates. It is optional because the name of global symbols are already
1161// uniqued and hashing them again has a big cost for a small value: uniquing1143// uniqued and hashing them again has a big cost for a small value: uniquing
1162// them with some other string that happens to be the same.1144// them with some other string that happens to be the same.
1163unsigned StringTableSection::addString(StringRef S, bool HashIt) {1145unsigned StringTableSection::addString(StringRef s, bool hashIt) {
1164 if (HashIt) {1146 if (hashIt) {
1165 auto R = StringMap.insert(std::make_pair(S, this->Size));1147 auto r = stringMap.insert(std::make_pair(s, this->size));
1166 if (!R.second)1148 if (!r.second)
1167 return R.first->second;1149 return r.first->second;
1168 }1150 }
1169 unsigned Ret = this->Size;1151 unsigned ret = this->size;
1170 this->Size = this->Size + S.size() + 1;1152 this->size = this->size + s.size() + 1;
1171 Strings.push_back(S);1153 strings.push_back(s);
1172 return Ret;1154 return ret;
1173}1155}
11741156
1175void StringTableSection::writeTo(uint8_t *Buf) {1157void StringTableSection::writeTo(uint8_t *buf) {
1176 for (StringRef S : Strings) {1158 for (StringRef s : strings) {
1177 memcpy(Buf, S.data(), S.size());1159 memcpy(buf, s.data(), s.size());
1178 Buf[S.size()] = '\0';1160 buf[s.size()] = '\0';
1179 Buf += S.size() + 1;1161 buf += s.size() + 1;
1180 }1162 }
1181}1163}
11821164
1183// Returns the number of version definition entries. Because the first entry1165// Returns the number of version definition entries. Because the first entry
1184// is for the version definition itself, it is the number of versioned symbols1166// is for the version definition itself, it is the number of versioned symbols
1185// plus one. Note that we don't support multiple versions yet.1167// plus one. Note that we don't support multiple versions yet.
1186static unsigned getVerDefNum() { return Config->VersionDefinitions.size() + 1; }1168static unsigned getVerDefNum() { return config->versionDefinitions.size() + 1; }
11871169
1188template <class ELFT>1170template <class ELFT>
1189DynamicSection<ELFT>::DynamicSection()1171DynamicSection<ELFT>::DynamicSection()
1190 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, Config->Wordsize,1172 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_DYNAMIC, config->wordsize,
1191 ".dynamic") {1173 ".dynamic") {
1192 this->Entsize = ELFT::Is64Bits ? 16 : 8;1174 this->entsize = ELFT::Is64Bits ? 16 : 8;
11931175
1194 // .dynamic section is not writable on MIPS and on Fuchsia OS1176 // .dynamic section is not writable on MIPS and on Fuchsia OS
1195 // which passes -z rodynamic.1177 // which passes -z rodynamic.
1196 // See "Special Section" in Chapter 4 in the following document:1178 // See "Special Section" in Chapter 4 in the following document:
1197 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf1179 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1198 if (Config->EMachine == EM_MIPS || Config->ZRodynamic)1180 if (config->emachine == EM_MIPS || config->zRodynamic)
1199 this->Flags = SHF_ALLOC;1181 this->flags = SHF_ALLOC;
1200
1201 // Add strings to .dynstr early so that .dynstr's size will be
1202 // fixed early.
1203 for (StringRef S : Config->FilterList)
1204 addInt(DT_FILTER, In.DynStrTab->addString(S));
1205 for (StringRef S : Config->AuxiliaryList)
1206 addInt(DT_AUXILIARY, In.DynStrTab->addString(S));
1207
1208 if (!Config->Rpath.empty())
1209 addInt(Config->EnableNewDtags ? DT_RUNPATH : DT_RPATH,
1210 In.DynStrTab->addString(Config->Rpath));
1211
1212 for (InputFile *File : SharedFiles) {
1213 SharedFile<ELFT> *F = cast<SharedFile<ELFT>>(File);
1214 if (F->IsNeeded)
1215 addInt(DT_NEEDED, In.DynStrTab->addString(F->SoName));
1216 }
1217 if (!Config->SoName.empty())
1218 addInt(DT_SONAME, In.DynStrTab->addString(Config->SoName));
1219}1182}
12201183
1221template <class ELFT>1184template <class ELFT>
1222void DynamicSection<ELFT>::add(int32_t Tag, std::function<uint64_t()> Fn) {1185void DynamicSection<ELFT>::add(int32_t tag, std::function<uint64_t()> fn) {
1223 Entries.push_back({Tag, Fn});1186 entries.push_back({tag, fn});
1224}1187}
12251188
1226template <class ELFT>1189template <class ELFT>
1227void DynamicSection<ELFT>::addInt(int32_t Tag, uint64_t Val) {1190void DynamicSection<ELFT>::addInt(int32_t tag, uint64_t val) {
1228 Entries.push_back({Tag, [=] { return Val; }});1191 entries.push_back({tag, [=] { return val; }});
1229}1192}
12301193
1231template <class ELFT>1194template <class ELFT>
1232void DynamicSection<ELFT>::addInSec(int32_t Tag, InputSection *Sec) {1195void DynamicSection<ELFT>::addInSec(int32_t tag, InputSection *sec) {
1233 Entries.push_back({Tag, [=] { return Sec->getVA(0); }});1196 entries.push_back({tag, [=] { return sec->getVA(0); }});
1234}1197}
12351198
1236template <class ELFT>1199template <class ELFT>
1237void DynamicSection<ELFT>::addInSecRelative(int32_t Tag, InputSection *Sec) {1200void DynamicSection<ELFT>::addInSecRelative(int32_t tag, InputSection *sec) {
1238 size_t TagOffset = Entries.size() * Entsize;1201 size_t tagOffset = entries.size() * entsize;
1239 Entries.push_back(1202 entries.push_back(
1240 {Tag, [=] { return Sec->getVA(0) - (getVA() + TagOffset); }});1203 {tag, [=] { return sec->getVA(0) - (getVA() + tagOffset); }});
1241}1204}
12421205
1243template <class ELFT>1206template <class ELFT>
1244void DynamicSection<ELFT>::addOutSec(int32_t Tag, OutputSection *Sec) {1207void DynamicSection<ELFT>::addOutSec(int32_t tag, OutputSection *sec) {
1245 Entries.push_back({Tag, [=] { return Sec->Addr; }});1208 entries.push_back({tag, [=] { return sec->addr; }});
1246}1209}
12471210
1248template <class ELFT>1211template <class ELFT>
1249void DynamicSection<ELFT>::addSize(int32_t Tag, OutputSection *Sec) {1212void DynamicSection<ELFT>::addSize(int32_t tag, OutputSection *sec) {
1250 Entries.push_back({Tag, [=] { return Sec->Size; }});1213 entries.push_back({tag, [=] { return sec->size; }});
1251}1214}
12521215
1253template <class ELFT>1216template <class ELFT>
1254void DynamicSection<ELFT>::addSym(int32_t Tag, Symbol *Sym) {1217void DynamicSection<ELFT>::addSym(int32_t tag, Symbol *sym) {
1255 Entries.push_back({Tag, [=] { return Sym->getVA(); }});1218 entries.push_back({tag, [=] { return sym->getVA(); }});
1256}1219}
12571220
1258// A Linker script may assign the RELA relocation sections to the same1221// A Linker script may assign the RELA relocation sections to the same
...@@ -1260,47 +1223,74 @@ void DynamicSection<ELFT>::addSym(int32_t Tag, Symbol *Sym) {...@@ -1260,47 +1223,74 @@ void DynamicSection<ELFT>::addSym(int32_t Tag, Symbol *Sym) {
1260// Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to1223// Size. Moreover the [DT_JMPREL, DT_JMPREL + DT_PLTRELSZ) is permitted to
1261// overlap with the [DT_RELA, DT_RELA + DT_RELASZ).1224// overlap with the [DT_RELA, DT_RELA + DT_RELASZ).
1262static uint64_t addPltRelSz() {1225static uint64_t addPltRelSz() {
1263 size_t Size = In.RelaPlt->getSize();1226 size_t size = in.relaPlt->getSize();
1264 if (In.RelaIplt->getParent() == In.RelaPlt->getParent() &&1227 if (in.relaIplt->getParent() == in.relaPlt->getParent() &&
1265 In.RelaIplt->Name == In.RelaPlt->Name)1228 in.relaIplt->name == in.relaPlt->name)
1266 Size += In.RelaIplt->getSize();1229 size += in.relaIplt->getSize();
1267 return Size;1230 return size;
1268}1231}
12691232
1270// Add remaining entries to complete .dynamic contents.1233// Add remaining entries to complete .dynamic contents.
1271template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {1234template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
1235 elf::Partition &part = getPartition();
1236 bool isMain = part.name.empty();
1237
1238 for (StringRef s : config->filterList)
1239 addInt(DT_FILTER, part.dynStrTab->addString(s));
1240 for (StringRef s : config->auxiliaryList)
1241 addInt(DT_AUXILIARY, part.dynStrTab->addString(s));
1242
1243 if (!config->rpath.empty())
1244 addInt(config->enableNewDtags ? DT_RUNPATH : DT_RPATH,
1245 part.dynStrTab->addString(config->rpath));
1246
1247 for (SharedFile *file : sharedFiles)
1248 if (file->isNeeded)
1249 addInt(DT_NEEDED, part.dynStrTab->addString(file->soName));
1250
1251 if (isMain) {
1252 if (!config->soName.empty())
1253 addInt(DT_SONAME, part.dynStrTab->addString(config->soName));
1254 } else {
1255 if (!config->soName.empty())
1256 addInt(DT_NEEDED, part.dynStrTab->addString(config->soName));
1257 addInt(DT_SONAME, part.dynStrTab->addString(part.name));
1258 }
1259
1272 // Set DT_FLAGS and DT_FLAGS_1.1260 // Set DT_FLAGS and DT_FLAGS_1.
1273 uint32_t DtFlags = 0;1261 uint32_t dtFlags = 0;
1274 uint32_t DtFlags1 = 0;1262 uint32_t dtFlags1 = 0;
1275 if (Config->Bsymbolic)1263 if (config->bsymbolic)
1276 DtFlags |= DF_SYMBOLIC;1264 dtFlags |= DF_SYMBOLIC;
1277 if (Config->ZGlobal)1265 if (config->zGlobal)
1278 DtFlags1 |= DF_1_GLOBAL;1266 dtFlags1 |= DF_1_GLOBAL;
1279 if (Config->ZInitfirst)1267 if (config->zInitfirst)
1280 DtFlags1 |= DF_1_INITFIRST;1268 dtFlags1 |= DF_1_INITFIRST;
1281 if (Config->ZInterpose)1269 if (config->zInterpose)
1282 DtFlags1 |= DF_1_INTERPOSE;1270 dtFlags1 |= DF_1_INTERPOSE;
1283 if (Config->ZNodefaultlib)1271 if (config->zNodefaultlib)
1284 DtFlags1 |= DF_1_NODEFLIB;1272 dtFlags1 |= DF_1_NODEFLIB;
1285 if (Config->ZNodelete)1273 if (config->zNodelete)
1286 DtFlags1 |= DF_1_NODELETE;1274 dtFlags1 |= DF_1_NODELETE;
1287 if (Config->ZNodlopen)1275 if (config->zNodlopen)
1288 DtFlags1 |= DF_1_NOOPEN;1276 dtFlags1 |= DF_1_NOOPEN;
1289 if (Config->ZNow) {1277 if (config->zNow) {
1290 DtFlags |= DF_BIND_NOW;1278 dtFlags |= DF_BIND_NOW;
1291 DtFlags1 |= DF_1_NOW;1279 dtFlags1 |= DF_1_NOW;
1292 }1280 }
1293 if (Config->ZOrigin) {1281 if (config->zOrigin) {
1294 DtFlags |= DF_ORIGIN;1282 dtFlags |= DF_ORIGIN;
1295 DtFlags1 |= DF_1_ORIGIN;1283 dtFlags1 |= DF_1_ORIGIN;
1296 }1284 }
1297 if (!Config->ZText)1285 if (!config->zText)
1298 DtFlags |= DF_TEXTREL;1286 dtFlags |= DF_TEXTREL;
12991287 if (config->hasStaticTlsModel)
1300 if (DtFlags)1288 dtFlags |= DF_STATIC_TLS;
1301 addInt(DT_FLAGS, DtFlags);1289
1302 if (DtFlags1)1290 if (dtFlags)
1303 addInt(DT_FLAGS_1, DtFlags1);1291 addInt(DT_FLAGS, dtFlags);
1292 if (dtFlags1)
1293 addInt(DT_FLAGS_1, dtFlags1);
13041294
1305 // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We1295 // DT_DEBUG is a pointer to debug informaion used by debuggers at runtime. We
1306 // need it for each process, so we don't write it for DSOs. The loader writes1296 // need it for each process, so we don't write it for DSOs. The loader writes
...@@ -1310,268 +1300,287 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {...@@ -1310,268 +1300,287 @@ template <class ELFT> void DynamicSection<ELFT>::finalizeContents() {
1310 // systems (currently only Fuchsia OS) provide other means to give the1300 // systems (currently only Fuchsia OS) provide other means to give the
1311 // debugger this information. Such systems may choose make .dynamic read-only.1301 // debugger this information. Such systems may choose make .dynamic read-only.
1312 // If the target is such a system (used -z rodynamic) don't write DT_DEBUG.1302 // If the target is such a system (used -z rodynamic) don't write DT_DEBUG.
1313 if (!Config->Shared && !Config->Relocatable && !Config->ZRodynamic)1303 if (!config->shared && !config->relocatable && !config->zRodynamic)
1314 addInt(DT_DEBUG, 0);1304 addInt(DT_DEBUG, 0);
13151305
1316 if (OutputSection *Sec = In.DynStrTab->getParent())1306 if (OutputSection *sec = part.dynStrTab->getParent())
1317 this->Link = Sec->SectionIndex;1307 this->link = sec->sectionIndex;
13181308
1319 if (!In.RelaDyn->empty()) {1309 if (part.relaDyn->isNeeded()) {
1320 addInSec(In.RelaDyn->DynamicTag, In.RelaDyn);1310 addInSec(part.relaDyn->dynamicTag, part.relaDyn);
1321 addSize(In.RelaDyn->SizeDynamicTag, In.RelaDyn->getParent());1311 addSize(part.relaDyn->sizeDynamicTag, part.relaDyn->getParent());
13221312
1323 bool IsRela = Config->IsRela;1313 bool isRela = config->isRela;
1324 addInt(IsRela ? DT_RELAENT : DT_RELENT,1314 addInt(isRela ? DT_RELAENT : DT_RELENT,
1325 IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel));1315 isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel));
13261316
1327 // MIPS dynamic loader does not support RELCOUNT tag.1317 // MIPS dynamic loader does not support RELCOUNT tag.
1328 // The problem is in the tight relation between dynamic1318 // The problem is in the tight relation between dynamic
1329 // relocations and GOT. So do not emit this tag on MIPS.1319 // relocations and GOT. So do not emit this tag on MIPS.
1330 if (Config->EMachine != EM_MIPS) {1320 if (config->emachine != EM_MIPS) {
1331 size_t NumRelativeRels = In.RelaDyn->getRelativeRelocCount();1321 size_t numRelativeRels = part.relaDyn->getRelativeRelocCount();
1332 if (Config->ZCombreloc && NumRelativeRels)1322 if (config->zCombreloc && numRelativeRels)
1333 addInt(IsRela ? DT_RELACOUNT : DT_RELCOUNT, NumRelativeRels);1323 addInt(isRela ? DT_RELACOUNT : DT_RELCOUNT, numRelativeRels);
1334 }1324 }
1335 }1325 }
1336 if (In.RelrDyn && !In.RelrDyn->Relocs.empty()) {1326 if (part.relrDyn && !part.relrDyn->relocs.empty()) {
1337 addInSec(Config->UseAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR,1327 addInSec(config->useAndroidRelrTags ? DT_ANDROID_RELR : DT_RELR,
1338 In.RelrDyn);1328 part.relrDyn);
1339 addSize(Config->UseAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,1329 addSize(config->useAndroidRelrTags ? DT_ANDROID_RELRSZ : DT_RELRSZ,
1340 In.RelrDyn->getParent());1330 part.relrDyn->getParent());
1341 addInt(Config->UseAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,1331 addInt(config->useAndroidRelrTags ? DT_ANDROID_RELRENT : DT_RELRENT,
1342 sizeof(Elf_Relr));1332 sizeof(Elf_Relr));
1343 }1333 }
1344 // .rel[a].plt section usually consists of two parts, containing plt and1334 // .rel[a].plt section usually consists of two parts, containing plt and
1345 // iplt relocations. It is possible to have only iplt relocations in the1335 // iplt relocations. It is possible to have only iplt relocations in the
1346 // output. In that case RelaPlt is empty and have zero offset, the same offset1336 // output. In that case relaPlt is empty and have zero offset, the same offset
1347 // as RelaIplt have. And we still want to emit proper dynamic tags for that1337 // as relaIplt has. And we still want to emit proper dynamic tags for that
1348 // case, so here we always use RelaPlt as marker for the begining of1338 // case, so here we always use relaPlt as marker for the begining of
1349 // .rel[a].plt section.1339 // .rel[a].plt section.
1350 if (In.RelaPlt->getParent()->Live) {1340 if (isMain && (in.relaPlt->isNeeded() || in.relaIplt->isNeeded())) {
1351 addInSec(DT_JMPREL, In.RelaPlt);1341 addInSec(DT_JMPREL, in.relaPlt);
1352 Entries.push_back({DT_PLTRELSZ, addPltRelSz});1342 entries.push_back({DT_PLTRELSZ, addPltRelSz});
1353 switch (Config->EMachine) {1343 switch (config->emachine) {
1354 case EM_MIPS:1344 case EM_MIPS:
1355 addInSec(DT_MIPS_PLTGOT, In.GotPlt);1345 addInSec(DT_MIPS_PLTGOT, in.gotPlt);
1356 break;1346 break;
1357 case EM_SPARCV9:1347 case EM_SPARCV9:
1358 addInSec(DT_PLTGOT, In.Plt);1348 addInSec(DT_PLTGOT, in.plt);
1359 break;1349 break;
1360 default:1350 default:
1361 addInSec(DT_PLTGOT, In.GotPlt);1351 addInSec(DT_PLTGOT, in.gotPlt);
1362 break;1352 break;
1363 }1353 }
1364 addInt(DT_PLTREL, Config->IsRela ? DT_RELA : DT_REL);1354 addInt(DT_PLTREL, config->isRela ? DT_RELA : DT_REL);
1355 }
1356
1357 if (config->emachine == EM_AARCH64) {
1358 if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_BTI)
1359 addInt(DT_AARCH64_BTI_PLT, 0);
1360 if (config->andFeatures & GNU_PROPERTY_AARCH64_FEATURE_1_PAC)
1361 addInt(DT_AARCH64_PAC_PLT, 0);
1365 }1362 }
13661363
1367 addInSec(DT_SYMTAB, In.DynSymTab);1364 addInSec(DT_SYMTAB, part.dynSymTab);
1368 addInt(DT_SYMENT, sizeof(Elf_Sym));1365 addInt(DT_SYMENT, sizeof(Elf_Sym));
1369 addInSec(DT_STRTAB, In.DynStrTab);1366 addInSec(DT_STRTAB, part.dynStrTab);
1370 addInt(DT_STRSZ, In.DynStrTab->getSize());1367 addInt(DT_STRSZ, part.dynStrTab->getSize());
1371 if (!Config->ZText)1368 if (!config->zText)
1372 addInt(DT_TEXTREL, 0);1369 addInt(DT_TEXTREL, 0);
1373 if (In.GnuHashTab)1370 if (part.gnuHashTab)
1374 addInSec(DT_GNU_HASH, In.GnuHashTab);1371 addInSec(DT_GNU_HASH, part.gnuHashTab);
1375 if (In.HashTab)1372 if (part.hashTab)
1376 addInSec(DT_HASH, In.HashTab);1373 addInSec(DT_HASH, part.hashTab);
13771374
1378 if (Out::PreinitArray) {1375 if (isMain) {
1379 addOutSec(DT_PREINIT_ARRAY, Out::PreinitArray);1376 if (Out::preinitArray) {
1380 addSize(DT_PREINIT_ARRAYSZ, Out::PreinitArray);1377 addOutSec(DT_PREINIT_ARRAY, Out::preinitArray);
1381 }1378 addSize(DT_PREINIT_ARRAYSZ, Out::preinitArray);
1382 if (Out::InitArray) {1379 }
1383 addOutSec(DT_INIT_ARRAY, Out::InitArray);1380 if (Out::initArray) {
1384 addSize(DT_INIT_ARRAYSZ, Out::InitArray);1381 addOutSec(DT_INIT_ARRAY, Out::initArray);
1385 }1382 addSize(DT_INIT_ARRAYSZ, Out::initArray);
1386 if (Out::FiniArray) {1383 }
1387 addOutSec(DT_FINI_ARRAY, Out::FiniArray);1384 if (Out::finiArray) {
1388 addSize(DT_FINI_ARRAYSZ, Out::FiniArray);1385 addOutSec(DT_FINI_ARRAY, Out::finiArray);
1389 }1386 addSize(DT_FINI_ARRAYSZ, Out::finiArray);
13901387 }
1391 if (Symbol *B = Symtab->find(Config->Init))1388
1392 if (B->isDefined())1389 if (Symbol *b = symtab->find(config->init))
1393 addSym(DT_INIT, B);1390 if (b->isDefined())
1394 if (Symbol *B = Symtab->find(Config->Fini))1391 addSym(DT_INIT, b);
1395 if (B->isDefined())1392 if (Symbol *b = symtab->find(config->fini))
1396 addSym(DT_FINI, B);1393 if (b->isDefined())
13971394 addSym(DT_FINI, b);
1398 bool HasVerNeed = InX<ELFT>::VerNeed->getNeedNum() != 0;1395 }
1399 if (HasVerNeed || In.VerDef)1396
1400 addInSec(DT_VERSYM, InX<ELFT>::VerSym);1397 bool hasVerNeed = SharedFile::vernauxNum != 0;
1401 if (In.VerDef) {1398 if (hasVerNeed || part.verDef)
1402 addInSec(DT_VERDEF, In.VerDef);1399 addInSec(DT_VERSYM, part.verSym);
1400 if (part.verDef) {
1401 addInSec(DT_VERDEF, part.verDef);
1403 addInt(DT_VERDEFNUM, getVerDefNum());1402 addInt(DT_VERDEFNUM, getVerDefNum());
1404 }1403 }
1405 if (HasVerNeed) {1404 if (hasVerNeed) {
1406 addInSec(DT_VERNEED, InX<ELFT>::VerNeed);1405 addInSec(DT_VERNEED, part.verNeed);
1407 addInt(DT_VERNEEDNUM, InX<ELFT>::VerNeed->getNeedNum());1406 unsigned needNum = 0;
1407 for (SharedFile *f : sharedFiles)
1408 if (!f->vernauxs.empty())
1409 ++needNum;
1410 addInt(DT_VERNEEDNUM, needNum);
1408 }1411 }
14091412
1410 if (Config->EMachine == EM_MIPS) {1413 if (config->emachine == EM_MIPS) {
1411 addInt(DT_MIPS_RLD_VERSION, 1);1414 addInt(DT_MIPS_RLD_VERSION, 1);
1412 addInt(DT_MIPS_FLAGS, RHF_NOTPOT);1415 addInt(DT_MIPS_FLAGS, RHF_NOTPOT);
1413 addInt(DT_MIPS_BASE_ADDRESS, Target->getImageBase());1416 addInt(DT_MIPS_BASE_ADDRESS, target->getImageBase());
1414 addInt(DT_MIPS_SYMTABNO, In.DynSymTab->getNumSymbols());1417 addInt(DT_MIPS_SYMTABNO, part.dynSymTab->getNumSymbols());
14151418
1416 add(DT_MIPS_LOCAL_GOTNO, [] { return In.MipsGot->getLocalEntriesNum(); });1419 add(DT_MIPS_LOCAL_GOTNO, [] { return in.mipsGot->getLocalEntriesNum(); });
14171420
1418 if (const Symbol *B = In.MipsGot->getFirstGlobalEntry())1421 if (const Symbol *b = in.mipsGot->getFirstGlobalEntry())
1419 addInt(DT_MIPS_GOTSYM, B->DynsymIndex);1422 addInt(DT_MIPS_GOTSYM, b->dynsymIndex);
1420 else1423 else
1421 addInt(DT_MIPS_GOTSYM, In.DynSymTab->getNumSymbols());1424 addInt(DT_MIPS_GOTSYM, part.dynSymTab->getNumSymbols());
1422 addInSec(DT_PLTGOT, In.MipsGot);1425 addInSec(DT_PLTGOT, in.mipsGot);
1423 if (In.MipsRldMap) {1426 if (in.mipsRldMap) {
1424 if (!Config->Pie)1427 if (!config->pie)
1425 addInSec(DT_MIPS_RLD_MAP, In.MipsRldMap);1428 addInSec(DT_MIPS_RLD_MAP, in.mipsRldMap);
1426 // Store the offset to the .rld_map section1429 // Store the offset to the .rld_map section
1427 // relative to the address of the tag.1430 // relative to the address of the tag.
1428 addInSecRelative(DT_MIPS_RLD_MAP_REL, In.MipsRldMap);1431 addInSecRelative(DT_MIPS_RLD_MAP_REL, in.mipsRldMap);
1429 }1432 }
1430 }1433 }
14311434
1435 // DT_PPC_GOT indicates to glibc Secure PLT is used. If DT_PPC_GOT is absent,
1436 // glibc assumes the old-style BSS PLT layout which we don't support.
1437 if (config->emachine == EM_PPC)
1438 add(DT_PPC_GOT, [] { return in.got->getVA(); });
1439
1432 // Glink dynamic tag is required by the V2 abi if the plt section isn't empty.1440 // Glink dynamic tag is required by the V2 abi if the plt section isn't empty.
1433 if (Config->EMachine == EM_PPC64 && !In.Plt->empty()) {1441 if (config->emachine == EM_PPC64 && in.plt->isNeeded()) {
1434 // The Glink tag points to 32 bytes before the first lazy symbol resolution1442 // The Glink tag points to 32 bytes before the first lazy symbol resolution
1435 // stub, which starts directly after the header.1443 // stub, which starts directly after the header.
1436 Entries.push_back({DT_PPC64_GLINK, [=] {1444 entries.push_back({DT_PPC64_GLINK, [=] {
1437 unsigned Offset = Target->PltHeaderSize - 32;1445 unsigned offset = target->pltHeaderSize - 32;
1438 return In.Plt->getVA(0) + Offset;1446 return in.plt->getVA(0) + offset;
1439 }});1447 }});
1440 }1448 }
14411449
1442 addInt(DT_NULL, 0);1450 addInt(DT_NULL, 0);
14431451
1444 getParent()->Link = this->Link;1452 getParent()->link = this->link;
1445 this->Size = Entries.size() * this->Entsize;1453 this->size = entries.size() * this->entsize;
1446}1454}
14471455
1448template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *Buf) {1456template <class ELFT> void DynamicSection<ELFT>::writeTo(uint8_t *buf) {
1449 auto *P = reinterpret_cast<Elf_Dyn *>(Buf);1457 auto *p = reinterpret_cast<Elf_Dyn *>(buf);
14501458
1451 for (std::pair<int32_t, std::function<uint64_t()>> &KV : Entries) {1459 for (std::pair<int32_t, std::function<uint64_t()>> &kv : entries) {
1452 P->d_tag = KV.first;1460 p->d_tag = kv.first;
1453 P->d_un.d_val = KV.second();1461 p->d_un.d_val = kv.second();
1454 ++P;1462 ++p;
1455 }1463 }
1456}1464}
14571465
1458uint64_t DynamicReloc::getOffset() const {1466uint64_t DynamicReloc::getOffset() const {
1459 return InputSec->getVA(OffsetInSec);1467 return inputSec->getVA(offsetInSec);
1460}1468}
14611469
1462int64_t DynamicReloc::computeAddend() const {1470int64_t DynamicReloc::computeAddend() const {
1463 if (UseSymVA)1471 if (useSymVA)
1464 return Sym->getVA(Addend);1472 return sym->getVA(addend);
1465 if (!OutputSec)1473 if (!outputSec)
1466 return Addend;1474 return addend;
1467 // See the comment in the DynamicReloc ctor.1475 // See the comment in the DynamicReloc ctor.
1468 return getMipsPageAddr(OutputSec->Addr) + Addend;1476 return getMipsPageAddr(outputSec->addr) + addend;
1469}1477}
14701478
1471uint32_t DynamicReloc::getSymIndex() const {1479uint32_t DynamicReloc::getSymIndex(SymbolTableBaseSection *symTab) const {
1472 if (Sym && !UseSymVA)1480 if (sym && !useSymVA)
1473 return Sym->DynsymIndex;1481 return symTab->getSymbolIndex(sym);
1474 return 0;1482 return 0;
1475}1483}
14761484
1477RelocationBaseSection::RelocationBaseSection(StringRef Name, uint32_t Type,1485RelocationBaseSection::RelocationBaseSection(StringRef name, uint32_t type,
1478 int32_t DynamicTag,1486 int32_t dynamicTag,
1479 int32_t SizeDynamicTag)1487 int32_t sizeDynamicTag)
1480 : SyntheticSection(SHF_ALLOC, Type, Config->Wordsize, Name),1488 : SyntheticSection(SHF_ALLOC, type, config->wordsize, name),
1481 DynamicTag(DynamicTag), SizeDynamicTag(SizeDynamicTag) {}1489 dynamicTag(dynamicTag), sizeDynamicTag(sizeDynamicTag) {}
14821490
1483void RelocationBaseSection::addReloc(RelType DynType, InputSectionBase *IS,1491void RelocationBaseSection::addReloc(RelType dynType, InputSectionBase *isec,
1484 uint64_t OffsetInSec, Symbol *Sym) {1492 uint64_t offsetInSec, Symbol *sym) {
1485 addReloc({DynType, IS, OffsetInSec, false, Sym, 0});1493 addReloc({dynType, isec, offsetInSec, false, sym, 0});
1486}1494}
14871495
1488void RelocationBaseSection::addReloc(RelType DynType,1496void RelocationBaseSection::addReloc(RelType dynType,
1489 InputSectionBase *InputSec,1497 InputSectionBase *inputSec,
1490 uint64_t OffsetInSec, Symbol *Sym,1498 uint64_t offsetInSec, Symbol *sym,
1491 int64_t Addend, RelExpr Expr,1499 int64_t addend, RelExpr expr,
1492 RelType Type) {1500 RelType type) {
1493 // Write the addends to the relocated address if required. We skip1501 // Write the addends to the relocated address if required. We skip
1494 // it if the written value would be zero.1502 // it if the written value would be zero.
1495 if (Config->WriteAddends && (Expr != R_ADDEND || Addend != 0))1503 if (config->writeAddends && (expr != R_ADDEND || addend != 0))
1496 InputSec->Relocations.push_back({Expr, Type, OffsetInSec, Addend, Sym});1504 inputSec->relocations.push_back({expr, type, offsetInSec, addend, sym});
1497 addReloc({DynType, InputSec, OffsetInSec, Expr != R_ADDEND, Sym, Addend});1505 addReloc({dynType, inputSec, offsetInSec, expr != R_ADDEND, sym, addend});
1498}1506}
14991507
1500void RelocationBaseSection::addReloc(const DynamicReloc &Reloc) {1508void RelocationBaseSection::addReloc(const DynamicReloc &reloc) {
1501 if (Reloc.Type == Target->RelativeRel)1509 if (reloc.type == target->relativeRel)
1502 ++NumRelativeRelocs;1510 ++numRelativeRelocs;
1503 Relocs.push_back(Reloc);1511 relocs.push_back(reloc);
1504}1512}
15051513
1506void RelocationBaseSection::finalizeContents() {1514void RelocationBaseSection::finalizeContents() {
1515 SymbolTableBaseSection *symTab = getPartition().dynSymTab;
1516
1507 // When linking glibc statically, .rel{,a}.plt contains R_*_IRELATIVE1517 // 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 that1518 // relocations due to IFUNC (e.g. strcpy). sh_link will be set to 0 in that
1509 // case.1519 // case.
1510 InputSection *SymTab = Config->Relocatable ? In.SymTab : In.DynSymTab;1520 if (symTab && symTab->getParent())
1511 if (SymTab && SymTab->getParent())1521 getParent()->link = symTab->getParent()->sectionIndex;
1512 getParent()->Link = SymTab->getParent()->SectionIndex;
1513 else1522 else
1514 getParent()->Link = 0;1523 getParent()->link = 0;
15151524
1516 if (In.RelaPlt == this)1525 if (in.relaPlt == this)
1517 getParent()->Info = In.GotPlt->getParent()->SectionIndex;1526 getParent()->info = in.gotPlt->getParent()->sectionIndex;
1518 if (In.RelaIplt == this)1527 if (in.relaIplt == this)
1519 getParent()->Info = In.IgotPlt->getParent()->SectionIndex;1528 getParent()->info = in.igotPlt->getParent()->sectionIndex;
1520}1529}
15211530
1522RelrBaseSection::RelrBaseSection()1531RelrBaseSection::RelrBaseSection()
1523 : SyntheticSection(SHF_ALLOC,1532 : SyntheticSection(SHF_ALLOC,
1524 Config->UseAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR,1533 config->useAndroidRelrTags ? SHT_ANDROID_RELR : SHT_RELR,
1525 Config->Wordsize, ".relr.dyn") {}1534 config->wordsize, ".relr.dyn") {}
15261535
1527template <class ELFT>1536template <class ELFT>
1528static void encodeDynamicReloc(typename ELFT::Rela *P,1537static void encodeDynamicReloc(SymbolTableBaseSection *symTab,
1529 const DynamicReloc &Rel) {1538 typename ELFT::Rela *p,
1530 if (Config->IsRela)1539 const DynamicReloc &rel) {
1531 P->r_addend = Rel.computeAddend();1540 if (config->isRela)
1532 P->r_offset = Rel.getOffset();1541 p->r_addend = rel.computeAddend();
1533 P->setSymbolAndType(Rel.getSymIndex(), Rel.Type, Config->IsMips64EL);1542 p->r_offset = rel.getOffset();
1543 p->setSymbolAndType(rel.getSymIndex(symTab), rel.type, config->isMips64EL);
1534}1544}
15351545
1536template <class ELFT>1546template <class ELFT>
1537RelocationSection<ELFT>::RelocationSection(StringRef Name, bool Sort)1547RelocationSection<ELFT>::RelocationSection(StringRef name, bool sort)
1538 : RelocationBaseSection(Name, Config->IsRela ? SHT_RELA : SHT_REL,1548 : RelocationBaseSection(name, config->isRela ? SHT_RELA : SHT_REL,
1539 Config->IsRela ? DT_RELA : DT_REL,1549 config->isRela ? DT_RELA : DT_REL,
1540 Config->IsRela ? DT_RELASZ : DT_RELSZ),1550 config->isRela ? DT_RELASZ : DT_RELSZ),
1541 Sort(Sort) {1551 sort(sort) {
1542 this->Entsize = Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);1552 this->entsize = config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
1543}1553}
15441554
1545static bool compRelocations(const DynamicReloc &A, const DynamicReloc &B) {1555template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *buf) {
1546 bool AIsRel = A.Type == Target->RelativeRel;1556 SymbolTableBaseSection *symTab = getPartition().dynSymTab;
1547 bool BIsRel = B.Type == Target->RelativeRel;
1548 if (AIsRel != BIsRel)
1549 return AIsRel;
1550 return A.getSymIndex() < B.getSymIndex();
1551}
15521557
1553template <class ELFT> void RelocationSection<ELFT>::writeTo(uint8_t *Buf) {1558 // Sort by (!IsRelative,SymIndex,r_offset). DT_REL[A]COUNT requires us to
1554 if (Sort)1559 // place R_*_RELATIVE first. SymIndex is to improve locality, while r_offset
1555 std::stable_sort(Relocs.begin(), Relocs.end(), compRelocations);1560 // is to make results easier to read.
1561 if (sort)
1562 llvm::stable_sort(
1563 relocs, [&](const DynamicReloc &a, const DynamicReloc &b) {
1564 return std::make_tuple(a.type != target->relativeRel,
1565 a.getSymIndex(symTab), a.getOffset()) <
1566 std::make_tuple(b.type != target->relativeRel,
1567 b.getSymIndex(symTab), b.getOffset());
1568 });
15561569
1557 for (const DynamicReloc &Rel : Relocs) {1570 for (const DynamicReloc &rel : relocs) {
1558 encodeDynamicReloc<ELFT>(reinterpret_cast<Elf_Rela *>(Buf), Rel);1571 encodeDynamicReloc<ELFT>(symTab, reinterpret_cast<Elf_Rela *>(buf), rel);
1559 Buf += Config->IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);1572 buf += config->isRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
1560 }1573 }
1561}1574}
15621575
1563template <class ELFT> unsigned RelocationSection<ELFT>::getRelocOffset() {
1564 return this->Entsize * Relocs.size();
1565}
1566
1567template <class ELFT>1576template <class ELFT>
1568AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection(1577AndroidPackedRelocationSection<ELFT>::AndroidPackedRelocationSection(
1569 StringRef Name)1578 StringRef name)
1570 : RelocationBaseSection(1579 : RelocationBaseSection(
1571 Name, Config->IsRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL,1580 name, config->isRela ? SHT_ANDROID_RELA : SHT_ANDROID_REL,
1572 Config->IsRela ? DT_ANDROID_RELA : DT_ANDROID_REL,1581 config->isRela ? DT_ANDROID_RELA : DT_ANDROID_REL,
1573 Config->IsRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) {1582 config->isRela ? DT_ANDROID_RELASZ : DT_ANDROID_RELSZ) {
1574 this->Entsize = 1;1583 this->entsize = 1;
1575}1584}
15761585
1577template <class ELFT>1586template <class ELFT>
...@@ -1621,32 +1630,32 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {...@@ -1621,32 +1630,32 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
1621 // RELOCATION_GROUPED_BY_ADDEND_FLAG is not set) the r_addend delta for1630 // RELOCATION_GROUPED_BY_ADDEND_FLAG is not set) the r_addend delta for
1622 // this relocation.1631 // this relocation.
16231632
1624 size_t OldSize = RelocData.size();1633 size_t oldSize = relocData.size();
16251634
1626 RelocData = {'A', 'P', 'S', '2'};1635 relocData = {'A', 'P', 'S', '2'};
1627 raw_svector_ostream OS(RelocData);1636 raw_svector_ostream os(relocData);
1628 auto Add = [&](int64_t V) { encodeSLEB128(V, OS); };1637 auto add = [&](int64_t v) { encodeSLEB128(v, os); };
16291638
1630 // The format header includes the number of relocations and the initial1639 // The format header includes the number of relocations and the initial
1631 // offset (we set this to zero because the first relocation group will1640 // offset (we set this to zero because the first relocation group will
1632 // perform the initial adjustment).1641 // perform the initial adjustment).
1633 Add(Relocs.size());1642 add(relocs.size());
1634 Add(0);1643 add(0);
16351644
1636 std::vector<Elf_Rela> Relatives, NonRelatives;1645 std::vector<Elf_Rela> relatives, nonRelatives;
16371646
1638 for (const DynamicReloc &Rel : Relocs) {1647 for (const DynamicReloc &rel : relocs) {
1639 Elf_Rela R;1648 Elf_Rela r;
1640 encodeDynamicReloc<ELFT>(&R, Rel);1649 encodeDynamicReloc<ELFT>(getPartition().dynSymTab, &r, rel);
16411650
1642 if (R.getType(Config->IsMips64EL) == Target->RelativeRel)1651 if (r.getType(config->isMips64EL) == target->relativeRel)
1643 Relatives.push_back(R);1652 relatives.push_back(r);
1644 else1653 else
1645 NonRelatives.push_back(R);1654 nonRelatives.push_back(r);
1646 }1655 }
16471656
1648 llvm::sort(Relatives, [](const Elf_Rel &A, const Elf_Rel &B) {1657 llvm::sort(relatives, [](const Elf_Rel &a, const Elf_Rel &b) {
1649 return A.r_offset < B.r_offset;1658 return a.r_offset < b.r_offset;
1650 });1659 });
16511660
1652 // Try to find groups of relative relocations which are spaced one word1661 // Try to find groups of relative relocations which are spaced one word
...@@ -1655,108 +1664,108 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {...@@ -1655,108 +1664,108 @@ bool AndroidPackedRelocationSection<ELFT>::updateAllocSize() {
1655 // encoding, but each group will cost 7 bytes in addition to the offset from1664 // encoding, but each group will cost 7 bytes in addition to the offset from
1656 // the previous group, so it is only profitable to do this for groups of1665 // the previous group, so it is only profitable to do this for groups of
1657 // size 8 or larger.1666 // size 8 or larger.
1658 std::vector<Elf_Rela> UngroupedRelatives;1667 std::vector<Elf_Rela> ungroupedRelatives;
1659 std::vector<std::vector<Elf_Rela>> RelativeGroups;1668 std::vector<std::vector<Elf_Rela>> relativeGroups;
1660 for (auto I = Relatives.begin(), E = Relatives.end(); I != E;) {1669 for (auto i = relatives.begin(), e = relatives.end(); i != e;) {
1661 std::vector<Elf_Rela> Group;1670 std::vector<Elf_Rela> group;
1662 do {1671 do {
1663 Group.push_back(*I++);1672 group.push_back(*i++);
1664 } while (I != E && (I - 1)->r_offset + Config->Wordsize == I->r_offset);1673 } while (i != e && (i - 1)->r_offset + config->wordsize == i->r_offset);
16651674
1666 if (Group.size() < 8)1675 if (group.size() < 8)
1667 UngroupedRelatives.insert(UngroupedRelatives.end(), Group.begin(),1676 ungroupedRelatives.insert(ungroupedRelatives.end(), group.begin(),
1668 Group.end());1677 group.end());
1669 else1678 else
1670 RelativeGroups.emplace_back(std::move(Group));1679 relativeGroups.emplace_back(std::move(group));
1671 }1680 }
16721681
1673 unsigned HasAddendIfRela =1682 unsigned hasAddendIfRela =
1674 Config->IsRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0;1683 config->isRela ? RELOCATION_GROUP_HAS_ADDEND_FLAG : 0;
16751684
1676 uint64_t Offset = 0;1685 uint64_t offset = 0;
1677 uint64_t Addend = 0;1686 uint64_t addend = 0;
16781687
1679 // Emit the run-length encoding for the groups of adjacent relative1688 // Emit the run-length encoding for the groups of adjacent relative
1680 // relocations. Each group is represented using two groups in the packed1689 // relocations. Each group is represented using two groups in the packed
1681 // format. The first is used to set the current offset to the start of the1690 // format. The first is used to set the current offset to the start of the
1682 // group (and also encodes the first relocation), and the second encodes the1691 // group (and also encodes the first relocation), and the second encodes the
1683 // remaining relocations.1692 // remaining relocations.
1684 for (std::vector<Elf_Rela> &G : RelativeGroups) {1693 for (std::vector<Elf_Rela> &g : relativeGroups) {
1685 // The first relocation in the group.1694 // The first relocation in the group.
1686 Add(1);1695 add(1);
1687 Add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG |1696 add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG |
1688 RELOCATION_GROUPED_BY_INFO_FLAG | HasAddendIfRela);1697 RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
1689 Add(G[0].r_offset - Offset);1698 add(g[0].r_offset - offset);
1690 Add(Target->RelativeRel);1699 add(target->relativeRel);
1691 if (Config->IsRela) {1700 if (config->isRela) {
1692 Add(G[0].r_addend - Addend);1701 add(g[0].r_addend - addend);
1693 Addend = G[0].r_addend;1702 addend = g[0].r_addend;
1694 }1703 }
16951704
1696 // The remaining relocations.1705 // The remaining relocations.
1697 Add(G.size() - 1);1706 add(g.size() - 1);
1698 Add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG |1707 add(RELOCATION_GROUPED_BY_OFFSET_DELTA_FLAG |
1699 RELOCATION_GROUPED_BY_INFO_FLAG | HasAddendIfRela);1708 RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
1700 Add(Config->Wordsize);1709 add(config->wordsize);
1701 Add(Target->RelativeRel);1710 add(target->relativeRel);
1702 if (Config->IsRela) {1711 if (config->isRela) {
1703 for (auto I = G.begin() + 1, E = G.end(); I != E; ++I) {1712 for (auto i = g.begin() + 1, e = g.end(); i != e; ++i) {
1704 Add(I->r_addend - Addend);1713 add(i->r_addend - addend);
1705 Addend = I->r_addend;1714 addend = i->r_addend;
1706 }1715 }
1707 }1716 }
17081717
1709 Offset = G.back().r_offset;1718 offset = g.back().r_offset;
1710 }1719 }
17111720
1712 // Now the ungrouped relatives.1721 // Now the ungrouped relatives.
1713 if (!UngroupedRelatives.empty()) {1722 if (!ungroupedRelatives.empty()) {
1714 Add(UngroupedRelatives.size());1723 add(ungroupedRelatives.size());
1715 Add(RELOCATION_GROUPED_BY_INFO_FLAG | HasAddendIfRela);1724 add(RELOCATION_GROUPED_BY_INFO_FLAG | hasAddendIfRela);
1716 Add(Target->RelativeRel);1725 add(target->relativeRel);
1717 for (Elf_Rela &R : UngroupedRelatives) {1726 for (Elf_Rela &r : ungroupedRelatives) {
1718 Add(R.r_offset - Offset);1727 add(r.r_offset - offset);
1719 Offset = R.r_offset;1728 offset = r.r_offset;
1720 if (Config->IsRela) {1729 if (config->isRela) {
1721 Add(R.r_addend - Addend);1730 add(r.r_addend - addend);
1722 Addend = R.r_addend;1731 addend = r.r_addend;
1723 }1732 }
1724 }1733 }
1725 }1734 }
17261735
1727 // Finally the non-relative relocations.1736 // Finally the non-relative relocations.
1728 llvm::sort(NonRelatives, [](const Elf_Rela &A, const Elf_Rela &B) {1737 llvm::sort(nonRelatives, [](const Elf_Rela &a, const Elf_Rela &b) {
1729 return A.r_offset < B.r_offset;1738 return a.r_offset < b.r_offset;
1730 });1739 });
1731 if (!NonRelatives.empty()) {1740 if (!nonRelatives.empty()) {
1732 Add(NonRelatives.size());1741 add(nonRelatives.size());
1733 Add(HasAddendIfRela);1742 add(hasAddendIfRela);
1734 for (Elf_Rela &R : NonRelatives) {1743 for (Elf_Rela &r : nonRelatives) {
1735 Add(R.r_offset - Offset);1744 add(r.r_offset - offset);
1736 Offset = R.r_offset;1745 offset = r.r_offset;
1737 Add(R.r_info);1746 add(r.r_info);
1738 if (Config->IsRela) {1747 if (config->isRela) {
1739 Add(R.r_addend - Addend);1748 add(r.r_addend - addend);
1740 Addend = R.r_addend;1749 addend = r.r_addend;
1741 }1750 }
1742 }1751 }
1743 }1752 }
17441753
1745 // Don't allow the section to shrink; otherwise the size of the section can1754 // Don't allow the section to shrink; otherwise the size of the section can
1746 // oscillate infinitely.1755 // oscillate infinitely.
1747 if (RelocData.size() < OldSize)1756 if (relocData.size() < oldSize)
1748 RelocData.append(OldSize - RelocData.size(), 0);1757 relocData.append(oldSize - relocData.size(), 0);
17491758
1750 // Returns whether the section size changed. We need to keep recomputing both1759 // Returns whether the section size changed. We need to keep recomputing both
1751 // section layout and the contents of this section until the size converges1760 // section layout and the contents of this section until the size converges
1752 // because changing this section's size can affect section layout, which in1761 // because changing this section's size can affect section layout, which in
1753 // turn can affect the sizes of the LEB-encoded integers stored in this1762 // turn can affect the sizes of the LEB-encoded integers stored in this
1754 // section.1763 // section.
1755 return RelocData.size() != OldSize;1764 return relocData.size() != oldSize;
1756}1765}
17571766
1758template <class ELFT> RelrSection<ELFT>::RelrSection() {1767template <class ELFT> RelrSection<ELFT>::RelrSection() {
1759 this->Entsize = Config->Wordsize;1768 this->entsize = config->wordsize;
1760}1769}
17611770
1762template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() {1771template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() {
...@@ -1790,90 +1799,90 @@ template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() {...@@ -1790,90 +1799,90 @@ template <class ELFT> bool RelrSection<ELFT>::updateAllocSize() {
1790 // even means address, odd means bitmap.1799 // even means address, odd means bitmap.
1791 // 2. Just a simple list of addresses is a valid encoding.1800 // 2. Just a simple list of addresses is a valid encoding.
17921801
1793 size_t OldSize = RelrRelocs.size();1802 size_t oldSize = relrRelocs.size();
1794 RelrRelocs.clear();1803 relrRelocs.clear();
17951804
1796 // Same as Config->Wordsize but faster because this is a compile-time1805 // Same as Config->Wordsize but faster because this is a compile-time
1797 // constant.1806 // constant.
1798 const size_t Wordsize = sizeof(typename ELFT::uint);1807 const size_t wordsize = sizeof(typename ELFT::uint);
17991808
1800 // Number of bits to use for the relocation offsets bitmap.1809 // Number of bits to use for the relocation offsets bitmap.
1801 // Must be either 63 or 31.1810 // Must be either 63 or 31.
1802 const size_t NBits = Wordsize * 8 - 1;1811 const size_t nBits = wordsize * 8 - 1;
18031812
1804 // Get offsets for all relative relocations and sort them.1813 // Get offsets for all relative relocations and sort them.
1805 std::vector<uint64_t> Offsets;1814 std::vector<uint64_t> offsets;
1806 for (const RelativeReloc &Rel : Relocs)1815 for (const RelativeReloc &rel : relocs)
1807 Offsets.push_back(Rel.getOffset());1816 offsets.push_back(rel.getOffset());
1808 llvm::sort(Offsets.begin(), Offsets.end());1817 llvm::sort(offsets);
18091818
1810 // For each leading relocation, find following ones that can be folded1819 // For each leading relocation, find following ones that can be folded
1811 // as a bitmap and fold them.1820 // as a bitmap and fold them.
1812 for (size_t I = 0, E = Offsets.size(); I < E;) {1821 for (size_t i = 0, e = offsets.size(); i < e;) {
1813 // Add a leading relocation.1822 // Add a leading relocation.
1814 RelrRelocs.push_back(Elf_Relr(Offsets[I]));1823 relrRelocs.push_back(Elf_Relr(offsets[i]));
1815 uint64_t Base = Offsets[I] + Wordsize;1824 uint64_t base = offsets[i] + wordsize;
1816 ++I;1825 ++i;
18171826
1818 // Find foldable relocations to construct bitmaps.1827 // Find foldable relocations to construct bitmaps.
1819 while (I < E) {1828 while (i < e) {
1820 uint64_t Bitmap = 0;1829 uint64_t bitmap = 0;
18211830
1822 while (I < E) {1831 while (i < e) {
1823 uint64_t Delta = Offsets[I] - Base;1832 uint64_t delta = offsets[i] - base;
18241833
1825 // If it is too far, it cannot be folded.1834 // If it is too far, it cannot be folded.
1826 if (Delta >= NBits * Wordsize)1835 if (delta >= nBits * wordsize)
1827 break;1836 break;
18281837
1829 // If it is not a multiple of wordsize away, it cannot be folded.1838 // If it is not a multiple of wordsize away, it cannot be folded.
1830 if (Delta % Wordsize)1839 if (delta % wordsize)
1831 break;1840 break;
18321841
1833 // Fold it.1842 // Fold it.
1834 Bitmap |= 1ULL << (Delta / Wordsize);1843 bitmap |= 1ULL << (delta / wordsize);
1835 ++I;1844 ++i;
1836 }1845 }
18371846
1838 if (!Bitmap)1847 if (!bitmap)
1839 break;1848 break;
18401849
1841 RelrRelocs.push_back(Elf_Relr((Bitmap << 1) | 1));1850 relrRelocs.push_back(Elf_Relr((bitmap << 1) | 1));
1842 Base += NBits * Wordsize;1851 base += nBits * wordsize;
1843 }1852 }
1844 }1853 }
18451854
1846 return RelrRelocs.size() != OldSize;1855 return relrRelocs.size() != oldSize;
1847}1856}
18481857
1849SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &StrTabSec)1858SymbolTableBaseSection::SymbolTableBaseSection(StringTableSection &strTabSec)
1850 : SyntheticSection(StrTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0,1859 : SyntheticSection(strTabSec.isDynamic() ? (uint64_t)SHF_ALLOC : 0,
1851 StrTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,1860 strTabSec.isDynamic() ? SHT_DYNSYM : SHT_SYMTAB,
1852 Config->Wordsize,1861 config->wordsize,
1853 StrTabSec.isDynamic() ? ".dynsym" : ".symtab"),1862 strTabSec.isDynamic() ? ".dynsym" : ".symtab"),
1854 StrTabSec(StrTabSec) {}1863 strTabSec(strTabSec) {}
18551864
1856// Orders symbols according to their positions in the GOT,1865// Orders symbols according to their positions in the GOT,
1857// in compliance with MIPS ABI rules.1866// in compliance with MIPS ABI rules.
1858// See "Global Offset Table" in Chapter 5 in the following document1867// See "Global Offset Table" in Chapter 5 in the following document
1859// for detailed description:1868// for detailed description:
1860// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf1869// ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
1861static bool sortMipsSymbols(const SymbolTableEntry &L,1870static bool sortMipsSymbols(const SymbolTableEntry &l,
1862 const SymbolTableEntry &R) {1871 const SymbolTableEntry &r) {
1863 // Sort entries related to non-local preemptible symbols by GOT indexes.1872 // Sort entries related to non-local preemptible symbols by GOT indexes.
1864 // All other entries go to the beginning of a dynsym in arbitrary order.1873 // All other entries go to the beginning of a dynsym in arbitrary order.
1865 if (L.Sym->isInGot() && R.Sym->isInGot())1874 if (l.sym->isInGot() && r.sym->isInGot())
1866 return L.Sym->GotIndex < R.Sym->GotIndex;1875 return l.sym->gotIndex < r.sym->gotIndex;
1867 if (!L.Sym->isInGot() && !R.Sym->isInGot())1876 if (!l.sym->isInGot() && !r.sym->isInGot())
1868 return false;1877 return false;
1869 return !L.Sym->isInGot();1878 return !l.sym->isInGot();
1870}1879}
18711880
1872void SymbolTableBaseSection::finalizeContents() {1881void SymbolTableBaseSection::finalizeContents() {
1873 if (OutputSection *Sec = StrTabSec.getParent())1882 if (OutputSection *sec = strTabSec.getParent())
1874 getParent()->Link = Sec->SectionIndex;1883 getParent()->link = sec->sectionIndex;
18751884
1876 if (this->Type != SHT_DYNSYM) {1885 if (this->type != SHT_DYNSYM) {
1877 sortSymTabSymbols();1886 sortSymTabSymbols();
1878 return;1887 return;
1879 }1888 }
...@@ -1883,18 +1892,22 @@ void SymbolTableBaseSection::finalizeContents() {...@@ -1883,18 +1892,22 @@ void SymbolTableBaseSection::finalizeContents() {
18831892
1884 // Section's Info field has the index of the first non-local symbol.1893 // Section's Info field has the index of the first non-local symbol.
1885 // Because the first symbol entry is a null entry, 1 is the first.1894 // Because the first symbol entry is a null entry, 1 is the first.
1886 getParent()->Info = 1;1895 getParent()->info = 1;
18871896
1888 if (In.GnuHashTab) {1897 if (getPartition().gnuHashTab) {
1889 // NB: It also sorts Symbols to meet the GNU hash table requirements.1898 // NB: It also sorts Symbols to meet the GNU hash table requirements.
1890 In.GnuHashTab->addSymbols(Symbols);1899 getPartition().gnuHashTab->addSymbols(symbols);
1891 } else if (Config->EMachine == EM_MIPS) {1900 } else if (config->emachine == EM_MIPS) {
1892 std::stable_sort(Symbols.begin(), Symbols.end(), sortMipsSymbols);1901 llvm::stable_sort(symbols, sortMipsSymbols);
1893 }1902 }
18941903
1895 size_t I = 0;1904 // Only the main partition's dynsym indexes are stored in the symbols
1896 for (const SymbolTableEntry &S : Symbols)1905 // themselves. All other partitions use a lookup table.
1897 S.Sym->DynsymIndex = ++I;1906 if (this == mainPart->dynSymTab) {
1907 size_t i = 0;
1908 for (const SymbolTableEntry &s : symbols)
1909 s.sym->dynsymIndex = ++i;
1910 }
1898}1911}
18991912
1900// The ELF spec requires that all local symbols precede global symbols, so we1913// The ELF spec requires that all local symbols precede global symbols, so we
...@@ -1906,193 +1919,210 @@ void SymbolTableBaseSection::finalizeContents() {...@@ -1906,193 +1919,210 @@ void SymbolTableBaseSection::finalizeContents() {
1906// coming from.1919// coming from.
1907void SymbolTableBaseSection::sortSymTabSymbols() {1920void SymbolTableBaseSection::sortSymTabSymbols() {
1908 // Move all local symbols before global symbols.1921 // Move all local symbols before global symbols.
1909 auto E = std::stable_partition(1922 auto e = std::stable_partition(
1910 Symbols.begin(), Symbols.end(), [](const SymbolTableEntry &S) {1923 symbols.begin(), symbols.end(), [](const SymbolTableEntry &s) {
1911 return S.Sym->isLocal() || S.Sym->computeBinding() == STB_LOCAL;1924 return s.sym->isLocal() || s.sym->computeBinding() == STB_LOCAL;
1912 });1925 });
1913 size_t NumLocals = E - Symbols.begin();1926 size_t numLocals = e - symbols.begin();
1914 getParent()->Info = NumLocals + 1;1927 getParent()->info = numLocals + 1;
19151928
1916 // We want to group the local symbols by file. For that we rebuild the local1929 // We want to group the local symbols by file. For that we rebuild the local
1917 // part of the symbols vector. We do not need to care about the STT_FILE1930 // part of the symbols vector. We do not need to care about the STT_FILE
1918 // symbols, they are already naturally placed first in each group. That1931 // symbols, they are already naturally placed first in each group. That
1919 // happens because STT_FILE is always the first symbol in the object and hence1932 // happens because STT_FILE is always the first symbol in the object and hence
1920 // precede all other local symbols we add for a file.1933 // precede all other local symbols we add for a file.
1921 MapVector<InputFile *, std::vector<SymbolTableEntry>> Arr;1934 MapVector<InputFile *, std::vector<SymbolTableEntry>> arr;
1922 for (const SymbolTableEntry &S : llvm::make_range(Symbols.begin(), E))1935 for (const SymbolTableEntry &s : llvm::make_range(symbols.begin(), e))
1923 Arr[S.Sym->File].push_back(S);1936 arr[s.sym->file].push_back(s);
19241937
1925 auto I = Symbols.begin();1938 auto i = symbols.begin();
1926 for (std::pair<InputFile *, std::vector<SymbolTableEntry>> &P : Arr)1939 for (std::pair<InputFile *, std::vector<SymbolTableEntry>> &p : arr)
1927 for (SymbolTableEntry &Entry : P.second)1940 for (SymbolTableEntry &entry : p.second)
1928 *I++ = Entry;1941 *i++ = entry;
1929}1942}
19301943
1931void SymbolTableBaseSection::addSymbol(Symbol *B) {1944void SymbolTableBaseSection::addSymbol(Symbol *b) {
1932 // Adding a local symbol to a .dynsym is a bug.1945 // Adding a local symbol to a .dynsym is a bug.
1933 assert(this->Type != SHT_DYNSYM || !B->isLocal());1946 assert(this->type != SHT_DYNSYM || !b->isLocal());
19341947
1935 bool HashIt = B->isLocal();1948 bool hashIt = b->isLocal();
1936 Symbols.push_back({B, StrTabSec.addString(B->getName(), HashIt)});1949 symbols.push_back({b, strTabSec.addString(b->getName(), hashIt)});
1937}1950}
19381951
1939size_t SymbolTableBaseSection::getSymbolIndex(Symbol *Sym) {1952size_t SymbolTableBaseSection::getSymbolIndex(Symbol *sym) {
1940 // Initializes symbol lookup tables lazily. This is used only1953 if (this == mainPart->dynSymTab)
1941 // for -r or -emit-relocs.1954 return sym->dynsymIndex;
1942 llvm::call_once(OnceFlag, [&] {1955
1943 SymbolIndexMap.reserve(Symbols.size());1956 // Initializes symbol lookup tables lazily. This is used only for -r,
1944 size_t I = 0;1957 // -emit-relocs and dynsyms in partitions other than the main one.
1945 for (const SymbolTableEntry &E : Symbols) {1958 llvm::call_once(onceFlag, [&] {
1946 if (E.Sym->Type == STT_SECTION)1959 symbolIndexMap.reserve(symbols.size());
1947 SectionIndexMap[E.Sym->getOutputSection()] = ++I;1960 size_t i = 0;
1961 for (const SymbolTableEntry &e : symbols) {
1962 if (e.sym->type == STT_SECTION)
1963 sectionIndexMap[e.sym->getOutputSection()] = ++i;
1948 else1964 else
1949 SymbolIndexMap[E.Sym] = ++I;1965 symbolIndexMap[e.sym] = ++i;
1950 }1966 }
1951 });1967 });
19521968
1953 // Section symbols are mapped based on their output sections1969 // Section symbols are mapped based on their output sections
1954 // to maintain their semantics.1970 // to maintain their semantics.
1955 if (Sym->Type == STT_SECTION)1971 if (sym->type == STT_SECTION)
1956 return SectionIndexMap.lookup(Sym->getOutputSection());1972 return sectionIndexMap.lookup(sym->getOutputSection());
1957 return SymbolIndexMap.lookup(Sym);1973 return symbolIndexMap.lookup(sym);
1958}1974}
19591975
1960template <class ELFT>1976template <class ELFT>
1961SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &StrTabSec)1977SymbolTableSection<ELFT>::SymbolTableSection(StringTableSection &strTabSec)
1962 : SymbolTableBaseSection(StrTabSec) {1978 : SymbolTableBaseSection(strTabSec) {
1963 this->Entsize = sizeof(Elf_Sym);1979 this->entsize = sizeof(Elf_Sym);
1964}1980}
19651981
1966static BssSection *getCommonSec(Symbol *Sym) {1982static BssSection *getCommonSec(Symbol *sym) {
1967 if (!Config->DefineCommon)1983 if (!config->defineCommon)
1968 if (auto *D = dyn_cast<Defined>(Sym))1984 if (auto *d = dyn_cast<Defined>(sym))
1969 return dyn_cast_or_null<BssSection>(D->Section);1985 return dyn_cast_or_null<BssSection>(d->section);
1970 return nullptr;1986 return nullptr;
1971}1987}
19721988
1973static uint32_t getSymSectionIndex(Symbol *Sym) {1989static uint32_t getSymSectionIndex(Symbol *sym) {
1974 if (getCommonSec(Sym))1990 if (getCommonSec(sym))
1975 return SHN_COMMON;1991 return SHN_COMMON;
1976 if (!isa<Defined>(Sym) || Sym->NeedsPltAddr)1992 if (!isa<Defined>(sym) || sym->needsPltAddr)
1977 return SHN_UNDEF;1993 return SHN_UNDEF;
1978 if (const OutputSection *OS = Sym->getOutputSection())1994 if (const OutputSection *os = sym->getOutputSection())
1979 return OS->SectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX1995 return os->sectionIndex >= SHN_LORESERVE ? (uint32_t)SHN_XINDEX
1980 : OS->SectionIndex;1996 : os->sectionIndex;
1981 return SHN_ABS;1997 return SHN_ABS;
1982}1998}
19831999
1984// Write the internal symbol table contents to the output symbol table.2000// Write the internal symbol table contents to the output symbol table.
1985template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *Buf) {2001template <class ELFT> void SymbolTableSection<ELFT>::writeTo(uint8_t *buf) {
1986 // The first entry is a null entry as per the ELF spec.2002 // The first entry is a null entry as per the ELF spec.
1987 memset(Buf, 0, sizeof(Elf_Sym));2003 memset(buf, 0, sizeof(Elf_Sym));
1988 Buf += sizeof(Elf_Sym);2004 buf += sizeof(Elf_Sym);
19892005
1990 auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);2006 auto *eSym = reinterpret_cast<Elf_Sym *>(buf);
19912007
1992 for (SymbolTableEntry &Ent : Symbols) {2008 for (SymbolTableEntry &ent : symbols) {
1993 Symbol *Sym = Ent.Sym;2009 Symbol *sym = ent.sym;
2010 bool isDefinedHere = type == SHT_SYMTAB || sym->partition == partition;
19942011
1995 // Set st_info and st_other.2012 // Set st_info and st_other.
1996 ESym->st_other = 0;2013 eSym->st_other = 0;
1997 if (Sym->isLocal()) {2014 if (sym->isLocal()) {
1998 ESym->setBindingAndType(STB_LOCAL, Sym->Type);2015 eSym->setBindingAndType(STB_LOCAL, sym->type);
1999 } else {2016 } else {
2000 ESym->setBindingAndType(Sym->computeBinding(), Sym->Type);2017 eSym->setBindingAndType(sym->computeBinding(), sym->type);
2001 ESym->setVisibility(Sym->Visibility);2018 eSym->setVisibility(sym->visibility);
2002 }2019 }
20032020
2004 ESym->st_name = Ent.StrTabOffset;2021 // The 3 most significant bits of st_other are used by OpenPOWER ABI.
2005 ESym->st_shndx = getSymSectionIndex(Ent.Sym);2022 // See getPPC64GlobalEntryToLocalEntryOffset() for more details.
2023 if (config->emachine == EM_PPC64)
2024 eSym->st_other |= sym->stOther & 0xe0;
2025
2026 eSym->st_name = ent.strTabOffset;
2027 if (isDefinedHere)
2028 eSym->st_shndx = getSymSectionIndex(ent.sym);
2029 else
2030 eSym->st_shndx = 0;
20062031
2007 // Copy symbol size if it is a defined symbol. st_size is not significant2032 // Copy symbol size if it is a defined symbol. st_size is not significant
2008 // for undefined symbols, so whether copying it or not is up to us if that's2033 // for undefined symbols, so whether copying it or not is up to us if that's
2009 // the case. We'll leave it as zero because by not setting a value, we can2034 // the case. We'll leave it as zero because by not setting a value, we can
2010 // get the exact same outputs for two sets of input files that differ only2035 // get the exact same outputs for two sets of input files that differ only
2011 // in undefined symbol size in DSOs.2036 // in undefined symbol size in DSOs.
2012 if (ESym->st_shndx == SHN_UNDEF)2037 if (eSym->st_shndx == SHN_UNDEF || !isDefinedHere)
2013 ESym->st_size = 0;2038 eSym->st_size = 0;
2014 else2039 else
2015 ESym->st_size = Sym->getSize();2040 eSym->st_size = sym->getSize();
20162041
2017 // st_value is usually an address of a symbol, but that has a2042 // st_value is usually an address of a symbol, but that has a
2018 // special meaining for uninstantiated common symbols (this can2043 // special meaining for uninstantiated common symbols (this can
2019 // occur if -r is given).2044 // occur if -r is given).
2020 if (BssSection *CommonSec = getCommonSec(Ent.Sym))2045 if (BssSection *commonSec = getCommonSec(ent.sym))
2021 ESym->st_value = CommonSec->Alignment;2046 eSym->st_value = commonSec->alignment;
2047 else if (isDefinedHere)
2048 eSym->st_value = sym->getVA();
2022 else2049 else
2023 ESym->st_value = Sym->getVA();2050 eSym->st_value = 0;
20242051
2025 ++ESym;2052 ++eSym;
2026 }2053 }
20272054
2028 // On MIPS we need to mark symbol which has a PLT entry and requires2055 // On MIPS we need to mark symbol which has a PLT entry and requires
2029 // pointer equality by STO_MIPS_PLT flag. That is necessary to help2056 // pointer equality by STO_MIPS_PLT flag. That is necessary to help
2030 // dynamic linker distinguish such symbols and MIPS lazy-binding stubs.2057 // dynamic linker distinguish such symbols and MIPS lazy-binding stubs.
2031 // https://sourceware.org/ml/binutils/2008-07/txt00000.txt2058 // https://sourceware.org/ml/binutils/2008-07/txt00000.txt
2032 if (Config->EMachine == EM_MIPS) {2059 if (config->emachine == EM_MIPS) {
2033 auto *ESym = reinterpret_cast<Elf_Sym *>(Buf);2060 auto *eSym = reinterpret_cast<Elf_Sym *>(buf);
20342061
2035 for (SymbolTableEntry &Ent : Symbols) {2062 for (SymbolTableEntry &ent : symbols) {
2036 Symbol *Sym = Ent.Sym;2063 Symbol *sym = ent.sym;
2037 if (Sym->isInPlt() && Sym->NeedsPltAddr)2064 if (sym->isInPlt() && sym->needsPltAddr)
2038 ESym->st_other |= STO_MIPS_PLT;2065 eSym->st_other |= STO_MIPS_PLT;
2039 if (isMicroMips()) {2066 if (isMicroMips()) {
2040 // Set STO_MIPS_MICROMIPS flag and less-significant bit for2067 // We already set the less-significant bit for symbols
2041 // a defined microMIPS symbol and symbol should point to its2068 // marked by the `STO_MIPS_MICROMIPS` flag and for microMIPS PLT
2042 // PLT entry (in case of microMIPS, PLT entries always contain2069 // records. That allows us to distinguish such symbols in
2043 // microMIPS code).2070 // the `MIPS<ELFT>::relocateOne()` routine. Now we should
2044 if (Sym->isDefined() &&2071 // clear that bit for non-dynamic symbol table, so tools
2045 ((Sym->StOther & STO_MIPS_MICROMIPS) || Sym->NeedsPltAddr)) {2072 // like `objdump` will be able to deal with a correct
2046 if (StrTabSec.isDynamic())2073 // symbol position.
2047 ESym->st_value |= 1;2074 if (sym->isDefined() &&
2048 ESym->st_other |= STO_MIPS_MICROMIPS;2075 ((sym->stOther & STO_MIPS_MICROMIPS) || sym->needsPltAddr)) {
2076 if (!strTabSec.isDynamic())
2077 eSym->st_value &= ~1;
2078 eSym->st_other |= STO_MIPS_MICROMIPS;
2049 }2079 }
2050 }2080 }
2051 if (Config->Relocatable)2081 if (config->relocatable)
2052 if (auto *D = dyn_cast<Defined>(Sym))2082 if (auto *d = dyn_cast<Defined>(sym))
2053 if (isMipsPIC<ELFT>(D))2083 if (isMipsPIC<ELFT>(d))
2054 ESym->st_other |= STO_MIPS_PIC;2084 eSym->st_other |= STO_MIPS_PIC;
2055 ++ESym;2085 ++eSym;
2056 }2086 }
2057 }2087 }
2058}2088}
20592089
2060SymtabShndxSection::SymtabShndxSection()2090SymtabShndxSection::SymtabShndxSection()
2061 : SyntheticSection(0, SHT_SYMTAB_SHNDX, 4, ".symtab_shndxr") {2091 : SyntheticSection(0, SHT_SYMTAB_SHNDX, 4, ".symtab_shndx") {
2062 this->Entsize = 4;2092 this->entsize = 4;
2063}2093}
20642094
2065void SymtabShndxSection::writeTo(uint8_t *Buf) {2095void SymtabShndxSection::writeTo(uint8_t *buf) {
2066 // We write an array of 32 bit values, where each value has 1:1 association2096 // We write an array of 32 bit values, where each value has 1:1 association
2067 // with an entry in .symtab. If the corresponding entry contains SHN_XINDEX,2097 // with an entry in .symtab. If the corresponding entry contains SHN_XINDEX,
2068 // we need to write actual index, otherwise, we must write SHN_UNDEF(0).2098 // we need to write actual index, otherwise, we must write SHN_UNDEF(0).
2069 Buf += 4; // Ignore .symtab[0] entry.2099 buf += 4; // Ignore .symtab[0] entry.
2070 for (const SymbolTableEntry &Entry : In.SymTab->getSymbols()) {2100 for (const SymbolTableEntry &entry : in.symTab->getSymbols()) {
2071 if (getSymSectionIndex(Entry.Sym) == SHN_XINDEX)2101 if (getSymSectionIndex(entry.sym) == SHN_XINDEX)
2072 write32(Buf, Entry.Sym->getOutputSection()->SectionIndex);2102 write32(buf, entry.sym->getOutputSection()->sectionIndex);
2073 Buf += 4;2103 buf += 4;
2074 }2104 }
2075}2105}
20762106
2077bool SymtabShndxSection::empty() const {2107bool SymtabShndxSection::isNeeded() const {
2078 // SHT_SYMTAB can hold symbols with section indices values up to2108 // SHT_SYMTAB can hold symbols with section indices values up to
2079 // SHN_LORESERVE. If we need more, we want to use extension SHT_SYMTAB_SHNDX2109 // SHN_LORESERVE. If we need more, we want to use extension SHT_SYMTAB_SHNDX
2080 // section. Problem is that we reveal the final section indices a bit too2110 // section. Problem is that we reveal the final section indices a bit too
2081 // late, and we do not know them here. For simplicity, we just always create2111 // late, and we do not know them here. For simplicity, we just always create
2082 // a .symtab_shndxr section when the amount of output sections is huge.2112 // a .symtab_shndx section when the amount of output sections is huge.
2083 size_t Size = 0;2113 size_t size = 0;
2084 for (BaseCommand *Base : Script->SectionCommands)2114 for (BaseCommand *base : script->sectionCommands)
2085 if (isa<OutputSection>(Base))2115 if (isa<OutputSection>(base))
2086 ++Size;2116 ++size;
2087 return Size < SHN_LORESERVE;2117 return size >= SHN_LORESERVE;
2088}2118}
20892119
2090void SymtabShndxSection::finalizeContents() {2120void SymtabShndxSection::finalizeContents() {
2091 getParent()->Link = In.SymTab->getParent()->SectionIndex;2121 getParent()->link = in.symTab->getParent()->sectionIndex;
2092}2122}
20932123
2094size_t SymtabShndxSection::getSize() const {2124size_t SymtabShndxSection::getSize() const {
2095 return In.SymTab->getNumSymbols() * 4;2125 return in.symTab->getNumSymbols() * 4;
2096}2126}
20972127
2098// .hash and .gnu.hash sections contain on-disk hash tables that map2128// .hash and .gnu.hash sections contain on-disk hash tables that map
...@@ -2127,45 +2157,45 @@ size_t SymtabShndxSection::getSize() const {...@@ -2127,45 +2157,45 @@ size_t SymtabShndxSection::getSize() const {
2127// about .gnu.hash, you want to specify -hash-style=gnu. Otherwise, a2157// about .gnu.hash, you want to specify -hash-style=gnu. Otherwise, a
2128// safe bet is to specify -hash-style=both for backward compatibilty.2158// safe bet is to specify -hash-style=both for backward compatibilty.
2129GnuHashTableSection::GnuHashTableSection()2159GnuHashTableSection::GnuHashTableSection()
2130 : SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, Config->Wordsize, ".gnu.hash") {2160 : SyntheticSection(SHF_ALLOC, SHT_GNU_HASH, config->wordsize, ".gnu.hash") {
2131}2161}
21322162
2133void GnuHashTableSection::finalizeContents() {2163void GnuHashTableSection::finalizeContents() {
2134 if (OutputSection *Sec = In.DynSymTab->getParent())2164 if (OutputSection *sec = getPartition().dynSymTab->getParent())
2135 getParent()->Link = Sec->SectionIndex;2165 getParent()->link = sec->sectionIndex;
21362166
2137 // Computes bloom filter size in word size. We want to allocate 122167 // Computes bloom filter size in word size. We want to allocate 12
2138 // bits for each symbol. It must be a power of two.2168 // bits for each symbol. It must be a power of two.
2139 if (Symbols.empty()) {2169 if (symbols.empty()) {
2140 MaskWords = 1;2170 maskWords = 1;
2141 } else {2171 } else {
2142 uint64_t NumBits = Symbols.size() * 12;2172 uint64_t numBits = symbols.size() * 12;
2143 MaskWords = NextPowerOf2(NumBits / (Config->Wordsize * 8));2173 maskWords = NextPowerOf2(numBits / (config->wordsize * 8));
2144 }2174 }
21452175
2146 Size = 16; // Header2176 size = 16; // Header
2147 Size += Config->Wordsize * MaskWords; // Bloom filter2177 size += config->wordsize * maskWords; // Bloom filter
2148 Size += NBuckets * 4; // Hash buckets2178 size += nBuckets * 4; // Hash buckets
2149 Size += Symbols.size() * 4; // Hash values2179 size += symbols.size() * 4; // Hash values
2150}2180}
21512181
2152void GnuHashTableSection::writeTo(uint8_t *Buf) {2182void GnuHashTableSection::writeTo(uint8_t *buf) {
2153 // The output buffer is not guaranteed to be zero-cleared because we pre-2183 // The output buffer is not guaranteed to be zero-cleared because we pre-
2154 // fill executable sections with trap instructions. This is a precaution2184 // fill executable sections with trap instructions. This is a precaution
2155 // for that case, which happens only when -no-rosegment is given.2185 // for that case, which happens only when -no-rosegment is given.
2156 memset(Buf, 0, Size);2186 memset(buf, 0, size);
21572187
2158 // Write a header.2188 // Write a header.
2159 write32(Buf, NBuckets);2189 write32(buf, nBuckets);
2160 write32(Buf + 4, In.DynSymTab->getNumSymbols() - Symbols.size());2190 write32(buf + 4, getPartition().dynSymTab->getNumSymbols() - symbols.size());
2161 write32(Buf + 8, MaskWords);2191 write32(buf + 8, maskWords);
2162 write32(Buf + 12, Shift2);2192 write32(buf + 12, Shift2);
2163 Buf += 16;2193 buf += 16;
21642194
2165 // Write a bloom filter and a hash table.2195 // Write a bloom filter and a hash table.
2166 writeBloomFilter(Buf);2196 writeBloomFilter(buf);
2167 Buf += Config->Wordsize * MaskWords;2197 buf += config->wordsize * maskWords;
2168 writeHashTable(Buf);2198 writeHashTable(buf);
2169}2199}
21702200
2171// This function writes a 2-bit bloom filter. This bloom filter alone2201// This function writes a 2-bit bloom filter. This bloom filter alone
...@@ -2175,57 +2205,58 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) {...@@ -2175,57 +2205,58 @@ void GnuHashTableSection::writeTo(uint8_t *Buf) {
2175//2205//
2176// [1] Ulrich Drepper (2011), "How To Write Shared Libraries" (Ver. 4.1.2),2206// [1] Ulrich Drepper (2011), "How To Write Shared Libraries" (Ver. 4.1.2),
2177// p.9, https://www.akkadia.org/drepper/dsohowto.pdf2207// p.9, https://www.akkadia.org/drepper/dsohowto.pdf
2178void GnuHashTableSection::writeBloomFilter(uint8_t *Buf) {2208void GnuHashTableSection::writeBloomFilter(uint8_t *buf) {
2179 unsigned C = Config->Is64 ? 64 : 32;2209 unsigned c = config->is64 ? 64 : 32;
2180 for (const Entry &Sym : Symbols) {2210 for (const Entry &sym : symbols) {
2181 // When C = 64, we choose a word with bits [6:...] and set 1 to two bits in2211 // 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].2212 // the word using bits [0:5] and [26:31].
2183 size_t I = (Sym.Hash / C) & (MaskWords - 1);2213 size_t i = (sym.hash / c) & (maskWords - 1);
2184 uint64_t Val = readUint(Buf + I * Config->Wordsize);2214 uint64_t val = readUint(buf + i * config->wordsize);
2185 Val |= uint64_t(1) << (Sym.Hash % C);2215 val |= uint64_t(1) << (sym.hash % c);
2186 Val |= uint64_t(1) << ((Sym.Hash >> Shift2) % C);2216 val |= uint64_t(1) << ((sym.hash >> Shift2) % c);
2187 writeUint(Buf + I * Config->Wordsize, Val);2217 writeUint(buf + i * config->wordsize, val);
2188 }2218 }
2189}2219}
21902220
2191void GnuHashTableSection::writeHashTable(uint8_t *Buf) {2221void GnuHashTableSection::writeHashTable(uint8_t *buf) {
2192 uint32_t *Buckets = reinterpret_cast<uint32_t *>(Buf);2222 uint32_t *buckets = reinterpret_cast<uint32_t *>(buf);
2193 uint32_t OldBucket = -1;2223 uint32_t oldBucket = -1;
2194 uint32_t *Values = Buckets + NBuckets;2224 uint32_t *values = buckets + nBuckets;
2195 for (auto I = Symbols.begin(), E = Symbols.end(); I != E; ++I) {2225 for (auto i = symbols.begin(), e = symbols.end(); i != e; ++i) {
2196 // Write a hash value. It represents a sequence of chains that share the2226 // Write a hash value. It represents a sequence of chains that share the
2197 // same hash modulo value. The last element of each chain is terminated by2227 // same hash modulo value. The last element of each chain is terminated by
2198 // LSB 1.2228 // LSB 1.
2199 uint32_t Hash = I->Hash;2229 uint32_t hash = i->hash;
2200 bool IsLastInChain = (I + 1) == E || I->BucketIdx != (I + 1)->BucketIdx;2230 bool isLastInChain = (i + 1) == e || i->bucketIdx != (i + 1)->bucketIdx;
2201 Hash = IsLastInChain ? Hash | 1 : Hash & ~1;2231 hash = isLastInChain ? hash | 1 : hash & ~1;
2202 write32(Values++, Hash);2232 write32(values++, hash);
22032233
2204 if (I->BucketIdx == OldBucket)2234 if (i->bucketIdx == oldBucket)
2205 continue;2235 continue;
2206 // Write a hash bucket. Hash buckets contain indices in the following hash2236 // Write a hash bucket. Hash buckets contain indices in the following hash
2207 // value table.2237 // value table.
2208 write32(Buckets + I->BucketIdx, I->Sym->DynsymIndex);2238 write32(buckets + i->bucketIdx,
2209 OldBucket = I->BucketIdx;2239 getPartition().dynSymTab->getSymbolIndex(i->sym));
2240 oldBucket = i->bucketIdx;
2210 }2241 }
2211}2242}
22122243
2213static uint32_t hashGnu(StringRef Name) {2244static uint32_t hashGnu(StringRef name) {
2214 uint32_t H = 5381;2245 uint32_t h = 5381;
2215 for (uint8_t C : Name)2246 for (uint8_t c : name)
2216 H = (H << 5) + H + C;2247 h = (h << 5) + h + c;
2217 return H;2248 return h;
2218}2249}
22192250
2220// Add symbols to this symbol hash table. Note that this function2251// Add symbols to this symbol hash table. Note that this function
2221// destructively sort a given vector -- which is needed because2252// destructively sort a given vector -- which is needed because
2222// GNU-style hash table places some sorting requirements.2253// GNU-style hash table places some sorting requirements.
2223void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &V) {2254void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &v) {
2224 // We cannot use 'auto' for Mid because GCC 6.1 cannot deduce2255 // We cannot use 'auto' for Mid because GCC 6.1 cannot deduce
2225 // its type correctly.2256 // its type correctly.
2226 std::vector<SymbolTableEntry>::iterator Mid =2257 std::vector<SymbolTableEntry>::iterator mid =
2227 std::stable_partition(V.begin(), V.end(), [](const SymbolTableEntry &S) {2258 std::stable_partition(v.begin(), v.end(), [&](const SymbolTableEntry &s) {
2228 return !S.Sym->isDefined();2259 return !s.sym->isDefined() || s.sym->partition != partition;
2229 });2260 });
22302261
2231 // We chose load factor 4 for the on-disk hash table. For each hash2262 // We chose load factor 4 for the on-disk hash table. For each hash
...@@ -2237,138 +2268,143 @@ void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &V) {...@@ -2237,138 +2268,143 @@ void GnuHashTableSection::addSymbols(std::vector<SymbolTableEntry> &V) {
2237 // Android loader as of 2018 doesn't like a .gnu.hash containing such2268 // Android loader as of 2018 doesn't like a .gnu.hash containing such
2238 // table. If that's the case, we create a hash table with one unused2269 // table. If that's the case, we create a hash table with one unused
2239 // dummy slot.2270 // dummy slot.
2240 NBuckets = std::max<size_t>((V.end() - Mid) / 4, 1);2271 nBuckets = std::max<size_t>((v.end() - mid) / 4, 1);
22412272
2242 if (Mid == V.end())2273 if (mid == v.end())
2243 return;2274 return;
22442275
2245 for (SymbolTableEntry &Ent : llvm::make_range(Mid, V.end())) {2276 for (SymbolTableEntry &ent : llvm::make_range(mid, v.end())) {
2246 Symbol *B = Ent.Sym;2277 Symbol *b = ent.sym;
2247 uint32_t Hash = hashGnu(B->getName());2278 uint32_t hash = hashGnu(b->getName());
2248 uint32_t BucketIdx = Hash % NBuckets;2279 uint32_t bucketIdx = hash % nBuckets;
2249 Symbols.push_back({B, Ent.StrTabOffset, Hash, BucketIdx});2280 symbols.push_back({b, ent.strTabOffset, hash, bucketIdx});
2250 }2281 }
22512282
2252 std::stable_sort(2283 llvm::stable_sort(symbols, [](const Entry &l, const Entry &r) {
2253 Symbols.begin(), Symbols.end(),2284 return l.bucketIdx < r.bucketIdx;
2254 [](const Entry &L, const Entry &R) { return L.BucketIdx < R.BucketIdx; });2285 });
22552286
2256 V.erase(Mid, V.end());2287 v.erase(mid, v.end());
2257 for (const Entry &Ent : Symbols)2288 for (const Entry &ent : symbols)
2258 V.push_back({Ent.Sym, Ent.StrTabOffset});2289 v.push_back({ent.sym, ent.strTabOffset});
2259}2290}
22602291
2261HashTableSection::HashTableSection()2292HashTableSection::HashTableSection()
2262 : SyntheticSection(SHF_ALLOC, SHT_HASH, 4, ".hash") {2293 : SyntheticSection(SHF_ALLOC, SHT_HASH, 4, ".hash") {
2263 this->Entsize = 4;2294 this->entsize = 4;
2264}2295}
22652296
2266void HashTableSection::finalizeContents() {2297void HashTableSection::finalizeContents() {
2267 if (OutputSection *Sec = In.DynSymTab->getParent())2298 SymbolTableBaseSection *symTab = getPartition().dynSymTab;
2268 getParent()->Link = Sec->SectionIndex;
22692299
2270 unsigned NumEntries = 2; // nbucket and nchain.2300 if (OutputSection *sec = symTab->getParent())
2271 NumEntries += In.DynSymTab->getNumSymbols(); // The chain entries.2301 getParent()->link = sec->sectionIndex;
2302
2303 unsigned numEntries = 2; // nbucket and nchain.
2304 numEntries += symTab->getNumSymbols(); // The chain entries.
22722305
2273 // Create as many buckets as there are symbols.2306 // Create as many buckets as there are symbols.
2274 NumEntries += In.DynSymTab->getNumSymbols();2307 numEntries += symTab->getNumSymbols();
2275 this->Size = NumEntries * 4;2308 this->size = numEntries * 4;
2276}2309}
22772310
2278void HashTableSection::writeTo(uint8_t *Buf) {2311void HashTableSection::writeTo(uint8_t *buf) {
2312 SymbolTableBaseSection *symTab = getPartition().dynSymTab;
2313
2279 // See comment in GnuHashTableSection::writeTo.2314 // See comment in GnuHashTableSection::writeTo.
2280 memset(Buf, 0, Size);2315 memset(buf, 0, size);
22812316
2282 unsigned NumSymbols = In.DynSymTab->getNumSymbols();2317 unsigned numSymbols = symTab->getNumSymbols();
22832318
2284 uint32_t *P = reinterpret_cast<uint32_t *>(Buf);2319 uint32_t *p = reinterpret_cast<uint32_t *>(buf);
2285 write32(P++, NumSymbols); // nbucket2320 write32(p++, numSymbols); // nbucket
2286 write32(P++, NumSymbols); // nchain2321 write32(p++, numSymbols); // nchain
22872322
2288 uint32_t *Buckets = P;2323 uint32_t *buckets = p;
2289 uint32_t *Chains = P + NumSymbols;2324 uint32_t *chains = p + numSymbols;
22902325
2291 for (const SymbolTableEntry &S : In.DynSymTab->getSymbols()) {2326 for (const SymbolTableEntry &s : symTab->getSymbols()) {
2292 Symbol *Sym = S.Sym;2327 Symbol *sym = s.sym;
2293 StringRef Name = Sym->getName();2328 StringRef name = sym->getName();
2294 unsigned I = Sym->DynsymIndex;2329 unsigned i = sym->dynsymIndex;
2295 uint32_t Hash = hashSysV(Name) % NumSymbols;2330 uint32_t hash = hashSysV(name) % numSymbols;
2296 Chains[I] = Buckets[Hash];2331 chains[i] = buckets[hash];
2297 write32(Buckets + Hash, I);2332 write32(buckets + hash, i);
2298 }2333 }
2299}2334}
23002335
2301// On PowerPC64 the lazy symbol resolvers go into the `global linkage table`2336// On PowerPC64 the lazy symbol resolvers go into the `global linkage table`
2302// in the .glink section, rather then the typical .plt section.2337// in the .glink section, rather then the typical .plt section.
2303PltSection::PltSection(bool IsIplt)2338PltSection::PltSection(bool isIplt)
2304 : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16,2339 : SyntheticSection(
2305 Config->EMachine == EM_PPC64 ? ".glink" : ".plt"),2340 SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS, 16,
2306 HeaderSize(!IsIplt || Config->ZRetpolineplt ? Target->PltHeaderSize : 0),2341 (config->emachine == EM_PPC || config->emachine == EM_PPC64)
2307 IsIplt(IsIplt) {2342 ? ".glink"
2343 : ".plt"),
2344 headerSize(!isIplt || config->zRetpolineplt ? target->pltHeaderSize : 0),
2345 isIplt(isIplt) {
2308 // The PLT needs to be writable on SPARC as the dynamic linker will2346 // The PLT needs to be writable on SPARC as the dynamic linker will
2309 // modify the instructions in the PLT entries.2347 // modify the instructions in the PLT entries.
2310 if (Config->EMachine == EM_SPARCV9)2348 if (config->emachine == EM_SPARCV9)
2311 this->Flags |= SHF_WRITE;2349 this->flags |= SHF_WRITE;
2312}2350}
23132351
2314void PltSection::writeTo(uint8_t *Buf) {2352void PltSection::writeTo(uint8_t *buf) {
2353 if (config->emachine == EM_PPC) {
2354 writePPC32GlinkSection(buf, entries.size());
2355 return;
2356 }
2357
2315 // At beginning of PLT or retpoline IPLT, we have code to call the dynamic2358 // At beginning of PLT or retpoline IPLT, we have code to call the dynamic
2316 // linker to resolve dynsyms at runtime. Write such code.2359 // linker to resolve dynsyms at runtime. Write such code.
2317 if (HeaderSize > 0)2360 if (headerSize)
2318 Target->writePltHeader(Buf);2361 target->writePltHeader(buf);
2319 size_t Off = HeaderSize;2362 size_t off = headerSize;
2320 // The IPlt is immediately after the Plt, account for this in RelOff2363
2321 unsigned PltOff = getPltRelocOff();2364 RelocationBaseSection *relSec = isIplt ? in.relaIplt : in.relaPlt;
23222365
2323 for (auto &I : Entries) {2366 // The IPlt is immediately after the Plt, account for this in relOff
2324 const Symbol *B = I.first;2367 size_t pltOff = isIplt ? in.plt->getSize() : 0;
2325 unsigned RelOff = I.second + PltOff;2368
2326 uint64_t Got = B->getGotPltVA();2369 for (size_t i = 0, e = entries.size(); i != e; ++i) {
2327 uint64_t Plt = this->getVA() + Off;2370 const Symbol *b = entries[i];
2328 Target->writePlt(Buf + Off, Got, Plt, B->PltIndex, RelOff);2371 unsigned relOff = relSec->entsize * i + pltOff;
2329 Off += Target->PltEntrySize;2372 uint64_t got = b->getGotPltVA();
2373 uint64_t plt = this->getVA() + off;
2374 target->writePlt(buf + off, got, plt, b->pltIndex, relOff);
2375 off += target->pltEntrySize;
2330 }2376 }
2331}2377}
23322378
2333template <class ELFT> void PltSection::addEntry(Symbol &Sym) {2379template <class ELFT> void PltSection::addEntry(Symbol &sym) {
2334 Sym.PltIndex = Entries.size();2380 sym.pltIndex = entries.size();
2335 RelocationBaseSection *PltRelocSection = In.RelaPlt;2381 entries.push_back(&sym);
2336 if (IsIplt) {
2337 PltRelocSection = In.RelaIplt;
2338 Sym.IsInIplt = true;
2339 }
2340 unsigned RelOff =
2341 static_cast<RelocationSection<ELFT> *>(PltRelocSection)->getRelocOffset();
2342 Entries.push_back(std::make_pair(&Sym, RelOff));
2343}2382}
23442383
2345size_t PltSection::getSize() const {2384size_t PltSection::getSize() const {
2346 return HeaderSize + Entries.size() * Target->PltEntrySize;2385 return headerSize + entries.size() * target->pltEntrySize;
2347}2386}
23482387
2349// Some architectures such as additional symbols in the PLT section. For2388// Some architectures such as additional symbols in the PLT section. For
2350// example ARM uses mapping symbols to aid disassembly2389// example ARM uses mapping symbols to aid disassembly
2351void PltSection::addSymbols() {2390void PltSection::addSymbols() {
2352 // The PLT may have symbols defined for the Header, the IPLT has no header2391 // The PLT may have symbols defined for the Header, the IPLT has no header
2353 if (!IsIplt)2392 if (!isIplt)
2354 Target->addPltHeaderSymbols(*this);2393 target->addPltHeaderSymbols(*this);
2355 size_t Off = HeaderSize;
2356 for (size_t I = 0; I < Entries.size(); ++I) {
2357 Target->addPltSymbols(*this, Off);
2358 Off += Target->PltEntrySize;
2359 }
2360}
23612394
2362unsigned PltSection::getPltRelocOff() const {2395 size_t off = headerSize;
2363 return IsIplt ? In.Plt->getSize() : 0;2396 for (size_t i = 0; i < entries.size(); ++i) {
2397 target->addPltSymbols(*this, off);
2398 off += target->pltEntrySize;
2399 }
2364}2400}
23652401
2366// The string hash function for .gdb_index.2402// The string hash function for .gdb_index.
2367static uint32_t computeGdbHash(StringRef S) {2403static uint32_t computeGdbHash(StringRef s) {
2368 uint32_t H = 0;2404 uint32_t h = 0;
2369 for (uint8_t C : S)2405 for (uint8_t c : s)
2370 H = H * 67 + toLower(C) - 113;2406 h = h * 67 + toLower(c) - 113;
2371 return H;2407 return h;
2372}2408}
23732409
2374GdbIndexSection::GdbIndexSection()2410GdbIndexSection::GdbIndexSection()
...@@ -2377,367 +2413,384 @@ GdbIndexSection::GdbIndexSection()...@@ -2377,367 +2413,384 @@ GdbIndexSection::GdbIndexSection()
2377// Returns the desired size of an on-disk hash table for a .gdb_index section.2413// Returns the desired size of an on-disk hash table for a .gdb_index section.
2378// There's a tradeoff between size and collision rate. We aim 75% utilization.2414// There's a tradeoff between size and collision rate. We aim 75% utilization.
2379size_t GdbIndexSection::computeSymtabSize() const {2415size_t GdbIndexSection::computeSymtabSize() const {
2380 return std::max<size_t>(NextPowerOf2(Symbols.size() * 4 / 3), 1024);2416 return std::max<size_t>(NextPowerOf2(symbols.size() * 4 / 3), 1024);
2381}2417}
23822418
2383// Compute the output section size.2419// Compute the output section size.
2384void GdbIndexSection::initOutputSize() {2420void GdbIndexSection::initOutputSize() {
2385 Size = sizeof(GdbIndexHeader) + computeSymtabSize() * 8;2421 size = sizeof(GdbIndexHeader) + computeSymtabSize() * 8;
23862422
2387 for (GdbChunk &Chunk : Chunks)2423 for (GdbChunk &chunk : chunks)
2388 Size += Chunk.CompilationUnits.size() * 16 + Chunk.AddressAreas.size() * 20;2424 size += chunk.compilationUnits.size() * 16 + chunk.addressAreas.size() * 20;
23892425
2390 // Add the constant pool size if exists.2426 // Add the constant pool size if exists.
2391 if (!Symbols.empty()) {2427 if (!symbols.empty()) {
2392 GdbSymbol &Sym = Symbols.back();2428 GdbSymbol &sym = symbols.back();
2393 Size += Sym.NameOff + Sym.Name.size() + 1;2429 size += sym.nameOff + sym.name.size() + 1;
2394 }2430 }
2395}2431}
23962432
2397static std::vector<InputSection *> getDebugInfoSections() {2433static std::vector<InputSection *> getDebugInfoSections() {
2398 std::vector<InputSection *> Ret;2434 std::vector<InputSection *> ret;
2399 for (InputSectionBase *S : InputSections)2435 for (InputSectionBase *s : inputSections)
2400 if (InputSection *IS = dyn_cast<InputSection>(S))2436 if (InputSection *isec = dyn_cast<InputSection>(s))
2401 if (IS->Name == ".debug_info")2437 if (isec->name == ".debug_info")
2402 Ret.push_back(IS);2438 ret.push_back(isec);
2403 return Ret;2439 return ret;
2404}2440}
24052441
2406static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &Dwarf) {2442static std::vector<GdbIndexSection::CuEntry> readCuList(DWARFContext &dwarf) {
2407 std::vector<GdbIndexSection::CuEntry> Ret;2443 std::vector<GdbIndexSection::CuEntry> ret;
2408 for (std::unique_ptr<DWARFUnit> &Cu : Dwarf.compile_units())2444 for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units())
2409 Ret.push_back({Cu->getOffset(), Cu->getLength() + 4});2445 ret.push_back({cu->getOffset(), cu->getLength() + 4});
2410 return Ret;2446 return ret;
2411}2447}
24122448
2413static std::vector<GdbIndexSection::AddressEntry>2449static std::vector<GdbIndexSection::AddressEntry>
2414readAddressAreas(DWARFContext &Dwarf, InputSection *Sec) {2450readAddressAreas(DWARFContext &dwarf, InputSection *sec) {
2415 std::vector<GdbIndexSection::AddressEntry> Ret;2451 std::vector<GdbIndexSection::AddressEntry> ret;
24162452
2417 uint32_t CuIdx = 0;2453 uint32_t cuIdx = 0;
2418 for (std::unique_ptr<DWARFUnit> &Cu : Dwarf.compile_units()) {2454 for (std::unique_ptr<DWARFUnit> &cu : dwarf.compile_units()) {
2419 Expected<DWARFAddressRangesVector> Ranges = Cu->collectAddressRanges();2455 Expected<DWARFAddressRangesVector> ranges = cu->collectAddressRanges();
2420 if (!Ranges) {2456 if (!ranges) {
2421 error(toString(Sec) + ": " + toString(Ranges.takeError()));2457 error(toString(sec) + ": " + toString(ranges.takeError()));
2422 return {};2458 return {};
2423 }2459 }
24242460
2425 ArrayRef<InputSectionBase *> Sections = Sec->File->getSections();2461 ArrayRef<InputSectionBase *> sections = sec->file->getSections();
2426 for (DWARFAddressRange &R : *Ranges) {2462 for (DWARFAddressRange &r : *ranges) {
2427 InputSectionBase *S = Sections[R.SectionIndex];2463 if (r.SectionIndex == -1ULL)
2428 if (!S || S == &InputSection::Discarded || !S->Live)2464 continue;
2465 InputSectionBase *s = sections[r.SectionIndex];
2466 if (!s || s == &InputSection::discarded || !s->isLive())
2429 continue;2467 continue;
2430 // Range list with zero size has no effect.2468 // Range list with zero size has no effect.
2431 if (R.LowPC == R.HighPC)2469 if (r.LowPC == r.HighPC)
2432 continue;2470 continue;
2433 auto *IS = cast<InputSection>(S);2471 auto *isec = cast<InputSection>(s);
2434 uint64_t Offset = IS->getOffsetInFile();2472 uint64_t offset = isec->getOffsetInFile();
2435 Ret.push_back({IS, R.LowPC - Offset, R.HighPC - Offset, CuIdx});2473 ret.push_back({isec, r.LowPC - offset, r.HighPC - offset, cuIdx});
2436 }2474 }
2437 ++CuIdx;2475 ++cuIdx;
2438 }2476 }
24392477
2440 return Ret;2478 return ret;
2441}2479}
24422480
2443template <class ELFT>2481template <class ELFT>
2444static std::vector<GdbIndexSection::NameAttrEntry>2482static std::vector<GdbIndexSection::NameAttrEntry>
2445readPubNamesAndTypes(const LLDDwarfObj<ELFT> &Obj,2483readPubNamesAndTypes(const LLDDwarfObj<ELFT> &obj,
2446 const std::vector<GdbIndexSection::CuEntry> &CUs) {2484 const std::vector<GdbIndexSection::CuEntry> &cUs) {
2447 const DWARFSection &PubNames = Obj.getGnuPubNamesSection();2485 const DWARFSection &pubNames = obj.getGnuPubNamesSection();
2448 const DWARFSection &PubTypes = Obj.getGnuPubTypesSection();2486 const DWARFSection &pubTypes = obj.getGnuPubTypesSection();
24492487
2450 std::vector<GdbIndexSection::NameAttrEntry> Ret;2488 std::vector<GdbIndexSection::NameAttrEntry> ret;
2451 for (const DWARFSection *Pub : {&PubNames, &PubTypes}) {2489 for (const DWARFSection *pub : {&pubNames, &pubTypes}) {
2452 DWARFDebugPubTable Table(Obj, *Pub, Config->IsLE, true);2490 DWARFDebugPubTable table(obj, *pub, config->isLE, true);
2453 for (const DWARFDebugPubTable::Set &Set : Table.getData()) {2491 for (const DWARFDebugPubTable::Set &set : table.getData()) {
2454 // The value written into the constant pool is Kind << 24 | CuIndex. As we2492 // 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 compute2493 // don't know how many compilation units precede this object to compute
2456 // CuIndex, we compute (Kind << 24 | CuIndexInThisObject) instead, and add2494 // cuIndex, we compute (kind << 24 | cuIndexInThisObject) instead, and add
2457 // the number of preceding compilation units later.2495 // the number of preceding compilation units later.
2458 uint32_t I =2496 uint32_t i =
2459 lower_bound(CUs, Set.Offset,2497 lower_bound(cUs, set.Offset,
2460 [](GdbIndexSection::CuEntry CU, uint32_t Offset) {2498 [](GdbIndexSection::CuEntry cu, uint32_t offset) {
2461 return CU.CuOffset < Offset;2499 return cu.cuOffset < offset;
2462 }) -2500 }) -
2463 CUs.begin();2501 cUs.begin();
2464 for (const DWARFDebugPubTable::Entry &Ent : Set.Entries)2502 for (const DWARFDebugPubTable::Entry &ent : set.Entries)
2465 Ret.push_back({{Ent.Name, computeGdbHash(Ent.Name)},2503 ret.push_back({{ent.Name, computeGdbHash(ent.Name)},
2466 (Ent.Descriptor.toBits() << 24) | I});2504 (ent.Descriptor.toBits() << 24) | i});
2467 }2505 }
2468 }2506 }
2469 return Ret;2507 return ret;
2470}2508}
24712509
2472// Create a list of symbols from a given list of symbol names and types2510// Create a list of symbols from a given list of symbol names and types
2473// by uniquifying them by name.2511// by uniquifying them by name.
2474static std::vector<GdbIndexSection::GdbSymbol>2512static std::vector<GdbIndexSection::GdbSymbol>
2475createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> NameAttrs,2513createSymbols(ArrayRef<std::vector<GdbIndexSection::NameAttrEntry>> nameAttrs,
2476 const std::vector<GdbIndexSection::GdbChunk> &Chunks) {2514 const std::vector<GdbIndexSection::GdbChunk> &chunks) {
2477 typedef GdbIndexSection::GdbSymbol GdbSymbol;2515 using GdbSymbol = GdbIndexSection::GdbSymbol;
2478 typedef GdbIndexSection::NameAttrEntry NameAttrEntry;2516 using NameAttrEntry = GdbIndexSection::NameAttrEntry;
24792517
2480 // For each chunk, compute the number of compilation units preceding it.2518 // For each chunk, compute the number of compilation units preceding it.
2481 uint32_t CuIdx = 0;2519 uint32_t cuIdx = 0;
2482 std::vector<uint32_t> CuIdxs(Chunks.size());2520 std::vector<uint32_t> cuIdxs(chunks.size());
2483 for (uint32_t I = 0, E = Chunks.size(); I != E; ++I) {2521 for (uint32_t i = 0, e = chunks.size(); i != e; ++i) {
2484 CuIdxs[I] = CuIdx;2522 cuIdxs[i] = cuIdx;
2485 CuIdx += Chunks[I].CompilationUnits.size();2523 cuIdx += chunks[i].compilationUnits.size();
2486 }2524 }
24872525
2488 // The number of symbols we will handle in this function is of the order2526 // The number of symbols we will handle in this function is of the order
2489 // of millions for very large executables, so we use multi-threading to2527 // of millions for very large executables, so we use multi-threading to
2490 // speed it up.2528 // speed it up.
2491 size_t NumShards = 32;2529 size_t numShards = 32;
2492 size_t Concurrency = 1;2530 size_t concurrency = 1;
2493 if (ThreadsEnabled)2531 if (threadsEnabled)
2494 Concurrency =2532 concurrency =
2495 std::min<size_t>(PowerOf2Floor(hardware_concurrency()), NumShards);2533 std::min<size_t>(PowerOf2Floor(hardware_concurrency()), numShards);
24962534
2497 // A sharded map to uniquify symbols by name.2535 // A sharded map to uniquify symbols by name.
2498 std::vector<DenseMap<CachedHashStringRef, size_t>> Map(NumShards);2536 std::vector<DenseMap<CachedHashStringRef, size_t>> map(numShards);
2499 size_t Shift = 32 - countTrailingZeros(NumShards);2537 size_t shift = 32 - countTrailingZeros(numShards);
25002538
2501 // Instantiate GdbSymbols while uniqufying them by name.2539 // Instantiate GdbSymbols while uniqufying them by name.
2502 std::vector<std::vector<GdbSymbol>> Symbols(NumShards);2540 std::vector<std::vector<GdbSymbol>> symbols(numShards);
2503 parallelForEachN(0, Concurrency, [&](size_t ThreadId) {2541 parallelForEachN(0, concurrency, [&](size_t threadId) {
2504 uint32_t I = 0;2542 uint32_t i = 0;
2505 for (ArrayRef<NameAttrEntry> Entries : NameAttrs) {2543 for (ArrayRef<NameAttrEntry> entries : nameAttrs) {
2506 for (const NameAttrEntry &Ent : Entries) {2544 for (const NameAttrEntry &ent : entries) {
2507 size_t ShardId = Ent.Name.hash() >> Shift;2545 size_t shardId = ent.name.hash() >> shift;
2508 if ((ShardId & (Concurrency - 1)) != ThreadId)2546 if ((shardId & (concurrency - 1)) != threadId)
2509 continue;2547 continue;
25102548
2511 uint32_t V = Ent.CuIndexAndAttrs + CuIdxs[I];2549 uint32_t v = ent.cuIndexAndAttrs + cuIdxs[i];
2512 size_t &Idx = Map[ShardId][Ent.Name];2550 size_t &idx = map[shardId][ent.name];
2513 if (Idx) {2551 if (idx) {
2514 Symbols[ShardId][Idx - 1].CuVector.push_back(V);2552 symbols[shardId][idx - 1].cuVector.push_back(v);
2515 continue;2553 continue;
2516 }2554 }
25172555
2518 Idx = Symbols[ShardId].size() + 1;2556 idx = symbols[shardId].size() + 1;
2519 Symbols[ShardId].push_back({Ent.Name, {V}, 0, 0});2557 symbols[shardId].push_back({ent.name, {v}, 0, 0});
2520 }2558 }
2521 ++I;2559 ++i;
2522 }2560 }
2523 });2561 });
25242562
2525 size_t NumSymbols = 0;2563 size_t numSymbols = 0;
2526 for (ArrayRef<GdbSymbol> V : Symbols)2564 for (ArrayRef<GdbSymbol> v : symbols)
2527 NumSymbols += V.size();2565 numSymbols += v.size();
25282566
2529 // The return type is a flattened vector, so we'll copy each vector2567 // The return type is a flattened vector, so we'll copy each vector
2530 // contents to Ret.2568 // contents to Ret.
2531 std::vector<GdbSymbol> Ret;2569 std::vector<GdbSymbol> ret;
2532 Ret.reserve(NumSymbols);2570 ret.reserve(numSymbols);
2533 for (std::vector<GdbSymbol> &Vec : Symbols)2571 for (std::vector<GdbSymbol> &vec : symbols)
2534 for (GdbSymbol &Sym : Vec)2572 for (GdbSymbol &sym : vec)
2535 Ret.push_back(std::move(Sym));2573 ret.push_back(std::move(sym));
25362574
2537 // CU vectors and symbol names are adjacent in the output file.2575 // CU vectors and symbol names are adjacent in the output file.
2538 // We can compute their offsets in the output file now.2576 // We can compute their offsets in the output file now.
2539 size_t Off = 0;2577 size_t off = 0;
2540 for (GdbSymbol &Sym : Ret) {2578 for (GdbSymbol &sym : ret) {
2541 Sym.CuVectorOff = Off;2579 sym.cuVectorOff = off;
2542 Off += (Sym.CuVector.size() + 1) * 4;2580 off += (sym.cuVector.size() + 1) * 4;
2543 }2581 }
2544 for (GdbSymbol &Sym : Ret) {2582 for (GdbSymbol &sym : ret) {
2545 Sym.NameOff = Off;2583 sym.nameOff = off;
2546 Off += Sym.Name.size() + 1;2584 off += sym.name.size() + 1;
2547 }2585 }
25482586
2549 return Ret;2587 return ret;
2550}2588}
25512589
2552// Returns a newly-created .gdb_index section.2590// Returns a newly-created .gdb_index section.
2553template <class ELFT> GdbIndexSection *GdbIndexSection::create() {2591template <class ELFT> GdbIndexSection *GdbIndexSection::create() {
2554 std::vector<InputSection *> Sections = getDebugInfoSections();2592 std::vector<InputSection *> sections = getDebugInfoSections();
25552593
2556 // .debug_gnu_pub{names,types} are useless in executables.2594 // .debug_gnu_pub{names,types} are useless in executables.
2557 // They are present in input object files solely for creating2595 // They are present in input object files solely for creating
2558 // a .gdb_index. So we can remove them from the output.2596 // a .gdb_index. So we can remove them from the output.
2559 for (InputSectionBase *S : InputSections)2597 for (InputSectionBase *s : inputSections)
2560 if (S->Name == ".debug_gnu_pubnames" || S->Name == ".debug_gnu_pubtypes")2598 if (s->name == ".debug_gnu_pubnames" || s->name == ".debug_gnu_pubtypes")
2561 S->Live = false;2599 s->markDead();
25622600
2563 std::vector<GdbChunk> Chunks(Sections.size());2601 std::vector<GdbChunk> chunks(sections.size());
2564 std::vector<std::vector<NameAttrEntry>> NameAttrs(Sections.size());2602 std::vector<std::vector<NameAttrEntry>> nameAttrs(sections.size());
25652603
2566 parallelForEachN(0, Sections.size(), [&](size_t I) {2604 parallelForEachN(0, sections.size(), [&](size_t i) {
2567 ObjFile<ELFT> *File = Sections[I]->getFile<ELFT>();2605 ObjFile<ELFT> *file = sections[i]->getFile<ELFT>();
2568 DWARFContext Dwarf(make_unique<LLDDwarfObj<ELFT>>(File));2606 DWARFContext dwarf(make_unique<LLDDwarfObj<ELFT>>(file));
25692607
2570 Chunks[I].Sec = Sections[I];2608 chunks[i].sec = sections[i];
2571 Chunks[I].CompilationUnits = readCuList(Dwarf);2609 chunks[i].compilationUnits = readCuList(dwarf);
2572 Chunks[I].AddressAreas = readAddressAreas(Dwarf, Sections[I]);2610 chunks[i].addressAreas = readAddressAreas(dwarf, sections[i]);
2573 NameAttrs[I] = readPubNamesAndTypes<ELFT>(2611 nameAttrs[i] = readPubNamesAndTypes<ELFT>(
2574 static_cast<const LLDDwarfObj<ELFT> &>(Dwarf.getDWARFObj()),2612 static_cast<const LLDDwarfObj<ELFT> &>(dwarf.getDWARFObj()),
2575 Chunks[I].CompilationUnits);2613 chunks[i].compilationUnits);
2576 });2614 });
25772615
2578 auto *Ret = make<GdbIndexSection>();2616 auto *ret = make<GdbIndexSection>();
2579 Ret->Chunks = std::move(Chunks);2617 ret->chunks = std::move(chunks);
2580 Ret->Symbols = createSymbols(NameAttrs, Ret->Chunks);2618 ret->symbols = createSymbols(nameAttrs, ret->chunks);
2581 Ret->initOutputSize();2619 ret->initOutputSize();
2582 return Ret;2620 return ret;
2583}2621}
25842622
2585void GdbIndexSection::writeTo(uint8_t *Buf) {2623void GdbIndexSection::writeTo(uint8_t *buf) {
2586 // Write the header.2624 // Write the header.
2587 auto *Hdr = reinterpret_cast<GdbIndexHeader *>(Buf);2625 auto *hdr = reinterpret_cast<GdbIndexHeader *>(buf);
2588 uint8_t *Start = Buf;2626 uint8_t *start = buf;
2589 Hdr->Version = 7;2627 hdr->version = 7;
2590 Buf += sizeof(*Hdr);2628 buf += sizeof(*hdr);
25912629
2592 // Write the CU list.2630 // Write the CU list.
2593 Hdr->CuListOff = Buf - Start;2631 hdr->cuListOff = buf - start;
2594 for (GdbChunk &Chunk : Chunks) {2632 for (GdbChunk &chunk : chunks) {
2595 for (CuEntry &Cu : Chunk.CompilationUnits) {2633 for (CuEntry &cu : chunk.compilationUnits) {
2596 write64le(Buf, Chunk.Sec->OutSecOff + Cu.CuOffset);2634 write64le(buf, chunk.sec->outSecOff + cu.cuOffset);
2597 write64le(Buf + 8, Cu.CuLength);2635 write64le(buf + 8, cu.cuLength);
2598 Buf += 16;2636 buf += 16;
2599 }2637 }
2600 }2638 }
26012639
2602 // Write the address area.2640 // Write the address area.
2603 Hdr->CuTypesOff = Buf - Start;2641 hdr->cuTypesOff = buf - start;
2604 Hdr->AddressAreaOff = Buf - Start;2642 hdr->addressAreaOff = buf - start;
2605 uint32_t CuOff = 0;2643 uint32_t cuOff = 0;
2606 for (GdbChunk &Chunk : Chunks) {2644 for (GdbChunk &chunk : chunks) {
2607 for (AddressEntry &E : Chunk.AddressAreas) {2645 for (AddressEntry &e : chunk.addressAreas) {
2608 uint64_t BaseAddr = E.Section->getVA(0);2646 uint64_t baseAddr = e.section->getVA(0);
2609 write64le(Buf, BaseAddr + E.LowAddress);2647 write64le(buf, baseAddr + e.lowAddress);
2610 write64le(Buf + 8, BaseAddr + E.HighAddress);2648 write64le(buf + 8, baseAddr + e.highAddress);
2611 write32le(Buf + 16, E.CuIndex + CuOff);2649 write32le(buf + 16, e.cuIndex + cuOff);
2612 Buf += 20;2650 buf += 20;
2613 }2651 }
2614 CuOff += Chunk.CompilationUnits.size();2652 cuOff += chunk.compilationUnits.size();
2615 }2653 }
26162654
2617 // Write the on-disk open-addressing hash table containing symbols.2655 // Write the on-disk open-addressing hash table containing symbols.
2618 Hdr->SymtabOff = Buf - Start;2656 hdr->symtabOff = buf - start;
2619 size_t SymtabSize = computeSymtabSize();2657 size_t symtabSize = computeSymtabSize();
2620 uint32_t Mask = SymtabSize - 1;2658 uint32_t mask = symtabSize - 1;
26212659
2622 for (GdbSymbol &Sym : Symbols) {2660 for (GdbSymbol &sym : symbols) {
2623 uint32_t H = Sym.Name.hash();2661 uint32_t h = sym.name.hash();
2624 uint32_t I = H & Mask;2662 uint32_t i = h & mask;
2625 uint32_t Step = ((H * 17) & Mask) | 1;2663 uint32_t step = ((h * 17) & mask) | 1;
26262664
2627 while (read32le(Buf + I * 8))2665 while (read32le(buf + i * 8))
2628 I = (I + Step) & Mask;2666 i = (i + step) & mask;
26292667
2630 write32le(Buf + I * 8, Sym.NameOff);2668 write32le(buf + i * 8, sym.nameOff);
2631 write32le(Buf + I * 8 + 4, Sym.CuVectorOff);2669 write32le(buf + i * 8 + 4, sym.cuVectorOff);
2632 }2670 }
26332671
2634 Buf += SymtabSize * 8;2672 buf += symtabSize * 8;
26352673
2636 // Write the string pool.2674 // Write the string pool.
2637 Hdr->ConstantPoolOff = Buf - Start;2675 hdr->constantPoolOff = buf - start;
2638 parallelForEach(Symbols, [&](GdbSymbol &Sym) {2676 parallelForEach(symbols, [&](GdbSymbol &sym) {
2639 memcpy(Buf + Sym.NameOff, Sym.Name.data(), Sym.Name.size());2677 memcpy(buf + sym.nameOff, sym.name.data(), sym.name.size());
2640 });2678 });
26412679
2642 // Write the CU vectors.2680 // Write the CU vectors.
2643 for (GdbSymbol &Sym : Symbols) {2681 for (GdbSymbol &sym : symbols) {
2644 write32le(Buf, Sym.CuVector.size());2682 write32le(buf, sym.cuVector.size());
2645 Buf += 4;2683 buf += 4;
2646 for (uint32_t Val : Sym.CuVector) {2684 for (uint32_t val : sym.cuVector) {
2647 write32le(Buf, Val);2685 write32le(buf, val);
2648 Buf += 4;2686 buf += 4;
2649 }2687 }
2650 }2688 }
2651}2689}
26522690
2653bool GdbIndexSection::empty() const { return Chunks.empty(); }2691bool GdbIndexSection::isNeeded() const { return !chunks.empty(); }
26542692
2655EhFrameHeader::EhFrameHeader()2693EhFrameHeader::EhFrameHeader()
2656 : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".eh_frame_hdr") {}2694 : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".eh_frame_hdr") {}
26572695
2696void EhFrameHeader::writeTo(uint8_t *buf) {
2697 // Unlike most sections, the EhFrameHeader section is written while writing
2698 // another section, namely EhFrameSection, which calls the write() function
2699 // below from its writeTo() function. This is necessary because the contents
2700 // of EhFrameHeader depend on the relocated contents of EhFrameSection and we
2701 // don't know which order the sections will be written in.
2702}
2703
2658// .eh_frame_hdr contains a binary search table of pointers to FDEs.2704// .eh_frame_hdr contains a binary search table of pointers to FDEs.
2659// Each entry of the search table consists of two values,2705// Each entry of the search table consists of two values,
2660// the starting PC from where FDEs covers, and the FDE's address.2706// the starting PC from where FDEs covers, and the FDE's address.
2661// It is sorted by PC.2707// It is sorted by PC.
2662void EhFrameHeader::writeTo(uint8_t *Buf) {2708void EhFrameHeader::write() {
2663 typedef EhFrameSection::FdeData FdeData;2709 uint8_t *buf = Out::bufferStart + getParent()->offset + outSecOff;
2710 using FdeData = EhFrameSection::FdeData;
26642711
2665 std::vector<FdeData> Fdes = In.EhFrame->getFdeData();2712 std::vector<FdeData> fdes = getPartition().ehFrame->getFdeData();
26662713
2667 Buf[0] = 1;2714 buf[0] = 1;
2668 Buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;2715 buf[1] = DW_EH_PE_pcrel | DW_EH_PE_sdata4;
2669 Buf[2] = DW_EH_PE_udata4;2716 buf[2] = DW_EH_PE_udata4;
2670 Buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;2717 buf[3] = DW_EH_PE_datarel | DW_EH_PE_sdata4;
2671 write32(Buf + 4, In.EhFrame->getParent()->Addr - this->getVA() - 4);2718 write32(buf + 4,
2672 write32(Buf + 8, Fdes.size());2719 getPartition().ehFrame->getParent()->addr - this->getVA() - 4);
2673 Buf += 12;2720 write32(buf + 8, fdes.size());
2721 buf += 12;
26742722
2675 for (FdeData &Fde : Fdes) {2723 for (FdeData &fde : fdes) {
2676 write32(Buf, Fde.PcRel);2724 write32(buf, fde.pcRel);
2677 write32(Buf + 4, Fde.FdeVARel);2725 write32(buf + 4, fde.fdeVARel);
2678 Buf += 8;2726 buf += 8;
2679 }2727 }
2680}2728}
26812729
2682size_t EhFrameHeader::getSize() const {2730size_t EhFrameHeader::getSize() const {
2683 // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.2731 // .eh_frame_hdr has a 12 bytes header followed by an array of FDEs.
2684 return 12 + In.EhFrame->NumFdes * 8;2732 return 12 + getPartition().ehFrame->numFdes * 8;
2685}2733}
26862734
2687bool EhFrameHeader::empty() const { return In.EhFrame->empty(); }2735bool EhFrameHeader::isNeeded() const {
2736 return isLive() && getPartition().ehFrame->isNeeded();
2737}
26882738
2689VersionDefinitionSection::VersionDefinitionSection()2739VersionDefinitionSection::VersionDefinitionSection()
2690 : SyntheticSection(SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t),2740 : SyntheticSection(SHF_ALLOC, SHT_GNU_verdef, sizeof(uint32_t),
2691 ".gnu.version_d") {}2741 ".gnu.version_d") {}
26922742
2693static StringRef getFileDefName() {2743StringRef VersionDefinitionSection::getFileDefName() {
2694 if (!Config->SoName.empty())2744 if (!getPartition().name.empty())
2695 return Config->SoName;2745 return getPartition().name;
2696 return Config->OutputFile;2746 if (!config->soName.empty())
2747 return config->soName;
2748 return config->outputFile;
2697}2749}
26982750
2699void VersionDefinitionSection::finalizeContents() {2751void VersionDefinitionSection::finalizeContents() {
2700 FileDefNameOff = In.DynStrTab->addString(getFileDefName());2752 fileDefNameOff = getPartition().dynStrTab->addString(getFileDefName());
2701 for (VersionDefinition &V : Config->VersionDefinitions)2753 for (VersionDefinition &v : config->versionDefinitions)
2702 V.NameOff = In.DynStrTab->addString(V.Name);2754 verDefNameOffs.push_back(getPartition().dynStrTab->addString(v.name));
27032755
2704 if (OutputSection *Sec = In.DynStrTab->getParent())2756 if (OutputSection *sec = getPartition().dynStrTab->getParent())
2705 getParent()->Link = Sec->SectionIndex;2757 getParent()->link = sec->sectionIndex;
27062758
2707 // sh_info should be set to the number of definitions. This fact is missed in2759 // sh_info should be set to the number of definitions. This fact is missed in
2708 // documentation, but confirmed by binutils community:2760 // documentation, but confirmed by binutils community:
2709 // https://sourceware.org/ml/binutils/2014-11/msg00355.html2761 // https://sourceware.org/ml/binutils/2014-11/msg00355.html
2710 getParent()->Info = getVerDefNum();2762 getParent()->info = getVerDefNum();
2711}2763}
27122764
2713void VersionDefinitionSection::writeOne(uint8_t *Buf, uint32_t Index,2765void VersionDefinitionSection::writeOne(uint8_t *buf, uint32_t index,
2714 StringRef Name, size_t NameOff) {2766 StringRef name, size_t nameOff) {
2715 uint16_t Flags = Index == 1 ? VER_FLG_BASE : 0;2767 uint16_t flags = index == 1 ? VER_FLG_BASE : 0;
27162768
2717 // Write a verdef.2769 // Write a verdef.
2718 write16(Buf, 1); // vd_version2770 write16(buf, 1); // vd_version
2719 write16(Buf + 2, Flags); // vd_flags2771 write16(buf + 2, flags); // vd_flags
2720 write16(Buf + 4, Index); // vd_ndx2772 write16(buf + 4, index); // vd_ndx
2721 write16(Buf + 6, 1); // vd_cnt2773 write16(buf + 6, 1); // vd_cnt
2722 write32(Buf + 8, hashSysV(Name)); // vd_hash2774 write32(buf + 8, hashSysV(name)); // vd_hash
2723 write32(Buf + 12, 20); // vd_aux2775 write32(buf + 12, 20); // vd_aux
2724 write32(Buf + 16, 28); // vd_next2776 write32(buf + 16, 28); // vd_next
27252777
2726 // Write a veraux.2778 // Write a veraux.
2727 write32(Buf + 20, NameOff); // vda_name2779 write32(buf + 20, nameOff); // vda_name
2728 write32(Buf + 24, 0); // vda_next2780 write32(buf + 24, 0); // vda_next
2729}2781}
27302782
2731void VersionDefinitionSection::writeTo(uint8_t *Buf) {2783void VersionDefinitionSection::writeTo(uint8_t *buf) {
2732 writeOne(Buf, 1, getFileDefName(), FileDefNameOff);2784 writeOne(buf, 1, getFileDefName(), fileDefNameOff);
27332785
2734 for (VersionDefinition &V : Config->VersionDefinitions) {2786 auto nameOffIt = verDefNameOffs.begin();
2735 Buf += EntrySize;2787 for (VersionDefinition &v : config->versionDefinitions) {
2736 writeOne(Buf, V.Id, V.Name, V.NameOff);2788 buf += EntrySize;
2789 writeOne(buf, v.id, v.name, *nameOffIt++);
2737 }2790 }
27382791
2739 // Need to terminate the last version definition.2792 // Need to terminate the last version definition.
2740 write32(Buf + 16, 0); // vd_next2793 write32(buf + 16, 0); // vd_next
2741}2794}
27422795
2743size_t VersionDefinitionSection::getSize() const {2796size_t VersionDefinitionSection::getSize() const {
...@@ -2745,160 +2798,161 @@ size_t VersionDefinitionSection::getSize() const {...@@ -2745,160 +2798,161 @@ size_t VersionDefinitionSection::getSize() const {
2745}2798}
27462799
2747// .gnu.version is a table where each entry is 2 byte long.2800// .gnu.version is a table where each entry is 2 byte long.
2748template <class ELFT>2801VersionTableSection::VersionTableSection()
2749VersionTableSection<ELFT>::VersionTableSection()
2750 : SyntheticSection(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t),2802 : SyntheticSection(SHF_ALLOC, SHT_GNU_versym, sizeof(uint16_t),
2751 ".gnu.version") {2803 ".gnu.version") {
2752 this->Entsize = 2;2804 this->entsize = 2;
2753}2805}
27542806
2755template <class ELFT> void VersionTableSection<ELFT>::finalizeContents() {2807void VersionTableSection::finalizeContents() {
2756 // At the moment of june 2016 GNU docs does not mention that sh_link field2808 // At the moment of june 2016 GNU docs does not mention that sh_link field
2757 // should be set, but Sun docs do. Also readelf relies on this field.2809 // should be set, but Sun docs do. Also readelf relies on this field.
2758 getParent()->Link = In.DynSymTab->getParent()->SectionIndex;2810 getParent()->link = getPartition().dynSymTab->getParent()->sectionIndex;
2759}2811}
27602812
2761template <class ELFT> size_t VersionTableSection<ELFT>::getSize() const {2813size_t VersionTableSection::getSize() const {
2762 return (In.DynSymTab->getSymbols().size() + 1) * 2;2814 return (getPartition().dynSymTab->getSymbols().size() + 1) * 2;
2763}2815}
27642816
2765template <class ELFT> void VersionTableSection<ELFT>::writeTo(uint8_t *Buf) {2817void VersionTableSection::writeTo(uint8_t *buf) {
2766 Buf += 2;2818 buf += 2;
2767 for (const SymbolTableEntry &S : In.DynSymTab->getSymbols()) {2819 for (const SymbolTableEntry &s : getPartition().dynSymTab->getSymbols()) {
2768 write16(Buf, S.Sym->VersionId);2820 write16(buf, s.sym->versionId);
2769 Buf += 2;2821 buf += 2;
2770 }2822 }
2771}2823}
27722824
2773template <class ELFT> bool VersionTableSection<ELFT>::empty() const {2825bool VersionTableSection::isNeeded() const {
2774 return !In.VerDef && InX<ELFT>::VerNeed->empty();2826 return getPartition().verDef || getPartition().verNeed->isNeeded();
2827}
2828
2829void elf::addVerneed(Symbol *ss) {
2830 auto &file = cast<SharedFile>(*ss->file);
2831 if (ss->verdefIndex == VER_NDX_GLOBAL) {
2832 ss->versionId = VER_NDX_GLOBAL;
2833 return;
2834 }
2835
2836 if (file.vernauxs.empty())
2837 file.vernauxs.resize(file.verdefs.size());
2838
2839 // Select a version identifier for the vernaux data structure, if we haven't
2840 // already allocated one. The verdef identifiers cover the range
2841 // [1..getVerDefNum()]; this causes the vernaux identifiers to start from
2842 // getVerDefNum()+1.
2843 if (file.vernauxs[ss->verdefIndex] == 0)
2844 file.vernauxs[ss->verdefIndex] = ++SharedFile::vernauxNum + getVerDefNum();
2845
2846 ss->versionId = file.vernauxs[ss->verdefIndex];
2775}2847}
27762848
2777template <class ELFT>2849template <class ELFT>
2778VersionNeedSection<ELFT>::VersionNeedSection()2850VersionNeedSection<ELFT>::VersionNeedSection()
2779 : SyntheticSection(SHF_ALLOC, SHT_GNU_verneed, sizeof(uint32_t),2851 : SyntheticSection(SHF_ALLOC, SHT_GNU_verneed, sizeof(uint32_t),
2780 ".gnu.version_r") {2852 ".gnu.version_r") {}
2781 // Identifiers in verneed section start at 2 because 0 and 1 are reserved
2782 // for VER_NDX_LOCAL and VER_NDX_GLOBAL.
2783 // First identifiers are reserved by verdef section if it exist.
2784 NextIndex = getVerDefNum() + 1;
2785}
27862853
2787template <class ELFT> void VersionNeedSection<ELFT>::addSymbol(Symbol *SS) {2854template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
2788 auto &File = cast<SharedFile<ELFT>>(*SS->File);2855 for (SharedFile *f : sharedFiles) {
2789 if (SS->VerdefIndex == VER_NDX_GLOBAL) {2856 if (f->vernauxs.empty())
2790 SS->VersionId = VER_NDX_GLOBAL;2857 continue;
2791 return;2858 verneeds.emplace_back();
2859 Verneed &vn = verneeds.back();
2860 vn.nameStrTab = getPartition().dynStrTab->addString(f->soName);
2861 for (unsigned i = 0; i != f->vernauxs.size(); ++i) {
2862 if (f->vernauxs[i] == 0)
2863 continue;
2864 auto *verdef =
2865 reinterpret_cast<const typename ELFT::Verdef *>(f->verdefs[i]);
2866 vn.vernauxs.push_back(
2867 {verdef->vd_hash, f->vernauxs[i],
2868 getPartition().dynStrTab->addString(f->getStringTable().data() +
2869 verdef->getAux()->vda_name)});
2870 }
2792 }2871 }
27932872
2794 // If we don't already know that we need an Elf_Verneed for this DSO, prepare2873 if (OutputSection *sec = getPartition().dynStrTab->getParent())
2795 // to create one by adding it to our needed list and creating a dynstr entry2874 getParent()->link = sec->sectionIndex;
2796 // for the soname.2875 getParent()->info = verneeds.size();
2797 if (File.VerdefMap.empty())
2798 Needed.push_back({&File, In.DynStrTab->addString(File.SoName)});
2799 const typename ELFT::Verdef *Ver = File.Verdefs[SS->VerdefIndex];
2800 typename SharedFile<ELFT>::NeededVer &NV = File.VerdefMap[Ver];
2801
2802 // If we don't already know that we need an Elf_Vernaux for this Elf_Verdef,
2803 // prepare to create one by allocating a version identifier and creating a
2804 // dynstr entry for the version name.
2805 if (NV.Index == 0) {
2806 NV.StrTab = In.DynStrTab->addString(File.getStringTable().data() +
2807 Ver->getAux()->vda_name);
2808 NV.Index = NextIndex++;
2809 }
2810 SS->VersionId = NV.Index;
2811}2876}
28122877
2813template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *Buf) {2878template <class ELFT> void VersionNeedSection<ELFT>::writeTo(uint8_t *buf) {
2814 // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs.2879 // The Elf_Verneeds need to appear first, followed by the Elf_Vernauxs.
2815 auto *Verneed = reinterpret_cast<Elf_Verneed *>(Buf);2880 auto *verneed = reinterpret_cast<Elf_Verneed *>(buf);
2816 auto *Vernaux = reinterpret_cast<Elf_Vernaux *>(Verneed + Needed.size());2881 auto *vernaux = reinterpret_cast<Elf_Vernaux *>(verneed + verneeds.size());
28172882
2818 for (std::pair<SharedFile<ELFT> *, size_t> &P : Needed) {2883 for (auto &vn : verneeds) {
2819 // Create an Elf_Verneed for this DSO.2884 // Create an Elf_Verneed for this DSO.
2820 Verneed->vn_version = 1;2885 verneed->vn_version = 1;
2821 Verneed->vn_cnt = P.first->VerdefMap.size();2886 verneed->vn_cnt = vn.vernauxs.size();
2822 Verneed->vn_file = P.second;2887 verneed->vn_file = vn.nameStrTab;
2823 Verneed->vn_aux =2888 verneed->vn_aux =
2824 reinterpret_cast<char *>(Vernaux) - reinterpret_cast<char *>(Verneed);2889 reinterpret_cast<char *>(vernaux) - reinterpret_cast<char *>(verneed);
2825 Verneed->vn_next = sizeof(Elf_Verneed);2890 verneed->vn_next = sizeof(Elf_Verneed);
2826 ++Verneed;2891 ++verneed;
28272892
2828 // Create the Elf_Vernauxs for this Elf_Verneed. The loop iterates over2893 // Create the Elf_Vernauxs for this Elf_Verneed.
2829 // VerdefMap, which will only contain references to needed version2894 for (auto &vna : vn.vernauxs) {
2830 // definitions. Each Elf_Vernaux is based on the information contained in2895 vernaux->vna_hash = vna.hash;
2831 // the Elf_Verdef in the source DSO. This loop iterates over a std::map of2896 vernaux->vna_flags = 0;
2832 // pointers, but is deterministic because the pointers refer to Elf_Verdef2897 vernaux->vna_other = vna.verneedIndex;
2833 // data structures within a single input file.2898 vernaux->vna_name = vna.nameStrTab;
2834 for (auto &NV : P.first->VerdefMap) {2899 vernaux->vna_next = sizeof(Elf_Vernaux);
2835 Vernaux->vna_hash = NV.first->vd_hash;2900 ++vernaux;
2836 Vernaux->vna_flags = 0;
2837 Vernaux->vna_other = NV.second.Index;
2838 Vernaux->vna_name = NV.second.StrTab;
2839 Vernaux->vna_next = sizeof(Elf_Vernaux);
2840 ++Vernaux;
2841 }2901 }
28422902
2843 Vernaux[-1].vna_next = 0;2903 vernaux[-1].vna_next = 0;
2844 }2904 }
2845 Verneed[-1].vn_next = 0;2905 verneed[-1].vn_next = 0;
2846}
2847
2848template <class ELFT> void VersionNeedSection<ELFT>::finalizeContents() {
2849 if (OutputSection *Sec = In.DynStrTab->getParent())
2850 getParent()->Link = Sec->SectionIndex;
2851 getParent()->Info = Needed.size();
2852}2906}
28532907
2854template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const {2908template <class ELFT> size_t VersionNeedSection<ELFT>::getSize() const {
2855 unsigned Size = Needed.size() * sizeof(Elf_Verneed);2909 return verneeds.size() * sizeof(Elf_Verneed) +
2856 for (const std::pair<SharedFile<ELFT> *, size_t> &P : Needed)2910 SharedFile::vernauxNum * sizeof(Elf_Vernaux);
2857 Size += P.first->VerdefMap.size() * sizeof(Elf_Vernaux);
2858 return Size;
2859}2911}
28602912
2861template <class ELFT> bool VersionNeedSection<ELFT>::empty() const {2913template <class ELFT> bool VersionNeedSection<ELFT>::isNeeded() const {
2862 return getNeedNum() == 0;2914 return SharedFile::vernauxNum != 0;
2863}2915}
28642916
2865void MergeSyntheticSection::addSection(MergeInputSection *MS) {2917void MergeSyntheticSection::addSection(MergeInputSection *ms) {
2866 MS->Parent = this;2918 ms->parent = this;
2867 Sections.push_back(MS);2919 sections.push_back(ms);
2920 assert(alignment == ms->alignment || !(ms->flags & SHF_STRINGS));
2921 alignment = std::max(alignment, ms->alignment);
2868}2922}
28692923
2870MergeTailSection::MergeTailSection(StringRef Name, uint32_t Type,2924MergeTailSection::MergeTailSection(StringRef name, uint32_t type,
2871 uint64_t Flags, uint32_t Alignment)2925 uint64_t flags, uint32_t alignment)
2872 : MergeSyntheticSection(Name, Type, Flags, Alignment),2926 : MergeSyntheticSection(name, type, flags, alignment),
2873 Builder(StringTableBuilder::RAW, Alignment) {}2927 builder(StringTableBuilder::RAW, alignment) {}
28742928
2875size_t MergeTailSection::getSize() const { return Builder.getSize(); }2929size_t MergeTailSection::getSize() const { return builder.getSize(); }
28762930
2877void MergeTailSection::writeTo(uint8_t *Buf) { Builder.write(Buf); }2931void MergeTailSection::writeTo(uint8_t *buf) { builder.write(buf); }
28782932
2879void MergeTailSection::finalizeContents() {2933void MergeTailSection::finalizeContents() {
2880 // Add all string pieces to the string table builder to create section2934 // Add all string pieces to the string table builder to create section
2881 // contents.2935 // contents.
2882 for (MergeInputSection *Sec : Sections)2936 for (MergeInputSection *sec : sections)
2883 for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I)2937 for (size_t i = 0, e = sec->pieces.size(); i != e; ++i)
2884 if (Sec->Pieces[I].Live)2938 if (sec->pieces[i].live)
2885 Builder.add(Sec->getData(I));2939 builder.add(sec->getData(i));
28862940
2887 // Fix the string table content. After this, the contents will never change.2941 // Fix the string table content. After this, the contents will never change.
2888 Builder.finalize();2942 builder.finalize();
28892943
2890 // finalize() fixed tail-optimized strings, so we can now get2944 // finalize() fixed tail-optimized strings, so we can now get
2891 // offsets of strings. Get an offset for each string and save it2945 // offsets of strings. Get an offset for each string and save it
2892 // to a corresponding StringPiece for easy access.2946 // to a corresponding SectionPiece for easy access.
2893 for (MergeInputSection *Sec : Sections)2947 for (MergeInputSection *sec : sections)
2894 for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I)2948 for (size_t i = 0, e = sec->pieces.size(); i != e; ++i)
2895 if (Sec->Pieces[I].Live)2949 if (sec->pieces[i].live)
2896 Sec->Pieces[I].OutputOff = Builder.getOffset(Sec->getData(I));2950 sec->pieces[i].outputOff = builder.getOffset(sec->getData(i));
2897}2951}
28982952
2899void MergeNoTailSection::writeTo(uint8_t *Buf) {2953void MergeNoTailSection::writeTo(uint8_t *buf) {
2900 for (size_t I = 0; I < NumShards; ++I)2954 for (size_t i = 0; i < numShards; ++i)
2901 Shards[I].write(Buf + ShardOffsets[I]);2955 shards[i].write(buf + shardOffsets[i]);
2902}2956}
29032957
2904// This function is very hot (i.e. it can take several seconds to finish)2958// This function is very hot (i.e. it can take several seconds to finish)
...@@ -2911,66 +2965,68 @@ void MergeNoTailSection::writeTo(uint8_t *Buf) {...@@ -2911,66 +2965,68 @@ void MergeNoTailSection::writeTo(uint8_t *Buf) {
2911// We do it in parallel.2965// We do it in parallel.
2912void MergeNoTailSection::finalizeContents() {2966void MergeNoTailSection::finalizeContents() {
2913 // Initializes string table builders.2967 // Initializes string table builders.
2914 for (size_t I = 0; I < NumShards; ++I)2968 for (size_t i = 0; i < numShards; ++i)
2915 Shards.emplace_back(StringTableBuilder::RAW, Alignment);2969 shards.emplace_back(StringTableBuilder::RAW, alignment);
29162970
2917 // Concurrency level. Must be a power of 2 to avoid expensive modulo2971 // Concurrency level. Must be a power of 2 to avoid expensive modulo
2918 // operations in the following tight loop.2972 // operations in the following tight loop.
2919 size_t Concurrency = 1;2973 size_t concurrency = 1;
2920 if (ThreadsEnabled)2974 if (threadsEnabled)
2921 Concurrency =2975 concurrency =
2922 std::min<size_t>(PowerOf2Floor(hardware_concurrency()), NumShards);2976 std::min<size_t>(PowerOf2Floor(hardware_concurrency()), numShards);
29232977
2924 // Add section pieces to the builders.2978 // Add section pieces to the builders.
2925 parallelForEachN(0, Concurrency, [&](size_t ThreadId) {2979 parallelForEachN(0, concurrency, [&](size_t threadId) {
2926 for (MergeInputSection *Sec : Sections) {2980 for (MergeInputSection *sec : sections) {
2927 for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I) {2981 for (size_t i = 0, e = sec->pieces.size(); i != e; ++i) {
2928 size_t ShardId = getShardId(Sec->Pieces[I].Hash);2982 if (!sec->pieces[i].live)
2929 if ((ShardId & (Concurrency - 1)) == ThreadId && Sec->Pieces[I].Live)2983 continue;
2930 Sec->Pieces[I].OutputOff = Shards[ShardId].add(Sec->getData(I));2984 size_t shardId = getShardId(sec->pieces[i].hash);
2985 if ((shardId & (concurrency - 1)) == threadId)
2986 sec->pieces[i].outputOff = shards[shardId].add(sec->getData(i));
2931 }2987 }
2932 }2988 }
2933 });2989 });
29342990
2935 // Compute an in-section offset for each shard.2991 // Compute an in-section offset for each shard.
2936 size_t Off = 0;2992 size_t off = 0;
2937 for (size_t I = 0; I < NumShards; ++I) {2993 for (size_t i = 0; i < numShards; ++i) {
2938 Shards[I].finalizeInOrder();2994 shards[i].finalizeInOrder();
2939 if (Shards[I].getSize() > 0)2995 if (shards[i].getSize() > 0)
2940 Off = alignTo(Off, Alignment);2996 off = alignTo(off, alignment);
2941 ShardOffsets[I] = Off;2997 shardOffsets[i] = off;
2942 Off += Shards[I].getSize();2998 off += shards[i].getSize();
2943 }2999 }
2944 Size = Off;3000 size = off;
29453001
2946 // So far, section pieces have offsets from beginning of shards, but3002 // So far, section pieces have offsets from beginning of shards, but
2947 // we want offsets from beginning of the whole section. Fix them.3003 // we want offsets from beginning of the whole section. Fix them.
2948 parallelForEach(Sections, [&](MergeInputSection *Sec) {3004 parallelForEach(sections, [&](MergeInputSection *sec) {
2949 for (size_t I = 0, E = Sec->Pieces.size(); I != E; ++I)3005 for (size_t i = 0, e = sec->pieces.size(); i != e; ++i)
2950 if (Sec->Pieces[I].Live)3006 if (sec->pieces[i].live)
2951 Sec->Pieces[I].OutputOff +=3007 sec->pieces[i].outputOff +=
2952 ShardOffsets[getShardId(Sec->Pieces[I].Hash)];3008 shardOffsets[getShardId(sec->pieces[i].hash)];
2953 });3009 });
2954}3010}
29553011
2956static MergeSyntheticSection *createMergeSynthetic(StringRef Name,3012static MergeSyntheticSection *createMergeSynthetic(StringRef name,
2957 uint32_t Type,3013 uint32_t type,
2958 uint64_t Flags,3014 uint64_t flags,
2959 uint32_t Alignment) {3015 uint32_t alignment) {
2960 bool ShouldTailMerge = (Flags & SHF_STRINGS) && Config->Optimize >= 2;3016 bool shouldTailMerge = (flags & SHF_STRINGS) && config->optimize >= 2;
2961 if (ShouldTailMerge)3017 if (shouldTailMerge)
2962 return make<MergeTailSection>(Name, Type, Flags, Alignment);3018 return make<MergeTailSection>(name, type, flags, alignment);
2963 return make<MergeNoTailSection>(Name, Type, Flags, Alignment);3019 return make<MergeNoTailSection>(name, type, flags, alignment);
2964}3020}
29653021
2966template <class ELFT> void elf::splitSections() {3022template <class ELFT> void elf::splitSections() {
2967 // splitIntoPieces needs to be called on each MergeInputSection3023 // splitIntoPieces needs to be called on each MergeInputSection
2968 // before calling finalizeContents().3024 // before calling finalizeContents().
2969 parallelForEach(InputSections, [](InputSectionBase *Sec) {3025 parallelForEach(inputSections, [](InputSectionBase *sec) {
2970 if (auto *S = dyn_cast<MergeInputSection>(Sec))3026 if (auto *s = dyn_cast<MergeInputSection>(sec))
2971 S->splitIntoPieces();3027 s->splitIntoPieces();
2972 else if (auto *Eh = dyn_cast<EhInputSection>(Sec))3028 else if (auto *eh = dyn_cast<EhInputSection>(sec))
2973 Eh->split<ELFT>();3029 eh->split<ELFT>();
2974 });3030 });
2975}3031}
29763032
...@@ -2982,23 +3038,22 @@ template <class ELFT> void elf::splitSections() {...@@ -2982,23 +3038,22 @@ template <class ELFT> void elf::splitSections() {
2982// that it replaces. It then finalizes each synthetic section in order3038// that it replaces. It then finalizes each synthetic section in order
2983// to compute an output offset for each piece of each input section.3039// to compute an output offset for each piece of each input section.
2984void elf::mergeSections() {3040void elf::mergeSections() {
2985 std::vector<MergeSyntheticSection *> MergeSections;3041 std::vector<MergeSyntheticSection *> mergeSections;
2986 for (InputSectionBase *&S : InputSections) {3042 for (InputSectionBase *&s : inputSections) {
2987 MergeInputSection *MS = dyn_cast<MergeInputSection>(S);3043 MergeInputSection *ms = dyn_cast<MergeInputSection>(s);
2988 if (!MS)3044 if (!ms)
2989 continue;3045 continue;
29903046
2991 // We do not want to handle sections that are not alive, so just remove3047 // We do not want to handle sections that are not alive, so just remove
2992 // them instead of trying to merge.3048 // them instead of trying to merge.
2993 if (!MS->Live) {3049 if (!ms->isLive()) {
2994 S = nullptr;3050 s = nullptr;
2995 continue;3051 continue;
2996 }3052 }
29973053
2998 StringRef OutsecName = getOutputSectionName(MS);3054 StringRef outsecName = getOutputSectionName(ms);
2999 uint32_t Alignment = std::max<uint32_t>(MS->Alignment, MS->Entsize);
30003055
3001 auto I = llvm::find_if(MergeSections, [=](MergeSyntheticSection *Sec) {3056 auto i = llvm::find_if(mergeSections, [=](MergeSyntheticSection *sec) {
3002 // While we could create a single synthetic section for two different3057 // While we could create a single synthetic section for two different
3003 // values of Entsize, it is better to take Entsize into consideration.3058 // values of Entsize, it is better to take Entsize into consideration.
3004 //3059 //
...@@ -3007,98 +3062,285 @@ void elf::mergeSections() {...@@ -3007,98 +3062,285 @@ void elf::mergeSections() {
3007 //3062 //
3008 // Using Entsize in here also allows us to propagate it to the synthetic3063 // Using Entsize in here also allows us to propagate it to the synthetic
3009 // section.3064 // section.
3010 return Sec->Name == OutsecName && Sec->Flags == MS->Flags &&3065 //
3011 Sec->Entsize == MS->Entsize && Sec->Alignment == Alignment;3066 // SHF_STRINGS section with different alignments should not be merged.
3067 return sec->name == outsecName && sec->flags == ms->flags &&
3068 sec->entsize == ms->entsize &&
3069 (sec->alignment == ms->alignment || !(sec->flags & SHF_STRINGS));
3012 });3070 });
3013 if (I == MergeSections.end()) {3071 if (i == mergeSections.end()) {
3014 MergeSyntheticSection *Syn =3072 MergeSyntheticSection *syn =
3015 createMergeSynthetic(OutsecName, MS->Type, MS->Flags, Alignment);3073 createMergeSynthetic(outsecName, ms->type, ms->flags, ms->alignment);
3016 MergeSections.push_back(Syn);3074 mergeSections.push_back(syn);
3017 I = std::prev(MergeSections.end());3075 i = std::prev(mergeSections.end());
3018 S = Syn;3076 s = syn;
3019 Syn->Entsize = MS->Entsize;3077 syn->entsize = ms->entsize;
3020 } else {3078 } else {
3021 S = nullptr;3079 s = nullptr;
3022 }3080 }
3023 (*I)->addSection(MS);3081 (*i)->addSection(ms);
3024 }3082 }
3025 for (auto *MS : MergeSections)3083 for (auto *ms : mergeSections)
3026 MS->finalizeContents();3084 ms->finalizeContents();
30273085
3028 std::vector<InputSectionBase *> &V = InputSections;3086 std::vector<InputSectionBase *> &v = inputSections;
3029 V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());3087 v.erase(std::remove(v.begin(), v.end(), nullptr), v.end());
3030}3088}
30313089
3032MipsRldMapSection::MipsRldMapSection()3090MipsRldMapSection::MipsRldMapSection()
3033 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, Config->Wordsize,3091 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, config->wordsize,
3034 ".rld_map") {}3092 ".rld_map") {}
30353093
3036ARMExidxSentinelSection::ARMExidxSentinelSection()3094ARMExidxSyntheticSection::ARMExidxSyntheticSection()
3037 : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX,3095 : SyntheticSection(SHF_ALLOC | SHF_LINK_ORDER, SHT_ARM_EXIDX,
3038 Config->Wordsize, ".ARM.exidx") {}3096 config->wordsize, ".ARM.exidx") {}
30393097
3040// Write a terminating sentinel entry to the end of the .ARM.exidx table.3098static InputSection *findExidxSection(InputSection *isec) {
3041// This section will have been sorted last in the .ARM.exidx table.3099 for (InputSection *d : isec->dependentSections)
3042// This table entry will have the form:3100 if (d->type == SHT_ARM_EXIDX)
3043// | PREL31 upper bound of code that has exception tables | EXIDX_CANTUNWIND |3101 return d;
3044// The sentinel must have the PREL31 value of an address higher than any3102 return nullptr;
3045// address described by any other table entry.3103}
3046void ARMExidxSentinelSection::writeTo(uint8_t *Buf) {3104
3047 assert(Highest);3105bool ARMExidxSyntheticSection::addSection(InputSection *isec) {
3048 uint64_t S = Highest->getVA(Highest->getSize());3106 if (isec->type == SHT_ARM_EXIDX) {
3049 uint64_t P = getVA();3107 exidxSections.push_back(isec);
3050 Target->relocateOne(Buf, R_ARM_PREL31, S - P);3108 return true;
3051 write32le(Buf + 4, 1);3109 }
3052}3110
30533111 if ((isec->flags & SHF_ALLOC) && (isec->flags & SHF_EXECINSTR) &&
3054// The sentinel has to be removed if there are no other .ARM.exidx entries.3112 isec->getSize() > 0) {
3055bool ARMExidxSentinelSection::empty() const {3113 executableSections.push_back(isec);
3056 for (InputSection *IS : getInputSections(getParent()))3114 if (empty && findExidxSection(isec))
3057 if (!isa<ARMExidxSentinelSection>(IS))3115 empty = false;
3116 return false;
3117 }
3118
3119 // FIXME: we do not output a relocation section when --emit-relocs is used
3120 // as we do not have relocation sections for linker generated table entries
3121 // and we would have to erase at a late stage relocations from merged entries.
3122 // Given that exception tables are already position independent and a binary
3123 // analyzer could derive the relocations we choose to erase the relocations.
3124 if (config->emitRelocs && isec->type == SHT_REL)
3125 if (InputSectionBase *ex = isec->getRelocatedSection())
3126 if (isa<InputSection>(ex) && ex->type == SHT_ARM_EXIDX)
3127 return true;
3128
3129 return false;
3130}
3131
3132// References to .ARM.Extab Sections have bit 31 clear and are not the
3133// special EXIDX_CANTUNWIND bit-pattern.
3134static bool isExtabRef(uint32_t unwind) {
3135 return (unwind & 0x80000000) == 0 && unwind != 0x1;
3136}
3137
3138// Return true if the .ARM.exidx section Cur can be merged into the .ARM.exidx
3139// section Prev, where Cur follows Prev in the table. This can be done if the
3140// unwinding instructions in Cur are identical to Prev. Linker generated
3141// EXIDX_CANTUNWIND entries are represented by nullptr as they do not have an
3142// InputSection.
3143static bool isDuplicateArmExidxSec(InputSection *prev, InputSection *cur) {
3144
3145 struct ExidxEntry {
3146 ulittle32_t fn;
3147 ulittle32_t unwind;
3148 };
3149 // Get the last table Entry from the previous .ARM.exidx section. If Prev is
3150 // nullptr then it will be a synthesized EXIDX_CANTUNWIND entry.
3151 ExidxEntry prevEntry = {ulittle32_t(0), ulittle32_t(1)};
3152 if (prev)
3153 prevEntry = prev->getDataAs<ExidxEntry>().back();
3154 if (isExtabRef(prevEntry.unwind))
3155 return false;
3156
3157 // We consider the unwind instructions of an .ARM.exidx table entry
3158 // a duplicate if the previous unwind instructions if:
3159 // - Both are the special EXIDX_CANTUNWIND.
3160 // - Both are the same inline unwind instructions.
3161 // We do not attempt to follow and check links into .ARM.extab tables as
3162 // consecutive identical entries are rare and the effort to check that they
3163 // are identical is high.
3164
3165 // If Cur is nullptr then this is synthesized EXIDX_CANTUNWIND entry.
3166 if (cur == nullptr)
3167 return prevEntry.unwind == 1;
3168
3169 for (const ExidxEntry entry : cur->getDataAs<ExidxEntry>())
3170 if (isExtabRef(entry.unwind) || entry.unwind != prevEntry.unwind)
3058 return false;3171 return false;
3172
3173 // All table entries in this .ARM.exidx Section can be merged into the
3174 // previous Section.
3059 return true;3175 return true;
3060}3176}
30613177
3062bool ARMExidxSentinelSection::classof(const SectionBase *D) {3178// The .ARM.exidx table must be sorted in ascending order of the address of the
3063 return D->kind() == InputSectionBase::Synthetic && D->Type == SHT_ARM_EXIDX;3179// functions the table describes. Optionally duplicate adjacent table entries
3180// can be removed. At the end of the function the ExecutableSections must be
3181// sorted in ascending order of address, Sentinel is set to the InputSection
3182// with the highest address and any InputSections that have mergeable
3183// .ARM.exidx table entries are removed from it.
3184void ARMExidxSyntheticSection::finalizeContents() {
3185 // Sort the executable sections that may or may not have associated
3186 // .ARM.exidx sections by order of ascending address. This requires the
3187 // relative positions of InputSections to be known.
3188 auto compareByFilePosition = [](const InputSection *a,
3189 const InputSection *b) {
3190 OutputSection *aOut = a->getParent();
3191 OutputSection *bOut = b->getParent();
3192
3193 if (aOut != bOut)
3194 return aOut->sectionIndex < bOut->sectionIndex;
3195 return a->outSecOff < b->outSecOff;
3196 };
3197 llvm::stable_sort(executableSections, compareByFilePosition);
3198 sentinel = executableSections.back();
3199 // Optionally merge adjacent duplicate entries.
3200 if (config->mergeArmExidx) {
3201 std::vector<InputSection *> selectedSections;
3202 selectedSections.reserve(executableSections.size());
3203 selectedSections.push_back(executableSections[0]);
3204 size_t prev = 0;
3205 for (size_t i = 1; i < executableSections.size(); ++i) {
3206 InputSection *ex1 = findExidxSection(executableSections[prev]);
3207 InputSection *ex2 = findExidxSection(executableSections[i]);
3208 if (!isDuplicateArmExidxSec(ex1, ex2)) {
3209 selectedSections.push_back(executableSections[i]);
3210 prev = i;
3211 }
3212 }
3213 executableSections = std::move(selectedSections);
3214 }
3215
3216 size_t offset = 0;
3217 size = 0;
3218 for (InputSection *isec : executableSections) {
3219 if (InputSection *d = findExidxSection(isec)) {
3220 d->outSecOff = offset;
3221 d->parent = getParent();
3222 offset += d->getSize();
3223 } else {
3224 offset += 8;
3225 }
3226 }
3227 // Size includes Sentinel.
3228 size = offset + 8;
3229}
3230
3231InputSection *ARMExidxSyntheticSection::getLinkOrderDep() const {
3232 return executableSections.front();
3064}3233}
30653234
3066ThunkSection::ThunkSection(OutputSection *OS, uint64_t Off)3235// To write the .ARM.exidx table from the ExecutableSections we have three cases
3236// 1.) The InputSection has a .ARM.exidx InputSection in its dependent sections.
3237// We write the .ARM.exidx section contents and apply its relocations.
3238// 2.) The InputSection does not have a dependent .ARM.exidx InputSection. We
3239// must write the contents of an EXIDX_CANTUNWIND directly. We use the
3240// start of the InputSection as the purpose of the linker generated
3241// section is to terminate the address range of the previous entry.
3242// 3.) A trailing EXIDX_CANTUNWIND sentinel section is required at the end of
3243// the table to terminate the address range of the final entry.
3244void ARMExidxSyntheticSection::writeTo(uint8_t *buf) {
3245
3246 const uint8_t cantUnwindData[8] = {0, 0, 0, 0, // PREL31 to target
3247 1, 0, 0, 0}; // EXIDX_CANTUNWIND
3248
3249 uint64_t offset = 0;
3250 for (InputSection *isec : executableSections) {
3251 assert(isec->getParent() != nullptr);
3252 if (InputSection *d = findExidxSection(isec)) {
3253 memcpy(buf + offset, d->data().data(), d->data().size());
3254 d->relocateAlloc(buf, buf + d->getSize());
3255 offset += d->getSize();
3256 } else {
3257 // A Linker generated CANTUNWIND section.
3258 memcpy(buf + offset, cantUnwindData, sizeof(cantUnwindData));
3259 uint64_t s = isec->getVA();
3260 uint64_t p = getVA() + offset;
3261 target->relocateOne(buf + offset, R_ARM_PREL31, s - p);
3262 offset += 8;
3263 }
3264 }
3265 // Write Sentinel.
3266 memcpy(buf + offset, cantUnwindData, sizeof(cantUnwindData));
3267 uint64_t s = sentinel->getVA(sentinel->getSize());
3268 uint64_t p = getVA() + offset;
3269 target->relocateOne(buf + offset, R_ARM_PREL31, s - p);
3270 assert(size == offset + 8);
3271}
3272
3273bool ARMExidxSyntheticSection::classof(const SectionBase *d) {
3274 return d->kind() == InputSectionBase::Synthetic && d->type == SHT_ARM_EXIDX;
3275}
3276
3277ThunkSection::ThunkSection(OutputSection *os, uint64_t off)
3067 : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,3278 : SyntheticSection(SHF_ALLOC | SHF_EXECINSTR, SHT_PROGBITS,
3068 Config->Wordsize, ".text.thunk") {3279 config->wordsize, ".text.thunk") {
3069 this->Parent = OS;3280 this->parent = os;
3070 this->OutSecOff = Off;3281 this->outSecOff = off;
3071}3282}
30723283
3073void ThunkSection::addThunk(Thunk *T) {3284void ThunkSection::addThunk(Thunk *t) {
3074 Thunks.push_back(T);3285 thunks.push_back(t);
3075 T->addSymbols(*this);3286 t->addSymbols(*this);
3076}3287}
30773288
3078void ThunkSection::writeTo(uint8_t *Buf) {3289void ThunkSection::writeTo(uint8_t *buf) {
3079 for (Thunk *T : Thunks)3290 for (Thunk *t : thunks)
3080 T->writeTo(Buf + T->Offset);3291 t->writeTo(buf + t->offset);
3081}3292}
30823293
3083InputSection *ThunkSection::getTargetInputSection() const {3294InputSection *ThunkSection::getTargetInputSection() const {
3084 if (Thunks.empty())3295 if (thunks.empty())
3085 return nullptr;3296 return nullptr;
3086 const Thunk *T = Thunks.front();3297 const Thunk *t = thunks.front();
3087 return T->getTargetInputSection();3298 return t->getTargetInputSection();
3088}3299}
30893300
3090bool ThunkSection::assignOffsets() {3301bool ThunkSection::assignOffsets() {
3091 uint64_t Off = 0;3302 uint64_t off = 0;
3092 for (Thunk *T : Thunks) {3303 for (Thunk *t : thunks) {
3093 Off = alignTo(Off, T->Alignment);3304 off = alignTo(off, t->alignment);
3094 T->setOffset(Off);3305 t->setOffset(off);
3095 uint32_t Size = T->size();3306 uint32_t size = t->size();
3096 T->getThunkTargetSym()->Size = Size;3307 t->getThunkTargetSym()->size = size;
3097 Off += Size;3308 off += size;
3098 }3309 }
3099 bool Changed = Off != Size;3310 bool changed = off != size;
3100 Size = Off;3311 size = off;
3101 return Changed;3312 return changed;
3313}
3314
3315PPC32Got2Section::PPC32Got2Section()
3316 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 4, ".got2") {}
3317
3318bool PPC32Got2Section::isNeeded() const {
3319 // See the comment below. This is not needed if there is no other
3320 // InputSection.
3321 for (BaseCommand *base : getParent()->sectionCommands)
3322 if (auto *isd = dyn_cast<InputSectionDescription>(base))
3323 for (InputSection *isec : isd->sections)
3324 if (isec != this)
3325 return true;
3326 return false;
3327}
3328
3329void PPC32Got2Section::finalizeContents() {
3330 // PPC32 may create multiple GOT sections for -fPIC/-fPIE, one per file in
3331 // .got2 . This function computes outSecOff of each .got2 to be used in
3332 // PPC32PltCallStub::writeTo(). The purpose of this empty synthetic section is
3333 // to collect input sections named ".got2".
3334 uint32_t offset = 0;
3335 for (BaseCommand *base : getParent()->sectionCommands)
3336 if (auto *isd = dyn_cast<InputSectionDescription>(base)) {
3337 for (InputSection *isec : isd->sections) {
3338 if (isec == this)
3339 continue;
3340 isec->file->ppc32Got2OutSecOff = offset;
3341 offset += (uint32_t)isec->getSize();
3342 }
3343 }
3102}3344}
31033345
3104// If linking position-dependent code then the table will store the addresses3346// If linking position-dependent code then the table will store the addresses
...@@ -3107,48 +3349,188 @@ bool ThunkSection::assignOffsets() {...@@ -3107,48 +3349,188 @@ bool ThunkSection::assignOffsets() {
3107// allocated and filled in by the dynamic linker.3349// allocated and filled in by the dynamic linker.
3108PPC64LongBranchTargetSection::PPC64LongBranchTargetSection()3350PPC64LongBranchTargetSection::PPC64LongBranchTargetSection()
3109 : SyntheticSection(SHF_ALLOC | SHF_WRITE,3351 : SyntheticSection(SHF_ALLOC | SHF_WRITE,
3110 Config->Pic ? SHT_NOBITS : SHT_PROGBITS, 8,3352 config->isPic ? SHT_NOBITS : SHT_PROGBITS, 8,
3111 ".branch_lt") {}3353 ".branch_lt") {}
31123354
3113void PPC64LongBranchTargetSection::addEntry(Symbol &Sym) {3355void PPC64LongBranchTargetSection::addEntry(Symbol &sym) {
3114 assert(Sym.PPC64BranchltIndex == 0xffff);3356 assert(sym.ppc64BranchltIndex == 0xffff);
3115 Sym.PPC64BranchltIndex = Entries.size();3357 sym.ppc64BranchltIndex = entries.size();
3116 Entries.push_back(&Sym);3358 entries.push_back(&sym);
3117}3359}
31183360
3119size_t PPC64LongBranchTargetSection::getSize() const {3361size_t PPC64LongBranchTargetSection::getSize() const {
3120 return Entries.size() * 8;3362 return entries.size() * 8;
3121}3363}
31223364
3123void PPC64LongBranchTargetSection::writeTo(uint8_t *Buf) {3365void 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 get3366 // 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 allocate3367 // written to the table directly. For pic the dynamic linker will allocate
3127 // the section and fill it it.3368 // the section and fill it it.
3128 if (Config->Pic)3369 if (config->isPic)
3129 return;3370 return;
31303371
3131 for (const Symbol *Sym : Entries) {3372 for (const Symbol *sym : entries) {
3132 assert(Sym->getVA());3373 assert(sym->getVA());
3133 // Need calls to branch to the local entry-point since a long-branch3374 // Need calls to branch to the local entry-point since a long-branch
3134 // must be a local-call.3375 // must be a local-call.
3135 write64(Buf,3376 write64(buf,
3136 Sym->getVA() + getPPC64GlobalEntryToLocalEntryOffset(Sym->StOther));3377 sym->getVA() + getPPC64GlobalEntryToLocalEntryOffset(sym->stOther));
3137 Buf += Target->GotPltEntrySize;3378 buf += 8;
3138 }3379 }
3139}3380}
31403381
3141bool PPC64LongBranchTargetSection::empty() const {3382bool PPC64LongBranchTargetSection::isNeeded() const {
3142 // `removeUnusedSyntheticSections()` is called before thunk allocation which3383 // `removeUnusedSyntheticSections()` is called before thunk allocation which
3143 // is too early to determine if this section will be empty or not. We need3384 // 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. Finalized3385 // Finalized to keep the section alive until after thunk creation. Finalized
3145 // only gets set to true once `finalizeSections()` is called after thunk3386 // 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 end3387 // 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.3388 // up with an empty .branch_lt section in the binary.
3148 return Finalized && Entries.empty();3389 return !finalized || !entries.empty();
3149}3390}
31503391
3151InStruct elf::In;3392RISCVSdataSection::RISCVSdataSection()
3393 : SyntheticSection(SHF_ALLOC | SHF_WRITE, SHT_PROGBITS, 1, ".sdata") {}
3394
3395bool RISCVSdataSection::isNeeded() const {
3396 if (!ElfSym::riscvGlobalPointer)
3397 return false;
3398
3399 // __global_pointer$ is defined relative to .sdata . If the section does not
3400 // exist, create a dummy one.
3401 for (BaseCommand *base : getParent()->sectionCommands)
3402 if (auto *isd = dyn_cast<InputSectionDescription>(base))
3403 for (InputSection *isec : isd->sections)
3404 if (isec != this)
3405 return false;
3406 return true;
3407}
3408
3409static uint8_t getAbiVersion() {
3410 // MIPS non-PIC executable gets ABI version 1.
3411 if (config->emachine == EM_MIPS) {
3412 if (!config->isPic && !config->relocatable &&
3413 (config->eflags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
3414 return 1;
3415 return 0;
3416 }
3417
3418 if (config->emachine == EM_AMDGPU) {
3419 uint8_t ver = objectFiles[0]->abiVersion;
3420 for (InputFile *file : makeArrayRef(objectFiles).slice(1))
3421 if (file->abiVersion != ver)
3422 error("incompatible ABI version: " + toString(file));
3423 return ver;
3424 }
3425
3426 return 0;
3427}
3428
3429template <typename ELFT> void elf::writeEhdr(uint8_t *buf, Partition &part) {
3430 // For executable segments, the trap instructions are written before writing
3431 // the header. Setting Elf header bytes to zero ensures that any unused bytes
3432 // in header are zero-cleared, instead of having trap instructions.
3433 memset(buf, 0, sizeof(typename ELFT::Ehdr));
3434 memcpy(buf, "\177ELF", 4);
3435
3436 auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf);
3437 eHdr->e_ident[EI_CLASS] = config->is64 ? ELFCLASS64 : ELFCLASS32;
3438 eHdr->e_ident[EI_DATA] = config->isLE ? ELFDATA2LSB : ELFDATA2MSB;
3439 eHdr->e_ident[EI_VERSION] = EV_CURRENT;
3440 eHdr->e_ident[EI_OSABI] = config->osabi;
3441 eHdr->e_ident[EI_ABIVERSION] = getAbiVersion();
3442 eHdr->e_machine = config->emachine;
3443 eHdr->e_version = EV_CURRENT;
3444 eHdr->e_flags = config->eflags;
3445 eHdr->e_ehsize = sizeof(typename ELFT::Ehdr);
3446 eHdr->e_phnum = part.phdrs.size();
3447 eHdr->e_shentsize = sizeof(typename ELFT::Shdr);
3448
3449 if (!config->relocatable) {
3450 eHdr->e_phoff = sizeof(typename ELFT::Ehdr);
3451 eHdr->e_phentsize = sizeof(typename ELFT::Phdr);
3452 }
3453}
3454
3455template <typename ELFT> void elf::writePhdrs(uint8_t *buf, Partition &part) {
3456 // Write the program header table.
3457 auto *hBuf = reinterpret_cast<typename ELFT::Phdr *>(buf);
3458 for (PhdrEntry *p : part.phdrs) {
3459 hBuf->p_type = p->p_type;
3460 hBuf->p_flags = p->p_flags;
3461 hBuf->p_offset = p->p_offset;
3462 hBuf->p_vaddr = p->p_vaddr;
3463 hBuf->p_paddr = p->p_paddr;
3464 hBuf->p_filesz = p->p_filesz;
3465 hBuf->p_memsz = p->p_memsz;
3466 hBuf->p_align = p->p_align;
3467 ++hBuf;
3468 }
3469}
3470
3471template <typename ELFT>
3472PartitionElfHeaderSection<ELFT>::PartitionElfHeaderSection()
3473 : SyntheticSection(SHF_ALLOC, SHT_LLVM_PART_EHDR, 1, "") {}
3474
3475template <typename ELFT>
3476size_t PartitionElfHeaderSection<ELFT>::getSize() const {
3477 return sizeof(typename ELFT::Ehdr);
3478}
3479
3480template <typename ELFT>
3481void PartitionElfHeaderSection<ELFT>::writeTo(uint8_t *buf) {
3482 writeEhdr<ELFT>(buf, getPartition());
3483
3484 // Loadable partitions are always ET_DYN.
3485 auto *eHdr = reinterpret_cast<typename ELFT::Ehdr *>(buf);
3486 eHdr->e_type = ET_DYN;
3487}
3488
3489template <typename ELFT>
3490PartitionProgramHeadersSection<ELFT>::PartitionProgramHeadersSection()
3491 : SyntheticSection(SHF_ALLOC, SHT_LLVM_PART_PHDR, 1, ".phdrs") {}
3492
3493template <typename ELFT>
3494size_t PartitionProgramHeadersSection<ELFT>::getSize() const {
3495 return sizeof(typename ELFT::Phdr) * getPartition().phdrs.size();
3496}
3497
3498template <typename ELFT>
3499void PartitionProgramHeadersSection<ELFT>::writeTo(uint8_t *buf) {
3500 writePhdrs<ELFT>(buf, getPartition());
3501}
3502
3503PartitionIndexSection::PartitionIndexSection()
3504 : SyntheticSection(SHF_ALLOC, SHT_PROGBITS, 4, ".rodata") {}
3505
3506size_t PartitionIndexSection::getSize() const {
3507 return 12 * (partitions.size() - 1);
3508}
3509
3510void PartitionIndexSection::finalizeContents() {
3511 for (size_t i = 1; i != partitions.size(); ++i)
3512 partitions[i].nameStrTab = mainPart->dynStrTab->addString(partitions[i].name);
3513}
3514
3515void PartitionIndexSection::writeTo(uint8_t *buf) {
3516 uint64_t va = getVA();
3517 for (size_t i = 1; i != partitions.size(); ++i) {
3518 write32(buf, mainPart->dynStrTab->getVA() + partitions[i].nameStrTab - va);
3519 write32(buf + 4, partitions[i].elfHeader->getVA() - (va + 4));
3520
3521 SyntheticSection *next =
3522 i == partitions.size() - 1 ? in.partEnd : partitions[i + 1].elfHeader;
3523 write32(buf + 8, next->getVA() - partitions[i].elfHeader->getVA());
3524
3525 va += 12;
3526 buf += 12;
3527 }
3528}
3529
3530InStruct elf::in;
3531
3532std::vector<Partition> elf::partitions;
3533Partition *elf::mainPart;
31523534
3153template GdbIndexSection *GdbIndexSection::create<ELF32LE>();3535template GdbIndexSection *GdbIndexSection::create<ELF32LE>();
3154template GdbIndexSection *GdbIndexSection::create<ELF32BE>();3536template GdbIndexSection *GdbIndexSection::create<ELF32BE>();
...@@ -3170,11 +3552,6 @@ template void PltSection::addEntry<ELF32BE>(Symbol &Sym);...@@ -3170,11 +3552,6 @@ template void PltSection::addEntry<ELF32BE>(Symbol &Sym);
3170template void PltSection::addEntry<ELF64LE>(Symbol &Sym);3552template void PltSection::addEntry<ELF64LE>(Symbol &Sym);
3171template void PltSection::addEntry<ELF64BE>(Symbol &Sym);3553template void PltSection::addEntry<ELF64BE>(Symbol &Sym);
31723554
3173template void MipsGotSection::build<ELF32LE>();
3174template void MipsGotSection::build<ELF32BE>();
3175template void MipsGotSection::build<ELF64LE>();
3176template void MipsGotSection::build<ELF64BE>();
3177
3178template class elf::MipsAbiFlagsSection<ELF32LE>;3555template class elf::MipsAbiFlagsSection<ELF32LE>;
3179template class elf::MipsAbiFlagsSection<ELF32BE>;3556template class elf::MipsAbiFlagsSection<ELF32BE>;
3180template class elf::MipsAbiFlagsSection<ELF64LE>;3557template class elf::MipsAbiFlagsSection<ELF64LE>;
...@@ -3215,12 +3592,27 @@ template class elf::SymbolTableSection<ELF32BE>;...@@ -3215,12 +3592,27 @@ template class elf::SymbolTableSection<ELF32BE>;
3215template class elf::SymbolTableSection<ELF64LE>;3592template class elf::SymbolTableSection<ELF64LE>;
3216template class elf::SymbolTableSection<ELF64BE>;3593template class elf::SymbolTableSection<ELF64BE>;
32173594
3218template class elf::VersionTableSection<ELF32LE>;
3219template class elf::VersionTableSection<ELF32BE>;
3220template class elf::VersionTableSection<ELF64LE>;
3221template class elf::VersionTableSection<ELF64BE>;
3222
3223template class elf::VersionNeedSection<ELF32LE>;3595template class elf::VersionNeedSection<ELF32LE>;
3224template class elf::VersionNeedSection<ELF32BE>;3596template class elf::VersionNeedSection<ELF32BE>;
3225template class elf::VersionNeedSection<ELF64LE>;3597template class elf::VersionNeedSection<ELF64LE>;
3226template class elf::VersionNeedSection<ELF64BE>;3598template class elf::VersionNeedSection<ELF64BE>;
3599
3600template void elf::writeEhdr<ELF32LE>(uint8_t *Buf, Partition &Part);
3601template void elf::writeEhdr<ELF32BE>(uint8_t *Buf, Partition &Part);
3602template void elf::writeEhdr<ELF64LE>(uint8_t *Buf, Partition &Part);
3603template void elf::writeEhdr<ELF64BE>(uint8_t *Buf, Partition &Part);
3604
3605template void elf::writePhdrs<ELF32LE>(uint8_t *Buf, Partition &Part);
3606template void elf::writePhdrs<ELF32BE>(uint8_t *Buf, Partition &Part);
3607template void elf::writePhdrs<ELF64LE>(uint8_t *Buf, Partition &Part);
3608template void elf::writePhdrs<ELF64BE>(uint8_t *Buf, Partition &Part);
3609
3610template class elf::PartitionElfHeaderSection<ELF32LE>;
3611template class elf::PartitionElfHeaderSection<ELF32BE>;
3612template class elf::PartitionElfHeaderSection<ELF64LE>;
3613template class elf::PartitionElfHeaderSection<ELF64BE>;
3614
3615template class elf::PartitionProgramHeadersSection<ELF32LE>;
3616template class elf::PartitionProgramHeadersSection<ELF32BE>;
3617template class elf::PartitionProgramHeadersSection<ELF64LE>;
3618template class elf::PartitionProgramHeadersSection<ELF64BE>;
deps/lld/ELF/SyntheticSections.h+519-374
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- SyntheticSection.h ---------------------------------------*- C++ -*-===//1//===- SyntheticSection.h ---------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -18,8 +17,8 @@...@@ -18,8 +17,8 @@
18//17//
19//===----------------------------------------------------------------------===//18//===----------------------------------------------------------------------===//
2019
21#ifndef LLD_ELF_SYNTHETIC_SECTION_H20#ifndef LLD_ELF_SYNTHETIC_SECTIONS_H
22#define LLD_ELF_SYNTHETIC_SECTION_H21#define LLD_ELF_SYNTHETIC_SECTIONS_H
2322
24#include "DWARF.h"23#include "DWARF.h"
25#include "EhFrame.h"24#include "EhFrame.h"
...@@ -32,107 +31,113 @@...@@ -32,107 +31,113 @@
32namespace lld {31namespace lld {
33namespace elf {32namespace elf {
34class Defined;33class Defined;
35class SharedSymbol;34struct PhdrEntry;
35class SymbolTableBaseSection;
36class VersionNeedBaseSection;
3637
37class SyntheticSection : public InputSection {38class SyntheticSection : public InputSection {
38public:39public:
39 SyntheticSection(uint64_t Flags, uint32_t Type, uint32_t Alignment,40 SyntheticSection(uint64_t flags, uint32_t type, uint32_t alignment,
40 StringRef Name)41 StringRef name)
41 : InputSection(nullptr, Flags, Type, Alignment, {}, Name,42 : InputSection(nullptr, flags, type, alignment, {}, name,
42 InputSectionBase::Synthetic) {43 InputSectionBase::Synthetic) {
43 this->Live = true;44 markLive();
44 }45 }
4546
46 virtual ~SyntheticSection() = default;47 virtual ~SyntheticSection() = default;
47 virtual void writeTo(uint8_t *Buf) = 0;48 virtual void writeTo(uint8_t *buf) = 0;
48 virtual size_t getSize() const = 0;49 virtual size_t getSize() const = 0;
49 virtual void finalizeContents() {}50 virtual void finalizeContents() {}
50 // If the section has the SHF_ALLOC flag and the size may be changed if51 // If the section has the SHF_ALLOC flag and the size may be changed if
51 // thunks are added, update the section size.52 // thunks are added, update the section size.
52 virtual bool updateAllocSize() { return false; }53 virtual bool updateAllocSize() { return false; }
53 virtual bool empty() const { return false; }54 virtual bool isNeeded() const { return true; }
5455
55 static bool classof(const SectionBase *D) {56 static bool classof(const SectionBase *d) {
56 return D->kind() == InputSectionBase::Synthetic;57 return d->kind() == InputSectionBase::Synthetic;
57 }58 }
58};59};
5960
60struct CieRecord {61struct CieRecord {
61 EhSectionPiece *Cie = nullptr;62 EhSectionPiece *cie = nullptr;
62 std::vector<EhSectionPiece *> Fdes;63 std::vector<EhSectionPiece *> fdes;
63};64};
6465
65// Section for .eh_frame.66// Section for .eh_frame.
66class EhFrameSection final : public SyntheticSection {67class EhFrameSection final : public SyntheticSection {
67public:68public:
68 EhFrameSection();69 EhFrameSection();
69 void writeTo(uint8_t *Buf) override;70 void writeTo(uint8_t *buf) override;
70 void finalizeContents() override;71 void finalizeContents() override;
71 bool empty() const override { return Sections.empty(); }72 bool isNeeded() const override { return !sections.empty(); }
72 size_t getSize() const override { return Size; }73 size_t getSize() const override { return size; }
74
75 static bool classof(const SectionBase *d) {
76 return SyntheticSection::classof(d) && d->name == ".eh_frame";
77 }
7378
74 template <class ELFT> void addSection(InputSectionBase *S);79 template <class ELFT> void addSection(InputSectionBase *s);
7580
76 std::vector<EhInputSection *> Sections;81 std::vector<EhInputSection *> sections;
77 size_t NumFdes = 0;82 size_t numFdes = 0;
7883
79 struct FdeData {84 struct FdeData {
80 uint32_t PcRel;85 uint32_t pcRel;
81 uint32_t FdeVARel;86 uint32_t fdeVARel;
82 };87 };
8388
84 std::vector<FdeData> getFdeData() const;89 std::vector<FdeData> getFdeData() const;
85 ArrayRef<CieRecord *> getCieRecords() const { return CieRecords; }90 ArrayRef<CieRecord *> getCieRecords() const { return cieRecords; }
8691
87private:92private:
88 // This is used only when parsing EhInputSection. We keep it here to avoid93 // This is used only when parsing EhInputSection. We keep it here to avoid
89 // allocating one for each EhInputSection.94 // allocating one for each EhInputSection.
90 llvm::DenseMap<size_t, CieRecord *> OffsetToCie;95 llvm::DenseMap<size_t, CieRecord *> offsetToCie;
9196
92 uint64_t Size = 0;97 uint64_t size = 0;
9398
94 template <class ELFT, class RelTy>99 template <class ELFT, class RelTy>
95 void addSectionAux(EhInputSection *S, llvm::ArrayRef<RelTy> Rels);100 void addSectionAux(EhInputSection *s, llvm::ArrayRef<RelTy> rels);
96101
97 template <class ELFT, class RelTy>102 template <class ELFT, class RelTy>
98 CieRecord *addCie(EhSectionPiece &Piece, ArrayRef<RelTy> Rels);103 CieRecord *addCie(EhSectionPiece &piece, ArrayRef<RelTy> rels);
99104
100 template <class ELFT, class RelTy>105 template <class ELFT, class RelTy>
101 bool isFdeLive(EhSectionPiece &Piece, ArrayRef<RelTy> Rels);106 bool isFdeLive(EhSectionPiece &piece, ArrayRef<RelTy> rels);
102107
103 uint64_t getFdePc(uint8_t *Buf, size_t Off, uint8_t Enc) const;108 uint64_t getFdePc(uint8_t *buf, size_t off, uint8_t enc) const;
104109
105 std::vector<CieRecord *> CieRecords;110 std::vector<CieRecord *> cieRecords;
106111
107 // CIE records are uniquified by their contents and personality functions.112 // CIE records are uniquified by their contents and personality functions.
108 llvm::DenseMap<std::pair<ArrayRef<uint8_t>, Symbol *>, CieRecord *> CieMap;113 llvm::DenseMap<std::pair<ArrayRef<uint8_t>, Symbol *>, CieRecord *> cieMap;
109};114};
110115
111class GotSection : public SyntheticSection {116class GotSection : public SyntheticSection {
112public:117public:
113 GotSection();118 GotSection();
114 size_t getSize() const override { return Size; }119 size_t getSize() const override { return size; }
115 void finalizeContents() override;120 void finalizeContents() override;
116 bool empty() const override;121 bool isNeeded() const override;
117 void writeTo(uint8_t *Buf) override;122 void writeTo(uint8_t *buf) override;
118123
119 void addEntry(Symbol &Sym);124 void addEntry(Symbol &sym);
120 bool addDynTlsEntry(Symbol &Sym);125 bool addDynTlsEntry(Symbol &sym);
121 bool addTlsIndex();126 bool addTlsIndex();
122 uint64_t getGlobalDynAddr(const Symbol &B) const;127 uint64_t getGlobalDynAddr(const Symbol &b) const;
123 uint64_t getGlobalDynOffset(const Symbol &B) const;128 uint64_t getGlobalDynOffset(const Symbol &b) const;
124129
125 uint64_t getTlsIndexVA() { return this->getVA() + TlsIndexOff; }130 uint64_t getTlsIndexVA() { return this->getVA() + tlsIndexOff; }
126 uint32_t getTlsIndexOff() const { return TlsIndexOff; }131 uint32_t getTlsIndexOff() const { return tlsIndexOff; }
127132
128 // Flag to force GOT to be in output if we have relocations133 // Flag to force GOT to be in output if we have relocations
129 // that relies on its address.134 // that relies on its address.
130 bool HasGotOffRel = false;135 bool hasGotOffRel = false;
131136
132protected:137protected:
133 size_t NumEntries = 0;138 size_t numEntries = 0;
134 uint32_t TlsIndexOff = -1;139 uint32_t tlsIndexOff = -1;
135 uint64_t Size = 0;140 uint64_t size = 0;
136};141};
137142
138// .note.GNU-stack section.143// .note.GNU-stack section.
...@@ -140,27 +145,31 @@ class GnuStackSection : public SyntheticSection {...@@ -140,27 +145,31 @@ class GnuStackSection : public SyntheticSection {
140public:145public:
141 GnuStackSection()146 GnuStackSection()
142 : SyntheticSection(0, llvm::ELF::SHT_PROGBITS, 1, ".note.GNU-stack") {}147 : SyntheticSection(0, llvm::ELF::SHT_PROGBITS, 1, ".note.GNU-stack") {}
143 void writeTo(uint8_t *Buf) override {}148 void writeTo(uint8_t *buf) override {}
144 size_t getSize() const override { return 0; }149 size_t getSize() const override { return 0; }
145};150};
146151
152class GnuPropertySection : public SyntheticSection {
153public:
154 GnuPropertySection();
155 void writeTo(uint8_t *buf) override;
156 size_t getSize() const override;
157};
158
147// .note.gnu.build-id section.159// .note.gnu.build-id section.
148class BuildIdSection : public SyntheticSection {160class BuildIdSection : public SyntheticSection {
149 // First 16 bytes are a header.161 // First 16 bytes are a header.
150 static const unsigned HeaderSize = 16;162 static const unsigned headerSize = 16;
151163
152public:164public:
165 const size_t hashSize;
153 BuildIdSection();166 BuildIdSection();
154 void writeTo(uint8_t *Buf) override;167 void writeTo(uint8_t *buf) override;
155 size_t getSize() const override { return HeaderSize + HashSize; }168 size_t getSize() const override { return headerSize + hashSize; }
156 void writeBuildId(llvm::ArrayRef<uint8_t> Buf);169 void writeBuildId(llvm::ArrayRef<uint8_t> buf);
157170
158private:171private:
159 void computeHash(llvm::ArrayRef<uint8_t> Buf,172 uint8_t *hashBuf;
160 std::function<void(uint8_t *, ArrayRef<uint8_t>)> Hash);
161
162 size_t HashSize;
163 uint8_t *HashBuf;
164};173};
165174
166// BssSection is used to reserve space for copy relocations and common symbols.175// BssSection is used to reserve space for copy relocations and common symbols.
...@@ -169,40 +178,40 @@ private:...@@ -169,40 +178,40 @@ private:
169// respectively.178// respectively.
170class BssSection final : public SyntheticSection {179class BssSection final : public SyntheticSection {
171public:180public:
172 BssSection(StringRef Name, uint64_t Size, uint32_t Alignment);181 BssSection(StringRef name, uint64_t size, uint32_t alignment);
173 void writeTo(uint8_t *) override {182 void writeTo(uint8_t *) override {
174 llvm_unreachable("unexpected writeTo() call for SHT_NOBITS section");183 llvm_unreachable("unexpected writeTo() call for SHT_NOBITS section");
175 }184 }
176 bool empty() const override { return getSize() == 0; }185 bool isNeeded() const override { return size != 0; }
177 size_t getSize() const override { return Size; }186 size_t getSize() const override { return size; }
178187
179 static bool classof(const SectionBase *S) { return S->Bss; }188 static bool classof(const SectionBase *s) { return s->bss; }
180 uint64_t Size;189 uint64_t size;
181};190};
182191
183class MipsGotSection final : public SyntheticSection {192class MipsGotSection final : public SyntheticSection {
184public:193public:
185 MipsGotSection();194 MipsGotSection();
186 void writeTo(uint8_t *Buf) override;195 void writeTo(uint8_t *buf) override;
187 size_t getSize() const override { return Size; }196 size_t getSize() const override { return size; }
188 bool updateAllocSize() override;197 bool updateAllocSize() override;
189 void finalizeContents() override;198 void finalizeContents() override;
190 bool empty() const override;199 bool isNeeded() const override;
191200
192 // Join separate GOTs built for each input file to generate201 // Join separate GOTs built for each input file to generate
193 // primary and optional multiple secondary GOTs.202 // primary and optional multiple secondary GOTs.
194 template <class ELFT> void build();203 void build();
195204
196 void addEntry(InputFile &File, Symbol &Sym, int64_t Addend, RelExpr Expr);205 void addEntry(InputFile &file, Symbol &sym, int64_t addend, RelExpr expr);
197 void addDynTlsEntry(InputFile &File, Symbol &Sym);206 void addDynTlsEntry(InputFile &file, Symbol &sym);
198 void addTlsIndex(InputFile &File);207 void addTlsIndex(InputFile &file);
199208
200 uint64_t getPageEntryOffset(const InputFile *F, const Symbol &S,209 uint64_t getPageEntryOffset(const InputFile *f, const Symbol &s,
201 int64_t Addend) const;210 int64_t addend) const;
202 uint64_t getSymEntryOffset(const InputFile *F, const Symbol &S,211 uint64_t getSymEntryOffset(const InputFile *f, const Symbol &s,
203 int64_t Addend) const;212 int64_t addend) const;
204 uint64_t getGlobalDynOffset(const InputFile *F, const Symbol &S) const;213 uint64_t getGlobalDynOffset(const InputFile *f, const Symbol &s) const;
205 uint64_t getTlsIndexOffset(const InputFile *F) const;214 uint64_t getTlsIndexOffset(const InputFile *f) const;
206215
207 // Returns the symbol which corresponds to the first entry of the global part216 // Returns the symbol which corresponds to the first entry of the global part
208 // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic217 // of GOT on MIPS platform. It is required to fill up MIPS-specific dynamic
...@@ -215,7 +224,7 @@ public:...@@ -215,7 +224,7 @@ public:
215 unsigned getLocalEntriesNum() const;224 unsigned getLocalEntriesNum() const;
216225
217 // Return _gp value for primary GOT (nullptr) or particular input file.226 // Return _gp value for primary GOT (nullptr) or particular input file.
218 uint64_t getGp(const InputFile *F = nullptr) const;227 uint64_t getGp(const InputFile *f = nullptr) const;
219228
220private:229private:
221 // MIPS GOT consists of three parts: local, global and tls. Each part230 // MIPS GOT consists of three parts: local, global and tls. Each part
...@@ -305,34 +314,35 @@ private:...@@ -305,34 +314,35 @@ private:
305 // https://dmz-portal.mips.com/wiki/MIPS_Multi_GOT314 // https://dmz-portal.mips.com/wiki/MIPS_Multi_GOT
306315
307 // Number of "Header" entries.316 // Number of "Header" entries.
308 static const unsigned HeaderEntriesNum = 2;317 static const unsigned headerEntriesNum = 2;
309318
310 uint64_t Size = 0;319 uint64_t size = 0;
311320
312 // Symbol and addend.321 // Symbol and addend.
313 typedef std::pair<Symbol *, int64_t> GotEntry;322 using GotEntry = std::pair<Symbol *, int64_t>;
314323
315 struct FileGot {324 struct FileGot {
316 InputFile *File = nullptr;325 InputFile *file = nullptr;
317 size_t StartIndex = 0;326 size_t startIndex = 0;
318327
319 struct PageBlock {328 struct PageBlock {
320 size_t FirstIndex = 0;329 size_t firstIndex;
321 size_t Count = 0;330 size_t count;
331 PageBlock() : firstIndex(0), count(0) {}
322 };332 };
323333
324 // Map output sections referenced by MIPS GOT relocations334 // Map output sections referenced by MIPS GOT relocations
325 // to the description (index/count) "page" entries allocated335 // to the description (index/count) "page" entries allocated
326 // for this section.336 // for this section.
327 llvm::SmallMapVector<const OutputSection *, PageBlock, 16> PagesMap;337 llvm::SmallMapVector<const OutputSection *, PageBlock, 16> pagesMap;
328 // Maps from Symbol+Addend pair or just Symbol to the GOT entry index.338 // Maps from Symbol+Addend pair or just Symbol to the GOT entry index.
329 llvm::MapVector<GotEntry, size_t> Local16;339 llvm::MapVector<GotEntry, size_t> local16;
330 llvm::MapVector<GotEntry, size_t> Local32;340 llvm::MapVector<GotEntry, size_t> local32;
331 llvm::MapVector<Symbol *, size_t> Global;341 llvm::MapVector<Symbol *, size_t> global;
332 llvm::MapVector<Symbol *, size_t> Relocs;342 llvm::MapVector<Symbol *, size_t> relocs;
333 llvm::MapVector<Symbol *, size_t> Tls;343 llvm::MapVector<Symbol *, size_t> tls;
334 // Set of symbols referenced by dynamic TLS relocations.344 // Set of symbols referenced by dynamic TLS relocations.
335 llvm::MapVector<Symbol *, size_t> DynTlsSymbols;345 llvm::MapVector<Symbol *, size_t> dynTlsSymbols;
336346
337 // Total number of all entries.347 // Total number of all entries.
338 size_t getEntriesNum() const;348 size_t getEntriesNum() const;
...@@ -345,27 +355,31 @@ private:...@@ -345,27 +355,31 @@ private:
345 // Container of GOT created for each input file.355 // Container of GOT created for each input file.
346 // After building a final series of GOTs this container356 // After building a final series of GOTs this container
347 // holds primary and secondary GOT's.357 // holds primary and secondary GOT's.
348 std::vector<FileGot> Gots;358 std::vector<FileGot> gots;
349359
350 // Return (and create if necessary) `FileGot`.360 // Return (and create if necessary) `FileGot`.
351 FileGot &getGot(InputFile &F);361 FileGot &getGot(InputFile &f);
352362
353 // Try to merge two GOTs. In case of success the `Dst` contains363 // Try to merge two GOTs. In case of success the `Dst` contains
354 // result of merging and the function returns true. In case of364 // result of merging and the function returns true. In case of
355 // ovwerflow the `Dst` is unchanged and the function returns false.365 // ovwerflow the `Dst` is unchanged and the function returns false.
356 bool tryMergeGots(FileGot & Dst, FileGot & Src, bool IsPrimary);366 bool tryMergeGots(FileGot & dst, FileGot & src, bool isPrimary);
357};367};
358368
359class GotPltSection final : public SyntheticSection {369class GotPltSection final : public SyntheticSection {
360public:370public:
361 GotPltSection();371 GotPltSection();
362 void addEntry(Symbol &Sym);372 void addEntry(Symbol &sym);
363 size_t getSize() const override;373 size_t getSize() const override;
364 void writeTo(uint8_t *Buf) override;374 void writeTo(uint8_t *buf) override;
365 bool empty() const override;375 bool isNeeded() const override;
376
377 // Flag to force GotPlt to be in output if we have relocations
378 // that relies on its address.
379 bool hasGotPltOffRel = false;
366380
367private:381private:
368 std::vector<const Symbol *> Entries;382 std::vector<const Symbol *> entries;
369};383};
370384
371// The IgotPltSection is a Got associated with the PltSection for GNU Ifunc385// The IgotPltSection is a Got associated with the PltSection for GNU Ifunc
...@@ -375,167 +389,164 @@ private:...@@ -375,167 +389,164 @@ private:
375class IgotPltSection final : public SyntheticSection {389class IgotPltSection final : public SyntheticSection {
376public:390public:
377 IgotPltSection();391 IgotPltSection();
378 void addEntry(Symbol &Sym);392 void addEntry(Symbol &sym);
379 size_t getSize() const override;393 size_t getSize() const override;
380 void writeTo(uint8_t *Buf) override;394 void writeTo(uint8_t *buf) override;
381 bool empty() const override { return Entries.empty(); }395 bool isNeeded() const override { return !entries.empty(); }
382396
383private:397private:
384 std::vector<const Symbol *> Entries;398 std::vector<const Symbol *> entries;
385};399};
386400
387class StringTableSection final : public SyntheticSection {401class StringTableSection final : public SyntheticSection {
388public:402public:
389 StringTableSection(StringRef Name, bool Dynamic);403 StringTableSection(StringRef name, bool dynamic);
390 unsigned addString(StringRef S, bool HashIt = true);404 unsigned addString(StringRef s, bool hashIt = true);
391 void writeTo(uint8_t *Buf) override;405 void writeTo(uint8_t *buf) override;
392 size_t getSize() const override { return Size; }406 size_t getSize() const override { return size; }
393 bool isDynamic() const { return Dynamic; }407 bool isDynamic() const { return dynamic; }
394408
395private:409private:
396 const bool Dynamic;410 const bool dynamic;
397411
398 uint64_t Size = 0;412 uint64_t size = 0;
399413
400 llvm::DenseMap<StringRef, unsigned> StringMap;414 llvm::DenseMap<StringRef, unsigned> stringMap;
401 std::vector<StringRef> Strings;415 std::vector<StringRef> strings;
402};416};
403417
404class DynamicReloc {418class DynamicReloc {
405public:419public:
406 DynamicReloc(RelType Type, const InputSectionBase *InputSec,420 DynamicReloc(RelType type, const InputSectionBase *inputSec,
407 uint64_t OffsetInSec, bool UseSymVA, Symbol *Sym, int64_t Addend)421 uint64_t offsetInSec, bool useSymVA, Symbol *sym, int64_t addend)
408 : Type(Type), Sym(Sym), InputSec(InputSec), OffsetInSec(OffsetInSec),422 : type(type), sym(sym), inputSec(inputSec), offsetInSec(offsetInSec),
409 UseSymVA(UseSymVA), Addend(Addend), OutputSec(nullptr) {}423 useSymVA(useSymVA), addend(addend), outputSec(nullptr) {}
410 // This constructor records dynamic relocation settings used by MIPS424 // This constructor records dynamic relocation settings used by MIPS
411 // multi-GOT implementation. It's to relocate addresses of 64kb pages425 // multi-GOT implementation. It's to relocate addresses of 64kb pages
412 // lie inside the output section.426 // lie inside the output section.
413 DynamicReloc(RelType Type, const InputSectionBase *InputSec,427 DynamicReloc(RelType type, const InputSectionBase *inputSec,
414 uint64_t OffsetInSec, const OutputSection *OutputSec,428 uint64_t offsetInSec, const OutputSection *outputSec,
415 int64_t Addend)429 int64_t addend)
416 : Type(Type), Sym(nullptr), InputSec(InputSec), OffsetInSec(OffsetInSec),430 : type(type), sym(nullptr), inputSec(inputSec), offsetInSec(offsetInSec),
417 UseSymVA(false), Addend(Addend), OutputSec(OutputSec) {}431 useSymVA(false), addend(addend), outputSec(outputSec) {}
418432
419 uint64_t getOffset() const;433 uint64_t getOffset() const;
420 uint32_t getSymIndex() const;434 uint32_t getSymIndex(SymbolTableBaseSection *symTab) const;
421 const InputSectionBase *getInputSec() const { return InputSec; }
422435
423 // Computes the addend of the dynamic relocation. Note that this is not the436 // Computes the addend of the dynamic relocation. Note that this is not the
424 // same as the Addend member variable as it also includes the symbol address437 // same as the addend member variable as it also includes the symbol address
425 // if UseSymVA is true.438 // if useSymVA is true.
426 int64_t computeAddend() const;439 int64_t computeAddend() const;
427440
428 RelType Type;441 RelType type;
429442
430private:443 Symbol *sym;
431 Symbol *Sym;444 const InputSectionBase *inputSec = nullptr;
432 const InputSectionBase *InputSec = nullptr;445 uint64_t offsetInSec;
433 uint64_t OffsetInSec;
434 // If this member is true, the dynamic relocation will not be against the446 // If this member is true, the dynamic relocation will not be against the
435 // symbol but will instead be a relative relocation that simply adds the447 // symbol but will instead be a relative relocation that simply adds the
436 // load address. This means we need to write the symbol virtual address448 // load address. This means we need to write the symbol virtual address
437 // plus the original addend as the final relocation addend.449 // plus the original addend as the final relocation addend.
438 bool UseSymVA;450 bool useSymVA;
439 int64_t Addend;451 int64_t addend;
440 const OutputSection *OutputSec;452 const OutputSection *outputSec;
441};453};
442454
443template <class ELFT> class DynamicSection final : public SyntheticSection {455template <class ELFT> class DynamicSection final : public SyntheticSection {
444 typedef typename ELFT::Dyn Elf_Dyn;456 using Elf_Dyn = typename ELFT::Dyn;
445 typedef typename ELFT::Rel Elf_Rel;457 using Elf_Rel = typename ELFT::Rel;
446 typedef typename ELFT::Rela Elf_Rela;458 using Elf_Rela = typename ELFT::Rela;
447 typedef typename ELFT::Relr Elf_Relr;459 using Elf_Relr = typename ELFT::Relr;
448 typedef typename ELFT::Shdr Elf_Shdr;460 using Elf_Shdr = typename ELFT::Shdr;
449 typedef typename ELFT::Sym Elf_Sym;461 using Elf_Sym = typename ELFT::Sym;
450462
451 // finalizeContents() fills this vector with the section contents.463 // finalizeContents() fills this vector with the section contents.
452 std::vector<std::pair<int32_t, std::function<uint64_t()>>> Entries;464 std::vector<std::pair<int32_t, std::function<uint64_t()>>> entries;
453465
454public:466public:
455 DynamicSection();467 DynamicSection();
456 void finalizeContents() override;468 void finalizeContents() override;
457 void writeTo(uint8_t *Buf) override;469 void writeTo(uint8_t *buf) override;
458 size_t getSize() const override { return Size; }470 size_t getSize() const override { return size; }
459471
460private:472private:
461 void add(int32_t Tag, std::function<uint64_t()> Fn);473 void add(int32_t tag, std::function<uint64_t()> fn);
462 void addInt(int32_t Tag, uint64_t Val);474 void addInt(int32_t tag, uint64_t val);
463 void addInSec(int32_t Tag, InputSection *Sec);475 void addInSec(int32_t tag, InputSection *sec);
464 void addInSecRelative(int32_t Tag, InputSection *Sec);476 void addInSecRelative(int32_t tag, InputSection *sec);
465 void addOutSec(int32_t Tag, OutputSection *Sec);477 void addOutSec(int32_t tag, OutputSection *sec);
466 void addSize(int32_t Tag, OutputSection *Sec);478 void addSize(int32_t tag, OutputSection *sec);
467 void addSym(int32_t Tag, Symbol *Sym);479 void addSym(int32_t tag, Symbol *sym);
468480
469 uint64_t Size = 0;481 uint64_t size = 0;
470};482};
471483
472class RelocationBaseSection : public SyntheticSection {484class RelocationBaseSection : public SyntheticSection {
473public:485public:
474 RelocationBaseSection(StringRef Name, uint32_t Type, int32_t DynamicTag,486 RelocationBaseSection(StringRef name, uint32_t type, int32_t dynamicTag,
475 int32_t SizeDynamicTag);487 int32_t sizeDynamicTag);
476 void addReloc(RelType DynType, InputSectionBase *IS, uint64_t OffsetInSec,488 void addReloc(RelType dynType, InputSectionBase *isec, uint64_t offsetInSec,
477 Symbol *Sym);489 Symbol *sym);
478 // Add a dynamic relocation that might need an addend. This takes care of490 // Add a dynamic relocation that might need an addend. This takes care of
479 // writing the addend to the output section if needed.491 // writing the addend to the output section if needed.
480 void addReloc(RelType DynType, InputSectionBase *InputSec,492 void addReloc(RelType dynType, InputSectionBase *inputSec,
481 uint64_t OffsetInSec, Symbol *Sym, int64_t Addend, RelExpr Expr,493 uint64_t offsetInSec, Symbol *sym, int64_t addend, RelExpr expr,
482 RelType Type);494 RelType type);
483 void addReloc(const DynamicReloc &Reloc);495 void addReloc(const DynamicReloc &reloc);
484 bool empty() const override { return Relocs.empty(); }496 bool isNeeded() const override { return !relocs.empty(); }
485 size_t getSize() const override { return Relocs.size() * this->Entsize; }497 size_t getSize() const override { return relocs.size() * this->entsize; }
486 size_t getRelativeRelocCount() const { return NumRelativeRelocs; }498 size_t getRelativeRelocCount() const { return numRelativeRelocs; }
487 void finalizeContents() override;499 void finalizeContents() override;
488 int32_t DynamicTag, SizeDynamicTag;500 int32_t dynamicTag, sizeDynamicTag;
501 std::vector<DynamicReloc> relocs;
489502
490protected:503protected:
491 std::vector<DynamicReloc> Relocs;504 size_t numRelativeRelocs = 0;
492 size_t NumRelativeRelocs = 0;
493};505};
494506
495template <class ELFT>507template <class ELFT>
496class RelocationSection final : public RelocationBaseSection {508class RelocationSection final : public RelocationBaseSection {
497 typedef typename ELFT::Rel Elf_Rel;509 using Elf_Rel = typename ELFT::Rel;
498 typedef typename ELFT::Rela Elf_Rela;510 using Elf_Rela = typename ELFT::Rela;
499511
500public:512public:
501 RelocationSection(StringRef Name, bool Sort);513 RelocationSection(StringRef name, bool sort);
502 unsigned getRelocOffset();514 void writeTo(uint8_t *buf) override;
503 void writeTo(uint8_t *Buf) override;
504515
505private:516private:
506 bool Sort;517 bool sort;
507};518};
508519
509template <class ELFT>520template <class ELFT>
510class AndroidPackedRelocationSection final : public RelocationBaseSection {521class AndroidPackedRelocationSection final : public RelocationBaseSection {
511 typedef typename ELFT::Rel Elf_Rel;522 using Elf_Rel = typename ELFT::Rel;
512 typedef typename ELFT::Rela Elf_Rela;523 using Elf_Rela = typename ELFT::Rela;
513524
514public:525public:
515 AndroidPackedRelocationSection(StringRef Name);526 AndroidPackedRelocationSection(StringRef name);
516527
517 bool updateAllocSize() override;528 bool updateAllocSize() override;
518 size_t getSize() const override { return RelocData.size(); }529 size_t getSize() const override { return relocData.size(); }
519 void writeTo(uint8_t *Buf) override {530 void writeTo(uint8_t *buf) override {
520 memcpy(Buf, RelocData.data(), RelocData.size());531 memcpy(buf, relocData.data(), relocData.size());
521 }532 }
522533
523private:534private:
524 SmallVector<char, 0> RelocData;535 SmallVector<char, 0> relocData;
525};536};
526537
527struct RelativeReloc {538struct RelativeReloc {
528 uint64_t getOffset() const { return InputSec->getVA(OffsetInSec); }539 uint64_t getOffset() const { return inputSec->getVA(offsetInSec); }
529540
530 const InputSectionBase *InputSec;541 const InputSectionBase *inputSec;
531 uint64_t OffsetInSec;542 uint64_t offsetInSec;
532};543};
533544
534class RelrBaseSection : public SyntheticSection {545class RelrBaseSection : public SyntheticSection {
535public:546public:
536 RelrBaseSection();547 RelrBaseSection();
537 bool empty() const override { return Relocs.empty(); }548 bool isNeeded() const override { return !relocs.empty(); }
538 std::vector<RelativeReloc> Relocs;549 std::vector<RelativeReloc> relocs;
539};550};
540551
541// RelrSection is used to encode offsets for relative relocations.552// RelrSection is used to encode offsets for relative relocations.
...@@ -543,65 +554,65 @@ public:...@@ -543,65 +554,65 @@ public:
543// https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg554// https://groups.google.com/forum/#!topic/generic-abi/bX460iggiKg
544// For more details, see the comment in RelrSection::updateAllocSize().555// For more details, see the comment in RelrSection::updateAllocSize().
545template <class ELFT> class RelrSection final : public RelrBaseSection {556template <class ELFT> class RelrSection final : public RelrBaseSection {
546 typedef typename ELFT::Relr Elf_Relr;557 using Elf_Relr = typename ELFT::Relr;
547558
548public:559public:
549 RelrSection();560 RelrSection();
550561
551 bool updateAllocSize() override;562 bool updateAllocSize() override;
552 size_t getSize() const override { return RelrRelocs.size() * this->Entsize; }563 size_t getSize() const override { return relrRelocs.size() * this->entsize; }
553 void writeTo(uint8_t *Buf) override {564 void writeTo(uint8_t *buf) override {
554 memcpy(Buf, RelrRelocs.data(), getSize());565 memcpy(buf, relrRelocs.data(), getSize());
555 }566 }
556567
557private:568private:
558 std::vector<Elf_Relr> RelrRelocs;569 std::vector<Elf_Relr> relrRelocs;
559};570};
560571
561struct SymbolTableEntry {572struct SymbolTableEntry {
562 Symbol *Sym;573 Symbol *sym;
563 size_t StrTabOffset;574 size_t strTabOffset;
564};575};
565576
566class SymbolTableBaseSection : public SyntheticSection {577class SymbolTableBaseSection : public SyntheticSection {
567public:578public:
568 SymbolTableBaseSection(StringTableSection &StrTabSec);579 SymbolTableBaseSection(StringTableSection &strTabSec);
569 void finalizeContents() override;580 void finalizeContents() override;
570 size_t getSize() const override { return getNumSymbols() * Entsize; }581 size_t getSize() const override { return getNumSymbols() * entsize; }
571 void addSymbol(Symbol *Sym);582 void addSymbol(Symbol *sym);
572 unsigned getNumSymbols() const { return Symbols.size() + 1; }583 unsigned getNumSymbols() const { return symbols.size() + 1; }
573 size_t getSymbolIndex(Symbol *Sym);584 size_t getSymbolIndex(Symbol *sym);
574 ArrayRef<SymbolTableEntry> getSymbols() const { return Symbols; }585 ArrayRef<SymbolTableEntry> getSymbols() const { return symbols; }
575586
576protected:587protected:
577 void sortSymTabSymbols();588 void sortSymTabSymbols();
578589
579 // A vector of symbols and their string table offsets.590 // A vector of symbols and their string table offsets.
580 std::vector<SymbolTableEntry> Symbols;591 std::vector<SymbolTableEntry> symbols;
581592
582 StringTableSection &StrTabSec;593 StringTableSection &strTabSec;
583594
584 llvm::once_flag OnceFlag;595 llvm::once_flag onceFlag;
585 llvm::DenseMap<Symbol *, size_t> SymbolIndexMap;596 llvm::DenseMap<Symbol *, size_t> symbolIndexMap;
586 llvm::DenseMap<OutputSection *, size_t> SectionIndexMap;597 llvm::DenseMap<OutputSection *, size_t> sectionIndexMap;
587};598};
588599
589template <class ELFT>600template <class ELFT>
590class SymbolTableSection final : public SymbolTableBaseSection {601class SymbolTableSection final : public SymbolTableBaseSection {
591 typedef typename ELFT::Sym Elf_Sym;602 using Elf_Sym = typename ELFT::Sym;
592603
593public:604public:
594 SymbolTableSection(StringTableSection &StrTabSec);605 SymbolTableSection(StringTableSection &strTabSec);
595 void writeTo(uint8_t *Buf) override;606 void writeTo(uint8_t *buf) override;
596};607};
597608
598class SymtabShndxSection final : public SyntheticSection {609class SymtabShndxSection final : public SyntheticSection {
599public:610public:
600 SymtabShndxSection();611 SymtabShndxSection();
601612
602 void writeTo(uint8_t *Buf) override;613 void writeTo(uint8_t *buf) override;
603 size_t getSize() const override;614 size_t getSize() const override;
604 bool empty() const override;615 bool isNeeded() const override;
605 void finalizeContents() override;616 void finalizeContents() override;
606};617};
607618
...@@ -611,42 +622,42 @@ class GnuHashTableSection final : public SyntheticSection {...@@ -611,42 +622,42 @@ class GnuHashTableSection final : public SyntheticSection {
611public:622public:
612 GnuHashTableSection();623 GnuHashTableSection();
613 void finalizeContents() override;624 void finalizeContents() override;
614 void writeTo(uint8_t *Buf) override;625 void writeTo(uint8_t *buf) override;
615 size_t getSize() const override { return Size; }626 size_t getSize() const override { return size; }
616627
617 // Adds symbols to the hash table.628 // Adds symbols to the hash table.
618 // Sorts the input to satisfy GNU hash section requirements.629 // Sorts the input to satisfy GNU hash section requirements.
619 void addSymbols(std::vector<SymbolTableEntry> &Symbols);630 void addSymbols(std::vector<SymbolTableEntry> &symbols);
620631
621private:632private:
622 // See the comment in writeBloomFilter.633 // See the comment in writeBloomFilter.
623 enum { Shift2 = 26 };634 enum { Shift2 = 26 };
624635
625 void writeBloomFilter(uint8_t *Buf);636 void writeBloomFilter(uint8_t *buf);
626 void writeHashTable(uint8_t *Buf);637 void writeHashTable(uint8_t *buf);
627638
628 struct Entry {639 struct Entry {
629 Symbol *Sym;640 Symbol *sym;
630 size_t StrTabOffset;641 size_t strTabOffset;
631 uint32_t Hash;642 uint32_t hash;
632 uint32_t BucketIdx;643 uint32_t bucketIdx;
633 };644 };
634645
635 std::vector<Entry> Symbols;646 std::vector<Entry> symbols;
636 size_t MaskWords;647 size_t maskWords;
637 size_t NBuckets = 0;648 size_t nBuckets = 0;
638 size_t Size = 0;649 size_t size = 0;
639};650};
640651
641class HashTableSection final : public SyntheticSection {652class HashTableSection final : public SyntheticSection {
642public:653public:
643 HashTableSection();654 HashTableSection();
644 void finalizeContents() override;655 void finalizeContents() override;
645 void writeTo(uint8_t *Buf) override;656 void writeTo(uint8_t *buf) override;
646 size_t getSize() const override { return Size; }657 size_t getSize() const override { return size; }
647658
648private:659private:
649 size_t Size = 0;660 size_t size = 0;
650};661};
651662
652// The PltSection is used for both the Plt and Iplt. The former usually has a663// The PltSection is used for both the Plt and Iplt. The former usually has a
...@@ -655,67 +666,66 @@ private:...@@ -655,67 +666,66 @@ private:
655// Target->IRelativeRel.666// Target->IRelativeRel.
656class PltSection : public SyntheticSection {667class PltSection : public SyntheticSection {
657public:668public:
658 PltSection(bool IsIplt);669 PltSection(bool isIplt);
659 void writeTo(uint8_t *Buf) override;670 void writeTo(uint8_t *buf) override;
660 size_t getSize() const override;671 size_t getSize() const override;
661 bool empty() const override { return Entries.empty(); }672 bool isNeeded() const override { return !entries.empty(); }
662 void addSymbols();673 void addSymbols();
663 template <class ELFT> void addEntry(Symbol &Sym);674 template <class ELFT> void addEntry(Symbol &sym);
664675
665 size_t HeaderSize;676 size_t headerSize;
666677
667private:678private:
668 unsigned getPltRelocOff() const;679 std::vector<const Symbol *> entries;
669 std::vector<std::pair<const Symbol *, unsigned>> Entries;680 bool isIplt;
670 bool IsIplt;
671};681};
672682
673class GdbIndexSection final : public SyntheticSection {683class GdbIndexSection final : public SyntheticSection {
674public:684public:
675 struct AddressEntry {685 struct AddressEntry {
676 InputSection *Section;686 InputSection *section;
677 uint64_t LowAddress;687 uint64_t lowAddress;
678 uint64_t HighAddress;688 uint64_t highAddress;
679 uint32_t CuIndex;689 uint32_t cuIndex;
680 };690 };
681691
682 struct CuEntry {692 struct CuEntry {
683 uint64_t CuOffset;693 uint64_t cuOffset;
684 uint64_t CuLength;694 uint64_t cuLength;
685 };695 };
686696
687 struct NameAttrEntry {697 struct NameAttrEntry {
688 llvm::CachedHashStringRef Name;698 llvm::CachedHashStringRef name;
689 uint32_t CuIndexAndAttrs;699 uint32_t cuIndexAndAttrs;
690 };700 };
691701
692 struct GdbChunk {702 struct GdbChunk {
693 InputSection *Sec;703 InputSection *sec;
694 std::vector<AddressEntry> AddressAreas;704 std::vector<AddressEntry> addressAreas;
695 std::vector<CuEntry> CompilationUnits;705 std::vector<CuEntry> compilationUnits;
696 };706 };
697707
698 struct GdbSymbol {708 struct GdbSymbol {
699 llvm::CachedHashStringRef Name;709 llvm::CachedHashStringRef name;
700 std::vector<uint32_t> CuVector;710 std::vector<uint32_t> cuVector;
701 uint32_t NameOff;711 uint32_t nameOff;
702 uint32_t CuVectorOff;712 uint32_t cuVectorOff;
703 };713 };
704714
705 GdbIndexSection();715 GdbIndexSection();
706 template <typename ELFT> static GdbIndexSection *create();716 template <typename ELFT> static GdbIndexSection *create();
707 void writeTo(uint8_t *Buf) override;717 void writeTo(uint8_t *buf) override;
708 size_t getSize() const override { return Size; }718 size_t getSize() const override { return size; }
709 bool empty() const override;719 bool isNeeded() const override;
710720
711private:721private:
712 struct GdbIndexHeader {722 struct GdbIndexHeader {
713 llvm::support::ulittle32_t Version;723 llvm::support::ulittle32_t version;
714 llvm::support::ulittle32_t CuListOff;724 llvm::support::ulittle32_t cuListOff;
715 llvm::support::ulittle32_t CuTypesOff;725 llvm::support::ulittle32_t cuTypesOff;
716 llvm::support::ulittle32_t AddressAreaOff;726 llvm::support::ulittle32_t addressAreaOff;
717 llvm::support::ulittle32_t SymtabOff;727 llvm::support::ulittle32_t symtabOff;
718 llvm::support::ulittle32_t ConstantPoolOff;728 llvm::support::ulittle32_t constantPoolOff;
719 };729 };
720730
721 void initOutputSize();731 void initOutputSize();
...@@ -723,12 +733,12 @@ private:...@@ -723,12 +733,12 @@ private:
723733
724 // Each chunk contains information gathered from debug sections of a734 // Each chunk contains information gathered from debug sections of a
725 // single object file.735 // single object file.
726 std::vector<GdbChunk> Chunks;736 std::vector<GdbChunk> chunks;
727737
728 // A symbol table for this .gdb_index section.738 // A symbol table for this .gdb_index section.
729 std::vector<GdbSymbol> Symbols;739 std::vector<GdbSymbol> symbols;
730740
731 size_t Size;741 size_t size;
732};742};
733743
734// --eh-frame-hdr option tells linker to construct a header for all the744// --eh-frame-hdr option tells linker to construct a header for all the
...@@ -743,9 +753,10 @@ private:...@@ -743,9 +753,10 @@ private:
743class EhFrameHeader final : public SyntheticSection {753class EhFrameHeader final : public SyntheticSection {
744public:754public:
745 EhFrameHeader();755 EhFrameHeader();
746 void writeTo(uint8_t *Buf) override;756 void write();
757 void writeTo(uint8_t *buf) override;
747 size_t getSize() const override;758 size_t getSize() const override;
748 bool empty() const override;759 bool isNeeded() const override;
749};760};
750761
751// For more information about .gnu.version and .gnu.version_r see:762// For more information about .gnu.version and .gnu.version_r see:
...@@ -761,13 +772,15 @@ public:...@@ -761,13 +772,15 @@ public:
761 VersionDefinitionSection();772 VersionDefinitionSection();
762 void finalizeContents() override;773 void finalizeContents() override;
763 size_t getSize() const override;774 size_t getSize() const override;
764 void writeTo(uint8_t *Buf) override;775 void writeTo(uint8_t *buf) override;
765776
766private:777private:
767 enum { EntrySize = 28 };778 enum { EntrySize = 28 };
768 void writeOne(uint8_t *Buf, uint32_t Index, StringRef Name, size_t NameOff);779 void writeOne(uint8_t *buf, uint32_t index, StringRef name, size_t nameOff);
780 StringRef getFileDefName();
769781
770 unsigned FileDefNameOff;782 unsigned fileDefNameOff;
783 std::vector<unsigned> verDefNameOffs;
771};784};
772785
773// The .gnu.version section specifies the required version of each symbol in the786// The .gnu.version section specifies the required version of each symbol in the
...@@ -776,14 +789,13 @@ private:...@@ -776,14 +789,13 @@ private:
776// identifier defined in the either .gnu.version_r or .gnu.version_d section.789// identifier defined in the either .gnu.version_r or .gnu.version_d section.
777// The values 0 and 1 are reserved. All other values are used for versions in790// The values 0 and 1 are reserved. All other values are used for versions in
778// the own object or in any of the dependencies.791// the own object or in any of the dependencies.
779template <class ELFT>
780class VersionTableSection final : public SyntheticSection {792class VersionTableSection final : public SyntheticSection {
781public:793public:
782 VersionTableSection();794 VersionTableSection();
783 void finalizeContents() override;795 void finalizeContents() override;
784 size_t getSize() const override;796 size_t getSize() const override;
785 void writeTo(uint8_t *Buf) override;797 void writeTo(uint8_t *buf) override;
786 bool empty() const override;798 bool isNeeded() const override;
787};799};
788800
789// The .gnu.version_r section defines the version identifiers used by801// The .gnu.version_r section defines the version identifiers used by
...@@ -791,25 +803,30 @@ public:...@@ -791,25 +803,30 @@ public:
791// Elf_Verneed specifies the version requirements for a single DSO, and contains803// Elf_Verneed specifies the version requirements for a single DSO, and contains
792// a reference to a linked list of Elf_Vernaux data structures which define the804// a reference to a linked list of Elf_Vernaux data structures which define the
793// mapping from version identifiers to version names.805// mapping from version identifiers to version names.
794template <class ELFT> class VersionNeedSection final : public SyntheticSection {806template <class ELFT>
795 typedef typename ELFT::Verneed Elf_Verneed;807class VersionNeedSection final : public SyntheticSection {
796 typedef typename ELFT::Vernaux Elf_Vernaux;808 using Elf_Verneed = typename ELFT::Verneed;
809 using Elf_Vernaux = typename ELFT::Vernaux;
810
811 struct Vernaux {
812 uint64_t hash;
813 uint32_t verneedIndex;
814 uint64_t nameStrTab;
815 };
797816
798 // A vector of shared files that need Elf_Verneed data structures and the817 struct Verneed {
799 // string table offsets of their sonames.818 uint64_t nameStrTab;
800 std::vector<std::pair<SharedFile<ELFT> *, size_t>> Needed;819 std::vector<Vernaux> vernauxs;
820 };
801821
802 // The next available version identifier.822 std::vector<Verneed> verneeds;
803 unsigned NextIndex;
804823
805public:824public:
806 VersionNeedSection();825 VersionNeedSection();
807 void addSymbol(Symbol *Sym);
808 void finalizeContents() override;826 void finalizeContents() override;
809 void writeTo(uint8_t *Buf) override;827 void writeTo(uint8_t *buf) override;
810 size_t getSize() const override;828 size_t getSize() const override;
811 size_t getNeedNum() const { return Needed.size(); }829 bool isNeeded() const override;
812 bool empty() const override;
813};830};
814831
815// MergeSyntheticSection is a class that allows us to put mergeable sections832// MergeSyntheticSection is a class that allows us to put mergeable sections
...@@ -818,36 +835,36 @@ public:...@@ -818,36 +835,36 @@ public:
818// attached to regular output sections.835// attached to regular output sections.
819class MergeSyntheticSection : public SyntheticSection {836class MergeSyntheticSection : public SyntheticSection {
820public:837public:
821 void addSection(MergeInputSection *MS);838 void addSection(MergeInputSection *ms);
822 std::vector<MergeInputSection *> Sections;839 std::vector<MergeInputSection *> sections;
823840
824protected:841protected:
825 MergeSyntheticSection(StringRef Name, uint32_t Type, uint64_t Flags,842 MergeSyntheticSection(StringRef name, uint32_t type, uint64_t flags,
826 uint32_t Alignment)843 uint32_t alignment)
827 : SyntheticSection(Flags, Type, Alignment, Name) {}844 : SyntheticSection(flags, type, alignment, name) {}
828};845};
829846
830class MergeTailSection final : public MergeSyntheticSection {847class MergeTailSection final : public MergeSyntheticSection {
831public:848public:
832 MergeTailSection(StringRef Name, uint32_t Type, uint64_t Flags,849 MergeTailSection(StringRef name, uint32_t type, uint64_t flags,
833 uint32_t Alignment);850 uint32_t alignment);
834851
835 size_t getSize() const override;852 size_t getSize() const override;
836 void writeTo(uint8_t *Buf) override;853 void writeTo(uint8_t *buf) override;
837 void finalizeContents() override;854 void finalizeContents() override;
838855
839private:856private:
840 llvm::StringTableBuilder Builder;857 llvm::StringTableBuilder builder;
841};858};
842859
843class MergeNoTailSection final : public MergeSyntheticSection {860class MergeNoTailSection final : public MergeSyntheticSection {
844public:861public:
845 MergeNoTailSection(StringRef Name, uint32_t Type, uint64_t Flags,862 MergeNoTailSection(StringRef name, uint32_t type, uint64_t flags,
846 uint32_t Alignment)863 uint32_t alignment)
847 : MergeSyntheticSection(Name, Type, Flags, Alignment) {}864 : MergeSyntheticSection(name, type, flags, alignment) {}
848865
849 size_t getSize() const override { return Size; }866 size_t getSize() const override { return size; }
850 void writeTo(uint8_t *Buf) override;867 void writeTo(uint8_t *buf) override;
851 void finalizeContents() override;868 void finalizeContents() override;
852869
853private:870private:
...@@ -856,67 +873,68 @@ private:...@@ -856,67 +873,68 @@ private:
856 // because DenseMap also uses lower bits to determine a bucket ID.873 // because DenseMap also uses lower bits to determine a bucket ID.
857 // If we use lower bits, it significantly increases the probability of874 // If we use lower bits, it significantly increases the probability of
858 // hash collisons.875 // hash collisons.
859 size_t getShardId(uint32_t Hash) {876 size_t getShardId(uint32_t hash) {
860 return Hash >> (32 - llvm::countTrailingZeros(NumShards));877 assert((hash >> 31) == 0);
878 return hash >> (31 - llvm::countTrailingZeros(numShards));
861 }879 }
862880
863 // Section size881 // Section size
864 size_t Size;882 size_t size;
865883
866 // String table contents884 // String table contents
867 constexpr static size_t NumShards = 32;885 constexpr static size_t numShards = 32;
868 std::vector<llvm::StringTableBuilder> Shards;886 std::vector<llvm::StringTableBuilder> shards;
869 size_t ShardOffsets[NumShards];887 size_t shardOffsets[numShards];
870};888};
871889
872// .MIPS.abiflags section.890// .MIPS.abiflags section.
873template <class ELFT>891template <class ELFT>
874class MipsAbiFlagsSection final : public SyntheticSection {892class MipsAbiFlagsSection final : public SyntheticSection {
875 typedef llvm::object::Elf_Mips_ABIFlags<ELFT> Elf_Mips_ABIFlags;893 using Elf_Mips_ABIFlags = llvm::object::Elf_Mips_ABIFlags<ELFT>;
876894
877public:895public:
878 static MipsAbiFlagsSection *create();896 static MipsAbiFlagsSection *create();
879897
880 MipsAbiFlagsSection(Elf_Mips_ABIFlags Flags);898 MipsAbiFlagsSection(Elf_Mips_ABIFlags flags);
881 size_t getSize() const override { return sizeof(Elf_Mips_ABIFlags); }899 size_t getSize() const override { return sizeof(Elf_Mips_ABIFlags); }
882 void writeTo(uint8_t *Buf) override;900 void writeTo(uint8_t *buf) override;
883901
884private:902private:
885 Elf_Mips_ABIFlags Flags;903 Elf_Mips_ABIFlags flags;
886};904};
887905
888// .MIPS.options section.906// .MIPS.options section.
889template <class ELFT> class MipsOptionsSection final : public SyntheticSection {907template <class ELFT> class MipsOptionsSection final : public SyntheticSection {
890 typedef llvm::object::Elf_Mips_Options<ELFT> Elf_Mips_Options;908 using Elf_Mips_Options = llvm::object::Elf_Mips_Options<ELFT>;
891 typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;909 using Elf_Mips_RegInfo = llvm::object::Elf_Mips_RegInfo<ELFT>;
892910
893public:911public:
894 static MipsOptionsSection *create();912 static MipsOptionsSection *create();
895913
896 MipsOptionsSection(Elf_Mips_RegInfo Reginfo);914 MipsOptionsSection(Elf_Mips_RegInfo reginfo);
897 void writeTo(uint8_t *Buf) override;915 void writeTo(uint8_t *buf) override;
898916
899 size_t getSize() const override {917 size_t getSize() const override {
900 return sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);918 return sizeof(Elf_Mips_Options) + sizeof(Elf_Mips_RegInfo);
901 }919 }
902920
903private:921private:
904 Elf_Mips_RegInfo Reginfo;922 Elf_Mips_RegInfo reginfo;
905};923};
906924
907// MIPS .reginfo section.925// MIPS .reginfo section.
908template <class ELFT> class MipsReginfoSection final : public SyntheticSection {926template <class ELFT> class MipsReginfoSection final : public SyntheticSection {
909 typedef llvm::object::Elf_Mips_RegInfo<ELFT> Elf_Mips_RegInfo;927 using Elf_Mips_RegInfo = llvm::object::Elf_Mips_RegInfo<ELFT>;
910928
911public:929public:
912 static MipsReginfoSection *create();930 static MipsReginfoSection *create();
913931
914 MipsReginfoSection(Elf_Mips_RegInfo Reginfo);932 MipsReginfoSection(Elf_Mips_RegInfo reginfo);
915 size_t getSize() const override { return sizeof(Elf_Mips_RegInfo); }933 size_t getSize() const override { return sizeof(Elf_Mips_RegInfo); }
916 void writeTo(uint8_t *Buf) override;934 void writeTo(uint8_t *buf) override;
917935
918private:936private:
919 Elf_Mips_RegInfo Reginfo;937 Elf_Mips_RegInfo reginfo;
920};938};
921939
922// This is a MIPS specific section to hold a space within the data segment940// This is a MIPS specific section to hold a space within the data segment
...@@ -926,45 +944,115 @@ private:...@@ -926,45 +944,115 @@ private:
926class MipsRldMapSection : public SyntheticSection {944class MipsRldMapSection : public SyntheticSection {
927public:945public:
928 MipsRldMapSection();946 MipsRldMapSection();
929 size_t getSize() const override { return Config->Wordsize; }947 size_t getSize() const override { return config->wordsize; }
930 void writeTo(uint8_t *Buf) override {}948 void writeTo(uint8_t *buf) override {}
931};949};
932950
933class ARMExidxSentinelSection : public SyntheticSection {951// Representation of the combined .ARM.Exidx input sections. We process these
952// as a SyntheticSection like .eh_frame as we need to merge duplicate entries
953// and add terminating sentinel entries.
954//
955// The .ARM.exidx input sections after SHF_LINK_ORDER processing is done form
956// a table that the unwinder can derive (Addresses are encoded as offsets from
957// table):
958// | Address of function | Unwind instructions for function |
959// where the unwind instructions are either a small number of unwind or the
960// special EXIDX_CANTUNWIND entry representing no unwinding information.
961// When an exception is thrown from an address A, the unwinder searches the
962// table for the closest table entry with Address of function <= A. This means
963// that for two consecutive table entries:
964// | A1 | U1 |
965// | A2 | U2 |
966// The range of addresses described by U1 is [A1, A2)
967//
968// There are two cases where we need a linker generated table entry to fixup
969// the address ranges in the table
970// Case 1:
971// - A sentinel entry added with an address higher than all
972// executable sections. This was needed to work around libunwind bug pr31091.
973// - After address assignment we need to find the highest addressed executable
974// section and use the limit of that section so that the unwinder never
975// matches it.
976// Case 2:
977// - InputSections without a .ARM.exidx section (usually from Assembly)
978// need a table entry so that they terminate the range of the previously
979// function. This is pr40277.
980//
981// Instead of storing pointers to the .ARM.exidx InputSections from
982// InputObjects, we store pointers to the executable sections that need
983// .ARM.exidx sections. We can then use the dependentSections of these to
984// either find the .ARM.exidx section or know that we need to generate one.
985class ARMExidxSyntheticSection : public SyntheticSection {
934public:986public:
935 ARMExidxSentinelSection();987 ARMExidxSyntheticSection();
936 size_t getSize() const override { return 8; }988
937 void writeTo(uint8_t *Buf) override;989 // Add an input section to the ARMExidxSyntheticSection. Returns whether the
938 bool empty() const override;990 // section needs to be removed from the main input section list.
991 bool addSection(InputSection *isec);
939992
940 static bool classof(const SectionBase *D);993 size_t getSize() const override { return size; }
994 void writeTo(uint8_t *buf) override;
995 bool isNeeded() const override { return !empty; }
996 // Sort and remove duplicate entries.
997 void finalizeContents() override;
998 InputSection *getLinkOrderDep() const;
999
1000 static bool classof(const SectionBase *d);
1001
1002 // Links to the ARMExidxSections so we can transfer the relocations once the
1003 // layout is known.
1004 std::vector<InputSection *> exidxSections;
9411005
942 // The last section referenced by a regular .ARM.exidx section.1006private:
943 // It is found and filled in Writer<ELFT>::resolveShfLinkOrder().1007 size_t size;
944 // The sentinel points at the end of that section.1008
945 InputSection *Highest = nullptr;1009 // Empty if ExecutableSections contains no dependent .ARM.exidx sections.
1010 bool empty = true;
1011
1012 // Instead of storing pointers to the .ARM.exidx InputSections from
1013 // InputObjects, we store pointers to the executable sections that need
1014 // .ARM.exidx sections. We can then use the dependentSections of these to
1015 // either find the .ARM.exidx section or know that we need to generate one.
1016 std::vector<InputSection *> executableSections;
1017
1018 // The executable InputSection with the highest address to use for the
1019 // sentinel. We store separately from ExecutableSections as merging of
1020 // duplicate entries may mean this InputSection is removed from
1021 // ExecutableSections.
1022 InputSection *sentinel = nullptr;
946};1023};
9471024
948// A container for one or more linker generated thunks. Instances of these1025// A container for one or more linker generated thunks. Instances of these
949// thunks including ARM interworking and Mips LA25 PI to non-PI thunks.1026// thunks including ARM interworking and Mips LA25 PI to non-PI thunks.
950class ThunkSection : public SyntheticSection {1027class ThunkSection : public SyntheticSection {
951public:1028public:
952 // ThunkSection in OS, with desired OutSecOff of Off1029 // ThunkSection in OS, with desired outSecOff of Off
953 ThunkSection(OutputSection *OS, uint64_t Off);1030 ThunkSection(OutputSection *os, uint64_t off);
9541031
955 // Add a newly created Thunk to this container:1032 // Add a newly created Thunk to this container:
956 // Thunk is given offset from start of this InputSection1033 // Thunk is given offset from start of this InputSection
957 // Thunk defines a symbol in this InputSection that can be used as target1034 // Thunk defines a symbol in this InputSection that can be used as target
958 // of a relocation1035 // of a relocation
959 void addThunk(Thunk *T);1036 void addThunk(Thunk *t);
960 size_t getSize() const override { return Size; }1037 size_t getSize() const override { return size; }
961 void writeTo(uint8_t *Buf) override;1038 void writeTo(uint8_t *buf) override;
962 InputSection *getTargetInputSection() const;1039 InputSection *getTargetInputSection() const;
963 bool assignOffsets();1040 bool assignOffsets();
9641041
965private:1042private:
966 std::vector<Thunk *> Thunks;1043 std::vector<Thunk *> thunks;
967 size_t Size = 0;1044 size_t size = 0;
1045};
1046
1047// Used to compute outSecOff of .got2 in each object file. This is needed to
1048// synthesize PLT entries for PPC32 Secure PLT ABI.
1049class PPC32Got2Section final : public SyntheticSection {
1050public:
1051 PPC32Got2Section();
1052 size_t getSize() const override { return 0; }
1053 bool isNeeded() const override;
1054 void finalizeContents() override;
1055 void writeTo(uint8_t *buf) override {}
968};1056};
9691057
970// This section is used to store the addresses of functions that are called1058// This section is used to store the addresses of functions that are called
...@@ -975,15 +1063,48 @@ private:...@@ -975,15 +1063,48 @@ private:
975class PPC64LongBranchTargetSection final : public SyntheticSection {1063class PPC64LongBranchTargetSection final : public SyntheticSection {
976public:1064public:
977 PPC64LongBranchTargetSection();1065 PPC64LongBranchTargetSection();
978 void addEntry(Symbol &Sym);1066 void addEntry(Symbol &sym);
979 size_t getSize() const override;1067 size_t getSize() const override;
980 void writeTo(uint8_t *Buf) override;1068 void writeTo(uint8_t *buf) override;
981 bool empty() const override;1069 bool isNeeded() const override;
982 void finalizeContents() override { Finalized = true; }1070 void finalizeContents() override { finalized = true; }
9831071
984private:1072private:
985 std::vector<const Symbol *> Entries;1073 std::vector<const Symbol *> entries;
986 bool Finalized = false;1074 bool finalized = false;
1075};
1076
1077template <typename ELFT>
1078class PartitionElfHeaderSection : public SyntheticSection {
1079public:
1080 PartitionElfHeaderSection();
1081 size_t getSize() const override;
1082 void writeTo(uint8_t *buf) override;
1083};
1084
1085template <typename ELFT>
1086class PartitionProgramHeadersSection : public SyntheticSection {
1087public:
1088 PartitionProgramHeadersSection();
1089 size_t getSize() const override;
1090 void writeTo(uint8_t *buf) override;
1091};
1092
1093class PartitionIndexSection : public SyntheticSection {
1094public:
1095 PartitionIndexSection();
1096 size_t getSize() const override;
1097 void finalizeContents() override;
1098 void writeTo(uint8_t *buf) override;
1099};
1100
1101// Create a dummy .sdata for __global_pointer$ if .sdata does not exist.
1102class RISCVSdataSection final : public SyntheticSection {
1103public:
1104 RISCVSdataSection();
1105 size_t getSize() const override { return 0; }
1106 bool isNeeded() const override;
1107 void writeTo(uint8_t *buf) override {}
987};1108};
9881109
989InputSection *createInterpSection();1110InputSection *createInterpSection();
...@@ -991,52 +1112,76 @@ MergeInputSection *createCommentSection();...@@ -991,52 +1112,76 @@ MergeInputSection *createCommentSection();
991template <class ELFT> void splitSections();1112template <class ELFT> void splitSections();
992void mergeSections();1113void mergeSections();
9931114
994Defined *addSyntheticLocal(StringRef Name, uint8_t Type, uint64_t Value,1115template <typename ELFT> void writeEhdr(uint8_t *buf, Partition &part);
995 uint64_t Size, InputSectionBase &Section);1116template <typename ELFT> void writePhdrs(uint8_t *buf, Partition &part);
9961117
997// Linker generated sections which can be used as inputs.1118Defined *addSyntheticLocal(StringRef name, uint8_t type, uint64_t value,
998struct InStruct {1119 uint64_t size, InputSectionBase &section);
999 InputSection *ARMAttributes;1120
1000 BssSection *Bss;1121void addVerneed(Symbol *ss);
1001 BssSection *BssRelRo;1122
1002 BuildIdSection *BuildId;1123// Linker generated per-partition sections.
1003 EhFrameHeader *EhFrameHdr;1124struct Partition {
1004 EhFrameSection *EhFrame;1125 StringRef name;
1005 SyntheticSection *Dynamic;1126 uint64_t nameStrTab;
1006 StringTableSection *DynStrTab;1127
1007 SymbolTableBaseSection *DynSymTab;1128 SyntheticSection *elfHeader;
1008 GnuHashTableSection *GnuHashTab;1129 SyntheticSection *programHeaders;
1009 HashTableSection *HashTab;1130 std::vector<PhdrEntry *> phdrs;
1010 InputSection *Interp;1131
1011 GdbIndexSection *GdbIndex;1132 ARMExidxSyntheticSection *armExidx;
1012 GotSection *Got;1133 BuildIdSection *buildId;
1013 GotPltSection *GotPlt;1134 SyntheticSection *dynamic;
1014 IgotPltSection *IgotPlt;1135 StringTableSection *dynStrTab;
1015 PPC64LongBranchTargetSection *PPC64LongBranchTarget;1136 SymbolTableBaseSection *dynSymTab;
1016 MipsGotSection *MipsGot;1137 EhFrameHeader *ehFrameHdr;
1017 MipsRldMapSection *MipsRldMap;1138 EhFrameSection *ehFrame;
1018 PltSection *Plt;1139 GnuHashTableSection *gnuHashTab;
1019 PltSection *Iplt;1140 HashTableSection *hashTab;
1020 RelocationBaseSection *RelaDyn;1141 RelocationBaseSection *relaDyn;
1021 RelrBaseSection *RelrDyn;1142 RelrBaseSection *relrDyn;
1022 RelocationBaseSection *RelaPlt;1143 VersionDefinitionSection *verDef;
1023 RelocationBaseSection *RelaIplt;1144 SyntheticSection *verNeed;
1024 StringTableSection *ShStrTab;1145 VersionTableSection *verSym;
1025 StringTableSection *StrTab;1146
1026 SymbolTableBaseSection *SymTab;1147 unsigned getNumber() const { return this - &partitions[0] + 1; }
1027 SymtabShndxSection *SymTabShndx;
1028 VersionDefinitionSection *VerDef;
1029};1148};
10301149
1031extern InStruct In;1150extern Partition *mainPart;
10321151
1033template <class ELFT> struct InX {1152inline Partition &SectionBase::getPartition() const {
1034 static VersionTableSection<ELFT> *VerSym;1153 assert(isLive());
1035 static VersionNeedSection<ELFT> *VerNeed;1154 return partitions[partition - 1];
1155}
1156
1157// Linker generated sections which can be used as inputs and are not specific to
1158// a partition.
1159struct InStruct {
1160 InputSection *armAttributes;
1161 BssSection *bss;
1162 BssSection *bssRelRo;
1163 GotSection *got;
1164 GotPltSection *gotPlt;
1165 IgotPltSection *igotPlt;
1166 PPC64LongBranchTargetSection *ppc64LongBranchTarget;
1167 MipsGotSection *mipsGot;
1168 MipsRldMapSection *mipsRldMap;
1169 SyntheticSection *partEnd;
1170 SyntheticSection *partIndex;
1171 PltSection *plt;
1172 PltSection *iplt;
1173 PPC32Got2Section *ppc32Got2;
1174 RISCVSdataSection *riscvSdata;
1175 RelocationBaseSection *relaPlt;
1176 RelocationBaseSection *relaIplt;
1177 StringTableSection *shStrTab;
1178 StringTableSection *strTab;
1179 SymbolTableBaseSection *symTab;
1180 SymtabShndxSection *symTabShndx;
1036};1181};
10371182
1038template <class ELFT> VersionTableSection<ELFT> *InX<ELFT>::VerSym;1183extern InStruct in;
1039template <class ELFT> VersionNeedSection<ELFT> *InX<ELFT>::VerNeed;1184
1040} // namespace elf1185} // namespace elf
1041} // namespace lld1186} // namespace lld
10421187
deps/lld/ELF/Target.cpp+49-52
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Target.cpp ---------------------------------------------------------===//1//===- Target.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -38,17 +37,17 @@ using namespace llvm::ELF;...@@ -38,17 +37,17 @@ using namespace llvm::ELF;
38using namespace lld;37using namespace lld;
39using namespace lld::elf;38using namespace lld::elf;
4039
41TargetInfo *elf::Target;40const TargetInfo *elf::target;
4241
43std::string lld::toString(RelType Type) {42std::string lld::toString(RelType type) {
44 StringRef S = getELFRelocationTypeName(elf::Config->EMachine, Type);43 StringRef s = getELFRelocationTypeName(elf::config->emachine, type);
45 if (S == "Unknown")44 if (s == "Unknown")
46 return ("Unknown (" + Twine(Type) + ")").str();45 return ("Unknown (" + Twine(type) + ")").str();
47 return S;46 return s;
48}47}
4948
50TargetInfo *elf::getTarget() {49TargetInfo *elf::getTarget() {
51 switch (Config->EMachine) {50 switch (config->emachine) {
52 case EM_386:51 case EM_386:
53 case EM_IAMCU:52 case EM_IAMCU:
54 return getX86TargetInfo();53 return getX86TargetInfo();
...@@ -63,7 +62,7 @@ TargetInfo *elf::getTarget() {...@@ -63,7 +62,7 @@ TargetInfo *elf::getTarget() {
63 case EM_HEXAGON:62 case EM_HEXAGON:
64 return getHexagonTargetInfo();63 return getHexagonTargetInfo();
65 case EM_MIPS:64 case EM_MIPS:
66 switch (Config->EKind) {65 switch (config->ekind) {
67 case ELF32LEKind:66 case ELF32LEKind:
68 return getMipsTargetInfo<ELF32LE>();67 return getMipsTargetInfo<ELF32LE>();
69 case ELF32BEKind:68 case ELF32BEKind:
...@@ -86,36 +85,34 @@ TargetInfo *elf::getTarget() {...@@ -86,36 +85,34 @@ TargetInfo *elf::getTarget() {
86 case EM_SPARCV9:85 case EM_SPARCV9:
87 return getSPARCV9TargetInfo();86 return getSPARCV9TargetInfo();
88 case EM_X86_64:87 case EM_X86_64:
89 if (Config->EKind == ELF32LEKind)
90 return getX32TargetInfo();
91 return getX86_64TargetInfo();88 return getX86_64TargetInfo();
92 }89 }
93 llvm_unreachable("unknown target machine");90 llvm_unreachable("unknown target machine");
94}91}
9592
96template <class ELFT> static ErrorPlace getErrPlace(const uint8_t *Loc) {93template <class ELFT> static ErrorPlace getErrPlace(const uint8_t *loc) {
97 for (InputSectionBase *D : InputSections) {94 for (InputSectionBase *d : inputSections) {
98 auto *IS = cast<InputSection>(D);95 auto *isec = cast<InputSection>(d);
99 if (!IS->getParent())96 if (!isec->getParent())
100 continue;97 continue;
10198
102 uint8_t *ISLoc = IS->getParent()->Loc + IS->OutSecOff;99 uint8_t *isecLoc = Out::bufferStart + isec->getParent()->offset + isec->outSecOff;
103 if (ISLoc <= Loc && Loc < ISLoc + IS->getSize())100 if (isecLoc <= loc && loc < isecLoc + isec->getSize())
104 return {IS, IS->template getLocation<ELFT>(Loc - ISLoc) + ": "};101 return {isec, isec->template getLocation<ELFT>(loc - isecLoc) + ": "};
105 }102 }
106 return {};103 return {};
107}104}
108105
109ErrorPlace elf::getErrorPlace(const uint8_t *Loc) {106ErrorPlace elf::getErrorPlace(const uint8_t *loc) {
110 switch (Config->EKind) {107 switch (config->ekind) {
111 case ELF32LEKind:108 case ELF32LEKind:
112 return getErrPlace<ELF32LE>(Loc);109 return getErrPlace<ELF32LE>(loc);
113 case ELF32BEKind:110 case ELF32BEKind:
114 return getErrPlace<ELF32BE>(Loc);111 return getErrPlace<ELF32BE>(loc);
115 case ELF64LEKind:112 case ELF64LEKind:
116 return getErrPlace<ELF64LE>(Loc);113 return getErrPlace<ELF64LE>(loc);
117 case ELF64BEKind:114 case ELF64BEKind:
118 return getErrPlace<ELF64BE>(Loc);115 return getErrPlace<ELF64BE>(loc);
119 default:116 default:
120 llvm_unreachable("unknown ELF type");117 llvm_unreachable("unknown ELF type");
121 }118 }
...@@ -123,62 +120,62 @@ ErrorPlace elf::getErrorPlace(const uint8_t *Loc) {...@@ -123,62 +120,62 @@ ErrorPlace elf::getErrorPlace(const uint8_t *Loc) {
123120
124TargetInfo::~TargetInfo() {}121TargetInfo::~TargetInfo() {}
125122
126int64_t TargetInfo::getImplicitAddend(const uint8_t *Buf, RelType Type) const {123int64_t TargetInfo::getImplicitAddend(const uint8_t *buf, RelType type) const {
127 return 0;124 return 0;
128}125}
129126
130bool TargetInfo::usesOnlyLowPageBits(RelType Type) const { return false; }127bool TargetInfo::usesOnlyLowPageBits(RelType type) const { return false; }
131128
132bool TargetInfo::needsThunk(RelExpr Expr, RelType Type, const InputFile *File,129bool TargetInfo::needsThunk(RelExpr expr, RelType type, const InputFile *file,
133 uint64_t BranchAddr, const Symbol &S) const {130 uint64_t branchAddr, const Symbol &s) const {
134 return false;131 return false;
135}132}
136133
137bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End,134bool TargetInfo::adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
138 uint8_t StOther) const {135 uint8_t stOther) const {
139 llvm_unreachable("Target doesn't support split stacks.");136 llvm_unreachable("Target doesn't support split stacks.");
140}137}
141138
142bool TargetInfo::inBranchRange(RelType Type, uint64_t Src, uint64_t Dst) const {139bool TargetInfo::inBranchRange(RelType type, uint64_t src, uint64_t dst) const {
143 return true;140 return true;
144}141}
145142
146void TargetInfo::writeIgotPlt(uint8_t *Buf, const Symbol &S) const {143void TargetInfo::writeIgotPlt(uint8_t *buf, const Symbol &s) const {
147 writeGotPlt(Buf, S);144 writeGotPlt(buf, s);
148}145}
149146
150RelExpr TargetInfo::adjustRelaxExpr(RelType Type, const uint8_t *Data,147RelExpr TargetInfo::adjustRelaxExpr(RelType type, const uint8_t *data,
151 RelExpr Expr) const {148 RelExpr expr) const {
152 return Expr;149 return expr;
153}150}
154151
155void TargetInfo::relaxGot(uint8_t *Loc, uint64_t Val) const {152void TargetInfo::relaxGot(uint8_t *loc, RelType type, uint64_t val) const {
156 llvm_unreachable("Should not have claimed to be relaxable");153 llvm_unreachable("Should not have claimed to be relaxable");
157}154}
158155
159void TargetInfo::relaxTlsGdToLe(uint8_t *Loc, RelType Type,156void TargetInfo::relaxTlsGdToLe(uint8_t *loc, RelType type,
160 uint64_t Val) const {157 uint64_t val) const {
161 llvm_unreachable("Should not have claimed to be relaxable");158 llvm_unreachable("Should not have claimed to be relaxable");
162}159}
163160
164void TargetInfo::relaxTlsGdToIe(uint8_t *Loc, RelType Type,161void TargetInfo::relaxTlsGdToIe(uint8_t *loc, RelType type,
165 uint64_t Val) const {162 uint64_t val) const {
166 llvm_unreachable("Should not have claimed to be relaxable");163 llvm_unreachable("Should not have claimed to be relaxable");
167}164}
168165
169void TargetInfo::relaxTlsIeToLe(uint8_t *Loc, RelType Type,166void TargetInfo::relaxTlsIeToLe(uint8_t *loc, RelType type,
170 uint64_t Val) const {167 uint64_t val) const {
171 llvm_unreachable("Should not have claimed to be relaxable");168 llvm_unreachable("Should not have claimed to be relaxable");
172}169}
173170
174void TargetInfo::relaxTlsLdToLe(uint8_t *Loc, RelType Type,171void TargetInfo::relaxTlsLdToLe(uint8_t *loc, RelType type,
175 uint64_t Val) const {172 uint64_t val) const {
176 llvm_unreachable("Should not have claimed to be relaxable");173 llvm_unreachable("Should not have claimed to be relaxable");
177}174}
178175
179uint64_t TargetInfo::getImageBase() {176uint64_t TargetInfo::getImageBase() const {
180 // Use -image-base if set. Fall back to the target default if not.177 // Use -image-base if set. Fall back to the target default if not.
181 if (Config->ImageBase)178 if (config->imageBase)
182 return *Config->ImageBase;179 return *config->imageBase;
183 return Config->Pic ? 0 : DefaultImageBase;180 return config->isPic ? 0 : defaultImageBase;
184}181}
deps/lld/ELF/Target.h+117-116
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Target.h -------------------------------------------------*- C++ -*-===//1//===- Target.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -17,7 +16,7 @@...@@ -17,7 +16,7 @@
17#include <array>16#include <array>
1817
19namespace lld {18namespace lld {
20std::string toString(elf::RelType Type);19std::string toString(elf::RelType type);
2120
22namespace elf {21namespace elf {
23class Defined;22class Defined;
...@@ -27,36 +26,39 @@ class Symbol;...@@ -27,36 +26,39 @@ class Symbol;
27class TargetInfo {26class TargetInfo {
28public:27public:
29 virtual uint32_t calcEFlags() const { return 0; }28 virtual uint32_t calcEFlags() const { return 0; }
30 virtual RelType getDynRel(RelType Type) const { return Type; }29 virtual RelExpr getRelExpr(RelType type, const Symbol &s,
31 virtual void writeGotPltHeader(uint8_t *Buf) const {}30 const uint8_t *loc) const = 0;
32 virtual void writeGotHeader(uint8_t *Buf) const {}31 virtual RelType getDynRel(RelType type) const { return 0; }
33 virtual void writeGotPlt(uint8_t *Buf, const Symbol &S) const {};32 virtual void writeGotPltHeader(uint8_t *buf) const {}
34 virtual void writeIgotPlt(uint8_t *Buf, const Symbol &S) const;33 virtual void writeGotHeader(uint8_t *buf) const {}
35 virtual int64_t getImplicitAddend(const uint8_t *Buf, RelType Type) const;34 virtual void writeGotPlt(uint8_t *buf, const Symbol &s) const {};
35 virtual void writeIgotPlt(uint8_t *buf, const Symbol &s) const;
36 virtual int64_t getImplicitAddend(const uint8_t *buf, RelType type) const;
37 virtual int getTlsGdRelaxSkip(RelType type) const { return 1; }
3638
37 // If lazy binding is supported, the first entry of the PLT has code39 // If lazy binding is supported, the first entry of the PLT has code
38 // to call the dynamic linker to resolve PLT entries the first time40 // to call the dynamic linker to resolve PLT entries the first time
39 // they are called. This function writes that code.41 // they are called. This function writes that code.
40 virtual void writePltHeader(uint8_t *Buf) const {}42 virtual void writePltHeader(uint8_t *buf) const {}
4143
42 virtual void writePlt(uint8_t *Buf, uint64_t GotEntryAddr,44 virtual void writePlt(uint8_t *buf, uint64_t gotEntryAddr,
43 uint64_t PltEntryAddr, int32_t Index,45 uint64_t pltEntryAddr, int32_t index,
44 unsigned RelOff) const {}46 unsigned relOff) const {}
45 virtual void addPltHeaderSymbols(InputSection &IS) const {}47 virtual void addPltHeaderSymbols(InputSection &isec) const {}
46 virtual void addPltSymbols(InputSection &IS, uint64_t Off) const {}48 virtual void addPltSymbols(InputSection &isec, uint64_t off) const {}
4749
48 // Returns true if a relocation only uses the low bits of a value such that50 // Returns true if a relocation only uses the low bits of a value such that
49 // all those bits are in the same page. For example, if the relocation51 // all those bits are in the same page. For example, if the relocation
50 // only uses the low 12 bits in a system with 4k pages. If this is true, the52 // only uses the low 12 bits in a system with 4k pages. If this is true, the
51 // bits will always have the same value at runtime and we don't have to emit53 // bits will always have the same value at runtime and we don't have to emit
52 // a dynamic relocation.54 // a dynamic relocation.
53 virtual bool usesOnlyLowPageBits(RelType Type) const;55 virtual bool usesOnlyLowPageBits(RelType type) const;
5456
55 // Decide whether a Thunk is needed for the relocation from File57 // Decide whether a Thunk is needed for the relocation from File
56 // targeting S.58 // targeting S.
57 virtual bool needsThunk(RelExpr Expr, RelType RelocType,59 virtual bool needsThunk(RelExpr expr, RelType relocType,
58 const InputFile *File, uint64_t BranchAddr,60 const InputFile *file, uint64_t branchAddr,
59 const Symbol &S) const;61 const Symbol &s) const;
6062
61 // On systems with range extensions we place collections of Thunks at63 // On systems with range extensions we place collections of Thunks at
62 // regular spacings that enable the majority of branches reach the Thunks.64 // regular spacings that enable the majority of branches reach the Thunks.
...@@ -68,77 +70,71 @@ public:...@@ -68,77 +70,71 @@ public:
68 // to do the right thing. See https://gcc.gnu.org/wiki/SplitStacks.70 // to do the right thing. See https://gcc.gnu.org/wiki/SplitStacks.
69 // The symbols st_other flags are needed on PowerPC64 for determining the71 // The symbols st_other flags are needed on PowerPC64 for determining the
70 // offset to the split-stack prologue.72 // offset to the split-stack prologue.
71 virtual bool adjustPrologueForCrossSplitStack(uint8_t *Loc, uint8_t *End,73 virtual bool adjustPrologueForCrossSplitStack(uint8_t *loc, uint8_t *end,
72 uint8_t StOther) const;74 uint8_t stOther) const;
7375
74 // Return true if we can reach Dst from Src with Relocation RelocType76 // Return true if we can reach dst from src with RelType type.
75 virtual bool inBranchRange(RelType Type, uint64_t Src,77 virtual bool inBranchRange(RelType type, uint64_t src,
76 uint64_t Dst) const;78 uint64_t dst) const;
77 virtual RelExpr getRelExpr(RelType Type, const Symbol &S,
78 const uint8_t *Loc) const = 0;
7979
80 virtual void relocateOne(uint8_t *Loc, RelType Type, uint64_t Val) const = 0;80 virtual void relocateOne(uint8_t *loc, RelType type, uint64_t val) const = 0;
8181
82 virtual ~TargetInfo();82 virtual ~TargetInfo();
8383
84 unsigned TlsGdRelaxSkip = 1;84 unsigned defaultCommonPageSize = 4096;
85 unsigned PageSize = 4096;85 unsigned defaultMaxPageSize = 4096;
86 unsigned DefaultMaxPageSize = 4096;
8786
88 uint64_t getImageBase();87 uint64_t getImageBase() const;
8988
90 // Offset of _GLOBAL_OFFSET_TABLE_ from base of .got or .got.plt section.
91 uint64_t GotBaseSymOff = 0;
92 // True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got.89 // True if _GLOBAL_OFFSET_TABLE_ is relative to .got.plt, false if .got.
93 bool GotBaseSymInGotPlt = true;90 bool gotBaseSymInGotPlt = true;
9491
95 RelType CopyRel;92 RelType copyRel;
96 RelType GotRel;93 RelType gotRel;
97 RelType NoneRel;94 RelType noneRel;
98 RelType PltRel;95 RelType pltRel;
99 RelType RelativeRel;96 RelType relativeRel;
100 RelType IRelativeRel;97 RelType iRelativeRel;
101 RelType TlsDescRel;98 RelType symbolicRel;
102 RelType TlsGotRel;99 RelType tlsDescRel;
103 RelType TlsModuleIndexRel;100 RelType tlsGotRel;
104 RelType TlsOffsetRel;101 RelType tlsModuleIndexRel;
105 unsigned GotEntrySize = 0;102 RelType tlsOffsetRel;
106 unsigned GotPltEntrySize = 0;103 unsigned pltEntrySize;
107 unsigned PltEntrySize;104 unsigned pltHeaderSize;
108 unsigned PltHeaderSize;
109105
110 // At least on x86_64 positions 1 and 2 are used by the first plt entry106 // At least on x86_64 positions 1 and 2 are used by the first plt entry
111 // to support lazy loading.107 // to support lazy loading.
112 unsigned GotPltHeaderEntriesNum = 3;108 unsigned gotPltHeaderEntriesNum = 3;
113109
114 // On PPC ELF V2 abi, the first entry in the .got is the .TOC.110 // On PPC ELF V2 abi, the first entry in the .got is the .TOC.
115 unsigned GotHeaderEntriesNum = 0;111 unsigned gotHeaderEntriesNum = 0;
116112
117 bool NeedsThunks = false;113 bool needsThunks = false;
118114
119 // A 4-byte field corresponding to one or more trap instructions, used to pad115 // A 4-byte field corresponding to one or more trap instructions, used to pad
120 // executable OutputSections.116 // executable OutputSections.
121 std::array<uint8_t, 4> TrapInstr;117 std::array<uint8_t, 4> trapInstr;
122118
123 // If a target needs to rewrite calls to __morestack to instead call119 // If a target needs to rewrite calls to __morestack to instead call
124 // __morestack_non_split when a split-stack enabled caller calls a120 // __morestack_non_split when a split-stack enabled caller calls a
125 // non-split-stack callee this will return true. Otherwise returns false.121 // non-split-stack callee this will return true. Otherwise returns false.
126 bool NeedsMoreStackNonSplit = true;122 bool needsMoreStackNonSplit = true;
127123
128 virtual RelExpr adjustRelaxExpr(RelType Type, const uint8_t *Data,124 virtual RelExpr adjustRelaxExpr(RelType type, const uint8_t *data,
129 RelExpr Expr) const;125 RelExpr expr) const;
130 virtual void relaxGot(uint8_t *Loc, uint64_t Val) const;126 virtual void relaxGot(uint8_t *loc, RelType type, uint64_t val) const;
131 virtual void relaxTlsGdToIe(uint8_t *Loc, RelType Type, uint64_t Val) const;127 virtual void relaxTlsGdToIe(uint8_t *loc, RelType type, uint64_t val) const;
132 virtual void relaxTlsGdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const;128 virtual void relaxTlsGdToLe(uint8_t *loc, RelType type, uint64_t val) const;
133 virtual void relaxTlsIeToLe(uint8_t *Loc, RelType Type, uint64_t Val) const;129 virtual void relaxTlsIeToLe(uint8_t *loc, RelType type, uint64_t val) const;
134 virtual void relaxTlsLdToLe(uint8_t *Loc, RelType Type, uint64_t Val) const;130 virtual void relaxTlsLdToLe(uint8_t *loc, RelType type, uint64_t val) const;
135131
136protected:132protected:
137 // On FreeBSD x86_64 the first page cannot be mmaped.133 // On FreeBSD x86_64 the first page cannot be mmaped.
138 // On Linux that is controled by vm.mmap_min_addr. At least on some x86_64134 // On Linux that is controled by vm.mmap_min_addr. At least on some x86_64
139 // installs that is 65536, so the first 15 pages cannot be used.135 // installs that is 65536, so the first 15 pages cannot be used.
140 // Given that, the smallest value that can be used in here is 0x10000.136 // Given that, the smallest value that can be used in here is 0x10000.
141 uint64_t DefaultImageBase = 0x10000;137 uint64_t defaultImageBase = 0x10000;
142};138};
143139
144TargetInfo *getAArch64TargetInfo();140TargetInfo *getAArch64TargetInfo();
...@@ -151,108 +147,113 @@ TargetInfo *getPPC64TargetInfo();...@@ -151,108 +147,113 @@ TargetInfo *getPPC64TargetInfo();
151TargetInfo *getPPCTargetInfo();147TargetInfo *getPPCTargetInfo();
152TargetInfo *getRISCVTargetInfo();148TargetInfo *getRISCVTargetInfo();
153TargetInfo *getSPARCV9TargetInfo();149TargetInfo *getSPARCV9TargetInfo();
154TargetInfo *getX32TargetInfo();
155TargetInfo *getX86TargetInfo();150TargetInfo *getX86TargetInfo();
156TargetInfo *getX86_64TargetInfo();151TargetInfo *getX86_64TargetInfo();
157template <class ELFT> TargetInfo *getMipsTargetInfo();152template <class ELFT> TargetInfo *getMipsTargetInfo();
158153
159struct ErrorPlace {154struct ErrorPlace {
160 InputSectionBase *IS;155 InputSectionBase *isec;
161 std::string Loc;156 std::string loc;
162};157};
163158
164// Returns input section and corresponding source string for the given location.159// Returns input section and corresponding source string for the given location.
165ErrorPlace getErrorPlace(const uint8_t *Loc);160ErrorPlace getErrorPlace(const uint8_t *loc);
166161
167static inline std::string getErrorLocation(const uint8_t *Loc) {162static inline std::string getErrorLocation(const uint8_t *loc) {
168 return getErrorPlace(Loc).Loc;163 return getErrorPlace(loc).loc;
169}164}
170165
171// In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first is166void writePPC32GlinkSection(uint8_t *buf, size_t numEntries);
172// a global entry point (GEP) which typically is used to intiailzie the TOC167
168bool tryRelaxPPC64TocIndirection(RelType type, const Relocation &rel,
169 uint8_t *bufLoc);
170unsigned getPPCDFormOp(unsigned secondaryOp);
171
172// In the PowerPC64 Elf V2 abi a function can have 2 entry points. The first
173// is a global entry point (GEP) which typically is used to initialize the TOC
173// pointer in general purpose register 2. The second is a local entry174// pointer in general purpose register 2. The second is a local entry
174// point (LEP) which bypasses the TOC pointer initialization code. The175// 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// 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-point177// This function will return the offset (in bytes) from the global entry-point
177// to the local entry-point.178// to the local entry-point.
178unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t StOther);179unsigned getPPC64GlobalEntryToLocalEntryOffset(uint8_t stOther);
180
181// Returns true if a relocation is a small code model relocation that accesses
182// the .toc section.
183bool isPPC64SmallCodeModelTocReloc(RelType type);
179184
180uint64_t getPPC64TocBase();185uint64_t getPPC64TocBase();
181uint64_t getAArch64Page(uint64_t Expr);186uint64_t getAArch64Page(uint64_t expr);
182187
183extern TargetInfo *Target;188extern const TargetInfo *target;
184TargetInfo *getTarget();189TargetInfo *getTarget();
185190
186template <class ELFT> bool isMipsPIC(const Defined *Sym);191template <class ELFT> bool isMipsPIC(const Defined *sym);
187192
188static inline void reportRangeError(uint8_t *Loc, RelType Type, const Twine &V,193static inline void reportRangeError(uint8_t *loc, RelType type, const Twine &v,
189 int64_t Min, uint64_t Max) {194 int64_t min, uint64_t max) {
190 ErrorPlace ErrPlace = getErrorPlace(Loc);195 ErrorPlace errPlace = getErrorPlace(loc);
191 StringRef Hint;196 StringRef hint;
192 if (ErrPlace.IS && ErrPlace.IS->Name.startswith(".debug"))197 if (errPlace.isec && errPlace.isec->name.startswith(".debug"))
193 Hint = "; consider recompiling with -fdebug-types-section to reduce size "198 hint = "; consider recompiling with -fdebug-types-section to reduce size "
194 "of debug sections";199 "of debug sections";
195200
196 errorOrWarn(ErrPlace.Loc + "relocation " + lld::toString(Type) +201 errorOrWarn(errPlace.loc + "relocation " + lld::toString(type) +
197 " out of range: " + V.str() + " is not in [" + Twine(Min).str() +202 " out of range: " + v.str() + " is not in [" + Twine(min).str() +
198 ", " + Twine(Max).str() + "]" + Hint);203 ", " + Twine(max).str() + "]" + hint);
199}
200
201inline unsigned getPltEntryOffset(unsigned Idx) {
202 return Target->PltHeaderSize + Target->PltEntrySize * Idx;
203}204}
204205
205// Make sure that V can be represented as an N bit signed integer.206// Make sure that V can be represented as an N bit signed integer.
206inline void checkInt(uint8_t *Loc, int64_t V, int N, RelType Type) {207inline void checkInt(uint8_t *loc, int64_t v, int n, RelType type) {
207 if (V != llvm::SignExtend64(V, N))208 if (v != llvm::SignExtend64(v, n))
208 reportRangeError(Loc, Type, Twine(V), llvm::minIntN(N), llvm::maxIntN(N));209 reportRangeError(loc, type, Twine(v), llvm::minIntN(n), llvm::maxIntN(n));
209}210}
210211
211// Make sure that V can be represented as an N bit unsigned integer.212// Make sure that V can be represented as an N bit unsigned integer.
212inline void checkUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) {213inline void checkUInt(uint8_t *loc, uint64_t v, int n, RelType type) {
213 if ((V >> N) != 0)214 if ((v >> n) != 0)
214 reportRangeError(Loc, Type, Twine(V), 0, llvm::maxUIntN(N));215 reportRangeError(loc, type, Twine(v), 0, llvm::maxUIntN(n));
215}216}
216217
217// Make sure that V can be represented as an N bit signed or unsigned integer.218// Make sure that V can be represented as an N bit signed or unsigned integer.
218inline void checkIntUInt(uint8_t *Loc, uint64_t V, int N, RelType Type) {219inline void checkIntUInt(uint8_t *loc, uint64_t v, int n, RelType type) {
219 // For the error message we should cast V to a signed integer so that error220 // For the error message we should cast V to a signed integer so that error
220 // messages show a small negative value rather than an extremely large one221 // messages show a small negative value rather than an extremely large one
221 if (V != (uint64_t)llvm::SignExtend64(V, N) && (V >> N) != 0)222 if (v != (uint64_t)llvm::SignExtend64(v, n) && (v >> n) != 0)
222 reportRangeError(Loc, Type, Twine((int64_t)V), llvm::minIntN(N),223 reportRangeError(loc, type, Twine((int64_t)v), llvm::minIntN(n),
223 llvm::maxIntN(N));224 llvm::maxUIntN(n));
224}225}
225226
226inline void checkAlignment(uint8_t *Loc, uint64_t V, int N, RelType Type) {227inline void checkAlignment(uint8_t *loc, uint64_t v, int n, RelType type) {
227 if ((V & (N - 1)) != 0)228 if ((v & (n - 1)) != 0)
228 error(getErrorLocation(Loc) + "improper alignment for relocation " +229 error(getErrorLocation(loc) + "improper alignment for relocation " +
229 lld::toString(Type) + ": 0x" + llvm::utohexstr(V) +230 lld::toString(type) + ": 0x" + llvm::utohexstr(v) +
230 " is not aligned to " + Twine(N) + " bytes");231 " is not aligned to " + Twine(n) + " bytes");
231}232}
232233
233// Endianness-aware read/write.234// Endianness-aware read/write.
234inline uint16_t read16(const void *P) {235inline uint16_t read16(const void *p) {
235 return llvm::support::endian::read16(P, Config->Endianness);236 return llvm::support::endian::read16(p, config->endianness);
236}237}
237238
238inline uint32_t read32(const void *P) {239inline uint32_t read32(const void *p) {
239 return llvm::support::endian::read32(P, Config->Endianness);240 return llvm::support::endian::read32(p, config->endianness);
240}241}
241242
242inline uint64_t read64(const void *P) {243inline uint64_t read64(const void *p) {
243 return llvm::support::endian::read64(P, Config->Endianness);244 return llvm::support::endian::read64(p, config->endianness);
244}245}
245246
246inline void write16(void *P, uint16_t V) {247inline void write16(void *p, uint16_t v) {
247 llvm::support::endian::write16(P, V, Config->Endianness);248 llvm::support::endian::write16(p, v, config->endianness);
248}249}
249250
250inline void write32(void *P, uint32_t V) {251inline void write32(void *p, uint32_t v) {
251 llvm::support::endian::write32(P, V, Config->Endianness);252 llvm::support::endian::write32(p, v, config->endianness);
252}253}
253254
254inline void write64(void *P, uint64_t V) {255inline void write64(void *p, uint64_t v) {
255 llvm::support::endian::write64(P, V, Config->Endianness);256 llvm::support::endian::write64(p, v, config->endianness);
256}257}
257} // namespace elf258} // namespace elf
258} // namespace lld259} // namespace lld
deps/lld/ELF/Thunks.cpp+450-359
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Thunks.cpp --------------------------------------------------------===//1//===- Thunks.cpp --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===---------------------------------------------------------------------===//7//===---------------------------------------------------------------------===//
9//8//
...@@ -50,18 +49,18 @@ namespace {...@@ -50,18 +49,18 @@ namespace {
50// AArch64 long range Thunks49// AArch64 long range Thunks
51class AArch64ABSLongThunk final : public Thunk {50class AArch64ABSLongThunk final : public Thunk {
52public:51public:
53 AArch64ABSLongThunk(Symbol &Dest) : Thunk(Dest) {}52 AArch64ABSLongThunk(Symbol &dest) : Thunk(dest) {}
54 uint32_t size() override { return 16; }53 uint32_t size() override { return 16; }
55 void writeTo(uint8_t *Buf) override;54 void writeTo(uint8_t *buf) override;
56 void addSymbols(ThunkSection &IS) override;55 void addSymbols(ThunkSection &isec) override;
57};56};
5857
59class AArch64ADRPThunk final : public Thunk {58class AArch64ADRPThunk final : public Thunk {
60public:59public:
61 AArch64ADRPThunk(Symbol &Dest) : Thunk(Dest) {}60 AArch64ADRPThunk(Symbol &dest) : Thunk(dest) {}
62 uint32_t size() override { return 12; }61 uint32_t size() override { return 12; }
63 void writeTo(uint8_t *Buf) override;62 void writeTo(uint8_t *buf) override;
64 void addSymbols(ThunkSection &IS) override;63 void addSymbols(ThunkSection &isec) override;
65};64};
6665
67// Base class for ARM thunks.66// Base class for ARM thunks.
...@@ -74,18 +73,19 @@ public:...@@ -74,18 +73,19 @@ public:
74// if the target is in range, otherwise it creates a long thunk.73// if the target is in range, otherwise it creates a long thunk.
75class ARMThunk : public Thunk {74class ARMThunk : public Thunk {
76public:75public:
77 ARMThunk(Symbol &Dest) : Thunk(Dest) {}76 ARMThunk(Symbol &dest) : Thunk(dest) {}
7877
79 bool mayUseShortThunk();78 bool getMayUseShortThunk();
80 uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }79 uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); }
81 void writeTo(uint8_t *Buf) override;80 void writeTo(uint8_t *buf) override;
82 bool isCompatibleWith(RelType Type) const override;81 bool isCompatibleWith(const InputSection &isec,
82 const Relocation &rel) const override;
8383
84 // Returns the size of a long thunk.84 // Returns the size of a long thunk.
85 virtual uint32_t sizeLong() = 0;85 virtual uint32_t sizeLong() = 0;
8686
87 // Writes a long thunk to Buf.87 // Writes a long thunk to Buf.
88 virtual void writeLong(uint8_t *Buf) = 0;88 virtual void writeLong(uint8_t *buf) = 0;
8989
90private:90private:
91 // This field tracks whether all previously considered layouts would allow91 // This field tracks whether all previously considered layouts would allow
...@@ -94,7 +94,7 @@ private:...@@ -94,7 +94,7 @@ private:
94 // distance to the target. We do this because transitioning from long to short94 // distance to the target. We do this because transitioning from long to short
95 // can create layout oscillations in certain corner cases which would prevent95 // can create layout oscillations in certain corner cases which would prevent
96 // the layout from converging.96 // the layout from converging.
97 bool MayUseShortThunk = true;97 bool mayUseShortThunk = true;
98};98};
9999
100// Base class for Thumb-2 thunks.100// Base class for Thumb-2 thunks.
...@@ -103,60 +103,61 @@ private:...@@ -103,60 +103,61 @@ private:
103// which has a range of 16MB.103// which has a range of 16MB.
104class ThumbThunk : public Thunk {104class ThumbThunk : public Thunk {
105public:105public:
106 ThumbThunk(Symbol &Dest) : Thunk(Dest) { Alignment = 2; }106 ThumbThunk(Symbol &dest) : Thunk(dest) { alignment = 2; }
107107
108 bool mayUseShortThunk();108 bool getMayUseShortThunk();
109 uint32_t size() override { return mayUseShortThunk() ? 4 : sizeLong(); }109 uint32_t size() override { return getMayUseShortThunk() ? 4 : sizeLong(); }
110 void writeTo(uint8_t *Buf) override;110 void writeTo(uint8_t *buf) override;
111 bool isCompatibleWith(RelType Type) const override;111 bool isCompatibleWith(const InputSection &isec,
112 const Relocation &rel) const override;
112113
113 // Returns the size of a long thunk.114 // Returns the size of a long thunk.
114 virtual uint32_t sizeLong() = 0;115 virtual uint32_t sizeLong() = 0;
115116
116 // Writes a long thunk to Buf.117 // Writes a long thunk to Buf.
117 virtual void writeLong(uint8_t *Buf) = 0;118 virtual void writeLong(uint8_t *buf) = 0;
118119
119private:120private:
120 // See comment in ARMThunk above.121 // See comment in ARMThunk above.
121 bool MayUseShortThunk = true;122 bool mayUseShortThunk = true;
122};123};
123124
124// Specific ARM Thunk implementations. The naming convention is:125// Specific ARM Thunk implementations. The naming convention is:
125// Source State, TargetState, Target Requirement, ABS or PI, Range126// Source State, TargetState, Target Requirement, ABS or PI, Range
126class ARMV7ABSLongThunk final : public ARMThunk {127class ARMV7ABSLongThunk final : public ARMThunk {
127public:128public:
128 ARMV7ABSLongThunk(Symbol &Dest) : ARMThunk(Dest) {}129 ARMV7ABSLongThunk(Symbol &dest) : ARMThunk(dest) {}
129130
130 uint32_t sizeLong() override { return 12; }131 uint32_t sizeLong() override { return 12; }
131 void writeLong(uint8_t *Buf) override;132 void writeLong(uint8_t *buf) override;
132 void addSymbols(ThunkSection &IS) override;133 void addSymbols(ThunkSection &isec) override;
133};134};
134135
135class ARMV7PILongThunk final : public ARMThunk {136class ARMV7PILongThunk final : public ARMThunk {
136public:137public:
137 ARMV7PILongThunk(Symbol &Dest) : ARMThunk(Dest) {}138 ARMV7PILongThunk(Symbol &dest) : ARMThunk(dest) {}
138139
139 uint32_t sizeLong() override { return 16; }140 uint32_t sizeLong() override { return 16; }
140 void writeLong(uint8_t *Buf) override;141 void writeLong(uint8_t *buf) override;
141 void addSymbols(ThunkSection &IS) override;142 void addSymbols(ThunkSection &isec) override;
142};143};
143144
144class ThumbV7ABSLongThunk final : public ThumbThunk {145class ThumbV7ABSLongThunk final : public ThumbThunk {
145public:146public:
146 ThumbV7ABSLongThunk(Symbol &Dest) : ThumbThunk(Dest) {}147 ThumbV7ABSLongThunk(Symbol &dest) : ThumbThunk(dest) {}
147148
148 uint32_t sizeLong() override { return 10; }149 uint32_t sizeLong() override { return 10; }
149 void writeLong(uint8_t *Buf) override;150 void writeLong(uint8_t *buf) override;
150 void addSymbols(ThunkSection &IS) override;151 void addSymbols(ThunkSection &isec) override;
151};152};
152153
153class ThumbV7PILongThunk final : public ThumbThunk {154class ThumbV7PILongThunk final : public ThumbThunk {
154public:155public:
155 ThumbV7PILongThunk(Symbol &Dest) : ThumbThunk(Dest) {}156 ThumbV7PILongThunk(Symbol &dest) : ThumbThunk(dest) {}
156157
157 uint32_t sizeLong() override { return 12; }158 uint32_t sizeLong() override { return 12; }
158 void writeLong(uint8_t *Buf) override;159 void writeLong(uint8_t *buf) override;
159 void addSymbols(ThunkSection &IS) override;160 void addSymbols(ThunkSection &isec) override;
160};161};
161162
162// Implementations of Thunks for older Arm architectures that do not support163// Implementations of Thunks for older Arm architectures that do not support
...@@ -166,76 +167,96 @@ public:...@@ -166,76 +167,96 @@ public:
166// can result in a thunk167// can result in a thunk
167class ARMV5ABSLongThunk final : public ARMThunk {168class ARMV5ABSLongThunk final : public ARMThunk {
168public:169public:
169 ARMV5ABSLongThunk(Symbol &Dest) : ARMThunk(Dest) {}170 ARMV5ABSLongThunk(Symbol &dest) : ARMThunk(dest) {}
170171
171 uint32_t sizeLong() override { return 8; }172 uint32_t sizeLong() override { return 8; }
172 void writeLong(uint8_t *Buf) override;173 void writeLong(uint8_t *buf) override;
173 void addSymbols(ThunkSection &IS) override;174 void addSymbols(ThunkSection &isec) override;
174 bool isCompatibleWith(uint32_t RelocType) const override;175 bool isCompatibleWith(const InputSection &isec,
176 const Relocation &rel) const override;
175};177};
176178
177class ARMV5PILongThunk final : public ARMThunk {179class ARMV5PILongThunk final : public ARMThunk {
178public:180public:
179 ARMV5PILongThunk(Symbol &Dest) : ARMThunk(Dest) {}181 ARMV5PILongThunk(Symbol &dest) : ARMThunk(dest) {}
180182
181 uint32_t sizeLong() override { return 16; }183 uint32_t sizeLong() override { return 16; }
182 void writeLong(uint8_t *Buf) override;184 void writeLong(uint8_t *buf) override;
183 void addSymbols(ThunkSection &IS) override;185 void addSymbols(ThunkSection &isec) override;
184 bool isCompatibleWith(uint32_t RelocType) const override;186 bool isCompatibleWith(const InputSection &isec,
187 const Relocation &rel) const override;
185};188};
186189
187// Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted190// Implementations of Thunks for Arm v6-M. Only Thumb instructions are permitted
188class ThumbV6MABSLongThunk final : public ThumbThunk {191class ThumbV6MABSLongThunk final : public ThumbThunk {
189public:192public:
190 ThumbV6MABSLongThunk(Symbol &Dest) : ThumbThunk(Dest) {}193 ThumbV6MABSLongThunk(Symbol &dest) : ThumbThunk(dest) {}
191194
192 uint32_t sizeLong() override { return 12; }195 uint32_t sizeLong() override { return 12; }
193 void writeLong(uint8_t *Buf) override;196 void writeLong(uint8_t *buf) override;
194 void addSymbols(ThunkSection &IS) override;197 void addSymbols(ThunkSection &isec) override;
195};198};
196199
197class ThumbV6MPILongThunk final : public ThumbThunk {200class ThumbV6MPILongThunk final : public ThumbThunk {
198public:201public:
199 ThumbV6MPILongThunk(Symbol &Dest) : ThumbThunk(Dest) {}202 ThumbV6MPILongThunk(Symbol &dest) : ThumbThunk(dest) {}
200203
201 uint32_t sizeLong() override { return 16; }204 uint32_t sizeLong() override { return 16; }
202 void writeLong(uint8_t *Buf) override;205 void writeLong(uint8_t *buf) override;
203 void addSymbols(ThunkSection &IS) override;206 void addSymbols(ThunkSection &isec) override;
204};207};
205208
206// MIPS LA25 thunk209// MIPS LA25 thunk
207class MipsThunk final : public Thunk {210class MipsThunk final : public Thunk {
208public:211public:
209 MipsThunk(Symbol &Dest) : Thunk(Dest) {}212 MipsThunk(Symbol &dest) : Thunk(dest) {}
210213
211 uint32_t size() override { return 16; }214 uint32_t size() override { return 16; }
212 void writeTo(uint8_t *Buf) override;215 void writeTo(uint8_t *buf) override;
213 void addSymbols(ThunkSection &IS) override;216 void addSymbols(ThunkSection &isec) override;
214 InputSection *getTargetInputSection() const override;217 InputSection *getTargetInputSection() const override;
215};218};
216219
217// microMIPS R2-R5 LA25 thunk220// microMIPS R2-R5 LA25 thunk
218class MicroMipsThunk final : public Thunk {221class MicroMipsThunk final : public Thunk {
219public:222public:
220 MicroMipsThunk(Symbol &Dest) : Thunk(Dest) {}223 MicroMipsThunk(Symbol &dest) : Thunk(dest) {}
221224
222 uint32_t size() override { return 14; }225 uint32_t size() override { return 14; }
223 void writeTo(uint8_t *Buf) override;226 void writeTo(uint8_t *buf) override;
224 void addSymbols(ThunkSection &IS) override;227 void addSymbols(ThunkSection &isec) override;
225 InputSection *getTargetInputSection() const override;228 InputSection *getTargetInputSection() const override;
226};229};
227230
228// microMIPS R6 LA25 thunk231// microMIPS R6 LA25 thunk
229class MicroMipsR6Thunk final : public Thunk {232class MicroMipsR6Thunk final : public Thunk {
230public:233public:
231 MicroMipsR6Thunk(Symbol &Dest) : Thunk(Dest) {}234 MicroMipsR6Thunk(Symbol &dest) : Thunk(dest) {}
232235
233 uint32_t size() override { return 12; }236 uint32_t size() override { return 12; }
234 void writeTo(uint8_t *Buf) override;237 void writeTo(uint8_t *buf) override;
235 void addSymbols(ThunkSection &IS) override;238 void addSymbols(ThunkSection &isec) override;
236 InputSection *getTargetInputSection() const override;239 InputSection *getTargetInputSection() const override;
237};240};
238241
242class PPC32PltCallStub final : public Thunk {
243public:
244 PPC32PltCallStub(const InputSection &isec, const Relocation &rel, Symbol &dest)
245 : Thunk(dest), addend(rel.type == R_PPC_PLTREL24 ? rel.addend : 0),
246 file(isec.file) {}
247 uint32_t size() override { return 16; }
248 void writeTo(uint8_t *buf) override;
249 void addSymbols(ThunkSection &isec) override;
250 bool isCompatibleWith(const InputSection &isec, const Relocation &rel) const override;
251
252private:
253 // For R_PPC_PLTREL24, this records the addend, which will be used to decide
254 // the offsets in the call stub.
255 uint32_t addend;
256
257 // Records the call site of the call stub.
258 const InputFile *file;
259};
239260
240// PPC64 Plt call stubs.261// PPC64 Plt call stubs.
241// Any call site that needs to call through a plt entry needs a call stub in262// Any call site that needs to call through a plt entry needs a call stub in
...@@ -247,10 +268,10 @@ public:...@@ -247,10 +268,10 @@ public:
247// 3) Transfering control to the target function through an indirect branch.268// 3) Transfering control to the target function through an indirect branch.
248class PPC64PltCallStub final : public Thunk {269class PPC64PltCallStub final : public Thunk {
249public:270public:
250 PPC64PltCallStub(Symbol &Dest) : Thunk(Dest) {}271 PPC64PltCallStub(Symbol &dest) : Thunk(dest) {}
251 uint32_t size() override { return 20; }272 uint32_t size() override { return 20; }
252 void writeTo(uint8_t *Buf) override;273 void writeTo(uint8_t *buf) override;
253 void addSymbols(ThunkSection &IS) override;274 void addSymbols(ThunkSection &isec) override;
254};275};
255276
256// A bl instruction uses a signed 24 bit offset, with an implicit 4 byte277// A bl instruction uses a signed 24 bit offset, with an implicit 4 byte
...@@ -264,74 +285,75 @@ public:...@@ -264,74 +285,75 @@ public:
264class PPC64LongBranchThunk : public Thunk {285class PPC64LongBranchThunk : public Thunk {
265public:286public:
266 uint32_t size() override { return 16; }287 uint32_t size() override { return 16; }
267 void writeTo(uint8_t *Buf) override;288 void writeTo(uint8_t *buf) override;
268 void addSymbols(ThunkSection &IS) override;289 void addSymbols(ThunkSection &isec) override;
269290
270protected:291protected:
271 PPC64LongBranchThunk(Symbol &Dest) : Thunk(Dest) {}292 PPC64LongBranchThunk(Symbol &dest) : Thunk(dest) {}
272};293};
273294
274class PPC64PILongBranchThunk final : public PPC64LongBranchThunk {295class PPC64PILongBranchThunk final : public PPC64LongBranchThunk {
275public:296public:
276 PPC64PILongBranchThunk(Symbol &Dest) : PPC64LongBranchThunk(Dest) {297 PPC64PILongBranchThunk(Symbol &dest) : PPC64LongBranchThunk(dest) {
277 assert(!Dest.IsPreemptible);298 assert(!dest.isPreemptible);
278 if (Dest.isInPPC64Branchlt())299 if (dest.isInPPC64Branchlt())
279 return;300 return;
280301
281 In.PPC64LongBranchTarget->addEntry(Dest);302 in.ppc64LongBranchTarget->addEntry(dest);
282 In.RelaDyn->addReloc({Target->RelativeRel, In.PPC64LongBranchTarget,303 mainPart->relaDyn->addReloc(
283 Dest.getPPC64LongBranchOffset(), true, &Dest,304 {target->relativeRel, in.ppc64LongBranchTarget,
284 getPPC64GlobalEntryToLocalEntryOffset(Dest.StOther)});305 dest.getPPC64LongBranchOffset(), true, &dest,
306 getPPC64GlobalEntryToLocalEntryOffset(dest.stOther)});
285 }307 }
286};308};
287309
288class PPC64PDLongBranchThunk final : public PPC64LongBranchThunk {310class PPC64PDLongBranchThunk final : public PPC64LongBranchThunk {
289public:311public:
290 PPC64PDLongBranchThunk(Symbol &Dest) : PPC64LongBranchThunk(Dest) {312 PPC64PDLongBranchThunk(Symbol &dest) : PPC64LongBranchThunk(dest) {
291 if (!Dest.isInPPC64Branchlt())313 if (!dest.isInPPC64Branchlt())
292 In.PPC64LongBranchTarget->addEntry(Dest);314 in.ppc64LongBranchTarget->addEntry(dest);
293 }315 }
294};316};
295317
296} // end anonymous namespace318} // end anonymous namespace
297319
298Defined *Thunk::addSymbol(StringRef Name, uint8_t Type, uint64_t Value,320Defined *Thunk::addSymbol(StringRef name, uint8_t type, uint64_t value,
299 InputSectionBase &Section) {321 InputSectionBase &section) {
300 Defined *D = addSyntheticLocal(Name, Type, Value, /*Size=*/0, Section);322 Defined *d = addSyntheticLocal(name, type, value, /*size=*/0, section);
301 Syms.push_back(D);323 syms.push_back(d);
302 return D;324 return d;
303}325}
304326
305void Thunk::setOffset(uint64_t NewOffset) {327void Thunk::setOffset(uint64_t newOffset) {
306 for (Defined *D : Syms)328 for (Defined *d : syms)
307 D->Value = D->Value - Offset + NewOffset;329 d->value = d->value - offset + newOffset;
308 Offset = NewOffset;330 offset = newOffset;
309}331}
310332
311// AArch64 long range Thunks333// AArch64 long range Thunks
312334
313static uint64_t getAArch64ThunkDestVA(const Symbol &S) {335static uint64_t getAArch64ThunkDestVA(const Symbol &s) {
314 uint64_t V = S.isInPlt() ? S.getPltVA() : S.getVA();336 uint64_t v = s.isInPlt() ? s.getPltVA() : s.getVA();
315 return V;337 return v;
316}338}
317339
318void AArch64ABSLongThunk::writeTo(uint8_t *Buf) {340void AArch64ABSLongThunk::writeTo(uint8_t *buf) {
319 const uint8_t Data[] = {341 const uint8_t data[] = {
320 0x50, 0x00, 0x00, 0x58, // ldr x16, L0342 0x50, 0x00, 0x00, 0x58, // ldr x16, L0
321 0x00, 0x02, 0x1f, 0xd6, // br x16343 0x00, 0x02, 0x1f, 0xd6, // br x16
322 0x00, 0x00, 0x00, 0x00, // L0: .xword S344 0x00, 0x00, 0x00, 0x00, // L0: .xword S
323 0x00, 0x00, 0x00, 0x00,345 0x00, 0x00, 0x00, 0x00,
324 };346 };
325 uint64_t S = getAArch64ThunkDestVA(Destination);347 uint64_t s = getAArch64ThunkDestVA(destination);
326 memcpy(Buf, Data, sizeof(Data));348 memcpy(buf, data, sizeof(data));
327 Target->relocateOne(Buf + 8, R_AARCH64_ABS64, S);349 target->relocateOne(buf + 8, R_AARCH64_ABS64, s);
328}350}
329351
330void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) {352void AArch64ABSLongThunk::addSymbols(ThunkSection &isec) {
331 addSymbol(Saver.save("__AArch64AbsLongThunk_" + Destination.getName()),353 addSymbol(saver.save("__AArch64AbsLongThunk_" + destination.getName()),
332 STT_FUNC, 0, IS);354 STT_FUNC, 0, isec);
333 addSymbol("$x", STT_NOTYPE, 0, IS);355 addSymbol("$x", STT_NOTYPE, 0, isec);
334 addSymbol("$d", STT_NOTYPE, 8, IS);356 addSymbol("$d", STT_NOTYPE, 8, isec);
335}357}
336358
337// This Thunk has a maximum range of 4Gb, this is sufficient for all programs359// This Thunk has a maximum range of 4Gb, this is sufficient for all programs
...@@ -339,259 +361,263 @@ void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) {...@@ -339,259 +361,263 @@ void AArch64ABSLongThunk::addSymbols(ThunkSection &IS) {
339// clang and gcc do not support the large code model for position independent361// clang and gcc do not support the large code model for position independent
340// code so it is safe to use this for position independent thunks without362// code so it is safe to use this for position independent thunks without
341// worrying about the destination being more than 4Gb away.363// worrying about the destination being more than 4Gb away.
342void AArch64ADRPThunk::writeTo(uint8_t *Buf) {364void AArch64ADRPThunk::writeTo(uint8_t *buf) {
343 const uint8_t Data[] = {365 const uint8_t data[] = {
344 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest)366 0x10, 0x00, 0x00, 0x90, // adrp x16, Dest R_AARCH64_ADR_PREL_PG_HI21(Dest)
345 0x10, 0x02, 0x00, 0x91, // add x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest)367 0x10, 0x02, 0x00, 0x91, // add x16, x16, R_AARCH64_ADD_ABS_LO12_NC(Dest)
346 0x00, 0x02, 0x1f, 0xd6, // br x16368 0x00, 0x02, 0x1f, 0xd6, // br x16
347 };369 };
348 uint64_t S = getAArch64ThunkDestVA(Destination);370 uint64_t s = getAArch64ThunkDestVA(destination);
349 uint64_t P = getThunkTargetSym()->getVA();371 uint64_t p = getThunkTargetSym()->getVA();
350 memcpy(Buf, Data, sizeof(Data));372 memcpy(buf, data, sizeof(data));
351 Target->relocateOne(Buf, R_AARCH64_ADR_PREL_PG_HI21,373 target->relocateOne(buf, R_AARCH64_ADR_PREL_PG_HI21,
352 getAArch64Page(S) - getAArch64Page(P));374 getAArch64Page(s) - getAArch64Page(p));
353 Target->relocateOne(Buf + 4, R_AARCH64_ADD_ABS_LO12_NC, S);375 target->relocateOne(buf + 4, R_AARCH64_ADD_ABS_LO12_NC, s);
354}376}
355377
356void AArch64ADRPThunk::addSymbols(ThunkSection &IS) {378void AArch64ADRPThunk::addSymbols(ThunkSection &isec) {
357 addSymbol(Saver.save("__AArch64ADRPThunk_" + Destination.getName()), STT_FUNC,379 addSymbol(saver.save("__AArch64ADRPThunk_" + destination.getName()), STT_FUNC,
358 0, IS);380 0, isec);
359 addSymbol("$x", STT_NOTYPE, 0, IS);381 addSymbol("$x", STT_NOTYPE, 0, isec);
360}382}
361383
362// ARM Target Thunks384// ARM Target Thunks
363static uint64_t getARMThunkDestVA(const Symbol &S) {385static uint64_t getARMThunkDestVA(const Symbol &s) {
364 uint64_t V = S.isInPlt() ? S.getPltVA() : S.getVA();386 uint64_t v = s.isInPlt() ? s.getPltVA() : s.getVA();
365 return SignExtend64<32>(V);387 return SignExtend64<32>(v);
366}388}
367389
368// This function returns true if the target is not Thumb and is within 2^26, and390// This function returns true if the target is not Thumb and is within 2^26, and
369// it has not previously returned false (see comment for MayUseShortThunk).391// it has not previously returned false (see comment for mayUseShortThunk).
370bool ARMThunk::mayUseShortThunk() {392bool ARMThunk::getMayUseShortThunk() {
371 if (!MayUseShortThunk)393 if (!mayUseShortThunk)
372 return false;394 return false;
373 uint64_t S = getARMThunkDestVA(Destination);395 uint64_t s = getARMThunkDestVA(destination);
374 if (S & 1) {396 if (s & 1) {
375 MayUseShortThunk = false;397 mayUseShortThunk = false;
376 return false;398 return false;
377 }399 }
378 uint64_t P = getThunkTargetSym()->getVA();400 uint64_t p = getThunkTargetSym()->getVA();
379 int64_t Offset = S - P - 8;401 int64_t offset = s - p - 8;
380 MayUseShortThunk = llvm::isInt<26>(Offset);402 mayUseShortThunk = llvm::isInt<26>(offset);
381 return MayUseShortThunk;403 return mayUseShortThunk;
382}404}
383405
384void ARMThunk::writeTo(uint8_t *Buf) {406void ARMThunk::writeTo(uint8_t *buf) {
385 if (!mayUseShortThunk()) {407 if (!getMayUseShortThunk()) {
386 writeLong(Buf);408 writeLong(buf);
387 return;409 return;
388 }410 }
389411
390 uint64_t S = getARMThunkDestVA(Destination);412 uint64_t s = getARMThunkDestVA(destination);
391 uint64_t P = getThunkTargetSym()->getVA();413 uint64_t p = getThunkTargetSym()->getVA();
392 int64_t Offset = S - P - 8;414 int64_t offset = s - p - 8;
393 const uint8_t Data[] = {415 const uint8_t data[] = {
394 0x00, 0x00, 0x00, 0xea, // b S416 0x00, 0x00, 0x00, 0xea, // b S
395 };417 };
396 memcpy(Buf, Data, sizeof(Data));418 memcpy(buf, data, sizeof(data));
397 Target->relocateOne(Buf, R_ARM_JUMP24, Offset);419 target->relocateOne(buf, R_ARM_JUMP24, offset);
398}420}
399421
400bool ARMThunk::isCompatibleWith(RelType Type) const {422bool ARMThunk::isCompatibleWith(const InputSection &isec,
423 const Relocation &rel) const {
401 // Thumb branch relocations can't use BLX424 // Thumb branch relocations can't use BLX
402 return Type != R_ARM_THM_JUMP19 && Type != R_ARM_THM_JUMP24;425 return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24;
403}426}
404427
405// This function returns true if the target is Thumb and is within 2^25, and428// This function returns true if the target is Thumb and is within 2^25, and
406// it has not previously returned false (see comment for MayUseShortThunk).429// it has not previously returned false (see comment for mayUseShortThunk).
407bool ThumbThunk::mayUseShortThunk() {430bool ThumbThunk::getMayUseShortThunk() {
408 if (!MayUseShortThunk)431 if (!mayUseShortThunk)
409 return false;432 return false;
410 uint64_t S = getARMThunkDestVA(Destination);433 uint64_t s = getARMThunkDestVA(destination);
411 if ((S & 1) == 0) {434 if ((s & 1) == 0) {
412 MayUseShortThunk = false;435 mayUseShortThunk = false;
413 return false;436 return false;
414 }437 }
415 uint64_t P = getThunkTargetSym()->getVA() & ~1;438 uint64_t p = getThunkTargetSym()->getVA() & ~1;
416 int64_t Offset = S - P - 4;439 int64_t offset = s - p - 4;
417 MayUseShortThunk = llvm::isInt<25>(Offset);440 mayUseShortThunk = llvm::isInt<25>(offset);
418 return MayUseShortThunk;441 return mayUseShortThunk;
419}442}
420443
421void ThumbThunk::writeTo(uint8_t *Buf) {444void ThumbThunk::writeTo(uint8_t *buf) {
422 if (!mayUseShortThunk()) {445 if (!getMayUseShortThunk()) {
423 writeLong(Buf);446 writeLong(buf);
424 return;447 return;
425 }448 }
426449
427 uint64_t S = getARMThunkDestVA(Destination);450 uint64_t s = getARMThunkDestVA(destination);
428 uint64_t P = getThunkTargetSym()->getVA();451 uint64_t p = getThunkTargetSym()->getVA();
429 int64_t Offset = S - P - 4;452 int64_t offset = s - p - 4;
430 const uint8_t Data[] = {453 const uint8_t data[] = {
431 0x00, 0xf0, 0x00, 0xb0, // b.w S454 0x00, 0xf0, 0x00, 0xb0, // b.w S
432 };455 };
433 memcpy(Buf, Data, sizeof(Data));456 memcpy(buf, data, sizeof(data));
434 Target->relocateOne(Buf, R_ARM_THM_JUMP24, Offset);457 target->relocateOne(buf, R_ARM_THM_JUMP24, offset);
435}458}
436459
437bool ThumbThunk::isCompatibleWith(RelType Type) const {460bool ThumbThunk::isCompatibleWith(const InputSection &isec,
461 const Relocation &rel) const {
438 // ARM branch relocations can't use BLX462 // ARM branch relocations can't use BLX
439 return Type != R_ARM_JUMP24 && Type != R_ARM_PC24 && Type != R_ARM_PLT32;463 return rel.type != R_ARM_JUMP24 && rel.type != R_ARM_PC24 && rel.type != R_ARM_PLT32;
440}464}
441465
442void ARMV7ABSLongThunk::writeLong(uint8_t *Buf) {466void ARMV7ABSLongThunk::writeLong(uint8_t *buf) {
443 const uint8_t Data[] = {467 const uint8_t data[] = {
444 0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S468 0x00, 0xc0, 0x00, 0xe3, // movw ip,:lower16:S
445 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S469 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S
446 0x1c, 0xff, 0x2f, 0xe1, // bx ip470 0x1c, 0xff, 0x2f, 0xe1, // bx ip
447 };471 };
448 uint64_t S = getARMThunkDestVA(Destination);472 uint64_t s = getARMThunkDestVA(destination);
449 memcpy(Buf, Data, sizeof(Data));473 memcpy(buf, data, sizeof(data));
450 Target->relocateOne(Buf, R_ARM_MOVW_ABS_NC, S);474 target->relocateOne(buf, R_ARM_MOVW_ABS_NC, s);
451 Target->relocateOne(Buf + 4, R_ARM_MOVT_ABS, S);475 target->relocateOne(buf + 4, R_ARM_MOVT_ABS, s);
452}476}
453477
454void ARMV7ABSLongThunk::addSymbols(ThunkSection &IS) {478void ARMV7ABSLongThunk::addSymbols(ThunkSection &isec) {
455 addSymbol(Saver.save("__ARMv7ABSLongThunk_" + Destination.getName()),479 addSymbol(saver.save("__ARMv7ABSLongThunk_" + destination.getName()),
456 STT_FUNC, 0, IS);480 STT_FUNC, 0, isec);
457 addSymbol("$a", STT_NOTYPE, 0, IS);481 addSymbol("$a", STT_NOTYPE, 0, isec);
458}482}
459483
460void ThumbV7ABSLongThunk::writeLong(uint8_t *Buf) {484void ThumbV7ABSLongThunk::writeLong(uint8_t *buf) {
461 const uint8_t Data[] = {485 const uint8_t data[] = {
462 0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S486 0x40, 0xf2, 0x00, 0x0c, // movw ip, :lower16:S
463 0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S487 0xc0, 0xf2, 0x00, 0x0c, // movt ip, :upper16:S
464 0x60, 0x47, // bx ip488 0x60, 0x47, // bx ip
465 };489 };
466 uint64_t S = getARMThunkDestVA(Destination);490 uint64_t s = getARMThunkDestVA(destination);
467 memcpy(Buf, Data, sizeof(Data));491 memcpy(buf, data, sizeof(data));
468 Target->relocateOne(Buf, R_ARM_THM_MOVW_ABS_NC, S);492 target->relocateOne(buf, R_ARM_THM_MOVW_ABS_NC, s);
469 Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_ABS, S);493 target->relocateOne(buf + 4, R_ARM_THM_MOVT_ABS, s);
470}494}
471495
472void ThumbV7ABSLongThunk::addSymbols(ThunkSection &IS) {496void ThumbV7ABSLongThunk::addSymbols(ThunkSection &isec) {
473 addSymbol(Saver.save("__Thumbv7ABSLongThunk_" + Destination.getName()),497 addSymbol(saver.save("__Thumbv7ABSLongThunk_" + destination.getName()),
474 STT_FUNC, 1, IS);498 STT_FUNC, 1, isec);
475 addSymbol("$t", STT_NOTYPE, 0, IS);499 addSymbol("$t", STT_NOTYPE, 0, isec);
476}500}
477501
478void ARMV7PILongThunk::writeLong(uint8_t *Buf) {502void ARMV7PILongThunk::writeLong(uint8_t *buf) {
479 const uint8_t Data[] = {503 const uint8_t data[] = {
480 0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) + 8)504 0xf0, 0xcf, 0x0f, 0xe3, // P: movw ip,:lower16:S - (P + (L1-P) + 8)
481 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P) + 8)505 0x00, 0xc0, 0x40, 0xe3, // movt ip,:upper16:S - (P + (L1-P) + 8)
482 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc506 0x0f, 0xc0, 0x8c, 0xe0, // L1: add ip, ip, pc
483 0x1c, 0xff, 0x2f, 0xe1, // bx ip507 0x1c, 0xff, 0x2f, 0xe1, // bx ip
484 };508 };
485 uint64_t S = getARMThunkDestVA(Destination);509 uint64_t s = getARMThunkDestVA(destination);
486 uint64_t P = getThunkTargetSym()->getVA();510 uint64_t p = getThunkTargetSym()->getVA();
487 int64_t Offset = S - P - 16;511 int64_t offset = s - p - 16;
488 memcpy(Buf, Data, sizeof(Data));512 memcpy(buf, data, sizeof(data));
489 Target->relocateOne(Buf, R_ARM_MOVW_PREL_NC, Offset);513 target->relocateOne(buf, R_ARM_MOVW_PREL_NC, offset);
490 Target->relocateOne(Buf + 4, R_ARM_MOVT_PREL, Offset);514 target->relocateOne(buf + 4, R_ARM_MOVT_PREL, offset);
491}515}
492516
493void ARMV7PILongThunk::addSymbols(ThunkSection &IS) {517void ARMV7PILongThunk::addSymbols(ThunkSection &isec) {
494 addSymbol(Saver.save("__ARMV7PILongThunk_" + Destination.getName()), STT_FUNC,518 addSymbol(saver.save("__ARMV7PILongThunk_" + destination.getName()), STT_FUNC,
495 0, IS);519 0, isec);
496 addSymbol("$a", STT_NOTYPE, 0, IS);520 addSymbol("$a", STT_NOTYPE, 0, isec);
497}521}
498522
499void ThumbV7PILongThunk::writeLong(uint8_t *Buf) {523void ThumbV7PILongThunk::writeLong(uint8_t *buf) {
500 const uint8_t Data[] = {524 const uint8_t data[] = {
501 0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)525 0x4f, 0xf6, 0xf4, 0x7c, // P: movw ip,:lower16:S - (P + (L1-P) + 4)
502 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4)526 0xc0, 0xf2, 0x00, 0x0c, // movt ip,:upper16:S - (P + (L1-P) + 4)
503 0xfc, 0x44, // L1: add ip, pc527 0xfc, 0x44, // L1: add ip, pc
504 0x60, 0x47, // bx ip528 0x60, 0x47, // bx ip
505 };529 };
506 uint64_t S = getARMThunkDestVA(Destination);530 uint64_t s = getARMThunkDestVA(destination);
507 uint64_t P = getThunkTargetSym()->getVA() & ~0x1;531 uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
508 int64_t Offset = S - P - 12;532 int64_t offset = s - p - 12;
509 memcpy(Buf, Data, sizeof(Data));533 memcpy(buf, data, sizeof(data));
510 Target->relocateOne(Buf, R_ARM_THM_MOVW_PREL_NC, Offset);534 target->relocateOne(buf, R_ARM_THM_MOVW_PREL_NC, offset);
511 Target->relocateOne(Buf + 4, R_ARM_THM_MOVT_PREL, Offset);535 target->relocateOne(buf + 4, R_ARM_THM_MOVT_PREL, offset);
512}536}
513537
514void ThumbV7PILongThunk::addSymbols(ThunkSection &IS) {538void ThumbV7PILongThunk::addSymbols(ThunkSection &isec) {
515 addSymbol(Saver.save("__ThumbV7PILongThunk_" + Destination.getName()),539 addSymbol(saver.save("__ThumbV7PILongThunk_" + destination.getName()),
516 STT_FUNC, 1, IS);540 STT_FUNC, 1, isec);
517 addSymbol("$t", STT_NOTYPE, 0, IS);541 addSymbol("$t", STT_NOTYPE, 0, isec);
518}542}
519543
520void ARMV5ABSLongThunk::writeLong(uint8_t *Buf) {544void ARMV5ABSLongThunk::writeLong(uint8_t *buf) {
521 const uint8_t Data[] = {545 const uint8_t data[] = {
522 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc,#-4] ; L1546 0x04, 0xf0, 0x1f, 0xe5, // ldr pc, [pc,#-4] ; L1
523 0x00, 0x00, 0x00, 0x00, // L1: .word S547 0x00, 0x00, 0x00, 0x00, // L1: .word S
524 };548 };
525 memcpy(Buf, Data, sizeof(Data));549 memcpy(buf, data, sizeof(data));
526 Target->relocateOne(Buf + 4, R_ARM_ABS32, getARMThunkDestVA(Destination));550 target->relocateOne(buf + 4, R_ARM_ABS32, getARMThunkDestVA(destination));
527}551}
528552
529void ARMV5ABSLongThunk::addSymbols(ThunkSection &IS) {553void ARMV5ABSLongThunk::addSymbols(ThunkSection &isec) {
530 addSymbol(Saver.save("__ARMv5ABSLongThunk_" + Destination.getName()),554 addSymbol(saver.save("__ARMv5ABSLongThunk_" + destination.getName()),
531 STT_FUNC, 0, IS);555 STT_FUNC, 0, isec);
532 addSymbol("$a", STT_NOTYPE, 0, IS);556 addSymbol("$a", STT_NOTYPE, 0, isec);
533 addSymbol("$d", STT_NOTYPE, 4, IS);557 addSymbol("$d", STT_NOTYPE, 4, isec);
534}558}
535559
536bool ARMV5ABSLongThunk::isCompatibleWith(uint32_t RelocType) const {560bool ARMV5ABSLongThunk::isCompatibleWith(const InputSection &isec,
561 const Relocation &rel) const {
537 // Thumb branch relocations can't use BLX562 // Thumb branch relocations can't use BLX
538 return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;563 return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24;
539}564}
540565
541void ARMV5PILongThunk::writeLong(uint8_t *Buf) {566void ARMV5PILongThunk::writeLong(uint8_t *buf) {
542 const uint8_t Data[] = {567 const uint8_t data[] = {
543 0x04, 0xc0, 0x9f, 0xe5, // P: ldr ip, [pc,#4] ; L2568 0x04, 0xc0, 0x9f, 0xe5, // P: ldr ip, [pc,#4] ; L2
544 0x0c, 0xc0, 0x8f, 0xe0, // L1: add ip, pc, ip569 0x0c, 0xc0, 0x8f, 0xe0, // L1: add ip, pc, ip
545 0x1c, 0xff, 0x2f, 0xe1, // bx ip570 0x1c, 0xff, 0x2f, 0xe1, // bx ip
546 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 8)571 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 8)
547 };572 };
548 uint64_t S = getARMThunkDestVA(Destination);573 uint64_t s = getARMThunkDestVA(destination);
549 uint64_t P = getThunkTargetSym()->getVA() & ~0x1;574 uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
550 memcpy(Buf, Data, sizeof(Data));575 memcpy(buf, data, sizeof(data));
551 Target->relocateOne(Buf + 12, R_ARM_REL32, S - P - 12);576 target->relocateOne(buf + 12, R_ARM_REL32, s - p - 12);
552}577}
553578
554void ARMV5PILongThunk::addSymbols(ThunkSection &IS) {579void ARMV5PILongThunk::addSymbols(ThunkSection &isec) {
555 addSymbol(Saver.save("__ARMV5PILongThunk_" + Destination.getName()), STT_FUNC,580 addSymbol(saver.save("__ARMV5PILongThunk_" + destination.getName()), STT_FUNC,
556 0, IS);581 0, isec);
557 addSymbol("$a", STT_NOTYPE, 0, IS);582 addSymbol("$a", STT_NOTYPE, 0, isec);
558 addSymbol("$d", STT_NOTYPE, 12, IS);583 addSymbol("$d", STT_NOTYPE, 12, isec);
559}584}
560585
561bool ARMV5PILongThunk::isCompatibleWith(uint32_t RelocType) const {586bool ARMV5PILongThunk::isCompatibleWith(const InputSection &isec,
587 const Relocation &rel) const {
562 // Thumb branch relocations can't use BLX588 // Thumb branch relocations can't use BLX
563 return RelocType != R_ARM_THM_JUMP19 && RelocType != R_ARM_THM_JUMP24;589 return rel.type != R_ARM_THM_JUMP19 && rel.type != R_ARM_THM_JUMP24;
564}590}
565591
566void ThumbV6MABSLongThunk::writeLong(uint8_t *Buf) {592void ThumbV6MABSLongThunk::writeLong(uint8_t *buf) {
567 // Most Thumb instructions cannot access the high registers r8 - r15. As the593 // 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 register594 // 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 we595 // 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.596 // don't need to get some space to use for the return address.
571 const uint8_t Data[] = {597 const uint8_t data[] = {
572 0x03, 0xb4, // push {r0, r1} ; Obtain scratch registers598 0x03, 0xb4, // push {r0, r1} ; Obtain scratch registers
573 0x01, 0x48, // ldr r0, [pc, #4] ; L1599 0x01, 0x48, // ldr r0, [pc, #4] ; L1
574 0x01, 0x90, // str r0, [sp, #4] ; SP + 4 = S600 0x01, 0x90, // str r0, [sp, #4] ; SP + 4 = S
575 0x01, 0xbd, // pop {r0, pc} ; restore r0 and branch to dest601 0x01, 0xbd, // pop {r0, pc} ; restore r0 and branch to dest
576 0x00, 0x00, 0x00, 0x00 // L1: .word S602 0x00, 0x00, 0x00, 0x00 // L1: .word S
577 };603 };
578 uint64_t S = getARMThunkDestVA(Destination);604 uint64_t s = getARMThunkDestVA(destination);
579 memcpy(Buf, Data, sizeof(Data));605 memcpy(buf, data, sizeof(data));
580 Target->relocateOne(Buf + 8, R_ARM_ABS32, S);606 target->relocateOne(buf + 8, R_ARM_ABS32, s);
581}607}
582608
583void ThumbV6MABSLongThunk::addSymbols(ThunkSection &IS) {609void ThumbV6MABSLongThunk::addSymbols(ThunkSection &isec) {
584 addSymbol(Saver.save("__Thumbv6MABSLongThunk_" + Destination.getName()),610 addSymbol(saver.save("__Thumbv6MABSLongThunk_" + destination.getName()),
585 STT_FUNC, 1, IS);611 STT_FUNC, 1, isec);
586 addSymbol("$t", STT_NOTYPE, 0, IS);612 addSymbol("$t", STT_NOTYPE, 0, isec);
587 addSymbol("$d", STT_NOTYPE, 8, IS);613 addSymbol("$d", STT_NOTYPE, 8, isec);
588}614}
589615
590void ThumbV6MPILongThunk::writeLong(uint8_t *Buf) {616void ThumbV6MPILongThunk::writeLong(uint8_t *buf) {
591 // Most Thumb instructions cannot access the high registers r8 - r15. As the617 // 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 low618 // 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.619 // register to the stack to use as a scratch register.
594 const uint8_t Data[] = {620 const uint8_t data[] = {
595 0x01, 0xb4, // P: push {r0} ; Obtain scratch register621 0x01, 0xb4, // P: push {r0} ; Obtain scratch register
596 0x02, 0x48, // ldr r0, [pc, #8] ; L2622 0x02, 0x48, // ldr r0, [pc, #8] ; L2
597 0x84, 0x46, // mov ip, r0 ; high to low register623 0x84, 0x46, // mov ip, r0 ; high to low register
...@@ -600,131 +626,185 @@ void ThumbV6MPILongThunk::writeLong(uint8_t *Buf) {...@@ -600,131 +626,185 @@ void ThumbV6MPILongThunk::writeLong(uint8_t *Buf) {
600 0xc0, 0x46, // nop ; pad to 4-byte boundary626 0xc0, 0x46, // nop ; pad to 4-byte boundary
601 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 4)627 0x00, 0x00, 0x00, 0x00, // L2: .word S - (P + (L1 - P) + 4)
602 };628 };
603 uint64_t S = getARMThunkDestVA(Destination);629 uint64_t s = getARMThunkDestVA(destination);
604 uint64_t P = getThunkTargetSym()->getVA() & ~0x1;630 uint64_t p = getThunkTargetSym()->getVA() & ~0x1;
605 memcpy(Buf, Data, sizeof(Data));631 memcpy(buf, data, sizeof(data));
606 Target->relocateOne(Buf + 12, R_ARM_REL32, S - P - 12);632 target->relocateOne(buf + 12, R_ARM_REL32, s - p - 12);
607}633}
608634
609void ThumbV6MPILongThunk::addSymbols(ThunkSection &IS) {635void ThumbV6MPILongThunk::addSymbols(ThunkSection &isec) {
610 addSymbol(Saver.save("__Thumbv6MPILongThunk_" + Destination.getName()),636 addSymbol(saver.save("__Thumbv6MPILongThunk_" + destination.getName()),
611 STT_FUNC, 1, IS);637 STT_FUNC, 1, isec);
612 addSymbol("$t", STT_NOTYPE, 0, IS);638 addSymbol("$t", STT_NOTYPE, 0, isec);
613 addSymbol("$d", STT_NOTYPE, 12, IS);639 addSymbol("$d", STT_NOTYPE, 12, isec);
614}640}
615641
616// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.642// Write MIPS LA25 thunk code to call PIC function from the non-PIC one.
617void MipsThunk::writeTo(uint8_t *Buf) {643void MipsThunk::writeTo(uint8_t *buf) {
618 uint64_t S = Destination.getVA();644 uint64_t s = destination.getVA();
619 write32(Buf, 0x3c190000); // lui $25, %hi(func)645 write32(buf, 0x3c190000); // lui $25, %hi(func)
620 write32(Buf + 4, 0x08000000 | (S >> 2)); // j func646 write32(buf + 4, 0x08000000 | (s >> 2)); // j func
621 write32(Buf + 8, 0x27390000); // addiu $25, $25, %lo(func)647 write32(buf + 8, 0x27390000); // addiu $25, $25, %lo(func)
622 write32(Buf + 12, 0x00000000); // nop648 write32(buf + 12, 0x00000000); // nop
623 Target->relocateOne(Buf, R_MIPS_HI16, S);649 target->relocateOne(buf, R_MIPS_HI16, s);
624 Target->relocateOne(Buf + 8, R_MIPS_LO16, S);650 target->relocateOne(buf + 8, R_MIPS_LO16, s);
625}651}
626652
627void MipsThunk::addSymbols(ThunkSection &IS) {653void MipsThunk::addSymbols(ThunkSection &isec) {
628 addSymbol(Saver.save("__LA25Thunk_" + Destination.getName()), STT_FUNC, 0,654 addSymbol(saver.save("__LA25Thunk_" + destination.getName()), STT_FUNC, 0,
629 IS);655 isec);
630}656}
631657
632InputSection *MipsThunk::getTargetInputSection() const {658InputSection *MipsThunk::getTargetInputSection() const {
633 auto &DR = cast<Defined>(Destination);659 auto &dr = cast<Defined>(destination);
634 return dyn_cast<InputSection>(DR.Section);660 return dyn_cast<InputSection>(dr.section);
635}661}
636662
637// Write microMIPS R2-R5 LA25 thunk code663// Write microMIPS R2-R5 LA25 thunk code
638// to call PIC function from the non-PIC one.664// to call PIC function from the non-PIC one.
639void MicroMipsThunk::writeTo(uint8_t *Buf) {665void MicroMipsThunk::writeTo(uint8_t *buf) {
640 uint64_t S = Destination.getVA() | 1;666 uint64_t s = destination.getVA();
641 write16(Buf, 0x41b9); // lui $25, %hi(func)667 write16(buf, 0x41b9); // lui $25, %hi(func)
642 write16(Buf + 4, 0xd400); // j func668 write16(buf + 4, 0xd400); // j func
643 write16(Buf + 8, 0x3339); // addiu $25, $25, %lo(func)669 write16(buf + 8, 0x3339); // addiu $25, $25, %lo(func)
644 write16(Buf + 12, 0x0c00); // nop670 write16(buf + 12, 0x0c00); // nop
645 Target->relocateOne(Buf, R_MICROMIPS_HI16, S);671 target->relocateOne(buf, R_MICROMIPS_HI16, s);
646 Target->relocateOne(Buf + 4, R_MICROMIPS_26_S1, S);672 target->relocateOne(buf + 4, R_MICROMIPS_26_S1, s);
647 Target->relocateOne(Buf + 8, R_MICROMIPS_LO16, S);673 target->relocateOne(buf + 8, R_MICROMIPS_LO16, s);
648}674}
649675
650void MicroMipsThunk::addSymbols(ThunkSection &IS) {676void MicroMipsThunk::addSymbols(ThunkSection &isec) {
651 Defined *D = addSymbol(677 Defined *d = addSymbol(
652 Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS);678 saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec);
653 D->StOther |= STO_MIPS_MICROMIPS;679 d->stOther |= STO_MIPS_MICROMIPS;
654}680}
655681
656InputSection *MicroMipsThunk::getTargetInputSection() const {682InputSection *MicroMipsThunk::getTargetInputSection() const {
657 auto &DR = cast<Defined>(Destination);683 auto &dr = cast<Defined>(destination);
658 return dyn_cast<InputSection>(DR.Section);684 return dyn_cast<InputSection>(dr.section);
659}685}
660686
661// Write microMIPS R6 LA25 thunk code687// Write microMIPS R6 LA25 thunk code
662// to call PIC function from the non-PIC one.688// to call PIC function from the non-PIC one.
663void MicroMipsR6Thunk::writeTo(uint8_t *Buf) {689void MicroMipsR6Thunk::writeTo(uint8_t *buf) {
664 uint64_t S = Destination.getVA() | 1;690 uint64_t s = destination.getVA();
665 uint64_t P = getThunkTargetSym()->getVA();691 uint64_t p = getThunkTargetSym()->getVA();
666 write16(Buf, 0x1320); // lui $25, %hi(func)692 write16(buf, 0x1320); // lui $25, %hi(func)
667 write16(Buf + 4, 0x3339); // addiu $25, $25, %lo(func)693 write16(buf + 4, 0x3339); // addiu $25, $25, %lo(func)
668 write16(Buf + 8, 0x9400); // bc func694 write16(buf + 8, 0x9400); // bc func
669 Target->relocateOne(Buf, R_MICROMIPS_HI16, S);695 target->relocateOne(buf, R_MICROMIPS_HI16, s);
670 Target->relocateOne(Buf + 4, R_MICROMIPS_LO16, S);696 target->relocateOne(buf + 4, R_MICROMIPS_LO16, s);
671 Target->relocateOne(Buf + 8, R_MICROMIPS_PC26_S1, S - P - 12);697 target->relocateOne(buf + 8, R_MICROMIPS_PC26_S1, s - p - 12);
672}698}
673699
674void MicroMipsR6Thunk::addSymbols(ThunkSection &IS) {700void MicroMipsR6Thunk::addSymbols(ThunkSection &isec) {
675 Defined *D = addSymbol(701 Defined *d = addSymbol(
676 Saver.save("__microLA25Thunk_" + Destination.getName()), STT_FUNC, 0, IS);702 saver.save("__microLA25Thunk_" + destination.getName()), STT_FUNC, 0, isec);
677 D->StOther |= STO_MIPS_MICROMIPS;703 d->stOther |= STO_MIPS_MICROMIPS;
678}704}
679705
680InputSection *MicroMipsR6Thunk::getTargetInputSection() const {706InputSection *MicroMipsR6Thunk::getTargetInputSection() const {
681 auto &DR = cast<Defined>(Destination);707 auto &dr = cast<Defined>(destination);
682 return dyn_cast<InputSection>(DR.Section);708 return dyn_cast<InputSection>(dr.section);
683}709}
684710
685static void writePPCLoadAndBranch(uint8_t *Buf, int64_t Offset) {711void PPC32PltCallStub::writeTo(uint8_t *buf) {
686 uint16_t OffHa = (Offset + 0x8000) >> 16;712 if (!config->isPic) {
687 uint16_t OffLo = Offset & 0xffff;713 uint64_t va = destination.getGotPltVA();
714 write32(buf + 0, 0x3d600000 | (va + 0x8000) >> 16); // lis r11,ha
715 write32(buf + 4, 0x816b0000 | (uint16_t)va); // lwz r11,l(r11)
716 write32(buf + 8, 0x7d6903a6); // mtctr r11
717 write32(buf + 12, 0x4e800420); // bctr
718 return;
719 }
720 uint32_t offset;
721 if (addend >= 0x8000) {
722 // The stub loads an address relative to r30 (.got2+Addend). Addend is
723 // almost always 0x8000. The address of .got2 is different in another object
724 // file, so a stub cannot be shared.
725 offset = destination.getGotPltVA() - (in.ppc32Got2->getParent()->getVA() +
726 file->ppc32Got2OutSecOff + addend);
727 } else {
728 // The stub loads an address relative to _GLOBAL_OFFSET_TABLE_ (which is
729 // currently the address of .got).
730 offset = destination.getGotPltVA() - in.got->getVA();
731 }
732 uint16_t ha = (offset + 0x8000) >> 16, l = (uint16_t)offset;
733 if (ha == 0) {
734 write32(buf + 0, 0x817e0000 | l); // lwz r11,l(r30)
735 write32(buf + 4, 0x7d6903a6); // mtctr r11
736 write32(buf + 8, 0x4e800420); // bctr
737 write32(buf + 12, 0x60000000); // nop
738 } else {
739 write32(buf + 0, 0x3d7e0000 | ha); // addis r11,r30,ha
740 write32(buf + 4, 0x816b0000 | l); // lwz r11,l(r11)
741 write32(buf + 8, 0x7d6903a6); // mtctr r11
742 write32(buf + 12, 0x4e800420); // bctr
743 }
744}
745
746void PPC32PltCallStub::addSymbols(ThunkSection &isec) {
747 std::string buf;
748 raw_string_ostream os(buf);
749 os << format_hex_no_prefix(addend, 8);
750 if (!config->isPic)
751 os << ".plt_call32.";
752 else if (addend >= 0x8000)
753 os << ".got2.plt_pic32.";
754 else
755 os << ".plt_pic32.";
756 os << destination.getName();
757 addSymbol(saver.save(os.str()), STT_FUNC, 0, isec);
758}
759
760bool PPC32PltCallStub::isCompatibleWith(const InputSection &isec,
761 const Relocation &rel) const {
762 return !config->isPic || (isec.file == file && rel.addend == addend);
763}
688764
689 write32(Buf + 0, 0x3d820000 | OffHa); // addis r12, r2, OffHa765static void writePPCLoadAndBranch(uint8_t *buf, int64_t offset) {
690 write32(Buf + 4, 0xe98c0000 | OffLo); // ld r12, OffLo(r12)766 uint16_t offHa = (offset + 0x8000) >> 16;
691 write32(Buf + 8, 0x7d8903a6); // mtctr r12767 uint16_t offLo = offset & 0xffff;
692 write32(Buf + 12, 0x4e800420); // bctr768
769 write32(buf + 0, 0x3d820000 | offHa); // addis r12, r2, OffHa
770 write32(buf + 4, 0xe98c0000 | offLo); // ld r12, OffLo(r12)
771 write32(buf + 8, 0x7d8903a6); // mtctr r12
772 write32(buf + 12, 0x4e800420); // bctr
693}773}
694774
695void PPC64PltCallStub::writeTo(uint8_t *Buf) {775void PPC64PltCallStub::writeTo(uint8_t *buf) {
696 int64_t Offset = Destination.getGotPltVA() - getPPC64TocBase();776 int64_t offset = destination.getGotPltVA() - getPPC64TocBase();
697 // Save the TOC pointer to the save-slot reserved in the call frame.777 // Save the TOC pointer to the save-slot reserved in the call frame.
698 write32(Buf + 0, 0xf8410018); // std r2,24(r1)778 write32(buf + 0, 0xf8410018); // std r2,24(r1)
699 writePPCLoadAndBranch(Buf + 4, Offset);779 writePPCLoadAndBranch(buf + 4, offset);
700}780}
701781
702void PPC64PltCallStub::addSymbols(ThunkSection &IS) {782void PPC64PltCallStub::addSymbols(ThunkSection &isec) {
703 Defined *S = addSymbol(Saver.save("__plt_" + Destination.getName()), STT_FUNC,783 Defined *s = addSymbol(saver.save("__plt_" + destination.getName()), STT_FUNC,
704 0, IS);784 0, isec);
705 S->NeedsTocRestore = true;785 s->needsTocRestore = true;
706}786}
707787
708void PPC64LongBranchThunk::writeTo(uint8_t *Buf) {788void PPC64LongBranchThunk::writeTo(uint8_t *buf) {
709 int64_t Offset = Destination.getPPC64LongBranchTableVA() - getPPC64TocBase();789 int64_t offset = destination.getPPC64LongBranchTableVA() - getPPC64TocBase();
710 writePPCLoadAndBranch(Buf, Offset);790 writePPCLoadAndBranch(buf, offset);
711}791}
712792
713void PPC64LongBranchThunk::addSymbols(ThunkSection &IS) {793void PPC64LongBranchThunk::addSymbols(ThunkSection &isec) {
714 addSymbol(Saver.save("__long_branch_" + Destination.getName()), STT_FUNC, 0,794 addSymbol(saver.save("__long_branch_" + destination.getName()), STT_FUNC, 0,
715 IS);795 isec);
716}796}
717797
718Thunk::Thunk(Symbol &D) : Destination(D), Offset(0) {}798Thunk::Thunk(Symbol &d) : destination(d), offset(0) {}
719799
720Thunk::~Thunk() = default;800Thunk::~Thunk() = default;
721801
722static Thunk *addThunkAArch64(RelType Type, Symbol &S) {802static Thunk *addThunkAArch64(RelType type, Symbol &s) {
723 if (Type != R_AARCH64_CALL26 && Type != R_AARCH64_JUMP26)803 if (type != R_AARCH64_CALL26 && type != R_AARCH64_JUMP26)
724 fatal("unrecognized relocation type");804 fatal("unrecognized relocation type");
725 if (Config->PicThunk)805 if (config->picThunk)
726 return make<AArch64ADRPThunk>(S);806 return make<AArch64ADRPThunk>(s);
727 return make<AArch64ABSLongThunk>(S);807 return make<AArch64ABSLongThunk>(s);
728}808}
729809
730// Creates a thunk for Thumb-ARM interworking.810// Creates a thunk for Thumb-ARM interworking.
...@@ -732,18 +812,18 @@ static Thunk *addThunkAArch64(RelType Type, Symbol &S) {...@@ -732,18 +812,18 @@ static Thunk *addThunkAArch64(RelType Type, Symbol &S) {
732// - MOVT and MOVW instructions cannot be used812// - MOVT and MOVW instructions cannot be used
733// - Only Thumb relocation that can generate a Thunk is a BL, this can always813// - Only Thumb relocation that can generate a Thunk is a BL, this can always
734// be transformed into a BLX814// be transformed into a BLX
735static Thunk *addThunkPreArmv7(RelType Reloc, Symbol &S) {815static Thunk *addThunkPreArmv7(RelType reloc, Symbol &s) {
736 switch (Reloc) {816 switch (reloc) {
737 case R_ARM_PC24:817 case R_ARM_PC24:
738 case R_ARM_PLT32:818 case R_ARM_PLT32:
739 case R_ARM_JUMP24:819 case R_ARM_JUMP24:
740 case R_ARM_CALL:820 case R_ARM_CALL:
741 case R_ARM_THM_CALL:821 case R_ARM_THM_CALL:
742 if (Config->PicThunk)822 if (config->picThunk)
743 return make<ARMV5PILongThunk>(S);823 return make<ARMV5PILongThunk>(s);
744 return make<ARMV5ABSLongThunk>(S);824 return make<ARMV5ABSLongThunk>(s);
745 }825 }
746 fatal("relocation " + toString(Reloc) + " to " + toString(S) +826 fatal("relocation " + toString(reloc) + " to " + toString(s) +
747 " not supported for Armv5 or Armv6 targets");827 " not supported for Armv5 or Armv6 targets");
748}828}
749829
...@@ -752,21 +832,21 @@ static Thunk *addThunkPreArmv7(RelType Reloc, Symbol &S) {...@@ -752,21 +832,21 @@ static Thunk *addThunkPreArmv7(RelType Reloc, Symbol &S) {
752// - MOVT and MOVW instructions cannot be used.832// - MOVT and MOVW instructions cannot be used.
753// - Only a limited number of instructions can access registers r8 and above833// - Only a limited number of instructions can access registers r8 and above
754// - No interworking support is needed (all Thumb).834// - No interworking support is needed (all Thumb).
755static Thunk *addThunkV6M(RelType Reloc, Symbol &S) {835static Thunk *addThunkV6M(RelType reloc, Symbol &s) {
756 switch (Reloc) {836 switch (reloc) {
757 case R_ARM_THM_JUMP19:837 case R_ARM_THM_JUMP19:
758 case R_ARM_THM_JUMP24:838 case R_ARM_THM_JUMP24:
759 case R_ARM_THM_CALL:839 case R_ARM_THM_CALL:
760 if (Config->Pic)840 if (config->isPic)
761 return make<ThumbV6MPILongThunk>(S);841 return make<ThumbV6MPILongThunk>(s);
762 return make<ThumbV6MABSLongThunk>(S);842 return make<ThumbV6MABSLongThunk>(s);
763 }843 }
764 fatal("relocation " + toString(Reloc) + " to " + toString(S) +844 fatal("relocation " + toString(reloc) + " to " + toString(s) +
765 " not supported for Armv6-M targets");845 " not supported for Armv6-M targets");
766}846}
767847
768// Creates a thunk for Thumb-ARM interworking or branch range extension.848// Creates a thunk for Thumb-ARM interworking or branch range extension.
769static Thunk *addThunkArm(RelType Reloc, Symbol &S) {849static Thunk *addThunkArm(RelType reloc, Symbol &s) {
770 // Decide which Thunk is needed based on:850 // Decide which Thunk is needed based on:
771 // Available instruction set851 // Available instruction set
772 // - An Arm Thunk can only be used if Arm state is available.852 // - An Arm Thunk can only be used if Arm state is available.
...@@ -783,61 +863,72 @@ static Thunk *addThunkArm(RelType Reloc, Symbol &S) {...@@ -783,61 +863,72 @@ static Thunk *addThunkArm(RelType Reloc, Symbol &S) {
783 // can use in Thunks. The flags below are set by reading the BuildAttributes863 // can use in Thunks. The flags below are set by reading the BuildAttributes
784 // of the input objects. InputFiles.cpp contains the mapping from ARM864 // of the input objects. InputFiles.cpp contains the mapping from ARM
785 // architecture to flag.865 // architecture to flag.
786 if (!Config->ARMHasMovtMovw) {866 if (!config->armHasMovtMovw) {
787 if (!Config->ARMJ1J2BranchEncoding)867 if (!config->armJ1J2BranchEncoding)
788 return addThunkPreArmv7(Reloc, S);868 return addThunkPreArmv7(reloc, s);
789 return addThunkV6M(Reloc, S);869 return addThunkV6M(reloc, s);
790 }870 }
791871
792 switch (Reloc) {872 switch (reloc) {
793 case R_ARM_PC24:873 case R_ARM_PC24:
794 case R_ARM_PLT32:874 case R_ARM_PLT32:
795 case R_ARM_JUMP24:875 case R_ARM_JUMP24:
796 case R_ARM_CALL:876 case R_ARM_CALL:
797 if (Config->PicThunk)877 if (config->picThunk)
798 return make<ARMV7PILongThunk>(S);878 return make<ARMV7PILongThunk>(s);
799 return make<ARMV7ABSLongThunk>(S);879 return make<ARMV7ABSLongThunk>(s);
800 case R_ARM_THM_JUMP19:880 case R_ARM_THM_JUMP19:
801 case R_ARM_THM_JUMP24:881 case R_ARM_THM_JUMP24:
802 case R_ARM_THM_CALL:882 case R_ARM_THM_CALL:
803 if (Config->PicThunk)883 if (config->picThunk)
804 return make<ThumbV7PILongThunk>(S);884 return make<ThumbV7PILongThunk>(s);
805 return make<ThumbV7ABSLongThunk>(S);885 return make<ThumbV7ABSLongThunk>(s);
806 }886 }
807 fatal("unrecognized relocation type");887 fatal("unrecognized relocation type");
808}888}
809889
810static Thunk *addThunkMips(RelType Type, Symbol &S) {890static Thunk *addThunkMips(RelType type, Symbol &s) {
811 if ((S.StOther & STO_MIPS_MICROMIPS) && isMipsR6())891 if ((s.stOther & STO_MIPS_MICROMIPS) && isMipsR6())
812 return make<MicroMipsR6Thunk>(S);892 return make<MicroMipsR6Thunk>(s);
813 if (S.StOther & STO_MIPS_MICROMIPS)893 if (s.stOther & STO_MIPS_MICROMIPS)
814 return make<MicroMipsThunk>(S);894 return make<MicroMipsThunk>(s);
815 return make<MipsThunk>(S);895 return make<MipsThunk>(s);
896}
897
898static Thunk *addThunkPPC32(const InputSection &isec, const Relocation &rel, Symbol &s) {
899 assert((rel.type == R_PPC_REL24 || rel.type == R_PPC_PLTREL24) &&
900 "unexpected relocation type for thunk");
901 return make<PPC32PltCallStub>(isec, rel, s);
816}902}
817903
818static Thunk *addThunkPPC64(RelType Type, Symbol &S) {904static Thunk *addThunkPPC64(RelType type, Symbol &s) {
819 assert(Type == R_PPC64_REL24 && "unexpected relocation type for thunk");905 assert(type == R_PPC64_REL24 && "unexpected relocation type for thunk");
820 if (S.isInPlt())906 if (s.isInPlt())
821 return make<PPC64PltCallStub>(S);907 return make<PPC64PltCallStub>(s);
822908
823 if (Config->PicThunk)909 if (config->picThunk)
824 return make<PPC64PILongBranchThunk>(S);910 return make<PPC64PILongBranchThunk>(s);
825911
826 return make<PPC64PDLongBranchThunk>(S);912 return make<PPC64PDLongBranchThunk>(s);
827}913}
828914
829Thunk *addThunk(RelType Type, Symbol &S) {915Thunk *addThunk(const InputSection &isec, Relocation &rel) {
830 if (Config->EMachine == EM_AARCH64)916 Symbol &s = *rel.sym;
831 return addThunkAArch64(Type, S);917
918 if (config->emachine == EM_AARCH64)
919 return addThunkAArch64(rel.type, s);
920
921 if (config->emachine == EM_ARM)
922 return addThunkArm(rel.type, s);
832923
833 if (Config->EMachine == EM_ARM)924 if (config->emachine == EM_MIPS)
834 return addThunkArm(Type, S);925 return addThunkMips(rel.type, s);
835926
836 if (Config->EMachine == EM_MIPS)927 if (config->emachine == EM_PPC)
837 return addThunkMips(Type, S);928 return addThunkPPC32(isec, rel, s);
838929
839 if (Config->EMachine == EM_PPC64)930 if (config->emachine == EM_PPC64)
840 return addThunkPPC64(Type, S);931 return addThunkPPC64(rel.type, s);
841932
842 llvm_unreachable("add Thunk only supported for ARM, Mips and PowerPC");933 llvm_unreachable("add Thunk only supported for ARM, Mips and PowerPC");
843}934}
deps/lld/ELF/Thunks.h+22-20
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Thunks.h --------------------------------------------------------===//1//===- Thunks.h --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -28,42 +27,45 @@ class ThunkSection;...@@ -28,42 +27,45 @@ class ThunkSection;
28// Thunks are assigned to synthetic ThunkSections27// Thunks are assigned to synthetic ThunkSections
29class Thunk {28class Thunk {
30public:29public:
31 Thunk(Symbol &Destination);30 Thunk(Symbol &destination);
32 virtual ~Thunk();31 virtual ~Thunk();
3332
34 virtual uint32_t size() = 0;33 virtual uint32_t size() = 0;
35 virtual void writeTo(uint8_t *Buf) = 0;34 virtual void writeTo(uint8_t *buf) = 0;
3635
37 // All Thunks must define at least one symbol, known as the thunk target36 // All Thunks must define at least one symbol, known as the thunk target
38 // symbol, so that we can redirect relocations to it. The thunk may define37 // symbol, so that we can redirect relocations to it. The thunk may define
39 // additional symbols, but these are never targets for relocations.38 // additional symbols, but these are never targets for relocations.
40 virtual void addSymbols(ThunkSection &IS) = 0;39 virtual void addSymbols(ThunkSection &isec) = 0;
4140
42 void setOffset(uint64_t Offset);41 void setOffset(uint64_t offset);
43 Defined *addSymbol(StringRef Name, uint8_t Type, uint64_t Value,42 Defined *addSymbol(StringRef name, uint8_t type, uint64_t value,
44 InputSectionBase &Section);43 InputSectionBase &section);
4544
46 // Some Thunks must be placed immediately before their Target as they elide45 // Some Thunks must be placed immediately before their Target as they elide
47 // a branch and fall through to the first Symbol in the Target.46 // a branch and fall through to the first Symbol in the Target.
48 virtual InputSection *getTargetInputSection() const { return nullptr; }47 virtual InputSection *getTargetInputSection() const { return nullptr; }
4948
50 // To reuse a Thunk the caller as identified by the Type must be49 // To reuse a Thunk the InputSection and the relocation must be compatible
51 // compatible with it.50 // with it.
52 virtual bool isCompatibleWith(RelType Type) const { return true; }51 virtual bool isCompatibleWith(const InputSection &,
52 const Relocation &) const {
53 return true;
54 }
5355
54 Defined *getThunkTargetSym() const { return Syms[0]; }56 Defined *getThunkTargetSym() const { return syms[0]; }
5557
56 // The alignment requirement for this Thunk, defaults to the size of the58 // The alignment requirement for this Thunk, defaults to the size of the
57 // typical code section alignment.59 // typical code section alignment.
58 Symbol &Destination;60 Symbol &destination;
59 llvm::SmallVector<Defined *, 3> Syms;61 llvm::SmallVector<Defined *, 3> syms;
60 uint64_t Offset = 0;62 uint64_t offset = 0;
61 uint32_t Alignment = 4;63 uint32_t alignment = 4;
62};64};
6365
64// For a Relocation to symbol S create a Thunk to be added to a synthetic66// For a Relocation to symbol S create a Thunk to be added to a synthetic
65// ThunkSection. At present there are implementations for ARM and Mips Thunks.67// ThunkSection.
66Thunk *addThunk(RelType Type, Symbol &S);68Thunk *addThunk(const InputSection &isec, Relocation &rel);
6769
68} // namespace elf70} // namespace elf
69} // namespace lld71} // namespace lld
deps/lld/ELF/Writer.cpp+1415-1253
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Writer.cpp ---------------------------------------------------------===//1//===- Writer.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -11,7 +10,6 @@...@@ -11,7 +10,6 @@
11#include "AArch64ErrataFix.h"10#include "AArch64ErrataFix.h"
12#include "CallGraphSort.h"11#include "CallGraphSort.h"
13#include "Config.h"12#include "Config.h"
14#include "Filesystem.h"
15#include "LinkerScript.h"13#include "LinkerScript.h"
16#include "MapFile.h"14#include "MapFile.h"
17#include "OutputSections.h"15#include "OutputSections.h"
...@@ -20,11 +18,15 @@...@@ -20,11 +18,15 @@
20#include "Symbols.h"18#include "Symbols.h"
21#include "SyntheticSections.h"19#include "SyntheticSections.h"
22#include "Target.h"20#include "Target.h"
21#include "lld/Common/Filesystem.h"
23#include "lld/Common/Memory.h"22#include "lld/Common/Memory.h"
24#include "lld/Common/Strings.h"23#include "lld/Common/Strings.h"
25#include "lld/Common/Threads.h"24#include "lld/Common/Threads.h"
26#include "llvm/ADT/StringMap.h"25#include "llvm/ADT/StringMap.h"
27#include "llvm/ADT/StringSwitch.h"26#include "llvm/ADT/StringSwitch.h"
27#include "llvm/Support/RandomNumberGenerator.h"
28#include "llvm/Support/SHA1.h"
29#include "llvm/Support/xxhash.h"
28#include <climits>30#include <climits>
2931
30using namespace llvm;32using namespace llvm;
...@@ -40,31 +42,32 @@ namespace {...@@ -40,31 +42,32 @@ namespace {
40// The writer writes a SymbolTable result to a file.42// The writer writes a SymbolTable result to a file.
41template <class ELFT> class Writer {43template <class ELFT> class Writer {
42public:44public:
43 Writer() : Buffer(errorHandler().OutputBuffer) {}45 Writer() : buffer(errorHandler().outputBuffer) {}
44 typedef typename ELFT::Shdr Elf_Shdr;46 using Elf_Shdr = typename ELFT::Shdr;
45 typedef typename ELFT::Ehdr Elf_Ehdr;47 using Elf_Ehdr = typename ELFT::Ehdr;
46 typedef typename ELFT::Phdr Elf_Phdr;48 using Elf_Phdr = typename ELFT::Phdr;
4749
48 void run();50 void run();
4951
50private:52private:
51 void copyLocalSymbols();53 void copyLocalSymbols();
52 void addSectionSymbols();54 void addSectionSymbols();
53 void forEachRelSec(llvm::function_ref<void(InputSectionBase &)> Fn);55 void forEachRelSec(llvm::function_ref<void(InputSectionBase &)> fn);
54 void sortSections();56 void sortSections();
55 void resolveShfLinkOrder();57 void resolveShfLinkOrder();
56 void maybeAddThunks();58 void finalizeAddressDependentContent();
57 void sortInputSections();59 void sortInputSections();
58 void finalizeSections();60 void finalizeSections();
59 void checkExecuteOnly();61 void checkExecuteOnly();
60 void setReservedSymbolSections();62 void setReservedSymbolSections();
6163
62 std::vector<PhdrEntry *> createPhdrs();64 std::vector<PhdrEntry *> createPhdrs(Partition &part);
63 void removeEmptyPTLoad();65 void removeEmptyPTLoad(std::vector<PhdrEntry *> &phdrEntry);
64 void addPtArmExid(std::vector<PhdrEntry *> &Phdrs);66 void addPhdrForSection(Partition &part, unsigned shType, unsigned pType,
67 unsigned pFlags);
65 void assignFileOffsets();68 void assignFileOffsets();
66 void assignFileOffsetsBinary();69 void assignFileOffsetsBinary();
67 void setPhdrs();70 void setPhdrs(Partition &part);
68 void checkSections();71 void checkSections();
69 void fixSectionAlignments();72 void fixSectionAlignments();
70 void openFile();73 void openFile();
...@@ -74,36 +77,34 @@ private:...@@ -74,36 +77,34 @@ private:
74 void writeSectionsBinary();77 void writeSectionsBinary();
75 void writeBuildId();78 void writeBuildId();
7679
77 std::unique_ptr<FileOutputBuffer> &Buffer;80 std::unique_ptr<FileOutputBuffer> &buffer;
7881
79 void addRelIpltSymbols();82 void addRelIpltSymbols();
80 void addStartEndSymbols();83 void addStartEndSymbols();
81 void addStartStopSymbols(OutputSection *Sec);84 void addStartStopSymbols(OutputSection *sec);
82
83 std::vector<PhdrEntry *> Phdrs;
8485
85 uint64_t FileSize;86 uint64_t fileSize;
86 uint64_t SectionHeaderOff;87 uint64_t sectionHeaderOff;
87};88};
88} // anonymous namespace89} // anonymous namespace
8990
90static bool isSectionPrefix(StringRef Prefix, StringRef Name) {91static bool isSectionPrefix(StringRef prefix, StringRef name) {
91 return Name.startswith(Prefix) || Name == Prefix.drop_back();92 return name.startswith(prefix) || name == prefix.drop_back();
92}93}
9394
94StringRef elf::getOutputSectionName(const InputSectionBase *S) {95StringRef elf::getOutputSectionName(const InputSectionBase *s) {
95 if (Config->Relocatable)96 if (config->relocatable)
96 return S->Name;97 return s->name;
9798
98 // This is for --emit-relocs. If .text.foo is emitted as .text.bar, we want99 // This is for --emit-relocs. If .text.foo is emitted as .text.bar, we want
99 // to emit .rela.text.foo as .rela.text.bar for consistency (this is not100 // to emit .rela.text.foo as .rela.text.bar for consistency (this is not
100 // technically required, but not doing it is odd). This code guarantees that.101 // technically required, but not doing it is odd). This code guarantees that.
101 if (auto *IS = dyn_cast<InputSection>(S)) {102 if (auto *isec = dyn_cast<InputSection>(s)) {
102 if (InputSectionBase *Rel = IS->getRelocatedSection()) {103 if (InputSectionBase *rel = isec->getRelocatedSection()) {
103 OutputSection *Out = Rel->getOutputSection();104 OutputSection *out = rel->getOutputSection();
104 if (S->Type == SHT_RELA)105 if (s->type == SHT_RELA)
105 return Saver.save(".rela" + Out->Name);106 return saver.save(".rela" + out->name);
106 return Saver.save(".rel" + Out->Name);107 return saver.save(".rel" + out->name);
107 }108 }
108 }109 }
109110
...@@ -113,97 +114,133 @@ StringRef elf::getOutputSectionName(const InputSectionBase *S) {...@@ -113,97 +114,133 @@ StringRef elf::getOutputSectionName(const InputSectionBase *S) {
113 // When enabled, this allows identifying the hot code region (.text.hot) in114 // When enabled, this allows identifying the hot code region (.text.hot) in
114 // the final binary which can be selectively mapped to huge pages or mlocked,115 // the final binary which can be selectively mapped to huge pages or mlocked,
115 // for instance.116 // for instance.
116 if (Config->ZKeepTextSectionPrefix)117 if (config->zKeepTextSectionPrefix)
117 for (StringRef V :118 for (StringRef v :
118 {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."})119 {".text.hot.", ".text.unlikely.", ".text.startup.", ".text.exit."})
119 if (isSectionPrefix(V, S->Name))120 if (isSectionPrefix(v, s->name))
120 return V.drop_back();121 return v.drop_back();
121122
122 for (StringRef V :123 for (StringRef v :
123 {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",124 {".text.", ".rodata.", ".data.rel.ro.", ".data.", ".bss.rel.ro.",
124 ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",125 ".bss.", ".init_array.", ".fini_array.", ".ctors.", ".dtors.", ".tbss.",
125 ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."})126 ".gcc_except_table.", ".tdata.", ".ARM.exidx.", ".ARM.extab."})
126 if (isSectionPrefix(V, S->Name))127 if (isSectionPrefix(v, s->name))
127 return V.drop_back();128 return v.drop_back();
128129
129 // CommonSection is identified as "COMMON" in linker scripts.130 // CommonSection is identified as "COMMON" in linker scripts.
130 // By default, it should go to .bss section.131 // By default, it should go to .bss section.
131 if (S->Name == "COMMON")132 if (s->name == "COMMON")
132 return ".bss";133 return ".bss";
133134
134 return S->Name;135 return s->name;
135}136}
136137
137static bool needsInterpSection() {138static bool needsInterpSection() {
138 return !SharedFiles.empty() && !Config->DynamicLinker.empty() &&139 return !sharedFiles.empty() && !config->dynamicLinker.empty() &&
139 Script->needsInterpSection();140 script->needsInterpSection();
140}141}
141142
142template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); }143template <class ELFT> void elf::writeResult() { Writer<ELFT>().run(); }
143144
144template <class ELFT> void Writer<ELFT>::removeEmptyPTLoad() {145template <class ELFT>
145 llvm::erase_if(Phdrs, [&](const PhdrEntry *P) {146void Writer<ELFT>::removeEmptyPTLoad(std::vector<PhdrEntry *> &phdrs) {
146 if (P->p_type != PT_LOAD)147 llvm::erase_if(phdrs, [&](const PhdrEntry *p) {
148 if (p->p_type != PT_LOAD)
147 return false;149 return false;
148 if (!P->FirstSec)150 if (!p->firstSec)
149 return true;151 return true;
150 uint64_t Size = P->LastSec->Addr + P->LastSec->Size - P->FirstSec->Addr;152 uint64_t size = p->lastSec->addr + p->lastSec->size - p->firstSec->addr;
151 return Size == 0;153 return size == 0;
152 });154 });
153}155}
154156
155template <class ELFT> static void combineEhFrameSections() {157template <class ELFT> static void copySectionsIntoPartitions() {
156 for (InputSectionBase *&S : InputSections) {158 std::vector<InputSectionBase *> newSections;
157 EhInputSection *ES = dyn_cast<EhInputSection>(S);159 for (unsigned part = 2; part != partitions.size() + 1; ++part) {
158 if (!ES || !ES->Live)160 for (InputSectionBase *s : inputSections) {
161 if (!(s->flags & SHF_ALLOC) || !s->isLive())
162 continue;
163 InputSectionBase *copy;
164 if (s->type == SHT_NOTE)
165 copy = make<InputSection>(cast<InputSection>(*s));
166 else if (auto *es = dyn_cast<EhInputSection>(s))
167 copy = make<EhInputSection>(*es);
168 else
169 continue;
170 copy->partition = part;
171 newSections.push_back(copy);
172 }
173 }
174
175 inputSections.insert(inputSections.end(), newSections.begin(),
176 newSections.end());
177}
178
179template <class ELFT> static void combineEhSections() {
180 for (InputSectionBase *&s : inputSections) {
181 // Ignore dead sections and the partition end marker (.part.end),
182 // whose partition number is out of bounds.
183 if (!s->isLive() || s->partition == 255)
159 continue;184 continue;
160185
161 In.EhFrame->addSection<ELFT>(ES);186 Partition &part = s->getPartition();
162 S = nullptr;187 if (auto *es = dyn_cast<EhInputSection>(s)) {
188 part.ehFrame->addSection<ELFT>(es);
189 s = nullptr;
190 } else if (s->kind() == SectionBase::Regular && part.armExidx &&
191 part.armExidx->addSection(cast<InputSection>(s))) {
192 s = nullptr;
193 }
163 }194 }
164195
165 std::vector<InputSectionBase *> &V = InputSections;196 std::vector<InputSectionBase *> &v = inputSections;
166 V.erase(std::remove(V.begin(), V.end(), nullptr), V.end());197 v.erase(std::remove(v.begin(), v.end(), nullptr), v.end());
167}198}
168199
169static Defined *addOptionalRegular(StringRef Name, SectionBase *Sec,200static Defined *addOptionalRegular(StringRef name, SectionBase *sec,
170 uint64_t Val, uint8_t StOther = STV_HIDDEN,201 uint64_t val, uint8_t stOther = STV_HIDDEN,
171 uint8_t Binding = STB_GLOBAL) {202 uint8_t binding = STB_GLOBAL) {
172 Symbol *S = Symtab->find(Name);203 Symbol *s = symtab->find(name);
173 if (!S || S->isDefined())204 if (!s || s->isDefined())
174 return nullptr;205 return nullptr;
175 return Symtab->addDefined(Name, StOther, STT_NOTYPE, Val,206
176 /*Size=*/0, Binding, Sec,207 s->resolve(Defined{/*file=*/nullptr, name, binding, stOther, STT_NOTYPE, val,
177 /*File=*/nullptr);208 /*size=*/0, sec});
209 return cast<Defined>(s);
178}210}
179211
180static Defined *addAbsolute(StringRef Name) {212static Defined *addAbsolute(StringRef name) {
181 return Symtab->addDefined(Name, STV_HIDDEN, STT_NOTYPE, 0, 0, STB_GLOBAL,213 Symbol *sym = symtab->addSymbol(Defined{nullptr, name, STB_GLOBAL, STV_HIDDEN,
182 nullptr, nullptr);214 STT_NOTYPE, 0, 0, nullptr});
215 return cast<Defined>(sym);
183}216}
184217
185// The linker is expected to define some symbols depending on218// The linker is expected to define some symbols depending on
186// the linking result. This function defines such symbols.219// the linking result. This function defines such symbols.
187void elf::addReservedSymbols() {220void elf::addReservedSymbols() {
188 if (Config->EMachine == EM_MIPS) {221 if (config->emachine == EM_MIPS) {
189 // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer222 // Define _gp for MIPS. st_value of _gp symbol will be updated by Writer
190 // so that it points to an absolute address which by default is relative223 // so that it points to an absolute address which by default is relative
191 // to GOT. Default offset is 0x7ff0.224 // to GOT. Default offset is 0x7ff0.
192 // See "Global Data Symbols" in Chapter 6 in the following document:225 // See "Global Data Symbols" in Chapter 6 in the following document:
193 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf226 // ftp://www.linux-mips.org/pub/linux/mips/doc/ABI/mipsabi.pdf
194 ElfSym::MipsGp = addAbsolute("_gp");227 ElfSym::mipsGp = addAbsolute("_gp");
195228
196 // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between229 // On MIPS O32 ABI, _gp_disp is a magic symbol designates offset between
197 // start of function and 'gp' pointer into GOT.230 // start of function and 'gp' pointer into GOT.
198 if (Symtab->find("_gp_disp"))231 if (symtab->find("_gp_disp"))
199 ElfSym::MipsGpDisp = addAbsolute("_gp_disp");232 ElfSym::mipsGpDisp = addAbsolute("_gp_disp");
200233
201 // The __gnu_local_gp is a magic symbol equal to the current value of 'gp'234 // The __gnu_local_gp is a magic symbol equal to the current value of 'gp'
202 // pointer. This symbol is used in the code generated by .cpload pseudo-op235 // pointer. This symbol is used in the code generated by .cpload pseudo-op
203 // in case of using -mno-shared option.236 // in case of using -mno-shared option.
204 // https://sourceware.org/ml/binutils/2004-12/msg00094.html237 // https://sourceware.org/ml/binutils/2004-12/msg00094.html
205 if (Symtab->find("__gnu_local_gp"))238 if (symtab->find("__gnu_local_gp"))
206 ElfSym::MipsLocalGp = addAbsolute("__gnu_local_gp");239 ElfSym::mipsLocalGp = addAbsolute("__gnu_local_gp");
240 } else if (config->emachine == EM_PPC) {
241 // glibc *crt1.o has a undefined reference to _SDA_BASE_. Since we don't
242 // support Small Data Area, define it arbitrarily as 0.
243 addOptionalRegular("_SDA_BASE_", nullptr, 0, STV_HIDDEN);
207 }244 }
208245
209 // The Power Architecture 64-bit v2 ABI defines a TableOfContents (TOC) which246 // The Power Architecture 64-bit v2 ABI defines a TableOfContents (TOC) which
...@@ -214,56 +251,62 @@ void elf::addReservedSymbols() {...@@ -214,56 +251,62 @@ void elf::addReservedSymbols() {
214 // the .got section.251 // the .got section.
215 // We do not allow _GLOBAL_OFFSET_TABLE_ to be defined by input objects as the252 // We do not allow _GLOBAL_OFFSET_TABLE_ to be defined by input objects as the
216 // correctness of some relocations depends on its value.253 // correctness of some relocations depends on its value.
217 StringRef GotTableSymName =254 StringRef gotSymName =
218 (Config->EMachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_";255 (config->emachine == EM_PPC64) ? ".TOC." : "_GLOBAL_OFFSET_TABLE_";
219 if (Symbol *S = Symtab->find(GotTableSymName)) {256
220 if (S->isDefined())257 if (Symbol *s = symtab->find(gotSymName)) {
221 error(toString(S->File) + " cannot redefine linker defined symbol '" +258 if (s->isDefined()) {
222 GotTableSymName + "'");259 error(toString(s->file) + " cannot redefine linker defined symbol '" +
223 else260 gotSymName + "'");
224 ElfSym::GlobalOffsetTable = Symtab->addDefined(261 return;
225 GotTableSymName, STV_HIDDEN, STT_NOTYPE, Target->GotBaseSymOff,262 }
226 /*Size=*/0, STB_GLOBAL, Out::ElfHeader,263
227 /*File=*/nullptr);264 uint64_t gotOff = 0;
265 if (config->emachine == EM_PPC64)
266 gotOff = 0x8000;
267
268 s->resolve(Defined{/*file=*/nullptr, gotSymName, STB_GLOBAL, STV_HIDDEN,
269 STT_NOTYPE, gotOff, /*size=*/0, Out::elfHeader});
270 ElfSym::globalOffsetTable = cast<Defined>(s);
228 }271 }
229272
230 // __ehdr_start is the location of ELF file headers. Note that we define273 // __ehdr_start is the location of ELF file headers. Note that we define
231 // this symbol unconditionally even when using a linker script, which274 // this symbol unconditionally even when using a linker script, which
232 // differs from the behavior implemented by GNU linker which only define275 // differs from the behavior implemented by GNU linker which only define
233 // this symbol if ELF headers are in the memory mapped segment.276 // this symbol if ELF headers are in the memory mapped segment.
234 addOptionalRegular("__ehdr_start", Out::ElfHeader, 0, STV_HIDDEN);277 addOptionalRegular("__ehdr_start", Out::elfHeader, 0, STV_HIDDEN);
235278
236 // __executable_start is not documented, but the expectation of at279 // __executable_start is not documented, but the expectation of at
237 // least the Android libc is that it points to the ELF header.280 // least the Android libc is that it points to the ELF header.
238 addOptionalRegular("__executable_start", Out::ElfHeader, 0, STV_HIDDEN);281 addOptionalRegular("__executable_start", Out::elfHeader, 0, STV_HIDDEN);
239282
240 // __dso_handle symbol is passed to cxa_finalize as a marker to identify283 // __dso_handle symbol is passed to cxa_finalize as a marker to identify
241 // each DSO. The address of the symbol doesn't matter as long as they are284 // each DSO. The address of the symbol doesn't matter as long as they are
242 // different in different DSOs, so we chose the start address of the DSO.285 // different in different DSOs, so we chose the start address of the DSO.
243 addOptionalRegular("__dso_handle", Out::ElfHeader, 0, STV_HIDDEN);286 addOptionalRegular("__dso_handle", Out::elfHeader, 0, STV_HIDDEN);
244287
245 // If linker script do layout we do not need to create any standart symbols.288 // If linker script do layout we do not need to create any standart symbols.
246 if (Script->HasSectionsCommand)289 if (script->hasSectionsCommand)
247 return;290 return;
248291
249 auto Add = [](StringRef S, int64_t Pos) {292 auto add = [](StringRef s, int64_t pos) {
250 return addOptionalRegular(S, Out::ElfHeader, Pos, STV_DEFAULT);293 return addOptionalRegular(s, Out::elfHeader, pos, STV_DEFAULT);
251 };294 };
252295
253 ElfSym::Bss = Add("__bss_start", 0);296 ElfSym::bss = add("__bss_start", 0);
254 ElfSym::End1 = Add("end", -1);297 ElfSym::end1 = add("end", -1);
255 ElfSym::End2 = Add("_end", -1);298 ElfSym::end2 = add("_end", -1);
256 ElfSym::Etext1 = Add("etext", -1);299 ElfSym::etext1 = add("etext", -1);
257 ElfSym::Etext2 = Add("_etext", -1);300 ElfSym::etext2 = add("_etext", -1);
258 ElfSym::Edata1 = Add("edata", -1);301 ElfSym::edata1 = add("edata", -1);
259 ElfSym::Edata2 = Add("_edata", -1);302 ElfSym::edata2 = add("_edata", -1);
260}303}
261304
262static OutputSection *findSection(StringRef Name) {305static OutputSection *findSection(StringRef name, unsigned partition = 1) {
263 for (BaseCommand *Base : Script->SectionCommands)306 for (BaseCommand *base : script->sectionCommands)
264 if (auto *Sec = dyn_cast<OutputSection>(Base))307 if (auto *sec = dyn_cast<OutputSection>(base))
265 if (Sec->Name == Name)308 if (sec->name == name && sec->partition == partition)
266 return Sec;309 return sec;
267 return nullptr;310 return nullptr;
268}311}
269312
...@@ -271,202 +314,263 @@ static OutputSection *findSection(StringRef Name) {...@@ -271,202 +314,263 @@ static OutputSection *findSection(StringRef Name) {
271template <class ELFT> static void createSyntheticSections() {314template <class ELFT> static void createSyntheticSections() {
272 // Initialize all pointers with NULL. This is needed because315 // Initialize all pointers with NULL. This is needed because
273 // you can call lld::elf::main more than once as a library.316 // you can call lld::elf::main more than once as a library.
274 memset(&Out::First, 0, sizeof(Out));317 memset(&Out::first, 0, sizeof(Out));
275318
276 auto Add = [](InputSectionBase *Sec) { InputSections.push_back(Sec); };319 auto add = [](InputSectionBase *sec) { inputSections.push_back(sec); };
277320
278 In.DynStrTab = make<StringTableSection>(".dynstr", true);321 in.shStrTab = make<StringTableSection>(".shstrtab", false);
279 In.Dynamic = make<DynamicSection<ELFT>>();
280 if (Config->AndroidPackDynRelocs) {
281 In.RelaDyn = make<AndroidPackedRelocationSection<ELFT>>(
282 Config->IsRela ? ".rela.dyn" : ".rel.dyn");
283 } else {
284 In.RelaDyn = make<RelocationSection<ELFT>>(
285 Config->IsRela ? ".rela.dyn" : ".rel.dyn", Config->ZCombreloc);
286 }
287 In.ShStrTab = make<StringTableSection>(".shstrtab", false);
288322
289 Out::ProgramHeaders = make<OutputSection>("", 0, SHF_ALLOC);323 Out::programHeaders = make<OutputSection>("", 0, SHF_ALLOC);
290 Out::ProgramHeaders->Alignment = Config->Wordsize;324 Out::programHeaders->alignment = config->wordsize;
291325
292 if (needsInterpSection()) {326 if (config->strip != StripPolicy::All) {
293 In.Interp = createInterpSection();327 in.strTab = make<StringTableSection>(".strtab", false);
294 Add(In.Interp);328 in.symTab = make<SymbolTableSection<ELFT>>(*in.strTab);
329 in.symTabShndx = make<SymtabShndxSection>();
295 }330 }
296331
297 if (Config->Strip != StripPolicy::All) {332 in.bss = make<BssSection>(".bss", 0, 1);
298 In.StrTab = make<StringTableSection>(".strtab", false);333 add(in.bss);
299 In.SymTab = make<SymbolTableSection<ELFT>>(*In.StrTab);
300 In.SymTabShndx = make<SymtabShndxSection>();
301 }
302
303 if (Config->BuildId != BuildIdKind::None) {
304 In.BuildId = make<BuildIdSection>();
305 Add(In.BuildId);
306 }
307
308 In.Bss = make<BssSection>(".bss", 0, 1);
309 Add(In.Bss);
310334
311 // If there is a SECTIONS command and a .data.rel.ro section name use name335 // If there is a SECTIONS command and a .data.rel.ro section name use name
312 // .data.rel.ro.bss so that we match in the .data.rel.ro output section.336 // .data.rel.ro.bss so that we match in the .data.rel.ro output section.
313 // This makes sure our relro is contiguous.337 // This makes sure our relro is contiguous.
314 bool HasDataRelRo = Script->HasSectionsCommand && findSection(".data.rel.ro");338 bool hasDataRelRo =
315 In.BssRelRo =339 script->hasSectionsCommand && findSection(".data.rel.ro", 0);
316 make<BssSection>(HasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);340 in.bssRelRo =
317 Add(In.BssRelRo);341 make<BssSection>(hasDataRelRo ? ".data.rel.ro.bss" : ".bss.rel.ro", 0, 1);
342 add(in.bssRelRo);
318343
319 // Add MIPS-specific sections.344 // Add MIPS-specific sections.
320 if (Config->EMachine == EM_MIPS) {345 if (config->emachine == EM_MIPS) {
321 if (!Config->Shared && Config->HasDynSymTab) {346 if (!config->shared && config->hasDynSymTab) {
322 In.MipsRldMap = make<MipsRldMapSection>();347 in.mipsRldMap = make<MipsRldMapSection>();
323 Add(In.MipsRldMap);348 add(in.mipsRldMap);
324 }349 }
325 if (auto *Sec = MipsAbiFlagsSection<ELFT>::create())350 if (auto *sec = MipsAbiFlagsSection<ELFT>::create())
326 Add(Sec);351 add(sec);
327 if (auto *Sec = MipsOptionsSection<ELFT>::create())352 if (auto *sec = MipsOptionsSection<ELFT>::create())
328 Add(Sec);353 add(sec);
329 if (auto *Sec = MipsReginfoSection<ELFT>::create())354 if (auto *sec = MipsReginfoSection<ELFT>::create())
330 Add(Sec);355 add(sec);
331 }356 }
332357
333 if (Config->HasDynSymTab) {358 for (Partition &part : partitions) {
334 In.DynSymTab = make<SymbolTableSection<ELFT>>(*In.DynStrTab);359 auto add = [&](InputSectionBase *sec) {
335 Add(In.DynSymTab);360 sec->partition = part.getNumber();
361 inputSections.push_back(sec);
362 };
363
364 if (!part.name.empty()) {
365 part.elfHeader = make<PartitionElfHeaderSection<ELFT>>();
366 part.elfHeader->name = part.name;
367 add(part.elfHeader);
336368
337 InX<ELFT>::VerSym = make<VersionTableSection<ELFT>>();369 part.programHeaders = make<PartitionProgramHeadersSection<ELFT>>();
338 Add(InX<ELFT>::VerSym);370 add(part.programHeaders);
371 }
339372
340 if (!Config->VersionDefinitions.empty()) {373 if (config->buildId != BuildIdKind::None) {
341 In.VerDef = make<VersionDefinitionSection>();374 part.buildId = make<BuildIdSection>();
342 Add(In.VerDef);375 add(part.buildId);
343 }376 }
344377
345 InX<ELFT>::VerNeed = make<VersionNeedSection<ELFT>>();378 part.dynStrTab = make<StringTableSection>(".dynstr", true);
346 Add(InX<ELFT>::VerNeed);379 part.dynSymTab = make<SymbolTableSection<ELFT>>(*part.dynStrTab);
380 part.dynamic = make<DynamicSection<ELFT>>();
381 if (config->androidPackDynRelocs) {
382 part.relaDyn = make<AndroidPackedRelocationSection<ELFT>>(
383 config->isRela ? ".rela.dyn" : ".rel.dyn");
384 } else {
385 part.relaDyn = make<RelocationSection<ELFT>>(
386 config->isRela ? ".rela.dyn" : ".rel.dyn", config->zCombreloc);
387 }
388
389 if (needsInterpSection())
390 add(createInterpSection());
391
392 if (config->hasDynSymTab) {
393 part.dynSymTab = make<SymbolTableSection<ELFT>>(*part.dynStrTab);
394 add(part.dynSymTab);
395
396 part.verSym = make<VersionTableSection>();
397 add(part.verSym);
398
399 if (!config->versionDefinitions.empty()) {
400 part.verDef = make<VersionDefinitionSection>();
401 add(part.verDef);
402 }
403
404 part.verNeed = make<VersionNeedSection<ELFT>>();
405 add(part.verNeed);
406
407 if (config->gnuHash) {
408 part.gnuHashTab = make<GnuHashTableSection>();
409 add(part.gnuHashTab);
410 }
411
412 if (config->sysvHash) {
413 part.hashTab = make<HashTableSection>();
414 add(part.hashTab);
415 }
347416
348 if (Config->GnuHash) {417 add(part.dynamic);
349 In.GnuHashTab = make<GnuHashTableSection>();418 add(part.dynStrTab);
350 Add(In.GnuHashTab);419 add(part.relaDyn);
351 }420 }
352421
353 if (Config->SysvHash) {422 if (config->relrPackDynRelocs) {
354 In.HashTab = make<HashTableSection>();423 part.relrDyn = make<RelrSection<ELFT>>();
355 Add(In.HashTab);424 add(part.relrDyn);
356 }425 }
357426
358 Add(In.Dynamic);427 if (!config->relocatable) {
359 Add(In.DynStrTab);428 if (config->ehFrameHdr) {
360 Add(In.RelaDyn);429 part.ehFrameHdr = make<EhFrameHeader>();
430 add(part.ehFrameHdr);
431 }
432 part.ehFrame = make<EhFrameSection>();
433 add(part.ehFrame);
434 }
435
436 if (config->emachine == EM_ARM && !config->relocatable) {
437 // The ARMExidxsyntheticsection replaces all the individual .ARM.exidx
438 // InputSections.
439 part.armExidx = make<ARMExidxSyntheticSection>();
440 add(part.armExidx);
441 }
361 }442 }
362443
363 if (Config->RelrPackDynRelocs) {444 if (partitions.size() != 1) {
364 In.RelrDyn = make<RelrSection<ELFT>>();445 // Create the partition end marker. This needs to be in partition number 255
365 Add(In.RelrDyn);446 // so that it is sorted after all other partitions. It also has other
447 // special handling (see createPhdrs() and combineEhSections()).
448 in.partEnd = make<BssSection>(".part.end", config->maxPageSize, 1);
449 in.partEnd->partition = 255;
450 add(in.partEnd);
451
452 in.partIndex = make<PartitionIndexSection>();
453 addOptionalRegular("__part_index_begin", in.partIndex, 0);
454 addOptionalRegular("__part_index_end", in.partIndex,
455 in.partIndex->getSize());
456 add(in.partIndex);
366 }457 }
367458
368 // Add .got. MIPS' .got is so different from the other archs,459 // Add .got. MIPS' .got is so different from the other archs,
369 // it has its own class.460 // it has its own class.
370 if (Config->EMachine == EM_MIPS) {461 if (config->emachine == EM_MIPS) {
371 In.MipsGot = make<MipsGotSection>();462 in.mipsGot = make<MipsGotSection>();
372 Add(In.MipsGot);463 add(in.mipsGot);
373 } else {464 } else {
374 In.Got = make<GotSection>();465 in.got = make<GotSection>();
375 Add(In.Got);466 add(in.got);
467 }
468
469 if (config->emachine == EM_PPC) {
470 in.ppc32Got2 = make<PPC32Got2Section>();
471 add(in.ppc32Got2);
376 }472 }
377473
378 if (Config->EMachine == EM_PPC64) {474 if (config->emachine == EM_PPC64) {
379 In.PPC64LongBranchTarget = make<PPC64LongBranchTargetSection>();475 in.ppc64LongBranchTarget = make<PPC64LongBranchTargetSection>();
380 Add(In.PPC64LongBranchTarget);476 add(in.ppc64LongBranchTarget);
381 }477 }
382478
383 In.GotPlt = make<GotPltSection>();479 if (config->emachine == EM_RISCV) {
384 Add(In.GotPlt);480 in.riscvSdata = make<RISCVSdataSection>();
385 In.IgotPlt = make<IgotPltSection>();481 add(in.riscvSdata);
386 Add(In.IgotPlt);482 }
483
484 in.gotPlt = make<GotPltSection>();
485 add(in.gotPlt);
486 in.igotPlt = make<IgotPltSection>();
487 add(in.igotPlt);
387488
388 if (Config->GdbIndex) {489 // _GLOBAL_OFFSET_TABLE_ is defined relative to either .got.plt or .got. Treat
389 In.GdbIndex = GdbIndexSection::create<ELFT>();490 // it as a relocation and ensure the referenced section is created.
390 Add(In.GdbIndex);491 if (ElfSym::globalOffsetTable && config->emachine != EM_MIPS) {
492 if (target->gotBaseSymInGotPlt)
493 in.gotPlt->hasGotPltOffRel = true;
494 else
495 in.got->hasGotOffRel = true;
391 }496 }
392497
498 if (config->gdbIndex)
499 add(GdbIndexSection::create<ELFT>());
500
393 // We always need to add rel[a].plt to output if it has entries.501 // We always need to add rel[a].plt to output if it has entries.
394 // Even for static linking it can contain R_[*]_IRELATIVE relocations.502 // Even for static linking it can contain R_[*]_IRELATIVE relocations.
395 In.RelaPlt = make<RelocationSection<ELFT>>(503 in.relaPlt = make<RelocationSection<ELFT>>(
396 Config->IsRela ? ".rela.plt" : ".rel.plt", false /*Sort*/);504 config->isRela ? ".rela.plt" : ".rel.plt", /*sort=*/false);
397 Add(In.RelaPlt);505 add(in.relaPlt);
398506
399 // The RelaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure507 // The relaIplt immediately follows .rel.plt (.rel.dyn for ARM) to ensure
400 // that the IRelative relocations are processed last by the dynamic loader.508 // that the IRelative relocations are processed last by the dynamic loader.
401 // We cannot place the iplt section in .rel.dyn when Android relocation509 // We cannot place the iplt section in .rel.dyn when Android relocation
402 // packing is enabled because that would cause a section type mismatch.510 // packing is enabled because that would cause a section type mismatch.
403 // However, because the Android dynamic loader reads .rel.plt after .rel.dyn,511 // However, because the Android dynamic loader reads .rel.plt after .rel.dyn,
404 // we can get the desired behaviour by placing the iplt section in .rel.plt.512 // we can get the desired behaviour by placing the iplt section in .rel.plt.
405 In.RelaIplt = make<RelocationSection<ELFT>>(513 in.relaIplt = make<RelocationSection<ELFT>>(
406 (Config->EMachine == EM_ARM && !Config->AndroidPackDynRelocs)514 (config->emachine == EM_ARM && !config->androidPackDynRelocs)
407 ? ".rel.dyn"515 ? ".rel.dyn"
408 : In.RelaPlt->Name,516 : in.relaPlt->name,
409 false /*Sort*/);517 /*sort=*/false);
410 Add(In.RelaIplt);518 add(in.relaIplt);
519
520 in.plt = make<PltSection>(false);
521 add(in.plt);
522 in.iplt = make<PltSection>(true);
523 add(in.iplt);
411524
412 In.Plt = make<PltSection>(false);525 if (config->andFeatures)
413 Add(In.Plt);526 add(make<GnuPropertySection>());
414 In.Iplt = make<PltSection>(true);
415 Add(In.Iplt);
416527
417 // .note.GNU-stack is always added when we are creating a re-linkable528 // .note.GNU-stack is always added when we are creating a re-linkable
418 // object file. Other linkers are using the presence of this marker529 // object file. Other linkers are using the presence of this marker
419 // section to control the executable-ness of the stack area, but that530 // section to control the executable-ness of the stack area, but that
420 // is irrelevant these days. Stack area should always be non-executable531 // is irrelevant these days. Stack area should always be non-executable
421 // by default. So we emit this section unconditionally.532 // by default. So we emit this section unconditionally.
422 if (Config->Relocatable)533 if (config->relocatable)
423 Add(make<GnuStackSection>());534 add(make<GnuStackSection>());
424
425 if (!Config->Relocatable) {
426 if (Config->EhFrameHdr) {
427 In.EhFrameHdr = make<EhFrameHeader>();
428 Add(In.EhFrameHdr);
429 }
430 In.EhFrame = make<EhFrameSection>();
431 Add(In.EhFrame);
432 }
433
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);
441535
442 if (Config->EMachine == EM_ARM && !Config->Relocatable)536 if (in.symTab)
443 // Add a sentinel to terminate .ARM.exidx. It helps an unwinder537 add(in.symTab);
444 // to find the exact address range of the last entry.538 if (in.symTabShndx)
445 Add(make<ARMExidxSentinelSection>());539 add(in.symTabShndx);
540 add(in.shStrTab);
541 if (in.strTab)
542 add(in.strTab);
446}543}
447544
448// The main function of the writer.545// The main function of the writer.
449template <class ELFT> void Writer<ELFT>::run() {546template <class ELFT> void Writer<ELFT>::run() {
547 // Make copies of any input sections that need to be copied into each
548 // partition.
549 copySectionsIntoPartitions<ELFT>();
550
450 // Create linker-synthesized sections such as .got or .plt.551 // Create linker-synthesized sections such as .got or .plt.
451 // Such sections are of type input section.552 // Such sections are of type input section.
452 createSyntheticSections<ELFT>();553 createSyntheticSections<ELFT>();
453554
454 if (!Config->Relocatable)555 // Some input sections that are used for exception handling need to be moved
455 combineEhFrameSections<ELFT>();556 // into synthetic sections. Do that now so that they aren't assigned to
557 // output sections in the usual way.
558 if (!config->relocatable)
559 combineEhSections<ELFT>();
456560
457 // We want to process linker script commands. When SECTIONS command561 // We want to process linker script commands. When SECTIONS command
458 // is given we let it create sections.562 // is given we let it create sections.
459 Script->processSectionCommands();563 script->processSectionCommands();
460564
461 // Linker scripts controls how input sections are assigned to output sections.565 // Linker scripts controls how input sections are assigned to output sections.
462 // Input sections that were not handled by scripts are called "orphans", and566 // Input sections that were not handled by scripts are called "orphans", and
463 // they are assigned to output sections by the default rule. Process that.567 // they are assigned to output sections by the default rule. Process that.
464 Script->addOrphanSections();568 script->addOrphanSections();
465569
466 if (Config->Discard != DiscardPolicy::All)570 if (config->discard != DiscardPolicy::All)
467 copyLocalSymbols();571 copyLocalSymbols();
468572
469 if (Config->CopyRelocs)573 if (config->copyRelocs)
470 addSectionSymbols();574 addSectionSymbols();
471575
472 // Now that we have a complete set of output sections. This function576 // Now that we have a complete set of output sections. This function
...@@ -478,33 +582,35 @@ template <class ELFT> void Writer<ELFT>::run() {...@@ -478,33 +582,35 @@ template <class ELFT> void Writer<ELFT>::run() {
478 if (errorCount())582 if (errorCount())
479 return;583 return;
480584
481 Script->assignAddresses();585 script->assignAddresses();
482586
483 // If -compressed-debug-sections is specified, we need to compress587 // If -compressed-debug-sections is specified, we need to compress
484 // .debug_* sections. Do it right now because it changes the size of588 // .debug_* sections. Do it right now because it changes the size of
485 // output sections.589 // output sections.
486 for (OutputSection *Sec : OutputSections)590 for (OutputSection *sec : outputSections)
487 Sec->maybeCompress<ELFT>();591 sec->maybeCompress<ELFT>();
488592
489 Script->allocateHeaders(Phdrs);593 script->allocateHeaders(mainPart->phdrs);
490594
491 // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a595 // Remove empty PT_LOAD to avoid causing the dynamic linker to try to mmap a
492 // 0 sized region. This has to be done late since only after assignAddresses596 // 0 sized region. This has to be done late since only after assignAddresses
493 // we know the size of the sections.597 // we know the size of the sections.
494 removeEmptyPTLoad();598 for (Partition &part : partitions)
599 removeEmptyPTLoad(part.phdrs);
495600
496 if (!Config->OFormatBinary)601 if (!config->oFormatBinary)
497 assignFileOffsets();602 assignFileOffsets();
498 else603 else
499 assignFileOffsetsBinary();604 assignFileOffsetsBinary();
500605
501 setPhdrs();606 for (Partition &part : partitions)
607 setPhdrs(part);
502608
503 if (Config->Relocatable)609 if (config->relocatable)
504 for (OutputSection *Sec : OutputSections)610 for (OutputSection *sec : outputSections)
505 Sec->Addr = 0;611 sec->addr = 0;
506612
507 if (Config->CheckSections)613 if (config->checkSections)
508 checkSections();614 checkSections();
509615
510 // It does not make sense try to open the file if we have error already.616 // It does not make sense try to open the file if we have error already.
...@@ -515,7 +621,7 @@ template <class ELFT> void Writer<ELFT>::run() {...@@ -515,7 +621,7 @@ template <class ELFT> void Writer<ELFT>::run() {
515 if (errorCount())621 if (errorCount())
516 return;622 return;
517623
518 if (!Config->OFormatBinary) {624 if (!config->oFormatBinary) {
519 writeTrapInstr();625 writeTrapInstr();
520 writeHeader();626 writeHeader();
521 writeSections();627 writeSections();
...@@ -535,16 +641,20 @@ template <class ELFT> void Writer<ELFT>::run() {...@@ -535,16 +641,20 @@ template <class ELFT> void Writer<ELFT>::run() {
535 if (errorCount())641 if (errorCount())
536 return;642 return;
537643
538 if (auto E = Buffer->commit())644 if (auto e = buffer->commit())
539 error("failed to write to the output file: " + toString(std::move(E)));645 error("failed to write to the output file: " + toString(std::move(e)));
540}646}
541647
542static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName,648static bool shouldKeepInSymtab(const Defined &sym) {
543 const Symbol &B) {649 if (sym.isSection())
544 if (B.isSection())
545 return false;650 return false;
546651
547 if (Config->Discard == DiscardPolicy::None)652 if (config->discard == DiscardPolicy::None)
653 return true;
654
655 // If -emit-reloc is given, all symbols including local ones need to be
656 // copied because they may be referenced by relocations.
657 if (config->emitRelocs)
548 return true;658 return true;
549659
550 // In ELF assembly .L symbols are normally discarded by the assembler.660 // In ELF assembly .L symbols are normally discarded by the assembler.
...@@ -552,61 +662,62 @@ static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName,...@@ -552,61 +662,62 @@ static bool shouldKeepInSymtab(SectionBase *Sec, StringRef SymName,
552 // * --discard-locals is used.662 // * --discard-locals is used.
553 // * The symbol is in a SHF_MERGE section, which is normally the reason for663 // * The symbol is in a SHF_MERGE section, which is normally the reason for
554 // the assembler keeping the .L symbol.664 // the assembler keeping the .L symbol.
555 if (!SymName.startswith(".L") && !SymName.empty())665 StringRef name = sym.getName();
666 bool isLocal = name.startswith(".L") || name.empty();
667 if (!isLocal)
556 return true;668 return true;
557669
558 if (Config->Discard == DiscardPolicy::Locals)670 if (config->discard == DiscardPolicy::Locals)
559 return false;671 return false;
560672
561 return !Sec || !(Sec->Flags & SHF_MERGE);673 SectionBase *sec = sym.section;
674 return !sec || !(sec->flags & SHF_MERGE);
562}675}
563676
564static bool includeInSymtab(const Symbol &B) {677static bool includeInSymtab(const Symbol &b) {
565 if (!B.isLocal() && !B.IsUsedInRegularObj)678 if (!b.isLocal() && !b.isUsedInRegularObj)
566 return false;679 return false;
567680
568 if (auto *D = dyn_cast<Defined>(&B)) {681 if (auto *d = dyn_cast<Defined>(&b)) {
569 // Always include absolute symbols.682 // Always include absolute symbols.
570 SectionBase *Sec = D->Section;683 SectionBase *sec = d->section;
571 if (!Sec)684 if (!sec)
572 return true;685 return true;
573 Sec = Sec->Repl;686 sec = sec->repl;
574687
575 // Exclude symbols pointing to garbage-collected sections.688 // Exclude symbols pointing to garbage-collected sections.
576 if (isa<InputSectionBase>(Sec) && !Sec->Live)689 if (isa<InputSectionBase>(sec) && !sec->isLive())
577 return false;690 return false;
578691
579 if (auto *S = dyn_cast<MergeInputSection>(Sec))692 if (auto *s = dyn_cast<MergeInputSection>(sec))
580 if (!S->getSectionPiece(D->Value)->Live)693 if (!s->getSectionPiece(d->value)->live)
581 return false;694 return false;
582 return true;695 return true;
583 }696 }
584 return B.Used;697 return b.used;
585}698}
586699
587// Local symbols are not in the linker's symbol table. This function scans700// Local symbols are not in the linker's symbol table. This function scans
588// each object file's symbol table to copy local symbols to the output.701// each object file's symbol table to copy local symbols to the output.
589template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {702template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
590 if (!In.SymTab)703 if (!in.symTab)
591 return;704 return;
592 for (InputFile *File : ObjectFiles) {705 for (InputFile *file : objectFiles) {
593 ObjFile<ELFT> *F = cast<ObjFile<ELFT>>(File);706 ObjFile<ELFT> *f = cast<ObjFile<ELFT>>(file);
594 for (Symbol *B : F->getLocalSymbols()) {707 for (Symbol *b : f->getLocalSymbols()) {
595 if (!B->isLocal())708 if (!b->isLocal())
596 fatal(toString(F) +709 fatal(toString(f) +
597 ": broken object: getLocalSymbols returns a non-local symbol");710 ": broken object: getLocalSymbols returns a non-local symbol");
598 auto *DR = dyn_cast<Defined>(B);711 auto *dr = dyn_cast<Defined>(b);
599712
600 // No reason to keep local undefined symbol in symtab.713 // No reason to keep local undefined symbol in symtab.
601 if (!DR)714 if (!dr)
602 continue;715 continue;
603 if (!includeInSymtab(*B))716 if (!includeInSymtab(*b))
604 continue;717 continue;
605718 if (!shouldKeepInSymtab(*dr))
606 SectionBase *Sec = DR->Section;
607 if (!shouldKeepInSymtab(Sec, B->getName(), *B))
608 continue;719 continue;
609 In.SymTab->addSymbol(B);720 in.symTab->addSymbol(b);
610 }721 }
611 }722 }
612}723}
...@@ -616,33 +727,33 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {...@@ -616,33 +727,33 @@ template <class ELFT> void Writer<ELFT>::copyLocalSymbols() {
616// referring to a section (that happens if the section is a synthetic one), we727// referring to a section (that happens if the section is a synthetic one), we
617// don't create a section symbol for that section.728// don't create a section symbol for that section.
618template <class ELFT> void Writer<ELFT>::addSectionSymbols() {729template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
619 for (BaseCommand *Base : Script->SectionCommands) {730 for (BaseCommand *base : script->sectionCommands) {
620 auto *Sec = dyn_cast<OutputSection>(Base);731 auto *sec = dyn_cast<OutputSection>(base);
621 if (!Sec)732 if (!sec)
622 continue;733 continue;
623 auto I = llvm::find_if(Sec->SectionCommands, [](BaseCommand *Base) {734 auto i = llvm::find_if(sec->sectionCommands, [](BaseCommand *base) {
624 if (auto *ISD = dyn_cast<InputSectionDescription>(Base))735 if (auto *isd = dyn_cast<InputSectionDescription>(base))
625 return !ISD->Sections.empty();736 return !isd->sections.empty();
626 return false;737 return false;
627 });738 });
628 if (I == Sec->SectionCommands.end())739 if (i == sec->sectionCommands.end())
629 continue;740 continue;
630 InputSection *IS = cast<InputSectionDescription>(*I)->Sections[0];741 InputSection *isec = cast<InputSectionDescription>(*i)->sections[0];
631742
632 // Relocations are not using REL[A] section symbols.743 // Relocations are not using REL[A] section symbols.
633 if (IS->Type == SHT_REL || IS->Type == SHT_RELA)744 if (isec->type == SHT_REL || isec->type == SHT_RELA)
634 continue;745 continue;
635746
636 // Unlike other synthetic sections, mergeable output sections contain data747 // Unlike other synthetic sections, mergeable output sections contain data
637 // copied from input sections, and there may be a relocation pointing to its748 // copied from input sections, and there may be a relocation pointing to its
638 // contents if -r or -emit-reloc are given.749 // contents if -r or -emit-reloc are given.
639 if (isa<SyntheticSection>(IS) && !(IS->Flags & SHF_MERGE))750 if (isa<SyntheticSection>(isec) && !(isec->flags & SHF_MERGE))
640 continue;751 continue;
641752
642 auto *Sym =753 auto *sym =
643 make<Defined>(IS->File, "", STB_LOCAL, /*StOther=*/0, STT_SECTION,754 make<Defined>(isec->file, "", STB_LOCAL, /*stOther=*/0, STT_SECTION,
644 /*Value=*/0, /*Size=*/0, IS);755 /*value=*/0, /*size=*/0, isec);
645 In.SymTab->addSymbol(Sym);756 in.symTab->addSymbol(sym);
646 }757 }
647}758}
648759
...@@ -652,25 +763,25 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {...@@ -652,25 +763,25 @@ template <class ELFT> void Writer<ELFT>::addSectionSymbols() {
652//763//
653// This function returns true if a section needs to be put into a764// This function returns true if a section needs to be put into a
654// PT_GNU_RELRO segment.765// PT_GNU_RELRO segment.
655static bool isRelroSection(const OutputSection *Sec) {766static bool isRelroSection(const OutputSection *sec) {
656 if (!Config->ZRelro)767 if (!config->zRelro)
657 return false;768 return false;
658769
659 uint64_t Flags = Sec->Flags;770 uint64_t flags = sec->flags;
660771
661 // Non-allocatable or non-writable sections don't need RELRO because772 // Non-allocatable or non-writable sections don't need RELRO because
662 // they are not writable or not even mapped to memory in the first place.773 // they are not writable or not even mapped to memory in the first place.
663 // RELRO is for sections that are essentially read-only but need to774 // RELRO is for sections that are essentially read-only but need to
664 // be writable only at process startup to allow dynamic linker to775 // be writable only at process startup to allow dynamic linker to
665 // apply relocations.776 // apply relocations.
666 if (!(Flags & SHF_ALLOC) || !(Flags & SHF_WRITE))777 if (!(flags & SHF_ALLOC) || !(flags & SHF_WRITE))
667 return false;778 return false;
668779
669 // Once initialized, TLS data segments are used as data templates780 // Once initialized, TLS data segments are used as data templates
670 // for a thread-local storage. For each new thread, runtime781 // for a thread-local storage. For each new thread, runtime
671 // allocates memory for a TLS and copy templates there. No thread782 // allocates memory for a TLS and copy templates there. No thread
672 // are supposed to use templates directly. Thus, it can be in RELRO.783 // are supposed to use templates directly. Thus, it can be in RELRO.
673 if (Flags & SHF_TLS)784 if (flags & SHF_TLS)
674 return true;785 return true;
675786
676 // .init_array, .preinit_array and .fini_array contain pointers to787 // .init_array, .preinit_array and .fini_array contain pointers to
...@@ -679,15 +790,15 @@ static bool isRelroSection(const OutputSection *Sec) {...@@ -679,15 +790,15 @@ static bool isRelroSection(const OutputSection *Sec) {
679 // to change at runtime. But if you are an attacker, you could do790 // to change at runtime. But if you are an attacker, you could do
680 // interesting things by manipulating pointers in .fini_array, for791 // interesting things by manipulating pointers in .fini_array, for
681 // example. So they are put into RELRO.792 // example. So they are put into RELRO.
682 uint32_t Type = Sec->Type;793 uint32_t type = sec->type;
683 if (Type == SHT_INIT_ARRAY || Type == SHT_FINI_ARRAY ||794 if (type == SHT_INIT_ARRAY || type == SHT_FINI_ARRAY ||
684 Type == SHT_PREINIT_ARRAY)795 type == SHT_PREINIT_ARRAY)
685 return true;796 return true;
686797
687 // .got contains pointers to external symbols. They are resolved by798 // .got contains pointers to external symbols. They are resolved by
688 // the dynamic linker when a module is loaded into memory, and after799 // the dynamic linker when a module is loaded into memory, and after
689 // that they are not expected to change. So, it can be in RELRO.800 // that they are not expected to change. So, it can be in RELRO.
690 if (In.Got && Sec == In.Got->getParent())801 if (in.got && sec == in.got->getParent())
691 return true;802 return true;
692803
693 // .toc is a GOT-ish section for PowerPC64. Their contents are accessed804 // .toc is a GOT-ish section for PowerPC64. Their contents are accessed
...@@ -695,30 +806,30 @@ static bool isRelroSection(const OutputSection *Sec) {...@@ -695,30 +806,30 @@ static bool isRelroSection(const OutputSection *Sec) {
695 // for accessing .got as well, .got and .toc need to be close enough in the806 // 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 place807 // virtual address space. Usually, .toc comes just after .got. Since we place
697 // .got into RELRO, .toc needs to be placed into RELRO too.808 // .got into RELRO, .toc needs to be placed into RELRO too.
698 if (Sec->Name.equals(".toc"))809 if (sec->name.equals(".toc"))
699 return true;810 return true;
700811
701 // .got.plt contains pointers to external function symbols. They are812 // .got.plt contains pointers to external function symbols. They are
702 // by default resolved lazily, so we usually cannot put it into RELRO.813 // by default resolved lazily, so we usually cannot put it into RELRO.
703 // However, if "-z now" is given, the lazy symbol resolution is814 // However, if "-z now" is given, the lazy symbol resolution is
704 // disabled, which enables us to put it into RELRO.815 // disabled, which enables us to put it into RELRO.
705 if (Sec == In.GotPlt->getParent())816 if (sec == in.gotPlt->getParent())
706 return Config->ZNow;817 return config->zNow;
707818
708 // .dynamic section contains data for the dynamic linker, and819 // .dynamic section contains data for the dynamic linker, and
709 // there's no need to write to it at runtime, so it's better to put820 // there's no need to write to it at runtime, so it's better to put
710 // it into RELRO.821 // it into RELRO.
711 if (Sec == In.Dynamic->getParent())822 if (sec->name == ".dynamic")
712 return true;823 return true;
713824
714 // Sections with some special names are put into RELRO. This is a825 // Sections with some special names are put into RELRO. This is a
715 // bit unfortunate because section names shouldn't be significant in826 // bit unfortunate because section names shouldn't be significant in
716 // ELF in spirit. But in reality many linker features depend on827 // ELF in spirit. But in reality many linker features depend on
717 // magic section names.828 // magic section names.
718 StringRef S = Sec->Name;829 StringRef s = sec->name;
719 return S == ".data.rel.ro" || S == ".bss.rel.ro" || S == ".ctors" ||830 return s == ".data.rel.ro" || s == ".bss.rel.ro" || s == ".ctors" ||
720 S == ".dtors" || S == ".jcr" || S == ".eh_frame" ||831 s == ".dtors" || s == ".jcr" || s == ".eh_frame" ||
721 S == ".openbsd.randomdata";832 s == ".openbsd.randomdata";
722}833}
723834
724// We compute a rank for each section. The rank indicates where the835// We compute a rank for each section. The rank indicates where the
...@@ -729,16 +840,18 @@ static bool isRelroSection(const OutputSection *Sec) {...@@ -729,16 +840,18 @@ static bool isRelroSection(const OutputSection *Sec) {
729// * It is easy to check if a give branch was taken.840// * It is easy to check if a give branch was taken.
730// * It is easy two see how similar two ranks are (see getRankProximity).841// * It is easy two see how similar two ranks are (see getRankProximity).
731enum RankFlags {842enum RankFlags {
732 RF_NOT_ADDR_SET = 1 << 18,843 RF_NOT_ADDR_SET = 1 << 27,
733 RF_NOT_ALLOC = 1 << 17,844 RF_NOT_ALLOC = 1 << 26,
734 RF_NOT_INTERP = 1 << 16,845 RF_PARTITION = 1 << 18, // Partition number (8 bits)
735 RF_NOT_NOTE = 1 << 15,846 RF_NOT_PART_EHDR = 1 << 17,
736 RF_WRITE = 1 << 14,847 RF_NOT_PART_PHDR = 1 << 16,
737 RF_EXEC_WRITE = 1 << 13,848 RF_NOT_INTERP = 1 << 15,
738 RF_EXEC = 1 << 12,849 RF_NOT_NOTE = 1 << 14,
739 RF_RODATA = 1 << 11,850 RF_WRITE = 1 << 13,
740 RF_NON_TLS_BSS = 1 << 10,851 RF_EXEC_WRITE = 1 << 12,
741 RF_NON_TLS_BSS_RO = 1 << 9,852 RF_EXEC = 1 << 11,
853 RF_RODATA = 1 << 10,
854 RF_NOT_RELRO = 1 << 9,
742 RF_NOT_TLS = 1 << 8,855 RF_NOT_TLS = 1 << 8,
743 RF_BSS = 1 << 7,856 RF_BSS = 1 << 7,
744 RF_PPC_NOT_TOCBSS = 1 << 6,857 RF_PPC_NOT_TOCBSS = 1 << 6,
...@@ -750,33 +863,41 @@ enum RankFlags {...@@ -750,33 +863,41 @@ enum RankFlags {
750 RF_MIPS_NOT_GOT = 1 << 0863 RF_MIPS_NOT_GOT = 1 << 0
751};864};
752865
753static unsigned getSectionRank(const OutputSection *Sec) {866static unsigned getSectionRank(const OutputSection *sec) {
754 unsigned Rank = 0;867 unsigned rank = sec->partition * RF_PARTITION;
755868
756 // We want to put section specified by -T option first, so we869 // We want to put section specified by -T option first, so we
757 // can start assigning VA starting from them later.870 // can start assigning VA starting from them later.
758 if (Config->SectionStartMap.count(Sec->Name))871 if (config->sectionStartMap.count(sec->name))
759 return Rank;872 return rank;
760 Rank |= RF_NOT_ADDR_SET;873 rank |= RF_NOT_ADDR_SET;
761874
762 // Allocatable sections go first to reduce the total PT_LOAD size and875 // Allocatable sections go first to reduce the total PT_LOAD size and
763 // so debug info doesn't change addresses in actual code.876 // so debug info doesn't change addresses in actual code.
764 if (!(Sec->Flags & SHF_ALLOC))877 if (!(sec->flags & SHF_ALLOC))
765 return Rank | RF_NOT_ALLOC;878 return rank | RF_NOT_ALLOC;
879
880 if (sec->type == SHT_LLVM_PART_EHDR)
881 return rank;
882 rank |= RF_NOT_PART_EHDR;
883
884 if (sec->type == SHT_LLVM_PART_PHDR)
885 return rank;
886 rank |= RF_NOT_PART_PHDR;
766887
767 // Put .interp first because some loaders want to see that section888 // Put .interp first because some loaders want to see that section
768 // on the first page of the executable file when loaded into memory.889 // on the first page of the executable file when loaded into memory.
769 if (Sec->Name == ".interp")890 if (sec->name == ".interp")
770 return Rank;891 return rank;
771 Rank |= RF_NOT_INTERP;892 rank |= RF_NOT_INTERP;
772893
773 // Put .note sections (which make up one PT_NOTE) at the beginning so that894 // 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 is895 // 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 be896 // 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.897 // included in a core to match core files with executables.
777 if (Sec->Type == SHT_NOTE)898 if (sec->type == SHT_NOTE)
778 return Rank;899 return rank;
779 Rank |= RF_NOT_NOTE;900 rank |= RF_NOT_NOTE;
780901
781 // Sort sections based on their access permission in the following902 // Sort sections based on their access permission in the following
782 // order: R, RX, RWX, RW. This order is based on the following903 // order: R, RX, RWX, RW. This order is based on the following
...@@ -789,116 +910,105 @@ static unsigned getSectionRank(const OutputSection *Sec) {...@@ -789,116 +910,105 @@ static unsigned getSectionRank(const OutputSection *Sec) {
789 // between .text and .data.910 // between .text and .data.
790 // * Writable sections come last, such that .bss lands at the very911 // * Writable sections come last, such that .bss lands at the very
791 // end of the last PT_LOAD.912 // end of the last PT_LOAD.
792 bool IsExec = Sec->Flags & SHF_EXECINSTR;913 bool isExec = sec->flags & SHF_EXECINSTR;
793 bool IsWrite = Sec->Flags & SHF_WRITE;914 bool isWrite = sec->flags & SHF_WRITE;
794915
795 if (IsExec) {916 if (isExec) {
796 if (IsWrite)917 if (isWrite)
797 Rank |= RF_EXEC_WRITE;918 rank |= RF_EXEC_WRITE;
798 else919 else
799 Rank |= RF_EXEC;920 rank |= RF_EXEC;
800 } else if (IsWrite) {921 } else if (isWrite) {
801 Rank |= RF_WRITE;922 rank |= RF_WRITE;
802 } else if (Sec->Type == SHT_PROGBITS) {923 } else if (sec->type == SHT_PROGBITS) {
803 // Make non-executable and non-writable PROGBITS sections (e.g .rodata924 // Make non-executable and non-writable PROGBITS sections (e.g .rodata
804 // .eh_frame) closer to .text. They likely contain PC or GOT relative925 // .eh_frame) closer to .text. They likely contain PC or GOT relative
805 // relocations and there could be relocation overflow if other huge sections926 // relocations and there could be relocation overflow if other huge sections
806 // (.dynstr .dynsym) were placed in between.927 // (.dynstr .dynsym) were placed in between.
807 Rank |= RF_RODATA;928 rank |= RF_RODATA;
808 }929 }
809930
810 // If we got here we know that both A and B are in the same PT_LOAD.931 // Place RelRo sections first. After considering SHT_NOBITS below, the
932 // ordering is PT_LOAD(PT_GNU_RELRO(.data.rel.ro .bss.rel.ro) | .data .bss),
933 // where | marks where page alignment happens. An alternative ordering is
934 // PT_LOAD(.data | PT_GNU_RELRO( .data.rel.ro .bss.rel.ro) | .bss), but it may
935 // waste more bytes due to 2 alignment places.
936 if (!isRelroSection(sec))
937 rank |= RF_NOT_RELRO;
811938
812 bool IsTls = Sec->Flags & SHF_TLS;939 // If we got here we know that both A and B are in the same PT_LOAD.
813 bool IsNoBits = Sec->Type == SHT_NOBITS;
814
815 // The first requirement we have is to put (non-TLS) nobits sections last. The
816 // reason is that the only thing the dynamic linker will see about them is a
817 // p_memsz that is larger than p_filesz. Seeing that it zeros the end of the
818 // PT_LOAD, so that has to correspond to the nobits sections.
819 bool IsNonTlsNoBits = IsNoBits && !IsTls;
820 if (IsNonTlsNoBits)
821 Rank |= RF_NON_TLS_BSS;
822
823 // We place nobits RelRo sections before plain r/w ones, and non-nobits RelRo
824 // sections after r/w ones, so that the RelRo sections are contiguous.
825 bool IsRelRo = isRelroSection(Sec);
826 if (IsNonTlsNoBits && !IsRelRo)
827 Rank |= RF_NON_TLS_BSS_RO;
828 if (!IsNonTlsNoBits && IsRelRo)
829 Rank |= RF_NON_TLS_BSS_RO;
830940
831 // The TLS initialization block needs to be a single contiguous block in a R/W941 // The TLS initialization block needs to be a single contiguous block in a R/W
832 // PT_LOAD, so stick TLS sections directly before the other RelRo R/W942 // PT_LOAD, so stick TLS sections directly before the other RelRo R/W
833 // sections. The TLS NOBITS sections are placed here as they don't take up943 // sections. Since p_filesz can be less than p_memsz, place NOBITS sections
834 // virtual address space in the PT_LOAD.944 // after PROGBITS.
835 if (!IsTls)945 if (!(sec->flags & SHF_TLS))
836 Rank |= RF_NOT_TLS;946 rank |= RF_NOT_TLS;
837947
838 // Within the TLS initialization block, the non-nobits sections need to appear948 // Within TLS sections, or within other RelRo sections, or within non-RelRo
839 // first.949 // sections, place non-NOBITS sections first.
840 if (IsNoBits)950 if (sec->type == SHT_NOBITS)
841 Rank |= RF_BSS;951 rank |= RF_BSS;
842952
843 // Some architectures have additional ordering restrictions for sections953 // Some architectures have additional ordering restrictions for sections
844 // within the same PT_LOAD.954 // within the same PT_LOAD.
845 if (Config->EMachine == EM_PPC64) {955 if (config->emachine == EM_PPC64) {
846 // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections956 // PPC64 has a number of special SHT_PROGBITS+SHF_ALLOC+SHF_WRITE sections
847 // that we would like to make sure appear is a specific order to maximize957 // that we would like to make sure appear is a specific order to maximize
848 // their coverage by a single signed 16-bit offset from the TOC base958 // their coverage by a single signed 16-bit offset from the TOC base
849 // pointer. Conversely, the special .tocbss section should be first among959 // pointer. Conversely, the special .tocbss section should be first among
850 // all SHT_NOBITS sections. This will put it next to the loaded special960 // all SHT_NOBITS sections. This will put it next to the loaded special
851 // PPC64 sections (and, thus, within reach of the TOC base pointer).961 // PPC64 sections (and, thus, within reach of the TOC base pointer).
852 StringRef Name = Sec->Name;962 StringRef name = sec->name;
853 if (Name != ".tocbss")963 if (name != ".tocbss")
854 Rank |= RF_PPC_NOT_TOCBSS;964 rank |= RF_PPC_NOT_TOCBSS;
855965
856 if (Name == ".toc1")966 if (name == ".toc1")
857 Rank |= RF_PPC_TOCL;967 rank |= RF_PPC_TOCL;
858968
859 if (Name == ".toc")969 if (name == ".toc")
860 Rank |= RF_PPC_TOC;970 rank |= RF_PPC_TOC;
861971
862 if (Name == ".got")972 if (name == ".got")
863 Rank |= RF_PPC_GOT;973 rank |= RF_PPC_GOT;
864974
865 if (Name == ".branch_lt")975 if (name == ".branch_lt")
866 Rank |= RF_PPC_BRANCH_LT;976 rank |= RF_PPC_BRANCH_LT;
867 }977 }
868978
869 if (Config->EMachine == EM_MIPS) {979 if (config->emachine == EM_MIPS) {
870 // All sections with SHF_MIPS_GPREL flag should be grouped together980 // All sections with SHF_MIPS_GPREL flag should be grouped together
871 // because data in these sections is addressable with a gp relative address.981 // because data in these sections is addressable with a gp relative address.
872 if (Sec->Flags & SHF_MIPS_GPREL)982 if (sec->flags & SHF_MIPS_GPREL)
873 Rank |= RF_MIPS_GPREL;983 rank |= RF_MIPS_GPREL;
874984
875 if (Sec->Name != ".got")985 if (sec->name != ".got")
876 Rank |= RF_MIPS_NOT_GOT;986 rank |= RF_MIPS_NOT_GOT;
877 }987 }
878988
879 return Rank;989 return rank;
880}990}
881991
882static bool compareSections(const BaseCommand *ACmd, const BaseCommand *BCmd) {992static bool compareSections(const BaseCommand *aCmd, const BaseCommand *bCmd) {
883 const OutputSection *A = cast<OutputSection>(ACmd);993 const OutputSection *a = cast<OutputSection>(aCmd);
884 const OutputSection *B = cast<OutputSection>(BCmd);994 const OutputSection *b = cast<OutputSection>(bCmd);
885995
886 if (A->SortRank != B->SortRank)996 if (a->sortRank != b->sortRank)
887 return A->SortRank < B->SortRank;997 return a->sortRank < b->sortRank;
888998
889 if (!(A->SortRank & RF_NOT_ADDR_SET))999 if (!(a->sortRank & RF_NOT_ADDR_SET))
890 return Config->SectionStartMap.lookup(A->Name) <1000 return config->sectionStartMap.lookup(a->name) <
891 Config->SectionStartMap.lookup(B->Name);1001 config->sectionStartMap.lookup(b->name);
892 return false;1002 return false;
893}1003}
8941004
895void PhdrEntry::add(OutputSection *Sec) {1005void PhdrEntry::add(OutputSection *sec) {
896 LastSec = Sec;1006 lastSec = sec;
897 if (!FirstSec)1007 if (!firstSec)
898 FirstSec = Sec;1008 firstSec = sec;
899 p_align = std::max(p_align, Sec->Alignment);1009 p_align = std::max(p_align, sec->alignment);
900 if (p_type == PT_LOAD)1010 if (p_type == PT_LOAD)
901 Sec->PtLoad = this;1011 sec->ptLoad = this;
902}1012}
9031013
904// The beginning and the ending of .rel[a].plt section are marked1014// The beginning and the ending of .rel[a].plt section are marked
...@@ -908,35 +1018,40 @@ void PhdrEntry::add(OutputSection *Sec) {...@@ -908,35 +1018,40 @@ void PhdrEntry::add(OutputSection *Sec) {
908// need these symbols, since IRELATIVE relocs are resolved through GOT1018// need these symbols, since IRELATIVE relocs are resolved through GOT
909// and PLT. For details, see http://www.airs.com/blog/archives/403.1019// and PLT. For details, see http://www.airs.com/blog/archives/403.
910template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {1020template <class ELFT> void Writer<ELFT>::addRelIpltSymbols() {
911 if (Config->Relocatable || needsInterpSection())1021 if (config->relocatable || needsInterpSection())
912 return;1022 return;
9131023
914 // By default, __rela_iplt_{start,end} belong to a dummy section 01024 // By default, __rela_iplt_{start,end} belong to a dummy section 0
915 // because .rela.plt might be empty and thus removed from output.1025 // because .rela.plt might be empty and thus removed from output.
916 // We'll override Out::ElfHeader with In.RelaIplt later when we are1026 // We'll override Out::elfHeader with In.relaIplt later when we are
917 // sure that .rela.plt exists in output.1027 // sure that .rela.plt exists in output.
918 ElfSym::RelaIpltStart = addOptionalRegular(1028 ElfSym::relaIpltStart = addOptionalRegular(
919 Config->IsRela ? "__rela_iplt_start" : "__rel_iplt_start",1029 config->isRela ? "__rela_iplt_start" : "__rel_iplt_start",
920 Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK);1030 Out::elfHeader, 0, STV_HIDDEN, STB_WEAK);
9211031
922 ElfSym::RelaIpltEnd = addOptionalRegular(1032 ElfSym::relaIpltEnd = addOptionalRegular(
923 Config->IsRela ? "__rela_iplt_end" : "__rel_iplt_end",1033 config->isRela ? "__rela_iplt_end" : "__rel_iplt_end",
924 Out::ElfHeader, 0, STV_HIDDEN, STB_WEAK);1034 Out::elfHeader, 0, STV_HIDDEN, STB_WEAK);
925}1035}
9261036
927template <class ELFT>1037template <class ELFT>
928void Writer<ELFT>::forEachRelSec(1038void Writer<ELFT>::forEachRelSec(
929 llvm::function_ref<void(InputSectionBase &)> Fn) {1039 llvm::function_ref<void(InputSectionBase &)> fn) {
930 // Scan all relocations. Each relocation goes through a series1040 // Scan all relocations. Each relocation goes through a series
931 // of tests to determine if it needs special treatment, such as1041 // of tests to determine if it needs special treatment, such as
932 // creating GOT, PLT, copy relocations, etc.1042 // creating GOT, PLT, copy relocations, etc.
933 // Note that relocations for non-alloc sections are directly1043 // Note that relocations for non-alloc sections are directly
934 // processed by InputSection::relocateNonAlloc.1044 // processed by InputSection::relocateNonAlloc.
935 for (InputSectionBase *IS : InputSections)1045 for (InputSectionBase *isec : inputSections)
936 if (IS->Live && isa<InputSection>(IS) && (IS->Flags & SHF_ALLOC))1046 if (isec->isLive() && isa<InputSection>(isec) && (isec->flags & SHF_ALLOC))
937 Fn(*IS);1047 fn(*isec);
938 for (EhInputSection *ES : In.EhFrame->Sections)1048 for (Partition &part : partitions) {
939 Fn(*ES);1049 for (EhInputSection *es : part.ehFrame->sections)
1050 fn(*es);
1051 if (part.armExidx && part.armExidx->isLive())
1052 for (InputSection *ex : part.armExidx->exidxSections)
1053 fn(*ex);
1054 }
940}1055}
9411056
942// This function generates assignments for predefined symbols (e.g. _end or1057// This function generates assignments for predefined symbols (e.g. _end or
...@@ -945,76 +1060,78 @@ void Writer<ELFT>::forEachRelSec(...@@ -945,76 +1060,78 @@ void Writer<ELFT>::forEachRelSec(
945// time any references to these symbols are processed and is equivalent to1060// time any references to these symbols are processed and is equivalent to
946// defining these symbols explicitly in the linker script.1061// defining these symbols explicitly in the linker script.
947template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {1062template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
948 if (ElfSym::GlobalOffsetTable) {1063 if (ElfSym::globalOffsetTable) {
949 // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually1064 // The _GLOBAL_OFFSET_TABLE_ symbol is defined by target convention usually
950 // to the start of the .got or .got.plt section.1065 // to the start of the .got or .got.plt section.
951 InputSection *GotSection = In.GotPlt;1066 InputSection *gotSection = in.gotPlt;
952 if (!Target->GotBaseSymInGotPlt)1067 if (!target->gotBaseSymInGotPlt)
953 GotSection = In.MipsGot ? cast<InputSection>(In.MipsGot)1068 gotSection = in.mipsGot ? cast<InputSection>(in.mipsGot)
954 : cast<InputSection>(In.Got);1069 : cast<InputSection>(in.got);
955 ElfSym::GlobalOffsetTable->Section = GotSection;1070 ElfSym::globalOffsetTable->section = gotSection;
956 }1071 }
9571072
958 // .rela_iplt_{start,end} mark the start and the end of .rela.plt section.1073 // .rela_iplt_{start,end} mark the start and the end of .rela.plt section.
959 if (ElfSym::RelaIpltStart && !In.RelaIplt->empty()) {1074 if (ElfSym::relaIpltStart && in.relaIplt->isNeeded()) {
960 ElfSym::RelaIpltStart->Section = In.RelaIplt;1075 ElfSym::relaIpltStart->section = in.relaIplt;
961 ElfSym::RelaIpltEnd->Section = In.RelaIplt;1076 ElfSym::relaIpltEnd->section = in.relaIplt;
962 ElfSym::RelaIpltEnd->Value = In.RelaIplt->getSize();1077 ElfSym::relaIpltEnd->value = in.relaIplt->getSize();
963 }1078 }
9641079
965 PhdrEntry *Last = nullptr;1080 PhdrEntry *last = nullptr;
966 PhdrEntry *LastRO = nullptr;1081 PhdrEntry *lastRO = nullptr;
9671082
968 for (PhdrEntry *P : Phdrs) {1083 for (Partition &part : partitions) {
969 if (P->p_type != PT_LOAD)1084 for (PhdrEntry *p : part.phdrs) {
970 continue;1085 if (p->p_type != PT_LOAD)
971 Last = P;1086 continue;
972 if (!(P->p_flags & PF_W))1087 last = p;
973 LastRO = P;1088 if (!(p->p_flags & PF_W))
1089 lastRO = p;
1090 }
974 }1091 }
9751092
976 if (LastRO) {1093 if (lastRO) {
977 // _etext is the first location after the last read-only loadable segment.1094 // _etext is the first location after the last read-only loadable segment.
978 if (ElfSym::Etext1)1095 if (ElfSym::etext1)
979 ElfSym::Etext1->Section = LastRO->LastSec;1096 ElfSym::etext1->section = lastRO->lastSec;
980 if (ElfSym::Etext2)1097 if (ElfSym::etext2)
981 ElfSym::Etext2->Section = LastRO->LastSec;1098 ElfSym::etext2->section = lastRO->lastSec;
982 }1099 }
9831100
984 if (Last) {1101 if (last) {
985 // _edata points to the end of the last mapped initialized section.1102 // _edata points to the end of the last mapped initialized section.
986 OutputSection *Edata = nullptr;1103 OutputSection *edata = nullptr;
987 for (OutputSection *OS : OutputSections) {1104 for (OutputSection *os : outputSections) {
988 if (OS->Type != SHT_NOBITS)1105 if (os->type != SHT_NOBITS)
989 Edata = OS;1106 edata = os;
990 if (OS == Last->LastSec)1107 if (os == last->lastSec)
991 break;1108 break;
992 }1109 }
9931110
994 if (ElfSym::Edata1)1111 if (ElfSym::edata1)
995 ElfSym::Edata1->Section = Edata;1112 ElfSym::edata1->section = edata;
996 if (ElfSym::Edata2)1113 if (ElfSym::edata2)
997 ElfSym::Edata2->Section = Edata;1114 ElfSym::edata2->section = edata;
9981115
999 // _end is the first location after the uninitialized data region.1116 // _end is the first location after the uninitialized data region.
1000 if (ElfSym::End1)1117 if (ElfSym::end1)
1001 ElfSym::End1->Section = Last->LastSec;1118 ElfSym::end1->section = last->lastSec;
1002 if (ElfSym::End2)1119 if (ElfSym::end2)
1003 ElfSym::End2->Section = Last->LastSec;1120 ElfSym::end2->section = last->lastSec;
1004 }1121 }
10051122
1006 if (ElfSym::Bss)1123 if (ElfSym::bss)
1007 ElfSym::Bss->Section = findSection(".bss");1124 ElfSym::bss->section = findSection(".bss");
10081125
1009 // Setup MIPS _gp_disp/__gnu_local_gp symbols which should1126 // Setup MIPS _gp_disp/__gnu_local_gp symbols which should
1010 // be equal to the _gp symbol's value.1127 // be equal to the _gp symbol's value.
1011 if (ElfSym::MipsGp) {1128 if (ElfSym::mipsGp) {
1012 // Find GP-relative section with the lowest address1129 // Find GP-relative section with the lowest address
1013 // and use this address to calculate default _gp value.1130 // and use this address to calculate default _gp value.
1014 for (OutputSection *OS : OutputSections) {1131 for (OutputSection *os : outputSections) {
1015 if (OS->Flags & SHF_MIPS_GPREL) {1132 if (os->flags & SHF_MIPS_GPREL) {
1016 ElfSym::MipsGp->Section = OS;1133 ElfSym::mipsGp->section = os;
1017 ElfSym::MipsGp->Value = 0x7ff0;1134 ElfSym::mipsGp->value = 0x7ff0;
1018 break;1135 break;
1019 }1136 }
1020 }1137 }
...@@ -1025,14 +1142,13 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {...@@ -1025,14 +1142,13 @@ template <class ELFT> void Writer<ELFT>::setReservedSymbolSections() {
1025// The more branches in getSectionRank that match, the more similar they are.1142// The more branches in getSectionRank that match, the more similar they are.
1026// Since each branch corresponds to a bit flag, we can just use1143// Since each branch corresponds to a bit flag, we can just use
1027// countLeadingZeros.1144// countLeadingZeros.
1028static int getRankProximityAux(OutputSection *A, OutputSection *B) {1145static int getRankProximityAux(OutputSection *a, OutputSection *b) {
1029 return countLeadingZeros(A->SortRank ^ B->SortRank);1146 return countLeadingZeros(a->sortRank ^ b->sortRank);
1030}1147}
10311148
1032static int getRankProximity(OutputSection *A, BaseCommand *B) {1149static int getRankProximity(OutputSection *a, BaseCommand *b) {
1033 if (auto *Sec = dyn_cast<OutputSection>(B))1150 auto *sec = dyn_cast<OutputSection>(b);
1034 return getRankProximityAux(A, Sec);1151 return (sec && sec->hasInputSections) ? getRankProximityAux(a, sec) : -1;
1035 return -1;
1036}1152}
10371153
1038// When placing orphan sections, we want to place them after symbol assignments1154// When placing orphan sections, we want to place them after symbol assignments
...@@ -1049,137 +1165,142 @@ static int getRankProximity(OutputSection *A, BaseCommand *B) {...@@ -1049,137 +1165,142 @@ static int getRankProximity(OutputSection *A, BaseCommand *B) {
1049// /* The RW PT_LOAD starts here*/1165// /* The RW PT_LOAD starts here*/
1050// rw_sec : { *(rw_sec) }1166// rw_sec : { *(rw_sec) }
1051// would mean that the RW PT_LOAD would become unaligned.1167// would mean that the RW PT_LOAD would become unaligned.
1052static bool shouldSkip(BaseCommand *Cmd) {1168static bool shouldSkip(BaseCommand *cmd) {
1053 if (auto *Assign = dyn_cast<SymbolAssignment>(Cmd))1169 if (auto *assign = dyn_cast<SymbolAssignment>(cmd))
1054 return Assign->Name != ".";1170 return assign->name != ".";
1055 return false;1171 return false;
1056}1172}
10571173
1058// We want to place orphan sections so that they share as much1174// We want to place orphan sections so that they share as much
1059// characteristics with their neighbors as possible. For example, if1175// characteristics with their neighbors as possible. For example, if
1060// both are rw, or both are tls.1176// both are rw, or both are tls.
1061template <typename ELFT>
1062static std::vector<BaseCommand *>::iterator1177static std::vector<BaseCommand *>::iterator
1063findOrphanPos(std::vector<BaseCommand *>::iterator B,1178findOrphanPos(std::vector<BaseCommand *>::iterator b,
1064 std::vector<BaseCommand *>::iterator E) {1179 std::vector<BaseCommand *>::iterator e) {
1065 OutputSection *Sec = cast<OutputSection>(*E);1180 OutputSection *sec = cast<OutputSection>(*e);
10661181
1067 // Find the first element that has as close a rank as possible.1182 // Find the first element that has as close a rank as possible.
1068 auto I = std::max_element(B, E, [=](BaseCommand *A, BaseCommand *B) {1183 auto i = std::max_element(b, e, [=](BaseCommand *a, BaseCommand *b) {
1069 return getRankProximity(Sec, A) < getRankProximity(Sec, B);1184 return getRankProximity(sec, a) < getRankProximity(sec, b);
1070 });1185 });
1071 if (I == E)1186 if (i == e)
1072 return E;1187 return e;
10731188
1074 // Consider all existing sections with the same proximity.1189 // Consider all existing sections with the same proximity.
1075 int Proximity = getRankProximity(Sec, *I);1190 int proximity = getRankProximity(sec, *i);
1076 for (; I != E; ++I) {1191 for (; i != e; ++i) {
1077 auto *CurSec = dyn_cast<OutputSection>(*I);1192 auto *curSec = dyn_cast<OutputSection>(*i);
1078 if (!CurSec)1193 if (!curSec || !curSec->hasInputSections)
1079 continue;1194 continue;
1080 if (getRankProximity(Sec, CurSec) != Proximity ||1195 if (getRankProximity(sec, curSec) != proximity ||
1081 Sec->SortRank < CurSec->SortRank)1196 sec->sortRank < curSec->sortRank)
1082 break;1197 break;
1083 }1198 }
10841199
1085 auto IsOutputSec = [](BaseCommand *Cmd) { return isa<OutputSection>(Cmd); };1200 auto isOutputSecWithInputSections = [](BaseCommand *cmd) {
1086 auto J = std::find_if(llvm::make_reverse_iterator(I),1201 auto *os = dyn_cast<OutputSection>(cmd);
1087 llvm::make_reverse_iterator(B), IsOutputSec);1202 return os && os->hasInputSections;
1088 I = J.base();1203 };
1204 auto j = std::find_if(llvm::make_reverse_iterator(i),
1205 llvm::make_reverse_iterator(b),
1206 isOutputSecWithInputSections);
1207 i = j.base();
10891208
1090 // As a special case, if the orphan section is the last section, put1209 // As a special case, if the orphan section is the last section, put
1091 // it at the very end, past any other commands.1210 // it at the very end, past any other commands.
1092 // This matches bfd's behavior and is convenient when the linker script fully1211 // This matches bfd's behavior and is convenient when the linker script fully
1093 // specifies the start of the file, but doesn't care about the end (the non1212 // specifies the start of the file, but doesn't care about the end (the non
1094 // alloc sections for example).1213 // alloc sections for example).
1095 auto NextSec = std::find_if(I, E, IsOutputSec);1214 auto nextSec = std::find_if(i, e, isOutputSecWithInputSections);
1096 if (NextSec == E)1215 if (nextSec == e)
1097 return E;1216 return e;
10981217
1099 while (I != E && shouldSkip(*I))1218 while (i != e && shouldSkip(*i))
1100 ++I;1219 ++i;
1101 return I;1220 return i;
1102}1221}
11031222
1104// Builds section order for handling --symbol-ordering-file.1223// Builds section order for handling --symbol-ordering-file.
1105static DenseMap<const InputSectionBase *, int> buildSectionOrder() {1224static DenseMap<const InputSectionBase *, int> buildSectionOrder() {
1106 DenseMap<const InputSectionBase *, int> SectionOrder;1225 DenseMap<const InputSectionBase *, int> sectionOrder;
1107 // Use the rarely used option -call-graph-ordering-file to sort sections.1226 // Use the rarely used option -call-graph-ordering-file to sort sections.
1108 if (!Config->CallGraphProfile.empty())1227 if (!config->callGraphProfile.empty())
1109 return computeCallGraphProfileOrder();1228 return computeCallGraphProfileOrder();
11101229
1111 if (Config->SymbolOrderingFile.empty())1230 if (config->symbolOrderingFile.empty())
1112 return SectionOrder;1231 return sectionOrder;
11131232
1114 struct SymbolOrderEntry {1233 struct SymbolOrderEntry {
1115 int Priority;1234 int priority;
1116 bool Present;1235 bool present;
1117 };1236 };
11181237
1119 // Build a map from symbols to their priorities. Symbols that didn't1238 // Build a map from symbols to their priorities. Symbols that didn't
1120 // appear in the symbol ordering file have the lowest priority 0.1239 // appear in the symbol ordering file have the lowest priority 0.
1121 // All explicitly mentioned symbols have negative (higher) priorities.1240 // All explicitly mentioned symbols have negative (higher) priorities.
1122 DenseMap<StringRef, SymbolOrderEntry> SymbolOrder;1241 DenseMap<StringRef, SymbolOrderEntry> symbolOrder;
1123 int Priority = -Config->SymbolOrderingFile.size();1242 int priority = -config->symbolOrderingFile.size();
1124 for (StringRef S : Config->SymbolOrderingFile)1243 for (StringRef s : config->symbolOrderingFile)
1125 SymbolOrder.insert({S, {Priority++, false}});1244 symbolOrder.insert({s, {priority++, false}});
11261245
1127 // Build a map from sections to their priorities.1246 // Build a map from sections to their priorities.
1128 auto AddSym = [&](Symbol &Sym) {1247 auto addSym = [&](Symbol &sym) {
1129 auto It = SymbolOrder.find(Sym.getName());1248 auto it = symbolOrder.find(sym.getName());
1130 if (It == SymbolOrder.end())1249 if (it == symbolOrder.end())
1131 return;1250 return;
1132 SymbolOrderEntry &Ent = It->second;1251 SymbolOrderEntry &ent = it->second;
1133 Ent.Present = true;1252 ent.present = true;
11341253
1135 maybeWarnUnorderableSymbol(&Sym);1254 maybeWarnUnorderableSymbol(&sym);
11361255
1137 if (auto *D = dyn_cast<Defined>(&Sym)) {1256 if (auto *d = dyn_cast<Defined>(&sym)) {
1138 if (auto *Sec = dyn_cast_or_null<InputSectionBase>(D->Section)) {1257 if (auto *sec = dyn_cast_or_null<InputSectionBase>(d->section)) {
1139 int &Priority = SectionOrder[cast<InputSectionBase>(Sec->Repl)];1258 int &priority = sectionOrder[cast<InputSectionBase>(sec->repl)];
1140 Priority = std::min(Priority, Ent.Priority);1259 priority = std::min(priority, ent.priority);
1141 }1260 }
1142 }1261 }
1143 };1262 };
11441263
1145 // We want both global and local symbols. We get the global ones from the1264 // We want both global and local symbols. We get the global ones from the
1146 // symbol table and iterate the object files for the local ones.1265 // symbol table and iterate the object files for the local ones.
1147 for (Symbol *Sym : Symtab->getSymbols())1266 symtab->forEachSymbol([&](Symbol *sym) {
1148 if (!Sym->isLazy())1267 if (!sym->isLazy())
1149 AddSym(*Sym);1268 addSym(*sym);
1150 for (InputFile *File : ObjectFiles)1269 });
1151 for (Symbol *Sym : File->getSymbols())
1152 if (Sym->isLocal())
1153 AddSym(*Sym);
11541270
1155 if (Config->WarnSymbolOrdering)1271 for (InputFile *file : objectFiles)
1156 for (auto OrderEntry : SymbolOrder)1272 for (Symbol *sym : file->getSymbols())
1157 if (!OrderEntry.second.Present)1273 if (sym->isLocal())
1158 warn("symbol ordering file: no such symbol: " + OrderEntry.first);1274 addSym(*sym);
11591275
1160 return SectionOrder;1276 if (config->warnSymbolOrdering)
1277 for (auto orderEntry : symbolOrder)
1278 if (!orderEntry.second.present)
1279 warn("symbol ordering file: no such symbol: " + orderEntry.first);
1280
1281 return sectionOrder;
1161}1282}
11621283
1163// Sorts the sections in ISD according to the provided section order.1284// Sorts the sections in ISD according to the provided section order.
1164static void1285static void
1165sortISDBySectionOrder(InputSectionDescription *ISD,1286sortISDBySectionOrder(InputSectionDescription *isd,
1166 const DenseMap<const InputSectionBase *, int> &Order) {1287 const DenseMap<const InputSectionBase *, int> &order) {
1167 std::vector<InputSection *> UnorderedSections;1288 std::vector<InputSection *> unorderedSections;
1168 std::vector<std::pair<InputSection *, int>> OrderedSections;1289 std::vector<std::pair<InputSection *, int>> orderedSections;
1169 uint64_t UnorderedSize = 0;1290 uint64_t unorderedSize = 0;
11701291
1171 for (InputSection *IS : ISD->Sections) {1292 for (InputSection *isec : isd->sections) {
1172 auto I = Order.find(IS);1293 auto i = order.find(isec);
1173 if (I == Order.end()) {1294 if (i == order.end()) {
1174 UnorderedSections.push_back(IS);1295 unorderedSections.push_back(isec);
1175 UnorderedSize += IS->getSize();1296 unorderedSize += isec->getSize();
1176 continue;1297 continue;
1177 }1298 }
1178 OrderedSections.push_back({IS, I->second});1299 orderedSections.push_back({isec, i->second});
1179 }1300 }
1180 llvm::sort(OrderedSections, [&](std::pair<InputSection *, int> A,1301 llvm::sort(orderedSections, [&](std::pair<InputSection *, int> a,
1181 std::pair<InputSection *, int> B) {1302 std::pair<InputSection *, int> b) {
1182 return A.second < B.second;1303 return a.second < b.second;
1183 });1304 });
11841305
1185 // Find an insertion point for the ordered section list in the unordered1306 // Find an insertion point for the ordered section list in the unordered
...@@ -1209,96 +1330,114 @@ sortISDBySectionOrder(InputSectionDescription *ISD,...@@ -1209,96 +1330,114 @@ sortISDBySectionOrder(InputSectionDescription *ISD,
1209 // of the second block of cold code can call the hot code without a thunk. So1330 // of the second block of cold code can call the hot code without a thunk. So
1210 // we effectively double the amount of code that could potentially call into1331 // we effectively double the amount of code that could potentially call into
1211 // the hot code without a thunk.1332 // the hot code without a thunk.
1212 size_t InsPt = 0;1333 size_t insPt = 0;
1213 if (Target->getThunkSectionSpacing() && !OrderedSections.empty()) {1334 if (target->getThunkSectionSpacing() && !orderedSections.empty()) {
1214 uint64_t UnorderedPos = 0;1335 uint64_t unorderedPos = 0;
1215 for (; InsPt != UnorderedSections.size(); ++InsPt) {1336 for (; insPt != unorderedSections.size(); ++insPt) {
1216 UnorderedPos += UnorderedSections[InsPt]->getSize();1337 unorderedPos += unorderedSections[insPt]->getSize();
1217 if (UnorderedPos > UnorderedSize / 2)1338 if (unorderedPos > unorderedSize / 2)
1218 break;1339 break;
1219 }1340 }
1220 }1341 }
12211342
1222 ISD->Sections.clear();1343 isd->sections.clear();
1223 for (InputSection *IS : makeArrayRef(UnorderedSections).slice(0, InsPt))1344 for (InputSection *isec : makeArrayRef(unorderedSections).slice(0, insPt))
1224 ISD->Sections.push_back(IS);1345 isd->sections.push_back(isec);
1225 for (std::pair<InputSection *, int> P : OrderedSections)1346 for (std::pair<InputSection *, int> p : orderedSections)
1226 ISD->Sections.push_back(P.first);1347 isd->sections.push_back(p.first);
1227 for (InputSection *IS : makeArrayRef(UnorderedSections).slice(InsPt))1348 for (InputSection *isec : makeArrayRef(unorderedSections).slice(insPt))
1228 ISD->Sections.push_back(IS);1349 isd->sections.push_back(isec);
1229}1350}
12301351
1231static void sortSection(OutputSection *Sec,1352static void sortSection(OutputSection *sec,
1232 const DenseMap<const InputSectionBase *, int> &Order) {1353 const DenseMap<const InputSectionBase *, int> &order) {
1233 StringRef Name = Sec->Name;1354 StringRef name = sec->name;
12341355
1235 // Sort input sections by section name suffixes for1356 // Sort input sections by section name suffixes for
1236 // __attribute__((init_priority(N))).1357 // __attribute__((init_priority(N))).
1237 if (Name == ".init_array" || Name == ".fini_array") {1358 if (name == ".init_array" || name == ".fini_array") {
1238 if (!Script->HasSectionsCommand)1359 if (!script->hasSectionsCommand)
1239 Sec->sortInitFini();1360 sec->sortInitFini();
1240 return;1361 return;
1241 }1362 }
12421363
1243 // Sort input sections by the special rule for .ctors and .dtors.1364 // Sort input sections by the special rule for .ctors and .dtors.
1244 if (Name == ".ctors" || Name == ".dtors") {1365 if (name == ".ctors" || name == ".dtors") {
1245 if (!Script->HasSectionsCommand)1366 if (!script->hasSectionsCommand)
1246 Sec->sortCtorsDtors();1367 sec->sortCtorsDtors();
1247 return;1368 return;
1248 }1369 }
12491370
1250 // Never sort these.1371 // Never sort these.
1251 if (Name == ".init" || Name == ".fini")1372 if (name == ".init" || name == ".fini")
1373 return;
1374
1375 // .toc is allocated just after .got and is accessed using GOT-relative
1376 // relocations. Object files compiled with small code model have an
1377 // addressable range of [.got, .got + 0xFFFC] for GOT-relative relocations.
1378 // To reduce the risk of relocation overflow, .toc contents are sorted so that
1379 // sections having smaller relocation offsets are at beginning of .toc
1380 if (config->emachine == EM_PPC64 && name == ".toc") {
1381 if (script->hasSectionsCommand)
1382 return;
1383 assert(sec->sectionCommands.size() == 1);
1384 auto *isd = cast<InputSectionDescription>(sec->sectionCommands[0]);
1385 llvm::stable_sort(isd->sections,
1386 [](const InputSection *a, const InputSection *b) -> bool {
1387 return a->file->ppc64SmallCodeModelTocRelocs &&
1388 !b->file->ppc64SmallCodeModelTocRelocs;
1389 });
1252 return;1390 return;
1391 }
12531392
1254 // Sort input sections by priority using the list provided1393 // Sort input sections by priority using the list provided
1255 // by --symbol-ordering-file.1394 // by --symbol-ordering-file.
1256 if (!Order.empty())1395 if (!order.empty())
1257 for (BaseCommand *B : Sec->SectionCommands)1396 for (BaseCommand *b : sec->sectionCommands)
1258 if (auto *ISD = dyn_cast<InputSectionDescription>(B))1397 if (auto *isd = dyn_cast<InputSectionDescription>(b))
1259 sortISDBySectionOrder(ISD, Order);1398 sortISDBySectionOrder(isd, order);
1260}1399}
12611400
1262// If no layout was provided by linker script, we want to apply default1401// If no layout was provided by linker script, we want to apply default
1263// sorting for special input sections. This also handles --symbol-ordering-file.1402// sorting for special input sections. This also handles --symbol-ordering-file.
1264template <class ELFT> void Writer<ELFT>::sortInputSections() {1403template <class ELFT> void Writer<ELFT>::sortInputSections() {
1265 // Build the order once since it is expensive.1404 // Build the order once since it is expensive.
1266 DenseMap<const InputSectionBase *, int> Order = buildSectionOrder();1405 DenseMap<const InputSectionBase *, int> order = buildSectionOrder();
1267 for (BaseCommand *Base : Script->SectionCommands)1406 for (BaseCommand *base : script->sectionCommands)
1268 if (auto *Sec = dyn_cast<OutputSection>(Base))1407 if (auto *sec = dyn_cast<OutputSection>(base))
1269 sortSection(Sec, Order);1408 sortSection(sec, order);
1270}1409}
12711410
1272template <class ELFT> void Writer<ELFT>::sortSections() {1411template <class ELFT> void Writer<ELFT>::sortSections() {
1273 Script->adjustSectionsBeforeSorting();1412 script->adjustSectionsBeforeSorting();
12741413
1275 // Don't sort if using -r. It is not necessary and we want to preserve the1414 // Don't sort if using -r. It is not necessary and we want to preserve the
1276 // relative order for SHF_LINK_ORDER sections.1415 // relative order for SHF_LINK_ORDER sections.
1277 if (Config->Relocatable)1416 if (config->relocatable)
1278 return;1417 return;
12791418
1280 sortInputSections();1419 sortInputSections();
12811420
1282 for (BaseCommand *Base : Script->SectionCommands) {1421 for (BaseCommand *base : script->sectionCommands) {
1283 auto *OS = dyn_cast<OutputSection>(Base);1422 auto *os = dyn_cast<OutputSection>(base);
1284 if (!OS)1423 if (!os)
1285 continue;1424 continue;
1286 OS->SortRank = getSectionRank(OS);1425 os->sortRank = getSectionRank(os);
12871426
1288 // We want to assign rude approximation values to OutSecOff fields1427 // We want to assign rude approximation values to outSecOff fields
1289 // to know the relative order of the input sections. We use it for1428 // to know the relative order of the input sections. We use it for
1290 // sorting SHF_LINK_ORDER sections. See resolveShfLinkOrder().1429 // sorting SHF_LINK_ORDER sections. See resolveShfLinkOrder().
1291 uint64_t I = 0;1430 uint64_t i = 0;
1292 for (InputSection *Sec : getInputSections(OS))1431 for (InputSection *sec : getInputSections(os))
1293 Sec->OutSecOff = I++;1432 sec->outSecOff = i++;
1294 }1433 }
12951434
1296 if (!Script->HasSectionsCommand) {1435 if (!script->hasSectionsCommand) {
1297 // We know that all the OutputSections are contiguous in this case.1436 // We know that all the OutputSections are contiguous in this case.
1298 auto IsSection = [](BaseCommand *Base) { return isa<OutputSection>(Base); };1437 auto isSection = [](BaseCommand *base) { return isa<OutputSection>(base); };
1299 std::stable_sort(1438 std::stable_sort(
1300 llvm::find_if(Script->SectionCommands, IsSection),1439 llvm::find_if(script->sectionCommands, isSection),
1301 llvm::find_if(llvm::reverse(Script->SectionCommands), IsSection).base(),1440 llvm::find_if(llvm::reverse(script->sectionCommands), isSection).base(),
1302 compareSections);1441 compareSections);
1303 return;1442 return;
1304 }1443 }
...@@ -1342,211 +1481,127 @@ template <class ELFT> void Writer<ELFT>::sortSections() {...@@ -1342,211 +1481,127 @@ template <class ELFT> void Writer<ELFT>::sortSections() {
1342 // after another commands. For the details, look at shouldSkip1481 // after another commands. For the details, look at shouldSkip
1343 // function.1482 // function.
13441483
1345 auto I = Script->SectionCommands.begin();1484 auto i = script->sectionCommands.begin();
1346 auto E = Script->SectionCommands.end();1485 auto e = script->sectionCommands.end();
1347 auto NonScriptI = std::find_if(I, E, [](BaseCommand *Base) {1486 auto nonScriptI = std::find_if(i, e, [](BaseCommand *base) {
1348 if (auto *Sec = dyn_cast<OutputSection>(Base))1487 if (auto *sec = dyn_cast<OutputSection>(base))
1349 return Sec->SectionIndex == UINT32_MAX;1488 return sec->sectionIndex == UINT32_MAX;
1350 return false;1489 return false;
1351 });1490 });
13521491
1353 // Sort the orphan sections.1492 // Sort the orphan sections.
1354 std::stable_sort(NonScriptI, E, compareSections);1493 std::stable_sort(nonScriptI, e, compareSections);
13551494
1356 // As a horrible special case, skip the first . assignment if it is before any1495 // As a horrible special case, skip the first . assignment if it is before any
1357 // section. We do this because it is common to set a load address by starting1496 // section. We do this because it is common to set a load address by starting
1358 // the script with ". = 0xabcd" and the expectation is that every section is1497 // the script with ". = 0xabcd" and the expectation is that every section is
1359 // after that.1498 // after that.
1360 auto FirstSectionOrDotAssignment =1499 auto firstSectionOrDotAssignment =
1361 std::find_if(I, E, [](BaseCommand *Cmd) { return !shouldSkip(Cmd); });1500 std::find_if(i, e, [](BaseCommand *cmd) { return !shouldSkip(cmd); });
1362 if (FirstSectionOrDotAssignment != E &&1501 if (firstSectionOrDotAssignment != e &&
1363 isa<SymbolAssignment>(**FirstSectionOrDotAssignment))1502 isa<SymbolAssignment>(**firstSectionOrDotAssignment))
1364 ++FirstSectionOrDotAssignment;1503 ++firstSectionOrDotAssignment;
1365 I = FirstSectionOrDotAssignment;1504 i = firstSectionOrDotAssignment;
13661505
1367 while (NonScriptI != E) {1506 while (nonScriptI != e) {
1368 auto Pos = findOrphanPos<ELFT>(I, NonScriptI);1507 auto pos = findOrphanPos(i, nonScriptI);
1369 OutputSection *Orphan = cast<OutputSection>(*NonScriptI);1508 OutputSection *orphan = cast<OutputSection>(*nonScriptI);
13701509
1371 // As an optimization, find all sections with the same sort rank1510 // As an optimization, find all sections with the same sort rank
1372 // and insert them with one rotate.1511 // and insert them with one rotate.
1373 unsigned Rank = Orphan->SortRank;1512 unsigned rank = orphan->sortRank;
1374 auto End = std::find_if(NonScriptI + 1, E, [=](BaseCommand *Cmd) {1513 auto end = std::find_if(nonScriptI + 1, e, [=](BaseCommand *cmd) {
1375 return cast<OutputSection>(Cmd)->SortRank != Rank;1514 return cast<OutputSection>(cmd)->sortRank != rank;
1376 });1515 });
1377 std::rotate(Pos, NonScriptI, End);1516 std::rotate(pos, nonScriptI, end);
1378 NonScriptI = End;1517 nonScriptI = end;
1379 }1518 }
13801519
1381 Script->adjustSectionsAfterSorting();1520 script->adjustSectionsAfterSorting();
1382}1521}
13831522
1384static bool compareByFilePosition(InputSection *A, InputSection *B) {1523static bool compareByFilePosition(InputSection *a, InputSection *b) {
1385 // Synthetic, i. e. a sentinel section, should go last.1524 InputSection *la = a->getLinkOrderDep();
1386 if (A->kind() == InputSectionBase::Synthetic ||1525 InputSection *lb = b->getLinkOrderDep();
1387 B->kind() == InputSectionBase::Synthetic)1526 OutputSection *aOut = la->getParent();
1388 return A->kind() != InputSectionBase::Synthetic;1527 OutputSection *bOut = lb->getParent();
1389
1390 InputSection *LA = A->getLinkOrderDep();
1391 InputSection *LB = B->getLinkOrderDep();
1392 OutputSection *AOut = LA->getParent();
1393 OutputSection *BOut = LB->getParent();
1394
1395 if (AOut != BOut)
1396 return AOut->SectionIndex < BOut->SectionIndex;
1397 return LA->OutSecOff < LB->OutSecOff;
1398}
1399
1400// This function is used by the --merge-exidx-entries to detect duplicate
1401// .ARM.exidx sections. It is Arm only.
1402//
1403// The .ARM.exidx section is of the form:
1404// | PREL31 offset to function | Unwind instructions for function |
1405// where the unwind instructions are either a small number of unwind
1406// instructions inlined into the table entry, the special CANT_UNWIND value of
1407// 0x1 or a PREL31 offset into a .ARM.extab Section that contains unwind
1408// instructions.
1409//
1410// We return true if all the unwind instructions in the .ARM.exidx entries of
1411// Cur can be merged into the last entry of Prev.
1412static bool isDuplicateArmExidxSec(InputSection *Prev, InputSection *Cur) {
1413
1414 // References to .ARM.Extab Sections have bit 31 clear and are not the
1415 // special EXIDX_CANTUNWIND bit-pattern.
1416 auto IsExtabRef = [](uint32_t Unwind) {
1417 return (Unwind & 0x80000000) == 0 && Unwind != 0x1;
1418 };
1419
1420 struct ExidxEntry {
1421 ulittle32_t Fn;
1422 ulittle32_t Unwind;
1423 };
1424
1425 // Get the last table Entry from the previous .ARM.exidx section.
1426 const ExidxEntry &PrevEntry = Prev->getDataAs<ExidxEntry>().back();
1427 if (IsExtabRef(PrevEntry.Unwind))
1428 return false;
1429
1430 // We consider the unwind instructions of an .ARM.exidx table entry
1431 // a duplicate if the previous unwind instructions if:
1432 // - Both are the special EXIDX_CANTUNWIND.
1433 // - Both are the same inline unwind instructions.
1434 // We do not attempt to follow and check links into .ARM.extab tables as
1435 // consecutive identical entries are rare and the effort to check that they
1436 // are identical is high.
14371528
1438 for (const ExidxEntry Entry : Cur->getDataAs<ExidxEntry>())1529 if (aOut != bOut)
1439 if (IsExtabRef(Entry.Unwind) || Entry.Unwind != PrevEntry.Unwind)1530 return aOut->sectionIndex < bOut->sectionIndex;
1440 return false;1531 return la->outSecOff < lb->outSecOff;
1441
1442 // All table entries in this .ARM.exidx Section can be merged into the
1443 // previous Section.
1444 return true;
1445}1532}
14461533
1447template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {1534template <class ELFT> void Writer<ELFT>::resolveShfLinkOrder() {
1448 for (OutputSection *Sec : OutputSections) {1535 for (OutputSection *sec : outputSections) {
1449 if (!(Sec->Flags & SHF_LINK_ORDER))1536 if (!(sec->flags & SHF_LINK_ORDER))
1450 continue;1537 continue;
14511538
1452 // Link order may be distributed across several InputSectionDescriptions1539 // Link order may be distributed across several InputSectionDescriptions
1453 // but sort must consider them all at once.1540 // but sort must consider them all at once.
1454 std::vector<InputSection **> ScriptSections;1541 std::vector<InputSection **> scriptSections;
1455 std::vector<InputSection *> Sections;1542 std::vector<InputSection *> sections;
1456 for (BaseCommand *Base : Sec->SectionCommands) {1543 for (BaseCommand *base : sec->sectionCommands) {
1457 if (auto *ISD = dyn_cast<InputSectionDescription>(Base)) {1544 if (auto *isd = dyn_cast<InputSectionDescription>(base)) {
1458 for (InputSection *&IS : ISD->Sections) {1545 for (InputSection *&isec : isd->sections) {
1459 ScriptSections.push_back(&IS);1546 scriptSections.push_back(&isec);
1460 Sections.push_back(IS);1547 sections.push_back(isec);
1461 }1548 }
1462 }1549 }
1463 }1550 }
1464 std::stable_sort(Sections.begin(), Sections.end(), compareByFilePosition);
1465
1466 if (!Config->Relocatable && Config->EMachine == EM_ARM &&
1467 Sec->Type == SHT_ARM_EXIDX) {
1468
1469 if (auto *Sentinel = dyn_cast<ARMExidxSentinelSection>(Sections.back())) {
1470 assert(Sections.size() >= 2 &&
1471 "We should create a sentinel section only if there are "
1472 "alive regular exidx sections.");
14731551
1474 // The last executable section is required to fill the sentinel.1552 // The ARM.exidx section use SHF_LINK_ORDER, but we have consolidated
1475 // Remember it here so that we don't have to find it again.1553 // this processing inside the ARMExidxsyntheticsection::finalizeContents().
1476 Sentinel->Highest = Sections[Sections.size() - 2]->getLinkOrderDep();1554 if (!config->relocatable && config->emachine == EM_ARM &&
1477 }1555 sec->type == SHT_ARM_EXIDX)
14781556 continue;
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.
1485 if (Config->MergeArmExidx) {
1486 size_t Prev = 0;
1487 // The last one is a sentinel entry which should not be removed.
1488 for (size_t I = 1; I < Sections.size() - 1; ++I) {
1489 if (isDuplicateArmExidxSec(Sections[Prev], Sections[I]))
1490 Sections[I] = nullptr;
1491 else
1492 Prev = I;
1493 }
1494 }
1495 }
14961557
1497 for (int I = 0, N = Sections.size(); I < N; ++I)1558 llvm::stable_sort(sections, compareByFilePosition);
1498 *ScriptSections[I] = Sections[I];
14991559
1500 // Remove the Sections we marked as duplicate earlier.1560 for (int i = 0, n = sections.size(); i < n; ++i)
1501 for (BaseCommand *Base : Sec->SectionCommands)1561 *scriptSections[i] = sections[i];
1502 if (auto *ISD = dyn_cast<InputSectionDescription>(Base))
1503 llvm::erase_if(ISD->Sections, [](InputSection *IS) { return !IS; });
1504 }1562 }
1505}1563}
15061564
1507// For most RISC ISAs, we need to generate content that depends on the address1565// We need to generate and finalize the content that depends on the address of
1508// of InputSections. For example some architectures such as AArch64 use small1566// InputSections. As the generation of the content may also alter InputSection
1509// displacements for jump instructions that is the linker's responsibility for1567// addresses we must converge to a fixed point. We do that here. See the comment
1510// creating range extension thunks for. As the generation of the content may1568// in Writer<ELFT>::finalizeSections().
1511// also alter InputSection addresses we must converge to a fixed point.1569template <class ELFT> void Writer<ELFT>::finalizeAddressDependentContent() {
1512template <class ELFT> void Writer<ELFT>::maybeAddThunks() {1570 ThunkCreator tc;
1513 if (!Target->NeedsThunks && !Config->AndroidPackDynRelocs &&1571 AArch64Err843419Patcher a64p;
1514 !Config->RelrPackDynRelocs)
1515 return;
1516
1517 ThunkCreator TC;
1518 AArch64Err843419Patcher A64P;
15191572
1573 // For some targets, like x86, this loop iterates only once.
1520 for (;;) {1574 for (;;) {
1521 bool Changed = false;1575 bool changed = false;
15221576
1523 Script->assignAddresses();1577 script->assignAddresses();
15241578
1525 if (Target->NeedsThunks)1579 if (target->needsThunks)
1526 Changed |= TC.createThunks(OutputSections);1580 changed |= tc.createThunks(outputSections);
15271581
1528 if (Config->FixCortexA53Errata843419) {1582 if (config->fixCortexA53Errata843419) {
1529 if (Changed)1583 if (changed)
1530 Script->assignAddresses();1584 script->assignAddresses();
1531 Changed |= A64P.createFixes();1585 changed |= a64p.createFixes();
1532 }1586 }
15331587
1534 if (In.MipsGot)1588 if (in.mipsGot)
1535 In.MipsGot->updateAllocSize();1589 in.mipsGot->updateAllocSize();
1536
1537 Changed |= In.RelaDyn->updateAllocSize();
15381590
1539 if (In.RelrDyn)1591 for (Partition &part : partitions) {
1540 Changed |= In.RelrDyn->updateAllocSize();1592 changed |= part.relaDyn->updateAllocSize();
1593 if (part.relrDyn)
1594 changed |= part.relrDyn->updateAllocSize();
1595 }
15411596
1542 if (!Changed)1597 if (!changed)
1543 return;1598 return;
1544 }1599 }
1545}1600}
15461601
1547static void finalizeSynthetic(SyntheticSection *Sec) {1602static void finalizeSynthetic(SyntheticSection *sec) {
1548 if (Sec && !Sec->empty() && Sec->getParent())1603 if (sec && sec->isNeeded() && sec->getParent())
1549 Sec->finalizeContents();1604 sec->finalizeContents();
1550}1605}
15511606
1552// In order to allow users to manipulate linker-synthesized sections,1607// In order to allow users to manipulate linker-synthesized sections,
...@@ -1565,128 +1620,190 @@ static void removeUnusedSyntheticSections() {...@@ -1565,128 +1620,190 @@ static void removeUnusedSyntheticSections() {
1565 // All input synthetic sections that can be empty are placed after1620 // All input synthetic sections that can be empty are placed after
1566 // all regular ones. We iterate over them all and exit at first1621 // all regular ones. We iterate over them all and exit at first
1567 // non-synthetic.1622 // non-synthetic.
1568 for (InputSectionBase *S : llvm::reverse(InputSections)) {1623 for (InputSectionBase *s : llvm::reverse(inputSections)) {
1569 SyntheticSection *SS = dyn_cast<SyntheticSection>(S);1624 SyntheticSection *ss = dyn_cast<SyntheticSection>(s);
1570 if (!SS)1625 if (!ss)
1571 return;1626 return;
1572 OutputSection *OS = SS->getParent();1627 OutputSection *os = ss->getParent();
1573 if (!OS || !SS->empty())1628 if (!os || ss->isNeeded())
1574 continue;1629 continue;
15751630
1576 // If we reach here, then SS is an unused synthetic section and we want to1631 // If we reach here, then SS is an unused synthetic section and we want to
1577 // remove it from corresponding input section description of output section.1632 // remove it from corresponding input section description of output section.
1578 for (BaseCommand *B : OS->SectionCommands)1633 for (BaseCommand *b : os->sectionCommands)
1579 if (auto *ISD = dyn_cast<InputSectionDescription>(B))1634 if (auto *isd = dyn_cast<InputSectionDescription>(b))
1580 llvm::erase_if(ISD->Sections,1635 llvm::erase_if(isd->sections,
1581 [=](InputSection *IS) { return IS == SS; });1636 [=](InputSection *isec) { return isec == ss; });
1582 }1637 }
1583}1638}
15841639
1585// Returns true if a symbol can be replaced at load-time by a symbol1640// Returns true if a symbol can be replaced at load-time by a symbol
1586// with the same name defined in other ELF executable or DSO.1641// with the same name defined in other ELF executable or DSO.
1587static bool computeIsPreemptible(const Symbol &B) {1642static bool computeIsPreemptible(const Symbol &b) {
1588 assert(!B.isLocal());1643 assert(!b.isLocal());
15891644
1590 // Only symbols that appear in dynsym can be preempted.1645 // Only symbols that appear in dynsym can be preempted.
1591 if (!B.includeInDynsym())1646 if (!b.includeInDynsym())
1592 return false;1647 return false;
15931648
1594 // Only default visibility symbols can be preempted.1649 // Only default visibility symbols can be preempted.
1595 if (B.Visibility != STV_DEFAULT)1650 if (b.visibility != STV_DEFAULT)
1596 return false;1651 return false;
15971652
1598 // At this point copy relocations have not been created yet, so any1653 // At this point copy relocations have not been created yet, so any
1599 // symbol that is not defined locally is preemptible.1654 // symbol that is not defined locally is preemptible.
1600 if (!B.isDefined())1655 if (!b.isDefined())
1601 return true;1656 return true;
16021657
1603 // If we have a dynamic list it specifies which local symbols are preemptible.1658 // If we have a dynamic list it specifies which local symbols are preemptible.
1604 if (Config->HasDynamicList)1659 if (config->hasDynamicList)
1605 return false;1660 return false;
16061661
1607 if (!Config->Shared)1662 if (!config->shared)
1608 return false;1663 return false;
16091664
1610 // -Bsymbolic means that definitions are not preempted.1665 // -Bsymbolic means that definitions are not preempted.
1611 if (Config->Bsymbolic || (Config->BsymbolicFunctions && B.isFunc()))1666 if (config->bsymbolic || (config->bsymbolicFunctions && b.isFunc()))
1612 return false;1667 return false;
1613 return true;1668 return true;
1614}1669}
16151670
1616// Create output section objects and add them to OutputSections.1671// Create output section objects and add them to OutputSections.
1617template <class ELFT> void Writer<ELFT>::finalizeSections() {1672template <class ELFT> void Writer<ELFT>::finalizeSections() {
1618 Out::PreinitArray = findSection(".preinit_array");1673 Out::preinitArray = findSection(".preinit_array");
1619 Out::InitArray = findSection(".init_array");1674 Out::initArray = findSection(".init_array");
1620 Out::FiniArray = findSection(".fini_array");1675 Out::finiArray = findSection(".fini_array");
16211676
1622 // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop1677 // The linker needs to define SECNAME_start, SECNAME_end and SECNAME_stop
1623 // symbols for sections, so that the runtime can get the start and end1678 // symbols for sections, so that the runtime can get the start and end
1624 // addresses of each section by section name. Add such symbols.1679 // addresses of each section by section name. Add such symbols.
1625 if (!Config->Relocatable) {1680 if (!config->relocatable) {
1626 addStartEndSymbols();1681 addStartEndSymbols();
1627 for (BaseCommand *Base : Script->SectionCommands)1682 for (BaseCommand *base : script->sectionCommands)
1628 if (auto *Sec = dyn_cast<OutputSection>(Base))1683 if (auto *sec = dyn_cast<OutputSection>(base))
1629 addStartStopSymbols(Sec);1684 addStartStopSymbols(sec);
1630 }1685 }
16311686
1632 // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.1687 // Add _DYNAMIC symbol. Unlike GNU gold, our _DYNAMIC symbol has no type.
1633 // It should be okay as no one seems to care about the type.1688 // It should be okay as no one seems to care about the type.
1634 // Even the author of gold doesn't remember why gold behaves that way.1689 // Even the author of gold doesn't remember why gold behaves that way.
1635 // https://sourceware.org/ml/binutils/2002-03/msg00360.html1690 // https://sourceware.org/ml/binutils/2002-03/msg00360.html
1636 if (In.Dynamic->Parent)1691 if (mainPart->dynamic->parent)
1637 Symtab->addDefined("_DYNAMIC", STV_HIDDEN, STT_NOTYPE, 0 /*Value*/,1692 symtab->addSymbol(Defined{/*file=*/nullptr, "_DYNAMIC", STB_WEAK,
1638 /*Size=*/0, STB_WEAK, In.Dynamic,1693 STV_HIDDEN, STT_NOTYPE,
1639 /*File=*/nullptr);1694 /*value=*/0, /*size=*/0, mainPart->dynamic});
16401695
1641 // Define __rel[a]_iplt_{start,end} symbols if needed.1696 // Define __rel[a]_iplt_{start,end} symbols if needed.
1642 addRelIpltSymbols();1697 addRelIpltSymbols();
16431698
1644 // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800 if not defined.1699 // RISC-V's gp can address +/- 2 KiB, set it to .sdata + 0x800 if not defined.
1645 if (Config->EMachine == EM_RISCV)1700 // This symbol should only be defined in an executable.
1646 if (!dyn_cast_or_null<Defined>(Symtab->find("__global_pointer$")))1701 if (config->emachine == EM_RISCV && !config->shared)
1647 addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800);1702 ElfSym::riscvGlobalPointer =
1703 addOptionalRegular("__global_pointer$", findSection(".sdata"), 0x800,
1704 STV_DEFAULT, STB_GLOBAL);
1705
1706 if (config->emachine == EM_X86_64) {
1707 // On targets that support TLSDESC, _TLS_MODULE_BASE_ is defined in such a
1708 // way that:
1709 //
1710 // 1) Without relaxation: it produces a dynamic TLSDESC relocation that
1711 // computes 0.
1712 // 2) With LD->LE relaxation: _TLS_MODULE_BASE_@tpoff = 0 (lowest address in
1713 // the TLS block).
1714 //
1715 // 2) is special cased in @tpoff computation. To satisfy 1), we define it as
1716 // an absolute symbol of zero. This is different from GNU linkers which
1717 // define _TLS_MODULE_BASE_ relative to the first TLS section.
1718 Symbol *s = symtab->find("_TLS_MODULE_BASE_");
1719 if (s && s->isUndefined()) {
1720 s->resolve(Defined{/*file=*/nullptr, s->getName(), STB_GLOBAL, STV_HIDDEN,
1721 STT_TLS, /*value=*/0, 0,
1722 /*section=*/nullptr});
1723 ElfSym::tlsModuleBase = cast<Defined>(s);
1724 }
1725 }
16481726
1649 // This responsible for splitting up .eh_frame section into1727 // This responsible for splitting up .eh_frame section into
1650 // pieces. The relocation scan uses those pieces, so this has to be1728 // pieces. The relocation scan uses those pieces, so this has to be
1651 // earlier.1729 // earlier.
1652 finalizeSynthetic(In.EhFrame);1730 for (Partition &part : partitions)
1731 finalizeSynthetic(part.ehFrame);
16531732
1654 for (Symbol *S : Symtab->getSymbols())1733 symtab->forEachSymbol([](Symbol *s) {
1655 if (!S->IsPreemptible)1734 if (!s->isPreemptible)
1656 S->IsPreemptible = computeIsPreemptible(*S);1735 s->isPreemptible = computeIsPreemptible(*s);
1736 });
16571737
1658 // Scan relocations. This must be done after every symbol is declared so that1738 // Scan relocations. This must be done after every symbol is declared so that
1659 // we can correctly decide if a dynamic relocation is needed.1739 // we can correctly decide if a dynamic relocation is needed.
1660 if (!Config->Relocatable)1740 if (!config->relocatable) {
1661 forEachRelSec(scanRelocations<ELFT>);1741 forEachRelSec(scanRelocations<ELFT>);
1742 reportUndefinedSymbols<ELFT>();
1743 }
16621744
1663 if (In.Plt && !In.Plt->empty())1745 addIRelativeRelocs();
1664 In.Plt->addSymbols();1746
1665 if (In.Iplt && !In.Iplt->empty())1747 if (in.plt && in.plt->isNeeded())
1666 In.Iplt->addSymbols();1748 in.plt->addSymbols();
1749 if (in.iplt && in.iplt->isNeeded())
1750 in.iplt->addSymbols();
1751
1752 if (!config->allowShlibUndefined) {
1753 // Error on undefined symbols in a shared object, if all of its DT_NEEDED
1754 // entires are seen. These cases would otherwise lead to runtime errors
1755 // reported by the dynamic linker.
1756 //
1757 // ld.bfd traces all DT_NEEDED to emulate the logic of the dynamic linker to
1758 // catch more cases. That is too much for us. Our approach resembles the one
1759 // used in ld.gold, achieves a good balance to be useful but not too smart.
1760 for (SharedFile *file : sharedFiles)
1761 file->allNeededIsKnown =
1762 llvm::all_of(file->dtNeeded, [&](StringRef needed) {
1763 return symtab->soNames.count(needed);
1764 });
1765
1766 symtab->forEachSymbol([](Symbol *sym) {
1767 if (sym->isUndefined() && !sym->isWeak())
1768 if (auto *f = dyn_cast_or_null<SharedFile>(sym->file))
1769 if (f->allNeededIsKnown)
1770 error(toString(f) + ": undefined reference to " + toString(*sym));
1771 });
1772 }
16671773
1668 // Now that we have defined all possible global symbols including linker-1774 // Now that we have defined all possible global symbols including linker-
1669 // synthesized ones. Visit all symbols to give the finishing touches.1775 // synthesized ones. Visit all symbols to give the finishing touches.
1670 for (Symbol *Sym : Symtab->getSymbols()) {1776 symtab->forEachSymbol([](Symbol *sym) {
1671 if (!includeInSymtab(*Sym))1777 if (!includeInSymtab(*sym))
1672 continue;1778 return;
1673 if (In.SymTab)1779 if (in.symTab)
1674 In.SymTab->addSymbol(Sym);1780 in.symTab->addSymbol(sym);
16751781
1676 if (Sym->includeInDynsym()) {1782 if (sym->includeInDynsym()) {
1677 In.DynSymTab->addSymbol(Sym);1783 partitions[sym->partition - 1].dynSymTab->addSymbol(sym);
1678 if (auto *File = dyn_cast_or_null<SharedFile<ELFT>>(Sym->File))1784 if (auto *file = dyn_cast_or_null<SharedFile>(sym->file))
1679 if (File->IsNeeded && !Sym->isUndefined())1785 if (file->isNeeded && !sym->isUndefined())
1680 InX<ELFT>::VerNeed->addSymbol(Sym);1786 addVerneed(sym);
1681 }1787 }
1788 });
1789
1790 // We also need to scan the dynamic relocation tables of the other partitions
1791 // and add any referenced symbols to the partition's dynsym.
1792 for (Partition &part : MutableArrayRef<Partition>(partitions).slice(1)) {
1793 DenseSet<Symbol *> syms;
1794 for (const SymbolTableEntry &e : part.dynSymTab->getSymbols())
1795 syms.insert(e.sym);
1796 for (DynamicReloc &reloc : part.relaDyn->relocs)
1797 if (reloc.sym && !reloc.useSymVA && syms.insert(reloc.sym).second)
1798 part.dynSymTab->addSymbol(reloc.sym);
1682 }1799 }
16831800
1684 // Do not proceed if there was an undefined symbol.1801 // Do not proceed if there was an undefined symbol.
1685 if (errorCount())1802 if (errorCount())
1686 return;1803 return;
16871804
1688 if (In.MipsGot)1805 if (in.mipsGot)
1689 In.MipsGot->build<ELFT>();1806 in.mipsGot->build();
16901807
1691 removeUnusedSyntheticSections();1808 removeUnusedSyntheticSections();
16921809
...@@ -1694,116 +1811,147 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {...@@ -1694,116 +1811,147 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
16941811
1695 // Now that we have the final list, create a list of all the1812 // Now that we have the final list, create a list of all the
1696 // OutputSections for convenience.1813 // OutputSections for convenience.
1697 for (BaseCommand *Base : Script->SectionCommands)1814 for (BaseCommand *base : script->sectionCommands)
1698 if (auto *Sec = dyn_cast<OutputSection>(Base))1815 if (auto *sec = dyn_cast<OutputSection>(base))
1699 OutputSections.push_back(Sec);1816 outputSections.push_back(sec);
17001817
1701 // Prefer command line supplied address over other constraints.1818 // Prefer command line supplied address over other constraints.
1702 for (OutputSection *Sec : OutputSections) {1819 for (OutputSection *sec : outputSections) {
1703 auto I = Config->SectionStartMap.find(Sec->Name);1820 auto i = config->sectionStartMap.find(sec->name);
1704 if (I != Config->SectionStartMap.end())1821 if (i != config->sectionStartMap.end())
1705 Sec->AddrExpr = [=] { return I->second; };1822 sec->addrExpr = [=] { return i->second; };
1706 }1823 }
17071824
1708 // This is a bit of a hack. A value of 0 means undef, so we set it1825 // This is a bit of a hack. A value of 0 means undef, so we set it
1709 // to 1 to make __ehdr_start defined. The section number is not1826 // to 1 to make __ehdr_start defined. The section number is not
1710 // particularly relevant.1827 // particularly relevant.
1711 Out::ElfHeader->SectionIndex = 1;1828 Out::elfHeader->sectionIndex = 1;
17121829
1713 for (size_t I = 0, E = OutputSections.size(); I != E; ++I) {1830 for (size_t i = 0, e = outputSections.size(); i != e; ++i) {
1714 OutputSection *Sec = OutputSections[I];1831 OutputSection *sec = outputSections[i];
1715 Sec->SectionIndex = I + 1;1832 sec->sectionIndex = i + 1;
1716 Sec->ShName = In.ShStrTab->addString(Sec->Name);1833 sec->shName = in.shStrTab->addString(sec->name);
1717 }1834 }
17181835
1719 // Binary and relocatable output does not have PHDRS.1836 // Binary and relocatable output does not have PHDRS.
1720 // The headers have to be created before finalize as that can influence the1837 // The headers have to be created before finalize as that can influence the
1721 // image base and the dynamic section on mips includes the image base.1838 // image base and the dynamic section on mips includes the image base.
1722 if (!Config->Relocatable && !Config->OFormatBinary) {1839 if (!config->relocatable && !config->oFormatBinary) {
1723 Phdrs = Script->hasPhdrsCommands() ? Script->createPhdrs() : createPhdrs();1840 for (Partition &part : partitions) {
1724 addPtArmExid(Phdrs);1841 part.phdrs = script->hasPhdrsCommands() ? script->createPhdrs()
1725 Out::ProgramHeaders->Size = sizeof(Elf_Phdr) * Phdrs.size();1842 : createPhdrs(part);
1843 if (config->emachine == EM_ARM) {
1844 // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME
1845 addPhdrForSection(part, SHT_ARM_EXIDX, PT_ARM_EXIDX, PF_R);
1846 }
1847 if (config->emachine == EM_MIPS) {
1848 // Add separate segments for MIPS-specific sections.
1849 addPhdrForSection(part, SHT_MIPS_REGINFO, PT_MIPS_REGINFO, PF_R);
1850 addPhdrForSection(part, SHT_MIPS_OPTIONS, PT_MIPS_OPTIONS, PF_R);
1851 addPhdrForSection(part, SHT_MIPS_ABIFLAGS, PT_MIPS_ABIFLAGS, PF_R);
1852 }
1853 }
1854 Out::programHeaders->size = sizeof(Elf_Phdr) * mainPart->phdrs.size();
17261855
1727 // Find the TLS segment. This happens before the section layout loop so that1856 // Find the TLS segment. This happens before the section layout loop so that
1728 // Android relocation packing can look up TLS symbol addresses.1857 // Android relocation packing can look up TLS symbol addresses. We only need
1729 for (PhdrEntry *P : Phdrs)1858 // to care about the main partition here because all TLS symbols were moved
1730 if (P->p_type == PT_TLS)1859 // to the main partition (see MarkLive.cpp).
1731 Out::TlsPhdr = P;1860 for (PhdrEntry *p : mainPart->phdrs)
1861 if (p->p_type == PT_TLS)
1862 Out::tlsPhdr = p;
1732 }1863 }
17331864
1734 // Some symbols are defined in term of program headers. Now that we1865 // Some symbols are defined in term of program headers. Now that we
1735 // have the headers, we can find out which sections they point to.1866 // have the headers, we can find out which sections they point to.
1736 setReservedSymbolSections();1867 setReservedSymbolSections();
17371868
1869 finalizeSynthetic(in.bss);
1870 finalizeSynthetic(in.bssRelRo);
1871 finalizeSynthetic(in.symTabShndx);
1872 finalizeSynthetic(in.shStrTab);
1873 finalizeSynthetic(in.strTab);
1874 finalizeSynthetic(in.got);
1875 finalizeSynthetic(in.mipsGot);
1876 finalizeSynthetic(in.igotPlt);
1877 finalizeSynthetic(in.gotPlt);
1878 finalizeSynthetic(in.relaIplt);
1879 finalizeSynthetic(in.relaPlt);
1880 finalizeSynthetic(in.plt);
1881 finalizeSynthetic(in.iplt);
1882 finalizeSynthetic(in.ppc32Got2);
1883 finalizeSynthetic(in.riscvSdata);
1884 finalizeSynthetic(in.partIndex);
1885
1738 // Dynamic section must be the last one in this list and dynamic1886 // Dynamic section must be the last one in this list and dynamic
1739 // symbol table section (DynSymTab) must be the first one.1887 // symbol table section (dynSymTab) must be the first one.
1740 finalizeSynthetic(In.DynSymTab);1888 for (Partition &part : partitions) {
1741 finalizeSynthetic(In.Bss);1889 finalizeSynthetic(part.armExidx);
1742 finalizeSynthetic(In.BssRelRo);1890 finalizeSynthetic(part.dynSymTab);
1743 finalizeSynthetic(In.GnuHashTab);1891 finalizeSynthetic(part.gnuHashTab);
1744 finalizeSynthetic(In.HashTab);1892 finalizeSynthetic(part.hashTab);
1745 finalizeSynthetic(In.SymTabShndx);1893 finalizeSynthetic(part.verDef);
1746 finalizeSynthetic(In.ShStrTab);1894 finalizeSynthetic(part.relaDyn);
1747 finalizeSynthetic(In.StrTab);1895 finalizeSynthetic(part.relrDyn);
1748 finalizeSynthetic(In.VerDef);1896 finalizeSynthetic(part.ehFrameHdr);
1749 finalizeSynthetic(In.DynStrTab);1897 finalizeSynthetic(part.verSym);
1750 finalizeSynthetic(In.Got);1898 finalizeSynthetic(part.verNeed);
1751 finalizeSynthetic(In.MipsGot);1899 finalizeSynthetic(part.dynamic);
1752 finalizeSynthetic(In.IgotPlt);1900 }
1753 finalizeSynthetic(In.GotPlt);1901
1754 finalizeSynthetic(In.RelaDyn);1902 if (!script->hasSectionsCommand && !config->relocatable)
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);
1764
1765 if (!Script->HasSectionsCommand && !Config->Relocatable)
1766 fixSectionAlignments();1903 fixSectionAlignments();
17671904
1768 // After link order processing .ARM.exidx sections can be deduplicated, which1905 // SHFLinkOrder processing must be processed after relative section placements are
1769 // needs to be resolved before any other address dependent operation.1906 // known but before addresses are allocated.
1770 resolveShfLinkOrder();1907 resolveShfLinkOrder();
17711908
1772 // Jump instructions in many ISAs have small displacements, and therefore they1909 // This is used to:
1773 // cannot jump to arbitrary addresses in memory. For example, RISC-V JAL1910 // 1) Create "thunks":
1774 // instruction can target only +-1 MiB from PC. It is a linker's1911 // Jump instructions in many ISAs have small displacements, and therefore
1775 // responsibility to create and insert small pieces of code between sections1912 // they cannot jump to arbitrary addresses in memory. For example, RISC-V
1776 // to extend the ranges if jump targets are out of range. Such code pieces are1913 // JAL instruction can target only +-1 MiB from PC. It is a linker's
1777 // called "thunks".1914 // responsibility to create and insert small pieces of code between
1915 // sections to extend the ranges if jump targets are out of range. Such
1916 // code pieces are called "thunks".
1778 //1917 //
1779 // We add thunks at this stage. We couldn't do this before this point because1918 // We add thunks at this stage. We couldn't do this before this point
1780 // this is the earliest point where we know sizes of sections and their1919 // because this is the earliest point where we know sizes of sections and
1781 // layouts (that are needed to determine if jump targets are in range).1920 // their layouts (that are needed to determine if jump targets are in
1782 maybeAddThunks();1921 // range).
1922 //
1923 // 2) Update the sections. We need to generate content that depends on the
1924 // address of InputSections. For example, MIPS GOT section content or
1925 // android packed relocations sections content.
1926 //
1927 // 3) Assign the final values for the linker script symbols. Linker scripts
1928 // sometimes using forward symbol declarations. We want to set the correct
1929 // values. They also might change after adding the thunks.
1930 finalizeAddressDependentContent();
17831931
1784 // maybeAddThunks may have added local symbols to the static symbol table.1932 // finalizeAddressDependentContent may have added local symbols to the static symbol table.
1785 finalizeSynthetic(In.SymTab);1933 finalizeSynthetic(in.symTab);
1786 finalizeSynthetic(In.PPC64LongBranchTarget);1934 finalizeSynthetic(in.ppc64LongBranchTarget);
17871935
1788 // Fill other section headers. The dynamic table is finalized1936 // Fill other section headers. The dynamic table is finalized
1789 // at the end because some tags like RELSZ depend on result1937 // at the end because some tags like RELSZ depend on result
1790 // of finalizing other sections.1938 // of finalizing other sections.
1791 for (OutputSection *Sec : OutputSections)1939 for (OutputSection *sec : outputSections)
1792 Sec->finalize<ELFT>();1940 sec->finalize();
1793}1941}
17941942
1795// Ensure data sections are not mixed with executable sections when1943// Ensure data sections are not mixed with executable sections when
1796// -execute-only is used. -execute-only is a feature to make pages executable1944// -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.1945// but not readable, and the feature is currently supported only on AArch64.
1798template <class ELFT> void Writer<ELFT>::checkExecuteOnly() {1946template <class ELFT> void Writer<ELFT>::checkExecuteOnly() {
1799 if (!Config->ExecuteOnly)1947 if (!config->executeOnly)
1800 return;1948 return;
18011949
1802 for (OutputSection *OS : OutputSections)1950 for (OutputSection *os : outputSections)
1803 if (OS->Flags & SHF_EXECINSTR)1951 if (os->flags & SHF_EXECINSTR)
1804 for (InputSection *IS : getInputSections(OS))1952 for (InputSection *isec : getInputSections(os))
1805 if (!(IS->Flags & SHF_EXECINSTR))1953 if (!(isec->flags & SHF_EXECINSTR))
1806 error("cannot place " + toString(IS) + " into " + toString(OS->Name) +1954 error("cannot place " + toString(isec) + " into " + toString(os->name) +
1807 ": -execute-only does not support intermingling data and code");1955 ": -execute-only does not support intermingling data and code");
1808}1956}
18091957
...@@ -1828,24 +1976,24 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {...@@ -1828,24 +1976,24 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
1828 // case, use the image base address as a last resort.1976 // case, use the image base address as a last resort.
1829 OutputSection *Default = findSection(".text");1977 OutputSection *Default = findSection(".text");
1830 if (!Default)1978 if (!Default)
1831 Default = Out::ElfHeader;1979 Default = Out::elfHeader;
18321980
1833 auto Define = [=](StringRef Start, StringRef End, OutputSection *OS) {1981 auto define = [=](StringRef start, StringRef end, OutputSection *os) {
1834 if (OS) {1982 if (os) {
1835 addOptionalRegular(Start, OS, 0);1983 addOptionalRegular(start, os, 0);
1836 addOptionalRegular(End, OS, -1);1984 addOptionalRegular(end, os, -1);
1837 } else {1985 } else {
1838 addOptionalRegular(Start, Default, 0);1986 addOptionalRegular(start, Default, 0);
1839 addOptionalRegular(End, Default, 0);1987 addOptionalRegular(end, Default, 0);
1840 }1988 }
1841 };1989 };
18421990
1843 Define("__preinit_array_start", "__preinit_array_end", Out::PreinitArray);1991 define("__preinit_array_start", "__preinit_array_end", Out::preinitArray);
1844 Define("__init_array_start", "__init_array_end", Out::InitArray);1992 define("__init_array_start", "__init_array_end", Out::initArray);
1845 Define("__fini_array_start", "__fini_array_end", Out::FiniArray);1993 define("__fini_array_start", "__fini_array_end", Out::finiArray);
18461994
1847 if (OutputSection *Sec = findSection(".ARM.exidx"))1995 if (OutputSection *sec = findSection(".ARM.exidx"))
1848 Define("__exidx_start", "__exidx_end", Sec);1996 define("__exidx_start", "__exidx_end", sec);
1849}1997}
18501998
1851// If a section name is valid as a C identifier (which is rare because of1999// If a section name is valid as a C identifier (which is rare because of
...@@ -1854,22 +2002,22 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {...@@ -1854,22 +2002,22 @@ template <class ELFT> void Writer<ELFT>::addStartEndSymbols() {
1854// respectively. This is not requested by the ELF standard, but GNU ld and2002// respectively. This is not requested by the ELF standard, but GNU ld and
1855// gold provide the feature, and used by many programs.2003// gold provide the feature, and used by many programs.
1856template <class ELFT>2004template <class ELFT>
1857void Writer<ELFT>::addStartStopSymbols(OutputSection *Sec) {2005void Writer<ELFT>::addStartStopSymbols(OutputSection *sec) {
1858 StringRef S = Sec->Name;2006 StringRef s = sec->name;
1859 if (!isValidCIdentifier(S))2007 if (!isValidCIdentifier(s))
1860 return;2008 return;
1861 addOptionalRegular(Saver.save("__start_" + S), Sec, 0, STV_PROTECTED);2009 addOptionalRegular(saver.save("__start_" + s), sec, 0, STV_PROTECTED);
1862 addOptionalRegular(Saver.save("__stop_" + S), Sec, -1, STV_PROTECTED);2010 addOptionalRegular(saver.save("__stop_" + s), sec, -1, STV_PROTECTED);
1863}2011}
18642012
1865static bool needsPtLoad(OutputSection *Sec) {2013static bool needsPtLoad(OutputSection *sec) {
1866 if (!(Sec->Flags & SHF_ALLOC) || Sec->Noload)2014 if (!(sec->flags & SHF_ALLOC) || sec->noload)
1867 return false;2015 return false;
18682016
1869 // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is2017 // Don't allocate VA space for TLS NOBITS sections. The PT_TLS PHDR is
1870 // responsible for allocating space for them, not the PT_LOAD that2018 // responsible for allocating space for them, not the PT_LOAD that
1871 // contains the TLS initialization image.2019 // contains the TLS initialization image.
1872 if ((Sec->Flags & SHF_TLS) && Sec->Type == SHT_NOBITS)2020 if ((sec->flags & SHF_TLS) && sec->type == SHT_NOBITS)
1873 return false;2021 return false;
1874 return true;2022 return true;
1875}2023}
...@@ -1878,46 +2026,93 @@ static bool needsPtLoad(OutputSection *Sec) {...@@ -1878,46 +2026,93 @@ static bool needsPtLoad(OutputSection *Sec) {
1878// linker scripts are designed for creating two PT_LOADs only, one RX and one2026// linker scripts are designed for creating two PT_LOADs only, one RX and one
1879// RW. This means that there is no alignment in the RO to RX transition and we2027// RW. This means that there is no alignment in the RO to RX transition and we
1880// cannot create a PT_LOAD there.2028// cannot create a PT_LOAD there.
1881static uint64_t computeFlags(uint64_t Flags) {2029static uint64_t computeFlags(uint64_t flags) {
1882 if (Config->Omagic)2030 if (config->omagic)
1883 return PF_R | PF_W | PF_X;2031 return PF_R | PF_W | PF_X;
1884 if (Config->ExecuteOnly && (Flags & PF_X))2032 if (config->executeOnly && (flags & PF_X))
1885 return Flags & ~PF_R;2033 return flags & ~PF_R;
1886 if (Config->SingleRoRx && !(Flags & PF_W))2034 if (config->singleRoRx && !(flags & PF_W))
1887 return Flags | PF_X;2035 return flags | PF_X;
1888 return Flags;2036 return flags;
1889}2037}
18902038
1891// Decide which program headers to create and which sections to include in each2039// Decide which program headers to create and which sections to include in each
1892// one.2040// one.
1893template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {2041template <class ELFT>
1894 std::vector<PhdrEntry *> Ret;2042std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs(Partition &part) {
1895 auto AddHdr = [&](unsigned Type, unsigned Flags) -> PhdrEntry * {2043 std::vector<PhdrEntry *> ret;
1896 Ret.push_back(make<PhdrEntry>(Type, Flags));2044 auto addHdr = [&](unsigned type, unsigned flags) -> PhdrEntry * {
1897 return Ret.back();2045 ret.push_back(make<PhdrEntry>(type, flags));
2046 return ret.back();
1898 };2047 };
18992048
2049 unsigned partNo = part.getNumber();
2050 bool isMain = partNo == 1;
2051
1900 // The first phdr entry is PT_PHDR which describes the program header itself.2052 // The first phdr entry is PT_PHDR which describes the program header itself.
1901 AddHdr(PT_PHDR, PF_R)->add(Out::ProgramHeaders);2053 if (isMain)
2054 addHdr(PT_PHDR, PF_R)->add(Out::programHeaders);
2055 else
2056 addHdr(PT_PHDR, PF_R)->add(part.programHeaders->getParent());
19022057
1903 // PT_INTERP must be the second entry if exists.2058 // PT_INTERP must be the second entry if exists.
1904 if (OutputSection *Cmd = findSection(".interp"))2059 if (OutputSection *cmd = findSection(".interp", partNo))
1905 AddHdr(PT_INTERP, Cmd->getPhdrFlags())->add(Cmd);2060 addHdr(PT_INTERP, cmd->getPhdrFlags())->add(cmd);
19062061
1907 // Add the first PT_LOAD segment for regular output sections.2062 // Add the first PT_LOAD segment for regular output sections.
1908 uint64_t Flags = computeFlags(PF_R);2063 uint64_t flags = computeFlags(PF_R);
1909 PhdrEntry *Load = AddHdr(PT_LOAD, Flags);2064 PhdrEntry *load = nullptr;
19102065
1911 // Add the headers. We will remove them if they don't fit.2066 // Add the headers. We will remove them if they don't fit.
1912 Load->add(Out::ElfHeader);2067 // In the other partitions the headers are ordinary sections, so they don't
1913 Load->add(Out::ProgramHeaders);2068 // need to be added here.
2069 if (isMain) {
2070 load = addHdr(PT_LOAD, flags);
2071 load->add(Out::elfHeader);
2072 load->add(Out::programHeaders);
2073 }
2074
2075 // PT_GNU_RELRO includes all sections that should be marked as
2076 // read-only by dynamic linker after proccessing relocations.
2077 // Current dynamic loaders only support one PT_GNU_RELRO PHDR, give
2078 // an error message if more than one PT_GNU_RELRO PHDR is required.
2079 PhdrEntry *relRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R);
2080 bool inRelroPhdr = false;
2081 OutputSection *relroEnd = nullptr;
2082 for (OutputSection *sec : outputSections) {
2083 if (sec->partition != partNo || !needsPtLoad(sec))
2084 continue;
2085 if (isRelroSection(sec)) {
2086 inRelroPhdr = true;
2087 if (!relroEnd)
2088 relRo->add(sec);
2089 else
2090 error("section: " + sec->name + " is not contiguous with other relro" +
2091 " sections");
2092 } else if (inRelroPhdr) {
2093 inRelroPhdr = false;
2094 relroEnd = sec;
2095 }
2096 }
19142097
1915 for (OutputSection *Sec : OutputSections) {2098 for (OutputSection *sec : outputSections) {
1916 if (!(Sec->Flags & SHF_ALLOC))2099 if (!(sec->flags & SHF_ALLOC))
1917 break;2100 break;
1918 if (!needsPtLoad(Sec))2101 if (!needsPtLoad(sec))
1919 continue;2102 continue;
19202103
2104 // Normally, sections in partitions other than the current partition are
2105 // ignored. But partition number 255 is a special case: it contains the
2106 // partition end marker (.part.end). It needs to be added to the main
2107 // partition so that a segment is created for it in the main partition,
2108 // which will cause the dynamic loader to reserve space for the other
2109 // partitions.
2110 if (sec->partition != partNo) {
2111 if (isMain && sec->partition == 255)
2112 addHdr(PT_LOAD, computeFlags(sec->getPhdrFlags()))->add(sec);
2113 continue;
2114 }
2115
1921 // Segments are contiguous memory regions that has the same attributes2116 // Segments are contiguous memory regions that has the same attributes
1922 // (e.g. executable or writable). There is one phdr for each segment.2117 // (e.g. executable or writable). There is one phdr for each segment.
1923 // Therefore, we need to create a new phdr when the next section has2118 // Therefore, we need to create a new phdr when the next section has
...@@ -1925,222 +2120,187 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {...@@ -1925,222 +2120,187 @@ template <class ELFT> std::vector<PhdrEntry *> Writer<ELFT>::createPhdrs() {
1925 // region using AT or AT> linker script command, respectively. At the same2120 // region using AT or AT> linker script command, respectively. At the same
1926 // time, we don't want to create a separate load segment for the headers,2121 // time, we don't want to create a separate load segment for the headers,
1927 // even if the first output section has an AT or AT> attribute.2122 // even if the first output section has an AT or AT> attribute.
1928 uint64_t NewFlags = computeFlags(Sec->getPhdrFlags());2123 uint64_t newFlags = computeFlags(sec->getPhdrFlags());
1929 if (((Sec->LMAExpr ||2124 if (!load ||
1930 (Sec->LMARegion && (Sec->LMARegion != Load->FirstSec->LMARegion))) &&2125 ((sec->lmaExpr ||
1931 Load->LastSec != Out::ProgramHeaders) ||2126 (sec->lmaRegion && (sec->lmaRegion != load->firstSec->lmaRegion))) &&
1932 Sec->MemRegion != Load->FirstSec->MemRegion || Flags != NewFlags) {2127 load->lastSec != Out::programHeaders) ||
19332128 sec->memRegion != load->firstSec->memRegion || flags != newFlags ||
1934 Load = AddHdr(PT_LOAD, NewFlags);2129 sec == relroEnd) {
1935 Flags = NewFlags;2130 load = addHdr(PT_LOAD, newFlags);
2131 flags = newFlags;
1936 }2132 }
19372133
1938 Load->add(Sec);2134 load->add(sec);
1939 }2135 }
19402136
1941 // Add a TLS segment if any.2137 // Add a TLS segment if any.
1942 PhdrEntry *TlsHdr = make<PhdrEntry>(PT_TLS, PF_R);2138 PhdrEntry *tlsHdr = make<PhdrEntry>(PT_TLS, PF_R);
1943 for (OutputSection *Sec : OutputSections)2139 for (OutputSection *sec : outputSections)
1944 if (Sec->Flags & SHF_TLS)2140 if (sec->partition == partNo && sec->flags & SHF_TLS)
1945 TlsHdr->add(Sec);2141 tlsHdr->add(sec);
1946 if (TlsHdr->FirstSec)2142 if (tlsHdr->firstSec)
1947 Ret.push_back(TlsHdr);2143 ret.push_back(tlsHdr);
19482144
1949 // Add an entry for .dynamic.2145 // Add an entry for .dynamic.
1950 if (OutputSection *Sec = In.Dynamic->getParent())2146 if (OutputSection *sec = part.dynamic->getParent())
1951 AddHdr(PT_DYNAMIC, Sec->getPhdrFlags())->add(Sec);2147 addHdr(PT_DYNAMIC, sec->getPhdrFlags())->add(sec);
19522148
1953 // PT_GNU_RELRO includes all sections that should be marked as2149 if (relRo->firstSec)
1954 // read-only by dynamic linker after proccessing relocations.2150 ret.push_back(relRo);
1955 // Current dynamic loaders only support one PT_GNU_RELRO PHDR, give
1956 // an error message if more than one PT_GNU_RELRO PHDR is required.
1957 PhdrEntry *RelRo = make<PhdrEntry>(PT_GNU_RELRO, PF_R);
1958 bool InRelroPhdr = false;
1959 bool IsRelroFinished = false;
1960 for (OutputSection *Sec : OutputSections) {
1961 if (!needsPtLoad(Sec))
1962 continue;
1963 if (isRelroSection(Sec)) {
1964 InRelroPhdr = true;
1965 if (!IsRelroFinished)
1966 RelRo->add(Sec);
1967 else
1968 error("section: " + Sec->Name + " is not contiguous with other relro" +
1969 " sections");
1970 } else if (InRelroPhdr) {
1971 InRelroPhdr = false;
1972 IsRelroFinished = true;
1973 }
1974 }
1975 if (RelRo->FirstSec)
1976 Ret.push_back(RelRo);
19772151
1978 // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.2152 // PT_GNU_EH_FRAME is a special section pointing on .eh_frame_hdr.
1979 if (!In.EhFrame->empty() && In.EhFrameHdr && In.EhFrame->getParent() &&2153 if (part.ehFrame->isNeeded() && part.ehFrameHdr &&
1980 In.EhFrameHdr->getParent())2154 part.ehFrame->getParent() && part.ehFrameHdr->getParent())
1981 AddHdr(PT_GNU_EH_FRAME, In.EhFrameHdr->getParent()->getPhdrFlags())2155 addHdr(PT_GNU_EH_FRAME, part.ehFrameHdr->getParent()->getPhdrFlags())
1982 ->add(In.EhFrameHdr->getParent());2156 ->add(part.ehFrameHdr->getParent());
19832157
1984 // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes2158 // PT_OPENBSD_RANDOMIZE is an OpenBSD-specific feature. That makes
1985 // the dynamic linker fill the segment with random data.2159 // the dynamic linker fill the segment with random data.
1986 if (OutputSection *Cmd = findSection(".openbsd.randomdata"))2160 if (OutputSection *cmd = findSection(".openbsd.randomdata", partNo))
1987 AddHdr(PT_OPENBSD_RANDOMIZE, Cmd->getPhdrFlags())->add(Cmd);2161 addHdr(PT_OPENBSD_RANDOMIZE, cmd->getPhdrFlags())->add(cmd);
19882162
1989 // PT_GNU_STACK is a special section to tell the loader to make the2163 // PT_GNU_STACK is a special section to tell the loader to make the
1990 // pages for the stack non-executable. If you really want an executable2164 // pages for the stack non-executable. If you really want an executable
1991 // stack, you can pass -z execstack, but that's not recommended for2165 // stack, you can pass -z execstack, but that's not recommended for
1992 // security reasons.2166 // security reasons.
1993 unsigned Perm = PF_R | PF_W;2167 unsigned perm = PF_R | PF_W;
1994 if (Config->ZExecstack)2168 if (config->zExecstack)
1995 Perm |= PF_X;2169 perm |= PF_X;
1996 AddHdr(PT_GNU_STACK, Perm)->p_memsz = Config->ZStackSize;2170 addHdr(PT_GNU_STACK, perm)->p_memsz = config->zStackSize;
19972171
1998 // PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable2172 // PT_OPENBSD_WXNEEDED is a OpenBSD-specific header to mark the executable
1999 // is expected to perform W^X violations, such as calling mprotect(2) or2173 // is expected to perform W^X violations, such as calling mprotect(2) or
2000 // mmap(2) with PROT_WRITE | PROT_EXEC, which is prohibited by default on2174 // mmap(2) with PROT_WRITE | PROT_EXEC, which is prohibited by default on
2001 // OpenBSD.2175 // OpenBSD.
2002 if (Config->ZWxneeded)2176 if (config->zWxneeded)
2003 AddHdr(PT_OPENBSD_WXNEEDED, PF_X);2177 addHdr(PT_OPENBSD_WXNEEDED, PF_X);
20042178
2005 // Create one PT_NOTE per a group of contiguous .note sections.2179 // Create one PT_NOTE per a group of contiguous SHT_NOTE sections with the
2006 PhdrEntry *Note = nullptr;2180 // same alignment.
2007 for (OutputSection *Sec : OutputSections) {2181 PhdrEntry *note = nullptr;
2008 if (Sec->Type == SHT_NOTE && (Sec->Flags & SHF_ALLOC)) {2182 for (OutputSection *sec : outputSections) {
2009 if (!Note || Sec->LMAExpr)2183 if (sec->partition != partNo)
2010 Note = AddHdr(PT_NOTE, PF_R);2184 continue;
2011 Note->add(Sec);2185 if (sec->type == SHT_NOTE && (sec->flags & SHF_ALLOC)) {
2186 if (!note || sec->lmaExpr || note->lastSec->alignment != sec->alignment)
2187 note = addHdr(PT_NOTE, PF_R);
2188 note->add(sec);
2012 } else {2189 } else {
2013 Note = nullptr;2190 note = nullptr;
2014 }2191 }
2015 }2192 }
2016 return Ret;2193 return ret;
2017}2194}
20182195
2019template <class ELFT>2196template <class ELFT>
2020void Writer<ELFT>::addPtArmExid(std::vector<PhdrEntry *> &Phdrs) {2197void Writer<ELFT>::addPhdrForSection(Partition &part, unsigned shType,
2021 if (Config->EMachine != EM_ARM)2198 unsigned pType, unsigned pFlags) {
2022 return;2199 unsigned partNo = part.getNumber();
2023 auto I = llvm::find_if(OutputSections, [](OutputSection *Cmd) {2200 auto i = llvm::find_if(outputSections, [=](OutputSection *cmd) {
2024 return Cmd->Type == SHT_ARM_EXIDX;2201 return cmd->partition == partNo && cmd->type == shType;
2025 });2202 });
2026 if (I == OutputSections.end())2203 if (i == outputSections.end())
2027 return;2204 return;
20282205
2029 // PT_ARM_EXIDX is the ARM EHABI equivalent of PT_GNU_EH_FRAME2206 PhdrEntry *entry = make<PhdrEntry>(pType, pFlags);
2030 PhdrEntry *ARMExidx = make<PhdrEntry>(PT_ARM_EXIDX, PF_R);2207 entry->add(*i);
2031 ARMExidx->add(*I);2208 part.phdrs.push_back(entry);
2032 Phdrs.push_back(ARMExidx);
2033}2209}
20342210
2035// The first section of each PT_LOAD, the first section in PT_GNU_RELRO and the2211// The first section of each PT_LOAD, the first section in PT_GNU_RELRO and the
2036// first section after PT_GNU_RELRO have to be page aligned so that the dynamic2212// first section after PT_GNU_RELRO have to be page aligned so that the dynamic
2037// linker can set the permissions.2213// linker can set the permissions.
2038template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {2214template <class ELFT> void Writer<ELFT>::fixSectionAlignments() {
2039 auto PageAlign = [](OutputSection *Cmd) {2215 auto pageAlign = [](OutputSection *cmd) {
2040 if (Cmd && !Cmd->AddrExpr)2216 if (cmd && !cmd->addrExpr)
2041 Cmd->AddrExpr = [=] {2217 cmd->addrExpr = [=] {
2042 return alignTo(Script->getDot(), Config->MaxPageSize);2218 return alignTo(script->getDot(), config->maxPageSize);
2043 };2219 };
2044 };2220 };
20452221
2046 for (const PhdrEntry *P : Phdrs)2222 for (Partition &part : partitions) {
2047 if (P->p_type == PT_LOAD && P->FirstSec)2223 for (const PhdrEntry *p : part.phdrs)
2048 PageAlign(P->FirstSec);2224 if (p->p_type == PT_LOAD && p->firstSec)
20492225 pageAlign(p->firstSec);
2050 for (const PhdrEntry *P : Phdrs) {
2051 if (P->p_type != PT_GNU_RELRO)
2052 continue;
2053
2054 if (P->FirstSec)
2055 PageAlign(P->FirstSec);
2056
2057 // Find the first section after PT_GNU_RELRO. If it is in a PT_LOAD we
2058 // have to align it to a page.
2059 auto End = OutputSections.end();
2060 auto I = std::find(OutputSections.begin(), End, P->LastSec);
2061 if (I == End || (I + 1) == End)
2062 continue;
2063
2064 OutputSection *Cmd = (*(I + 1));
2065 if (needsPtLoad(Cmd))
2066 PageAlign(Cmd);
2067 }2226 }
2068}2227}
20692228
2070// Compute an in-file position for a given section. The file offset must be the2229// 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 can2230// same with its virtual address modulo the page size, so that the loader can
2072// load executables without any address adjustment.2231// load executables without any address adjustment.
2073static uint64_t computeFileOffset(OutputSection *OS, uint64_t Off) {2232static uint64_t computeFileOffset(OutputSection *os, uint64_t off) {
2074 // File offsets are not significant for .bss sections. By convention, we keep2233 // File offsets are not significant for .bss sections. By convention, we keep
2075 // section offsets monotonically increasing rather than setting to zero.2234 // section offsets monotonically increasing rather than setting to zero.
2076 if (OS->Type == SHT_NOBITS)2235 if (os->type == SHT_NOBITS)
2077 return Off;2236 return off;
20782237
2079 // If the section is not in a PT_LOAD, we just have to align it.2238 // If the section is not in a PT_LOAD, we just have to align it.
2080 if (!OS->PtLoad)2239 if (!os->ptLoad)
2081 return alignTo(Off, OS->Alignment);2240 return alignTo(off, os->alignment);
20822241
2083 // The first section in a PT_LOAD has to have congruent offset and address2242 // The first section in a PT_LOAD has to have congruent offset and address
2084 // module the page size.2243 // module the page size.
2085 OutputSection *First = OS->PtLoad->FirstSec;2244 OutputSection *first = os->ptLoad->firstSec;
2086 if (OS == First) {2245 if (os == first) {
2087 uint64_t Alignment = std::max<uint64_t>(OS->Alignment, Config->MaxPageSize);2246 uint64_t alignment = std::max<uint64_t>(os->alignment, config->maxPageSize);
2088 return alignTo(Off, Alignment, OS->Addr);2247 return alignTo(off, alignment, os->addr);
2089 }2248 }
20902249
2091 // If two sections share the same PT_LOAD the file offset is calculated2250 // If two sections share the same PT_LOAD the file offset is calculated
2092 // using this formula: Off2 = Off1 + (VA2 - VA1).2251 // using this formula: Off2 = Off1 + (VA2 - VA1).
2093 return First->Offset + OS->Addr - First->Addr;2252 return first->offset + os->addr - first->addr;
2094}2253}
20952254
2096// Set an in-file position to a given section and returns the end position of2255// Set an in-file position to a given section and returns the end position of
2097// the section.2256// the section.
2098static uint64_t setFileOffset(OutputSection *OS, uint64_t Off) {2257static uint64_t setFileOffset(OutputSection *os, uint64_t off) {
2099 Off = computeFileOffset(OS, Off);2258 off = computeFileOffset(os, off);
2100 OS->Offset = Off;2259 os->offset = off;
21012260
2102 if (OS->Type == SHT_NOBITS)2261 if (os->type == SHT_NOBITS)
2103 return Off;2262 return off;
2104 return Off + OS->Size;2263 return off + os->size;
2105}2264}
21062265
2107template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {2266template <class ELFT> void Writer<ELFT>::assignFileOffsetsBinary() {
2108 uint64_t Off = 0;2267 uint64_t off = 0;
2109 for (OutputSection *Sec : OutputSections)2268 for (OutputSection *sec : outputSections)
2110 if (Sec->Flags & SHF_ALLOC)2269 if (sec->flags & SHF_ALLOC)
2111 Off = setFileOffset(Sec, Off);2270 off = setFileOffset(sec, off);
2112 FileSize = alignTo(Off, Config->Wordsize);2271 fileSize = alignTo(off, config->wordsize);
2113}2272}
21142273
2115static std::string rangeToString(uint64_t Addr, uint64_t Len) {2274static std::string rangeToString(uint64_t addr, uint64_t len) {
2116 return "[0x" + utohexstr(Addr) + ", 0x" + utohexstr(Addr + Len - 1) + "]";2275 return "[0x" + utohexstr(addr) + ", 0x" + utohexstr(addr + len - 1) + "]";
2117}2276}
21182277
2119// Assign file offsets to output sections.2278// Assign file offsets to output sections.
2120template <class ELFT> void Writer<ELFT>::assignFileOffsets() {2279template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
2121 uint64_t Off = 0;2280 uint64_t off = 0;
2122 Off = setFileOffset(Out::ElfHeader, Off);2281 off = setFileOffset(Out::elfHeader, off);
2123 Off = setFileOffset(Out::ProgramHeaders, Off);2282 off = setFileOffset(Out::programHeaders, off);
21242283
2125 PhdrEntry *LastRX = nullptr;2284 PhdrEntry *lastRX = nullptr;
2126 for (PhdrEntry *P : Phdrs)2285 for (Partition &part : partitions)
2127 if (P->p_type == PT_LOAD && (P->p_flags & PF_X))2286 for (PhdrEntry *p : part.phdrs)
2128 LastRX = P;2287 if (p->p_type == PT_LOAD && (p->p_flags & PF_X))
21292288 lastRX = p;
2130 for (OutputSection *Sec : OutputSections) {2289
2131 Off = setFileOffset(Sec, Off);2290 for (OutputSection *sec : outputSections) {
2132 if (Script->HasSectionsCommand)2291 off = setFileOffset(sec, off);
2292 if (script->hasSectionsCommand)
2133 continue;2293 continue;
21342294
2135 // If this is a last section of the last executable segment and that2295 // If this is a last section of the last executable segment and that
2136 // segment is the last loadable segment, align the offset of the2296 // segment is the last loadable segment, align the offset of the
2137 // following section to avoid loading non-segments parts of the file.2297 // following section to avoid loading non-segments parts of the file.
2138 if (LastRX && LastRX->LastSec == Sec)2298 if (lastRX && lastRX->lastSec == sec)
2139 Off = alignTo(Off, Target->PageSize);2299 off = alignTo(off, config->commonPageSize);
2140 }2300 }
21412301
2142 SectionHeaderOff = alignTo(Off, Config->Wordsize);2302 sectionHeaderOff = alignTo(off, config->wordsize);
2143 FileSize = SectionHeaderOff + (OutputSections.size() + 1) * sizeof(Elf_Shdr);2303 fileSize = sectionHeaderOff + (outputSections.size() + 1) * sizeof(Elf_Shdr);
21442304
2145 // Our logic assumes that sections have rising VA within the same segment.2305 // Our logic assumes that sections have rising VA within the same segment.
2146 // With use of linker scripts it is possible to violate this rule and get file2306 // With use of linker scripts it is possible to violate this rule and get file
...@@ -2151,62 +2311,49 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {...@@ -2151,62 +2311,49 @@ template <class ELFT> void Writer<ELFT>::assignFileOffsets() {
2151 // backwards, so we have to allow doing that to support linking them. We2311 // backwards, so we have to allow doing that to support linking them. We
2152 // perform non-critical checks for overlaps in checkSectionOverlap(), but here2312 // perform non-critical checks for overlaps in checkSectionOverlap(), but here
2153 // we want to prevent file size overflows because it would crash the linker.2313 // we want to prevent file size overflows because it would crash the linker.
2154 for (OutputSection *Sec : OutputSections) {2314 for (OutputSection *sec : outputSections) {
2155 if (Sec->Type == SHT_NOBITS)2315 if (sec->type == SHT_NOBITS)
2156 continue;2316 continue;
2157 if ((Sec->Offset > FileSize) || (Sec->Offset + Sec->Size > FileSize))2317 if ((sec->offset > fileSize) || (sec->offset + sec->size > fileSize))
2158 error("unable to place section " + Sec->Name + " at file offset " +2318 error("unable to place section " + sec->name + " at file offset " +
2159 rangeToString(Sec->Offset, Sec->Size) +2319 rangeToString(sec->offset, sec->size) +
2160 "; check your linker script for overflows");2320 "; check your linker script for overflows");
2161 }2321 }
2162}2322}
21632323
2164// Finalize the program headers. We call this function after we assign2324// Finalize the program headers. We call this function after we assign
2165// file offsets and VAs to all sections.2325// file offsets and VAs to all sections.
2166template <class ELFT> void Writer<ELFT>::setPhdrs() {2326template <class ELFT> void Writer<ELFT>::setPhdrs(Partition &part) {
2167 for (PhdrEntry *P : Phdrs) {2327 for (PhdrEntry *p : part.phdrs) {
2168 OutputSection *First = P->FirstSec;2328 OutputSection *first = p->firstSec;
2169 OutputSection *Last = P->LastSec;2329 OutputSection *last = p->lastSec;
21702330
2171 if (First) {2331 if (first) {
2172 P->p_filesz = Last->Offset - First->Offset;2332 p->p_filesz = last->offset - first->offset;
2173 if (Last->Type != SHT_NOBITS)2333 if (last->type != SHT_NOBITS)
2174 P->p_filesz += Last->Size;2334 p->p_filesz += last->size;
21752335
2176 P->p_memsz = Last->Addr + Last->Size - First->Addr;2336 p->p_memsz = last->addr + last->size - first->addr;
2177 P->p_offset = First->Offset;2337 p->p_offset = first->offset;
2178 P->p_vaddr = First->Addr;2338 p->p_vaddr = first->addr;
21792339
2180 if (!P->HasLMA)2340 // File offsets in partitions other than the main partition are relative
2181 P->p_paddr = First->getLMA();2341 // to the offset of the ELF headers. Perform that adjustment now.
2342 if (part.elfHeader)
2343 p->p_offset -= part.elfHeader->getParent()->offset;
2344
2345 if (!p->hasLMA)
2346 p->p_paddr = first->getLMA();
2182 }2347 }
21832348
2184 if (P->p_type == PT_LOAD) {2349 if (p->p_type == PT_LOAD) {
2185 P->p_align = std::max<uint64_t>(P->p_align, Config->MaxPageSize);2350 p->p_align = std::max<uint64_t>(p->p_align, config->maxPageSize);
2186 } else if (P->p_type == PT_GNU_RELRO) {2351 } else if (p->p_type == PT_GNU_RELRO) {
2187 P->p_align = 1;2352 p->p_align = 1;
2188 // The glibc dynamic loader rounds the size down, so we need to round up2353 // The glibc dynamic loader rounds the size down, so we need to round up
2189 // to protect the last page. This is a no-op on FreeBSD which always2354 // to protect the last page. This is a no-op on FreeBSD which always
2190 // rounds up.2355 // rounds up.
2191 P->p_memsz = alignTo(P->p_memsz, Target->PageSize);2356 p->p_memsz = alignTo(p->p_memsz, config->commonPageSize);
2192 }
2193
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);
2210 }2357 }
2211 }2358 }
2212}2359}
...@@ -2214,37 +2361,37 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {...@@ -2214,37 +2361,37 @@ template <class ELFT> void Writer<ELFT>::setPhdrs() {
2214// A helper struct for checkSectionOverlap.2361// A helper struct for checkSectionOverlap.
2215namespace {2362namespace {
2216struct SectionOffset {2363struct SectionOffset {
2217 OutputSection *Sec;2364 OutputSection *sec;
2218 uint64_t Offset;2365 uint64_t offset;
2219};2366};
2220} // namespace2367} // namespace
22212368
2222// Check whether sections overlap for a specific address range (file offsets,2369// Check whether sections overlap for a specific address range (file offsets,
2223// load and virtual adresses).2370// load and virtual adresses).
2224static void checkOverlap(StringRef Name, std::vector<SectionOffset> &Sections,2371static void checkOverlap(StringRef name, std::vector<SectionOffset> &sections,
2225 bool IsVirtualAddr) {2372 bool isVirtualAddr) {
2226 llvm::sort(Sections, [=](const SectionOffset &A, const SectionOffset &B) {2373 llvm::sort(sections, [=](const SectionOffset &a, const SectionOffset &b) {
2227 return A.Offset < B.Offset;2374 return a.offset < b.offset;
2228 });2375 });
22292376
2230 // Finding overlap is easy given a vector is sorted by start position.2377 // Finding overlap is easy given a vector is sorted by start position.
2231 // If an element starts before the end of the previous element, they overlap.2378 // If an element starts before the end of the previous element, they overlap.
2232 for (size_t I = 1, End = Sections.size(); I < End; ++I) {2379 for (size_t i = 1, end = sections.size(); i < end; ++i) {
2233 SectionOffset A = Sections[I - 1];2380 SectionOffset a = sections[i - 1];
2234 SectionOffset B = Sections[I];2381 SectionOffset b = sections[i];
2235 if (B.Offset >= A.Offset + A.Sec->Size)2382 if (b.offset >= a.offset + a.sec->size)
2236 continue;2383 continue;
22372384
2238 // If both sections are in OVERLAY we allow the overlapping of virtual2385 // If both sections are in OVERLAY we allow the overlapping of virtual
2239 // addresses, because it is what OVERLAY was designed for.2386 // addresses, because it is what OVERLAY was designed for.
2240 if (IsVirtualAddr && A.Sec->InOverlay && B.Sec->InOverlay)2387 if (isVirtualAddr && a.sec->inOverlay && b.sec->inOverlay)
2241 continue;2388 continue;
22422389
2243 errorOrWarn("section " + A.Sec->Name + " " + Name +2390 errorOrWarn("section " + a.sec->name + " " + name +
2244 " range overlaps with " + B.Sec->Name + "\n>>> " + A.Sec->Name +2391 " range overlaps with " + b.sec->name + "\n>>> " + a.sec->name +
2245 " range is " + rangeToString(A.Offset, A.Sec->Size) + "\n>>> " +2392 " range is " + rangeToString(a.offset, a.sec->size) + "\n>>> " +
2246 B.Sec->Name + " range is " +2393 b.sec->name + " range is " +
2247 rangeToString(B.Offset, B.Sec->Size));2394 rangeToString(b.offset, b.sec->size));
2248 }2395 }
2249}2396}
22502397
...@@ -2255,11 +2402,11 @@ static void checkOverlap(StringRef Name, std::vector<SectionOffset> &Sections,...@@ -2255,11 +2402,11 @@ static void checkOverlap(StringRef Name, std::vector<SectionOffset> &Sections,
2255// ranges and the virtual address ranges don't overlap2402// ranges and the virtual address ranges don't overlap
2256template <class ELFT> void Writer<ELFT>::checkSections() {2403template <class ELFT> void Writer<ELFT>::checkSections() {
2257 // First, check that section's VAs fit in available address space for target.2404 // First, check that section's VAs fit in available address space for target.
2258 for (OutputSection *OS : OutputSections)2405 for (OutputSection *os : outputSections)
2259 if ((OS->Addr + OS->Size < OS->Addr) ||2406 if ((os->addr + os->size < os->addr) ||
2260 (!ELFT::Is64Bits && OS->Addr + OS->Size > UINT32_MAX))2407 (!ELFT::Is64Bits && os->addr + os->size > UINT32_MAX))
2261 errorOrWarn("section " + OS->Name + " at 0x" + utohexstr(OS->Addr) +2408 errorOrWarn("section " + os->name + " at 0x" + utohexstr(os->addr) +
2262 " of size 0x" + utohexstr(OS->Size) +2409 " of size 0x" + utohexstr(os->size) +
2263 " exceeds available address space");2410 " exceeds available address space");
22642411
2265 // Check for overlapping file offsets. In this case we need to skip any2412 // Check for overlapping file offsets. In this case we need to skip any
...@@ -2267,17 +2414,17 @@ template <class ELFT> void Writer<ELFT>::checkSections() {...@@ -2267,17 +2414,17 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
2267 // the file so Sec->Offset + Sec->Size can overlap with others. If --oformat2414 // the file so Sec->Offset + Sec->Size can overlap with others. If --oformat
2268 // binary is specified only add SHF_ALLOC sections are added to the output2415 // binary is specified only add SHF_ALLOC sections are added to the output
2269 // file so we skip any non-allocated sections in that case.2416 // file so we skip any non-allocated sections in that case.
2270 std::vector<SectionOffset> FileOffs;2417 std::vector<SectionOffset> fileOffs;
2271 for (OutputSection *Sec : OutputSections)2418 for (OutputSection *sec : outputSections)
2272 if (Sec->Size > 0 && Sec->Type != SHT_NOBITS &&2419 if (sec->size > 0 && sec->type != SHT_NOBITS &&
2273 (!Config->OFormatBinary || (Sec->Flags & SHF_ALLOC)))2420 (!config->oFormatBinary || (sec->flags & SHF_ALLOC)))
2274 FileOffs.push_back({Sec, Sec->Offset});2421 fileOffs.push_back({sec, sec->offset});
2275 checkOverlap("file", FileOffs, false);2422 checkOverlap("file", fileOffs, false);
22762423
2277 // When linking with -r there is no need to check for overlapping virtual/load2424 // When linking with -r there is no need to check for overlapping virtual/load
2278 // addresses since those addresses will only be assigned when the final2425 // addresses since those addresses will only be assigned when the final
2279 // executable/shared object is created.2426 // executable/shared object is created.
2280 if (Config->Relocatable)2427 if (config->relocatable)
2281 return;2428 return;
22822429
2283 // Checking for overlapping virtual and load addresses only needs to take2430 // Checking for overlapping virtual and load addresses only needs to take
...@@ -2285,20 +2432,20 @@ template <class ELFT> void Writer<ELFT>::checkSections() {...@@ -2285,20 +2432,20 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
2285 // Furthermore, we also need to skip SHF_TLS sections since these will be2432 // Furthermore, we also need to skip SHF_TLS sections since these will be
2286 // mapped to other addresses at runtime and can therefore have overlapping2433 // mapped to other addresses at runtime and can therefore have overlapping
2287 // ranges in the file.2434 // ranges in the file.
2288 std::vector<SectionOffset> VMAs;2435 std::vector<SectionOffset> vmas;
2289 for (OutputSection *Sec : OutputSections)2436 for (OutputSection *sec : outputSections)
2290 if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))2437 if (sec->size > 0 && (sec->flags & SHF_ALLOC) && !(sec->flags & SHF_TLS))
2291 VMAs.push_back({Sec, Sec->Addr});2438 vmas.push_back({sec, sec->addr});
2292 checkOverlap("virtual address", VMAs, true);2439 checkOverlap("virtual address", vmas, true);
22932440
2294 // Finally, check that the load addresses don't overlap. This will usually be2441 // Finally, check that the load addresses don't overlap. This will usually be
2295 // the same as the virtual addresses but can be different when using a linker2442 // the same as the virtual addresses but can be different when using a linker
2296 // script with AT().2443 // script with AT().
2297 std::vector<SectionOffset> LMAs;2444 std::vector<SectionOffset> lmas;
2298 for (OutputSection *Sec : OutputSections)2445 for (OutputSection *sec : outputSections)
2299 if (Sec->Size > 0 && (Sec->Flags & SHF_ALLOC) && !(Sec->Flags & SHF_TLS))2446 if (sec->size > 0 && (sec->flags & SHF_ALLOC) && !(sec->flags & SHF_TLS))
2300 LMAs.push_back({Sec, Sec->getLMA()});2447 lmas.push_back({sec, sec->getLMA()});
2301 checkOverlap("load address", LMAs, false);2448 checkOverlap("load address", lmas, false);
2302}2449}
23032450
2304// The entry point address is chosen in the following ways.2451// The entry point address is chosen in the following ways.
...@@ -2311,89 +2458,45 @@ template <class ELFT> void Writer<ELFT>::checkSections() {...@@ -2311,89 +2458,45 @@ template <class ELFT> void Writer<ELFT>::checkSections() {
2311// 6. the address 0.2458// 6. the address 0.
2312static uint64_t getEntryAddr() {2459static uint64_t getEntryAddr() {
2313 // Case 1, 2 or 32460 // Case 1, 2 or 3
2314 if (Symbol *B = Symtab->find(Config->Entry))2461 if (Symbol *b = symtab->find(config->entry))
2315 return B->getVA();2462 return b->getVA();
23162463
2317 // Case 42464 // Case 4
2318 uint64_t Addr;2465 uint64_t addr;
2319 if (to_integer(Config->Entry, Addr))2466 if (to_integer(config->entry, addr))
2320 return Addr;2467 return addr;
23212468
2322 // Case 52469 // Case 5
2323 if (OutputSection *Sec = findSection(".text")) {2470 if (OutputSection *sec = findSection(".text")) {
2324 if (Config->WarnMissingEntry)2471 if (config->warnMissingEntry)
2325 warn("cannot find entry symbol " + Config->Entry + "; defaulting to 0x" +2472 warn("cannot find entry symbol " + config->entry + "; defaulting to 0x" +
2326 utohexstr(Sec->Addr));2473 utohexstr(sec->addr));
2327 return Sec->Addr;2474 return sec->addr;
2328 }2475 }
23292476
2330 // Case 62477 // Case 6
2331 if (Config->WarnMissingEntry)2478 if (config->warnMissingEntry)
2332 warn("cannot find entry symbol " + Config->Entry +2479 warn("cannot find entry symbol " + config->entry +
2333 "; not setting start address");2480 "; not setting start address");
2334 return 0;2481 return 0;
2335}2482}
23362483
2337static uint16_t getELFType() {2484static uint16_t getELFType() {
2338 if (Config->Pic)2485 if (config->isPic)
2339 return ET_DYN;2486 return ET_DYN;
2340 if (Config->Relocatable)2487 if (config->relocatable)
2341 return ET_REL;2488 return ET_REL;
2342 return ET_EXEC;2489 return ET_EXEC;
2343}2490}
23442491
2345static uint8_t getAbiVersion() {
2346 // MIPS non-PIC executable gets ABI version 1.
2347 if (Config->EMachine == EM_MIPS && getELFType() == ET_EXEC &&
2348 (Config->EFlags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC)
2349 return 1;
2350 return 0;
2351}
2352
2353template <class ELFT> void Writer<ELFT>::writeHeader() {2492template <class ELFT> void Writer<ELFT>::writeHeader() {
2354 uint8_t *Buf = Buffer->getBufferStart();2493 writeEhdr<ELFT>(Out::bufferStart, *mainPart);
23552494 writePhdrs<ELFT>(Out::bufferStart + sizeof(Elf_Ehdr), *mainPart);
2356 // For executable segments, the trap instructions are written before writing2495
2357 // the header. Setting Elf header bytes to zero ensures that any unused bytes2496 auto *eHdr = reinterpret_cast<Elf_Ehdr *>(Out::bufferStart);
2358 // in header are zero-cleared, instead of having trap instructions.2497 eHdr->e_type = getELFType();
2359 memset(Buf, 0, sizeof(Elf_Ehdr));2498 eHdr->e_entry = getEntryAddr();
2360 memcpy(Buf, "\177ELF", 4);2499 eHdr->e_shoff = sectionHeaderOff;
2361
2362 // Write the ELF header.
2363 auto *EHdr = reinterpret_cast<Elf_Ehdr *>(Buf);
2364 EHdr->e_ident[EI_CLASS] = Config->Is64 ? ELFCLASS64 : ELFCLASS32;
2365 EHdr->e_ident[EI_DATA] = Config->IsLE ? ELFDATA2LSB : ELFDATA2MSB;
2366 EHdr->e_ident[EI_VERSION] = EV_CURRENT;
2367 EHdr->e_ident[EI_OSABI] = Config->OSABI;
2368 EHdr->e_ident[EI_ABIVERSION] = getAbiVersion();
2369 EHdr->e_type = getELFType();
2370 EHdr->e_machine = Config->EMachine;
2371 EHdr->e_version = EV_CURRENT;
2372 EHdr->e_entry = getEntryAddr();
2373 EHdr->e_shoff = SectionHeaderOff;
2374 EHdr->e_flags = Config->EFlags;
2375 EHdr->e_ehsize = sizeof(Elf_Ehdr);
2376 EHdr->e_phnum = Phdrs.size();
2377 EHdr->e_shentsize = sizeof(Elf_Shdr);
2378
2379 if (!Config->Relocatable) {
2380 EHdr->e_phoff = sizeof(Elf_Ehdr);
2381 EHdr->e_phentsize = sizeof(Elf_Phdr);
2382 }
2383
2384 // Write the program header table.
2385 auto *HBuf = reinterpret_cast<Elf_Phdr *>(Buf + EHdr->e_phoff);
2386 for (PhdrEntry *P : Phdrs) {
2387 HBuf->p_type = P->p_type;
2388 HBuf->p_flags = P->p_flags;
2389 HBuf->p_offset = P->p_offset;
2390 HBuf->p_vaddr = P->p_vaddr;
2391 HBuf->p_paddr = P->p_paddr;
2392 HBuf->p_filesz = P->p_filesz;
2393 HBuf->p_memsz = P->p_memsz;
2394 HBuf->p_align = P->p_align;
2395 ++HBuf;
2396 }
23972500
2398 // Write the section header table.2501 // Write the section header table.
2399 //2502 //
...@@ -2404,57 +2507,58 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {...@@ -2404,57 +2507,58 @@ template <class ELFT> void Writer<ELFT>::writeHeader() {
2404 // the value. The sentinel values and fields are:2507 // the value. The sentinel values and fields are:
2405 // e_shnum = 0, SHdrs[0].sh_size = number of sections.2508 // e_shnum = 0, SHdrs[0].sh_size = number of sections.
2406 // e_shstrndx = SHN_XINDEX, SHdrs[0].sh_link = .shstrtab section index.2509 // e_shstrndx = SHN_XINDEX, SHdrs[0].sh_link = .shstrtab section index.
2407 auto *SHdrs = reinterpret_cast<Elf_Shdr *>(Buf + EHdr->e_shoff);2510 auto *sHdrs = reinterpret_cast<Elf_Shdr *>(Out::bufferStart + eHdr->e_shoff);
2408 size_t Num = OutputSections.size() + 1;2511 size_t num = outputSections.size() + 1;
2409 if (Num >= SHN_LORESERVE)2512 if (num >= SHN_LORESERVE)
2410 SHdrs->sh_size = Num;2513 sHdrs->sh_size = num;
2411 else2514 else
2412 EHdr->e_shnum = Num;2515 eHdr->e_shnum = num;
24132516
2414 uint32_t StrTabIndex = In.ShStrTab->getParent()->SectionIndex;2517 uint32_t strTabIndex = in.shStrTab->getParent()->sectionIndex;
2415 if (StrTabIndex >= SHN_LORESERVE) {2518 if (strTabIndex >= SHN_LORESERVE) {
2416 SHdrs->sh_link = StrTabIndex;2519 sHdrs->sh_link = strTabIndex;
2417 EHdr->e_shstrndx = SHN_XINDEX;2520 eHdr->e_shstrndx = SHN_XINDEX;
2418 } else {2521 } else {
2419 EHdr->e_shstrndx = StrTabIndex;2522 eHdr->e_shstrndx = strTabIndex;
2420 }2523 }
24212524
2422 for (OutputSection *Sec : OutputSections)2525 for (OutputSection *sec : outputSections)
2423 Sec->writeHeaderTo<ELFT>(++SHdrs);2526 sec->writeHeaderTo<ELFT>(++sHdrs);
2424}2527}
24252528
2426// Open a result file.2529// Open a result file.
2427template <class ELFT> void Writer<ELFT>::openFile() {2530template <class ELFT> void Writer<ELFT>::openFile() {
2428 uint64_t MaxSize = Config->Is64 ? INT64_MAX : UINT32_MAX;2531 uint64_t maxSize = config->is64 ? INT64_MAX : UINT32_MAX;
2429 if (MaxSize < FileSize) {2532 if (fileSize != size_t(fileSize) || maxSize < fileSize) {
2430 error("output file too large: " + Twine(FileSize) + " bytes");2533 error("output file too large: " + Twine(fileSize) + " bytes");
2431 return;2534 return;
2432 }2535 }
24332536
2434 unlinkAsync(Config->OutputFile);2537 unlinkAsync(config->outputFile);
2435 unsigned Flags = 0;2538 unsigned flags = 0;
2436 if (!Config->Relocatable)2539 if (!config->relocatable)
2437 Flags = FileOutputBuffer::F_executable;2540 flags = FileOutputBuffer::F_executable;
2438 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =2541 Expected<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
2439 FileOutputBuffer::create(Config->OutputFile, FileSize, Flags);2542 FileOutputBuffer::create(config->outputFile, fileSize, flags);
24402543
2441 if (!BufferOrErr)2544 if (!bufferOrErr) {
2442 error("failed to open " + Config->OutputFile + ": " +2545 error("failed to open " + config->outputFile + ": " +
2443 llvm::toString(BufferOrErr.takeError()));2546 llvm::toString(bufferOrErr.takeError()));
2444 else2547 return;
2445 Buffer = std::move(*BufferOrErr);2548 }
2549 buffer = std::move(*bufferOrErr);
2550 Out::bufferStart = buffer->getBufferStart();
2446}2551}
24472552
2448template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {2553template <class ELFT> void Writer<ELFT>::writeSectionsBinary() {
2449 uint8_t *Buf = Buffer->getBufferStart();2554 for (OutputSection *sec : outputSections)
2450 for (OutputSection *Sec : OutputSections)2555 if (sec->flags & SHF_ALLOC)
2451 if (Sec->Flags & SHF_ALLOC)2556 sec->writeTo<ELFT>(Out::bufferStart + sec->offset);
2452 Sec->writeTo<ELFT>(Buf + Sec->Offset);
2453}2557}
24542558
2455static void fillTrap(uint8_t *I, uint8_t *End) {2559static void fillTrap(uint8_t *i, uint8_t *end) {
2456 for (; I + 4 <= End; I += 4)2560 for (; i + 4 <= end; i += 4)
2457 memcpy(I, &Target->TrapInstr, 4);2561 memcpy(i, &target->trapInstr, 4);
2458}2562}
24592563
2460// Fill the last page of executable segments with trap instructions2564// Fill the last page of executable segments with trap instructions
...@@ -2464,61 +2568,119 @@ static void fillTrap(uint8_t *I, uint8_t *End) {...@@ -2464,61 +2568,119 @@ static void fillTrap(uint8_t *I, uint8_t *End) {
2464// We'll leave other pages in segments as-is because the rest will be2568// We'll leave other pages in segments as-is because the rest will be
2465// overwritten by output sections.2569// overwritten by output sections.
2466template <class ELFT> void Writer<ELFT>::writeTrapInstr() {2570template <class ELFT> void Writer<ELFT>::writeTrapInstr() {
2467 if (Script->HasSectionsCommand)2571 if (script->hasSectionsCommand)
2468 return;2572 return;
24692573
2470 // Fill the last page.2574 for (Partition &part : partitions) {
2471 uint8_t *Buf = Buffer->getBufferStart();2575 // Fill the last page.
2472 for (PhdrEntry *P : Phdrs)2576 for (PhdrEntry *p : part.phdrs)
2473 if (P->p_type == PT_LOAD && (P->p_flags & PF_X))2577 if (p->p_type == PT_LOAD && (p->p_flags & PF_X))
2474 fillTrap(Buf + alignDown(P->p_offset + P->p_filesz, Target->PageSize),2578 fillTrap(Out::bufferStart + alignDown(p->firstSec->offset + p->p_filesz,
2475 Buf + alignTo(P->p_offset + P->p_filesz, Target->PageSize));2579 config->commonPageSize),
24762580 Out::bufferStart + alignTo(p->firstSec->offset + p->p_filesz,
2477 // Round up the file size of the last segment to the page boundary iff it is2581 config->commonPageSize));
2478 // an executable segment to ensure that other tools don't accidentally2582
2479 // trim the instruction padding (e.g. when stripping the file).2583 // Round up the file size of the last segment to the page boundary iff it is
2480 PhdrEntry *Last = nullptr;2584 // an executable segment to ensure that other tools don't accidentally
2481 for (PhdrEntry *P : Phdrs)2585 // trim the instruction padding (e.g. when stripping the file).
2482 if (P->p_type == PT_LOAD)2586 PhdrEntry *last = nullptr;
2483 Last = P;2587 for (PhdrEntry *p : part.phdrs)
24842588 if (p->p_type == PT_LOAD)
2485 if (Last && (Last->p_flags & PF_X))2589 last = p;
2486 Last->p_memsz = Last->p_filesz = alignTo(Last->p_filesz, Target->PageSize);2590
2591 if (last && (last->p_flags & PF_X))
2592 last->p_memsz = last->p_filesz =
2593 alignTo(last->p_filesz, config->commonPageSize);
2594 }
2487}2595}
24882596
2489// Write section contents to a mmap'ed file.2597// Write section contents to a mmap'ed file.
2490template <class ELFT> void Writer<ELFT>::writeSections() {2598template <class ELFT> void Writer<ELFT>::writeSections() {
2491 uint8_t *Buf = Buffer->getBufferStart();
2492
2493 OutputSection *EhFrameHdr = nullptr;
2494 if (In.EhFrameHdr && !In.EhFrameHdr->empty())
2495 EhFrameHdr = In.EhFrameHdr->getParent();
2496
2497 // In -r or -emit-relocs mode, write the relocation sections first as in2599 // In -r or -emit-relocs mode, write the relocation sections first as in
2498 // ELf_Rel targets we might find out that we need to modify the relocated2600 // ELf_Rel targets we might find out that we need to modify the relocated
2499 // section while doing it.2601 // section while doing it.
2500 for (OutputSection *Sec : OutputSections)2602 for (OutputSection *sec : outputSections)
2501 if (Sec->Type == SHT_REL || Sec->Type == SHT_RELA)2603 if (sec->type == SHT_REL || sec->type == SHT_RELA)
2502 Sec->writeTo<ELFT>(Buf + Sec->Offset);2604 sec->writeTo<ELFT>(Out::bufferStart + sec->offset);
2605
2606 for (OutputSection *sec : outputSections)
2607 if (sec->type != SHT_REL && sec->type != SHT_RELA)
2608 sec->writeTo<ELFT>(Out::bufferStart + sec->offset);
2609}
2610
2611// Split one uint8 array into small pieces of uint8 arrays.
2612static std::vector<ArrayRef<uint8_t>> split(ArrayRef<uint8_t> arr,
2613 size_t chunkSize) {
2614 std::vector<ArrayRef<uint8_t>> ret;
2615 while (arr.size() > chunkSize) {
2616 ret.push_back(arr.take_front(chunkSize));
2617 arr = arr.drop_front(chunkSize);
2618 }
2619 if (!arr.empty())
2620 ret.push_back(arr);
2621 return ret;
2622}
25032623
2504 for (OutputSection *Sec : OutputSections)2624// Computes a hash value of Data using a given hash function.
2505 if (Sec != EhFrameHdr && Sec->Type != SHT_REL && Sec->Type != SHT_RELA)2625// In order to utilize multiple cores, we first split data into 1MB
2506 Sec->writeTo<ELFT>(Buf + Sec->Offset);2626// chunks, compute a hash for each chunk, and then compute a hash value
2627// of the hash values.
2628static void
2629computeHash(llvm::MutableArrayRef<uint8_t> hashBuf,
2630 llvm::ArrayRef<uint8_t> data,
2631 std::function<void(uint8_t *dest, ArrayRef<uint8_t> arr)> hashFn) {
2632 std::vector<ArrayRef<uint8_t>> chunks = split(data, 1024 * 1024);
2633 std::vector<uint8_t> hashes(chunks.size() * hashBuf.size());
2634
2635 // Compute hash values.
2636 parallelForEachN(0, chunks.size(), [&](size_t i) {
2637 hashFn(hashes.data() + i * hashBuf.size(), chunks[i]);
2638 });
25072639
2508 // The .eh_frame_hdr depends on .eh_frame section contents, therefore2640 // Write to the final output buffer.
2509 // it should be written after .eh_frame is written.2641 hashFn(hashBuf.data(), hashes);
2510 if (EhFrameHdr)
2511 EhFrameHdr->writeTo<ELFT>(Buf + EhFrameHdr->Offset);
2512}2642}
25132643
2514template <class ELFT> void Writer<ELFT>::writeBuildId() {2644template <class ELFT> void Writer<ELFT>::writeBuildId() {
2515 if (!In.BuildId || !In.BuildId->getParent())2645 if (!mainPart->buildId || !mainPart->buildId->getParent())
2516 return;2646 return;
25172647
2648 if (config->buildId == BuildIdKind::Hexstring) {
2649 for (Partition &part : partitions)
2650 part.buildId->writeBuildId(config->buildIdVector);
2651 return;
2652 }
2653
2518 // Compute a hash of all sections of the output file.2654 // Compute a hash of all sections of the output file.
2519 uint8_t *Start = Buffer->getBufferStart();2655 size_t hashSize = mainPart->buildId->hashSize;
2520 uint8_t *End = Start + FileSize;2656 std::vector<uint8_t> buildId(hashSize);
2521 In.BuildId->writeBuildId({Start, End});2657 llvm::ArrayRef<uint8_t> buf{Out::bufferStart, size_t(fileSize)};
2658
2659 switch (config->buildId) {
2660 case BuildIdKind::Fast:
2661 computeHash(buildId, buf, [](uint8_t *dest, ArrayRef<uint8_t> arr) {
2662 write64le(dest, xxHash64(arr));
2663 });
2664 break;
2665 case BuildIdKind::Md5:
2666 computeHash(buildId, buf, [&](uint8_t *dest, ArrayRef<uint8_t> arr) {
2667 memcpy(dest, MD5::hash(arr).data(), hashSize);
2668 });
2669 break;
2670 case BuildIdKind::Sha1:
2671 computeHash(buildId, buf, [&](uint8_t *dest, ArrayRef<uint8_t> arr) {
2672 memcpy(dest, SHA1::hash(arr).data(), hashSize);
2673 });
2674 break;
2675 case BuildIdKind::Uuid:
2676 if (auto ec = llvm::getRandomBytes(buildId.data(), hashSize))
2677 error("entropy source failure: " + ec.message());
2678 break;
2679 default:
2680 llvm_unreachable("unknown BuildIdKind");
2681 }
2682 for (Partition &part : partitions)
2683 part.buildId->writeBuildId(buildId);
2522}2684}
25232685
2524template void elf::writeResult<ELF32LE>();2686template void elf::writeResult<ELF32LE>();
deps/lld/ELF/Writer.h+13-16
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Writer.h -------------------------------------------------*- C++ -*-===//1//===- Writer.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -20,16 +19,14 @@ namespace elf {...@@ -20,16 +19,14 @@ namespace elf {
20class InputFile;19class InputFile;
21class OutputSection;20class OutputSection;
22class InputSectionBase;21class InputSectionBase;
23template <class ELFT> class ObjFile;
24class SymbolTable;
25template <class ELFT> void writeResult();22template <class ELFT> void writeResult();
2623
27// This describes a program header entry.24// This describes a program header entry.
28// Each contains type, access flags and range of output sections that will be25// Each contains type, access flags and range of output sections that will be
29// placed in it.26// placed in it.
30struct PhdrEntry {27struct PhdrEntry {
31 PhdrEntry(unsigned Type, unsigned Flags) : p_type(Type), p_flags(Flags) {}28 PhdrEntry(unsigned type, unsigned flags) : p_type(type), p_flags(flags) {}
32 void add(OutputSection *Sec);29 void add(OutputSection *sec);
3330
34 uint64_t p_paddr = 0;31 uint64_t p_paddr = 0;
35 uint64_t p_vaddr = 0;32 uint64_t p_vaddr = 0;
...@@ -40,22 +37,22 @@ struct PhdrEntry {...@@ -40,22 +37,22 @@ struct PhdrEntry {
40 uint32_t p_type = 0;37 uint32_t p_type = 0;
41 uint32_t p_flags = 0;38 uint32_t p_flags = 0;
4239
43 OutputSection *FirstSec = nullptr;40 OutputSection *firstSec = nullptr;
44 OutputSection *LastSec = nullptr;41 OutputSection *lastSec = nullptr;
45 bool HasLMA = false;42 bool hasLMA = false;
4643
47 uint64_t LMAOffset = 0;44 uint64_t lmaOffset = 0;
48};45};
4946
50void addReservedSymbols();47void addReservedSymbols();
51llvm::StringRef getOutputSectionName(const InputSectionBase *S);48llvm::StringRef getOutputSectionName(const InputSectionBase *s);
5249
53template <class ELFT> uint32_t calcMipsEFlags();50template <class ELFT> uint32_t calcMipsEFlags();
5451
55uint8_t getMipsFpAbiFlag(uint8_t OldFlag, uint8_t NewFlag,52uint8_t getMipsFpAbiFlag(uint8_t oldFlag, uint8_t newFlag,
56 llvm::StringRef FileName);53 llvm::StringRef fileName);
5754
58bool isMipsN32Abi(const InputFile *F);55bool isMipsN32Abi(const InputFile *f);
59bool isMicroMips();56bool isMicroMips();
60bool isMipsR6();57bool isMipsR6();
61} // namespace elf58} // namespace elf
deps/lld/LICENSE.TXT+236-20
...@@ -1,5 +1,240 @@...@@ -1,5 +1,240 @@
1==============================================================================1==============================================================================
2lld License2The LLVM Project is under the Apache License v2.0 with LLVM Exceptions:
3==============================================================================
4
5 Apache License
6 Version 2.0, January 2004
7 http://www.apache.org/licenses/
8
9 TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
10
11 1. Definitions.
12
13 "License" shall mean the terms and conditions for use, reproduction,
14 and distribution as defined by Sections 1 through 9 of this document.
15
16 "Licensor" shall mean the copyright owner or entity authorized by
17 the copyright owner that is granting the License.
18
19 "Legal Entity" shall mean the union of the acting entity and all
20 other entities that control, are controlled by, or are under common
21 control with that entity. For the purposes of this definition,
22 "control" means (i) the power, direct or indirect, to cause the
23 direction or management of such entity, whether by contract or
24 otherwise, or (ii) ownership of fifty percent (50%) or more of the
25 outstanding shares, or (iii) beneficial ownership of such entity.
26
27 "You" (or "Your") shall mean an individual or Legal Entity
28 exercising permissions granted by this License.
29
30 "Source" form shall mean the preferred form for making modifications,
31 including but not limited to software source code, documentation
32 source, and configuration files.
33
34 "Object" form shall mean any form resulting from mechanical
35 transformation or translation of a Source form, including but
36 not limited to compiled object code, generated documentation,
37 and conversions to other media types.
38
39 "Work" shall mean the work of authorship, whether in Source or
40 Object form, made available under the License, as indicated by a
41 copyright notice that is included in or attached to the work
42 (an example is provided in the Appendix below).
43
44 "Derivative Works" shall mean any work, whether in Source or Object
45 form, that is based on (or derived from) the Work and for which the
46 editorial revisions, annotations, elaborations, or other modifications
47 represent, as a whole, an original work of authorship. For the purposes
48 of this License, Derivative Works shall not include works that remain
49 separable from, or merely link (or bind by name) to the interfaces of,
50 the Work and Derivative Works thereof.
51
52 "Contribution" shall mean any work of authorship, including
53 the original version of the Work and any modifications or additions
54 to that Work or Derivative Works thereof, that is intentionally
55 submitted to Licensor for inclusion in the Work by the copyright owner
56 or by an individual or Legal Entity authorized to submit on behalf of
57 the copyright owner. For the purposes of this definition, "submitted"
58 means any form of electronic, verbal, or written communication sent
59 to the Licensor or its representatives, including but not limited to
60 communication on electronic mailing lists, source code control systems,
61 and issue tracking systems that are managed by, or on behalf of, the
62 Licensor for the purpose of discussing and improving the Work, but
63 excluding communication that is conspicuously marked or otherwise
64 designated in writing by the copyright owner as "Not a Contribution."
65
66 "Contributor" shall mean Licensor and any individual or Legal Entity
67 on behalf of whom a Contribution has been received by Licensor and
68 subsequently incorporated within the Work.
69
70 2. Grant of Copyright License. Subject to the terms and conditions of
71 this License, each Contributor hereby grants to You a perpetual,
72 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
73 copyright license to reproduce, prepare Derivative Works of,
74 publicly display, publicly perform, sublicense, and distribute the
75 Work and such Derivative Works in Source or Object form.
76
77 3. Grant of Patent License. Subject to the terms and conditions of
78 this License, each Contributor hereby grants to You a perpetual,
79 worldwide, non-exclusive, no-charge, royalty-free, irrevocable
80 (except as stated in this section) patent license to make, have made,
81 use, offer to sell, sell, import, and otherwise transfer the Work,
82 where such license applies only to those patent claims licensable
83 by such Contributor that are necessarily infringed by their
84 Contribution(s) alone or by combination of their Contribution(s)
85 with the Work to which such Contribution(s) was submitted. If You
86 institute patent litigation against any entity (including a
87 cross-claim or counterclaim in a lawsuit) alleging that the Work
88 or a Contribution incorporated within the Work constitutes direct
89 or contributory patent infringement, then any patent licenses
90 granted to You under this License for that Work shall terminate
91 as of the date such litigation is filed.
92
93 4. Redistribution. You may reproduce and distribute copies of the
94 Work or Derivative Works thereof in any medium, with or without
95 modifications, and in Source or Object form, provided that You
96 meet the following conditions:
97
98 (a) You must give any other recipients of the Work or
99 Derivative Works a copy of this License; and
100
101 (b) You must cause any modified files to carry prominent notices
102 stating that You changed the files; and
103
104 (c) You must retain, in the Source form of any Derivative Works
105 that You distribute, all copyright, patent, trademark, and
106 attribution notices from the Source form of the Work,
107 excluding those notices that do not pertain to any part of
108 the Derivative Works; and
109
110 (d) If the Work includes a "NOTICE" text file as part of its
111 distribution, then any Derivative Works that You distribute must
112 include a readable copy of the attribution notices contained
113 within such NOTICE file, excluding those notices that do not
114 pertain to any part of the Derivative Works, in at least one
115 of the following places: within a NOTICE text file distributed
116 as part of the Derivative Works; within the Source form or
117 documentation, if provided along with the Derivative Works; or,
118 within a display generated by the Derivative Works, if and
119 wherever such third-party notices normally appear. The contents
120 of the NOTICE file are for informational purposes only and
121 do not modify the License. You may add Your own attribution
122 notices within Derivative Works that You distribute, alongside
123 or as an addendum to the NOTICE text from the Work, provided
124 that such additional attribution notices cannot be construed
125 as modifying the License.
126
127 You may add Your own copyright statement to Your modifications and
128 may provide additional or different license terms and conditions
129 for use, reproduction, or distribution of Your modifications, or
130 for any such Derivative Works as a whole, provided Your use,
131 reproduction, and distribution of the Work otherwise complies with
132 the conditions stated in this License.
133
134 5. Submission of Contributions. Unless You explicitly state otherwise,
135 any Contribution intentionally submitted for inclusion in the Work
136 by You to the Licensor shall be under the terms and conditions of
137 this License, without any additional terms or conditions.
138 Notwithstanding the above, nothing herein shall supersede or modify
139 the terms of any separate license agreement you may have executed
140 with Licensor regarding such Contributions.
141
142 6. Trademarks. This License does not grant permission to use the trade
143 names, trademarks, service marks, or product names of the Licensor,
144 except as required for reasonable and customary use in describing the
145 origin of the Work and reproducing the content of the NOTICE file.
146
147 7. Disclaimer of Warranty. Unless required by applicable law or
148 agreed to in writing, Licensor provides the Work (and each
149 Contributor provides its Contributions) on an "AS IS" BASIS,
150 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
151 implied, including, without limitation, any warranties or conditions
152 of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
153 PARTICULAR PURPOSE. You are solely responsible for determining the
154 appropriateness of using or redistributing the Work and assume any
155 risks associated with Your exercise of permissions under this License.
156
157 8. Limitation of Liability. In no event and under no legal theory,
158 whether in tort (including negligence), contract, or otherwise,
159 unless required by applicable law (such as deliberate and grossly
160 negligent acts) or agreed to in writing, shall any Contributor be
161 liable to You for damages, including any direct, indirect, special,
162 incidental, or consequential damages of any character arising as a
163 result of this License or out of the use or inability to use the
164 Work (including but not limited to damages for loss of goodwill,
165 work stoppage, computer failure or malfunction, or any and all
166 other commercial damages or losses), even if such Contributor
167 has been advised of the possibility of such damages.
168
169 9. Accepting Warranty or Additional Liability. While redistributing
170 the Work or Derivative Works thereof, You may choose to offer,
171 and charge a fee for, acceptance of support, warranty, indemnity,
172 or other liability obligations and/or rights consistent with this
173 License. However, in accepting such obligations, You may act only
174 on Your own behalf and on Your sole responsibility, not on behalf
175 of any other Contributor, and only if You agree to indemnify,
176 defend, and hold each Contributor harmless for any liability
177 incurred by, or claims asserted against, such Contributor by reason
178 of your accepting any such warranty or additional liability.
179
180 END OF TERMS AND CONDITIONS
181
182 APPENDIX: How to apply the Apache License to your work.
183
184 To apply the Apache License to your work, attach the following
185 boilerplate notice, with the fields enclosed by brackets "[]"
186 replaced with your own identifying information. (Don't include
187 the brackets!) The text should be enclosed in the appropriate
188 comment syntax for the file format. We also recommend that a
189 file or class name and description of purpose be included on the
190 same "printed page" as the copyright notice for easier
191 identification within third-party archives.
192
193 Copyright [yyyy] [name of copyright owner]
194
195 Licensed under the Apache License, Version 2.0 (the "License");
196 you may not use this file except in compliance with the License.
197 You may obtain a copy of the License at
198
199 http://www.apache.org/licenses/LICENSE-2.0
200
201 Unless required by applicable law or agreed to in writing, software
202 distributed under the License is distributed on an "AS IS" BASIS,
203 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
204 See the License for the specific language governing permissions and
205 limitations under the License.
206
207
208---- LLVM Exceptions to the Apache 2.0 License ----
209
210As an exception, if, as a result of your compiling your source code, portions
211of this Software are embedded into an Object form of such source code, you
212may redistribute such embedded portions in such Object form without complying
213with the conditions of Sections 4(a), 4(b) and 4(d) of the License.
214
215In addition, if you combine or link compiled forms of this Software with
216software that is licensed under the GPLv2 ("Combined Software") and if a
217court of competent jurisdiction determines that the patent provision (Section
2183), the indemnity provision (Section 9) or other Section of the License
219conflicts with the conditions of the GPLv2, you may retroactively and
220prospectively choose to deem waived or otherwise exclude such Section(s) of
221the License, but only in their entirety and only with respect to the Combined
222Software.
223
224==============================================================================
225Software from third parties included in the LLVM Project:
226==============================================================================
227The LLVM Project contains third party software which is under different license
228terms. All such code will be identified clearly using at least one of two
229mechanisms:
2301) It will be in a separate directory tree with its own `LICENSE.txt` or
231 `LICENSE` file at the top containing the specific license and restrictions
232 which apply to that software, or
2332) It will contain specific license and restriction terms at the top of every
234 file.
235
236==============================================================================
237Legacy LLVM License (https://llvm.org/docs/DeveloperPolicy.html#legacy):
3==============================================================================238==============================================================================
4University of Illinois/NCSA239University of Illinois/NCSA
5Open Source License240Open Source License
...@@ -41,22 +276,3 @@ CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER...@@ -41,22 +276,3 @@ CONTRIBUTORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
41LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,276LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
42OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE277OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE
43SOFTWARE.278SOFTWARE.
44
45==============================================================================
46The lld software contains code written by third parties. Such software will
47have its own individual LICENSE.TXT file in the directory in which it appears.
48This file will describe the copyrights, license, and restrictions which apply
49to that code.
50
51The disclaimer of warranty in the University of Illinois Open Source License
52applies to all code in the lld Distribution, and nothing in any of the
53other licenses gives permission to use the names of the LLVM Team or the
54University of Illinois to endorse or promote products derived from this
55Software.
56
57The following pieces of software have additional or alternate copyrights,
58licenses, and/or restrictions:
59
60Program Directory
61------- ---------
62<none yet>
deps/lld/MinGW/Driver.cpp+216-145
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MinGW/Driver.cpp ---------------------------------------------------===//1//===- MinGW/Driver.cpp ---------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -31,10 +30,13 @@...@@ -31,10 +30,13 @@
3130
32#include "lld/Common/Driver.h"31#include "lld/Common/Driver.h"
33#include "lld/Common/ErrorHandler.h"32#include "lld/Common/ErrorHandler.h"
33#include "lld/Common/Memory.h"
34#include "lld/Common/Version.h"
34#include "llvm/ADT/ArrayRef.h"35#include "llvm/ADT/ArrayRef.h"
35#include "llvm/ADT/Optional.h"36#include "llvm/ADT/Optional.h"
36#include "llvm/ADT/StringExtras.h"37#include "llvm/ADT/StringExtras.h"
37#include "llvm/ADT/StringRef.h"38#include "llvm/ADT/StringRef.h"
39#include "llvm/ADT/Triple.h"
38#include "llvm/Option/Arg.h"40#include "llvm/Option/Arg.h"
39#include "llvm/Option/ArgList.h"41#include "llvm/Option/ArgList.h"
40#include "llvm/Option/Option.h"42#include "llvm/Option/Option.h"
...@@ -63,7 +65,7 @@ enum {...@@ -63,7 +65,7 @@ enum {
63#undef PREFIX65#undef PREFIX
6466
65// Create table mapping all options defined in Options.td67// Create table mapping all options defined in Options.td
66static const opt::OptTable::Info InfoTable[] = {68static const opt::OptTable::Info infoTable[] = {
67#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \69#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
68 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \70 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \
69 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},71 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
...@@ -74,208 +76,277 @@ static const opt::OptTable::Info InfoTable[] = {...@@ -74,208 +76,277 @@ static const opt::OptTable::Info InfoTable[] = {
74namespace {76namespace {
75class MinGWOptTable : public opt::OptTable {77class MinGWOptTable : public opt::OptTable {
76public:78public:
77 MinGWOptTable() : OptTable(InfoTable, false) {}79 MinGWOptTable() : OptTable(infoTable, false) {}
78 opt::InputArgList parse(ArrayRef<const char *> Argv);80 opt::InputArgList parse(ArrayRef<const char *> argv);
79};81};
80} // namespace82} // namespace
8183
82opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> Argv) {84static void printHelp(const char *argv0) {
83 unsigned MissingIndex;85 MinGWOptTable().PrintHelp(
84 unsigned MissingCount;86 outs(), (std::string(argv0) + " [options] file...").c_str(), "lld",
87 false /*ShowHidden*/, true /*ShowAllAliases*/);
88 outs() << "\n";
89}
8590
86 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());91static cl::TokenizerCallback getQuotingStyle() {
87 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);92 if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32)
93 return cl::TokenizeWindowsCommandLine;
94 return cl::TokenizeGNUCommandLine;
95}
8896
89 if (MissingCount)97opt::InputArgList MinGWOptTable::parse(ArrayRef<const char *> argv) {
90 fatal(StringRef(Args.getArgString(MissingIndex)) + ": missing argument");98 unsigned missingIndex;
91 for (auto *Arg : Args.filtered(OPT_UNKNOWN))99 unsigned missingCount;
92 fatal("unknown argument: " + Arg->getSpelling());100
93 if (!Args.hasArg(OPT_INPUT) && !Args.hasArg(OPT_l))101 SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
94 fatal("no input files");102 cl::ExpandResponseFiles(saver, getQuotingStyle(), vec);
95 return Args;103 opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount);
104
105 if (missingCount)
106 fatal(StringRef(args.getArgString(missingIndex)) + ": missing argument");
107 for (auto *arg : args.filtered(OPT_UNKNOWN))
108 fatal("unknown argument: " + arg->getAsString(args));
109 return args;
96}110}
97111
98// Find a file by concatenating given paths.112// Find a file by concatenating given paths.
99static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) {113static Optional<std::string> findFile(StringRef path1, const Twine &path2) {
100 SmallString<128> S;114 SmallString<128> s;
101 sys::path::append(S, Path1, Path2);115 sys::path::append(s, path1, path2);
102 if (sys::fs::exists(S))116 if (sys::fs::exists(s))
103 return S.str().str();117 return s.str().str();
104 return None;118 return None;
105}119}
106120
107// This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths.121// This is for -lfoo. We'll look for libfoo.dll.a or libfoo.a from search paths.
108static std::string122static std::string
109searchLibrary(StringRef Name, ArrayRef<StringRef> SearchPaths, bool BStatic) {123searchLibrary(StringRef name, ArrayRef<StringRef> searchPaths, bool bStatic) {
110 if (Name.startswith(":")) {124 if (name.startswith(":")) {
111 for (StringRef Dir : SearchPaths)125 for (StringRef dir : searchPaths)
112 if (Optional<std::string> S = findFile(Dir, Name.substr(1)))126 if (Optional<std::string> s = findFile(dir, name.substr(1)))
113 return *S;127 return *s;
114 fatal("unable to find library -l" + Name);128 fatal("unable to find library -l" + name);
115 }129 }
116130
117 for (StringRef Dir : SearchPaths) {131 for (StringRef dir : searchPaths) {
118 if (!BStatic)132 if (!bStatic)
119 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".dll.a"))133 if (Optional<std::string> s = findFile(dir, "lib" + name + ".dll.a"))
120 return *S;134 return *s;
121 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a"))135 if (Optional<std::string> s = findFile(dir, "lib" + name + ".a"))
122 return *S;136 return *s;
123 }137 }
124 fatal("unable to find library -l" + Name);138 fatal("unable to find library -l" + name);
125}139}
126140
127// Convert Unix-ish command line arguments to Windows-ish ones and141// Convert Unix-ish command line arguments to Windows-ish ones and
128// then call coff::link.142// then call coff::link.
129bool mingw::link(ArrayRef<const char *> ArgsArr, raw_ostream &Diag) {143bool mingw::link(ArrayRef<const char *> argsArr, raw_ostream &diag) {
130 MinGWOptTable Parser;144 MinGWOptTable parser;
131 opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));145 opt::InputArgList args = parser.parse(argsArr.slice(1));
146
147 if (args.hasArg(OPT_help)) {
148 printHelp(argsArr[0]);
149 return true;
150 }
151
152 // A note about "compatible with GNU linkers" message: this is a hack for
153 // scripts generated by GNU Libtool 2.4.6 (released in February 2014 and
154 // still the newest version in March 2017) or earlier to recognize LLD as
155 // a GNU compatible linker. As long as an output for the -v option
156 // contains "GNU" or "with BFD", they recognize us as GNU-compatible.
157 if (args.hasArg(OPT_v) || args.hasArg(OPT_version))
158 message(getLLDVersion() + " (compatible with GNU linkers)");
159
160 // The behavior of -v or --version is a bit strange, but this is
161 // needed for compatibility with GNU linkers.
162 if (args.hasArg(OPT_v) && !args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l))
163 return true;
164 if (args.hasArg(OPT_version))
165 return true;
132166
133 std::vector<std::string> LinkArgs;167 if (!args.hasArg(OPT_INPUT) && !args.hasArg(OPT_l))
134 auto Add = [&](const Twine &S) { LinkArgs.push_back(S.str()); };168 fatal("no input files");
169
170 std::vector<std::string> linkArgs;
171 auto add = [&](const Twine &s) { linkArgs.push_back(s.str()); };
135172
136 Add("lld-link");173 add("lld-link");
137 Add("-lldmingw");174 add("-lldmingw");
138175
139 if (auto *A = Args.getLastArg(OPT_entry)) {176 if (auto *a = args.getLastArg(OPT_entry)) {
140 StringRef S = A->getValue();177 StringRef s = a->getValue();
141 if (Args.getLastArgValue(OPT_m) == "i386pe" && S.startswith("_"))178 if (args.getLastArgValue(OPT_m) == "i386pe" && s.startswith("_"))
142 Add("-entry:" + S.substr(1));179 add("-entry:" + s.substr(1));
143 else180 else
144 Add("-entry:" + S);181 add("-entry:" + s);
182 }
183
184 if (args.hasArg(OPT_major_os_version, OPT_minor_os_version,
185 OPT_major_subsystem_version, OPT_minor_subsystem_version)) {
186 auto *majOSVer = args.getLastArg(OPT_major_os_version);
187 auto *minOSVer = args.getLastArg(OPT_minor_os_version);
188 auto *majSubSysVer = args.getLastArg(OPT_major_subsystem_version);
189 auto *minSubSysVer = args.getLastArg(OPT_minor_subsystem_version);
190 if (majOSVer && majSubSysVer &&
191 StringRef(majOSVer->getValue()) != StringRef(majSubSysVer->getValue()))
192 warn("--major-os-version and --major-subsystem-version set to differing "
193 "versions, not supported");
194 if (minOSVer && minSubSysVer &&
195 StringRef(minOSVer->getValue()) != StringRef(minSubSysVer->getValue()))
196 warn("--minor-os-version and --minor-subsystem-version set to differing "
197 "versions, not supported");
198 StringRef subSys = args.getLastArgValue(OPT_subs, "default");
199 StringRef major = majOSVer ? majOSVer->getValue()
200 : majSubSysVer ? majSubSysVer->getValue() : "6";
201 StringRef minor = minOSVer ? minOSVer->getValue()
202 : minSubSysVer ? minSubSysVer->getValue() : "";
203 StringRef sep = minor.empty() ? "" : ".";
204 add("-subsystem:" + subSys + "," + major + sep + minor);
205 } else if (auto *a = args.getLastArg(OPT_subs)) {
206 add("-subsystem:" + StringRef(a->getValue()));
145 }207 }
146208
147 if (auto *A = Args.getLastArg(OPT_subs))209 if (auto *a = args.getLastArg(OPT_out_implib))
148 Add("-subsystem:" + StringRef(A->getValue()));210 add("-implib:" + StringRef(a->getValue()));
149 if (auto *A = Args.getLastArg(OPT_out_implib))211 if (auto *a = args.getLastArg(OPT_stack))
150 Add("-implib:" + StringRef(A->getValue()));212 add("-stack:" + StringRef(a->getValue()));
151 if (auto *A = Args.getLastArg(OPT_stack))213 if (auto *a = args.getLastArg(OPT_output_def))
152 Add("-stack:" + StringRef(A->getValue()));214 add("-output-def:" + StringRef(a->getValue()));
153 if (auto *A = Args.getLastArg(OPT_output_def))215 if (auto *a = args.getLastArg(OPT_image_base))
154 Add("-output-def:" + StringRef(A->getValue()));216 add("-base:" + StringRef(a->getValue()));
155 if (auto *A = Args.getLastArg(OPT_image_base))217 if (auto *a = args.getLastArg(OPT_map))
156 Add("-base:" + StringRef(A->getValue()));218 add("-lldmap:" + StringRef(a->getValue()));
157 if (auto *A = Args.getLastArg(OPT_map))219
158 Add("-lldmap:" + StringRef(A->getValue()));220 if (auto *a = args.getLastArg(OPT_o))
159221 add("-out:" + StringRef(a->getValue()));
160 if (auto *A = Args.getLastArg(OPT_o))222 else if (args.hasArg(OPT_shared))
161 Add("-out:" + StringRef(A->getValue()));223 add("-out:a.dll");
162 else if (Args.hasArg(OPT_shared))
163 Add("-out:a.dll");
164 else224 else
165 Add("-out:a.exe");225 add("-out:a.exe");
166226
167 if (auto *A = Args.getLastArg(OPT_pdb)) {227 if (auto *a = args.getLastArg(OPT_pdb)) {
168 Add("-debug");228 add("-debug");
169 Add("-pdb:" + StringRef(A->getValue()));229 StringRef v = a->getValue();
170 } else if (Args.hasArg(OPT_strip_debug)) {230 if (!v.empty())
171 Add("-debug:symtab");231 add("-pdb:" + v);
172 } else if (!Args.hasArg(OPT_strip_all)) {232 } else if (args.hasArg(OPT_strip_debug)) {
173 Add("-debug:dwarf");233 add("-debug:symtab");
234 } else if (!args.hasArg(OPT_strip_all)) {
235 add("-debug:dwarf");
174 }236 }
175237
176 if (Args.hasArg(OPT_shared))238 if (args.hasArg(OPT_shared))
177 Add("-dll");239 add("-dll");
178 if (Args.hasArg(OPT_verbose))240 if (args.hasArg(OPT_verbose))
179 Add("-verbose");241 add("-verbose");
180 if (Args.hasArg(OPT_export_all_symbols))242 if (args.hasArg(OPT_exclude_all_symbols))
181 Add("-export-all-symbols");243 add("-exclude-all-symbols");
182 if (Args.hasArg(OPT_large_address_aware))244 if (args.hasArg(OPT_export_all_symbols))
183 Add("-largeaddressaware");245 add("-export-all-symbols");
184 if (Args.hasArg(OPT_kill_at))246 if (args.hasArg(OPT_large_address_aware))
185 Add("-kill-at");247 add("-largeaddressaware");
186248 if (args.hasArg(OPT_kill_at))
187 if (Args.getLastArgValue(OPT_m) != "thumb2pe" &&249 add("-kill-at");
188 Args.getLastArgValue(OPT_m) != "arm64pe" && !Args.hasArg(OPT_dynamicbase))250 if (args.hasArg(OPT_appcontainer))
189 Add("-dynamicbase:no");251 add("-appcontainer");
190252
191 if (Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false))253 if (args.getLastArgValue(OPT_m) != "thumb2pe" &&
192 Add("-opt:ref");254 args.getLastArgValue(OPT_m) != "arm64pe" && !args.hasArg(OPT_dynamicbase))
255 add("-dynamicbase:no");
256
257 if (args.hasFlag(OPT_no_insert_timestamp, OPT_insert_timestamp, false))
258 add("-timestamp:0");
259
260 if (args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, false))
261 add("-opt:ref");
193 else262 else
194 Add("-opt:noref");263 add("-opt:noref");
195264
196 if (auto *A = Args.getLastArg(OPT_icf)) {265 if (auto *a = args.getLastArg(OPT_icf)) {
197 StringRef S = A->getValue();266 StringRef s = a->getValue();
198 if (S == "all")267 if (s == "all")
199 Add("-opt:icf");268 add("-opt:icf");
200 else if (S == "safe" || S == "none")269 else if (s == "safe" || s == "none")
201 Add("-opt:noicf");270 add("-opt:noicf");
202 else271 else
203 fatal("unknown parameter: --icf=" + S);272 fatal("unknown parameter: --icf=" + s);
204 } else {273 } else {
205 Add("-opt:noicf");274 add("-opt:noicf");
206 }275 }
207276
208 if (auto *A = Args.getLastArg(OPT_m)) {277 if (auto *a = args.getLastArg(OPT_m)) {
209 StringRef S = A->getValue();278 StringRef s = a->getValue();
210 if (S == "i386pe")279 if (s == "i386pe")
211 Add("-machine:x86");280 add("-machine:x86");
212 else if (S == "i386pep")281 else if (s == "i386pep")
213 Add("-machine:x64");282 add("-machine:x64");
214 else if (S == "thumb2pe")283 else if (s == "thumb2pe")
215 Add("-machine:arm");284 add("-machine:arm");
216 else if (S == "arm64pe")285 else if (s == "arm64pe")
217 Add("-machine:arm64");286 add("-machine:arm64");
218 else287 else
219 fatal("unknown parameter: -m" + S);288 fatal("unknown parameter: -m" + s);
220 }289 }
221290
222 for (auto *A : Args.filtered(OPT_mllvm))291 for (auto *a : args.filtered(OPT_mllvm))
223 Add("-mllvm:" + StringRef(A->getValue()));292 add("-mllvm:" + StringRef(a->getValue()));
224293
225 for (auto *A : Args.filtered(OPT_Xlink))294 for (auto *a : args.filtered(OPT_Xlink))
226 Add(A->getValue());295 add(a->getValue());
227296
228 if (Args.getLastArgValue(OPT_m) == "i386pe")297 if (args.getLastArgValue(OPT_m) == "i386pe")
229 Add("-alternatename:__image_base__=___ImageBase");298 add("-alternatename:__image_base__=___ImageBase");
230 else299 else
231 Add("-alternatename:__image_base__=__ImageBase");300 add("-alternatename:__image_base__=__ImageBase");
232301
233 for (auto *A : Args.filtered(OPT_require_defined))302 for (auto *a : args.filtered(OPT_require_defined))
234 Add("-include:" + StringRef(A->getValue()));303 add("-include:" + StringRef(a->getValue()));
304 for (auto *a : args.filtered(OPT_undefined))
305 add("-includeoptional:" + StringRef(a->getValue()));
235306
236 std::vector<StringRef> SearchPaths;307 std::vector<StringRef> searchPaths;
237 for (auto *A : Args.filtered(OPT_L)) {308 for (auto *a : args.filtered(OPT_L)) {
238 SearchPaths.push_back(A->getValue());309 searchPaths.push_back(a->getValue());
239 Add("-libpath:" + StringRef(A->getValue()));310 add("-libpath:" + StringRef(a->getValue()));
240 }311 }
241312
242 StringRef Prefix = "";313 StringRef prefix = "";
243 bool Static = false;314 bool isStatic = false;
244 for (auto *A : Args) {315 for (auto *a : args) {
245 switch (A->getOption().getUnaliasedOption().getID()) {316 switch (a->getOption().getID()) {
246 case OPT_INPUT:317 case OPT_INPUT:
247 if (StringRef(A->getValue()).endswith_lower(".def"))318 if (StringRef(a->getValue()).endswith_lower(".def"))
248 Add("-def:" + StringRef(A->getValue()));319 add("-def:" + StringRef(a->getValue()));
249 else320 else
250 Add(Prefix + StringRef(A->getValue()));321 add(prefix + StringRef(a->getValue()));
251 break;322 break;
252 case OPT_l:323 case OPT_l:
253 Add(Prefix + searchLibrary(A->getValue(), SearchPaths, Static));324 add(prefix + searchLibrary(a->getValue(), searchPaths, isStatic));
254 break;325 break;
255 case OPT_whole_archive:326 case OPT_whole_archive:
256 Prefix = "-wholearchive:";327 prefix = "-wholearchive:";
257 break;328 break;
258 case OPT_no_whole_archive:329 case OPT_no_whole_archive:
259 Prefix = "";330 prefix = "";
260 break;331 break;
261 case OPT_Bstatic:332 case OPT_Bstatic:
262 Static = true;333 isStatic = true;
263 break;334 break;
264 case OPT_Bdynamic:335 case OPT_Bdynamic:
265 Static = false;336 isStatic = false;
266 break;337 break;
267 }338 }
268 }339 }
269340
270 if (Args.hasArg(OPT_verbose) || Args.hasArg(OPT__HASH_HASH_HASH))341 if (args.hasArg(OPT_verbose) || args.hasArg(OPT__HASH_HASH_HASH))
271 outs() << llvm::join(LinkArgs, " ") << "\n";342 outs() << llvm::join(linkArgs, " ") << "\n";
272343
273 if (Args.hasArg(OPT__HASH_HASH_HASH))344 if (args.hasArg(OPT__HASH_HASH_HASH))
274 return true;345 return true;
275346
276 // Repack vector of strings to vector of const char pointers for coff::link.347 // Repack vector of strings to vector of const char pointers for coff::link.
277 std::vector<const char *> Vec;348 std::vector<const char *> vec;
278 for (const std::string &S : LinkArgs)349 for (const std::string &s : linkArgs)
279 Vec.push_back(S.c_str());350 vec.push_back(s.c_str());
280 return coff::link(Vec, true);351 return coff::link(vec, true);
281}352}
deps/lld/MinGW/Options.td+51-23
...@@ -6,20 +6,45 @@ class S<string name>: Separate<["--", "-"], name>;...@@ -6,20 +6,45 @@ class S<string name>: Separate<["--", "-"], name>;
66
7def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,7def L: JoinedOrSeparate<["-"], "L">, MetaVarName<"<dir>">,
8 HelpText<"Add a directory to the library search path">;8 HelpText<"Add a directory to the library search path">;
9def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">;
10def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;
9def dynamicbase: F<"dynamicbase">, HelpText<"Enable ASLR">;11def dynamicbase: F<"dynamicbase">, HelpText<"Enable ASLR">;
10def entry: S<"entry">, MetaVarName<"<entry>">,12def entry: S<"entry">, MetaVarName<"<entry>">,
11 HelpText<"Name of entry point symbol">;13 HelpText<"Name of entry point symbol">;
14def exclude_all_symbols: F<"exclude-all-symbols">,
15 HelpText<"Don't automatically export any symbols">;
12def export_all_symbols: F<"export-all-symbols">,16def export_all_symbols: F<"export-all-symbols">,
13 HelpText<"Export all symbols even if a def file or dllexport attributes are used">;17 HelpText<"Export all symbols even if a def file or dllexport attributes are used">;
14def gc_sections: F<"gc-sections">, HelpText<"Remove unused sections">;18def gc_sections: F<"gc-sections">, HelpText<"Remove unused sections">;
19def help: F<"help">, HelpText<"Print option help">;
15def icf: J<"icf=">, HelpText<"Identical code folding">;20def icf: J<"icf=">, HelpText<"Identical code folding">;
16def image_base: S<"image-base">, HelpText<"Base address of the program">;21def image_base: S<"image-base">, HelpText<"Base address of the program">;
22def insert_timestamp: F<"insert-timestamp">,
23 HelpText<"Include PE header timestamp">;
17def kill_at: F<"kill-at">, HelpText<"Remove @n from exported symbols">;24def kill_at: F<"kill-at">, HelpText<"Remove @n from exported symbols">;
18def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,25def l: JoinedOrSeparate<["-"], "l">, MetaVarName<"<libName>">,
19 HelpText<"Root name of library to use">;26 HelpText<"Root name of library to use">;
20def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;27def m: JoinedOrSeparate<["-"], "m">, HelpText<"Set target emulation">;
28def major_os_version: Separate<["--"], "major-os-version">,
29 HelpText<"Set the OS and subsystem major version">;
30def major_os_version_eq: Joined<["--"], "major-os-version=">,
31 Alias<major_os_version>;
32def major_subsystem_version: Separate<["--"], "major-subsystem-version">,
33 HelpText<"Set the OS and subsystem major version">;
34def major_subsystem_version_eq: Joined<["--"], "major-subsystem-version=">,
35 Alias<major_subsystem_version>;
21def map: S<"Map">, HelpText<"Output a linker map">;36def map: S<"Map">, HelpText<"Output a linker map">;
22def map_eq: J<"Map=">, Alias<map>;37def map_eq: J<"Map=">, Alias<map>;
38def minor_os_version: Separate<["--"], "minor-os-version">,
39 HelpText<"Set the OS and subsystem minor version">;
40def minor_os_version_eq: Joined<["--"], "minor-os-version=">,
41 Alias<minor_os_version>;
42def minor_subsystem_version: Separate<["--"], "minor-subsystem-version">,
43 HelpText<"Set the OS and subsystem minor version">;
44def minor_subsystem_version_eq: Joined<["--"], "minor-subsystem-version=">,
45 Alias<minor_subsystem_version>;
46def no_insert_timestamp: F<"no-insert-timestamp">,
47 HelpText<"Don't include PE header timestamp">;
23def no_whole_archive: F<"no-whole-archive">,48def no_whole_archive: F<"no-whole-archive">,
24 HelpText<"No longer include all object files for following archives">;49 HelpText<"No longer include all object files for following archives">;
25def large_address_aware: Flag<["--"], "large-address-aware">,50def large_address_aware: Flag<["--"], "large-address-aware">,
...@@ -32,14 +57,21 @@ def out_implib_eq: Joined<["--"], "out-implib=">, Alias<out_implib>;...@@ -32,14 +57,21 @@ def out_implib_eq: Joined<["--"], "out-implib=">, Alias<out_implib>;
32def output_def: S<"output-def">, HelpText<"Output def file">;57def output_def: S<"output-def">, HelpText<"Output def file">;
33def shared: F<"shared">, HelpText<"Build a shared object">;58def shared: F<"shared">, HelpText<"Build a shared object">;
34def subs: S<"subsystem">, HelpText<"Specify subsystem">;59def subs: S<"subsystem">, HelpText<"Specify subsystem">;
60def subs_eq: J<"subsystem=">, Alias<subs>;
35def stack: S<"stack">;61def stack: S<"stack">;
36def strip_all: F<"strip-all">,62def strip_all: F<"strip-all">,
37 HelpText<"Omit all symbol information from the output binary">;63 HelpText<"Omit all symbol information from the output binary">;
38def strip_debug: F<"strip-debug">,64def strip_debug: F<"strip-debug">,
39 HelpText<"Omit all debug information, but keep symbol information">;65 HelpText<"Omit all debug information, but keep symbol information">;
66def undefined: S<"u">,
67 HelpText<"Include symbol in the link, if available">;
68def undefined_long: S<"undefined">, Alias<undefined>;
69def undefined_eq: J<"undefined=">, Alias<undefined>;
40def whole_archive: F<"whole-archive">,70def whole_archive: F<"whole-archive">,
41 HelpText<"Include all object files for following archives">;71 HelpText<"Include all object files for following archives">;
72def v: Flag<["-"], "v">, HelpText<"Display the version number">;
42def verbose: F<"verbose">, HelpText<"Verbose mode">;73def verbose: F<"verbose">, HelpText<"Verbose mode">;
74def version: F<"version">, HelpText<"Display the version number and exit">;
43def require_defined: S<"require-defined">,75def require_defined: S<"require-defined">,
44 HelpText<"Force symbol to be added to symbol table as an undefined one">;76 HelpText<"Force symbol to be added to symbol table as an undefined one">;
45def require_defined_eq: J<"require-defined=">, Alias<require_defined>;77def require_defined_eq: J<"require-defined=">, Alias<require_defined>;
...@@ -47,40 +79,36 @@ def require_defined_eq: J<"require-defined=">, Alias<require_defined>;...@@ -47,40 +79,36 @@ def require_defined_eq: J<"require-defined=">, Alias<require_defined>;
47// LLD specific options79// LLD specific options
48def _HASH_HASH_HASH : Flag<["-"], "###">,80def _HASH_HASH_HASH : Flag<["-"], "###">,
49 HelpText<"Print (but do not run) the commands to run for this compilation">;81 HelpText<"Print (but do not run) the commands to run for this compilation">;
82def appcontainer: F<"appcontainer">, HelpText<"Set the appcontainer flag in the executable">;
50def mllvm: S<"mllvm">;83def mllvm: S<"mllvm">;
51def pdb: S<"pdb">, HelpText<"Specify output PDB debug information file">;84def pdb: S<"pdb">, HelpText<"Output PDB debug info file, chosen implicitly if the argument is empty">;
85def pdb_eq: J<"pdb=">, Alias<pdb>;
52def Xlink : J<"Xlink=">, MetaVarName<"<arg>">,86def Xlink : J<"Xlink=">, MetaVarName<"<arg>">,
53 HelpText<"Pass <arg> to the COFF linker">;87 HelpText<"Pass <arg> to the COFF linker">;
5488
55// Currently stubs to avoid errors
56def Bdynamic: F<"Bdynamic">, HelpText<"Link against shared libraries">;
57def Bstatic: F<"Bstatic">, HelpText<"Do not link against shared libraries">;
58def O: Joined<["-"], "O">, HelpText<"Optimize output file size">;
59def build_id: F<"build-id">;
60def disable_auto_image_base: F<"disable-auto-image-base">;
61def enable_auto_image_base: F<"enable-auto-image-base">;
62def enable_auto_import: F<"enable-auto-import">;
63def end_group: F<"end-group">;
64def full_shutdown: Flag<["--"], "full-shutdown">;
65def high_entropy_va: F<"high-entropy-va">, HelpText<"Enable 64-bit ASLR">;
66def major_image_version: S<"major-image-version">;
67def minor_image_version: S<"minor-image-version">;
68def no_seh: F<"no-seh">;
69def nxcompat: F<"nxcompat">, HelpText<"Enable data execution prevention">;
70def pic_executable: F<"pic-executable">;
71def sysroot: J<"sysroot">, HelpText<"Sysroot">;
72def start_group: F<"start-group">;
73def tsaware: F<"tsaware">, HelpText<"Create Terminal Server aware executable">;
74def v: Flag<["-"], "v">, HelpText<"Display the version number">;
75def version: F<"version">, HelpText<"Display the version number and exit">;
76
77// Alias89// Alias
78def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>;90def alias_entry_e: JoinedOrSeparate<["-"], "e">, Alias<entry>;
79def alias_strip_s: Flag<["-"], "s">, Alias<strip_all>;91def alias_strip_s: Flag<["-"], "s">, Alias<strip_all>;
80def alias_strip_S: Flag<["-"], "S">, Alias<strip_debug>;92def alias_strip_S: Flag<["-"], "S">, Alias<strip_debug>;
8193
82// Ignored options94// Ignored options
95def: Joined<["-"], "O">;
96def: F<"build-id">;
97def: F<"disable-auto-image-base">;
98def: F<"enable-auto-image-base">;
99def: F<"enable-auto-import">, HelpText<"Ignored; listed for libtool compatibility">;
100def: F<"end-group">;
101def: Flag<["--"], "full-shutdown">;
102def: F<"high-entropy-va">;
103def: S<"major-image-version">;
104def: S<"minor-image-version">;
105def: F<"no-seh">;
106def: F<"nxcompat">;
107def: F<"pic-executable">;
83def: S<"plugin">;108def: S<"plugin">;
84def: J<"plugin=">;109def: J<"plugin=">;
85def: S<"plugin-opt">;110def: S<"plugin-opt">;
86def: J<"plugin-opt=">;111def: J<"plugin-opt=">;
112def: J<"sysroot">;
113def: F<"start-group">;
114def: F<"tsaware">;
deps/lld/docs/NewLLD.rst+8
...@@ -307,3 +307,11 @@ Glossary...@@ -307,3 +307,11 @@ Glossary
307 On Unix, your program is generally not guaranteed to be safe with ICF,307 On Unix, your program is generally not guaranteed to be safe with ICF,
308 although large programs happen to work correctly.308 although large programs happen to work correctly.
309 LLD works fine with ICF for example.309 LLD works fine with ICF for example.
310
311Other Info
312----------
313
314.. toctree::
315 :maxdepth: 1
316
317 missingkeyfunction
deps/lld/docs/Partitions.rst created+116
...@@ -0,0 +1,116 @@
1Partitions
2==========
3
4.. warning::
5
6 This feature is currently experimental, and its interface is subject
7 to change.
8
9LLD's partitioning feature allows a program (which may be an executable
10or a shared library) to be split into multiple pieces, or partitions. A
11partitioned program consists of a main partition together with a number of
12loadable partitions. The loadable partitions depend on the main partition
13in a similar way to a regular ELF shared object dependency, but unlike a
14shared object, the main partition and the loadable partitions share a virtual
15address space at link time, and each loadable partition is assigned a fixed
16offset from the main partition. This allows the loadable partitions to refer
17to code and data in the main partition directly without the binary size and
18performance overhead of PLTs, GOTs or symbol table entries.
19
20Usage
21-----
22
23A program that uses the partitioning feature must decide which symbols are
24going to be used as the "entry points" for each partition. An entry point
25could, for example, be the equivalent of the partition's ``main`` function, or
26there could be a group of functions that expose the functionality implemented
27by the partition. The intent is that in order to use a loadable partition,
28the program will use ``dlopen``/``dlsym`` or similar functions to dynamically
29load the partition at its assigned address, look up an entry point by name
30and call it. Note, however, that the standard ``dlopen`` function does not
31allow specifying a load address. On Android, the ``android_dlopen_ext``
32function may be used together with the ``ANDROID_DLEXT_RESERVED_ADDRESS``
33flag to load a shared object at a specific address.
34
35Once the entry points have been decided, the translation unit(s)
36containing the entry points should be compiled using the Clang compiler flag
37``-fsymbol-partition=<soname>``, where ``<soname>`` is the intended soname
38of the partition. The resulting object files are passed to the linker in
39the usual way.
40
41The linker will then use these entry points to automatically split the program
42into partitions according to which sections of the program are reachable from
43which entry points, similarly to how ``--gc-sections`` removes unused parts of
44a program. Any sections that are only reachable from a loadable partition's
45entry point are assigned to that partition, while all other sections are
46assigned to the main partition, including sections only reachable from
47loadable partitions.
48
49The following diagram illustrates how sections are assigned to partitions. Each
50section is colored according to its assigned partition.
51
52.. image:: partitions.svg
53
54The result of linking a program that uses partitions is essentially an
55ELF file with all of the partitions concatenated together. This file is
56referred to as a combined output file. To extract a partition from the
57combined output file, the ``llvm-objcopy`` tool should be used together
58with the flag ``--extract-main-partition`` to extract the main partition, or
59``-extract-partition=<soname>`` to extract one of the loadable partitions.
60An example command sequence is shown below:
61
62.. code-block:: shell
63
64 # Compile the main program.
65 clang -ffunction-sections -fdata-sections -c main.c
66
67 # Compile a feature to be placed in a loadable partition.
68 # Note that this is likely to be a separate build step to the main partition.
69 clang -ffunction-sections -fdata-sections -fsymbol-partition=libfeature.so -c feature.c
70
71 # Link the combined output file.
72 clang main.o feature.o -fuse-ld=lld -shared -o libcombined.so -Wl,-soname,libmain.so -Wl,--gc-sections
73
74 # Extract the partitions.
75 llvm-objcopy libcombined.so libmain.so --extract-main-partition
76 llvm-objcopy libcombined.so libfeature.so --extract-partition=libfeature.so
77
78In order to allow a program to discover the names of its loadable partitions
79and the locations of their reserved regions, the linker creates a partition
80index, which is an array of structs with the following definition:
81
82.. code-block:: c
83
84 struct partition_index_entry {
85 int32_t name_offset;
86 int32_t addr_offset;
87 uint32_t size;
88 };
89
90The ``name_offset`` field is a relative pointer to a null-terminated string
91containing the soname of the partition, the ``addr_offset`` field is a
92relative pointer to its load address and the ``size`` field contains the
93size of the region reserved for the partition. To derive an absolute pointer
94from the relative pointer fields in this data structure, the address of the
95field should be added to the value stored in the field.
96
97The program may discover the location of the partition index using the
98linker-defined symbols ``__part_index_begin`` and ``__part_index_end``.
99
100Restrictions
101------------
102
103This feature is currently only supported in the ELF linker.
104
105The partitioning feature may not currently be used together with the
106``SECTIONS`` or ``PHDRS`` linker script features, nor may it be used with the
107``--section-start``, ``-Ttext``, ``-Tdata`` or ``-Tbss`` flags. All of these
108features assume a single set of output sections and/or program headers, which
109makes their semantics ambiguous in the presence of more than one partition.
110
111The partitioning feature may not currently be used on the MIPS architecture
112because it is unclear whether the MIPS multi-GOT ABI is compatible with
113partitions.
114
115The current implementation only supports creating up to 254 partitions due
116to implementation limitations. This limit may be relaxed in the future.
deps/lld/docs/ReleaseNotes.rst+50-79
...@@ -1,19 +1,22 @@...@@ -1,19 +1,22 @@
1=======================1=======================
2lld 8.0.0 Release Notes2lld 9.0.0 Release Notes
3=======================3=======================
44
5.. contents::5.. contents::
6 :local:6 :local:
77
8.. warning::
9 These are in-progress notes for the upcoming LLVM 9.0.0 release.
10 Release notes for previous releases can be found on
11 `the Download Page <https://releases.llvm.org/download.html>`_.
12
8Introduction13Introduction
9============14============
1015
11lld is a high-performance linker that supports ELF (Unix), COFF (Windows),16This document contains the release notes for the lld linker, release 9.0.0.
12Mach-O (macOS), MinGW and WebAssembly. lld is command-line-compatible with17Here we describe the status of lld, including major improvements
13GNU linkers and Microsoft link.exe and is significantly faster than the18from the previous release. All lld releases may be downloaded
14system default linkers.19from the `LLVM releases web site <https://llvm.org/releases/>`_.
15
16lld 8.0.0 has lots of feature improvements and bug fixes.
1720
18Non-comprehensive list of changes in this release21Non-comprehensive list of changes in this release
19=================================================22=================================================
...@@ -21,101 +24,69 @@ Non-comprehensive list of changes in this release...@@ -21,101 +24,69 @@ Non-comprehensive list of changes in this release
21ELF Improvements24ELF Improvements
22----------------25----------------
2326
24* lld now supports RISC-V. (`r33936427* ld.lld now has typo suggestions for flags:
25 <https://reviews.llvm.org/rL339364>`_)28 ``$ ld.lld --call-shared`` now prints
2629 ``unknown argument '--call-shared', did you mean '--call_shared'``.
27* Default image base address has changed from 65536 to 2 MiB for i386
28 and 4 MiB for AArch64 to make lld-generated executables work better
29 with automatic superpage promotion. FreeBSD can promote contiguous
30 non-superpages to a superpage if they are aligned to the superpage
31 size. (`r342746 <https://reviews.llvm.org/rL342746>`_)
32
33* lld now attempts to place a ``.note`` segment in the first page of a
34 generated file, so that you can find some important information
35 (``.note.gnu.build-id`` in particular) in a core file even if a core
36 file is truncated by ulimit.
37 (`r349524 <https://reviews.llvm.org/rL349524>`_)
38
39* lld now reports an error if ``_GLOBAL_OFFSET_TABLE_`` symbol is
40 defined by an input object file, as the symbol is supposed to be
41 synthesized by the linker.
42 (`r347854 <https://reviews.llvm.org/rL347854>`_)
43
44* lld/Hexagon can now link Linux kernel and musl libc for Qualcomm
45 Hexagon ISA.
46
47* Initial MSP430 ISA support has landed.
4830
49* lld now uses the ``sigrie`` instruction as a trap instruction for31* ...
50 MIPS targets.
51
52* lld now creates a TLS segment for AArch64 with a slightly larger
53 alignment requirement, so that the loader makes a few bytes room
54 before each TLS segment at runtime. The aim of this change is to
55 make room to accomodate nonstandard Android TLS slots while keeping
56 the compatibility with the standard AArch64 ABI.
57 (`r350681 <https://reviews.llvm.org/rL350681>`_)
58
59* The following flags have been added: ``--call-graph-profile``,
60 ``--no-call-graph-profile``, ``--warn-ifunc-textrel``,
61 ``-z interpose``, ``-z global``, ``-z nodefaultlib``
6232
63COFF Improvements33COFF Improvements
64-----------------34-----------------
6535
66* PDB GUID is set to hash of PDB contents instead to a random byte36* Like the ELF driver, lld-link now has typo suggestions for flags.
67 sequence for build reproducibility.37
38* lld-link now correctly reports duplicate symbol errors for obj files
39 that were compiled with /Gy.
6840
69* ``/pdbsourcepath:`` is now also used to make ``"cwd"``, ``"exe"``, ``"pdb"``41* lld-link now correctly reports duplicate symbol errors when several res
70 in the env block of PDB outputs absolute if they are relative, and to make42 input files define resources with the same type, name, and language.
71 paths to obj files referenced in PDB outputs absolute if they are relative.43 This can be demoted to a warning using ``/force:multipleres``.
72 Together with the previous item, this makes it possible to generate
73 executables and PDBs that are fully deterministic and independent of the
74 absolute path to the build directory, so that different machines building
75 the same code in different directories can produce exactly the same output.
7644
77* The following flags have been added: ``/force:multiple``45* Having more than two ``/natvis:`` now works correctly; it used to not
46 work for larger binaries before.
7847
79* lld now can link against import libraries produced by GNU tools.48* Undefined symbols are now printed only in demangled form. Pass
49 ``/demangle:no`` to see raw symbol names instead.
8050
81* lld can create thunks for ARM and ARM64, to allow linking larger images51* The following flags have been added: ``/functionpadmin``, ``/swaprun:``,
82 (over 16 MB for ARM and over 128 MB for ARM64)52 ``/threads:no``
8353
84* Several speed and memory usage improvements.54* Several speed and memory usage improvements.
8555
86* lld now creates debug info for typedefs.56* Range extension thunks are now created for ARM64, if needed
8757
88* lld can now link obj files produced by ``cl.exe /Z7 /Yc``.58* lld-link now supports resource object files created by GNU windres and
59 MS cvtres, not only llvm-cvtres
8960
90* lld now understands ``%_PDB%`` and ``%_EXT%`` in ``/pdbaltpath:``.61* The generated thunks for delayimports now share the majority of code
62 among thunks, significantly reducing the overhead of using delayimport
9163
92* Undefined symbols are now printed in demangled form in addition to raw form.64* ...
9365
94MinGW Improvements66MinGW Improvements
95------------------67------------------
9668
97* lld can now automatically import data variables from DLLs without the69* lld now correctly links crtend.o as the last object file, handling
98 use of the dllimport attribute.70 terminators for the sections such as .eh_frame properly, fixing
71 DWARF exception handling with libgcc and gcc's crtend.o.
9972
100* lld can now use existing normal MinGW sysroots with import libraries and73* lld now also handles DWARF unwind info generated by GCC, when linking
101 CRT startup object files for GNU binutils. lld can handle most object74 with libgcc
102 files produced by GCC, and thus works as a drop-in replacement for
103 ld.bfd in such environments. (There are known issues with linking crtend.o
104 from GCC in setups with DWARF exceptions though, where object files are
105 linked in a different order than with GNU ld, inserting a DWARF exception
106 table terminator too early.)
10775
108* lld now supports COFF embedded directives for linking to nondefault76* Many more GNU ld options are now supported, which e.g. allows the lld
109 libraries, just like for the normal COFF target.77 MinGW frontend to be called by GCC
78
79* PDB output can be requested without manually specifying the PDB file
80 name, with the new option ``-pdb=`` with an empty value to the option.
81 (The old existing syntax ``-pdb <filename>`` was more cumbersome to use
82 with an empty parameter value.)
83
84MachO Improvements
85------------------
11086
111* Actually generate a codeview build id signature, even if not creating a PDB.87* Item 1.
112 Previously, the ``--build-id`` option did not actually generate a build id
113 unless ``--pdb`` was specified.
11488
115WebAssembly Improvements89WebAssembly Improvements
116------------------------90------------------------
11791
118* Add initial support for creating shared libraries (-shared).92* ...
119 Note: The shared library format is still under active development and may
120 undergo significant changes in future versions.
121 See: https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
deps/lld/docs/WebAssembly.rst+65-13
...@@ -4,21 +4,17 @@ WebAssembly lld port...@@ -4,21 +4,17 @@ WebAssembly lld port
4The WebAssembly version of lld takes WebAssembly binaries as inputs and produces4The WebAssembly version of lld takes WebAssembly binaries as inputs and produces
5a WebAssembly binary as its output. For the most part it tries to mimic the5a WebAssembly binary as its output. For the most part it tries to mimic the
6behaviour of traditional ELF linkers and specifically the ELF lld port. Where6behaviour of traditional ELF linkers and specifically the ELF lld port. Where
7possible that command line flags and the semantics should be the same.7possible the command line flags and the semantics should be the same.
88
99
10Object file format10Object file format
11------------------11------------------
1212
13The format the input object files that lld expects is specified as part of the13The WebAssembly object file format used by LLVM and LLD is specified as part of
14the WebAssembly tool conventions14the WebAssembly tool conventions on linking_.
15https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md.
16
17This is object format that the llvm will produce when run with the
18``wasm32-unknown-unknown`` target. To build llvm with WebAssembly support
19currently requires enabling the experimental backed using
20``-DLLVM_EXPERIMENTAL_TARGETS_TO_BUILD=WebAssembly``.
2115
16This is the object format that the llvm will produce when run with the
17``wasm32-unknown-unknown`` target.
2218
23Usage19Usage
24-----20-----
...@@ -88,10 +84,52 @@ WebAssembly-specific options:...@@ -88,10 +84,52 @@ WebAssembly-specific options:
88By default the function table is neither imported nor exported, but defined84By default the function table is neither imported nor exported, but defined
89for internal use only.85for internal use only.
9086
91When building shared libraries symbols are exported if they are marked87Behaviour
92as ``visibility=default``. When building executables only the entry point is88---------
93exported by default. In addition any symbol included on the command line via89
94``--export`` is also exported.90In general, where possible, the WebAssembly linker attempts to emulate the
91behaviour of a traditional ELF linker, and in particular the ELF port of lld.
92For more specific details on how this is achieved see the tool conventions on
93linking_.
94
95Function Signatures
96~~~~~~~~~~~~~~~~~~~
97
98One way in which the WebAssembly linker differs from traditional native linkers
99is that function signature checking is strict in WebAssembly. It is a
100validation error for a module to contain a call site that doesn't agree with
101the target signature. Even though this is undefined behaviour in C/C++, it is not
102uncommon to find this in real-world C/C++ programs. For example, a call site in
103one compilation unit which calls a function defined in another compilation
104unit but with too many arguments.
105
106In order not to generate such invalid modules, lld has two modes of handling such
107mismatches: it can simply error-out or it can create stub functions that will
108trap at runtime (functions that contain only an ``unreachable`` instruction)
109and use these stub functions at the otherwise invalid call sites.
110
111The default behaviour is to generate these stub function and to produce
112a warning. The ``--falal-warnings`` flag can be used to disable this behaviour
113and error out if mismatched are found.
114
115Imports and Exports
116~~~~~~~~~~~~~~~~~~~
117
118When building a shared library any symbols marked as ``visibility=default`` will
119be exported. When building an executable, only the entry point and symbols
120flagged as ``WASM_SYMBOL_EXPORTED`` are exported by default. In LLVM the
121``WASM_SYMBOL_EXPORTED`` flag is applied to any symbol in the ``llvm.used`` list
122which corresponds to ``__attribute__((used))`` in C/C++ sources.
123
124In addition, symbols can be exported via the linker command line using
125``--export``.
126
127Finally, just like with native ELF linker the ``--export-dynamic`` flag can be
128used to export symbol in the executable which are marked as
129``visibility=default``.
130
131Garbage Collection
132~~~~~~~~~~~~~~~~~~
95133
96Since WebAssembly is designed with size in mind the linker defaults to134Since WebAssembly is designed with size in mind the linker defaults to
97``--gc-sections`` which means that all unused functions and data segments will135``--gc-sections`` which means that all unused functions and data segments will
...@@ -103,6 +141,18 @@ The symbols which are preserved by default are:...@@ -103,6 +141,18 @@ The symbols which are preserved by default are:
103- Any symbol which is to be exported.141- Any symbol which is to be exported.
104- Any symbol transitively referenced by the above.142- Any symbol transitively referenced by the above.
105143
144Weak Undefined Functions
145~~~~~~~~~~~~~~~~~~~~~~~~
146
147On native platforms, calls to weak undefined functions end up as calls to the
148null function pointer. With WebAssembly, direct calls must reference a defined
149function (with the correct signature). In order to handle this case the linker
150will generate function a stub containing only the ``unreachable`` instruction
151and use this for any direct references to an undefined weak function.
152
153For example a runtime call to a weak undefined function ``foo`` will up trapping
154on ``unreachable`` inside and linker-generated function called
155``undefined:foo``.
106156
107Missing features157Missing features
108----------------158----------------
...@@ -112,3 +162,5 @@ Missing features...@@ -112,3 +162,5 @@ Missing features
112- No support for creating shared libraries. The spec for shared libraries in162- No support for creating shared libraries. The spec for shared libraries in
113 WebAssembly is still in flux:163 WebAssembly is still in flux:
114 https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md164 https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
165
166.. _linking: https://github.com/WebAssembly/tool-conventions/blob/master/Linking.md
deps/lld/docs/conf.py+2-2
...@@ -48,9 +48,9 @@ copyright = u'2011-%d, LLVM Project' % date.today().year...@@ -48,9 +48,9 @@ copyright = u'2011-%d, LLVM Project' % date.today().year
48# built documents.48# built documents.
49#49#
50# The short version.50# The short version.
51version = '8'51version = '9'
52# The full version, including alpha/beta/rc tags.52# The full version, including alpha/beta/rc tags.
53release = '8'53release = '9'
5454
55# The language for content autogenerated by Sphinx. Refer to documentation55# The language for content autogenerated by Sphinx. Refer to documentation
56# for a list of supported languages.56# for a list of supported languages.
deps/lld/docs/getting_started.rst+8-27
...@@ -28,23 +28,15 @@ On Unix-like Systems...@@ -28,23 +28,15 @@ On Unix-like Systems
28.. _libc++: http://libcxx.llvm.org/28.. _libc++: http://libcxx.llvm.org/
29.. _Python 2.4: http://python.org/download/29.. _Python 2.4: http://python.org/download/
3030
312. Check out LLVM::312. Check out LLVM and subprojects (including lld)::
3232
33 $ cd path/to/llvm-project33 $ git clone https://github.com/llvm/llvm-project.git
34 $ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
35
363. Check out lld::
37
38 $ cd llvm/tools
39 $ svn co http://llvm.org/svn/llvm-project/lld/trunk lld
40
41 * lld can also be checked out to ``path/to/llvm-project`` and built as an external
42 project.
4334
444. Build LLVM and lld::354. Build LLVM and lld::
4536
46 $ cd path/to/llvm-build/llvm (out of source build required)37 $ cd llvm-project
47 $ cmake -G "Unix Makefiles" path/to/llvm-project/llvm38 $ mkdir build && cd build
39 $ cmake -G "Unix Makefiles" -DLLVM_ENABLE_PROJECTS=lld ../llvm
48 $ make40 $ make
4941
50 * If you want to build with clang and it is not the default compiler or42 * If you want to build with clang and it is not the default compiler or
...@@ -71,23 +63,12 @@ Using Visual Studio...@@ -71,23 +63,12 @@ Using Visual Studio
71.. _Visual Studio 12 (2013) or later: http://www.microsoft.com/visualstudio/11/en-us63.. _Visual Studio 12 (2013) or later: http://www.microsoft.com/visualstudio/11/en-us
72.. _Python 2.4: http://python.org/download/64.. _Python 2.4: http://python.org/download/
7365
74#. Check out LLVM::66#. Check out LLVM as above.
75
76 $ cd path/to/llvm-project
77 $ svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
78
79#. Check out lld::
80
81 $ cd llvm/tools
82 $ svn co http://llvm.org/svn/llvm-project/lld/trunk lld
83
84 * lld can also be checked out to ``path/to/llvm-project`` and built as an external
85 project.
8667
87#. Generate Visual Studio project files::68#. Generate Visual Studio project files::
8869
89 $ cd path/to/llvm-build/llvm (out of source build required)70 $ cd llvm-project/build (out of source build required)
90 $ cmake -G "Visual Studio 11" path/to/llvm-project/llvm71 $ cmake -G "Visual Studio 11" -DLLVM_ENABLE_PROJECTS=lld ../llvm
9172
92#. Build73#. Build
9374
deps/lld/docs/index.rst+2-1
...@@ -106,7 +106,7 @@ build that tree. You need `cmake` and of course a C++ compiler....@@ -106,7 +106,7 @@ build that tree. You need `cmake` and of course a C++ compiler.
106106
107.. code-block:: console107.. code-block:: console
108108
109 $ git clone https://github.com/llvm-project/llvm-project-20170507 llvm-project109 $ git clone https://github.com/llvm/llvm-project llvm-project
110 $ mkdir build110 $ mkdir build
111 $ cd build111 $ cd build
112 $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=lld -DCMAKE_INSTALL_PREFIX=/usr/local ../llvm-project/llvm112 $ cmake -DCMAKE_BUILD_TYPE=Release -DLLVM_ENABLE_PROJECTS=lld -DCMAKE_INSTALL_PREFIX=/usr/local ../llvm-project/llvm
...@@ -174,4 +174,5 @@ document soon....@@ -174,4 +174,5 @@ document soon.
174 WebAssembly174 WebAssembly
175 windows_support175 windows_support
176 missingkeyfunction176 missingkeyfunction
177 Partitions
177 ReleaseNotes178 ReleaseNotes
deps/lld/docs/ld.lld.1+109-8
...@@ -1,9 +1,10 @@...@@ -1,9 +1,10 @@
1.\" This file is distributed under the University of Illinois Open Source1.\" Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2.\" License. See LICENSE.TXT for details.2.\" See https://llvm.org/LICENSE.txt for license information.
3.\" SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
3.\"4.\"
4.\" This man page documents only lld's ELF linking support, obtained originally5.\" This man page documents only lld's ELF linking support, obtained originally
5.\" from FreeBSD.6.\" from FreeBSD.
6.Dd September 26, 20187.Dd May 12, 2019
7.Dt LD.LLD 18.Dt LD.LLD 1
8.Os9.Os
9.Sh NAME10.Sh NAME
...@@ -45,6 +46,9 @@ as a native linker as well as a cross linker....@@ -45,6 +46,9 @@ as a native linker as well as a cross linker.
45.It Fl -allow-multiple-definition46.It Fl -allow-multiple-definition
46Do not error if a symbol is defined multiple times.47Do not error if a symbol is defined multiple times.
47The first definition will be used.48The first definition will be used.
49.It Fl -allow-shlib-undefined
50Allow unresolved references in shared libraries.
51This option is enabled by default when linking a shared library.
48.It Fl -apply-dynamic-relocs52.It Fl -apply-dynamic-relocs
49Apply link-time values for dynamic relocations.53Apply link-time values for dynamic relocations.
50.It Fl -as-needed54.It Fl -as-needed
...@@ -178,6 +182,8 @@ Set the...@@ -178,6 +182,8 @@ Set the
178field to the specified value.182field to the specified value.
179.It Fl -fini Ns = Ns Ar symbol183.It Fl -fini Ns = Ns Ar symbol
180Specify a finalizer function.184Specify a finalizer function.
185.It Fl -force-bti
186Force enable AArch64 BTI instruction in PLT, warn if Input ELF file does not have GNU_PROPERTY_AARCH64_FEATURE_1_BTI property.
181.It Fl -format Ns = Ns Ar input-format , Fl b Ar input-format187.It Fl -format Ns = Ns Ar input-format , Fl b Ar input-format
182Specify the format of the inputs following this option.188Specify the format of the inputs following this option.
183.Ar input-format189.Ar input-format
...@@ -213,6 +219,15 @@ Enable identical code folding....@@ -213,6 +219,15 @@ Enable identical code folding.
213Enable safe identical code folding.219Enable safe identical code folding.
214.It Fl -icf Ns = Ns Cm none220.It Fl -icf Ns = Ns Cm none
215Disable identical code folding.221Disable identical code folding.
222.It Fl -ignore-data-address-equality
223Ignore address equality of data. C/C++ requires each data to have a unique
224address. This option allows lld to do unsafe optimization that breaks the
225requirement: create copies of read-only data or merge two or more read-only data
226that happen to have the same value.
227.It Fl -ignore-function-address-equality
228Ignore address equality of functions. This option allows non-PIC calls to a
229function with non-default visibility in a shared object. The function may have
230different addresses within the executable and within the shared object.
216.It Fl -image-base Ns = Ns Ar value231.It Fl -image-base Ns = Ns Ar value
217Set the base address to232Set the base address to
218.Ar value .233.Ar value .
...@@ -241,6 +256,11 @@ Set target emulation....@@ -241,6 +256,11 @@ Set target emulation.
241.It Fl -Map Ns = Ns Ar file , Fl M Ar file256.It Fl -Map Ns = Ns Ar file , Fl M Ar file
242Print a link map to257Print a link map to
243.Ar file .258.Ar file .
259.It Fl -nmagic , Fl n
260Do not page align sections, link against static libraries.
261.It Fl -no-allow-shlib-undefined
262Do not allow unresolved references in shared libraries.
263This option is enabled by default when linking an executable.
244.It Fl -no-as-needed264.It Fl -no-as-needed
245Always set265Always set
246.Dv DT_NEEDED266.Dv DT_NEEDED
...@@ -259,6 +279,12 @@ section....@@ -259,6 +279,12 @@ section.
259Disable garbage collection of unused sections.279Disable garbage collection of unused sections.
260.It Fl -no-gnu-unique280.It Fl -no-gnu-unique
261Disable STB_GNU_UNIQUE symbol binding.281Disable STB_GNU_UNIQUE symbol binding.
282.It Fl -no-merge-exidx-entries
283Disable merging .ARM.exidx entries.
284.It Fl -no-nmagic
285Page align sections.
286.It Fl -no-omagic
287Do not set the text data sections to be writable, page align sections.
262.It Fl -no-rosegment288.It Fl -no-rosegment
263Do not put read-only non-executable sections in their own segment.289Do not put read-only non-executable sections in their own segment.
264.It Fl -no-threads290.It Fl -no-threads
...@@ -267,9 +293,11 @@ Do not run the linker multi-threaded....@@ -267,9 +293,11 @@ Do not run the linker multi-threaded.
267Report version scripts that refer undefined symbols.293Report version scripts that refer undefined symbols.
268.It Fl -no-undefined294.It Fl -no-undefined
269Report unresolved symbols even if the linker is creating a shared library.295Report unresolved symbols even if the linker is creating a shared library.
296.It Fl -no-warn-symbol-ordering
297Do not warn about problems with the symbol ordering file or call graph profile.
270.It Fl -no-whole-archive298.It Fl -no-whole-archive
271Restores the default behavior of loading archive members.299Restores the default behavior of loading archive members.
272.It Fl -no-pie300.It Fl -no-pie , Fl -no-pic-executable
273Do not create a position independent executable.301Do not create a position independent executable.
274.It Fl -noinhibit-exec302.It Fl -noinhibit-exec
275Retain the executable output file whenever it is still usable.303Retain the executable output file whenever it is still usable.
...@@ -305,15 +333,62 @@ is...@@ -305,15 +333,62 @@ is
305.Cm binary ,333.Cm binary ,
306which produces output with no ELF header.334which produces output with no ELF header.
307.It Fl -omagic , Fl N335.It Fl -omagic , Fl N
308Set the text and data sections to be readable and writable.336Set the text and data sections to be readable and writable, do not page align sections, link against static libraries.
309.It Fl -opt-remarks-filename Ar file337.It Fl -opt-remarks-filename Ar file
310Write optimization remarks in YAML format to338Write optimization remarks in YAML format to
311.Ar file .339.Ar file .
340.It Fl -opt-remarks-passes Ar pass-regex
341Filter optimization remarks by only allowing the passes matching
342.Ar pass-regex .
312.It Fl -opt-remarks-with-hotness343.It Fl -opt-remarks-with-hotness
313Include hotness information in the optimization remarks file.344Include hotness information in the optimization remarks file.
345.It Fl -orphan-handling Ns = Ns Ar mode
346Control how orphan sections are handled. An orphan section is one not
347specifically mentioned in a linker script.
348.Ar mode
349may be:
350.Pp
351.Bl -tag -width 2n -compact
352.It Cm place
353Place orphan sections in suitable output sections.
354.It Cm warn
355Place orphan sections as for
356.Cm place
357and also report a warning.
358.It Cm error
359Place orphan sections as for
360.Cm place
361and also report an error.
362.El
363.Pp
364.Cm place
365is the default.
366.It Fl -pack-dyn-relocs Ns = Ns Ar format
367Pack dynamic relocations in the given format.
368.Ar format
369may be:
370.Pp
371.Bl -tag -width 2n -compact
372.It Cm none
373Don't pack. Dynamic relocations are encoded in SHT_REL(A).
374.It Cm android
375Pack dynamic relocations in SHT_ANDROID_REL(A).
376.It Cm relr
377Pack relative relocations in SHT_RELR, and the rest of dynamic relocations in SHT_REL(A).
378.It Cm android+relr
379Pack relative relocations in SHT_RELR, and the rest of dynamic relocations in SHT_ANDROID_REL(A).
380.El
381.Pp
382.Cm none
383is the default. If
384.Fl -use-android-relr-tags
385is specified, use SHT_ANDROID_RELR instead of SHT_RELR.
386.Pp
387.It Fl -pac-plt
388AArch64 only, use pointer authentication in PLT.
314.It Fl -pic-veneer389.It Fl -pic-veneer
315Always generate position independent thunks.390Always generate position independent thunks.
316.It Fl -pie391.It Fl -pie , Fl -pic-executable
317Create a position independent executable.392Create a position independent executable.
318.It Fl -print-gc-sections393.It Fl -print-gc-sections
319List removed unused sections.394List removed unused sections.
...@@ -358,6 +433,8 @@ Set...@@ -358,6 +433,8 @@ Set
358.Dv DT_SONAME433.Dv DT_SONAME
359to434to
360.Ar value .435.Ar value .
436.It Fl -sort-common
437This option is ignored for GNU compatibility.
361.It Fl -sort-section Ns = Ns Ar value438.It Fl -sort-section Ns = Ns Ar value
362Specifies sections sorting rule when linkerscript is used.439Specifies sections sorting rule when linkerscript is used.
363.It Fl -start-lib440.It Fl -start-lib
...@@ -427,11 +504,27 @@ Print the names of the input files....@@ -427,11 +504,27 @@ Print the names of the input files.
427Trace references to504Trace references to
428.Ar symbol .505.Ar symbol .
429.It Fl -undefined Ns = Ns Ar symbol , Fl u Ar symbol506.It Fl -undefined Ns = Ns Ar symbol , Fl u Ar symbol
430Force507If
431.Ar symbol508.Ar symbol
432to be an undefined symbol during linking.509is not defined after symbol resolution, and there's a static library
510that contains an object file defining the symbol, load the member
511to include the object file in the output file.
512.It Fl -undefined-glob Ns = Ns Ar pattern
513Synonym for
514.Fl -undefined ,
515except that it takes a glob pattern. In a glob pattern,
516.Cm *
517matches zero or more characters,
518.Cm ?
519matches any single character, and
520.Cm [...]
521matches the characters within brackets. All symbols that match
522a given pattern are handled as if they were given as arguments of
523.Fl -undefined .
433.It Fl -unresolved-symbols Ns = Ns Ar value524.It Fl -unresolved-symbols Ns = Ns Ar value
434Determine how to handle unresolved symbols.525Determine how to handle unresolved symbols.
526.It Fl -use-android-relr-tags
527Use SHT_ANDROID_RELR / DT_ANDROID_RELR* tags instead of SHT_RELR / DT_RELR*.
435.It Fl v528.It Fl v
436Display the version number and proceed with linking if object files are529Display the version number and proceed with linking if object files are
437specified.530specified.
...@@ -479,6 +572,14 @@ Sets the...@@ -479,6 +572,14 @@ Sets the
479.Dv DYNAMIC572.Dv DYNAMIC
480section.573section.
481Different loaders can decide how to handle this flag on their own.574Different loaders can decide how to handle this flag on their own.
575.It Cm ifunc-noplt
576Do not emit PLT entries for ifunc symbols.
577Instead, emit text relocations referencing the resolver.
578This is an experimental optimization and only suitable for standalone
579environments where text relocations do not have the usual drawbacks.
580This option must be combined with the
581.Fl z Li notext
582option.
482.It Cm initfirst583.It Cm initfirst
483Sets the584Sets the
484.Dv DF_1_INITFIRST585.Dv DF_1_INITFIRST
deps/lld/docs/missingkeyfunction.rst+16-15
...@@ -4,23 +4,24 @@ Missing Key Function...@@ -4,23 +4,24 @@ Missing Key Function
4If your build failed with a linker error something like this::4If your build failed with a linker error something like this::
55
6 foo.cc:28: error: undefined reference to 'vtable for C'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)7 the vtable symbol may be undefined because the class is missing its key function
8 (see https://lld.llvm.org/missingkeyfunction)
89
9it's likely that your class C has a key function (defined by the ABI as the first10it's likely that your class C has a key function (defined by the ABI as the first
10non-pure, non-inline, virtual method), but you haven't actually defined it.11non-pure, non-inline, virtual function), but you haven't actually defined it.
1112
12When a class has a key function, the compiler emits the vtable (and some other13When a class has a key function, the compiler emits the vtable (and some other
13things as well) only in the translation unit that defines that key function. Thus,14things as well) only in the translation unit that defines that key function. Thus,
14if you're missing the key function, you'll also be missing the vtable. If no other15if you're missing the key function, you'll also be missing the vtable. If no other
15function calls your missing method, you won't see any undefined reference errors16function calls your missing function, you won't see any undefined reference errors
16for it, but you will see undefined references to the vtable symbol.17for it, but you will see undefined references to the vtable symbol.
1718
18When a class has no non-pure, non-inline, virtual methods, there is no key19When a class has no non-pure, non-inline, virtual functions, there is no key
19method, and the compiler is forced to emit the vtable in every translation unit20function, and the compiler is forced to emit the vtable in every translation unit
20that references the class. In this case, it is emitted in a COMDAT section,21that references the class. In this case, it is emitted in a COMDAT section,
21which allows the linker to eliminate all duplicate copies. This is still22which allows the linker to eliminate all duplicate copies. This is still
22wasteful in terms of object file size and link time, so it's always advisable to23wasteful in terms of object file size and link time, so it's always advisable to
23ensure there is at least one eligible method that can serve as the key function.24ensure there is at least one eligible function that can serve as the key function.
2425
25Here are the most common mistakes that lead to this error:26Here are the most common mistakes that lead to this error:
2627
...@@ -36,8 +37,8 @@ Say you have a base class declared in a header file::...@@ -36,8 +37,8 @@ Say you have a base class declared in a header file::
36 ...37 ...
37 };38 };
3839
39Here, ``~B`` is the first non-pure, non-inline, virtual method, so it is the key40Here, ``~B`` is the first non-pure, non-inline, virtual function, so it is the key
40method. If you forget to define ``B::~B`` in your source file, the compiler will41function. If you forget to define ``B::~B`` in your source file, the compiler will
41not emit the vtable for ``B``, and you'll get an undefined reference to "vtable42not emit the vtable for ``B``, and you'll get an undefined reference to "vtable
42for B".43for B".
4344
...@@ -47,10 +48,10 @@ the first eligible key function and it's easy to forget to implement them. It's...@@ -47,10 +48,10 @@ the first eligible key function and it's easy to forget to implement them. It's
47also more likely that you won't have any direct references to the destructor, so48also more likely that you won't have any direct references to the destructor, so
48you won't see any undefined reference errors that point directly to the problem.49you won't see any undefined reference errors that point directly to the problem.
4950
50The solution in this case is to implement the missing method.51The solution in this case is to implement the missing function.
5152
52Forgetting to declare a virtual method in an abstract class as pure53Forgetting to declare a virtual function in an abstract class as pure
53-------------------------------------------------------------------54---------------------------------------------------------------------
5455
55Say you have an abstract base class declared in a header file::56Say you have an abstract base class declared in a header file::
5657
...@@ -65,18 +66,18 @@ Say you have an abstract base class declared in a header file::...@@ -65,18 +66,18 @@ Say you have an abstract base class declared in a header file::
65 };66 };
6667
67This base class is intended to be abstract, but you forgot to mark one of the68This base class is intended to be abstract, but you forgot to mark one of the
68methods pure. Here, ``A::bar``, being non-pure, is nominated as the key function,69functions pure. Here, ``A::bar``, being non-pure, is nominated as the key function,
69and as a result, the vtable for ``A`` is not emitted, because the compiler is70and as a result, the vtable for ``A`` is not emitted, because the compiler is
70waiting for a translation unit that defines ``A::bar``.71waiting for a translation unit that defines ``A::bar``.
7172
72The solution in this case is to add the missing ``= 0`` to the declaration of73The solution in this case is to add the missing ``= 0`` to the declaration of
73``A::bar``.74``A::bar``.
7475
75Key method is defined, but the linker doesn't see it76Key function is defined, but the linker doesn't see it
76----------------------------------------------------77------------------------------------------------------
7778
78It's also possible that you have defined the key function somewhere, but the79It's also possible that you have defined the key function somewhere, but the
79object file containing the definition of that method isn't being linked into80object file containing the definition of that function isn't being linked into
80your application.81your application.
8182
82The solution in this case is to check your dependencies to make sure that83The solution in this case is to check your dependencies to make sure that
deps/lld/docs/partitions.dot created+22
...@@ -0,0 +1,22 @@
1digraph G {
2 part_main [label="Main partition",shape=plaintext];
3 part1 [label="Loadable partition 1",shape=plaintext];
4 part2 [label="Loadable partition 2",shape=plaintext];
5 main [style=filled,fillcolor=lightblue];
6 f1 [style=filled,fillcolor=lightsalmon];
7 f2 [style=filled,fillcolor=palegreen];
8 f3 [style=filled,fillcolor=lightblue];
9 f4 [style=filled,fillcolor=lightsalmon];
10 f5 [style=filled,fillcolor=lightblue];
11 f6 [style=filled,fillcolor=palegreen];
12 part_main -> main;
13 main -> f3;
14 part1 -> f1;
15 f1 -> f3;
16 f1 -> f4;
17 f1 -> f5;
18 part2 -> f2;
19 f2 -> f3;
20 f2 -> f5;
21 f2 -> f6;
22}
deps/lld/docs/partitions.svg created+110
...@@ -0,0 +1,110 @@
1<?xml version="1.0" encoding="UTF-8" standalone="no"?>
2<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
3 "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
4<!-- Generated by graphviz version 2.38.0 (20140413.2041)
5 -->
6<!-- Title: G Pages: 1 -->
7<svg width="393pt" height="188pt"
8 viewBox="0.00 0.00 393.00 188.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
9<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 184)">
10<title>G</title>
11<polygon fill="white" stroke="none" points="-4,4 -4,-184 389,-184 389,4 -4,4"/>
12<!-- part_main -->
13<g id="node1" class="node"><title>part_main</title>
14<text text-anchor="middle" x="47.5" y="-158.3" font-family="Times,serif" font-size="14.00">Main partition</text>
15</g>
16<!-- main -->
17<g id="node4" class="node"><title>main</title>
18<ellipse fill="lightblue" stroke="black" cx="75.5" cy="-90" rx="28.6953" ry="18"/>
19<text text-anchor="middle" x="75.5" y="-86.3" font-family="Times,serif" font-size="14.00">main</text>
20</g>
21<!-- part_main&#45;&gt;main -->
22<g id="edge1" class="edge"><title>part_main&#45;&gt;main</title>
23<path fill="none" stroke="black" d="M54.4214,-143.697C57.6218,-135.696 61.492,-126.02 65.0381,-117.155"/>
24<polygon fill="black" stroke="black" points="68.3868,-118.207 68.8511,-107.622 61.8874,-115.607 68.3868,-118.207"/>
25</g>
26<!-- part1 -->
27<g id="node2" class="node"><title>part1</title>
28<text text-anchor="middle" x="176.5" y="-158.3" font-family="Times,serif" font-size="14.00">Loadable partition 1</text>
29</g>
30<!-- f1 -->
31<g id="node5" class="node"><title>f1</title>
32<ellipse fill="lightsalmon" stroke="black" cx="176.5" cy="-90" rx="27" ry="18"/>
33<text text-anchor="middle" x="176.5" y="-86.3" font-family="Times,serif" font-size="14.00">f1</text>
34</g>
35<!-- part1&#45;&gt;f1 -->
36<g id="edge3" class="edge"><title>part1&#45;&gt;f1</title>
37<path fill="none" stroke="black" d="M176.5,-143.697C176.5,-135.983 176.5,-126.712 176.5,-118.112"/>
38<polygon fill="black" stroke="black" points="180,-118.104 176.5,-108.104 173,-118.104 180,-118.104"/>
39</g>
40<!-- part2 -->
41<g id="node3" class="node"><title>part2</title>
42<text text-anchor="middle" x="321.5" y="-158.3" font-family="Times,serif" font-size="14.00">Loadable partition 2</text>
43</g>
44<!-- f2 -->
45<g id="node6" class="node"><title>f2</title>
46<ellipse fill="palegreen" stroke="black" cx="284.5" cy="-90" rx="27" ry="18"/>
47<text text-anchor="middle" x="284.5" y="-86.3" font-family="Times,serif" font-size="14.00">f2</text>
48</g>
49<!-- part2&#45;&gt;f2 -->
50<g id="edge7" class="edge"><title>part2&#45;&gt;f2</title>
51<path fill="none" stroke="black" d="M312.354,-143.697C307.97,-135.403 302.636,-125.311 297.813,-116.187"/>
52<polygon fill="black" stroke="black" points="300.801,-114.35 293.034,-107.145 294.612,-117.621 300.801,-114.35"/>
53</g>
54<!-- f3 -->
55<g id="node7" class="node"><title>f3</title>
56<ellipse fill="lightblue" stroke="black" cx="104.5" cy="-18" rx="27" ry="18"/>
57<text text-anchor="middle" x="104.5" y="-14.3" font-family="Times,serif" font-size="14.00">f3</text>
58</g>
59<!-- main&#45;&gt;f3 -->
60<g id="edge2" class="edge"><title>main&#45;&gt;f3</title>
61<path fill="none" stroke="black" d="M82.3726,-72.411C85.7675,-64.2164 89.9422,-54.1395 93.7473,-44.9548"/>
62<polygon fill="black" stroke="black" points="97.0828,-46.0481 97.6767,-35.4699 90.6158,-43.3689 97.0828,-46.0481"/>
63</g>
64<!-- f1&#45;&gt;f3 -->
65<g id="edge4" class="edge"><title>f1&#45;&gt;f3</title>
66<path fill="none" stroke="black" d="M161.93,-74.8345C151.75,-64.9376 137.976,-51.5462 126.469,-40.3591"/>
67<polygon fill="black" stroke="black" points="128.905,-37.8461 119.296,-33.3847 124.026,-42.865 128.905,-37.8461"/>
68</g>
69<!-- f4 -->
70<g id="node8" class="node"><title>f4</title>
71<ellipse fill="lightsalmon" stroke="black" cx="176.5" cy="-18" rx="27" ry="18"/>
72<text text-anchor="middle" x="176.5" y="-14.3" font-family="Times,serif" font-size="14.00">f4</text>
73</g>
74<!-- f1&#45;&gt;f4 -->
75<g id="edge5" class="edge"><title>f1&#45;&gt;f4</title>
76<path fill="none" stroke="black" d="M176.5,-71.6966C176.5,-63.9827 176.5,-54.7125 176.5,-46.1124"/>
77<polygon fill="black" stroke="black" points="180,-46.1043 176.5,-36.1043 173,-46.1044 180,-46.1043"/>
78</g>
79<!-- f5 -->
80<g id="node9" class="node"><title>f5</title>
81<ellipse fill="lightblue" stroke="black" cx="248.5" cy="-18" rx="27" ry="18"/>
82<text text-anchor="middle" x="248.5" y="-14.3" font-family="Times,serif" font-size="14.00">f5</text>
83</g>
84<!-- f1&#45;&gt;f5 -->
85<g id="edge6" class="edge"><title>f1&#45;&gt;f5</title>
86<path fill="none" stroke="black" d="M191.07,-74.8345C201.25,-64.9376 215.024,-51.5462 226.531,-40.3591"/>
87<polygon fill="black" stroke="black" points="228.974,-42.865 233.704,-33.3847 224.095,-37.8461 228.974,-42.865"/>
88</g>
89<!-- f2&#45;&gt;f3 -->
90<g id="edge8" class="edge"><title>f2&#45;&gt;f3</title>
91<path fill="none" stroke="black" d="M260.806,-81.0022C232.063,-71.1346 182.266,-53.5073 140.5,-36 138.683,-35.2385 136.825,-34.4358 134.957,-33.6106"/>
92<polygon fill="black" stroke="black" points="136.231,-30.3452 125.68,-29.3829 133.328,-36.7149 136.231,-30.3452"/>
93</g>
94<!-- f2&#45;&gt;f5 -->
95<g id="edge9" class="edge"><title>f2&#45;&gt;f5</title>
96<path fill="none" stroke="black" d="M276.15,-72.7646C271.788,-64.2831 266.353,-53.7144 261.459,-44.1974"/>
97<polygon fill="black" stroke="black" points="264.49,-42.4395 256.804,-35.1473 258.265,-45.6409 264.49,-42.4395"/>
98</g>
99<!-- f6 -->
100<g id="node10" class="node"><title>f6</title>
101<ellipse fill="palegreen" stroke="black" cx="320.5" cy="-18" rx="27" ry="18"/>
102<text text-anchor="middle" x="320.5" y="-14.3" font-family="Times,serif" font-size="14.00">f6</text>
103</g>
104<!-- f2&#45;&gt;f6 -->
105<g id="edge10" class="edge"><title>f2&#45;&gt;f6</title>
106<path fill="none" stroke="black" d="M292.85,-72.7646C297.212,-64.2831 302.647,-53.7144 307.541,-44.1974"/>
107<polygon fill="black" stroke="black" points="310.735,-45.6409 312.196,-35.1473 304.51,-42.4395 310.735,-45.6409"/>
108</g>
109</g>
110</svg>
deps/lld/docs/sphinx_intro.rst+2-2
...@@ -43,8 +43,8 @@ to install it using:...@@ -43,8 +43,8 @@ to install it using:
43 Use your distribution's standard package management tool to install it,43 Use your distribution's standard package management tool to install it,
44 i.e., ``apt-get install easy_install`` or ``yum install easy_install``.44 i.e., ``apt-get install easy_install`` or ``yum install easy_install``.
4545
46 Mac OS X46 macOS
47 All modern Mac OS X systems come with ``easy_install`` as part of the base47 All modern macOS systems come with ``easy_install`` as part of the base
48 system.48 system.
4949
50 Windows50 Windows
deps/lld/include/lld/Common/Args.h+14-9
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Args.h ---------------------------------------------------*- C++ -*-===//1//===- Args.h ---------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -11,6 +10,7 @@...@@ -11,6 +10,7 @@
11#define LLD_ARGS_H10#define LLD_ARGS_H
1211
13#include "lld/Common/LLVM.h"12#include "lld/Common/LLVM.h"
13#include "llvm/Support/CodeGen.h"
14#include "llvm/Support/MemoryBuffer.h"14#include "llvm/Support/MemoryBuffer.h"
15#include <vector>15#include <vector>
1616
...@@ -22,15 +22,20 @@ class InputArgList;...@@ -22,15 +22,20 @@ class InputArgList;
2222
23namespace lld {23namespace lld {
24namespace args {24namespace args {
25int getInteger(llvm::opt::InputArgList &Args, unsigned Key, int Default);
26std::vector<StringRef> getStrings(llvm::opt::InputArgList &Args, int Id);
2725
28uint64_t getZOptionValue(llvm::opt::InputArgList &Args, int Id, StringRef Key,26llvm::CodeGenOpt::Level getCGOptLevel(int optLevelLTO);
27
28int64_t getInteger(llvm::opt::InputArgList &args, unsigned key,
29 int64_t Default);
30
31std::vector<StringRef> getStrings(llvm::opt::InputArgList &args, int id);
32
33uint64_t getZOptionValue(llvm::opt::InputArgList &args, int id, StringRef key,
29 uint64_t Default);34 uint64_t Default);
3035
31std::vector<StringRef> getLines(MemoryBufferRef MB);36std::vector<StringRef> getLines(MemoryBufferRef mb);
3237
33StringRef getFilenameWithoutExe(StringRef Path);38StringRef getFilenameWithoutExe(StringRef path);
3439
35} // namespace args40} // namespace args
36} // namespace lld41} // namespace lld
deps/lld/include/lld/Common/Driver.h+13-14
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/Common/Driver.h - Linker Driver Emulator -----------------------===//1//===- lld/Common/Driver.h - Linker Driver Emulator -----------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -15,28 +14,28 @@...@@ -15,28 +14,28 @@
1514
16namespace lld {15namespace lld {
17namespace coff {16namespace coff {
18bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,17bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
19 llvm::raw_ostream &Diag = llvm::errs());18 llvm::raw_ostream &diag = llvm::errs());
20}19}
2120
22namespace mingw {21namespace mingw {
23bool link(llvm::ArrayRef<const char *> Args,22bool link(llvm::ArrayRef<const char *> args,
24 llvm::raw_ostream &Diag = llvm::errs());23 llvm::raw_ostream &diag = llvm::errs());
25}24}
2625
27namespace elf {26namespace elf {
28bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,27bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
29 llvm::raw_ostream &Diag = llvm::errs());28 llvm::raw_ostream &diag = llvm::errs());
30}29}
3130
32namespace mach_o {31namespace mach_o {
33bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,32bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
34 llvm::raw_ostream &Diag = llvm::errs());33 llvm::raw_ostream &diag = llvm::errs());
35}34}
3635
37namespace wasm {36namespace wasm {
38bool link(llvm::ArrayRef<const char *> Args, bool CanExitEarly,37bool link(llvm::ArrayRef<const char *> args, bool canExitEarly,
39 llvm::raw_ostream &Diag = llvm::errs());38 llvm::raw_ostream &diag = llvm::errs());
40}39}
41}40}
4241
deps/lld/include/lld/Common/ErrorHandler.h+49-49
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- ErrorHandler.h -------------------------------------------*- C++ -*-===//1//===- ErrorHandler.h -------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -83,74 +82,75 @@ namespace lld {...@@ -83,74 +82,75 @@ namespace lld {
8382
84class ErrorHandler {83class ErrorHandler {
85public:84public:
86 uint64_t ErrorCount = 0;85 uint64_t errorCount = 0;
87 uint64_t ErrorLimit = 20;86 uint64_t errorLimit = 20;
88 StringRef ErrorLimitExceededMsg = "too many errors emitted, stopping now";87 StringRef errorLimitExceededMsg = "too many errors emitted, stopping now";
89 StringRef LogName = "lld";88 StringRef logName = "lld";
90 llvm::raw_ostream *ErrorOS = &llvm::errs();89 llvm::raw_ostream *errorOS = &llvm::errs();
91 bool ColorDiagnostics = llvm::errs().has_colors();90 bool colorDiagnostics = llvm::errs().has_colors();
92 bool ExitEarly = true;91 bool exitEarly = true;
93 bool FatalWarnings = false;92 bool fatalWarnings = false;
94 bool Verbose = false;93 bool verbose = false;
9594 bool vsDiagnostics = false;
96 void error(const Twine &Msg);95
97 LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg);96 void error(const Twine &msg);
98 void log(const Twine &Msg);97 LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &msg);
99 void message(const Twine &Msg);98 void log(const Twine &msg);
100 void warn(const Twine &Msg);99 void message(const Twine &msg);
101100 void warn(const Twine &msg);
102 std::unique_ptr<llvm::FileOutputBuffer> OutputBuffer;101
102 std::unique_ptr<llvm::FileOutputBuffer> outputBuffer;
103103
104private:104private:
105 void print(StringRef S, raw_ostream::Colors C);105 void printHeader(StringRef s, raw_ostream::Colors c, const Twine &msg);
106};106};
107107
108/// Returns the default error handler.108/// Returns the default error handler.
109ErrorHandler &errorHandler();109ErrorHandler &errorHandler();
110110
111inline void error(const Twine &Msg) { errorHandler().error(Msg); }111inline void error(const Twine &msg) { errorHandler().error(msg); }
112inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &Msg) {112inline LLVM_ATTRIBUTE_NORETURN void fatal(const Twine &msg) {
113 errorHandler().fatal(Msg);113 errorHandler().fatal(msg);
114}114}
115inline void log(const Twine &Msg) { errorHandler().log(Msg); }115inline void log(const Twine &msg) { errorHandler().log(msg); }
116inline void message(const Twine &Msg) { errorHandler().message(Msg); }116inline void message(const Twine &msg) { errorHandler().message(msg); }
117inline void warn(const Twine &Msg) { errorHandler().warn(Msg); }117inline void warn(const Twine &msg) { errorHandler().warn(msg); }
118inline uint64_t errorCount() { return errorHandler().ErrorCount; }118inline uint64_t errorCount() { return errorHandler().errorCount; }
119119
120LLVM_ATTRIBUTE_NORETURN void exitLld(int Val);120LLVM_ATTRIBUTE_NORETURN void exitLld(int val);
121121
122void diagnosticHandler(const llvm::DiagnosticInfo &DI);122void diagnosticHandler(const llvm::DiagnosticInfo &di);
123void checkError(Error E);123void checkError(Error e);
124124
125// check functions are convenient functions to strip errors125// check functions are convenient functions to strip errors
126// from error-or-value objects.126// from error-or-value objects.
127template <class T> T check(ErrorOr<T> E) {127template <class T> T check(ErrorOr<T> e) {
128 if (auto EC = E.getError())128 if (auto ec = e.getError())
129 fatal(EC.message());129 fatal(ec.message());
130 return std::move(*E);130 return std::move(*e);
131}131}
132132
133template <class T> T check(Expected<T> E) {133template <class T> T check(Expected<T> e) {
134 if (!E)134 if (!e)
135 fatal(llvm::toString(E.takeError()));135 fatal(llvm::toString(e.takeError()));
136 return std::move(*E);136 return std::move(*e);
137}137}
138138
139template <class T>139template <class T>
140T check2(ErrorOr<T> E, llvm::function_ref<std::string()> Prefix) {140T check2(ErrorOr<T> e, llvm::function_ref<std::string()> prefix) {
141 if (auto EC = E.getError())141 if (auto ec = e.getError())
142 fatal(Prefix() + ": " + EC.message());142 fatal(prefix() + ": " + ec.message());
143 return std::move(*E);143 return std::move(*e);
144}144}
145145
146template <class T>146template <class T>
147T check2(Expected<T> E, llvm::function_ref<std::string()> Prefix) {147T check2(Expected<T> e, llvm::function_ref<std::string()> prefix) {
148 if (!E)148 if (!e)
149 fatal(Prefix() + ": " + toString(E.takeError()));149 fatal(prefix() + ": " + toString(e.takeError()));
150 return std::move(*E);150 return std::move(*e);
151}151}
152152
153inline std::string toString(const Twine &S) { return S.str(); }153inline std::string toString(const Twine &s) { return s.str(); }
154154
155// To evaluate the second argument lazily, we use C macro.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); })
deps/lld/include/lld/Common/Filesystem.h created+20
...@@ -0,0 +1,20 @@
1//===- Filesystem.h ---------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_FILESYSTEM_H
10#define LLD_FILESYSTEM_H
11
12#include "lld/Common/LLVM.h"
13#include <system_error>
14
15namespace lld {
16void unlinkAsync(StringRef path);
17std::error_code tryCreateFile(StringRef path);
18} // namespace lld
19
20#endif
deps/lld/include/lld/Common/LLVM.h+5-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===//1//===--- LLVM.h - Import various common LLVM datatypes ----------*- C++ -*-===//
2//2//
3// The LLVM Compiler Infrastructure3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -30,6 +29,7 @@ class Twine;...@@ -30,6 +29,7 @@ class Twine;
30class MemoryBuffer;29class MemoryBuffer;
31class MemoryBufferRef;30class MemoryBufferRef;
32template <typename T> class ArrayRef;31template <typename T> class ArrayRef;
32template <typename T> class MutableArrayRef;
33template <unsigned InternalLen> class SmallString;33template <unsigned InternalLen> class SmallString;
34template <typename T, unsigned N> class SmallVector;34template <typename T, unsigned N> class SmallVector;
35template <typename T> class ErrorOr;35template <typename T> class ErrorOr;
...@@ -63,6 +63,7 @@ using llvm::isa;...@@ -63,6 +63,7 @@ using llvm::isa;
6363
64// ADT's.64// ADT's.
65using llvm::ArrayRef;65using llvm::ArrayRef;
66using llvm::MutableArrayRef;
66using llvm::Error;67using llvm::Error;
67using llvm::ErrorOr;68using llvm::ErrorOr;
68using llvm::Expected;69using llvm::Expected;
deps/lld/include/lld/Common/Memory.h+12-13
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Memory.h -------------------------------------------------*- C++ -*-===//1//===- Memory.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -29,30 +28,30 @@...@@ -29,30 +28,30 @@
29namespace lld {28namespace lld {
3029
31// Use this arena if your object doesn't have a destructor.30// Use this arena if your object doesn't have a destructor.
32extern llvm::BumpPtrAllocator BAlloc;31extern llvm::BumpPtrAllocator bAlloc;
33extern llvm::StringSaver Saver;32extern llvm::StringSaver saver;
3433
35void freeArena();34void freeArena();
3635
37// These two classes are hack to keep track of all36// These two classes are hack to keep track of all
38// SpecificBumpPtrAllocator instances.37// SpecificBumpPtrAllocator instances.
39struct SpecificAllocBase {38struct SpecificAllocBase {
40 SpecificAllocBase() { Instances.push_back(this); }39 SpecificAllocBase() { instances.push_back(this); }
41 virtual ~SpecificAllocBase() = default;40 virtual ~SpecificAllocBase() = default;
42 virtual void reset() = 0;41 virtual void reset() = 0;
43 static std::vector<SpecificAllocBase *> Instances;42 static std::vector<SpecificAllocBase *> instances;
44};43};
4544
46template <class T> struct SpecificAlloc : public SpecificAllocBase {45template <class T> struct SpecificAlloc : public SpecificAllocBase {
47 void reset() override { Alloc.DestroyAll(); }46 void reset() override { alloc.DestroyAll(); }
48 llvm::SpecificBumpPtrAllocator<T> Alloc;47 llvm::SpecificBumpPtrAllocator<T> alloc;
49};48};
5049
51// Use this arena if your object has a destructor.50// Use this arena if your object has a destructor.
52// Your destructor will be invoked from freeArena().51// Your destructor will be invoked from freeArena().
53template <typename T, typename... U> T *make(U &&... Args) {52template <typename T, typename... U> T *make(U &&... args) {
54 static SpecificAlloc<T> Alloc;53 static SpecificAlloc<T> alloc;
55 return new (Alloc.Alloc.Allocate()) T(std::forward<U>(Args)...);54 return new (alloc.alloc.Allocate()) T(std::forward<U>(args)...);
56}55}
5756
58} // namespace lld57} // namespace lld
deps/lld/include/lld/Common/Reproduce.h+6-11
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Reproduce.h - Utilities for creating reproducers ---------*- C++ -*-===//1//===- Reproduce.h - Utilities for creating reproducers ---------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -23,17 +22,13 @@ namespace lld {...@@ -23,17 +22,13 @@ namespace lld {
23// Makes a given pathname an absolute path first, and then remove22// Makes a given pathname an absolute path first, and then remove
24// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",23// beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
25// assuming that the current directory is "/home/john/bar".24// assuming that the current directory is "/home/john/bar".
26std::string relativeToRoot(StringRef Path);25std::string relativeToRoot(StringRef path);
2726
28// Quote a given string if it contains a space character.27// Quote a given string if it contains a space character.
29std::string quote(StringRef S);28std::string quote(StringRef s);
30
31// Rewrite the given path if a file exists with that pathname, otherwise
32// returns the original path.
33std::string rewritePath(StringRef S);
3429
35// Returns the string form of the given argument.30// Returns the string form of the given argument.
36std::string toString(const llvm::opt::Arg &Arg);31std::string toString(const llvm::opt::Arg &arg);
37}32}
3833
39#endif34#endif
deps/lld/include/lld/Common/Strings.h+11-12
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Strings.h ------------------------------------------------*- C++ -*-===//1//===- Strings.h ------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -20,25 +19,25 @@...@@ -20,25 +19,25 @@
20namespace lld {19namespace lld {
21// Returns a demangled C++ symbol name. If Name is not a mangled20// Returns a demangled C++ symbol name. If Name is not a mangled
22// name, it returns Optional::None.21// name, it returns Optional::None.
23llvm::Optional<std::string> demangleItanium(llvm::StringRef Name);22llvm::Optional<std::string> demangleItanium(llvm::StringRef name);
24llvm::Optional<std::string> demangleMSVC(llvm::StringRef S);23llvm::Optional<std::string> demangleMSVC(llvm::StringRef s);
2524
26std::vector<uint8_t> parseHex(llvm::StringRef S);25std::vector<uint8_t> parseHex(llvm::StringRef s);
27bool isValidCIdentifier(llvm::StringRef S);26bool isValidCIdentifier(llvm::StringRef s);
2827
29// Write the contents of the a buffer to a file28// Write the contents of the a buffer to a file
30void saveBuffer(llvm::StringRef Buffer, const llvm::Twine &Path);29void saveBuffer(llvm::StringRef buffer, const llvm::Twine &path);
3130
32// This class represents multiple glob patterns.31// This class represents multiple glob patterns.
33class StringMatcher {32class StringMatcher {
34public:33public:
35 StringMatcher() = default;34 StringMatcher() = default;
36 explicit StringMatcher(llvm::ArrayRef<llvm::StringRef> Pat);35 explicit StringMatcher(llvm::ArrayRef<llvm::StringRef> pat);
3736
38 bool match(llvm::StringRef S) const;37 bool match(llvm::StringRef s) const;
3938
40private:39private:
41 std::vector<llvm::GlobPattern> Patterns;40 std::vector<llvm::GlobPattern> patterns;
42};41};
4342
44} // namespace lld43} // namespace lld
deps/lld/include/lld/Common/TargetOptionsCommandFlags.h+7-8
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===-- TargetOptionsCommandFlags.h ----------------------------*- C++ -*-===//1//===-- TargetOptionsCommandFlags.h ----------------------------*- C++ -*-===//
2//2//
3// The LLVM Compiler Infrastructure3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -16,8 +15,8 @@...@@ -16,8 +15,8 @@
16#include "llvm/Target/TargetOptions.h"15#include "llvm/Target/TargetOptions.h"
1716
18namespace lld {17namespace lld {
19llvm::TargetOptions InitTargetOptionsFromCodeGenFlags();18llvm::TargetOptions initTargetOptionsFromCodeGenFlags();
20llvm::Optional<llvm::CodeModel::Model> GetCodeModelFromCMModel();19llvm::Optional<llvm::CodeModel::Model> getCodeModelFromCMModel();
21std::string GetCPUStr();20std::string getCPUStr();
22std::vector<std::string> GetMAttrs();21std::vector<std::string> getMAttrs();
23}22}
deps/lld/include/lld/Common/Threads.h+20-14
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Threads.h ------------------------------------------------*- C++ -*-===//1//===- Threads.h ------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -64,21 +63,28 @@...@@ -64,21 +63,28 @@
6463
65namespace lld {64namespace lld {
6665
67extern bool ThreadsEnabled;66extern bool threadsEnabled;
67
68template <typename R, class FuncTy> void parallelForEach(R &&range, FuncTy fn) {
69 if (threadsEnabled)
70 for_each(llvm::parallel::par, std::begin(range), std::end(range), fn);
71 else
72 for_each(llvm::parallel::seq, std::begin(range), std::end(range), fn);
73}
6874
69template <typename R, class FuncTy> void parallelForEach(R &&Range, FuncTy Fn) {75inline void parallelForEachN(size_t begin, size_t end,
70 if (ThreadsEnabled)76 llvm::function_ref<void(size_t)> fn) {
71 for_each(llvm::parallel::par, std::begin(Range), std::end(Range), Fn);77 if (threadsEnabled)
78 for_each_n(llvm::parallel::par, begin, end, fn);
72 else79 else
73 for_each(llvm::parallel::seq, std::begin(Range), std::end(Range), Fn);80 for_each_n(llvm::parallel::seq, begin, end, fn);
74}81}
7582
76inline void parallelForEachN(size_t Begin, size_t End,83template <typename R, class FuncTy> void parallelSort(R &&range, FuncTy fn) {
77 llvm::function_ref<void(size_t)> Fn) {84 if (threadsEnabled)
78 if (ThreadsEnabled)85 sort(llvm::parallel::par, std::begin(range), std::end(range), fn);
79 for_each_n(llvm::parallel::par, Begin, End, Fn);
80 else86 else
81 for_each_n(llvm::parallel::seq, Begin, End, Fn);87 sort(llvm::parallel::seq, std::begin(range), std::end(range), fn);
82}88}
8389
84} // namespace lld90} // namespace lld
deps/lld/include/lld/Common/Timer.h+14-15
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Timer.h ----------------------------------------------*- C++ -*-===//1//===- Timer.h ----------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -22,18 +21,18 @@ namespace lld {...@@ -22,18 +21,18 @@ namespace lld {
22class Timer;21class Timer;
2322
24struct ScopedTimer {23struct ScopedTimer {
25 explicit ScopedTimer(Timer &T);24 explicit ScopedTimer(Timer &t);
2625
27 ~ScopedTimer();26 ~ScopedTimer();
2827
29 void stop();28 void stop();
3029
31 Timer *T = nullptr;30 Timer *t = nullptr;
32};31};
3332
34class Timer {33class Timer {
35public:34public:
36 Timer(llvm::StringRef Name, Timer &Parent);35 Timer(llvm::StringRef name, Timer &parent);
3736
38 static Timer &root();37 static Timer &root();
3938
...@@ -44,14 +43,14 @@ public:...@@ -44,14 +43,14 @@ public:
44 double millis() const;43 double millis() const;
4544
46private:45private:
47 explicit Timer(llvm::StringRef Name);46 explicit Timer(llvm::StringRef name);
48 void print(int Depth, double TotalDuration, bool Recurse = true) const;47 void print(int depth, double totalDuration, bool recurse = true) const;
4948
50 std::chrono::time_point<std::chrono::high_resolution_clock> StartTime;49 std::chrono::time_point<std::chrono::high_resolution_clock> startTime;
51 std::chrono::nanoseconds Total;50 std::chrono::nanoseconds total;
52 std::vector<Timer *> Children;51 std::vector<Timer *> children;
53 std::string Name;52 std::string name;
54 Timer *Parent;53 Timer *parent;
55};54};
5655
57} // namespace lld56} // namespace lld
deps/lld/include/lld/Common/Version.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/Common/Version.h - LLD Version Number ----------------*- C++ -*-===//1//===- lld/Common/Version.h - LLD Version Number ----------------*- C++ -*-===//
2//2//
3// The LLVM Compiler Infrastructure3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
deps/lld/include/lld/Core/AbsoluteAtom.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/AbsoluteAtom.h - An absolute Atom -----------------------------===//1//===- Core/AbsoluteAtom.h - An absolute Atom -----------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/ArchiveLibraryFile.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/ArchiveLibraryFile.h - Models static library ------------------===//1//===- Core/ArchiveLibraryFile.h - Models static library ------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/Atom.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/Atom.h - A node in linking graph --------------------*- C++ -*-===//1//===- Core/Atom.h - A node in linking graph --------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/DefinedAtom.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/DefinedAtom.h - An Atom with content --------------------------===//1//===- Core/DefinedAtom.h - An Atom with content --------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/Error.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Error.h - system_error extensions for lld ----------------*- C++ -*-===//1//===- Error.h - system_error extensions for lld ----------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
deps/lld/include/lld/Core/File.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/File.h - A Container of Atoms ---------------------------------===//1//===- Core/File.h - A Container of Atoms ---------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/Instrumentation.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- include/Core/Instrumentation.h - Instrumentation API ---------------===//1//===- include/Core/Instrumentation.h - Instrumentation API ---------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9///8///
deps/lld/include/lld/Core/LinkingContext.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/Core/LinkingContext.h - Linker Target Info Interface -*- C++ -*-===//1//===- lld/Core/LinkingContext.h - Linker Target Info Interface -*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/Node.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/Core/Node.h - Input file class -----------------------*- C++ -*-===//1//===- lld/Core/Node.h - Input file class -----------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9///8///
deps/lld/include/lld/Core/Pass.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===------ Core/Pass.h - Base class for linker passes ----------*- C++ -*-===//1//===------ Core/Pass.h - Base class for linker passes ----------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/PassManager.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/Core/PassManager.h - Manage linker passes ----------------------===//1//===- lld/Core/PassManager.h - Manage linker passes ----------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/Reader.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/Core/Reader.h - Abstract File Format Reading Interface ---------===//1//===- lld/Core/Reader.h - Abstract File Format Reading Interface ---------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/Reference.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/References.h - A Reference to Another Atom ----------*- C++ -*-===//1//===- Core/References.h - A Reference to Another Atom ----------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/Resolver.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/Resolver.h - Resolves Atom References -------------------------===//1//===- Core/Resolver.h - Resolves Atom References -------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/SharedLibraryAtom.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/SharedLibraryAtom.h - A Shared Library Atom -------------------===//1//===- Core/SharedLibraryAtom.h - A Shared Library Atom -------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/SharedLibraryFile.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/SharedLibraryFile.h - Models shared libraries as Atoms --------===//1//===- Core/SharedLibraryFile.h - Models shared libraries as Atoms --------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/Simple.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/Core/Simple.h - Simple implementations of Atom and File --------===//1//===- lld/Core/Simple.h - Simple implementations of Atom and File --------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9///8///
deps/lld/include/lld/Core/SymbolTable.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/SymbolTable.h - Main Symbol Table -----------------------------===//1//===- Core/SymbolTable.h - Main Symbol Table -----------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/UndefinedAtom.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/UndefinedAtom.h - An Undefined Atom ---------------------------===//1//===- Core/UndefinedAtom.h - An Undefined Atom ---------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/Core/Writer.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/Core/Writer.h - Abstract File Format Interface -----------------===//1//===- lld/Core/Writer.h - Abstract File Format Interface -----------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/ReaderWriter/MachOLinkingContext.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/ReaderWriter/MachOLinkingContext.h -----------------------------===//1//===- lld/ReaderWriter/MachOLinkingContext.h -----------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/include/lld/ReaderWriter/YamlContext.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/ReaderWriter/YamlContext.h - object used in YAML I/O context ---===//1//===- lld/ReaderWriter/YamlContext.h - object used in YAML I/O context ---===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/Core/DefinedAtom.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- DefinedAtom.cpp ------------------------------------------*- C++ -*-===//1//===- DefinedAtom.cpp ------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/Core/Error.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Error.cpp - system_error extensions for lld --------------*- C++ -*-===//1//===- Error.cpp - system_error extensions for lld --------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/Core/File.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/File.cpp - A Container of Atoms -------------------------------===//1//===- Core/File.cpp - A Container of Atoms -------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/Core/LinkingContext.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/Core/LinkingContext.cpp - Linker Context Object Interface ------===//1//===- lib/Core/LinkingContext.cpp - Linker Context Object Interface ------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/Core/Reader.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/Core/Reader.cpp ------------------------------------------------===//1//===- lib/Core/Reader.cpp ------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/Core/Resolver.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/Resolver.cpp - Resolves Atom References -----------------------===//1//===- Core/Resolver.cpp - Resolves Atom References -----------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/Core/SymbolTable.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Core/SymbolTable.cpp - Main Symbol Table ---------------------------===//1//===- Core/SymbolTable.cpp - Main Symbol Table ---------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/Core/Writer.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/Core/Writer.cpp ------------------------------------------------===//1//===- lib/Core/Writer.cpp ------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/Driver/DarwinLdDriver.cpp+15-16
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/Driver/DarwinLdDriver.cpp --------------------------------------===//1//===- lib/Driver/DarwinLdDriver.cpp --------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9///8///
...@@ -334,8 +333,8 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) {...@@ -334,8 +333,8 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) {
334 Twine(unknownArg->getAsString(parsedArgs)));333 Twine(unknownArg->getAsString(parsedArgs)));
335 }334 }
336335
337 errorHandler().Verbose = parsedArgs.hasArg(OPT_v);336 errorHandler().verbose = parsedArgs.hasArg(OPT_v);
338 errorHandler().ErrorLimit = args::getInteger(parsedArgs, OPT_error_limit, 20);337 errorHandler().errorLimit = args::getInteger(parsedArgs, OPT_error_limit, 20);
339338
340 // Figure out output kind ( -dylib, -r, -bundle, -preload, or -static )339 // Figure out output kind ( -dylib, -r, -bundle, -preload, or -static )
341 llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE;340 llvm::MachO::HeaderFileType fileType = llvm::MachO::MH_EXECUTE;
...@@ -638,7 +637,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) {...@@ -638,7 +637,7 @@ bool parse(llvm::ArrayRef<const char *> args, MachOLinkingContext &ctx) {
638637
639 // Now that we've constructed the final set of search paths, print out those638 // Now that we've constructed the final set of search paths, print out those
640 // search paths in verbose mode.639 // search paths in verbose mode.
641 if (errorHandler().Verbose) {640 if (errorHandler().verbose) {
642 message("Library search paths:");641 message("Library search paths:");
643 for (auto path : ctx.searchDirs()) {642 for (auto path : ctx.searchDirs()) {
644 message(" " + path);643 message(" " + path);
...@@ -1146,13 +1145,13 @@ static void createFiles(MachOLinkingContext &ctx, bool Implicit) {...@@ -1146,13 +1145,13 @@ static void createFiles(MachOLinkingContext &ctx, bool Implicit) {
1146/// This is where the link is actually performed.1145/// This is where the link is actually performed.
1147bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,1146bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,
1148 raw_ostream &Error) {1147 raw_ostream &Error) {
1149 errorHandler().LogName = args::getFilenameWithoutExe(args[0]);1148 errorHandler().logName = args::getFilenameWithoutExe(args[0]);
1150 errorHandler().ErrorLimitExceededMsg =1149 errorHandler().errorLimitExceededMsg =
1151 "too many errors emitted, stopping now (use "1150 "too many errors emitted, stopping now (use "
1152 "'-error-limit 0' to see all errors)";1151 "'-error-limit 0' to see all errors)";
1153 errorHandler().ErrorOS = &Error;1152 errorHandler().errorOS = &Error;
1154 errorHandler().ExitEarly = CanExitEarly;1153 errorHandler().exitEarly = CanExitEarly;
1155 errorHandler().ColorDiagnostics = Error.has_colors();1154 errorHandler().colorDiagnostics = Error.has_colors();
11561155
1157 MachOLinkingContext ctx;1156 MachOLinkingContext ctx;
1158 if (!parse(args, ctx))1157 if (!parse(args, ctx))
...@@ -1197,9 +1196,9 @@ bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,...@@ -1197,9 +1196,9 @@ bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,
1197 if (auto ec = pm.runOnFile(*merged)) {1196 if (auto ec = pm.runOnFile(*merged)) {
1198 // FIXME: This should be passed to logAllUnhandledErrors but it needs1197 // FIXME: This should be passed to logAllUnhandledErrors but it needs
1199 // to be passed a Twine instead of a string.1198 // to be passed a Twine instead of a string.
1200 *errorHandler().ErrorOS << "Failed to run passes on file '"1199 *errorHandler().errorOS << "Failed to run passes on file '"
1201 << ctx.outputPath() << "': ";1200 << ctx.outputPath() << "': ";
1202 logAllUnhandledErrors(std::move(ec), *errorHandler().ErrorOS,1201 logAllUnhandledErrors(std::move(ec), *errorHandler().errorOS,
1203 std::string());1202 std::string());
1204 return false;1203 return false;
1205 }1204 }
...@@ -1211,9 +1210,9 @@ bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,...@@ -1211,9 +1210,9 @@ bool link(llvm::ArrayRef<const char *> args, bool CanExitEarly,
1211 if (auto ec = ctx.writeFile(*merged)) {1210 if (auto ec = ctx.writeFile(*merged)) {
1212 // FIXME: This should be passed to logAllUnhandledErrors but it needs1211 // FIXME: This should be passed to logAllUnhandledErrors but it needs
1213 // to be passed a Twine instead of a string.1212 // to be passed a Twine instead of a string.
1214 *errorHandler().ErrorOS << "Failed to write file '" << ctx.outputPath()1213 *errorHandler().errorOS << "Failed to write file '" << ctx.outputPath()
1215 << "': ";1214 << "': ";
1216 logAllUnhandledErrors(std::move(ec), *errorHandler().ErrorOS,1215 logAllUnhandledErrors(std::move(ec), *errorHandler().errorOS,
1217 std::string());1216 std::string());
1218 return false;1217 return false;
1219 }1218 }
deps/lld/lib/ReaderWriter/FileArchive.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/FileArchive.cpp -----------------------------------===//1//===- lib/ReaderWriter/FileArchive.cpp -----------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/ArchHandler.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/FileFormat/MachO/ArchHandler.cpp -------------------------------===//1//===- lib/FileFormat/MachO/ArchHandler.cpp -------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/ArchHandler.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/FileFormat/MachO/ArchHandler.h ---------------------------------===//1//===- lib/FileFormat/MachO/ArchHandler.h ---------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/ArchHandler_arm.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/FileFormat/MachO/ArchHandler_arm.cpp ---------------------------===//1//===- lib/FileFormat/MachO/ArchHandler_arm.cpp ---------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/ArchHandler_arm64.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/FileFormat/MachO/ArchHandler_arm64.cpp -------------------------===//1//===- lib/FileFormat/MachO/ArchHandler_arm64.cpp -------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/FileFormat/MachO/ArchHandler_x86.cpp ---------------------------===//1//===- lib/FileFormat/MachO/ArchHandler_x86.cpp ---------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/ArchHandler_x86_64.cpp+4-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/FileFormat/MachO/ArchHandler_x86_64.cpp ------------------------===//1//===- lib/FileFormat/MachO/ArchHandler_x86_64.cpp ------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -622,6 +621,7 @@ void ArchHandler_x86_64::applyFixupFinal(...@@ -622,6 +621,7 @@ void ArchHandler_x86_64::applyFixupFinal(
622 // Fall into llvm_unreachable().621 // Fall into llvm_unreachable().
623 break;622 break;
624 }623 }
624 llvm_unreachable("invalid x86_64 Reference Kind");
625}625}
626626
627void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,627void ArchHandler_x86_64::applyFixupRelocatable(const Reference &ref,
deps/lld/lib/ReaderWriter/MachO/Atoms.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/Atoms.h ---------------------------*- C++ -*-===//1//===- lib/ReaderWriter/MachO/Atoms.h ---------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/CompactUnwindPass.cpp+7-12
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/CompactUnwindPass.cpp -------------*- C++ -*-===//1//===- lib/ReaderWriter/MachO/CompactUnwindPass.cpp -------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9///8///
...@@ -388,12 +387,9 @@ private:...@@ -388,12 +387,9 @@ private:
388387
389 // Gather the personality functions now, so that they're in deterministic388 // Gather the personality functions now, so that they're in deterministic
390 // order (derived from the DefinedAtom order).389 // order (derived from the DefinedAtom order).
391 if (unwindEntry.personalityFunction) {390 if (unwindEntry.personalityFunction &&
392 auto pFunc = std::find(personalities.begin(), personalities.end(),391 !llvm::count(personalities, unwindEntry.personalityFunction))
393 unwindEntry.personalityFunction);392 personalities.push_back(unwindEntry.personalityFunction);
394 if (pFunc == personalities.end())
395 personalities.push_back(unwindEntry.personalityFunction);
396 }
397 }393 }
398 }394 }
399395
...@@ -552,8 +548,7 @@ private:...@@ -552,8 +548,7 @@ private:
552 }548 }
553 }549 }
554550
555 auto personality = std::find(personalities.begin(), personalities.end(),551 auto personality = llvm::find(personalities, entry.personalityFunction);
556 entry.personalityFunction);
557 uint32_t personalityIdx = personality == personalities.end()552 uint32_t personalityIdx = personality == personalities.end()
558 ? 0553 ? 0
559 : personality - personalities.begin() + 1;554 : personality - personalities.begin() + 1;
deps/lld/lib/ReaderWriter/MachO/DebugInfo.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//1//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/ExecutableAtoms.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/ExecutableAtoms.h ---------------------------===//1//===- lib/ReaderWriter/MachO/ExecutableAtoms.h ---------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/File.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//1//===- lib/ReaderWriter/MachO/File.h ----------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/FlatNamespaceFile.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/FlatNamespaceFile.h -------------------------===//1//===- lib/ReaderWriter/MachO/FlatNamespaceFile.h -------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/GOTPass.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/GOTPass.cpp -----------------------*- C++ -*-===//1//===- lib/ReaderWriter/MachO/GOTPass.cpp -----------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9///8///
deps/lld/lib/ReaderWriter/MachO/LayoutPass.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===-- ReaderWriter/MachO/LayoutPass.cpp - Layout atoms ------------------===//1//===-- ReaderWriter/MachO/LayoutPass.cpp - Layout atoms ------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/LayoutPass.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===------ lib/ReaderWriter/MachO/LayoutPass.h - Handles Layout of atoms -===//1//===------ lib/ReaderWriter/MachO/LayoutPass.h - Handles Layout of atoms -===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/MachOLinkingContext.cpp+8-11
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/MachOLinkingContext.cpp ---------------------===//1//===- lib/ReaderWriter/MachO/MachOLinkingContext.cpp ---------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -768,8 +767,7 @@ void MachOLinkingContext::registerDylib(MachODylibFile *dylib,...@@ -768,8 +767,7 @@ void MachOLinkingContext::registerDylib(MachODylibFile *dylib,
768 bool upward) const {767 bool upward) const {
769 std::lock_guard<std::mutex> lock(_dylibsMutex);768 std::lock_guard<std::mutex> lock(_dylibsMutex);
770769
771 if (std::find(_allDylibs.begin(),770 if (!llvm::count(_allDylibs, dylib))
772 _allDylibs.end(), dylib) == _allDylibs.end())
773 _allDylibs.push_back(dylib);771 _allDylibs.push_back(dylib);
774 _pathToDylibMap[dylib->installName()] = dylib;772 _pathToDylibMap[dylib->installName()] = dylib;
775 // If path is different than install name, register path too.773 // If path is different than install name, register path too.
...@@ -1016,11 +1014,10 @@ static bool isLibrary(const std::unique_ptr<Node> &elem) {...@@ -1016,11 +1014,10 @@ static bool isLibrary(const std::unique_ptr<Node> &elem) {
1016// new undefines from libraries.1014// new undefines from libraries.
1017void MachOLinkingContext::finalizeInputFiles() {1015void MachOLinkingContext::finalizeInputFiles() {
1018 std::vector<std::unique_ptr<Node>> &elements = getNodes();1016 std::vector<std::unique_ptr<Node>> &elements = getNodes();
1019 std::stable_sort(elements.begin(), elements.end(),1017 llvm::stable_sort(elements, [](const std::unique_ptr<Node> &a,
1020 [](const std::unique_ptr<Node> &a,1018 const std::unique_ptr<Node> &b) {
1021 const std::unique_ptr<Node> &b) {1019 return !isLibrary(a) && isLibrary(b);
1022 return !isLibrary(a) && isLibrary(b);1020 });
1023 });
1024 size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary);1021 size_t numLibs = std::count_if(elements.begin(), elements.end(), isLibrary);
1025 elements.push_back(llvm::make_unique<GroupEnd>(numLibs));1022 elements.push_back(llvm::make_unique<GroupEnd>(numLibs));
1026}1023}
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFile.h+5-5
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/MachONormalizedFile.h -----------------------===//1//===- lib/ReaderWriter/MachO/MachONormalizedFile.h -----------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -288,7 +287,8 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,...@@ -288,7 +287,8 @@ readBinary(std::unique_ptr<MemoryBuffer> &mb,
288/// Takes in-memory normalized view and writes a mach-o object file.287/// Takes in-memory normalized view and writes a mach-o object file.
289llvm::Error writeBinary(const NormalizedFile &file, StringRef path);288llvm::Error writeBinary(const NormalizedFile &file, StringRef path);
290289
291size_t headerAndLoadCommandsSize(const NormalizedFile &file);290size_t headerAndLoadCommandsSize(const NormalizedFile &file,
291 bool includeFunctionStarts);
292292
293293
294/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.294/// Parses a yaml encoded mach-o file to produce an in-memory normalized view.
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp ---------===//1//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryReader.cpp ---------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h ------------===//1//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryUtils.h ------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp+20-14
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp ---------===//1//===- lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp ---------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -109,7 +108,7 @@ private:...@@ -109,7 +108,7 @@ private:
109class MachOFileLayout {108class MachOFileLayout {
110public:109public:
111 /// All layout computation is done in the constructor.110 /// All layout computation is done in the constructor.
112 MachOFileLayout(const NormalizedFile &file);111 MachOFileLayout(const NormalizedFile &file, bool alwaysIncludeFunctionStarts);
113112
114 /// Returns the final file size as computed in the constructor.113 /// Returns the final file size as computed in the constructor.
115 size_t size() const;114 size_t size() const;
...@@ -123,7 +122,8 @@ public:...@@ -123,7 +122,8 @@ public:
123 llvm::Error writeBinary(StringRef path);122 llvm::Error writeBinary(StringRef path);
124123
125private:124private:
126 uint32_t loadCommandsSize(uint32_t &count);125 uint32_t loadCommandsSize(uint32_t &count,
126 bool alwaysIncludeFunctionStarts);
127 void buildFileOffsets();127 void buildFileOffsets();
128 void writeMachHeader();128 void writeMachHeader();
129 llvm::Error writeLoadCommands();129 llvm::Error writeLoadCommands();
...@@ -232,8 +232,9 @@ private:...@@ -232,8 +232,9 @@ private:
232 ByteBuffer _exportTrie;232 ByteBuffer _exportTrie;
233};233};
234234
235size_t headerAndLoadCommandsSize(const NormalizedFile &file) {235size_t headerAndLoadCommandsSize(const NormalizedFile &file,
236 MachOFileLayout layout(file);236 bool includeFunctionStarts) {
237 MachOFileLayout layout(file, includeFunctionStarts);
237 return layout.headerAndLoadCommandsSize();238 return layout.headerAndLoadCommandsSize();
238}239}
239240
...@@ -250,7 +251,8 @@ size_t MachOFileLayout::headerAndLoadCommandsSize() const {...@@ -250,7 +251,8 @@ size_t MachOFileLayout::headerAndLoadCommandsSize() const {
250 return _endOfLoadCommands;251 return _endOfLoadCommands;
251}252}
252253
253MachOFileLayout::MachOFileLayout(const NormalizedFile &file)254MachOFileLayout::MachOFileLayout(const NormalizedFile &file,
255 bool alwaysIncludeFunctionStarts)
254 : _file(file),256 : _file(file),
255 _is64(MachOLinkingContext::is64Bit(file.arch)),257 _is64(MachOLinkingContext::is64Bit(file.arch)),
256 _swap(!MachOLinkingContext::isHostEndian(file.arch)),258 _swap(!MachOLinkingContext::isHostEndian(file.arch)),
...@@ -271,7 +273,7 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)...@@ -271,7 +273,7 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
271 _endOfLoadCommands += sizeof(version_min_command);273 _endOfLoadCommands += sizeof(version_min_command);
272 _countOfLoadCommands++;274 _countOfLoadCommands++;
273 }275 }
274 if (!_file.functionStarts.empty()) {276 if (!_file.functionStarts.empty() || alwaysIncludeFunctionStarts) {
275 _endOfLoadCommands += sizeof(linkedit_data_command);277 _endOfLoadCommands += sizeof(linkedit_data_command);
276 _countOfLoadCommands++;278 _countOfLoadCommands++;
277 }279 }
...@@ -326,7 +328,8 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)...@@ -326,7 +328,8 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
326 } else {328 } else {
327 // Final linked images have one load command per segment.329 // Final linked images have one load command per segment.
328 _endOfLoadCommands = _startOfLoadCommands330 _endOfLoadCommands = _startOfLoadCommands
329 + loadCommandsSize(_countOfLoadCommands);331 + loadCommandsSize(_countOfLoadCommands,
332 alwaysIncludeFunctionStarts);
330333
331 // Assign section file offsets.334 // Assign section file offsets.
332 buildFileOffsets();335 buildFileOffsets();
...@@ -375,7 +378,8 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)...@@ -375,7 +378,8 @@ MachOFileLayout::MachOFileLayout(const NormalizedFile &file)
375 }378 }
376}379}
377380
378uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {381uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count,
382 bool alwaysIncludeFunctionStarts) {
379 uint32_t size = 0;383 uint32_t size = 0;
380 count = 0;384 count = 0;
381385
...@@ -445,7 +449,7 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {...@@ -445,7 +449,7 @@ uint32_t MachOFileLayout::loadCommandsSize(uint32_t &count) {
445 }449 }
446450
447 // Add LC_FUNCTION_STARTS if needed451 // Add LC_FUNCTION_STARTS if needed
448 if (!_file.functionStarts.empty()) {452 if (!_file.functionStarts.empty() || alwaysIncludeFunctionStarts) {
449 size += sizeof(linkedit_data_command);453 size += sizeof(linkedit_data_command);
450 ++count;454 ++count;
451 }455 }
...@@ -1007,6 +1011,7 @@ llvm::Error MachOFileLayout::writeLoadCommands() {...@@ -1007,6 +1011,7 @@ llvm::Error MachOFileLayout::writeLoadCommands() {
1007 lc += sizeof(linkedit_data_command);1011 lc += sizeof(linkedit_data_command);
1008 }1012 }
1009 }1013 }
1014 assert(lc == &_buffer[_endOfLoadCommands]);
1010 return llvm::Error::success();1015 return llvm::Error::success();
1011}1016}
10121017
...@@ -1018,6 +1023,7 @@ void MachOFileLayout::writeSectionContent() {...@@ -1018,6 +1023,7 @@ void MachOFileLayout::writeSectionContent() {
1018 if (s.content.empty())1023 if (s.content.empty())
1019 continue;1024 continue;
1020 uint32_t offset = _sectInfo[&s].fileOffset;1025 uint32_t offset = _sectInfo[&s].fileOffset;
1026 assert(offset >= _endOfLoadCommands);
1021 uint8_t *p = &_buffer[offset];1027 uint8_t *p = &_buffer[offset];
1022 memcpy(p, &s.content[0], s.content.size());1028 memcpy(p, &s.content[0], s.content.size());
1023 p += s.content.size();1029 p += s.content.size();
...@@ -1543,7 +1549,7 @@ llvm::Error MachOFileLayout::writeBinary(StringRef path) {...@@ -1543,7 +1549,7 @@ llvm::Error MachOFileLayout::writeBinary(StringRef path) {
15431549
1544/// Takes in-memory normalized view and writes a mach-o object file.1550/// Takes in-memory normalized view and writes a mach-o object file.
1545llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {1551llvm::Error writeBinary(const NormalizedFile &file, StringRef path) {
1546 MachOFileLayout layout(file);1552 MachOFileLayout layout(file, false);
1547 return layout.writeBinary(path);1553 return layout.writeBinary(path);
1548}1554}
15491555
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp+5-5
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp ------------===//1//===- lib/ReaderWriter/MachO/MachONormalizedFileFromAtoms.cpp ------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -588,7 +587,8 @@ void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,...@@ -588,7 +587,8 @@ void Util::layoutSectionsInTextSegment(size_t hlcSize, SegmentInfo *seg,
588587
589void Util::assignAddressesToSections(const NormalizedFile &file) {588void Util::assignAddressesToSections(const NormalizedFile &file) {
590 // NOTE!: Keep this in sync with organizeSections.589 // NOTE!: Keep this in sync with organizeSections.
591 size_t hlcSize = headerAndLoadCommandsSize(file);590 size_t hlcSize = headerAndLoadCommandsSize(file,
591 _ctx.generateFunctionStartsLoadCommand());
592 uint64_t address = 0;592 uint64_t address = 0;
593 for (SegmentInfo *seg : _segmentInfos) {593 for (SegmentInfo *seg : _segmentInfos) {
594 if (seg->name.equals("__PAGEZERO")) {594 if (seg->name.equals("__PAGEZERO")) {
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --------------===//1//===- lib/ReaderWriter/MachO/MachONormalizedFileToAtoms.cpp --------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp -----------------===//1//===- lib/ReaderWriter/MachO/MachONormalizedFileYAML.cpp -----------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/MachOPasses.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/MachOPasses.h -------------------------------===//1//===- lib/ReaderWriter/MachO/MachOPasses.h -------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/ObjCPass.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/ObjCPass.cpp -------------------------------===//1//===- lib/ReaderWriter/MachO/ObjCPass.cpp -------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
deps/lld/lib/ReaderWriter/MachO/SectCreateFile.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===---- lib/ReaderWriter/MachO/SectCreateFile.h ---------------*- c++ -*-===//1//===---- lib/ReaderWriter/MachO/SectCreateFile.h ---------------*- c++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/MachO/ShimPass.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/ShimPass.cpp -------------------------------===//1//===- lib/ReaderWriter/MachO/ShimPass.cpp -------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
deps/lld/lib/ReaderWriter/MachO/StubsPass.cpp+5-7
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/StubsPass.cpp ---------------------*- C++ -*-===//1//===- lib/ReaderWriter/MachO/StubsPass.cpp ---------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -271,9 +270,8 @@ public:...@@ -271,9 +270,8 @@ public:
271 mergedFile.addAtom(*helperCacheNLPAtom);270 mergedFile.addAtom(*helperCacheNLPAtom);
272271
273 // Add reference to dyld_stub_binder in libSystem.dylib272 // Add reference to dyld_stub_binder in libSystem.dylib
274 auto I = std::find_if(273 auto I = llvm::find_if(
275 mergedFile.sharedLibrary().begin(), mergedFile.sharedLibrary().end(),274 mergedFile.sharedLibrary(), [&](const SharedLibraryAtom *atom) {
276 [&](const SharedLibraryAtom *atom) {
277 return atom->name().equals(_stubInfo.binderSymbolName);275 return atom->name().equals(_stubInfo.binderSymbolName);
278 });276 });
279 assert(I != mergedFile.sharedLibrary().end() &&277 assert(I != mergedFile.sharedLibrary().end() &&
deps/lld/lib/ReaderWriter/MachO/TLVPass.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/TLVPass.cpp -----------------------*- C++ -*-===//1//===- lib/ReaderWriter/MachO/TLVPass.cpp -----------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9///8///
deps/lld/lib/ReaderWriter/MachO/WriterMachO.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/MachO/WriterMachO.cpp -----------------------------===//1//===- lib/ReaderWriter/MachO/WriterMachO.cpp -----------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/lib/ReaderWriter/YAML/ReaderWriterYAML.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lib/ReaderWriter/YAML/ReaderWriterYAML.cpp -------------------------===//1//===- lib/ReaderWriter/YAML/ReaderWriterYAML.cpp -------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/test/CMakeLists.txt+5-3
...@@ -14,7 +14,9 @@ if(LLD_BUILT_STANDALONE)...@@ -14,7 +14,9 @@ if(LLD_BUILT_STANDALONE)
14endif()14endif()
1515
16llvm_canonicalize_cmake_booleans(16llvm_canonicalize_cmake_booleans(
17 HAVE_LIBZ)17 HAVE_LIBZ
18 LLVM_LIBXML2_ENABLED
19 )
1820
19configure_lit_site_cfg(21configure_lit_site_cfg(
20 ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in22 ${CMAKE_CURRENT_SOURCE_DIR}/lit.site.cfg.py.in
...@@ -32,8 +34,8 @@ configure_lit_site_cfg(...@@ -32,8 +34,8 @@ configure_lit_site_cfg(
32set(LLD_TEST_DEPS lld)34set(LLD_TEST_DEPS lld)
33if (NOT LLD_BUILT_STANDALONE)35if (NOT LLD_BUILT_STANDALONE)
34 list(APPEND LLD_TEST_DEPS36 list(APPEND LLD_TEST_DEPS
35 FileCheck count llc llvm-ar llvm-as llvm-bcanalyzer llvm-config llvm-dis37 FileCheck count llc llvm-ar llvm-as llvm-bcanalyzer llvm-config llvm-cvtres
36 llvm-dwarfdump llvm-lib llvm-mc llvm-nm llvm-objcopy llvm-objdump38 llvm-dis llvm-dwarfdump llvm-lib llvm-mc llvm-nm llvm-objcopy llvm-objdump
37 llvm-pdbutil llvm-readelf llvm-readobj not obj2yaml opt yaml2obj39 llvm-pdbutil llvm-readelf llvm-readobj not obj2yaml opt yaml2obj
38 )40 )
39endif()41endif()
deps/lld/test/COFF/Inputs/combined-resources-2.rc+36-36
...@@ -1,36 +1,36 @@...@@ -1,36 +1,36 @@
1#include "windows.h" 1#include "windows.h"
2 2
3LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US 3LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US
4randomdat RCDATA 4randomdat RCDATA
5{ 5{
6 "this is a random bit of data that means nothing\0", 6 "this is a random bit of data that means nothing\0",
7 0x23a9, 7 0x23a9,
8 0x140e, 8 0x140e,
9 194292, 9 194292,
10} 10}
11 11
12LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED 12LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
13randomdat RCDATA 13randomdat RCDATA
14{ 14{
15 "zhe4 shi4 yi1ge4 sui2ji1 de shu4ju4, zhe4 yi4wei4zhe shen2me\0", 15 "zhe4 shi4 yi1ge4 sui2ji1 de shu4ju4, zhe4 yi4wei4zhe shen2me\0",
16 0x23a9, 16 0x23a9,
17 0x140e, 17 0x140e,
18 194292, 18 194292,
19} 19}
20 20
21LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG 21LANGUAGE LANG_GERMAN, SUBLANG_GERMAN_LUXEMBOURG
22randomdat RCDATA 22randomdat RCDATA
23{ 23{
24 "Dies ist ein zufälliges Bit von Daten, die nichts bedeutet\0", 24 "Dies ist ein zufälliges Bit von Daten, die nichts bedeutet\0",
25 0x23a9, 25 0x23a9,
26 0x140e, 26 0x140e,
27 194292, 27 194292,
28} 28}
29 29
30LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED 30LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED
31myaccelerators ACCELERATORS 31myaccelerators ACCELERATORS
32{ 32{
33 "^C", 999, VIRTKEY, ALT 33 "^C", 999, VIRTKEY, ALT
34 "D", 1100, VIRTKEY, CONTROL, SHIFT 34 "D", 1100, VIRTKEY, CONTROL, SHIFT
35 "^R", 444, ASCII, NOINVERT 35 "^R", 444, ASCII, NOINVERT
36} 36}
deps/lld/test/COFF/Inputs/crt-dyn-initializer-order_1.yaml+15-15
...@@ -1,15 +1,15 @@...@@ -1,15 +1,15 @@
1--- !COFF 1--- !COFF
2header: 2header:
3 Machine: IMAGE_FILE_MACHINE_AMD64 3 Machine: IMAGE_FILE_MACHINE_AMD64
4 Characteristics: [ ] 4 Characteristics: [ ]
5sections: 5sections:
6 - Name: '.CRT$XCU' 6 - Name: '.CRT$XCU'
7 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] 7 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
8 Alignment: 1 8 Alignment: 1
9 SectionData: 55 9 SectionData: 55
10 - Name: '.CRT$XCU' 10 - Name: '.CRT$XCU'
11 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] 11 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
12 Alignment: 1 12 Alignment: 1
13 SectionData: 70 13 SectionData: 70
14symbols: 14symbols:
15... 15...
deps/lld/test/COFF/Inputs/crt-dyn-initializer-order_2.yaml+19-19
...@@ -1,19 +1,19 @@...@@ -1,19 +1,19 @@
1--- !COFF 1--- !COFF
2header: 2header:
3 Machine: IMAGE_FILE_MACHINE_AMD64 3 Machine: IMAGE_FILE_MACHINE_AMD64
4 Characteristics: [ ] 4 Characteristics: [ ]
5sections: 5sections:
6 - Name: '.CRT$XCU' 6 - Name: '.CRT$XCU'
7 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] 7 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
8 Alignment: 1 8 Alignment: 1
9 SectionData: 10 9 SectionData: 10
10 - Name: '.CRT$XCU' 10 - Name: '.CRT$XCU'
11 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] 11 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
12 Alignment: 1 12 Alignment: 1
13 SectionData: 11 13 SectionData: 11
14 - Name: '.CRT$XCU' 14 - Name: '.CRT$XCU'
15 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] 15 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
16 Alignment: 1 16 Alignment: 1
17 SectionData: 12 17 SectionData: 12
18symbols: 18symbols:
19... 19...
deps/lld/test/COFF/Inputs/delayimporttables-dll1.yaml created+57
...@@ -0,0 +1,57 @@
1--- !COFF
2header:
3 Machine: IMAGE_FILE_MACHINE_AMD64
4 Characteristics: [ ]
5sections:
6 - Name: .drectve
7 Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
8 Alignment: 1
9 SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D455322202F4558504F52543A6F6E65202F4558504F52543A74776F20
10 - Name: '.text$mn'
11 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
12 Alignment: 16
13 SectionData: C20000CCCCCCCCCCCCCCCCCCCCCCCCCCC20000CCCCCCCCCCCCCCCCCCCCCCCCCC4C894424188954241048894C240833C0C3
14symbols:
15 - Name: .drectve
16 Value: 0
17 SectionNumber: 1
18 SimpleType: IMAGE_SYM_TYPE_NULL
19 ComplexType: IMAGE_SYM_DTYPE_NULL
20 StorageClass: IMAGE_SYM_CLASS_STATIC
21 SectionDefinition:
22 Length: 71
23 NumberOfRelocations: 0
24 NumberOfLinenumbers: 0
25 CheckSum: 4081356488
26 Number: 0
27 - Name: '.text$mn'
28 Value: 0
29 SectionNumber: 2
30 SimpleType: IMAGE_SYM_TYPE_NULL
31 ComplexType: IMAGE_SYM_DTYPE_NULL
32 StorageClass: IMAGE_SYM_CLASS_STATIC
33 SectionDefinition:
34 Length: 49
35 NumberOfRelocations: 0
36 NumberOfLinenumbers: 0
37 CheckSum: 405845281
38 Number: 0
39 - Name: one
40 Value: 0
41 SectionNumber: 2
42 SimpleType: IMAGE_SYM_TYPE_NULL
43 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
44 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
45 - Name: two
46 Value: 16
47 SectionNumber: 2
48 SimpleType: IMAGE_SYM_TYPE_NULL
49 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
50 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
51 - Name: DllMain
52 Value: 32
53 SectionNumber: 2
54 SimpleType: IMAGE_SYM_TYPE_NULL
55 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
56 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
57...
deps/lld/test/COFF/Inputs/delayimporttables-dll2.yaml created+57
...@@ -0,0 +1,57 @@
1--- !COFF
2header:
3 Machine: IMAGE_FILE_MACHINE_AMD64
4 Characteristics: [ ]
5sections:
6 - Name: .drectve
7 Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
8 Alignment: 1
9 SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D455322202F4558504F52543A6C656674202F4558504F52543A726967687420
10 - Name: '.text$mn'
11 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
12 Alignment: 16
13 SectionData: C20000CCCCCCCCCCCCCCCCCCCCCCCCCCC20000CCCCCCCCCCCCCCCCCCCCCCCCCC4C894424188954241048894C240833C0C3
14symbols:
15 - Name: .drectve
16 Value: 0
17 SectionNumber: 1
18 SimpleType: IMAGE_SYM_TYPE_NULL
19 ComplexType: IMAGE_SYM_DTYPE_NULL
20 StorageClass: IMAGE_SYM_CLASS_STATIC
21 SectionDefinition:
22 Length: 74
23 NumberOfRelocations: 0
24 NumberOfLinenumbers: 0
25 CheckSum: 127731413
26 Number: 0
27 - Name: '.text$mn'
28 Value: 0
29 SectionNumber: 2
30 SimpleType: IMAGE_SYM_TYPE_NULL
31 ComplexType: IMAGE_SYM_DTYPE_NULL
32 StorageClass: IMAGE_SYM_CLASS_STATIC
33 SectionDefinition:
34 Length: 49
35 NumberOfRelocations: 0
36 NumberOfLinenumbers: 0
37 CheckSum: 405845281
38 Number: 0
39 - Name: left
40 Value: 0
41 SectionNumber: 2
42 SimpleType: IMAGE_SYM_TYPE_NULL
43 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
44 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
45 - Name: right
46 Value: 16
47 SectionNumber: 2
48 SimpleType: IMAGE_SYM_TYPE_NULL
49 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
50 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
51 - Name: DllMain
52 Value: 32
53 SectionNumber: 2
54 SimpleType: IMAGE_SYM_TYPE_NULL
55 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
56 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
57...
deps/lld/test/COFF/Inputs/eh_frame_terminator-crtend.s created+3
...@@ -0,0 +1,3 @@
1 .section .eh_frame,"dr"
2__FRAME_END__:
3 .byte 3
deps/lld/test/COFF/Inputs/eh_frame_terminator-otherfunc.s created+7
...@@ -0,0 +1,7 @@
1 .text
2 .globl otherfunc
3otherfunc:
4 ret
5
6 .section .eh_frame,"dr"
7 .byte 2
deps/lld/test/COFF/Inputs/failmismatch1.ll created+15
...@@ -0,0 +1,15 @@
1; ModuleID = 'test.cpp'
2
3; Function Attrs: noinline nounwind optnone sspstrong uwtable
4define dso_local i32 @"?f@@YAHXZ"() #0 {
5 ret i32 0
6}
7
8!llvm.linker.options = !{!0}
9!llvm.module.flags = !{!1, !2}
10!llvm.ident = !{!3}
11
12!0 = !{!"/FAILIFMISMATCH:\22TEST=1\22"}
13!1 = !{i32 1, !"wchar_size", i32 2}
14!2 = !{i32 7, !"PIC Level", i32 2}
15!3 = !{!"clang version 7.0.1 (tags/RELEASE_701/final)"}
deps/lld/test/COFF/Inputs/failmismatch2.ll created+20
...@@ -0,0 +1,20 @@
1; ModuleID = 'test2.cpp'
2
3; Function Attrs: noinline norecurse nounwind optnone sspstrong uwtable
4define dso_local i32 @main() #0 {
5 %1 = alloca i32, align 4
6 store i32 0, i32* %1, align 4
7 %2 = call i32 @"?f@@YAHXZ"()
8 ret i32 %2
9}
10
11declare dso_local i32 @"?f@@YAHXZ"() #1
12
13!llvm.linker.options = !{!0}
14!llvm.module.flags = !{!1, !2}
15!llvm.ident = !{!3}
16
17!0 = !{!"/FAILIFMISMATCH:\22TEST=2\22"}
18!1 = !{i32 1, !"wchar_size", i32 2}
19!2 = !{i32 7, !"PIC Level", i32 2}
20!3 = !{!"clang version 7.0.1 (tags/RELEASE_701/final)"}
deps/lld/test/COFF/Inputs/hello32.yaml+6
...@@ -79,4 +79,10 @@ symbols:...@@ -79,4 +79,10 @@ symbols:
79 SimpleType: IMAGE_SYM_TYPE_NULL79 SimpleType: IMAGE_SYM_TYPE_NULL
80 ComplexType: IMAGE_SYM_DTYPE_FUNCTION80 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
81 StorageClass: IMAGE_SYM_CLASS_EXTERNAL81 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
82 - Name: '@feat.00'
83 Value: 1
84 SectionNumber: -1
85 SimpleType: IMAGE_SYM_TYPE_NULL
86 ComplexType: IMAGE_SYM_DTYPE_NULL
87 StorageClass: IMAGE_SYM_CLASS_STATIC
82...88...
deps/lld/test/COFF/Inputs/id.res created
Binary files /dev/null and b/deps/lld/test/COFF/Inputs/id.res differ
deps/lld/test/COFF/Inputs/id.res.o created
Binary files /dev/null and b/deps/lld/test/COFF/Inputs/id.res.o differ
deps/lld/test/COFF/Inputs/no-ipi-stream-obj.obj.yaml created+13
...@@ -0,0 +1,13 @@
1--- !COFF
2header:
3 Machine: IMAGE_FILE_MACHINE_I386
4sections:
5 - Name: '.debug$T'
6 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
7 Types:
8 - Kind: LF_TYPESERVER2
9 TypeServer2:
10 Guid: '{01234567-0123-0123-0123-0123456789AB}'
11 Age: 1
12 Name: 'no-ipi-stream-pdb.pdb'
13symbols:
deps/lld/test/COFF/Inputs/no-ipi-stream-pdb.pdb.yaml created+2
...@@ -0,0 +1,2 @@
1PdbStream:
2 Guid: '{01234567-0123-0123-0123-0123456789AB}'
deps/lld/test/COFF/Inputs/pdb-diff.cpp+10-10
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1// Build with cl: 1// Build with cl:
2// cl.exe /Z7 pdb-diff.cpp /link /debug /pdb:pdb-diff-cl.pdb 2// cl.exe /Z7 pdb-diff.cpp /link /debug /pdb:pdb-diff-cl.pdb
3// /nodefaultlib /entry:main 3// /nodefaultlib /entry:main
4// Build with lld (after running the above cl command): 4// Build with lld (after running the above cl command):
5// lld-link.exe /debug /pdb:pdb-diff-lld.pdb /nodefaultlib 5// lld-link.exe /debug /pdb:pdb-diff-lld.pdb /nodefaultlib
6// /entry:main pdb-diff.obj 6// /entry:main pdb-diff.obj
7 7
8void *__purecall = 0; 8void *__purecall = 0;
9 9
10int main() { return 42; } 10int main() { return 42; }
deps/lld/test/COFF/Inputs/pdb-file-statics-a.yaml+1
...@@ -1280,6 +1280,7 @@ sections:...@@ -1280,6 +1280,7 @@ sections:
1280 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]1280 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
1281 Alignment: 41281 Alignment: 4
1282 SectionData: ''1282 SectionData: ''
1283 SizeOfRawData: 4
1283 - Name: '.text$mn'1284 - Name: '.text$mn'
1284 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]1285 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
1285 Alignment: 41286 Alignment: 4
deps/lld/test/COFF/Inputs/pdb-file-statics-b.yaml+1
...@@ -1255,6 +1255,7 @@ sections:...@@ -1255,6 +1255,7 @@ sections:
1255 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]1255 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
1256 Alignment: 41256 Alignment: 4
1257 SectionData: ''1257 SectionData: ''
1258 SizeOfRawData: 4
1258 - Name: '.text$mn'1259 - Name: '.text$mn'
1259 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]1260 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
1260 Alignment: 41261 Alignment: 4
deps/lld/test/COFF/Inputs/pdb-global-constants-a.s created+214
...@@ -0,0 +1,214 @@
1 .text
2 .def @feat.00;
3 .scl 3;
4 .type 0;
5 .endef
6 .globl @feat.00
7.set @feat.00, 0
8 .file "t.cpp"
9 .def main;
10 .scl 2;
11 .type 32;
12 .endef
13 .globl main # -- Begin function main
14 .p2align 4, 0x90
15main: # @main
16.Lfunc_begin0:
17 .cv_func_id 0
18 .cv_file 1 "C:\\src\\testing\\t.cpp" "D28AB0CC784E17E5DF9BBB49CB629C81" 1
19 .cv_loc 0 1 4 0 # t.cpp:4:0
20.seh_proc main
21# %bb.0: # %entry
22 pushq %rax
23 .seh_stackalloc 8
24 .seh_endprologue
25 movl $0, 4(%rsp)
26.Ltmp0:
27 movl $83, %eax
28 popq %rcx
29 retq
30.Ltmp1:
31.Lfunc_end0:
32 .seh_handlerdata
33 .text
34 .seh_endproc
35 # -- End function
36 .section .debug$S,"dr"
37 .p2align 2
38 .long 4 # Debug section magic
39 .long 241
40 .long .Ltmp3-.Ltmp2 # Subsection size
41.Ltmp2:
42 .short .Ltmp5-.Ltmp4 # Record length
43.Ltmp4:
44 .short 4412 # Record kind: S_COMPILE3
45 .long 1 # Flags and language
46 .short 208 # CPUType
47 .short 9 # Frontend version
48 .short 0
49 .short 0
50 .short 0
51 .short 9000 # Backend version
52 .short 0
53 .short 0
54 .short 0
55 .asciz "clang version 9.0.0 (https://github.com/llvm/llvm-project.git ad522e17b285b1f2667163d52da5abf0968ec650)" # Null-terminated compiler version string
56 .p2align 2
57.Ltmp5:
58.Ltmp3:
59 .p2align 2
60 .long 241 # Symbol subsection for main
61 .long .Ltmp7-.Ltmp6 # Subsection size
62.Ltmp6:
63 .short .Ltmp9-.Ltmp8 # Record length
64.Ltmp8:
65 .short 4423 # Record kind: S_GPROC32_ID
66 .long 0 # PtrParent
67 .long 0 # PtrEnd
68 .long 0 # PtrNext
69 .long .Lfunc_end0-main # Code size
70 .long 0 # Offset after prologue
71 .long 0 # Offset before epilogue
72 .long 4098 # Function type index
73 .secrel32 main # Function section relative address
74 .secidx main # Function section index
75 .byte 0 # Flags
76 .asciz "main" # Function name
77 .p2align 2
78.Ltmp9:
79 .short .Ltmp11-.Ltmp10 # Record length
80.Ltmp10:
81 .short 4114 # Record kind: S_FRAMEPROC
82 .long 8 # FrameSize
83 .long 0 # Padding
84 .long 0 # Offset of padding
85 .long 0 # Bytes of callee saved registers
86 .long 0 # Exception handler offset
87 .short 0 # Exception handler section
88 .long 81920 # Flags (defines frame register)
89 .p2align 2
90.Ltmp11:
91 .short 2 # Record length
92 .short 4431 # Record kind: S_PROC_ID_END
93.Ltmp7:
94 .p2align 2
95 .cv_linetable 0, main, .Lfunc_end0
96 .long 241 # Symbol subsection for globals
97 .long .Ltmp13-.Ltmp12 # Subsection size
98.Ltmp12:
99 .short .Ltmp15-.Ltmp14 # Record length
100.Ltmp14:
101 .short 4359 # Record kind: S_CONSTANT
102 .long 4099 # Type
103 .byte 0x29, 0x00 # Value
104 .asciz "Foo" # Name
105 .p2align 2
106.Ltmp15:
107 .short .Ltmp17-.Ltmp16 # Record length
108.Ltmp16:
109 .short 4359 # Record kind: S_CONSTANT
110 .long 4099 # Type
111 .byte 0x2a, 0x00 # Value
112 .asciz "Bar" # Name
113 .p2align 2
114.Ltmp17:
115.Ltmp13:
116 .p2align 2
117 .cv_filechecksums # File index to string table offset subsection
118 .cv_stringtable # String table
119 .long 241
120 .long .Ltmp19-.Ltmp18 # Subsection size
121.Ltmp18:
122 .short .Ltmp21-.Ltmp20 # Record length
123.Ltmp20:
124 .short 4428 # Record kind: S_BUILDINFO
125 .long 4102 # LF_BUILDINFO index
126 .p2align 2
127.Ltmp21:
128.Ltmp19:
129 .p2align 2
130 .section .debug$T,"dr"
131 .p2align 2
132 .long 4 # Debug section magic
133 # ArgList (0x1000) {
134 # TypeLeafKind: LF_ARGLIST (0x1201)
135 # NumArgs: 0
136 # Arguments [
137 # ]
138 # }
139 .byte 0x06, 0x00, 0x01, 0x12
140 .byte 0x00, 0x00, 0x00, 0x00
141 # Procedure (0x1001) {
142 # TypeLeafKind: LF_PROCEDURE (0x1008)
143 # ReturnType: int (0x74)
144 # CallingConvention: NearC (0x0)
145 # FunctionOptions [ (0x0)
146 # ]
147 # NumParameters: 0
148 # ArgListType: () (0x1000)
149 # }
150 .byte 0x0e, 0x00, 0x08, 0x10
151 .byte 0x74, 0x00, 0x00, 0x00
152 .byte 0x00, 0x00, 0x00, 0x00
153 .byte 0x00, 0x10, 0x00, 0x00
154 # FuncId (0x1002) {
155 # TypeLeafKind: LF_FUNC_ID (0x1601)
156 # ParentScope: 0x0
157 # FunctionType: int () (0x1001)
158 # Name: main
159 # }
160 .byte 0x12, 0x00, 0x01, 0x16
161 .byte 0x00, 0x00, 0x00, 0x00
162 .byte 0x01, 0x10, 0x00, 0x00
163 .byte 0x6d, 0x61, 0x69, 0x6e
164 .byte 0x00, 0xf3, 0xf2, 0xf1
165 # Modifier (0x1003) {
166 # TypeLeafKind: LF_MODIFIER (0x1001)
167 # ModifiedType: int (0x74)
168 # Modifiers [ (0x1)
169 # Const (0x1)
170 # ]
171 # }
172 .byte 0x0a, 0x00, 0x01, 0x10
173 .byte 0x74, 0x00, 0x00, 0x00
174 .byte 0x01, 0x00, 0xf2, 0xf1
175 # StringId (0x1004) {
176 # TypeLeafKind: LF_STRING_ID (0x1605)
177 # Id: 0x0
178 # StringData: C:\src\testing
179 # }
180 .byte 0x16, 0x00, 0x05, 0x16
181 .byte 0x00, 0x00, 0x00, 0x00
182 .byte 0x43, 0x3a, 0x5c, 0x73
183 .byte 0x72, 0x63, 0x5c, 0x74
184 .byte 0x65, 0x73, 0x74, 0x69
185 .byte 0x6e, 0x67, 0x00, 0xf1
186 # StringId (0x1005) {
187 # TypeLeafKind: LF_STRING_ID (0x1605)
188 # Id: 0x0
189 # StringData: t.cpp
190 # }
191 .byte 0x0e, 0x00, 0x05, 0x16
192 .byte 0x00, 0x00, 0x00, 0x00
193 .byte 0x74, 0x2e, 0x63, 0x70
194 .byte 0x70, 0x00, 0xf2, 0xf1
195 # BuildInfo (0x1006) {
196 # TypeLeafKind: LF_BUILDINFO (0x1603)
197 # NumArgs: 5
198 # Arguments [
199 # ArgType: C:\src\testing (0x1004)
200 # ArgType: 0x0
201 # ArgType: t.cpp (0x1005)
202 # ArgType: 0x0
203 # ArgType: 0x0
204 # ]
205 # }
206 .byte 0x1a, 0x00, 0x03, 0x16
207 .byte 0x05, 0x00, 0x04, 0x10
208 .byte 0x00, 0x00, 0x00, 0x00
209 .byte 0x00, 0x00, 0x05, 0x10
210 .byte 0x00, 0x00, 0x00, 0x00
211 .byte 0x00, 0x00, 0x00, 0x00
212 .byte 0x00, 0x00, 0xf2, 0xf1
213
214 .addrsig
deps/lld/test/COFF/Inputs/pdb-global-constants-b.s created+204
...@@ -0,0 +1,204 @@
1 .text
2 .def @feat.00;
3 .scl 3;
4 .type 0;
5 .endef
6 .globl @feat.00
7.set @feat.00, 0
8 .file "t2.cpp"
9 .def "?foobar@@YAHXZ";
10 .scl 2;
11 .type 32;
12 .endef
13 .globl "?foobar@@YAHXZ" # -- Begin function ?foobar@@YAHXZ
14 .p2align 4, 0x90
15"?foobar@@YAHXZ": # @"?foobar@@YAHXZ"
16.Lfunc_begin0:
17 .cv_func_id 0
18# %bb.0: # %entry
19 .cv_file 1 "C:\\src\\testing\\t2.cpp" "C9D7AF07363FDE8EC16D73EC30039C5B" 1
20 .cv_loc 0 1 5 0 # t2.cpp:5:0
21 movl $84, %eax
22 retq
23.Ltmp0:
24.Lfunc_end0:
25 # -- End function
26 .section .debug$S,"dr"
27 .p2align 2
28 .long 4 # Debug section magic
29 .long 241
30 .long .Ltmp2-.Ltmp1 # Subsection size
31.Ltmp1:
32 .short .Ltmp4-.Ltmp3 # Record length
33.Ltmp3:
34 .short 4412 # Record kind: S_COMPILE3
35 .long 1 # Flags and language
36 .short 208 # CPUType
37 .short 9 # Frontend version
38 .short 0
39 .short 0
40 .short 0
41 .short 9000 # Backend version
42 .short 0
43 .short 0
44 .short 0
45 .asciz "clang version 9.0.0 (https://github.com/llvm/llvm-project.git ad522e17b285b1f2667163d52da5abf0968ec650)" # Null-terminated compiler version string
46 .p2align 2
47.Ltmp4:
48.Ltmp2:
49 .p2align 2
50 .long 241 # Symbol subsection for foobar
51 .long .Ltmp6-.Ltmp5 # Subsection size
52.Ltmp5:
53 .short .Ltmp8-.Ltmp7 # Record length
54.Ltmp7:
55 .short 4423 # Record kind: S_GPROC32_ID
56 .long 0 # PtrParent
57 .long 0 # PtrEnd
58 .long 0 # PtrNext
59 .long .Lfunc_end0-"?foobar@@YAHXZ" # Code size
60 .long 0 # Offset after prologue
61 .long 0 # Offset before epilogue
62 .long 4098 # Function type index
63 .secrel32 "?foobar@@YAHXZ" # Function section relative address
64 .secidx "?foobar@@YAHXZ" # Function section index
65 .byte 0 # Flags
66 .asciz "foobar" # Function name
67 .p2align 2
68.Ltmp8:
69 .short .Ltmp10-.Ltmp9 # Record length
70.Ltmp9:
71 .short 4114 # Record kind: S_FRAMEPROC
72 .long 0 # FrameSize
73 .long 0 # Padding
74 .long 0 # Offset of padding
75 .long 0 # Bytes of callee saved registers
76 .long 0 # Exception handler offset
77 .short 0 # Exception handler section
78 .long 0 # Flags (defines frame register)
79 .p2align 2
80.Ltmp10:
81 .short 2 # Record length
82 .short 4431 # Record kind: S_PROC_ID_END
83.Ltmp6:
84 .p2align 2
85 .cv_linetable 0, "?foobar@@YAHXZ", .Lfunc_end0
86 .long 241 # Symbol subsection for globals
87 .long .Ltmp12-.Ltmp11 # Subsection size
88.Ltmp11:
89 .short .Ltmp14-.Ltmp13 # Record length
90.Ltmp13:
91 .short 4359 # Record kind: S_CONSTANT
92 .long 4099 # Type
93 .byte 0x2a, 0x00 # Value
94 .asciz "Foo" # Name
95 .p2align 2
96.Ltmp14:
97 .short .Ltmp16-.Ltmp15 # Record length
98.Ltmp15:
99 .short 4359 # Record kind: S_CONSTANT
100 .long 4099 # Type
101 .byte 0x2a, 0x00 # Value
102 .asciz "Bar" # Name
103 .p2align 2
104.Ltmp16:
105.Ltmp12:
106 .p2align 2
107 .cv_filechecksums # File index to string table offset subsection
108 .cv_stringtable # String table
109 .long 241
110 .long .Ltmp18-.Ltmp17 # Subsection size
111.Ltmp17:
112 .short .Ltmp20-.Ltmp19 # Record length
113.Ltmp19:
114 .short 4428 # Record kind: S_BUILDINFO
115 .long 4102 # LF_BUILDINFO index
116 .p2align 2
117.Ltmp20:
118.Ltmp18:
119 .p2align 2
120 .section .debug$T,"dr"
121 .p2align 2
122 .long 4 # Debug section magic
123 # ArgList (0x1000) {
124 # TypeLeafKind: LF_ARGLIST (0x1201)
125 # NumArgs: 0
126 # Arguments [
127 # ]
128 # }
129 .byte 0x06, 0x00, 0x01, 0x12
130 .byte 0x00, 0x00, 0x00, 0x00
131 # Procedure (0x1001) {
132 # TypeLeafKind: LF_PROCEDURE (0x1008)
133 # ReturnType: int (0x74)
134 # CallingConvention: NearC (0x0)
135 # FunctionOptions [ (0x0)
136 # ]
137 # NumParameters: 0
138 # ArgListType: () (0x1000)
139 # }
140 .byte 0x0e, 0x00, 0x08, 0x10
141 .byte 0x74, 0x00, 0x00, 0x00
142 .byte 0x00, 0x00, 0x00, 0x00
143 .byte 0x00, 0x10, 0x00, 0x00
144 # FuncId (0x1002) {
145 # TypeLeafKind: LF_FUNC_ID (0x1601)
146 # ParentScope: 0x0
147 # FunctionType: int () (0x1001)
148 # Name: foobar
149 # }
150 .byte 0x12, 0x00, 0x01, 0x16
151 .byte 0x00, 0x00, 0x00, 0x00
152 .byte 0x01, 0x10, 0x00, 0x00
153 .byte 0x66, 0x6f, 0x6f, 0x62
154 .byte 0x61, 0x72, 0x00, 0xf1
155 # Modifier (0x1003) {
156 # TypeLeafKind: LF_MODIFIER (0x1001)
157 # ModifiedType: int (0x74)
158 # Modifiers [ (0x1)
159 # Const (0x1)
160 # ]
161 # }
162 .byte 0x0a, 0x00, 0x01, 0x10
163 .byte 0x74, 0x00, 0x00, 0x00
164 .byte 0x01, 0x00, 0xf2, 0xf1
165 # StringId (0x1004) {
166 # TypeLeafKind: LF_STRING_ID (0x1605)
167 # Id: 0x0
168 # StringData: C:\src\testing
169 # }
170 .byte 0x16, 0x00, 0x05, 0x16
171 .byte 0x00, 0x00, 0x00, 0x00
172 .byte 0x43, 0x3a, 0x5c, 0x73
173 .byte 0x72, 0x63, 0x5c, 0x74
174 .byte 0x65, 0x73, 0x74, 0x69
175 .byte 0x6e, 0x67, 0x00, 0xf1
176 # StringId (0x1005) {
177 # TypeLeafKind: LF_STRING_ID (0x1605)
178 # Id: 0x0
179 # StringData: t2.cpp
180 # }
181 .byte 0x0e, 0x00, 0x05, 0x16
182 .byte 0x00, 0x00, 0x00, 0x00
183 .byte 0x74, 0x32, 0x2e, 0x63
184 .byte 0x70, 0x70, 0x00, 0xf1
185 # BuildInfo (0x1006) {
186 # TypeLeafKind: LF_BUILDINFO (0x1603)
187 # NumArgs: 5
188 # Arguments [
189 # ArgType: C:\src\testing (0x1004)
190 # ArgType: 0x0
191 # ArgType: t2.cpp (0x1005)
192 # ArgType: 0x0
193 # ArgType: 0x0
194 # ]
195 # }
196 .byte 0x1a, 0x00, 0x03, 0x16
197 .byte 0x05, 0x00, 0x04, 0x10
198 .byte 0x00, 0x00, 0x00, 0x00
199 .byte 0x00, 0x00, 0x05, 0x10
200 .byte 0x00, 0x00, 0x00, 0x00
201 .byte 0x00, 0x00, 0x00, 0x00
202 .byte 0x00, 0x00, 0xf2, 0xf1
203
204 .addrsig
deps/lld/test/COFF/Inputs/pdb-globals.yaml+1-1
...@@ -70,6 +70,7 @@ sections:...@@ -70,6 +70,7 @@ sections:
70 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]70 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
71 Alignment: 471 Alignment: 4
72 SectionData: ''72 SectionData: ''
73 SizeOfRawData: 4
73 - Name: .text74 - Name: .text
74 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]75 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
75 Alignment: 1676 Alignment: 16
...@@ -263,7 +264,6 @@ sections:...@@ -263,7 +264,6 @@ sections:
263 - Name: '.debug$T'264 - Name: '.debug$T'
264 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]265 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
265 Alignment: 4266 Alignment: 4
266 SectionData: 0400000006000112000000000E000810740000000000000000100000160001160000000001100000476C6F62616C46756E6300F10A000210700400000A8000000E0001120200000074000000031000000E0008107400000000000200041000001200011600000000051000006D61696E00F3F2F13200051500008002000000000000000000000000000048656C6C6F506F696E74002E3F415548656C6C6F506F696E74404000F2F1260003120D15030074000000000058000D15030074000000040059000D1503007400000008005A0032000515030000020810000000000000000000000C0048656C6C6F506F696E74002E3F415548656C6C6F506F696E74404000F2F13E00051600000000643A5C7372635C6C6C766D2D6D6F6E6F5C6C6C645C746573745C636F66665C696E707574735C7064622D676C6F62616C732E63707000F2F10E000616091000000A100000060000000A000210071000000A8000001A00091003000000071000000C1000000B000000001000000000000016000216071000000D10000048656C6C6F506F696E7400F11600011600000000011000004C6F63616C46756E6300F2F10A000110740000000100F2F10A000210101000000A800000
267 Types:267 Types:
268 - Kind: LF_ARGLIST268 - Kind: LF_ARGLIST
269 ArgList:269 ArgList:
deps/lld/test/COFF/Inputs/pdb-type-server-invalid-path.yaml created+121
...@@ -0,0 +1,121 @@
1--- !COFF
2header:
3 Machine: IMAGE_FILE_MACHINE_AMD64
4 Characteristics: [ ]
5sections:
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: 1
73 Name: 'c:\some_invalid_path_AABB98765\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
78symbols:
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/pdb_comdat_bar.yaml+1
...@@ -190,6 +190,7 @@ sections:...@@ -190,6 +190,7 @@ sections:
190 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]190 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
191 Alignment: 4191 Alignment: 4
192 SectionData: ''192 SectionData: ''
193 SizeOfRawData: 4
193 - Name: '.text$mn'194 - Name: '.text$mn'
194 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]195 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
195 Alignment: 16196 Alignment: 16
deps/lld/test/COFF/Inputs/thinlto-empty.ll created+2
...@@ -0,0 +1,2 @@
1target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
2target triple = "x86_64-pc-windows-msvc19.0.24215"
deps/lld/test/COFF/Inputs/thinlto.ll created+6
...@@ -0,0 +1,6 @@
1target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
2target triple = "x86_64-pc-windows-msvc19.0.24215"
3
4define void @g() {
5 ret void
6}
deps/lld/test/COFF/Inputs/tlssup.s created+10
...@@ -0,0 +1,10 @@
1 .section .tls,"dw"
2 .byte 0xaa
3
4 .section .tls$ZZZ,"dw"
5 .byte 0xff
6
7 .globl _tls_index
8 .data
9_tls_index:
10 .int 0
deps/lld/test/COFF/Inputs/undefined-symbol-lto-a.ll created+82
...@@ -0,0 +1,82 @@
1; ModuleID = 't.obj'
2source_filename = "t.cpp"
3target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
4target triple = "x86_64-pc-windows-msvc19.21.27702"
5
6%struct.Init = type { %struct.S }
7%struct.S = type { i32 (...)** }
8%rtti.CompleteObjectLocator = type { i32, i32, i32, i32, i32, i32 }
9%rtti.TypeDescriptor7 = type { i8**, i8*, [8 x i8] }
10%rtti.ClassHierarchyDescriptor = type { i32, i32, i32, i32 }
11%rtti.BaseClassDescriptor = type { i32, i32, i32, i32, i32, i32, i32 }
12
13$"??_SS@@6B@" = comdat largest
14
15$"??_R4S@@6B@" = comdat any
16
17$"??_R0?AUS@@@8" = comdat any
18
19$"??_R3S@@8" = comdat any
20
21$"??_R2S@@8" = comdat any
22
23$"??_R1A@?0A@EA@S@@8" = comdat any
24
25@"?d@@3UInit@@A" = dso_local local_unnamed_addr global %struct.Init zeroinitializer, align 8
26@anon.bcb2691509de99310dddb690fcdb4cdc.0 = private unnamed_addr constant { [2 x i8*] } { [2 x i8*] [i8* bitcast (%rtti.CompleteObjectLocator* @"??_R4S@@6B@" to i8*), i8* bitcast (void (%struct.S*)* @"?foo@S@@UEAAXXZ" to i8*)] }, comdat($"??_SS@@6B@"), !type !0
27@"??_R4S@@6B@" = linkonce_odr constant %rtti.CompleteObjectLocator { i32 1, i32 0, i32 0, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUS@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3S@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.CompleteObjectLocator* @"??_R4S@@6B@" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
28@"??_7type_info@@6B@" = external constant i8*
29@"??_R0?AUS@@@8" = linkonce_odr global %rtti.TypeDescriptor7 { i8** @"??_7type_info@@6B@", i8* null, [8 x i8] c".?AUS@@\00" }, comdat
30@__ImageBase = external dso_local constant i8
31@"??_R3S@@8" = linkonce_odr constant %rtti.ClassHierarchyDescriptor { i32 0, i32 0, i32 1, i32 trunc (i64 sub nuw nsw (i64 ptrtoint ([2 x i32]* @"??_R2S@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
32@"??_R2S@@8" = linkonce_odr constant [2 x i32] [i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.BaseClassDescriptor* @"??_R1A@?0A@EA@S@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0], comdat
33@"??_R1A@?0A@EA@S@@8" = linkonce_odr constant %rtti.BaseClassDescriptor { i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.TypeDescriptor7* @"??_R0?AUS@@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32), i32 0, i32 0, i32 -1, i32 0, i32 64, i32 trunc (i64 sub nuw nsw (i64 ptrtoint (%rtti.ClassHierarchyDescriptor* @"??_R3S@@8" to i64), i64 ptrtoint (i8* @__ImageBase to i64)) to i32) }, comdat
34@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [{ i32, void ()*, i8* } { i32 65535, void ()* @_GLOBAL__sub_I_t.cpp, i8* null }]
35
36@"??_SS@@6B@" = unnamed_addr alias i8*, getelementptr inbounds ({ [2 x i8*] }, { [2 x i8*] }* @anon.bcb2691509de99310dddb690fcdb4cdc.0, i32 0, i32 0, i32 1)
37
38declare dso_local void @"?undefined_ref@@YAXXZ"() local_unnamed_addr #0
39
40declare dllimport void @"?foo@S@@UEAAXXZ"(%struct.S*) unnamed_addr #0
41
42; Function Attrs: nounwind sspstrong uwtable
43define internal void @_GLOBAL__sub_I_t.cpp() #1 {
44entry:
45 store i32 (...)** bitcast (i8** @"??_SS@@6B@" to i32 (...)**), i32 (...)*** getelementptr inbounds (%struct.Init, %struct.Init* @"?d@@3UInit@@A", i64 0, i32 0, i32 0), align 8
46 tail call void @"?undefined_ref@@YAXXZ"() #2
47 ret void
48}
49
50attributes #0 = { "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-nans-fp-math"="false" "no-signed-zeros-fp-math"="false" "no-trapping-math"="false" "stack-protector-buffer-size"="8" "target-cpu"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
51attributes #1 = { nounwind sspstrong uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "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"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
52attributes #2 = { nounwind }
53
54!llvm.linker.options = !{!1, !2}
55!llvm.module.flags = !{!3, !4, !5, !6}
56!llvm.ident = !{!7}
57
58!0 = !{i64 8, !"?AUS@@"}
59!1 = !{!"/DEFAULTLIB:libcmt.lib"}
60!2 = !{!"/DEFAULTLIB:oldnames.lib"}
61!3 = !{i32 1, !"wchar_size", i32 2}
62!4 = !{i32 7, !"PIC Level", i32 2}
63!5 = !{i32 1, !"ThinLTO", i32 0}
64!6 = !{i32 1, !"EnableSplitLTOUnit", i32 0}
65!7 = !{!"clang version 9.0.0 (git@github.com:llvm/llvm-project.git 1a285c27fdf6407ceed3398e015d00559f5f533d)"}
66
67^0 = module: (path: "t.obj", hash: (0, 0, 0, 0, 0))
68^1 = gv: (name: "__ImageBase") ; guid = 434928772013489304
69^2 = gv: (name: "??_R2S@@8", summaries: (variable: (module: ^0, flags: (linkage: linkonce_odr, notEligibleToImport: 1, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), refs: (^1, ^6)))) ; guid = 2160898732728284029
70^3 = gv: (name: "llvm.global_ctors", summaries: (variable: (module: ^0, flags: (linkage: appending, notEligibleToImport: 1, live: 1, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), refs: (^14)))) ; guid = 2412314959268824392
71^4 = gv: (name: "?foo@S@@UEAAXXZ") ; guid = 6578172636330484861
72^5 = gv: (name: "??_SS@@6B@", summaries: (alias: (module: ^0, flags: (linkage: external, notEligibleToImport: 1, live: 0, dsoLocal: 0, canAutoHide: 0), aliasee: ^10))) ; guid = 8774897714842691026
73^6 = gv: (name: "??_R1A@?0A@EA@S@@8", summaries: (variable: (module: ^0, flags: (linkage: linkonce_odr, notEligibleToImport: 1, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), refs: (^11, ^1, ^8)))) ; guid = 9397802696236423453
74^7 = gv: (name: "?undefined_ref@@YAXXZ") ; guid = 9774674600202276560
75^8 = gv: (name: "??_R3S@@8", summaries: (variable: (module: ^0, flags: (linkage: linkonce_odr, notEligibleToImport: 1, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), refs: (^1, ^2)))) ; guid = 10685958509605791599
76^9 = gv: (name: "??_7type_info@@6B@") ; guid = 10826752452437539368
77^10 = gv: (name: "anon.bcb2691509de99310dddb690fcdb4cdc.0", summaries: (variable: (module: ^0, flags: (linkage: private, notEligibleToImport: 1, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), vTableFuncs: ((virtFunc: ^4, offset: 8)), refs: (^13, ^4)))) ; guid = 11510395461204283992
78^11 = gv: (name: "??_R0?AUS@@@8", summaries: (variable: (module: ^0, flags: (linkage: linkonce_odr, notEligibleToImport: 1, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), refs: (^9)))) ; guid = 12346607659584231960
79^12 = gv: (name: "?d@@3UInit@@A", summaries: (variable: (module: ^0, flags: (linkage: external, notEligibleToImport: 1, live: 0, dsoLocal: 1, canAutoHide: 0), varFlags: (readonly: 1, writeonly: 1)))) ; guid = 14563354643524156382
80^13 = gv: (name: "??_R4S@@6B@", summaries: (variable: (module: ^0, flags: (linkage: linkonce_odr, notEligibleToImport: 1, live: 0, dsoLocal: 0, canAutoHide: 0), varFlags: (readonly: 0, writeonly: 0), refs: (^13, ^11, ^1, ^8)))) ; guid = 14703528065171087394
81^14 = gv: (name: "_GLOBAL__sub_I_t.cpp", summaries: (function: (module: ^0, flags: (linkage: internal, notEligibleToImport: 1, live: 0, dsoLocal: 1, canAutoHide: 0), insts: 3, calls: ((callee: ^7)), refs: (^12, ^5)))) ; guid = 15085897428757412588
82^15 = typeidCompatibleVTable: (name: "?AUS@@", summary: ((offset: 8, ^10))) ; guid = 13986515119763165370
deps/lld/test/COFF/Inputs/undefined-symbol-lto-b.ll created+29
...@@ -0,0 +1,29 @@
1; ModuleID = 'b.obj'
2source_filename = "b.cpp"
3target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
4target triple = "x86_64-pc-windows-msvc19.21.27702"
5
6%struct.S = type { i32 (...)** }
7
8; Function Attrs: norecurse nounwind readnone sspstrong uwtable
9define dso_local void @"?foo@S@@UEAAXXZ"(%struct.S* nocapture %this) unnamed_addr #0 align 2 {
10entry:
11 ret void
12}
13
14attributes #0 = { norecurse nounwind readnone sspstrong uwtable "correctly-rounded-divide-sqrt-fp-math"="false" "disable-tail-calls"="false" "less-precise-fpmad"="false" "min-legal-vector-width"="0" "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"="x86-64" "target-features"="+cx8,+fxsr,+mmx,+sse,+sse2,+x87" "unsafe-fp-math"="false" "use-soft-float"="false" }
15
16!llvm.linker.options = !{!0, !1}
17!llvm.module.flags = !{!2, !3, !4, !5}
18!llvm.ident = !{!6}
19
20!0 = !{!"/DEFAULTLIB:libcmt.lib"}
21!1 = !{!"/DEFAULTLIB:oldnames.lib"}
22!2 = !{i32 1, !"wchar_size", i32 2}
23!3 = !{i32 7, !"PIC Level", i32 2}
24!4 = !{i32 1, !"ThinLTO", i32 0}
25!5 = !{i32 1, !"EnableSplitLTOUnit", i32 0}
26!6 = !{!"clang version 9.0.0 (git@github.com:llvm/llvm-project.git 1a285c27fdf6407ceed3398e015d00559f5f533d)"}
27
28^0 = module: (path: "b.obj", hash: (0, 0, 0, 0, 0))
29^1 = gv: (name: "?foo@S@@UEAAXXZ", summaries: (function: (module: ^0, flags: (linkage: external, notEligibleToImport: 1, live: 0, dsoLocal: 1, canAutoHide: 0), insts: 1, funcFlags: (readNone: 1, readOnly: 0, noRecurse: 1, returnDoesNotAlias: 0, noInline: 0)))) ; guid = 6578172636330484861
deps/lld/test/COFF/allow-unknown-debug-info.test created+26
...@@ -0,0 +1,26 @@
1# RUN: yaml2obj %s > %t.obj
2# RUN: lld-link -safeseh:no /dll /noentry /debug %t.obj 2>&1 | FileCheck %s
3
4# CHECK: ignoring section .debug$S with unrecognized magic 0x1
5
6--- !COFF
7header:
8 Machine: IMAGE_FILE_MACHINE_I386
9 Characteristics: []
10sections:
11 - Name: '.debug$S'
12 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
13 SectionData: 01000000
14symbols:
15 - Name: '.debug$S'
16 Value: 0
17 SectionNumber: 1
18 SimpleType: IMAGE_SYM_TYPE_NULL
19 ComplexType: IMAGE_SYM_DTYPE_NULL
20 StorageClass: IMAGE_SYM_CLASS_STATIC
21 SectionDefinition:
22 Length: 4
23 NumberOfRelocations: 0
24 NumberOfLinenumbers: 0
25 CheckSum: 0
26 Number: 0
deps/lld/test/COFF/arm64-delayimport.yaml+27-26
...@@ -3,35 +3,36 @@...@@ -3,35 +3,36 @@
3# RUN: yaml2obj < %s > %t.obj3# 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.dll4# 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 DISASM5# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix DISASM
6# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s -check-prefix IMPORTS6# RUN: llvm-readobj --coff-imports %t.exe | FileCheck %s -check-prefix IMPORTS
77
8# DISASM: 140001014: 11 00 00 d0 adrp x17, #81928# DISASM: 140001014: 11 00 00 d0 adrp x17, #8192
9# DISASM: 140001018: 31 22 00 91 add x17, x17, #89# DISASM: 140001018: 31 22 00 91 add x17, x17, #8
10# DISASM: 14000101c: fd 7b b3 a9 stp x29, x30, [sp, #-208]!10# DISASM: 14000101c: 01 00 00 14 b #4 <.text+0x20>
11# DISASM: 140001020: fd 03 00 91 mov x29, sp11# DISASM: 140001020: fd 7b b3 a9 stp x29, x30, [sp, #-208]!
12# DISASM: 140001024: e0 07 01 a9 stp x0, x1, [sp, #16]12# DISASM: 140001024: fd 03 00 91 mov x29, sp
13# DISASM: 140001028: e2 0f 02 a9 stp x2, x3, [sp, #32]13# DISASM: 140001028: e0 07 01 a9 stp x0, x1, [sp, #16]
14# DISASM: 14000102c: e4 17 03 a9 stp x4, x5, [sp, #48]14# DISASM: 14000102c: e2 0f 02 a9 stp x2, x3, [sp, #32]
15# DISASM: 140001030: e6 1f 04 a9 stp x6, x7, [sp, #64]15# DISASM: 140001030: e4 17 03 a9 stp x4, x5, [sp, #48]
16# DISASM: 140001034: e0 87 02 ad stp q0, q1, [sp, #80]16# DISASM: 140001034: e6 1f 04 a9 stp x6, x7, [sp, #64]
17# DISASM: 140001038: e2 8f 03 ad stp q2, q3, [sp, #112]17# DISASM: 140001038: e0 87 02 ad stp q0, q1, [sp, #80]
18# DISASM: 14000103c: e4 97 04 ad stp q4, q5, [sp, #144]18# DISASM: 14000103c: e2 8f 03 ad stp q2, q3, [sp, #112]
19# DISASM: 140001040: e6 9f 05 ad stp q6, q7, [sp, #176]19# DISASM: 140001040: e4 97 04 ad stp q4, q5, [sp, #144]
20# DISASM: 140001044: e1 03 11 aa mov x1, x1720# DISASM: 140001044: e6 9f 05 ad stp q6, q7, [sp, #176]
21# DISASM: 140001048: 00 00 00 b0 adrp x0, #409621# DISASM: 140001048: e1 03 11 aa mov x1, x17
22# DISASM: 14000104c: 00 00 00 91 add x0, x0, #022# DISASM: 14000104c: 00 00 00 b0 adrp x0, #4096
23# DISASM: 140001050: ec ff ff 97 bl #-80 <.text>23# DISASM: 140001050: 00 00 00 91 add x0, x0, #0
24# DISASM: 140001054: f0 03 00 aa mov x16, x024# DISASM: 140001054: eb ff ff 97 bl #-84 <.text>
25# DISASM: 140001058: e6 9f 45 ad ldp q6, q7, [sp, #176]25# DISASM: 140001058: f0 03 00 aa mov x16, x0
26# DISASM: 14000105c: e4 97 44 ad ldp q4, q5, [sp, #144]26# DISASM: 14000105c: e6 9f 45 ad ldp q6, q7, [sp, #176]
27# DISASM: 140001060: e2 8f 43 ad ldp q2, q3, [sp, #112]27# DISASM: 140001060: e4 97 44 ad ldp q4, q5, [sp, #144]
28# DISASM: 140001064: e0 87 42 ad ldp q0, q1, [sp, #80]28# DISASM: 140001064: e2 8f 43 ad ldp q2, q3, [sp, #112]
29# DISASM: 140001068: e6 1f 44 a9 ldp x6, x7, [sp, #64]29# DISASM: 140001068: e0 87 42 ad ldp q0, q1, [sp, #80]
30# DISASM: 14000106c: e4 17 43 a9 ldp x4, x5, [sp, #48]30# DISASM: 14000106c: e6 1f 44 a9 ldp x6, x7, [sp, #64]
31# DISASM: 140001070: e2 0f 42 a9 ldp x2, x3, [sp, #32]31# DISASM: 140001070: e4 17 43 a9 ldp x4, x5, [sp, #48]
32# DISASM: 140001074: e0 07 41 a9 ldp x0, x1, [sp, #16]32# DISASM: 140001074: e2 0f 42 a9 ldp x2, x3, [sp, #32]
33# DISASM: 140001078: fd 7b cd a8 ldp x29, x30, [sp], #20833# DISASM: 140001078: e0 07 41 a9 ldp x0, x1, [sp, #16]
34# DISASM: 14000107c: 00 02 1f d6 br x1634# DISASM: 14000107c: fd 7b cd a8 ldp x29, x30, [sp], #208
35# DISASM: 140001080: 00 02 1f d6 br x16
3536
36# IMPORTS: Format: COFF-ARM6437# IMPORTS: Format: COFF-ARM64
37# IMPORTS: Arch: aarch6438# IMPORTS: Arch: aarch64
deps/lld/test/COFF/arm64-import2.test+3-1
...@@ -4,14 +4,16 @@...@@ -4,14 +4,16 @@
4# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE4# RUN: llvm-objdump -d %t.obj | FileCheck %s -check-prefix BEFORE
5# RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t.obj %p/Inputs/library-arm64.lib %p/Inputs/library2-arm64.lib5# RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t.obj %p/Inputs/library-arm64.lib %p/Inputs/library2-arm64.lib
6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
7# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s -check-prefix IMPORTS7# RUN: llvm-readobj --coff-imports %t.exe | FileCheck %s -check-prefix IMPORTS
88
9# BEFORE: Disassembly of section .text:9# BEFORE: Disassembly of section .text:
10# BEFORE-EMPTY:
10# BEFORE: 0: 00 00 00 94 bl #011# BEFORE: 0: 00 00 00 94 bl #0
11# BEFORE: 4: 00 00 00 94 bl #012# BEFORE: 4: 00 00 00 94 bl #0
12# BEFORE: 8: c0 03 5f d6 ret13# BEFORE: 8: c0 03 5f d6 ret
1314
14# AFTER: Disassembly of section .text:15# AFTER: Disassembly of section .text:
16# AFTER-EMPTY:
15# AFTER: 140001000: 03 00 00 94 bl #1217# AFTER: 140001000: 03 00 00 94 bl #12
16# AFTER: 140001004: 05 00 00 94 bl #2018# AFTER: 140001004: 05 00 00 94 bl #20
17# AFTER: 140001008: c0 03 5f d6 ret19# AFTER: 140001008: c0 03 5f d6 ret
deps/lld/test/COFF/arm64-magic.yaml+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /entry:mainCRTStartup /subsystem:console %t.obj2# RUN: lld-link /out:%t.exe /entry:mainCRTStartup /subsystem:console %t.obj
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
44
5# CHECK: Format: COFF-ARM645# CHECK: Format: COFF-ARM64
6# CHECK: Arch: aarch646# CHECK: Arch: aarch64
deps/lld/test/COFF/arm64-relocs-imports.test+14-7
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
77
8# BEFORE: Disassembly of section .text:8# BEFORE: Disassembly of section .text:
9# BEFORE-EMPTY:
9# BEFORE: 0: fe 0f 1f f8 str x30, [sp, #-16]!10# BEFORE: 0: fe 0f 1f f8 str x30, [sp, #-16]!
10# BEFORE: 4: 00 00 00 90 adrp x0, #011# BEFORE: 4: 00 00 00 90 adrp x0, #0
11# BEFORE: 8: 00 08 00 91 add x0, x0, #212# BEFORE: 8: 00 08 00 91 add x0, x0, #2
...@@ -45,12 +46,14 @@...@@ -45,12 +46,14 @@
45# BEFORE: 90: 20 1a 09 30 adr x0, #7456546# BEFORE: 90: 20 1a 09 30 adr x0, #74565
46# BEFORE: 94: 01 00 00 54 b.ne #047# BEFORE: 94: 01 00 00 54 b.ne #0
47# BEFORE: 98: 00 00 00 36 tbz w0, #0, #048# BEFORE: 98: 00 00 00 36 tbz w0, #0, #0
49# BEFORE: 9c: 01 00 00 00 udf #1
4850
49# AFTER: Disassembly of section .text:51# AFTER: Disassembly of section .text:
52# AFTER-EMPTY:
50# AFTER: 140001000: fe 0f 1f f8 str x30, [sp, #-16]!53# AFTER: 140001000: fe 0f 1f f8 str x30, [sp, #-16]!
51# AFTER: 140001004: 00 00 00 b0 adrp x0, #409654# AFTER: 140001004: 00 00 00 b0 adrp x0, #4096
52# AFTER: 140001008: 00 18 00 91 add x0, x0, #655# AFTER: 140001008: 00 18 00 91 add x0, x0, #6
53# AFTER: 14000100c: 24 00 00 94 bl #14456# AFTER: 14000100c: 25 00 00 94 bl #148
54# AFTER: 140001010: 00 21 40 39 ldrb w0, [x8, #8]57# AFTER: 140001010: 00 21 40 39 ldrb w0, [x8, #8]
55# AFTER: 140001014: 00 11 40 79 ldrh w0, [x8, #8]58# AFTER: 140001014: 00 11 40 79 ldrh w0, [x8, #8]
56# AFTER: 140001018: 00 09 40 b9 ldr w0, [x8, #8]59# AFTER: 140001018: 00 09 40 b9 ldr w0, [x8, #8]
...@@ -84,11 +87,12 @@...@@ -84,11 +87,12 @@
84# AFTER: 140001088: 00 c4 41 f9 ldr x0, [x0, #904]87# AFTER: 140001088: 00 c4 41 f9 ldr x0, [x0, #904]
85# AFTER: 14000108c: 03 00 00 00 udf #388# AFTER: 14000108c: 03 00 00 00 udf #3
86# AFTER: 140001090: e0 95 09 30 adr x0, #7852589# AFTER: 140001090: e0 95 09 30 adr x0, #78525
87# AFTER: 140001094: 41 00 00 54 b.ne #890# AFTER: 140001094: 61 00 00 54 b.ne #12
88# AFTER: 140001098: 20 00 00 36 tbz w0, #0, #491# AFTER: 140001098: 40 00 00 36 tbz w0, #0, #8
89# AFTER: 14000109c: 10 00 00 b0 adrp x16, #409692# AFTER: 14000109c: 61 ff ff ff <unknown>
90# AFTER: 1400010a0: 10 2a 40 f9 ldr x16, [x16, #80]93# AFTER: 1400010a0: 10 00 00 b0 adrp x16, #4096
91# AFTER: 1400010a4: 00 02 1f d6 br x1694# AFTER: 1400010a4: 10 2a 40 f9 ldr x16, [x16, #80]
95# AFTER: 1400010a8: 00 02 1f d6 br x16
9296
93--- !COFF97--- !COFF
94header:98header:
...@@ -98,7 +102,7 @@ sections:...@@ -98,7 +102,7 @@ sections:
98 - Name: .text102 - Name: .text
99 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]103 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
100 Alignment: 4104 Alignment: 4
101 SectionData: FE0F1FF80000009000080091000000940001403900014079000140B9000140F90001003900010079000100B9000100F90001403D0001407D000140BD000140FD0001C03D0001003D0001007D000100BD000100FD0001803D000540F9201A01B000FC4FF9E0031F2AFE0741F8C0035FD6080000000000000001000000010000000000009100004091000040f901000000201a09300100005400000036105 SectionData: FE0F1FF80000009000080091000000940001403900014079000140B9000140F90001003900010079000100B9000100F90001403D0001407D000140BD000140FD0001C03D0001003D0001007D000100BD000100FD0001803D000540F9201A01B000FC4FF9E0031F2AFE0741F8C0035FD6080000000000000001000000010000000000009100004091000040f901000000201a0930010000540000003601000000
102 Relocations:106 Relocations:
103 - VirtualAddress: 4107 - VirtualAddress: 4
104 SymbolName: .Lstr108 SymbolName: .Lstr
...@@ -202,6 +206,9 @@ sections:...@@ -202,6 +206,9 @@ sections:
202 - VirtualAddress: 152206 - VirtualAddress: 152
203 SymbolName: function207 SymbolName: function
204 Type: IMAGE_REL_ARM64_BRANCH14208 Type: IMAGE_REL_ARM64_BRANCH14
209 - VirtualAddress: 156
210 SymbolName: main
211 Type: IMAGE_REL_ARM64_REL32
205 - Name: .data212 - Name: .data
206 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]213 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
207 Alignment: 4214 Alignment: 4
deps/lld/test/COFF/armnt-blx23t.test+2
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
77
8# BEFORE: Disassembly of section .text:8# BEFORE: Disassembly of section .text:
9# BEFORE-EMPTY:
9# BEFORE: 0: 70 47 bx lr10# BEFORE: 0: 70 47 bx lr
10# BEFORE: 2: 00 bf nop11# BEFORE: 2: 00 bf nop
11# BEFORE: 4: 2d e9 00 48 push.w {r11, lr}12# BEFORE: 4: 2d e9 00 48 push.w {r11, lr}
...@@ -16,6 +17,7 @@...@@ -16,6 +17,7 @@
16# BEFORE: 12: bd e8 00 88 pop.w {r11, pc}17# BEFORE: 12: bd e8 00 88 pop.w {r11, pc}
1718
18# AFTER: Disassembly of section .text:19# AFTER: Disassembly of section .text:
20# AFTER-EMPTY:
19# AFTER: 1000: 70 47 bx lr21# AFTER: 1000: 70 47 bx lr
20# AFTER: 1002: 00 bf nop22# AFTER: 1002: 00 bf nop
21# AFTER: 1004: 2d e9 00 48 push.w {r11, lr}23# AFTER: 1004: 2d e9 00 48 push.w {r11, lr}
deps/lld/test/COFF/armnt-branch24t.test+2
...@@ -6,12 +6,14 @@...@@ -6,12 +6,14 @@
6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
77
8# BEFORE: Disassembly of section .text:8# BEFORE: Disassembly of section .text:
9# BEFORE-EMPTY:
9# BEFORE: 0: 70 47 bx lr10# BEFORE: 0: 70 47 bx lr
10# BEFORE: 2: 00 bf nop11# BEFORE: 2: 00 bf nop
11# BEFORE: 4: 20 20 movs r0, #3212# BEFORE: 4: 20 20 movs r0, #32
12# BEFORE: 6: 00 f0 00 b8 b.w #013# BEFORE: 6: 00 f0 00 b8 b.w #0
1314
14# AFTER: Disassembly of section .text:15# AFTER: Disassembly of section .text:
16# AFTER-EMPTY:
15# AFTER: .text:17# AFTER: .text:
16# AFTER: 1000: 70 47 bx lr18# AFTER: 1000: 70 47 bx lr
17# AFTER: 1002: 00 bf nop19# AFTER: 1002: 00 bf nop
deps/lld/test/COFF/armnt-entry-point.test+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# RUN: yaml2obj < %p/Inputs/armnt-executable.obj.yaml > %t.obj1# RUN: yaml2obj < %p/Inputs/armnt-executable.obj.yaml > %t.obj
2# RUN: lld-link /out:%t.exe /entry:mainCRTStartup /subsystem:console %t.obj2# RUN: lld-link /out:%t.exe /entry:mainCRTStartup /subsystem:console %t.obj
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
44
5CHECK: AddressOfEntryPoint: 0x10015CHECK: AddressOfEntryPoint: 0x1001
deps/lld/test/COFF/armnt-imports.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /subsystem:console %t.obj \2# RUN: lld-link /out:%t.exe /subsystem:console %t.obj \
3# RUN: /entry:mainCRTStartup %p/Inputs/library.lib3# RUN: /entry:mainCRTStartup %p/Inputs/library.lib
4# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s4# RUN: llvm-readobj --coff-imports %t.exe | FileCheck %s
55
6# CHECK: Import {6# CHECK: Import {
7# CHECK: Name: library.dll7# CHECK: Name: library.dll
deps/lld/test/COFF/armnt-mov32t-exec.test+2
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
77
8# BEFORE: Disassembly of section .text:8# BEFORE: Disassembly of section .text:
9# BEFORE-EMPTY:
9# BEFORE: 0: 70 47 bx lr10# BEFORE: 0: 70 47 bx lr
10# BEFORE: 2: 00 bf nop11# BEFORE: 2: 00 bf nop
11# BEFORE: 4: 40 f2 00 00 movw r0, #012# BEFORE: 4: 40 f2 00 00 movw r0, #0
...@@ -13,6 +14,7 @@...@@ -13,6 +14,7 @@
13# BEFORE: c: 70 47 bx lr14# BEFORE: c: 70 47 bx lr
1415
15# AFTER: Disassembly of section .text:16# AFTER: Disassembly of section .text:
17# AFTER-EMPTY:
16# AFTER: 1000: 70 47 bx lr18# AFTER: 1000: 70 47 bx lr
17# AFTER: 1002: 00 bf nop19# AFTER: 1002: 00 bf nop
18# AFTER: 1004: 41 f2 01 00 movw r0, #409720# AFTER: 1004: 41 f2 01 00 movw r0, #4097
deps/lld/test/COFF/armnt-movt32t.test+2
...@@ -6,11 +6,13 @@...@@ -6,11 +6,13 @@
6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER6# RUN: llvm-objdump -d %t.exe | FileCheck %s -check-prefix AFTER
77
8# BEFORE: Disassembly of section .text:8# BEFORE: Disassembly of section .text:
9# BEFORE-EMPTY:
9# BEFORE: 0: 40 f2 00 00 movw r0, #010# BEFORE: 0: 40 f2 00 00 movw r0, #0
10# BEFORE: 4: c0 f2 00 00 movt r0, #011# BEFORE: 4: c0 f2 00 00 movt r0, #0
11# BEFORE: 8: 70 47 bx lr12# BEFORE: 8: 70 47 bx lr
1213
13# AFTER: Disassembly of section .text:14# AFTER: Disassembly of section .text:
15# AFTER-EMPTY:
14# AFTER: 0: 42 f2 00 00 movw r0, #819216# AFTER: 0: 42 f2 00 00 movw r0, #8192
15# AFTER: 4: c0 f2 40 00 movt r0, #6417# AFTER: 4: c0 f2 40 00 movt r0, #64
16# AFTER: 8: 70 47 bx lr18# AFTER: 8: 70 47 bx lr
deps/lld/test/COFF/armnt-rel32.yaml created+47
...@@ -0,0 +1,47 @@
1# REQUIRES: arm
2
3# RUN: yaml2obj < %s > %t.obj
4# RUN: llvm-objdump -s %t.obj | FileCheck %s -check-prefix BEFORE
5# RUN: lld-link /entry:function /subsystem:console /out:%t.exe %t.obj
6# RUN: llvm-objdump -s %t.exe | FileCheck %s -check-prefix AFTER
7
8# BEFORE: Contents of section .text:
9# BEFORE: 0000 704700bf 01000000 01000000
10
11# AFTER: Contents of section .text:
12# AFTER: 401000 704700bf faffffff f50f0000
13
14--- !COFF
15header:
16 Machine: IMAGE_FILE_MACHINE_ARMNT
17 Characteristics: []
18sections:
19 - Name: .text
20 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_PURGEABLE, IMAGE_SCN_MEM_16BIT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
21 Alignment: 4
22 SectionData: 704700BF0100000001000000
23 Relocations:
24 - VirtualAddress: 4
25 SymbolName: function
26 Type: IMAGE_REL_ARM_REL32
27 - VirtualAddress: 8
28 SymbolName: data
29 Type: IMAGE_REL_ARM_REL32
30 - Name: .rdata
31 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
32 Alignment: 1
33 SectionData: 00
34symbols:
35 - Name: function
36 Value: 0
37 SectionNumber: 1
38 SimpleType: IMAGE_SYM_TYPE_NULL
39 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
40 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
41 - Name: data
42 Value: 0
43 SectionNumber: 2
44 SimpleType: IMAGE_SYM_TYPE_NULL
45 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
46 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
47...
deps/lld/test/COFF/associative-comdat-empty.test created+56
...@@ -0,0 +1,56 @@
1# RUN: yaml2obj < %s > %t.obj
2# RUN: not lld-link /include:symbol /dll /noentry /nodefaultlib %t.obj /out:%t.exe 2>&1 | FileCheck %s
3
4# Tests an associative comdat being associated with an empty section errors.
5# CHECK: lld-link: error: {{.*}}: associative comdat .text$ac1 (sec 1) has invalid reference to section .text$nm (sec 2)
6# CHECK-NOT: lld-link: error:
7
8--- !COFF
9header:
10 Machine: IMAGE_FILE_MACHINE_AMD64
11 Characteristics: [ ]
12sections:
13 - Name: '.text$ac1'
14 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
15 Alignment: 1
16 SectionData: '01000000'
17 - Name: '.text$nm'
18 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
19 Alignment: 1
20 SectionData: '01000000'
21symbols:
22 - Name: '.text$ac1'
23 Value: 0
24 SectionNumber: 1
25 SimpleType: IMAGE_SYM_TYPE_NULL
26 ComplexType: IMAGE_SYM_DTYPE_NULL
27 StorageClass: IMAGE_SYM_CLASS_STATIC
28 SectionDefinition:
29 Length: 4
30 NumberOfRelocations: 0
31 NumberOfLinenumbers: 0
32 CheckSum: 3099354981
33 Number: 2
34 Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE
35 - Name: '.text$nm'
36 Value: 0
37 SectionNumber: 2
38 SimpleType: IMAGE_SYM_TYPE_NULL
39 ComplexType: IMAGE_SYM_DTYPE_NULL
40 StorageClass: IMAGE_SYM_CLASS_STATIC
41 SectionDefinition:
42 Length: 0
43 NumberOfRelocations: 0
44 NumberOfLinenumbers: 0
45 CheckSum: 3099354981
46 Number: 4
47 Selection: IMAGE_COMDAT_SELECT_ANY
48 - Name: assocsym
49 Value: 0
50 SectionNumber: 1
51 SimpleType: IMAGE_SYM_TYPE_NULL
52 ComplexType: IMAGE_SYM_DTYPE_NULL
53 StorageClass: IMAGE_SYM_CLASS_STATIC
54...
55
56
deps/lld/test/COFF/associative-comdat-mingw-i386.s created+37
...@@ -0,0 +1,37 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj
4
5# RUN: lld-link -lldmingw -entry:main %t.obj -out:%t.exe
6# RUN: llvm-objdump -s %t.exe | FileCheck %s
7
8# Check that the .eh_frame comdat was included, even if it had no symbols,
9# due to associativity with the symbol _foo.
10
11# CHECK: Contents of section .eh_fram:
12# CHECK: 403000 42
13
14 .text
15 .def _main;
16 .scl 2;
17 .type 32;
18 .endef
19 .globl _main
20 .p2align 4, 0x90
21_main:
22 call _foo
23 ret
24
25 .section .eh_frame$foo,"dr"
26 .linkonce discard
27 .byte 0x42
28
29 .def _foo;
30 .scl 2;
31 .type 32;
32 .endef
33 .section .text$foo,"xr",discard,foo
34 .globl _foo
35 .p2align 4
36_foo:
37 ret
deps/lld/test/COFF/associative-comdat-mingw.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/associative-comdat-mingw-2.s -filetype=obj -o %t2.obj4# RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/associative-comdat-mingw-2.s -filetype=obj -o %t2.obj
55
6# RUN: lld-link -lldmingw -entry:main %t1.obj %t2.obj -out:%t.gc.exe -verbose6# RUN: lld-link -lldmingw -entry:main %t1.obj %t2.obj -out:%t.gc.exe -verbose
7# RUN: llvm-readobj -sections %t.gc.exe | FileCheck %s7# RUN: llvm-readobj --sections %t.gc.exe | FileCheck %s
88
9# CHECK: Sections [9# CHECK: Sections [
10# CHECK: Section {10# CHECK: Section {
deps/lld/test/COFF/associative-comdat-order.test created+97
...@@ -0,0 +1,97 @@
1# Tests that an associative comdat being associated with another
2# associated comdat later in the file produces an error.
3# RUN: sed -e s/ASSOC1/2/ -e s/ASSOC2/3/ %s | yaml2obj > %t.obj
4# RUN: not lld-link /include:symbol /dll /noentry /nodefaultlib %t.obj /out:%t.exe 2>&1 | FileCheck --check-prefix=FORWARD %s
5# FORWARD: lld-link: error: {{.*}}: associative comdat .text$ac1 (sec 1) has invalid reference to section .text$ac2 (sec 2)
6# FORWARD-NOT: lld-link: error:
7
8# Tests that an associative comdat being associated with another
9# associated comdat earlier in the file works.
10# RUN: sed -e s/ASSOC1/3/ -e s/ASSOC2/1/ %s | yaml2obj > %t.obj
11
12# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.obj /out:%t.exe
13# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=BACKWARD %s
14# BACKWARD: Contents of section .text:
15# BACKWARD: 180001000 01000000 02000000 03000000 ............
16
17# RUN: lld-link /dll /noentry /nodefaultlib %t.obj /out:%t.exe
18# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=BACKWARDDROP %s
19# BACKWARDDROP-NOT: Contents of section .text:
20
21--- !COFF
22header:
23 Machine: IMAGE_FILE_MACHINE_AMD64
24 Characteristics: [ ]
25sections:
26 - Name: '.text$ac1'
27 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
28 Alignment: 1
29 SectionData: '01000000'
30 - Name: '.text$ac2'
31 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
32 Alignment: 1
33 SectionData: '02000000'
34 - Name: '.text$nm'
35 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
36 Alignment: 1
37 SectionData: '03000000'
38symbols:
39 - Name: '.text$ac1'
40 Value: 0
41 SectionNumber: 1
42 SimpleType: IMAGE_SYM_TYPE_NULL
43 ComplexType: IMAGE_SYM_DTYPE_NULL
44 StorageClass: IMAGE_SYM_CLASS_STATIC
45 SectionDefinition:
46 Length: 4
47 NumberOfRelocations: 0
48 NumberOfLinenumbers: 0
49 CheckSum: 3099354981
50 Number: ASSOC1
51 Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE
52 - Name: '.text$ac2'
53 Value: 0
54 SectionNumber: 2
55 SimpleType: IMAGE_SYM_TYPE_NULL
56 ComplexType: IMAGE_SYM_DTYPE_NULL
57 StorageClass: IMAGE_SYM_CLASS_STATIC
58 SectionDefinition:
59 Length: 4
60 NumberOfRelocations: 0
61 NumberOfLinenumbers: 0
62 CheckSum: 3099354981
63 Number: ASSOC2
64 Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE
65 - Name: '.text$nm'
66 Value: 0
67 SectionNumber: 3
68 SimpleType: IMAGE_SYM_TYPE_NULL
69 ComplexType: IMAGE_SYM_DTYPE_NULL
70 StorageClass: IMAGE_SYM_CLASS_STATIC
71 SectionDefinition:
72 Length: 4
73 NumberOfRelocations: 0
74 NumberOfLinenumbers: 0
75 CheckSum: 3099354981
76 Number: 4
77 Selection: IMAGE_COMDAT_SELECT_ANY
78 - Name: symbol
79 Value: 0
80 SectionNumber: 3
81 SimpleType: IMAGE_SYM_TYPE_NULL
82 ComplexType: IMAGE_SYM_DTYPE_NULL
83 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
84 - Name: assocsym2
85 Value: 0
86 SectionNumber: 1
87 SimpleType: IMAGE_SYM_TYPE_NULL
88 ComplexType: IMAGE_SYM_DTYPE_NULL
89 StorageClass: IMAGE_SYM_CLASS_STATIC
90 - Name: assocsym
91 Value: 0
92 SectionNumber: 2
93 SimpleType: IMAGE_SYM_TYPE_NULL
94 ComplexType: IMAGE_SYM_DTYPE_NULL
95 StorageClass: IMAGE_SYM_CLASS_STATIC
96...
97
deps/lld/test/COFF/associative-comdat.s+2-2
...@@ -3,10 +3,10 @@...@@ -3,10 +3,10 @@
3# RUN: llvm-mc -triple=x86_64-windows-msvc %S/Inputs/associative-comdat-2.s -filetype=obj -o %t2.obj3# RUN: llvm-mc -triple=x86_64-windows-msvc %S/Inputs/associative-comdat-2.s -filetype=obj -o %t2.obj
44
5# RUN: lld-link -entry:main %t1.obj %t2.obj -out:%t.gc.exe5# RUN: lld-link -entry:main %t1.obj %t2.obj -out:%t.gc.exe
6# RUN: llvm-readobj -sections %t.gc.exe | FileCheck %s6# RUN: llvm-readobj --sections %t.gc.exe | FileCheck %s
77
8# RUN: lld-link -entry:main %t1.obj %t2.obj -opt:noref -out:%t.nogc.exe8# RUN: lld-link -entry:main %t1.obj %t2.obj -opt:noref -out:%t.nogc.exe
9# RUN: llvm-readobj -sections %t.nogc.exe | FileCheck %s9# RUN: llvm-readobj --sections %t.nogc.exe | FileCheck %s
1010
11# CHECK: Sections [11# CHECK: Sections [
12# CHECK: Section {12# CHECK: Section {
deps/lld/test/COFF/autoimport-arm-data.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: llvm-mc -triple=armv7-windows-gnu %s -filetype=obj -o %t.obj7# 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 -verbose8# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose
99
10# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s10# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
11# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s11# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s
1212
13# IMPORTS: Import {13# IMPORTS: Import {
deps/lld/test/COFF/autoimport-arm64-data.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: llvm-mc -triple=aarch64-windows-gnu %s -filetype=obj -o %t.obj7# 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 -verbose8# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose
99
10# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s10# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
11# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s11# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s
1212
13# IMPORTS: Import {13# IMPORTS: Import {
deps/lld/test/COFF/autoimport-gnu-implib.s+1-1
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj9# 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 -verbose10# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-implib.a -verbose
1111
12# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s12# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
1313
14# IMPORTS: Import {14# IMPORTS: Import {
15# IMPORTS-NEXT: Name: foo.dll15# IMPORTS-NEXT: Name: foo.dll
deps/lld/test/COFF/autoimport-refptr.s+2-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj7# 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 -verbose8# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose
99
10# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s10# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
11# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s11# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s
12# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s12# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s
1313
...@@ -19,6 +19,7 @@...@@ -19,6 +19,7 @@
19# IMPORTS-NEXT: }19# IMPORTS-NEXT: }
2020
21# DISASM: Disassembly of section .text:21# DISASM: Disassembly of section .text:
22# DISASM-EMPTY:
22# DISASM: .text:23# DISASM: .text:
23# Relative offset at 0x1002 pointing at the IAT at 0x206024# Relative offset at 0x1002 pointing at the IAT at 0x2060
24# DISASM: 140001000: 48 8b 05 59 10 00 00 movq 4185(%rip), %rax25# DISASM: 140001000: 48 8b 05 59 10 00 00 movq 4185(%rip), %rax
deps/lld/test/COFF/autoimport-x86.s+2-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj7# 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 -verbose8# RUN: lld-link -lldmingw -out:%t.exe -entry:main %t.obj %t-lib.lib -verbose
99
10# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s10# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
11# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s11# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s
12# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s12# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=CONTENTS %s
1313
...@@ -19,6 +19,7 @@...@@ -19,6 +19,7 @@
19# IMPORTS-NEXT: }19# IMPORTS-NEXT: }
2020
21# DISASM: Disassembly of section .text:21# DISASM: Disassembly of section .text:
22# DISASM-EMPTY:
22# DISASM: .text:23# DISASM: .text:
23# Relative offset at 0x1002 pointing at the IAT at 0x2080.24# Relative offset at 0x1002 pointing at the IAT at 0x2080.
24# DISASM: 140001000: 8b 05 7a 10 00 00 movl 4218(%rip), %eax25# DISASM: 140001000: 8b 05 7a 10 00 00 movl 4218(%rip), %eax
deps/lld/test/COFF/base.test+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
22
3# RUN: lld-link /out:%t.exe /entry:main %t.obj3# RUN: lld-link /out:%t.exe /entry:main %t.obj
4# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DEFAULT-HEADER %s4# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=DEFAULT-HEADER %s
5# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=DEFAULT-TEXT %s5# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=DEFAULT-TEXT %s
66
7# DEFAULT-HEADER: ImageBase: 0x1400000007# DEFAULT-HEADER: ImageBase: 0x140000000
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9# DEFAULT-TEXT-NEXT: 1000 00000040 010000009# DEFAULT-TEXT-NEXT: 1000 00000040 01000000
1010
11# RUN: lld-link /out:%t.exe /entry:main %t.obj /base:0x28000000011# RUN: lld-link /out:%t.exe /entry:main %t.obj /base:0x280000000
12# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=BASE-HEADER %s12# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=BASE-HEADER %s
13# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=BASE-TEXT %s13# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=BASE-TEXT %s
1414
15# BASE-HEADER: ImageBase: 0x28000000015# BASE-HEADER: ImageBase: 0x280000000
deps/lld/test/COFF/baserel.test+4-4
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2#2#
3# RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib3# RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
4# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck %s -check-prefix=BASEREL4# RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck %s -check-prefix=BASEREL
5#5#
6# RUN: lld-link /out:%t.exe /entry:main /fixed %t.obj %p/Inputs/std64.lib6# RUN: lld-link /out:%t.exe /entry:main /fixed %t.obj %p/Inputs/std64.lib
7# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck %s -check-prefix=NOBASEREL7# RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck %s -check-prefix=NOBASEREL
8#8#
9# BASEREL: BaseReloc [9# BASEREL: BaseReloc [
10# BASEREL-NEXT: Entry {10# BASEREL-NEXT: Entry {
...@@ -44,11 +44,11 @@...@@ -44,11 +44,11 @@
44# NOBASEREL-NEXT: ]44# NOBASEREL-NEXT: ]
45#45#
46# RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib46# RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
47# RUN: llvm-readobj -file-headers -sections %t.exe | FileCheck %s \47# RUN: llvm-readobj --file-headers --sections %t.exe | FileCheck %s \
48# RUN: --check-prefix=BASEREL-HEADER48# RUN: --check-prefix=BASEREL-HEADER
49#49#
50# RUN: lld-link /out:%t.exe /entry:main /fixed %t.obj %p/Inputs/std64.lib50# 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 \51# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s \
52# RUN: --check-prefix=NOBASEREL-HEADER52# RUN: --check-prefix=NOBASEREL-HEADER
53#53#
54# BASEREL-HEADER-NOT: IMAGE_FILE_RELOCS_STRIPPED54# BASEREL-HEADER-NOT: IMAGE_FILE_RELOCS_STRIPPED
deps/lld/test/COFF/color-diagnostics.test created+18
...@@ -0,0 +1,18 @@
1# Windows command prompt doesn't support ANSI escape sequences.
2# REQUIRES: shell
3
4# RUN: not lld-link -xyz --color-diagnostics /nosuchfile 2>&1 \
5# RUN: | FileCheck -check-prefix=COLOR %s
6# RUN: not lld-link -xyz --color-diagnostics=always /nosuchfile 2>&1 \
7# RUN: | FileCheck -check-prefix=COLOR %s
8
9# COLOR: {{lld-link: .\[0;1;35mwarning: .\[0mignoring unknown argument '-xyz'}}
10# COLOR: {{lld-link: .\[0;1;31merror: .\[0mcould not open '/nosuchfile'}}
11
12# RUN: not lld-link /nosuchfile 2>&1 | FileCheck -check-prefix=NOCOLOR %s
13# RUN: not lld-link -color-diagnostics=never /nosuchfile 2>&1 \
14# RUN: | FileCheck -check-prefix=NOCOLOR %s
15# RUN: not lld-link -color-diagnostics=always -no-color-diagnostics \
16# RUN: /nosuchfile 2>&1 | FileCheck -check-prefix=NOCOLOR %s
17
18# NOCOLOR: lld-link: error: could not open '/nosuchfile'
deps/lld/test/COFF/combined-resources.test+1-1
...@@ -8,7 +8,7 @@...@@ -8,7 +8,7 @@
8# RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/resource.res \8# RUN: lld-link /out:%t.exe /entry:main %t.obj %p/Inputs/resource.res \
9# RUN: %p/Inputs/combined-resources.res %p/Inputs/combined-resources-2.res9# RUN: %p/Inputs/combined-resources.res %p/Inputs/combined-resources-2.res
1010
11# RUN: llvm-readobj -coff-resources -file-headers -section-data %t.exe | \11# RUN: llvm-readobj --coff-resources --file-headers --section-data %t.exe | \
12# RUN: FileCheck %s12# RUN: FileCheck %s
1313
14CHECK: ResourceTableRVA: 0x200014CHECK: ResourceTableRVA: 0x2000
deps/lld/test/COFF/comdat-selection-associative-largest.s created+45
...@@ -0,0 +1,45 @@
1# REQUIRES: x86
2
3# Tests handling of several comdats with "largest" selection type that each
4# has an associative comdat.
5
6# Create obj files.
7# RUN: sed -e s/TYPE/.byte/ -e s/SIZE/1/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.1.obj
8# RUN: sed -e s/TYPE/.short/ -e s/SIZE/2/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.2.obj
9# RUN: sed -e s/TYPE/.long/ -e s/SIZE/4/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.4.obj
10
11 .section .text$ac, "", associative, symbol
12assocsym:
13 .long SIZE
14
15 .section .text$nm, "", largest, symbol
16 .globl symbol
17symbol:
18 TYPE SIZE
19
20# Pass the obj files in different orders and check that only the associative
21# comdat of the largest obj file makes it into the output, independent of
22# the order of the obj files on the command line.
23
24# FIXME: Make these pass when /opt:noref is passed.
25
26# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.1.obj %t.2.obj %t.4.obj /out:%t.exe
27# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=ALL124 %s
28# ALL124: Contents of section .text:
29# ALL124: 180001000 04000000 04000000 ....
30
31# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.4.obj %t.2.obj %t.1.obj /out:%t.exe
32# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=ALL421 %s
33# ALL421: Contents of section .text:
34# ALL421: 180001000 04000000 04000000 ....
35
36# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.2.obj %t.4.obj %t.1.obj /out:%t.exe
37# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=ALL241 %s
38# ALL241: Contents of section .text:
39# ALL241: 180001000 04000000 04000000 ....
40
41# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.2.obj %t.1.obj /out:%t.exe
42# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=JUST21 %s
43# JUST21: Contents of section .text:
44# JUST21: 180001000 02000000 0200 ....
45
deps/lld/test/COFF/comdat-selection.s created+107
...@@ -0,0 +1,107 @@
1# REQUIRES: x86
2
3# Tests handling of the comdat selection type.
4# (Except associative which is tested in associative-comdat.s and
5# comdat-selection-associate-largest.s instead.)
6
7# Create obj files with each selection type.
8# RUN: sed -e s/SEL/discard/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.discard.obj
9# RUN: sed -e s/SEL/discard/ -e s/.long/.short/ -e s/1/2/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.discard.short.2.obj
10# RUN: sed -e s/SEL/one_only/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.one_only.obj
11# RUN: sed -e s/SEL/same_size/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_size.obj
12# RUN: sed -e s/SEL/same_size/ -e s/.long/.short/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_size.short.obj
13# RUN: sed -e s/SEL/same_contents/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_contents.obj
14# RUN: sed -e s/SEL/same_contents/ -e s/.long/.short/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_contents.short.obj
15# RUN: sed -e s/SEL/same_contents/ -e s/1/2/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.same_contents.2.obj
16# RUN: sed -e s/SEL/largest/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.largest.obj
17# RUN: sed -e s/SEL/largest/ -e s/.long/.short/ -e s/1/2/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.largest.short.2.obj
18# RUN: sed -e s/SEL/newest/ %s | llvm-mc -triple x86_64-pc-win32 -filetype=obj -o %t.newest.obj
19
20 .section .text$nm, "", SEL, symbol
21 .globl symbol
22symbol:
23 .long 1
24
25# First, pass each selection type twice. All should link fine except for
26# one_only which should report a duplicate symbol error and newest which
27# link.exe (and hence lld-link) doesn't understand.
28
29# RUN: cp %t.discard.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.discard.obj %t.obj
30# RUN: cp %t.one_only.obj %t.obj && not lld-link /dll /noentry /nodefaultlib %t.one_only.obj %t.obj 2>&1 | FileCheck --check-prefix=ONEONE %s
31# ONEONE: lld-link: error: duplicate symbol: symbol
32# RUN: cp %t.same_size.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.same_size.obj %t.obj
33# RUN: cp %t.same_contents.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.same_contents.obj %t.obj
34# RUN: cp %t.largest.obj %t.obj && lld-link /dll /noentry /nodefaultlib %t.largest.obj %t.obj
35# RUN: cp %t.newest.obj %t.obj && not lld-link /dll /noentry /nodefaultlib %t.newest.obj %t.obj 2>&1 | FileCheck --check-prefix=NEWNEW %s
36# NEWNEW: lld-link: error: unknown comdat type 7 for symbol
37
38# /force doesn't affect errors about unknown comdat types.
39# RUN: cp %t.newest.obj %t.obj && not lld-link /force /dll /noentry /nodefaultlib %t.newest.obj %t.obj 2>&1 | FileCheck --check-prefix=NEWNEWFORCE %s
40# NEWNEWFORCE: lld-link: error: unknown comdat type 7 for symbol
41
42# Check that same_size, same_contents, largest do what they're supposed to.
43
44# Check that the "same_size" selection produces an error if passed two symbols
45# with different size.
46# RUN: not lld-link /dll /noentry /nodefaultlib %t.same_size.obj %t.same_size.short.obj 2>&1 | FileCheck --check-prefix=SAMESIZEDUPE %s
47# SAMESIZEDUPE: lld-link: error: duplicate symbol: symbol
48
49# Check that the "same_contents" selection produces an error if passed two
50# symbols with different contents.
51# RUN: not lld-link /dll /noentry /nodefaultlib %t.same_contents.obj %t.same_contents.2.obj 2>&1 | FileCheck --check-prefix=SAMECONTENTSDUPE1 %s
52# SAMECONTENTSDUPE1: lld-link: error: duplicate symbol: symbol
53# RUN: not lld-link /dll /noentry /nodefaultlib %t.same_contents.obj %t.same_contents.2.obj 2>&1 | FileCheck --check-prefix=SAMECONTENTSDUPE2 %s
54# SAMECONTENTSDUPE2: lld-link: error: duplicate symbol: symbol
55
56# Check that the "largest" selection picks the larger comdat (independent of
57# the order the .obj files are passed on the commandline).
58# RUN: lld-link /opt:noref /include:symbol /dll /noentry /nodefaultlib %t.largest.obj %t.largest.short.2.obj /out:%t.exe
59# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=LARGEST1 %s
60# LARGEST1: Contents of section .text:
61# LARGEST1: 180001000 01000000 ....
62
63# FIXME: Make this pass when /opt:noref is passed.
64# RUN: lld-link /include:symbol /dll /noentry /nodefaultlib %t.largest.short.2.obj %t.largest.obj /out:%t.exe
65# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=LARGEST2 %s
66# LARGEST2: Contents of section .text:
67# LARGEST2: 180001000 01000000 ....
68
69
70# Test linking the same symbol with different comdat selection types.
71# link.exe generally rejects this, except for "largest" which is allowed to
72# combine with everything (https://bugs.llvm.org/show_bug.cgi?id=40094#c7).
73# lld-link rejects all comdat selection type mismatches. Spot-test just a few
74# combinations.
75
76# RUN: not lld-link /verbose /dll /noentry /nodefaultlib %t.discard.obj %t.one_only.obj 2>&1 | FileCheck --check-prefix=DISCARDONE %s
77# DISCARDONE: lld-link: conflicting comdat type for symbol: 2 in
78# DISCARDONE: lld-link: error: duplicate symbol: symbol
79# RUN: lld-link /verbose /force /dll /noentry /nodefaultlib %t.discard.obj %t.one_only.obj 2>&1 | FileCheck --check-prefix=DISCARDONEFORCE %s
80# DISCARDONEFORCE: lld-link: conflicting comdat type for symbol: 2 in
81# DISCARDONEFORCE: lld-link: warning: duplicate symbol: symbol
82
83# Make sure the error isn't depending on the order of .obj files.
84# RUN: not lld-link /verbose /dll /noentry /nodefaultlib %t.one_only.obj %t.discard.obj 2>&1 | FileCheck --check-prefix=ONEDISCARD %s
85# ONEDISCARD: lld-link: conflicting comdat type for symbol: 1 in
86# ONEDISCARD: lld-link: error: duplicate symbol: symbol
87
88# RUN: not lld-link /verbose /dll /noentry /nodefaultlib %t.same_contents.obj %t.same_size.obj 2>&1 | FileCheck --check-prefix=CONTENTSSIZE %s
89# CONTENTSSIZE: lld-link: conflicting comdat type for symbol: 4 in
90# CONTENTSSIZE: lld-link: error: duplicate symbol: symbol
91
92# Check that linking one 'discard' and one 'largest' has the effect of
93# 'largest'.
94# RUN: lld-link /dll /noentry /nodefaultlib %t.discard.short.2.obj %t.largest.obj
95# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=DISCARDLARGEST %s
96# DISCARDLARGEST: Contents of section .text:
97# DISCARDLARGEST: 180001000 01000000 ....
98# RUN: lld-link /dll /noentry /nodefaultlib %t.largest.obj %t.discard.short.2.obj
99# RUN: llvm-objdump -s %t.exe | FileCheck --check-prefix=LARGESTDISCARD %s
100# LARGESTDISCARD: Contents of section .text:
101# LARGESTDISCARD: 180001000 01000000 ....
102
103
104# These cases are accepted by link.exe but not by lld-link.
105# RUN: not lld-link /verbose /dll /noentry /nodefaultlib %t.largest.obj %t.one_only.obj 2>&1 | FileCheck --check-prefix=LARGESTONE %s
106# LARGESTONE: lld-link: conflicting comdat type for symbol: 6 in
107# LARGESTONE: lld-link: error: duplicate symbol: symbol
deps/lld/test/COFF/common-replacement.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6# RUN: lld-link -lldmingw -entry:main %t1.obj %t2.obj -out:%t.exe -verbose 2>&1 \6# RUN: lld-link -lldmingw -entry:main %t1.obj %t2.obj -out:%t.exe -verbose 2>&1 \
7# RUN: | FileCheck -check-prefix VERBOSE %s7# RUN: | FileCheck -check-prefix VERBOSE %s
8# RUN: llvm-readobj -s %t.exe | FileCheck -check-prefix SECTIONS %s8# RUN: llvm-readobj -S %t.exe | FileCheck -check-prefix SECTIONS %s
99
10# VERBOSE: -aligncomm:"foo",210# VERBOSE: -aligncomm:"foo",2
1111
deps/lld/test/COFF/common.test+1-1
...@@ -79,7 +79,7 @@ symbols:...@@ -79,7 +79,7 @@ symbols:
79 ComplexType: IMAGE_SYM_DTYPE_NULL79 ComplexType: IMAGE_SYM_DTYPE_NULL
80 StorageClass: IMAGE_SYM_CLASS_EXTERNAL80 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
81 - Name: bssdata1681 - Name: bssdata16
82 Value: 1682 Value: 15
83 SectionNumber: 083 SectionNumber: 0
84 SimpleType: IMAGE_SYM_TYPE_NULL84 SimpleType: IMAGE_SYM_TYPE_NULL
85 ComplexType: IMAGE_SYM_DTYPE_NULL85 ComplexType: IMAGE_SYM_DTYPE_NULL
deps/lld/test/COFF/conflict-mangled.test+5-2
...@@ -1,10 +1,13 @@...@@ -1,10 +1,13 @@
1# REQUIRES: system-windows
2# RUN: yaml2obj < %s > %t1.obj1# RUN: yaml2obj < %s > %t1.obj
3# RUN: yaml2obj < %s > %t2.obj2# RUN: yaml2obj < %s > %t2.obj
4# RUN: not lld-link /out:%t.exe %t1.obj %t2.obj >& %t.log3# RUN: not lld-link /out:%t.exe %t1.obj %t2.obj >& %t.log
5# RUN: FileCheck %s < %t.log4# RUN: FileCheck %s < %t.log
5# RUN: not lld-link /out:%t.exe /demangle %t1.obj %t2.obj 2>&1 | FileCheck %s
6# RUN: not lld-link /out:%t.exe /demangle:no %t1.obj %t2.obj 2>&1 | FileCheck --check-prefix=NODEMANGLE %s
67
7# CHECK: duplicate symbol: "int __cdecl mangled(void)" (?mangled@@YAHXZ) in {{.+}}1.obj and in {{.+}}2.obj8# NODEMANGLE: duplicate symbol: ?mangled@@YAHXZ in {{.+}}1.obj and in {{.+}}2.obj
9
10# CHECK: duplicate symbol: int __cdecl mangled(void) in {{.+}}1.obj and in {{.+}}2.obj
811
9--- !COFF12--- !COFF
10header:13header:
deps/lld/test/COFF/constant-export.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# RUN: mkdir -p %t1# RUN: mkdir -p %t
2# RUN: yaml2obj -o %t/constant-export.obj %s2# RUN: yaml2obj -o %t/constant-export.obj %s
3# RUN: lld-link /machine:x86 /dll /entry:__CFConstantStringClassReference -out:%t/constant-export.dll %t/constant-export.obj3# RUN: lld-link /machine:x86 /dll /entry:__CFConstantStringClassReference -out:%t/constant-export.dll %t/constant-export.obj
4# RUN: llvm-readobj -coff-exports %t/constant-export.lib | FileCheck %s4# RUN: llvm-readobj --coff-exports %t/constant-export.lib | FileCheck %s
55
6# CHECK: Type: const6# CHECK: Type: const
7# CHECK: Name type: noprefix7# CHECK: Name type: noprefix
deps/lld/test/COFF/constant.test+2-2
...@@ -2,5 +2,5 @@ REQUIRES: x86...@@ -2,5 +2,5 @@ REQUIRES: x86
2RUN: mkdir -p %t2RUN: mkdir -p %t
3RUN: llvm-mc -triple i686-unknown-windows-msvc -filetype obj -o %t/import.o %S/Inputs/constant-import.s3RUN: llvm-mc -triple i686-unknown-windows-msvc -filetype obj -o %t/import.o %S/Inputs/constant-import.s
4RUN: llc -mtriple i686-unknown-windows-msvc -filetype obj -o %t/export.o %S/Inputs/constant-export.ll4RUN: llc -mtriple i686-unknown-windows-msvc -filetype obj -o %t/export.o %S/Inputs/constant-export.ll
5RUN: lld-link -machine:x86 -dll -out:%t/export.dll %t/export.o -entry:__CFConstantStringClassReference5RUN: lld-link -safeseh:no -machine:x86 -dll -out:%t/export.dll %t/export.o -entry:__CFConstantStringClassReference
6RUN: lld-link -machine:x86 -dll -out:%t/import.dll %t/import.o %t/export.lib6RUN: lld-link -safeseh:no -machine:x86 -dll -out:%t/import.dll %t/import.o %t/export.lib
deps/lld/test/COFF/could-not-open.test+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1RUN: not lld-link 01 2>&1 | FileCheck %s1RUN: not lld-link 01 2>&1 | FileCheck %s
22
3CHECK: could not open 013CHECK: could not open '01'
4CHECK-NOT: /machine is not specified4CHECK-NOT: /machine is not specified
5CHECK-NOT: subsystem must be defined5CHECK-NOT: subsystem must be defined
deps/lld/test/COFF/crt-chars.test+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj %s > %t.obj1# RUN: yaml2obj %s > %t.obj
2# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj2# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj
3# RUN: llvm-readobj -sections -section-data %t.dll | FileCheck %s3# RUN: llvm-readobj --sections --section-data %t.dll | FileCheck %s
44
5# CHECK: Name: .CRT5# CHECK: Name: .CRT
6# CHECK: Characteristics [6# CHECK: Characteristics [
deps/lld/test/COFF/crt-dyn-initializer-order.test+100-100
...@@ -1,100 +1,100 @@...@@ -1,100 +1,100 @@
1# // a.cpp 1# // a.cpp
2# #include <iostream> 2# #include <iostream>
3# #include <vector> 3# #include <vector>
4# 4#
5# template <int Magic> struct TemplatedObject { 5# template <int Magic> struct TemplatedObject {
6# static std::vector<TemplatedObject<Magic> *> Instances; 6# static std::vector<TemplatedObject<Magic> *> Instances;
7# TemplatedObject() { Instances.push_back(this); } 7# TemplatedObject() { Instances.push_back(this); }
8# }; 8# };
9# 9#
10# using Object = TemplatedObject<0>; 10# using Object = TemplatedObject<0>;
11# template <> std::vector<Object *> Object::Instances{}; 11# template <> std::vector<Object *> Object::Instances{};
12# Object idle{}; 12# Object idle{};
13# 13#
14# int main() { 14# int main() {
15# if (Object::Instances.size() == 0) 15# if (Object::Instances.size() == 0)
16# std::cout << "It's broken" << std::endl; 16# std::cout << "It's broken" << std::endl;
17# else 17# else
18# std::cout << "It works!" << std::endl; 18# std::cout << "It works!" << std::endl;
19# return 0; 19# return 0;
20# } 20# }
21# // using `clang-cl /c a.cpp | lld-link a.obj` works 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() 22# // using `cl /c a.cpp | lld-link a.obj` fails without lld/COFF/Writer.cpp/Writer::sortSectionChunks()
23 23
24# RUN: yaml2obj %s > %t.obj 24# RUN: yaml2obj %s > %t.obj
25# RUN: yaml2obj %S/Inputs/crt-dyn-initializer-order_1.yaml > %t1.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 26# RUN: yaml2obj %S/Inputs/crt-dyn-initializer-order_2.yaml > %t2.obj
27 27
28# CHECK: Name: .CRT 28# CHECK: Name: .CRT
29# CHECK: Characteristics [ 29# CHECK: Characteristics [
30# CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA 30# CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA
31# CHECK-NEXT: IMAGE_SCN_MEM_READ 31# CHECK-NEXT: IMAGE_SCN_MEM_READ
32# CHECK-NEXT: ] 32# CHECK-NEXT: ]
33# CHECK-NEXT: SectionData ( 33# CHECK-NEXT: SectionData (
34 34
35# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj %t1.obj %t2.obj 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 36# RUN: llvm-readobj --sections --section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE1
37# CASE1-NEXT: 01020304 55701011 1205 37# CASE1-NEXT: 01020304 55701011 1205
38 38
39# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj %t2.obj %t1.obj 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 40# RUN: llvm-readobj --sections --section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE2
41# CASE2-NEXT: 01020304 10111255 7005 41# CASE2-NEXT: 01020304 10111255 7005
42 42
43# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t1.obj %t2.obj %t.obj 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 44# RUN: llvm-readobj --sections --section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE3
45# CASE3-NEXT: 01557010 11120203 0405 45# CASE3-NEXT: 01557010 11120203 0405
46 46
47# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t1.obj %t.obj %t2.obj 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 48# RUN: llvm-readobj --sections --section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE4
49# CASE4-NEXT: 01557002 03041011 1205 49# CASE4-NEXT: 01557002 03041011 1205
50 50
51# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t2.obj %t1.obj %t.obj 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 52# RUN: llvm-readobj --sections --section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE5
53# CASE5-NEXT: 01101112 55700203 0405 53# CASE5-NEXT: 01101112 55700203 0405
54 54
55# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t2.obj %t.obj %t1.obj 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 56# RUN: llvm-readobj --sections --section-data %t.dll | FileCheck %s --check-prefixes CHECK,CASE6
57# CASE6-NEXT: 01101112 02030455 7005 57# CASE6-NEXT: 01101112 02030455 7005
58 58
59# CHECK-NEXT: ) 59# CHECK-NEXT: )
60 60
61--- !COFF 61--- !COFF
62header: 62header:
63 Machine: IMAGE_FILE_MACHINE_AMD64 63 Machine: IMAGE_FILE_MACHINE_AMD64
64 Characteristics: [ ] 64 Characteristics: [ ]
65sections: 65sections:
66 - Name: '.CRT$XCA' 66 - Name: '.CRT$XCA'
67 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] 67 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
68 Alignment: 1 68 Alignment: 1
69 SectionData: 01 69 SectionData: 01
70 - Name: '.CRT$XCU' 70 - Name: '.CRT$XCU'
71 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] 71 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
72 Alignment: 1 72 Alignment: 1
73 SectionData: 02 73 SectionData: 02
74 - Name: '.CRT$XCU' 74 - Name: '.CRT$XCU'
75 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_LNK_COMDAT ] 75 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_LNK_COMDAT ]
76 Alignment: 1 76 Alignment: 1
77 SectionData: 03 77 SectionData: 03
78 - Name: '.CRT$XCU' 78 - Name: '.CRT$XCU'
79 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] 79 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
80 Alignment: 1 80 Alignment: 1
81 SectionData: 04 81 SectionData: 04
82 - Name: '.CRT$XCZ' 82 - Name: '.CRT$XCZ'
83 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ] 83 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_READ ]
84 Alignment: 1 84 Alignment: 1
85 SectionData: 05 85 SectionData: 05
86symbols: 86symbols:
87 - Name: '.CRT$XCU' 87 - Name: '.CRT$XCU'
88 Value: 0 88 Value: 0
89 SectionNumber: 3 89 SectionNumber: 3
90 SimpleType: IMAGE_SYM_TYPE_NULL 90 SimpleType: IMAGE_SYM_TYPE_NULL
91 ComplexType: IMAGE_SYM_DTYPE_NULL 91 ComplexType: IMAGE_SYM_DTYPE_NULL
92 StorageClass: IMAGE_SYM_CLASS_STATIC 92 StorageClass: IMAGE_SYM_CLASS_STATIC
93 SectionDefinition: 93 SectionDefinition:
94 Length: 1 94 Length: 1
95 NumberOfRelocations: 0 95 NumberOfRelocations: 0
96 NumberOfLinenumbers: 0 96 NumberOfLinenumbers: 0
97 CheckSum: 1 97 CheckSum: 1
98 Number: 2 98 Number: 2
99 Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE 99 Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE
100... 100...
deps/lld/test/COFF/debug-reloc.s+4-4
...@@ -3,10 +3,10 @@...@@ -3,10 +3,10 @@
3# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj3# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj
44
5# RUN: lld-link -lldmingw -debug:dwarf -out:%t.exe -entry:mainfunc -subsystem:console %t.obj5# RUN: lld-link -lldmingw -debug:dwarf -out:%t.exe -entry:mainfunc -subsystem:console %t.obj
6# RUN: llvm-readobj -sections %t.exe | FileCheck %s -check-prefix SECTIONS6# RUN: llvm-readobj --sections %t.exe | FileCheck %s -check-prefix SECTIONS
7# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck %s -check-prefix RELOCS7# RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck %s -check-prefix RELOCS
8# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s -check-prefix HEADERS8# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s -check-prefix HEADERS
9# RUN: llvm-readobj -coff-debug-directory %t.exe | FileCheck %s -check-prefix DEBUG9# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck %s -check-prefix DEBUG
1010
11# SECTIONS: Number: 311# SECTIONS: Number: 3
12# SECTIONS-NEXT: Name: .buildid (2E 62 75 69 6C 64 69 64)12# SECTIONS-NEXT: Name: .buildid (2E 62 75 69 6C 64 69 64)
deps/lld/test/COFF/def-export-stdcall.s+7-7
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o %t.obj2# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o %t.obj
3# RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall\n fastcall\n vectorcall\n _underscored" > %t.def3# RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall\n fastcall\n vectorcall\n _underscored" > %t.def
4# RUN: lld-link -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib4# RUN: lld-link -safeseh:no -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib
5# RUN: llvm-readobj %t.lib | FileCheck -check-prefix UNDECORATED-IMPLIB %s5# RUN: llvm-readobj %t.lib | FileCheck -check-prefix UNDECORATED-IMPLIB %s
6# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix UNDECORATED-EXPORTS %s6# RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix UNDECORATED-EXPORTS %s
77
8# UNDECORATED-IMPLIB: Name type: noprefix8# UNDECORATED-IMPLIB: Name type: noprefix
9# UNDECORATED-IMPLIB-NEXT: __imp___underscored9# UNDECORATED-IMPLIB-NEXT: __imp___underscored
...@@ -25,9 +25,9 @@...@@ -25,9 +25,9 @@
2525
2626
27# RUN: echo -e "LIBRARY foo\nEXPORTS\n _stdcall@8\n @fastcall@8\n vectorcall@@8" > %t.def27# RUN: echo -e "LIBRARY foo\nEXPORTS\n _stdcall@8\n @fastcall@8\n vectorcall@@8" > %t.def
28# RUN: lld-link -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib28# RUN: lld-link -safeseh:no -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib
29# RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-IMPLIB %s29# RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-IMPLIB %s
30# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix DECORATED-EXPORTS %s30# RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix DECORATED-EXPORTS %s
3131
32# DECORATED-IMPLIB: Name type: name32# DECORATED-IMPLIB: Name type: name
33# DECORATED-IMPLIB-NEXT: __imp_@fastcall@833# DECORATED-IMPLIB-NEXT: __imp_@fastcall@8
...@@ -48,7 +48,7 @@...@@ -48,7 +48,7 @@
48# RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall@8\n @fastcall@8\n vectorcall@@8" > %t.def48# RUN: echo -e "LIBRARY foo\nEXPORTS\n stdcall@8\n @fastcall@8\n vectorcall@@8" > %t.def
49# RUN: lld-link -lldmingw -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib49# RUN: lld-link -lldmingw -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib
50# RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-MINGW-IMPLIB %s50# RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-MINGW-IMPLIB %s
51# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix DECORATED-MINGW-EXPORTS %s51# RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix DECORATED-MINGW-EXPORTS %s
5252
53# DECORATED-MINGW-IMPLIB: Name type: name53# DECORATED-MINGW-IMPLIB: Name type: name
54# DECORATED-MINGW-IMPLIB-NEXT: __imp_@fastcall@854# DECORATED-MINGW-IMPLIB-NEXT: __imp_@fastcall@8
...@@ -68,11 +68,11 @@...@@ -68,11 +68,11 @@
6868
69# RUN: lld-link -lldmingw -kill-at -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib69# RUN: lld-link -lldmingw -kill-at -entry:dllmain -dll -def:%t.def %t.obj -out:%t.dll -implib:%t.lib
70# RUN: llvm-readobj %t.lib | FileCheck -check-prefix MINGW-KILL-AT-IMPLIB %s70# RUN: llvm-readobj %t.lib | FileCheck -check-prefix MINGW-KILL-AT-IMPLIB %s
71# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix MINGW-KILL-AT-EXPORTS %s71# RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix MINGW-KILL-AT-EXPORTS %s
7272
73# RUN: lld-link -lldmingw -kill-at -entry:dllmain -dll %t.obj -out:%t.dll -implib:%t.lib73# RUN: lld-link -lldmingw -kill-at -entry:dllmain -dll %t.obj -out:%t.dll -implib:%t.lib
74# RUN: llvm-readobj %t.lib | FileCheck -check-prefix MINGW-KILL-AT-IMPLIB %s74# RUN: llvm-readobj %t.lib | FileCheck -check-prefix MINGW-KILL-AT-IMPLIB %s
75# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix MINGW-KILL-AT-EXPORTS %s75# RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix MINGW-KILL-AT-EXPORTS %s
7676
77# MINGW-KILL-AT-IMPLIB: Name type: noprefix77# MINGW-KILL-AT-IMPLIB: Name type: noprefix
78# MINGW-KILL-AT-IMPLIB: __imp__fastcall78# MINGW-KILL-AT-IMPLIB: __imp__fastcall
deps/lld/test/COFF/delayimports-armnt.yaml+5-4
...@@ -3,8 +3,8 @@...@@ -3,8 +3,8 @@
3# RUN: lld-link %t.obj %p/Inputs/library.lib /subsystem:console \3# RUN: lld-link %t.obj %p/Inputs/library.lib /subsystem:console \
4# RUN: /entry:mainCRTStartup /alternatename:__delayLoadHelper2=mainCRTStartup \4# RUN: /entry:mainCRTStartup /alternatename:__delayLoadHelper2=mainCRTStartup \
5# RUN: /delayload:library.dll /out:%t.exe5# RUN: /delayload:library.dll /out:%t.exe
6# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s6# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
7# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s7# RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
8# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s8# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s
99
10# IMPORT: Format: COFF-ARM10# IMPORT: Format: COFF-ARM
...@@ -35,7 +35,7 @@...@@ -35,7 +35,7 @@
35# BASEREL-NEXT: }35# BASEREL-NEXT: }
36# BASEREL-NEXT: Entry {36# BASEREL-NEXT: Entry {
37# BASEREL-NEXT: Type: ARM_MOV32(T)37# BASEREL-NEXT: Type: ARM_MOV32(T)
38# BASEREL-NEXT: Address: 0x102238# BASEREL-NEXT: Address: 0x1026
39# BASEREL-NEXT: }39# BASEREL-NEXT: }
40# BASEREL-NEXT: Entry {40# BASEREL-NEXT: Entry {
41# BASEREL-NEXT: Type: ABSOLUTE41# BASEREL-NEXT: Type: ABSOLUTE
...@@ -53,13 +53,14 @@...@@ -53,13 +53,14 @@
53#53#
54# DISASM: 40100c: 43 f2 08 0c movw r12, #1229654# DISASM: 40100c: 43 f2 08 0c movw r12, #12296
55# DISASM-NEXT: c0 f2 40 0c movt r12, #6455# DISASM-NEXT: c0 f2 40 0c movt r12, #64
56# DISASM-NEXT: 00 f0 00 b8 b.w #0
56# DISASM-NEXT: 2d e9 0f 48 push.w {r0, r1, r2, r3, r11, lr}57# DISASM-NEXT: 2d e9 0f 48 push.w {r0, r1, r2, r3, r11, lr}
57# DISASM-NEXT: 0d f2 10 0b addw r11, sp, #1658# DISASM-NEXT: 0d f2 10 0b addw r11, sp, #16
58# DISASM-NEXT: 2d ed 10 0b vpush {d0, d1, d2, d3, d4, d5, d6, d7}59# DISASM-NEXT: 2d ed 10 0b vpush {d0, d1, d2, d3, d4, d5, d6, d7}
59# DISASM-NEXT: 61 46 mov r1, r1260# DISASM-NEXT: 61 46 mov r1, r12
60# DISASM-NEXT: 42 f2 00 00 movw r0, #819261# DISASM-NEXT: 42 f2 00 00 movw r0, #8192
61# DISASM-NEXT: c0 f2 40 00 movt r0, #6462# DISASM-NEXT: c0 f2 40 00 movt r0, #64
62# DISASM-NEXT: ff f7 e9 ff bl #-4663# DISASM-NEXT: ff f7 e7 ff bl #-50
63# DISASM-NEXT: 84 46 mov r12, r064# DISASM-NEXT: 84 46 mov r12, r0
64# DISASM-NEXT: bd ec 10 0b vpop {d0, d1, d2, d3, d4, d5, d6, d7}65# DISASM-NEXT: bd ec 10 0b vpop {d0, d1, d2, d3, d4, d5, d6, d7}
65# DISASM-NEXT: bd e8 0f 48 pop.w {r0, r1, r2, r3, r11, lr}66# DISASM-NEXT: bd e8 0f 48 pop.w {r0, r1, r2, r3, r11, lr}
deps/lld/test/COFF/delayimports.test+4-4
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \1# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \
2# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /delayload:STD64.DLL \2# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /delayload:STD64.DLL \
3# RUN: /alternatename:__delayLoadHelper2=main3# RUN: /alternatename:__delayLoadHelper2=main
4# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s4# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
5# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s5# RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
66
7IMPORT: DelayImport {7IMPORT: DelayImport {
8IMPORT-NEXT: Name: std64.dll8IMPORT-NEXT: Name: std64.dll
...@@ -18,11 +18,11 @@ IMPORT-NEXT: Address: 0x140001066...@@ -18,11 +18,11 @@ IMPORT-NEXT: Address: 0x140001066
18IMPORT-NEXT: }18IMPORT-NEXT: }
19IMPORT-NEXT: Import {19IMPORT-NEXT: Import {
20IMPORT-NEXT: Symbol: (50)20IMPORT-NEXT: Symbol: (50)
21IMPORT-NEXT: Address: 0x1400010BD21IMPORT-NEXT: Address: 0x140001072
22IMPORT-NEXT: }22IMPORT-NEXT: }
23IMPORT-NEXT: Import {23IMPORT-NEXT: Import {
24IMPORT-NEXT: Symbol: MessageBoxA (0)24IMPORT-NEXT: Symbol: MessageBoxA (0)
25IMPORT-NEXT: Address: 0x14000111425IMPORT-NEXT: Address: 0x14000107E
26IMPORT-NEXT: }26IMPORT-NEXT: }
27IMPORT-NEXT: }27IMPORT-NEXT: }
2828
deps/lld/test/COFF/delayimports32.test+20-22
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj2# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
3# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \3# RUN: lld-link -safeseh:no %t.obj %p/Inputs/std32.lib /subsystem:console \
4# RUN: /entry:main@0 /alternatename:___delayLoadHelper2@8=_main@0 \4# RUN: /entry:main@0 /alternatename:___delayLoadHelper2@8=_main@0 \
5# RUN: /delayload:std32.dll /out:%t.exe5# RUN: /delayload:std32.dll /out:%t.exe
6# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s6# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
7# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s7# RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
8# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s8# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=DISASM %s
99
10IMPORT: Format: COFF-i38610IMPORT: Format: COFF-i386
...@@ -24,7 +24,7 @@ IMPORT-NEXT: Address: 0x401029...@@ -24,7 +24,7 @@ IMPORT-NEXT: Address: 0x401029
24IMPORT-NEXT: }24IMPORT-NEXT: }
25IMPORT-NEXT: Import {25IMPORT-NEXT: Import {
26IMPORT-NEXT: Symbol: MessageBoxA (0)26IMPORT-NEXT: Symbol: MessageBoxA (0)
27IMPORT-NEXT: Address: 0x40103E27IMPORT-NEXT: Address: 0x401033
28IMPORT-NEXT: }28IMPORT-NEXT: }
29IMPORT-NEXT: }29IMPORT-NEXT: }
3030
...@@ -47,19 +47,19 @@ BASEREL-NEXT: Address: 0x1025...@@ -47,19 +47,19 @@ BASEREL-NEXT: Address: 0x1025
47BASEREL-NEXT: }47BASEREL-NEXT: }
48BASEREL-NEXT: Entry {48BASEREL-NEXT: Entry {
49BASEREL-NEXT: Type: HIGHLOW49BASEREL-NEXT: Type: HIGHLOW
50BASEREL-NEXT: Address: 0x102C50BASEREL-NEXT: Address: 0x102A
51BASEREL-NEXT: }51BASEREL-NEXT: }
52BASEREL-NEXT: Entry {52BASEREL-NEXT: Entry {
53BASEREL-NEXT: Type: HIGHLOW53BASEREL-NEXT: Type: HIGHLOW
54BASEREL-NEXT: Address: 0x103154BASEREL-NEXT: Address: 0x1034
55BASEREL-NEXT: }55BASEREL-NEXT: }
56BASEREL-NEXT: Entry {56BASEREL-NEXT: Entry {
57BASEREL-NEXT: Type: HIGHLOW57BASEREL-NEXT: Type: HIGHLOW
58BASEREL-NEXT: Address: 0x104158BASEREL-NEXT: Address: 0x1041
59BASEREL-NEXT: }59BASEREL-NEXT: }
60BASEREL-NEXT: Entry {60BASEREL-NEXT: Entry {
61BASEREL-NEXT: Type: HIGHLOW61BASEREL-NEXT: Type: ABSOLUTE
62BASEREL-NEXT: Address: 0x104662BASEREL-NEXT: Address: 0x1000
63BASEREL-NEXT: }63BASEREL-NEXT: }
64BASEREL-NEXT: Entry {64BASEREL-NEXT: Entry {
65BASEREL-NEXT: Type: HIGHLOW65BASEREL-NEXT: Type: HIGHLOW
...@@ -71,17 +71,15 @@ BASEREL-NEXT: Address: 0x3024...@@ -71,17 +71,15 @@ BASEREL-NEXT: Address: 0x3024
71BASEREL-NEXT: }71BASEREL-NEXT: }
72BASEREL-NEXT: ]72BASEREL-NEXT: ]
7373
74DISASM: 102b: 68 20 30 40 00 pushl $420662474DISASM: 1029: b8 20 30 40 00 movl $4206624, %eax
75DISASM-NEXT: 1030: 68 00 20 40 00 pushl $420249675DISASM-NEXT: 102e: e9 0a 00 00 00 jmp 10 <.text+0x3d>
76DISASM-NEXT: 1035: e8 c6 ff ff ff calll -58 <.text>76DISASM-NEXT: 1033: b8 24 30 40 00 movl $4206628, %eax
77DISASM-NEXT: 103a: 5a popl %edx77DISASM-NEXT: 1038: e9 00 00 00 00 jmp 0 <.text+0x3d>
78DISASM-NEXT: 103b: 59 popl %ecx78DISASM-NEXT: 103d: 51 pushl %ecx
79DISASM-NEXT: 103c: ff e0 jmpl *%eax79DISASM-NEXT: 103e: 52 pushl %edx
80DISASM-NEXT: 103e: 51 pushl %ecx80DISASM-NEXT: 103f: 50 pushl %eax
81DISASM-NEXT: 103f: 52 pushl %edx81DISASM-NEXT: 1040: 68 00 20 40 00 pushl $4202496
82DISASM-NEXT: 1040: 68 24 30 40 00 pushl $420662882DISASM-NEXT: 1045: e8 b6 ff ff ff calll -74 <.text>
83DISASM-NEXT: 1045: 68 00 20 40 00 pushl $420249683DISASM-NEXT: 104a: 5a popl %edx
84DISASM-NEXT: 104a: e8 b1 ff ff ff calll -79 <.text>84DISASM-NEXT: 104b: 59 popl %ecx
85DISASM-NEXT: 104f: 5a popl %edx85DISASM-NEXT: 104c: ff e0 jmpl *%eax
86DISASM-NEXT: 1050: 59 popl %ecx
87DISASM-NEXT: 1051: ff e0 jmpl *%eax
deps/lld/test/COFF/delayimporttables.yaml created+122
...@@ -0,0 +1,122 @@
1# RUN: yaml2obj %p/Inputs/delayimporttables-dll1.yaml > %t1.obj
2# RUN: yaml2obj %p/Inputs/delayimporttables-dll2.yaml > %t2.obj
3# RUN: yaml2obj %s > %t.obj
4# RUN: lld-link /nodefaultlib /entry:DllMain /out:%T/delayimporttables-dll1.dll /dll /implib:%t-dll1.lib %t1.obj
5# RUN: lld-link /nodefaultlib /entry:DllMain /out:%T/delayimporttables-dll2.dll /dll /implib:%t-dll2.lib %t2.obj
6# RUN: lld-link /nodefaultlib /entry:main /out:%t.exe /delayload:delayimporttables-dll1.dll /delayload:delayimporttables-dll2.dll %t.obj %t-dll1.lib %t-dll2.lib
7# RUN: llvm-readobj --coff-imports %t.exe |FileCheck %s
8
9# CHECK: Format: COFF-x86-64
10# CHECK-NEXT: Arch: x86_64
11# CHECK-NEXT: AddressSize: 64bit
12# CHECK-NEXT: DelayImport {
13# CHECK-NEXT: Name: delayimporttables-dll1.dll
14# CHECK-NEXT: Attributes: 0x1
15# CHECK-NEXT: ModuleHandle: 0x3000
16# CHECK-NEXT: ImportAddressTable: 0x3010
17# CHECK-NEXT: ImportNameTable: 0x2060
18# CHECK-NEXT: BoundDelayImportTable: 0x0
19# CHECK-NEXT: UnloadDelayImportTable: 0x0
20# CHECK-NEXT: Import {
21# CHECK-NEXT: Symbol: one (0)
22# CHECK-NEXT: Address: 0x14000104D
23# CHECK-NEXT: }
24# CHECK-NEXT: Import {
25# CHECK-NEXT: Symbol: two (0)
26# CHECK-NEXT: Address: 0x140001059
27# CHECK-NEXT: }
28# CHECK-NEXT: }
29# CHECK-NEXT: DelayImport {
30# CHECK-NEXT: Name: delayimporttables-dll2.dll
31# CHECK-NEXT: Attributes: 0x1
32# CHECK-NEXT: ModuleHandle: 0x3008
33# CHECK-NEXT: ImportAddressTable: 0x3028
34# CHECK-NEXT: ImportNameTable: 0x2078
35# CHECK-NEXT: BoundDelayImportTable: 0x0
36# CHECK-NEXT: UnloadDelayImportTable: 0x0
37# CHECK-NEXT: Import {
38# CHECK-NEXT: Symbol: left (0)
39# CHECK-NEXT: Address: 0x1400010B8
40# CHECK-NEXT: }
41# CHECK-NEXT: Import {
42# CHECK-NEXT: Symbol: right (0)
43# CHECK-NEXT: Address: 0x1400010C4
44# CHECK-NEXT: }
45# CHECK-NEXT: }
46
47--- !COFF
48header:
49 Machine: IMAGE_FILE_MACHINE_AMD64
50 Characteristics: [ ]
51sections:
52 - Name: .drectve
53 Characteristics: [ IMAGE_SCN_LNK_INFO, IMAGE_SCN_LNK_REMOVE ]
54 Alignment: 1
55 SectionData: 2020202F44454641554C544C49423A224C4942434D5422202F44454641554C544C49423A224F4C444E414D45532220
56 - Name: '.text$mn'
57 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
58 Alignment: 16
59 SectionData: 4889542410894C24084883EC28FF1500000000FF1500000000FF1500000000FF150000000033C04883C428C3CCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC488954241048894C240833C0C3
60 Relocations:
61 - VirtualAddress: 15
62 SymbolName: __imp_one
63 Type: IMAGE_REL_AMD64_REL32
64 - VirtualAddress: 21
65 SymbolName: __imp_two
66 Type: IMAGE_REL_AMD64_REL32
67 - VirtualAddress: 27
68 SymbolName: __imp_left
69 Type: IMAGE_REL_AMD64_REL32
70 - VirtualAddress: 33
71 SymbolName: __imp_right
72 Type: IMAGE_REL_AMD64_REL32
73symbols:
74 - Name: .drectve
75 Value: 0
76 SectionNumber: 1
77 SimpleType: IMAGE_SYM_TYPE_NULL
78 ComplexType: IMAGE_SYM_DTYPE_NULL
79 StorageClass: IMAGE_SYM_CLASS_STATIC
80 SectionDefinition:
81 Length: 47
82 NumberOfRelocations: 0
83 NumberOfLinenumbers: 0
84 CheckSum: 0
85 Number: 0
86 - Name: __imp_one
87 Value: 0
88 SectionNumber: 0
89 SimpleType: IMAGE_SYM_TYPE_NULL
90 ComplexType: IMAGE_SYM_DTYPE_NULL
91 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
92 - Name: __imp_two
93 Value: 0
94 SectionNumber: 0
95 SimpleType: IMAGE_SYM_TYPE_NULL
96 ComplexType: IMAGE_SYM_DTYPE_NULL
97 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
98 - Name: __imp_left
99 Value: 0
100 SectionNumber: 0
101 SimpleType: IMAGE_SYM_TYPE_NULL
102 ComplexType: IMAGE_SYM_DTYPE_NULL
103 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
104 - Name: __imp_right
105 Value: 0
106 SectionNumber: 0
107 SimpleType: IMAGE_SYM_TYPE_NULL
108 ComplexType: IMAGE_SYM_DTYPE_NULL
109 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
110 - Name: main
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: __delayLoadHelper2
117 Value: 64
118 SectionNumber: 2
119 SimpleType: IMAGE_SYM_TYPE_NULL
120 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
121 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
122...
deps/lld/test/COFF/dll.test+2-2
...@@ -42,10 +42,10 @@ EXPORT-LTO-NEXT: 3 0x1030 exportfn3...@@ -42,10 +42,10 @@ EXPORT-LTO-NEXT: 3 0x1030 exportfn3
42# RUN: /export:exportfn1 /export:exportfn242# RUN: /export:exportfn1 /export:exportfn2
43# RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj43# RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj
44# RUN: lld-link /out:%t2.exe /entry:main %t2.obj %t2.lib44# RUN: lld-link /out:%t2.exe /entry:main %t2.obj %t2.lib
45# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=IMPORT %s45# RUN: llvm-readobj --coff-imports %t2.exe | FileCheck -check-prefix=IMPORT %s
4646
47# RUN: lld-link /out:%t2.lto.exe /entry:main %t2.obj %t.lto.lib47# RUN: lld-link /out:%t2.lto.exe /entry:main %t2.obj %t.lto.lib
48# RUN: llvm-readobj -coff-imports %t2.lto.exe | FileCheck -check-prefix=IMPORT %s48# RUN: llvm-readobj --coff-imports %t2.lto.exe | FileCheck -check-prefix=IMPORT %s
4949
50IMPORT: Symbol: exportfn150IMPORT: Symbol: exportfn1
51IMPORT: Symbol: exportfn251IMPORT: Symbol: exportfn2
deps/lld/test/COFF/dllexport.s+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o %t.obj2# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o %t.obj
33
4# RUN: lld-link -entry:dllmain -dll %t.obj -out:%t.dll -implib:%t.lib4# RUN: lld-link -safeseh:no -entry:dllmain -dll %t.obj -out:%t.dll -implib:%t.lib
5# RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-IMPLIB %s5# RUN: llvm-readobj %t.lib | FileCheck -check-prefix DECORATED-IMPLIB %s
6# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix DECORATED-EXPORTS %s6# RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix DECORATED-EXPORTS %s
77
8# DECORATED-IMPLIB: Name type: name8# DECORATED-IMPLIB: Name type: name
9# DECORATED-IMPLIB-NEXT: __imp_@fastcall@89# DECORATED-IMPLIB-NEXT: __imp_@fastcall@8
deps/lld/test/COFF/dllimport-gc.test+2-2
...@@ -6,11 +6,11 @@...@@ -6,11 +6,11 @@
6# RUN: yaml2obj < %s > %t.obj6# RUN: yaml2obj < %s > %t.obj
77
8# RUN: lld-link /out:%t1.exe /entry:main %t.obj %t-oldname.obj %t.lib8# RUN: lld-link /out:%t1.exe /entry:main %t.obj %t-oldname.obj %t.lib
9# RUN: llvm-readobj -coff-imports %t1.exe | FileCheck -check-prefix=REF %s9# RUN: llvm-readobj --coff-imports %t1.exe | FileCheck -check-prefix=REF %s
10# REF-NOT: Symbol: exportfn110# REF-NOT: Symbol: exportfn1
1111
12# RUN: lld-link /out:%t2.exe /entry:main %t.obj %t-oldname.obj %t.lib /opt:noref12# RUN: lld-link /out:%t2.exe /entry:main %t.obj %t-oldname.obj %t.lib /opt:noref
13# RUN: llvm-readobj -coff-imports %t2.exe | FileCheck -check-prefix=NOREF %s13# RUN: llvm-readobj --coff-imports %t2.exe | FileCheck -check-prefix=NOREF %s
14# NOREF: Symbol: exportfn114# NOREF: Symbol: exportfn1
1515
16--- !COFF16--- !COFF
deps/lld/test/COFF/driver.test+23-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: not lld-link nosuchfile.obj >& %t.log1# RUN: not lld-link nosuchfile.obj >& %t.log
2# RUN: FileCheck -check-prefix=MISSING %s < %t.log2# RUN: FileCheck -check-prefix=MISSING %s < %t.log
3MISSING: nosuchfile.obj: {{[Nn]}}o such file or directory3MISSING: 'nosuchfile.obj': {{[Nn]}}o such file or directory
44
5# RUN: lld-link --version | FileCheck -check-prefix=VERSION %s5# RUN: lld-link --version | FileCheck -check-prefix=VERSION %s
6VERSION: {{LLD [0-9]+\.[0-9]+}}6VERSION: {{LLD [0-9]+\.[0-9]+}}
...@@ -15,3 +15,25 @@ LIBHELP: OVERVIEW: LLVM Lib...@@ -15,3 +15,25 @@ LIBHELP: OVERVIEW: LLVM Lib
1515
16# RUN: not lld-link /WX /lib 2>&1 | FileCheck -check-prefix=LIBBAD %s16# RUN: not lld-link /WX /lib 2>&1 | FileCheck -check-prefix=LIBBAD %s
17LIBBAD: ignoring /lib since it's not the first argument17LIBBAD: ignoring /lib since it's not the first argument
18
19# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
20# RUN: not lld-link /out:/ %t.obj 2>&1 | FileCheck -check-prefix=DIR %s
21DIR: cannot open output file
22
23# RUN: not lld-link -version 2>&1 | FileCheck -check-prefix=SPELLVERSION %s
24SPELLVERSION: ignoring unknown argument '-version', did you mean '--version'
25SPELLVERSION: no input files
26
27# RUN: not lld-link -nodefaultlibs 2>&1 | FileCheck -check-prefix=SPELLNODEFAULTLIB %s
28SPELLNODEFAULTLIB: ignoring unknown argument '-nodefaultlibs', did you mean '-nodefaultlib'
29SPELLNODEFAULTLIB: no input files
30
31# RUN: not lld-link /nodefaultlibs 2>&1 | FileCheck -check-prefix=SPELLNODEFAULTLIB_SLASH %s
32SPELLNODEFAULTLIB_SLASH: could not open '/nodefaultlibs': {{.*}}; did you mean '/nodefaultlib'
33SPELLNODEFAULTLIB_SLASH-NOT: no input files
34
35# Getting flags as typo corrections for normal input files is a side effect
36# of how spell checking for /-style flags is implemented.
37# RUN: not lld-link force 2>&1 | FileCheck -check-prefix=SPELLFORCE %s
38SPELLFORCE: could not open 'force': {{.*}}; did you mean '/force'
39SPELLFORCE-NOT: no input files
deps/lld/test/COFF/eh_frame_suffix_sorting.s created+39
...@@ -0,0 +1,39 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.main.o
4# RUN: llvm-mc -filetype=obj -triple=i686-windows-gnu \
5# RUN: %p/Inputs/eh_frame_terminator-crtend.s -o %t.crtend.o
6
7# RUN: lld-link -lldmingw -entry:main %t.main.o %t.crtend.o -out:%t.exe
8# RUN: llvm-objdump -s %t.exe | FileCheck %s
9
10# Check that the contents of .eh_frame$foo was placed before .eh_frame from
11# crtend.o, even if the former had a section name suffix.
12
13# CHECK: Contents of section .eh_fram:
14# CHECK: 403000 4203
15
16 .text
17 .def _main;
18 .scl 2;
19 .type 32;
20 .endef
21 .globl _main
22 .p2align 4, 0x90
23_main:
24 call _foo
25 ret
26
27 .section .eh_frame$foo,"dr"
28 .linkonce discard
29 .byte 0x42
30
31 .def _foo;
32 .scl 2;
33 .type 32;
34 .endef
35 .section .text$foo,"xr",discard,foo
36 .globl _foo
37 .p2align 4
38_foo:
39 ret
deps/lld/test/COFF/eh_frame_terminator.s created+26
...@@ -0,0 +1,26 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-windows-gnu %s -o %t.main.o
3// RUN: llvm-mc -filetype=obj -triple=x86_64-windows-gnu \
4// RUN: %p/Inputs/eh_frame_terminator-otherfunc.s -o %t.otherfunc.o
5// RUN: llvm-mc -filetype=obj -triple=x86_64-windows-gnu \
6// RUN: %p/Inputs/eh_frame_terminator-crtend.s -o %t.crtend.o
7// RUN: rm -f %t.otherfunc.lib
8// RUN: llvm-ar rcs %t.otherfunc.lib %t.otherfunc.o
9// RUN: lld-link -lldmingw %t.main.o %t.otherfunc.lib %t.crtend.o -out:%t.exe
10// RUN: llvm-objdump -s %t.exe | FileCheck %s
11
12 .text
13 .globl main
14main:
15 call otherfunc
16 ret
17
18 .globl mainCRTStartup
19mainCRTStartup:
20 call main
21
22 .section .eh_frame,"dr"
23 .byte 1
24
25// CHECK: Contents of section .eh_fram:
26// CHECK-NEXT: 140003000 010203
deps/lld/test/COFF/entry-drectve.test+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /subsystem:console /out:%t.exe %t.obj2# RUN: lld-link -safeseh:no /subsystem:console /out:%t.exe %t.obj
33
4--- !COFF4--- !COFF
5header:5header:
deps/lld/test/COFF/entry-inference-mingw.s+3-3
...@@ -5,9 +5,9 @@...@@ -5,9 +5,9 @@
5# RUN: lld-link -lldmingw %t.o -out:%t-cui.exe -subsystem:console 2>&1 | FileCheck -allow-empty -check-prefix=LINK %s5# 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 %s6# RUN: lld-link -lldmingw %t.o -out:%t-gui.exe -subsystem:windows 2>&1 | FileCheck -allow-empty -check-prefix=LINK %s
77
8# RUN: llvm-readobj -file-headers %t-default.exe | FileCheck -check-prefix=CUI %s8# 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 %s9# 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 %s10# RUN: llvm-readobj --file-headers %t-gui.exe | FileCheck -check-prefix=GUI %s
1111
12# Check that this doesn't print any warnings.12# Check that this doesn't print any warnings.
13# LINK-NOT: found both wmain and main13# LINK-NOT: found both wmain and main
deps/lld/test/COFF/entry-inference332.test+2-2
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1# RUN: sed -e s/ENTRYNAME/_mainCRTStartup/ %s | yaml2obj > %t.obj1# RUN: sed -e s/ENTRYNAME/_mainCRTStartup/ %s | yaml2obj > %t.obj
2# RUN: lld-link /subsystem:console /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&12# RUN: lld-link -safeseh:no /subsystem:console /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
3# RUN: FileCheck %s < %t.log3# RUN: FileCheck %s < %t.log
44
5# RUN: sed -e s/ENTRYNAME/?mainCRTStartup@@YAHXZ/ %s | yaml2obj > %t.obj5# RUN: sed -e s/ENTRYNAME/?mainCRTStartup@@YAHXZ/ %s | yaml2obj > %t.obj
6# RUN: lld-link /subsystem:console /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&16# RUN: lld-link -safeseh:no /subsystem:console /out:%t.exe %t.obj /verbose /nodefaultlib > %t.log 2>&1
7# RUN: FileCheck %s < %t.log7# RUN: FileCheck %s < %t.log
88
9# CHECK: Entry name inferred: _mainCRTStartup9# CHECK: Entry name inferred: _mainCRTStartup
deps/lld/test/COFF/error-limit.test+10-10
...@@ -1,26 +1,26 @@...@@ -1,26 +1,26 @@
1RUN: not lld-link 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 \1RUN: not lld-link 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 16 17 18 19 20 \
2RUN: 21 22 2>&1 | FileCheck -check-prefix=DEFAULT %s2RUN: 21 22 2>&1 | FileCheck -check-prefix=DEFAULT %s
33
4DEFAULT: could not open 014DEFAULT: could not open '01'
5DEFAULT: could not open 205DEFAULT: could not open '20'
6DEFAULT-NEXT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)6DEFAULT-NEXT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)
7DEFAULT-NOT: could not open 217DEFAULT-NOT: could not open '21'
88
9RUN: not lld-link /errorlimit:5 01 02 03 04 05 06 07 08 09 10 2>&1 \9RUN: not lld-link /errorlimit:5 01 02 03 04 05 06 07 08 09 10 2>&1 \
10RUN: | FileCheck -check-prefix=LIMIT5 %s10RUN: | FileCheck -check-prefix=LIMIT5 %s
1111
12LIMIT5: could not open 0112LIMIT5: could not open '01'
13LIMIT5: could not open 0513LIMIT5: could not open '05'
14LIMIT5-NEXT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)14LIMIT5-NEXT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)
15LIMIT5-NOT: could not open 0615LIMIT5-NOT: could not open '06'
1616
17RUN: not lld-link /errorlimit:0 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 \17RUN: not lld-link /errorlimit:0 01 02 03 04 05 06 07 08 09 10 11 12 13 14 15 \
18RUN: 16 17 18 19 20 21 22 2>&1 | FileCheck -check-prefix=UNLIMITED %s18RUN: 16 17 18 19 20 21 22 2>&1 | FileCheck -check-prefix=UNLIMITED %s
1919
20UNLIMITED: could not open 0120UNLIMITED: could not open '01'
21UNLIMITED: could not open 2021UNLIMITED: could not open '20'
22UNLIMITED: could not open 2122UNLIMITED: could not open '21'
23UNLIMITED: could not open 2223UNLIMITED: could not open '22'
24UNLIMITED-NOT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)24UNLIMITED-NOT: too many errors emitted, stopping now (use /errorlimit:0 to see all errors)
2525
26RUN: not lld-link /errorlimit:XYZ 01 02 03 04 05 06 07 08 09 10 11 12 13 14 \26RUN: not lld-link /errorlimit:XYZ 01 02 03 04 05 06 07 08 09 10 11 12 13 14 \
deps/lld/test/COFF/exclude-all.s created+31
...@@ -0,0 +1,31 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj
4
5# RUN: lld-link -lldmingw -exclude-all-symbols -dll -out:%t.dll -entry:DllMainCRTStartup@12 %t.obj
6# RUN: llvm-readobj --coff-exports %t.dll | FileCheck %s -check-prefix=NO-EXPORTS
7
8# NO-EXPORTS-NOT: Name:
9
10.global _foobar
11.global _DllMainCRTStartup@12
12.global _dataSym
13.text
14_DllMainCRTStartup@12:
15 ret
16_foobar:
17 ret
18.data
19_dataSym:
20 .int 4
21
22# Test specifying -exclude-all-symbols, on an object file that contains
23# dllexport directive for some of the symbols. In this case, the dllexported
24# symbols are still exported.
25
26# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
27#
28# RUN: lld-link -safeseh:no -out:%t.dll -dll %t.obj -lldmingw -exclude-all-symbols -output-def:%t.def
29# RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix=DLLEXPORT %s
30
31# DLLEXPORT: Name: exportfn3
deps/lld/test/COFF/export-all.s+5-5
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj3# RUN: llvm-mc -triple=i686-windows-gnu %s -filetype=obj -o %t.obj
44
5# RUN: lld-link -lldmingw -dll -out:%t.dll -entry:DllMainCRTStartup@12 %t.obj -implib:%t.lib5# RUN: lld-link -lldmingw -dll -out:%t.dll -entry:DllMainCRTStartup@12 %t.obj -implib:%t.lib
6# RUN: llvm-readobj -coff-exports %t.dll | grep Name: | FileCheck %s6# RUN: llvm-readobj --coff-exports %t.dll | grep Name: | FileCheck %s
7# RUN: llvm-readobj %t.lib | FileCheck -check-prefix=IMPLIB %s7# RUN: llvm-readobj %t.lib | FileCheck -check-prefix=IMPLIB %s
88
9# CHECK: Name:9# CHECK: Name:
...@@ -42,8 +42,8 @@ __imp__unexported:...@@ -42,8 +42,8 @@ __imp__unexported:
4242
43# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj43# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
44#44#
45# RUN: lld-link -out:%t.dll -dll %t.obj -lldmingw -export-all-symbols -output-def:%t.def45# RUN: lld-link -safeseh:no -out:%t.dll -dll %t.obj -lldmingw -export-all-symbols -output-def:%t.def
46# RUN: llvm-readobj -coff-exports %t.dll | FileCheck -check-prefix=CHECK2 %s46# RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix=CHECK2 %s
47# RUN: cat %t.def | FileCheck -check-prefix=CHECK2-DEF %s47# RUN: cat %t.def | FileCheck -check-prefix=CHECK2-DEF %s
4848
49# Note, this will actually export _DllMainCRTStartup as well, since49# Note, this will actually export _DllMainCRTStartup as well, since
...@@ -69,7 +69,7 @@ __imp__unexported:...@@ -69,7 +69,7 @@ __imp__unexported:
69# RUN: llvm-ar rcs %T/libs/libmingwex.a %T/libs/mingwfunc.o69# RUN: llvm-ar rcs %T/libs/libmingwex.a %T/libs/mingwfunc.o
70# RUN: echo -e ".global crtfunc\n.text\ncrtfunc:\nret\n" > %T/libs/crtfunc.s70# RUN: echo -e ".global crtfunc\n.text\ncrtfunc:\nret\n" > %T/libs/crtfunc.s
71# RUN: llvm-mc -triple=x86_64-windows-gnu %T/libs/crtfunc.s -filetype=obj -o %T/libs/crt2.o71# RUN: llvm-mc -triple=x86_64-windows-gnu %T/libs/crtfunc.s -filetype=obj -o %T/libs/crt2.o
72# RUN: lld-link -out:%t.dll -dll -entry:DllMainCRTStartup %t.main.obj -lldmingw %T/libs/crt2.o %T/libs/libmingwex.a -output-def:%t.def72# RUN: lld-link -safeseh:no -out:%t.dll -dll -entry:DllMainCRTStartup %t.main.obj -lldmingw %T/libs/crt2.o %T/libs/libmingwex.a -output-def:%t.def
73# RUN: echo "EOF" >> %t.def73# RUN: echo "EOF" >> %t.def
74# RUN: cat %t.def | FileCheck -check-prefix=CHECK-EXCLUDE %s74# RUN: cat %t.def | FileCheck -check-prefix=CHECK-EXCLUDE %s
7575
...@@ -80,7 +80,7 @@ __imp__unexported:...@@ -80,7 +80,7 @@ __imp__unexported:
80# Test that libraries included with -wholearchive: are autoexported, even if80# Test that libraries included with -wholearchive: are autoexported, even if
81# they are in a library that otherwise normally would be excluded.81# they are in a library that otherwise normally would be excluded.
8282
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.def83# RUN: lld-link -safeseh:no -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.def84# RUN: echo "EOF" >> %t.def
85# RUN: cat %t.def | FileCheck -check-prefix=CHECK-WHOLEARCHIVE %s85# RUN: cat %t.def | FileCheck -check-prefix=CHECK-WHOLEARCHIVE %s
8686
deps/lld/test/COFF/export-stdcall.s created+32
...@@ -0,0 +1,32 @@
1# REQUIRES: x86
2# RUN: llvm-mc -triple i686-windows-msvc %s -o %t.obj -filetype=obj
3# RUN: lld-link -safeseh:no %t.obj -out:%t.dll -dll -nodefaultlib -noentry -export:foo_std=bar_std -export:foo_fast=bar_fast
4# RUN: llvm-nm %t.lib | FileCheck %s
5
6# MSVC fudges the lookup of 'bar' to allow it to find the stdcall function
7# _bar_std@8, and then exports _foo_std@8. Same for fastcall and other mangling
8# schemes.
9
10# CHECK: export-stdcall.s.tmp.dll:
11# CHECK: 00000000 T @foo_fast@8
12# CHECK: 00000000 T __imp_@foo_fast@8
13
14# CHECK: export-stdcall.s.tmp.dll:
15# CHECK: 00000000 T __imp__foo_std@8
16# CHECK: 00000000 T _foo_std@8
17
18 .text
19 .def _bar_std@8; .scl 2; .type 32; .endef
20 .globl _bar_std@8
21_bar_std@8:
22 movl 8(%esp), %eax
23 movl 4(%esp), %ecx
24 leal 42(%ecx,%eax), %eax
25 retl $8
26
27 .def @bar_fast@8; .scl 2; .type 32; .endef
28 .globl @bar_fast@8
29@bar_fast@8:
30 leal 42(%ecx,%eax), %eax
31 retl
32
deps/lld/test/COFF/export-weak-alias.s created+33
...@@ -0,0 +1,33 @@
1# REQUIRES: x86
2# RUN: llvm-mc -triple x86_64-windows-msvc %s -o %t.obj -filetype=obj
3# RUN: lld-link %t.obj -out:%t.dll -dll -nodefaultlib -noentry
4# RUN: llvm-nm %t.lib | FileCheck %s
5
6# CHECK: export-weak-alias.s.tmp.dll:
7# CHECK: 00000000 T __imp_foo_dll{{$}}
8# CHECK: 00000000 T foo_dll{{$}}
9
10 .text
11 .def @feat.00;
12 .scl 3;
13 .type 0;
14 .endef
15 .globl @feat.00
16.set @feat.00, 0
17 .file "t.c"
18 .def foo_def;
19 .scl 2;
20 .type 32;
21 .endef
22 .globl foo_def # -- Begin function foo_def
23 .p2align 4, 0x90
24foo_def: # @foo_def
25# %bb.0: # %entry
26 movl $42, %eax
27 retq
28 # -- End function
29 .section .drectve,"yn"
30 .ascii " /alternatename:foo=foo_def"
31 .ascii " /export:foo_dll=foo"
32
33 .addrsig
deps/lld/test/COFF/export32.test+10-10
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2#2#
3# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn23# RUN: lld-link -safeseh:no /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2
4# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK1 %s4# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK1 %s
5#5#
6# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 /merge:.edata=.rdata6# RUN: lld-link -safeseh:no /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 /merge:.edata=.rdata
7# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK1 %s7# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK1 %s
8# RUN: llvm-readobj -file-headers -sections %t.dll | FileCheck -check-prefix=HEADER-MERGE %s8# RUN: llvm-readobj --file-headers --sections %t.dll | FileCheck -check-prefix=HEADER-MERGE %s
99
10# CHECK1: Export Table:10# CHECK1: Export Table:
11# CHECK1: DLL name: export32.test.tmp.dll11# CHECK1: DLL name: export32.test.tmp.dll
...@@ -20,7 +20,7 @@...@@ -20,7 +20,7 @@
20# HEADER-MERGE-NEXT: VirtualSize: 0x7E20# HEADER-MERGE-NEXT: VirtualSize: 0x7E
21# HEADER-MERGE-NEXT: VirtualAddress: 0x200021# HEADER-MERGE-NEXT: VirtualAddress: 0x2000
2222
23# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1,@5 \23# RUN: lld-link -safeseh:no /out:%t.dll /dll %t.obj /export:exportfn1,@5 \
24# RUN: /export:exportfn2 /export:mangled24# RUN: /export:exportfn2 /export:mangled
25# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK2 %s25# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK2 %s
2626
...@@ -37,7 +37,7 @@...@@ -37,7 +37,7 @@
37# CHECK2-NEXT: 7 0x1010 exportfn337# CHECK2-NEXT: 7 0x1010 exportfn3
38# CHECK2-NEXT: 8 0x1010 mangled38# CHECK2-NEXT: 8 0x1010 mangled
3939
40# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1,@5,noname /export:exportfn240# RUN: lld-link -safeseh:no /out:%t.dll /dll %t.obj /export:exportfn1,@5,noname /export:exportfn2
41# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK3 %s41# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK3 %s
4242
43# CHECK3: Export Table:43# CHECK3: Export Table:
...@@ -51,7 +51,7 @@...@@ -51,7 +51,7 @@
51# CHECK3-NEXT: 5 0x100851# CHECK3-NEXT: 5 0x1008
52# CHECK3-NEXT: 6 0x1010 exportfn252# CHECK3-NEXT: 6 0x1010 exportfn2
5353
54# RUN: lld-link /out:%t.dll /dll %t.obj /export:f1=exportfn1 /export:f2=exportfn254# RUN: lld-link -safeseh:no /out:%t.dll /dll %t.obj /export:f1=exportfn1 /export:f2=exportfn2
55# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK4 %s55# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK4 %s
5656
57# CHECK4: Export Table:57# CHECK4: Export Table:
...@@ -64,12 +64,12 @@...@@ -64,12 +64,12 @@
6464
65# RUN: echo "EXPORTS exportfn1 @3" > %t.def65# RUN: echo "EXPORTS exportfn1 @3" > %t.def
66# RUN: echo "fn2=exportfn2 @2" >> %t.def66# RUN: echo "fn2=exportfn2 @2" >> %t.def
67# RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def67# RUN: lld-link -safeseh:no /out:%t.dll /dll %t.obj /def:%t.def
68# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s68# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s
6969
70# RUN: echo "EXPORTS exportfn1 @ 3" > %t.def70# RUN: echo "EXPORTS exportfn1 @ 3" > %t.def
71# RUN: echo "fn2=exportfn2 @ 2" >> %t.def71# RUN: echo "fn2=exportfn2 @ 2" >> %t.def
72# RUN: lld-link /out:%t.dll /dll %t.obj /def:%t.def72# RUN: lld-link -safeseh:no /out:%t.dll /dll %t.obj /def:%t.def
73# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s73# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK5 %s
7474
75# CHECK5: Export Table:75# CHECK5: Export Table:
...@@ -81,14 +81,14 @@...@@ -81,14 +81,14 @@
81# CHECK5-NEXT: 3 0x1008 exportfn181# CHECK5-NEXT: 3 0x1008 exportfn1
82# CHECK5-NEXT: 4 0x1010 exportfn382# CHECK5-NEXT: 4 0x1010 exportfn3
8383
84# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 \84# RUN: lld-link -safeseh:no /out:%t.dll /dll %t.obj /export:exportfn1 /export:exportfn2 \
85# RUN: /export:exportfn1 /export:exportfn2,@5 >& %t.log85# RUN: /export:exportfn1 /export:exportfn2,@5 >& %t.log
86# RUN: FileCheck -check-prefix=CHECK6 %s < %t.log86# RUN: FileCheck -check-prefix=CHECK6 %s < %t.log
8787
88# CHECK6: duplicate /export option: _exportfn288# CHECK6: duplicate /export option: _exportfn2
89# CHECK6-NOT: duplicate /export option: _exportfn189# CHECK6-NOT: duplicate /export option: _exportfn1
9090
91# RUN: lld-link /out:%t.dll /dll %t.obj /export:foo=mangled91# RUN: lld-link -safeseh:no /out:%t.dll /dll %t.obj /export:foo=mangled
92# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK7 %s92# RUN: llvm-objdump -p %t.dll | FileCheck -check-prefix=CHECK7 %s
9393
94# CHECK7: Export Table:94# CHECK7: Export Table:
deps/lld/test/COFF/failifmismatch.test+29-8
...@@ -1,11 +1,32 @@...@@ -1,11 +1,32 @@
1# RUN: lld-link /entry:main /subsystem:console /out:%t.exe \1REQUIRES: x86
2# RUN: %p/Inputs/ret42.obj
32
4# RUN: lld-link /entry:main /subsystem:console /out:%t.exe \3RUN: lld-link /entry:main /subsystem:console /out:%t.exe \
5# RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k2=v14RUN: %p/Inputs/ret42.obj
65
7# RUN: lld-link /entry:main /subsystem:console /out:%t.exe \6RUN: lld-link /entry:main /subsystem:console /out:%t.exe \
8# RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v17RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k2=v1
98
10# RUN: not lld-link /entry:main /subsystem:console /out:%t.exe \9RUN: lld-link /entry:main /subsystem:console /out:%t.exe \
11# RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v210RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v1
11
12RUN: not lld-link /entry:main /subsystem:console /out:%t.exe \
13RUN: %p/Inputs/ret42.obj /failifmismatch:k1=v1 /failifmismatch:k1=v2 2>&1 | FileCheck %s
14
15RUN: llc < %p/Inputs/failmismatch1.ll -mtriple x86_64-windows-msvc -filetype obj -o %t1.obj
16RUN: llc < %p/Inputs/failmismatch2.ll -mtriple x86_64-windows-msvc -filetype obj -o %t2.obj
17RUN: not lld-link %t1.obj %t2.obj 2>&1 | FileCheck %s -check-prefix OBJ
18
19RUN: llvm-lib %t1.obj /out:%t.lib
20RUN: not lld-link %t.lib %t2.obj 2>&1 | FileCheck %s -check-prefix LIB
21
22CHECK: lld-link: error: /failifmismatch: mismatch detected for 'k1':
23CHECK-NEXT: >>> cmd-line has value v1
24CHECK-NEXT: >>> cmd-line has value v2
25
26OBJ: lld-link: error: /failifmismatch: mismatch detected for 'TEST':
27OBJ-NEXT: >>> {{.*}}failifmismatch.test.tmp1.obj has value 1
28OBJ-NEXT: >>> {{.*}}failifmismatch.test.tmp2.obj has value 2
29
30LIB: lld-link: error: /failifmismatch: mismatch detected for 'TEST':
31LIB-NEXT: >>> {{.*}}failifmismatch.test.tmp2.obj has value 2
32LIB-NEXT: >>> failifmismatch.test.tmp.lib(failifmismatch.test.tmp1.obj) has value 1
deps/lld/test/COFF/filealign.test created+51
...@@ -0,0 +1,51 @@
1# RUN: yaml2obj < %s > %t.obj
2
3# RUN: lld-link /out:%t.exe /entry:main %t.obj
4# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=DEFAULT-HEADER %s
5
6# DEFAULT-HEADER: FileAlignment: 512
7
8# RUN: lld-link /out:%t.exe /entry:main %t.obj /filealign:4096
9# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=FILEALIGN-HEADER %s
10
11# FILEALIGN-HEADER: FileAlignment: 4096
12
13--- !COFF
14header:
15 Machine: IMAGE_FILE_MACHINE_AMD64
16 Characteristics: []
17sections:
18 - Name: .text
19 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
20 Alignment: 4096
21 SectionData: 0000000000000000
22 Relocations:
23 - VirtualAddress: 0
24 SymbolName: __ImageBase
25 Type: IMAGE_REL_AMD64_ADDR64
26symbols:
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: 8
35 NumberOfRelocations: 1
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 - Name: __ImageBase
46 Value: 0
47 SectionNumber: 0
48 SimpleType: IMAGE_SYM_TYPE_NULL
49 ComplexType: IMAGE_SYM_DTYPE_NULL
50 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
51...
deps/lld/test/COFF/fixed.test+8-8
...@@ -1,22 +1,22 @@...@@ -1,22 +1,22 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj2# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
3#3#
4# RUN: lld-link %t.obj /fixed %p/Inputs/std32.lib /subsystem:console \4# RUN: lld-link -safeseh:no %t.obj /fixed %p/Inputs/std32.lib /subsystem:console \
5# RUN: /entry:main@0 /debug /out:%t.fixed.exe5# RUN: /entry:main@0 /debug /out:%t.fixed.exe
6# RUN: llvm-readobj -file-headers %t.fixed.exe | \6# RUN: llvm-readobj --file-headers %t.fixed.exe | \
7# RUN: FileCheck -check-prefix=EXEFIXED %s7# RUN: FileCheck -check-prefix=EXEFIXED %s
8#8#
9# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \9# RUN: lld-link -safeseh:no %t.obj %p/Inputs/std32.lib /subsystem:console \
10# RUN: /entry:main@0 /debug /out:%t.exe10# RUN: /entry:main@0 /debug /out:%t.exe
11# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=EXEREL %s11# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=EXEREL %s
12#12#
13# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj13# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
14#14#
15# RUN: lld-link %t.obj /dll /fixed /debug /out:%t.fixed.dll15# RUN: lld-link -safeseh:no %t.obj /dll /fixed /debug /out:%t.fixed.dll
16# RUN: llvm-readobj -file-headers %t.fixed.dll | FileCheck -check-prefix=DLLFIXED %s16# RUN: llvm-readobj --file-headers %t.fixed.dll | FileCheck -check-prefix=DLLFIXED %s
17#17#
18# RUN: lld-link %t.obj /dll /debug /out:%t.dll18# RUN: lld-link -safeseh:no %t.obj /dll /debug /out:%t.dll
19# RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=DLLREL %s19# RUN: llvm-readobj --file-headers %t.dll | FileCheck -check-prefix=DLLREL %s
2020
21EXEFIXED-NOT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE21EXEFIXED-NOT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
22DLLFIXED-NOT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE22DLLFIXED-NOT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE
deps/lld/test/COFF/force-multipleres.test created+21
...@@ -0,0 +1,21 @@
1// Check that lld-link rejects duplicate resources, unless
2// /force or /force:multipleres is passed.
3// The input was generated with the following command, using the original Windows
4// rc.exe:
5// > rc /fo id.res /nologo id.rc
6// > rc /fo name.res /nologo name.rc
7
8RUN: rm -rf %t.dir
9RUN: mkdir %t.dir
10RUN: cp %S/Inputs/id.res %t.dir/id1.res
11RUN: cp %S/Inputs/id.res %t.dir/id2.res
12
13RUN: not lld-link /machine:x64 /nodefaultlib /noentry /dll %t.dir/id1.res %t.dir/id2.res 2>&1 | \
14RUN: FileCheck -check-prefix=ERR %s
15ERR: error: duplicate resource: type STRINGTABLE (ID 6)/name ID 3/language 1033, in {{.*}}id1.res and in {{.*}}id2.res
16
17RUN: lld-link /force /machine:x64 /nodefaultlib /noentry /dll %t.dir/id1.res %t.dir/id2.res 2>&1 | \
18RUN: FileCheck -check-prefix=WARN %s
19RUN: lld-link /force:multipleres /machine:x64 /nodefaultlib /noentry /dll %t.dir/id1.res %t.dir/id2.res 2>&1 | \
20RUN: FileCheck -check-prefix=WARN %s
21WARN: warning: duplicate resource: type STRINGTABLE (ID 6)/name ID 3/language 1033, in {{.*}}id1.res and in {{.*}}id2.res
deps/lld/test/COFF/functionpadmin.test created+147
...@@ -0,0 +1,147 @@
1// ---- precomp-a.obj - x86_64, hotpatch
2RUN: lld-link %S/Inputs/precomp-a.obj /out:%t.exe /nodefaultlib /force
3RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix BASE
4
5RUN: lld-link %S/Inputs/precomp-a.obj /out:%t.exe /nodefaultlib /force /functionpadmin
6RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix PADDED
7
8RUN: lld-link %S/Inputs/precomp-a.obj /out:%t.exe /nodefaultlib /force /functionpadmin:17
9RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix PADDED-MORE
10
11// ---- Many arguments
12RUN: lld-link %S/Inputs/precomp-a.obj /out:%t.exe /nodefaultlib /force /functionpadmin:17 /functionpadmin
13RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix PADDED
14
15RUN: lld-link %S/Inputs/precomp-a.obj /out:%t.exe /nodefaultlib /force /functionpadmin /functionpadmin:17
16RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix PADDED-MORE
17
18RUN: not lld-link %S/Inputs/precomp-a.obj /out:%t.exe /nodefaultlib /force /functionpadmin:zz 2>&1 | FileCheck %s --check-prefix FAIL
19
20// ---- precomp-a.obj, precomp-b.obj - x86_64, hotpatch - Ensure several functions are properly padded
21RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /out:%t.exe /nodefaultlib /force
22RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix MULTI-BASE
23
24RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /out:%t.exe /nodefaultlib /force /functionpadmin
25RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix MULTI-BASE-PADDED
26
27RUN: lld-link %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj %S/Inputs/precomp.obj /out:%t.exe /nodefaultlib /force /functionpadmin:17
28RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix MULTI-BASE-PADDED-MORE
29
30// ---- pdb-diff.obj - x86, no hotpatch - No padding is applied
31RUN: lld-link %S/Inputs/pdb-diff.obj /out:%t.exe /nodefaultlib /force /functionpadmin
32RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix NO-HOTPATCH
33
34// ---- hello64.obj - MASM, x86_64, no hotpatch - No padding is applied
35RUN: lld-link %S/Inputs/hello64.obj /out:%t.exe /nodefaultlib /force /functionpadmin
36RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix HELLO
37
38// ---- std64.lib - Import library, x86_64 - Ensure thunks are padded
39RUN: lld-link %S/Inputs/std64.lib /entry:ExitProcess /out:%t.exe /nodefaultlib /force /subsystem:console
40RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix THUNKS-NO-PAD
41RUN: llvm-readobj --file-headers %t.exe | FileCheck %s --check-prefix THUNKS-NO-PAD-ENTRY
42
43RUN: lld-link %S/Inputs/std64.lib /entry:ExitProcess /out:%t.exe /nodefaultlib /force /functionpadmin /subsystem:console
44RUN: llvm-objdump -s %t.exe | FileCheck %s --check-prefix THUNKS-PAD
45RUN: llvm-readobj --file-headers %t.exe | FileCheck %s --check-prefix THUNKS-PAD-ENTRY
46
47BASE: Contents of section .text:
48BASE-NEXT: 140001000 4883ec28 b161e8f5 efffbf33 c04883c4 H..(.a.....3.H..
49BASE-NEXT: 140001010 28c3 (.
50BASE-NEXT: Contents of section .rdata:
51BASE-NEXT: 140002000 01040100 04420000 .....B..
52BASE-NEXT: Contents of section .pdata:
53BASE-NEXT: 140003000 00100000 12100000 00200000 ......... ..
54
55PADDED: Contents of section .text:
56PADDED-NEXT: 140001000 cccccccc cccccccc cccccccc cccccccc ................
57PADDED-NEXT: 140001010 4883ec28 b161e8e5 efffbf33 c04883c4 H..(.a.....3.H..
58PADDED-NEXT: 140001020 28c3 (.
59PADDED-NEXT: Contents of section .rdata:
60PADDED-NEXT: 140002000 01040100 04420000 .....B..
61PADDED-NEXT: Contents of section .pdata:
62PADDED-NEXT: 140003000 10100000 22100000 00200000 ....".... ..
63
64PADDED-MORE: Contents of section .text:
65PADDED-MORE-NEXT: 140001000 cccccccc cccccccc cccccccc cccccccc ................
66PADDED-MORE-NEXT: 140001010 cccccccc cccccccc cccccccc cccccccc ................
67PADDED-MORE-NEXT: 140001020 4883ec28 b161e8d5 efffbf33 c04883c4 H..(.a.....3.H..
68PADDED-MORE-NEXT: 140001030 28c3 (.
69PADDED-MORE-NEXT: Contents of section .rdata:
70PADDED-MORE-NEXT: 140002000 01040100 04420000 .....B..
71PADDED-MORE-NEXT: Contents of section .pdata:
72PADDED-MORE-NEXT: 140003000 20100000 32100000 00200000 ...2.... ..
73
74FAIL: lld-link: error: /functionpadmin: invalid argument: zz
75
76MULTI-BASE: Contents of section .text:
77MULTI-BASE-NEXT: 140001000 4883ec28 b161e815 00000033 c04883c4 H..(.a.....3.H..
78MULTI-BASE-NEXT: 140001010 28c3cccc cccccccc cccccccc cccccccc (...............
79MULTI-BASE-NEXT: 140001020 884c2408 0fbe4424 08c3 .L$...D$..
80MULTI-BASE-NEXT: Contents of section .rdata:
81MULTI-BASE-NEXT: 140002000 01040100 04420000 .....B..
82MULTI-BASE-NEXT: Contents of section .pdata:
83MULTI-BASE-NEXT: 140004000 00100000 12100000 00200000 ......... ..
84
85MULTI-BASE-PADDED: Contents of section .text:
86MULTI-BASE-PADDED-NEXT: 140001000 cccccccc cccccccc cccccccc cccccccc ................
87MULTI-BASE-PADDED-NEXT: 140001010 4883ec28 b161e815 00000033 c04883c4 H..(.a.....3.H..
88MULTI-BASE-PADDED-NEXT: 140001020 28c3cccc cccccccc cccccccc cccccccc (...............
89MULTI-BASE-PADDED-NEXT: 140001030 884c2408 0fbe4424 08c3 .L$...D$..
90MULTI-BASE-PADDED-NEXT: Contents of section .rdata:
91MULTI-BASE-PADDED-NEXT: 140002000 01040100 04420000 .....B..
92MULTI-BASE-PADDED-NEXT: Contents of section .pdata:
93MULTI-BASE-PADDED-NEXT: 140004000 10100000 22100000 00200000 ....".... ..
94
95MULTI-BASE-PADDED-MORE: Contents of section .text:
96MULTI-BASE-PADDED-MORE-NEXT: 140001000 cccccccc cccccccc cccccccc cccccccc ................
97MULTI-BASE-PADDED-MORE-NEXT: 140001010 cccccccc cccccccc cccccccc cccccccc ................
98MULTI-BASE-PADDED-MORE-NEXT: 140001020 4883ec28 b161e825 00000033 c04883c4 H..(.a.%...3.H..
99MULTI-BASE-PADDED-MORE-NEXT: 140001030 28c3cccc cccccccc cccccccc cccccccc (...............
100MULTI-BASE-PADDED-MORE-NEXT: 140001040 cccccccc cccccccc cccccccc cccccccc ................
101MULTI-BASE-PADDED-MORE-NEXT: 140001050 884c2408 0fbe4424 08c3 .L$...D$..
102MULTI-BASE-PADDED-MORE-NEXT: Contents of section .rdata:
103MULTI-BASE-PADDED-MORE-NEXT: 140002000 01040100 04420000 .....B..
104MULTI-BASE-PADDED-MORE-NEXT: Contents of section .pdata:
105MULTI-BASE-PADDED-MORE-NEXT: 140004000 20100000 32100000 00200000 ...2.... ..
106
107
108NO-HOTPATCH: Contents of section .text:
109NO-HOTPATCH-NEXT: 401000 558becb8 2a000000 5dc3 U...*...].
110
111HELLO: Contents of section .text:
112HELLO-NEXT: 140001000 4883ec28 48c7c100 00000048 8d15f40f H..(H......H....
113HELLO-NEXT: 140001010 00004c8d 05e70f00 0041b900 000000e8 ..L......A......
114HELLO-NEXT: 140001020 dcefffbf b9000000 00e8d2ef ffbfe8cd ................
115HELLO-NEXT: 140001030 efffbf ...
116HELLO-NEXT: Contents of section .data:
117HELLO-NEXT: 140002000 48656c6c 6f004865 6c6c6f20 576f726c Hello.Hello Worl
118HELLO-NEXT: 140002010 642100 d!.
119
120THUNKS-NO-PAD: Contents of section .text:
121THUNKS-NO-PAD-NEXT: 140001000 ff253210 0000 .%2...
122THUNKS-NO-PAD-NEXT: Contents of section .rdata:
123THUNKS-NO-PAD-NEXT: 140002000 28200000 00000000 00000000 56200000 ( ..........V ..
124THUNKS-NO-PAD-NEXT: 140002010 38200000 00000000 00000000 00000000 8 ..............
125THUNKS-NO-PAD-NEXT: 140002020 00000000 00000000 48200000 00000000 ........H ......
126THUNKS-NO-PAD-NEXT: 140002030 00000000 00000000 48200000 00000000 ........H ......
127THUNKS-NO-PAD-NEXT: 140002040 00000000 00000000 00004578 69745072 ..........ExitPr
128THUNKS-NO-PAD-NEXT: 140002050 6f636573 73007374 6436342e 646c6c00 ocess.std64.dll.
129
130THUNKS-NO-PAD-ENTRY-LABEL: ImageOptionalHeader {
131THUNKS-NO-PAD-ENTRY: AddressOfEntryPoint: 0x1000
132THUNKS-NO-PAD-ENTRY-NEXT: BaseOfCode: 0x1000
133
134THUNKS-PAD: Contents of section .text:
135THUNKS-PAD-NEXT: 140001000 cccccccc cccccccc cccccccc cccccccc ................
136THUNKS-PAD-NEXT: 140001010 ff252210 0000 .%"...
137THUNKS-PAD-NEXT: Contents of section .rdata:
138THUNKS-PAD-NEXT: 140002000 28200000 00000000 00000000 56200000 ( ..........V ..
139THUNKS-PAD-NEXT: 140002010 38200000 00000000 00000000 00000000 8 ..............
140THUNKS-PAD-NEXT: 140002020 00000000 00000000 48200000 00000000 ........H ......
141THUNKS-PAD-NEXT: 140002030 00000000 00000000 48200000 00000000 ........H ......
142THUNKS-PAD-NEXT: 140002040 00000000 00000000 00004578 69745072 ..........ExitPr
143THUNKS-PAD-NEXT: 140002050 6f636573 73007374 6436342e 646c6c00 ocess.std64.dll.
144
145THUNKS-PAD-ENTRY-LABEL: ImageOptionalHeader {
146THUNKS-PAD-ENTRY: AddressOfEntryPoint: 0x1010
147THUNKS-PAD-ENTRY-NEXT: BaseOfCode: 0x1000
deps/lld/test/COFF/gfids-corrupt.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj2# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj
3# RUN: lld-link %t.obj -opt:noref -guard:nolongjmp -out:%t.exe -entry:main 2>&1 | FileCheck %s --check-prefix=ERRS3# RUN: lld-link %t.obj -opt:noref -guard:nolongjmp -out:%t.exe -entry:main 2>&1 | FileCheck %s --check-prefix=ERRS
4# RUN: llvm-readobj -file-headers -coff-load-config %t.exe | FileCheck %s4# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s
55
6# ERRS: warning: ignoring .gfids$y symbol table index section in object {{.*}}gfids-corrupt{{.*}}6# ERRS: warning: ignoring .gfids$y symbol table index section in object {{.*}}gfids-corrupt{{.*}}
7# ERRS: warning: ignoring invalid symbol table index in section .gfids$y in object {{.*}}gfids-corrupt{{.*}}7# ERRS: warning: ignoring invalid symbol table index in section .gfids$y in object {{.*}}gfids-corrupt{{.*}}
deps/lld/test/COFF/gfids-export.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple x86_64-pc-win32 %s -filetype=obj -o %t.obj2# 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 -noentry3# 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=CHECK4# RUN: llvm-readobj --coff-load-config %t.dll | FileCheck %s --check-prefix=CHECK
55
6# There should be a single entry in the table for the exported symbol.6# There should be a single entry in the table for the exported symbol.
7#7#
deps/lld/test/COFF/gfids-fallback.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: grep -B99999 [S]PLITMARKER %s | llvm-mc -triple x86_64-windows-msvc -filetype=obj -o %t1.obj2# RUN: grep -B99999 [S]PLITMARKER %s | llvm-mc -triple x86_64-windows-msvc -filetype=obj -o %t1.obj
3# RUN: grep -A99999 [S]PLITMARKER %s | llvm-mc -triple x86_64-windows-msvc -filetype=obj -o %t2.obj3# RUN: grep -A99999 [S]PLITMARKER %s | llvm-mc -triple x86_64-windows-msvc -filetype=obj -o %t2.obj
4# RUN: lld-link %t1.obj %t2.obj -guard:nolongjmp -out:%t.exe -entry:main -opt:noref4# RUN: lld-link %t1.obj %t2.obj -guard:nolongjmp -out:%t.exe -entry:main -opt:noref
5# RUN: llvm-readobj -file-headers -coff-load-config %t.exe | FileCheck %s5# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s
66
7# CHECK: ImageBase: 0x1400000007# CHECK: ImageBase: 0x140000000
8# CHECK: LoadConfig [8# CHECK: LoadConfig [
deps/lld/test/COFF/gfids-gc.s+3-3
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj2# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj
3# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:noref -entry:main3# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:noref -entry:main
4# RUN: llvm-readobj -file-headers -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-NOGC4# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-NOGC
5# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:noref -entry:main -debug:dwarf5# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:noref -entry:main -debug:dwarf
6# RUN: llvm-readobj -file-headers -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-NOGC6# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-NOGC
7# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:ref -entry:main7# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:ref -entry:main
8# RUN: llvm-readobj -file-headers -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-GC8# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK-GC
99
10# This assembly is meant to mimic what CL emits for this kind of C code when10# This assembly is meant to mimic what CL emits for this kind of C code when
11# /Gw (-fdata-sections) is enabled:11# /Gw (-fdata-sections) is enabled:
deps/lld/test/COFF/gfids-icf.s+11-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj2# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj
3# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:icf -entry:main3# RUN: lld-link %t.obj -guard:nolongjmp -out:%t.exe -opt:icf -entry:main
4# RUN: llvm-readobj -file-headers -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK4# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK
55
6# This assembly is meant to mimic what CL emits for this kind of C code:6# This assembly is meant to mimic what CL emits for this kind of C code:
7# int icf1() { return 42; }7# int icf1() { return 42; }
...@@ -35,6 +35,16 @@...@@ -35,6 +35,16 @@
35# CHECK-NEXT: 0x14000{{.*}}35# CHECK-NEXT: 0x14000{{.*}}
36# CHECK-NEXT: ]36# CHECK-NEXT: ]
3737
38# There should be no .gfids section in the output exectuable when we link with
39# -guard:cf or with no -guard:cf/nolongjmp flag.
40# RUN: llvm-readobj --sections %t.exe | FileCheck %s --check-prefix NOGFIDSEC
41# RUN: lld-link %t.obj -out:%t.exe -opt:icf -entry:main
42# RUN: llvm-readobj --sections %t.exe | FileCheck %s --check-prefix NOGFIDSEC
43
44# NOGFIDSEC: Sections [
45# NOGFIDSEC: Section {
46# NOGFIDSEC: Name: .text
47# NOGFIDSEC-NOT: Name: .gfids
3848
39# Indicate that gfids are present.49# Indicate that gfids are present.
40 .def @feat.00; .scl 3; .type 0; .endef50 .def @feat.00; .scl 3; .type 0; .endef
deps/lld/test/COFF/gfids-relocations32.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple i686-pc-win32 %s -filetype=obj -o %t.obj2# 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:main3# RUN: lld-link -safeseh:no %t.obj -guard:cf -out:%t.exe -entry:main
4# RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK4# RUN: llvm-readobj --coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK
55
6# Only f and _main should go in the table.6# Only f and _main should go in the table.
7# (use /lldmap:map.txt to check their addresses).7# (use /lldmap:map.txt to check their addresses).
deps/lld/test/COFF/gfids-relocations64.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple x86_64-pc-win32 %s -filetype=obj -o %t.obj2# 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:main3# 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=CHECK4# RUN: llvm-readobj --coff-load-config %t.exe | FileCheck %s --check-prefix=CHECK
55
6# f, g, and main go in the table.6# f, g, and main go in the table.
7# Including g isn't strictly necessary since it's not an indirect call target,7# Including g isn't strictly necessary since it's not an indirect call target,
deps/lld/test/COFF/guard-longjmp.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj2# RUN: llvm-mc -triple x86_64-windows-msvc %s -filetype=obj -o %t.obj
3# RUN: lld-link %t.obj -guard:cf -out:%t.exe -entry:main3# RUN: lld-link %t.obj -guard:cf -out:%t.exe -entry:main
4# RUN: llvm-readobj -file-headers -coff-load-config %t.exe | FileCheck %s4# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s
55
6# CHECK: ImageBase: 0x1400000006# CHECK: ImageBase: 0x140000000
7# CHECK: LoadConfig [7# CHECK: LoadConfig [
deps/lld/test/COFF/guardcf-align.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: > %T/guardcf-align-foobar.obj4# RUN: > %T/guardcf-align-foobar.obj
5# RUN: lld-link -out:%T/guardcf-align.exe -entry:main -guard:cf \5# RUN: lld-link -out:%T/guardcf-align.exe -entry:main -guard:cf \
6# RUN: %t.obj %T/guardcf-align-foobar.obj6# RUN: %t.obj %T/guardcf-align-foobar.obj
7# RUN: llvm-readobj -coff-load-config %T/guardcf-align.exe | FileCheck %s7# RUN: llvm-readobj --coff-load-config %T/guardcf-align.exe | FileCheck %s
88
9# Check that the gfids table contains at least one entry that ends in 09# Check that the gfids table contains at least one entry that ends in 0
10# and no entries that end in something other than 0.10# and no entries that end in something other than 0.
deps/lld/test/COFF/guardcf-lto.ll+1-1
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
99
10; RUN: llvm-as %s -o %t.bc10; RUN: llvm-as %s -o %t.bc
11; RUN: lld-link -entry:main -guard:cf -dll %t.bc %t.lib %t.ldcfg.obj -out:%t.dll11; RUN: lld-link -entry:main -guard:cf -dll %t.bc %t.lib %t.ldcfg.obj -out:%t.dll
12; RUN: llvm-readobj -coff-load-config %t.dll | FileCheck %s12; RUN: llvm-readobj --coff-load-config %t.dll | FileCheck %s
1313
14; There must be *two* entries in the table: DLL entry point, and my_handler.14; There must be *two* entries in the table: DLL entry point, and my_handler.
1515
deps/lld/test/COFF/guardcf-thunk.s created+43
...@@ -0,0 +1,43 @@
1# REQUIRES: x86
2
3# Make a DLL that exports exportfn1.
4# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
5# RUN: lld-link /out:%t.dll /dll %t.obj /export:exportfn1 /implib:%t.lib
6
7# Make an obj that takes the address of that exported function.
8# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc %s -o %t2.obj
9# RUN: lld-link -entry:main -guard:cf %t2.obj %t.lib -nodefaultlib -out:%t.exe
10# RUN: llvm-readobj --coff-load-config %t.exe | FileCheck %s
11
12# Check that the gfids table contains *exactly* two entries, one for exportfn1
13# and one for main.
14# CHECK: GuardFidTable [
15# CHECK-NEXT: 0x{{[0-9A-Fa-f]+0$}}
16# CHECK-NEXT: 0x{{[0-9A-Fa-f]+0$}}
17# CHECK-NEXT: ]
18
19
20 .def @feat.00;
21 .scl 3;
22 .type 0;
23 .endef
24 .globl @feat.00
25@feat.00 = 0x001
26
27 .section .text,"rx"
28 .def main; .scl 2; .type 32; .endef
29 .global main
30main:
31 leaq exportfn1(%rip), %rax
32 retq
33
34 .section .rdata,"dr"
35.globl _load_config_used
36_load_config_used:
37 .long 256
38 .fill 124, 1, 0
39 .quad __guard_fids_table
40 .quad __guard_fids_count
41 .long __guard_flags
42 .fill 128, 1, 0
43
deps/lld/test/COFF/header-size.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-windows %s -o %t.obj2// 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.exe3// RUN: lld-link -entry:main -subsystem:console %t.obj -out:%t.exe
4// RUN: llvm-readobj -sections %t.exe | FileCheck %s4// RUN: llvm-readobj --sections %t.exe | FileCheck %s
5 .globl main5 .globl main
6main:6main:
7 ret7 ret
deps/lld/test/COFF/heap.test+5-5
...@@ -1,25 +1,25 @@...@@ -1,25 +1,25 @@
1# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj1# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
22
3# RUN: lld-link /out:%t.exe /entry:main %t.obj3# RUN: lld-link /out:%t.exe /entry:main %t.obj
4# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s4# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s
55
6DEFAULT: SizeOfHeapReserve: 10485766DEFAULT: SizeOfHeapReserve: 1048576
7DEFAULT: SizeOfHeapCommit: 40967DEFAULT: SizeOfHeapCommit: 4096
88
9# RUN: lld-link /out:%t.exe /entry:main /heap:0x3000 %t.obj9# RUN: lld-link /out:%t.exe /entry:main /heap:0x3000 %t.obj
10# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s10# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
11# RUN: echo "HEAPSIZE 12288" > %t.def11# RUN: echo "HEAPSIZE 12288" > %t.def
12# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj12# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
13# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s13# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
1414
15CHECK1: SizeOfHeapReserve: 1228815CHECK1: SizeOfHeapReserve: 12288
16CHECK1: SizeOfHeapCommit: 409616CHECK1: SizeOfHeapCommit: 4096
1717
18# RUN: lld-link /out:%t.exe /entry:main /heap:0x5000,0x3000 %t.obj18# RUN: lld-link /out:%t.exe /entry:main /heap:0x5000,0x3000 %t.obj
19# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s19# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
20# RUN: echo "HEAPSIZE 20480,12288" > %t.def20# RUN: echo "HEAPSIZE 20480,12288" > %t.def
21# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj21# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
22# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s22# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
2323
24CHECK2: SizeOfHeapReserve: 2048024CHECK2: SizeOfHeapReserve: 20480
25CHECK2: SizeOfHeapCommit: 1228825CHECK2: SizeOfHeapCommit: 12288
deps/lld/test/COFF/hello32.test+5-6
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj1# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
2# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \2# RUN: lld-link -safeseh:no %t.obj %p/Inputs/std32.lib /subsystem:console \
3# RUN: /entry:main@0 /out:%t.exe /appcontainer3# RUN: /entry:main@0 /out:%t.exe /appcontainer
4# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s4# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=HEADER %s
5# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s5# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORTS %s
6# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s6# RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
77
8HEADER: Format: COFF-i3868HEADER: Format: COFF-i386
9HEADER-NEXT: Arch: i3869HEADER-NEXT: Arch: i386
...@@ -42,10 +42,9 @@ HEADER-NEXT: MinorSubsystemVersion: 0...@@ -42,10 +42,9 @@ HEADER-NEXT: MinorSubsystemVersion: 0
42HEADER-NEXT: SizeOfImage: 2048042HEADER-NEXT: SizeOfImage: 20480
43HEADER-NEXT: SizeOfHeaders: 102443HEADER-NEXT: SizeOfHeaders: 1024
44HEADER-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)44HEADER-NEXT: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
45HEADER-NEXT: Characteristics [ (0x9540)45HEADER-NEXT: Characteristics [ (0x9140)
46HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_APPCONTAINER (0x1000)46HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_APPCONTAINER (0x1000)
47HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)47HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE (0x40)
48HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_NO_SEH (0x400)
49HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)48HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT (0x100)
50HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)49HEADER-NEXT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE (0x8000)
51HEADER-NEXT: ]50HEADER-NEXT: ]
deps/lld/test/COFF/icf-pdata.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc %s -triple x86_64-windows-msvc -filetype=obj -o %t.obj2# RUN: llvm-mc %s -triple x86_64-windows-msvc -filetype=obj -o %t.obj
3# RUN: lld-link %t.obj -dll -noentry -out:%t.dll -merge:.xdata=.xdata3# RUN: lld-link %t.obj -dll -noentry -out:%t.dll -merge:.xdata=.xdata
4# RUN: llvm-readobj -sections -coff-exports %t.dll | FileCheck %s4# RUN: llvm-readobj --sections --coff-exports %t.dll | FileCheck %s
55
6# CHECK: Name: .pdata6# CHECK: Name: .pdata
7# CHECK-NEXT: VirtualSize: 0x187# CHECK-NEXT: VirtualSize: 0x18
deps/lld/test/COFF/icf-xdata.s+2-2
...@@ -2,9 +2,9 @@...@@ -2,9 +2,9 @@
2# RUN: llvm-mc %s -triple x86_64-windows-msvc -filetype=obj -o %t.obj2# RUN: llvm-mc %s -triple x86_64-windows-msvc -filetype=obj -o %t.obj
3# RUN: lld-link %t.obj -dll -noentry -out:%t.dll -merge:.xdata=.xdata 2>&1 \3# RUN: lld-link %t.obj -dll -noentry -out:%t.dll -merge:.xdata=.xdata 2>&1 \
4# RUN: | FileCheck %s --check-prefix=WARN4# RUN: | FileCheck %s --check-prefix=WARN
5# RUN: llvm-readobj -sections %t.dll | FileCheck %s --check-prefix=XDATA5# RUN: llvm-readobj --sections %t.dll | FileCheck %s --check-prefix=XDATA
6# RUN: lld-link %t.obj -dll -noentry -out:%t.dll6# RUN: lld-link %t.obj -dll -noentry -out:%t.dll
7# RUN: llvm-readobj -sections %t.dll | FileCheck %s --check-prefix=RDATA7# RUN: llvm-readobj --sections %t.dll | FileCheck %s --check-prefix=RDATA
88
9# There shouldn't be much xdata, because all three .pdata entries (12 bytes9# There shouldn't be much xdata, because all three .pdata entries (12 bytes
10# each) should use the same .xdata unwind info.10# each) should use the same .xdata unwind info.
deps/lld/test/COFF/imports-gnu-autoexport.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: llvm-ar rcs %t-implib.a %t-dabcdh.o %t-dabcds00000.o %t-dabcdt.o7# 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 \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:func9# 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 %s10# RUN: llvm-readobj --coff-exports %t.dll | FileCheck -check-prefix=EXPORT %s
1111
12# Check that only the single normal symbol was exported, none of the symbols12# Check that only the single normal symbol was exported, none of the symbols
13# from the import library.13# from the import library.
deps/lld/test/COFF/imports-gnu.test+1-1
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9# Not linking with -lldmingw; one can link to GNU import libs even if not targeting MinGW.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 \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:func11# 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 %s12# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
1313
14# Check that import entries from both libraries show up.14# Check that import entries from both libraries show up.
1515
deps/lld/test/COFF/imports-mangle.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /opt:noref /entry:main \2# RUN: lld-link /out:%t.exe /opt:noref /entry:main \
3# RUN: %t.obj %p/Inputs/imports-mangle.lib3# RUN: %t.obj %p/Inputs/imports-mangle.lib
4# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s4# RUN: llvm-readobj --coff-imports %t.exe | FileCheck %s
55
6# CHECK: Import {6# CHECK: Import {
7# CHECK: Symbol: sym4 (0)7# CHECK: Symbol: sym4 (0)
deps/lld/test/COFF/imports.test+4-3
...@@ -4,14 +4,15 @@...@@ -4,14 +4,15 @@
4# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \4# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \
5# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib5# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib
6# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=TEXT %s6# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=TEXT %s
7# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s7# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
88
9# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \9# RUN: lld-link /out:%t.exe /entry:main /subsystem:console \
10# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /include:ExitProcess10# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /include:ExitProcess
11# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=TEXT %s11# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=TEXT %s
12# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s12# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=IMPORT %s
1313
14TEXT: Disassembly of section .text:14TEXT: Disassembly of section .text:
15TEXT-EMPTY:
15TEXT-NEXT: .text:16TEXT-NEXT: .text:
16TEXT-NEXT: subq $40, %rsp17TEXT-NEXT: subq $40, %rsp
17TEXT-NEXT: movq $0, %rcx18TEXT-NEXT: movq $0, %rcx
...@@ -37,7 +38,7 @@ IMPORT-NEXT: }...@@ -37,7 +38,7 @@ IMPORT-NEXT: }
3738
38# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /merge:.rdata=.text \39# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /merge:.rdata=.text \
39# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /include:ExitProcess40# RUN: %p/Inputs/hello64.obj %p/Inputs/std64.lib /include:ExitProcess
40# RUN: llvm-readobj -coff-imports %t.exe | FileCheck -check-prefix=MERGE %s41# RUN: llvm-readobj --coff-imports %t.exe | FileCheck -check-prefix=MERGE %s
4142
42MERGE: Import {43MERGE: Import {
43MERGE-NEXT: Name: std64.dll44MERGE-NEXT: Name: std64.dll
deps/lld/test/COFF/includeoptional.yaml created+39
...@@ -0,0 +1,39 @@
1# RUN: yaml2obj < %s > %t.main.obj
2# RUN: yaml2obj < %p/Inputs/include1c.yaml > %t.lib.obj
3# RUN: rm -f %t.lib.lib
4# RUN: llvm-ar cru %t.lib.lib %t.lib.obj
5# RUN: lld-link /out:%t.exe /entry:main /includeoptional:bar /includeoptional:actuallymissing %t.main.obj %t.lib.lib /verbose >& %t.log
6# RUN: FileCheck %s < %t.log
7
8# CHECK: includeoptional.yaml.tmp.main.obj
9# CHECK: includeoptional.yaml.tmp.lib.lib
10# CHECK: includeoptional.yaml.tmp.lib.lib(includeoptional.yaml.tmp.lib.obj) for bar
11--- !COFF
12header:
13 Machine: IMAGE_FILE_MACHINE_AMD64
14 Characteristics: []
15sections:
16 - Name: .text
17 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
18 Alignment: 4
19 SectionData: B800000000506800000000680000000050E80000000050E800000000
20symbols:
21 - Name: .text
22 Value: 0
23 SectionNumber: 1
24 SimpleType: IMAGE_SYM_TYPE_NULL
25 ComplexType: IMAGE_SYM_DTYPE_NULL
26 StorageClass: IMAGE_SYM_CLASS_STATIC
27 SectionDefinition:
28 Length: 28
29 NumberOfRelocations: 4
30 NumberOfLinenumbers: 0
31 CheckSum: 0
32 Number: 0
33 - Name: main
34 Value: 0
35 SectionNumber: 1
36 SimpleType: IMAGE_SYM_TYPE_NULL
37 ComplexType: IMAGE_SYM_DTYPE_NULL
38 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
39...
deps/lld/test/COFF/includeoptional2.yaml created+44
...@@ -0,0 +1,44 @@
1# RUN: yaml2obj < %s > %t.obj
2# RUN: not lld-link /out:%t.exe /entry:main /includeoptional:undeffunc %t.obj /verbose 2>&1 | FileCheck %s
3
4# CHECK: error: undefined symbol: undeffunc
5
6--- !COFF
7header:
8 Machine: IMAGE_FILE_MACHINE_AMD64
9 Characteristics: []
10sections:
11 - Name: .text
12 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
13 Alignment: 4
14 SectionData: B800000000506800000000680000000050E80000000050E800000000
15 Relocations:
16 - VirtualAddress: 17
17 SymbolName: undeffunc
18 Type: IMAGE_REL_AMD64_REL32
19symbols:
20 - Name: .text
21 Value: 0
22 SectionNumber: 1
23 SimpleType: IMAGE_SYM_TYPE_NULL
24 ComplexType: IMAGE_SYM_DTYPE_NULL
25 StorageClass: IMAGE_SYM_CLASS_STATIC
26 SectionDefinition:
27 Length: 28
28 NumberOfRelocations: 1
29 NumberOfLinenumbers: 0
30 CheckSum: 0
31 Number: 0
32 - Name: main
33 Value: 0
34 SectionNumber: 1
35 SimpleType: IMAGE_SYM_TYPE_NULL
36 ComplexType: IMAGE_SYM_DTYPE_NULL
37 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
38 - Name: undeffunc
39 Value: 0
40 SectionNumber: 0
41 SimpleType: IMAGE_SYM_TYPE_NULL
42 ComplexType: IMAGE_SYM_DTYPE_NULL
43 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
44...
deps/lld/test/COFF/invalid-debug-type.test+8-3
...@@ -1,6 +1,11 @@...@@ -1,6 +1,11 @@
1# RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj1# RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj
2# RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj2# RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj
3# RUN: lld-link /debug /debugtype:invalid /pdb:%t.pdb /dll /out:%t.dll /entry:main /nodefaultlib \3# RUN: lld-link /debug /debugtype:invalid /pdb:%t.pdb /dll /out:%t.dll \
4# RUN: %t1.obj %t2.obj 2>&1 | FileCheck %s4# RUN: /entry:main /nodefaultlib %t1.obj %t2.obj 2>&1 | FileCheck %s
5# CHECK: /debugtype: unknown option 'invalid'
56
6# CHECK: /debugtype: unknown option: invalid
\ No newline at end of file
7# RUN: lld-link /debug /debugtype:invalid,foo /pdb:%t.pdb /dll /out:%t.dll \
8# RUN: /entry:main /nodefaultlib %t1.obj %t2.obj 2>&1 | \
9# RUN: FileCheck --check-prefix=TWO %s
10# TWO: /debugtype: unknown option 'invalid'
11# TWO: /debugtype: unknown option 'foo'
deps/lld/test/COFF/largeaddressaware.test+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj1# RUN: yaml2obj < %p/Inputs/hello32.yaml > %t.obj
2# RUN: lld-link %t.obj %p/Inputs/std32.lib /subsystem:console \2# RUN: lld-link -safeseh:no %t.obj %p/Inputs/std32.lib /subsystem:console \
3# RUN: /entry:main@0 /out:%t.exe /largeaddressaware3# RUN: /entry:main@0 /out:%t.exe /largeaddressaware
4# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s4# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=HEADER %s
55
6HEADER: Format: COFF-i3866HEADER: Format: COFF-i386
7HEADER-NEXT: Arch: i3867HEADER-NEXT: Arch: i386
deps/lld/test/COFF/lib-module-asm.ll created+22
...@@ -0,0 +1,22 @@
1; REQUIRES: x86
2; PR41803: llvm-link /lib on object with module asm crashes
3; RUN: rm -f %t.lib
4; RUN: llvm-as -o %t.obj %s
5; RUN: lld-link /lib /out:%t.lib %t.obj
6; RUN: llvm-nm -M %t.lib | FileCheck %s
7
8target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
9target triple = "i386-pc-windows-msvc19.11.0"
10
11module asm ".global global_asm_sym"
12module asm "global_asm_sym:"
13module asm "local_asm_sym:"
14module asm ".long undef_asm_sym"
15
16; CHECK: Archive map
17; CHECK-NEXT: global_asm_sym in {{.*}}lib-module-asm.ll.tmp.obj
18
19; CHECK: lib-module-asm.ll.tmp.obj:{{$}}
20; CHECK-NEXT: T global_asm_sym
21; CHECK-NEXT: t local_asm_sym
22; CHECK-NEXT: U undef_asm_sym
deps/lld/test/COFF/line-error.yaml+160-160
...@@ -1,160 +1,160 @@...@@ -1,160 +1,160 @@
1# RUN: yaml2obj %s -o %t.obj 1# RUN: yaml2obj %s -o %t.obj
2# RUN: not lld-link %t.obj /subsystem:console 2>&1 | FileCheck %s 2# RUN: not lld-link %t.obj /subsystem:console 2>&1 | FileCheck %s
3 3
4# CHECK: lld-link: error: undefined symbol: function 4# CHECK: lld-link: error: undefined symbol: function
5# CHECK-NEXT: >>> referenced by {{.*}}line-error.yaml.tmp.obj:(caller1) 5# CHECK-NEXT: >>> referenced by {{.*}}line-error.yaml.tmp.obj:(caller1)
6# CHECK-NEXT: >>> referenced by E:\file.cpp:1935 6# CHECK-NEXT: >>> referenced by E:\file.cpp:1935
7# CHECK-NEXT: >>> {{.*}}line-error.yaml.tmp.obj:(caller22) 7# CHECK-NEXT: >>> {{.*}}line-error.yaml.tmp.obj:(caller22)
8 8
9--- !COFF 9--- !COFF
10header: 10header:
11 Machine: IMAGE_FILE_MACHINE_AMD64 11 Machine: IMAGE_FILE_MACHINE_AMD64
12 Characteristics: [ ] 12 Characteristics: [ ]
13sections: 13sections:
14 - Name: .text 14 - Name: .text
15 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] 15 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
16 Alignment: 16 16 Alignment: 16
17 SectionData: 488B0500000000488B51284881C2D80000004889C148FF2500000000 17 SectionData: 488B0500000000488B51284881C2D80000004889C148FF2500000000
18 Relocations: 18 Relocations:
19 - VirtualAddress: 3 19 - VirtualAddress: 3
20 SymbolName: function 20 SymbolName: function
21 Type: IMAGE_REL_AMD64_REL32 21 Type: IMAGE_REL_AMD64_REL32
22 - Name: .text 22 - Name: .text
23 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ] 23 Characteristics: [ IMAGE_SCN_CNT_CODE, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_EXECUTE, IMAGE_SCN_MEM_READ ]
24 Alignment: 16 24 Alignment: 16
25 SectionData: 488B0500000000488B51084881C2D80000004889C148FF2500000000 25 SectionData: 488B0500000000488B51084881C2D80000004889C148FF2500000000
26 Relocations: 26 Relocations:
27 - VirtualAddress: 3 27 - VirtualAddress: 3
28 SymbolName: function 28 SymbolName: function
29 Type: IMAGE_REL_AMD64_REL32 29 Type: IMAGE_REL_AMD64_REL32
30 - Name: '.debug$S' 30 - Name: '.debug$S'
31 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] 31 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
32 Alignment: 4 32 Alignment: 4
33 Subsections: 33 Subsections:
34 - !FileChecksums 34 - !FileChecksums
35 Checksums: 35 Checksums:
36 - FileName: 'E:\file.cpp' 36 - FileName: 'E:\file.cpp'
37 Kind: MD5 37 Kind: MD5
38 Checksum: D72EDEF8B8E50C364A330F9CB3CD904B 38 Checksum: D72EDEF8B8E50C364A330F9CB3CD904B
39 - !StringTable 39 - !StringTable
40 Strings: 40 Strings:
41 - 'E:\file.cpp' 41 - 'E:\file.cpp'
42 - Name: '.debug$S' 42 - Name: '.debug$S'
43 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] 43 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
44 Alignment: 4 44 Alignment: 4
45 Subsections: 45 Subsections:
46 - !Lines 46 - !Lines
47 CodeSize: 28 47 CodeSize: 28
48 Flags: [ ] 48 Flags: [ ]
49 RelocOffset: 0 49 RelocOffset: 0
50 RelocSegment: 0 50 RelocSegment: 0
51 Blocks: [] 51 Blocks: []
52 Relocations: 52 Relocations:
53 - VirtualAddress: 12 53 - VirtualAddress: 12
54 SymbolName: caller1 54 SymbolName: caller1
55 Type: IMAGE_REL_AMD64_SECREL 55 Type: IMAGE_REL_AMD64_SECREL
56 - Name: '.debug$S' 56 - Name: '.debug$S'
57 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ] 57 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_LNK_COMDAT, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
58 Alignment: 4 58 Alignment: 4
59 Subsections: 59 Subsections:
60 - !Lines 60 - !Lines
61 CodeSize: 28 61 CodeSize: 28
62 Flags: [ ] 62 Flags: [ ]
63 RelocOffset: 0 63 RelocOffset: 0
64 RelocSegment: 0 64 RelocSegment: 0
65 Blocks: 65 Blocks:
66 - FileName: 'E:\file.cpp' 66 - FileName: 'E:\file.cpp'
67 Lines: 67 Lines:
68 - Offset: 11 68 - Offset: 11
69 LineStart: 1935 69 LineStart: 1935
70 IsStatement: false 70 IsStatement: false
71 EndDelta: 0 71 EndDelta: 0
72 Columns: [] 72 Columns: []
73 Relocations: 73 Relocations:
74 - VirtualAddress: 12 74 - VirtualAddress: 12
75 SymbolName: caller22 75 SymbolName: caller22
76 Type: IMAGE_REL_AMD64_SECREL 76 Type: IMAGE_REL_AMD64_SECREL
77symbols: 77symbols:
78 - Name: .text 78 - Name: .text
79 Value: 0 79 Value: 0
80 SectionNumber: 1 80 SectionNumber: 1
81 SimpleType: IMAGE_SYM_TYPE_NULL 81 SimpleType: IMAGE_SYM_TYPE_NULL
82 ComplexType: IMAGE_SYM_DTYPE_NULL 82 ComplexType: IMAGE_SYM_DTYPE_NULL
83 StorageClass: IMAGE_SYM_CLASS_STATIC 83 StorageClass: IMAGE_SYM_CLASS_STATIC
84 SectionDefinition: 84 SectionDefinition:
85 Length: 28 85 Length: 28
86 NumberOfRelocations: 2 86 NumberOfRelocations: 2
87 NumberOfLinenumbers: 0 87 NumberOfLinenumbers: 0
88 CheckSum: 2430089736 88 CheckSum: 2430089736
89 Number: 1 89 Number: 1
90 Selection: IMAGE_COMDAT_SELECT_NODUPLICATES 90 Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
91 - Name: caller1 91 - Name: caller1
92 Value: 0 92 Value: 0
93 SectionNumber: 1 93 SectionNumber: 1
94 SimpleType: IMAGE_SYM_TYPE_NULL 94 SimpleType: IMAGE_SYM_TYPE_NULL
95 ComplexType: IMAGE_SYM_DTYPE_FUNCTION 95 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
96 StorageClass: IMAGE_SYM_CLASS_EXTERNAL 96 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
97 - Name: .text 97 - Name: .text
98 Value: 0 98 Value: 0
99 SectionNumber: 2 99 SectionNumber: 2
100 SimpleType: IMAGE_SYM_TYPE_NULL 100 SimpleType: IMAGE_SYM_TYPE_NULL
101 ComplexType: IMAGE_SYM_DTYPE_NULL 101 ComplexType: IMAGE_SYM_DTYPE_NULL
102 StorageClass: IMAGE_SYM_CLASS_STATIC 102 StorageClass: IMAGE_SYM_CLASS_STATIC
103 SectionDefinition: 103 SectionDefinition:
104 Length: 28 104 Length: 28
105 NumberOfRelocations: 2 105 NumberOfRelocations: 2
106 NumberOfLinenumbers: 0 106 NumberOfLinenumbers: 0
107 CheckSum: 3449717304 107 CheckSum: 3449717304
108 Number: 2 108 Number: 2
109 Selection: IMAGE_COMDAT_SELECT_NODUPLICATES 109 Selection: IMAGE_COMDAT_SELECT_NODUPLICATES
110 - Name: caller22 110 - Name: caller22
111 Value: 0 111 Value: 0
112 SectionNumber: 2 112 SectionNumber: 2
113 SimpleType: IMAGE_SYM_TYPE_NULL 113 SimpleType: IMAGE_SYM_TYPE_NULL
114 ComplexType: IMAGE_SYM_DTYPE_FUNCTION 114 ComplexType: IMAGE_SYM_DTYPE_FUNCTION
115 StorageClass: IMAGE_SYM_CLASS_EXTERNAL 115 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
116 - Name: '.debug$S' 116 - Name: '.debug$S'
117 Value: 0 117 Value: 0
118 SectionNumber: 3 118 SectionNumber: 3
119 SimpleType: IMAGE_SYM_TYPE_NULL 119 SimpleType: IMAGE_SYM_TYPE_NULL
120 ComplexType: IMAGE_SYM_DTYPE_NULL 120 ComplexType: IMAGE_SYM_DTYPE_NULL
121 StorageClass: IMAGE_SYM_CLASS_STATIC 121 StorageClass: IMAGE_SYM_CLASS_STATIC
122 SectionDefinition: 122 SectionDefinition:
123 Length: 767204 123 Length: 767204
124 NumberOfRelocations: 0 124 NumberOfRelocations: 0
125 NumberOfLinenumbers: 0 125 NumberOfLinenumbers: 0
126 CheckSum: 4280093374 126 CheckSum: 4280093374
127 Number: 3 127 Number: 3
128 - Name: '.debug$S' 128 - Name: '.debug$S'
129 Value: 0 129 Value: 0
130 SectionNumber: 4 130 SectionNumber: 4
131 SimpleType: IMAGE_SYM_TYPE_NULL 131 SimpleType: IMAGE_SYM_TYPE_NULL
132 ComplexType: IMAGE_SYM_DTYPE_NULL 132 ComplexType: IMAGE_SYM_DTYPE_NULL
133 StorageClass: IMAGE_SYM_CLASS_STATIC 133 StorageClass: IMAGE_SYM_CLASS_STATIC
134 SectionDefinition: 134 SectionDefinition:
135 Length: 296 135 Length: 296
136 NumberOfRelocations: 1 136 NumberOfRelocations: 1
137 NumberOfLinenumbers: 0 137 NumberOfLinenumbers: 0
138 CheckSum: 1957793731 138 CheckSum: 1957793731
139 Number: 1 139 Number: 1
140 Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE 140 Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE
141 - Name: '.debug$S' 141 - Name: '.debug$S'
142 Value: 0 142 Value: 0
143 SectionNumber: 5 143 SectionNumber: 5
144 SimpleType: IMAGE_SYM_TYPE_NULL 144 SimpleType: IMAGE_SYM_TYPE_NULL
145 ComplexType: IMAGE_SYM_DTYPE_NULL 145 ComplexType: IMAGE_SYM_DTYPE_NULL
146 StorageClass: IMAGE_SYM_CLASS_STATIC 146 StorageClass: IMAGE_SYM_CLASS_STATIC
147 SectionDefinition: 147 SectionDefinition:
148 Length: 276 148 Length: 276
149 NumberOfRelocations: 1 149 NumberOfRelocations: 1
150 NumberOfLinenumbers: 0 150 NumberOfLinenumbers: 0
151 CheckSum: 1957793731 151 CheckSum: 1957793731
152 Number: 2 152 Number: 2
153 Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE 153 Selection: IMAGE_COMDAT_SELECT_ASSOCIATIVE
154 - Name: function 154 - Name: function
155 Value: 0 155 Value: 0
156 SectionNumber: 0 156 SectionNumber: 0
157 SimpleType: IMAGE_SYM_TYPE_NULL 157 SimpleType: IMAGE_SYM_TYPE_NULL
158 ComplexType: IMAGE_SYM_DTYPE_NULL 158 ComplexType: IMAGE_SYM_DTYPE_NULL
159 StorageClass: IMAGE_SYM_CLASS_EXTERNAL 159 StorageClass: IMAGE_SYM_CLASS_EXTERNAL
160... 160...
deps/lld/test/COFF/linkrepro-pdb.test+14-1
...@@ -4,6 +4,19 @@ RUN: rm -rf %t && mkdir -p %t && cd %t...@@ -4,6 +4,19 @@ RUN: rm -rf %t && mkdir -p %t && cd %t
4RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj4RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj
5RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj5RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj
6RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb6RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb
7RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib -linkrepro:.7RUN: lld-link a.obj b.obj -entry:main -debug -out:%t.exe -pdb:%t.pdb -nodefaultlib -linkrepro:.
8RUN: tar xOf repro.tar repro/%:t/ts.pdb > repro-ts.pdb8RUN: tar xOf repro.tar repro/%:t/ts.pdb > repro-ts.pdb
9RUN: diff ts.pdb repro-ts.pdb9RUN: diff ts.pdb repro-ts.pdb
10
11RUN: tar xf repro.tar
12RUN: cat repro/response.txt | FileCheck -check-prefix=PDB %s
13
14PDB: -out:linkrepro-pdb.test.tmp.exe
15PDB-NEXT: -pdb:linkrepro-pdb.test.tmp.pdb
16
17RUN: yaml2obj < %p/Inputs/export.yaml > %t1.obj
18RUN: lld-link /out:%t1.dll /dll %t1.obj /implib:%t1.lib /export:exportfn1 /export:exportfn2 /linkrepro:.
19RUN: tar xf repro.tar
20RUN: cat repro/response.txt | FileCheck -check-prefix=IMP %s
21
22IMP: /implib:linkrepro-pdb.test.tmp1.lib
deps/lld/test/COFF/loadcfg.ll+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1; REQUIRES: x861; REQUIRES: x86
2; RUN: llvm-as -o %t.obj %s2; RUN: llvm-as -o %t.obj %s
3; RUN: lld-link /out:%t.exe %t.obj /entry:main /subsystem:console3; RUN: lld-link /out:%t.exe %t.obj /entry:main /subsystem:console
4; RUN: llvm-readobj -file-headers %t.exe | FileCheck %s4; RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
55
6; CHECK: LoadConfigTableRVA: 0x20006; CHECK: LoadConfigTableRVA: 0x2000
7; CHECK: LoadConfigTableSize: 0x707; CHECK: LoadConfigTableSize: 0x70
deps/lld/test/COFF/loadcfg.test+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe %t.obj /entry:main /subsystem:console2# RUN: lld-link /out:%t.exe %t.obj /entry:main /subsystem:console
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
44
5# CHECK: LoadConfigTableRVA: 0x20005# CHECK: LoadConfigTableRVA: 0x2000
6# CHECK: LoadConfigTableSize: 0x706# CHECK: LoadConfigTableSize: 0x70
deps/lld/test/COFF/loadcfg32.test+2-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe %t.obj /entry:main /subsystem:console2# RUN: lld-link -safeseh:no /out:%t.exe %t.obj /entry:main /subsystem:console
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
44
5# CHECK: LoadConfigTableRVA: 0x20005# CHECK: LoadConfigTableRVA: 0x2000
6# CHECK: LoadConfigTableSize: 0x406# CHECK: LoadConfigTableSize: 0x40
deps/lld/test/COFF/locally-imported-arm64.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /entry:main %t.obj2# RUN: lld-link /out:%t.exe /entry:main %t.obj
3# RUN: llvm-objdump -s %t.exe | FileCheck %s3# RUN: llvm-objdump -s %t.exe | FileCheck %s
4# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s4# RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
55
6# CHECK: Contents of section .text:6# CHECK: Contents of section .text:
7# CHECK-NEXT: 1000 002000007# CHECK-NEXT: 1000 00200000
deps/lld/test/COFF/locally-imported.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /entry:main %t.obj 2>&1 | FileCheck -check-prefix=WARN %s2# RUN: lld-link /out:%t.exe /entry:main %t.obj 2>&1 | FileCheck -check-prefix=WARN %s
3# RUN: llvm-objdump -s %t.exe | FileCheck %s3# RUN: llvm-objdump -s %t.exe | FileCheck %s
4# RUN: llvm-readobj -coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s4# RUN: llvm-readobj --coff-basereloc %t.exe | FileCheck -check-prefix=BASEREL %s
55
6# WARN: warning: [[INPUT:.+]]: locally defined symbol imported: main (defined in [[INPUT]])6# WARN: warning: [[INPUT:.+]]: locally defined symbol imported: main (defined in [[INPUT]])
77
deps/lld/test/COFF/locally-imported32.test+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /entry:main %t.obj2# RUN: lld-link -safeseh:no /out:%t.exe /entry:main %t.obj
3# RUN: llvm-objdump -s %t.exe | FileCheck %s3# RUN: llvm-objdump -s %t.exe | FileCheck %s
44
5# CHECK: Contents of section .text:5# CHECK: Contents of section .text:
deps/lld/test/COFF/long-section-name.test+2-2
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /entry:main %t.obj2# RUN: lld-link /out:%t.exe /entry:main %t.obj
3# RUN: llvm-readobj -sections %t.exe | FileCheck %s3# RUN: llvm-readobj --sections %t.exe | FileCheck %s
4# RUN: lld-link /debug /out:%t2.exe /entry:main %t.obj4# RUN: lld-link /debug /out:%t2.exe /entry:main %t.obj
5# RUN: llvm-readobj -sections %t2.exe | FileCheck %s5# RUN: llvm-readobj --sections %t2.exe | FileCheck %s
66
7# CHECK: Name: .eh_fram (7# CHECK: Name: .eh_fram (
8# CHECK: Name: .data_long_section_name8# CHECK: Name: .data_long_section_name
deps/lld/test/COFF/lto-comdat.ll+9-6
...@@ -14,40 +14,42 @@...@@ -14,40 +14,42 @@
14; Check that, when we use an LTO main with LTO objects, we optimize away all14; Check that, when we use an LTO main with LTO objects, we optimize away all
15; of f1, f2, and comdat.15; of f1, f2, and comdat.
16; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat1.lto.obj %T/comdat2.lto.obj16; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat1.lto.obj %T/comdat2.lto.obj
17; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-11 %s17; RUN: llvm-readobj --file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-11 %s
18; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-11 %s18; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-11 %s
19; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat.lto.lib19; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat.lto.lib
20; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-11 %s20; RUN: llvm-readobj --file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-11 %s
21; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-11 %s21; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-11 %s
2222
23; Check that, when we use a non-LTO main with LTO objects, we pick the comdat23; Check that, when we use a non-LTO main with LTO objects, we pick the comdat
24; implementation in LTO, elide calls to it from inside LTO, and retain the24; implementation in LTO, elide calls to it from inside LTO, and retain the
25; call to comdat from main.25; call to comdat from main.
26; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.obj %T/comdat1.lto.obj %T/comdat2.lto.obj26; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.obj %T/comdat1.lto.obj %T/comdat2.lto.obj
27; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-01 %s27; RUN: llvm-readobj --file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-01 %s
28; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-01 %s28; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-01 %s
29; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.obj %T/comdat.lto.lib29; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.obj %T/comdat.lto.lib
30; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-01 %s30; RUN: llvm-readobj --file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-01 %s
31; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-01 %s31; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-01 %s
3232
33; Check that, when we use an LTO main with non-LTO objects, we pick the comdat33; Check that, when we use an LTO main with non-LTO objects, we pick the comdat
34; implementation in LTO, elide the call to it from inside LTO, and keep the34; implementation in LTO, elide the call to it from inside LTO, and keep the
35; calls to comdat from the non-LTO objects.35; calls to comdat from the non-LTO objects.
36; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat1.obj %T/comdat2.obj36; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat1.obj %T/comdat2.obj
37; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-10 %s37; RUN: llvm-readobj --file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-10 %s
38; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-10 %s38; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-10 %s
39; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat.lib39; RUN: lld-link /out:%T/comdat-main.exe /entry:main /subsystem:console %T/comdat-main.lto.obj %T/comdat.lib
40; RUN: llvm-readobj -file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-10 %s40; RUN: llvm-readobj --file-headers %T/comdat-main.exe | FileCheck -check-prefix=HEADERS-10 %s
41; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-10 %s41; RUN: llvm-objdump -d %T/comdat-main.exe | FileCheck -check-prefix=TEXT-10 %s
4242
43; HEADERS-11: AddressOfEntryPoint: 0x100043; HEADERS-11: AddressOfEntryPoint: 0x1000
44; TEXT-11: Disassembly of section .text:44; TEXT-11: Disassembly of section .text:
45; TEXT-11-EMPTY:
45; TEXT-11-NEXT: .text:46; TEXT-11-NEXT: .text:
46; TEXT-11-NEXT: xorl %eax, %eax47; TEXT-11-NEXT: xorl %eax, %eax
47; TEXT-11-NEXT: retq48; TEXT-11-NEXT: retq
4849
49; HEADERS-01: AddressOfEntryPoint: 0x100050; HEADERS-01: AddressOfEntryPoint: 0x1000
50; TEXT-01: Disassembly of section .text:51; TEXT-01: Disassembly of section .text:
52; TEXT-01-EMPTY:
51; TEXT-01-NEXT: .text:53; TEXT-01-NEXT: .text:
52; TEXT-01-NEXT: subq $40, %rsp54; TEXT-01-NEXT: subq $40, %rsp
53; TEXT-01-NEXT: callq 2355; TEXT-01-NEXT: callq 23
...@@ -65,6 +67,7 @@...@@ -65,6 +67,7 @@
6567
66; HEADERS-10: AddressOfEntryPoint: 0x102068; HEADERS-10: AddressOfEntryPoint: 0x1020
67; TEXT-10: Disassembly of section .text:69; TEXT-10: Disassembly of section .text:
70; TEXT-10-EMPTY:
68; TEXT-10-NEXT: .text:71; TEXT-10-NEXT: .text:
69; TEXT-10-NEXT: subq $40, %rsp72; TEXT-10-NEXT: subq $40, %rsp
70; TEXT-10-NEXT: callq 5573; TEXT-10-NEXT: callq 55
deps/lld/test/COFF/lto-icf.ll+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
44
5; RUN: llvm-as %s -o %t.bc5; RUN: llvm-as %s -o %t.bc
6; RUN: lld-link -opt:icf -dll -noentry %t.bc -out:%t.dll6; RUN: lld-link -opt:icf -dll -noentry %t.bc -out:%t.dll
7; RUN: llvm-readobj -coff-exports %t.dll | FileCheck %s7; RUN: llvm-readobj --coff-exports %t.dll | FileCheck %s
88
9; CHECK: Export {9; CHECK: Export {
10; CHECK: Export {10; CHECK: Export {
deps/lld/test/COFF/lto-lazy-reference.ll+4
...@@ -9,6 +9,10 @@...@@ -9,6 +9,10 @@
9target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"9target datalayout = "e-m:x-p:32:32-i64:64-f80:32-n8:16:32-a:0:32-S32"
10target triple = "i686-pc-windows-msvc18.0.0"10target triple = "i686-pc-windows-msvc18.0.0"
1111
12; Define fltused, since we don't link against the MS C runtime but are
13; using floats.
14@_fltused = dllexport global i32 0, align 4
15
12define double @main(double %x) {16define double @main(double %x) {
13entry:17entry:
14 ; When compiled, this defines the __real@40800000 symbol, which already has a18 ; When compiled, this defines the __real@40800000 symbol, which already has a
deps/lld/test/COFF/lto-new-symbol.ll+4
...@@ -5,6 +5,10 @@...@@ -5,6 +5,10 @@
5target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"5target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
6target triple = "x86_64-pc-windows-msvc"6target triple = "x86_64-pc-windows-msvc"
77
8; Define fltused, since we don't link against the MS C runtime but are
9; using floats.
10@_fltused = dllexport global i32 0, align 4
11
8define void @foo(<4 x i32>* %p, <4 x float>* %q, i1 %t) nounwind {12define void @foo(<4 x i32>* %p, <4 x float>* %q, i1 %t) nounwind {
9entry:13entry:
10 br label %loop14 br label %loop
deps/lld/test/COFF/lto.ll+9-6
...@@ -10,30 +10,31 @@...@@ -10,30 +10,31 @@
10; RUN: llvm-ar cru %T/foo.lib %T/foo.obj10; RUN: llvm-ar cru %T/foo.lib %T/foo.obj
1111
12; RUN: lld-link /out:%T/main.exe /entry:main /include:f2 /subsystem:console %T/main.lto.obj %T/foo.lto.obj12; RUN: lld-link /out:%T/main.exe /entry:main /include:f2 /subsystem:console %T/main.lto.obj %T/foo.lto.obj
13; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-11 %s13; RUN: llvm-readobj --file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-11 %s
14; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-11 %s14; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-11 %s
15; RUN: lld-link /out:%T/main.exe /entry:main /include:f2 /subsystem:console %T/main.lto.obj %T/foo.lto.lib /verbose 2>&1 | FileCheck -check-prefix=VERBOSE %s15; RUN: lld-link /out:%T/main.exe /entry:main /include:f2 /subsystem:console %T/main.lto.obj %T/foo.lto.lib /verbose 2>&1 | FileCheck -check-prefix=VERBOSE %s
16; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-11 %s16; RUN: llvm-readobj --file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-11 %s
17; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-11 %s17; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-11 %s
1818
19; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.obj %T/foo.lto.obj19; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.obj %T/foo.lto.obj
20; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-01 %s20; RUN: llvm-readobj --file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-01 %s
21; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-01 %s21; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-01 %s
22; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.obj %T/foo.lto.lib22; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.obj %T/foo.lto.lib
23; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-01 %s23; RUN: llvm-readobj --file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-01 %s
24; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-01 %s24; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-01 %s
2525
26; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.lto.obj %T/foo.obj26; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.lto.obj %T/foo.obj
27; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-10 %s27; RUN: llvm-readobj --file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-10 %s
28; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-10 %s28; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-10 %s
29; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.lto.obj %T/foo.lib29; RUN: lld-link /out:%T/main.exe /entry:main /subsystem:console %T/main.lto.obj %T/foo.lib
30; RUN: llvm-readobj -file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-10 %s30; RUN: llvm-readobj --file-headers %T/main.exe | FileCheck -check-prefix=HEADERS-10 %s
31; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-10 %s31; RUN: llvm-objdump -d %T/main.exe | FileCheck -check-prefix=TEXT-10 %s
3232
33; VERBOSE: foo.lto.lib({{.*}}foo.lto.obj)33; VERBOSE: foo.lto.lib({{.*}}foo.lto.obj)
3434
35; HEADERS-11: AddressOfEntryPoint: 0x100035; HEADERS-11: AddressOfEntryPoint: 0x1000
36; TEXT-11: Disassembly of section .text:36; TEXT-11: Disassembly of section .text:
37; TEXT-11-EMPTY:
37; TEXT-11-NEXT: .text:38; TEXT-11-NEXT: .text:
38; TEXT-11-NEXT: xorl %eax, %eax39; TEXT-11-NEXT: xorl %eax, %eax
39; TEXT-11-NEXT: retq40; TEXT-11-NEXT: retq
...@@ -55,6 +56,7 @@...@@ -55,6 +56,7 @@
5556
56; HEADERS-01: AddressOfEntryPoint: 0x100057; HEADERS-01: AddressOfEntryPoint: 0x1000
57; TEXT-01: Disassembly of section .text:58; TEXT-01: Disassembly of section .text:
59; TEXT-01-EMPTY:
58; TEXT-01-NEXT: .text:60; TEXT-01-NEXT: .text:
59; TEXT-01-NEXT: subq $40, %rsp61; TEXT-01-NEXT: subq $40, %rsp
60; TEXT-01-NEXT: callq 2362; TEXT-01-NEXT: callq 23
...@@ -81,6 +83,7 @@...@@ -81,6 +83,7 @@
8183
82; HEADERS-10: AddressOfEntryPoint: 0x102084; HEADERS-10: AddressOfEntryPoint: 0x1020
83; TEXT-10: Disassembly of section .text:85; TEXT-10: Disassembly of section .text:
86; TEXT-10-EMPTY:
84; TEXT-10-NEXT: .text:87; TEXT-10-NEXT: .text:
85; TEXT-10-NEXT: retq88; TEXT-10-NEXT: retq
86; TEXT-10-NEXT: nop89; TEXT-10-NEXT: nop
deps/lld/test/COFF/machine.test+8-8
...@@ -1,18 +1,18 @@...@@ -1,18 +1,18 @@
1# RUN: yaml2obj %p/Inputs/machine-x64.yaml > %t.obj1# RUN: yaml2obj %p/Inputs/machine-x64.yaml > %t.obj
2# RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t.obj2# RUN: lld-link -safeseh:no /entry:main /subsystem:console /out:%t.exe %t.obj
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=AMD64 %s
4# RUN: lld-link /entry:main /subsystem:console /machine:x64 \4# RUN: lld-link -safeseh:no /entry:main /subsystem:console /machine:x64 \
5# RUN: /out:%t.exe %t.obj5# RUN: /out:%t.exe %t.obj
6# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=AMD64 %s6# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=AMD64 %s
77
8AMD64: Machine: IMAGE_FILE_MACHINE_AMD648AMD64: Machine: IMAGE_FILE_MACHINE_AMD64
99
10# RUN: yaml2obj %p/Inputs/machine-x86.yaml > %t.obj10# RUN: yaml2obj %p/Inputs/machine-x86.yaml > %t.obj
11# RUN: lld-link /entry:main /subsystem:console /out:%t.exe %t.obj11# RUN: lld-link -safeseh:no /entry:main /subsystem:console /out:%t.exe %t.obj
12# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=I386 %s12# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=I386 %s
13# RUN: lld-link /entry:main /subsystem:console /machine:x86 \13# RUN: lld-link -safeseh:no /entry:main /subsystem:console /machine:x86 \
14# RUN: /out:%t.exe %t.obj /fixed14# RUN: /out:%t.exe %t.obj /fixed
15# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=I386 %s15# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=I386 %s
1616
17I386: Machine: IMAGE_FILE_MACHINE_I38617I386: Machine: IMAGE_FILE_MACHINE_I386
1818
deps/lld/test/COFF/manifestinput.test+2-2
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5# RUN: /manifest:embed \5# RUN: /manifest:embed \
6# RUN: /manifestuac:"level='requireAdministrator'" \6# RUN: /manifestuac:"level='requireAdministrator'" \
7# RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj7# RUN: /manifestinput:%p/Inputs/manifestinput.test %t.obj
8# RUN: llvm-readobj -coff-resources -file-headers %t.exe | FileCheck %s \8# RUN: llvm-readobj --coff-resources --file-headers %t.exe | FileCheck %s \
9# RUN: -check-prefix TEST_EMBED9# RUN: -check-prefix TEST_EMBED
1010
11TEST_EMBED: ResourceTableRVA: 0x200011TEST_EMBED: ResourceTableRVA: 0x2000
...@@ -14,7 +14,7 @@ TEST_EMBED-DAG: Resources [...@@ -14,7 +14,7 @@ TEST_EMBED-DAG: Resources [
14TEST_EMBED-NEXT: Total Number of Resources: 114TEST_EMBED-NEXT: Total Number of Resources: 1
15TEST_EMBED-DAG: Number of String Entries: 015TEST_EMBED-DAG: Number of String Entries: 0
16TEST_EMBED-NEXT: Number of ID Entries: 116TEST_EMBED-NEXT: Number of ID Entries: 1
17TEST_EMBED-NEXT: Type: kRT_MANIFEST (ID 24) [17TEST_EMBED-NEXT: Type: MANIFEST (ID 24) [
18TEST_EMBED-NEXT: Table Offset: 0x1818TEST_EMBED-NEXT: Table Offset: 0x18
19TEST_EMBED-NEXT: Number of String Entries: 019TEST_EMBED-NEXT: Number of String Entries: 0
20TEST_EMBED-NEXT: Number of ID Entries: 120TEST_EMBED-NEXT: Number of ID Entries: 1
deps/lld/test/COFF/merge.test+2-2
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \2# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
3# RUN: /merge:.foo=.abc /merge:.bar=.def %t.obj /debug3# RUN: /merge:.foo=.abc /merge:.bar=.def %t.obj /debug
4# RUN: llvm-readobj -sections %t.exe | FileCheck %s4# RUN: llvm-readobj --sections %t.exe | FileCheck %s
55
6# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \6# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
7# RUN: /merge:.foo=.bar /merge:.bar=.abc %t.obj /debug7# RUN: /merge:.foo=.bar /merge:.bar=.abc %t.obj /debug
8# RUN: llvm-readobj -sections %t.exe | FileCheck --check-prefix=CHECK2 %s8# RUN: llvm-readobj --sections %t.exe | FileCheck --check-prefix=CHECK2 %s
99
10# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \10# RUN: not lld-link /out:%t.exe /entry:main /subsystem:console /force \
11# RUN: /merge:.rsrc=.foo %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RSRC %s11# RUN: /merge:.rsrc=.foo %t.obj /debug 2>&1 | FileCheck --check-prefix=NO-RSRC %s
deps/lld/test/COFF/multiple-resource-objs.test created+11
...@@ -0,0 +1,11 @@
1# RUN: llvm-cvtres /out:%t_resource.obj %S/Inputs/resource.res
2# RUN: llvm-cvtres /out:%t_id.obj %S/Inputs/id.res
3# RUN: not lld-link /out:%t.exe /dll /noentry %t_id.obj %t_resource.obj 2>&1 | \
4# RUN: FileCheck --check-prefix=TWOOBJ %s
5
6TWOOBJ: error: {{.*}}_resource.obj: more than one resource obj file not allowed, already got {{.*}}_id.obj
7
8# RUN: not lld-link /out:%t.exe /dll /noentry %S/Inputs/id.res %t_resource.obj 2>&1 | \
9# RUN: FileCheck --check-prefix=OBJRES %s
10
11OBJRES: error: internal .obj file created from .res files: more than one resource obj file not allowed, already got {{.*}}_resource.obj
deps/lld/test/COFF/no-idata.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.obj3# 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.obj4# RUN: lld-link -out:%t.exe -entry:main -subsystem:console %t.obj
5# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=DUMP %s5# RUN: llvm-objdump -s %t.exe | FileCheck -check-prefix=DUMP %s
6# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DIRECTORY %s6# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=DIRECTORY %s
77
8 .text8 .text
9 .global main9 .global main
deps/lld/test/COFF/no-ipi-stream.test created+4
...@@ -0,0 +1,4 @@
1# RUN: rm -rf %t && mkdir %t
2# RUN: yaml2obj < %p/Inputs/no-ipi-stream-obj.obj.yaml > %t/no-ipi-stream-obj.obj
3# RUN: llvm-pdbutil yaml2pdb %p/Inputs/no-ipi-stream-pdb.pdb.yaml -pdb=%t/no-ipi-stream-pdb.pdb
4# RUN: lld-link -safeseh:no /dll /noentry /debug %t/no-ipi-stream-obj.obj
deps/lld/test/COFF/nodefaultlib.test+9-2
...@@ -19,8 +19,8 @@...@@ -19,8 +19,8 @@
19# RUN: /nodefaultlib:std64.lib >& %t.log || true19# RUN: /nodefaultlib:std64.lib >& %t.log || true
20# RUN: FileCheck -check-prefix=CHECK3 %s < %t.log20# RUN: FileCheck -check-prefix=CHECK3 %s < %t.log
2121
22CHECK1: error: could not open hello64.obj: {{[Nn]}}o such file or directory22CHECK1: error: could not open 'hello64.obj': {{[Nn]}}o such file or directory
23CHECK2: error: could not open hello64: {{[Nn]}}o such file or directory23CHECK2: error: could not open 'hello64': {{[Nn]}}o such file or directory
24CHECK3: error: undefined symbol: MessageBoxA24CHECK3: error: undefined symbol: MessageBoxA
25CHECK3-NEXT: >>> referenced by {{.*}}hello64.obj:(main)25CHECK3-NEXT: >>> referenced by {{.*}}hello64.obj:(main)
2626
...@@ -29,3 +29,10 @@ CHECK3-NEXT: >>> referenced by {{.*}}hello64.obj:(main)...@@ -29,3 +29,10 @@ CHECK3-NEXT: >>> referenced by {{.*}}hello64.obj:(main)
2929
30# RUN: env LIB=%T lld-link /out:%t.exe /entry:main \30# RUN: env LIB=%T lld-link /out:%t.exe /entry:main \
31# RUN: /subsystem:console hello64.obj /defaultlib:std64.lib31# RUN: /subsystem:console hello64.obj /defaultlib:std64.lib
32
33MSVC stamps uppercase references in OBJ directives, thus ensure that passing lowercase 'libcmt' and 'oldnames' to /nodefaultlib works.
34# RUN: lld-link %S/Inputs/precomp.obj %S/Inputs/precomp-a.obj %S/Inputs/precomp-b.obj /nodefaultlib:libcmt /nodefaultlib:oldnames /entry:main /debug /pdb:%t.pdb /out:%t.exe /opt:ref /opt:icf
35# RUN: llvm-pdbutil dump -modules %t.pdb | FileCheck %s -check-prefix UPPERCASE
36
37UPPERCASE-NOT: OLDNAMES
38UPPERCASE-NOT: LIBCMT
deps/lld/test/COFF/noentry.test+2-2
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj1# RUN: yaml2obj < %p/Inputs/export.yaml > %t.obj
2# RUN: lld-link /out:%t.dll /dll %t.obj2# RUN: lld-link /out:%t.dll /dll %t.obj
3# RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=ENTRY %s3# RUN: llvm-readobj --file-headers %t.dll | FileCheck -check-prefix=ENTRY %s
4# RUN: lld-link /out:%t.dll /dll /noentry %t.obj4# RUN: lld-link /out:%t.dll /dll /noentry %t.obj
5# RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=NOENTRY %s5# RUN: llvm-readobj --file-headers %t.dll | FileCheck -check-prefix=NOENTRY %s
66
7ENTRY: AddressOfEntryPoint: 0x10007ENTRY: AddressOfEntryPoint: 0x1000
8NOENTRY: AddressOfEntryPoint: 0x08NOENTRY: AddressOfEntryPoint: 0x0
deps/lld/test/COFF/options.test+60-20
...@@ -1,65 +1,105 @@...@@ -1,65 +1,105 @@
1# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj1# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
22
3# RUN: lld-link /out:%t.exe /entry:main %t.obj3# RUN: lld-link /out:%t.exe /entry:main %t.obj
4# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=BIND %s4# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=BIND %s
5# RUN: lld-link /allowbind /out:%t.exe /entry:main %t.obj5# RUN: lld-link /allowbind /out:%t.exe /entry:main %t.obj
6# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=BIND %s6# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=BIND %s
7BIND-NOT: IMAGE_DLL_CHARACTERISTICS_NO_BIND7BIND-NOT: IMAGE_DLL_CHARACTERISTICS_NO_BIND
88
9# RUN: lld-link /allowbind:no /out:%t.exe /entry:main %t.obj9# RUN: lld-link /allowbind:no /out:%t.exe /entry:main %t.obj
10# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOBIND %s10# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NOBIND %s
11NOBIND: IMAGE_DLL_CHARACTERISTICS_NO_BIND11NOBIND: IMAGE_DLL_CHARACTERISTICS_NO_BIND
1212
13# RUN: lld-link /out:%t.exe /entry:main %t.obj13# RUN: lld-link /out:%t.exe /entry:main %t.obj
14# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ISO %s14# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=ISO %s
15# RUN: lld-link /allowisolation /out:%t.exe /entry:main %t.obj15# RUN: lld-link /allowisolation /out:%t.exe /entry:main %t.obj
16# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ISO %s16# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=ISO %s
17ISO-NOT: IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION17ISO-NOT: IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION
1818
19# RUN: lld-link /allowisolation:no /out:%t.exe /entry:main %t.obj19# RUN: lld-link /allowisolation:no /out:%t.exe /entry:main %t.obj
20# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOISO %s20# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NOISO %s
21NOISO: IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION21NOISO: IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION
2222
23# RUN: lld-link /out:%t.exe /entry:main %t.obj23# RUN: lld-link /out:%t.exe /entry:main %t.obj
24# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ENT %s24# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=ENT %s
25# RUN: lld-link /out:%t.exe /entry:main /highentropyva %t.obj25# RUN: lld-link /out:%t.exe /entry:main /highentropyva %t.obj
26# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=ENT %s26# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=ENT %s
27ENT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA27ENT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
2828
29# RUN: lld-link /out:%t.exe /highentropyva:no /out:%t.exe /entry:main %t.obj29# RUN: lld-link /out:%t.exe /highentropyva:no /out:%t.exe /entry:main %t.obj
30# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOENT %s30# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NOENT %s
31NOENT-NOT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA31NOENT-NOT: IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA
3232
33# RUN: lld-link /out:%t.exe /entry:main /integritycheck %t.obj33# RUN: lld-link /out:%t.exe /entry:main /integritycheck %t.obj
34# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=INT %s34# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=INT %s
35INT: IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY35INT: IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY
3636
37# RUN: lld-link /out:%t.exe /entry:main %t.obj37# RUN: lld-link /out:%t.exe /entry:main %t.obj
38# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOINT %s38# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NOINT %s
39# RUN: lld-link /out:%t.exe /integritycheck:no /out:%t.exe /entry:main %t.obj39# RUN: lld-link /out:%t.exe /integritycheck:no /out:%t.exe /entry:main %t.obj
40# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOINT %s40# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NOINT %s
41NOINT-NOT: IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY41NOINT-NOT: IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY
4242
43# RUN: lld-link /out:%t.exe /entry:main %t.obj43# RUN: lld-link /out:%t.exe /entry:main %t.obj
44# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NXCOMPAT %s44# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NXCOMPAT %s
45# RUN: lld-link /out:%t.exe /entry:main /nxcompat %t.obj45# RUN: lld-link /out:%t.exe /entry:main /nxcompat %t.obj
46# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NXCOMPAT %s46# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NXCOMPAT %s
47NXCOMPAT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT47NXCOMPAT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
4848
49# RUN: lld-link /out:%t.exe /nxcompat:no /out:%t.exe /entry:main %t.obj49# RUN: lld-link /out:%t.exe /nxcompat:no /out:%t.exe /entry:main %t.obj
50# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NONXCOMPAT %s50# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NONXCOMPAT %s
51NONXCOMPAT-NOT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT51NONXCOMPAT-NOT: IMAGE_DLL_CHARACTERISTICS_NX_COMPAT
5252
53# RUN: lld-link /out:%t.exe /entry:main /swaprun:CD %t.obj
54# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=SWAPCD %s
55# RUN: lld-link /out:%t.exe /entry:main /swaprun:cd,net %t.obj
56# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=SWAPCD %s
57SWAPCD: IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
58
59# RUN: lld-link /out:%t.exe /entry:main %t.obj
60# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NOSWAPCD %s
61NOSWAPCD-NOT: IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP
62
63# RUN: lld-link /out:%t.exe /entry:main /swaprun:NeT %t.obj
64# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=SWAPNET %s
65# RUN: lld-link /out:%t.exe /entry:main /swaprun:net,cd,cd,net %t.obj
66# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=SWAPNET %s
67SWAPNET: IMAGE_FILE_NET_RUN_FROM_SWAP
68
69# RUN: lld-link /out:%t.exe /entry:main %t.obj
70# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NOSWAPNET %s
71NOSWAPNET-NOT: IMAGE_FILE_NET_RUN_FROM_SWAP
72
73# RUN: not lld-link /out:%t.exe /entry:main /swaprun: %t.obj 2>&1 | \
74# RUN: FileCheck -check-prefix=SWAPERR1 %s
75# RUN: not lld-link /out:%t.exe /entry:main /swaprun:cd, %t.obj 2>&1 | \
76# RUN: FileCheck -check-prefix=SWAPERR1 %s
77# RUN: not lld-link /out:%t.exe /entry:main /swaprun:,, %t.obj 2>&1 | \
78# RUN: FileCheck -check-prefix=SWAPERR1 %s
79# RUN: not lld-link /out:%t.exe /entry:main /swaprun:,cd %t.obj 2>&1 | \
80# RUN: FileCheck -check-prefix=SWAPERR1 %s
81SWAPERR1: /swaprun: missing argument
82
83# RUN: not lld-link /out:%t.exe /entry:main /swaprun:foo %t.obj 2>&1 | \
84# RUN: FileCheck -check-prefix=SWAPERR2 %s
85# RUN: not lld-link /out:%t.exe /entry:main /swaprun:cd,foo,net %t.obj 2>&1 | \
86# RUN: FileCheck -check-prefix=SWAPERR2 %s
87SWAPERR2: /swaprun: invalid argument: foo
88
89# RUN: not lld-link /out:%t.exe /entry:main /swaprun:cdfoo,net %t.obj 2>&1 | \
90# RUN: FileCheck -check-prefix=SWAPERR3 %s
91SWAPERR3: /swaprun: invalid argument: cdfoo
92
53# RUN: lld-link /out:%t.exe /entry:main %t.obj93# RUN: lld-link /out:%t.exe /entry:main %t.obj
54# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=TSAWARE %s94# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=TSAWARE %s
55# RUN: lld-link /out:%t.exe /entry:main /tsaware %t.obj95# RUN: lld-link /out:%t.exe /entry:main /tsaware %t.obj
56# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=TSAWARE %s96# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=TSAWARE %s
57TSAWARE: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE97TSAWARE: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE
5898
59# RUN: lld-link /tsaware:no /out:%t.exe /entry:main %t.obj99# RUN: lld-link /tsaware:no /out:%t.exe /entry:main %t.obj
60# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=NOTSAWARE %s100# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=NOTSAWARE %s
61# RUN: lld-link /dll /out:%t.dll /entry:main %t.obj101# RUN: lld-link /dll /out:%t.dll /entry:main %t.obj
62# RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=NOTSAWARE %s102# RUN: llvm-readobj --file-headers %t.dll | FileCheck -check-prefix=NOTSAWARE %s
63# RUN: lld-link /tsaware /dll /out:%t.dll /entry:main %t.obj103# RUN: lld-link /tsaware /dll /out:%t.dll /entry:main %t.obj
64# RUN: llvm-readobj -file-headers %t.dll | FileCheck -check-prefix=NOTSAWARE %s104# RUN: llvm-readobj --file-headers %t.dll | FileCheck -check-prefix=NOTSAWARE %s
65NOTSAWARE-NOT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE105NOTSAWARE-NOT: IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE
deps/lld/test/COFF/order-i386.test+2-2
...@@ -3,12 +3,12 @@...@@ -3,12 +3,12 @@
3# RUN: echo fn1 > %t.order3# RUN: echo fn1 > %t.order
4# RUN: echo fn2 >> %t.order4# RUN: echo fn2 >> %t.order
55
6# RUN: lld-link -entry:fn1 -subsystem:console -opt:noref %t.obj \6# RUN: lld-link -safeseh:no -entry:fn1 -subsystem:console -opt:noref %t.obj \
7# RUN: -lldmap:- -out:%t.exe -order:@%t.order | FileCheck %s7# RUN: -lldmap:- -out:%t.exe -order:@%t.order | FileCheck %s
8# CHECK: fn18# CHECK: fn1
9# CHECK: fn29# CHECK: fn2
1010
11# RUN: lld-link -entry:fn1 -subsystem:console -opt:noref %t.obj \11# RUN: lld-link -safeseh:no -entry:fn1 -subsystem:console -opt:noref %t.obj \
12# RUN: -lldmap:- -out:%t.exe | FileCheck -check-prefix=DEFAULT %s12# RUN: -lldmap:- -out:%t.exe | FileCheck -check-prefix=DEFAULT %s
13# DEFAULT: fn213# DEFAULT: fn2
14# DEFAULT: fn114# DEFAULT: fn1
deps/lld/test/COFF/output-chars.test+4-4
...@@ -1,12 +1,12 @@...@@ -1,12 +1,12 @@
1# RUN: yaml2obj %s > %t.obj1# RUN: yaml2obj %s > %t.obj
2# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj2# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj
3# RUN: llvm-readobj -sections %t.dll | FileCheck %s3# RUN: llvm-readobj --sections %t.dll | FileCheck %s
4# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj /section:.foo,rwe4# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj /section:.foo,rwe
5# RUN: llvm-readobj -sections %t.dll | FileCheck --check-prefix=SECTION %s5# RUN: llvm-readobj --sections %t.dll | FileCheck --check-prefix=SECTION %s
6# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj /merge:.foo=.bar6# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj /merge:.foo=.bar
7# RUN: llvm-readobj -sections -section-data %t.dll | FileCheck --check-prefix=MERGE %s7# RUN: llvm-readobj --sections --section-data %t.dll | FileCheck --check-prefix=MERGE %s
8# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj /merge:.foo=.bar /section:.foo,rwe8# RUN: lld-link /out:%t.dll /entry:__ImageBase /dll %t.obj /merge:.foo=.bar /section:.foo,rwe
9# RUN: llvm-readobj -sections %t.dll | FileCheck --check-prefix=MERGE-SECTION %s9# RUN: llvm-readobj --sections %t.dll | FileCheck --check-prefix=MERGE-SECTION %s
1010
11# CHECK: Name: .foo11# CHECK: Name: .foo
12# CHECK: Characteristics [12# CHECK: Characteristics [
deps/lld/test/COFF/pdb-comdat.test+2-2
...@@ -48,9 +48,9 @@ CHECK-NEXT: module = 2, sum name = 0, offset = 120...@@ -48,9 +48,9 @@ CHECK-NEXT: module = 2, sum name = 0, offset = 120
48CHECK-NEXT: 128 | S_PROCREF [size = 20] `foo`48CHECK-NEXT: 128 | S_PROCREF [size = 20] `foo`
49CHECK-NEXT: module = 1, sum name = 0, offset = 20849CHECK-NEXT: module = 1, sum name = 0, offset = 208
50CHECK-NEXT: 104 | S_GDATA32 [size = 24] `global`50CHECK-NEXT: 104 | S_GDATA32 [size = 24] `global`
51CHECK-NEXT: type = 0x0074 (int), addr = 0000:000051CHECK-NEXT: type = 0x0074 (int), addr = 0003:0000
52CHECK-NEXT: 168 | S_GDATA32 [size = 24] `global`52CHECK-NEXT: 168 | S_GDATA32 [size = 24] `global`
53CHECK-NEXT: type = 0x0074 (int), addr = 0000:000053CHECK-NEXT: type = 0x0074 (int), addr = 0003:0000
5454
55CHECK: Symbols55CHECK: Symbols
56CHECK: ============================================================56CHECK: ============================================================
deps/lld/test/COFF/pdb-debug-f.s+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple=i386-pc-win32 -filetype=obj -o %t.obj %s2# 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.obj3# RUN: lld-link -safeseh:no /subsystem:console /debug /nodefaultlib /entry:foo /out:%t.exe /pdb:%t.pdb %t.obj
4# RUN: llvm-pdbutil dump -fpo %t.pdb | FileCheck %s4# RUN: llvm-pdbutil dump -fpo %t.pdb | FileCheck %s
55
6# CHECK: Old FPO Data6# CHECK: Old FPO Data
deps/lld/test/COFF/pdb-exe-path-dots.test+1-1
...@@ -5,6 +5,6 @@ RUN: mkdir %t...@@ -5,6 +5,6 @@ RUN: mkdir %t
5RUN: mkdir %t/foo5RUN: mkdir %t/foo
6RUN: lld-link /debug /pdb:%t/foo/./out.pdb /out:%t/out.exe /entry:main /nodefaultlib \6RUN: lld-link /debug /pdb:%t/foo/./out.pdb /out:%t/out.exe /entry:main /nodefaultlib \
7RUN: %t1.obj %t2.obj7RUN: %t1.obj %t2.obj
8RUN: llvm-readobj -coff-debug-directory %t/out.exe | FileCheck %s8RUN: llvm-readobj --coff-debug-directory %t/out.exe | FileCheck %s
99
10CHECK: PDBFileName: {{.*}}tmp{{/|\\}}foo{{/|\\}}out.pdb10CHECK: PDBFileName: {{.*}}tmp{{/|\\}}foo{{/|\\}}out.pdb
\ No newline at end of file
deps/lld/test/COFF/pdb-global-constants.test created+28
...@@ -0,0 +1,28 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj %S/Inputs/pdb-global-constants-a.s -o %t-a.obj -triple x86_64-windows-msvc
3# RUN: llvm-mc -filetype=obj %S/Inputs/pdb-global-constants-b.s -o %t-b.obj -triple x86_64-windows-msvc
4# RUN: lld-link -entry:main -nodefaultlib %t-a.obj %t-b.obj -out:%t.exe -pdb:%t.pdb -debug
5# RUN: llvm-pdbutil dump -globals %t.pdb | FileCheck %s
6
7# Test that lld deduplicates S_CONSTANT records with the same name and value.
8#
9# Compiled from this C code, using
10# clang t.cpp -g -gcodeview -S
11#
12# %t-a.cpp:
13# const int Foo = 41;
14# const int Bar = 42;
15# int main() { return Foo + Bar; }
16#
17# %t-b.cpp:
18# const int Foo = 42;
19# const int Bar = 42;
20# int foobar() { return Foo + Bar; }
21
22CHECK: Global Symbols
23CHECK: 88 | S_CONSTANT [size = 16] `Bar`
24CHECK-NEXT: type = 0x1002 (const int), value = 42
25CHECK-NEXT: 72 | S_CONSTANT [size = 16] `Foo`
26CHECK-NEXT: type = 0x1002 (const int), value = 41
27CHECK-NEXT: 128 | S_CONSTANT [size = 16] `Foo`
28CHECK-NEXT: type = 0x1002 (const int), value = 42
deps/lld/test/COFF/pdb-global-gc.yaml+1
...@@ -23,6 +23,7 @@...@@ -23,6 +23,7 @@
23# CHECK: ============================================================23# CHECK: ============================================================
24# CHECK-NEXT: Mod 0000 | `{{.*}}pdb-global-gc.yaml.tmp.obj`:24# CHECK-NEXT: Mod 0000 | `{{.*}}pdb-global-gc.yaml.tmp.obj`:
25# CHECK-NEXT: Mod 0001 | `{{.*}}pdb-global-gc.yaml.tmp2.obj`:25# CHECK-NEXT: Mod 0001 | `{{.*}}pdb-global-gc.yaml.tmp2.obj`:
26# CHECK-NEXT: Error loading module stream 1. The specified stream could not be loaded. Module stream not present
26# CHECK-NEXT: Mod 0002 | `* Linker *`:27# CHECK-NEXT: Mod 0002 | `* Linker *`:
2728
28--- !COFF29--- !COFF
deps/lld/test/COFF/pdb-globals.test+5
...@@ -2,6 +2,11 @@ RUN: yaml2obj %S/Inputs/pdb-globals.yaml > %t.obj...@@ -2,6 +2,11 @@ RUN: yaml2obj %S/Inputs/pdb-globals.yaml > %t.obj
2RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj2RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj
3RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s3RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s
44
5RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj /threads
6RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s
7RUN: lld-link /debug /nodefaultlib /entry:main /out:%t.exe /pdb:%t.pdb %t.obj /threads:no
8RUN: llvm-pdbutil dump -symbols -globals %t.pdb | FileCheck %s
9
5# Test that we correctly distribute symbols between the globals and module10# Test that we correctly distribute symbols between the globals and module
6# symbol streams. Specifically:11# symbol streams. Specifically:
7# * S_UDT, S_GDATA32, and S_CONSTANT end up in the globals stream, and are12# * S_UDT, S_GDATA32, and S_CONSTANT end up in the globals stream, and are
deps/lld/test/COFF/pdb-inlinees-extrafiles.s created+334
...@@ -0,0 +1,334 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj %s -o %t.obj -triple x86_64-windows-msvc
3# RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe -pdb:%t.pdb -debug
4# RUN: llvm-pdbutil dump -il %t.pdb | FileCheck %s
5
6# The assembly was hand written to model the following C code. As of this
7# writing, clang does not emit extra files for inlinees, so it had to be hand
8# written.
9
10# // t1.h:
11# ++x;
12# #include "t2.h"
13# ++x;
14
15# // t2.h:
16# ++x;
17# __debugbreak();
18# ++x;
19
20# // t.c:
21# volatile int x;
22# static __forceinline void inlinee_1(void) {
23# ++x;
24# #include "t1.inc"
25# ++x;
26# }
27# int main() {
28# ++x;
29# inlinee_1();
30# ++x;
31# return x;
32# }
33
34# CHECK: Inlinee Lines
35# CHECK: Mod 0000 | `{{.*}}pdb-inlinees-extrafiles.s.tmp.obj`:
36# CHECK-NEXT: Inlinee | Line | Source File
37# CHECK-NEXT: 0x1000 | 7 | C:\src\llvm-project\build\t.c (MD5: A79D837C976E9F0463A474D74E2EE9E7)
38# CHECK-NEXT: C:\src\llvm-project\build\t1.h (MD5: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
39# CHECK-NEXT: C:\src\llvm-project\build\t2.h (MD5: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
40
41 .text
42 .def @feat.00;
43 .scl 3;
44 .type 0;
45 .endef
46 .globl @feat.00
47.set @feat.00, 0
48 .intel_syntax noprefix
49 .file "t.c"
50 .def main;
51 .scl 2;
52 .type 32;
53 .endef
54 .section .text,"xr",one_only,main
55 .globl main # -- Begin function main
56main: # @main
57.Lfunc_begin0:
58 .cv_func_id 0
59# %bb.0: # %entry
60 .cv_file 1 "C:\\src\\llvm-project\\build\\t.c" "A79D837C976E9F0463A474D74E2EE9E7" 1
61 .cv_file 2 "C:\\src\\llvm-project\\build\\t1.h" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1
62 .cv_file 3 "C:\\src\\llvm-project\\build\\t2.h" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1
63 .cv_loc 0 1 13 0 # t.c:13:0
64 inc dword ptr [rip + x]
65.Ltmp0:
66 .cv_inline_site_id 1 within 0 inlined_at 1 14 0
67 .cv_loc 1 1 3 0 # t.c:3:0
68 inc dword ptr [rip + x]
69.Ltmp1:
70 .cv_loc 1 2 1 0 # t1.h:1:0
71 inc dword ptr [rip + x]
72 .cv_loc 1 3 1 0 # t2.h:1:0
73 inc dword ptr [rip + x]
74 .cv_loc 1 3 2 0 # t2.h:2:0
75 int3
76 .cv_loc 1 3 3 0 # t2.h:3:0
77 inc dword ptr [rip + x]
78 .cv_loc 1 2 3 0 # t1.h:3:0
79 inc dword ptr [rip + x]
80.Ltmp2:
81 .cv_loc 1 1 5 0 # t.c:5:0
82 inc dword ptr [rip + x]
83.Ltmp3:
84 .cv_loc 0 1 15 0 # t.c:15:0
85 inc dword ptr [rip + x]
86 .cv_loc 0 1 16 0 # t.c:16:0
87 mov eax, dword ptr [rip + x]
88 ret
89.Ltmp4:
90.Lfunc_end0:
91 # -- End function
92 .comm x,4,2 # @x
93 .section .debug$S,"dr"
94 .p2align 2
95 .long 4 # Debug section magic
96 .long 241
97 .long .Ltmp6-.Ltmp5 # Subsection size
98.Ltmp5:
99 .short .Ltmp8-.Ltmp7 # Record length
100.Ltmp7:
101 .short 4412 # Record kind: S_COMPILE3
102 .long 0 # Flags and language
103 .short 208 # CPUType
104 .short 9 # Frontend version
105 .short 0
106 .short 0
107 .short 0
108 .short 9000 # Backend version
109 .short 0
110 .short 0
111 .short 0
112 .asciz "clang version 9.0.0 (git@github.com:llvm/llvm-project.git aa762a56caf3ef2b0b41c501e66d3ef32903a2d0)" # Null-terminated compiler version string
113 .p2align 2
114.Ltmp8:
115.Ltmp6:
116 .p2align 2
117 .long 246 # Inlinee lines subsection
118 .long .Ltmp10-.Ltmp9 # Subsection size
119.Ltmp9:
120 .long 1 # Inlinee lines signature, extra files
121
122 # Inlined function inlinee_1 starts at t.c:7
123 .long 4098 # Type index of inlined function
124 .cv_filechecksumoffset 1 # Offset into filechecksum table
125 .long 7 # Starting line number
126 .long 2
127 .cv_filechecksumoffset 2 # Offset into filechecksum table
128 .cv_filechecksumoffset 3 # Offset into filechecksum table
129
130.Ltmp10:
131 .p2align 2
132 .section .debug$S,"dr",associative,main
133 .p2align 2
134 .long 4 # Debug section magic
135 .long 241 # Symbol subsection for main
136 .long .Ltmp12-.Ltmp11 # Subsection size
137.Ltmp11:
138 .short .Ltmp14-.Ltmp13 # Record length
139.Ltmp13:
140 .short 4423 # Record kind: S_GPROC32_ID
141 .long 0 # PtrParent
142 .long 0 # PtrEnd
143 .long 0 # PtrNext
144 .long .Lfunc_end0-main # Code size
145 .long 0 # Offset after prologue
146 .long 0 # Offset before epilogue
147 .long 4101 # Function type index
148 .secrel32 main # Function section relative address
149 .secidx main # Function section index
150 .byte 0 # Flags
151 .asciz "main" # Function name
152 .p2align 2
153.Ltmp14:
154 .short .Ltmp16-.Ltmp15 # Record length
155.Ltmp15:
156 .short 4114 # Record kind: S_FRAMEPROC
157 .long 0 # FrameSize
158 .long 0 # Padding
159 .long 0 # Offset of padding
160 .long 0 # Bytes of callee saved registers
161 .long 0 # Exception handler offset
162 .short 0 # Exception handler section
163 .long 0 # Flags (defines frame register)
164 .p2align 2
165.Ltmp16:
166 .short .Ltmp18-.Ltmp17 # Record length
167.Ltmp17:
168 .short 4429 # Record kind: S_INLINESITE
169 .long 0 # PtrParent
170 .long 0 # PtrEnd
171 .long 4098 # Inlinee type index
172 .cv_inline_linetable 1 1 7 .Lfunc_begin0 .Lfunc_end0
173 .p2align 2
174.Ltmp18:
175 .short 2 # Record length
176 .short 4430 # Record kind: S_INLINESITE_END
177 .short 2 # Record length
178 .short 4431 # Record kind: S_PROC_ID_END
179.Ltmp12:
180 .p2align 2
181 .cv_linetable 0, main, .Lfunc_end0
182 .section .debug$S,"dr"
183 .long 241 # Symbol subsection for globals
184 .long .Ltmp22-.Ltmp21 # Subsection size
185.Ltmp21:
186 .short .Ltmp24-.Ltmp23 # Record length
187.Ltmp23:
188 .short 4365 # Record kind: S_GDATA32
189 .long 4102 # Type
190 .secrel32 x # DataOffset
191 .secidx x # Segment
192 .asciz "x" # Name
193 .p2align 2
194.Ltmp24:
195.Ltmp22:
196 .p2align 2
197 .cv_filechecksums # File index to string table offset subsection
198 .cv_stringtable # String table
199 .long 241
200 .long .Ltmp26-.Ltmp25 # Subsection size
201.Ltmp25:
202 .short .Ltmp28-.Ltmp27 # Record length
203.Ltmp27:
204 .short 4428 # Record kind: S_BUILDINFO
205 .long 4105 # LF_BUILDINFO index
206 .p2align 2
207.Ltmp28:
208.Ltmp26:
209 .p2align 2
210 .section .debug$T,"dr"
211 .p2align 2
212 .long 4 # Debug section magic
213 # ArgList (0x1000) {
214 # TypeLeafKind: LF_ARGLIST (0x1201)
215 # NumArgs: 0
216 # Arguments [
217 # ]
218 # }
219 .byte 0x06, 0x00, 0x01, 0x12
220 .byte 0x00, 0x00, 0x00, 0x00
221 # Procedure (0x1001) {
222 # TypeLeafKind: LF_PROCEDURE (0x1008)
223 # ReturnType: void (0x3)
224 # CallingConvention: NearC (0x0)
225 # FunctionOptions [ (0x0)
226 # ]
227 # NumParameters: 0
228 # ArgListType: () (0x1000)
229 # }
230 .byte 0x0e, 0x00, 0x08, 0x10
231 .byte 0x03, 0x00, 0x00, 0x00
232 .byte 0x00, 0x00, 0x00, 0x00
233 .byte 0x00, 0x10, 0x00, 0x00
234 # FuncId (0x1002) {
235 # TypeLeafKind: LF_FUNC_ID (0x1601)
236 # ParentScope: 0x0
237 # FunctionType: void () (0x1001)
238 # Name: inlinee_1
239 # }
240 .byte 0x16, 0x00, 0x01, 0x16
241 .byte 0x00, 0x00, 0x00, 0x00
242 .byte 0x01, 0x10, 0x00, 0x00
243 .byte 0x69, 0x6e, 0x6c, 0x69
244 .byte 0x6e, 0x65, 0x65, 0x5f
245 .byte 0x31, 0x00, 0xf2, 0xf1
246 # FuncId (0x1003) {
247 # TypeLeafKind: LF_FUNC_ID (0x1601)
248 # ParentScope: 0x0
249 # FunctionType: void () (0x1001)
250 # Name: inlinee_2
251 # }
252 .byte 0x16, 0x00, 0x01, 0x16
253 .byte 0x00, 0x00, 0x00, 0x00
254 .byte 0x01, 0x10, 0x00, 0x00
255 .byte 0x69, 0x6e, 0x6c, 0x69
256 .byte 0x6e, 0x65, 0x65, 0x5f
257 .byte 0x32, 0x00, 0xf2, 0xf1
258 # Procedure (0x1004) {
259 # TypeLeafKind: LF_PROCEDURE (0x1008)
260 # ReturnType: int (0x74)
261 # CallingConvention: NearC (0x0)
262 # FunctionOptions [ (0x0)
263 # ]
264 # NumParameters: 0
265 # ArgListType: () (0x1000)
266 # }
267 .byte 0x0e, 0x00, 0x08, 0x10
268 .byte 0x74, 0x00, 0x00, 0x00
269 .byte 0x00, 0x00, 0x00, 0x00
270 .byte 0x00, 0x10, 0x00, 0x00
271 # FuncId (0x1005) {
272 # TypeLeafKind: LF_FUNC_ID (0x1601)
273 # ParentScope: 0x0
274 # FunctionType: int () (0x1004)
275 # Name: main
276 # }
277 .byte 0x12, 0x00, 0x01, 0x16
278 .byte 0x00, 0x00, 0x00, 0x00
279 .byte 0x04, 0x10, 0x00, 0x00
280 .byte 0x6d, 0x61, 0x69, 0x6e
281 .byte 0x00, 0xf3, 0xf2, 0xf1
282 # Modifier (0x1006) {
283 # TypeLeafKind: LF_MODIFIER (0x1001)
284 # ModifiedType: int (0x74)
285 # Modifiers [ (0x2)
286 # Volatile (0x2)
287 # ]
288 # }
289 .byte 0x0a, 0x00, 0x01, 0x10
290 .byte 0x74, 0x00, 0x00, 0x00
291 .byte 0x02, 0x00, 0xf2, 0xf1
292 # StringId (0x1007) {
293 # TypeLeafKind: LF_STRING_ID (0x1605)
294 # Id: 0x0
295 # StringData: C:\src\llvm-project\build
296 # }
297 .byte 0x22, 0x00, 0x05, 0x16
298 .byte 0x00, 0x00, 0x00, 0x00
299 .byte 0x43, 0x3a, 0x5c, 0x73
300 .byte 0x72, 0x63, 0x5c, 0x6c
301 .byte 0x6c, 0x76, 0x6d, 0x2d
302 .byte 0x70, 0x72, 0x6f, 0x6a
303 .byte 0x65, 0x63, 0x74, 0x5c
304 .byte 0x62, 0x75, 0x69, 0x6c
305 .byte 0x64, 0x00, 0xf2, 0xf1
306 # StringId (0x1008) {
307 # TypeLeafKind: LF_STRING_ID (0x1605)
308 # Id: 0x0
309 # StringData: t.c
310 # }
311 .byte 0x0a, 0x00, 0x05, 0x16
312 .byte 0x00, 0x00, 0x00, 0x00
313 .byte 0x74, 0x2e, 0x63, 0x00
314 # BuildInfo (0x1009) {
315 # TypeLeafKind: LF_BUILDINFO (0x1603)
316 # NumArgs: 5
317 # Arguments [
318 # ArgType: C:\src\llvm-project\build (0x1007)
319 # ArgType: 0x0
320 # ArgType: t.c (0x1008)
321 # ArgType: 0x0
322 # ArgType: 0x0
323 # ]
324 # }
325 .byte 0x1a, 0x00, 0x03, 0x16
326 .byte 0x05, 0x00, 0x07, 0x10
327 .byte 0x00, 0x00, 0x00, 0x00
328 .byte 0x00, 0x00, 0x08, 0x10
329 .byte 0x00, 0x00, 0x00, 0x00
330 .byte 0x00, 0x00, 0x00, 0x00
331 .byte 0x00, 0x00, 0xf2, 0xf1
332
333 .addrsig
334 .addrsig_sym x
deps/lld/test/COFF/pdb-inlinees.s created+332
...@@ -0,0 +1,332 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj %s -o %t.obj -triple x86_64-windows-msvc
3# RUN: lld-link -entry:main -nodefaultlib %t.obj -out:%t.exe -pdb:%t.pdb -debug
4# RUN: llvm-pdbutil dump -il %t.pdb | FileCheck %s
5
6# Compiled from this C code, with modifications to test multiple file checksums:
7# volatile int x;
8# static __forceinline void inlinee_2(void) {
9# ++x;
10# __debugbreak();
11# ++x;
12# }
13# static __forceinline void inlinee_1(void) {
14# ++x;
15# inlinee_2();
16# ++x;
17# }
18# int main() {
19# ++x;
20# inlinee_1();
21# ++x;
22# return x;
23# }
24
25# CHECK: Inlinee Lines
26# CHECK: Mod 0000 | `{{.*}}pdb-inlinees.s.tmp.obj`:
27# CHECK-NEXT: Inlinee | Line | Source File
28# CHECK-NEXT: 0x1000 | 7 | C:\src\llvm-project\build\t.c (MD5: A79D837C976E9F0463A474D74E2EE9E7)
29# CHECK-NEXT: 0x1001 | 2 | C:\src\llvm-project\build\file2.h (MD5: FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF)
30
31 .text
32 .def @feat.00;
33 .scl 3;
34 .type 0;
35 .endef
36 .globl @feat.00
37.set @feat.00, 0
38 .intel_syntax noprefix
39 .file "t.c"
40 .def main;
41 .scl 2;
42 .type 32;
43 .endef
44 .section .text,"xr",one_only,main
45 .globl main # -- Begin function main
46main: # @main
47.Lfunc_begin0:
48 .cv_func_id 0
49# %bb.0: # %entry
50 .cv_file 1 "C:\\src\\llvm-project\\build\\t.c" "A79D837C976E9F0463A474D74E2EE9E7" 1
51 .cv_file 2 "C:\\src\\llvm-project\\build\\file2.h" "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF" 1
52 .cv_loc 0 1 13 0 # t.c:13:0
53 inc dword ptr [rip + x]
54.Ltmp0:
55 .cv_inline_site_id 1 within 0 inlined_at 1 14 0
56 .cv_loc 1 1 8 0 # t.c:8:0
57 inc dword ptr [rip + x]
58.Ltmp1:
59 .cv_inline_site_id 2 within 1 inlined_at 1 9 0
60 .cv_loc 2 2 3 0 # file2.h:3:0
61 inc dword ptr [rip + x]
62 .cv_loc 2 2 4 0 # file2.h:4:0
63 int3
64 .cv_loc 2 2 5 0 # file2.h:5:0
65 inc dword ptr [rip + x]
66.Ltmp2:
67 .cv_loc 1 1 10 0 # t.c:10:0
68 inc dword ptr [rip + x]
69.Ltmp3:
70 .cv_loc 0 1 15 0 # t.c:15:0
71 inc dword ptr [rip + x]
72 .cv_loc 0 1 16 0 # t.c:16:0
73 mov eax, dword ptr [rip + x]
74 ret
75.Ltmp4:
76.Lfunc_end0:
77 # -- End function
78 .comm x,4,2 # @x
79 .section .debug$S,"dr"
80 .p2align 2
81 .long 4 # Debug section magic
82 .long 241
83 .long .Ltmp6-.Ltmp5 # Subsection size
84.Ltmp5:
85 .short .Ltmp8-.Ltmp7 # Record length
86.Ltmp7:
87 .short 4412 # Record kind: S_COMPILE3
88 .long 0 # Flags and language
89 .short 208 # CPUType
90 .short 9 # Frontend version
91 .short 0
92 .short 0
93 .short 0
94 .short 9000 # Backend version
95 .short 0
96 .short 0
97 .short 0
98 .asciz "clang version 9.0.0 (git@github.com:llvm/llvm-project.git aa762a56caf3ef2b0b41c501e66d3ef32903a2d0)" # Null-terminated compiler version string
99 .p2align 2
100.Ltmp8:
101.Ltmp6:
102 .p2align 2
103 .long 246 # Inlinee lines subsection
104 .long .Ltmp10-.Ltmp9 # Subsection size
105.Ltmp9:
106 .long 0 # Inlinee lines signature
107
108 # Inlined function inlinee_1 starts at t.c:7
109 .long 4098 # Type index of inlined function
110 .cv_filechecksumoffset 1 # Offset into filechecksum table
111 .long 7 # Starting line number
112
113 # Inlined function inlinee_2 starts at file2.h:2
114 .long 4099 # Type index of inlined function
115 .cv_filechecksumoffset 2 # Offset into filechecksum table
116 .long 2 # Starting line number
117.Ltmp10:
118 .p2align 2
119 .section .debug$S,"dr",associative,main
120 .p2align 2
121 .long 4 # Debug section magic
122 .long 241 # Symbol subsection for main
123 .long .Ltmp12-.Ltmp11 # Subsection size
124.Ltmp11:
125 .short .Ltmp14-.Ltmp13 # Record length
126.Ltmp13:
127 .short 4423 # Record kind: S_GPROC32_ID
128 .long 0 # PtrParent
129 .long 0 # PtrEnd
130 .long 0 # PtrNext
131 .long .Lfunc_end0-main # Code size
132 .long 0 # Offset after prologue
133 .long 0 # Offset before epilogue
134 .long 4101 # Function type index
135 .secrel32 main # Function section relative address
136 .secidx main # Function section index
137 .byte 0 # Flags
138 .asciz "main" # Function name
139 .p2align 2
140.Ltmp14:
141 .short .Ltmp16-.Ltmp15 # Record length
142.Ltmp15:
143 .short 4114 # Record kind: S_FRAMEPROC
144 .long 0 # FrameSize
145 .long 0 # Padding
146 .long 0 # Offset of padding
147 .long 0 # Bytes of callee saved registers
148 .long 0 # Exception handler offset
149 .short 0 # Exception handler section
150 .long 0 # Flags (defines frame register)
151 .p2align 2
152.Ltmp16:
153 .short .Ltmp18-.Ltmp17 # Record length
154.Ltmp17:
155 .short 4429 # Record kind: S_INLINESITE
156 .long 0 # PtrParent
157 .long 0 # PtrEnd
158 .long 4098 # Inlinee type index
159 .cv_inline_linetable 1 1 7 .Lfunc_begin0 .Lfunc_end0
160 .p2align 2
161.Ltmp18:
162 .short .Ltmp20-.Ltmp19 # Record length
163.Ltmp19:
164 .short 4429 # Record kind: S_INLINESITE
165 .long 0 # PtrParent
166 .long 0 # PtrEnd
167 .long 4099 # Inlinee type index
168 .cv_inline_linetable 2 2 2 .Lfunc_begin0 .Lfunc_end0
169 .p2align 2
170.Ltmp20:
171 .short 2 # Record length
172 .short 4430 # Record kind: S_INLINESITE_END
173 .short 2 # Record length
174 .short 4430 # Record kind: S_INLINESITE_END
175 .short 2 # Record length
176 .short 4431 # Record kind: S_PROC_ID_END
177.Ltmp12:
178 .p2align 2
179 .cv_linetable 0, main, .Lfunc_end0
180 .section .debug$S,"dr"
181 .long 241 # Symbol subsection for globals
182 .long .Ltmp22-.Ltmp21 # Subsection size
183.Ltmp21:
184 .short .Ltmp24-.Ltmp23 # Record length
185.Ltmp23:
186 .short 4365 # Record kind: S_GDATA32
187 .long 4102 # Type
188 .secrel32 x # DataOffset
189 .secidx x # Segment
190 .asciz "x" # Name
191 .p2align 2
192.Ltmp24:
193.Ltmp22:
194 .p2align 2
195 .cv_filechecksums # File index to string table offset subsection
196 .cv_stringtable # String table
197 .long 241
198 .long .Ltmp26-.Ltmp25 # Subsection size
199.Ltmp25:
200 .short .Ltmp28-.Ltmp27 # Record length
201.Ltmp27:
202 .short 4428 # Record kind: S_BUILDINFO
203 .long 4105 # LF_BUILDINFO index
204 .p2align 2
205.Ltmp28:
206.Ltmp26:
207 .p2align 2
208 .section .debug$T,"dr"
209 .p2align 2
210 .long 4 # Debug section magic
211 # ArgList (0x1000) {
212 # TypeLeafKind: LF_ARGLIST (0x1201)
213 # NumArgs: 0
214 # Arguments [
215 # ]
216 # }
217 .byte 0x06, 0x00, 0x01, 0x12
218 .byte 0x00, 0x00, 0x00, 0x00
219 # Procedure (0x1001) {
220 # TypeLeafKind: LF_PROCEDURE (0x1008)
221 # ReturnType: void (0x3)
222 # CallingConvention: NearC (0x0)
223 # FunctionOptions [ (0x0)
224 # ]
225 # NumParameters: 0
226 # ArgListType: () (0x1000)
227 # }
228 .byte 0x0e, 0x00, 0x08, 0x10
229 .byte 0x03, 0x00, 0x00, 0x00
230 .byte 0x00, 0x00, 0x00, 0x00
231 .byte 0x00, 0x10, 0x00, 0x00
232 # FuncId (0x1002) {
233 # TypeLeafKind: LF_FUNC_ID (0x1601)
234 # ParentScope: 0x0
235 # FunctionType: void () (0x1001)
236 # Name: inlinee_1
237 # }
238 .byte 0x16, 0x00, 0x01, 0x16
239 .byte 0x00, 0x00, 0x00, 0x00
240 .byte 0x01, 0x10, 0x00, 0x00
241 .byte 0x69, 0x6e, 0x6c, 0x69
242 .byte 0x6e, 0x65, 0x65, 0x5f
243 .byte 0x31, 0x00, 0xf2, 0xf1
244 # FuncId (0x1003) {
245 # TypeLeafKind: LF_FUNC_ID (0x1601)
246 # ParentScope: 0x0
247 # FunctionType: void () (0x1001)
248 # Name: inlinee_2
249 # }
250 .byte 0x16, 0x00, 0x01, 0x16
251 .byte 0x00, 0x00, 0x00, 0x00
252 .byte 0x01, 0x10, 0x00, 0x00
253 .byte 0x69, 0x6e, 0x6c, 0x69
254 .byte 0x6e, 0x65, 0x65, 0x5f
255 .byte 0x32, 0x00, 0xf2, 0xf1
256 # Procedure (0x1004) {
257 # TypeLeafKind: LF_PROCEDURE (0x1008)
258 # ReturnType: int (0x74)
259 # CallingConvention: NearC (0x0)
260 # FunctionOptions [ (0x0)
261 # ]
262 # NumParameters: 0
263 # ArgListType: () (0x1000)
264 # }
265 .byte 0x0e, 0x00, 0x08, 0x10
266 .byte 0x74, 0x00, 0x00, 0x00
267 .byte 0x00, 0x00, 0x00, 0x00
268 .byte 0x00, 0x10, 0x00, 0x00
269 # FuncId (0x1005) {
270 # TypeLeafKind: LF_FUNC_ID (0x1601)
271 # ParentScope: 0x0
272 # FunctionType: int () (0x1004)
273 # Name: main
274 # }
275 .byte 0x12, 0x00, 0x01, 0x16
276 .byte 0x00, 0x00, 0x00, 0x00
277 .byte 0x04, 0x10, 0x00, 0x00
278 .byte 0x6d, 0x61, 0x69, 0x6e
279 .byte 0x00, 0xf3, 0xf2, 0xf1
280 # Modifier (0x1006) {
281 # TypeLeafKind: LF_MODIFIER (0x1001)
282 # ModifiedType: int (0x74)
283 # Modifiers [ (0x2)
284 # Volatile (0x2)
285 # ]
286 # }
287 .byte 0x0a, 0x00, 0x01, 0x10
288 .byte 0x74, 0x00, 0x00, 0x00
289 .byte 0x02, 0x00, 0xf2, 0xf1
290 # StringId (0x1007) {
291 # TypeLeafKind: LF_STRING_ID (0x1605)
292 # Id: 0x0
293 # StringData: C:\src\llvm-project\build
294 # }
295 .byte 0x22, 0x00, 0x05, 0x16
296 .byte 0x00, 0x00, 0x00, 0x00
297 .byte 0x43, 0x3a, 0x5c, 0x73
298 .byte 0x72, 0x63, 0x5c, 0x6c
299 .byte 0x6c, 0x76, 0x6d, 0x2d
300 .byte 0x70, 0x72, 0x6f, 0x6a
301 .byte 0x65, 0x63, 0x74, 0x5c
302 .byte 0x62, 0x75, 0x69, 0x6c
303 .byte 0x64, 0x00, 0xf2, 0xf1
304 # StringId (0x1008) {
305 # TypeLeafKind: LF_STRING_ID (0x1605)
306 # Id: 0x0
307 # StringData: t.c
308 # }
309 .byte 0x0a, 0x00, 0x05, 0x16
310 .byte 0x00, 0x00, 0x00, 0x00
311 .byte 0x74, 0x2e, 0x63, 0x00
312 # BuildInfo (0x1009) {
313 # TypeLeafKind: LF_BUILDINFO (0x1603)
314 # NumArgs: 5
315 # Arguments [
316 # ArgType: C:\src\llvm-project\build (0x1007)
317 # ArgType: 0x0
318 # ArgType: t.c (0x1008)
319 # ArgType: 0x0
320 # ArgType: 0x0
321 # ]
322 # }
323 .byte 0x1a, 0x00, 0x03, 0x16
324 .byte 0x05, 0x00, 0x07, 0x10
325 .byte 0x00, 0x00, 0x00, 0x00
326 .byte 0x00, 0x00, 0x08, 0x10
327 .byte 0x00, 0x00, 0x00, 0x00
328 .byte 0x00, 0x00, 0x00, 0x00
329 .byte 0x00, 0x00, 0xf2, 0xf1
330
331 .addrsig
332 .addrsig_sym x
deps/lld/test/COFF/pdb-lib.s+4-4
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o foo.obj3# RUN: llvm-mc -filetype=obj -triple=i686-windows-msvc %s -o foo.obj
4# RUN: llc %S/Inputs/bar.ll -filetype=obj -mtriple=i686-windows-msvc -o bar.obj4# RUN: llc %S/Inputs/bar.ll -filetype=obj -mtriple=i686-windows-msvc -o bar.obj
5# RUN: llvm-lib bar.obj -out:bar.lib5# RUN: llvm-lib bar.obj -out:bar.lib
6# RUN: lld-link -debug -pdb:foo.pdb foo.obj bar.lib -out:foo.exe -entry:main6# RUN: lld-link -safeseh:no -debug -pdb:foo.pdb foo.obj bar.lib -out:foo.exe -entry:main
7# RUN: llvm-pdbutil dump -modules %t/foo.pdb | FileCheck %s7# RUN: llvm-pdbutil dump -modules %t/foo.pdb | FileCheck %s
88
9# Make sure that the PDB has module descriptors. foo.obj and bar.lib should be9# Make sure that the PDB has module descriptors. foo.obj and bar.lib should be
...@@ -13,15 +13,15 @@...@@ -13,15 +13,15 @@
13# CHECK-NEXT: ============================================================13# CHECK-NEXT: ============================================================
14# CHECK-NEXT: Mod 0000 | `{{.*pdb-lib.s.tmp[/\\]foo.obj}}`:14# CHECK-NEXT: Mod 0000 | `{{.*pdb-lib.s.tmp[/\\]foo.obj}}`:
15# CHECK-NEXT: Obj: `{{.*pdb-lib.s.tmp[/\\]foo.obj}}`:15# CHECK-NEXT: Obj: `{{.*pdb-lib.s.tmp[/\\]foo.obj}}`:
16# CHECK-NEXT: debug stream: 10, # files: 0, has ec info: false16# CHECK-NEXT: debug stream: 65535, # files: 0, has ec info: false
17# CHECK-NEXT: pdb file ni: 0 ``, src file ni: 0 ``17# CHECK-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
18# CHECK-NEXT: Mod 0001 | `bar.obj`:18# CHECK-NEXT: Mod 0001 | `bar.obj`:
19# CHECK-NEXT: Obj: `{{.*pdb-lib.s.tmp[/\\]bar.lib}}`:19# CHECK-NEXT: Obj: `{{.*pdb-lib.s.tmp[/\\]bar.lib}}`:
20# CHECK-NEXT: debug stream: 11, # files: 0, has ec info: false20# CHECK-NEXT: debug stream: 65535, # files: 0, has ec info: false
21# CHECK-NEXT: pdb file ni: 0 ``, src file ni: 0 ``21# CHECK-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
22# CHECK-NEXT: Mod 0002 | `* Linker *`:22# CHECK-NEXT: Mod 0002 | `* Linker *`:
23# CHECK-NEXT: Obj: ``:23# CHECK-NEXT: Obj: ``:
24# CHECK-NEXT: debug stream: 12, # files: 0, has ec info: false24# CHECK-NEXT: debug stream: 10, # files: 0, has ec info: false
25# CHECK-NEXT: pdb file ni: 1 `{{.*foo.pdb}}`, src file ni: 0 ``25# CHECK-NEXT: pdb file ni: 1 `{{.*foo.pdb}}`, src file ni: 0 ``
2626
27 .def _main;27 .def _main;
deps/lld/test/COFF/pdb-publics-import.test+148-5
...@@ -8,7 +8,48 @@ RUN: /export:exportfn1 /export:exportfn2...@@ -8,7 +8,48 @@ RUN: /export:exportfn1 /export:exportfn2
8RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj8RUN: yaml2obj < %p/Inputs/import.yaml > %t2.obj
9RUN: lld-link /out:%t2.exe /pdb:%t2.pdb /pdbaltpath:test.pdb \9RUN: lld-link /out:%t2.exe /pdb:%t2.pdb /pdbaltpath:test.pdb \
10RUN: /debug /entry:main %t2.obj %t1.lib10RUN: /debug /entry:main %t2.obj %t1.lib
11RUN: llvm-pdbutil dump %t2.pdb -publics -section-contribs | FileCheck %s11RUN: llvm-pdbutil dump %t2.pdb -all | FileCheck %s
12
13CHECK: Streams
14CHECK-NEXT: ============================================================
15CHECK-LABEL: Stream 10 ( 256 bytes): [Module "Import:pdb-publics-import.test.tmp1.dll"]
16
17CHECK: Module Stats
18CHECK-NEXT: ============================================================
19CHECK-NEXT: Mod 0000 | `{{.*}}pdb-publics-import.test.tmp2.obj`:
20CHECK-NEXT: Mod 0 (debug info not present): [{{.*}}pdb-publics-import.test.tmp2.obj]
21CHECK-NEXT: Mod 0001 | `pdb-publics-import.test.tmp1.dll`:
22CHECK-NEXT: Mod 1 (debug info not present): [pdb-publics-import.test.tmp1.dll]
23CHECK-NEXT: Mod 0002 | `Import:pdb-publics-import.test.tmp1.dll`:
24CHECK-NEXT: Stream 10, 256 bytes
25
26CHECK: Modules
27CHECK-NEXT: ============================================================
28CHECK-NEXT: Mod 0000 | `{{.*}}pdb-publics-import.test.tmp2.obj`:
29CHECK-NEXT: SC[.text] | mod = 0, 0001:0000, size = 8, data crc = 0, reloc crc = 0
30CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_EXECUTE |
31CHECK-NEXT: IMAGE_SCN_MEM_READ
32CHECK-NEXT: Obj: `{{.*}}pdb-publics-import.test.tmp2.obj`:
33CHECK-NEXT: debug stream: 65535, # files: 0, has ec info: false
34CHECK-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
35CHECK-NEXT: Mod 0001 | `pdb-publics-import.test.tmp1.dll`:
36CHECK-NEXT: SC[???] | mod = 65535, 65535:0000, size = -1, data crc = 0, reloc crc = 0
37CHECK-NEXT: none
38CHECK-NEXT: Obj: `{{.*}}pdb-publics-import.test.tmp1.lib`:
39CHECK-NEXT: debug stream: 65535, # files: 0, has ec info: false
40CHECK-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
41CHECK-NEXT: Mod 0002 | `Import:pdb-publics-import.test.tmp1.dll`:
42CHECK-NEXT: SC[.text] | mod = 2, 0001:0032, size = 6, data crc = 0, reloc crc = 0
43CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
44CHECK-NEXT: Obj: `{{.*}}pdb-publics-import.test.tmp1.lib`:
45CHECK-NEXT: debug stream: 10, # files: 0, has ec info: false
46CHECK-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
47CHECK-NEXT: Mod 0003 | `* Linker *`:
48CHECK-NEXT: SC[???] | mod = 65535, 65535:0000, size = -1, data crc = 0, reloc crc = 0
49CHECK-NEXT: none
50CHECK-NEXT: Obj: ``:
51CHECK-NEXT: debug stream: 11, # files: 0, has ec info: false
52CHECK-NEXT: pdb file ni: 1 `{{.*}}pdb-publics-import.test.tmp2.pdb`, src file ni: 0 ``
1253
13CHECK: Public Symbols54CHECK: Public Symbols
14CHECK-NEXT: ============================================================55CHECK-NEXT: ============================================================
...@@ -24,6 +65,86 @@ CHECK-NEXT: flags = none, addr = 0002:0136...@@ -24,6 +65,86 @@ CHECK-NEXT: flags = none, addr = 0002:0136
24CHECK-NEXT: 0 | S_PUB32 [size = 32] `__imp_exportfn1`65CHECK-NEXT: 0 | S_PUB32 [size = 32] `__imp_exportfn1`
25CHECK-NEXT: flags = none, addr = 0002:012866CHECK-NEXT: flags = none, addr = 0002:0128
2667
68CHECK: Symbols
69CHECK-NEXT: ============================================================
70CHECK-NEXT: Mod 0000 | `{{.*}}pdb-publics-import.test.tmp2.obj`:
71CHECK-NEXT: Error loading module stream 0. The specified stream could not be loaded. Module stream not present
72CHECK-NEXT: Mod 0001 | `pdb-publics-import.test.tmp1.dll`:
73CHECK-NEXT: Error loading module stream 1. The specified stream could not be loaded. Module stream not present
74CHECK-NEXT: Mod 0002 | `Import:pdb-publics-import.test.tmp1.dll`:
75CHECK-NEXT: 4 | S_OBJNAME [size = 44] sig=0, `pdb-publics-import.test.tmp1.dll`
76CHECK-NEXT: 48 | S_COMPILE3 [size = 40]
77CHECK-NEXT: machine = intel x86-x64, Ver = LLVM Linker, language = link
78CHECK-NEXT: frontend = 0.0.0.0, backend = 14.10.25019.0
79CHECK-NEXT: flags = none
80CHECK-NEXT: 88 | S_THUNK32 [size = 36] `exportfn1`
81CHECK-NEXT: parent = 0, end = 124, next = 0
82CHECK-NEXT: kind = thunk, size = 6, addr = 0001:0016
83CHECK-NEXT: 124 | S_END [size = 4]
84CHECK-NEXT: 128 | S_OBJNAME [size = 44] sig=0, `pdb-publics-import.test.tmp1.dll`
85CHECK-NEXT: 172 | S_COMPILE3 [size = 40]
86CHECK-NEXT: machine = intel x86-x64, Ver = LLVM Linker, language = link
87CHECK-NEXT: frontend = 0.0.0.0, backend = 14.10.25019.0
88CHECK-NEXT: flags = none
89CHECK-NEXT: 212 | S_THUNK32 [size = 36] `exportfn2`
90CHECK-NEXT: parent = 0, end = 248, next = 0
91CHECK-NEXT: kind = thunk, size = 6, addr = 0001:0032
92CHECK-NEXT: 248 | S_END [size = 4]
93CHECK-NEXT: Mod 0003 | `* Linker *`:
94CHECK-NEXT: 4 | S_OBJNAME [size = 20] sig=0, `* Linker *`
95CHECK-NEXT: 24 | S_COMPILE3 [size = 40]
96CHECK-NEXT: machine = intel x86-x64, Ver = LLVM Linker, language = link
97CHECK-NEXT: frontend = 0.0.0.0, backend = 14.10.25019.0
98CHECK-NEXT: flags = none
99CHECK-NEXT: 64 | S_ENVBLOCK [size = {{[0-9]+}}]
100CHECK: {{[0-9]+}} | S_SECTION [size = 28] `.text`
101CHECK-NEXT: length = 38, alignment = 12, rva = 4096, section # = 1
102CHECK-NEXT: characteristics =
103CHECK-NEXT: code
104CHECK-NEXT: execute permissions
105CHECK-NEXT: read permissions
106CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 24] `.text`
107CHECK-NEXT: length = 8, addr = 0001:0000
108CHECK-NEXT: characteristics =
109CHECK-NEXT: code
110CHECK-NEXT: execute permissions
111CHECK-NEXT: read permissions
112CHECK-NEXT: {{[0-9]+}} | S_SECTION [size = 28] `.rdata`
113CHECK-NEXT: length = 209, alignment = 12, rva = 8192, section # = 2
114CHECK-NEXT: characteristics =
115CHECK-NEXT: initialized data
116CHECK-NEXT: read permissions
117CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$2`
118CHECK-NEXT: length = 40, addr = 0002:0061
119CHECK-NEXT: characteristics =
120CHECK-NEXT: initialized data
121CHECK-NEXT: read permissions
122CHECK-NEXT: write permissions
123CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$4`
124CHECK-NEXT: length = 24, addr = 0002:0104
125CHECK-NEXT: characteristics =
126CHECK-NEXT: initialized data
127CHECK-NEXT: read permissions
128CHECK-NEXT: write permissions
129CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$5`
130CHECK-NEXT: length = 24, addr = 0002:0128
131CHECK-NEXT: characteristics =
132CHECK-NEXT: initialized data
133CHECK-NEXT: read permissions
134CHECK-NEXT: write permissions
135CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$6`
136CHECK-NEXT: length = 24, addr = 0002:0152
137CHECK-NEXT: characteristics =
138CHECK-NEXT: initialized data
139CHECK-NEXT: read permissions
140CHECK-NEXT: write permissions
141CHECK-NEXT: {{[0-9]+}} | S_COFFGROUP [size = 28] `.idata$7`
142CHECK-NEXT: length = 33, addr = 0002:0176
143CHECK-NEXT: characteristics =
144CHECK-NEXT: initialized data
145CHECK-NEXT: read permissions
146CHECK-NEXT: write permissions
147
27CHECK: Section Contributions148CHECK: Section Contributions
28CHECK-NEXT: ============================================================149CHECK-NEXT: ============================================================
29 main150 main
...@@ -31,13 +152,35 @@ CHECK-NEXT: SC[.text] | mod = 0, 0001:0000, size = 8, data crc = 0, reloc cr...@@ -31,13 +152,35 @@ CHECK-NEXT: SC[.text] | mod = 0, 0001:0000, size = 8, data crc = 0, reloc cr
31CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_EXECUTE |152CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_ALIGN_4BYTES | IMAGE_SCN_MEM_EXECUTE |
32CHECK-NEXT: IMAGE_SCN_MEM_READ153CHECK-NEXT: IMAGE_SCN_MEM_READ
33 exportfn1 thunk154 exportfn1 thunk
34CHECK-NEXT: SC[.text] | mod = 1, 0001:0016, size = 6, data crc = 0, reloc crc = 0155CHECK-NEXT: SC[.text] | mod = 3, 0001:0016, size = 6, data crc = 0, reloc crc = 0
35CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ156CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
36 exportfn2 thunk157 exportfn2 thunk
37CHECK-NEXT: SC[.text] | mod = 1, 0001:0032, size = 6, data crc = 0, reloc crc = 0158CHECK-NEXT: SC[.text] | mod = 3, 0001:0032, size = 6, data crc = 0, reloc crc = 0
38CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ159CHECK-NEXT: IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ
39 .rdata debug directory data chunks160 .rdata debug directory data chunks
40CHECK-NEXT: SC[.rdata] | mod = 1, 0002:0000, size = 28, data crc = 0, reloc crc = 0161CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0000, size = 28, data crc = 0, reloc crc = 0
162CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
163CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0028, size = 33, data crc = 0, reloc crc = 0
164CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
165CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0061, size = 20, data crc = 0, reloc crc = 0
166CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
167CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0081, size = 20, data crc = 0, reloc crc = 0
168CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
169CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0104, size = 8, data crc = 0, reloc crc = 0
170CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
171CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0112, size = 8, data crc = 0, reloc crc = 0
172CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
173CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0120, size = 8, data crc = 0, reloc crc = 0
174CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
175CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0128, size = 8, data crc = 0, reloc crc = 0
176CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
177CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0136, size = 8, data crc = 0, reloc crc = 0
178CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
179CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0144, size = 8, data crc = 0, reloc crc = 0
180CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
181CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0152, size = 12, data crc = 0, reloc crc = 0
182CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
183CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0164, size = 12, data crc = 0, reloc crc = 0
41CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ184CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
42CHECK-NEXT: SC[.rdata] | mod = 1, 0002:0028, size = 33, data crc = 0, reloc crc = 0185CHECK-NEXT: SC[.rdata] | mod = 3, 0002:0176, size = 33, data crc = 0, reloc crc = 0
43CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ186CHECK-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ
deps/lld/test/COFF/pdb-safeseh.yaml+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# RUN: yaml2obj %s -o %t.obj1# RUN: yaml2obj %s -o %t.obj
2# RUN: lld-link -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj2# RUN: lld-link -safeseh:no -debug -entry:main -out:%t.exe -pdb:%t.pdb %t.obj
3# RUN: llvm-pdbutil dump -globals %t.pdb | FileCheck %s3# RUN: llvm-pdbutil dump -globals %t.pdb | FileCheck %s
44
5# There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in5# There is an S_GDATA32 symbol record with .secrel32 and .secidx relocations in
deps/lld/test/COFF/pdb-tpi-hash-size.test created+10
...@@ -0,0 +1,10 @@
1# RUN: yaml2obj < %p/Inputs/pdb1.yaml > %t1.obj
2# RUN: yaml2obj < %p/Inputs/pdb2.yaml > %t2.obj
3# RUN: rm -f %t.dll %t.pdb
4# RUN: lld-link /debug /pdb:%t.pdb /dll /out:%t.dll \
5# RUN: /entry:main /nodefaultlib %t1.obj %t2.obj
6
7# RUN: llvm-pdbutil dump -types -type-extras %t.pdb | FileCheck %s
8
9CHECK: Hash Key Size: 4
10CHECK-NEXT: Num Hash Buckets: 262143
deps/lld/test/COFF/pdb-type-server-invalid-signature.yaml+12-4
...@@ -1,22 +1,30 @@...@@ -1,22 +1,30 @@
11
2# Test linking an OBJ with a reference to an out-of-date PDB type server
2# RUN: cd %S/Inputs3# RUN: cd %S/Inputs
3# RUN: yaml2obj %s -o %t.obj4# 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 %s5# RUN: lld-link %t.obj -out:%t.exe -debug -pdb:%t.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s
5# RUN: cd %S6# RUN: cd %S
67
7# CHECK: warning: Cannot use debug info for {{.*}}.obj8# CHECK: warning: Cannot use debug info for '{{.*}}.obj'
8# CHECK-NEXT: The signature does not match; the file(s) might be out of date9# CHECK-NEXT: The signature does not match; the file(s) might be out of date
910
10# Also test a valid match11# Also test linking an OBJ with a reference to *valid* PDB type server
11
12# RUN: cd %S/Inputs12# RUN: cd %S/Inputs
13# RUN: yaml2obj %S/Inputs/pdb-type-server-valid-signature.yaml -o %t2.obj13# 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-empty14# 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 %S15# RUN: cd %S
1616
17# VALID-SIGNATURE-NOT: warning: Cannot use debug info for {{.*}}.obj17# 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 date18# VALID-SIGNATURE-NOT: The signature does not match; the file(s) might be out of date
1919
20# Test an invalid path reference to a PDB type server; as a fallback LLD should try to load the PDB in the same path as the OBJ
21# RUN: yaml2obj %S/Inputs/pdb-type-server-invalid-path.yaml -o %t3.obj
22# RUN: cp %S/Inputs/pdb-diff-cl.pdb %T
23# RUN: lld-link %t3.obj -out:%t3.exe -debug -pdb:%t3.pdb -nodefaultlib -entry:main 2>&1 | FileCheck %s -check-prefix=INVALID-PATH -allow-empty
24
25# INVALID-PATH-NOT: warning: Cannot use debug info for '{{.*}}3.obj' [LNK4099]
26# INVALID-PATH-NOT: failed to load reference 'c:\some_invalid_path_AABB98765\pdb-diff-cl.pdb': {{[Nn]}}o such file or directory
27
20--- !COFF28--- !COFF
21header:29header:
22 Machine: IMAGE_FILE_MACHINE_AMD6430 Machine: IMAGE_FILE_MACHINE_AMD64
deps/lld/test/COFF/pdb-type-server-simple.test+12-1
...@@ -20,7 +20,7 @@ RUN: rm -rf %t && mkdir -p %t && cd %t...@@ -20,7 +20,7 @@ RUN: rm -rf %t && mkdir -p %t && cd %t
20RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj20RUN: yaml2obj %S/Inputs/pdb-type-server-simple-a.yaml -o a.obj
21RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj21RUN: yaml2obj %S/Inputs/pdb-type-server-simple-b.yaml -o b.obj
22RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb22RUN: llvm-pdbutil yaml2pdb %S/Inputs/pdb-type-server-simple-ts.yaml -pdb ts.pdb
23RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib23RUN: lld-link a.obj b.obj -entry:main -debug -out:t.exe -pdb:t.pdb -nodefaultlib /summary | FileCheck %s -check-prefix SUMMARY
24RUN: llvm-pdbutil dump -symbols -types -ids -globals %t/t.pdb | FileCheck %s24RUN: llvm-pdbutil dump -symbols -types -ids -globals %t/t.pdb | FileCheck %s
2525
2626
...@@ -95,3 +95,14 @@ CHECK: type = [[FOO_PTR]] (Foo*), register = RSP, offset = 8...@@ -95,3 +95,14 @@ CHECK: type = [[FOO_PTR]] (Foo*), register = RSP, offset = 8
95CHECK: 196 | S_END [size = 4]95CHECK: 196 | S_END [size = 4]
96CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]`96CHECK: 200 | S_BUILDINFO [size = 8] BuildId = `[[B_BUILD]]`
97CHECK-LABEL: Mod 0002 | `* Linker *`:97CHECK-LABEL: Mod 0002 | `* Linker *`:
98
99SUMMARY: Summary
100SUMMARY-NEXT: --------------------------------------------------------------------------------
101SUMMARY-NEXT: 2 Input OBJ files (expanded from all cmd-line inputs)
102SUMMARY-NEXT: 1 PDB type server dependencies
103SUMMARY-NEXT: 0 Precomp OBJ dependencies
104SUMMARY-NEXT: 25 Merged TPI records
105SUMMARY-NEXT: 3 Output PDB strings
106SUMMARY-NEXT: 4 Global symbol records
107SUMMARY-NEXT: 14 Module symbol records
108SUMMARY-NEXT: 2 Public symbol records
\ No newline at end of file
deps/lld/test/COFF/pdb-unknown-subsection.s created+60
...@@ -0,0 +1,60 @@
1# Check that unknown symbol subsections are ignored with a warning, and a PDB
2# is produced anyway.
3
4# REQUIRES: x86
5# RUN: llvm-mc -triple=i386-pc-win32 -filetype=obj -o %t.obj %s
6# RUN: lld-link -safeseh:no -subsystem:console -debug -nodefaultlib -entry:foo -out:%t.exe -pdb:%t.pdb %t.obj 2>&1 | FileCheck %s --check-prefix=WARNING
7# RUN: llvm-pdbutil dump -symbols %t.pdb | FileCheck %s
8
9# WARNING-NOT: ignoring unknown
10# WARNING: ignoring unknown debug$S subsection kind 0xFF
11# WARNING-NOT: ignoring unknown
12
13# CHECK: Symbols
14# CHECK: 4 | S_COMPILE3 [size = 52]
15# CHECK: machine = intel x86-x64, Ver = clang version SENTINEL, language = c
16
17.text
18_foo:
19ret
20
21.global _foo
22
23.section .debug$S,"dr"
24 .p2align 2
25 .long 4 # Debug section magic
26 .long 0xF1 # Symbol subsection
27 .long .Ltmp6-.Ltmp5 # Subsection size
28.Ltmp5:
29 .short .Ltmp8-.Ltmp7 # Record length
30.Ltmp7:
31 .short 4412 # Record kind: S_COMPILE3
32 .long 0 # Flags and language
33 .short 208 # CPUType
34 .short 9 # Frontend version
35 .short 0
36 .short 0
37 .short 0
38 .short 9000 # Backend version
39 .short 0
40 .short 0
41 .short 0
42 .asciz "clang version SENTINEL" # Null-terminated compiler version string
43 .p2align 2
44.Ltmp8:
45.Ltmp6:
46 .long 0xFF # Unknown subsection kind
47 .long 4 # Subsection size
48 .long 0
49 .long 0x800000F1 # Unknown subsection kind
50 .long 4 # Subsection size
51 .long 0
52 .long 0x800000F2 # Unknown subsection kind
53 .long 4 # Subsection size
54 .long 0
55 .long 0x800000F3 # Unknown subsection kind
56 .long 4 # Subsection size
57 .long 0
58 .long 0x800000F4 # Unknown subsection kind
59 .long 4 # Subsection size
60 .long 0
deps/lld/test/COFF/pdb.test+18-18
...@@ -134,7 +134,7 @@ RAW-NEXT: Obj: `{{.*}}pdb.test.tmp2.obj`:...@@ -134,7 +134,7 @@ RAW-NEXT: Obj: `{{.*}}pdb.test.tmp2.obj`:
134RAW-NEXT: debug stream: 12, # files: 1, has ec info: false134RAW-NEXT: debug stream: 12, # files: 1, has ec info: false
135RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 ``135RAW-NEXT: pdb file ni: 0 ``, src file ni: 0 ``
136RAW-NEXT: Mod 0002 | `* Linker *`:136RAW-NEXT: Mod 0002 | `* Linker *`:
137RAW-NEXT: SC[???] | mod = 2, 0000:0000, size = 0, data crc = 0, reloc crc = 0137RAW-NEXT: SC[???] | mod = 65535, 65535:0000, size = -1, data crc = 0, reloc crc = 0
138RAW-NEXT: none138RAW-NEXT: none
139RAW-NEXT: Obj: ``:139RAW-NEXT: Obj: ``:
140RAW-NEXT: debug stream: 13, # files: 0, has ec info: false140RAW-NEXT: debug stream: 13, # files: 0, has ec info: false
...@@ -142,40 +142,40 @@ RAW-NEXT: pdb file ni: 1 `{{.*pdb.test.tmp.pdb}}`, src file ni: 0 `...@@ -142,40 +142,40 @@ RAW-NEXT: pdb file ni: 1 `{{.*pdb.test.tmp.pdb}}`, src file ni: 0 `
142RAW: Types (TPI Stream)142RAW: Types (TPI Stream)
143RAW-NEXT: ============================================================143RAW-NEXT: ============================================================
144RAW-NEXT: Showing 5 records144RAW-NEXT: Showing 5 records
145RAW-NEXT: 0x1000 | LF_ARGLIST [size = 8, hash = 0xEC0]145RAW-NEXT: 0x1000 | LF_ARGLIST [size = 8, hash = 0x32484]
146RAW-NEXT: 0x1001 | LF_PROCEDURE [size = 16, hash = 0x7BC]146RAW-NEXT: 0x1001 | LF_PROCEDURE [size = 16, hash = 0x27EE9]
147RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1000147RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1000
148RAW-NEXT: calling conv = cdecl, options = None148RAW-NEXT: calling conv = cdecl, options = None
149RAW-NEXT: 0x1002 | LF_POINTER [size = 12, hash = 0x884]149RAW-NEXT: 0x1002 | LF_POINTER [size = 12, hash = 0x39732]
150RAW-NEXT: referent = 0x1001, mode = pointer, opts = None, kind = ptr64150RAW-NEXT: referent = 0x1001, mode = pointer, opts = None, kind = ptr64
151RAW-NEXT: 0x1003 | LF_ARGLIST [size = 12, hash = 0x936]151RAW-NEXT: 0x1003 | LF_ARGLIST [size = 12, hash = 0x1FC10]
152RAW-NEXT: <no type>: ``152RAW-NEXT: <no type>: ``
153RAW-NEXT: 0x1004 | LF_PROCEDURE [size = 16, hash = 0x852]153RAW-NEXT: 0x1004 | LF_PROCEDURE [size = 16, hash = 0x1BD3]
154RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1003154RAW-NEXT: return type = 0x0074 (int), # args = 0, param list = 0x1003
155RAW-NEXT: calling conv = cdecl, options = None155RAW-NEXT: calling conv = cdecl, options = None
156RAW: Types (IPI Stream)156RAW: Types (IPI Stream)
157RAW-NEXT: ============================================================157RAW-NEXT: ============================================================
158RAW-NEXT: Showing 12 records158RAW-NEXT: Showing 12 records
159RAW-NEXT: 0x1000 | LF_FUNC_ID [size = 20, hash = 0x330]159RAW-NEXT: 0x1000 | LF_FUNC_ID [size = 20, hash = 0x38E5A]
160RAW-NEXT: name = main, type = 0x1004, parent scope = <no type>160RAW-NEXT: name = main, type = 0x1004, parent scope = <no type>
161RAW-NEXT: 0x1001 | LF_FUNC_ID [size = 16, hash = 0x120]161RAW-NEXT: 0x1001 | LF_FUNC_ID [size = 16, hash = 0xD08E]
162RAW-NEXT: name = foo, type = 0x1001, parent scope = <no type>162RAW-NEXT: name = foo, type = 0x1001, parent scope = <no type>
163RAW-NEXT: 0x1002 | LF_STRING_ID [size = 16, hash = 0x757] ID: <no type>, String: D:\b163RAW-NEXT: 0x1002 | LF_STRING_ID [size = 16, hash = 0x3EBD9] ID: <no type>, String: D:\b
164RAW-NEXT: 0x1003 | LF_STRING_ID [size = 36, hash = 0xC3A] ID: <no type>, String: C:\vs14\VC\BIN\amd64\cl.exe164RAW-NEXT: 0x1003 | LF_STRING_ID [size = 36, hash = 0xD327] ID: <no type>, String: C:\vs14\VC\BIN\amd64\cl.exe
165RAW-NEXT: 0x1004 | LF_STRING_ID [size = 260, hash = 0x433] ID: <no type>, String: -Z7 -c -MT -IC:\vs14\VC\INCLUDE -IC:\vs14\VC\ATLMFC\INCLUDE -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared"165RAW-NEXT: 0x1004 | LF_STRING_ID [size = 260, hash = 0x2FA6A] ID: <no type>, String: -Z7 -c -MT -IC:\vs14\VC\INCLUDE -IC:\vs14\VC\ATLMFC\INCLUDE -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared"
166RAW-NEXT: 0x1005 | LF_SUBSTR_LIST [size = 12, hash = 0x759]166RAW-NEXT: 0x1005 | LF_SUBSTR_LIST [size = 12, hash = 0x6053]
167RAW-NEXT: 0x1004: `-Z7 -c -MT -IC:\vs14\VC\INCLUDE -IC:\vs14\VC\ATLMFC\INCLUDE -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared"`167RAW-NEXT: 0x1004: `-Z7 -c -MT -IC:\vs14\VC\INCLUDE -IC:\vs14\VC\ATLMFC\INCLUDE -I"C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt" -I"C:\Program Files (x86)\Windows Kits\NETFXSDK\4.6\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\shared"`
168RAW-NEXT: 0x1006 | LF_STRING_ID [size = 132, hash = 0xF57] ID: 0x1005, String: -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X168RAW-NEXT: 0x1006 | LF_STRING_ID [size = 132, hash = 0xCAC7] ID: 0x1005, String: -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X
169RAW-NEXT: 0x1007 | LF_STRING_ID [size = 24, hash = 0x2D1] ID: <no type>, String: ret42-main.c169RAW-NEXT: 0x1007 | LF_STRING_ID [size = 24, hash = 0x21783] ID: <no type>, String: ret42-main.c
170RAW-NEXT: 0x1008 | LF_STRING_ID [size = 24, hash = 0xB8B] ID: <no type>, String: D:\b\vc140.pdb170RAW-NEXT: 0x1008 | LF_STRING_ID [size = 24, hash = 0x1DB87] ID: <no type>, String: D:\b\vc140.pdb
171RAW-NEXT: 0x1009 | LF_BUILDINFO [size = 28, hash = 0xA8C]171RAW-NEXT: 0x1009 | LF_BUILDINFO [size = 28, hash = 0x5E91]
172RAW-NEXT: 0x1002: `D:\b`172RAW-NEXT: 0x1002: `D:\b`
173RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe`173RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe`
174RAW-NEXT: 0x1007: `ret42-main.c`174RAW-NEXT: 0x1007: `ret42-main.c`
175RAW-NEXT: 0x1008: `D:\b\vc140.pdb`175RAW-NEXT: 0x1008: `D:\b\vc140.pdb`
176RAW-NEXT: 0x1006: ` -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X`176RAW-NEXT: 0x1006: ` -I"C:\Program Files (x86)\Windows Kits\8.1\include\um" -I"C:\Program Files (x86)\Windows Kits\8.1\include\winrt" -TC -X`
177RAW-NEXT: 0x100A | LF_STRING_ID [size = 20, hash = 0x39C] ID: <no type>, String: ret42-sub.c177RAW-NEXT: 0x100A | LF_STRING_ID [size = 20, hash = 0x7C68] ID: <no type>, String: ret42-sub.c
178RAW-NEXT: 0x100B | LF_BUILDINFO [size = 28, hash = 0xAD7]178RAW-NEXT: 0x100B | LF_BUILDINFO [size = 28, hash = 0x254D2]
179RAW-NEXT: 0x1002: `D:\b`179RAW-NEXT: 0x1002: `D:\b`
180RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe`180RAW-NEXT: 0x1003: `C:\vs14\VC\BIN\amd64\cl.exe`
181RAW-NEXT: 0x100A: `ret42-sub.c`181RAW-NEXT: 0x100A: `ret42-sub.c`
deps/lld/test/COFF/pdbaltpath.test+9-9
...@@ -1,39 +1,39 @@...@@ -1,39 +1,39 @@
1# RUN: yaml2obj %p/Inputs/empty.yaml > %t.obj1# RUN: yaml2obj %p/Inputs/empty.yaml > %t.obj
22
3# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:hello.pdb3# 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 %s4# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck --check-prefix HELLO %s
5# HELLO: PDBFileName: hello.pdb5# HELLO: PDBFileName: hello.pdb
66
7# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:%_Pdb%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 %s8# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck --check-prefix PDBVAR %s
9# PDBVAR: PDBFileName: pdbaltpath.test.tmp.pdb9# PDBVAR: PDBFileName: pdbaltpath.test.tmp.pdb
1010
11# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_ExT%.pdb11# 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 %s12# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck --check-prefix EXTVAR %s
13# EXTVAR: PDBFileName: fooexe.pdb13# EXTVAR: PDBFileName: fooexe.pdb
1414
15# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:%_PDB15# 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 %s16# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck --check-prefix NOCLOSE %s
17# NOCLOSE: PDBFileName: %_PDB17# NOCLOSE: PDBFileName: %_PDB
1818
19# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB19# 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 %s20# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck --check-prefix NOCLOSE2 %s
21# NOCLOSE2: PDBFileName: foo%_PDB21# NOCLOSE2: PDBFileName: foo%_PDB
2222
23# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB%bar%_EXT23# 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 %s24# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck --check-prefix CLOSEONE %s
25# CLOSEONE: PDBFileName: foopdbaltpath.test.tmp.pdbbar%_EXT25# CLOSEONE: PDBFileName: foopdbaltpath.test.tmp.pdbbar%_EXT
2626
27# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB%bar%_EXT%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 %s28# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck --check-prefix CLOSETWO %s
29# CLOSETWO: PDBFileName: foopdbaltpath.test.tmp.pdbbarexe29# CLOSETWO: PDBFileName: foopdbaltpath.test.tmp.pdbbarexe
3030
31# RUN: lld-link /entry:main %t.obj /out:%t.exe /debug /pdbaltpath:foo%_PDB%bar%_EXT%a31# 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 %s32# RUN: llvm-readobj --coff-debug-directory %t.exe | FileCheck --check-prefix CLOSETWO2 %s
33# CLOSETWO2: PDBFileName: foopdbaltpath.test.tmp.pdbbarexea33# CLOSETWO2: PDBFileName: foopdbaltpath.test.tmp.pdbbarexea
3434
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 %s35# 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 %s36# 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 literal37# 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 literal38# UNKNOWN-WARN: only %_PDB% and %_EXT% supported in /pdbaltpath:, keeping %r% as literal
39# ENVVARS: PDBFileName: foo%FoO%bar%r%a39# ENVVARS: PDBFileName: foo%FoO%bar%r%a
deps/lld/test/COFF/precomp-link.test+54-42
...@@ -1,42 +1,54 @@...@@ -1,42 +1,54 @@
1RUN: 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 1RUN: 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 /summary | FileCheck %s -check-prefix SUMMARY
2RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s 2RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
3 3
4RUN: 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 4RUN: 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
5RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s 5RUN: llvm-pdbutil dump -types %t.pdb | FileCheck %s
6 6
7RUN: 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 7RUN: 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 8
9RUN: 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 9RUN: 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 10
11FAILURE: warning: Cannot use debug info for 'precomp-invalid.obj' [LNK4099] 11FAILURE: warning: Cannot use debug info for '{{.*}}precomp-invalid.obj' [LNK4099]
12FAILURE-NEXT: failed to load reference '{{.*}}precomp.obj': The signature does not match; the file(s) might be out of date. 12FAILURE-NEXT: failed to load reference '{{.*}}precomp.obj': The signature does not match; the file(s) might be out of date.
13 13
14FAILURE-MISSING-PRECOMPOBJ: warning: Cannot use debug info for 'precomp-a.obj' [LNK4099] 14FAILURE-MISSING-PRECOMPOBJ: warning: Cannot use debug info for '{{.*}}precomp-a.obj' [LNK4099]
15FAILURE-MISSING-PRECOMPOBJ-NEXT: failed to load reference '{{.*}}precomp.obj': The path to this file must be provided on the command-line 15FAILURE-MISSING-PRECOMPOBJ-NEXT: failed to load reference '{{.*}}precomp.obj': The path to this file must be provided on the command-line
16 16
17CHECK: Types (TPI Stream) 17CHECK: Types (TPI Stream)
18CHECK-NOT: LF_PRECOMP 18CHECK-NOT: LF_PRECOMP
19CHECK-NOT: LF_ENDPRECOMP 19CHECK-NOT: LF_ENDPRECOMP
20 20
21// precomp.h 21
22#pragma once 22SUMMARY: Summary
23int Function(char A); 23SUMMARY-NEXT: --------------------------------------------------------------------------------
24 24SUMMARY-NEXT: 3 Input OBJ files (expanded from all cmd-line inputs)
25// precomp.cpp 25SUMMARY-NEXT: 0 PDB type server dependencies
26#include "precomp.h" 26SUMMARY-NEXT: 1 Precomp OBJ dependencies
27 27SUMMARY-NEXT: 1044 Merged TPI records
28// a.cpp 28SUMMARY-NEXT: 5 Output PDB strings
29#include "precomp.h" 29SUMMARY-NEXT: 167 Global symbol records
30int main(void) { 30SUMMARY-NEXT: 20 Module symbol records
31 Function('a'); 31SUMMARY-NEXT: 3 Public symbol records
32 return 0; 32
33} 33// precomp.h
34 34#pragma once
35// b.cpp 35int Function(char A);
36#include "precomp.h" 36
37int Function(char a) { 37// precomp.cpp
38 return (int)a; 38#include "precomp.h"
39} 39
40 40// a.cpp
41// cl.exe precomp.cpp /Z7 /Ycprecomp.h /c 41#include "precomp.h"
42// cl.exe a.cpp b.cpp /Z7 /Yuprecomp.h /c 42int main(void) {
43 Function('a');
44 return 0;
45}
46
47// b.cpp
48#include "precomp.h"
49int Function(char a) {
50 return (int)a;
51}
52
53// cl.exe precomp.cpp /Z7 /Ycprecomp.h /c
54// cl.exe a.cpp b.cpp /Z7 /Yuprecomp.h /c
deps/lld/test/COFF/reloc-x86.test+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: yaml2obj < %s > %t.obj2# RUN: yaml2obj < %s > %t.obj
3# RUN: lld-link /out:%t.exe /entry:main /base:0x400000 %t.obj3# RUN: lld-link -safeseh:no /out:%t.exe /entry:main /base:0x400000 %t.obj
4# RUN: llvm-objdump -d %t.exe | FileCheck %s4# RUN: llvm-objdump -d %t.exe | FileCheck %s
55
6# CHECK: .text:6# CHECK: .text:
deps/lld/test/COFF/resource-objs.test created+5
...@@ -0,0 +1,5 @@
1# RUN: lld-link /out:%t.exe /dll /noentry %S/Inputs/id.res.o
2# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s
3
4CHECK: ResourceTableRVA: 0x1000
5CHECK: ResourceTableSize: 0x80
deps/lld/test/COFF/resource.test+2-2
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7EXE: {{H.e.l.l.o}}7EXE: {{H.e.l.l.o}}
88
9# Verify the resource tree layout in the final executable.9# Verify the resource tree layout in the final executable.
10# RUN: llvm-readobj -file-headers -coff-resources -section-data %t.exe | \10# RUN: llvm-readobj --file-headers --coff-resources --section-data %t.exe | \
11# RUN: FileCheck --check-prefix=RESOURCE_INFO %s11# RUN: FileCheck --check-prefix=RESOURCE_INFO %s
1212
13RESOURCE_INFO: ResourceTableRVA: 0x200013RESOURCE_INFO: ResourceTableRVA: 0x2000
...@@ -17,7 +17,7 @@ RESOURCE_INFO-NEXT: Total Number of Resources: 1...@@ -17,7 +17,7 @@ RESOURCE_INFO-NEXT: Total Number of Resources: 1
17RESOURCE_INFO-NEXT: Base Table Address: 0x60017RESOURCE_INFO-NEXT: Base Table Address: 0x600
18RESOURCE_INFO-DAG: Number of String Entries: 018RESOURCE_INFO-DAG: Number of String Entries: 0
19RESOURCE_INFO-NEXT: Number of ID Entries: 119RESOURCE_INFO-NEXT: Number of ID Entries: 1
20RESOURCE_INFO-NEXT: Type: kRT_STRING (ID 6) [20RESOURCE_INFO-NEXT: Type: STRINGTABLE (ID 6) [
21RESOURCE_INFO-NEXT: Table Offset: 0x1821RESOURCE_INFO-NEXT: Table Offset: 0x18
22RESOURCE_INFO-NEXT: Number of String Entries: 022RESOURCE_INFO-NEXT: Number of String Entries: 0
23RESOURCE_INFO-NEXT: Number of ID Entries: 123RESOURCE_INFO-NEXT: Number of ID Entries: 1
deps/lld/test/COFF/responsefile.test+4-4
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: echo /out:%t.exe /entry:main %t.obj > %t.rsp3# RUN: echo /out:%t.exe /entry:main %t.obj > %t.rsp
4# RUN: lld-link @%t.rsp /heap:0x30004# RUN: lld-link @%t.rsp /heap:0x3000
5# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s5# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
6CHECK: SizeOfHeapReserve: 122886CHECK: SizeOfHeapReserve: 12288
77
8# RUN: not lld-link --rsp-quoting=foobar @%t.rsp 2>&1 | \8# RUN: not lld-link --rsp-quoting=foobar @%t.rsp 2>&1 | \
...@@ -12,14 +12,14 @@ INVRSP: invalid response file quoting: foobar...@@ -12,14 +12,14 @@ INVRSP: invalid response file quoting: foobar
12# RUN: echo "blah\foo" > %t.rsp12# RUN: echo "blah\foo" > %t.rsp
13# RUN: not lld-link @%t.rsp 2>&1 | \13# RUN: not lld-link @%t.rsp 2>&1 | \
14# RUN: FileCheck --check-prefix=DEFRSP %s14# RUN: FileCheck --check-prefix=DEFRSP %s
15DEFRSP: error: could not open blah\foo15DEFRSP: error: could not open 'blah\foo'
1616
17# RUN: echo "blah\foo" > %t.rsp17# RUN: echo "blah\foo" > %t.rsp
18# RUN: not lld-link --rsp-quoting=windows @%t.rsp 2>&1 | \18# RUN: not lld-link --rsp-quoting=windows @%t.rsp 2>&1 | \
19# RUN: FileCheck --check-prefix=WINRSP %s19# RUN: FileCheck --check-prefix=WINRSP %s
20WINRSP: error: could not open blah\foo20WINRSP: error: could not open 'blah\foo'
2121
22# RUN: echo "blah\foo" > %t.rsp22# RUN: echo "blah\foo" > %t.rsp
23# RUN: not lld-link --rsp-quoting=posix @%t.rsp 2>&1 | \23# RUN: not lld-link --rsp-quoting=posix @%t.rsp 2>&1 | \
24# RUN: FileCheck --check-prefix=POSRSP %s24# RUN: FileCheck --check-prefix=POSRSP %s
25POSRSP: error: could not open blahfoo25POSRSP: error: could not open 'blahfoo'
deps/lld/test/COFF/rsds.test+7-7
...@@ -2,29 +2,29 @@...@@ -2,29 +2,29 @@
22
3# RUN: rm -f %t.dll %t.pdb3# RUN: rm -f %t.dll %t.pdb
4# RUN: lld-link /debug /pdbaltpath:test.pdb /dll /out:%t.dll /entry:DllMain %t.obj4# RUN: lld-link /debug /pdbaltpath:test.pdb /dll /out:%t.dll /entry:DllMain %t.obj
5# RUN: llvm-readobj -coff-debug-directory %t.dll > %t.1.txt5# RUN: llvm-readobj --coff-debug-directory %t.dll > %t.1.txt
6# RUN: lld-link /debug /pdbaltpath:test.pdb /dll /out:%t.dll /entry:DllMain %t.obj6# RUN: lld-link /debug /pdbaltpath:test.pdb /dll /out:%t.dll /entry:DllMain %t.obj
7# RUN: llvm-readobj -coff-debug-directory %t.dll > %t.2.txt7# RUN: llvm-readobj --coff-debug-directory %t.dll > %t.2.txt
8# RUN: cat %t.1.txt %t.2.txt | FileCheck %s8# RUN: cat %t.1.txt %t.2.txt | FileCheck %s
99
10# RUN: rm -f %t.dll %t.pdb10# RUN: rm -f %t.dll %t.pdb
11# RUN: lld-link /debug /pdb:%t1.pdb /dll /out:%t.dll /entry:DllMain %t.obj11# RUN: lld-link /debug /pdb:%t1.pdb /dll /out:%t.dll /entry:DllMain %t.obj
12# RUN: llvm-readobj -coff-debug-directory %t.dll > %t.3.txt12# RUN: llvm-readobj --coff-debug-directory %t.dll > %t.3.txt
13# RUN: lld-link /debug /pdb:%t2.pdb /dll /out:%t.dll /entry:DllMain %t.obj13# RUN: lld-link /debug /pdb:%t2.pdb /dll /out:%t.dll /entry:DllMain %t.obj
14# RUN: llvm-readobj -coff-debug-directory %t.dll > %t.4.txt14# RUN: llvm-readobj --coff-debug-directory %t.dll > %t.4.txt
15# RUN: cat %t.3.txt %t.4.txt | FileCheck --check-prefix TWOPDBS %s15# RUN: cat %t.3.txt %t.4.txt | FileCheck --check-prefix TWOPDBS %s
1616
17# RUN: rm -f %t.dll %t.pdb17# RUN: rm -f %t.dll %t.pdb
18# RUN: lld-link /Brepro /dll /out:%t.dll /entry:DllMain %t.obj18# 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 %s19# RUN: llvm-readobj --coff-debug-directory %t.dll | FileCheck --check-prefix REPRO %s
2020
21# RUN: rm -f %t.dll %t.pdb21# RUN: rm -f %t.dll %t.pdb
22# RUN: lld-link /Brepro /debug /dll /out:%t.dll /entry:DllMain %t.obj22# 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 %s23# RUN: llvm-readobj --coff-debug-directory %t.dll | FileCheck --check-prefix REPRODEBUG %s
2424
25# RUN: rm -f %t.dll %t.pdb25# RUN: rm -f %t.dll %t.pdb
26# RUN: lld-link /lldmingw /debug:dwarf /dll /out:%t.dll /entry:DllMain %t.obj26# 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 %s27# RUN: llvm-readobj --coff-debug-directory %t.dll | FileCheck --check-prefix MINGW %s
2828
29# CHECK: File: [[FILE:.*]].dll29# CHECK: File: [[FILE:.*]].dll
30# CHECK: DebugDirectory [30# CHECK: DebugDirectory [
deps/lld/test/COFF/s_udt.s+442-442
...@@ -27,450 +27,450 @@...@@ -27,450 +27,450 @@
27# CHECK-NEXT: ============================================================27# CHECK-NEXT: ============================================================
28# CHECK: {{.*}} | S_GPROC32 [size = 44] `main`28# CHECK: {{.*}} | S_GPROC32 [size = 44] `main`
29# CHECK-NEXT: parent = 0, end = 252, addr = 0001:0000, code size = 5229# 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 30# CHECK-NEXT: type = `0x1002 (int (int, char**))`, debug start = 0, debug end = 0, flags = none
31# CHECK-NOT: {{.*}} | S_END31# CHECK-NOT: {{.*}} | S_END
32# CHECK: {{.*}} | S_UDT [size = 28] `main::LocalTypedef`32# CHECK: {{.*}} | S_UDT [size = 28] `main::LocalTypedef`
33# CHECK-NEXT: original type = 0x100433# CHECK-NEXT: original type = 0x1004
34# CHECK: {{.*}} | S_END [size = 4] 34# CHECK: {{.*}} | S_END [size = 4]
35 35
36# source code to re-generate: 36# source code to re-generate:
37# clang-cl /Z7 /GS- /GR- /c foo.cpp 37# clang-cl /Z7 /GS- /GR- /c foo.cpp
38# 38#
39# struct Struct { 39# struct Struct {
40# int x; 40# int x;
41# }; 41# };
42# 42#
43# using IntTypedef = int; 43# using IntTypedef = int;
44# using StructTypedef = Struct; 44# using StructTypedef = Struct;
45# Struct S; 45# Struct S;
46# StructTypedef SS; 46# StructTypedef SS;
47# IntTypedef I; 47# IntTypedef I;
48# 48#
49# int main(int argc, char **argv) { 49# int main(int argc, char **argv) {
50# using LocalTypedef = Struct*; 50# using LocalTypedef = Struct*;
51# LocalTypedef SPtr; 51# LocalTypedef SPtr;
52# return I + S.x + SS.x + SPtr->x; 52# return I + S.x + SS.x + SPtr->x;
53# }53# }
5454
55 .text 55 .text
56 .def @feat.00; 56 .def @feat.00;
57 .scl 3; 57 .scl 3;
58 .type 0; 58 .type 0;
59 .endef 59 .endef
60 .globl @feat.00 60 .globl @feat.00
61.set @feat.00, 0 61.set @feat.00, 0
62 .intel_syntax noprefix 62 .intel_syntax noprefix
63 .def main; 63 .def main;
64 .scl 2; 64 .scl 2;
65 .type 32; 65 .type 32;
66 .endef 66 .endef
67 .globl main # -- Begin function main 67 .globl main # -- Begin function main
68 .p2align 4, 0x90 68 .p2align 4, 0x90
69main: # @main 69main: # @main
70.Lfunc_begin0: 70.Lfunc_begin0:
71 .cv_func_id 0 71 .cv_func_id 0
72 .cv_file 1 "D:\\src\\llvmbuild\\cl\\Debug\\x64\\foo.cpp" "2B62298EE3EEF94E1D81FDFE18BD46A6" 1 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 73 .cv_loc 0 1 12 0 # foo.cpp:12:0
74.seh_proc main 74.seh_proc main
75# %bb.0: # %entry 75# %bb.0: # %entry
76 sub rsp, 32 76 sub rsp, 32
77 .seh_stackalloc 32 77 .seh_stackalloc 32
78 .seh_endprologue 78 .seh_endprologue
79 mov dword ptr [rsp + 28], 0 79 mov dword ptr [rsp + 28], 0
80 mov qword ptr [rsp + 16], rdx 80 mov qword ptr [rsp + 16], rdx
81 mov dword ptr [rsp + 12], ecx 81 mov dword ptr [rsp + 12], ecx
82.Ltmp0: 82.Ltmp0:
83 .cv_loc 0 1 15 0 # foo.cpp:15:0 83 .cv_loc 0 1 15 0 # foo.cpp:15:0
84 mov ecx, dword ptr [rip + "?I@@3HA"] 84 mov ecx, dword ptr [rip + "?I@@3HA"]
85 add ecx, dword ptr [rip + "?S@@3UStruct@@A"] 85 add ecx, dword ptr [rip + "?S@@3UStruct@@A"]
86 add ecx, dword ptr [rip + "?SS@@3UStruct@@A"] 86 add ecx, dword ptr [rip + "?SS@@3UStruct@@A"]
87 mov rdx, qword ptr [rsp] 87 mov rdx, qword ptr [rsp]
88 add ecx, dword ptr [rdx] 88 add ecx, dword ptr [rdx]
89 mov eax, ecx 89 mov eax, ecx
90 add rsp, 32 90 add rsp, 32
91 ret 91 ret
92.Ltmp1: 92.Ltmp1:
93.Lfunc_end0: 93.Lfunc_end0:
94 .seh_handlerdata 94 .seh_handlerdata
95 .text 95 .text
96 .seh_endproc 96 .seh_endproc
97 # -- End function 97 # -- End function
98 .bss 98 .bss
99 .globl "?S@@3UStruct@@A" # @"?S@@3UStruct@@A" 99 .globl "?S@@3UStruct@@A" # @"?S@@3UStruct@@A"
100 .p2align 2 100 .p2align 2
101"?S@@3UStruct@@A": 101"?S@@3UStruct@@A":
102 .zero 4 102 .zero 4
103 103
104 .globl "?SS@@3UStruct@@A" # @"?SS@@3UStruct@@A" 104 .globl "?SS@@3UStruct@@A" # @"?SS@@3UStruct@@A"
105 .p2align 2 105 .p2align 2
106"?SS@@3UStruct@@A": 106"?SS@@3UStruct@@A":
107 .zero 4 107 .zero 4
108 108
109 .globl "?I@@3HA" # @"?I@@3HA" 109 .globl "?I@@3HA" # @"?I@@3HA"
110 .p2align 2 110 .p2align 2
111"?I@@3HA": 111"?I@@3HA":
112 .long 0 # 0x0 112 .long 0 # 0x0
113 113
114 .section .drectve,"yn" 114 .section .drectve,"yn"
115 .ascii " /DEFAULTLIB:libcmt.lib" 115 .ascii " /DEFAULTLIB:libcmt.lib"
116 .ascii " /DEFAULTLIB:oldnames.lib" 116 .ascii " /DEFAULTLIB:oldnames.lib"
117 .section .debug$S,"dr" 117 .section .debug$S,"dr"
118 .p2align 2 118 .p2align 2
119 .long 4 # Debug section magic 119 .long 4 # Debug section magic
120 .long 241 120 .long 241
121 .long .Ltmp3-.Ltmp2 # Subsection size 121 .long .Ltmp3-.Ltmp2 # Subsection size
122.Ltmp2: 122.Ltmp2:
123 .short .Ltmp5-.Ltmp4 # Record length 123 .short .Ltmp5-.Ltmp4 # Record length
124.Ltmp4: 124.Ltmp4:
125 .short 4412 # Record kind: S_COMPILE3 125 .short 4412 # Record kind: S_COMPILE3
126 .long 1 # Flags and language 126 .long 1 # Flags and language
127 .short 208 # CPUType 127 .short 208 # CPUType
128 .short 8 # Frontend version 128 .short 8 # Frontend version
129 .short 0 129 .short 0
130 .short 0 130 .short 0
131 .short 0 131 .short 0
132 .short 8000 # Backend version 132 .short 8000 # Backend version
133 .short 0 133 .short 0
134 .short 0 134 .short 0
135 .short 0 135 .short 0
136 .asciz "clang version 8.0.0 " # Null-terminated compiler version string 136 .asciz "clang version 8.0.0 " # Null-terminated compiler version string
137.Ltmp5: 137.Ltmp5:
138.Ltmp3: 138.Ltmp3:
139 .p2align 2 139 .p2align 2
140 .long 241 # Symbol subsection for main 140 .long 241 # Symbol subsection for main
141 .long .Ltmp7-.Ltmp6 # Subsection size 141 .long .Ltmp7-.Ltmp6 # Subsection size
142.Ltmp6: 142.Ltmp6:
143 .short .Ltmp9-.Ltmp8 # Record length 143 .short .Ltmp9-.Ltmp8 # Record length
144.Ltmp8: 144.Ltmp8:
145 .short 4423 # Record kind: S_GPROC32_ID 145 .short 4423 # Record kind: S_GPROC32_ID
146 .long 0 # PtrParent 146 .long 0 # PtrParent
147 .long 0 # PtrEnd 147 .long 0 # PtrEnd
148 .long 0 # PtrNext 148 .long 0 # PtrNext
149 .long .Lfunc_end0-main # Code size 149 .long .Lfunc_end0-main # Code size
150 .long 0 # Offset after prologue 150 .long 0 # Offset after prologue
151 .long 0 # Offset before epilogue 151 .long 0 # Offset before epilogue
152 .long 4099 # Function type index 152 .long 4099 # Function type index
153 .secrel32 main # Function section relative address 153 .secrel32 main # Function section relative address
154 .secidx main # Function section index 154 .secidx main # Function section index
155 .byte 0 # Flags 155 .byte 0 # Flags
156 .asciz "main" # Function name 156 .asciz "main" # Function name
157.Ltmp9: 157.Ltmp9:
158 .short .Ltmp11-.Ltmp10 # Record length 158 .short .Ltmp11-.Ltmp10 # Record length
159.Ltmp10: 159.Ltmp10:
160 .short 4114 # Record kind: S_FRAMEPROC 160 .short 4114 # Record kind: S_FRAMEPROC
161 .long 32 # FrameSize 161 .long 32 # FrameSize
162 .long 0 # Padding 162 .long 0 # Padding
163 .long 0 # Offset of padding 163 .long 0 # Offset of padding
164 .long 0 # Bytes of callee saved registers 164 .long 0 # Bytes of callee saved registers
165 .long 0 # Exception handler offset 165 .long 0 # Exception handler offset
166 .short 0 # Exception handler section 166 .short 0 # Exception handler section
167 .long 81920 # Flags (defines frame register) 167 .long 81920 # Flags (defines frame register)
168.Ltmp11: 168.Ltmp11:
169 .short .Ltmp13-.Ltmp12 # Record length 169 .short .Ltmp13-.Ltmp12 # Record length
170.Ltmp12: 170.Ltmp12:
171 .short 4414 # Record kind: S_LOCAL 171 .short 4414 # Record kind: S_LOCAL
172 .long 116 # TypeIndex 172 .long 116 # TypeIndex
173 .short 1 # Flags 173 .short 1 # Flags
174 .asciz "argc" 174 .asciz "argc"
175.Ltmp13: 175.Ltmp13:
176 .cv_def_range .Ltmp0 .Ltmp1, "B\021\f\000\000\000" 176 .cv_def_range .Ltmp0 .Ltmp1, "B\021\f\000\000\000"
177 .short .Ltmp15-.Ltmp14 # Record length 177 .short .Ltmp15-.Ltmp14 # Record length
178.Ltmp14: 178.Ltmp14:
179 .short 4414 # Record kind: S_LOCAL 179 .short 4414 # Record kind: S_LOCAL
180 .long 4096 # TypeIndex 180 .long 4096 # TypeIndex
181 .short 1 # Flags 181 .short 1 # Flags
182 .asciz "argv" 182 .asciz "argv"
183.Ltmp15: 183.Ltmp15:
184 .cv_def_range .Ltmp0 .Ltmp1, "B\021\020\000\000\000" 184 .cv_def_range .Ltmp0 .Ltmp1, "B\021\020\000\000\000"
185 .short .Ltmp17-.Ltmp16 # Record length 185 .short .Ltmp17-.Ltmp16 # Record length
186.Ltmp16: 186.Ltmp16:
187 .short 4414 # Record kind: S_LOCAL 187 .short 4414 # Record kind: S_LOCAL
188 .long 4101 # TypeIndex 188 .long 4101 # TypeIndex
189 .short 0 # Flags 189 .short 0 # Flags
190 .asciz "SPtr" 190 .asciz "SPtr"
191.Ltmp17: 191.Ltmp17:
192 .cv_def_range .Ltmp0 .Ltmp1, "B\021\000\000\000\000" 192 .cv_def_range .Ltmp0 .Ltmp1, "B\021\000\000\000\000"
193 .short .Ltmp19-.Ltmp18 # Record length 193 .short .Ltmp19-.Ltmp18 # Record length
194.Ltmp18: 194.Ltmp18:
195 .short 4360 # Record kind: S_UDT 195 .short 4360 # Record kind: S_UDT
196 .long 4101 # Type 196 .long 4101 # Type
197 .asciz "main::LocalTypedef" 197 .asciz "main::LocalTypedef"
198.Ltmp19: 198.Ltmp19:
199 .short 2 # Record length 199 .short 2 # Record length
200 .short 4431 # Record kind: S_PROC_ID_END 200 .short 4431 # Record kind: S_PROC_ID_END
201.Ltmp7: 201.Ltmp7:
202 .p2align 2 202 .p2align 2
203 .cv_linetable 0, main, .Lfunc_end0 203 .cv_linetable 0, main, .Lfunc_end0
204 .long 241 # Symbol subsection for globals 204 .long 241 # Symbol subsection for globals
205 .long .Ltmp21-.Ltmp20 # Subsection size 205 .long .Ltmp21-.Ltmp20 # Subsection size
206.Ltmp20: 206.Ltmp20:
207 .short .Ltmp23-.Ltmp22 # Record length 207 .short .Ltmp23-.Ltmp22 # Record length
208.Ltmp22: 208.Ltmp22:
209 .short 4365 # Record kind: S_GDATA32 209 .short 4365 # Record kind: S_GDATA32
210 .long 4103 # Type 210 .long 4103 # Type
211 .secrel32 "?S@@3UStruct@@A" # DataOffset 211 .secrel32 "?S@@3UStruct@@A" # DataOffset
212 .secidx "?S@@3UStruct@@A" # Segment 212 .secidx "?S@@3UStruct@@A" # Segment
213 .asciz "S" # Name 213 .asciz "S" # Name
214.Ltmp23: 214.Ltmp23:
215 .short .Ltmp25-.Ltmp24 # Record length 215 .short .Ltmp25-.Ltmp24 # Record length
216.Ltmp24: 216.Ltmp24:
217 .short 4365 # Record kind: S_GDATA32 217 .short 4365 # Record kind: S_GDATA32
218 .long 4100 # Type 218 .long 4100 # Type
219 .secrel32 "?SS@@3UStruct@@A" # DataOffset 219 .secrel32 "?SS@@3UStruct@@A" # DataOffset
220 .secidx "?SS@@3UStruct@@A" # Segment 220 .secidx "?SS@@3UStruct@@A" # Segment
221 .asciz "SS" # Name 221 .asciz "SS" # Name
222.Ltmp25: 222.Ltmp25:
223 .short .Ltmp27-.Ltmp26 # Record length 223 .short .Ltmp27-.Ltmp26 # Record length
224.Ltmp26: 224.Ltmp26:
225 .short 4365 # Record kind: S_GDATA32 225 .short 4365 # Record kind: S_GDATA32
226 .long 116 # Type 226 .long 116 # Type
227 .secrel32 "?I@@3HA" # DataOffset 227 .secrel32 "?I@@3HA" # DataOffset
228 .secidx "?I@@3HA" # Segment 228 .secidx "?I@@3HA" # Segment
229 .asciz "I" # Name 229 .asciz "I" # Name
230.Ltmp27: 230.Ltmp27:
231.Ltmp21: 231.Ltmp21:
232 .p2align 2 232 .p2align 2
233 .long 241 233 .long 241
234 .long .Ltmp29-.Ltmp28 # Subsection size 234 .long .Ltmp29-.Ltmp28 # Subsection size
235.Ltmp28: 235.Ltmp28:
236 .short .Ltmp31-.Ltmp30 # Record length 236 .short .Ltmp31-.Ltmp30 # Record length
237.Ltmp30: 237.Ltmp30:
238 .short 4360 # Record kind: S_UDT 238 .short 4360 # Record kind: S_UDT
239 .long 4103 # Type 239 .long 4103 # Type
240 .asciz "Struct" 240 .asciz "Struct"
241.Ltmp31: 241.Ltmp31:
242 .short .Ltmp33-.Ltmp32 # Record length 242 .short .Ltmp33-.Ltmp32 # Record length
243.Ltmp32: 243.Ltmp32:
244 .short 4360 # Record kind: S_UDT 244 .short 4360 # Record kind: S_UDT
245 .long 4100 # Type 245 .long 4100 # Type
246 .asciz "StructTypedef" 246 .asciz "StructTypedef"
247.Ltmp33: 247.Ltmp33:
248 .short .Ltmp35-.Ltmp34 # Record length 248 .short .Ltmp35-.Ltmp34 # Record length
249.Ltmp34: 249.Ltmp34:
250 .short 4360 # Record kind: S_UDT 250 .short 4360 # Record kind: S_UDT
251 .long 116 # Type 251 .long 116 # Type
252 .asciz "IntTypedef" 252 .asciz "IntTypedef"
253.Ltmp35: 253.Ltmp35:
254.Ltmp29: 254.Ltmp29:
255 .p2align 2 255 .p2align 2
256 .cv_filechecksums # File index to string table offset subsection 256 .cv_filechecksums # File index to string table offset subsection
257 .cv_stringtable # String table 257 .cv_stringtable # String table
258 .long 241 258 .long 241
259 .long .Ltmp37-.Ltmp36 # Subsection size 259 .long .Ltmp37-.Ltmp36 # Subsection size
260.Ltmp36: 260.Ltmp36:
261 .short 6 # Record length 261 .short 6 # Record length
262 .short 4428 # Record kind: S_BUILDINFO 262 .short 4428 # Record kind: S_BUILDINFO
263 .long 4108 # LF_BUILDINFO index 263 .long 4108 # LF_BUILDINFO index
264.Ltmp37: 264.Ltmp37:
265 .p2align 2 265 .p2align 2
266 .section .debug$T,"dr" 266 .section .debug$T,"dr"
267 .p2align 2 267 .p2align 2
268 .long 4 # Debug section magic 268 .long 4 # Debug section magic
269 # Pointer (0x1000) { 269 # Pointer (0x1000) {
270 # TypeLeafKind: LF_POINTER (0x1002) 270 # TypeLeafKind: LF_POINTER (0x1002)
271 # PointeeType: char* (0x670) 271 # PointeeType: char* (0x670)
272 # PtrType: Near64 (0xC) 272 # PtrType: Near64 (0xC)
273 # PtrMode: Pointer (0x0) 273 # PtrMode: Pointer (0x0)
274 # IsFlat: 0 274 # IsFlat: 0
275 # IsConst: 0 275 # IsConst: 0
276 # IsVolatile: 0 276 # IsVolatile: 0
277 # IsUnaligned: 0 277 # IsUnaligned: 0
278 # IsRestrict: 0 278 # IsRestrict: 0
279 # IsThisPtr&: 0 279 # IsThisPtr&: 0
280 # IsThisPtr&&: 0 280 # IsThisPtr&&: 0
281 # SizeOf: 8 281 # SizeOf: 8
282 # } 282 # }
283 .byte 0x0a, 0x00, 0x02, 0x10 283 .byte 0x0a, 0x00, 0x02, 0x10
284 .byte 0x70, 0x06, 0x00, 0x00 284 .byte 0x70, 0x06, 0x00, 0x00
285 .byte 0x0c, 0x00, 0x01, 0x00 285 .byte 0x0c, 0x00, 0x01, 0x00
286 # ArgList (0x1001) { 286 # ArgList (0x1001) {
287 # TypeLeafKind: LF_ARGLIST (0x1201) 287 # TypeLeafKind: LF_ARGLIST (0x1201)
288 # NumArgs: 2 288 # NumArgs: 2
289 # Arguments [ 289 # Arguments [
290 # ArgType: int (0x74) 290 # ArgType: int (0x74)
291 # ArgType: char** (0x1000) 291 # ArgType: char** (0x1000)
292 # ] 292 # ]
293 # } 293 # }
294 .byte 0x0e, 0x00, 0x01, 0x12 294 .byte 0x0e, 0x00, 0x01, 0x12
295 .byte 0x02, 0x00, 0x00, 0x00 295 .byte 0x02, 0x00, 0x00, 0x00
296 .byte 0x74, 0x00, 0x00, 0x00 296 .byte 0x74, 0x00, 0x00, 0x00
297 .byte 0x00, 0x10, 0x00, 0x00 297 .byte 0x00, 0x10, 0x00, 0x00
298 # Procedure (0x1002) { 298 # Procedure (0x1002) {
299 # TypeLeafKind: LF_PROCEDURE (0x1008) 299 # TypeLeafKind: LF_PROCEDURE (0x1008)
300 # ReturnType: int (0x74) 300 # ReturnType: int (0x74)
301 # CallingConvention: NearC (0x0) 301 # CallingConvention: NearC (0x0)
302 # FunctionOptions [ (0x0) 302 # FunctionOptions [ (0x0)
303 # ] 303 # ]
304 # NumParameters: 2 304 # NumParameters: 2
305 # ArgListType: (int, char**) (0x1001) 305 # ArgListType: (int, char**) (0x1001)
306 # } 306 # }
307 .byte 0x0e, 0x00, 0x08, 0x10 307 .byte 0x0e, 0x00, 0x08, 0x10
308 .byte 0x74, 0x00, 0x00, 0x00 308 .byte 0x74, 0x00, 0x00, 0x00
309 .byte 0x00, 0x00, 0x02, 0x00 309 .byte 0x00, 0x00, 0x02, 0x00
310 .byte 0x01, 0x10, 0x00, 0x00 310 .byte 0x01, 0x10, 0x00, 0x00
311 # FuncId (0x1003) { 311 # FuncId (0x1003) {
312 # TypeLeafKind: LF_FUNC_ID (0x1601) 312 # TypeLeafKind: LF_FUNC_ID (0x1601)
313 # ParentScope: 0x0 313 # ParentScope: 0x0
314 # FunctionType: int (int, char**) (0x1002) 314 # FunctionType: int (int, char**) (0x1002)
315 # Name: main 315 # Name: main
316 # } 316 # }
317 .byte 0x12, 0x00, 0x01, 0x16 317 .byte 0x12, 0x00, 0x01, 0x16
318 .byte 0x00, 0x00, 0x00, 0x00 318 .byte 0x00, 0x00, 0x00, 0x00
319 .byte 0x02, 0x10, 0x00, 0x00 319 .byte 0x02, 0x10, 0x00, 0x00
320 .byte 0x6d, 0x61, 0x69, 0x6e 320 .byte 0x6d, 0x61, 0x69, 0x6e
321 .byte 0x00, 0xf3, 0xf2, 0xf1 321 .byte 0x00, 0xf3, 0xf2, 0xf1
322 # Struct (0x1004) { 322 # Struct (0x1004) {
323 # TypeLeafKind: LF_STRUCTURE (0x1505) 323 # TypeLeafKind: LF_STRUCTURE (0x1505)
324 # MemberCount: 0 324 # MemberCount: 0
325 # Properties [ (0x280) 325 # Properties [ (0x280)
326 # ForwardReference (0x80) 326 # ForwardReference (0x80)
327 # HasUniqueName (0x200) 327 # HasUniqueName (0x200)
328 # ] 328 # ]
329 # FieldList: 0x0 329 # FieldList: 0x0
330 # DerivedFrom: 0x0 330 # DerivedFrom: 0x0
331 # VShape: 0x0 331 # VShape: 0x0
332 # SizeOf: 0 332 # SizeOf: 0
333 # Name: Struct 333 # Name: Struct
334 # LinkageName: .?AUStruct@@ 334 # LinkageName: .?AUStruct@@
335 # } 335 # }
336 .byte 0x2a, 0x00, 0x05, 0x15 336 .byte 0x2a, 0x00, 0x05, 0x15
337 .byte 0x00, 0x00, 0x80, 0x02 337 .byte 0x00, 0x00, 0x80, 0x02
338 .byte 0x00, 0x00, 0x00, 0x00 338 .byte 0x00, 0x00, 0x00, 0x00
339 .byte 0x00, 0x00, 0x00, 0x00 339 .byte 0x00, 0x00, 0x00, 0x00
340 .byte 0x00, 0x00, 0x00, 0x00 340 .byte 0x00, 0x00, 0x00, 0x00
341 .byte 0x00, 0x00, 0x53, 0x74 341 .byte 0x00, 0x00, 0x53, 0x74
342 .byte 0x72, 0x75, 0x63, 0x74 342 .byte 0x72, 0x75, 0x63, 0x74
343 .byte 0x00, 0x2e, 0x3f, 0x41 343 .byte 0x00, 0x2e, 0x3f, 0x41
344 .byte 0x55, 0x53, 0x74, 0x72 344 .byte 0x55, 0x53, 0x74, 0x72
345 .byte 0x75, 0x63, 0x74, 0x40 345 .byte 0x75, 0x63, 0x74, 0x40
346 .byte 0x40, 0x00, 0xf2, 0xf1 346 .byte 0x40, 0x00, 0xf2, 0xf1
347 # Pointer (0x1005) { 347 # Pointer (0x1005) {
348 # TypeLeafKind: LF_POINTER (0x1002) 348 # TypeLeafKind: LF_POINTER (0x1002)
349 # PointeeType: Struct (0x1004) 349 # PointeeType: Struct (0x1004)
350 # PtrType: Near64 (0xC) 350 # PtrType: Near64 (0xC)
351 # PtrMode: Pointer (0x0) 351 # PtrMode: Pointer (0x0)
352 # IsFlat: 0 352 # IsFlat: 0
353 # IsConst: 0 353 # IsConst: 0
354 # IsVolatile: 0 354 # IsVolatile: 0
355 # IsUnaligned: 0 355 # IsUnaligned: 0
356 # IsRestrict: 0 356 # IsRestrict: 0
357 # IsThisPtr&: 0 357 # IsThisPtr&: 0
358 # IsThisPtr&&: 0 358 # IsThisPtr&&: 0
359 # SizeOf: 8 359 # SizeOf: 8
360 # } 360 # }
361 .byte 0x0a, 0x00, 0x02, 0x10 361 .byte 0x0a, 0x00, 0x02, 0x10
362 .byte 0x04, 0x10, 0x00, 0x00 362 .byte 0x04, 0x10, 0x00, 0x00
363 .byte 0x0c, 0x00, 0x01, 0x00 363 .byte 0x0c, 0x00, 0x01, 0x00
364 # FieldList (0x1006) { 364 # FieldList (0x1006) {
365 # TypeLeafKind: LF_FIELDLIST (0x1203) 365 # TypeLeafKind: LF_FIELDLIST (0x1203)
366 # DataMember { 366 # DataMember {
367 # TypeLeafKind: LF_MEMBER (0x150D) 367 # TypeLeafKind: LF_MEMBER (0x150D)
368 # AccessSpecifier: Public (0x3) 368 # AccessSpecifier: Public (0x3)
369 # Type: int (0x74) 369 # Type: int (0x74)
370 # FieldOffset: 0x0 370 # FieldOffset: 0x0
371 # Name: x 371 # Name: x
372 # } 372 # }
373 # } 373 # }
374 .byte 0x0e, 0x00, 0x03, 0x12 374 .byte 0x0e, 0x00, 0x03, 0x12
375 .byte 0x0d, 0x15, 0x03, 0x00 375 .byte 0x0d, 0x15, 0x03, 0x00
376 .byte 0x74, 0x00, 0x00, 0x00 376 .byte 0x74, 0x00, 0x00, 0x00
377 .byte 0x00, 0x00, 0x78, 0x00 377 .byte 0x00, 0x00, 0x78, 0x00
378 # Struct (0x1007) { 378 # Struct (0x1007) {
379 # TypeLeafKind: LF_STRUCTURE (0x1505) 379 # TypeLeafKind: LF_STRUCTURE (0x1505)
380 # MemberCount: 1 380 # MemberCount: 1
381 # Properties [ (0x200) 381 # Properties [ (0x200)
382 # HasUniqueName (0x200) 382 # HasUniqueName (0x200)
383 # ] 383 # ]
384 # FieldList: <field list> (0x1006) 384 # FieldList: <field list> (0x1006)
385 # DerivedFrom: 0x0 385 # DerivedFrom: 0x0
386 # VShape: 0x0 386 # VShape: 0x0
387 # SizeOf: 4 387 # SizeOf: 4
388 # Name: Struct 388 # Name: Struct
389 # LinkageName: .?AUStruct@@ 389 # LinkageName: .?AUStruct@@
390 # } 390 # }
391 .byte 0x2a, 0x00, 0x05, 0x15 391 .byte 0x2a, 0x00, 0x05, 0x15
392 .byte 0x01, 0x00, 0x00, 0x02 392 .byte 0x01, 0x00, 0x00, 0x02
393 .byte 0x06, 0x10, 0x00, 0x00 393 .byte 0x06, 0x10, 0x00, 0x00
394 .byte 0x00, 0x00, 0x00, 0x00 394 .byte 0x00, 0x00, 0x00, 0x00
395 .byte 0x00, 0x00, 0x00, 0x00 395 .byte 0x00, 0x00, 0x00, 0x00
396 .byte 0x04, 0x00, 0x53, 0x74 396 .byte 0x04, 0x00, 0x53, 0x74
397 .byte 0x72, 0x75, 0x63, 0x74 397 .byte 0x72, 0x75, 0x63, 0x74
398 .byte 0x00, 0x2e, 0x3f, 0x41 398 .byte 0x00, 0x2e, 0x3f, 0x41
399 .byte 0x55, 0x53, 0x74, 0x72 399 .byte 0x55, 0x53, 0x74, 0x72
400 .byte 0x75, 0x63, 0x74, 0x40 400 .byte 0x75, 0x63, 0x74, 0x40
401 .byte 0x40, 0x00, 0xf2, 0xf1 401 .byte 0x40, 0x00, 0xf2, 0xf1
402 # StringId (0x1008) { 402 # StringId (0x1008) {
403 # TypeLeafKind: LF_STRING_ID (0x1605) 403 # TypeLeafKind: LF_STRING_ID (0x1605)
404 # Id: 0x0 404 # Id: 0x0
405 # StringData: D:\src\llvmbuild\cl\Debug\x64\foo.cpp 405 # StringData: D:\src\llvmbuild\cl\Debug\x64\foo.cpp
406 # } 406 # }
407 .byte 0x2e, 0x00, 0x05, 0x16 407 .byte 0x2e, 0x00, 0x05, 0x16
408 .byte 0x00, 0x00, 0x00, 0x00 408 .byte 0x00, 0x00, 0x00, 0x00
409 .byte 0x44, 0x3a, 0x5c, 0x73 409 .byte 0x44, 0x3a, 0x5c, 0x73
410 .byte 0x72, 0x63, 0x5c, 0x6c 410 .byte 0x72, 0x63, 0x5c, 0x6c
411 .byte 0x6c, 0x76, 0x6d, 0x62 411 .byte 0x6c, 0x76, 0x6d, 0x62
412 .byte 0x75, 0x69, 0x6c, 0x64 412 .byte 0x75, 0x69, 0x6c, 0x64
413 .byte 0x5c, 0x63, 0x6c, 0x5c 413 .byte 0x5c, 0x63, 0x6c, 0x5c
414 .byte 0x44, 0x65, 0x62, 0x75 414 .byte 0x44, 0x65, 0x62, 0x75
415 .byte 0x67, 0x5c, 0x78, 0x36 415 .byte 0x67, 0x5c, 0x78, 0x36
416 .byte 0x34, 0x5c, 0x66, 0x6f 416 .byte 0x34, 0x5c, 0x66, 0x6f
417 .byte 0x6f, 0x2e, 0x63, 0x70 417 .byte 0x6f, 0x2e, 0x63, 0x70
418 .byte 0x70, 0x00, 0xf2, 0xf1 418 .byte 0x70, 0x00, 0xf2, 0xf1
419 # UdtSourceLine (0x1009) { 419 # UdtSourceLine (0x1009) {
420 # TypeLeafKind: LF_UDT_SRC_LINE (0x1606) 420 # TypeLeafKind: LF_UDT_SRC_LINE (0x1606)
421 # UDT: Struct (0x1007) 421 # UDT: Struct (0x1007)
422 # SourceFile: D:\src\llvmbuild\cl\Debug\x64\foo.cpp (0x1008) 422 # SourceFile: D:\src\llvmbuild\cl\Debug\x64\foo.cpp (0x1008)
423 # LineNumber: 1 423 # LineNumber: 1
424 # } 424 # }
425 .byte 0x0e, 0x00, 0x06, 0x16 425 .byte 0x0e, 0x00, 0x06, 0x16
426 .byte 0x07, 0x10, 0x00, 0x00 426 .byte 0x07, 0x10, 0x00, 0x00
427 .byte 0x08, 0x10, 0x00, 0x00 427 .byte 0x08, 0x10, 0x00, 0x00
428 .byte 0x01, 0x00, 0x00, 0x00 428 .byte 0x01, 0x00, 0x00, 0x00
429 # StringId (0x100A) { 429 # StringId (0x100A) {
430 # TypeLeafKind: LF_STRING_ID (0x1605) 430 # TypeLeafKind: LF_STRING_ID (0x1605)
431 # Id: 0x0 431 # Id: 0x0
432 # StringData: D:\\src\\llvmbuild\\cl\\Debug\\x64 432 # StringData: D:\\src\\llvmbuild\\cl\\Debug\\x64
433 # } 433 # }
434 .byte 0x2a, 0x00, 0x05, 0x16 434 .byte 0x2a, 0x00, 0x05, 0x16
435 .byte 0x00, 0x00, 0x00, 0x00 435 .byte 0x00, 0x00, 0x00, 0x00
436 .byte 0x44, 0x3a, 0x5c, 0x5c 436 .byte 0x44, 0x3a, 0x5c, 0x5c
437 .byte 0x73, 0x72, 0x63, 0x5c 437 .byte 0x73, 0x72, 0x63, 0x5c
438 .byte 0x5c, 0x6c, 0x6c, 0x76 438 .byte 0x5c, 0x6c, 0x6c, 0x76
439 .byte 0x6d, 0x62, 0x75, 0x69 439 .byte 0x6d, 0x62, 0x75, 0x69
440 .byte 0x6c, 0x64, 0x5c, 0x5c 440 .byte 0x6c, 0x64, 0x5c, 0x5c
441 .byte 0x63, 0x6c, 0x5c, 0x5c 441 .byte 0x63, 0x6c, 0x5c, 0x5c
442 .byte 0x44, 0x65, 0x62, 0x75 442 .byte 0x44, 0x65, 0x62, 0x75
443 .byte 0x67, 0x5c, 0x5c, 0x78 443 .byte 0x67, 0x5c, 0x5c, 0x78
444 .byte 0x36, 0x34, 0x00, 0xf1 444 .byte 0x36, 0x34, 0x00, 0xf1
445 # StringId (0x100B) { 445 # StringId (0x100B) {
446 # TypeLeafKind: LF_STRING_ID (0x1605) 446 # TypeLeafKind: LF_STRING_ID (0x1605)
447 # Id: 0x0 447 # Id: 0x0
448 # StringData: foo.cpp 448 # StringData: foo.cpp
449 # } 449 # }
450 .byte 0x0e, 0x00, 0x05, 0x16 450 .byte 0x0e, 0x00, 0x05, 0x16
451 .byte 0x00, 0x00, 0x00, 0x00 451 .byte 0x00, 0x00, 0x00, 0x00
452 .byte 0x66, 0x6f, 0x6f, 0x2e 452 .byte 0x66, 0x6f, 0x6f, 0x2e
453 .byte 0x63, 0x70, 0x70, 0x00 453 .byte 0x63, 0x70, 0x70, 0x00
454 # BuildInfo (0x100C) { 454 # BuildInfo (0x100C) {
455 # TypeLeafKind: LF_BUILDINFO (0x1603) 455 # TypeLeafKind: LF_BUILDINFO (0x1603)
456 # NumArgs: 5 456 # NumArgs: 5
457 # Arguments [ 457 # Arguments [
458 # ArgType: D:\\src\\llvmbuild\\cl\\Debug\\x64 (0x100A) 458 # ArgType: D:\\src\\llvmbuild\\cl\\Debug\\x64 (0x100A)
459 # ArgType: 0x0 459 # ArgType: 0x0
460 # ArgType: foo.cpp (0x100B) 460 # ArgType: foo.cpp (0x100B)
461 # ArgType: 0x0 461 # ArgType: 0x0
462 # ArgType: 0x0 462 # ArgType: 0x0
463 # ] 463 # ]
464 # } 464 # }
465 .byte 0x1a, 0x00, 0x03, 0x16 465 .byte 0x1a, 0x00, 0x03, 0x16
466 .byte 0x05, 0x00, 0x0a, 0x10 466 .byte 0x05, 0x00, 0x0a, 0x10
467 .byte 0x00, 0x00, 0x00, 0x00 467 .byte 0x00, 0x00, 0x00, 0x00
468 .byte 0x00, 0x00, 0x0b, 0x10 468 .byte 0x00, 0x00, 0x0b, 0x10
469 .byte 0x00, 0x00, 0x00, 0x00 469 .byte 0x00, 0x00, 0x00, 0x00
470 .byte 0x00, 0x00, 0x00, 0x00 470 .byte 0x00, 0x00, 0x00, 0x00
471 .byte 0x00, 0x00, 0xf2, 0xf1 471 .byte 0x00, 0x00, 0xf2, 0xf1
472 472
473 .addrsig 473 .addrsig
474 .addrsig_sym "?S@@3UStruct@@A" 474 .addrsig_sym "?S@@3UStruct@@A"
475 .addrsig_sym "?SS@@3UStruct@@A" 475 .addrsig_sym "?SS@@3UStruct@@A"
476 .addrsig_sym "?I@@3HA" 476 .addrsig_sym "?I@@3HA"
deps/lld/test/COFF/safeseh-md.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj2# RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj
3# RUN: lld-link %t.obj %S/Inputs/except_handler3.lib -safeseh -out:%t.exe -opt:noref -entry:main3# RUN: lld-link %t.obj %S/Inputs/except_handler3.lib -safeseh -out:%t.exe -opt:noref -entry:main
4# RUN: llvm-readobj -coff-load-config %t.exe | FileCheck %s4# RUN: llvm-readobj --coff-load-config %t.exe | FileCheck %s
55
6# CHECK: SEHTable [6# CHECK: SEHTable [
7# CHECK-NEXT: 0x7# CHECK-NEXT: 0x
deps/lld/test/COFF/safeseh-no.s created+57
...@@ -0,0 +1,57 @@
1# REQUIRES: x86
2# RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj
3# RUN: not lld-link %t.obj -safeseh -out:%t.exe -entry:main 2>&1 | FileCheck %s --check-prefix=ERROR
4# safe seh should be on by default.
5# RUN: not lld-link %t.obj -out:%t.exe -entry:main 2>&1 | FileCheck %s --check-prefix=ERROR
6# RUN: lld-link %t.obj -safeseh:no -out:%t.exe -entry:main
7# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s
8# -lldmingw should also turn off safeseh by default.
9# RUN: lld-link %t.obj -lldmingw -out:%t.exe -entry:main
10# RUN: llvm-readobj --file-headers --coff-load-config %t.exe | FileCheck %s
11
12# ERROR: /safeseh: {{.*}}safeseh-no.s.tmp.obj is not compatible with SEH
13
14# CHECK: Characteristics [
15# CHECK-NOT: IMAGE_DLL_CHARACTERISTICS_NO_SEH
16# CHECK: ]
17# CHECK: LoadConfig [
18# CHECK: Size: 0x48
19# CHECK: SEHandlerTable: 0x0
20# CHECK: SEHandlerCount: 0
21# CHECK: ]
22# CHECK-NOT: SEHTable
23
24
25# Explicitly mark the object as not having safeseh. LLD should error unless
26# -safeseh:no is passed.
27 .def @feat.00; .scl 3; .type 0; .endef
28 .globl @feat.00
29@feat.00 = 0
30
31 .def _main;
32 .scl 2;
33 .type 32;
34 .endef
35 .section .text,"xr",one_only,_main
36 .globl _main
37_main:
38 movl $42, %eax
39 ret
40
41# Add a handler to create an .sxdata section, which -safeseh:no should ignore.
42 .def _my_handler; .scl 3; .type 32;
43 .endef
44 .section .text,"xr",one_only,_my_handler
45_my_handler:
46 ret
47.safeseh _my_handler
48
49
50 .section .rdata,"dr"
51.globl __load_config_used
52__load_config_used:
53 .long 72
54 .fill 60, 1, 0
55 .long ___safe_se_handler_table
56 .long ___safe_se_handler_count
57
deps/lld/test/COFF/safeseh-notable.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj2# RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj
3# RUN: lld-link %t.obj -safeseh -out:%t.exe -entry:main3# RUN: lld-link %t.obj -safeseh -out:%t.exe -entry:main
4# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s4# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
55
6# This object lacks a _load_config_used global, so we set6# This object lacks a _load_config_used global, so we set
7# IMAGE_DLL_CHARACTERISTICS_NO_SEH even though there is an exception handler.7# IMAGE_DLL_CHARACTERISTICS_NO_SEH even though there is an exception handler.
deps/lld/test/COFF/safeseh.s+3-3
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj2# RUN: llvm-mc -triple i686-windows-msvc %s -filetype=obj -o %t.obj
3# RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:noref -entry:main3# RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:noref -entry:main
4# RUN: llvm-readobj -coff-basereloc -coff-load-config -file-headers %t.exe | FileCheck %s --check-prefix=CHECK-NOGC4# RUN: llvm-readobj --coff-basereloc --coff-load-config --file-headers %t.exe | FileCheck %s --check-prefix=CHECK-NOGC
5# RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:noref -entry:main -debug:dwarf5# RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:noref -entry:main -debug:dwarf
6# RUN: llvm-readobj -coff-basereloc -coff-load-config -file-headers %t.exe | FileCheck %s --check-prefix=CHECK-NOGC6# RUN: llvm-readobj --coff-basereloc --coff-load-config --file-headers %t.exe | FileCheck %s --check-prefix=CHECK-NOGC
7# RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:ref -entry:main7# RUN: lld-link %t.obj -safeseh -out:%t.exe -opt:ref -entry:main
8# RUN: llvm-readobj -coff-basereloc -coff-load-config -file-headers %t.exe | FileCheck %s --check-prefix=CHECK-GC8# RUN: llvm-readobj --coff-basereloc --coff-load-config --file-headers %t.exe | FileCheck %s --check-prefix=CHECK-GC
99
10# __safe_se_handler_table needs to be relocated against ImageBase.10# __safe_se_handler_table needs to be relocated against ImageBase.
11# check that the relocation is present.11# check that the relocation is present.
deps/lld/test/COFF/section.test+4-4
...@@ -1,19 +1,19 @@...@@ -1,19 +1,19 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \2# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
3# RUN: /section:.foo,r %t.obj3# RUN: /section:.foo,r %t.obj
4# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=R %s4# RUN: llvm-readobj --sections %t.exe | FileCheck -check-prefix=R %s
55
6# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \6# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
7# RUN: /section:.foo,w %t.obj7# RUN: /section:.foo,w %t.obj
8# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=W %s8# RUN: llvm-readobj --sections %t.exe | FileCheck -check-prefix=W %s
99
10# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \10# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
11# RUN: /section:.foo,e %t.obj11# RUN: /section:.foo,e %t.obj
12# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=E %s12# RUN: llvm-readobj --sections %t.exe | FileCheck -check-prefix=E %s
1313
14# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \14# RUN: lld-link /out:%t.exe /entry:main /subsystem:console /force \
15# RUN: /section:.foo,s %t.obj15# RUN: /section:.foo,s %t.obj
16# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=S %s16# RUN: llvm-readobj --sections %t.exe | FileCheck -check-prefix=S %s
1717
18# R: Characteristics [18# R: Characteristics [
19# R-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA19# R-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA
deps/lld/test/COFF/sort-debug.test+5-4
...@@ -1,12 +1,12 @@...@@ -1,12 +1,12 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /debug /out:%t.exe /entry:main %t.obj2# RUN: lld-link /debug /out:%t.exe /entry:main %t.obj
3# RUN: llvm-readobj -sections %t.exe | FileCheck %s3# RUN: llvm-readobj --sections %t.exe | FileCheck %s
4# RUN: lld-link /debug:dwarf /out:%t.exe /entry:main %t.obj4# RUN: lld-link /debug:dwarf /out:%t.exe /entry:main %t.obj
5# RUN: llvm-readobj -sections %t.exe | FileCheck %s5# RUN: llvm-readobj --sections %t.exe | FileCheck %s
6# RUN: lld-link /out:%t.exe /entry:main %t.obj6# RUN: lld-link /out:%t.exe /entry:main %t.obj
7# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=NODEBUG %s7# RUN: llvm-readobj --sections %t.exe | FileCheck -check-prefix=NODEBUG %s
8# RUN: lld-link /debug:symtab /out:%t.exe /entry:main %t.obj8# RUN: lld-link /debug:symtab /out:%t.exe /entry:main %t.obj
9# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=NODEBUG %s9# RUN: llvm-readobj --sections %t.exe | FileCheck -check-prefix=NODEBUG %s
1010
11# CHECK: Name: .text11# CHECK: Name: .text
12# CHECK: Name: .reloc12# CHECK: Name: .reloc
...@@ -45,6 +45,7 @@ sections:...@@ -45,6 +45,7 @@ sections:
45 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]45 Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA, IMAGE_SCN_MEM_READ, IMAGE_SCN_MEM_WRITE ]
46 Alignment: 446 Alignment: 4
47 SectionData: ''47 SectionData: ''
48 SizeOfRawData: 4
48 - Name: '.debug$S'49 - Name: '.debug$S'
49 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]50 Characteristics: [ IMAGE_SCN_CNT_INITIALIZED_DATA, IMAGE_SCN_MEM_DISCARDABLE, IMAGE_SCN_MEM_READ ]
50 Alignment: 151 Alignment: 1
deps/lld/test/COFF/stack.test+5-5
...@@ -1,25 +1,25 @@...@@ -1,25 +1,25 @@
1# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj1# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
22
3# RUN: lld-link /out:%t.exe /entry:main %t.obj3# RUN: lld-link /out:%t.exe /entry:main %t.obj
4# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s4# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s
55
6DEFAULT: SizeOfStackReserve: 10485766DEFAULT: SizeOfStackReserve: 1048576
7DEFAULT: SizeOfStackCommit: 40967DEFAULT: SizeOfStackCommit: 4096
88
9# RUN: lld-link /out:%t.exe /entry:main %t.obj /stack:0x30009# RUN: lld-link /out:%t.exe /entry:main %t.obj /stack:0x3000
10# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s10# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
11# RUN: echo "STACKSIZE 12288" > %t.def11# RUN: echo "STACKSIZE 12288" > %t.def
12# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj12# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
13# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s13# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
1414
15CHECK1: SizeOfStackReserve: 1228815CHECK1: SizeOfStackReserve: 12288
16CHECK1: SizeOfStackCommit: 409616CHECK1: SizeOfStackCommit: 4096
1717
18# RUN: lld-link /out:%t.exe /entry:main %t.obj /stack:0x5000,0x300018# RUN: lld-link /out:%t.exe /entry:main %t.obj /stack:0x5000,0x3000
19# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s19# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
20# RUN: echo "STACKSIZE 20480,12288" > %t.def20# RUN: echo "STACKSIZE 20480,12288" > %t.def
21# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj21# RUN: lld-link /out:%t.exe /entry:main /def:%t.def %t.obj
22# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s22# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
2323
24CHECK2: SizeOfStackReserve: 2048024CHECK2: SizeOfStackReserve: 20480
25CHECK2: SizeOfStackCommit: 1228825CHECK2: SizeOfStackCommit: 12288
deps/lld/test/COFF/strtab-size.s+2-2
...@@ -12,8 +12,8 @@...@@ -12,8 +12,8 @@
12# output SymbolCount: 0 (and dumpbin.exe would error out with "invalid file12# output SymbolCount: 0 (and dumpbin.exe would error out with "invalid file
13# or disk full, cannot seek to 0x1602").13# or disk full, cannot seek to 0x1602").
1414
15# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s15# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
16# CHECK: SymbolCount: 19916# CHECK: SymbolCount: 197
1717
18.global main18.global main
19.text19.text
deps/lld/test/COFF/subsystem-drectve.test+2-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /dll /noentry /out:%t.dll %t.obj2# RUN: lld-link -safeseh:no /dll /noentry /out:%t.dll %t.obj
3# RUN: llvm-readobj -file-headers %t.dll | FileCheck %s3# RUN: llvm-readobj --file-headers %t.dll | FileCheck %s
44
5# CHECK: MajorOperatingSystemVersion: 425# CHECK: MajorOperatingSystemVersion: 42
6# CHECK: MinorOperatingSystemVersion: 436# CHECK: MinorOperatingSystemVersion: 43
deps/lld/test/COFF/subsystem-inference-mingw.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.o2# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.o
33
4# RUN: lld-link -lldmingw %t.o -out:%t.exe4# RUN: lld-link -lldmingw %t.o -out:%t.exe
5# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s5# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
66
7# CHECK: AddressOfEntryPoint: 0x10017# CHECK: AddressOfEntryPoint: 0x1001
8# CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)8# CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI (0x3)
deps/lld/test/COFF/subsystem-inference.test+8-4
...@@ -1,18 +1,22 @@...@@ -1,18 +1,22 @@
1# RUN: sed -e s/ENTRYNAME/main/ %s | yaml2obj > %t.obj1# RUN: sed -e s/ENTRYNAME/main/ %s | yaml2obj > %t.obj
2# RUN: lld-link /out:%t.exe %t.obj2# RUN: lld-link /out:%t.exe %t.obj
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MAIN %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=MAIN %s
4# RUN: lld-link /out:%t.exe %t.obj /subsystem:default,6.0
5# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=MAIN %s
46
5# RUN: sed s/ENTRYNAME/wmain/ %s | yaml2obj > %t.obj7# RUN: sed s/ENTRYNAME/wmain/ %s | yaml2obj > %t.obj
6# RUN: lld-link /out:%t.exe %t.obj8# RUN: lld-link /out:%t.exe %t.obj
7# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=WMAIN %s9# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=WMAIN %s
810
9# RUN: sed s/ENTRYNAME/WinMain/ %s | yaml2obj > %t.obj11# RUN: sed s/ENTRYNAME/WinMain/ %s | yaml2obj > %t.obj
10# RUN: lld-link /out:%t.exe %t.obj12# RUN: lld-link /out:%t.exe %t.obj
11# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=WINMAIN %s13# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=WINMAIN %s
14# RUN: lld-link /out:%t.exe %t.obj /subsystem:default,6.0
15# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=WINMAIN %s
1216
13# RUN: sed s/ENTRYNAME/wWinMain/ %s | yaml2obj > %t.obj17# RUN: sed s/ENTRYNAME/wWinMain/ %s | yaml2obj > %t.obj
14# RUN: lld-link /out:%t.exe %t.obj18# RUN: lld-link /out:%t.exe %t.obj
15# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=WWINMAIN %s19# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=WWINMAIN %s
1620
17# MAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI21# MAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
18# WMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI22# WMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
deps/lld/test/COFF/subsystem-inference2.test+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj %s > %t.obj1# RUN: yaml2obj %s > %t.obj
2# RUN: lld-link /out:%t.exe %t.obj 2>&1 | FileCheck -check-prefix=WARN %s2# RUN: lld-link /out:%t.exe %t.obj 2>&1 | FileCheck -check-prefix=WARN %s
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
44
5# WARN: warning: found main and WinMain; defaulting to /subsystem:console5# WARN: warning: found main and WinMain; defaulting to /subsystem:console
6# CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI6# CHECK: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
deps/lld/test/COFF/subsystem-inference32.test+8-8
...@@ -1,18 +1,18 @@...@@ -1,18 +1,18 @@
1# RUN: sed -e s/ENTRYNAME/_main/ %s | yaml2obj > %t.obj1# RUN: sed -e s/ENTRYNAME/_main/ %s | yaml2obj > %t.obj
2# RUN: lld-link /out:%t.exe %t.obj2# RUN: lld-link -safeseh:no /out:%t.exe %t.obj
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=MAIN %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=MAIN %s
44
5# RUN: sed s/ENTRYNAME/_wmain/ %s | yaml2obj > %t.obj5# RUN: sed s/ENTRYNAME/_wmain/ %s | yaml2obj > %t.obj
6# RUN: lld-link /out:%t.exe %t.obj6# RUN: lld-link -safeseh:no /out:%t.exe %t.obj
7# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=WMAIN %s7# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=WMAIN %s
88
9# RUN: sed s/ENTRYNAME/_WinMain@16/ %s | yaml2obj > %t.obj9# RUN: sed s/ENTRYNAME/_WinMain@16/ %s | yaml2obj > %t.obj
10# RUN: lld-link /out:%t.exe %t.obj10# RUN: lld-link -safeseh:no /out:%t.exe %t.obj
11# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=WINMAIN %s11# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=WINMAIN %s
1212
13# RUN: sed s/ENTRYNAME/_wWinMain@16/ %s | yaml2obj > %t.obj13# RUN: sed s/ENTRYNAME/_wWinMain@16/ %s | yaml2obj > %t.obj
14# RUN: lld-link /out:%t.exe %t.obj14# RUN: lld-link -safeseh:no /out:%t.exe %t.obj
15# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=WWINMAIN %s15# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=WWINMAIN %s
1616
17# MAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI17# MAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
18# WMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI18# WMAIN: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_CUI
deps/lld/test/COFF/subsystem.test+11-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: lld-link /entry:main /out:%t.exe /subsystem:windows \1# RUN: lld-link /entry:main /out:%t.exe /subsystem:windows \
2# RUN: %p/Inputs/ret42.obj2# RUN: %p/Inputs/ret42.obj
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
44
5CHECK1: MajorOperatingSystemVersion: 65CHECK1: MajorOperatingSystemVersion: 6
6CHECK1: MinorOperatingSystemVersion: 06CHECK1: MinorOperatingSystemVersion: 0
...@@ -10,10 +10,19 @@ CHECK1: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI...@@ -10,10 +10,19 @@ CHECK1: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
1010
11# RUN: lld-link /entry:main /out:%t.exe /subsystem:windows,8.9 \11# RUN: lld-link /entry:main /out:%t.exe /subsystem:windows,8.9 \
12# RUN: %p/Inputs/ret42.obj12# RUN: %p/Inputs/ret42.obj
13# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s13# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
1414
15CHECK2: MajorOperatingSystemVersion: 815CHECK2: MajorOperatingSystemVersion: 8
16CHECK2: MinorOperatingSystemVersion: 916CHECK2: MinorOperatingSystemVersion: 9
17CHECK2: MajorSubsystemVersion: 817CHECK2: MajorSubsystemVersion: 8
18CHECK2: MinorSubsystemVersion: 918CHECK2: MinorSubsystemVersion: 9
19CHECK2: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI19CHECK2: Subsystem: IMAGE_SUBSYSTEM_WINDOWS_GUI
20
21# RUN: lld-link /entry:main /out:%t.exe /subsystem:default,8.9 \
22# RUN: %p/Inputs/ret42.obj
23# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK3 %s
24
25CHECK3: MajorOperatingSystemVersion: 8
26CHECK3: MinorOperatingSystemVersion: 9
27CHECK3: MajorSubsystemVersion: 8
28CHECK3: MinorSubsystemVersion: 9
deps/lld/test/COFF/symtab-gc.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: lld-link -dll -entry:f -out:%t.dll -implib:%t.lib %tobject.obj4# RUN: lld-link -dll -entry:f -out:%t.dll -implib:%t.lib %tobject.obj
5# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %tmain.obj %s5# RUN: llvm-mc -filetype=obj -triple=x86_64-windows-msvc -o %tmain.obj %s
6# RUN: lld-link -entry:main -out:%t.exe -opt:ref -debug:dwarf %tmain.obj %t.lib6# RUN: lld-link -entry:main -out:%t.exe -opt:ref -debug:dwarf %tmain.obj %t.lib
7# RUN: llvm-readobj -coff-imports %t.exe | FileCheck %s7# RUN: llvm-readobj --coff-imports %t.exe | FileCheck %s
88
9# CHECK-NOT: Symbol: f9# CHECK-NOT: Symbol: f
1010
deps/lld/test/COFF/symtab.test+4-4
...@@ -1,13 +1,13 @@...@@ -1,13 +1,13 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /debug:dwarf /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib2# RUN: lld-link /debug:dwarf /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
3# RUN: llvm-readobj -symbols %t.exe | FileCheck %s3# RUN: llvm-readobj --symbols %t.exe | FileCheck %s
4# RUN: lld-link /debug:dwarf /opt:noref /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib4# RUN: lld-link /debug:dwarf /opt:noref /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
5# RUN: llvm-readobj -symbols %t.exe | FileCheck %s5# RUN: llvm-readobj --symbols %t.exe | FileCheck %s
6# RUN: lld-link /debug:symtab /opt:noref /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib6# RUN: lld-link /debug:symtab /opt:noref /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
7# RUN: llvm-readobj -symbols %t.exe | FileCheck %s7# RUN: llvm-readobj --symbols %t.exe | FileCheck %s
88
9# RUN: lld-link /debug /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib9# RUN: lld-link /debug /out:%t.exe /entry:main %t.obj %p/Inputs/std64.lib
10# RUN: llvm-readobj -symbols %t.exe | FileCheck -check-prefix=NO %s10# RUN: llvm-readobj --symbols %t.exe | FileCheck -check-prefix=NO %s
1111
12# CHECK: Symbols [12# CHECK: Symbols [
13# CHECK-NEXT: Symbol {13# CHECK-NEXT: Symbol {
deps/lld/test/COFF/thinlto-archivecollision.ll created+29
...@@ -0,0 +1,29 @@
1; REQUIRES: x86
2; RUN: rm -fr %t
3; RUN: mkdir %t %t/a %t/b
4; RUN: opt -thinlto-bc -o %t/main.obj %s
5; RUN: opt -thinlto-bc -o %t/a/bar.obj %S/Inputs/lto-dep.ll
6; RUN: opt -thinlto-bc -o %t/b/bar.obj %S/Inputs/bar.ll
7; RUN: llvm-ar crs %t/libbar.lib %t/a/bar.obj %t/b/bar.obj
8; RUN: lld-link -out:%t/main.exe -entry:main -lldsavetemps \
9; RUN: -subsystem:console %t/main.obj %t/libbar.lib
10; RUN: FileCheck %s < %t/main.exe.resolution.txt
11
12; CHECK: {{/|\\\\thinlto-archivecollision.ll.tmp/main.obj$}}
13; CHECK: {{^-r=.*/|\\\\thinlto-archivecollision.ll.tmp/main.obj,main,px$}}
14; CHECK: {{/|\\\\thinlto-archivecollision.ll.tmp/libbar.libbar.obj[0-9]+$}}
15; CHECK-NEXT: {{^-r=.*/|\\\\thinlto-archivecollision.ll.tmp/libbar.libbar.obj[0-9]+,foo,p$}}
16; CHECK-NEXT: {{/|\\\\thinlto-archivecollision.ll.tmp/libbar.libbar.obj[0-9]+$}}
17; CHECK-NEXT: {{^-r=.*/|\\\\thinlto-archivecollision.ll.tmp/libbar.libbar.obj[0-9]+,bar,p$}}
18
19target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
20target triple = "x86_64-pc-windows-msvc"
21
22declare void @bar()
23declare void @foo()
24
25define i32 @main() {
26 call void @foo()
27 call void @bar()
28 ret i32 0
29}
deps/lld/test/COFF/thinlto-archives.ll+4-4
...@@ -13,10 +13,10 @@...@@ -13,10 +13,10 @@
1313
14; CHECK: {{/thinlto-archives/main.obj$}}14; CHECK: {{/thinlto-archives/main.obj$}}
15; CHECK: {{^-r=.*/thinlto-archives/main.obj,main,px$}}15; CHECK: {{^-r=.*/thinlto-archives/main.obj,main,px$}}
16; CHECK: {{/thinlto-archives/a.libbar.obj$}}16; CHECK: {{/thinlto-archives/a.libbar.obj[0-9]+$}}
17; CHECK-NEXT: {{^-r=.*/thinlto-archives/a.libbar.obj,foo,p$}}17; CHECK-NEXT: {{^-r=.*/thinlto-archives/a.libbar.obj[0-9]+,foo,p$}}
18; CHECK-NEXT: {{/thinlto-archives/b.libbar.obj$}}18; CHECK-NEXT: {{/thinlto-archives/b.libbar.obj[0-9]+$}}
19; CHECK-NEXT: {{^-r=.*/thinlto-archives/b.libbar.obj,bar,p$}}19; CHECK-NEXT: {{^-r=.*/thinlto-archives/b.libbar.obj[0-9]+,bar,p$}}
2020
21target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"21target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
22target triple = "x86_64-pc-windows-msvc"22target triple = "x86_64-pc-windows-msvc"
deps/lld/test/COFF/thinlto-emit-imports.ll created+59
...@@ -0,0 +1,59 @@
1; REQUIRES: x86
2
3; Generate summary sections and test lld handling.
4; RUN: opt -module-summary %s -o %t1.obj
5; RUN: opt -module-summary %p/Inputs/thinlto.ll -o %t2.obj
6
7; Include a file with an empty module summary index, to ensure that the expected
8; output files are created regardless, for a distributed build system.
9; RUN: opt -module-summary %p/Inputs/thinlto-empty.ll -o %t3.obj
10
11; Ensure lld generates imports files if requested for distributed backends.
12; RUN: rm -f %t3.obj.imports %t3.obj.thinlto.bc
13; RUN: lld-link -entry:main -thinlto-index-only \
14; RUN: -thinlto-emit-imports-files %t1.obj %t2.obj %t3.obj -out:%t4.exe
15
16; The imports file for this module contains the bitcode file for
17; Inputs/thinlto.ll
18; RUN: cat %t1.obj.imports | count 1
19; RUN: cat %t1.obj.imports | FileCheck %s --check-prefix=IMPORTS1
20; IMPORTS1: thinlto-emit-imports.ll.tmp2.obj
21
22; The imports file for Input/thinlto.ll is empty as it does not import anything.
23; RUN: cat %t2.obj.imports | count 0
24
25; The imports file for Input/thinlto_empty.ll is empty but should exist.
26; RUN: cat %t3.obj.imports | count 0
27
28; The index file should be created even for the input with an empty summary.
29; RUN: ls %t3.obj.thinlto.bc
30
31; Ensure lld generates error if unable to write to imports file.
32; RUN: rm -f %t3.obj.imports
33; RUN: touch %t3.obj.imports
34; RUN: chmod 400 %t3.obj.imports
35; RUN: not lld-link -entry:main -thinlto-index-only \
36; RUN: -thinlto-emit-imports-files %t1.obj %t2.obj %t3.obj \
37; RUN: -out:%t4.exe 2>&1 | FileCheck %s --check-prefix=ERR
38; ERR: cannot open {{.*}}3.obj.imports: {{P|p}}ermission denied
39
40; Ensure lld doesn't generate import files when thinlto-index-only is not enabled
41; RUN: rm -f %t1.obj.imports
42; RUN: rm -f %t2.obj.imports
43; RUN: rm -f %t3.obj.imports
44; RUN: lld-link -entry:main -thinlto-emit-imports-files \
45; RUN: %t1.obj %t2.obj %t3.obj -out:%t4.exe
46; RUN: not ls %t1.obj.imports
47; RUN: not ls %t2.obj.imports
48; RUN: not ls %t3.obj.imports
49
50target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
51target triple = "x86_64-pc-windows-msvc19.0.24215"
52
53declare void @g(...)
54
55define void @main() {
56entry:
57 call void (...) @g()
58 ret void
59}
deps/lld/test/COFF/thinlto-index-only.ll created+52
...@@ -0,0 +1,52 @@
1; REQUIRES: x86
2
3; Basic ThinLTO tests.
4; RUN: opt -thinlto-bc %s -o %t1.obj
5; RUN: opt -thinlto-bc %p/Inputs/thinlto.ll -o %t2.obj
6; RUN: opt -thinlto-bc %p/Inputs/thinlto-empty.ll -o %t3.obj
7
8; Ensure lld generates an index and not a binary if requested.
9; RUN: rm -f %t4.exe
10; RUN: lld-link -thinlto-index-only -entry:main %t1.obj %t2.obj -out:%t4.exe
11; RUN: llvm-bcanalyzer -dump %t1.obj.thinlto.bc | FileCheck %s --check-prefix=BACKEND1
12; RUN: llvm-bcanalyzer -dump %t2.obj.thinlto.bc | FileCheck %s --check-prefix=BACKEND2
13; RUN: not test -e %t4.exe
14
15; The backend index for this module contains summaries from itself and
16; Inputs/thinlto.ll, as it imports from the latter.
17; BACKEND1: <MODULE_STRTAB_BLOCK
18; BACKEND1-NEXT: <ENTRY {{.*}} record string = '{{.*}}thinlto-index-only.ll.tmp{{.*}}.obj'
19; BACKEND1: <ENTRY {{.*}} record string = '{{.*}}thinlto-index-only.ll.tmp{{.*}}.obj'
20; BACKEND1-NOT: <ENTRY
21; BACKEND1: </MODULE_STRTAB_BLOCK
22; BACKEND1: <GLOBALVAL_SUMMARY_BLOCK
23; BACKEND1: <VERSION
24; BACKEND1: <FLAGS
25; BACKEND1: <VALUE_GUID op0={{1|2}} op1={{-5300342847281564238|-2624081020897602054}}
26; BACKEND1: <VALUE_GUID op0={{1|2}} op1={{-5300342847281564238|-2624081020897602054}}
27; BACKEND1: <COMBINED
28; BACKEND1: <COMBINED
29; BACKEND1: </GLOBALVAL_SUMMARY_BLOCK
30
31; The backend index for Input/thinlto.ll contains summaries from itself only,
32; as it does not import anything.
33; BACKEND2: <MODULE_STRTAB_BLOCK
34; BACKEND2-NEXT: <ENTRY {{.*}} record string = '{{.*}}thinlto-index-only.ll.tmp2.obj'
35; BACKEND2-NOT: <ENTRY
36; BACKEND2: </MODULE_STRTAB_BLOCK
37; BACKEND2-NEXT: <GLOBALVAL_SUMMARY_BLOCK
38; BACKEND2-NEXT: <VERSION
39; BACKEND2-NEXT: <FLAGS
40; BACKEND2-NEXT: <VALUE_GUID op0=1 op1=-5300342847281564238
41; BACKEND2-NEXT: <COMBINED
42; BACKEND2-NEXT: </GLOBALVAL_SUMMARY_BLOCK
43
44target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
45target triple = "x86_64-pc-windows-msvc19.0.24215"
46
47declare void @g(...)
48
49define void @main() {
50 call void (...) @g()
51 ret void
52}
deps/lld/test/COFF/thinlto-object-suffix-replace.ll created+50
...@@ -0,0 +1,50 @@
1; REQUIRES: x86
2
3; Test to make sure the thinlto-object-suffix-replace option is handled
4; correctly.
5
6; Generate bitcode file with summary, as well as a minimized bitcode without
7; the debug metadata for the thin link.
8; RUN: opt -thinlto-bc %s -thin-link-bitcode-file=%t1.thinlink.bc -o %t1.obj
9
10; First perform the thin link on the normal bitcode file, and save the
11; resulting index.
12; RUN: lld-link -thinlto-index-only -entry:main %t1.obj -out:%t3.exe
13; RUN: cp %t1.obj.thinlto.bc %t1.obj.thinlto.bc.orig
14
15; Next perform the thin link on the minimized bitcode file, and compare dump
16; of the resulting index to the above dump to ensure they are identical.
17; RUN: rm -f %t1.obj.thinlto.bc
18; Make sure it isn't inadvertently using the regular bitcode file.
19; RUN: rm -f %t1.obj
20; RUN: lld-link -entry:main -thinlto-index-only \
21; RUN: -thinlto-object-suffix-replace:".thinlink.bc;.obj" \
22; RUN: %t1.thinlink.bc -out:%t3.exe
23; RUN: diff %t1.obj.thinlto.bc.orig %t1.obj.thinlto.bc
24
25; Ensure lld generates error if suffix replace option not in 'old;new' format.
26; RUN: rm -f %t1.obj.thinlto.bc
27; RUN: not lld-link -entry:main -thinlto-index-only \
28; RUN: -thinlto-object-suffix-replace:"abc:def" %t1.thinlink.bc \
29; RUN: -out:%t3.exe 2>&1 | FileCheck %s --check-prefix=ERR1
30; ERR1: -thinlto-object-suffix-replace: expects 'old;new' format, but got abc:def
31
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: lld-link -entry:main -thinlto-index-only \
36; RUN: -thinlto-object-suffix-replace:".abc;.obj" %t1.thinlink.bc -out:%t3.exe
37; RUN: ls %t1.thinlink.bc.thinlto.bc
38
39target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
40target triple = "x86_64-pc-windows-msvc19.0.24215"
41
42define void @main() {
43entry:
44 ret void
45}
46
47!llvm.dbg.cu = !{}
48
49!1 = !{i32 2, !"Debug Info Version", i32 3}
50!llvm.module.flags = !{!1}
deps/lld/test/COFF/thinlto-prefix-replace.ll created+26
...@@ -0,0 +1,26 @@
1; REQUIRES: x86
2; Check that changing the output path via thinlto-prefix-replace works
3; RUN: mkdir -p %t/oldpath
4; RUN: opt -module-summary %s -o %t/oldpath/t.obj
5
6; Ensure that there is no existing file at the new path, so we properly
7; test the creation of the new file there.
8; RUN: rm -f %t/newpath/t.obj.thinlto.bc
9; RUN: lld-link -entry:main -thinlto-index-only \
10; RUN: -thinlto-prefix-replace:"%t/oldpath/;%t/newpath/" %t/oldpath/t.obj \
11; RUN: -out:%t/t.exe
12; RUN: ls %t/newpath/t.obj.thinlto.bc
13
14; Ensure that lld errors if prefix replace option is not in 'old;new' format.
15; RUN: rm -f %t/newpath/t.obj.thinlto.bc
16; RUN: not lld-link -entry:main -thinlto-index-only \
17; RUN: -thinlto-prefix-replace:"abc:def" %t/oldpath/t.obj \
18; RUN: -out:%t/t.exe 2>&1 | FileCheck --check-prefix=ERR %s
19; ERR: -thinlto-prefix-replace: expects 'old;new' format, but got abc:def
20
21target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
22target triple = "x86_64-pc-windows-msvc19.0.24215"
23
24define void @main() {
25 ret void
26}
deps/lld/test/COFF/timestamp.test+3-3
...@@ -3,9 +3,9 @@ RUN: yaml2obj %p/Inputs/generic.yaml > %t.obj...@@ -3,9 +3,9 @@ RUN: yaml2obj %p/Inputs/generic.yaml > %t.obj
3RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.1.exe3RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.1.exe
4RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.2.exe4RUN: lld-link %t.obj /debug /Brepro /entry:main /nodefaultlib /out:%t.2.exe
5RUN: lld-link %t.obj /debug /timestamp:0 /entry:main /nodefaultlib /out:%t.3.exe5RUN: lld-link %t.obj /debug /timestamp:0 /entry:main /nodefaultlib /out:%t.3.exe
6RUN: llvm-readobj -file-headers -coff-debug-directory %t.1.exe | FileCheck %s --check-prefix=HASH6RUN: llvm-readobj --file-headers --coff-debug-directory %t.1.exe | FileCheck %s --check-prefix=HASH
7RUN: llvm-readobj -file-headers -coff-debug-directory %t.2.exe | FileCheck %s --check-prefix=HASH7RUN: llvm-readobj --file-headers --coff-debug-directory %t.2.exe | FileCheck %s --check-prefix=HASH
8RUN: llvm-readobj -file-headers -coff-debug-directory %t.3.exe | FileCheck %s --check-prefix=ZERO8RUN: llvm-readobj --file-headers --coff-debug-directory %t.3.exe | FileCheck %s --check-prefix=ZERO
99
10HASH: ImageFileHeader {10HASH: ImageFileHeader {
11HASH: TimeDateStamp: [[STAMP:.*]]11HASH: TimeDateStamp: [[STAMP:.*]]
deps/lld/test/COFF/tls.test+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /entry:main %t.obj2# RUN: lld-link /out:%t.exe /entry:main %t.obj
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
44
5# CHECK: TLSTableRVA: 0x10005# CHECK: TLSTableRVA: 0x1000
6# CHECK: TLSTableSize: 0x286# CHECK: TLSTableSize: 0x28
deps/lld/test/COFF/tls32.test+2-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2# RUN: lld-link /out:%t.exe /entry:main %t.obj2# RUN: lld-link -safeseh:no /out:%t.exe /entry:main %t.obj
3# RUN: llvm-readobj -file-headers %t.exe | FileCheck %s3# RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
44
5# CHECK: TLSTableRVA: 0x10005# CHECK: TLSTableRVA: 0x1000
6# CHECK: TLSTableSize: 0x186# CHECK: TLSTableSize: 0x18
deps/lld/test/COFF/tls_suffix_sorting.s created+27
...@@ -0,0 +1,27 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -triple=x86_64-windows-gnu %S/Inputs/tlssup.s -filetype=obj -o %t.tlssup.o
4# RUN: llvm-mc -triple=x86_64-windows-gnu %s -filetype=obj -o %t.main.o
5
6# RUN: lld-link -lldmingw -entry:main %t.main.o %t.tlssup.o -out:%t.exe
7# RUN: llvm-objdump -s %t.exe | FileCheck %s
8
9# Check that .tls$$foo is sorted after the start marker (aa) and before the
10# end marker (ff).
11
12# CHECK: Contents of section .tls:
13# CHECK: 140004000 aabbff
14
15 .text
16 .globl main
17main:
18 movl _tls_index(%rip), %eax
19 movq %gs:88, %rcx
20 movq (%rcx,%rax,8), %rax
21 movb foo@SECREL32(%rax), %al
22 ret
23
24 .section .tls$$foo,"dw"
25 .linkonce discard
26foo:
27 .byte 0xbb
deps/lld/test/COFF/undefined-symbol-cv.s+3-3
...@@ -2,19 +2,19 @@...@@ -2,19 +2,19 @@
2# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s2# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s
3# RUN: not lld-link /out:%t.exe %t.obj 2>&1 | FileCheck %s3# RUN: not lld-link /out:%t.exe %t.obj 2>&1 | FileCheck %s
44
5# CHECK: error: undefined symbol: "int __cdecl foo(void)" (?foo@@YAHXZ)5# CHECK: error: undefined symbol: int __cdecl foo(void)
6# CHECK-NEXT: >>> referenced by file1.cpp:16# CHECK-NEXT: >>> referenced by file1.cpp:1
7# CHECK-NEXT: >>> {{.*}}.obj:(main)7# CHECK-NEXT: >>> {{.*}}.obj:(main)
8# CHECK-NEXT: >>> referenced by file1.cpp:28# CHECK-NEXT: >>> referenced by file1.cpp:2
9# CHECK-NEXT: >>> {{.*}}.obj:(main)9# CHECK-NEXT: >>> {{.*}}.obj:(main)
10# CHECK-EMPTY:10# CHECK-EMPTY:
11# CHECK-NEXT: error: undefined symbol: "int __cdecl bar(void)" (?bar@@YAHXZ)11# CHECK-NEXT: error: undefined symbol: int __cdecl bar(void)
12# CHECK-NEXT: >>> referenced by file2.cpp:312# CHECK-NEXT: >>> referenced by file2.cpp:3
13# CHECK-NEXT: >>> {{.*}}.obj:(main)13# CHECK-NEXT: >>> {{.*}}.obj:(main)
14# CHECK-NEXT: >>> referenced by file1.cpp:414# CHECK-NEXT: >>> referenced by file1.cpp:4
15# CHECK-NEXT: >>> {{.*}}.obj:(f1)15# CHECK-NEXT: >>> {{.*}}.obj:(f1)
16# CHECK-EMPTY:16# CHECK-EMPTY:
17# CHECK-NEXT: error: undefined symbol: "int __cdecl baz(void)" (?baz@@YAHXZ)17# CHECK-NEXT: error: undefined symbol: int __cdecl baz(void)
18# CHECK-NEXT: >>> referenced by file1.cpp:518# CHECK-NEXT: >>> referenced by file1.cpp:5
19# CHECK-NEXT: >>> {{.*}}.obj:(f2)19# CHECK-NEXT: >>> {{.*}}.obj:(f2)
2020
deps/lld/test/COFF/undefined-symbol-lto.test created+31
...@@ -0,0 +1,31 @@
1REQUIRES: x86
2
3RUN: rm -rf %t && mkdir -p %t && cd %t
4RUN: llvm-as %S/Inputs/undefined-symbol-lto-a.ll -o t.obj
5RUN: llvm-as %S/Inputs/undefined-symbol-lto-b.ll -o b.obj
6RUN: llvm-lib b.obj -out:b.lib
7RUN: not lld-link -entry:main -nodefaultlib t.obj b.lib -subsystem:console 2>&1 | FileCheck %s
8
9CHECK: undefined symbol: main
10CHECK: undefined symbol: void __cdecl undefined_ref(void)
11CHECK: referenced by
12
13Originally reported as PR42536.
14
15a.ll corresponds to this C++:
16
17struct __declspec(dllimport) S {
18 virtual void foo();
19};
20void undefined_ref();
21struct Init {
22 Init() { undefined_ref(); }
23 S c;
24} d;
25
26b.ll is from this C++:
27
28struct S {
29 virtual void foo();
30};
31void S::foo() {}
deps/lld/test/COFF/undefined-symbol-multi.s created+47
...@@ -0,0 +1,47 @@
1# REQUIRES: x86
2# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s
3
4# All references to a single undefined symbol count as a single error -- but
5# at most 10 references are printed.
6# RUN: echo ".globl bar" > %t.moreref.s
7# RUN: echo "bar:" >> %t.moreref.s
8# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
9# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
10# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
11# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
12# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
13# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
14# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
15# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
16# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
17# RUN: echo ' call "?foo@@YAHXZ"' >> %t.moreref.s
18# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t2.obj %t.moreref.s
19# RUN: not lld-link /out:/dev/null %t.obj %t2.obj 2>&1 | FileCheck %s
20
21# CHECK: error: undefined symbol: int __cdecl foo(void)
22# CHECK-NEXT: >>> referenced by {{.*}}tmp.obj:(main)
23# CHECK-NEXT: >>> referenced by {{.*}}tmp.obj:(main)
24# CHECK-NEXT: >>> referenced by {{.*}}tmp2.obj:(bar)
25# CHECK-NEXT: >>> referenced by {{.*}}tmp2.obj:(bar)
26# CHECK-NEXT: >>> referenced by {{.*}}tmp2.obj:(bar)
27# CHECK-NEXT: >>> referenced by {{.*}}tmp2.obj:(bar)
28# CHECK-NEXT: >>> referenced by {{.*}}tmp2.obj:(bar)
29# CHECK-NEXT: >>> referenced by {{.*}}tmp2.obj:(bar)
30# CHECK-NEXT: >>> referenced by {{.*}}tmp2.obj:(bar)
31# CHECK-NEXT: >>> referenced by {{.*}}tmp2.obj:(bar)
32# CHECK-NEXT: >>> referenced 2 more times
33# CHECK-EMPTY:
34# CHECK-NEXT: error: undefined symbol: int __cdecl bar(void)
35# CHECK-NEXT: >>> referenced by {{.*}}.obj:(main)
36# CHECK-NEXT: >>> referenced by {{.*}}.obj:(f1)
37
38 .section .text,"xr",one_only,main
39.globl main
40main:
41 call "?foo@@YAHXZ"
42 call "?foo@@YAHXZ"
43 call "?bar@@YAHXZ"
44
45f1:
46 call "?bar@@YAHXZ"
47.Lfunc_end1:
deps/lld/test/COFF/undefined-symbol.s+9-3
...@@ -1,16 +1,22 @@...@@ -1,16 +1,22 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s2# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s
3# RUN: not lld-link /out:%t.exe %t.obj 2>&1 | FileCheck %s3# RUN: not lld-link /out:%t.exe %t.obj 2>&1 | FileCheck %s
4# RUN: not lld-link /out:%t.exe /demangle %t.obj 2>&1 | FileCheck %s
5# RUN: not lld-link /out:%t.exe /demangle:no %t.obj 2>&1 | FileCheck --check-prefix=NODEMANGLE %s
46
5# CHECK: error: undefined symbol: "int __cdecl foo(void)" (?foo@@YAHXZ)7# NODEMANGLE: error: undefined symbol: ?foo@@YAHXZ
8# NODEMANGLE: error: undefined symbol: ?bar@@YAHXZ
9# NODEMANGLE: error: undefined symbol: __imp_?baz@@YAHXZ
10
11# CHECK: error: undefined symbol: int __cdecl foo(void)
6# CHECK-NEXT: >>> referenced by {{.*}}.obj:(main)12# CHECK-NEXT: >>> referenced by {{.*}}.obj:(main)
7# CHECK-NEXT: >>> referenced by {{.*}}.obj:(main)13# CHECK-NEXT: >>> referenced by {{.*}}.obj:(main)
8# CHECK-EMPTY:14# CHECK-EMPTY:
9# CHECK-NEXT: error: undefined symbol: "int __cdecl bar(void)" (?bar@@YAHXZ)15# CHECK-NEXT: error: undefined symbol: int __cdecl bar(void)
10# CHECK-NEXT: >>> referenced by {{.*}}.obj:(main)16# CHECK-NEXT: >>> referenced by {{.*}}.obj:(main)
11# CHECK-NEXT: >>> referenced by {{.*}}.obj:(f1)17# CHECK-NEXT: >>> referenced by {{.*}}.obj:(f1)
12# CHECK-EMPTY:18# CHECK-EMPTY:
13# CHECK-NEXT: error: undefined symbol: "__declspec(dllimport) int __cdecl baz(void)" (__imp_?baz@@YAHXZ)19# CHECK-NEXT: error: undefined symbol: __declspec(dllimport) int __cdecl baz(void)
14# CHECK-NEXT: >>> referenced by {{.*}}.obj:(f2)20# CHECK-NEXT: >>> referenced by {{.*}}.obj:(f2)
1521
16 .section .text,"xr",one_only,main22 .section .text,"xr",one_only,main
deps/lld/test/COFF/unwind.test+2-2
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1# RUN: yaml2obj < %s > %t.obj1# RUN: yaml2obj < %s > %t.obj
2#2#
3# RUN: lld-link /out:%t.exe /entry:main %t.obj3# RUN: lld-link /out:%t.exe /entry:main %t.obj
4# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=HEADER %s4# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=HEADER %s
5# RUN: llvm-objdump -unwind-info %t.exe | FileCheck -check-prefix=UNWIND %s5# RUN: llvm-objdump -unwind-info %t.exe | FileCheck -check-prefix=UNWIND %s
6#6#
7# RUN: lld-link /merge:.pdata=.rdata /out:%t.exe /entry:main %t.obj7# RUN: lld-link /merge:.pdata=.rdata /out:%t.exe /entry:main %t.obj
8# RUN: llvm-readobj -file-headers -sections %t.exe | FileCheck -check-prefix=HEADER-MERGE %s8# RUN: llvm-readobj --file-headers --sections %t.exe | FileCheck -check-prefix=HEADER-MERGE %s
9#9#
10# HEADER: ExceptionTableRVA: 0x300010# HEADER: ExceptionTableRVA: 0x3000
11#11#
deps/lld/test/COFF/used-lto.ll created+15
...@@ -0,0 +1,15 @@
1; REQUIRES: x86
2; RUN: llvm-as -o %t.obj %s
3; RUN: lld-link -dll -debug -opt:ref -noentry -out:%t.dll %t.obj
4; RUN: llvm-pdbutil dump -publics %t.pdb | FileCheck %s
5
6; CHECK: S_PUB32 {{.*}} `foo`
7
8target datalayout = "e-m:w-i64:64-f80:128-n8:16:32:64-S128"
9target triple = "x86_64-pc-windows-msvc"
10
11@llvm.used = appending global [1 x i8*] [i8* bitcast (void ()* @foo to i8*)], section "llvm.metadata"
12
13define void @foo() {
14 ret void
15}
deps/lld/test/COFF/version.test+3-3
...@@ -1,19 +1,19 @@...@@ -1,19 +1,19 @@
1# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj1# RUN: yaml2obj < %p/Inputs/ret42.yaml > %t.obj
22
3# RUN: lld-link /out:%t.exe /entry:main %t.obj3# RUN: lld-link /out:%t.exe /entry:main %t.obj
4# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s4# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=DEFAULT %s
55
6DEFAULT: MajorImageVersion: 06DEFAULT: MajorImageVersion: 0
7DEFAULT: MinorImageVersion: 07DEFAULT: MinorImageVersion: 0
88
9# RUN: lld-link /out:%t.exe /entry:main %t.obj /version:119# RUN: lld-link /out:%t.exe /entry:main %t.obj /version:11
10# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s10# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK1 %s
1111
12CHECK1: MajorImageVersion: 1112CHECK1: MajorImageVersion: 11
13CHECK1: MinorImageVersion: 013CHECK1: MinorImageVersion: 0
1414
15# RUN: lld-link /out:%t.exe /entry:main %t.obj /version:11.2215# RUN: lld-link /out:%t.exe /entry:main %t.obj /version:11.22
16# RUN: llvm-readobj -file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s16# RUN: llvm-readobj --file-headers %t.exe | FileCheck -check-prefix=CHECK2 %s
1717
18CHECK2: MajorImageVersion: 1118CHECK2: MajorImageVersion: 11
19CHECK2: MinorImageVersion: 2219CHECK2: MinorImageVersion: 22
deps/lld/test/COFF/wx.s+5-5
...@@ -1,15 +1,15 @@...@@ -1,15 +1,15 @@
1# REQUIRES: x861# REQUIRES: x86
22
3# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s3# RUN: llvm-mc -triple=x86_64-windows-msvc -filetype=obj -o %t.obj %s
4# RUN: not lld-link /out:%t.exe /entry:main -notarealoption /WX %t.obj 2>&1 | \4# RUN: not lld-link /out:%t.exe /entry:main -notarealopt=ion /WX %t.obj 2>&1 | \
5# RUN: FileCheck -check-prefix=ERROR %s5# RUN: FileCheck -check-prefix=ERROR %s
6# RUN: not lld-link /out:%t.exe /entry:main -notarealoption /WX:NO /WX %t.obj 2>&1 | \6# RUN: not lld-link /out:%t.exe /entry:main -notarealopt=ion /WX:NO /WX %t.obj 2>&1 | \
7# RUN: FileCheck -check-prefix=ERROR %s7# RUN: FileCheck -check-prefix=ERROR %s
8# RUN: lld-link /out:%t.exe /entry:main -notarealoption /WX /WX:NO %t.obj 2>&1 | \8# RUN: lld-link /out:%t.exe /entry:main -notarealopt=ion /WX /WX:NO %t.obj 2>&1 | \
9# RUN: FileCheck -check-prefix=WARNING %s9# RUN: FileCheck -check-prefix=WARNING %s
1010
11# ERROR: error: ignoring unknown argument: -notarealoption11# ERROR: error: ignoring unknown argument '-notarealopt=ion'
12# WARNING: warning: ignoring unknown argument: -notarealoption12# WARNING: warning: ignoring unknown argument '-notarealopt=ion'
1313
14.text14.text
15.global main15.global main
deps/lld/test/ELF/Inputs/aarch64-addrifunc.s created+8
...@@ -0,0 +1,8 @@
1 .text
2 .globl myfunc
3 .globl func1
4 .type func1, %function
5func1:
6 adrp x8, :got: myfunc
7 ldr x8, [x8, :got_lo12: myfunc]
8 ret
deps/lld/test/ELF/Inputs/aarch64-bti1.s created+19
...@@ -0,0 +1,19 @@
1.section ".note.gnu.property", "a"
2.long 4
3.long 0x10
4.long 0x5
5.asciz "GNU"
6
7.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
8.long 4
9.long 1 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
10.long 0
11
12.text
13.globl func2
14.type func2,@function
15func2:
16 .globl func3
17 .type func3, @function
18 bl func3
19 ret
deps/lld/test/ELF/Inputs/aarch64-btipac1.s created+19
...@@ -0,0 +1,19 @@
1.section ".note.gnu.property", "a"
2.long 4
3.long 0x10
4.long 0x5
5.asciz "GNU"
6
7.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
8.long 4
9.long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC and BTI
10.long 0
11
12.text
13.globl func2
14.type func2,@function
15func2:
16 .globl func3
17 .type func3, @function
18 bl func3
19 ret
deps/lld/test/ELF/Inputs/aarch64-func2.s created+8
...@@ -0,0 +1,8 @@
1.text
2.globl func2
3.type func2,@function
4func2:
5 .globl func3
6 .type func3, @function
7 bl func3
8 ret
deps/lld/test/ELF/Inputs/aarch64-func3-bti.s created+16
...@@ -0,0 +1,16 @@
1.section ".note.gnu.property", "a"
2.long 4
3.long 0x10
4.long 0x5
5.asciz "GNU"
6
7.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
8.long 4
9.long 1 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
10.long 0
11
12.text
13.globl func3
14.type func3,@function
15func3:
16 ret
deps/lld/test/ELF/Inputs/aarch64-func3-btipac.s created+16
...@@ -0,0 +1,16 @@
1.section ".note.gnu.property", "a"
2.long 4
3.long 0x10
4.long 0x5
5.asciz "GNU"
6
7.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
8.long 4
9.long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
10.long 0
11
12.text
13.globl func3
14.type func3,@function
15func3:
16 ret
deps/lld/test/ELF/Inputs/aarch64-func3-pac.s created+16
...@@ -0,0 +1,16 @@
1.section ".note.gnu.property", "a"
2.long 4
3.long 0x10
4.long 0x5
5.asciz "GNU"
6
7.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
8.long 4
9.long 2 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
10.long 0
11
12.text
13.globl func3
14.type func3,@function
15func3:
16 ret
deps/lld/test/ELF/Inputs/aarch64-func3.s created+5
...@@ -0,0 +1,5 @@
1.text
2.globl func3
3.type func3,@function
4func3:
5 ret
deps/lld/test/ELF/Inputs/aarch64-nobti.s created+8
...@@ -0,0 +1,8 @@
1.text
2.globl func2
3.type func2,@function
4func2:
5 .globl func3
6 .type func3, @function
7 bl func3
8 ret
deps/lld/test/ELF/Inputs/aarch64-nopac.s created+8
...@@ -0,0 +1,8 @@
1.text
2.globl func2
3.type func2,@function
4func2:
5 .globl func3
6 .type func3, @function
7 bl func3
8 ret
deps/lld/test/ELF/Inputs/aarch64-pac1.s created+19
...@@ -0,0 +1,19 @@
1.section ".note.gnu.property", "a"
2.long 4
3.long 0x10
4.long 0x5
5.asciz "GNU"
6
7.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
8.long 4
9.long 2 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
10.long 0
11
12.text
13.globl func2
14.type func2,@function
15func2:
16 .globl func3
17 .type func3, @function
18 bl func3
19 ret
deps/lld/test/ELF/Inputs/bad-reloc-target.test deleted-21
...@@ -1,21 +0,0 @@
1--- !ELF
2FileHeader:
3 Class: ELFCLASS64
4 Data: ELFDATA2LSB
5 Type: ET_REL
6 Machine: EM_X86_64
7Sections:
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
19Symbols:
20 Global:
21 - Name: foo
\ No newline at end of file
deps/lld/test/ELF/Inputs/comdat-discarded-reloc.s+7-5
...@@ -1,6 +1,8 @@...@@ -1,6 +1,8 @@
1.section .text.bar1,"aG",@progbits,group,comdat1.global bar, _start
22
3.section .text.bar23.section .text.foo,"aG",@progbits,group,comdat
4.global bar4
5bar:5.section .text
6 .quad .text.bar16_start:
7 .quad .text.foo
8 .quad bar
deps/lld/test/ELF/Inputs/deplibs-lib_bar.s created+2
...@@ -0,0 +1,2 @@
1 .global bar
2bar:
deps/lld/test/ELF/Inputs/deplibs-lib_foo.s created+2
...@@ -0,0 +1,2 @@
1 .global foo
2foo:
deps/lld/test/ELF/Inputs/dtrace-r.o deleted
Binary files a/deps/lld/test/ELF/Inputs/dtrace-r.o and /dev/null differ
deps/lld/test/ELF/Inputs/dummy-shared.s created+2
...@@ -0,0 +1,2 @@
1.globl bar
2bar:
deps/lld/test/ELF/Inputs/gdb-index-multiple-cu-2.s+1-1
...@@ -31,7 +31,7 @@ _start:...@@ -31,7 +31,7 @@ _start:
31 .byte 031 .byte 0
32.Lcu_end0:32.Lcu_end0:
3333
34# .debug_gnu_pubnames has just one set, associated with .Lcu_begin1 (CuIndex: 1)34# .debug_gnu_pubnames has just one set, associated with .Lcu_begin1 (cuIndex: 1)
35.section .debug_gnu_pubnames,"",@progbits35.section .debug_gnu_pubnames,"",@progbits
36 .long .LpubNames_end0 - .LpubNames_begin036 .long .LpubNames_end0 - .LpubNames_begin0
37.LpubNames_begin0:37.LpubNames_begin0:
deps/lld/test/ELF/Inputs/gnu-ifunc-canon-ro-abs.s created+2
...@@ -0,0 +1,2 @@
1.rodata
2.8byte ifunc
deps/lld/test/ELF/Inputs/gnu-ifunc-canon-ro-pcrel.s created+2
...@@ -0,0 +1,2 @@
1.rodata
2.4byte ifunc - .
deps/lld/test/ELF/Inputs/gnu-ifunc-canon-rw-addend.s created+2
...@@ -0,0 +1,2 @@
1.data
2.8byte ifunc + 1
deps/lld/test/ELF/Inputs/i386-cet1.s created+16
...@@ -0,0 +1,16 @@
1.section ".note.gnu.property", "a"
2.align 4
3.long 4
4.long 12
5.long 5
6.asciz "GNU"
7
8.long 0xc0000002
9.long 4
10.long 3
11
12.text
13.globl func2
14.type func2,@function
15func2:
16 ret
deps/lld/test/ELF/Inputs/i386-cet2.s created+20
...@@ -0,0 +1,20 @@
1.section ".note.gnu.property", "a"
2.align 4
3.long 4
4.long 24
5.long 5
6.asciz "GNU"
7
8.long 0xc0000000
9.long 4
10.long 0
11
12.long 0xc0000002
13.long 4
14.long 3
15
16.text
17.globl func2
18.type func2,@function
19func2:
20 ret
deps/lld/test/ELF/Inputs/i386-cet3.s created+5
...@@ -0,0 +1,5 @@
1.text
2.globl func2
3.type func2,@function
4func2:
5 ret
deps/lld/test/ELF/Inputs/i386-cet4.s created+16
...@@ -0,0 +1,16 @@
1.section ".note.gnu.property", "a"
2.align 4
3.long 4
4.long 12
5.long 5
6.asciz "GNU"
7
8.long 0xc0000002
9.long 4
10.long 0xfffffffd
11
12.text
13.globl func2
14.type func2,@function
15func2:
16 ret
deps/lld/test/ELF/Inputs/i386-reloc-16-error.s deleted-3
...@@ -1,3 +0,0 @@
1.globl foo
2.hidden foo
3foo = 65536
deps/lld/test/ELF/Inputs/i386-reloc-16.s deleted-3
...@@ -1,3 +0,0 @@
1.globl foo
2.hidden foo
3foo = 0xffff
deps/lld/test/ELF/Inputs/i386-reloc-8-error.s deleted-3
...@@ -1,3 +0,0 @@
1.globl foo
2.hidden foo
3foo = 256
deps/lld/test/ELF/Inputs/i386-reloc-8.s deleted-3
...@@ -1,3 +0,0 @@
1.globl foo
2.hidden foo
3foo = 0xff
deps/lld/test/ELF/Inputs/i386-static-tls-model1.s created+9
...@@ -0,0 +1,9 @@
1.section ".tdata", "awT", @progbits
2.globl var
3var:
4
5.section .foo, "aw"
6.global _start
7_start:
8 movl $var@tpoff, %edx # R_386_TLS_LE_32
9 movl %gs:0, %ecx
deps/lld/test/ELF/Inputs/i386-static-tls-model2.s created+9
...@@ -0,0 +1,9 @@
1.section ".tdata", "awT", @progbits
2.globl var
3var:
4
5.section .foo, "aw"
6.global _start
7_start:
8 movl %gs:0, %eax
9 addl var@gotntpoff(%ebx), %eax # R_386_TLS_GOTIE
deps/lld/test/ELF/Inputs/i386-static-tls-model3.s created+9
...@@ -0,0 +1,9 @@
1.section ".tdata", "awT", @progbits
2.globl var
3var:
4
5.section .foo, "aw"
6.global _start
7_start:
8 movl %gs:0, %eax
9 addl var@indntpoff, %eax # R_386_TLS_IE
deps/lld/test/ELF/Inputs/i386-static-tls-model4.s created+9
...@@ -0,0 +1,9 @@
1.section ".tdata", "awT", @progbits
2.globl var
3var:
4
5.section .foo, "aw"
6.global _start
7_start:
8 movl %gs:0, %eax
9 leal var@ntpoff(%eax), %eax # R_386_TLS_LE
deps/lld/test/ELF/Inputs/ppc64-sort-small-cm-relocs-input2.s created+23
...@@ -0,0 +1,23 @@
1 .text
2
3 .global set
4 .type set,@function
5set:
6.Lgep:
7 addis 2, 12, .TOC.-.Lgep@ha
8 addi 2, 2, .TOC.-.Lgep@l
9.Llep:
10 .localentry set, .Llep-.Lgep
11 addis 5, 2, .LC0@toc@ha
12 addis 6, 2, .LC1@toc@ha
13 ld 5, .LC0@toc@l(5)
14 ld 6, .LC1@toc@l(6)
15 stw 3, 0(5)
16 stw 4, 0(6)
17 blr
18
19 .section .toc,"aw",@progbits
20.LC0:
21 .tc c[TC],c
22.LC1:
23 .tc d[TC],d
deps/lld/test/ELF/Inputs/ppc64-sort-small-cm-relocs-input3.s created+41
...@@ -0,0 +1,41 @@
1 .text
2 .global getA
3 .type getA,@function
4getA:
5.LgepA:
6 addis 2, 12, .TOC.-.LgepA@ha
7 addi 2, 2, .TOC.-.LgepA@l
8.LlepA:
9 .localentry getA, .LlepA-.LgepA
10 ld 3, .LC0@toc(2)
11 lwa 3, 0(3)
12 blr
13
14 .global getB
15 .type getB,@function
16getB:
17.LgepB:
18 addis 2, 12, .TOC.-.LgepB@ha
19 addi 2, 2, .TOC.-.LgepB@l
20.LlepB:
21 .localentry getB, .LlepB-.LgepB
22 ld 3, .LC1@toc(2)
23 lwa 3, 0(3)
24 blr
25
26 .section .toc,"aw",@progbits
27.LC0:
28 .tc a[TC],a
29.LConst1:
30 .quad 0xa
31.LC1:
32 .tc b[TC],b
33.Lconst2:
34 .quad 0xaabbccddeeff
35
36 .type b,@object
37 .data
38 .global b
39b:
40 .long 22
41 .size b, 4
deps/lld/test/ELF/Inputs/ppc64-sort-small-cm-relocs-input4.s created+18
...@@ -0,0 +1,18 @@
1 .text
2 .global getRodata
3 .type getRodata,@function
4getRodata:
5.Lgep:
6 addis 2, 12, .TOC.-.Lgep@ha
7 addi 2, 2, .TOC.-.Lgep@l
8.Llep:
9 .localentry getRodata, .Llep-.Lgep
10 lwa 3, .LC0@toc(2)
11 blr
12
13 .section .rodata,"aMS",@progbits,8
14 .quad _start
15
16 .section .toc,"aw",@progbits
17.LC0:
18 .tc .rodata[TC], .rodata
deps/lld/test/ELF/Inputs/ppc64-toc-relax-shared.s created+7
...@@ -0,0 +1,7 @@
1.data
2
3.type shared,@object
4.globl shared
5shared:
6 .long 8
7 .size shared, 4
deps/lld/test/ELF/Inputs/ppc64-toc-relax.s created+15
...@@ -0,0 +1,15 @@
1.data
2
3.globl default, hidden
4.hidden hidden
5
6default:
7hidden:
8 .long 0
9
10.space 65532
11
12.globl hidden2
13.hidden hidden2
14hidden2:
15 .long 0
deps/lld/test/ELF/Inputs/print-icf.s+9-9
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1.section .text.f6, "ax" 1.section .text.f6, "ax"
2f6: 2f6:
3 mov $60, %rax 3 mov $60, %rax
4 mov $42, %rdi 4 mov $42, %rdi
5 syscall 5 syscall
6 6
7 .section .text.f7, "ax" 7 .section .text.f7, "ax"
8f7: 8f7:
9 mov $0, %rax 9 mov $0, %rax
deps/lld/test/ELF/Inputs/shf-info-link.test+2-2
...@@ -17,5 +17,5 @@ Sections:...@@ -17,5 +17,5 @@ Sections:
17 Symbol: foo17 Symbol: foo
18 Type: R_X86_64_6418 Type: R_X86_64_64
19Symbols:19Symbols:
20 Global:20 - Name: foo
21 - Name: foo21 Binding: STB_GLOBAL
deps/lld/test/ELF/Inputs/vs-diagnostics-duplicate2.s created+31
...@@ -0,0 +1,31 @@
1.global foo, bar
2
3.text
4foo:
5 nop
6
7.file 1 "duplicate2.s"
8.loc 1 20
9bar:
10 nop
11
12.section .debug_abbrev,"",@progbits
13 .byte 1 # Abbreviation Code
14 .byte 17 # DW_TAG_compile_unit
15 .byte 0 # DW_CHILDREN_no
16 .byte 16 # DW_AT_stmt_list
17 .byte 23 # DW_FORM_sec_offset
18 .byte 0 # EOM(1)
19 .byte 0 # EOM(2)
20 .byte 0 # EOM(3)
21
22.section .debug_info,"",@progbits
23 .long .Lend0 - .Lbegin0 # Length of Unit
24.Lbegin0:
25 .short 4 # DWARF version number
26 .long .debug_abbrev # Offset Into Abbrev. Section
27 .byte 8 # Address Size (in bytes)
28 .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
29 .long .debug_line # DW_AT_stmt_list
30.Lend0:
31 .section .debug_line,"",@progbits
deps/lld/test/ELF/Inputs/vs-diagnostics-duplicate3.s created+6
...@@ -0,0 +1,6 @@
1.file "duplicate3.s"
2
3.global baz
4.text
5baz:
6 nop
deps/lld/test/ELF/Inputs/x86-64-cet1.s created+17
...@@ -0,0 +1,17 @@
1.section ".note.gnu.property", "a"
2.align 4
3.long 4
4.long 16
5.long 5
6.asciz "GNU"
7
8.long 0xc0000002
9.long 4
10.long 3
11.long 0
12
13.text
14.globl func2
15.type func2,@function
16func2:
17 ret
deps/lld/test/ELF/Inputs/x86-64-cet2.s created+22
...@@ -0,0 +1,22 @@
1.section ".note.gnu.property", "a"
2.align 4
3.long 4
4.long 32
5.long 5
6.asciz "GNU"
7
8.long 0xc0000000
9.long 4
10.long 0
11.long 0
12
13.long 0xc0000002
14.long 4
15.long 3
16.long 0
17
18.text
19.globl func2
20.type func2,@function
21func2:
22 ret
deps/lld/test/ELF/Inputs/x86-64-cet3.s created+5
...@@ -0,0 +1,5 @@
1.text
2.globl func2
3.type func2,@function
4func2:
5 ret
deps/lld/test/ELF/Inputs/x86-64-cet4.s created+17
...@@ -0,0 +1,17 @@
1.section ".note.gnu.property", "a"
2.align 4
3.long 4
4.long 16
5.long 5
6.asciz "GNU"
7
8.long 0xc0000002
9.long 4
10.long 0xfffffffd
11.long 0
12
13.text
14.globl func2
15.type func2,@function
16func2:
17 ret
deps/lld/test/ELF/Inputs/x86-64-pcrel.s created+8
...@@ -0,0 +1,8 @@
1.globl foo
2foo:
3
4.word _start - foo
5.fill 14,1,0xcc
6
7.byte _start - foo
8.fill 15,1,0xcc
deps/lld/test/ELF/Inputs/x86-64-reloc-16-error.s deleted-3
...@@ -1,3 +0,0 @@
1.globl foo
2.hidden foo
3foo = 65536
deps/lld/test/ELF/Inputs/x86-64-reloc-16.s deleted-3
...@@ -1,3 +0,0 @@
1.globl foo
2.hidden foo
3foo = 0x42
deps/lld/test/ELF/Inputs/x86-64-reloc-8-error.s deleted-3
...@@ -1,3 +0,0 @@
1.globl foo
2.hidden foo
3foo = 256
deps/lld/test/ELF/Inputs/x86-64-reloc-8.s deleted-3
...@@ -1,3 +0,0 @@
1.globl foo
2.hidden foo
3foo = 0x42
deps/lld/test/ELF/aarch64-abs16.s+4-4
...@@ -20,8 +20,8 @@ _start:...@@ -20,8 +20,8 @@ _start:
20// S + A = 0x800020// S + A = 0x8000
21// CHECK-NEXT: 210000 ffff008021// CHECK-NEXT: 210000 ffff0080
2222
23// RUN: not ld.lld %t.o %t255.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW123// RUN: not ld.lld %t.o %t255.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW1
24// OVERFLOW1: relocation R_AARCH64_ABS16 out of range: -32769 is not in [-32768, 32767]24// OVERFLOW1: relocation R_AARCH64_ABS16 out of range: -32769 is not in [-32768, 65535]
2525
26// RUN: not ld.lld %t.o %t257.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW226// RUN: not ld.lld %t.o %t257.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW2
27// OVERFLOW2: relocation R_AARCH64_ABS16 out of range: 65536 is not in [-32768, 32767]27// OVERFLOW2: relocation R_AARCH64_ABS16 out of range: 65536 is not in [-32768, 65535]
deps/lld/test/ELF/aarch64-abs32-dyn.s created+14
...@@ -0,0 +1,14 @@
1# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64 %s -o %t.o
3# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s
4
5## Test we don't create R_AARCH64_RELATIVE.
6
7# CHECK: error: relocation R_AARCH64_ABS32 cannot be used against symbol hidden; recompile with -fPIC
8
9.globl hidden
10.hidden hidden
11hidden:
12
13.data
14.long hidden
deps/lld/test/ELF/aarch64-abs32.s+4-4
...@@ -20,8 +20,8 @@ _start:...@@ -20,8 +20,8 @@ _start:
20// S + A = 0x8000000020// S + A = 0x80000000
21// CHECK-NEXT: 210000 ffffffff 0000008021// CHECK-NEXT: 210000 ffffffff 00000080
2222
23// RUN: not ld.lld %t.o %t255.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW123// RUN: not ld.lld %t.o %t255.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW1
24// OVERFLOW1: relocation R_AARCH64_ABS32 out of range: -2147483649 is not in [-2147483648, 2147483647]24// OVERFLOW1: relocation R_AARCH64_ABS32 out of range: -2147483649 is not in [-2147483648, 4294967295]
2525
26// RUN: not ld.lld %t.o %t257.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW226// RUN: not ld.lld %t.o %t257.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=OVERFLOW2
27// OVERFLOW2: relocation R_AARCH64_ABS32 out of range: 4294967296 is not in [-2147483648, 2147483647]27// OVERFLOW2: relocation R_AARCH64_ABS32 out of range: 4294967296 is not in [-2147483648, 4294967295]
deps/lld/test/ELF/aarch64-abs64-dyn.s+1-1
...@@ -14,7 +14,7 @@ bar:...@@ -14,7 +14,7 @@ bar:
14 .xword bar14 .xword bar
1515
16// RUN: ld.lld -shared -o %t.so %t.o16// RUN: ld.lld -shared -o %t.so %t.o
17// RUN: llvm-readobj -symbols -dyn-relocations %t.so | FileCheck %s17// RUN: llvm-readobj --symbols --dyn-relocations %t.so | FileCheck %s
1818
19// CHECK: Dynamic Relocations {19// CHECK: Dynamic Relocations {
20// CHECK-NEXT: {{.*}} R_AARCH64_RELATIVE - [[BAR_ADDR:.*]]20// CHECK-NEXT: {{.*}} R_AARCH64_RELATIVE - [[BAR_ADDR:.*]]
deps/lld/test/ELF/aarch64-bti-pac-cli-error.s created+12
...@@ -0,0 +1,12 @@
1# REQUIRES: x86
2# RUN: llvm-mc --triple=x86_64-pc-linux --filetype=obj -o %t.o %s
3# RUN: not ld.lld --pac-plt --force-bti %t.o -o %t 2>&1 | FileCheck %s
4#
5## Check that we error if --pac-plt and --force-bti are used when target is not
6## aarch64
7
8# CHECK: error: --pac-plt only supported on AArch64
9# CHECK-NEXT: error: --force-bti only supported on AArch64
10
11 .globl start
12start: ret
deps/lld/test/ELF/aarch64-call26-thunk.s+1
...@@ -10,6 +10,7 @@ _start:...@@ -10,6 +10,7 @@ _start:
10 bl big10 bl big
1111
12// CHECK: Disassembly of section .text:12// CHECK: Disassembly of section .text:
13// CHECK-EMPTY:
13// CHECK-NEXT: _start:14// CHECK-NEXT: _start:
14// CHECK-NEXT: 210000: 02 00 00 94 bl #815// CHECK-NEXT: 210000: 02 00 00 94 bl #8
15// CHECK: __AArch64AbsLongThunk_big:16// CHECK: __AArch64AbsLongThunk_big:
deps/lld/test/ELF/aarch64-condb-reloc.s+14-10
...@@ -5,12 +5,13 @@...@@ -5,12 +5,13 @@
5# RUN: llvm-objdump -d %t | FileCheck %s5# RUN: llvm-objdump -d %t | FileCheck %s
6# RUN: ld.lld -shared %t1 %t2 -o %t36# RUN: ld.lld -shared %t1 %t2 -o %t3
7# RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=DSO %s7# RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=DSO %s
8# RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s8# RUN: llvm-readobj -S -r %t3 | FileCheck -check-prefix=DSOREL %s
99
10# 0x11024 - 36 = 0x1100010# 0x11024 - 36 = 0x11000
11# 0x11028 - 24 = 0x1101011# 0x11028 - 24 = 0x11010
12# 0x1102c - 16 = 0x1101c12# 0x1102c - 16 = 0x1101c
13# CHECK: Disassembly of section .text:13# CHECK: Disassembly of section .text:
14# CHECK-EMPTY:
14# CHECK-NEXT: _foo:15# CHECK-NEXT: _foo:
15# CHECK-NEXT: 210000: {{.*}} nop16# CHECK-NEXT: 210000: {{.*}} nop
16# CHECK-NEXT: 210004: {{.*}} nop17# CHECK-NEXT: 210004: {{.*}} nop
...@@ -36,8 +37,8 @@...@@ -36,8 +37,8 @@
36#DSOREL-NEXT: SHF_ALLOC37#DSOREL-NEXT: SHF_ALLOC
37#DSOREL-NEXT: SHF_WRITE38#DSOREL-NEXT: SHF_WRITE
38#DSOREL-NEXT: ]39#DSOREL-NEXT: ]
39#DSOREL-NEXT: Address: 0x2000040#DSOREL-NEXT: Address: 0x30000
40#DSOREL-NEXT: Offset: 0x2000041#DSOREL-NEXT: Offset: 0x30000
41#DSOREL-NEXT: Size: 4842#DSOREL-NEXT: Size: 48
42#DSOREL-NEXT: Link: 043#DSOREL-NEXT: Link: 0
43#DSOREL-NEXT: Info: 044#DSOREL-NEXT: Info: 0
...@@ -46,13 +47,14 @@...@@ -46,13 +47,14 @@
46#DSOREL-NEXT: }47#DSOREL-NEXT: }
47#DSOREL: Relocations [48#DSOREL: Relocations [
48#DSOREL-NEXT: Section ({{.*}}) .rela.plt {49#DSOREL-NEXT: Section ({{.*}}) .rela.plt {
49#DSOREL-NEXT: 0x20018 R_AARCH64_JUMP_SLOT _foo50#DSOREL-NEXT: 0x30018 R_AARCH64_JUMP_SLOT _foo
50#DSOREL-NEXT: 0x20020 R_AARCH64_JUMP_SLOT _bar51#DSOREL-NEXT: 0x30020 R_AARCH64_JUMP_SLOT _bar
51#DSOREL-NEXT: 0x20028 R_AARCH64_JUMP_SLOT _dah52#DSOREL-NEXT: 0x30028 R_AARCH64_JUMP_SLOT _dah
52#DSOREL-NEXT: }53#DSOREL-NEXT: }
53#DSOREL-NEXT:]54#DSOREL-NEXT:]
5455
55#DSO: Disassembly of section .text:56#DSO: Disassembly of section .text:
57#DSO-EMPTY:
56#DSO-NEXT: _foo:58#DSO-NEXT: _foo:
57#DSO-NEXT: 10000: {{.*}} nop59#DSO-NEXT: 10000: {{.*}} nop
58#DSO-NEXT: 10004: {{.*}} nop60#DSO-NEXT: 10004: {{.*}} nop
...@@ -69,10 +71,12 @@...@@ -69,10 +71,12 @@
69#DSO-NEXT: 10024: {{.*}} b.eq #4471#DSO-NEXT: 10024: {{.*}} b.eq #44
70#DSO-NEXT: 10028: {{.*}} b.eq #5672#DSO-NEXT: 10028: {{.*}} b.eq #56
71#DSO-NEXT: 1002c: {{.*}} b.eq #6873#DSO-NEXT: 1002c: {{.*}} b.eq #68
74#DSO-EMPTY:
72#DSO-NEXT: Disassembly of section .plt:75#DSO-NEXT: Disassembly of section .plt:
76#DSO-EMPTY:
73#DSO-NEXT: .plt:77#DSO-NEXT: .plt:
74#DSO-NEXT: 10030: {{.*}} stp x16, x30, [sp, #-16]!78#DSO-NEXT: 10030: {{.*}} stp x16, x30, [sp, #-16]!
75#DSO-NEXT: 10034: {{.*}} adrp x16, #6553679#DSO-NEXT: 10034: {{.*}} adrp x16, #131072
76#DSO-NEXT: 10038: {{.*}} ldr x17, [x16, #16]80#DSO-NEXT: 10038: {{.*}} ldr x17, [x16, #16]
77#DSO-NEXT: 1003c: {{.*}} add x16, x16, #1681#DSO-NEXT: 1003c: {{.*}} add x16, x16, #16
78#DSO-NEXT: 10040: {{.*}} br x1782#DSO-NEXT: 10040: {{.*}} br x17
...@@ -81,19 +85,19 @@...@@ -81,19 +85,19 @@
81#DSO-NEXT: 1004c: {{.*}} nop85#DSO-NEXT: 1004c: {{.*}} nop
82#DSO-EMPTY:86#DSO-EMPTY:
83#DSO-NEXT: _foo@plt:87#DSO-NEXT: _foo@plt:
84#DSO-NEXT: 10050: {{.*}} adrp x16, #6553688#DSO-NEXT: 10050: {{.*}} adrp x16, #131072
85#DSO-NEXT: 10054: {{.*}} ldr x17, [x16, #24]89#DSO-NEXT: 10054: {{.*}} ldr x17, [x16, #24]
86#DSO-NEXT: 10058: {{.*}} add x16, x16, #2490#DSO-NEXT: 10058: {{.*}} add x16, x16, #24
87#DSO-NEXT: 1005c: {{.*}} br x1791#DSO-NEXT: 1005c: {{.*}} br x17
88#DSO-EMPTY:92#DSO-EMPTY:
89#DSO-NEXT: _bar@plt:93#DSO-NEXT: _bar@plt:
90#DSO-NEXT: 10060: {{.*}} adrp x16, #6553694#DSO-NEXT: 10060: {{.*}} adrp x16, #131072
91#DSO-NEXT: 10064: {{.*}} ldr x17, [x16, #32]95#DSO-NEXT: 10064: {{.*}} ldr x17, [x16, #32]
92#DSO-NEXT: 10068: {{.*}} add x16, x16, #3296#DSO-NEXT: 10068: {{.*}} add x16, x16, #32
93#DSO-NEXT: 1006c: {{.*}} br x1797#DSO-NEXT: 1006c: {{.*}} br x17
94#DSO-EMPTY:98#DSO-EMPTY:
95#DSO-NEXT: _dah@plt:99#DSO-NEXT: _dah@plt:
96#DSO-NEXT: 10070: {{.*}} adrp x16, #65536100#DSO-NEXT: 10070: {{.*}} adrp x16, #131072
97#DSO-NEXT: 10074: {{.*}} ldr x17, [x16, #40]101#DSO-NEXT: 10074: {{.*}} ldr x17, [x16, #40]
98#DSO-NEXT: 10078: {{.*}} add x16, x16, #40102#DSO-NEXT: 10078: {{.*}} add x16, x16, #40
99#DSO-NEXT: 1007c: {{.*}} br x17103#DSO-NEXT: 1007c: {{.*}} br x17
deps/lld/test/ELF/aarch64-copy.s+3-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %p/Inputs/relocation-copy.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=aarch64-pc-freebsd %p/Inputs/relocation-copy.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -soname fixed-length-string.so -o %t2.so4// RUN: ld.lld -shared %t2.o -soname fixed-length-string.so -o %t2.so
5// RUN: ld.lld %t.o %t2.so -o %t35// RUN: ld.lld %t.o %t2.so -o %t3
6// RUN: llvm-readobj -s -r --expand-relocs -symbols %t3 | FileCheck %s6// RUN: llvm-readobj -S -r --expand-relocs --symbols %t3 | FileCheck %s
7// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s7// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
8// RUN: llvm-objdump -s -section=.rodata %t3 | FileCheck -check-prefix=RODATA %s8// RUN: llvm-objdump -s -section=.rodata %t3 | FileCheck -check-prefix=RODATA %s
99
...@@ -77,6 +77,7 @@ _start:...@@ -77,6 +77,7 @@ _start:
77// CHECK: ]77// CHECK: ]
7878
79// CODE: Disassembly of section .text:79// CODE: Disassembly of section .text:
80// CODE-EMPTY:
80// CODE-NEXT: _start:81// CODE-NEXT: _start:
81// S(x) = 0x230000, A = 0, P = 0x21000082// S(x) = 0x230000, A = 0, P = 0x210000
82// S + A - P = 0x20000 = 13107283// S + A - P = 0x20000 = 131072
...@@ -90,4 +91,4 @@ _start:...@@ -90,4 +91,4 @@ _start:
9091
91// RODATA: Contents of section .rodata:92// RODATA: Contents of section .rodata:
92// S(z) = 0x23001493// S(z) = 0x230014
93// RODATA-NEXT: 2002e0 1400230094// RODATA-NEXT: 200318 14002300
deps/lld/test/ELF/aarch64-copy2.s deleted-27
...@@ -1,27 +0,0 @@
1// REQUIRES: aarch64
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux
3// RUN: llvm-mc %p/Inputs/aarch64-copy2.s -o %t2.o -filetype=obj -triple=aarch64-pc-linux
4// RUN: ld.lld %t2.o -o %t2.so -shared
5// RUN: ld.lld %t.o %t2.so -o %t
6// RUN: llvm-readobj -t %t | FileCheck %s
7
8 .global _start
9_start:
10 adrp x8, foo
11 bl bar
12
13// CHECK: Name: bar
14// CHECK-NEXT: Value: 0x0
15// CHECK-NEXT: Size: 0
16// CHECK-NEXT: Binding: Global
17// CHECK-NEXT: Type: None
18// CHECK-NEXT: Other: 0
19// CHECK-NEXT: Section: Undefined
20
21// CHECK: Name: foo
22// CHECK-NEXT: Value: 0x210030
23// CHECK-NEXT: Size: 0
24// CHECK-NEXT: Binding: Global
25// CHECK-NEXT: Type: Function
26// CHECK-NEXT: Other: 0
27// CHECK-NEXT: Section: Undefined
deps/lld/test/ELF/aarch64-cortex-a53-843419-large.s+3-3
...@@ -42,7 +42,7 @@ t3_ff8_ldr:...@@ -42,7 +42,7 @@ t3_ff8_ldr:
42 ret42 ret
4343
44// CHECK3: t3_ff8_ldr:44// CHECK3: t3_ff8_ldr:
45// CHECK3-NEXT: 211ff8: 60 00 04 f0 adrp x0, #13427916845// CHECK3-NEXT: 211ff8: e0 00 04 f0 adrp x0, #134344704
46// CHECK3-NEXT: 211ffc: 21 00 40 f9 ldr x1, [x1]46// CHECK3-NEXT: 211ffc: 21 00 40 f9 ldr x1, [x1]
47// CHECK3-NEXT: 212000: 02 08 80 15 b #10067149647// CHECK3-NEXT: 212000: 02 08 80 15 b #100671496
48// CHECK3-NEXT: 212004: c0 03 5f d6 ret48// CHECK3-NEXT: 212004: c0 03 5f d6 ret
...@@ -63,7 +63,7 @@ t3_ff8_str:...@@ -63,7 +63,7 @@ t3_ff8_str:
63 ret63 ret
6464
65// CHECK4: t3_ff8_str:65// CHECK4: t3_ff8_str:
66// CHECK4-NEXT: 4213ff8: 60 00 02 b0 adrp x0, #6716211266// CHECK4-NEXT: 4213ff8: e0 00 02 b0 adrp x0, #67227648
67// CHECK4-NEXT: 4213ffc: 21 00 40 f9 ldr x1, [x1]67// CHECK4-NEXT: 4213ffc: 21 00 40 f9 ldr x1, [x1]
68// CHECK4-NEXT: 4214000: 04 00 80 14 b #3355444868// CHECK4-NEXT: 4214000: 04 00 80 14 b #33554448
69// CHECK4-NEXT: 4214004: c0 03 5f d6 ret69// CHECK4-NEXT: 4214004: c0 03 5f d6 ret
...@@ -102,7 +102,7 @@ t3_ffc_ldr:...@@ -102,7 +102,7 @@ t3_ffc_ldr:
102 ret102 ret
103103
104// CHECK7: t3_ffc_ldr:104// CHECK7: t3_ffc_ldr:
105// CHECK7-NEXT: 8211ffc: 60 00 00 f0 adrp x0, #61440105// CHECK7-NEXT: 8211ffc: e0 00 00 f0 adrp x0, #126976
106// CHECK7-NEXT: 8212000: 21 00 40 f9 ldr x1, [x1]106// CHECK7-NEXT: 8212000: 21 00 40 f9 ldr x1, [x1]
107// CHECK7-NEXT: 8212004: 02 00 00 14 b #8107// CHECK7-NEXT: 8212004: 02 00 00 14 b #8
108// CHECK7-NEXT: 8212008: c0 03 5f d6 ret108// CHECK7-NEXT: 8212008: c0 03 5f d6 ret
deps/lld/test/ELF/aarch64-cortex-a53-843419-recognize.s+26-26
...@@ -28,7 +28,7 @@...@@ -28,7 +28,7 @@
2828
29// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 211FF8 in unpatched output.29// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 211FF8 in unpatched output.
30// CHECK: t3_ff8_ldr:30// CHECK: t3_ff8_ldr:
31// CHECK-NEXT: 211ff8: e0 01 00 f0 adrp x0, #25804831// CHECK-NEXT: 211ff8: 60 02 00 f0 adrp x0, #323584
32// CHECK-NEXT: 211ffc: 21 00 40 f9 ldr x1, [x1]32// CHECK-NEXT: 211ffc: 21 00 40 f9 ldr x1, [x1]
33// CHECK-FIX: 212000: 03 c8 00 14 b #20481233// CHECK-FIX: 212000: 03 c8 00 14 b #204812
34// CHECK-NOFIX: 212000: 00 00 40 f9 ldr x0, [x0]34// CHECK-NOFIX: 212000: 00 00 40 f9 ldr x0, [x0]
...@@ -46,7 +46,7 @@ t3_ff8_ldr:...@@ -46,7 +46,7 @@ t3_ff8_ldr:
4646
47// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 213FF8 in unpatched output.47// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 213FF8 in unpatched output.
48// CHECK: t3_ff8_ldrsimd:48// CHECK: t3_ff8_ldrsimd:
49// CHECK-NEXT: 213ff8: e0 01 00 b0 adrp x0, #24985649// CHECK-NEXT: 213ff8: 60 02 00 b0 adrp x0, #315392
50// CHECK-NEXT: 213ffc: 21 00 40 bd ldr s1, [x1]50// CHECK-NEXT: 213ffc: 21 00 40 bd ldr s1, [x1]
51// CHECK-FIX: 214000: 05 c0 00 14 b #19662851// CHECK-FIX: 214000: 05 c0 00 14 b #196628
52// CHECK-NOFIX: 214000: 02 04 40 f9 ldr x2, [x0, #8]52// CHECK-NOFIX: 214000: 02 04 40 f9 ldr x2, [x0, #8]
...@@ -64,7 +64,7 @@ t3_ff8_ldrsimd:...@@ -64,7 +64,7 @@ t3_ff8_ldrsimd:
6464
65// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 215FFC in unpatched output.65// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 215FFC in unpatched output.
66// CHECK: t3_ffc_ldrpost:66// CHECK: t3_ffc_ldrpost:
67// CHECK-NEXT: 215ffc: c0 01 00 f0 adrp x0, #24166467// CHECK-NEXT: 215ffc: 40 02 00 f0 adrp x0, #307200
68// CHECK-NEXT: 216000: 21 84 40 bc ldr s1, [x1], #868// CHECK-NEXT: 216000: 21 84 40 bc ldr s1, [x1], #8
69// CHECK-FIX: 216004: 06 b8 00 14 b #18844069// CHECK-FIX: 216004: 06 b8 00 14 b #188440
70// CHECK-NOFIX: 216004: 03 08 40 f9 ldr x3, [x0, #16]70// CHECK-NOFIX: 216004: 03 08 40 f9 ldr x3, [x0, #16]
...@@ -82,7 +82,7 @@ t3_ffc_ldrpost:...@@ -82,7 +82,7 @@ t3_ffc_ldrpost:
8282
83// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 217FF8 in unpatched output.83// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 217FF8 in unpatched output.
84// CHECK: t3_ff8_strpre:84// CHECK: t3_ff8_strpre:
85// CHECK-NEXT: 217ff8: c0 01 00 b0 adrp x0, #23347285// CHECK-NEXT: 217ff8: 40 02 00 b0 adrp x0, #299008
86// CHECK-NEXT: 217ffc: 21 8c 00 bc str s1, [x1, #8]!86// CHECK-NEXT: 217ffc: 21 8c 00 bc str s1, [x1, #8]!
87// CHECK-FIX: 218000: 09 b0 00 14 b #18026087// CHECK-FIX: 218000: 09 b0 00 14 b #180260
88// CHECK-NOFIX: 218000: 02 00 40 f9 ldr x2, [x0]88// CHECK-NOFIX: 218000: 02 00 40 f9 ldr x2, [x0]
...@@ -100,7 +100,7 @@ t3_ff8_strpre:...@@ -100,7 +100,7 @@ t3_ff8_strpre:
100100
101// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 219FFC in unpatched output.101// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 219FFC in unpatched output.
102// CHECK: t3_ffc_str:102// CHECK: t3_ffc_str:
103// CHECK-NEXT: 219ffc: bc 01 00 f0 adrp x28, #225280103// CHECK-NEXT: 219ffc: 3c 02 00 f0 adrp x28, #290816
104// CHECK-NEXT: 21a000: 42 00 00 f9 str x2, [x2]104// CHECK-NEXT: 21a000: 42 00 00 f9 str x2, [x2]
105// CHECK-FIX: 21a004: 0a a8 00 14 b #172072105// CHECK-FIX: 21a004: 0a a8 00 14 b #172072
106// CHECK-NOFIX: 21a004: 9c 07 00 f9 str x28, [x28, #8]106// CHECK-NOFIX: 21a004: 9c 07 00 f9 str x28, [x28, #8]
...@@ -118,7 +118,7 @@ t3_ffc_str:...@@ -118,7 +118,7 @@ t3_ffc_str:
118118
119// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21BFFC in unpatched output.119// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21BFFC in unpatched output.
120// CHECK: t3_ffc_strsimd:120// CHECK: t3_ffc_strsimd:
121// CHECK-NEXT: 21bffc: bc 01 00 b0 adrp x28, #217088121// CHECK-NEXT: 21bffc: 3c 02 00 b0 adrp x28, #282624
122// CHECK-NEXT: 21c000: 44 00 00 b9 str w4, [x2]122// CHECK-NEXT: 21c000: 44 00 00 b9 str w4, [x2]
123// CHECK-FIX: 21c004: 0c a0 00 14 b #163888123// CHECK-FIX: 21c004: 0c a0 00 14 b #163888
124// CHECK-NOFIX: 21c004: 84 0b 00 f9 str x4, [x28, #16]124// CHECK-NOFIX: 21c004: 84 0b 00 f9 str x4, [x28, #16]
...@@ -136,7 +136,7 @@ t3_ffc_strsimd:...@@ -136,7 +136,7 @@ t3_ffc_strsimd:
136136
137// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21DFF8 in unpatched output.137// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21DFF8 in unpatched output.
138// CHECK: t3_ff8_ldrunpriv:138// CHECK: t3_ff8_ldrunpriv:
139// CHECK-NEXT: 21dff8: 9d 01 00 f0 adrp x29, #208896139// CHECK-NEXT: 21dff8: 1d 02 00 f0 adrp x29, #274432
140// CHECK-NEXT: 21dffc: 41 08 40 38 ldtrb w1, [x2]140// CHECK-NEXT: 21dffc: 41 08 40 38 ldtrb w1, [x2]
141// CHECK-FIX: 21e000: 0f 98 00 14 b #155708141// CHECK-FIX: 21e000: 0f 98 00 14 b #155708
142// CHECK-NOFIX: 21e000: bd 03 40 f9 ldr x29, [x29]142// CHECK-NOFIX: 21e000: bd 03 40 f9 ldr x29, [x29]
...@@ -154,7 +154,7 @@ t3_ff8_ldrunpriv:...@@ -154,7 +154,7 @@ t3_ff8_ldrunpriv:
154154
155// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21FFFC in unpatched output.155// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 21FFFC in unpatched output.
156// CHECK: t3_ffc_ldur:156// CHECK: t3_ffc_ldur:
157// CHECK-NEXT: 21fffc: 9d 01 00 b0 adrp x29, #200704157// CHECK-NEXT: 21fffc: 1d 02 00 b0 adrp x29, #266240
158// CHECK-NEXT: 220000: 42 40 40 b8 ldur w2, [x2, #4]158// CHECK-NEXT: 220000: 42 40 40 b8 ldur w2, [x2, #4]
159// CHECK-FIX: 220004: 10 90 00 14 b #147520159// CHECK-FIX: 220004: 10 90 00 14 b #147520
160// CHECK-NOFIX: 220004: bd 07 40 f9 ldr x29, [x29, #8]160// CHECK-NOFIX: 220004: bd 07 40 f9 ldr x29, [x29, #8]
...@@ -171,7 +171,7 @@ t3_ffc_ldur:...@@ -171,7 +171,7 @@ t3_ffc_ldur:
171171
172// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 221FFC in unpatched output.172// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 221FFC in unpatched output.
173// CHECK: t3_ffc_sturh:173// CHECK: t3_ffc_sturh:
174// CHECK-NEXT: 221ffc: 72 01 00 f0 adrp x18, #192512174// CHECK-NEXT: 221ffc: f2 01 00 f0 adrp x18, #258048
175// CHECK-NEXT: 222000: 43 40 00 78 sturh w3, [x2, #4]175// CHECK-NEXT: 222000: 43 40 00 78 sturh w3, [x2, #4]
176// CHECK-FIX: 222004: 12 88 00 14 b #139336176// CHECK-FIX: 222004: 12 88 00 14 b #139336
177// CHECK-NOFIX: 222004: 41 0a 40 f9 ldr x1, [x18, #16]177// CHECK-NOFIX: 222004: 41 0a 40 f9 ldr x1, [x18, #16]
...@@ -189,7 +189,7 @@ t3_ffc_sturh:...@@ -189,7 +189,7 @@ t3_ffc_sturh:
189189
190// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 223FF8 in unpatched output.190// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 223FF8 in unpatched output.
191// CHECK: t3_ff8_literal:191// CHECK: t3_ff8_literal:
192// CHECK-NEXT: 223ff8: 72 01 00 b0 adrp x18, #184320192// CHECK-NEXT: 223ff8: f2 01 00 b0 adrp x18, #249856
193// CHECK-NEXT: 223ffc: e3 ff ff 58 ldr x3, #-4193// CHECK-NEXT: 223ffc: e3 ff ff 58 ldr x3, #-4
194// CHECK-FIX: 224000: 15 80 00 14 b #131156194// CHECK-FIX: 224000: 15 80 00 14 b #131156
195// CHECK-NOFIX: 224000: 52 02 40 f9 ldr x18, [x18]195// CHECK-NOFIX: 224000: 52 02 40 f9 ldr x18, [x18]
...@@ -207,7 +207,7 @@ t3_ff8_literal:...@@ -207,7 +207,7 @@ t3_ff8_literal:
207207
208// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 225FFC in unpatched output.208// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 225FFC in unpatched output.
209// CHECK: t3_ffc_register:209// CHECK: t3_ffc_register:
210// CHECK-NEXT: 225ffc: 4f 01 00 f0 adrp x15, #176128210// CHECK-NEXT: 225ffc: cf 01 00 f0 adrp x15, #241664
211// CHECK-NEXT: 226000: 43 68 61 f8 ldr x3, [x2, x1]211// CHECK-NEXT: 226000: 43 68 61 f8 ldr x3, [x2, x1]
212// CHECK-FIX: 226004: 16 78 00 14 b #122968212// CHECK-FIX: 226004: 16 78 00 14 b #122968
213// CHECK-NOFIX: 226004: ea 05 40 f9 ldr x10, [x15, #8]213// CHECK-NOFIX: 226004: ea 05 40 f9 ldr x10, [x15, #8]
...@@ -225,7 +225,7 @@ t3_ffc_register:...@@ -225,7 +225,7 @@ t3_ffc_register:
225225
226// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 227FF8 in unpatched output.226// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 227FF8 in unpatched output.
227// CHECK: t3_ff8_stp:227// CHECK: t3_ff8_stp:
228// CHECK-NEXT: 227ff8: 50 01 00 b0 adrp x16, #167936228// CHECK-NEXT: 227ff8: d0 01 00 b0 adrp x16, #233472
229// CHECK-NEXT: 227ffc: 61 08 00 a9 stp x1, x2, [x3]229// CHECK-NEXT: 227ffc: 61 08 00 a9 stp x1, x2, [x3]
230// CHECK-FIX: 228000: 19 70 00 14 b #114788230// CHECK-FIX: 228000: 19 70 00 14 b #114788
231// CHECK-NOFIX: 228000: 0d 0a 40 f9 ldr x13, [x16, #16]231// CHECK-NOFIX: 228000: 0d 0a 40 f9 ldr x13, [x16, #16]
...@@ -243,7 +243,7 @@ t3_ff8_stp:...@@ -243,7 +243,7 @@ t3_ff8_stp:
243243
244// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 229FFC in unpatched output.244// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 229FFC in unpatched output.
245// CHECK: t3_ffc_stnp:245// CHECK: t3_ffc_stnp:
246// CHECK-NEXT: 229ffc: 27 01 00 f0 adrp x7, #159744246// CHECK-NEXT: 229ffc: a7 01 00 f0 adrp x7, #225280
247// CHECK-NEXT: 22a000: 61 08 00 a8 stnp x1, x2, [x3]247// CHECK-NEXT: 22a000: 61 08 00 a8 stnp x1, x2, [x3]
248// CHECK-FIX: 22a004: 1a 68 00 14 b #106600248// CHECK-FIX: 22a004: 1a 68 00 14 b #106600
249// CHECK-NOFIX: 22a004: e9 00 40 f9 ldr x9, [x7]249// CHECK-NOFIX: 22a004: e9 00 40 f9 ldr x9, [x7]
...@@ -261,7 +261,7 @@ t3_ffc_stnp:...@@ -261,7 +261,7 @@ t3_ffc_stnp:
261261
262// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 22BFFC in unpatched output.262// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 22BFFC in unpatched output.
263// CHECK: t3_ffc_st1singlepost:263// CHECK: t3_ffc_st1singlepost:
264// CHECK-NEXT: 22bffc: 37 01 00 b0 adrp x23, #151552264// CHECK-NEXT: 22bffc: b7 01 00 b0 adrp x23, #217088
265// CHECK-NEXT: 22c000: 20 04 82 0d st1 { v0.b }[1], [x1], x2265// CHECK-NEXT: 22c000: 20 04 82 0d st1 { v0.b }[1], [x1], x2
266// CHECK-FIX: 22c004: 1c 60 00 14 b #98416266// CHECK-FIX: 22c004: 1c 60 00 14 b #98416
267// CHECK-NOFIX: 22c004: f6 06 40 f9 ldr x22, [x23, #8]267// CHECK-NOFIX: 22c004: f6 06 40 f9 ldr x22, [x23, #8]
...@@ -279,7 +279,7 @@ t3_ffc_st1singlepost:...@@ -279,7 +279,7 @@ t3_ffc_st1singlepost:
279279
280// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 22DFF8 in unpatched output.280// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 22DFF8 in unpatched output.
281// CHECK: t3_ff8_st1multiple:281// CHECK: t3_ff8_st1multiple:
282// CHECK-NEXT: 22dff8: 17 01 00 f0 adrp x23, #143360282// CHECK-NEXT: 22dff8: 97 01 00 f0 adrp x23, #208896
283// CHECK-NEXT: 22dffc: 20 a0 00 4c st1 { v0.16b, v1.16b }, [x1]283// CHECK-NEXT: 22dffc: 20 a0 00 4c st1 { v0.16b, v1.16b }, [x1]
284// CHECK-FIX: 22e000: 1f 58 00 14 b #90236284// CHECK-FIX: 22e000: 1f 58 00 14 b #90236
285// CHECK-NOFIX: 22e000: f8 0a 40 f9 ldr x24, [x23, #16]285// CHECK-NOFIX: 22e000: f8 0a 40 f9 ldr x24, [x23, #16]
...@@ -297,7 +297,7 @@ t3_ff8_st1multiple:...@@ -297,7 +297,7 @@ t3_ff8_st1multiple:
297297
298// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 22FFF8 in unpatched output.298// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 22FFF8 in unpatched output.
299// CHECK: t4_ff8_ldr:299// CHECK: t4_ff8_ldr:
300// CHECK-NEXT: 22fff8: 00 01 00 b0 adrp x0, #135168300// CHECK-NEXT: 22fff8: 80 01 00 b0 adrp x0, #200704
301// CHECK-NEXT: 22fffc: 21 00 40 f9 ldr x1, [x1]301// CHECK-NEXT: 22fffc: 21 00 40 f9 ldr x1, [x1]
302// CHECK-NEXT: 230000: 42 00 00 8b add x2, x2, x0302// CHECK-NEXT: 230000: 42 00 00 8b add x2, x2, x0
303// CHECK-FIX: 230004: 20 50 00 14 b #82048303// CHECK-FIX: 230004: 20 50 00 14 b #82048
...@@ -317,7 +317,7 @@ t4_ff8_ldr:...@@ -317,7 +317,7 @@ t4_ff8_ldr:
317317
318// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 231FFC in unpatched output.318// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 231FFC in unpatched output.
319// CHECK: t4_ffc_str:319// CHECK: t4_ffc_str:
320// CHECK-NEXT: 231ffc: fc 00 00 f0 adrp x28, #126976320// CHECK-NEXT: 231ffc: 7c 01 00 f0 adrp x28, #192512
321// CHECK-NEXT: 232000: 42 00 00 f9 str x2, [x2]321// CHECK-NEXT: 232000: 42 00 00 f9 str x2, [x2]
322// CHECK-NEXT: 232004: 20 00 02 cb sub x0, x1, x2322// CHECK-NEXT: 232004: 20 00 02 cb sub x0, x1, x2
323// CHECK-FIX: 232008: 21 48 00 14 b #73860323// CHECK-FIX: 232008: 21 48 00 14 b #73860
...@@ -337,7 +337,7 @@ t4_ffc_str:...@@ -337,7 +337,7 @@ t4_ffc_str:
337337
338// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 233FF8 in unpatched output.338// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 233FF8 in unpatched output.
339// CHECK: t4_ff8_stp:339// CHECK: t4_ff8_stp:
340// CHECK-NEXT: 233ff8: f0 00 00 b0 adrp x16, #118784340// CHECK-NEXT: 233ff8: 70 01 00 b0 adrp x16, #184320
341// CHECK-NEXT: 233ffc: 61 08 00 a9 stp x1, x2, [x3]341// CHECK-NEXT: 233ffc: 61 08 00 a9 stp x1, x2, [x3]
342// CHECK-NEXT: 234000: 03 7e 10 9b mul x3, x16, x16342// CHECK-NEXT: 234000: 03 7e 10 9b mul x3, x16, x16
343// CHECK-FIX: 234004: 24 40 00 14 b #65680343// CHECK-FIX: 234004: 24 40 00 14 b #65680
...@@ -357,7 +357,7 @@ t4_ff8_stp:...@@ -357,7 +357,7 @@ t4_ff8_stp:
357357
358// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 235FF8 in unpatched output.358// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 235FF8 in unpatched output.
359// CHECK: t4_ff8_stppre:359// CHECK: t4_ff8_stppre:
360// CHECK-NEXT: 235ff8: d0 00 00 f0 adrp x16, #110592360// CHECK-NEXT: 235ff8: 50 01 00 f0 adrp x16, #176128
361// CHECK-NEXT: 235ffc: 61 08 81 a9 stp x1, x2, [x3, #16]!361// CHECK-NEXT: 235ffc: 61 08 81 a9 stp x1, x2, [x3, #16]!
362// CHECK-NEXT: 236000: 03 7e 10 9b mul x3, x16, x16362// CHECK-NEXT: 236000: 03 7e 10 9b mul x3, x16, x16
363// CHECK-FIX: 236004: 26 38 00 14 b #57496363// CHECK-FIX: 236004: 26 38 00 14 b #57496
...@@ -377,7 +377,7 @@ t4_ff8_stppre:...@@ -377,7 +377,7 @@ t4_ff8_stppre:
377377
378// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 237FF8 in unpatched output.378// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 237FF8 in unpatched output.
379// CHECK: t4_ff8_stppost:379// CHECK: t4_ff8_stppost:
380// CHECK-NEXT: 237ff8: d0 00 00 b0 adrp x16, #102400380// CHECK-NEXT: 237ff8: 50 01 00 b0 adrp x16, #167936
381// CHECK-NEXT: 237ffc: 61 08 81 a8 stp x1, x2, [x3], #16381// CHECK-NEXT: 237ffc: 61 08 81 a8 stp x1, x2, [x3], #16
382// CHECK-NEXT: 238000: 03 7e 10 9b mul x3, x16, x16382// CHECK-NEXT: 238000: 03 7e 10 9b mul x3, x16, x16
383// CHECK-FIX: 238004: 28 30 00 14 b #49312383// CHECK-FIX: 238004: 28 30 00 14 b #49312
...@@ -397,7 +397,7 @@ t4_ff8_stppost:...@@ -397,7 +397,7 @@ t4_ff8_stppost:
397397
398// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 239FFC in unpatched output.398// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 239FFC in unpatched output.
399// CHECK: t4_ffc_stpsimd:399// CHECK: t4_ffc_stpsimd:
400// CHECK-NEXT: 239ffc: b0 00 00 f0 adrp x16, #94208400// CHECK-NEXT: 239ffc: 30 01 00 f0 adrp x16, #159744
401// CHECK-NEXT: 23a000: 61 08 00 ad stp q1, q2, [x3]401// CHECK-NEXT: 23a000: 61 08 00 ad stp q1, q2, [x3]
402// CHECK-NEXT: 23a004: 03 7e 10 9b mul x3, x16, x16402// CHECK-NEXT: 23a004: 03 7e 10 9b mul x3, x16, x16
403// CHECK-FIX: 23a008: 29 28 00 14 b #41124403// CHECK-FIX: 23a008: 29 28 00 14 b #41124
...@@ -417,7 +417,7 @@ t4_ffc_stpsimd:...@@ -417,7 +417,7 @@ t4_ffc_stpsimd:
417417
418// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23BFFC in unpatched output.418// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23BFFC in unpatched output.
419// CHECK: t4_ffc_stnp:419// CHECK: t4_ffc_stnp:
420// CHECK-NEXT: 23bffc: a7 00 00 b0 adrp x7, #86016420// CHECK-NEXT: 23bffc: 27 01 00 b0 adrp x7, #151552
421// CHECK-NEXT: 23c000: 61 08 00 a8 stnp x1, x2, [x3]421// CHECK-NEXT: 23c000: 61 08 00 a8 stnp x1, x2, [x3]
422// CHECK-NEXT: 23c004: 1f 20 03 d5 nop422// CHECK-NEXT: 23c004: 1f 20 03 d5 nop
423// CHECK-FIX: 23c008: 2b 20 00 14 b #32940423// CHECK-FIX: 23c008: 2b 20 00 14 b #32940
...@@ -437,7 +437,7 @@ t4_ffc_stnp:...@@ -437,7 +437,7 @@ t4_ffc_stnp:
437437
438// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23DFFC in unpatched output.438// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23DFFC in unpatched output.
439// CHECK: t4_ffc_st1:439// CHECK: t4_ffc_st1:
440// CHECK-NEXT: 23dffc: 98 00 00 f0 adrp x24, #77824440// CHECK-NEXT: 23dffc: 18 01 00 f0 adrp x24, #143360
441// CHECK-NEXT: 23e000: 20 80 00 4d st1 { v0.s }[2], [x1]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]442// CHECK-NEXT: 23e004: f6 06 40 f9 ldr x22, [x23, #8]
443// CHECK-FIX: 23e008: 2d 18 00 14 b #24756443// CHECK-FIX: 23e008: 2d 18 00 14 b #24756
...@@ -457,7 +457,7 @@ t4_ffc_st1:...@@ -457,7 +457,7 @@ t4_ffc_st1:
457457
458// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23FFF8 in unpatched output.458// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 23FFF8 in unpatched output.
459// CHECK: t3_ff8_ldr_once:459// CHECK: t3_ff8_ldr_once:
460// CHECK-NEXT: 23fff8: 80 00 00 b0 adrp x0, #69632460// CHECK-NEXT: 23fff8: 00 01 00 b0 adrp x0, #135168
461// CHECK-NEXT: 23fffc: 20 70 82 4c st1 { v0.16b }, [x1], x2461// CHECK-NEXT: 23fffc: 20 70 82 4c st1 { v0.16b }, [x1], x2
462// CHECK-FIX: 240000: 31 10 00 14 b #16580462// CHECK-FIX: 240000: 31 10 00 14 b #16580
463// CHECK-NOFIX: 240000: 01 08 40 f9 ldr x1, [x0, #16]463// CHECK-NOFIX: 240000: 01 08 40 f9 ldr x1, [x0, #16]
...@@ -477,7 +477,7 @@ t3_ff8_ldr_once:...@@ -477,7 +477,7 @@ t3_ff8_ldr_once:
477477
478// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 241FF8 in unpatched output.478// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 241FF8 in unpatched output.
479// CHECK: t3_ff8_ldxr:479// CHECK: t3_ff8_ldxr:
480// CHECK-NEXT: 241ff8: 60 00 00 f0 adrp x0, #61440480// CHECK-NEXT: 241ff8: e0 00 00 f0 adrp x0, #126976
481// CHECK-NEXT: 241ffc: 03 7c 5f c8 ldxr x3, [x0]481// CHECK-NEXT: 241ffc: 03 7c 5f c8 ldxr x3, [x0]
482// CHECK-FIX: 242000: 33 08 00 14 b #8396482// CHECK-FIX: 242000: 33 08 00 14 b #8396
483// CHECK-NOFIX: 242000: 01 08 40 f9 ldr x1, [x0, #16]483// CHECK-NOFIX: 242000: 01 08 40 f9 ldr x1, [x0, #16]
...@@ -497,7 +497,7 @@ t3_ff8_ldxr:...@@ -497,7 +497,7 @@ t3_ff8_ldxr:
497497
498// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 243FF8 in unpatched output.498// CHECK-PRINT: detected cortex-a53-843419 erratum sequence starting at 243FF8 in unpatched output.
499// CHECK: t3_ff8_stxr:499// CHECK: t3_ff8_stxr:
500// CHECK-NEXT: 243ff8: 60 00 00 b0 adrp x0, #53248500// CHECK-NEXT: 243ff8: e0 00 00 b0 adrp x0, #118784
501// CHECK-NEXT: 243ffc: 03 7c 04 c8 stxr w4, x3, [x0]501// CHECK-NEXT: 243ffc: 03 7c 04 c8 stxr w4, x3, [x0]
502// CHECK-FIX: 244000: 35 00 00 14 b #212502// CHECK-FIX: 244000: 35 00 00 14 b #212
503// CHECK-NOFIX: 244000: 01 08 40 f9 ldr x1, [x0, #16]503// CHECK-NOFIX: 244000: 01 08 40 f9 ldr x1, [x0, #16]
deps/lld/test/ELF/aarch64-cortex-a53-843419-thunk.s+1-1
...@@ -44,7 +44,7 @@ t3_ff8_ldr:...@@ -44,7 +44,7 @@ t3_ff8_ldr:
44// CHECK-NEXT: 11004: 02 00 00 14 b #844// CHECK-NEXT: 11004: 02 00 00 14 b #8
45// CHECK-NEXT: 11008: c0 03 5f d6 ret45// CHECK-NEXT: 11008: c0 03 5f d6 ret
46// CHECK: __CortexA53843419_11004:46// CHECK: __CortexA53843419_11004:
47// CHECK-NEXT: 1100c: 00 08 40 f9 ldr x0, [x0, #16]47// CHECK-NEXT: 1100c: 00 04 40 f9 ldr x0, [x0, #8]
48// CHECK-NEXT: 11010: fe ff ff 17 b #-848// CHECK-NEXT: 11010: fe ff ff 17 b #-8
4949
50 .section .text.04, "ax", %progbits50 .section .text.04, "ax", %progbits
deps/lld/test/ELF/aarch64-cortex-a53-843419-tlsrelax.s+2-2
...@@ -26,9 +26,9 @@ _start:...@@ -26,9 +26,9 @@ _start:
26// CHECK: _start:26// CHECK: _start:
27// CHECK-NEXT: 210ff8: 41 d0 3b d5 mrs x1, TPIDR_EL027// CHECK-NEXT: 210ff8: 41 d0 3b d5 mrs x1, TPIDR_EL0
28// CHECK-NEXT: 210ffc: 00 00 a0 d2 movz x0, #0, lsl #1628// CHECK-NEXT: 210ffc: 00 00 a0 d2 movz x0, #0, lsl #16
29// CHECK-NEXT: 211000: 01 08 80 f2 movk x1, #6429// CHECK-NEXT: 211000: 01 02 80 f2 movk x1, #16
30// CHECK-NEXT: 211004: 00 00 a0 d2 movz x0, #0, lsl #1630// CHECK-NEXT: 211004: 00 00 a0 d2 movz x0, #0, lsl #16
31// CHECK-NEXT: 211008: 01 08 80 f2 movk x1, #6431// CHECK-NEXT: 211008: 01 02 80 f2 movk x1, #16
32// CHECK-NEXT: 21100c: c0 03 5f d6 ret32// CHECK-NEXT: 21100c: c0 03 5f d6 ret
3333
34 .type v,@object34 .type v,@object
deps/lld/test/ELF/aarch64-feature-bti.s created+218
...@@ -0,0 +1,218 @@
1# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
3# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-bti1.s -o %t1.o
4# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o
5# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-bti.s -o %t3.o
6# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o %tno.o
7
8## We do not add BTI support when the inputs don't have the .note.gnu.property
9## field.
10
11# RUN: ld.lld %tno.o %t3.o --shared -o %tno.so
12# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %tno.so | FileCheck --check-prefix=NOBTI %s
13# RUN: llvm-readelf -x .got.plt %tno.so | FileCheck --check-prefix SOGOTPLT %s
14# RUN: llvm-readelf --dynamic-table %tno.so | FileCheck --check-prefix NOBTIDYN %s
15
16# NOBTIDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT)
17# NOBTIDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT)
18
19# NOBTI: 0000000000010000 func2:
20# NOBTI-NEXT: 10000: bl #48 <func3@plt>
21# NOBTI-NEXT: 10004: ret
22# NOBTI: Disassembly of section .plt:
23# NOBTI: 0000000000010010 .plt:
24# NOBTI-NEXT: 10010: stp x16, x30, [sp, #-16]!
25# NOBTI-NEXT: 10014: adrp x16, #131072
26# NOBTI-NEXT: 10018: ldr x17, [x16, #16]
27# NOBTI-NEXT: 1001c: add x16, x16, #16
28# NOBTI-NEXT: 10020: br x17
29# NOBTI-NEXT: 10024: nop
30# NOBTI-NEXT: 10028: nop
31# NOBTI-NEXT: 1002c: nop
32# NOBTI: 0000000000010030 func3@plt:
33# NOBTI-NEXT: 10030: adrp x16, #131072
34# NOBTI-NEXT: 10034: ldr x17, [x16, #24]
35# NOBTI-NEXT: 10038: add x16, x16, #24
36# NOBTI-NEXT: 1003c: br x17
37
38## Expect a bti c at the start of plt[0], the plt entries do not need bti c as
39## their address doesn't escape the shared object, so they can't be indirectly
40## called. Expect no other difference.
41
42# RUN: ld.lld %t1.o %t3.o --shared -o %t.so
43# RUN: llvm-readelf -n %t.so | FileCheck --check-prefix BTIPROP %s
44# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %t.so | FileCheck --check-prefix BTISO %s
45# RUN: llvm-readelf -x .got.plt %t.so | FileCheck --check-prefix SOGOTPLT %s
46# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix BTIDYN %s
47
48# BTIPROP: Properties: aarch64 feature: BTI
49
50# BTIDYN: 0x0000000070000001 (AARCH64_BTI_PLT)
51# BTIDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT)
52
53# BTISO: 0000000000010000 func2:
54# BTISO-NEXT: 10000: bl #48 <func3@plt>
55# BTISO-NEXT: 10004: ret
56# BTISO: Disassembly of section .plt:
57# BTISO: 0000000000010010 .plt:
58# BTISO-NEXT: 10010: bti c
59# BTISO-NEXT: 10014: stp x16, x30, [sp, #-16]!
60# BTISO-NEXT: 10018: adrp x16, #131072
61# BTISO-NEXT: 1001c: ldr x17, [x16, #16]
62# BTISO-NEXT: 10020: add x16, x16, #16
63# BTISO-NEXT: 10024: br x17
64# BTISO-NEXT: 10028: nop
65# BTISO-NEXT: 1002c: nop
66# BTISO: 0000000000010030 func3@plt:
67# BTISO-NEXT: 10030: adrp x16, #131072
68# BTISO-NEXT: 10034: ldr x17, [x16, #24]
69# BTISO-NEXT: 10038: add x16, x16, #24
70# BTISO-NEXT: 1003c: br x17
71
72## The .got.plt should be identical between the BTI and no BTI DSO PLT.
73# SOGOTPLT: Hex dump of section '.got.plt'
74# SOGOTPLT-NEXT: 0x00030000 00000000 00000000 00000000 00000000
75# SOGOTPLT-NEXT: 0x00030010 00000000 00000000 10000100 00000000
76
77## Build an executable with all relocatable inputs having the BTI
78## .note.gnu.property. We expect a bti c in front of all PLT entries as the
79## address of a PLT entry can escape an executable.
80
81# RUN: ld.lld %t2.o --shared -o %t2.so
82
83# RUN: ld.lld %t.o %t.so %t2.so -o %t.exe
84# RUN: llvm-readelf --dynamic-table -n %t.exe | FileCheck --check-prefix=BTIPROP %s
85# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %t.exe | FileCheck --check-prefix=EXECBTI %s
86
87# EXECBTI: Disassembly of section .text:
88# EXECBTI: 0000000000210000 func1:
89# EXECBTI-NEXT: 210000: bl #48 <func2@plt>
90# EXECBTI-NEXT: 210004: ret
91# EXECBTI: Disassembly of section .plt:
92# EXECBTI: 0000000000210010 .plt:
93# EXECBTI-NEXT: 210010: bti c
94# EXECBTI-NEXT: 210014: stp x16, x30, [sp, #-16]!
95# EXECBTI-NEXT: 210018: adrp x16, #131072
96# EXECBTI-NEXT: 21001c: ldr x17, [x16, #16]
97# EXECBTI-NEXT: 210020: add x16, x16, #16
98# EXECBTI-NEXT: 210024: br x17
99# EXECBTI-NEXT: 210028: nop
100# EXECBTI-NEXT: 21002c: nop
101# EXECBTI: 0000000000210030 func2@plt:
102# EXECBTI-NEXT: 210030: bti c
103# EXECBTI-NEXT: 210034: adrp x16, #131072
104# EXECBTI-NEXT: 210038: ldr x17, [x16, #24]
105# EXECBTI-NEXT: 21003c: add x16, x16, #24
106# EXECBTI-NEXT: 210040: br x17
107# EXECBTI-NEXT: 210044: nop
108
109## We expect the same for PIE, as the address of an ifunc can escape
110# RUN: ld.lld --pie %t.o %t.so %t2.so -o %tpie.exe
111# RUN: llvm-readelf -n %tpie.exe | FileCheck --check-prefix=BTIPROP %s
112# RUN: llvm-readelf --dynamic-table -n %tpie.exe | FileCheck --check-prefix=BTIPROP %s
113# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %tpie.exe | FileCheck --check-prefix=PIE %s
114
115# PIE: Disassembly of section .text:
116# PIE: 0000000000010000 func1:
117# PIE-NEXT: 10000: bl #48 <func2@plt>
118# PIE-NEXT: 10004: ret
119# PIE: Disassembly of section .plt:
120# PIE: 0000000000010010 .plt:
121# PIE-NEXT: 10010: bti c
122# PIE-NEXT: 10014: stp x16, x30, [sp, #-16]!
123# PIE-NEXT: 10018: adrp x16, #131072
124# PIE-NEXT: 1001c: ldr x17, [x16, #16]
125# PIE-NEXT: 10020: add x16, x16, #16
126# PIE-NEXT: 10024: br x17
127# PIE-NEXT: 10028: nop
128# PIE-NEXT: 1002c: nop
129# PIE: 0000000000010030 func2@plt:
130# PIE-NEXT: 10030: bti c
131# PIE-NEXT: 10034: adrp x16, #131072
132# PIE-NEXT: 10038: ldr x17, [x16, #24]
133# PIE-NEXT: 1003c: add x16, x16, #24
134# PIE-NEXT: 10040: br x17
135# PIE-NEXT: 10044: nop
136
137## Build and executable with not all relocatable inputs having the BTI
138## .note.property, expect no bti c and no .note.gnu.property entry
139
140# RUN: ld.lld %t.o %t2.o %t.so -o %tnobti.exe
141# RUN: llvm-readelf --dynamic-table %tnobti.exe | FileCheck --check-prefix NOBTIDYN %s
142# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %tnobti.exe | FileCheck --check-prefix=NOEX %s
143
144# NOEX: Disassembly of section .text:
145# NOEX: 0000000000210000 func1:
146# NOEX-NEXT: 210000: bl #48 <func2@plt>
147# NOEX-NEXT: 210004: ret
148# NOEX: 0000000000210008 func3:
149# NOEX-NEXT: 210008: ret
150# NOEX: Disassembly of section .plt:
151# NOEX: 0000000000210010 .plt:
152# NOEX-NEXT: 210010: stp x16, x30, [sp, #-16]!
153# NOEX-NEXT: 210014: adrp x16, #131072
154# NOEX-NEXT: 210018: ldr x17, [x16, #16]
155# NOEX-NEXT: 21001c: add x16, x16, #16
156# NOEX-NEXT: 210020: br x17
157# NOEX-NEXT: 210024: nop
158# NOEX-NEXT: 210028: nop
159# NOEX-NEXT: 21002c: nop
160# NOEX: 0000000000210030 func2@plt:
161# NOEX-NEXT: 210030: adrp x16, #131072
162# NOEX-NEXT: 210034: ldr x17, [x16, #24]
163# NOEX-NEXT: 210038: add x16, x16, #24
164# NOEX-NEXT: 21003c: br x17
165
166## Force BTI entries with the --force-bti command line option. Expect a warning
167## from the file without the .note.gnu.property.
168
169# RUN: ld.lld %t.o %t2.o --force-bti %t.so -o %tforcebti.exe 2>&1 | FileCheck --check-prefix=FORCE-WARN %s
170
171# FORCE-WARN: aarch64-feature-bti.s.tmp2.o: --force-bti: file does not have BTI property
172
173
174# RUN: llvm-readelf -n %tforcebti.exe | FileCheck --check-prefix=BTIPROP %s
175# RUN: llvm-readelf --dynamic-table %tforcebti.exe | FileCheck --check-prefix BTIDYN %s
176# RUN: llvm-objdump -d -mattr=+bti --no-show-raw-insn %tforcebti.exe | FileCheck --check-prefix=FORCE %s
177
178# FORCE: Disassembly of section .text:
179# FORCE: 0000000000210000 func1:
180# FORCE-NEXT: 210000: bl #48 <func2@plt>
181# FORCE-NEXT: 210004: ret
182# FORCE: 0000000000210008 func3:
183# FORCE-NEXT: 210008: ret
184# FORCE: Disassembly of section .plt:
185# FORCE: 0000000000210010 .plt:
186# FORCE-NEXT: 210010: bti c
187# FORCE-NEXT: 210014: stp x16, x30, [sp, #-16]!
188# FORCE-NEXT: 210018: adrp x16, #131072
189# FORCE-NEXT: 21001c: ldr x17, [x16, #16]
190# FORCE-NEXT: 210020: add x16, x16, #16
191# FORCE-NEXT: 210024: br x17
192# FORCE-NEXT: 210028: nop
193# FORCE-NEXT: 21002c: nop
194# FORCE: 0000000000210030 func2@plt:
195# FORCE-NEXT: 210030: bti c
196# FORCE-NEXT: 210034: adrp x16, #131072
197# FORCE-NEXT: 210038: ldr x17, [x16, #24]
198# FORCE-NEXT: 21003c: add x16, x16, #24
199# FORCE-NEXT: 210040: br x17
200# FORCE-NEXT: 210044: nop
201
202.section ".note.gnu.property", "a"
203.long 4
204.long 0x10
205.long 0x5
206.asciz "GNU"
207
208.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
209.long 4
210.long 1 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
211.long 0
212
213.text
214.globl _start
215.type func1,%function
216func1:
217 bl func2
218 ret
deps/lld/test/ELF/aarch64-feature-btipac.s created+142
...@@ -0,0 +1,142 @@
1# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
3# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-btipac1.s -o %t1.o
4# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t3.o
5# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-btipac.s -o %t3btipac.o
6
7## Build shared library with all inputs having BTI and PAC, expect PLT
8## entries supporting both PAC and BTI. For a shared library this means:
9## PLT[0] has bti c at start
10## PLT[n] has autia1716 before br x17
11
12# RUN: ld.lld %t1.o %t3btipac.o --shared -o %t.so
13# RUN: llvm-readelf -n %t.so | FileCheck --check-prefix BTIPACPROP %s
14# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.so | FileCheck --check-prefix BTIPACSO %s
15# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix BTIPACDYN %s
16
17# BTIPACSO: Disassembly of section .text:
18# BTIPACSO: 0000000000010000 func2:
19# BTIPACSO-NEXT: 10000: bl #48 <func3@plt>
20# BTIPACSO-NEXT: 10004: ret
21# BTIPACSO: 0000000000010008 func3:
22# BTIPACSO-NEXT: 10008: ret
23# BTIPACSO: Disassembly of section .plt:
24# BTIPACSO: 0000000000010010 .plt:
25# BTIPACSO-NEXT: 10010: bti c
26# BTIPACSO-NEXT: 10014: stp x16, x30, [sp, #-16]!
27# BTIPACSO-NEXT: 10018: adrp x16, #131072
28# BTIPACSO-NEXT: 1001c: ldr x17, [x16, #16]
29# BTIPACSO-NEXT: 10020: add x16, x16, #16
30# BTIPACSO-NEXT: 10024: br x17
31# BTIPACSO-NEXT: 10028: nop
32# BTIPACSO-NEXT: 1002c: nop
33# BTIPACSO: 0000000000010030 func3@plt:
34# BTIPACSO-NEXT: 10030: adrp x16, #131072
35# BTIPACSO-NEXT: 10034: ldr x17, [x16, #24]
36# BTIPACSO-NEXT: 10038: add x16, x16, #24
37# BTIPACSO-NEXT: 1003c: autia1716
38# BTIPACSO-NEXT: 10040: br x17
39# BTIPACSO-NEXT: 10044: nop
40
41# BTIPACPROP: Properties: aarch64 feature: BTI, PAC
42
43# BTIPACDYN: 0x0000000070000001 (AARCH64_BTI_PLT)
44# BTIPACDYN: 0x0000000070000003 (AARCH64_PAC_PLT)
45
46## Make an executable with both BTI and PAC properties. Expect:
47## PLT[0] bti c as first instruction
48## PLT[n] bti n as first instruction, autia1716 before br x17
49
50# RUN: ld.lld %t.o %t3btipac.o %t.so -o %t.exe
51# RUN: llvm-readelf -n %t.exe | FileCheck --check-prefix=BTIPACPROP %s
52# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.exe | FileCheck --check-prefix BTIPACEX %s
53# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix BTIPACDYN %s
54
55# BTIPACEX: Disassembly of section .text:
56# BTIPACEX: 0000000000210000 func1:
57# BTIPACEX-NEXT: 210000: bl #48 <func2@plt>
58# BTIPACEX-NEXT: 210004: ret
59# BTIPACEX-NEXT: 210008: ret
60# BTIPACEX: 000000000021000c func3:
61# BTIPACEX-NEXT: 21000c: ret
62# BTIPACEX: Disassembly of section .plt:
63# BTIPACEX: 0000000000210010 .plt:
64# BTIPACEX-NEXT: 210010: bti c
65# BTIPACEX-NEXT: 210014: stp x16, x30, [sp, #-16]!
66# BTIPACEX-NEXT: 210018: adrp x16, #131072
67# BTIPACEX-NEXT: 21001c: ldr x17, [x16, #16]
68# BTIPACEX-NEXT: 210020: add x16, x16, #16
69# BTIPACEX-NEXT: 210024: br x17
70# BTIPACEX-NEXT: 210028: nop
71# BTIPACEX-NEXT: 21002c: nop
72# BTIPACEX: 0000000000210030 func2@plt:
73# BTIPACEX-NEXT: 210030: bti c
74# BTIPACEX-NEXT: 210034: adrp x16, #131072
75# BTIPACEX-NEXT: 210038: ldr x17, [x16, #24]
76# BTIPACEX-NEXT: 21003c: add x16, x16, #24
77# BTIPACEX-NEXT: 210040: autia1716
78# BTIPACEX-NEXT: 210044: br x17
79
80## Check that combinations of BTI+PAC with 0 properties results in standard PLT
81
82# RUN: ld.lld %t.o %t3.o %t.so -o %t.exe
83# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.exe | FileCheck --check-prefix EX %s
84# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix=NODYN %s
85
86# EX: Disassembly of section .text:
87# EX: 0000000000210000 func1:
88# EX-NEXT: 210000: bl #48 <func2@plt>
89# EX-NEXT: 210004: ret
90# EX-NEXT: 210008: ret
91# EX: 000000000021000c func3:
92# EX-NEXT: 21000c: ret
93# EX: Disassembly of section .plt:
94# EX: 0000000000210010 .plt:
95# EX-NEXT: 210010: stp x16, x30, [sp, #-16]!
96# EX-NEXT: 210014: adrp x16, #131072
97# EX-NEXT: 210018: ldr x17, [x16, #16]
98# EX-NEXT: 21001c: add x16, x16, #16
99# EX-NEXT: 210020: br x17
100# EX-NEXT: 210024: nop
101# EX-NEXT: 210028: nop
102# EX-NEXT: 21002c: nop
103# EX: 0000000000210030 func2@plt:
104# EX: 210030: adrp x16, #131072
105# EX-NEXT: 210034: ldr x17, [x16, #24]
106# EX-NEXT: 210038: add x16, x16, #24
107# EX-NEXT: 21003c: br x17
108
109# NODYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT)
110# NODYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT)
111
112## Check that combination of --pac-plt and --force-bti warns for the file that
113## doesn't contain the BTI property, but generates PAC and BTI PLT sequences.
114## The --pac-plt doesn't warn as it is not required for correctness.
115
116# RUN: ld.lld %t.o %t3.o %t.so --pac-plt --force-bti -o %t.exe 2>&1 | FileCheck --check-prefix=FORCE-WARN %s
117
118# FORCE-WARN: aarch64-feature-btipac.s.tmp3.o: --force-bti: file does not have BTI property
119
120# RUN: llvm-readelf -n %t.exe | FileCheck --check-prefix=BTIPACPROP %s
121# RUN: llvm-objdump -d -mattr=+v8.5a --no-show-raw-insn %t.exe | FileCheck --check-prefix BTIPACEX %s
122# RUN: llvm-readelf --dynamic-table %t.exe | FileCheck --check-prefix BTIPACDYN %s
123.section ".note.gnu.property", "a"
124.long 4
125.long 0x10
126.long 0x5
127.asciz "GNU"
128
129.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
130.long 4
131.long 3 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI and PAC
132.long 0
133
134.text
135.globl _start
136.type func1,%function
137func1:
138 bl func2
139 ret
140.globl func3
141.type func3,%function
142 ret
deps/lld/test/ELF/aarch64-feature-pac.s created+129
...@@ -0,0 +1,129 @@
1# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
3# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-pac1.s -o %t1.o
4# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3.s -o %t2.o
5# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func3-pac.s -o %t3.o
6# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %p/Inputs/aarch64-func2.s -o %tno.o
7
8## We do not add PAC support when the inputs don't have the .note.gnu.property
9## field.
10
11# RUN: ld.lld %tno.o %t3.o --shared -o %tno.so
12# RUN: llvm-objdump -d -mattr=+v8.3a --no-show-raw-insn %tno.so | FileCheck --check-prefix=NOPAC %s
13# RUN: llvm-readelf -x .got.plt %tno.so | FileCheck --check-prefix SOGOTPLT %s
14# RUN: llvm-readelf --dynamic-table %tno.so | FileCheck --check-prefix NOPACDYN %s
15
16# NOPAC: 0000000000010000 func2:
17# NOPAC-NEXT: 10000: bl #48 <func3@plt>
18# NOPAC-NEXT: 10004: ret
19# NOPAC: Disassembly of section .plt:
20# NOPAC: 0000000000010010 .plt:
21# NOPAC-NEXT: 10010: stp x16, x30, [sp, #-16]!
22# NOPAC-NEXT: 10014: adrp x16, #131072
23# NOPAC-NEXT: 10018: ldr x17, [x16, #16]
24# NOPAC-NEXT: 1001c: add x16, x16, #16
25# NOPAC-NEXT: 10020: br x17
26# NOPAC-NEXT: 10024: nop
27# NOPAC-NEXT: 10028: nop
28# NOPAC-NEXT: 1002c: nop
29# NOPAC: 0000000000010030 func3@plt:
30# NOPAC-NEXT: 10030: adrp x16, #131072
31# NOPAC-NEXT: 10034: ldr x17, [x16, #24]
32# NOPAC-NEXT: 10038: add x16, x16, #24
33# NOPAC-NEXT: 1003c: br x17
34
35# NOPACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT)
36# NOPACDYN-NOT: 0x0000000070000003 (AARCH64_PAC_PLT)
37
38# RUN: ld.lld %t1.o %t3.o --shared -o %t.so
39# RUN: llvm-readelf -n %t.so | FileCheck --check-prefix PACPROP %s
40# RUN: llvm-objdump -d -mattr=+v8.3a --no-show-raw-insn %t.so | FileCheck --check-prefix PACSO %s
41# RUN: llvm-readelf -x .got.plt %t.so | FileCheck --check-prefix SOGOTPLT %s
42# RUN: llvm-readelf --dynamic-table %t.so | FileCheck --check-prefix PACDYN %s
43
44## PAC has no effect on PLT[0], for PLT[N] autia1716 is used to authenticate
45## the address in x17 (context in x16) before branching to it. The dynamic
46## loader is responsible for calling pacia1716 on the entry.
47# PACSO: 0000000000010000 func2:
48# PACSO-NEXT: 10000: bl #48 <func3@plt>
49# PACSO-NEXT: 10004: ret
50# PACSO: Disassembly of section .plt:
51# PACSO: 0000000000010010 .plt:
52# PACSO-NEXT: 10010: stp x16, x30, [sp, #-16]!
53# PACSO-NEXT: 10014: adrp x16, #131072
54# PACSO-NEXT: 10018: ldr x17, [x16, #16]
55# PACSO-NEXT: 1001c: add x16, x16, #16
56# PACSO-NEXT: 10020: br x17
57# PACSO-NEXT: 10024: nop
58# PACSO-NEXT: 10028: nop
59# PACSO-NEXT: 1002c: nop
60# PACSO: 0000000000010030 func3@plt:
61# PACSO-NEXT: 10030: adrp x16, #131072
62# PACSO-NEXT: 10034: ldr x17, [x16, #24]
63# PACSO-NEXT: 10038: add x16, x16, #24
64# PACSO-NEXT: 1003c: autia1716
65# PACSO-NEXT: 10040: br x17
66# PACSO-NEXT: 10044: nop
67
68# The .got.plt should be identical between the PAC and no PAC DSO PLT.
69# SOGOTPLT: Hex dump of section '.got.plt':
70# SOGOTPLT-NEXT: 0x00030000 00000000 00000000 00000000 00000000
71# SOGOTPLT-NEXT: 0x00030010 00000000 00000000 10000100 00000000
72
73# PACPROP: Properties: aarch64 feature: PAC
74
75# PACDYN-NOT: 0x0000000070000001 (AARCH64_BTI_PLT)
76# PACDYN: 0x0000000070000003 (AARCH64_PAC_PLT)
77
78## Turn on PAC entries with the --pac-plt command line option. There are no
79## warnings in this case as the choice to use PAC in PLT entries is orthogonal
80## to the choice of using PAC in relocatable objects. The presence of the PAC
81## .note.gnu.property is an indication of preference by the relocatable object.
82
83# RUN: ld.lld %t.o %t2.o --pac-plt %t.so -o %tpacplt.exe
84# RUN: llvm-readelf -n %tpacplt.exe | FileCheck --check-prefix=PACPROP %s
85# RUN: llvm-readelf --dynamic-table %tpacplt.exe | FileCheck --check-prefix PACDYN %s
86# RUN: llvm-objdump -d -mattr=+v8.3a --no-show-raw-insn %tpacplt.exe | FileCheck --check-prefix PACPLT %s
87
88# PACPLT: Disassembly of section .text:
89# PACPLT: 0000000000210000 func1:
90# PACPLT-NEXT: 210000: bl #48 <func2@plt>
91# PACPLT-NEXT: 210004: ret
92# PACPLT: 0000000000210008 func3:
93# PACPLT-NEXT: 210008: ret
94# PACPLT: Disassembly of section .plt:
95# PACPLT: 0000000000210010 .plt:
96# PACPLT-NEXT: 210010: stp x16, x30, [sp, #-16]!
97# PACPLT-NEXT: 210014: adrp x16, #131072
98# PACPLT-NEXT: 210018: ldr x17, [x16, #16]
99# PACPLT-NEXT: 21001c: add x16, x16, #16
100# PACPLT-NEXT: 210020: br x17
101# PACPLT-NEXT: 210024: nop
102# PACPLT-NEXT: 210028: nop
103# PACPLT-NEXT: 21002c: nop
104# PACPLT: 0000000000210030 func2@plt:
105# PACPLT-NEXT: 210030: adrp x16, #131072
106# PACPLT-NEXT: 210034: ldr x17, [x16, #24]
107# PACPLT-NEXT: 210038: add x16, x16, #24
108# PACPLT-NEXT: 21003c: autia1716
109# PACPLT-NEXT: 210040: br x17
110# PACPLT-NEXT: 210044: nop
111
112
113.section ".note.gnu.property", "a"
114.long 4
115.long 0x10
116.long 0x5
117.asciz "GNU"
118
119.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
120.long 4
121.long 2 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
122.long 0
123
124.text
125.globl _start
126.type func1,%function
127func1:
128 bl func2
129 ret
deps/lld/test/ELF/aarch64-fpic-adr_prel_pg_hi21.s+2
...@@ -4,8 +4,10 @@...@@ -4,8 +4,10 @@
4// CHECK: relocation R_AARCH64_ADR_PREL_PG_HI21 cannot be used against symbol dat; recompile with -fPIC4// CHECK: relocation R_AARCH64_ADR_PREL_PG_HI21 cannot be used against symbol dat; recompile with -fPIC
5// CHECK: >>> defined in {{.*}}.o5// CHECK: >>> defined in {{.*}}.o
6// CHECK: >>> referenced by {{.*}}.o:(.text+0x0)6// CHECK: >>> referenced by {{.*}}.o:(.text+0x0)
7// CHECK: relocation R_AARCH64_ADR_PREL_PG_HI21_NC cannot be used against symbol dat; recompile with -fPIC
78
8 adrp x0, dat9 adrp x0, dat
10 adrp x0, :pg_hi21_nc:dat
9.data11.data
10.globl dat12.globl dat
11dat:13dat:
deps/lld/test/ELF/aarch64-fpic-got.s+12-4
...@@ -3,14 +3,22 @@...@@ -3,14 +3,22 @@
3# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %s -o %t.o
4# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %p/Inputs/shared.s -o %t-lib.o4# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux %p/Inputs/shared.s -o %t-lib.o
5# RUN: ld.lld -shared %t-lib.o -o %t-lib.so5# RUN: ld.lld -shared %t-lib.o -o %t-lib.so
6
6# RUN: ld.lld %t-lib.so %t.o -o %t.exe7# RUN: ld.lld %t-lib.so %t.o -o %t.exe
7# RUN: llvm-readobj -dyn-relocations %t.exe | FileCheck %s8# RUN: llvm-readobj -r %t.exe | FileCheck --check-prefix=RELOC %s
9# RUN: llvm-objdump -d --no-show-raw-insn %t.exe | FileCheck --check-prefix=DIS %s
810
9## Checks if got access to dynamic objects is done through a got relative11## Checks if got access to dynamic objects is done through a got relative
10## dynamic relocation and not using plt relative (R_AARCH64_JUMP_SLOT).12## dynamic relocation and not using plt relative (R_AARCH64_JUMP_SLOT).
11# CHECK: Dynamic Relocations {13# RELOC: .rela.dyn {
12# CHECK-NEXT: 0x{{[0-9A-F]+}} R_AARCH64_GLOB_DAT bar 0x014# RELOC-NEXT: 0x2200C0 R_AARCH64_GLOB_DAT bar 0x0
13# CHECK-NEXT: }15# RELOC-NEXT: }
16
17## page(0x2200C0) - page(0x210000) = 65536
18## page(0x2200C0) & 0xff8 = 192
19# DIS: _start:
20# DIS-NEXT: 210000: adrp x0, #65536
21# DIS-NEXT: 210004: ldr x0, [x0, #192]
1422
15.globl _start23.globl _start
16_start:24_start:
deps/lld/test/ELF/aarch64-gnu-ifunc-address-pie.s deleted-44
...@@ -1,44 +0,0 @@
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
14myfunc:
15 ret
16
17.text
18.globl main
19.type main,@function
20main:
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+9-11
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: aarch641# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
3# RUN: ld.lld -shared %t.o -o %tout3# RUN: ld.lld -shared %t.o -o %tout
4# RUN: llvm-objdump -D %tout | FileCheck %s4# RUN: llvm-objdump -D --no-show-raw-insn %tout | FileCheck %s
5# RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=CHECK-RELOCS5# RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=CHECK-RELOCS
66
7# Test that when we take the address of a preemptible ifunc in a shared object7# Test that when we take the address of a preemptible ifunc in a shared object
...@@ -21,20 +21,18 @@ main:...@@ -21,20 +21,18 @@ main:
21 ldr x8, [x8, :got_lo12:myfunc]21 ldr x8, [x8, :got_lo12:myfunc]
22 ret22 ret
23# CHECK: 0000000000010004 main:23# CHECK: 0000000000010004 main:
24# x8 = 0x3000024# x8 = 0x20000
25# CHECK-NEXT: 10004: 08 01 00 90 adrp x8, #13107225# CHECK-NEXT: 10004: adrp x8, #65536
26# x8 = 0x300e0 = .got entry for myfunc with R_AARCH64_GLOB_DAT26# x8 = 0x200a0 = .got entry for myfunc with R_AARCH64_GLOB_DAT
27# CHECK-NEXT: 10008: 08 71 40 f9 ldr x8, [x8, #224]27# CHECK-NEXT: 10008: ldr x8, [x8, #160]
28# CHECK-NEXT: 1000c: c0 03 5f d6 ret28# CHECK-NEXT: 1000c: ret
2929
30# CHECK: Disassembly of section .got:30# CHECK: Disassembly of section .got:
31# CHECK-NEXT: 00000000000300e0 .got:31# CHECK-EMPTY:
32# CHECK-NEXT: 00000000000200a0 .got:
3233
33# CHECK-RELOCS: Relocations [34# CHECK-RELOCS: Relocations [
34# CHECK-RELOCS-NEXT: Section {{.*}} .rela.dyn {35# CHECK-RELOCS-NEXT: Section {{.*}} .rela.dyn {
35# CHECK-RELOCS-NEXT: 0x300E0 R_AARCH64_GLOB_DAT myfunc 0x036# CHECK-RELOCS-NEXT: 0x200A0 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: }37# CHECK-RELOCS-NEXT: }
40# CHECK-RELOCS-NEXT: ]38# CHECK-RELOCS-NEXT: ]
deps/lld/test/ELF/aarch64-gnu-ifunc-nonpreemptable.s created+72
...@@ -0,0 +1,72 @@
1# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
3
4# RUN: ld.lld %t.o -o %t
5# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PDE
6# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=PDE-RELOC
7
8# RUN: ld.lld -pie %t.o -o %t
9# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s --check-prefix=PIE
10# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=PIE-RELOC
11
12## When compiling with -fno-PIE or -fPIE, if the ifunc is in the same
13## translation unit as the address taker, the compiler knows that ifunc is not
14## defined in a shared library so it can use a non GOT generating relative reference.
15.text
16.globl myfunc
17.type myfunc,@gnu_indirect_function
18myfunc:
19.globl myfunc_resolver
20.type myfunc_resolver,@function
21myfunc_resolver:
22 ret
23
24.text
25.globl main
26.type main,@function
27main:
28 adrp x8, myfunc
29 add x8, x8, :lo12: myfunc
30 ret
31
32## The address of myfunc is the address of the PLT entry for myfunc.
33# PDE: myfunc_resolver:
34# PDE-NEXT: 210000: ret
35# PDE: main:
36# PDE-NEXT: 210004: adrp x8, #0
37# PDE-NEXT: 210008: add x8, x8, #16
38# PDE-NEXT: 21000c: ret
39# PDE-EMPTY:
40# PDE-NEXT: Disassembly of section .plt:
41# PDE-EMPTY:
42# PDE-NEXT: myfunc:
43## page(.got.plt) - page(0x210010) = 65536
44# PDE-NEXT: 210010: adrp x16, #65536
45# PDE-NEXT: 210014: ldr x17, [x16]
46# PDE-NEXT: 210018: add x16, x16, #0
47# PDE-NEXT: 21001c: br x17
48
49## The adrp to myfunc should generate a PLT entry and a GOT entry with an
50## irelative relocation.
51# PDE-RELOC: .rela.plt {
52# PDE-RELOC-NEXT: 0x220000 R_AARCH64_IRELATIVE - 0x210000
53# PDE-RELOC-NEXT: }
54
55# PIE: myfunc_resolver:
56# PIE-NEXT: 10000: ret
57# PIE: main:
58# PIE-NEXT: 10004: adrp x8, #0
59# PIE-NEXT: 10008: add x8, x8, #16
60# PIE-NEXT: 1000c: ret
61# PIE-EMPTY:
62# PIE-NEXT: Disassembly of section .plt:
63# PIE-EMPTY:
64# PIE-NEXT: myfunc:
65# PIE-NEXT: 10010: adrp x16, #131072
66# PIE-NEXT: 10014: ldr x17, [x16]
67# PIE-NEXT: 10018: add x16, x16, #0
68# PIE-NEXT: 1001c: br x17
69
70# PIE-RELOC: .rela.plt {
71# PIE-RELOC-NEXT: 0x30000 R_AARCH64_IRELATIVE - 0x10000
72# PIE-RELOC-NEXT: }
deps/lld/test/ELF/aarch64-gnu-ifunc-nosym.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: aarch641// REQUIRES: aarch64
2// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
3// RUN: ld.lld -static %t.o -o %tout3// RUN: ld.lld -static %t.o -o %tout
4// RUN: llvm-readobj -symbols %tout | FileCheck %s4// RUN: llvm-readobj --symbols %tout | FileCheck %s
55
6// Check that no __rela_iplt_end/__rela_iplt_start6// Check that no __rela_iplt_end/__rela_iplt_start
7// appear in symtab if there is no references to them.7// appear in symtab if there is no references to them.
deps/lld/test/ELF/aarch64-gnu-ifunc-plt.s+17-14
...@@ -5,24 +5,24 @@...@@ -5,24 +5,24 @@
5// RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout5// RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout
6// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM6// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
7// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT7// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT
8// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s8// RUN: llvm-readobj -r --dynamic-table %tout | FileCheck %s
99
10// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt10// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt
11// CHECK: Relocations [11// CHECK: Relocations [
12// CHECK-NEXT: Section (4) .rela.plt {12// CHECK-NEXT: Section (4) .rela.plt {
13// CHECK: 0x220018 R_AARCH64_JUMP_SLOT bar2 0x013// CHECK: 0x230018 R_AARCH64_JUMP_SLOT bar2 0x0
14// CHECK-NEXT: 0x220020 R_AARCH64_JUMP_SLOT zed2 0x014// CHECK-NEXT: 0x230020 R_AARCH64_JUMP_SLOT zed2 0x0
15// CHECK-NEXT: 0x220028 R_AARCH64_IRELATIVE - 0x21000015// CHECK-NEXT: 0x230028 R_AARCH64_IRELATIVE - 0x210000
16// CHECK-NEXT: 0x220030 R_AARCH64_IRELATIVE - 0x21000416// CHECK-NEXT: 0x230030 R_AARCH64_IRELATIVE - 0x210004
17// CHECK-NEXT: }17// CHECK-NEXT: }
18// CHECK-NEXT: ]18// CHECK-NEXT: ]
1919
20// Check that .got.plt entries point back to PLT header20// Check that .got.plt entries point back to PLT header
21// GOTPLT: Contents of section .got.plt:21// GOTPLT: Contents of section .got.plt:
22// GOTPLT-NEXT: 220000 00000000 00000000 00000000 0000000022// GOTPLT-NEXT: 230000 00000000 00000000 00000000 00000000
23// GOTPLT-NEXT: 220010 00000000 00000000 20002100 0000000023// GOTPLT-NEXT: 230010 00000000 00000000 20002100 00000000
24// GOTPLT-NEXT: 220020 20002100 00000000 20002100 0000000024// GOTPLT-NEXT: 230020 20002100 00000000 20002100 00000000
25// GOTPLT-NEXT: 220030 20002100 0000000025// GOTPLT-NEXT: 230030 20002100 00000000
2626
27// Check that the PLTRELSZ tag includes the IRELATIVE relocations27// Check that the PLTRELSZ tag includes the IRELATIVE relocations
28// CHECK: DynamicSection [28// CHECK: DynamicSection [
...@@ -30,6 +30,7 @@...@@ -30,6 +30,7 @@
3030
31// Check that a PLT header is written and the ifunc entries appear last31// Check that a PLT header is written and the ifunc entries appear last
32// DISASM: Disassembly of section .text:32// DISASM: Disassembly of section .text:
33// DISASM-EMPTY:
33// DISASM-NEXT: foo:34// DISASM-NEXT: foo:
34// DISASM-NEXT: 210000: {{.*}} ret35// DISASM-NEXT: 210000: {{.*}} ret
35// DISASM: bar:36// DISASM: bar:
...@@ -39,10 +40,12 @@...@@ -39,10 +40,12 @@
39// DISASM-NEXT: 21000c: {{.*}} bl #10040// DISASM-NEXT: 21000c: {{.*}} bl #100
40// DISASM-NEXT: 210010: {{.*}} bl #4841// DISASM-NEXT: 210010: {{.*}} bl #48
41// DISASM-NEXT: 210014: {{.*}} bl #6042// DISASM-NEXT: 210014: {{.*}} bl #60
43// DISASM-EMPTY:
42// DISASM-NEXT: Disassembly of section .plt:44// DISASM-NEXT: Disassembly of section .plt:
45// DISASM-EMPTY:
43// DISASM-NEXT: .plt:46// DISASM-NEXT: .plt:
44// DISASM-NEXT: 210020: {{.*}} stp x16, x30, [sp, #-16]!47// DISASM-NEXT: 210020: {{.*}} stp x16, x30, [sp, #-16]!
45// DISASM-NEXT: 210024: {{.*}} adrp x16, #6553648// DISASM-NEXT: 210024: {{.*}} adrp x16, #131072
46// DISASM-NEXT: 210028: {{.*}} ldr x17, [x16, #16]49// DISASM-NEXT: 210028: {{.*}} ldr x17, [x16, #16]
47// DISASM-NEXT: 21002c: {{.*}} add x16, x16, #1650// DISASM-NEXT: 21002c: {{.*}} add x16, x16, #16
48// DISASM-NEXT: 210030: {{.*}} br x1751// DISASM-NEXT: 210030: {{.*}} br x17
...@@ -51,21 +54,21 @@...@@ -51,21 +54,21 @@
51// DISASM-NEXT: 21003c: {{.*}} nop54// DISASM-NEXT: 21003c: {{.*}} nop
52// DISASM-EMPTY:55// DISASM-EMPTY:
53// DISASM-NEXT: bar2@plt:56// DISASM-NEXT: bar2@plt:
54// DISASM-NEXT: 210040: {{.*}} adrp x16, #6553657// DISASM-NEXT: 210040: {{.*}} adrp x16, #131072
55// DISASM-NEXT: 210044: {{.*}} ldr x17, [x16, #24]58// DISASM-NEXT: 210044: {{.*}} ldr x17, [x16, #24]
56// DISASM-NEXT: 210048: {{.*}} add x16, x16, #2459// DISASM-NEXT: 210048: {{.*}} add x16, x16, #24
57// DISASM-NEXT: 21004c: {{.*}} br x1760// DISASM-NEXT: 21004c: {{.*}} br x17
58// DISASM-EMPTY:61// DISASM-EMPTY:
59// DISASM-NEXT: zed2@plt:62// DISASM-NEXT: zed2@plt:
60// DISASM-NEXT: 210050: {{.*}} adrp x16, #6553663// DISASM-NEXT: 210050: {{.*}} adrp x16, #131072
61// DISASM-NEXT: 210054: {{.*}} ldr x17, [x16, #32]64// DISASM-NEXT: 210054: {{.*}} ldr x17, [x16, #32]
62// DISASM-NEXT: 210058: {{.*}} add x16, x16, #3265// DISASM-NEXT: 210058: {{.*}} add x16, x16, #32
63// DISASM-NEXT: 21005c: {{.*}} br x1766// DISASM-NEXT: 21005c: {{.*}} br x17
64// DISASM-NEXT: 210060: {{.*}} adrp x16, #6553667// DISASM-NEXT: 210060: {{.*}} adrp x16, #131072
65// DISASM-NEXT: 210064: {{.*}} ldr x17, [x16, #40]68// DISASM-NEXT: 210064: {{.*}} ldr x17, [x16, #40]
66// DISASM-NEXT: 210068: {{.*}} add x16, x16, #4069// DISASM-NEXT: 210068: {{.*}} add x16, x16, #40
67// DISASM-NEXT: 21006c: {{.*}} br x1770// DISASM-NEXT: 21006c: {{.*}} br x17
68// DISASM-NEXT: 210070: {{.*}} adrp x16, #6553671// DISASM-NEXT: 210070: {{.*}} adrp x16, #131072
69// DISASM-NEXT: 210074: {{.*}} ldr x17, [x16, #48]72// DISASM-NEXT: 210074: {{.*}} ldr x17, [x16, #48]
70// DISASM-NEXT: 210078: {{.*}} add x16, x16, #4873// DISASM-NEXT: 210078: {{.*}} add x16, x16, #48
71// DISASM-NEXT: 21007c: {{.*}} br x1774// DISASM-NEXT: 21007c: {{.*}} br x17
deps/lld/test/ELF/aarch64-gnu-ifunc.s+4-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
3// RUN: ld.lld -static %t.o -o %tout3// RUN: ld.lld -static %t.o -o %tout
4// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM4// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
5// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s5// RUN: llvm-readobj -r --symbols --sections %tout | FileCheck %s
66
7// CHECK: Sections [7// CHECK: Sections [
8// CHECK: Section {8// CHECK: Section {
...@@ -100,6 +100,7 @@...@@ -100,6 +100,7 @@
100// 392 = 0x188100// 392 = 0x188
101101
102// DISASM: Disassembly of section .text:102// DISASM: Disassembly of section .text:
103// DISASM-EMPTY:
103// DISASM-NEXT: foo:104// DISASM-NEXT: foo:
104// DISASM-NEXT: 210000: c0 03 5f d6 ret105// DISASM-NEXT: 210000: c0 03 5f d6 ret
105// DISASM: bar:106// DISASM: bar:
...@@ -109,7 +110,9 @@...@@ -109,7 +110,9 @@
109// DISASM-NEXT: 21000c: 09 00 00 94 bl #36110// DISASM-NEXT: 21000c: 09 00 00 94 bl #36
110// DISASM-NEXT: 210010: 42 60 05 91 add x2, x2, #344111// DISASM-NEXT: 210010: 42 60 05 91 add x2, x2, #344
111// DISASM-NEXT: 210014: 42 20 06 91 add x2, x2, #392112// DISASM-NEXT: 210014: 42 20 06 91 add x2, x2, #392
113// DISASM-EMPTY:
112// DISASM-NEXT: Disassembly of section .plt:114// DISASM-NEXT: Disassembly of section .plt:
115// DISASM-EMPTY:
113// DISASM-NEXT: .plt:116// DISASM-NEXT: .plt:
114// DISASM-NEXT: 210020: 90 00 00 90 adrp x16, #65536117// DISASM-NEXT: 210020: 90 00 00 90 adrp x16, #65536
115// DISASM-NEXT: 210024: 11 02 40 f9 ldr x17, [x16]118// DISASM-NEXT: 210024: 11 02 40 f9 ldr x17, [x16]
deps/lld/test/ELF/aarch64-gnu-ifunc2.s+5-7
...@@ -5,16 +5,18 @@...@@ -5,16 +5,18 @@
5# RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=RELOC5# RUN: llvm-readobj -r %tout | FileCheck %s --check-prefix=RELOC
66
7# CHECK: Disassembly of section .text:7# CHECK: Disassembly of section .text:
8# CHECK-EMPTY:
8# CHECK-NEXT: myfunc:9# CHECK-NEXT: myfunc:
9# CHECK-NEXT: 210000:10# CHECK-NEXT: 210000:
1011
11# CHECK: main:12# CHECK: main:
12# adrp x8, 0x230000, 0x230000 == address in .got13# adrp x8, 0x220000, 0x220000 == address in .got.plt
13# CHECK-NEXT: 210004: {{.*}} adrp x8, #13107214# CHECK-NEXT: 210004: {{.*}} adrp x8, #65536
14# CHECK-NEXT: 210008: {{.*}} ldr x8, [x8]15# CHECK-NEXT: 210008: {{.*}} ldr x8, [x8]
15# CHECK-NEXT: 21000c: {{.*}} ret16# CHECK-NEXT: 21000c: {{.*}} ret
1617
17# CHECK: Disassembly of section .plt:18# CHECK: Disassembly of section .plt:
19# CHECK-EMPTY:
18# CHECK-NEXT: .plt:20# CHECK-NEXT: .plt:
19# adrp x16, 0x220000, 0x220000 == address in .got.plt21# adrp x16, 0x220000, 0x220000 == address in .got.plt
20# CHECK-NEXT: 210010: {{.*}} adrp x16, #6553622# CHECK-NEXT: 210010: {{.*}} adrp x16, #65536
...@@ -23,14 +25,10 @@...@@ -23,14 +25,10 @@
23# CHECK-NEXT: 21001c: {{.*}} br x1725# CHECK-NEXT: 21001c: {{.*}} br x17
2426
25# CHECK: Disassembly of section .got.plt:27# CHECK: Disassembly of section .got.plt:
28# CHECK-EMPTY:
26# CHECK-NEXT: .got.plt:29# CHECK-NEXT: .got.plt:
27# CHECK-NEXT: 220000:30# CHECK-NEXT: 220000:
2831
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 [32# RELOC: Relocations [
35# RELOC-NEXT: Section {{.*}} .rela.plt {33# RELOC-NEXT: Section {{.*}} .rela.plt {
36# RELOC-NEXT: 0x220000 R_AARCH64_IRELATIVE - 0x21000034# RELOC-NEXT: 0x220000 R_AARCH64_IRELATIVE - 0x210000
deps/lld/test/ELF/aarch64-gnu-ifunc3.s deleted-49
...@@ -1,49 +0,0 @@
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
13myfunc:
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-got-reloc.s deleted-30
...@@ -1,30 +0,0 @@
1// REQUIRES: aarch64
2// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
3// RUN: ld.lld %t.o -o %t
4// RUN: llvm-readobj -s --section-data %t | FileCheck %s
5
6// CHECK: Name: .got
7// CHECK-NEXT: Type: SHT_PROGBITS
8// CHECK-NEXT: Flags [
9// CHECK-NEXT: SHF_ALLOC
10// CHECK-NEXT: SHF_WRITE
11// CHECK-NEXT: ]
12// CHECK-NEXT: Address:
13// CHECK-NEXT: Offset:
14// CHECK-NEXT: Size: 8
15// CHECK-NEXT: Link: 0
16// CHECK-NEXT: Info: 0
17// CHECK-NEXT: AddressAlignment: 8
18// CHECK-NEXT: EntrySize: 0
19// CHECK-NEXT: SectionData (
20// CHECK-NEXT: 0000: 00000000 00000000 |........|
21// CHECK-NEXT: )
22
23 .globl _start
24_start:
25 adrp x8, :got:foo
26 ldr x8, [x8, :got_lo12:foo]
27 ldr w0, [x8]
28 ret
29
30 .weak foo
deps/lld/test/ELF/aarch64-got-weak-undef.s created+18
...@@ -0,0 +1,18 @@
1// REQUIRES: aarch64
2// RUN: llvm-mc -filetype=obj -triple=aarch64-none-freebsd %s -o %t.o
3// RUN: ld.lld %t.o -o %t
4// RUN: llvm-readelf -r %t | FileCheck --check-prefix=RELOC %s
5// RUN: llvm-readelf -x .got %t | FileCheck %s
6
7// RELOC: no relocations
8
9// CHECK: 0x00220000 00000000 00000000
10
11 .globl _start
12_start:
13 adrp x8, :got:foo
14 ldr x8, [x8, :got_lo12:foo]
15 ldr w0, [x8]
16 ret
17
18 .weak foo
deps/lld/test/ELF/aarch64-got.s deleted-18
...@@ -1,18 +0,0 @@
1# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-readobj -s %t | FileCheck %s
5
6# CHECK-NOT: Name: .got
7
8.globl _start
9_start:
10 adrp x0, :gottprel:foo
11
12 .global foo
13 .section .tdata,"awT",%progbits
14 .align 2
15 .type foo, %object
16 .size foo, 4
17foo:
18 .word 5
deps/lld/test/ELF/aarch64-hi21-nc.s created+8
...@@ -0,0 +1,8 @@
1// REQUIRES: aarch64
2// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t
4// RUN: llvm-objdump -d %t | FileCheck %s
5
6foo = . + 0x1100000000000000
7// CHECK: adrp x0, #0
8adrp x0, :pg_hi21_nc:foo
deps/lld/test/ELF/aarch64-ifunc-bti.s created+65
...@@ -0,0 +1,65 @@
1# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %s -o %t.o
3# RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-gnu %p/Inputs/aarch64-addrifunc.s -o %t1.o
4
5# RUN: ld.lld --shared %t1.o -o %t1.so
6# RUN: ld.lld --pie %t1.so %t.o -o %t
7# RUN: llvm-objdump -d -mattr=+bti -triple=aarch64-linux-gnu %t | FileCheck %s
8
9# When the address of an ifunc is taken using a non-got reference which clang
10# can do, LLD exports a canonical PLT entry that may have its address taken so
11# we must use bti c.
12
13# CHECK: Disassembly of section .plt:
14# CHECK: 0000000000010020 .plt:
15# CHECK-NEXT: 10020: 5f 24 03 d5 bti c
16# CHECK-NEXT: 10024: f0 7b bf a9 stp x16, x30, [sp, #-16]!
17# CHECK-NEXT: 10028: 10 01 00 90 adrp x16, #131072
18# CHECK-NEXT: 1002c: 11 0a 40 f9 ldr x17, [x16, #16]
19# CHECK-NEXT: 10030: 10 42 00 91 add x16, x16, #16
20# CHECK-NEXT: 10034: 20 02 1f d6 br x17
21# CHECK-NEXT: 10038: 1f 20 03 d5 nop
22# CHECK-NEXT: 1003c: 1f 20 03 d5 nop
23# CHECK: 0000000000010040 func1@plt:
24# CHECK-NEXT: 10040: 5f 24 03 d5 bti c
25# CHECK-NEXT: 10044: 10 01 00 90 adrp x16, #131072
26# CHECK-NEXT: 10048: 11 0e 40 f9 ldr x17, [x16, #24]
27# CHECK-NEXT: 1004c: 10 62 00 91 add x16, x16, #24
28# CHECK-NEXT: 10050: 20 02 1f d6 br x17
29# CHECK-NEXT: 10054: 1f 20 03 d5 nop
30# CHECK-NEXT: ...
31# CHECK: 0000000000010060 myfunc:
32# CHECK-NEXT: 10060: 5f 24 03 d5 bti c
33# CHECK-NEXT: 10064: 10 01 00 90 adrp x16, #131072
34# CHECK-NEXT: 10068: 11 12 40 f9 ldr x17, [x16, #32]
35# CHECK-NEXT: 1006c: 10 82 00 91 add x16, x16, #32
36# CHECK-NEXT: 10070: 20 02 1f d6 br x17
37# CHECK-NEXT: 10074: 1f 20 03 d5 nop
38
39.section ".note.gnu.property", "a"
40.long 4
41.long 0x10
42.long 0x5
43.asciz "GNU"
44
45.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
46.long 4
47.long 1 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
48.long 0
49
50.text
51.globl myfunc
52.type myfunc,@gnu_indirect_function
53myfunc:
54 ret
55
56.globl func1
57
58.text
59.globl _start
60.type _start, %function
61_start:
62 bl func1
63 adrp x8, myfunc
64 add x8, x8, :lo12:myfunc
65 ret
deps/lld/test/ELF/aarch64-jump26-thunk.s+1
...@@ -10,6 +10,7 @@ _start:...@@ -10,6 +10,7 @@ _start:
10 b big10 b big
1111
12// CHECK: Disassembly of section .text:12// CHECK: Disassembly of section .text:
13// CHECK-EMPTY:
13// CHECK-NEXT: _start:14// CHECK-NEXT: _start:
14// CHECK-NEXT: 210000: 02 00 00 14 b #815// CHECK-NEXT: 210000: 02 00 00 14 b #8
15// CHECK: __AArch64AbsLongThunk_big:16// CHECK: __AArch64AbsLongThunk_big:
deps/lld/test/ELF/aarch64-ldprel-lo19-invalid.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o
4# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s4# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s
55
6# CHECK: relocation R_AARCH64_LD_PREL_LO19 out of range: 2065536 is not in [-1048576, 1048575]6# CHECK: relocation R_AARCH64_LD_PREL_LO19 out of range: 2131072 is not in [-1048576, 1048575]
77
8 ldr x8, patatino8 ldr x8, patatino
9 .data9 .data
deps/lld/test/ELF/aarch64-load-alignment.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-none %s -o %t.o
4# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s4# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s
55
6# CHECK: improper alignment for relocation R_AARCH64_LD_PREL_LO19: 0x10005 is not aligned to 4 bytes6# CHECK: improper alignment for relocation R_AARCH64_LD_PREL_LO19: 0x20005 is not aligned to 4 bytes
77
8 ldr x8, patatino8 ldr x8, patatino
9 .data9 .data
deps/lld/test/ELF/aarch64-nopic-plt.s created+27
...@@ -0,0 +1,27 @@
1// REQUIRES: aarch64
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=aarch64-pc-linux
3// RUN: llvm-mc %p/Inputs/aarch64-copy2.s -o %t2.o -filetype=obj -triple=aarch64-pc-linux
4// RUN: ld.lld %t2.o -o %t2.so -shared
5// RUN: ld.lld %t.o %t2.so -o %t
6// RUN: llvm-readobj --symbols %t | FileCheck %s
7
8 .global _start
9_start:
10 adrp x8, foo
11 bl bar
12
13// CHECK: Name: bar
14// CHECK-NEXT: Value: 0x0
15// CHECK-NEXT: Size: 0
16// CHECK-NEXT: Binding: Global
17// CHECK-NEXT: Type: None
18// CHECK-NEXT: Other: 0
19// CHECK-NEXT: Section: Undefined
20
21// CHECK: Name: foo
22// CHECK-NEXT: Value: 0x210030
23// CHECK-NEXT: Size: 0
24// CHECK-NEXT: Binding: Global
25// CHECK-NEXT: Type: Function
26// CHECK-NEXT: Other: 0
27// CHECK-NEXT: Section: Undefined
deps/lld/test/ELF/aarch64-prel16.s+2-2
...@@ -25,7 +25,7 @@ _start:...@@ -25,7 +25,7 @@ _start:
25// CHECK-NEXT: 201000 ffff008025// CHECK-NEXT: 201000 ffff0080
2626
27// RUN: not ld.lld -z max-page-size=4096 %t.o %t255.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW127// 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]28// OVERFLOW1: relocation R_AARCH64_PREL16 out of range: -32769 is not in [-32768, 65535]
2929
30// RUN: not ld.lld -z max-page-size=4096 %t.o %t257.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW230// 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]31// OVERFLOW2: relocation R_AARCH64_PREL16 out of range: 65536 is not in [-32768, 65535]
deps/lld/test/ELF/aarch64-prel32.s+2-2
...@@ -25,7 +25,7 @@ _start:...@@ -25,7 +25,7 @@ _start:
25// CHECK-NEXT: 201000 ffffffff 0000008025// CHECK-NEXT: 201000 ffffffff 00000080
2626
27// RUN: not ld.lld -z max-page-size=4096 %t.o %t255.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW127// 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]28// OVERFLOW1: relocation R_AARCH64_PREL32 out of range: -2147483649 is not in [-2147483648, 4294967295]
2929
30// RUN: not ld.lld -z max-page-size=4096 %t.o %t257.o -o %t2 2>&1 | FileCheck %s --check-prefix=OVERFLOW230// 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]31// OVERFLOW2: relocation R_AARCH64_PREL32 out of range: 4294967296 is not in [-2147483648, 4294967295]
deps/lld/test/ELF/aarch64-property-relocatable.s created+36
...@@ -0,0 +1,36 @@
1# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t.o
3# RUN: ld.lld -r %t.o -o %t2.o
4# RUN: llvm-readelf -n %t2.o | FileCheck -match-full-lines %s
5
6## Test that .note.gnu.property is passed through -r, and that we can handle
7## more than one FEATURE_AND in the same object file. This is logically the
8## same as if the features were combined in a single FEATURE_AND as the rule
9## states that the bit in the output pr_data field if it is set in all
10.text
11ret
12
13.section ".note.gnu.property", "a"
14.p2align 3
15.long 4
16.long 0x10
17.long 0x5
18.asciz "GNU"
19
20.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
21.long 4
22.long 1 // GNU_PROPERTY_AARCH64_FEATURE_1_BTI
23.long 0
24
25.long 4
26.long 0x10
27.long 0x5
28.asciz "GNU"
29.long 0xc0000000 // GNU_PROPERTY_AARCH64_FEATURE_1_AND
30.long 4
31.long 2 // GNU_PROPERTY_AARCH64_FEATURE_1_PAC
32.long 0
33
34# CHECK: Owner Data size Description
35# CHECK-NEXT: GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 (property note)
36# CHECK-NEXT: Properties: aarch64 feature: BTI, PAC
deps/lld/test/ELF/aarch64-relocs.s+12
...@@ -12,6 +12,7 @@ msg: .asciz "Hello, world\n"...@@ -12,6 +12,7 @@ msg: .asciz "Hello, world\n"
12msgend:12msgend:
1313
14# CHECK: Disassembly of section .R_AARCH64_ADR_PREL_LO21:14# CHECK: Disassembly of section .R_AARCH64_ADR_PREL_LO21:
15# CHECK-EMPTY:
15# CHECK: _start:16# CHECK: _start:
16# CHECK: 0: 21 00 00 10 adr x1, #417# CHECK: 0: 21 00 00 10 adr x1, #4
17# CHECK: msg:18# CHECK: msg:
...@@ -29,6 +30,7 @@ mystr:...@@ -29,6 +30,7 @@ mystr:
29# PAGE(P) = 0x21000030# PAGE(P) = 0x210000
30#31#
31# CHECK: Disassembly of section .R_AARCH64_ADR_PREL_PG_H121:32# CHECK: Disassembly of section .R_AARCH64_ADR_PREL_PG_H121:
33# CHECK-EMPTY:
32# CHECK-NEXT: $x.2:34# CHECK-NEXT: $x.2:
33# CHECK-NEXT: 210012: 01 00 00 90 adrp x1, #035# CHECK-NEXT: 210012: 01 00 00 90 adrp x1, #0
3436
...@@ -43,6 +45,7 @@ mystr:...@@ -43,6 +45,7 @@ mystr:
43# R << 10 = 0x7c0045# R << 10 = 0x7c00
44#46#
45# CHECK: Disassembly of section .R_AARCH64_ADD_ABS_LO12_NC:47# CHECK: Disassembly of section .R_AARCH64_ADD_ABS_LO12_NC:
48# CHECK-EMPTY:
46# CHECK-NEXT: $x.4:49# CHECK-NEXT: $x.4:
47# CHECK-NEXT: 21001b: 00 7c 00 91 add x0, x0, #3150# CHECK-NEXT: 21001b: 00 7c 00 91 add x0, x0, #31
4851
...@@ -56,6 +59,7 @@ foo:...@@ -56,6 +59,7 @@ foo:
56# R = ((S + A) & 0xFFF) << 7 = 0x0000140059# R = ((S + A) & 0xFFF) << 7 = 0x00001400
57# 0x00001400 | 0xf940177c = 0xf940177c60# 0x00001400 | 0xf940177c = 0xf940177c
58# CHECK: Disassembly of section .R_AARCH64_LDST64_ABS_LO12_NC:61# CHECK: Disassembly of section .R_AARCH64_LDST64_ABS_LO12_NC:
62# CHECK-EMPTY:
59# CHECK-NEXT: $x.6:63# CHECK-NEXT: $x.6:
60# CHECK-NEXT: 210024: 7c 17 40 f9 ldr x28, [x27, #40]64# CHECK-NEXT: 210024: 7c 17 40 f9 ldr x28, [x27, #40]
6165
...@@ -65,6 +69,7 @@ sub:...@@ -65,6 +69,7 @@ sub:
65 nop69 nop
6670
67# CHECK: Disassembly of section .SUB:71# CHECK: Disassembly of section .SUB:
72# CHECK-EMPTY:
68# CHECK-NEXT: $x.8:73# CHECK-NEXT: $x.8:
69# CHECK-NEXT: 21002c: 1f 20 03 d5 nop74# CHECK-NEXT: 21002c: 1f 20 03 d5 nop
70# CHECK: sub:75# CHECK: sub:
...@@ -79,6 +84,7 @@ call26:...@@ -79,6 +84,7 @@ call26:
79# (R & 0x0ffffffc) >> 2 = 0x03ffffff84# (R & 0x0ffffffc) >> 2 = 0x03ffffff
80# 0x94000000 | 0x03ffffff = 0x97ffffff85# 0x94000000 | 0x03ffffff = 0x97ffffff
81# CHECK: Disassembly of section .R_AARCH64_CALL26:86# CHECK: Disassembly of section .R_AARCH64_CALL26:
87# CHECK-EMPTY:
82# CHECK-NEXT: call26:88# CHECK-NEXT: call26:
83# CHECK-NEXT: 210034: ff ff ff 97 bl #-489# CHECK-NEXT: 210034: ff ff ff 97 bl #-4
8490
...@@ -91,6 +97,7 @@ jump26:...@@ -91,6 +97,7 @@ jump26:
91# (R & 0x0ffffffc) >> 2 = 0x03fffffe97# (R & 0x0ffffffc) >> 2 = 0x03fffffe
92# 0x14000000 | 0x03fffffe = 0x17fffffe98# 0x14000000 | 0x03fffffe = 0x17fffffe
93# CHECK: Disassembly of section .R_AARCH64_JUMP26:99# CHECK: Disassembly of section .R_AARCH64_JUMP26:
100# CHECK-EMPTY:
94# CHECK-NEXT: jump26:101# CHECK-NEXT: jump26:
95# CHECK-NEXT: 210038: fe ff ff 17 b #-8102# CHECK-NEXT: 210038: fe ff ff 17 b #-8
96103
...@@ -105,6 +112,7 @@ foo32:...@@ -105,6 +112,7 @@ foo32:
105# R = ((S + A) & 0xFFC) << 8 = 0x00004000112# R = ((S + A) & 0xFFC) << 8 = 0x00004000
106# 0x00004000 | 0xbd4000a4 = 0xbd4040a4113# 0x00004000 | 0xbd4000a4 = 0xbd4040a4
107# CHECK: Disassembly of section .R_AARCH64_LDST32_ABS_LO12_NC:114# CHECK: Disassembly of section .R_AARCH64_LDST32_ABS_LO12_NC:
115# CHECK-EMPTY:
108# CHECK-NEXT: ldst32:116# CHECK-NEXT: ldst32:
109# CHECK-NEXT: 21003c: a4 40 40 bd ldr s4, [x5, #64]117# CHECK-NEXT: 21003c: a4 40 40 bd ldr s4, [x5, #64]
110118
...@@ -119,6 +127,7 @@ foo8:...@@ -119,6 +127,7 @@ foo8:
119# R = ((S + A) & 0xFFF) << 10 = 0x00012000127# R = ((S + A) & 0xFFF) << 10 = 0x00012000
120# 0x00012000 | 0x398001ab = 0x398121ab128# 0x00012000 | 0x398001ab = 0x398121ab
121# CHECK: Disassembly of section .R_AARCH64_LDST8_ABS_LO12_NC:129# CHECK: Disassembly of section .R_AARCH64_LDST8_ABS_LO12_NC:
130# CHECK-EMPTY:
122# CHECK-NEXT: ldst8:131# CHECK-NEXT: ldst8:
123# CHECK-NEXT: 210044: ab 21 81 39 ldrsb x11, [x13, #72]132# CHECK-NEXT: 210044: ab 21 81 39 ldrsb x11, [x13, #72]
124133
...@@ -133,6 +142,7 @@ foo128:...@@ -133,6 +142,7 @@ foo128:
133# R = ((S + A) & 0xFF8) << 6 = 0x00001400142# R = ((S + A) & 0xFF8) << 6 = 0x00001400
134# 0x00001400 | 0x3dc00274 = 0x3dc01674143# 0x00001400 | 0x3dc00274 = 0x3dc01674
135# CHECK: Disassembly of section .R_AARCH64_LDST128_ABS_LO12_NC:144# CHECK: Disassembly of section .R_AARCH64_LDST128_ABS_LO12_NC:
145# CHECK-EMPTY:
136# CHECK: ldst128:146# CHECK: ldst128:
137# CHECK: 21004c: 74 16 c0 3d ldr q20, [x19, #80]147# CHECK: 21004c: 74 16 c0 3d ldr q20, [x19, #80]
138#foo128:148#foo128:
...@@ -151,6 +161,7 @@ foo16:...@@ -151,6 +161,7 @@ foo16:
151# R = ((S + A) & 0x0FFC) << 9 = 0xb000161# R = ((S + A) & 0x0FFC) << 9 = 0xb000
152# 0xb000 | 0x7d400271 = 0x7d40b271162# 0xb000 | 0x7d400271 = 0x7d40b271
153# CHECK: Disassembly of section .R_AARCH64_LDST16_ABS_LO12_NC:163# CHECK: Disassembly of section .R_AARCH64_LDST16_ABS_LO12_NC:
164# CHECK-EMPTY:
154# CHECK-NEXT: ldst16:165# CHECK-NEXT: ldst16:
155# CHECK-NEXT: 210054: 71 c2 40 7d ldr h17, [x19, #96]166# CHECK-NEXT: 210054: 71 c2 40 7d ldr h17, [x19, #96]
156# CHECK-NEXT: 210058: 61 c2 40 79 ldrh w1, [x19, #96]167# CHECK-NEXT: 210058: 61 c2 40 79 ldrh w1, [x19, #96]
...@@ -166,6 +177,7 @@ movz1:...@@ -166,6 +177,7 @@ movz1:
166177
167## 4222124650659840 == (0xF << 48)178## 4222124650659840 == (0xF << 48)
168# CHECK: Disassembly of section .R_AARCH64_MOVW_UABS:179# CHECK: Disassembly of section .R_AARCH64_MOVW_UABS:
180# CHECK-EMPTY:
169# CHECK-NEXT: movz1:181# CHECK-NEXT: movz1:
170# CHECK-NEXT: 8c 01 80 f2 movk x12, #12182# CHECK-NEXT: 8c 01 80 f2 movk x12, #12
171# CHECK-NEXT: ad 01 a0 f2 movk x13, #13, lsl #16183# CHECK-NEXT: ad 01 a0 f2 movk x13, #13, lsl #16
deps/lld/test/ELF/aarch64-relro.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: aarch641# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t
3# RUN: ld.lld %t -o %t23# RUN: ld.lld %t -o %t2
4# RUN: llvm-readobj -program-headers %t2 | FileCheck %s4# RUN: llvm-readobj -l %t2 | FileCheck %s
55
6# CHECK: Type: PT_GNU_RELRO6# CHECK: Type: PT_GNU_RELRO
7# CHECK-NEXT: Offset:7# CHECK-NEXT: Offset:
deps/lld/test/ELF/aarch64-thunk-pi.s+7-6
...@@ -72,11 +72,12 @@ high_target2:...@@ -72,11 +72,12 @@ high_target2:
72// CHECK-NEXT: 10000018: 00 02 1f d6 br x1672// CHECK-NEXT: 10000018: 00 02 1f d6 br x16
7373
74// CHECK: Disassembly of section .plt:74// CHECK: Disassembly of section .plt:
75// CHECK-EMPTY:
75// CHECK-NEXT: .plt:76// CHECK-NEXT: .plt:
76// CHECK-NEXT: 10000020: f0 7b bf a9 stp x16, x30, [sp, #-16]!77// CHECK-NEXT: 10000020: f0 7b bf a9 stp x16, x30, [sp, #-16]!
77// CHECK-NEXT: 10000024: 10 00 00 90 adrp x16, #078// CHECK-NEXT: 10000024: 10 00 00 90 adrp x16, #0
78// CHECK-NEXT: 10000028: 11 3a 40 f9 ldr x17, [x16, #112]79// CHECK-NEXT: 10000028: 11 92 40 f9 ldr x17, [x16, #288]
79// CHECK-NEXT: 1000002c: 10 c2 01 91 add x16, x16, #11280// CHECK-NEXT: 1000002c: 10 82 04 91 add x16, x16, #288
80// CHECK-NEXT: 10000030: 20 02 1f d6 br x1781// CHECK-NEXT: 10000030: 20 02 1f d6 br x17
81// CHECK-NEXT: 10000034: 1f 20 03 d5 nop82// CHECK-NEXT: 10000034: 1f 20 03 d5 nop
82// CHECK-NEXT: 10000038: 1f 20 03 d5 nop83// CHECK-NEXT: 10000038: 1f 20 03 d5 nop
...@@ -84,12 +85,12 @@ high_target2:...@@ -84,12 +85,12 @@ high_target2:
84// CHECK-EMPTY:85// CHECK-EMPTY:
85// CHECK-NEXT: high_target@plt:86// CHECK-NEXT: high_target@plt:
86// CHECK-NEXT: 10000040: 10 00 00 90 adrp x16, #087// CHECK-NEXT: 10000040: 10 00 00 90 adrp x16, #0
87// CHECK-NEXT: 10000044: 11 3e 40 f9 ldr x17, [x16, #120]88// CHECK-NEXT: 10000044: 11 96 40 f9 ldr x17, [x16, #296]
88// CHECK-NEXT: 10000048: 10 e2 01 91 add x16, x16, #12089// CHECK-NEXT: 10000048: 10 a2 04 91 add x16, x16, #296
89// CHECK-NEXT: 1000004c: 20 02 1f d6 br x1790// CHECK-NEXT: 1000004c: 20 02 1f d6 br x17
90// CHECK-EMPTY:91// CHECK-EMPTY:
91// CHECK-NEXT: low_target@plt:92// CHECK-NEXT: low_target@plt:
92// CHECK-NEXT: 10000050: 10 00 00 90 adrp x16, #093// CHECK-NEXT: 10000050: 10 00 00 90 adrp x16, #0
93// CHECK-NEXT: 10000054: 11 42 40 f9 ldr x17, [x16, #128]94// CHECK-NEXT: 10000054: 11 9a 40 f9 ldr x17, [x16, #304]
94// CHECK-NEXT: 10000058: 10 02 02 91 add x16, x16, #12895// CHECK-NEXT: 10000058: 10 c2 04 91 add x16, x16, #304
95// CHECK-NEXT: 1000005c: 20 02 1f d6 br x1796// CHECK-NEXT: 1000005c: 20 02 1f d6 br x17
deps/lld/test/ELF/aarch64-thunk-script.s+2
...@@ -26,6 +26,7 @@ high_target:...@@ -26,6 +26,7 @@ high_target:
26 ret26 ret
2727
28// CHECK: Disassembly of section .text_low:28// CHECK: Disassembly of section .text_low:
29// CHECK-EMPTY:
29// CHECK-NEXT: _start:30// CHECK-NEXT: _start:
30// CHECK-NEXT: 2000: 02 00 00 94 bl #831// CHECK-NEXT: 2000: 02 00 00 94 bl #8
31// CHECK-NEXT: 2004: c0 03 5f d6 ret32// CHECK-NEXT: 2004: c0 03 5f d6 ret
...@@ -36,6 +37,7 @@ high_target:...@@ -36,6 +37,7 @@ high_target:
36// CHECK-NEXT: 2010: 00 20 00 08 .word 0x0800200037// CHECK-NEXT: 2010: 00 20 00 08 .word 0x08002000
37// CHECK-NEXT: 2014: 00 00 00 00 .word 0x0000000038// CHECK-NEXT: 2014: 00 00 00 00 .word 0x00000000
38// CHECK: Disassembly of section .text_high:39// CHECK: Disassembly of section .text_high:
40// CHECK-EMPTY:
39// CHECK-NEXT: high_target:41// CHECK-NEXT: high_target:
40// CHECK-NEXT: 8002000: 00 00 00 96 bl #-13421772842// CHECK-NEXT: 8002000: 00 00 00 96 bl #-134217728
41// CHECK-NEXT: 8002004: c0 03 5f d6 ret43// CHECK-NEXT: 8002004: c0 03 5f d6 ret
deps/lld/test/ELF/aarch64-tls-gdie.s+7-7
...@@ -3,8 +3,8 @@...@@ -3,8 +3,8 @@
3// RUN: llvm-mc %p/Inputs/aarch64-tls-gdie.s -o %t2.o -filetype=obj -triple=aarch64-pc-linux3// RUN: llvm-mc %p/Inputs/aarch64-tls-gdie.s -o %t2.o -filetype=obj -triple=aarch64-pc-linux
4// RUN: ld.lld %t2.o -o %t2.so -shared4// RUN: ld.lld %t2.o -o %t2.so -shared
5// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t5// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t
6// RUN: llvm-readobj -s %t | FileCheck --check-prefix=SEC %s6// RUN: llvm-readobj -S %t | FileCheck --check-prefix=SEC %s
7// RUN: llvm-objdump -d %t | FileCheck %s7// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
88
9 .globl _start9 .globl _start
10_start:10_start:
...@@ -27,8 +27,8 @@ _start:...@@ -27,8 +27,8 @@ _start:
27// 0x0B0 = 17627// 0x0B0 = 176
2828
29// CHECK: _start:29// CHECK: _start:
30// CHECK-NEXT: 210000: {{.*}} nop30// CHECK-NEXT: 210000: nop
31// CHECK-NEXT: 210004: {{.*}} adrp x0, #6553631// CHECK-NEXT: 210004: adrp x0, #65536
32// CHECK-NEXT: 210008: {{.*}} ldr x0, [x0, #176]32// CHECK-NEXT: 210008: ldr x0, [x0, #176]
33// CHECK-NEXT: 21000c: {{.*}} nop33// CHECK-NEXT: 21000c: nop
34// CHECK-NEXT: 210010: {{.*}} nop34// CHECK-NEXT: 210010: nop
deps/lld/test/ELF/aarch64-tls-gdle.s+11-10
...@@ -2,20 +2,21 @@...@@ -2,20 +2,21 @@
2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/aarch64-tls-ie.s -o %ttlsie.o2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/aarch64-tls-ie.s -o %ttlsie.o
3# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tmain.o3# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tmain.o
4# RUN: ld.lld %tmain.o %ttlsie.o -o %tout4# RUN: ld.lld %tmain.o %ttlsie.o -o %tout
5# RUN: llvm-objdump -d %tout | FileCheck %s5# RUN: llvm-objdump -d --no-show-raw-insn %tout | FileCheck %s
6# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s6# RUN: llvm-readobj -r %tout | FileCheck -check-prefix=RELOC %s
77
8#Local-Dynamic to Local-Exec relax creates no8## Local-Dynamic to Local-Exec relax creates no dynamic relocations.
9#RELOC: Relocations [9# RELOC: Relocations [
10#RELOC-NEXT: ]10# RELOC-NEXT: ]
1111
12# TCB size = 64 and foo is first element from TLS register.12# TCB size = 0x16 and foo is first element from TLS register.
13# CHECK: Disassembly of section .text:13# CHECK: Disassembly of section .text:
14# CHECK-EMPTY:
14# CHECK: _start:15# CHECK: _start:
15# CHECK: 210000: 00 00 a0 d2 movz x0, #0, lsl #1616# CHECK: 210000: movz x0, #0, lsl #16
16# CHECK: 210004: 00 08 80 f2 movk x0, #6417# CHECK: 210004: movk x0, #16
17# CHECK: 210008: 1f 20 03 d5 nop18# CHECK: 210008: nop
18# CHECK: 21000c: 1f 20 03 d5 nop19# CHECK: 21000c: nop
1920
20.globl _start21.globl _start
21_start:22_start:
deps/lld/test/ELF/aarch64-tls-ie.s+33-35
...@@ -1,45 +1,43 @@...@@ -1,45 +1,43 @@
1// REQUIRES: aarch64
2# REQUIRES: aarch641# REQUIRES: aarch64
3# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-tls-ie.s -o %tdso.o2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %p/Inputs/aarch64-tls-ie.s -o %tdso.o
4# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o3# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o
5# RUN: ld.lld -shared %tdso.o -o %tdso.so4# RUN: ld.lld -shared %tdso.o -o %tdso.so
6# RUN: ld.lld --hash-style=sysv %tmain.o %tdso.so -o %tout5# RUN: ld.lld --hash-style=sysv %tmain.o %tdso.so -o %tout
7# RUN: llvm-objdump -d %tout | FileCheck %s6# RUN: llvm-objdump -d --no-show-raw-insn %tout | FileCheck %s
8# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s7# RUN: llvm-readobj -S -r %tout | FileCheck -check-prefix=RELOC %s
98
10#RELOC: Section {9# RELOC: Section {
11#RELOC: Index:10# RELOC: Index:
12#RELOC: Name: .got11# RELOC: Name: .got
13#RELOC-NEXT: Type: SHT_PROGBITS12# RELOC-NEXT: Type: SHT_PROGBITS
14#RELOC-NEXT: Flags [13# RELOC-NEXT: Flags [
15#RELOC-NEXT: SHF_ALLOC14# RELOC-NEXT: SHF_ALLOC
16#RELOC-NEXT: SHF_WRITE15# RELOC-NEXT: SHF_WRITE
17#RELOC-NEXT: ]16# RELOC-NEXT: ]
18#RELOC-NEXT: Address: 0x2200B017# RELOC-NEXT: Address: 0x2200B0
19#RELOC-NEXT: Offset: 0x200B018# RELOC-NEXT: Offset: 0x200B0
20#RELOC-NEXT: Size: 1619# RELOC-NEXT: Size: 16
21#RELOC-NEXT: Link: 020# RELOC-NEXT: Link: 0
22#RELOC-NEXT: Info: 021# RELOC-NEXT: Info: 0
23#RELOC-NEXT: AddressAlignment: 822# RELOC-NEXT: AddressAlignment: 8
24#RELOC-NEXT: EntrySize: 023# RELOC-NEXT: EntrySize: 0
25#RELOC-NEXT: }24# RELOC-NEXT: }
26#RELOC: Relocations [25# RELOC: Relocations [
27#RELOC-NEXT: Section ({{.*}}) .rela.dyn {26# RELOC-NEXT: Section ({{.*}}) .rela.dyn {
28#RELOC-NEXT: 0x2200B8 R_AARCH64_TLS_TPREL64 bar 0x027# RELOC-NEXT: 0x2200B8 R_AARCH64_TLS_TPREL64 bar 0x0
29#RELOC-NEXT: 0x2200B0 R_AARCH64_TLS_TPREL64 foo 0x028# RELOC-NEXT: 0x2200B0 R_AARCH64_TLS_TPREL64 foo 0x0
30#RELOC-NEXT: }29# RELOC-NEXT: }
31#RELOC-NEXT:]30# RELOC-NEXT:]
3231
33# Page(0x2200B0) - Page(0x210000) = 0x10000 = 6553632## Page(0x2200B0) - Page(0x210000) = 0x10000 = 65536
34# 0x2200B0 & 0xff8 = 0xB0 = 17633## 0x2200B0 & 0xff8 = 0xB0 = 176
35# Page(0x2200B8) - Page(0x210000) = 0x10000 = 6553634## Page(0x2200B8) - Page(0x210000) = 0x10000 = 65536
36# 0x2200B8 & 0xff8 = 0xB8 = 18435## 0x2200B8 & 0xff8 = 0xB8 = 184
37#CHECK: Disassembly of section .text:36# CHECK: _start:
38#CHECK: _start:37# CHECK-NEXT: 210000: adrp x0, #65536
39#CHECK: 210000: 80 00 00 90 adrp x0, #6553638# CHECK-NEXT: 210004: ldr x0, [x0, #176]
40#CHECK: 210004: 00 58 40 f9 ldr x0, [x0, #176]39# CHECK-NEXT: 210008: adrp x0, #65536
41#CHECK: 210008: 80 00 00 90 adrp x0, #6553640# CHECK-NEXT: 21000c: ldr x0, [x0, #184]
42#CHECK: 21000c: 00 5c 40 f9 ldr x0, [x0, #184]
4341
44.globl _start42.globl _start
45_start:43_start:
deps/lld/test/ELF/aarch64-tls-iele.s+12-7
...@@ -2,20 +2,25 @@...@@ -2,20 +2,25 @@
2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/aarch64-tls-ie.s -o %ttlsie.o2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/aarch64-tls-ie.s -o %ttlsie.o
3# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tmain.o3# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %tmain.o
4# RUN: ld.lld %tmain.o %ttlsie.o -o %tout4# RUN: ld.lld %tmain.o %ttlsie.o -o %tout
5# RUN: llvm-objdump -d %tout | FileCheck %s5# RUN: llvm-objdump -d --no-show-raw-insn %tout | FileCheck %s
6# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s6# RUN: llvm-readobj -r %tout | FileCheck -check-prefix=RELOC %s
7
8# RUN: ld.lld -pie %tmain.o %ttlsie.o -o %tout
9# RUN: llvm-objdump -d --no-show-raw-insn %tout | FileCheck %s
10# RUN: llvm-readobj -r %tout | FileCheck -check-prefix=RELOC %s
711
8# Initial-Exec to Local-Exec relax creates no dynamic relocations.12# Initial-Exec to Local-Exec relax creates no dynamic relocations.
9# RELOC: Relocations [13# RELOC: Relocations [
10# RELOC-NEXT: ]14# RELOC-NEXT: ]
1115
12# TCB size = 64 and foo is first element from TLS register.16# TCB size = 0x16 and foo is first element from TLS register.
13# CHECK: Disassembly of section .text:17# CHECK: Disassembly of section .text:
18# CHECK-EMPTY:
14# CHECK: _start:19# CHECK: _start:
15# CHECK-NEXT: 210000: 00 00 a0 d2 movz x0, #0, lsl #1620# CHECK-NEXT: movz x0, #0, lsl #16
16# CHECK-NEXT: 210004: 80 08 80 f2 movk x0, #6821# CHECK-NEXT: movk x0, #20
17# CHECK-NEXT: 210008: 00 00 a0 d2 movz x0, #0, lsl #1622# CHECK-NEXT: movz x0, #0, lsl #16
18# CHECK-NEXT: 21000c: 00 08 80 f2 movk x0, #6423# CHECK-NEXT: movk x0, #16
1924
20.section .tdata25.section .tdata
21.align 226.align 2
deps/lld/test/ELF/aarch64-tls-le.s+5-5
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %tmain.o
3# RUN: ld.lld %tmain.o -o %tout3# RUN: ld.lld %tmain.o -o %tout
4# RUN: llvm-objdump -d %tout | FileCheck %s4# RUN: llvm-objdump -d %tout | FileCheck %s
5# RUN: llvm-readobj -s -r %tout | FileCheck -check-prefix=RELOC %s5# RUN: llvm-readobj -S -r %tout | FileCheck -check-prefix=RELOC %s
66
7#Local-Dynamic to Local-Exec relax creates no7#Local-Dynamic to Local-Exec relax creates no
8#RELOC: Relocations [8#RELOC: Relocations [
...@@ -17,12 +17,12 @@ _start:...@@ -17,12 +17,12 @@ _start:
17 add x0, x0, :tprel_hi12:v217 add x0, x0, :tprel_hi12:v2
18 add x0, x0, :tprel_lo12_nc:v218 add x0, x0, :tprel_lo12_nc:v2
1919
20# TCB size = 64 and foo is first element from TLS register.20# TCB size = 0x16 and foo is first element from TLS register.
21#CHECK: Disassembly of section .text:21#CHECK: Disassembly of section .text:
22#CHECK: _start:22#CHECK: _start:
23#CHECK: 210000: 40 d0 3b d5 mrs x0, TPIDR_EL023#CHECK: 210000: 40 d0 3b d5 mrs x0, TPIDR_EL0
24#CHECK: 210004: 00 00 40 91 add x0, x0, #0, lsl #1224#CHECK: 210004: 00 00 40 91 add x0, x0, #0, lsl #12
25#CHECK: 210008: 00 00 01 91 add x0, x0, #6425#CHECK: 210008: 00 40 00 91 add x0, x0, #16
26#CHECK: 21000c: 40 d0 3b d5 mrs x0, TPIDR_EL026#CHECK: 21000c: 40 d0 3b d5 mrs x0, TPIDR_EL0
27#CHECK: 210010: 00 fc 7f 91 add x0, x0, #4095, lsl #1227#CHECK: 210010: 00 fc 7f 91 add x0, x0, #4095, lsl #12
28#CHECK: 210014: 00 e0 3f 91 add x0, x0, #408828#CHECK: 210014: 00 e0 3f 91 add x0, x0, #4088
...@@ -36,9 +36,9 @@ v1:...@@ -36,9 +36,9 @@ v1:
36.word 036.word 0
37.size v1, 437.size v1, 4
3838
39# The current offset from the thread pointer is 68. Raise it to just below the39# The current offset from the thread pointer is 20. Raise it to just below the
40# 24-bit limit.40# 24-bit limit.
41.space (0xfffff8 - 68)41.space (0xfffff8 - 20)
4242
43.type v2,@object43.type v2,@object
44.globl v244.globl v2
deps/lld/test/ELF/aarch64-tls-pie.s deleted-28
...@@ -1,28 +0,0 @@
1# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-cloudabi %s -o %t1.o
3# RUN: ld.lld -pie %t1.o -o %t
4# RUN: llvm-readobj -r %t | FileCheck %s
5
6# Similar to bug 27174: R_AARCH64_TLSLE_*TPREL* relocations should be
7# eliminated when building a PIE executable, as the static TLS layout is
8# fixed.
9#
10# CHECK: Relocations [
11# CHECK-NEXT: ]
12
13 .globl _start
14_start:
15 # Accessing the variable directly.
16 add x11, x8, :tprel_hi12:i
17 add x11, x11, :tprel_lo12_nc:i
18
19 # Accessing the variable through the GOT.
20 adrp x10, :gottprel:i
21 mrs x8, TPIDR_EL0
22 ldr x10, [x10, :gottprel_lo12:i]
23
24 .section .tbss.i,"awT",@nobits
25 .globl i
26i:
27 .word 0
28 .size i, 4
deps/lld/test/ELF/aarch64-tls-static.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: aarch641// REQUIRES: aarch64
2// RUN: llvm-mc %s -o %t.o -triple aarch64-pc-linux -filetype=obj2// RUN: llvm-mc %s -o %t.o -triple aarch64-pc-linux -filetype=obj
3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
4// RUN: llvm-readobj -s %t.so | FileCheck --check-prefix=SEC %s4// RUN: llvm-readobj -S %t.so | FileCheck --check-prefix=SEC %s
5// RUN: llvm-objdump -d %t.so | FileCheck %s5// RUN: llvm-objdump -d %t.so | FileCheck %s
66
7foo:7foo:
deps/lld/test/ELF/aarch64-tlsld-ldst.s+27-27
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: aarch641// REQUIRES: aarch64
2// RUN: llvm-mc -triple=aarch64-linux-gnu -filetype=obj %s -o %t.o2// RUN: llvm-mc -triple=aarch64-linux-gnu -filetype=obj %s -o %t.o
3// RUN: ld.lld %t.o -o %t3// RUN: ld.lld %t.o -o %t
4// RUN: llvm-objdump -d %t | FileCheck %s4// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
5// RUN: llvm-readelf --symbols %t | FileCheck -check-prefix CHECK-SYMS %s5// RUN: llvm-readelf --symbols %t | FileCheck -check-prefix CHECK-SYMS %s
66
7 .text7 .text
...@@ -25,28 +25,28 @@ _start: mrs x8, TPIDR_EL0...@@ -25,28 +25,28 @@ _start: mrs x8, TPIDR_EL0
25 ldrb w0, [x8, :tprel_lo12_nc:var4]25 ldrb w0, [x8, :tprel_lo12_nc:var4]
2626
27// CHECK: _start:27// CHECK: _start:
28// CHECK-NEXT: 210000: 48 d0 3b d5 mrs x8, TPIDR_EL028// CHECK-NEXT: 210000: mrs x8, TPIDR_EL0
29// 0x0 + c40 = 0xc40 = tcb (64-bytes) + var029// 0x0 + c10 = 0xc10 = tcb (16-bytes) + var0
30// CHECK-NEXT: 210004: 08 01 40 91 add x8, x8, #0, lsl #1230// CHECK-NEXT: 210004: add x8, x8, #0, lsl #12
31// CHECK-NEXT: 210008: 14 11 c3 3d ldr q20, [x8, #3136]31// CHECK-NEXT: 210008: ldr q20, [x8, #3088]
32// 0x1000 + 0x850 = 0x1850 = tcb + var132// 0x1000 + 0x820 = 0x1820 = tcb + var1
33// CHECK-NEXT: 21000c: 08 05 40 91 add x8, x8, #1, lsl #1233// CHECK-NEXT: 21000c: add x8, x8, #1, lsl #12
34// CHECK-NEXT: 210010: 00 29 44 f9 ldr x0, [x8, #2128]34// CHECK-NEXT: 210010: ldr x0, [x8, #2080]
35// 0x2000 + 0x458 = 0x2458 = tcb + var235// 0x2000 + 0x428 = 0x2428 = tcb + var2
36// CHECK-NEXT: 210014: 08 09 40 91 add x8, x8, #2, lsl #1236// CHECK-NEXT: 210014: add x8, x8, #2, lsl #12
37// CHECK-NEXT: 210018: 00 59 44 b9 ldr w0, [x8, #1112]37// CHECK-NEXT: 210018: ldr w0, [x8, #1064]
38// 0x3000 + 0x5c = 0x305c = tcb + var338// 0x3000 + 0x2c = 0x302c = tcb + var3
39// CHECK-NEXT: 21001c: 08 0d 40 91 add x8, x8, #3, lsl #1239// CHECK-NEXT: 21001c: add x8, x8, #3, lsl #12
40// CHECK-NEXT: 210020: 00 b9 40 79 ldrh w0, [x8, #92]40// CHECK-NEXT: 210020: ldrh w0, [x8, #44]
41// 0x3000 + 0xc5e = 0x3c5e = tcb + var441// 0x3000 + 0xc2e = 0x32ce = tcb + var4
42// CHECK-NEXT: 210024: 08 0d 40 91 add x8, x8, #3, lsl #1242// CHECK-NEXT: 210024: add x8, x8, #3, lsl #12
43// CHECK-NEXT: 210028: 00 79 71 39 ldrb w0, [x8, #3166]43// CHECK-NEXT: 210028: ldrb w0, [x8, #3118]
4444
45// CHECK-SYMS: 0000000000000c00 16 TLS GLOBAL DEFAULT 2 var045// CHECK-SYMS: 0000000000000c00 0 TLS GLOBAL DEFAULT 2 var0
46// CHECK-SYMS-NEXT: 0000000000001810 8 TLS GLOBAL DEFAULT 2 var146// CHECK-SYMS-NEXT: 0000000000001810 4 TLS GLOBAL DEFAULT 2 var1
47// CHECK-SYMS-NEXT: 0000000000002418 4 TLS GLOBAL DEFAULT 2 var247// CHECK-SYMS-NEXT: 0000000000002418 2 TLS GLOBAL DEFAULT 2 var2
48// CHECK-SYMS-NEXT: 000000000000301c 2 TLS GLOBAL DEFAULT 2 var348// CHECK-SYMS-NEXT: 000000000000301c 1 TLS GLOBAL DEFAULT 2 var3
49// CHECK-SYMS-NEXT: 0000000000003c1e 1 TLS GLOBAL DEFAULT 2 var449// CHECK-SYMS-NEXT: 0000000000003c1e 0 TLS GLOBAL DEFAULT 2 var4
5050
51 .globl var051 .globl var0
52 .globl var152 .globl var1
...@@ -59,12 +59,12 @@ _start: mrs x8, TPIDR_EL0...@@ -59,12 +59,12 @@ _start: mrs x8, TPIDR_EL0
59 .type var3,@object59 .type var3,@object
6060
61.section .tbss,"awT",@nobits61.section .tbss,"awT",@nobits
62 .balign 6462 .balign 16
63 .space 1024 * 363 .space 1024 * 3
64var0:64var0:
65 .quad 065 .quad 0
66 .quad 066 .quad 0
67 .size var0, 1667 .size var1, 16
68 .space 1024 * 368 .space 1024 * 3
69var1:69var1:
70 .quad 070 .quad 0
...@@ -72,14 +72,14 @@ var1:...@@ -72,14 +72,14 @@ var1:
72 .space 1024 * 372 .space 1024 * 3
73var2:73var2:
74 .word 074 .word 0
75 .size var2, 475 .size var1, 4
7676
77 .space 1024 * 377 .space 1024 * 3
78var3:78var3:
79 .hword 079 .hword 0
80 .size var3, 280 .size var2, 2
81 .space 1024 * 381 .space 1024 * 3
82var4:82var4:
83 .byte 083 .byte 0
84 .size var4, 184 .size var3, 1
85 .space 1024 * 385 .space 1024 * 3
deps/lld/test/ELF/aarch64-tstbr14-reloc.s+12-8
...@@ -5,13 +5,14 @@...@@ -5,13 +5,14 @@
5# RUN: llvm-objdump -d %t | FileCheck %s5# RUN: llvm-objdump -d %t | FileCheck %s
6# RUN: ld.lld -shared %t1 %t2 -o %t36# RUN: ld.lld -shared %t1 %t2 -o %t3
7# RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=DSO %s7# RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=DSO %s
8# RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s8# RUN: llvm-readobj -S -r %t3 | FileCheck -check-prefix=DSOREL %s
99
10# 0x1101c - 28 = 0x2000010# 0x1101c - 28 = 0x20000
11# 0x11020 - 16 = 0x2001011# 0x11020 - 16 = 0x20010
12# 0x11024 - 36 = 0x2000012# 0x11024 - 36 = 0x20000
13# 0x11028 - 24 = 0x2001013# 0x11028 - 24 = 0x20010
14# CHECK: Disassembly of section .text:14# CHECK: Disassembly of section .text:
15# CHECK-EMPTY:
15# CHECK-NEXT: _foo:16# CHECK-NEXT: _foo:
16# CHECK-NEXT: 210000: {{.*}} nop17# CHECK-NEXT: 210000: {{.*}} nop
17# CHECK-NEXT: 210004: {{.*}} nop18# CHECK-NEXT: 210004: {{.*}} nop
...@@ -35,8 +36,8 @@...@@ -35,8 +36,8 @@
35#DSOREL-NEXT: SHF_ALLOC36#DSOREL-NEXT: SHF_ALLOC
36#DSOREL-NEXT: SHF_WRITE37#DSOREL-NEXT: SHF_WRITE
37#DSOREL-NEXT: ]38#DSOREL-NEXT: ]
38#DSOREL-NEXT: Address: 0x2000039#DSOREL-NEXT: Address: 0x30000
39#DSOREL-NEXT: Offset: 0x2000040#DSOREL-NEXT: Offset: 0x30000
40#DSOREL-NEXT: Size: 4041#DSOREL-NEXT: Size: 40
41#DSOREL-NEXT: Link: 042#DSOREL-NEXT: Link: 0
42#DSOREL-NEXT: Info: 043#DSOREL-NEXT: Info: 0
...@@ -45,12 +46,13 @@...@@ -45,12 +46,13 @@
45#DSOREL-NEXT: }46#DSOREL-NEXT: }
46#DSOREL: Relocations [47#DSOREL: Relocations [
47#DSOREL-NEXT: Section ({{.*}}) .rela.plt {48#DSOREL-NEXT: Section ({{.*}}) .rela.plt {
48#DSOREL-NEXT: 0x20018 R_AARCH64_JUMP_SLOT _foo49#DSOREL-NEXT: 0x30018 R_AARCH64_JUMP_SLOT _foo
49#DSOREL-NEXT: 0x20020 R_AARCH64_JUMP_SLOT _bar50#DSOREL-NEXT: 0x30020 R_AARCH64_JUMP_SLOT _bar
50#DSOREL-NEXT: }51#DSOREL-NEXT: }
51#DSOREL-NEXT:]52#DSOREL-NEXT:]
5253
53#DSO: Disassembly of section .text:54#DSO: Disassembly of section .text:
55#DSO-EMPTY:
54#DSO-NEXT: _foo:56#DSO-NEXT: _foo:
55#DSO-NEXT: 10000: {{.*}} nop57#DSO-NEXT: 10000: {{.*}} nop
56#DSO-NEXT: 10004: {{.*}} nop58#DSO-NEXT: 10004: {{.*}} nop
...@@ -69,10 +71,12 @@...@@ -69,10 +71,12 @@
69#DSO-NEXT: 10020: {{.*}} tbnz w3, #15, #6471#DSO-NEXT: 10020: {{.*}} tbnz w3, #15, #64
70#DSO-NEXT: 10024: {{.*}} tbz x6, #45, #4472#DSO-NEXT: 10024: {{.*}} tbz x6, #45, #44
71#DSO-NEXT: 10028: {{.*}} tbz x6, #45, #5673#DSO-NEXT: 10028: {{.*}} tbz x6, #45, #56
74#DSO-EMPTY:
72#DSO-NEXT: Disassembly of section .plt:75#DSO-NEXT: Disassembly of section .plt:
76#DSO-EMPTY:
73#DSO-NEXT: .plt:77#DSO-NEXT: .plt:
74#DSO-NEXT: 10030: {{.*}} stp x16, x30, [sp, #-16]!78#DSO-NEXT: 10030: {{.*}} stp x16, x30, [sp, #-16]!
75#DSO-NEXT: 10034: {{.*}} adrp x16, #6553679#DSO-NEXT: 10034: {{.*}} adrp x16, #131072
76#DSO-NEXT: 10038: {{.*}} ldr x17, [x16, #16]80#DSO-NEXT: 10038: {{.*}} ldr x17, [x16, #16]
77#DSO-NEXT: 1003c: {{.*}} add x16, x16, #1681#DSO-NEXT: 1003c: {{.*}} add x16, x16, #16
78#DSO-NEXT: 10040: {{.*}} br x1782#DSO-NEXT: 10040: {{.*}} br x17
...@@ -81,13 +85,13 @@...@@ -81,13 +85,13 @@
81#DSO-NEXT: 1004c: {{.*}} nop85#DSO-NEXT: 1004c: {{.*}} nop
82#DSO-EMPTY:86#DSO-EMPTY:
83#DSO-NEXT: _foo@plt:87#DSO-NEXT: _foo@plt:
84#DSO-NEXT: 10050: {{.*}} adrp x16, #6553688#DSO-NEXT: 10050: {{.*}} adrp x16, #131072
85#DSO-NEXT: 10054: {{.*}} ldr x17, [x16, #24]89#DSO-NEXT: 10054: {{.*}} ldr x17, [x16, #24]
86#DSO-NEXT: 10058: {{.*}} add x16, x16, #2490#DSO-NEXT: 10058: {{.*}} add x16, x16, #24
87#DSO-NEXT: 1005c: {{.*}} br x1791#DSO-NEXT: 1005c: {{.*}} br x17
88#DSO-EMPTY:92#DSO-EMPTY:
89#DSO-NEXT: _bar@plt:93#DSO-NEXT: _bar@plt:
90#DSO-NEXT: 10060: {{.*}} adrp x16, #6553694#DSO-NEXT: 10060: {{.*}} adrp x16, #131072
91#DSO-NEXT: 10064: {{.*}} ldr x17, [x16, #32]95#DSO-NEXT: 10064: {{.*}} ldr x17, [x16, #32]
92#DSO-NEXT: 10068: {{.*}} add x16, x16, #3296#DSO-NEXT: 10068: {{.*}} add x16, x16, #32
93#DSO-NEXT: 1006c: {{.*}} br x1797#DSO-NEXT: 1006c: {{.*}} br x17
deps/lld/test/ELF/aarch64-undefined-weak.s+1
...@@ -34,6 +34,7 @@ _start:...@@ -34,6 +34,7 @@ _start:
34 ldr x8, target34 ldr x8, target
3535
36// CHECK: Disassembly of section .text:36// CHECK: Disassembly of section .text:
37// CHECK-EMPTY:
37// 2162688 = 0x21000038// 2162688 = 0x210000
38// CHECK: 210000: {{.*}} b #439// CHECK: 210000: {{.*}} b #4
39// CHECK-NEXT: 210004: {{.*}} bl #440// CHECK-NEXT: 210004: {{.*}} bl #4
deps/lld/test/ELF/abs-hidden.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// 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/abs-hidden.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/abs-hidden.s -o %t2.o
4// RUN: ld.lld --hash-style=sysv %t.o %t2.o -o %t.so -shared4// RUN: ld.lld --hash-style=sysv %t.o %t2.o -o %t.so -shared
5// RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s5// RUN: llvm-readobj -r -S --section-data %t.so | FileCheck %s
66
7 .quad foo7 .quad foo
8 .long foo@gotpcrel8 .long foo@gotpcrel
deps/lld/test/ELF/allow-shlib-undefined.s+20-16
...@@ -1,26 +1,30 @@...@@ -1,26 +1,30 @@
1# REQUIRES: x861# REQUIRES: x86
2# --allow-shlib-undefined and --no-allow-shlib-undefined are fully2
3# ignored in linker implementation.3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# --allow-shlib-undefined is set by default
5# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
6# RUN: %p/Inputs/allow-shlib-undefined.s -o %t5# RUN: %p/Inputs/allow-shlib-undefined.s -o %t1.o
7# RUN: ld.lld -shared %t -o %t.so6# RUN: ld.lld -shared %t1.o -o %t.so
8# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t17
8# RUN: ld.lld --allow-shlib-undefined %t.o %t.so -o /dev/null
9# RUN: not ld.lld --no-allow-shlib-undefined %t.o %t.so -o /dev/null 2>&1 | FileCheck %s
10# Executable defaults to --no-allow-shlib-undefined
11# RUN: not ld.lld %t.o %t.so -o /dev/null 2>&1 | FileCheck %s
12# -shared defaults to --allow-shlib-undefined
13# RUN: ld.lld -shared %t.o %t.so -o /dev/null
914
10# Executable: should link with DSO containing undefined symbols in any case.15# RUN: echo | llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %tempty.o
11# RUN: ld.lld %t1 %t.so -o %t216# RUN: ld.lld -shared %tempty.o -o %tempty.so
12# RUN: ld.lld --no-allow-shlib-undefined %t1 %t.so -o %t217# RUN: ld.lld -shared %t1.o %tempty.so -o %t2.so
13# RUN: ld.lld --allow-shlib-undefined %t1 %t.so -o %t218# RUN: ld.lld --no-allow-shlib-undefined %t.o %t2.so -o /dev/null
1419
15# DSO with undefines:20# DSO with undefines:
16# should link with or without any of these options.21# should link with or without any of these options.
17# RUN: ld.lld -shared %t -o %t.so22# RUN: ld.lld -shared %t1.o -o /dev/null
18# RUN: ld.lld -shared --allow-shlib-undefined %t -o %t.so23# RUN: ld.lld -shared --allow-shlib-undefined %t1.o -o /dev/null
19# RUN: ld.lld -shared --no-allow-shlib-undefined %t -o %t.so24# RUN: ld.lld -shared --no-allow-shlib-undefined %t1.o -o /dev/null
20
21# Executable still should not link when have undefines inside.
22# RUN: not ld.lld %t -o %t.so
2325
24.globl _start26.globl _start
25_start:27_start:
26 callq _shared@PLT28 callq _shared@PLT
29
30# CHECK: undefined reference to _unresolved
deps/lld/test/ELF/amdgpu-abi-version-err.s created+10
...@@ -0,0 +1,10 @@
1# REQUIRES: amdgpu
2# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx900 -filetype=obj %s -o %t-0.o
3# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx900 -mattr=-code-object-v3 -filetype=obj %s -o %t-1.o
4# RUN: not ld.lld -shared %t-0.o %t-1.o -o %t.so 2>&1 | FileCheck %s
5
6# CHECK: ld.lld: error: incompatible ABI version: {{.*}}-1.o
7
8.text
9 s_nop 0x0
10 s_endpgm
deps/lld/test/ELF/amdgpu-abi-version.s created+11
...@@ -0,0 +1,11 @@
1# REQUIRES: amdgpu
2# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx900 -filetype=obj %s -o %t.o
3# RUN: ld.lld -shared %t.o -o %t.so
4# RUN: llvm-readobj --file-headers %t.so | FileCheck %s
5
6# CHECK: OS/ABI: AMDGPU_HSA (0x40)
7# CHECK: ABIVersion: 1
8
9.text
10 s_nop 0x0
11 s_endpgm
deps/lld/test/ELF/amdgpu-elf-flags.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
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.o2# 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.o3# 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# RUN: ld.lld -shared %t-0.o %t-1.o -o %t.so4# RUN: ld.lld -shared %t-0.o %t-1.o -o %t.so
5# RUN: llvm-readobj -file-headers %t.so | FileCheck %s5# RUN: llvm-readobj --file-headers %t.so | FileCheck %s
66
7# CHECK: Flags [7# CHECK: Flags [
8# CHECK: EF_AMDGPU_MACH_AMDGCN_GFX803 (0x2A)8# CHECK: EF_AMDGPU_MACH_AMDGCN_GFX803 (0x2A)
deps/lld/test/ELF/amdgpu-globals.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: amdgpu1# REQUIRES: amdgpu
2# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri %s -o %t.o
3# RUN: ld.lld -shared %t.o -o %t3# RUN: ld.lld -shared %t.o -o %t
4# RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s4# RUN: llvm-readobj --sections --symbols -l %t | FileCheck %s
55
6.type glob0, @object6.type glob0, @object
7.data7.data
deps/lld/test/ELF/amdgpu-kernels.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: amdgpu1# REQUIRES: amdgpu
2# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri -mattr=-code-object-v3 %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple amdgcn--amdhsa -mcpu=kaveri -mattr=-code-object-v3 %s -o %t.o
3# RUN: ld.lld -shared %t.o -o %t3# RUN: ld.lld -shared %t.o -o %t
4# RUN: llvm-readobj -sections -symbols -program-headers %t | FileCheck %s4# RUN: llvm-readobj --sections --symbols -l %t | FileCheck %s
55
6.hsa_code_object_version 1,06.hsa_code_object_version 1,0
7.hsa_code_object_isa 7,0,0,"AMD","AMDGPU"7.hsa_code_object_isa 7,0,0,"AMD","AMDGPU"
deps/lld/test/ELF/amdgpu-relocs.s+19-7
...@@ -2,7 +2,8 @@...@@ -2,7 +2,8 @@
2# RUN: llvm-mc -filetype=obj -triple=amdgcn--amdhsa -mcpu=fiji %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=amdgcn--amdhsa -mcpu=fiji %s -o %t.o
3# RUN: ld.lld --hash-style=sysv -shared %t.o -o %t.so3# RUN: ld.lld --hash-style=sysv -shared %t.o -o %t.so
4# RUN: llvm-readobj -r %t.so | FileCheck %s4# RUN: llvm-readobj -r %t.so | FileCheck %s
5# RUN: llvm-objdump -s %t.so | FileCheck %s --check-prefix=OBJDUMP5# RUN: llvm-nm %t.so | FileCheck %s --check-prefix=NM
6# RUN: llvm-readelf -x .rodata -x nonalloc %t.so | FileCheck %s --check-prefix=HEX
67
7.text8.text
89
...@@ -48,6 +49,9 @@ kernel0:...@@ -48,6 +49,9 @@ kernel0:
48 .local local_var049 .local local_var0
49 .local local_var150 .local local_var1
50 .local local_var251 .local local_var2
52 local_var0:
53 local_var1:
54 local_var2:
5155
52# R_AMDGPU_ABS32:56# R_AMDGPU_ABS32:
53.section nonalloc, "w", @progbits57.section nonalloc, "w", @progbits
...@@ -68,6 +72,7 @@ ptr:...@@ -68,6 +72,7 @@ ptr:
68 .type temp2, @object72 .type temp2, @object
69 .local temp273 .local temp2
70 .size temp2, 474 .size temp2, 4
75 temp2:
7176
72 .type ptr2, @object77 .type ptr2, @object
73 .globl ptr278 .globl ptr2
...@@ -89,7 +94,7 @@ foo:...@@ -89,7 +94,7 @@ foo:
89# linker.94# linker.
90# CHECK: Relocations [95# CHECK: Relocations [
91# CHECK: .rela.dyn {96# CHECK: .rela.dyn {
92# CHECK-NEXT: R_AMDGPU_RELATIVE64 - 0x097# CHECK-NEXT: R_AMDGPU_RELATIVE64 - 0x3008
93# CHECK-NEXT: R_AMDGPU_ABS64 common_var0 0x098# CHECK-NEXT: R_AMDGPU_ABS64 common_var0 0x0
94# CHECK-NEXT: R_AMDGPU_ABS64 common_var1 0x099# CHECK-NEXT: R_AMDGPU_ABS64 common_var1 0x0
95# CHECK-NEXT: R_AMDGPU_ABS64 common_var2 0x0100# CHECK-NEXT: R_AMDGPU_ABS64 common_var2 0x0
...@@ -109,9 +114,16 @@ foo:...@@ -109,9 +114,16 @@ foo:
109# CHECK-NEXT: }114# CHECK-NEXT: }
110# CHECK-NEXT: ]115# CHECK-NEXT: ]
111116
112# OBJDUMP: Contents of section .rodata:117# NM: 0000000000003010 B common_var0
113# OBJDUMP: d0f8ffff ffffffff118# NM: 0000000000003410 B common_var1
119# NM: 0000000000003810 B common_var2
120# NM: 0000000000003008 d temp2
114121
115# OBJDUMP: Contents of section nonalloc:122# temp2 - foo = 0x3008-0x768 = 0x28a0
116# OBJDUMP-NEXT: 0000 00000000 04480000 00000000 08440000123# HEX: section '.rodata':
117# OBJDUMP-NEXT: 00000000 0c400000124# HEX-NEXT: 0x00000768 a0280000 00000000
125
126# common_var2+4, common_var1+8, and common_var0+12.
127# HEX: section 'nonalloc':
128# HEX-NEXT: 0x00000000 00000000 14380000 00000000 18340000
129# HEX-NEXT: 0x00000010 00000000 1c300000
deps/lld/test/ELF/archive-fetch.s+8-1
...@@ -9,7 +9,14 @@...@@ -9,7 +9,14 @@
9# RUN: llvm-ar rcs %t.a %tfoo.o %tbar.o9# RUN: llvm-ar rcs %t.a %tfoo.o %tbar.o
1010
11# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o11# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
12# RUN: ld.lld %t.a %t.o -o /dev/null12# RUN: ld.lld %t.a %t.o -o %t
13# RUN: llvm-nm %t | FileCheck %s
14
15# RUN: ld.lld -shared %t.o -o %t.so
16# RUN: ld.lld %t.a %t.so -o %t
17# RUN: llvm-nm %t | FileCheck %s
18
19# CHECK: T foo
1320
14_start:21_start:
15callq foo22callq foo
deps/lld/test/ELF/archive-no-index.s created+13
...@@ -0,0 +1,13 @@
1# REQUIRES: x86
2# Tests error on archive file without a symbol table
3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t.o %s
4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -o %t.archive.o %S/Inputs/archive.s
5# RUN: rm -f %t.a
6# RUN: llvm-ar crS %t.a %t.archive.o
7
8# RUN: not ld.lld -o /dev/null %t.o %t.a 2>&1 | FileCheck %s
9
10.globl _start
11_start:
12
13# CHECK: error: {{.*}}.a: archive has no index; run ranlib to add one
deps/lld/test/ELF/archive-thin-missing-member.s created+24
...@@ -0,0 +1,24 @@
1# REQUIRES: x86
2
3# RUN: rm -f %t-no-syms.a
4# RUN: rm -f %t-syms.a
5# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
6# RUN: llvm-ar rcTS %t-no-syms.a %t.o
7# RUN: llvm-ar rcT %t-syms.a %t.o
8# RUN: rm %t.o
9
10# Test error when loading symbols from missing thin archive member.
11# RUN: not ld.lld %t-no-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR1
12# ERR1: {{.*}}-no-syms.a: could not get the buffer for a child of the archive: '{{.*}}.o': {{[Nn]}}o such file or directory
13
14# Test error when thin archive has symbol table but member is missing.
15# RUN: not ld.lld -m elf_amd64_fbsd %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2
16# ERR2: {{.*}}-syms.a: could not get the buffer for the member defining symbol _start: '{{.*}}.o': {{[Nn]}}o such file or directory
17
18# Test error when thin archive is linked using --whole-archive but member is missing.
19# RUN: not ld.lld --whole-archive %t-syms.a -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR3
20# ERR3: {{.*}}-syms.a: could not get the buffer for a child of the archive: '{{.*}}.o': {{[Nn]}}o such file or directory
21
22.global _start
23_start:
24 nop
deps/lld/test/ELF/arm-abs32-dyn.s+12-3
...@@ -14,12 +14,19 @@ bar:...@@ -14,12 +14,19 @@ bar:
14 .word foo14 .word foo
15 .word bar15 .word bar
1616
17// In PIC mode, if R_ARM_TARGET1 represents R_ARM_ABS32 (the default), an
18// R_ARM_TARGET1 to a non-preemptable symbol also creates an R_ARM_RELATIVE in
19// a writable section.
20 .word bar(target1)
21
17// RUN: ld.lld -shared -o %t.so %t.o22// RUN: ld.lld -shared -o %t.so %t.o
18// RUN: llvm-readobj -symbols -dyn-relocations %t.so | FileCheck %s23// RUN: llvm-readobj --symbols --dyn-relocations %t.so | FileCheck %s
24// RUN: llvm-readelf -x .data %t.so | FileCheck --check-prefix=HEX %s
1925
20// CHECK: Dynamic Relocations {26// CHECK: Dynamic Relocations {
21// CHECK-NEXT: 0x1004 R_ARM_RELATIVE27// CHECK-NEXT: 0x2004 R_ARM_RELATIVE
22// CHECK-NEXT: 0x1000 R_ARM_ABS32 foo 0x028// CHECK-NEXT: 0x2008 R_ARM_RELATIVE
29// CHECK-NEXT: 0x2000 R_ARM_ABS32 foo 0x0
23// CHECK-NEXT: }30// CHECK-NEXT: }
2431
25// CHECK: Symbols [32// CHECK: Symbols [
...@@ -30,3 +37,5 @@ bar:...@@ -30,3 +37,5 @@ bar:
30// CHECK: Symbol {37// CHECK: Symbol {
31// CHECK: Name: foo38// CHECK: Name: foo
32// CHECK-NEXT: Value: 0x100039// CHECK-NEXT: Value: 0x1000
40
41// HEX: 0x00002000 00000000 00100000 00100000
deps/lld/test/ELF/arm-attributes.s+3-3
...@@ -3,11 +3,11 @@...@@ -3,11 +3,11 @@
3// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2.o
44
5// RUN: ld.lld %t1.o %t2.o -o %t5// RUN: ld.lld %t1.o %t2.o -o %t
6// RUN: llvm-readobj -arm-attributes %t | FileCheck %s6// RUN: llvm-readobj --arm-attributes %t | FileCheck %s
7// RUN: ld.lld %t1.o %t2.o -shared -o %t27// RUN: ld.lld %t1.o %t2.o -shared -o %t2
8// RUN: llvm-readobj -arm-attributes %t2 | FileCheck %s8// RUN: llvm-readobj --arm-attributes %t2 | FileCheck %s
9// RUN: ld.lld %t1.o %t2.o -r -o %t39// RUN: ld.lld %t1.o %t2.o -r -o %t3
10// RUN: llvm-readobj -arm-attributes %t3 | FileCheck %s10// RUN: llvm-readobj --arm-attributes %t3 | FileCheck %s
1111
12// Check that we retain only 1 SHT_ARM_ATTRIBUTES section. At present we do not12// Check that we retain only 1 SHT_ARM_ATTRIBUTES section. At present we do not
13// try and merge or use the contents of SHT_ARM_ATTRIBUTES sections. We just13// try and merge or use the contents of SHT_ARM_ATTRIBUTES sections. We just
deps/lld/test/ELF/arm-bl-v6-inrange.s+4
...@@ -28,9 +28,12 @@ _start:...@@ -28,9 +28,12 @@ _start:
28thumbfunc:28thumbfunc:
29 bx lr29 bx lr
30// CHECK-THUMB: Disassembly of section .callee1:30// CHECK-THUMB: Disassembly of section .callee1:
31// CHECK-THUMB-EMPTY:
31// CHECK-THUMB-NEXT: thumbfunc:32// CHECK-THUMB-NEXT: thumbfunc:
32// CHECK-THUMB-NEXT: 100004: 70 47 bx lr33// CHECK-THUMB-NEXT: 100004: 70 47 bx lr
34// CHECK-THUMB-EMPTY:
33// CHECK-THUMB-NEXT: Disassembly of section .caller:35// CHECK-THUMB-NEXT: Disassembly of section .caller:
36// CHECK-THUMB-EMPTY:
34// CHECK-THUMB-NEXT: _start:37// CHECK-THUMB-NEXT: _start:
35// CHECK-THUMB-NEXT: 500000: 00 f4 00 f8 bl #-419430438// CHECK-THUMB-NEXT: 500000: 00 f4 00 f8 bl #-4194304
36// CHECK-THUMB-NEXT: 500004: ff f3 fe ef blx #419430039// CHECK-THUMB-NEXT: 500004: ff f3 fe ef blx #4194300
...@@ -43,5 +46,6 @@ thumbfunc:...@@ -43,5 +46,6 @@ thumbfunc:
43armfunc:46armfunc:
44 bx lr47 bx lr
45// CHECK-ARM: Disassembly of section .callee2:48// CHECK-ARM: Disassembly of section .callee2:
49// CHECK-ARM-EMPTY:
46// CHECK-ARM-NEXT: armfunc:50// CHECK-ARM-NEXT: armfunc:
47// CHECK-ARM-NEXT: 900004: 1e ff 2f e1 bx lr51// CHECK-ARM-NEXT: 900004: 1e ff 2f e1 bx lr
deps/lld/test/ELF/arm-bl-v6.s+1
...@@ -26,6 +26,7 @@ _start:...@@ -26,6 +26,7 @@ _start:
26 bx lr26 bx lr
2727
28// CHECK-ARM1: Disassembly of section .text:28// CHECK-ARM1: Disassembly of section .text:
29// CHECK-ARM1-EMPTY:
29// CHECK-ARM1-NEXT: _start:30// CHECK-ARM1-NEXT: _start:
30// CHECK-ARM1-NEXT: 11000: 00 00 00 fa blx #0 <thumbfunc>31// CHECK-ARM1-NEXT: 11000: 00 00 00 fa blx #0 <thumbfunc>
31// CHECK-ARM1-NEXT: 11004: 1e ff 2f e1 bx lr32// CHECK-ARM1-NEXT: 11004: 1e ff 2f e1 bx lr
deps/lld/test/ELF/arm-blx.s+5
...@@ -74,16 +74,19 @@ callee_arm_high:...@@ -74,16 +74,19 @@ callee_arm_high:
74 bx lr74 bx lr
7575
76// CHECK-THUMB: Disassembly of section .callee1:76// CHECK-THUMB: Disassembly of section .callee1:
77// CHECK-THUMB-EMPTY:
77// CHECK-THUMB-NEXT: callee_low:78// CHECK-THUMB-NEXT: callee_low:
78// CHECK-THUMB-NEXT: b4: 70 47 bx lr79// CHECK-THUMB-NEXT: b4: 70 47 bx lr
79// CHECK-THUMB: callee_low2:80// CHECK-THUMB: callee_low2:
80// CHECK-THUMB-NEXT: b6: 70 47 bx lr81// CHECK-THUMB-NEXT: b6: 70 47 bx lr
8182
82// CHECK-ARM: Disassembly of section .callee2:83// CHECK-ARM: Disassembly of section .callee2:
84// CHECK-ARM-EMPTY:
83// CHECK-ARM-NEXT: callee_arm_low:85// CHECK-ARM-NEXT: callee_arm_low:
84// CHECK-ARM-NEXT: 100: 1e ff 2f e1 bx lr86// CHECK-ARM-NEXT: 100: 1e ff 2f e1 bx lr
8587
86// CHECK-ARM: Disassembly of section .caller:88// CHECK-ARM: Disassembly of section .caller:
89// CHECK-ARM-EMPTY:
87// CHECK-ARM-NEXT: _start:90// CHECK-ARM-NEXT: _start:
88// CHECK-ARM-NEXT: 10000: 2b c0 ff fa blx #-65364 <callee_low>91// CHECK-ARM-NEXT: 10000: 2b c0 ff fa blx #-65364 <callee_low>
89// CHECK-ARM-NEXT: 10004: 2a c0 ff fa blx #-65368 <callee_low>92// CHECK-ARM-NEXT: 10004: 2a c0 ff fa blx #-65368 <callee_low>
...@@ -104,11 +107,13 @@ callee_arm_high:...@@ -104,11 +107,13 @@ callee_arm_high:
104// CHECK-ARM-NEXT: 10038: 1e ff 2f e1 bx lr107// CHECK-ARM-NEXT: 10038: 1e ff 2f e1 bx lr
105108
106// CHECK-THUMB: Disassembly of section .callee3:109// CHECK-THUMB: Disassembly of section .callee3:
110// CHECK-THUMB-EMPTY:
107// CHECK-THUMB: callee_high:111// CHECK-THUMB: callee_high:
108// CHECK-THUMB-NEXT: 10100: 70 47 bx lr112// CHECK-THUMB-NEXT: 10100: 70 47 bx lr
109// CHECK-THUMB: callee_high2:113// CHECK-THUMB: callee_high2:
110// CHECK-THUMB-NEXT: 10102: 70 47 bx lr114// CHECK-THUMB-NEXT: 10102: 70 47 bx lr
111115
112// CHECK-ARM: Disassembly of section .callee4:116// CHECK-ARM: Disassembly of section .callee4:
117// CHECK-ARM-EMPTY:
113// CHECK-NEXT-ARM: callee_arm_high:118// CHECK-NEXT-ARM: callee_arm_high:
114// CHECK-NEXT-ARM: 10200: 1e ff 2f e1 bx lr119// CHECK-NEXT-ARM: 10200: 1e ff 2f e1 bx lr
deps/lld/test/ELF/arm-branch-rangethunk.s+2
...@@ -19,6 +19,7 @@ _start:...@@ -19,6 +19,7 @@ _start:
19 beq too_far319 beq too_far3
2020
21// SHORT: Disassembly of section .text:21// SHORT: Disassembly of section .text:
22// SHORT-EMPTY:
22// SHORT-NEXT: _start:23// SHORT-NEXT: _start:
23// SHORT-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1>24// SHORT-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1>
24// SHORT-NEXT: 20004: 01 00 00 ea b #4 <__ARMv7ABSLongThunk_too_far2>25// SHORT-NEXT: 20004: 01 00 00 ea b #4 <__ARMv7ABSLongThunk_too_far2>
...@@ -31,6 +32,7 @@ _start:...@@ -31,6 +32,7 @@ _start:
31// SHORT-NEXT: 20014: fd ff 7f ea b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffffc>32// SHORT-NEXT: 20014: fd ff 7f ea b #33554420 <__ARMv7ABSLongThunk_too_far3+0x1fffffc>
3233
33// LONG: Disassembly of section .text:34// LONG: Disassembly of section .text:
35// LONG-EMPTY:
34// LONG-NEXT: _start:36// LONG-NEXT: _start:
35// LONG-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1>37// LONG-NEXT: 20000: 01 00 00 eb bl #4 <__ARMv7ABSLongThunk_too_far1>
36// LONG-NEXT: 20004: 03 00 00 ea b #12 <__ARMv7ABSLongThunk_too_far2>38// LONG-NEXT: 20004: 03 00 00 ea b #12 <__ARMv7ABSLongThunk_too_far2>
deps/lld/test/ELF/arm-branch-undef-weak-plt-thunk.s+1
...@@ -22,6 +22,7 @@ _start:...@@ -22,6 +22,7 @@ _start:
22 .space 32 * 1024 * 102422 .space 32 * 1024 * 1024
2323
24// CHECK: Disassembly of section .text:24// CHECK: Disassembly of section .text:
25// CHECK-EMPTY:
25// CHECK-NEXT: _start:26// CHECK-NEXT: _start:
26// CHECK-NEXT: 11000: 00 00 00 ea b #0 <__ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for>27// CHECK-NEXT: 11000: 00 00 00 ea b #0 <__ARMv7ABSLongThunk_undefined_weak_we_expect_a_plt_entry_for>
27// CHECK-NEXT: 11004: 02 00 00 eb bl #8 <__ARMv7ABSLongThunk_bar2>28// CHECK-NEXT: 11004: 02 00 00 eb bl #8 <__ARMv7ABSLongThunk_bar2>
deps/lld/test/ELF/arm-branch.s+1
...@@ -38,6 +38,7 @@ callee_high:...@@ -38,6 +38,7 @@ callee_high:
38 bx lr38 bx lr
3939
40// CHECK: Disassembly of section .caller:40// CHECK: Disassembly of section .caller:
41// CHECK-EMPTY:
41// CHECK-NEXT: _start:42// CHECK-NEXT: _start:
42// S(callee_low) = 0xb4 P = 0x10000 A = -8 = -0xff54 = -6536443// S(callee_low) = 0xb4 P = 0x10000 A = -8 = -0xff54 = -65364
43// CHECK-NEXT: 10000: 2b c0 ff eb bl #-65364 <callee_low>44// CHECK-NEXT: 10000: 2b c0 ff eb bl #-65364 <callee_low>
deps/lld/test/ELF/arm-copy.s+3-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/relocation-copy-arm.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %p/Inputs/relocation-copy-arm.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -soname fixed-length-string.so -o %t2.so4// RUN: ld.lld -shared %t2.o -soname fixed-length-string.so -o %t2.so
5// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t35// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t3
6// RUN: llvm-readobj -s -r --expand-relocs -symbols %t3 | FileCheck %s6// RUN: llvm-readobj -S -r --expand-relocs --symbols %t3 | FileCheck %s
7// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CODE %s7// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CODE %s
8// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi -section=.rodata %t3 | FileCheck -check-prefix=RODATA %s8// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi -section=.rodata %t3 | FileCheck -check-prefix=RODATA %s
99
...@@ -65,6 +65,7 @@ _start:...@@ -65,6 +65,7 @@ _start:
65// CHECK-NEXT: Section: .bss65// CHECK-NEXT: Section: .bss
6666
67// CODE: Disassembly of section .text:67// CODE: Disassembly of section .text:
68// CODE-EMPTY:
68// CODE-NEXT: _start:69// CODE-NEXT: _start:
69// S(y) = 0x13000, A = 070// S(y) = 0x13000, A = 0
70// (S + A) & 0x0000ffff = 0x3000 = #1228871// (S + A) & 0x0000ffff = 0x3000 = #12288
...@@ -78,4 +79,4 @@ _start:...@@ -78,4 +79,4 @@ _start:
7879
79// RODATA: Contents of section .rodata:80// RODATA: Contents of section .rodata:
80// S(z) = 0x1300481// S(z) = 0x13004
81// RODATA-NEXT: 10190 0430010082// RODATA-NEXT: 101b0 04300100
deps/lld/test/ELF/arm-data-prel.s+9-13
...@@ -1,12 +1,11 @@...@@ -1,12 +1,11 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o2// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj --arm-add-build-attributes -o %t.o
3// RUN: echo "SECTIONS { \3// RUN: echo "SECTIONS { \
4// RUN: .text : { *(.text) } \4// RUN: .text : { *(.text) } \
5// RUN: .prel.test : { *(.ARM.exidx) } \5// RUN: .prel.test : { *(.ARM.exidx) } \
6// RUN: .prel.test.TEST1 : { *(.ARM.exidx.TEST1) } \
7// RUN: .TEST1 : { *(.TEST1) } } " > %t.script6// RUN: .TEST1 : { *(.TEST1) } } " > %t.script
8// RUN: ld.lld --script %t.script %t.o -o %t7// RUN: ld.lld --script %t.script %t.o -o %t
9// RUN: llvm-readobj -s -sd %t | FileCheck --check-prefix=CHECK %s8// RUN: llvm-readobj -S --section-data %t | FileCheck --check-prefix=CHECK %s
109
11// The R_ARM_PREL31 relocation is used in by the .ARM.exidx exception tables10// The R_ARM_PREL31 relocation is used in by the .ARM.exidx exception tables
12// bit31 of the place denotes whether the field is an inline table entry11// bit31 of the place denotes whether the field is an inline table entry
...@@ -47,17 +46,14 @@ __aeabi_unwind_cpp_pr0:...@@ -47,17 +46,14 @@ __aeabi_unwind_cpp_pr0:
47// The expected value of the exception table is46// The expected value of the exception table is
48// Word0 0 in bit 31, -4 encoded in 31-bit signed offset47// Word0 0 in bit 31, -4 encoded in 31-bit signed offset
49// Word1 Inline table entry EHT Inline Personality Routine #048// Word1 Inline table entry EHT Inline Personality Routine #0
50// CHECK: Name: .prel.test49// Word3 0 in bit 31, +10 encoded in 31-bit signed offset
51// CHECK: SectionData (50// Word4 Inline table entry EHT Inline Personality Routine #0
52// CHECK: 0000: FCFFFF7F B0B0B080
53// CHECK: )
54
55// The expected value of the exception table is
56// Word0 0 in bit 31, +8 encoded in 31-bit signed offset
57// Word1 Inline table entry EHT Inline Personality Routine #0
58// set vsp = r1151// set vsp = r11
59// pop r11, r1452// pop r11, r14
60// CHECK: Name: .prel.test.TEST153// Word5 Sentinel +18 EXIDX_CANTUNWIND
54
55// CHECK: Name: .prel.test
61// CHECK: SectionData (56// CHECK: SectionData (
62// CHECK: 0000: 08000000 80849B8057// CHECK: 0000: FCFFFF7F B0B0B080 10000000 80849B80
58// CHECK: 0010: 18000000 01000000
63// CHECK: )59// CHECK: )
deps/lld/test/ELF/arm-data-relocs.s+2
...@@ -12,9 +12,11 @@ _start:...@@ -12,9 +12,11 @@ _start:
12// S = 0x100, A = 0x2412// S = 0x100, A = 0x24
13// S + A = 0x12413// S + A = 0x124
14// CHECK: Disassembly of section .R_ARM_ABS32POS:14// CHECK: Disassembly of section .R_ARM_ABS32POS:
15// CHECK-EMPTY:
15// CHECK: 11000: 24 01 00 0016// CHECK: 11000: 24 01 00 00
16 .section .R_ARM_ABS32NEG, "ax",%progbits17 .section .R_ARM_ABS32NEG, "ax",%progbits
17 .word foo - 0x2418 .word foo - 0x24
18// S = 0x100, A = -0x2419// S = 0x100, A = -0x24
19// CHECK: Disassembly of section .R_ARM_ABS32NEG:20// CHECK: Disassembly of section .R_ARM_ABS32NEG:
21// CHECK-EMPTY:
20// CHECK: 11004: dc 00 00 0022// CHECK: 11004: dc 00 00 00
deps/lld/test/ELF/arm-eabi-version.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
3// RUN: ld.lld -static %t.o -o %tout3// RUN: ld.lld -static %t.o -o %tout
4// RUN: llvm-readobj -file-headers %tout | FileCheck %s4// RUN: llvm-readobj --file-headers %tout | FileCheck %s
5 .syntax unified5 .syntax unified
6 .text6 .text
7 .globl _start7 .globl _start
deps/lld/test/ELF/arm-exidx-add-missing.s created+66
...@@ -0,0 +1,66 @@
1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi --arm-add-build-attributes %s -o %t
3// RUN: ld.lld %t --no-merge-exidx-entries -o %t2
4// RUN: llvm-objdump -s %t2 | FileCheck %s
5// RUN: ld.lld %t -o %t3
6// RUN: llvm-objdump -s %t3 | FileCheck %s -check-prefix=CHECK-MERGE
7
8// The ARM.exidx section is a table of 8-byte entries of the form:
9// | PREL31 Relocation to start of function | Unwinding information |
10// The range of addresses covered by the table entry is terminated by the
11// next table entry. This means that an executable section without a .ARM.exidx
12// section does not terminate the range of addresses. To fix this the linker
13// synthesises an EXIDX_CANTUNWIND entry for each section wihout a .ARM.exidx
14// section.
15
16 .syntax unified
17
18 // Expect inline unwind instructions
19 .section .text.01, "ax", %progbits
20 .global f1
21f1:
22 .fnstart
23 bx lr
24 .save {r7, lr}
25 .setfp r7, sp, #0
26 .fnend
27
28 // Expect no unwind information from assembler. The linker must
29 // synthesise an EXIDX_CANTUNWIND entry to prevent an exception
30 // thrown through f2 from matching against the unwind instructions
31 // for f1.
32 .section .text.02, "ax", %progbits
33 .global f2
34f2:
35 bx lr
36
37
38 // Expect 1 EXIDX_CANTUNWIND entry that can be merged into the linker
39 // generated EXIDX_CANTUNWIND as if the assembler had generated it.
40 .section .text.03, "ax",%progbits
41 .global f3
42f3:
43 .fnstart
44 bx lr
45 .cantunwind
46 .fnend
47
48 // Dummy implementation of personality routines to satisfy reference
49 // from exception tables, linker will generate EXIDX_CANTUNWIND.
50 .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits
51 .global __aeabi_unwind_cpp_pr0
52__aeabi_unwind_cpp_pr0:
53 bx lr
54
55// f1, f2
56// CHECK: 100d4 2c0f0000 08849780 280f0000 01000000
57// f3, __aeabi_unwind_cpp_pr0
58// CHECK-NEXT: 100e4 240f0000 01000000 200f0000 01000000
59// sentinel
60// CHECK-NEXT: 100f4 1c0f0000 01000000
61
62// f1, (f2, f3, __aeabi_unwind_cpp_pr0)
63// CHECK-MERGE: 100d4 2c0f0000 08849780 280f0000 01000000
64// sentinel
65// CHECK-MERGE-NEXT: 100e4 2c0f0000 01000000
66
deps/lld/test/ELF/arm-exidx-canunwind.s+14-14
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
3// RUN: ld.lld %t -o %t2 2>&13// RUN: ld.lld %t -o %t2
4// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s4// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
5// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s5// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s
6// RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s6// RUN: llvm-readobj --program-headers --sections %t2 | FileCheck -check-prefix=CHECK-PT %s
...@@ -53,6 +53,7 @@ _start:...@@ -53,6 +53,7 @@ _start:
53 bx lr53 bx lr
5454
55// CHECK: Disassembly of section .text:55// CHECK: Disassembly of section .text:
56// CHECK-EMPTY:
56// CHECK-NEXT: _start:57// CHECK-NEXT: _start:
57// CHECK-NEXT: 11000: 01 00 00 eb bl #4 <func1>58// CHECK-NEXT: 11000: 01 00 00 eb bl #4 <func1>
58// CHECK-NEXT: 11004: 01 00 00 eb bl #4 <func2>59// CHECK-NEXT: 11004: 01 00 00 eb bl #4 <func2>
...@@ -66,15 +67,14 @@ _start:...@@ -66,15 +67,14 @@ _start:
66// CHECK: __aeabi_unwind_cpp_pr0:67// CHECK: __aeabi_unwind_cpp_pr0:
67// CHECK-NEXT: 11018: 1e ff 2f e1 bx lr68// CHECK-NEXT: 11018: 1e ff 2f e1 bx lr
6869
69// CHECK-EXIDX: Contents of section .ARM.exidx:70// 100d4 + f2c = 11000 = main (linker generated cantunwind)
70// 100d4 + f38 = 1100c = func1 (inline unwinding data)71// 100dc + f30 = 1100c = func1 (inline unwinding data)
71// 100dc + f34 = 11010 = func2 (100e0 + c = 100ec = .ARM.extab entry)72// CHECK-EXIDX: 100d4 2c0f0000 01000000 300f0000 08849780
72// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 0c00000073// 100e4 + f2c = 11010 = func2 (100e8 + 14 = 100fc = .ARM.extab entry)
73// 100e4 + f30 = 11014 = terminate = func2 + sizeof(func2)74// 100ec + f28 = 11014 = __gcc_personality_v0 (linker generated cantunwind)
74// CHECK-EXIDX-NEXT: 100e4 300f0000 0100000075// CHECK-EXIDX-NEXT: 100e4 2c0f0000 14000000 280f0000 01000000
75// CHECK-EXIDX-NEXT: Contents of section .ARM.extab:76// 100f4 + f28 = 1101c = sentinel
76// 100ec + f28 = 11014 = __gxx_personality_v077// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000
77// CHECK-EXIDX-NEXT: 100ec 280f0000 b0b0b000 00000000
7878
79// CHECK-PT: Name: .ARM.exidx79// CHECK-PT: Name: .ARM.exidx
80// CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001)80// CHECK-PT-NEXT: Type: SHT_ARM_EXIDX (0x70000001)
...@@ -84,14 +84,14 @@ _start:...@@ -84,14 +84,14 @@ _start:
84// CHECK-PT-NEXT: ]84// CHECK-PT-NEXT: ]
85// CHECK-PT-NEXT: Address: 0x100D485// CHECK-PT-NEXT: Address: 0x100D4
86// CHECK-PT-NEXT: Offset: 0xD486// CHECK-PT-NEXT: Offset: 0xD4
87// CHECK-PT-NEXT: Size: 2487// CHECK-PT-NEXT: Size: 40
8888
89// CHECK-PT: Type: PT_ARM_EXIDX (0x70000001)89// CHECK-PT: Type: PT_ARM_EXIDX (0x70000001)
90// CHECK-PT-NEXT: Offset: 0xD490// CHECK-PT-NEXT: Offset: 0xD4
91// CHECK-PT-NEXT: VirtualAddress: 0x100D491// CHECK-PT-NEXT: VirtualAddress: 0x100D4
92// CHECK-PT-NEXT: PhysicalAddress: 0x100D492// CHECK-PT-NEXT: PhysicalAddress: 0x100D4
93// CHECK-PT-NEXT: FileSize: 2493// CHECK-PT-NEXT: FileSize: 40
94// CHECK-PT-NEXT: MemSize: 2494// CHECK-PT-NEXT: MemSize: 40
95// CHECK-PT-NEXT: Flags [ (0x4)95// CHECK-PT-NEXT: Flags [ (0x4)
96// CHECK-PT-NEXT: PF_R (0x4)96// CHECK-PT-NEXT: PF_R (0x4)
97// CHECK-PT-NEXT: ]97// CHECK-PT-NEXT: ]
deps/lld/test/ELF/arm-exidx-dedup.s+14-11
...@@ -1,27 +1,29 @@...@@ -1,27 +1,29 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
3// RUN: ld.lld %t --no-merge-exidx-entries -o %t23// RUN: ld.lld %t --no-merge-exidx-entries -o %t2
4// RUN: llvm-objdump -s %t2 | FileCheck --check-prefix CHECK-DUPS %s4// RUN: llvm-objdump -s %t2 | FileCheck --check-prefix CHECK-DUPS %s
5// RUN: ld.lld %t -o %t35// RUN: ld.lld %t -o %t3
6// RUN: llvm-objdump -s %t3 | FileCheck %s6// RUN: llvm-objdump -s %t3 | FileCheck %s
7
7// Test that lld can at least remove duplicate .ARM.exidx sections. A more8// Test that lld can at least remove duplicate .ARM.exidx sections. A more
8// fine grained implementation will be able to remove duplicate entries within9// fine grained implementation will be able to remove duplicate entries within
9// a .ARM.exidx section.10// a .ARM.exidx section.
1011
11// With duplicate entries12// With duplicate entries
12// CHECK-DUPS: Contents of section .ARM.exidx:13// CHECK-DUPS: Contents of section .ARM.exidx:
13// CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 0100000014// CHECK-DUPS-NEXT: 100d4 2c0f0000 01000000 280f0000 01000000
14// CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 0100000015// CHECK-DUPS-NEXT: 100e4 240f0000 01000000 200f0000 01000000
15// CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 0884978016// CHECK-DUPS-NEXT: 100f4 1c0f0000 08849780 180f0000 08849780
16// CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 1400000017// CHECK-DUPS-NEXT: 10104 140f0000 08849780 100f0000 24000000
17// CHECK-DUPS-NEXT: 10114 0c0f0000 18000000 080f0000 0100000018// CHECK-DUPS-NEXT: 10114 0c0f0000 28000000 080f0000 01000000
19// CHECK-DUPS-NEXT: 10124 040f0000 01000000 000f0000 01000000
18// CHECK-DUPS-NEXT: Contents of section .ARM.extab:20// CHECK-DUPS-NEXT: Contents of section .ARM.extab:
1921
20// After duplicate entry removal22// After duplicate entry removal
21// CHECK: Contents of section .ARM.exidx:23// CHECK: Contents of section .ARM.exidx:
22// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 0884978024// CHECK-NEXT: 100d4 2c0f0000 01000000 340f0000 08849780
23// CHECK-NEXT: 100e4 380f0000 14000000 340f0000 1800000025// CHECK-NEXT: 100e4 380f0000 1c000000 340f0000 20000000
24// CHECK-NEXT: 100f4 300f0000 0100000026// CHECK-NEXT: 100f4 300f0000 01000000 300f0000 01000000
25// CHECK-NEXT: Contents of section .ARM.extab:27// CHECK-NEXT: Contents of section .ARM.extab:
26 .syntax unified28 .syntax unified
2729
...@@ -113,8 +115,9 @@ f8:...@@ -113,8 +115,9 @@ f8:
113 .long 0115 .long 0
114 .fnend116 .fnend
115117
116 // Dummy implementation of personality routines to satisfy reference from118// Dummy implementation of personality routines to satisfy reference from
117 // exception tables119// exception tables
120// Expect Linker generated EXIDX_CANTUNWIND tables
118 .section .text.__gcc_personality_v0, "ax", %progbits121 .section .text.__gcc_personality_v0, "ax", %progbits
119 .global __gxx_personality_v0122 .global __gxx_personality_v0
120__gxx_personality_v0:123__gxx_personality_v0:
deps/lld/test/ELF/arm-exidx-discard.s+5-2
...@@ -2,12 +2,15 @@...@@ -2,12 +2,15 @@
2// RUN: llvm-mc -filetype=obj -triple arm-gnu-linux-eabi -mcpu cortex-a7 -arm-add-build-attributes %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple arm-gnu-linux-eabi -mcpu cortex-a7 -arm-add-build-attributes %s -o %t.o
3// RUN: echo "ENTRY(__entrypoint) SECTIONS { . = 0x10000; .text : { *(.text .text.*) } /DISCARD/ : { *(.ARM.exidx*) *(.gnu.linkonce.armexidx.*) } }" > %t.script3// RUN: echo "ENTRY(__entrypoint) SECTIONS { . = 0x10000; .text : { *(.text .text.*) } /DISCARD/ : { *(.ARM.exidx*) *(.gnu.linkonce.armexidx.*) } }" > %t.script
4// RUN: ld.lld -T %t.script %t.o -o %t.elf 2>&14// RUN: ld.lld -T %t.script %t.o -o %t.elf 2>&1
5// RUN: llvm-readobj -sections %t.elf | FileCheck %s5// RUN: llvm-readobj --sections %t.elf | FileCheck %s
66
7.globl __entrypoint7.globl __entrypoint
8__entrypoint:8__entrypoint:
9.fnstart
9 bx lr10 bx lr
1011 .save {r7, lr}
12 .setfp r7, sp, #0
13 .fnend
11// Check that .ARM.exidx/.gnu.linkonce.armexidx14// Check that .ARM.exidx/.gnu.linkonce.armexidx
12// are correctly removed if they were added.15// are correctly removed if they were added.
13// CHECK-NOT: .ARM.exidx16// CHECK-NOT: .ARM.exidx
deps/lld/test/ELF/arm-exidx-emit-relocs.s created+71
...@@ -0,0 +1,71 @@
1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
3// RUN: ld.lld --emit-relocs %t -o %t2
4// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
5// RUN: llvm-readelf --relocs %t2 | FileCheck -check-prefix=CHECK-RELOCS %s
6
7// LLD does not support --emit-relocs for .ARM.exidx sections as the relocations
8// from synthetic table entries won't be represented. Given the known use cases
9// of --emit-relocs, relocating kernels, and binary analysis, the former doesn't
10// use exceptions and the latter can derive the relocations from the table if
11// they need them.
12 .syntax unified
13 // Will produce an ARM.exidx entry with inline unwinding instructions
14 .section .text.func1, "ax",%progbits
15 .global func1
16func1:
17 .fnstart
18 bx lr
19 .save {r7, lr}
20 .setfp r7, sp, #0
21 .fnend
22
23 .syntax unified
24 .section .text.func2, "ax",%progbits
25// A function with the same inline unwinding instructions, expect merge.
26 .global func2
27func2:
28 .fnstart
29 bx lr
30 .save {r7, lr}
31 .setfp r7, sp, #0
32 .fnend
33
34 .section .text.25, "ax", %progbits
35 .global func25
36func25:
37 .fnstart
38 bx lr
39 .cantunwind
40 .fnend
41
42 .section .text.26, "ax", %progbits
43 .global func26
44func26:
45 .fnstart
46 bx lr
47 .cantunwind
48 .fnend
49
50 .syntax unified
51 .section .text.func3, "ax",%progbits
52// A function with the same inline unwinding instructions, expect merge.
53 .global func3
54func3:
55 .fnstart
56 bx lr
57 .save {r7, lr}
58 .setfp r7, sp, #0
59 .fnend
60
61 .section .text.__aeabi_unwind_cpp_pr0, "ax", %progbits
62 .global __aeabi_unwind_cpp_pr0
63__aeabi_unwind_cpp_pr0:
64 bx lr
65
66// CHECK: Contents of section .ARM.exidx:
67// CHECK-NEXT: 100d4 2c0f0000 08849780 2c0f0000 01000000
68// CHECK-NEXT: 100e4 2c0f0000 08849780 280f0000 01000000
69// CHECK-NEXT: 100f4 240f0000 01000000
70
71// CHECK-RELOCS-NOT: Relocation section '.rel.ARM.exidx'
deps/lld/test/ELF/arm-exidx-gc.s+13-11
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2// RUN: llvm-mc -filetype=obj --arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
3// RUN: ld.lld %t --no-merge-exidx-entries -o %t2 --gc-sections 2>&13// RUN: ld.lld %t --no-merge-exidx-entries -o %t2 --gc-sections 2>&1
4// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s4// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t2 | FileCheck %s
5// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s5// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXIDX %s
...@@ -91,6 +91,7 @@ _start:...@@ -91,6 +91,7 @@ _start:
91// routines are kept alive by references from live .ARM.exidx and .ARM.extab91// routines are kept alive by references from live .ARM.exidx and .ARM.extab
92// sections92// sections
93// CHECK: Disassembly of section .text:93// CHECK: Disassembly of section .text:
94// CHECK-EMPTY:
94// CHECK-NEXT: _start:95// CHECK-NEXT: _start:
95// CHECK-NEXT: 11000: 01 00 00 eb bl #4 <func1>96// CHECK-NEXT: 11000: 01 00 00 eb bl #4 <func1>
96// CHECK-NEXT: 11004: 01 00 00 eb bl #4 <func2>97// CHECK-NEXT: 11004: 01 00 00 eb bl #4 <func2>
...@@ -111,14 +112,15 @@ _start:...@@ -111,14 +112,15 @@ _start:
111// CHECK-NOT: __gxx_personality_v1112// CHECK-NOT: __gxx_personality_v1
112113
113// CHECK-EXIDX: Contents of section .ARM.exidx:114// CHECK-EXIDX: Contents of section .ARM.exidx:
114// 100d4 + f38 = 1100c = func1115// 100d4 + f2c = 11000
115// 100dc + f34 = 11010 = func2 (100e0 + 1c = 100fc = .ARM.extab)116// 100dc + f30 = 1100c = func1
116// CHECK-EXIDX-NEXT: 100d4 380f0000 08849780 340f0000 1c000000117// CHECK-EXIDX-NEXT: 100d4 2c0f0000 01000000 300f0000 08849780
117// 100e4 + f30 = 11014 = __gxx_personality_v0118// 100e4 + f2c = 11010 = func2 (100e8 + 1c = 10104 = .ARM.extab)
118// 100ec + f2c = 11018 = __aeabi_unwind_cpp_pr0119// 100ec + f28 = 11014 = __gxx_personality_v0
119// CHECK-EXIDX-NEXT: 100e4 300f0000 01000000 2c0f0000 01000000120// CHECK-EXIDX-NEXT: 100e4 2c0f0000 1c000000 280f0000 01000000
120// 100f4 + f28 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0)121// 100f4 + f24 = 11018 = __aeabi_unwind_cpp_pr0
121// CHECK-EXIDX-NEXT: 100f4 280f0000 01000000122// 100fc + f20 = 1101c = __aeabi_unwind_cpp_pr0 + sizeof(__aeabi_unwind_cpp_pr0)
123// CHECK-EXIDX-NEXT: 100f4 240f0000 01000000 200f0000 01000000
122// CHECK-EXIDX-NEXT: Contents of section .ARM.extab:124// CHECK-EXIDX-NEXT: Contents of section .ARM.extab:
123// 100fc + f18 = 11014 = __gxx_personality_v0125// 10104 + f10 = 11014 = __gxx_personality_v0
124// CHECK-EXIDX-NEXT: 100fc 180f0000 b0b0b000126// CHECK-EXIDX-NEXT: 10104 100f0000 b0b0b000
deps/lld/test/ELF/arm-exidx-link.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -s %t.so | FileCheck %s4// RUN: llvm-readobj -S %t.so | FileCheck %s
55
6// CHECK: Name: .ARM.exidx6// CHECK: Name: .ARM.exidx
7// CHECK-NEXT: Type: SHT_ARM_EXIDX7// CHECK-NEXT: Type: SHT_ARM_EXIDX
deps/lld/test/ELF/arm-exidx-order.s+11
...@@ -54,6 +54,7 @@ f3:...@@ -54,6 +54,7 @@ f3:
54// Check default no linker script order.54// Check default no linker script order.
5555
56// CHECK: Disassembly of section .text:56// CHECK: Disassembly of section .text:
57// CHECK-EMPTY:
57// CHECK: _start:58// CHECK: _start:
58// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr59// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr
59// CHECK: f1:60// CHECK: f1:
...@@ -67,12 +68,15 @@ f3:...@@ -67,12 +68,15 @@ f3:
67// CHECK: func5:68// CHECK: func5:
68// CHECK-NEXT: 11014: 1e ff 2f e1 bx lr69// CHECK-NEXT: 11014: 1e ff 2f e1 bx lr
69// CHECK: Disassembly of section .func1:70// CHECK: Disassembly of section .func1:
71// CHECK-EMPTY:
70// CHECK-NEXT: func1:72// CHECK-NEXT: func1:
71// CHECK-NEXT: 11018: 1e ff 2f e1 bx lr73// CHECK-NEXT: 11018: 1e ff 2f e1 bx lr
72// CHECK: Disassembly of section .func2:74// CHECK: Disassembly of section .func2:
75// CHECK-EMPTY:
73// CHECK-NEXT: func2:76// CHECK-NEXT: func2:
74// CHECK-NEXT: 1101c: 1e ff 2f e1 bx lr77// CHECK-NEXT: 1101c: 1e ff 2f e1 bx lr
75// CHECK: Disassembly of section .func3:78// CHECK: Disassembly of section .func3:
79// CHECK-EMPTY:
76// CHECK-NEXT: func3:80// CHECK-NEXT: func3:
77// CHECK-NEXT: 11020: 1e ff 2f e1 bx lr81// CHECK-NEXT: 11020: 1e ff 2f e1 bx lr
7882
...@@ -128,6 +132,7 @@ f3:...@@ -128,6 +132,7 @@ f3:
128// the .text section but before the orphan sections132// the .text section but before the orphan sections
129133
130// CHECK-SCRIPT: Disassembly of section .text:134// CHECK-SCRIPT: Disassembly of section .text:
135// CHECK-SCRIPT-EMPTY:
131// CHECK-SCRIPT-NEXT: func4:136// CHECK-SCRIPT-NEXT: func4:
132// CHECK-SCRIPT-NEXT: 11000: 1e ff 2f e1 bx lr137// CHECK-SCRIPT-NEXT: 11000: 1e ff 2f e1 bx lr
133// CHECK-SCRIPT: func5:138// CHECK-SCRIPT: func5:
...@@ -140,13 +145,19 @@ f3:...@@ -140,13 +145,19 @@ f3:
140// CHECK-SCRIPT-NEXT: 11010: 1e ff 2f e1 bx lr145// CHECK-SCRIPT-NEXT: 11010: 1e ff 2f e1 bx lr
141// CHECK-SCRIPT: f3:146// CHECK-SCRIPT: f3:
142// CHECK-SCRIPT-NEXT: 11014: 1e ff 2f e1 bx lr147// CHECK-SCRIPT-NEXT: 11014: 1e ff 2f e1 bx lr
148// CHECK-SCRIPT-EMPTY:
143// CHECK-SCRIPT-NEXT: Disassembly of section .func1:149// CHECK-SCRIPT-NEXT: Disassembly of section .func1:
150// CHECK-SCRIPT-EMPTY:
144// CHECK-SCRIPT-NEXT: func1:151// CHECK-SCRIPT-NEXT: func1:
145// CHECK-SCRIPT-NEXT: 11018: 1e ff 2f e1 bx lr152// CHECK-SCRIPT-NEXT: 11018: 1e ff 2f e1 bx lr
153// CHECK-SCRIPT-EMPTY:
146// CHECK-SCRIPT-NEXT: Disassembly of section .func2:154// CHECK-SCRIPT-NEXT: Disassembly of section .func2:
155// CHECK-SCRIPT-EMPTY:
147// CHECK-SCRIPT-NEXT: func2:156// CHECK-SCRIPT-NEXT: func2:
148// CHECK-SCRIPT-NEXT: 1101c: 1e ff 2f e1 bx lr157// CHECK-SCRIPT-NEXT: 1101c: 1e ff 2f e1 bx lr
158// CHECK-SCRIPT-EMPTY:
149// CHECK-SCRIPT-NEXT: Disassembly of section .func3:159// CHECK-SCRIPT-NEXT: Disassembly of section .func3:
160// CHECK-SCRIPT-EMPTY:
150// CHECK-SCRIPT-NEXT: func3:161// CHECK-SCRIPT-NEXT: func3:
151// CHECK-SCRIPT-NEXT: 11020: 1e ff 2f e1 bx lr162// CHECK-SCRIPT-NEXT: 11020: 1e ff 2f e1 bx lr
152163
deps/lld/test/ELF/arm-exidx-output.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t
3// RUN: ld.lld %t -o %t2 2>&13// RUN: ld.lld %t -o %t2 2>&1
4// RUN: llvm-readobj -sections %t2 | FileCheck %s4// RUN: llvm-readobj --sections %t2 | FileCheck %s
55
6// Check that only a single .ARM.exidx output section is created when6// Check that only a single .ARM.exidx output section is created when
7// there are input sections of the form .ARM.exidx.<section-name>. The7// there are input sections of the form .ARM.exidx.<section-name>. The
deps/lld/test/ELF/arm-exidx-relocatable.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-exidx-cantunwind.s -o %tcantunwind3// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %S/Inputs/arm-exidx-cantunwind.s -o %tcantunwind
4// Check that relocatable link maintains SHF_LINK_ORDER4// Check that relocatable link maintains SHF_LINK_ORDER
5// RUN: ld.lld -r %t %tcantunwind -o %t4 2>&15// RUN: ld.lld -r %t %tcantunwind -o %t4 2>&1
6// RUN: llvm-readobj -s %t4 | FileCheck %s6// RUN: llvm-readobj -S %t4 | FileCheck %s
77
8// Each assembler created .ARM.exidx section has the SHF_LINK_ORDER flag set8// Each assembler created .ARM.exidx section has the SHF_LINK_ORDER flag set
9// with the sh_link containing the section index of the executable section9// with the sh_link containing the section index of the executable section
deps/lld/test/ELF/arm-exidx-sentinel-norelocatable.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o2// RUN: llvm-mc %s -triple=armv7-unknown-linux-gnueabi -filetype=obj -o %t.o
3// RUN: ld.lld -r %t.o -o %t3// RUN: ld.lld -r %t.o -o %t
4// RUN: llvm-readobj -s %t | FileCheck %s4// RUN: llvm-readobj -S %t | FileCheck %s
5// Check that when doing a relocatable link we don't add a terminating entry5// Check that when doing a relocatable link we don't add a terminating entry
6// to the .ARM.exidx section6// to the .ARM.exidx section
7 .syntax unified7 .syntax unified
deps/lld/test/ELF/arm-exidx-shared.s+5-5
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t2// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t
3// RUN: ld.lld --hash-style=sysv %t --shared -o %t2 2>&13// RUN: ld.lld --hash-style=sysv %t --shared -o %t2 2>&1
4// RUN: llvm-readobj --relocations %t2 | FileCheck %s4// RUN: llvm-readobj --relocations %t2 | FileCheck %s
5// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck -check-prefix=CHECK-EXTAB %s5// RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t2 | FileCheck --check-prefix=CHECK-EXTAB-NEXT %s
66
7// Check that the relative R_ARM_PREL31 relocation can access a PLT entry7// Check that the relative R_ARM_PREL31 relocation can access a PLT entry
8// for when the personality routine is referenced from a shared library.8// for when the personality routine is referenced from a shared library.
...@@ -38,8 +38,8 @@ __aeabi_unwind_cpp_pr0:...@@ -38,8 +38,8 @@ __aeabi_unwind_cpp_pr0:
3838
39// CHECK: Relocations [39// CHECK: Relocations [
40// CHECK-NEXT: Section {{.*}} .rel.plt {40// CHECK-NEXT: Section {{.*}} .rel.plt {
41// CHECK-NEXT: 0x200C R_ARM_JUMP_SLOT __gxx_personality_v041// CHECK-NEXT: 0x300C R_ARM_JUMP_SLOT __gxx_personality_v0
4242
43// CHECK-EXTAB: Contents of section .ARM.extab:43// CHECK-EXTAB: Contents of section .ARM.extab:
44// 0x0210 + 0x0e20 = 0x1030 = __gxx_personality_v0(PLT)44// 0x0238 + 0xdf8 = 0x1030 = __gxx_personality_v0(PLT)
45// CHECK-EXTAB-NEXT: 0210 200e0000 b0b0b000 0000000045// CHECK-EXTAB-NEXT: 0238 f80d0000 b0b0b000 00000000
deps/lld/test/ELF/arm-exidx-synthetic-link.s created+37
...@@ -0,0 +1,37 @@
1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -arm-add-build-attributes -triple=armv7a-none-linux-gnueabi %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -S %t.so | FileCheck %s
5
6// Test that when all the .ARM.exidx sections are merged into a single
7// synthetic EXIDX_CANTUNWIND entry we can still set the SHF_LINK_ORDER
8// link.
9 .syntax unified
10 .section .text.1, "ax", %progbits
11 .globl f1
12 .type f1, %function
13f1:
14 bx lr
15
16 .section .text.2, "ax", %progbits
17 .globl f2
18 .type f2, %function
19f2:
20 .fnstart
21 bx lr
22 .cantunwind
23 .fnend
24
25// CHECK: Name: .ARM.exidx
26// CHECK-NEXT: Type: SHT_ARM_EXIDX
27// CHECK-NEXT: Flags [
28// CHECK-NEXT: SHF_ALLOC
29// CHECK-NEXT: SHF_LINK_ORDER
30// CHECK-NEXT: ]
31// CHECK-NEXT: Address:
32// CHECK-NEXT: Offset:
33// CHECK-NEXT: Size:
34// CHECK-NEXT: Link: [[INDEX:.*]]
35
36// CHECK: Index: [[INDEX]]
37// CHECK-NEXT: Name: .text
deps/lld/test/ELF/arm-extreme-range-pi-thunk.s+4
...@@ -32,6 +32,7 @@ high:...@@ -32,6 +32,7 @@ high:
32// ARMv7a instructions and relocations.32// ARMv7a instructions and relocations.
3333
34// CHECK: Disassembly of section .text_low:34// CHECK: Disassembly of section .text_low:
35// CHECK-EMPTY:
35// CHECK-NEXT: _start:36// CHECK-NEXT: _start:
36// CHECK-NEXT: 130: 00 00 00 eb bl #0 <__ARMV7PILongThunk_high>37// CHECK-NEXT: 130: 00 00 00 eb bl #0 <__ARMV7PILongThunk_high>
37// CHECK-NEXT: 134: 1e ff 2f e1 bx lr38// CHECK-NEXT: 134: 1e ff 2f e1 bx lr
...@@ -44,6 +45,7 @@ high:...@@ -44,6 +45,7 @@ high:
44// CHECK-NEXT: 144: 1c ff 2f e1 bx r1245// CHECK-NEXT: 144: 1c ff 2f e1 bx r12
4546
46// CHECK: Disassembly of section .text_high:47// CHECK: Disassembly of section .text_high:
48// CHECK-EMPTY:
47// CHECK-NEXT: high:49// CHECK-NEXT: high:
48// CHECK-NEXT: f0000000: 00 00 00 eb bl #0 <__ARMV7PILongThunk__start>50// CHECK-NEXT: f0000000: 00 00 00 eb bl #0 <__ARMV7PILongThunk__start>
49// CHECK-NEXT: f0000004: 1e ff 2f e1 bx lr51// CHECK-NEXT: f0000004: 1e ff 2f e1 bx lr
...@@ -57,6 +59,7 @@ high:...@@ -57,6 +59,7 @@ high:
5759
58// Thumbv7a instructions and relocations60// Thumbv7a instructions and relocations
59// CHECK-THUMB: Disassembly of section .text_low:61// CHECK-THUMB: Disassembly of section .text_low:
62// CHECK-THUMB-EMPTY:
60// CHECK-THUMB-NEXT: _start:63// CHECK-THUMB-NEXT: _start:
61// CHECK-THUMB-NEXT: 130: 00 f0 02 f8 bl #464// CHECK-THUMB-NEXT: 130: 00 f0 02 f8 bl #4
62// CHECK-THUMB-NEXT: 134: 70 47 bx lr65// CHECK-THUMB-NEXT: 134: 70 47 bx lr
...@@ -70,6 +73,7 @@ high:...@@ -70,6 +73,7 @@ high:
70// CHECK-THUMB-NEXT: 142: 60 47 bx r1273// CHECK-THUMB-NEXT: 142: 60 47 bx r12
7174
72// CHECK-THUMB: Disassembly of section .text_high:75// CHECK-THUMB: Disassembly of section .text_high:
76// CHECK-THUMB-EMPTY:
73// CHECK-THUMB-NEXT: high:77// CHECK-THUMB-NEXT: high:
74// CHECK-THUMB-NEXT: f0000000: 00 f0 02 f8 bl #478// CHECK-THUMB-NEXT: f0000000: 00 f0 02 f8 bl #4
75// CHECK-THUMB-NEXT: f0000004: 70 47 bx lr79// CHECK-THUMB-NEXT: f0000004: 70 47 bx lr
deps/lld/test/ELF/arm-force-pi-thunk.s+2
...@@ -31,6 +31,7 @@ low_target2:...@@ -31,6 +31,7 @@ low_target2:
31 bl high_target231 bl high_target2
3232
33// CHECK: Disassembly of section .text_low:33// CHECK: Disassembly of section .text_low:
34// CHECK-EMPTY:
34// CHECK-NEXT: _start:35// CHECK-NEXT: _start:
35// CHECK-NEXT: 94: 70 47 bx lr36// CHECK-NEXT: 94: 70 47 bx lr
36// CHECK: low_target:37// CHECK: low_target:
...@@ -69,6 +70,7 @@ high_target2:...@@ -69,6 +70,7 @@ high_target2:
69 bl low_target270 bl low_target2
7071
71// CHECK: Disassembly of section .text_high:72// CHECK: Disassembly of section .text_high:
73// CHECK-EMPTY:
72// CHECK-NEXT: high_target:74// CHECK-NEXT: high_target:
73// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #475// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4
74// CHECK-NEXT: 2000004: 00 f0 06 f8 bl #1276// CHECK-NEXT: 2000004: 00 f0 06 f8 bl #12
deps/lld/test/ELF/arm-fpic-got.s+7-6
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
3// RUN: ld.lld %t.o -o %t3// RUN: ld.lld %t.o -o %t
4// RUN: llvm-readobj -s %t | FileCheck %s4// RUN: llvm-readobj -S %t | FileCheck %s
5// RUN: llvm-readobj -s -symbols %t | FileCheck -check-prefix=SYMBOLS %s5// RUN: llvm-readobj -S --symbols %t | FileCheck -check-prefix=SYMBOLS %s
6// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t | FileCheck -check-prefix=CODE %s6// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t | FileCheck -check-prefix=CODE %s
77
8// Test the R_ARM_GOT_PREL relocation8// Test the R_ARM_GOT_PREL relocation
...@@ -36,7 +36,7 @@ val:...@@ -36,7 +36,7 @@ val:
36// CHECK-NEXT: SHF_ALLOC36// CHECK-NEXT: SHF_ALLOC
37// CHECK-NEXT: SHF_WRITE37// CHECK-NEXT: SHF_WRITE
38// CHECK-NEXT: ]38// CHECK-NEXT: ]
39// CHECK-NEXT: Address: 0x1300039// CHECK-NEXT: Address: 0x12000
40// CHECK-NEXT: Offset:40// CHECK-NEXT: Offset:
41// CHECK-NEXT: Size: 441// CHECK-NEXT: Size: 4
42// CHECK-NEXT: Link:42// CHECK-NEXT: Link:
...@@ -45,7 +45,7 @@ val:...@@ -45,7 +45,7 @@ val:
45// CHECK-NEXT: EntrySize:45// CHECK-NEXT: EntrySize:
4646
47// SYMBOLS: Name: val47// SYMBOLS: Name: val
48// SYMBOLS-NEXT: Value: 0x1200048// SYMBOLS-NEXT: Value: 0x13000
49// SYMBOLS-NEXT: Size: 449// SYMBOLS-NEXT: Size: 4
50// SYMBOLS-NEXT: Binding: Global50// SYMBOLS-NEXT: Binding: Global
51// SYMBOLS-NEXT: Type: Object51// SYMBOLS-NEXT: Type: Object
...@@ -53,11 +53,12 @@ val:...@@ -53,11 +53,12 @@ val:
53// SYMBOLS-NEXT: Section: .data53// SYMBOLS-NEXT: Section: .data
5454
55// CODE: Disassembly of section .text:55// CODE: Disassembly of section .text:
56// CODE-EMPTY:
56// CODE-NEXT: _start:57// CODE-NEXT: _start:
57// CODE-NEXT: 11000: 08 00 9f e5 ldr r0, [pc, #8]58// CODE-NEXT: 11000: 08 00 9f e5 ldr r0, [pc, #8]
58// CODE-NEXT: 11004: 00 00 9f e7 ldr r0, [pc, r0]59// CODE-NEXT: 11004: 00 00 9f e7 ldr r0, [pc, r0]
59// CODE-NEXT: 11008: 00 00 90 e5 ldr r0, [r0]60// CODE-NEXT: 11008: 00 00 90 e5 ldr r0, [r0]
60// CODE-NEXT: 1100c: 1e ff 2f e1 bx lr61// CODE-NEXT: 1100c: 1e ff 2f e1 bx lr
61// CODE: $d.1:62// CODE: $d.1:
62// 0x11004 + 0x1ff4 + 8 = 0x13000 = .got63// 0x11004 + 0x0ff4 + 8 = 0x12000 = .got
63// CODE-NEXT: 11010: f4 1f 00 0064// CODE-NEXT: 11010: f4 0f 00 00
deps/lld/test/ELF/arm-gnu-ifunc-nosym.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
3// RUN: ld.lld -static %t.o -o %tout3// RUN: ld.lld -static %t.o -o %tout
4// RUN: llvm-readobj -symbols %tout | FileCheck %s4// RUN: llvm-readobj --symbols %tout | FileCheck %s
55
6// Check that no __rel_iplt_end/__rel_iplt_start6// Check that no __rel_iplt_end/__rel_iplt_start
7// appear in symtab if there are no references to them.7// appear in symtab if there are no references to them.
deps/lld/test/ELF/arm-gnu-ifunc-plt.s+19-16
...@@ -5,30 +5,31 @@...@@ -5,30 +5,31 @@
5// RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout5// RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout
6// RUN: llvm-objdump -triple=armv7a-linux-gnueabihf -d %tout | FileCheck %s --check-prefix=DISASM6// RUN: llvm-objdump -triple=armv7a-linux-gnueabihf -d %tout | FileCheck %s --check-prefix=DISASM
7// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT7// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT
8// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s8// RUN: llvm-readobj -r --dynamic-table %tout | FileCheck %s
99
10// Check that the IRELATIVE relocations are last in the .got10// Check that the IRELATIVE relocations are last in the .got
11// CHECK: Relocations [11// CHECK: Relocations [
12// CHECK-NEXT: Section (4) .rel.dyn {12// CHECK-NEXT: Section (4) .rel.dyn {
13// CHECK-NEXT: 0x13078 R_ARM_GLOB_DAT bar2 0x013// CHECK-NEXT: 0x12078 R_ARM_GLOB_DAT bar2 0x0
14// CHECK-NEXT: 0x1307C R_ARM_GLOB_DAT zed2 0x014// CHECK-NEXT: 0x1207C R_ARM_GLOB_DAT zed2 0x0
15// CHECK-NEXT: 0x13080 R_ARM_IRELATIVE - 0x015// CHECK-NEXT: 0x12080 R_ARM_IRELATIVE - 0x0
16// CHECK-NEXT: 0x13084 R_ARM_IRELATIVE - 0x016// CHECK-NEXT: 0x12084 R_ARM_IRELATIVE - 0x0
17// CHECK-NEXT: }17// CHECK-NEXT: }
18// CHECK-NEXT: Section (5) .rel.plt {18// CHECK-NEXT: Section (5) .rel.plt {
19// CHECK-NEXT: 0x1200C R_ARM_JUMP_SLOT bar2 0x019// CHECK-NEXT: 0x1300C R_ARM_JUMP_SLOT bar2 0x0
20// CHECK-NEXT: 0x12010 R_ARM_JUMP_SLOT zed2 0x020// CHECK-NEXT: 0x13010 R_ARM_JUMP_SLOT zed2 0x0
21// CHECK-NEXT: }21// CHECK-NEXT: }
22// CHECK-NEXT: ]22// CHECK-NEXT: ]
2323
24// Check that the GOT entries refer back to the ifunc resolver24// Check that the GOT entries refer back to the ifunc resolver
25// GOTPLT: Contents of section .got.plt:
26// GOTPLT-NEXT: 12000 00000000 00000000 00000000 20100100
27// GOTPLT-NEXT: 12010 20100100
28// GOTPLT: Contents of section .got:25// GOTPLT: Contents of section .got:
29// GOTPLT-NEXT: 13078 00000000 00000000 00100100 0410010026// GOTPLT-NEXT: 12078 00000000 00000000 00100100 04100100
27// GOTPLT: Contents of section .got.plt:
28// GOTPLT-NEXT: 13000 00000000 00000000 00000000 20100100
29// GOTPLT-NEXT: 13010 20100100
3030
31// DISASM: Disassembly of section .text:31// DISASM: Disassembly of section .text:
32// DISASM-EMPTY:
32// DISASM-NEXT: foo:33// DISASM-NEXT: foo:
33// DISASM-NEXT: 11000: 1e ff 2f e1 bx lr34// DISASM-NEXT: 11000: 1e ff 2f e1 bx lr
34// DISASM: bar:35// DISASM: bar:
...@@ -41,11 +42,13 @@...@@ -41,11 +42,13 @@
41// DISASM-NEXT: 11014: 04 00 00 00 .word 0x0000000442// DISASM-NEXT: 11014: 04 00 00 00 .word 0x00000004
42// DISASM: 11018: 08 00 00 eb bl #3243// DISASM: 11018: 08 00 00 eb bl #32
43// DISASM-NEXT: 1101c: 0b 00 00 eb bl #4444// DISASM-NEXT: 1101c: 0b 00 00 eb bl #44
45// DISASM-EMPTY:
44// DISASM-NEXT: Disassembly of section .plt:46// DISASM-NEXT: Disassembly of section .plt:
47// DISASM-EMPTY:
45// DISASM-NEXT: $a:48// DISASM-NEXT: $a:
46// DISASM-NEXT: 11020: 04 e0 2d e5 str lr, [sp, #-4]!49// DISASM-NEXT: 11020: 04 e0 2d e5 str lr, [sp, #-4]!
47// DISASM-NEXT: 11024: 00 e6 8f e2 add lr, pc, #0, #1250// DISASM-NEXT: 11024: 00 e6 8f e2 add lr, pc, #0, #12
48// DISASM-NEXT: 11028: 00 ea 8e e2 add lr, lr, #0, #2051// DISASM-NEXT: 11028: 01 ea 8e e2 add lr, lr, #4096
49// DISASM-NEXT: 1102c: dc ff be e5 ldr pc, [lr, #4060]!52// DISASM-NEXT: 1102c: dc ff be e5 ldr pc, [lr, #4060]!
50// DISASM: $d:53// DISASM: $d:
51// DISASM-NEXT: 11030: d4 d4 d4 d4 .word 0xd4d4d4d454// DISASM-NEXT: 11030: d4 d4 d4 d4 .word 0xd4d4d4d4
...@@ -54,25 +57,25 @@...@@ -54,25 +57,25 @@
54// DISASM-NEXT: 1103c: d4 d4 d4 d4 .word 0xd4d4d4d457// DISASM-NEXT: 1103c: d4 d4 d4 d4 .word 0xd4d4d4d4
55// DISASM: $a:58// DISASM: $a:
56// DISASM-NEXT: 11040: 00 c6 8f e2 add r12, pc, #0, #1259// DISASM-NEXT: 11040: 00 c6 8f e2 add r12, pc, #0, #12
57// DISASM-NEXT: 11044: 00 ca 8c e2 add r12, r12, #0, #2060// DISASM-NEXT: 11044: 01 ca 8c e2 add r12, r12, #4096
58// DISASM-NEXT: 11048: c4 ff bc e5 ldr pc, [r12, #4036]!61// DISASM-NEXT: 11048: c4 ff bc e5 ldr pc, [r12, #4036]!
59// DISASM: $d:62// DISASM: $d:
60// DISASM-NEXT: 1104c: d4 d4 d4 d4 .word 0xd4d4d4d463// DISASM-NEXT: 1104c: d4 d4 d4 d4 .word 0xd4d4d4d4
61// DISASM: $a:64// DISASM: $a:
62// DISASM-NEXT: 11050: 00 c6 8f e2 add r12, pc, #0, #1265// DISASM-NEXT: 11050: 00 c6 8f e2 add r12, pc, #0, #12
63// DISASM-NEXT: 11054: 00 ca 8c e2 add r12, r12, #0, #2066// DISASM-NEXT: 11054: 01 ca 8c e2 add r12, r12, #4096
64// DISASM-NEXT: 11058: b8 ff bc e5 ldr pc, [r12, #4024]!67// DISASM-NEXT: 11058: b8 ff bc e5 ldr pc, [r12, #4024]!
65// DISASM: $d:68// DISASM: $d:
66// DISASM-NEXT: 1105c: d4 d4 d4 d4 .word 0xd4d4d4d469// DISASM-NEXT: 1105c: d4 d4 d4 d4 .word 0xd4d4d4d4
67// DISASM: $a:70// DISASM: $a:
68// DISASM-NEXT: 11060: 00 c6 8f e2 add r12, pc, #0, #1271// DISASM-NEXT: 11060: 00 c6 8f e2 add r12, pc, #0, #12
69// DISASM-NEXT: 11064: 02 ca 8c e2 add r12, r12, #819272// DISASM-NEXT: 11064: 01 ca 8c e2 add r12, r12, #4096
70// DISASM-NEXT: 11068: 18 f0 bc e5 ldr pc, [r12, #24]!73// DISASM-NEXT: 11068: 18 f0 bc e5 ldr pc, [r12, #24]!
71// DISASM: $d:74// DISASM: $d:
72// DISASM-NEXT: 1106c: d4 d4 d4 d4 .word 0xd4d4d4d475// DISASM-NEXT: 1106c: d4 d4 d4 d4 .word 0xd4d4d4d4
73// DISASM: $a:76// DISASM: $a:
74// DISASM-NEXT: 11070: 00 c6 8f e2 add r12, pc, #0, #1277// DISASM-NEXT: 11070: 00 c6 8f e2 add r12, pc, #0, #12
75// DISASM-NEXT: 11074: 02 ca 8c e2 add r12, r12, #819278// DISASM-NEXT: 11074: 01 ca 8c e2 add r12, r12, #4096
76// DISASM-NEXT: 11078: 0c f0 bc e5 ldr pc, [r12, #12]!79// DISASM-NEXT: 11078: 0c f0 bc e5 ldr pc, [r12, #12]!
77// DISASM: $d:80// DISASM: $d:
78// DISASM-NEXT: 1107c: d4 d4 d4 d4 .word 0xd4d4d4d481// DISASM-NEXT: 1107c: d4 d4 d4 d4 .word 0xd4d4d4d4
deps/lld/test/ELF/arm-gnu-ifunc.s+4-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
3// RUN: ld.lld -static %t.o -o %tout3// RUN: ld.lld -static %t.o -o %tout
4// RUN: llvm-objdump -triple armv7a-none-linux-gnueabi -d %tout | FileCheck %s --check-prefix=DISASM4// RUN: llvm-objdump -triple armv7a-none-linux-gnueabi -d %tout | FileCheck %s --check-prefix=DISASM
5// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s5// RUN: llvm-readobj -r --symbols --sections %tout | FileCheck %s
6 .syntax unified6 .syntax unified
7 .text7 .text
8 .type foo STT_GNU_IFUNC8 .type foo STT_GNU_IFUNC
...@@ -113,6 +113,7 @@ _start:...@@ -113,6 +113,7 @@ _start:
113// CHECK-NEXT: }113// CHECK-NEXT: }
114114
115// DISASM: Disassembly of section .text:115// DISASM: Disassembly of section .text:
116// DISASM-EMPTY:
116// DISASM-NEXT: foo:117// DISASM-NEXT: foo:
117// DISASM-NEXT: 11000: 1e ff 2f e1 bx lr118// DISASM-NEXT: 11000: 1e ff 2f e1 bx lr
118// DISASM: bar:119// DISASM: bar:
...@@ -126,7 +127,9 @@ _start:...@@ -126,7 +127,9 @@ _start:
126// 1 * 65536 + 260 = 0x10104 __rel_iplt_end127// 1 * 65536 + 260 = 0x10104 __rel_iplt_end
127// DISASM-NEXT: 11018: 04 01 00 e3 movw r0, #260128// DISASM-NEXT: 11018: 04 01 00 e3 movw r0, #260
128// DISASM-NEXT: 1101c: 01 00 40 e3 movt r0, #1129// DISASM-NEXT: 1101c: 01 00 40 e3 movt r0, #1
130// DISASM-EMPTY:
129// DISASM-NEXT: Disassembly of section .plt:131// DISASM-NEXT: Disassembly of section .plt:
132// DISASM-EMPTY:
130// DISASM-NEXT: $a:133// DISASM-NEXT: $a:
131// DISASM-NEXT: 11020: 00 c6 8f e2 add r12, pc, #0, #12134// DISASM-NEXT: 11020: 00 c6 8f e2 add r12, pc, #0, #12
132// DISASM-NEXT: 11024: 00 ca 8c e2 add r12, r12, #0, #20135// DISASM-NEXT: 11024: 00 ca 8c e2 add r12, r12, #0, #20
deps/lld/test/ELF/arm-got-relative.s+2-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -position-independent -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o2// RUN: llvm-mc -position-independent -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
3// RUN: ld.lld --hash-style=sysv %t.o -shared -o %t3// RUN: ld.lld --hash-style=sysv %t.o -shared -o %t
4// RUN: llvm-readobj -s -symbols -dyn-relocations %t | FileCheck %s4// RUN: llvm-readobj -S --symbols --dyn-relocations %t | FileCheck %s
5// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t | FileCheck -check-prefix=CODE %s5// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t | FileCheck -check-prefix=CODE %s
6 .syntax unified6 .syntax unified
7 .text7 .text
...@@ -41,6 +41,7 @@ function:...@@ -41,6 +41,7 @@ function:
41// CHECK-NEXT: Section: .got41// CHECK-NEXT: Section: .got
4242
43// CODE: Disassembly of section .text:43// CODE: Disassembly of section .text:
44// CODE-EMPTY:
44// CODE-NEXT: _start:45// CODE-NEXT: _start:
45// CODE-NEXT: 1000: 08 30 9f e5 ldr r3, [pc, #8]46// CODE-NEXT: 1000: 08 30 9f e5 ldr r3, [pc, #8]
46// CODE-NEXT: 1004: 08 20 9f e5 ldr r2, [pc, #8]47// CODE-NEXT: 1004: 08 20 9f e5 ldr r2, [pc, #8]
deps/lld/test/ELF/arm-gotoff.s+2-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabi %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabi %s -o %t.o
3// RUN: ld.lld %t.o -o %t3// RUN: ld.lld %t.o -o %t
4// RUN: llvm-readobj -s -r -t %t | FileCheck %s4// RUN: llvm-readobj -S -r --symbols %t | FileCheck %s
5// RUN: llvm-objdump -triple=armv7a-linux-gnueabi -d %t | FileCheck --check-prefix=DISASM %s5// RUN: llvm-objdump -triple=armv7a-linux-gnueabi -d %t | FileCheck --check-prefix=DISASM %s
66
7// Test the R_ARM_GOTOFF32 relocation7// Test the R_ARM_GOTOFF32 relocation
...@@ -53,6 +53,7 @@...@@ -53,6 +53,7 @@
53// CHECK-NEXT: Section: .bss53// CHECK-NEXT: Section: .bss
5454
55// DISASM: Disassembly of section .text:55// DISASM: Disassembly of section .text:
56// DISASM-EMPTY:
56// DISASM-NEXT :_start:57// DISASM-NEXT :_start:
57// DISASM-NEXT 11000: 1e ff 2f e1 bx lr58// DISASM-NEXT 11000: 1e ff 2f e1 bx lr
58// Offset 0 from .got = bar59// Offset 0 from .got = bar
deps/lld/test/ELF/arm-icf-exidx.s+1
...@@ -23,6 +23,7 @@ __aeabi_unwind_cpp_pr0:...@@ -23,6 +23,7 @@ __aeabi_unwind_cpp_pr0:
23 bx lr23 bx lr
2424
25// CHECK: Disassembly of section .text:25// CHECK: Disassembly of section .text:
26// CHECK-EMPTY:
26// CHECK-NEXT: g:27// CHECK-NEXT: g:
27// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr28// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr
28// CHECK: __aeabi_unwind_cpp_pr0:29// CHECK: __aeabi_unwind_cpp_pr0:
deps/lld/test/ELF/arm-mov-relocs.s+2
...@@ -18,6 +18,7 @@ _start:...@@ -18,6 +18,7 @@ _start:
18 movw r3, :lower16:label318 movw r3, :lower16:label3
19 movw r4, :lower16:label3 + 419 movw r4, :lower16:label3 + 4
20// CHECK: Disassembly of section .R_ARM_MOVW_ABS_NC20// CHECK: Disassembly of section .R_ARM_MOVW_ABS_NC
21// CHECK-EMPTY:
21// CHECK: movw r0, #022// CHECK: movw r0, #0
22// CHECK: movw r1, #423// CHECK: movw r1, #4
23// CHECK: movw r2, #1224// CHECK: movw r2, #12
...@@ -30,6 +31,7 @@ _start:...@@ -30,6 +31,7 @@ _start:
30 movt r3, :upper16:label331 movt r3, :upper16:label3
31 movt r4, :upper16:label3 + 432 movt r4, :upper16:label3 + 4
32// CHECK: Disassembly of section .R_ARM_MOVT_ABS33// CHECK: Disassembly of section .R_ARM_MOVT_ABS
34// CHECK-EMPTY:
33// CHECK: movt r0, #235// CHECK: movt r0, #2
34// CHECK: movt r1, #236// CHECK: movt r1, #2
35// CHECK: movt r2, #237// CHECK: movt r2, #2
deps/lld/test/ELF/arm-pie-relative.s+2-2
...@@ -19,7 +19,7 @@ sym:...@@ -19,7 +19,7 @@ sym:
1919
20// CHECK: Relocations [20// CHECK: Relocations [
21// CHECK-NEXT: Section (4) .rel.dyn {21// CHECK-NEXT: Section (4) .rel.dyn {
22// CHECK-NEXT: 0x3058 R_ARM_RELATIVE22// CHECK-NEXT: 0x2058 R_ARM_RELATIVE
2323
24// GOT: Contents of section .got:24// GOT: Contents of section .got:
25// GOT-NEXT: 3058 0020000025// GOT-NEXT: 2058 00300000
deps/lld/test/ELF/arm-plt-reloc.s+29-16
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t | FileCheck %s5// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t | FileCheck %s
6// RUN: ld.lld --hash-style=sysv -shared %t1 %t2 -o %t36// RUN: ld.lld --hash-style=sysv -shared %t1 %t2 -o %t3
7// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSO %s7// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSO %s
8// RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s8// RUN: llvm-readobj -S -r %t3 | FileCheck -check-prefix=DSOREL %s
9//9//
10// Test PLT entry generation10// Test PLT entry generation
11 .syntax unified11 .syntax unified
...@@ -20,6 +20,7 @@ _start:...@@ -20,6 +20,7 @@ _start:
2020
21// Executable, expect no PLT21// Executable, expect no PLT
22// CHECK: Disassembly of section .text:22// CHECK: Disassembly of section .text:
23// CHECK-EMPTY:
23// CHECK-NEXT: func1:24// CHECK-NEXT: func1:
24// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr25// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr
25// CHECK: func2:26// CHECK: func2:
...@@ -34,6 +35,7 @@ _start:...@@ -34,6 +35,7 @@ _start:
34// Expect PLT entries as symbols can be preempted35// Expect PLT entries as symbols can be preempted
35// The .got.plt and .plt displacement is small so we can use small PLT entries.36// The .got.plt and .plt displacement is small so we can use small PLT entries.
36// DSO: Disassembly of section .text:37// DSO: Disassembly of section .text:
38// DSO-EMPTY:
37// DSO-NEXT: func1:39// DSO-NEXT: func1:
38// DSO-NEXT: 1000: 1e ff 2f e1 bx lr40// DSO-NEXT: 1000: 1e ff 2f e1 bx lr
39// DSO: func2:41// DSO: func2:
...@@ -47,12 +49,14 @@ _start:...@@ -47,12 +49,14 @@ _start:
47// DSO-NEXT: 1010: 0e 00 00 eb bl #5649// DSO-NEXT: 1010: 0e 00 00 eb bl #56
48// S(0x10160) - P(0x1014) + A(-8) = 0x44 = 6850// S(0x10160) - P(0x1014) + A(-8) = 0x44 = 68
49// DSO-NEXT: 1014: 11 00 00 0a beq #6851// DSO-NEXT: 1014: 11 00 00 0a beq #68
52// DSO-EMPTY:
50// DSO-NEXT: Disassembly of section .plt:53// DSO-NEXT: Disassembly of section .plt:
54// DSO-EMPTY:
51// DSO-NEXT: $a:55// DSO-NEXT: $a:
52// DSO-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]!56// DSO-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]!
53// (0x1024 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfdc) = 0x2008 = .got.plt[3]57// (0x1024 + 8) + (0 RoR 12) + 4096 + (0xfdc) = 0x3008 = .got.plt[3]
54// DSO-NEXT: 1024: 00 e6 8f e2 add lr, pc, #0, #1258// DSO-NEXT: 1024: 00 e6 8f e2 add lr, pc, #0, #12
55// DSO-NEXT: 1028: 00 ea 8e e2 add lr, lr, #0, #2059// DSO-NEXT: 1028: 01 ea 8e e2 add lr, lr, #4096
56// DSO-NEXT: 102c: dc ff be e5 ldr pc, [lr, #4060]!60// DSO-NEXT: 102c: dc ff be e5 ldr pc, [lr, #4060]!
57// DSO: $d:61// DSO: $d:
58// DSO-NEXT: 1030: d4 d4 d4 d4 .word 0xd4d4d4d462// DSO-NEXT: 1030: d4 d4 d4 d4 .word 0xd4d4d4d4
...@@ -60,23 +64,23 @@ _start:...@@ -60,23 +64,23 @@ _start:
60// DSO-NEXT: 1038: d4 d4 d4 d4 .word 0xd4d4d4d464// DSO-NEXT: 1038: d4 d4 d4 d4 .word 0xd4d4d4d4
61// DSO-NEXT: 103c: d4 d4 d4 d4 .word 0xd4d4d4d465// DSO-NEXT: 103c: d4 d4 d4 d4 .word 0xd4d4d4d4
62// DSO: $a:66// DSO: $a:
63// (0x1040 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfc4) = 0x200c67// (0x1040 + 8) + (0 RoR 12) + 4096 + (0xfc4) = 0x300c
64// DSO-NEXT: 1040: 00 c6 8f e2 add r12, pc, #0, #1268// DSO-NEXT: 1040: 00 c6 8f e2 add r12, pc, #0, #12
65// DSO-NEXT: 1044: 00 ca 8c e2 add r12, r12, #0, #2069// DSO-NEXT: 1044: 01 ca 8c e2 add r12, r12, #4096
66// DSO-NEXT: 1048: c4 ff bc e5 ldr pc, [r12, #4036]!70// DSO-NEXT: 1048: c4 ff bc e5 ldr pc, [r12, #4036]!
67// DSO: $d:71// DSO: $d:
68// DSO-NEXT: 104c: d4 d4 d4 d4 .word 0xd4d4d4d472// DSO-NEXT: 104c: d4 d4 d4 d4 .word 0xd4d4d4d4
69// DSO: $a:73// DSO: $a:
70// (0x1050 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfb8) = 0x201074// (0x1050 + 8) + (0 RoR 12) + 4096 + (0xfb8) = 0x3010
71// DSO-NEXT: 1050: 00 c6 8f e2 add r12, pc, #0, #1275// DSO-NEXT: 1050: 00 c6 8f e2 add r12, pc, #0, #12
72// DSO-NEXT: 1054: 00 ca 8c e2 add r12, r12, #0, #2076// DSO-NEXT: 1054: 01 ca 8c e2 add r12, r12, #4096
73// DSO-NEXT: 1058: b8 ff bc e5 ldr pc, [r12, #4024]!77// DSO-NEXT: 1058: b8 ff bc e5 ldr pc, [r12, #4024]!
74// DSO: $d:78// DSO: $d:
75// DSO-NEXT: 105c: d4 d4 d4 d4 .word 0xd4d4d4d479// DSO-NEXT: 105c: d4 d4 d4 d4 .word 0xd4d4d4d4
76// DSO: $a:80// DSO: $a:
77// (0x1060 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfac) = 0x201481// (0x1060 + 8) + (0 RoR 12) + 4096 + (0xfac) = 0x3014
78// DSO-NEXT: 1060: 00 c6 8f e2 add r12, pc, #0, #1282// DSO-NEXT: 1060: 00 c6 8f e2 add r12, pc, #0, #12
79// DSO-NEXT: 1064: 00 ca 8c e2 add r12, r12, #0, #2083// DSO-NEXT: 1064: 01 ca 8c e2 add r12, r12, #4096
80// DSO-NEXT: 1068: ac ff bc e5 ldr pc, [r12, #4012]!84// DSO-NEXT: 1068: ac ff bc e5 ldr pc, [r12, #4012]!
81// DSO: $d:85// DSO: $d:
82// DSO-NEXT: 106c: d4 d4 d4 d4 .word 0xd4d4d4d486// DSO-NEXT: 106c: d4 d4 d4 d4 .word 0xd4d4d4d4
...@@ -88,7 +92,7 @@ _start:...@@ -88,7 +92,7 @@ _start:
88// DSOREL-NEXT: SHF_ALLOC92// DSOREL-NEXT: SHF_ALLOC
89// DSOREL-NEXT: SHF_WRITE93// DSOREL-NEXT: SHF_WRITE
90// DSOREL-NEXT: ]94// DSOREL-NEXT: ]
91// DSOREL-NEXT: Address: 0x200095// DSOREL-NEXT: Address: 0x3000
92// DSOREL-NEXT: Offset:96// DSOREL-NEXT: Offset:
93// DSOREL-NEXT: Size: 2497// DSOREL-NEXT: Size: 24
94// DSOREL-NEXT: Link:98// DSOREL-NEXT: Link:
...@@ -97,9 +101,9 @@ _start:...@@ -97,9 +101,9 @@ _start:
97// DSOREL-NEXT: EntrySize:101// DSOREL-NEXT: EntrySize:
98// DSOREL: Relocations [102// DSOREL: Relocations [
99// DSOREL-NEXT: Section {{.*}} .rel.plt {103// DSOREL-NEXT: Section {{.*}} .rel.plt {
100// DSOREL-NEXT: 0x200C R_ARM_JUMP_SLOT func1 0x0104// DSOREL-NEXT: 0x300C R_ARM_JUMP_SLOT func1 0x0
101// DSOREL-NEXT: 0x2010 R_ARM_JUMP_SLOT func2 0x0105// DSOREL-NEXT: 0x3010 R_ARM_JUMP_SLOT func2 0x0
102// DSOREL-NEXT: 0x2014 R_ARM_JUMP_SLOT func3 0x0106// DSOREL-NEXT: 0x3014 R_ARM_JUMP_SLOT func3 0x0
103107
104// Test a large separation between the .plt and .got.plt108// Test a large separation between the .plt and .got.plt
105// The .got.plt and .plt displacement is large but still within the range109// The .got.plt and .plt displacement is large but still within the range
...@@ -111,9 +115,10 @@ _start:...@@ -111,9 +115,10 @@ _start:
111// RUN: }" > %t.script115// RUN: }" > %t.script
112// RUN: ld.lld --hash-style=sysv --script %t.script -shared %t1 %t2 -o %t4116// RUN: ld.lld --hash-style=sysv --script %t.script -shared %t1 %t2 -o %t4
113// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t4 | FileCheck --check-prefix=CHECKHIGH %s117// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t4 | FileCheck --check-prefix=CHECKHIGH %s
114// RUN: llvm-readobj -s -r %t4 | FileCheck --check-prefix=DSORELHIGH %s118// RUN: llvm-readobj -S -r %t4 | FileCheck --check-prefix=DSORELHIGH %s
115119
116// CHECKHIGH: Disassembly of section .text:120// CHECKHIGH: Disassembly of section .text:
121// CHECKHIGH-EMPTY:
117// CHECKHIGH-NEXT: func1:122// CHECKHIGH-NEXT: func1:
118// CHECKHIGH-NEXT: 1000: 1e ff 2f e1 bx lr123// CHECKHIGH-NEXT: 1000: 1e ff 2f e1 bx lr
119// CHECKHIGH: func2:124// CHECKHIGH: func2:
...@@ -124,7 +129,9 @@ _start:...@@ -124,7 +129,9 @@ _start:
124// CHECKHIGH-NEXT: 100c: 03 04 00 ea b #4108 <$a>129// CHECKHIGH-NEXT: 100c: 03 04 00 ea b #4108 <$a>
125// CHECKHIGH-NEXT: 1010: 06 04 00 eb bl #4120 <$a>130// CHECKHIGH-NEXT: 1010: 06 04 00 eb bl #4120 <$a>
126// CHECKHIGH-NEXT: 1014: 09 04 00 0a beq #4132 <$a>131// CHECKHIGH-NEXT: 1014: 09 04 00 0a beq #4132 <$a>
132// CHECKHIGH-EMPTY:
127// CHECKHIGH-NEXT: Disassembly of section .plt:133// CHECKHIGH-NEXT: Disassembly of section .plt:
134// CHECKHIGH-EMPTY:
128// CHECKHIGH-NEXT: $a:135// CHECKHIGH-NEXT: $a:
129// CHECKHIGH-NEXT: 2000: 04 e0 2d e5 str lr, [sp, #-4]!136// CHECKHIGH-NEXT: 2000: 04 e0 2d e5 str lr, [sp, #-4]!
130// CHECKHIGH-NEXT: 2004: 10 e6 8f e2 add lr, pc, #16, #12137// CHECKHIGH-NEXT: 2004: 10 e6 8f e2 add lr, pc, #16, #12
...@@ -176,9 +183,10 @@ _start:...@@ -176,9 +183,10 @@ _start:
176// RUN: }" > %t2.script183// RUN: }" > %t2.script
177// RUN: ld.lld --hash-style=sysv --script %t2.script -shared %t1 %t2 -o %t5184// RUN: ld.lld --hash-style=sysv --script %t2.script -shared %t1 %t2 -o %t5
178// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t5 | FileCheck --check-prefix=CHECKLONG %s185// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t5 | FileCheck --check-prefix=CHECKLONG %s
179// RUN: llvm-readobj -s -r %t5 | FileCheck --check-prefix=DSORELLONG %s186// RUN: llvm-readobj -S -r %t5 | FileCheck --check-prefix=DSORELLONG %s
180187
181// CHECKLONG: Disassembly of section .text:188// CHECKLONG: Disassembly of section .text:
189// CHECKLONG-EMPTY:
182// CHECKLONG-NEXT: func1:190// CHECKLONG-NEXT: func1:
183// CHECKLONG-NEXT: 1000: 1e ff 2f e1 bx lr191// CHECKLONG-NEXT: 1000: 1e ff 2f e1 bx lr
184// CHECKLONG: func2:192// CHECKLONG: func2:
...@@ -189,7 +197,9 @@ _start:...@@ -189,7 +197,9 @@ _start:
189// CHECKLONG-NEXT: 100c: 03 04 00 ea b #4108 <$a>197// CHECKLONG-NEXT: 100c: 03 04 00 ea b #4108 <$a>
190// CHECKLONG-NEXT: 1010: 06 04 00 eb bl #4120 <$a>198// CHECKLONG-NEXT: 1010: 06 04 00 eb bl #4120 <$a>
191// CHECKLONG-NEXT: 1014: 09 04 00 0a beq #4132 <$a>199// CHECKLONG-NEXT: 1014: 09 04 00 0a beq #4132 <$a>
200// CHECKLONG-EMPTY:
192// CHECKLONG-NEXT: Disassembly of section .plt:201// CHECKLONG-NEXT: Disassembly of section .plt:
202// CHECKLONG-EMPTY:
193// CHECKLONG-NEXT: $a:203// CHECKLONG-NEXT: $a:
194// CHECKLONG-NEXT: 2000: 04 e0 2d e5 str lr, [sp, #-4]!204// CHECKLONG-NEXT: 2000: 04 e0 2d e5 str lr, [sp, #-4]!
195// CHECKLONG-NEXT: 2004: 04 e0 9f e5 ldr lr, [pc, #4]205// CHECKLONG-NEXT: 2004: 04 e0 9f e5 ldr lr, [pc, #4]
...@@ -242,9 +252,10 @@ _start:...@@ -242,9 +252,10 @@ _start:
242// RUN: }" > %t3.script252// RUN: }" > %t3.script
243// RUN: ld.lld --hash-style=sysv --script %t3.script -shared %t1 %t2 -o %t6253// RUN: ld.lld --hash-style=sysv --script %t3.script -shared %t1 %t2 -o %t6
244// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t6 | FileCheck --check-prefix=CHECKMIX %s254// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t6 | FileCheck --check-prefix=CHECKMIX %s
245// RUN: llvm-readobj -s -r %t6 | FileCheck --check-prefix=DSORELMIX %s255// RUN: llvm-readobj -S -r %t6 | FileCheck --check-prefix=DSORELMIX %s
246256
247// CHECKMIX: Disassembly of section .text:257// CHECKMIX: Disassembly of section .text:
258// CHECKMIX-EMPTY:
248// CHECKMIX-NEXT: func1:259// CHECKMIX-NEXT: func1:
249// CHECKMIX-NEXT: 1000: 1e ff 2f e1 bx lr260// CHECKMIX-NEXT: 1000: 1e ff 2f e1 bx lr
250// CHECKMIX: func2:261// CHECKMIX: func2:
...@@ -255,7 +266,9 @@ _start:...@@ -255,7 +266,9 @@ _start:
255// CHECKMIX-NEXT: 100c: 03 04 00 ea b #4108 <$a>266// CHECKMIX-NEXT: 100c: 03 04 00 ea b #4108 <$a>
256// CHECKMIX-NEXT: 1010: 06 04 00 eb bl #4120 <$a>267// CHECKMIX-NEXT: 1010: 06 04 00 eb bl #4120 <$a>
257// CHECKMIX-NEXT: 1014: 09 04 00 0a beq #4132 <$a>268// CHECKMIX-NEXT: 1014: 09 04 00 0a beq #4132 <$a>
269// CHECKMIX-EMPTY:
258// CHECKMIX-NEXT: Disassembly of section .plt:270// CHECKMIX-NEXT: Disassembly of section .plt:
271// CHECKMIX-EMPTY:
259// CHECKMIX-NEXT: $a:272// CHECKMIX-NEXT: $a:
260// CHECKMIX-NEXT: 2000: 04 e0 2d e5 str lr, [sp, #-4]!273// CHECKMIX-NEXT: 2000: 04 e0 2d e5 str lr, [sp, #-4]!
261// CHECKMIX-NEXT: 2004: 04 e0 9f e5 ldr lr, [pc, #4]274// CHECKMIX-NEXT: 2004: 04 e0 9f e5 ldr lr, [pc, #4]
deps/lld/test/ELF/arm-sbrel32.s+1
...@@ -31,6 +31,7 @@ foo3: .space 4...@@ -31,6 +31,7 @@ foo3: .space 4
31foo4: .space 431foo4: .space 4
3232
33// CHECK: Disassembly of section .text:33// CHECK: Disassembly of section .text:
34// CHECK-EMPTY:
34// CHECK-NEXT: _start:35// CHECK-NEXT: _start:
35// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr36// CHECK-NEXT: 11000: 1e ff 2f e1 bx lr
36// CHECK: 11004: 00 00 00 00 .word 0x0000000037// CHECK: 11004: 00 00 00 00 .word 0x00000000
deps/lld/test/ELF/arm-tag-vfp-args.s+7-7
...@@ -7,15 +7,15 @@...@@ -7,15 +7,15 @@
77
8// The default for this file is 0 (Base AAPCS)8// The default for this file is 0 (Base AAPCS)
9// RUN: ld.lld %t.o -o %tdefault9// RUN: ld.lld %t.o -o %tdefault
10// RUN: llvm-readobj -file-headers %tdefault | FileCheck -check-prefix=CHECK-BASE %s10// RUN: llvm-readobj --file-headers %tdefault | FileCheck -check-prefix=CHECK-BASE %s
1111
12// Expect explicit Base AAPCS.12// Expect explicit Base AAPCS.
13// RUN: ld.lld %t.o %tbase.o -o %tbase13// RUN: ld.lld %t.o %tbase.o -o %tbase
14// RUN: llvm-readobj -file-headers %tbase | FileCheck -check-prefix=CHECK-BASE %s14// RUN: llvm-readobj --file-headers %tbase | FileCheck -check-prefix=CHECK-BASE %s
1515
16// Expect explicit Base AAPCS when linking Base and Compatible.16// Expect explicit Base AAPCS when linking Base and Compatible.
17// RUN: ld.lld %t.o %tbase.o %tcompat.o -o %tbasecompat17// RUN: ld.lld %t.o %tbase.o %tcompat.o -o %tbasecompat
18// RUN: llvm-readobj -file-headers %tbasecompat | FileCheck -check-prefix=CHECK-BASE %s18// RUN: llvm-readobj --file-headers %tbasecompat | FileCheck -check-prefix=CHECK-BASE %s
1919
20// CHECK-BASE: Flags [ (0x5000200)20// CHECK-BASE: Flags [ (0x5000200)
21// CHECK-BASE-NEXT: 0x20021// CHECK-BASE-NEXT: 0x200
...@@ -25,11 +25,11 @@...@@ -25,11 +25,11 @@
2525
26// Expect Hard float VFP AAPCS26// Expect Hard float VFP AAPCS
27// RUN: ld.lld %t.o %tvfp.o -o %tvfp27// RUN: ld.lld %t.o %tvfp.o -o %tvfp
28// RUN: llvm-readobj -file-headers %tvfp | FileCheck -check-prefix=CHECK-VFP %s28// RUN: llvm-readobj --file-headers %tvfp | FileCheck -check-prefix=CHECK-VFP %s
2929
30// Expect Hard float VFP AAPCS when linking VFP and Compatible30// Expect Hard float VFP AAPCS when linking VFP and Compatible
31// RUN: ld.lld %t.o %tvfp.o %tcompat.o -o %tvfpcompat31// RUN: ld.lld %t.o %tvfp.o %tcompat.o -o %tvfpcompat
32// RUN: llvm-readobj -file-headers %tvfpcompat | FileCheck -check-prefix=CHECK-VFP %s32// RUN: llvm-readobj --file-headers %tvfpcompat | FileCheck -check-prefix=CHECK-VFP %s
3333
34// CHECK-VFP: Flags [ (0x5000400)34// CHECK-VFP: Flags [ (0x5000400)
35// CHECK-VFP-NEXT: 0x40035// CHECK-VFP-NEXT: 0x400
...@@ -39,11 +39,11 @@...@@ -39,11 +39,11 @@
3939
40// Expect Toolchain specifc to not use either Base or VFP AAPCS40// Expect Toolchain specifc to not use either Base or VFP AAPCS
41// RUN: ld.lld %t.o %ttoolchain.o -o %ttoolchain41// RUN: ld.lld %t.o %ttoolchain.o -o %ttoolchain
42// RUN: llvm-readobj -file-headers %ttoolchain | FileCheck -check-prefix=CHECK-TOOLCHAIN %s42// RUN: llvm-readobj --file-headers %ttoolchain | FileCheck -check-prefix=CHECK-TOOLCHAIN %s
4343
44// Expect Toolchain and Compatible to have same affect as Toolchain.44// Expect Toolchain and Compatible to have same affect as Toolchain.
45// RUN: ld.lld %t.o %ttoolchain.o %tcompat.o -o %ttoolchaincompat45// RUN: ld.lld %t.o %ttoolchain.o %tcompat.o -o %ttoolchaincompat
46// RUN: llvm-readobj -file-headers %ttoolchaincompat | FileCheck -check-prefix=CHECK-TOOLCHAIN %s46// RUN: llvm-readobj --file-headers %ttoolchaincompat | FileCheck -check-prefix=CHECK-TOOLCHAIN %s
4747
48// CHECK-TOOLCHAIN: Flags [ (0x5000000)48// CHECK-TOOLCHAIN: Flags [ (0x5000000)
49// CHECK-TOOLCHAIN-NEXT: 0x100000049// CHECK-TOOLCHAIN-NEXT: 0x1000000
deps/lld/test/ELF/arm-target1.s+1
...@@ -26,6 +26,7 @@...@@ -26,6 +26,7 @@
26// Force generation of $d.0 as section is not all data26// Force generation of $d.0 as section is not all data
27 nop27 nop
28// RELATIVE: Disassembly of section .text:28// RELATIVE: Disassembly of section .text:
29// RELATIVE-EMPTY:
29// RELATIVE: $d.0:30// RELATIVE: $d.0:
30// RELATIVE: 1000: 04 00 00 00 .word 0x0000000431// RELATIVE: 1000: 04 00 00 00 .word 0x00000004
31// RELATIVE: SYMBOL TABLE:32// RELATIVE: SYMBOL TABLE:
deps/lld/test/ELF/arm-thumb-blx.s+5
...@@ -41,14 +41,17 @@ _start:...@@ -41,14 +41,17 @@ _start:
41 bx lr41 bx lr
4242
43// CHECK-ARM: Disassembly of section .R_ARM_CALL24_callee1:43// CHECK-ARM: Disassembly of section .R_ARM_CALL24_callee1:
44// CHECK-ARM-EMPTY:
44// CHECK-NEXT-ARM: callee_low:45// CHECK-NEXT-ARM: callee_low:
45// CHECK-NEXT-ARM: b4: 1e ff 2f e1 bx lr46// CHECK-NEXT-ARM: b4: 1e ff 2f e1 bx lr
4647
47// CHECK-THUMB: Disassembly of section .R_ARM_CALL24_callee2:48// CHECK-THUMB: Disassembly of section .R_ARM_CALL24_callee2:
49// CHECK-THUMB-EMPTY:
48// CHECK-NEXT-THUMB: callee_thumb_low:50// CHECK-NEXT-THUMB: callee_thumb_low:
49// CHECK-NEXT-THUMB: 100: 70 47 bx lr51// CHECK-NEXT-THUMB: 100: 70 47 bx lr
5052
51// CHECK-THUMB: Disassembly of section .caller:53// CHECK-THUMB: Disassembly of section .caller:
54// CHECK-THUMB-EMPTY:
52// CHECK-THUMB: _start:55// CHECK-THUMB: _start:
53// Align(0x10000,4) - 0xff50 (65360) + 4 = 0xb4 = callee_low56// Align(0x10000,4) - 0xff50 (65360) + 4 = 0xb4 = callee_low
54// CHECK-NEXT-THUMB: 10000: f0 f7 58 e8 blx #-6536057// CHECK-NEXT-THUMB: 10000: f0 f7 58 e8 blx #-65360
...@@ -77,9 +80,11 @@ _start:...@@ -77,9 +80,11 @@ _start:
7780
7881
79// CHECK-ARM: Disassembly of section .R_ARM_CALL24_callee3:82// CHECK-ARM: Disassembly of section .R_ARM_CALL24_callee3:
83// CHECK-ARM-EMPTY:
80// CHECK-NEXT-ARM: callee_high:84// CHECK-NEXT-ARM: callee_high:
81// CHECK-NEXT-ARM: 10100: 1e ff 2f e1 bx lr85// CHECK-NEXT-ARM: 10100: 1e ff 2f e1 bx lr
8286
83// CHECK: Disassembly of section .R_ARM_CALL24_callee4:87// CHECK: Disassembly of section .R_ARM_CALL24_callee4:
88// CHECK-EMPTY:
84// CHECK-NEXT-THUMB:callee_thumb_high:89// CHECK-NEXT-THUMB:callee_thumb_high:
85// CHECK-NEXT-THUMB: 10200: 70 47 bx lr90// CHECK-NEXT-THUMB: 10200: 70 47 bx lr
deps/lld/test/ELF/arm-thumb-branch-rangethunk.s+1
...@@ -17,6 +17,7 @@ _start:...@@ -17,6 +17,7 @@ _start:
17 beq.w too_far317 beq.w too_far3
1818
19// CHECK: Disassembly of section .text:19// CHECK: Disassembly of section .text:
20// CHECK-EMPTY:
20// CHECK-NEXT: _start:21// CHECK-NEXT: _start:
21// CHECK-NEXT: 20000: 00 f0 04 f8 bl #822// CHECK-NEXT: 20000: 00 f0 04 f8 bl #8
22// CHECK-NEXT: 20004: 00 f0 07 b8 b.w #14 <__Thumbv7ABSLongThunk_too_far2>23// CHECK-NEXT: 20004: 00 f0 07 b8 b.w #14 <__Thumbv7ABSLongThunk_too_far2>
deps/lld/test/ELF/arm-thumb-branch.s+5
...@@ -40,9 +40,12 @@ callee_high:...@@ -40,9 +40,12 @@ callee_high:
40 bx lr40 bx lr
4141
42// CHECK: Disassembly of section .callee1:42// CHECK: Disassembly of section .callee1:
43// CHECK-EMPTY:
43// CHECK-NEXT: callee_low:44// CHECK-NEXT: callee_low:
44// CHECK-NEXT: b4: 70 47 bx lr45// CHECK-NEXT: b4: 70 47 bx lr
46// CHECK-EMPTY:
45// CHECK-NEXT: Disassembly of section .caller:47// CHECK-NEXT: Disassembly of section .caller:
48// CHECK-EMPTY:
46// CHECK-NEXT: _start:49// CHECK-NEXT: _start:
47// CHECK-NEXT: 10000: f0 f7 58 f8 bl #-6536050// CHECK-NEXT: 10000: f0 f7 58 f8 bl #-65360
48// CHECK-NEXT: 10004: f0 f7 56 b8 b.w #-6536451// CHECK-NEXT: 10004: f0 f7 56 b8 b.w #-65364
...@@ -55,6 +58,8 @@ callee_high:...@@ -55,6 +58,8 @@ callee_high:
55// CHECK-NEXT: 10020: 3f f3 ff af bgt.w #104857458// CHECK-NEXT: 10020: 3f f3 ff af bgt.w #1048574
56// CHECK-NEXT: 10024: 70 47 bx lr59// CHECK-NEXT: 10024: 70 47 bx lr
57// CHECK-NEXT: 10026:60// CHECK-NEXT: 10026:
61// CHECK-EMPTY:
58// CHECK-NEXT: Disassembly of section .callee2:62// CHECK-NEXT: Disassembly of section .callee2:
63// CHECK-EMPTY:
59// CHECK-NEXT: callee_high:64// CHECK-NEXT: callee_high:
60// CHECK-NEXT: 10028: 70 47 bx lr65// CHECK-NEXT: 10028: 70 47 bx lr
deps/lld/test/ELF/arm-thumb-condbranch-thunk.s+1
...@@ -34,6 +34,7 @@ _start:...@@ -34,6 +34,7 @@ _start:
34// Section34// Section
35 bl tfunc3335 bl tfunc33
36// CHECK1: Disassembly of section .text:36// CHECK1: Disassembly of section .text:
37// CHECK1-EMPTY:
37// CHECK1-NEXT: tfunc00:38// CHECK1-NEXT: tfunc00:
38// CHECK1-NEXT: 80000: 70 47 bx lr39// CHECK1-NEXT: 80000: 70 47 bx lr
39// CHECK1-NEXT: 80002: 7f f3 ff d7 bl #1625292640// CHECK1-NEXT: 80002: 7f f3 ff d7 bl #16252926
deps/lld/test/ELF/arm-thumb-interwork-shared.s+5-3
...@@ -15,6 +15,7 @@ sym1:...@@ -15,6 +15,7 @@ sym1:
15// entry.15// entry.
1616
17// CHECK: Disassembly of section .text:17// CHECK: Disassembly of section .text:
18// CHECK-EMPTY:
18// CHECK-NEXT: sym1:19// CHECK-NEXT: sym1:
19// CHECK-NEXT: 1000: 00 f0 02 b8 b.w #4 <__ThumbV7PILongThunk_elsewhere>20// CHECK-NEXT: 1000: 00 f0 02 b8 b.w #4 <__ThumbV7PILongThunk_elsewhere>
20// CHECK-NEXT: 1004: 00 f0 06 b8 b.w #12 <__ThumbV7PILongThunk_weakref>21// CHECK-NEXT: 1004: 00 f0 06 b8 b.w #12 <__ThumbV7PILongThunk_weakref>
...@@ -30,10 +31,11 @@ sym1:...@@ -30,10 +31,11 @@ sym1:
30// CHECK-NEXT: 101e: 60 47 bx r1231// CHECK-NEXT: 101e: 60 47 bx r12
3132
32// PLT: Disassembly of section .plt:33// PLT: Disassembly of section .plt:
34// PLT-EMPTY:
33// PLT-NEXT: $a:35// PLT-NEXT: $a:
34// PLT-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]!36// PLT-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]!
35// PLT-NEXT: 1024: 00 e6 8f e2 add lr, pc, #0, #1237// PLT-NEXT: 1024: 00 e6 8f e2 add lr, pc, #0, #12
36// PLT-NEXT: 1028: 00 ea 8e e2 add lr, lr, #0, #2038// PLT-NEXT: 1028: 01 ea 8e e2 add lr, lr, #4096
37// PLT-NEXT: 102c: dc ff be e5 ldr pc, [lr, #4060]!39// PLT-NEXT: 102c: dc ff be e5 ldr pc, [lr, #4060]!
38// PLT: $d:40// PLT: $d:
39// PLT-NEXT: 1030: d4 d4 d4 d4 .word 0xd4d4d4d441// PLT-NEXT: 1030: d4 d4 d4 d4 .word 0xd4d4d4d4
...@@ -42,13 +44,13 @@ sym1:...@@ -42,13 +44,13 @@ sym1:
42// PLT-NEXT: 103c: d4 d4 d4 d4 .word 0xd4d4d4d444// PLT-NEXT: 103c: d4 d4 d4 d4 .word 0xd4d4d4d4
43// PLT: $a:45// PLT: $a:
44// PLT-NEXT: 1040: 00 c6 8f e2 add r12, pc, #0, #1246// PLT-NEXT: 1040: 00 c6 8f e2 add r12, pc, #0, #12
45// PLT-NEXT: 1044: 00 ca 8c e2 add r12, r12, #0, #2047// PLT-NEXT: 1044: 01 ca 8c e2 add r12, r12, #4096
46// PLT-NEXT: 1048: c4 ff bc e5 ldr pc, [r12, #4036]!48// PLT-NEXT: 1048: c4 ff bc e5 ldr pc, [r12, #4036]!
47// PLT: $d:49// PLT: $d:
48// PLT-NEXT: 104c: d4 d4 d4 d4 .word 0xd4d4d4d450// PLT-NEXT: 104c: d4 d4 d4 d4 .word 0xd4d4d4d4
49// PLT: $a:51// PLT: $a:
50// PLT-NEXT: 1050: 00 c6 8f e2 add r12, pc, #0, #1252// PLT-NEXT: 1050: 00 c6 8f e2 add r12, pc, #0, #12
51// PLT-NEXT: 1054: 00 ca 8c e2 add r12, r12, #0, #2053// PLT-NEXT: 1054: 01 ca 8c e2 add r12, r12, #4096
52// PLT-NEXT: 1058: b8 ff bc e5 ldr pc, [r12, #4024]!54// PLT-NEXT: 1058: b8 ff bc e5 ldr pc, [r12, #4024]!
53// PLT: $d:55// PLT: $d:
54// PLT-NEXT: 105c: d4 d4 d4 d4 .word 0xd4d4d4d456// PLT-NEXT: 105c: d4 d4 d4 d4 .word 0xd4d4d4d4
deps/lld/test/ELF/arm-thumb-interwork-thunk.s+11-1
...@@ -19,7 +19,7 @@...@@ -19,7 +19,7 @@
19// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-ARM %s19// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t3 | FileCheck -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-ARM %s
20// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t4 | FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-PI-PLT-THUMB %s20// RUN: llvm-objdump -d -triple=thumbv7a-none-linux-gnueabi %t4 | FileCheck -check-prefix=CHECK-THUMB -check-prefix=CHECK-PI-PLT-THUMB %s
21// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t4 | FileCheck -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-PLT-ARM %s21// RUN: llvm-objdump -d -triple=armv7a-none-linux-gnueabi %t4 | FileCheck -check-prefix=CHECK-ARM -check-prefix=CHECK-PI-PLT-ARM %s
22// RUN: llvm-readobj -s -r %t4 | FileCheck -check-prefix=CHECK-DSO-REL %s22// RUN: llvm-readobj -S -r %t4 | FileCheck -check-prefix=CHECK-DSO-REL %s
2323
24// Test ARM Thumb Interworking24// Test ARM Thumb Interworking
25// The file is linked and checked 3 times to check the following contexts25// The file is linked and checked 3 times to check the following contexts
...@@ -39,6 +39,7 @@ thumb_callee1:...@@ -39,6 +39,7 @@ thumb_callee1:
39 bx lr39 bx lr
4040
41// CHECK-THUMB: Disassembly of section .R_ARM_JUMP24_callee_1:41// CHECK-THUMB: Disassembly of section .R_ARM_JUMP24_callee_1:
42// CHECK-THUMB-EMPTY:
42// CHECK-THUMB: thumb_callee1:43// CHECK-THUMB: thumb_callee1:
43// CHECK-THUMB: 1000: 70 47 bx44// CHECK-THUMB: 1000: 70 47 bx
44 .section .R_ARM_THM_JUMP_callee_low, "ax", %progbits45 .section .R_ARM_THM_JUMP_callee_low, "ax", %progbits
...@@ -79,6 +80,7 @@ arm_caller:...@@ -79,6 +80,7 @@ arm_caller:
79 bne arm_callee380 bne arm_callee3
80 bx lr81 bx lr
81// CHECK-ARM-ABS-ARM: Disassembly of section .arm_caller:82// CHECK-ARM-ABS-ARM: Disassembly of section .arm_caller:
83// CHECK-ARM-ABS-ARM-EMPTY:
82// CHECK-ARM-ABS-ARM-NEXT: arm_caller:84// CHECK-ARM-ABS-ARM-NEXT: arm_caller:
83// CHECK-ARM-ABS-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>85// CHECK-ARM-ABS-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>
84// CHECK-ARM-ABS-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>86// CHECK-ARM-ABS-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>
...@@ -107,6 +109,7 @@ arm_caller:...@@ -107,6 +109,7 @@ arm_caller:
107// CHECK-ARM-ABS-ARM-NEXT: 1348: 1c ff 2f e1 bx r12109// CHECK-ARM-ABS-ARM-NEXT: 1348: 1c ff 2f e1 bx r12
108110
109// CHECK-PI-ARM: Disassembly of section .arm_caller:111// CHECK-PI-ARM: Disassembly of section .arm_caller:
112// CHECK-PI-ARM-EMPTY:
110// CHECK-PI-ARM-NEXT: arm_caller:113// CHECK-PI-ARM-NEXT: arm_caller:
111// CHECK-PI-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>114// CHECK-PI-ARM-NEXT: 1300: 3e ff ff fa blx #-776 <thumb_callee1>
112// CHECK-PI-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>115// CHECK-PI-ARM-NEXT: 1304: 3d ff ff fa blx #-780 <thumb_callee1>
...@@ -140,6 +143,7 @@ arm_caller:...@@ -140,6 +143,7 @@ arm_caller:
140143
141// All PLT entries are ARM, no need for interworking thunks144// All PLT entries are ARM, no need for interworking thunks
142// CHECK-PI-ARM-PLT: Disassembly of section .arm_caller:145// CHECK-PI-ARM-PLT: Disassembly of section .arm_caller:
146// CHECK-PI-ARM-PLT-EMPTY:
143// CHECK-PI-ARM-PLT-NEXT: arm_caller:147// CHECK-PI-ARM-PLT-NEXT: arm_caller:
144// 0x17e4 PLT(thumb_callee1)148// 0x17e4 PLT(thumb_callee1)
145// CHECK-PI-ARM-PLT-NEXT: 1300: 37 01 00 eb bl #1244149// CHECK-PI-ARM-PLT-NEXT: 1300: 37 01 00 eb bl #1244
...@@ -184,6 +188,7 @@ thumb_caller:...@@ -184,6 +188,7 @@ thumb_caller:
184 beq.w arm_callee2188 beq.w arm_callee2
185 bne.w arm_callee3189 bne.w arm_callee3
186// CHECK-ABS-THUMB: Disassembly of section .thumb_caller:190// CHECK-ABS-THUMB: Disassembly of section .thumb_caller:
191// CHECK-ABS-THUMB-EMPTY:
187// CHECK-ABS-THUMB-NEXT: thumb_caller:192// CHECK-ABS-THUMB-NEXT: thumb_caller:
188// CHECK-ABS-THUMB-NEXT: 1400: ff f7 7e ee blx #-772193// CHECK-ABS-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
189// CHECK-ABS-THUMB-NEXT: 1404: ff f7 7c ee blx #-776194// CHECK-ABS-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
...@@ -210,6 +215,7 @@ thumb_caller:...@@ -210,6 +215,7 @@ thumb_caller:
210// CHECK-ABS-THUMB-NEXT: 143c: 60 47 bx r12215// CHECK-ABS-THUMB-NEXT: 143c: 60 47 bx r12
211216
212// CHECK-PI-THUMB: Disassembly of section .thumb_caller:217// CHECK-PI-THUMB: Disassembly of section .thumb_caller:
218// CHECK-PI-THUMB-EMPTY:
213// CHECK-PI-THUMB-NEXT: thumb_caller:219// CHECK-PI-THUMB-NEXT: thumb_caller:
214// CHECK-PI-THUMB-NEXT: 1400: ff f7 7e ee blx #-772220// CHECK-PI-THUMB-NEXT: 1400: ff f7 7e ee blx #-772
215// CHECK-PI-THUMB-NEXT: 1404: ff f7 7c ee blx #-776221// CHECK-PI-THUMB-NEXT: 1404: ff f7 7c ee blx #-776
...@@ -239,6 +245,7 @@ thumb_caller:...@@ -239,6 +245,7 @@ thumb_caller:
239// CHECK-PI-THUMB-NEXT: 1442: 60 47 bx r12245// CHECK-PI-THUMB-NEXT: 1442: 60 47 bx r12
240246
241// CHECK-PI-THUMB-PLT: Disassembly of section .arm_caller:247// CHECK-PI-THUMB-PLT: Disassembly of section .arm_caller:
248// CHECK-PI-THUMB-PLT-EMPTY:
242// CHECK-PI-THUMB-PLT-NEXT: thumb_caller:249// CHECK-PI-THUMB-PLT-NEXT: thumb_caller:
243// 0x1400 + 4 + 0x410 = 0x1814 = PLT(arm_callee1)250// 0x1400 + 4 + 0x410 = 0x1814 = PLT(arm_callee1)
244// CHECK-PI-THUMB-PLT-NEXT: 1400: 00 f0 08 ea blx #1040251// CHECK-PI-THUMB-PLT-NEXT: 1400: 00 f0 08 ea blx #1040
...@@ -286,6 +293,7 @@ thumb_callee2:...@@ -286,6 +293,7 @@ thumb_callee2:
286thumb_callee3:293thumb_callee3:
287 bx lr294 bx lr
288// CHECK-THUMB: Disassembly of section .R_ARM_JUMP24_callee_2:295// CHECK-THUMB: Disassembly of section .R_ARM_JUMP24_callee_2:
296// CHECK-THUMB-EMPTY:
289// CHECK-THUMB-NEXT: thumb_callee2:297// CHECK-THUMB-NEXT: thumb_callee2:
290// CHECK-THUMB-NEXT: 1500: 70 47 bx lr298// CHECK-THUMB-NEXT: 1500: 70 47 bx lr
291// CHECK-THUMB: thumb_callee3:299// CHECK-THUMB: thumb_callee3:
...@@ -303,6 +311,7 @@ arm_callee2:...@@ -303,6 +311,7 @@ arm_callee2:
303arm_callee3:311arm_callee3:
304 bx lr312 bx lr
305// CHECK-ARM: Disassembly of section .R_ARM_THM_JUMP_callee_2:313// CHECK-ARM: Disassembly of section .R_ARM_THM_JUMP_callee_2:
314// CHECK-ARM-EMPTY:
306// CHECK-ARM-NEXT: arm_callee2:315// CHECK-ARM-NEXT: arm_callee2:
307// CHECK-ARM-NEXT: 1600: 1e ff 2f e1 bx lr316// CHECK-ARM-NEXT: 1600: 1e ff 2f e1 bx lr
308// CHECK-ARM: arm_callee3:317// CHECK-ARM: arm_callee3:
...@@ -321,6 +330,7 @@ _start:...@@ -321,6 +330,7 @@ _start:
321330
322331
323// CHECK-PI-ARM-PLT: Disassembly of section .plt:332// CHECK-PI-ARM-PLT: Disassembly of section .plt:
333// CHECK-PI-ARM-PLT-EMPTY:
324// CHECK-PI-ARM-PLT-NEXT: .plt:334// CHECK-PI-ARM-PLT-NEXT: .plt:
325// CHECK-PI-ARM-PLT-NEXT: 17b0: 04 e0 2d e5 str lr, [sp, #-4]!335// CHECK-PI-ARM-PLT-NEXT: 17b0: 04 e0 2d e5 str lr, [sp, #-4]!
326// CHECK-PI-ARM-PLT-NEXT: 17b4: 04 e0 9f e5 ldr lr, [pc, #4]336// CHECK-PI-ARM-PLT-NEXT: 17b4: 04 e0 9f e5 ldr lr, [pc, #4]
deps/lld/test/ELF/arm-thumb-narrow-branch-check.s+7
...@@ -50,9 +50,12 @@ callee_high:...@@ -50,9 +50,12 @@ callee_high:
50callee_high_far = 0x180d50callee_high_far = 0x180d
5151
52// CHECK: Disassembly of section .R_ARM_PC11_1:52// CHECK: Disassembly of section .R_ARM_PC11_1:
53// CHECK-EMPTY:
53// CHECK-NEXT: callee_low:54// CHECK-NEXT: callee_low:
54// CHECK-NEXT: 1000: 70 47 bx lr55// CHECK-NEXT: 1000: 70 47 bx lr
56// CHECK-EMPTY:
55// CHECK-NEXT: Disassembly of section .caller:57// CHECK-NEXT: Disassembly of section .caller:
58// CHECK-EMPTY:
56// CHECK-NEXT: callers:59// CHECK-NEXT: callers:
57// 1004 - 0x800 (2048) + 4 = 0x808 = callee_low_far60// 1004 - 0x800 (2048) + 4 = 0x808 = callee_low_far
58// CHECK-NEXT: 1004: 00 e4 b #-204861// CHECK-NEXT: 1004: 00 e4 b #-2048
...@@ -64,10 +67,14 @@ callee_high_far = 0x180d...@@ -64,10 +67,14 @@ callee_high_far = 0x180d
64// CHECK-NEXT: 100a: ff e3 b #204667// CHECK-NEXT: 100a: ff e3 b #2046
65// CHECK-NEXT: 100c: 70 47 bx lr68// CHECK-NEXT: 100c: 70 47 bx lr
66// CHECK-NEXT: 100e: 00 bf nop69// CHECK-NEXT: 100e: 00 bf nop
70// CHECK-EMPTY:
67// CHECK-NEXT: Disassembly of section .R_ARM_PC11_2:71// CHECK-NEXT: Disassembly of section .R_ARM_PC11_2:
72// CHECK-EMPTY:
68// CHECK-NEXT: callee_high:73// CHECK-NEXT: callee_high:
69// CHECK-NEXT: 1010: 70 47 bx lr74// CHECK-NEXT: 1010: 70 47 bx lr
75// CHECK-EMPTY:
70// CHECK-NEXT: Disassembly of section .text:76// CHECK-NEXT: Disassembly of section .text:
77// CHECK-EMPTY:
71// CHECK-NEXT: _start:78// CHECK-NEXT: _start:
72// CHECK-NEXT: 1014: ff f7 f6 ff bl #-2079// CHECK-NEXT: 1014: ff f7 f6 ff bl #-20
73// CHECK-NEXT: 1018: 70 47 bx lr80// CHECK-NEXT: 1018: 70 47 bx lr
deps/lld/test/ELF/arm-thumb-no-undefined-thunk.s+1
...@@ -17,6 +17,7 @@ _start:...@@ -17,6 +17,7 @@ _start:
17 b.w target17 b.w target
1818
19// CHECK: Disassembly of section .text:19// CHECK: Disassembly of section .text:
20// CHECK-EMPTY:
20// CHECK-NEXT: _start:21// CHECK-NEXT: _start:
21// 69636 = 0x11004 = next instruction22// 69636 = 0x11004 = next instruction
22// CHECK: 11000: {{.*}} bl #023// CHECK: 11000: {{.*}} bl #0
deps/lld/test/ELF/arm-thumb-plt-range-thunk-os.s+6-4
...@@ -35,6 +35,7 @@ preemptible:...@@ -35,6 +35,7 @@ preemptible:
35 bl far_nonpreemptible_alias35 bl far_nonpreemptible_alias
36 bx lr36 bx lr
37// CHECK1: Disassembly of section .text:37// CHECK1: Disassembly of section .text:
38// CHECK1-EMPTY:
38// CHECK1-NEXT: sym1:39// CHECK1-NEXT: sym1:
39// CHECK1-NEXT: 2000000: 00 f0 00 d8 bl #838860840// CHECK1-NEXT: 2000000: 00 f0 00 d8 bl #8388608
40// CHECK1-NEXT: 2000004: 00 f0 04 d8 bl #838861641// CHECK1-NEXT: 2000004: 00 f0 04 d8 bl #8388616
...@@ -84,10 +85,11 @@ far_nonpreemptible_alias:...@@ -84,10 +85,11 @@ far_nonpreemptible_alias:
84// CHECK3: 4000000: 00 f0 16 e8 blx #4485// CHECK3: 4000000: 00 f0 16 e8 blx #44
8586
86// CHECK4: Disassembly of section .plt:87// CHECK4: Disassembly of section .plt:
88// CHECK4-EMPTY:
87// CHECK4-NEXT: $a:89// CHECK4-NEXT: $a:
88// CHECK4-NEXT: 4000010: 04 e0 2d e5 str lr, [sp, #-4]!90// CHECK4-NEXT: 4000010: 04 e0 2d e5 str lr, [sp, #-4]!
89// CHECK4-NEXT: 4000014: 00 e6 8f e2 add lr, pc, #0, #1291// CHECK4-NEXT: 4000014: 00 e6 8f e2 add lr, pc, #0, #12
90// CHECK4-NEXT: 4000018: 00 ea 8e e2 add lr, lr, #0, #2092// CHECK4-NEXT: 4000018: 01 ea 8e e2 add lr, lr, #4096
91// CHECK4-NEXT: 400001c: ec ff be e5 ldr pc, [lr, #4076]!93// CHECK4-NEXT: 400001c: ec ff be e5 ldr pc, [lr, #4076]!
92// CHECK4: $d:94// CHECK4: $d:
93// CHECK4-NEXT: 4000020: d4 d4 d4 d4 .word 0xd4d4d4d495// CHECK4-NEXT: 4000020: d4 d4 d4 d4 .word 0xd4d4d4d4
...@@ -96,19 +98,19 @@ far_nonpreemptible_alias:...@@ -96,19 +98,19 @@ far_nonpreemptible_alias:
96// CHECK4-NEXT: 400002c: d4 d4 d4 d4 .word 0xd4d4d4d498// CHECK4-NEXT: 400002c: d4 d4 d4 d4 .word 0xd4d4d4d4
97// CHECK4: $a:99// CHECK4: $a:
98// CHECK4-NEXT: 4000030: 00 c6 8f e2 add r12, pc, #0, #12100// CHECK4-NEXT: 4000030: 00 c6 8f e2 add r12, pc, #0, #12
99// CHECK4-NEXT: 4000034: 00 ca 8c e2 add r12, r12, #0, #20101// CHECK4-NEXT: 4000034: 01 ca 8c e2 add r12, r12, #4096
100// CHECK4-NEXT: 4000038: d4 ff bc e5 ldr pc, [r12, #4052]!102// CHECK4-NEXT: 4000038: d4 ff bc e5 ldr pc, [r12, #4052]!
101// CHECK4: $d:103// CHECK4: $d:
102// CHECK4-NEXT: 400003c: d4 d4 d4 d4 .word 0xd4d4d4d4104// CHECK4-NEXT: 400003c: d4 d4 d4 d4 .word 0xd4d4d4d4
103// CHECK4: $a:105// CHECK4: $a:
104// CHECK4-NEXT: 4000040: 00 c6 8f e2 add r12, pc, #0, #12106// CHECK4-NEXT: 4000040: 00 c6 8f e2 add r12, pc, #0, #12
105// CHECK4-NEXT: 4000044: 00 ca 8c e2 add r12, r12, #0, #20107// CHECK4-NEXT: 4000044: 01 ca 8c e2 add r12, r12, #4096
106// CHECK4-NEXT: 4000048: c8 ff bc e5 ldr pc, [r12, #4040]!108// CHECK4-NEXT: 4000048: c8 ff bc e5 ldr pc, [r12, #4040]!
107// CHECK4: $d:109// CHECK4: $d:
108// CHECK4-NEXT: 400004c: d4 d4 d4 d4 .word 0xd4d4d4d4110// CHECK4-NEXT: 400004c: d4 d4 d4 d4 .word 0xd4d4d4d4
109// CHECK4: $a:111// CHECK4: $a:
110// CHECK4-NEXT: 4000050: 00 c6 8f e2 add r12, pc, #0, #12112// CHECK4-NEXT: 4000050: 00 c6 8f e2 add r12, pc, #0, #12
111// CHECK4-NEXT: 4000054: 00 ca 8c e2 add r12, r12, #0, #20113// CHECK4-NEXT: 4000054: 01 ca 8c e2 add r12, r12, #4096
112// CHECK4-NEXT: 4000058: bc ff bc e5 ldr pc, [r12, #4028]!114// CHECK4-NEXT: 4000058: bc ff bc e5 ldr pc, [r12, #4028]!
113// CHECK4: $d:115// CHECK4: $d:
114// CHECK4-NEXT: 400005c: d4 d4 d4 d4 .word 0xd4d4d4d4116// CHECK4-NEXT: 400005c: d4 d4 d4 d4 .word 0xd4d4d4d4
deps/lld/test/ELF/arm-thumb-plt-reloc.s+16-13
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6// RUN: ld.lld --hash-style=sysv -shared %t1 %t2 -o %t36// RUN: ld.lld --hash-style=sysv -shared %t1 %t2 -o %t3
7// RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOTHUMB %s7// RUN: llvm-objdump -triple=thumbv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOTHUMB %s
8// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOARM %s8// RUN: llvm-objdump -triple=armv7a-none-linux-gnueabi -d %t3 | FileCheck -check-prefix=DSOARM %s
9// RUN: llvm-readobj -s -r %t3 | FileCheck -check-prefix=DSOREL %s9// RUN: llvm-readobj -S -r %t3 | FileCheck -check-prefix=DSOREL %s
10//10//
11// Test PLT entry generation11// Test PLT entry generation
12 .syntax unified12 .syntax unified
...@@ -24,6 +24,7 @@ _start:...@@ -24,6 +24,7 @@ _start:
2424
25// Executable, expect no PLT25// Executable, expect no PLT
26// CHECK: Disassembly of section .text:26// CHECK: Disassembly of section .text:
27// CHECK-EMPTY:
27// CHECK-NEXT: func1:28// CHECK-NEXT: func1:
28// CHECK-NEXT: 11000: 70 47 bx lr29// CHECK-NEXT: 11000: 70 47 bx lr
29// CHECK: func2:30// CHECK: func2:
...@@ -43,6 +44,7 @@ _start:...@@ -43,6 +44,7 @@ _start:
43// .text is Thumb and .plt is ARM, llvm-objdump can currently only disassemble44// .text is Thumb and .plt is ARM, llvm-objdump can currently only disassemble
44// as ARM or Thumb. Work around by disassembling twice.45// as ARM or Thumb. Work around by disassembling twice.
45// DSOTHUMB: Disassembly of section .text:46// DSOTHUMB: Disassembly of section .text:
47// DSOTHUMB-EMPTY:
46// DSOTHUMB-NEXT: func1:48// DSOTHUMB-NEXT: func1:
47// DSOTHUMB-NEXT: 1000: 70 47 bx lr49// DSOTHUMB-NEXT: 1000: 70 47 bx lr
48// DSOTHUMB: func2:50// DSOTHUMB: func2:
...@@ -58,11 +60,12 @@ _start:...@@ -58,11 +60,12 @@ _start:
58// 0x1010 + 0x4C + 4 = 0x1060 = PLT func360// 0x1010 + 0x4C + 4 = 0x1060 = PLT func3
59// DSOTHUMB-NEXT: 1010: 00 f0 26 e8 blx #7661// DSOTHUMB-NEXT: 1010: 00 f0 26 e8 blx #76
60// DSOARM: Disassembly of section .plt:62// DSOARM: Disassembly of section .plt:
63// DSOARM-EMPTY:
61// DSOARM-NEXT: $a:64// DSOARM-NEXT: $a:
62// DSOARM-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]!65// DSOARM-NEXT: 1020: 04 e0 2d e5 str lr, [sp, #-4]!
63// (0x1024 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfdc) = 0x2008 = .got.plt[3]66// (0x1024 + 8) + (0 RoR 12) + 4096 + (0xfdc) = 0x3008 = .got.plt[3]
64// DSOARM-NEXT: 1024: 00 e6 8f e2 add lr, pc, #0, #1267// DSOARM-NEXT: 1024: 00 e6 8f e2 add lr, pc, #0, #12
65// DSOARM-NEXT: 1028: 00 ea 8e e2 add lr, lr, #0, #2068// DSOARM-NEXT: 1028: 01 ea 8e e2 add lr, lr, #4096
66// DSOARM-NEXT: 102c: dc ff be e5 ldr pc, [lr, #4060]!69// DSOARM-NEXT: 102c: dc ff be e5 ldr pc, [lr, #4060]!
67// DSOARM: $d:70// DSOARM: $d:
6871
...@@ -71,23 +74,23 @@ _start:...@@ -71,23 +74,23 @@ _start:
71// DSOARM-NEXT: 1038: d4 d4 d4 d4 .word 0xd4d4d4d474// DSOARM-NEXT: 1038: d4 d4 d4 d4 .word 0xd4d4d4d4
72// DSOARM-NEXT: 103c: d4 d4 d4 d4 .word 0xd4d4d4d475// DSOARM-NEXT: 103c: d4 d4 d4 d4 .word 0xd4d4d4d4
73// DSOARM: $a:76// DSOARM: $a:
74// (0x1040 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfc4) = 0x200c77// (0x1040 + 8) + (0 RoR 12) + 4096 + (0xfc4) = 0x300c
75// DSOARM-NEXT: 1040: 00 c6 8f e2 add r12, pc, #0, #1278// DSOARM-NEXT: 1040: 00 c6 8f e2 add r12, pc, #0, #12
76// DSOARM-NEXT: 1044: 00 ca 8c e2 add r12, r12, #0, #2079// DSOARM-NEXT: 1044: 01 ca 8c e2 add r12, r12, #4096
77// DSOARM-NEXT: 1048: c4 ff bc e5 ldr pc, [r12, #4036]!80// DSOARM-NEXT: 1048: c4 ff bc e5 ldr pc, [r12, #4036]!
78// DSOARM: $d:81// DSOARM: $d:
79// DSOARM-NEXT: 104c: d4 d4 d4 d4 .word 0xd4d4d4d482// DSOARM-NEXT: 104c: d4 d4 d4 d4 .word 0xd4d4d4d4
80// DSOARM: $a:83// DSOARM: $a:
81// (0x1050 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfb8) = 0x201084// (0x1050 + 8) + (0 RoR 12) + 4096 + (0xfb8) = 0x3010
82// DSOARM-NEXT: 1050: 00 c6 8f e2 add r12, pc, #0, #1285// DSOARM-NEXT: 1050: 00 c6 8f e2 add r12, pc, #0, #12
83// DSOARM-NEXT: 1054: 00 ca 8c e2 add r12, r12, #0, #2086// DSOARM-NEXT: 1054: 01 ca 8c e2 add r12, r12, #4096
84// DSOARM-NEXT: 1058: b8 ff bc e5 ldr pc, [r12, #4024]!87// DSOARM-NEXT: 1058: b8 ff bc e5 ldr pc, [r12, #4024]!
85// DSOARM: $d:88// DSOARM: $d:
86// DSOARM-NEXT: 105c: d4 d4 d4 d4 .word 0xd4d4d4d489// DSOARM-NEXT: 105c: d4 d4 d4 d4 .word 0xd4d4d4d4
87// DSOARM: $a:90// DSOARM: $a:
88// (0x1060 + 8) + (0 RoR 12) + (0 RoR 20) + (0xfac) = 0x201491// (0x1060 + 8) + (0 RoR 12) + 4096 + (0xfac) = 0x3014
89// DSOARM-NEXT: 1060: 00 c6 8f e2 add r12, pc, #0, #1292// DSOARM-NEXT: 1060: 00 c6 8f e2 add r12, pc, #0, #12
90// DSOARM-NEXT: 1064: 00 ca 8c e2 add r12, r12, #0, #2093// DSOARM-NEXT: 1064: 01 ca 8c e2 add r12, r12, #4096
91// DSOARM-NEXT: 1068: ac ff bc e5 ldr pc, [r12, #4012]!94// DSOARM-NEXT: 1068: ac ff bc e5 ldr pc, [r12, #4012]!
92// DSOARM: $d:95// DSOARM: $d:
93// DSOARM-NEXT: 106c: d4 d4 d4 d4 .word 0xd4d4d4d496// DSOARM-NEXT: 106c: d4 d4 d4 d4 .word 0xd4d4d4d4
...@@ -98,7 +101,7 @@ _start:...@@ -98,7 +101,7 @@ _start:
98// DSOREL-NEXT: SHF_ALLOC101// DSOREL-NEXT: SHF_ALLOC
99// DSOREL-NEXT: SHF_WRITE102// DSOREL-NEXT: SHF_WRITE
100// DSOREL-NEXT: ]103// DSOREL-NEXT: ]
101// DSOREL-NEXT: Address: 0x2000104// DSOREL-NEXT: Address: 0x3000
102// DSOREL-NEXT: Offset:105// DSOREL-NEXT: Offset:
103// DSOREL-NEXT: Size: 24106// DSOREL-NEXT: Size: 24
104// DSOREL-NEXT: Link:107// DSOREL-NEXT: Link:
...@@ -107,6 +110,6 @@ _start:...@@ -107,6 +110,6 @@ _start:
107// DSOREL-NEXT: EntrySize:110// DSOREL-NEXT: EntrySize:
108// DSOREL: Relocations [111// DSOREL: Relocations [
109// DSOREL-NEXT: Section (4) .rel.plt {112// DSOREL-NEXT: Section (4) .rel.plt {
110// DSOREL-NEXT: 0x200C R_ARM_JUMP_SLOT func1 0x0113// DSOREL-NEXT: 0x300C R_ARM_JUMP_SLOT func1 0x0
111// DSOREL-NEXT: 0x2010 R_ARM_JUMP_SLOT func2 0x0114// DSOREL-NEXT: 0x3010 R_ARM_JUMP_SLOT func2 0x0
112// DSOREL-NEXT: 0x2014 R_ARM_JUMP_SLOT func3 0x0115// DSOREL-NEXT: 0x3014 R_ARM_JUMP_SLOT func3 0x0
deps/lld/test/ELF/arm-thumb-range-thunk-os.s+1
...@@ -43,6 +43,7 @@ _start:...@@ -43,6 +43,7 @@ _start:
43// the first of the pre-created ThunkSections.43// the first of the pre-created ThunkSections.
44 bl tfunc1644 bl tfunc16
45// CHECK1: Disassembly of section .text:45// CHECK1: Disassembly of section .text:
46// CHECK1-EMPTY:
46// CHECK1-NEXT: _start:47// CHECK1-NEXT: _start:
47// CHECK1-NEXT: 100000: ff f0 fe ff bl #104857248// CHECK1-NEXT: 100000: ff f0 fe ff bl #1048572
48// CHECK1-NEXT: 100004: ff f3 fc d7 bl #1677720849// CHECK1-NEXT: 100004: ff f3 fc d7 bl #16777208
deps/lld/test/ELF/arm-thumb-thunk-empty-pass.s+1
...@@ -17,6 +17,7 @@ foo:...@@ -17,6 +17,7 @@ foo:
17 bl _start17 bl _start
1818
19// CHECK1: Disassembly of section .text:19// CHECK1: Disassembly of section .text:
20// CHECK1-EMPTY:
20// CHECK1-NEXT: _start:21// CHECK1-NEXT: _start:
21// CHECK1-NEXT: 11000: ff f7 fe ff bl #-422// CHECK1-NEXT: 11000: ff f7 fe ff bl #-4
22// CHECK1: __Thumbv7ABSLongThunk__start:23// CHECK1: __Thumbv7ABSLongThunk__start:
deps/lld/test/ELF/arm-thumb-thunk-v6m.s+4
...@@ -31,6 +31,7 @@ far:...@@ -31,6 +31,7 @@ far:
31 bx lr31 bx lr
3232
33// CHECK: Disassembly of section .text_low:33// CHECK: Disassembly of section .text_low:
34// CHECK-EMPTY:
34// CHECK-NEXT: _start:35// CHECK-NEXT: _start:
35// CHECK-NEXT: 94: 00 f0 00 f8 bl #036// CHECK-NEXT: 94: 00 f0 00 f8 bl #0
36// CHECK: __Thumbv6MABSLongThunk_far:37// CHECK: __Thumbv6MABSLongThunk_far:
...@@ -40,10 +41,12 @@ far:...@@ -40,10 +41,12 @@ far:
40// CHECK-NEXT: 9e: 01 bd pop {r0, pc}41// CHECK-NEXT: 9e: 01 bd pop {r0, pc}
41// CHECK: a0: 01 00 00 02 .word 0x0200000142// CHECK: a0: 01 00 00 02 .word 0x02000001
42// CHECK: Disassembly of section .text_high:43// CHECK: Disassembly of section .text_high:
44// CHECK-EMPTY:
43// CHECK-NEXT: far:45// CHECK-NEXT: far:
44// CHECK-NEXT: 2000000: 70 47 bx lr46// CHECK-NEXT: 2000000: 70 47 bx lr
4547
46// CHECK-PI: Disassembly of section .text_low:48// CHECK-PI: Disassembly of section .text_low:
49// CHECK-PI-EMPTY:
47// CHECK-PI-NEXT: _start:50// CHECK-PI-NEXT: _start:
48// CHECK-PI-NEXT: 130: 00 f0 00 f8 bl #051// CHECK-PI-NEXT: 130: 00 f0 00 f8 bl #0
49// CHECK-PI: __Thumbv6MPILongThunk_far:52// CHECK-PI: __Thumbv6MPILongThunk_far:
...@@ -57,5 +60,6 @@ far:...@@ -57,5 +60,6 @@ far:
57// CHECK-PI: 140: c1 fe ff 01 .word 0x01fffec160// CHECK-PI: 140: c1 fe ff 01 .word 0x01fffec1
5861
59// CHECK-PI: Disassembly of section .text_high:62// CHECK-PI: Disassembly of section .text_high:
63// CHECK-PI-EMPTY:
60// CHECK-PI-NEXT: far:64// CHECK-PI-NEXT: far:
61// CHECK-PI-NEXT: 2000000: 70 47 bx lr65// CHECK-PI-NEXT: 2000000: 70 47 bx lr
deps/lld/test/ELF/arm-thumb-undefined-weak-narrow.test+14-15
...@@ -4,6 +4,7 @@...@@ -4,6 +4,7 @@
4# RUN: llvm-objdump -triple=thumbv7a-linux-gnueabi -d %t | FileCheck %s4# RUN: llvm-objdump -triple=thumbv7a-linux-gnueabi -d %t | FileCheck %s
55
6# CHECK: Disassembly of section .text:6# CHECK: Disassembly of section .text:
7# CHECK-EMPTY:
7# CHECK-NEXT:_start:8# CHECK-NEXT:_start:
8# CHECK-NEXT: 11000: ff e7 b #-29# CHECK-NEXT: 11000: ff e7 b #-2
910
...@@ -33,18 +34,16 @@ Sections:...@@ -33,18 +34,16 @@ Sections:
33 Type: R_ARM_THM_JUMP1134 Type: R_ARM_THM_JUMP11
3435
35Symbols:36Symbols:
36 Global:37 - Type: STT_NOTYPE
37 - Type: STT_FUNC38 Name: "$t"
38 Name: _start39 Section: .text
39 Value: 140 Value: 0
40 Section: .text41 - Type: STT_FUNC
41 Local:42 Name: _start
42 - Type: STT_NOTYPE43 Value: 1
43 Name: "$t"44 Section: .text
44 Section: .text45 Binding: STB_GLOBAL
45 Value: 046 - Type: STT_NOTYPE
46 Weak:47 Name: undefined_weak
47 - Type: STT_NOTYPE48 Value: 0
48 Name: undefined_weak49 Binding: STB_WEAK
49 Value: 0
50
deps/lld/test/ELF/arm-thumb-undefined-weak.s+1
...@@ -28,6 +28,7 @@ _start:...@@ -28,6 +28,7 @@ _start:
28 movw r0, :lower16:target - .28 movw r0, :lower16:target - .
2929
30// CHECK: Disassembly of section .text:30// CHECK: Disassembly of section .text:
31// CHECK-EMPTY:
31// 69636 = 0x1100432// 69636 = 0x11004
32// CHECK: 11000: {{.*}} beq.w #0 <_start+0x4>33// CHECK: 11000: {{.*}} beq.w #0 <_start+0x4>
33// CHECK-NEXT: 11004: {{.*}} b.w #0 <_start+0x8>34// CHECK-NEXT: 11004: {{.*}} b.w #0 <_start+0x8>
deps/lld/test/ELF/arm-thunk-largesection.s+1
...@@ -16,6 +16,7 @@ _start:...@@ -16,6 +16,7 @@ _start:
16 bx lr16 bx lr
17 .space 0x100017 .space 0x1000
18// CHECK1: Disassembly of section .text:18// CHECK1: Disassembly of section .text:
19// CHECK1-EMPTY:
19// CHECK1-NEXT:_start:20// CHECK1-NEXT:_start:
20// CHECK1-NEXT: 11000: 70 47 bx lr21// CHECK1-NEXT: 11000: 70 47 bx lr
21// CHECK1-EMPTY:22// CHECK1-EMPTY:
deps/lld/test/ELF/arm-thunk-linkerscript-dotexpr.s+1
...@@ -28,6 +28,7 @@ low_target2:...@@ -28,6 +28,7 @@ low_target2:
28 bl high_target28 bl high_target
29 bl high_target229 bl high_target2
30// CHECK1: Disassembly of section .text_low:30// CHECK1: Disassembly of section .text_low:
31// CHECK1-EMPTY:
31// CHECK1-NEXT: _start:32// CHECK1-NEXT: _start:
32// CHECK1-NEXT: 94: 70 47 bx lr33// CHECK1-NEXT: 94: 70 47 bx lr
33// CHECK1: low_target:34// CHECK1: low_target:
deps/lld/test/ELF/arm-thunk-linkerscript-large.s+3
...@@ -53,6 +53,7 @@ _start:...@@ -53,6 +53,7 @@ _start:
53 // Expect a range extension thunk in .text OutputSection53 // Expect a range extension thunk in .text OutputSection
54 bl tfunch3154 bl tfunch31
55// CHECK1: Disassembly of section .text:55// CHECK1: Disassembly of section .text:
56// CHECK1-EMPTY:
56// CHECK1-NEXT: _start:57// CHECK1-NEXT: _start:
57// CHECK1-NEXT: 100000: ff f0 fe ff bl #104857258// CHECK1-NEXT: 100000: ff f0 fe ff bl #1048572
58// CHECK1-NEXT: 100004: 00 f0 00 f8 bl #059// CHECK1-NEXT: 100004: 00 f0 00 f8 bl #0
...@@ -66,6 +67,7 @@ _start:...@@ -66,6 +67,7 @@ _start:
66 // We can reuse existing thunk in .text67 // We can reuse existing thunk in .text
67 bl tfunch3168 bl tfunch31
68// CHECK2: Disassembly of section .textl:69// CHECK2: Disassembly of section .textl:
70// CHECK2-EMPTY:
69// CHECK2-NEXT: tfuncl00:71// CHECK2-NEXT: tfuncl00:
70// CHECK2-NEXT: 200000: 70 47 bx lr72// CHECK2-NEXT: 200000: 70 47 bx lr
71// CHECK2-NEXT: 200002: ff f0 ff df bl #943718273// CHECK2-NEXT: 200002: ff f0 ff df bl #9437182
...@@ -122,6 +124,7 @@ _start:...@@ -122,6 +124,7 @@ _start:
122 // Shouldn't need a thunk124 // Shouldn't need a thunk
123 bl tfuncl31125 bl tfuncl31
124// CHECK5: Disassembly of section .texth:126// CHECK5: Disassembly of section .texth:
127// CHECK5-EMPTY:
125// CHECK5-NEXT: tfunch00:128// CHECK5-NEXT: tfunch00:
126// CHECK5-NEXT: 2200000: 70 47 bx lr129// CHECK5-NEXT: 2200000: 70 47 bx lr
127// CHECK5-NEXT: 2200002: 00 f7 05 f8 bl #-1048566130// CHECK5-NEXT: 2200002: 00 f7 05 f8 bl #-1048566
deps/lld/test/ELF/arm-thunk-linkerscript-orphan.s+3
...@@ -18,6 +18,7 @@ low_target:...@@ -18,6 +18,7 @@ low_target:
18 bl high_target18 bl high_target
19 bl orphan_target19 bl orphan_target
20// CHECK: Disassembly of section .text_low:20// CHECK: Disassembly of section .text_low:
21// CHECK-EMPTY:
21// CHECK-NEXT: _start:22// CHECK-NEXT: _start:
22// CHECK-NEXT: 100000: 70 47 bx lr23// CHECK-NEXT: 100000: 70 47 bx lr
23// CHECK: low_target:24// CHECK: low_target:
...@@ -39,6 +40,7 @@ high_target:...@@ -39,6 +40,7 @@ high_target:
39 bl low_target40 bl low_target
40 bl orphan_target41 bl orphan_target
41// CHECK: Disassembly of section .text_high:42// CHECK: Disassembly of section .text_high:
43// CHECK-EMPTY:
42// CHECK-NEXT: high_target:44// CHECK-NEXT: high_target:
43// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #445// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4
44// CHECK-NEXT: 2000004: 00 f0 06 f8 bl #1246// CHECK-NEXT: 2000004: 00 f0 06 f8 bl #12
...@@ -55,6 +57,7 @@ orphan_target:...@@ -55,6 +57,7 @@ orphan_target:
55 bl low_target57 bl low_target
56 bl high_target58 bl high_target
57// CHECK: Disassembly of section orphan:59// CHECK: Disassembly of section orphan:
60// CHECK-EMPTY:
58// CHECK-NEXT: orphan_target:61// CHECK-NEXT: orphan_target:
59// CHECK-NEXT: 2000014: ff f7 f8 ff bl #-1662// CHECK-NEXT: 2000014: ff f7 f8 ff bl #-16
60// CHECK-NEXT: 2000018: ff f7 f2 ff bl #-2863// CHECK-NEXT: 2000018: ff f7 f2 ff bl #-28
deps/lld/test/ELF/arm-thunk-linkerscript.s+2
...@@ -28,6 +28,7 @@ low_target2:...@@ -28,6 +28,7 @@ low_target2:
28 bl high_target228 bl high_target2
2929
30// CHECK: Disassembly of section .text_low:30// CHECK: Disassembly of section .text_low:
31// CHECK-EMPTY:
31// CHECK-NEXT: _start:32// CHECK-NEXT: _start:
32// CHECK-NEXT: 94: 70 47 bx lr33// CHECK-NEXT: 94: 70 47 bx lr
33// CHECK: low_target:34// CHECK: low_target:
...@@ -62,6 +63,7 @@ high_target2:...@@ -62,6 +63,7 @@ high_target2:
62 bl low_target263 bl low_target2
6364
64// CHECK: Disassembly of section .text_high:65// CHECK: Disassembly of section .text_high:
66// CHECK-EMPTY:
65// CHECK-NEXT: high_target:67// CHECK-NEXT: high_target:
66// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #468// CHECK-NEXT: 2000000: 00 f0 02 f8 bl #4
67// CHECK-NEXT: 2000004: 00 f0 05 f8 bl #1069// CHECK-NEXT: 2000004: 00 f0 05 f8 bl #10
deps/lld/test/ELF/arm-thunk-multipass-plt.s created+95
...@@ -0,0 +1,95 @@
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 --shared 2>&1
4// RUN: llvm-objdump --start-address=7340044 --stop-address=7340048 --triple=armv5-none-linux-gnueabi -d %t2 | FileCheck %s
5// RUN: llvm-objdump --start-address=8388620 --stop-address=8388624 --triple=thumbv5-none-linux-gnueabi -d %t2 | FileCheck %s -check-prefix=CHECK-CALL
6// RUN: llvm-objdump --start-address=13631520 --stop-address=13631584 --triple=armv5-none-linux-gnueabi -d %t2 | FileCheck %s -check-prefix=CHECK-PLT
7// When we create a thunk to a PLT entry the relocation is redirected to the
8// Thunk, changing its expression to a non-PLT equivalent. If the thunk
9// becomes unusable we need to restore the relocation expression to the PLT
10// form so that when we create a new thunk it targets the PLT.
11
12// Test case that checks the case:
13// - Thunk is created on pass 1 to a PLT entry for preemptible
14// - Some other Thunk added in the same pass moves the thunk to
15// preemptible out of range of its caller.
16// - New Thunk is created on pass 2 to PLT entry for preemptible
17
18 .globl preemptible
19 .globl preemptible2
20.section .text.01, "ax", %progbits
21.balign 0x100000
22 .thumb
23 .globl needsplt
24 .type needsplt, %function
25needsplt:
26 bl preemptible
27 .section .text.02, "ax", %progbits
28 .space (1024 * 1024)
29
30 .section .text.03, "ax", %progbits
31 .space (1024 * 1024)
32
33 .section .text.04, "ax", %progbits
34 .space (1024 * 1024)
35
36 .section .text.05, "ax", %progbits
37 .space (1024 * 1024)
38
39 .section .text.06, "ax", %progbits
40 .space (1024 * 1024)
41
42 .section .text.07, "ax", %progbits
43 .space (1024 * 1024)
44// 0x70000c + 8 + 0x60002c = 0xd00040 = preemptible@plt
45// CHECK: 0070000c __ARMV5PILongThunk_preemptible:
46// CHECK-NEXT: 70000c: 0b 00 18 ea b #6291500
47
48 .section .text.08, "ax", %progbits
49 .space (1024 * 1024) - 4
50
51 .section .text.10, "ax", %progbits
52 .balign 2
53 bl preemptible
54 bl preemptible2
55// 0x80000c + 4 - 100004 = 0x70000c = __ARMv5PILongThunk_preemptible
56// CHECK-CALL: 80000c: ff f6 fe ef blx #-1048580
57 .balign 2
58 .globl preemptible
59 .type preemptible, %function
60preemptible:
61 bx lr
62 .globl preemptible2
63 .type preemptible2, %function
64preemptible2:
65 bx lr
66
67
68 .section .text.11, "ax", %progbits
69 .space (5 * 1024 * 1024)
70
71
72// CHECK-PLT: Disassembly of section .plt:
73// CHECK-PLT-EMPTY:
74// CHECK-PLT-NEXT: 00d00020 $a:
75// CHECK-PLT-NEXT: d00020: 04 e0 2d e5 str lr, [sp, #-4]!
76// CHECK-PLT-NEXT: d00024: 00 e6 8f e2 add lr, pc, #0, #12
77// CHECK-PLT-NEXT: d00028: 01 ea 8e e2 add lr, lr, #4096
78// CHECK-PLT-NEXT: d0002c: dc ff be e5 ldr pc, [lr, #4060]!
79// CHECK-PLT: 00d00030 $d:
80// CHECK-PLT-NEXT: d00030: d4 d4 d4 d4 .word 0xd4d4d4d4
81// CHECK-PLT-NEXT: d00034: d4 d4 d4 d4 .word 0xd4d4d4d4
82// CHECK-PLT-NEXT: d00038: d4 d4 d4 d4 .word 0xd4d4d4d4
83// CHECK-PLT-NEXT: d0003c: d4 d4 d4 d4 .word 0xd4d4d4d4
84// CHECK-PLT: 00d00040 $a:
85// CHECK-PLT-NEXT: d00040: 00 c6 8f e2 add r12, pc, #0, #12
86// CHECK-PLT-NEXT: d00044: 01 ca 8c e2 add r12, r12, #4096
87// CHECK-PLT-NEXT: d00048: c4 ff bc e5 ldr pc, [r12, #4036]!
88// CHECK-PLT: 00d0004c $d:
89// CHECK-PLT-NEXT: d0004c: d4 d4 d4 d4 .word 0xd4d4d4d4
90// CHECK-PLT: 00d00050 $a:
91// CHECK-PLT-NEXT: d00050: 00 c6 8f e2 add r12, pc, #0, #12
92// CHECK-PLT-NEXT: d00054: 01 ca 8c e2 add r12, r12, #4096
93// CHECK-PLT-NEXT: d00058: b8 ff bc e5 ldr pc, [r12, #4024]!
94// CHECK-PLT: 00d0005c $d:
95// CHECK-PLT-NEXT: d0005c: d4 d4 d4 d4 .word 0xd4d4d4d4
deps/lld/test/ELF/arm-thunk-re-add.s+4-3
...@@ -99,10 +99,11 @@ callers:...@@ -99,10 +99,11 @@ callers:
99// CHECK2-NEXT: 110001c: ff f6 f8 bf b.w #-1048592 <__ThumbV7PILongThunk_imported2>99// CHECK2-NEXT: 110001c: ff f6 f8 bf b.w #-1048592 <__ThumbV7PILongThunk_imported2>
100100
101// CHECK3: Disassembly of section .plt:101// CHECK3: Disassembly of section .plt:
102// CHECK3-EMPTY:
102// CHECK3-NEXT: $a:103// CHECK3-NEXT: $a:
103// CHECK3-NEXT: 1100020: 04 e0 2d e5 str lr, [sp, #-4]!104// CHECK3-NEXT: 1100020: 04 e0 2d e5 str lr, [sp, #-4]!
104// CHECK3-NEXT: 1100024: 00 e6 8f e2 add lr, pc, #0, #12105// CHECK3-NEXT: 1100024: 00 e6 8f e2 add lr, pc, #0, #12
105// CHECK3-NEXT: 1100028: 00 ea 8e e2 add lr, lr, #0, #20106// CHECK3-NEXT: 1100028: 01 ea 8e e2 add lr, lr, #4096
106// CHECK3-NEXT: 110002c: dc ff be e5 ldr pc, [lr, #4060]!107// CHECK3-NEXT: 110002c: dc ff be e5 ldr pc, [lr, #4060]!
107// CHECK3: $d:108// CHECK3: $d:
108// CHECK3-NEXT: 1100030: d4 d4 d4 d4 .word 0xd4d4d4d4109// CHECK3-NEXT: 1100030: d4 d4 d4 d4 .word 0xd4d4d4d4
...@@ -111,13 +112,13 @@ callers:...@@ -111,13 +112,13 @@ callers:
111// CHECK3-NEXT: 110003c: d4 d4 d4 d4 .word 0xd4d4d4d4112// CHECK3-NEXT: 110003c: d4 d4 d4 d4 .word 0xd4d4d4d4
112// CHECK3: $a:113// CHECK3: $a:
113// CHECK3-NEXT: 1100040: 00 c6 8f e2 add r12, pc, #0, #12114// CHECK3-NEXT: 1100040: 00 c6 8f e2 add r12, pc, #0, #12
114// CHECK3-NEXT: 1100044: 00 ca 8c e2 add r12, r12, #0, #20115// CHECK3-NEXT: 1100044: 01 ca 8c e2 add r12, r12, #4096
115// CHECK3-NEXT: 1100048: c4 ff bc e5 ldr pc, [r12, #4036]!116// CHECK3-NEXT: 1100048: c4 ff bc e5 ldr pc, [r12, #4036]!
116// CHECK3: $d:117// CHECK3: $d:
117// CHECK3-NEXT: 110004c: d4 d4 d4 d4 .word 0xd4d4d4d4118// CHECK3-NEXT: 110004c: d4 d4 d4 d4 .word 0xd4d4d4d4
118// CHECK3: $a:119// CHECK3: $a:
119// CHECK3-NEXT: 1100050: 00 c6 8f e2 add r12, pc, #0, #12120// CHECK3-NEXT: 1100050: 00 c6 8f e2 add r12, pc, #0, #12
120// CHECK3-NEXT: 1100054: 00 ca 8c e2 add r12, r12, #0, #20121// CHECK3-NEXT: 1100054: 01 ca 8c e2 add r12, r12, #4096
121// CHECK3-NEXT: 1100058: b8 ff bc e5 ldr pc, [r12, #4024]!122// CHECK3-NEXT: 1100058: b8 ff bc e5 ldr pc, [r12, #4024]!
122// CHECK3: $d:123// CHECK3: $d:
123// CHECK3-NEXT: 110005c: d4 d4 d4 d4 .word 0xd4d4d4d4124// CHECK3-NEXT: 110005c: d4 d4 d4 d4 .word 0xd4d4d4d4
deps/lld/test/ELF/arm-tls-gd32.s+2-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi
3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
4// RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s4// RUN: llvm-readobj -S --dyn-relocations %t.so | FileCheck --check-prefix=SEC %s
5// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s5// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s
66
7// Test the handling of the global-dynamic TLS model. Dynamic Loader finds7// Test the handling of the global-dynamic TLS model. Dynamic Loader finds
...@@ -91,8 +91,7 @@ x:...@@ -91,8 +91,7 @@ x:
91// SEC-NEXT: 0x2058 R_ARM_TLS_DTPOFF32 y91// SEC-NEXT: 0x2058 R_ARM_TLS_DTPOFF32 y
9292
9393
94// CHECK: Disassembly94// CHECK-LABEL: 00001000 func:
95// CHECK-NEXT: func:
96// CHECK-NEXT: 1000: 00 f0 20 e3 nop95// CHECK-NEXT: 1000: 00 f0 20 e3 nop
97// CHECK-NEXT: 1004: 00 f0 20 e3 nop96// CHECK-NEXT: 1004: 00 f0 20 e3 nop
98// CHECK-NEXT: 1008: 00 f0 20 e3 nop97// CHECK-NEXT: 1008: 00 f0 20 e3 nop
deps/lld/test/ELF/arm-tls-ie32.s+2-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi
3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
4// RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s4// RUN: llvm-readobj -S --dyn-relocations %t.so | FileCheck --check-prefix=SEC %s
5// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s5// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s
66
7// Test the handling of the initial-exec TLS model. Relative location within7// Test the handling of the initial-exec TLS model. Relative location within
...@@ -83,6 +83,7 @@ x:...@@ -83,6 +83,7 @@ x:
83// SEC: 0x2050 R_ARM_TLS_TPOFF32 y83// SEC: 0x2050 R_ARM_TLS_TPOFF32 y
8484
85// CHECK: Disassembly of section .text:85// CHECK: Disassembly of section .text:
86// CHECK-EMPTY:
86// CHECK-NEXT: func:87// CHECK-NEXT: func:
87// CHECK-NEXT: 1000: 00 f0 20 e3 nop88// CHECK-NEXT: 1000: 00 f0 20 e3 nop
88// CHECK-NEXT: 1004: 00 f0 20 e3 nop89// CHECK-NEXT: 1004: 00 f0 20 e3 nop
deps/lld/test/ELF/arm-tls-ldm32.s+3-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi
3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
4// RUN: llvm-readobj -s -dyn-relocations %t.so | FileCheck --check-prefix=SEC %s4// RUN: llvm-readobj -S --dyn-relocations %t.so | FileCheck --check-prefix=SEC %s
5// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s5// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t.so | FileCheck %s
66
7// Test the handling of the local-dynamic TLS model. Dynamic loader finds7// Test the handling of the local-dynamic TLS model. Dynamic loader finds
...@@ -56,6 +56,7 @@ x:...@@ -56,6 +56,7 @@ x:
56// SEC-NEXT: 0x204C R_ARM_TLS_DTPMOD32 - 0x056// SEC-NEXT: 0x204C R_ARM_TLS_DTPMOD32 - 0x0
5757
58// CHECK: Disassembly of section .text:58// CHECK: Disassembly of section .text:
59// CHECK-EMPTY:
59// CHECK-NEXT: _start:60// CHECK-NEXT: _start:
60// CHECK-NEXT: 1000: 00 f0 20 e3 nop61// CHECK-NEXT: 1000: 00 f0 20 e3 nop
6162
...@@ -65,6 +66,7 @@ x:...@@ -65,6 +66,7 @@ x:
65// CHECK-NEXT: 100c: 04 00 00 0066// CHECK-NEXT: 100c: 04 00 00 00
6667
67// CHECK-EXE: Disassembly of section .text:68// CHECK-EXE: Disassembly of section .text:
69// CHECK-EXE-EMPTY:
68// CHECK-NEXT-EXE: _start:70// CHECK-NEXT-EXE: _start:
69// CHECK-NEXT-EXE: 11000: 00 f0 20 e3 nop71// CHECK-NEXT-EXE: 11000: 00 f0 20 e3 nop
7072
deps/lld/test/ELF/arm-tls-le32.s+8-7
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi
3// RUN: ld.lld %t.o -o %t3// RUN: ld.lld %t.o -o %t
4// RUN: llvm-readobj -s -dyn-relocations %t | FileCheck --check-prefix=SEC %s4// RUN: llvm-readobj -S --dyn-relocations %t | FileCheck --check-prefix=SEC %s
5// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t | FileCheck %s5// RUN: llvm-objdump -d -triple=armv7a-linux-gnueabi %t | FileCheck %s
66
7// Test the handling of the local exec TLS model. TLS can be resolved7// Test the handling of the local exec TLS model. TLS can be resolved
...@@ -68,10 +68,11 @@ x:...@@ -68,10 +68,11 @@ x:
68// SEC-NEXT: }68// SEC-NEXT: }
6969
70// CHECK: Disassembly of section .text:70// CHECK: Disassembly of section .text:
71// CHECK-EMPTY:
71// CHECK-NEXT: _start:72// CHECK-NEXT: _start:
72// offset of x from Thread pointer = (TcbSize + 0x0 = 0x20)73// offset of x from Thread pointer = (TcbSize + 0x0 = 0x8)
73// CHECK-NEXT: 11000: 20 00 00 0074// CHECK-NEXT: 11000: 08 00 00 00
74// offset of z from Thread pointer = (TcbSize + 0x8 = 0x28)75// offset of z from Thread pointer = (TcbSize + 0x8 = 0x10)
75// CHECK-NEXT: 11004: 28 00 00 0076// CHECK-NEXT: 11004: 10 00 00 00
76// offset of y from Thread pointer = (TcbSize + 0x4 = 0x24)77// offset of y from Thread pointer = (TcbSize + 0x4 = 0xc)
77// CHECK-NEXT: 11008: 24 00 00 0078// CHECK-NEXT: 11008: 0c 00 00 00
deps/lld/test/ELF/arm-tls-norelax-gd-ie.s+4-4
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: ld.lld %t1 --shared -o %t1.so3// RUN: ld.lld %t1 --shared -o %t1.so
4// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi4// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=armv7a-linux-gnueabi
5// RUN: ld.lld --hash-style=sysv %t1.so %t.o -o %t5// RUN: ld.lld --hash-style=sysv %t1.so %t.o -o %t
6// RUN: llvm-readobj -s -dyn-relocations %t | FileCheck %s6// RUN: llvm-readobj -S --dyn-relocations %t | FileCheck %s
77
8// This tls global-dynamic sequence is with respect to a preemptible symbol but8// This tls global-dynamic sequence is with respect to a preemptible symbol but
9// is in an application so a relaxation to Initial Exec would normally be9// is in an application so a relaxation to Initial Exec would normally be
...@@ -25,6 +25,6 @@ func:...@@ -25,6 +25,6 @@ func:
25 .Lt0: .word y(TLSGD) + (. - .L0 - 8)25 .Lt0: .word y(TLSGD) + (. - .L0 - 8)
2626
27// CHECK: Dynamic Relocations {27// CHECK: Dynamic Relocations {
28// CHECK-NEXT: 0x13078 R_ARM_TLS_DTPMOD32 y28// CHECK-NEXT: 0x12078 R_ARM_TLS_DTPMOD32 y
29// CHECK-NEXT: 0x1307C R_ARM_TLS_DTPOFF32 y29// CHECK-NEXT: 0x1207C R_ARM_TLS_DTPOFF32 y
30// CHECK-NEXT: 0x1200C R_ARM_JUMP_SLOT __tls_get_addr30// CHECK-NEXT: 0x1300C R_ARM_JUMP_SLOT __tls_get_addr
deps/lld/test/ELF/arm-tls-norelax-gd-le.s+1-1
...@@ -33,7 +33,7 @@ x:...@@ -33,7 +33,7 @@ x:
3333
34// CHECK: Contents of section .got:34// CHECK: Contents of section .got:
35// Module index is always 1 for executable35// Module index is always 1 for executable
36// CHECK-NEXT: 13060 01000000 0000000036// CHECK-NEXT: 12060 01000000 00000000
3737
3838
39// Without any definition of __tls_get_addr we get an error39// Without any definition of __tls_get_addr we get an error
deps/lld/test/ELF/arm-tls-norelax-ie-le.s+2-2
...@@ -37,5 +37,5 @@ x2:...@@ -37,5 +37,5 @@ x2:
37 .type x2, %object37 .type x2, %object
3838
39// CHECK: Contents of section .got:39// CHECK: Contents of section .got:
40// x1 at offset 0x20 from TP, x2 at offset 0x24 from TP. Offsets include TCB size of 0x2040// x1 at offset 8 from TP, x2 at offset 0xc from TP. Offsets include TCB size of 8
41// CHECK-NEXT: 13064 20000000 2400000041// CHECK-NEXT: 12064 08000000 0c000000
deps/lld/test/ELF/arm-tls-norelax-ld-le.s+1-1
...@@ -32,4 +32,4 @@ x:...@@ -32,4 +32,4 @@ x:
32 .word 1032 .word 10
3333
34// CHECK: Contents of section .got:34// CHECK: Contents of section .got:
35// CHECK-NEXT: 13064 01000000 0000000035// CHECK-NEXT: 12064 01000000 00000000
deps/lld/test/ELF/arm-undefined-weak.s+1
...@@ -28,6 +28,7 @@ _start:...@@ -28,6 +28,7 @@ _start:
28 .word target - .28 .word target - .
2929
30// CHECK: Disassembly of section .text:30// CHECK: Disassembly of section .text:
31// CHECK-EMPTY:
31// 69636 = 0x1100432// 69636 = 0x11004
32// CHECK: 11000: {{.*}} b #-4 <_start+0x4>33// CHECK: 11000: {{.*}} b #-4 <_start+0x4>
33// CHECK-NEXT: 11004: {{.*}} bl #-4 <_start+0x8>34// CHECK-NEXT: 11004: {{.*}} bl #-4 <_start+0x8>
deps/lld/test/ELF/arm-v4bx.test+6-9
...@@ -27,14 +27,11 @@ Sections:...@@ -27,14 +27,11 @@ Sections:
27 Info: .text27 Info: .text
28 Relocations:28 Relocations:
29 - Offset: 0x000000000000000029 - Offset: 0x0000000000000000
30 Symbol: ''
31 Type: R_ARM_V4BX30 Type: R_ARM_V4BX
32Symbols:31Symbols:
33 Global:32 - Name: .text
34 - Name: _start33 Type: STT_SECTION
35 Section: .text34 Section: .text
36 Local:35 - Name: _start
37 - Name: .text36 Section: .text
38 Type: STT_SECTION37 Binding: STB_GLOBAL
39 Section: .text
40DynamicSymbols:
deps/lld/test/ELF/as-needed-weak.s+4-3
...@@ -10,9 +10,10 @@...@@ -10,9 +10,10 @@
1010
11# CHECK-NOT: libfoo11# CHECK-NOT: libfoo
1212
13# CHECK: Symbol table of .hash for image:13# CHECK: Symbol table '.dynsym' contains 2 entries:
14# CHECK-NEXT: Num Buc: Value Size Type Bind Vis Ndx Name14# CHECK-NEXT: Num: Value Size Type Bind Vis Ndx Name
15# CHECK-NEXT: 1 1: 0000000000000000 0 FUNC WEAK DEFAULT UND foo15# CHECK-NEXT: 0: 0000000000000000 0 NOTYPE LOCAL DEFAULT UND
16# CHECK-NEXT: 1: 0000000000000000 0 FUNC WEAK DEFAULT UND foo
1617
17.globl _start18.globl _start
18.weak foo19.weak foo
deps/lld/test/ELF/as-needed.s+6-6
...@@ -10,27 +10,27 @@...@@ -10,27 +10,27 @@
10/// Check if --as-needed actually works.10/// Check if --as-needed actually works.
1111
12// RUN: ld.lld %t.o %t2.so %t3.so %t4.so -o %t212// RUN: ld.lld %t.o %t2.so %t3.so %t4.so -o %t2
13// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s13// RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s
1414
15// RUN: ld.lld --as-needed %t.o %t2.so %t3.so %t4.so -o %t215// RUN: ld.lld --as-needed %t.o %t2.so %t3.so %t4.so -o %t2
16// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s16// RUN: llvm-readobj --dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
1717
18// Test with the .o last18// Test with the .o last
19// RUN: ld.lld --as-needed %t2.so %t3.so %t4.so %t.o -o %t219// RUN: ld.lld --as-needed %t2.so %t3.so %t4.so %t.o -o %t2
20// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s20// RUN: llvm-readobj --dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
2121
22// RUN: ld.lld --as-needed %t.o %t2.so --no-as-needed %t3.so %t4.so -o %t222// RUN: ld.lld --as-needed %t.o %t2.so --no-as-needed %t3.so %t4.so -o %t2
23// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s23// RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s
2424
25/// GROUP command is the same as listing the files on the command line.25/// GROUP command is the same as listing the files on the command line.
2626
27// RUN: echo "GROUP(\"%t2.so\" \"%t3.so\" \"%t4.so\")" > %t.script27// RUN: echo "GROUP(\"%t2.so\" \"%t3.so\" \"%t4.so\")" > %t.script
28// RUN: ld.lld %t.o %t.script -o %t228// RUN: ld.lld %t.o %t.script -o %t2
29// RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s29// RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s
3030
31// RUN: echo "GROUP(AS_NEEDED(\"%t2.so\" \"%t3.so\" \"%t4.so\"))" > %t.script31// RUN: echo "GROUP(AS_NEEDED(\"%t2.so\" \"%t3.so\" \"%t4.so\"))" > %t.script
32// RUN: ld.lld %t.o %t.script -o %t232// RUN: ld.lld %t.o %t.script -o %t2
33// RUN: llvm-readobj -dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s33// RUN: llvm-readobj --dynamic-table %t2 | FileCheck -check-prefix=CHECK2 %s
3434
35// CHECK: NEEDED Shared library: [shared1]35// CHECK: NEEDED Shared library: [shared1]
36// CHECK: NEEDED Shared library: [shared2]36// CHECK: NEEDED Shared library: [shared2]
deps/lld/test/ELF/assignment-archive.s+2-2
...@@ -6,14 +6,14 @@...@@ -6,14 +6,14 @@
66
7# RUN: echo "SECTIONS { foo = 1; }" > %t1.script7# RUN: echo "SECTIONS { foo = 1; }" > %t1.script
8# RUN: ld.lld -o %t1.exe --script %t1.script %tar.a %t.o8# RUN: ld.lld -o %t1.exe --script %t1.script %tar.a %t.o
9# RUN: llvm-readobj -symbols %t1.exe | FileCheck %s9# RUN: llvm-readobj --symbols %t1.exe | FileCheck %s
10# CHECK-NOT: bar10# CHECK-NOT: bar
11# CHECK: foo11# CHECK: foo
12# CHECK-NOT: bar12# CHECK-NOT: bar
1313
14# RUN: echo "SECTIONS { zed = foo; }" > %t2.script14# RUN: echo "SECTIONS { zed = foo; }" > %t2.script
15# RUN: ld.lld -o %t2.exe --script %t2.script %tar.a %t.o15# RUN: ld.lld -o %t2.exe --script %t2.script %tar.a %t.o
16# RUN: llvm-readobj -symbols %t2.exe | FileCheck %s --check-prefix=SYMS16# RUN: llvm-readobj --symbols %t2.exe | FileCheck %s --check-prefix=SYMS
17# SYMS: bar17# SYMS: bar
18# SYMS: foo18# SYMS: foo
1919
deps/lld/test/ELF/avoid-empty-program-headers.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %tout3// RUN: ld.lld %t -o %tout
4// RUN: llvm-readobj -program-headers %tout | FileCheck %s4// RUN: llvm-readobj -l %tout | FileCheck %s
55
6.global _start6.global _start
7_start:7_start:
deps/lld/test/ELF/bad-reloc-target.test deleted-29
...@@ -1,29 +0,0 @@
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
10FileHeader:
11 Class: ELFCLASS64
12 Data: ELFDATA2LSB
13 Type: ET_REL
14 Machine: EM_X86_64
15Sections:
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
27Symbols:
28 Global:
29 - Name: foo
\ No newline at end of file
deps/lld/test/ELF/basic-aarch64.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: aarch641# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %t
3# RUN: ld.lld %t -o %t23# RUN: ld.lld %t -o %t2
4# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 \4# RUN: llvm-readobj --file-headers --sections -l --symbols %t2 \
5# RUN: | FileCheck %s5# RUN: | FileCheck %s
66
7# exits with return code 42 on FreeBSD/AArch647# exits with return code 42 on FreeBSD/AArch64
deps/lld/test/ELF/basic-freebsd.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t
5# RUN: ld.lld %t -o %t25# RUN: ld.lld %t -o %t2
6# RUN: llvm-readobj -file-headers %t2 | FileCheck %s6# RUN: llvm-readobj --file-headers %t2 | FileCheck %s
77
8.globl _start8.globl _start
9_start:9_start:
deps/lld/test/ELF/basic-i386.s created+179
...@@ -0,0 +1,179 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-readobj --file-headers --sections -l %t | FileCheck %s
5
6# exits with return code 42 on linux
7.globl _start
8_start:
9 mov $1, %eax
10 mov $42, %ebx
11 int $0x80
12
13# CHECK: ElfHeader {
14# CHECK-NEXT: Ident {
15# CHECK-NEXT: Magic: (7F 45 4C 46)
16# CHECK-NEXT: Class: 32-bit (0x1)
17# CHECK-NEXT: DataEncoding: LittleEndian (0x1)
18# CHECK-NEXT: FileVersion: 1
19# CHECK-NEXT: OS/ABI: SystemV (0x0)
20# CHECK-NEXT: ABIVersion: 0
21# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
22# CHECK-NEXT: }
23# CHECK-NEXT: Type: Executable (0x2)
24# CHECK-NEXT: Machine: EM_386 (0x3)
25# CHECK-NEXT: Version: 1
26# CHECK-NEXT: Entry: 0x401000
27# CHECK-NEXT: ProgramHeaderOffset: 0x34
28# CHECK-NEXT: SectionHeaderOffset: 0x205C
29# CHECK-NEXT: Flags [ (0x0)
30# CHECK-NEXT: ]
31# CHECK-NEXT: HeaderSize: 52
32# CHECK-NEXT: ProgramHeaderEntrySize: 32
33# CHECK-NEXT: ProgramHeaderCount: 4
34# CHECK-NEXT: SectionHeaderEntrySize: 40
35# CHECK-NEXT: SectionHeaderCount: 6
36# CHECK-NEXT: StringTableSectionIndex: 4
37# CHECK-NEXT: }
38# CHECK-NEXT: Sections [
39# CHECK-NEXT: Section {
40# CHECK-NEXT: Index: 0
41# CHECK-NEXT: Name: (0)
42# CHECK-NEXT: Type: SHT_NULL (0x0)
43# CHECK-NEXT: Flags [ (0x0)
44# CHECK-NEXT: ]
45# CHECK-NEXT: Address: 0x0
46# CHECK-NEXT: Offset: 0x0
47# CHECK-NEXT: Size: 0
48# CHECK-NEXT: Link: 0
49# CHECK-NEXT: Info: 0
50# CHECK-NEXT: AddressAlignment: 0
51# CHECK-NEXT: EntrySize: 0
52# CHECK-NEXT: }
53# CHECK-NEXT: Section {
54# CHECK-NEXT: Index: 1
55# CHECK-NEXT: Name: .text
56# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
57# CHECK-NEXT: Flags [ (0x6)
58# CHECK-NEXT: SHF_ALLOC (0x2)
59# CHECK-NEXT: SHF_EXECINSTR (0x4)
60# CHECK-NEXT: ]
61# CHECK-NEXT: Address: 0x401000
62# CHECK-NEXT: Offset: 0x1000
63# CHECK-NEXT: Size: 12
64# CHECK-NEXT: Link: 0
65# CHECK-NEXT: Info: 0
66# CHECK-NEXT: AddressAlignment: 4
67# CHECK-NEXT: EntrySize: 0
68# CHECK-NEXT: }
69# CHECK-NEXT: Section {
70# CHECK-NEXT: Index: 2
71# CHECK-NEXT: Name: .comment
72# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
73# CHECK-NEXT: Flags [ (0x30)
74# CHECK-NEXT: SHF_MERGE (0x10)
75# CHECK-NEXT: SHF_STRINGS (0x20)
76# CHECK-NEXT: ]
77# CHECK-NEXT: Address: 0x0
78# CHECK-NEXT: Offset: 0x2000
79# CHECK-NEXT: Size: 8
80# CHECK-NEXT: Link: 0
81# CHECK-NEXT: Info: 0
82# CHECK-NEXT: AddressAlignment: 1
83# CHECK-NEXT: EntrySize: 1
84# CHECK-NEXT: }
85# CHECK-NEXT: Section {
86# CHECK-NEXT: Index: 3
87# CHECK-NEXT: Name: .symtab
88# CHECK-NEXT: Type: SHT_SYMTAB
89# CHECK-NEXT: Flags [
90# CHECK-NEXT: ]
91# CHECK-NEXT: Address: 0x0
92# CHECK-NEXT: Offset: 0x2008
93# CHECK-NEXT: Size: 32
94# CHECK-NEXT: Link: 5
95# CHECK-NEXT: Info: 1
96# CHECK-NEXT: AddressAlignment: 4
97# CHECK-NEXT: EntrySize: 16
98# CHECK-NEXT: }
99# CHECK-NEXT: Section {
100# CHECK-NEXT: Index: 4
101# CHECK-NEXT: Name: .shstrtab
102# CHECK-NEXT: Type: SHT_STRTAB (0x3)
103# CHECK-NEXT: Flags [ (0x0)
104# CHECK-NEXT: ]
105# CHECK-NEXT: Address: 0x0
106# CHECK-NEXT: Offset: 0x2028
107# CHECK-NEXT: Size: 42
108# CHECK-NEXT: Link: 0
109# CHECK-NEXT: Info: 0
110# CHECK-NEXT: AddressAlignment: 1
111# CHECK-NEXT: EntrySize: 0
112# CHECK-NEXT: }
113# CHECK-NEXT: Section {
114# CHECK-NEXT: Index: 5
115# CHECK-NEXT: Name: .strtab
116# CHECK-NEXT: Type: SHT_STRTAB (0x3)
117# CHECK-NEXT: Flags [ (0x0)
118# CHECK-NEXT: ]
119# CHECK-NEXT: Address: 0x0
120# CHECK-NEXT: Offset: 0x2052
121# CHECK-NEXT: Size: 8
122# CHECK-NEXT: Link: 0
123# CHECK-NEXT: Info: 0
124# CHECK-NEXT: AddressAlignment: 1
125# CHECK-NEXT: EntrySize: 0
126# CHECK-NEXT: }
127# CHECK-NEXT: ]
128# CHECK-NEXT: ProgramHeaders [
129# CHECK-NEXT: ProgramHeader {
130# CHECK-NEXT: Type: PT_PHDR (0x6)
131# CHECK-NEXT: Offset: 0x34
132# CHECK-NEXT: VirtualAddress: 0x400034
133# CHECK-NEXT: PhysicalAddress: 0x400034
134# CHECK-NEXT: FileSize: 128
135# CHECK-NEXT: MemSize: 128
136# CHECK-NEXT: Flags [ (0x4)
137# CHECK-NEXT: PF_R (0x4)
138# CHECK-NEXT: ]
139# CHECK-NEXT: Alignment: 4
140# CHECK-NEXT: }
141# CHECK-NEXT: ProgramHeader {
142# CHECK-NEXT: Type: PT_LOAD (0x1)
143# CHECK-NEXT: Offset: 0x0
144# CHECK-NEXT: VirtualAddress: 0x400000
145# CHECK-NEXT: PhysicalAddress: 0x400000
146# CHECK-NEXT: FileSize: 180
147# CHECK-NEXT: MemSize: 180
148# CHECK-NEXT: Flags [
149# CHECK-NEXT: PF_R
150# CHECK-NEXT: ]
151# CHECK-NEXT: Alignment: 4096
152# CHECK-NEXT: }
153# CHECK-NEXT: ProgramHeader {
154# CHECK-NEXT: Type: PT_LOAD (0x1)
155# CHECK-NEXT: Offset: 0x1000
156# CHECK-NEXT: VirtualAddress: 0x401000
157# CHECK-NEXT: PhysicalAddress: 0x401000
158# CHECK-NEXT: FileSize: 4096
159# CHECK-NEXT: MemSize: 4096
160# CHECK-NEXT: Flags [ (0x5)
161# CHECK-NEXT: PF_R (0x4)
162# CHECK-NEXT: PF_X (0x1)
163# CHECK-NEXT: ]
164# CHECK-NEXT: Alignment: 4096
165# CHECK-NEXT: }
166# CHECK-NEXT: ProgramHeader {
167# CHECK-NEXT: Type: PT_GNU_STACK
168# CHECK-NEXT: Offset: 0x0
169# CHECK-NEXT: VirtualAddress: 0x0
170# CHECK-NEXT: PhysicalAddress: 0x0
171# CHECK-NEXT: FileSize: 0
172# CHECK-NEXT: MemSize: 0
173# CHECK-NEXT: Flags [
174# CHECK-NEXT: PF_R
175# CHECK-NEXT: PF_W
176# CHECK-NEXT: ]
177# CHECK-NEXT: Alignment: 0
178# CHECK-NEXT: }
179# CHECK-NEXT: ]
deps/lld/test/ELF/basic-mips.s+47-23
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: mips1# REQUIRES: mips
2# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t.exe3# RUN: ld.lld %t.o -o %t.exe
4# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t.exe \4# RUN: llvm-readobj --file-headers --sections -l --symbols %t.exe \
5# RUN: | FileCheck %s5# RUN: | FileCheck %s
66
7# Exits with return code 1 on Linux.7# Exits with return code 1 on Linux.
...@@ -34,7 +34,7 @@ __start:...@@ -34,7 +34,7 @@ __start:
34# CHECK-NEXT: ]34# CHECK-NEXT: ]
35# CHECK-NEXT: HeaderSize: 5235# CHECK-NEXT: HeaderSize: 52
36# CHECK-NEXT: ProgramHeaderEntrySize: 3236# CHECK-NEXT: ProgramHeaderEntrySize: 32
37# CHECK-NEXT: ProgramHeaderCount: 537# CHECK-NEXT: ProgramHeaderCount: 7
38# CHECK-NEXT: SectionHeaderEntrySize: 4038# CHECK-NEXT: SectionHeaderEntrySize: 40
39# CHECK-NEXT: SectionHeaderCount: 1139# CHECK-NEXT: SectionHeaderCount: 11
40# CHECK-NEXT: StringTableSectionIndex: 940# CHECK-NEXT: StringTableSectionIndex: 9
...@@ -61,8 +61,8 @@ __start:...@@ -61,8 +61,8 @@ __start:
61# CHECK-NEXT: Flags [ (0x2)61# CHECK-NEXT: Flags [ (0x2)
62# CHECK-NEXT: SHF_ALLOC (0x2)62# CHECK-NEXT: SHF_ALLOC (0x2)
63# CHECK-NEXT: ]63# CHECK-NEXT: ]
64# CHECK-NEXT: Address: 0x100D864# CHECK-NEXT: Address: 0x10118
65# CHECK-NEXT: Offset: 0xD865# CHECK-NEXT: Offset: 0x118
66# CHECK-NEXT: Size: 2466# CHECK-NEXT: Size: 24
67# CHECK-NEXT: Link: 067# CHECK-NEXT: Link: 0
68# CHECK-NEXT: Info: 068# CHECK-NEXT: Info: 0
...@@ -76,8 +76,8 @@ __start:...@@ -76,8 +76,8 @@ __start:
76# CHECK-NEXT: Flags [ (0x2)76# CHECK-NEXT: Flags [ (0x2)
77# CHECK-NEXT: SHF_ALLOC (0x2)77# CHECK-NEXT: SHF_ALLOC (0x2)
78# CHECK-NEXT: ]78# CHECK-NEXT: ]
79# CHECK-NEXT: Address: 0x100F079# CHECK-NEXT: Address: 0x10130
80# CHECK-NEXT: Offset: 0xF080# CHECK-NEXT: Offset: 0x130
81# CHECK-NEXT: Size: 2481# CHECK-NEXT: Size: 24
82# CHECK-NEXT: Link: 082# CHECK-NEXT: Link: 0
83# CHECK-NEXT: Info: 083# CHECK-NEXT: Info: 0
...@@ -245,8 +245,8 @@ __start:...@@ -245,8 +245,8 @@ __start:
245# CHECK-NEXT: Offset: 0x34245# CHECK-NEXT: Offset: 0x34
246# CHECK-NEXT: VirtualAddress: 0x10034246# CHECK-NEXT: VirtualAddress: 0x10034
247# CHECK-NEXT: PhysicalAddress: 0x10034247# CHECK-NEXT: PhysicalAddress: 0x10034
248# CHECK-NEXT: FileSize: 160248# CHECK-NEXT: FileSize: 224
249# CHECK-NEXT: MemSize: 160249# CHECK-NEXT: MemSize: 224
250# CHECK-NEXT: Flags [ (0x4)250# CHECK-NEXT: Flags [ (0x4)
251# CHECK-NEXT: PF_R (0x4)251# CHECK-NEXT: PF_R (0x4)
252# CHECK-NEXT: ]252# CHECK-NEXT: ]
...@@ -257,8 +257,8 @@ __start:...@@ -257,8 +257,8 @@ __start:
257# CHECK-NEXT: Offset: 0x0257# CHECK-NEXT: Offset: 0x0
258# CHECK-NEXT: VirtualAddress: 0x10000258# CHECK-NEXT: VirtualAddress: 0x10000
259# CHECK-NEXT: PhysicalAddress: 0x10000259# CHECK-NEXT: PhysicalAddress: 0x10000
260# CHECK-NEXT: FileSize: 264260# CHECK-NEXT: FileSize: 328
261# CHECK-NEXT: MemSize: 264261# CHECK-NEXT: MemSize: 328
262# CHECK-NEXT: Flags [ (0x4)262# CHECK-NEXT: Flags [ (0x4)
263# CHECK-NEXT: PF_R (0x4)263# CHECK-NEXT: PF_R (0x4)
264# CHECK-NEXT: ]264# CHECK-NEXT: ]
...@@ -291,16 +291,40 @@ __start:...@@ -291,16 +291,40 @@ __start:
291# CHECK-NEXT: Alignment: 65536291# CHECK-NEXT: Alignment: 65536
292# CHECK-NEXT: }292# CHECK-NEXT: }
293# CHECK-NEXT: ProgramHeader {293# CHECK-NEXT: ProgramHeader {
294# CHECK-NEXT: Type: PT_GNU_STACK294# CHECK-NEXT: Type: PT_GNU_STACK
295# CHECK-NEXT: Offset: 0x0295# CHECK-NEXT: Offset: 0x0
296# CHECK-NEXT: VirtualAddress: 0x0296# CHECK-NEXT: VirtualAddress: 0x0
297# CHECK-NEXT: PhysicalAddress: 0x0297# CHECK-NEXT: PhysicalAddress: 0x0
298# CHECK-NEXT: FileSize: 0298# CHECK-NEXT: FileSize: 0
299# CHECK-NEXT: MemSize: 0299# CHECK-NEXT: MemSize: 0
300# CHECK-NEXT: Flags [300# CHECK-NEXT: Flags [
301# CHECK-NEXT: PF_R301# CHECK-NEXT: PF_R
302# CHECK-NEXT: PF_W302# CHECK-NEXT: PF_W
303# CHECK-NEXT: ]303# CHECK-NEXT: ]
304# CHECK-NEXT: Alignment: 0304# CHECK-NEXT: Alignment: 0
305# CHECK-NEXT: }305# CHECK-NEXT: }
306# CHECK-NEXT:]306# CHECK-NEXT: ProgramHeader {
307# CHECK-NEXT: Type: PT_MIPS_REGINFO
308# CHECK-NEXT: Offset: 0x130
309# CHECK-NEXT: VirtualAddress: 0x10130
310# CHECK-NEXT: PhysicalAddress: 0x10130
311# CHECK-NEXT: FileSize: 24
312# CHECK-NEXT: MemSize: 24
313# CHECK-NEXT: Flags [ (0x4)
314# CHECK-NEXT: PF_R (0x4)
315# CHECK-NEXT: ]
316# CHECK-NEXT: Alignment: 4
317# CHECK-NEXT: }
318# CHECK-NEXT: ProgramHeader {
319# CHECK-NEXT: Type: PT_MIPS_ABIFLAGS
320# CHECK-NEXT: Offset: 0x118
321# CHECK-NEXT: VirtualAddress: 0x10118
322# CHECK-NEXT: PhysicalAddress: 0x10118
323# CHECK-NEXT: FileSize: 24
324# CHECK-NEXT: MemSize: 24
325# CHECK-NEXT: Flags [ (0x4)
326# CHECK-NEXT: PF_R (0x4)
327# CHECK-NEXT: ]
328# CHECK-NEXT: Alignment: 8
329# CHECK-NEXT: }
330# CHECK-NEXT: ]
deps/lld/test/ELF/basic-ppc.s+41-165
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: ppc1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t2# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t.o
3# RUN: ld.lld --hash-style=sysv -discard-all -shared %t -o %t23# RUN: ld.lld %t.o -o %t
4# RUN: llvm-readobj -file-headers -sections -section-data -program-headers %t2 | FileCheck %s4# RUN: llvm-readobj --file-headers --sections --section-data -l %t | FileCheck %s
55
6# exits with return code 42 on FreeBSD6# exits with return code 42 on FreeBSD
7.text7.text
...@@ -23,20 +23,20 @@...@@ -23,20 +23,20 @@
23// CHECK-NEXT: ABIVersion: 023// CHECK-NEXT: ABIVersion: 0
24// CHECK-NEXT: Unused: (00 00 00 00 00 00 00)24// CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
25// CHECK-NEXT: }25// CHECK-NEXT: }
26// CHECK-NEXT: Type: SharedObject (0x3)26// CHECK-NEXT: Type: Executable (0x2)
27// CHECK-NEXT: Machine: EM_PPC (0x14)27// CHECK-NEXT: Machine: EM_PPC (0x14)
28// CHECK-NEXT: Version: 128// CHECK-NEXT: Version: 1
29// CHECK-NEXT: Entry: 0x100029// CHECK-NEXT: Entry: 0x10010000
30// CHECK-NEXT: ProgramHeaderOffset: 0x3430// CHECK-NEXT: ProgramHeaderOffset: 0x34
31// CHECK-NEXT: SectionHeaderOffset: 0x20AC31// CHECK-NEXT: SectionHeaderOffset: 0x11044
32// CHECK-NEXT: Flags [ (0x0)32// CHECK-NEXT: Flags [ (0x0)
33// CHECK-NEXT: ]33// CHECK-NEXT: ]
34// CHECK-NEXT: HeaderSize: 5234// CHECK-NEXT: HeaderSize: 52
35// CHECK-NEXT: ProgramHeaderEntrySize: 3235// CHECK-NEXT: ProgramHeaderEntrySize: 32
36// CHECK-NEXT: ProgramHeaderCount: 736// CHECK-NEXT: ProgramHeaderCount: 4
37// CHECK-NEXT: SectionHeaderEntrySize: 4037// CHECK-NEXT: SectionHeaderEntrySize: 40
38// CHECK-NEXT: SectionHeaderCount: 1038// CHECK-NEXT: SectionHeaderCount: 6
39// CHECK-NEXT: StringTableSectionIndex: 839// CHECK-NEXT: StringTableSectionIndex: 4
40// CHECK-NEXT: }40// CHECK-NEXT: }
41// CHECK-NEXT: Sections [41// CHECK-NEXT: Sections [
42// CHECK-NEXT: Section {42// CHECK-NEXT: Section {
...@@ -57,68 +57,14 @@...@@ -57,68 +57,14 @@
57// CHECK-NEXT: }57// CHECK-NEXT: }
58// CHECK-NEXT: Section {58// CHECK-NEXT: Section {
59// CHECK-NEXT: Index: 159// CHECK-NEXT: Index: 1
60// CHECK-NEXT: Name: .dynsym
61// CHECK-NEXT: Type: SHT_DYNSYM (0xB)
62// CHECK-NEXT: Flags [ (0x2)
63// CHECK-NEXT: SHF_ALLOC (0x2)
64// CHECK-NEXT: ]
65// CHECK-NEXT: Address: 0x114
66// CHECK-NEXT: Offset: 0x114
67// CHECK-NEXT: Size: 16
68// CHECK-NEXT: Link: 3
69// CHECK-NEXT: Info: 1
70// CHECK-NEXT: AddressAlignment: 4
71// CHECK-NEXT: EntrySize: 16
72// CHECK-NEXT: SectionData (
73// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
74// CHECK-NEXT: )
75// CHECK-NEXT: }
76// CHECK-NEXT: Section {
77// CHECK-NEXT: Index: 2
78// CHECK-NEXT: Name: .hash
79// CHECK-NEXT: Type: SHT_HASH (0x5)
80// CHECK-NEXT: Flags [ (0x2)
81// CHECK-NEXT: SHF_ALLOC (0x2)
82// CHECK-NEXT: ]
83// CHECK-NEXT: Address: 0x124
84// CHECK-NEXT: Offset: 0x124
85// CHECK-NEXT: Size: 16
86// CHECK-NEXT: Link: 1
87// CHECK-NEXT: Info: 0
88// CHECK-NEXT: AddressAlignment: 4
89// CHECK-NEXT: EntrySize: 4
90// CHECK-NEXT: SectionData (
91// CHECK-NEXT: 0000: 00000001 00000001 00000000 00000000 |................|
92// CHECK-NEXT: )
93// CHECK-NEXT: }
94// CHECK-NEXT: Section {
95// CHECK-NEXT: Index: 3
96// CHECK-NEXT: Name: .dynstr
97// CHECK-NEXT: Type: SHT_STRTAB (0x3)
98// CHECK-NEXT: Flags [ (0x2)
99// CHECK-NEXT: SHF_ALLOC (0x2)
100// CHECK-NEXT: ]
101// CHECK-NEXT: Address: 0x134
102// CHECK-NEXT: Offset: 0x134
103// CHECK-NEXT: Size: 1
104// CHECK-NEXT: Link: 0
105// CHECK-NEXT: Info: 0
106// CHECK-NEXT: AddressAlignment: 1
107// CHECK-NEXT: EntrySize: 0
108// CHECK-NEXT: SectionData (
109// CHECK-NEXT: 0000: 00 |.|
110// CHECK-NEXT: )
111// CHECK-NEXT: }
112// CHECK-NEXT: Section {
113// CHECK-NEXT: Index: 4
114// CHECK-NEXT: Name: .text60// CHECK-NEXT: Name: .text
115// CHECK-NEXT: Type: SHT_PROGBITS (0x1)61// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
116// CHECK-NEXT: Flags [ (0x6)62// CHECK-NEXT: Flags [ (0x6)
117// CHECK-NEXT: SHF_ALLOC (0x2)63// CHECK-NEXT: SHF_ALLOC (0x2)
118// CHECK-NEXT: SHF_EXECINSTR (0x4)64// CHECK-NEXT: SHF_EXECINSTR (0x4)
119// CHECK-NEXT: ]65// CHECK-NEXT: ]
120// CHECK-NEXT: Address: 0x100066// CHECK-NEXT: Address: 0x10010000
121// CHECK-NEXT: Offset: 0x100067// CHECK-NEXT: Offset: 0x10000
122// CHECK-NEXT: Size: 1268// CHECK-NEXT: Size: 12
123// CHECK-NEXT: Link: 069// CHECK-NEXT: Link: 0
124// CHECK-NEXT: Info: 070// CHECK-NEXT: Info: 0
...@@ -129,28 +75,7 @@...@@ -129,28 +75,7 @@
129// CHECK-NEXT: )75// CHECK-NEXT: )
130// CHECK-NEXT: }76// CHECK-NEXT: }
131// CHECK-NEXT: Section {77// CHECK-NEXT: Section {
132// CHECK-NEXT: Index: 578// CHECK-NEXT: Index: 2
133// CHECK-NEXT: Name: .dynamic
134// CHECK-NEXT: Type: SHT_DYNAMIC (0x6)
135// CHECK-NEXT: Flags [ (0x3)
136// CHECK-NEXT: SHF_ALLOC (0x2)
137// CHECK-NEXT: SHF_WRITE (0x1)
138// CHECK-NEXT: ]
139// CHECK-NEXT: Address: 0x2000
140// CHECK-NEXT: Offset: 0x2000
141// CHECK-NEXT: Size: 48
142// CHECK-NEXT: Link: 3
143// CHECK-NEXT: Info: 0
144// CHECK-NEXT: AddressAlignment: 4
145// CHECK-NEXT: EntrySize: 8
146// CHECK-NEXT: SectionData (
147// CHECK-NEXT: 0000: 00000006 00000114 0000000B 00000010
148// CHECK-NEXT: 0010: 00000005 00000134 0000000A 00000001
149// CHECK-NEXT: 0020: 00000004 00000124 00000000 00000000
150// CHECK-NEXT: )
151// CHECK-NEXT: }
152// CHECK-NEXT: Section {
153// CHECK-NEXT: Index: 6
154// CHECK-NEXT: Name: .comment79// CHECK-NEXT: Name: .comment
155// CHECK-NEXT: Type: SHT_PROGBITS (0x1)80// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
156// CHECK-NEXT: Flags [ (0x30)81// CHECK-NEXT: Flags [ (0x30)
...@@ -158,70 +83,59 @@...@@ -158,70 +83,59 @@
158// CHECK-NEXT: SHF_STRINGS (0x20)83// CHECK-NEXT: SHF_STRINGS (0x20)
159// CHECK-NEXT: ]84// CHECK-NEXT: ]
160// CHECK-NEXT: Address: 0x085// CHECK-NEXT: Address: 0x0
161// CHECK-NEXT: Offset: 0x203086// CHECK-NEXT: Offset: 0x11000
162// CHECK-NEXT: Size: 887// CHECK-NEXT: Size: 8
163// CHECK-NEXT: Link: 088// CHECK-NEXT: Link: 0
164// CHECK-NEXT: Info: 089// CHECK-NEXT: Info: 0
165// CHECK-NEXT: AddressAlignment: 190// CHECK-NEXT: AddressAlignment: 1
166// CHECK-NEXT: EntrySize: 191// CHECK-NEXT: EntrySize: 1
167// CHECK-NEXT: SectionData (92// CHECK: }
168// CHECK-NEXT: 0000: 4C4C4420 312E3000 |LLD 1.0.|
169// CHECK-NEXT: )
170// CHECK-NEXT: }
171// CHECK-NEXT: Section {93// CHECK-NEXT: Section {
172// CHECK-NEXT: Index: 794// CHECK-NEXT: Index: 3
173// CHECK-NEXT: Name: .symtab95// CHECK-NEXT: Name: .symtab
174// CHECK-NEXT: Type: SHT_SYMTAB (0x2)96// CHECK-NEXT: Type: SHT_SYMTAB (0x2)
175// CHECK-NEXT: Flags [ (0x0)97// CHECK-NEXT: Flags [ (0x0)
176// CHECK-NEXT: ]98// CHECK-NEXT: ]
177// CHECK-NEXT: Address: 0x099// CHECK-NEXT: Address: 0x0
178// CHECK-NEXT: Offset: 0x2038100// CHECK-NEXT: Offset: 0x11008
179// CHECK-NEXT: Size: 32101// CHECK-NEXT: Size: 16
180// CHECK-NEXT: Link: 9102// CHECK-NEXT: Link: 5
181// CHECK-NEXT: Info: 2103// CHECK-NEXT: Info: 1
182// CHECK-NEXT: AddressAlignment: 4104// CHECK-NEXT: AddressAlignment: 4
183// CHECK-NEXT: EntrySize: 16105// CHECK-NEXT: EntrySize: 16
184// CHECK-NEXT: SectionData (106// CHECK-NEXT: SectionData (
185// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|107// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
186// CHECK-NEXT: 0010: 00000001 00002000 00000000 00020005 |...... .........|
187// CHECK-NEXT: )108// CHECK-NEXT: )
188// CHECK-NEXT: }109// CHECK-NEXT: }
189// CHECK-NEXT: Section {110// CHECK-NEXT: Section {
190// CHECK-NEXT: Index: 8111// CHECK-NEXT: Index: 4
191// CHECK-NEXT: Name: .shstrtab112// CHECK-NEXT: Name: .shstrtab
192// CHECK-NEXT: Type: SHT_STRTAB (0x3)113// CHECK-NEXT: Type: SHT_STRTAB (0x3)
193// CHECK-NEXT: Flags [ (0x0)114// CHECK-NEXT: Flags [ (0x0)
194// CHECK-NEXT: ]115// CHECK-NEXT: ]
195// CHECK-NEXT: Address: 0x0116// CHECK-NEXT: Address: 0x0
196// CHECK-NEXT: Offset: 0x2058117// CHECK-NEXT: Offset: 0x11018
197// CHECK-NEXT: Size: 73118// CHECK-NEXT: Size: 42
198// CHECK-NEXT: Link: 0119// CHECK-NEXT: Link: 0
199// CHECK-NEXT: Info: 0120// CHECK-NEXT: Info: 0
200// CHECK-NEXT: AddressAlignment: 1121// CHECK-NEXT: AddressAlignment: 1
201// CHECK-NEXT: EntrySize: 0122// CHECK-NEXT: EntrySize: 0
202// CHECK-NEXT: SectionData (123// CHECK: }
203// CHECK-NEXT: 0000: 002E6479 6E73796D 002E6861 7368002E |..dynsym..hash..|
204// CHECK-NEXT: 0010: 64796E73 7472002E 74657874 002E6479 |dynstr..text..dy|
205// CHECK-NEXT: 0020: 6E616D69 63002E63 6F6D6D65 6E74002E |namic..comment..|
206// CHECK-NEXT: 0030: 73796D74 6162002E 73687374 72746162 |symtab..shstrtab|
207// CHECK-NEXT: 0040: 002E7374 72746162 00 |..strtab.|
208// CHECK-NEXT: )
209// CHECK-NEXT: }
210// CHECK-NEXT: Section {124// CHECK-NEXT: Section {
211// CHECK-NEXT: Index: 9125// CHECK-NEXT: Index: 5
212// CHECK-NEXT: Name: .strtab126// CHECK-NEXT: Name: .strtab
213// CHECK-NEXT: Type: SHT_STRTAB (0x3)127// CHECK-NEXT: Type: SHT_STRTAB (0x3)
214// CHECK-NEXT: Flags [ (0x0)128// CHECK-NEXT: Flags [ (0x0)
215// CHECK-NEXT: ]129// CHECK-NEXT: ]
216// CHECK-NEXT: Address: 0x0130// CHECK-NEXT: Address: 0x0
217// CHECK-NEXT: Offset: 0x20A1131// CHECK-NEXT: Offset: 0x11042
218// CHECK-NEXT: Size: 10132// CHECK-NEXT: Size: 1
219// CHECK-NEXT: Link: 0133// CHECK-NEXT: Link: 0
220// CHECK-NEXT: Info: 0134// CHECK-NEXT: Info: 0
221// CHECK-NEXT: AddressAlignment: 1135// CHECK-NEXT: AddressAlignment: 1
222// CHECK-NEXT: EntrySize: 0136// CHECK-NEXT: EntrySize: 0
223// CHECK-NEXT: SectionData (137// CHECK-NEXT: SectionData (
224// CHECK-NEXT: 0000: 005F4459 4E414D49 4300 |._DYNAMIC.|138// CHECK-NEXT: 0000: 00
225// CHECK-NEXT: )139// CHECK-NEXT: )
226// CHECK-NEXT: }140// CHECK-NEXT: }
227// CHECK-NEXT: ]141// CHECK-NEXT: ]
...@@ -229,10 +143,10 @@...@@ -229,10 +143,10 @@
229// CHECK-NEXT: ProgramHeader {143// CHECK-NEXT: ProgramHeader {
230// CHECK-NEXT: Type: PT_PHDR (0x6)144// CHECK-NEXT: Type: PT_PHDR (0x6)
231// CHECK-NEXT: Offset: 0x34145// CHECK-NEXT: Offset: 0x34
232// CHECK-NEXT: VirtualAddress: 0x34146// CHECK-NEXT: VirtualAddress: 0x10000034
233// CHECK-NEXT: PhysicalAddress: 0x34147// CHECK-NEXT: PhysicalAddress: 0x10000034
234// CHECK-NEXT: FileSize: 224148// CHECK-NEXT: FileSize: 128
235// CHECK-NEXT: MemSize: 224149// CHECK-NEXT: MemSize: 128
236// CHECK-NEXT: Flags [ (0x4)150// CHECK-NEXT: Flags [ (0x4)
237// CHECK-NEXT: PF_R (0x4)151// CHECK-NEXT: PF_R (0x4)
238// CHECK-NEXT: ]152// CHECK-NEXT: ]
...@@ -241,65 +155,27 @@...@@ -241,65 +155,27 @@
241// CHECK-NEXT: ProgramHeader {155// CHECK-NEXT: ProgramHeader {
242// CHECK-NEXT: Type: PT_LOAD (0x1)156// CHECK-NEXT: Type: PT_LOAD (0x1)
243// CHECK-NEXT: Offset: 0x0157// CHECK-NEXT: Offset: 0x0
244// CHECK-NEXT: VirtualAddress: 0x0158// CHECK-NEXT: VirtualAddress: 0x10000000
245// CHECK-NEXT: PhysicalAddress: 0x0159// CHECK-NEXT: PhysicalAddress: 0x10000000
246// CHECK-NEXT: FileSize: 309160// CHECK-NEXT: FileSize: 180
247// CHECK-NEXT: MemSize: 309161// CHECK-NEXT: MemSize: 180
248// CHECK-NEXT: Flags [ (0x4)162// CHECK-NEXT: Flags [ (0x4)
249// CHECK-NEXT: PF_R (0x4)163// CHECK-NEXT: PF_R (0x4)
250// CHECK-NEXT: ]164// CHECK-NEXT: ]
251// CHECK-NEXT: Alignment: 4096165// CHECK-NEXT: Alignment: 65536
252// CHECK-NEXT: }166// CHECK-NEXT: }
253// CHECK-NEXT: ProgramHeader {167// CHECK-NEXT: ProgramHeader {
254// CHECK-NEXT: Type: PT_LOAD (0x1)168// CHECK-NEXT: Type: PT_LOAD (0x1)
255// CHECK-NEXT: Offset: 0x1000169// CHECK-NEXT: Offset: 0x1000
256// CHECK-NEXT: VirtualAddress: 0x1000170// CHECK-NEXT: VirtualAddress: 0x10010000
257// CHECK-NEXT: PhysicalAddress: 0x1000171// CHECK-NEXT: PhysicalAddress: 0x10010000
258// CHECK-NEXT: FileSize: 12172// CHECK-NEXT: FileSize: 4096
259// CHECK-NEXT: MemSize: 12173// CHECK-NEXT: MemSize: 4096
260// CHECK-NEXT: Flags [ (0x5)174// CHECK-NEXT: Flags [ (0x5)
261// CHECK-NEXT: PF_R (0x4)175// CHECK-NEXT: PF_R (0x4)
262// CHECK-NEXT: PF_X (0x1)176// CHECK-NEXT: PF_X (0x1)
263// CHECK-NEXT: ]177// CHECK-NEXT: ]
264// CHECK-NEXT: Alignment: 4096178// CHECK-NEXT: Alignment: 65536
265// CHECK-NEXT: }
266// CHECK-NEXT: ProgramHeader {
267// CHECK-NEXT: Type: PT_LOAD (0x1)
268// CHECK-NEXT: Offset: 0x2000
269// CHECK-NEXT: VirtualAddress: 0x2000
270// CHECK-NEXT: PhysicalAddress: 0x2000
271// CHECK-NEXT: FileSize: 48
272// CHECK-NEXT: MemSize: 48
273// CHECK-NEXT: Flags [ (0x6)
274// CHECK-NEXT: PF_R (0x4)
275// CHECK-NEXT: PF_W (0x2)
276// CHECK-NEXT: ]
277// CHECK-NEXT: Alignment: 4096
278// CHECK-NEXT: }
279// CHECK-NEXT: ProgramHeader {
280// CHECK-NEXT: Type: PT_DYNAMIC (0x2)
281// CHECK-NEXT: Offset: 0x2000
282// CHECK-NEXT: VirtualAddress: 0x2000
283// CHECK-NEXT: PhysicalAddress: 0x2000
284// CHECK-NEXT: FileSize: 48
285// CHECK-NEXT: MemSize: 48
286// CHECK-NEXT: Flags [ (0x6)
287// CHECK-NEXT: PF_R (0x4)
288// CHECK-NEXT: PF_W (0x2)
289// CHECK-NEXT: ]
290// CHECK-NEXT: Alignment: 4
291// CHECK-NEXT: }
292// CHECK-NEXT: ProgramHeader {
293// CHECK-NEXT: Type: PT_GNU_RELRO (0x6474E552)
294// CHECK-NEXT: Offset: 0x2000
295// CHECK-NEXT: VirtualAddress: 0x2000
296// CHECK-NEXT: PhysicalAddress: 0x2000
297// CHECK-NEXT: FileSize: 48
298// CHECK-NEXT: MemSize: 4096
299// CHECK-NEXT: Flags [ (0x4)
300// CHECK-NEXT: PF_R (0x4)
301// CHECK-NEXT: ]
302// CHECK-NEXT: Alignment: 1
303// CHECK-NEXT: }179// CHECK-NEXT: }
304// CHECK-NEXT: ProgramHeader {180// CHECK-NEXT: ProgramHeader {
305// CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551)181// CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551)
deps/lld/test/ELF/basic-ppc64.s+48-30
...@@ -1,7 +1,12 @@...@@ -1,7 +1,12 @@
1# REQUIRES: ppc1# REQUIRES: ppc
2# # RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
3# RUN: ld.lld --hash-style=sysv -discard-all -shared %t -o %t23# RUN: ld.lld --hash-style=sysv -discard-all -shared %t.o -o %t.so
4# RUN: llvm-readobj -file-headers -sections -section-data -program-headers %t2 | FileCheck %s4# RUN: llvm-readobj --file-headers --sections --section-data -l %t.so | FileCheck --check-prefixes=CHECK,LE %s
5
6# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
7# RUN: ld.lld --hash-style=sysv -discard-all -shared %t.o -o %t.so
8# RUN: llvm-readobj --file-headers --sections --section-data -l %t.so | FileCheck --check-prefixes=CHECK,BE %s
9
5.abiversion 210.abiversion 2
6# Exits with return code 55 on linux.11# Exits with return code 55 on linux.
7.text12.text
...@@ -10,14 +15,16 @@...@@ -10,14 +15,16 @@
10 sc15 sc
1116
12// CHECK:Format: ELF64-ppc6417// CHECK:Format: ELF64-ppc64
13// CHECK-NEXT:Arch: powerpc64le18// LE-NEXT: Arch: powerpc64le
14// CHECK-NEXT:AddressSize: 64bit19// BE-NEXT: Arch: powerpc64{{$}}
15// CHECK-NEXT:LoadName: 20// CHECK-NEXT: AddressSize: 64bit
16// CHECK-NEXT:ElfHeader {21// CHECK-NEXT: LoadName:
22// CHECK-NEXT: ElfHeader {
17// CHECK-NEXT: Ident {23// CHECK-NEXT: Ident {
18// CHECK-NEXT: Magic: (7F 45 4C 46)24// CHECK-NEXT: Magic: (7F 45 4C 46)
19// CHECK-NEXT: Class: 64-bit (0x2)25// CHECK-NEXT: Class: 64-bit (0x2)
20// CHECK-NEXT: DataEncoding: LittleEndian (0x1)26// LE-NEXT: DataEncoding: LittleEndian (0x1)
27// BE-NEXT: DataEncoding: BigEndian (0x2)
21// CHECK-NEXT: FileVersion: 128// CHECK-NEXT: FileVersion: 1
22// CHECK-NEXT: OS/ABI: SystemV (0x0)29// CHECK-NEXT: OS/ABI: SystemV (0x0)
23// CHECK-NEXT: ABIVersion: 030// CHECK-NEXT: ABIVersion: 0
...@@ -63,8 +70,8 @@...@@ -63,8 +70,8 @@
63// CHECK-NEXT: Flags [ (0x2)70// CHECK-NEXT: Flags [ (0x2)
64// CHECK-NEXT: SHF_ALLOC (0x2)71// CHECK-NEXT: SHF_ALLOC (0x2)
65// CHECK-NEXT: ]72// CHECK-NEXT: ]
66// CHECK-NEXT: Address: 0x1C873// CHECK-NEXT: Address: 0x200
67// CHECK-NEXT: Offset: 0x1C874// CHECK-NEXT: Offset: 0x200
68// CHECK-NEXT: Size: 2475// CHECK-NEXT: Size: 24
69// CHECK-NEXT: Link: 376// CHECK-NEXT: Link: 3
70// CHECK-NEXT: Info: 177// CHECK-NEXT: Info: 1
...@@ -82,15 +89,16 @@...@@ -82,15 +89,16 @@
82// CHECK-NEXT: Flags [ (0x2)89// CHECK-NEXT: Flags [ (0x2)
83// CHECK-NEXT: SHF_ALLOC (0x2)90// CHECK-NEXT: SHF_ALLOC (0x2)
84// CHECK-NEXT: ]91// CHECK-NEXT: ]
85// CHECK-NEXT: Address: 0x1E092// CHECK-NEXT: Address: 0x218
86// CHECK-NEXT: Offset: 0x1E093// CHECK-NEXT: Offset: 0x218
87// CHECK-NEXT: Size: 1694// CHECK-NEXT: Size: 16
88// CHECK-NEXT: Link: 195// CHECK-NEXT: Link: 1
89// CHECK-NEXT: Info: 096// CHECK-NEXT: Info: 0
90// CHECK-NEXT: AddressAlignment: 497// CHECK-NEXT: AddressAlignment: 4
91// CHECK-NEXT: EntrySize: 498// CHECK-NEXT: EntrySize: 4
92// CHECK-NEXT: SectionData (99// CHECK-NEXT: SectionData (
93// CHECK-NEXT: 0000: 01000000 01000000 00000000 00000000 |................|100// LE-NEXT: 0000: 01000000 01000000 00000000 00000000
101// BE-NEXT: 0000: 00000001 00000001 00000000 00000000
94// CHECK-NEXT: )102// CHECK-NEXT: )
95// CHECK-NEXT: }103// CHECK-NEXT: }
96// CHECK-NEXT: Section {104// CHECK-NEXT: Section {
...@@ -100,8 +108,8 @@...@@ -100,8 +108,8 @@
100// CHECK-NEXT: Flags [ (0x2)108// CHECK-NEXT: Flags [ (0x2)
101// CHECK-NEXT: SHF_ALLOC (0x2)109// CHECK-NEXT: SHF_ALLOC (0x2)
102// CHECK-NEXT: ]110// CHECK-NEXT: ]
103// CHECK-NEXT: Address: 0x1F0111// CHECK-NEXT: Address: 0x228
104// CHECK-NEXT: Offset: 0x1F0112// CHECK-NEXT: Offset: 0x228
105// CHECK-NEXT: Size: 1113// CHECK-NEXT: Size: 1
106// CHECK-NEXT: Link: 0114// CHECK-NEXT: Link: 0
107// CHECK-NEXT: Info: 0115// CHECK-NEXT: Info: 0
...@@ -127,7 +135,8 @@...@@ -127,7 +135,8 @@
127// CHECK-NEXT: AddressAlignment: 4135// CHECK-NEXT: AddressAlignment: 4
128// CHECK-NEXT: EntrySize: 0136// CHECK-NEXT: EntrySize: 0
129// CHECK-NEXT: SectionData (137// CHECK-NEXT: SectionData (
130// CHECK-NEXT: 0000: 01000038 37006038 02000044 |...87.`8...D|138// LE-NEXT: 0000: 01000038 37006038 02000044
139// BE-NEXT: 0000: 38000001 38600037 44000002
131// CHECK-NEXT: )140// CHECK-NEXT: )
132// CHECK-NEXT: }141// CHECK-NEXT: }
133// CHECK-NEXT: Section {142// CHECK-NEXT: Section {
...@@ -146,12 +155,18 @@...@@ -146,12 +155,18 @@
146// CHECK-NEXT: AddressAlignment: 8155// CHECK-NEXT: AddressAlignment: 8
147// CHECK-NEXT: EntrySize: 16156// CHECK-NEXT: EntrySize: 16
148// CHECK-NEXT: SectionData (157// CHECK-NEXT: SectionData (
149// CHECK-NEXT: 0000: 06000000 00000000 C8010000 00000000 |................|158// LE-NEXT: 0000: 06000000 00000000 00020000 00000000 |
150// CHECK-NEXT: 0010: 0B000000 00000000 18000000 00000000 |................|159// LE-NEXT: 0010: 0B000000 00000000 18000000 00000000 |
151// CHECK-NEXT: 0020: 05000000 00000000 F0010000 00000000 |................|160// LE-NEXT: 0020: 05000000 00000000 28020000 00000000 |
152// CHECK-NEXT: 0030: 0A000000 00000000 01000000 00000000 |................|161// LE-NEXT: 0030: 0A000000 00000000 01000000 00000000 |
153// CHECK-NEXT: 0040: 04000000 00000000 E0010000 00000000 |................|162// LE-NEXT: 0040: 04000000 00000000 18020000 00000000 |
154// CHECK-NEXT: 0050: 00000000 00000000 00000000 00000000 |................|163// LE-NEXT: 0050: 00000000 00000000 00000000 00000000 |
164// BE-NEXT: 0000: 00000000 00000006 00000000 00000200 |
165// BE-NEXT: 0010: 00000000 0000000B 00000000 00000018 |
166// BE-NEXT: 0020: 00000000 00000005 00000000 00000228 |
167// BE-NEXT: 0030: 00000000 0000000A 00000000 00000001 |
168// BE-NEXT: 0040: 00000000 00000004 00000000 00000218 |
169// BE-NEXT: 0050: 00000000 00000000 00000000 00000000 |
155// CHECK-NEXT: )170// CHECK-NEXT: )
156// CHECK-NEXT: }171// CHECK-NEXT: }
157// CHECK-NEXT: Section {172// CHECK-NEXT: Section {
...@@ -203,9 +218,12 @@...@@ -203,9 +218,12 @@
203// CHECK-NEXT: AddressAlignment: 8218// CHECK-NEXT: AddressAlignment: 8
204// CHECK-NEXT: EntrySize: 24219// CHECK-NEXT: EntrySize: 24
205// CHECK-NEXT: SectionData (220// CHECK-NEXT: SectionData (
206// CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|221// LE-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
207// CHECK-NEXT: 0010: 00000000 00000000 01000000 00020500 |................|222// LE-NEXT: 0010: 00000000 00000000 01000000 00020500 |................|
208// CHECK-NEXT: 0020: 00000200 00000000 00000000 00000000 |................|223// LE-NEXT: 0020: 00000200 00000000 00000000 00000000 |................|
224// BE-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
225// BE-NEXT: 0010: 00000000 00000000 00000001 00020005 |................|
226// BE-NEXT: 0020: 00000000 00020000 00000000 00000000 |................|
209// CHECK-NEXT: )227// CHECK-NEXT: )
210// CHECK-NEXT: }228// CHECK-NEXT: }
211// CHECK-NEXT: Section {229// CHECK-NEXT: Section {
...@@ -254,8 +272,8 @@...@@ -254,8 +272,8 @@
254// CHECK-NEXT: Offset: 0x40272// CHECK-NEXT: Offset: 0x40
255// CHECK-NEXT: VirtualAddress: 0x40273// CHECK-NEXT: VirtualAddress: 0x40
256// CHECK-NEXT: PhysicalAddress: 0x40274// CHECK-NEXT: PhysicalAddress: 0x40
257// CHECK-NEXT: FileSize: 392275// CHECK-NEXT: FileSize: 448
258// CHECK-NEXT: MemSize: 392276// CHECK-NEXT: MemSize: 448
259// CHECK-NEXT: Flags [ (0x4)277// CHECK-NEXT: Flags [ (0x4)
260// CHECK-NEXT: PF_R (0x4)278// CHECK-NEXT: PF_R (0x4)
261// CHECK-NEXT: ]279// CHECK-NEXT: ]
...@@ -266,8 +284,8 @@...@@ -266,8 +284,8 @@
266// CHECK-NEXT: Offset: 0x0284// CHECK-NEXT: Offset: 0x0
267// CHECK-NEXT: VirtualAddress: 0x0285// CHECK-NEXT: VirtualAddress: 0x0
268// CHECK-NEXT: PhysicalAddress: 0x0286// CHECK-NEXT: PhysicalAddress: 0x0
269// CHECK-NEXT: FileSize: 497287// CHECK-NEXT: FileSize: 553
270// CHECK-NEXT: MemSize: 497288// CHECK-NEXT: MemSize: 553
271// CHECK-NEXT: Flags [ (0x4)289// CHECK-NEXT: Flags [ (0x4)
272// CHECK-NEXT: PF_R (0x4)290// CHECK-NEXT: PF_R (0x4)
273// CHECK-NEXT: ]291// CHECK-NEXT: ]
...@@ -292,7 +310,7 @@...@@ -292,7 +310,7 @@
292// CHECK-NEXT: VirtualAddress: 0x20000310// CHECK-NEXT: VirtualAddress: 0x20000
293// CHECK-NEXT: PhysicalAddress: 0x20000311// CHECK-NEXT: PhysicalAddress: 0x20000
294// CHECK-NEXT: FileSize: 96312// CHECK-NEXT: FileSize: 96
295// CHECK-NEXT: MemSize: 65536313// CHECK-NEXT: MemSize: 96
296// CHECK-NEXT: Flags [ (0x6)314// CHECK-NEXT: Flags [ (0x6)
297// CHECK-NEXT: PF_R (0x4)315// CHECK-NEXT: PF_R (0x4)
298// CHECK-NEXT: PF_W (0x2)316// CHECK-NEXT: PF_W (0x2)
deps/lld/test/ELF/basic-sparcv9.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: sparc1# REQUIRES: sparc
2# RUN: llvm-mc -filetype=obj -triple=sparc64-unknown-openbsd %s -o %t2# RUN: llvm-mc -filetype=obj -triple=sparc64-unknown-openbsd %s -o %t
3# RUN: ld.lld %t -o %t23# RUN: ld.lld %t -o %t2
4# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 \4# RUN: llvm-readobj --file-headers --sections -l --symbols %t2 \
5# RUN: | FileCheck %s5# RUN: | FileCheck %s
66
7# exits with return code 42 on OpenBSD/sparc647# exits with return code 42 on OpenBSD/sparc64
deps/lld/test/ELF/basic.s+6-3
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4# RUN: ld.lld %t -o %t24# RUN: ld.lld %t -o %t2
5# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 \5# RUN: llvm-readobj --file-headers --sections -l --symbols %t2 \
6# RUN: | FileCheck %s6# RUN: | FileCheck %s
7# RUN: ld.lld %t -o /dev/null7# RUN: ld.lld %t -o /dev/null
88
...@@ -204,7 +204,7 @@ _start:...@@ -204,7 +204,7 @@ _start:
204# Test for the response file (POSIX quoting style)204# Test for the response file (POSIX quoting style)
205# RUN: echo " -o %t2" > %t.responsefile205# RUN: echo " -o %t2" > %t.responsefile
206# RUN: ld.lld %t --rsp-quoting=posix @%t.responsefile206# RUN: ld.lld %t --rsp-quoting=posix @%t.responsefile
207# RUN: llvm-readobj -file-headers -sections -program-headers -symbols %t2 \207# RUN: llvm-readobj --file-headers --sections -l --symbols %t2 \
208# RUN: | FileCheck %s208# RUN: | FileCheck %s
209209
210# Test for the response file (Windows quoting style)210# Test for the response file (Windows quoting style)
...@@ -234,7 +234,7 @@ _start:...@@ -234,7 +234,7 @@ _start:
234# NO_O_VAL: -o: missing argument234# NO_O_VAL: -o: missing argument
235235
236# RUN: not ld.lld --foo 2>&1 | FileCheck --check-prefix=UNKNOWN %s236# RUN: not ld.lld --foo 2>&1 | FileCheck --check-prefix=UNKNOWN %s
237# UNKNOWN: unknown argument: --foo237# UNKNOWN: unknown argument '--foo'
238238
239# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t239# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
240# RUN: not ld.lld %t %t -o %t2 2>&1 | FileCheck --check-prefix=DUP %s240# RUN: not ld.lld %t %t -o %t2 2>&1 | FileCheck --check-prefix=DUP %s
...@@ -252,3 +252,6 @@ _start:...@@ -252,3 +252,6 @@ _start:
252# RUN: not ld.lld %t --thinlto-jobs=0 2>&1 | FileCheck --check-prefix=NOTHREADSTHIN %s252# RUN: not ld.lld %t --thinlto-jobs=0 2>&1 | FileCheck --check-prefix=NOTHREADSTHIN %s
253# RUN: not ld.lld %t --plugin-opt=jobs=0 2>&1 | FileCheck --check-prefix=NOTHREADSTHIN %s253# RUN: not ld.lld %t --plugin-opt=jobs=0 2>&1 | FileCheck --check-prefix=NOTHREADSTHIN %s
254# NOTHREADSTHIN: --thinlto-jobs: number of threads must be > 0254# NOTHREADSTHIN: --thinlto-jobs: number of threads must be > 0
255
256# RUN: not ld.lld %t -z ifunc-noplt -z text 2>&1 | FileCheck --check-prefix=NOIFUNCPLTNOTEXTREL %s
257# NOIFUNCPLTNOTEXTREL: -z text and -z ifunc-noplt may not be used together
deps/lld/test/ELF/basic32.s deleted-179
...@@ -1,179 +0,0 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t
3# RUN: ld.lld %t -o %t2
4# RUN: llvm-readobj -file-headers -sections -program-headers %t2 | FileCheck %s
5
6# exits with return code 42 on linux
7.globl _start
8_start:
9 mov $1, %eax
10 mov $42, %ebx
11 int $0x80
12
13# CHECK: ElfHeader {
14# CHECK-NEXT: Ident {
15# CHECK-NEXT: Magic: (7F 45 4C 46)
16# CHECK-NEXT: Class: 32-bit (0x1)
17# CHECK-NEXT: DataEncoding: LittleEndian (0x1)
18# CHECK-NEXT: FileVersion: 1
19# CHECK-NEXT: OS/ABI: SystemV (0x0)
20# CHECK-NEXT: ABIVersion: 0
21# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
22# CHECK-NEXT: }
23# CHECK-NEXT: Type: Executable (0x2)
24# CHECK-NEXT: Machine: EM_386 (0x3)
25# CHECK-NEXT: Version: 1
26# CHECK-NEXT: Entry: 0x401000
27# CHECK-NEXT: ProgramHeaderOffset: 0x34
28# CHECK-NEXT: SectionHeaderOffset: 0x205C
29# CHECK-NEXT: Flags [ (0x0)
30# CHECK-NEXT: ]
31# CHECK-NEXT: HeaderSize: 52
32# CHECK-NEXT: ProgramHeaderEntrySize: 32
33# CHECK-NEXT: ProgramHeaderCount: 4
34# CHECK-NEXT: SectionHeaderEntrySize: 40
35# CHECK-NEXT: SectionHeaderCount: 6
36# CHECK-NEXT: StringTableSectionIndex: 4
37# CHECK-NEXT: }
38# CHECK-NEXT: Sections [
39# CHECK-NEXT: Section {
40# CHECK-NEXT: Index: 0
41# CHECK-NEXT: Name: (0)
42# CHECK-NEXT: Type: SHT_NULL (0x0)
43# CHECK-NEXT: Flags [ (0x0)
44# CHECK-NEXT: ]
45# CHECK-NEXT: Address: 0x0
46# CHECK-NEXT: Offset: 0x0
47# CHECK-NEXT: Size: 0
48# CHECK-NEXT: Link: 0
49# CHECK-NEXT: Info: 0
50# CHECK-NEXT: AddressAlignment: 0
51# CHECK-NEXT: EntrySize: 0
52# CHECK-NEXT: }
53# CHECK-NEXT: Section {
54# CHECK-NEXT: Index: 1
55# CHECK-NEXT: Name: .text
56# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
57# CHECK-NEXT: Flags [ (0x6)
58# CHECK-NEXT: SHF_ALLOC (0x2)
59# CHECK-NEXT: SHF_EXECINSTR (0x4)
60# CHECK-NEXT: ]
61# CHECK-NEXT: Address: 0x401000
62# CHECK-NEXT: Offset: 0x1000
63# CHECK-NEXT: Size: 12
64# CHECK-NEXT: Link: 0
65# CHECK-NEXT: Info: 0
66# CHECK-NEXT: AddressAlignment: 4
67# CHECK-NEXT: EntrySize: 0
68# CHECK-NEXT: }
69# CHECK-NEXT: Section {
70# CHECK-NEXT: Index: 2
71# CHECK-NEXT: Name: .comment
72# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
73# CHECK-NEXT: Flags [ (0x30)
74# CHECK-NEXT: SHF_MERGE (0x10)
75# CHECK-NEXT: SHF_STRINGS (0x20)
76# CHECK-NEXT: ]
77# CHECK-NEXT: Address: 0x0
78# CHECK-NEXT: Offset: 0x2000
79# CHECK-NEXT: Size: 8
80# CHECK-NEXT: Link: 0
81# CHECK-NEXT: Info: 0
82# CHECK-NEXT: AddressAlignment: 1
83# CHECK-NEXT: EntrySize: 1
84# CHECK-NEXT: }
85# CHECK-NEXT: Section {
86# CHECK-NEXT: Index: 3
87# CHECK-NEXT: Name: .symtab
88# CHECK-NEXT: Type: SHT_SYMTAB
89# CHECK-NEXT: Flags [
90# CHECK-NEXT: ]
91# CHECK-NEXT: Address: 0x0
92# CHECK-NEXT: Offset: 0x2008
93# CHECK-NEXT: Size: 32
94# CHECK-NEXT: Link: 5
95# CHECK-NEXT: Info: 1
96# CHECK-NEXT: AddressAlignment: 4
97# CHECK-NEXT: EntrySize: 16
98# CHECK-NEXT: }
99# CHECK-NEXT: Section {
100# CHECK-NEXT: Index: 4
101# CHECK-NEXT: Name: .shstrtab
102# CHECK-NEXT: Type: SHT_STRTAB (0x3)
103# CHECK-NEXT: Flags [ (0x0)
104# CHECK-NEXT: ]
105# CHECK-NEXT: Address: 0x0
106# CHECK-NEXT: Offset: 0x2028
107# CHECK-NEXT: Size: 42
108# CHECK-NEXT: Link: 0
109# CHECK-NEXT: Info: 0
110# CHECK-NEXT: AddressAlignment: 1
111# CHECK-NEXT: EntrySize: 0
112# CHECK-NEXT: }
113# CHECK-NEXT: Section {
114# CHECK-NEXT: Index: 5
115# CHECK-NEXT: Name: .strtab
116# CHECK-NEXT: Type: SHT_STRTAB (0x3)
117# CHECK-NEXT: Flags [ (0x0)
118# CHECK-NEXT: ]
119# CHECK-NEXT: Address: 0x0
120# CHECK-NEXT: Offset: 0x2052
121# CHECK-NEXT: Size: 8
122# CHECK-NEXT: Link: 0
123# CHECK-NEXT: Info: 0
124# CHECK-NEXT: AddressAlignment: 1
125# CHECK-NEXT: EntrySize: 0
126# CHECK-NEXT: }
127# CHECK-NEXT: ]
128# CHECK-NEXT: ProgramHeaders [
129# CHECK-NEXT: ProgramHeader {
130# CHECK-NEXT: Type: PT_PHDR (0x6)
131# CHECK-NEXT: Offset: 0x34
132# CHECK-NEXT: VirtualAddress: 0x400034
133# CHECK-NEXT: PhysicalAddress: 0x400034
134# CHECK-NEXT: FileSize: 128
135# CHECK-NEXT: MemSize: 128
136# CHECK-NEXT: Flags [ (0x4)
137# CHECK-NEXT: PF_R (0x4)
138# CHECK-NEXT: ]
139# CHECK-NEXT: Alignment: 4
140# CHECK-NEXT: }
141# CHECK-NEXT: ProgramHeader {
142# CHECK-NEXT: Type: PT_LOAD (0x1)
143# CHECK-NEXT: Offset: 0x0
144# CHECK-NEXT: VirtualAddress: 0x400000
145# CHECK-NEXT: PhysicalAddress: 0x400000
146# CHECK-NEXT: FileSize: 180
147# CHECK-NEXT: MemSize: 180
148# CHECK-NEXT: Flags [
149# CHECK-NEXT: PF_R
150# CHECK-NEXT: ]
151# CHECK-NEXT: Alignment: 4096
152# CHECK-NEXT: }
153# CHECK-NEXT: ProgramHeader {
154# CHECK-NEXT: Type: PT_LOAD (0x1)
155# CHECK-NEXT: Offset: 0x1000
156# CHECK-NEXT: VirtualAddress: 0x401000
157# CHECK-NEXT: PhysicalAddress: 0x401000
158# CHECK-NEXT: FileSize: 4096
159# CHECK-NEXT: MemSize: 4096
160# CHECK-NEXT: Flags [ (0x5)
161# CHECK-NEXT: PF_R (0x4)
162# CHECK-NEXT: PF_X (0x1)
163# CHECK-NEXT: ]
164# CHECK-NEXT: Alignment: 4096
165# CHECK-NEXT: }
166# CHECK-NEXT: ProgramHeader {
167# CHECK-NEXT: Type: PT_GNU_STACK
168# CHECK-NEXT: Offset: 0x0
169# CHECK-NEXT: VirtualAddress: 0x0
170# CHECK-NEXT: PhysicalAddress: 0x0
171# CHECK-NEXT: FileSize: 0
172# CHECK-NEXT: MemSize: 0
173# CHECK-NEXT: Flags [
174# CHECK-NEXT: PF_R
175# CHECK-NEXT: PF_W
176# CHECK-NEXT: ]
177# CHECK-NEXT: Alignment: 0
178# CHECK-NEXT: }
179# CHECK-NEXT: ]
deps/lld/test/ELF/basic64be.s deleted-217
...@@ -1,217 +0,0 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
3# RUN: ld.lld -discard-all %t -o %t2
4# RUN: llvm-readobj -file-headers -sections -section-data -program-headers %t2 | FileCheck %s
5
6# exits with return code 42 on linux
7.text
8 li 0,1
9 li 3,42
10 sc
11# CHECK: ElfHeader {
12# CHECK-NEXT: Ident {
13# CHECK-NEXT: Magic: (7F 45 4C 46)
14# CHECK-NEXT: Class: 64-bit (0x2)
15# CHECK-NEXT: DataEncoding: BigEndian (0x2)
16# CHECK-NEXT: FileVersion: 1
17# CHECK-NEXT: OS/ABI: SystemV (0x0)
18# CHECK-NEXT: ABIVersion: 0
19# CHECK-NEXT: Unused: (00 00 00 00 00 00 00)
20# CHECK-NEXT: }
21# CHECK-NEXT: Type: Executable (0x2)
22# CHECK-NEXT: Machine: EM_PPC64 (0x15)
23# CHECK-NEXT: Version: 1
24# CHECK-NEXT: Entry: 0x10010000
25# CHECK-NEXT: ProgramHeaderOffset: 0x40
26# CHECK-NEXT: SectionHeaderOffset: 0x20058
27# CHECK-NEXT: Flags [ (0x2)
28# CHECK-NEXT: 0x2
29# CHECK-NEXT: ]
30# CHECK-NEXT: HeaderSize: 64
31# CHECK-NEXT: ProgramHeaderEntrySize: 56
32# CHECK-NEXT: ProgramHeaderCount: 4
33# CHECK-NEXT: SectionHeaderEntrySize: 64
34# CHECK-NEXT: SectionHeaderCount: 7
35# CHECK-NEXT: StringTableSectionIndex: 5
36# CHECK-NEXT: }
37# CHECK-NEXT: Sections [
38# CHECK-NEXT: Section {
39# CHECK-NEXT: Index: 0
40# CHECK-NEXT: Name: (0)
41# CHECK-NEXT: Type: SHT_NULL (0x0)
42# CHECK-NEXT: Flags [ (0x0)
43# CHECK-NEXT: ]
44# CHECK-NEXT: Address: 0x0
45# CHECK-NEXT: Offset: 0x0
46# CHECK-NEXT: Size: 0
47# CHECK-NEXT: Link: 0
48# CHECK-NEXT: Info: 0
49# CHECK-NEXT: AddressAlignment: 0
50# CHECK-NEXT: EntrySize: 0
51# CHECK-NEXT: SectionData (
52# CHECK-NEXT: )
53# CHECK-NEXT: }
54# CHECK-NEXT: Section {
55# CHECK-NEXT: Index: 1
56# CHECK-NEXT: Name: .text (1)
57# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
58# CHECK-NEXT: Flags [ (0x6)
59# CHECK-NEXT: SHF_ALLOC (0x2)
60# CHECK-NEXT: SHF_EXECINSTR (0x4)
61# CHECK-NEXT: ]
62# CHECK-NEXT: Address: 0x10010000
63# CHECK-NEXT: Offset: 0x10000
64# CHECK-NEXT: Size: 12
65# CHECK-NEXT: Link: 0
66# CHECK-NEXT: Info: 0
67# CHECK-NEXT: AddressAlignment: 4
68# CHECK-NEXT: EntrySize: 0
69# CHECK-NEXT: SectionData (
70# CHECK-NEXT: 0000: 38000001 3860002A 44000002 |8...8`.*D...|
71# CHECK-NEXT: )
72# CHECK-NEXT: }
73# CHECK-NEXT: Section {
74# CHECK-NEXT: Index: 2
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)
94# CHECK-NEXT: Type: SHT_PROGBITS (0x1)
95# CHECK-NEXT: Flags [ (0x30)
96# CHECK-NEXT: SHF_MERGE (0x10)
97# CHECK-NEXT: SHF_STRINGS (0x20)
98# CHECK-NEXT: ]
99# CHECK-NEXT: Address: 0x0
100# CHECK-NEXT: Offset: 0x20000
101# CHECK-NEXT: Size: 8
102# CHECK-NEXT: Link: 0
103# CHECK-NEXT: Info: 0
104# CHECK-NEXT: AddressAlignment: 1
105# CHECK-NEXT: EntrySize: 1
106# CHECK-NEXT: SectionData (
107# CHECK-NEXT: 0000: 4C4C4420 312E3000 |LLD 1.0.|
108# CHECK-NEXT: )
109# CHECK-NEXT: }
110# CHECK-NEXT: Section {
111# CHECK-NEXT: Index: 4
112# CHECK-NEXT: Name: .symtab (27)
113# CHECK-NEXT: Type: SHT_SYMTAB (0x2)
114# CHECK-NEXT: Flags [ (0x0)
115# CHECK-NEXT: ]
116# CHECK-NEXT: Address: 0x0
117# CHECK-NEXT: Offset: 0x20008
118# CHECK-NEXT: Size: 24
119# CHECK-NEXT: Link: 6
120# CHECK-NEXT: Info: 1
121# CHECK-NEXT: AddressAlignment: 8
122# CHECK-NEXT: EntrySize: 24
123# CHECK-NEXT: SectionData (
124# CHECK-NEXT: 0000: 00000000 00000000 00000000 00000000 |................|
125# CHECK-NEXT: 0010: 00000000 00000000 |........|
126# CHECK-NEXT: )
127# CHECK-NEXT: }
128# CHECK-NEXT: Section {
129# CHECK-NEXT: Index: 5
130# CHECK-NEXT: Name: .shstrtab (35)
131# CHECK-NEXT: Type: SHT_STRTAB (0x3)
132# CHECK-NEXT: Flags [ (0x0)
133# CHECK-NEXT: ]
134# CHECK-NEXT: Address: 0x0
135# CHECK-NEXT: Offset: 0x20020
136# CHECK-NEXT: Size: 53
137# CHECK-NEXT: Link: 0
138# CHECK-NEXT: Info: 0
139# CHECK-NEXT: AddressAlignment: 1
140# CHECK-NEXT: EntrySize: 0
141# CHECK-NEXT: SectionData (
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.|
146# CHECK-NEXT: )
147# CHECK-NEXT: }
148# CHECK-NEXT: Section {
149# CHECK-NEXT: Index: 6
150# CHECK-NEXT: Name: .strtab (45)
151# CHECK-NEXT: Type: SHT_STRTAB (0x3)
152# CHECK-NEXT: Flags [ (0x0)
153# CHECK-NEXT: ]
154# CHECK-NEXT: Address: 0x0
155# CHECK-NEXT: Offset: 0x20055
156# CHECK-NEXT: Size: 1
157# CHECK-NEXT: Link: 0
158# CHECK-NEXT: Info: 0
159# CHECK-NEXT: AddressAlignment: 1
160# CHECK-NEXT: EntrySize: 0
161# CHECK-NEXT: SectionData (
162# CHECK-NEXT: 0000: 00 |.|
163# CHECK-NEXT: )
164# CHECK-NEXT: }
165# CHECK-NEXT: ]
166# CHECK-NEXT: ProgramHeaders [
167# CHECK-NEXT: ProgramHeader {
168# CHECK-NEXT: Type: PT_PHDR (0x6)
169# CHECK-NEXT: Offset: 0x40
170# CHECK-NEXT: VirtualAddress: 0x10000040
171# CHECK-NEXT: PhysicalAddress: 0x10000040
172# CHECK-NEXT: FileSize: 280
173# CHECK-NEXT: MemSize: 280
174# CHECK-NEXT: Flags [ (0x4)
175# CHECK-NEXT: PF_R (0x4)
176# CHECK-NEXT: ]
177# CHECK-NEXT: Alignment: 8
178# CHECK-NEXT: }
179# CHECK-NEXT: ProgramHeader {
180# CHECK-NEXT: Type: PT_LOAD (0x1)
181# CHECK-NEXT: Offset: 0x0
182# CHECK-NEXT: VirtualAddress: 0x10000000
183# CHECK-NEXT: PhysicalAddress: 0x10000000
184# CHECK-NEXT: FileSize: 344
185# CHECK-NEXT: MemSize: 344
186# CHECK-NEXT: Flags [ (0x4)
187# CHECK-NEXT: PF_R (0x4)
188# CHECK-NEXT: ]
189# CHECK-NEXT: Alignment: 65536
190# CHECK-NEXT: }
191# CHECK-NEXT: ProgramHeader {
192# CHECK-NEXT: Type: PT_LOAD (0x1)
193# CHECK-NEXT: Offset: 0x10000
194# CHECK-NEXT: VirtualAddress: 0x10010000
195# CHECK-NEXT: PhysicalAddress: 0x10010000
196# CHECK-NEXT: FileSize: 4096
197# CHECK-NEXT: MemSize: 4096
198# CHECK-NEXT: Flags [ (0x5)
199# CHECK-NEXT: PF_R (0x4)
200# CHECK-NEXT: PF_X (0x1)
201# CHECK-NEXT: ]
202# CHECK-NEXT: Alignment: 65536
203# CHECK-NEXT: }
204# CHECK-NEXT: ProgramHeader {
205# CHECK-NEXT: Type: PT_GNU_STACK (0x6474E551)
206# CHECK-NEXT: Offset: 0x0
207# CHECK-NEXT: VirtualAddress: 0x0
208# CHECK-NEXT: PhysicalAddress: 0x0
209# CHECK-NEXT: FileSize: 0
210# CHECK-NEXT: MemSize: 0
211# CHECK-NEXT: Flags [ (0x6)
212# CHECK-NEXT: PF_R (0x4)
213# CHECK-NEXT: PF_W (0x2)
214# CHECK-NEXT: ]
215# CHECK-NEXT: Alignment: 0
216# CHECK-NEXT: }
217# CHECK-NEXT: ]
deps/lld/test/ELF/bss-start-common.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-objdump -t -section-headers %t2 | FileCheck %s4# RUN: llvm-objdump -t -section-headers %t2 | FileCheck %s
55
6# CHECK: Sections:6# CHECK: Sections:
7# CHECK: Idx Name Size Address Type7# CHECK: Idx Name Size VMA Type
8# CHECK: 2 .bss 00000004 0000000000201000 BSS8# CHECK: 2 .bss 00000004 0000000000201000 BSS
9# CHECK: SYMBOL TABLE:9# CHECK: SYMBOL TABLE:
10# CHECK: 0000000000201000 .bss 00000000 __bss_start10# CHECK: 0000000000201000 .bss 00000000 __bss_start
deps/lld/test/ELF/bss.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %t23// RUN: ld.lld %t -o %t2
4// RUN: llvm-readobj -sections %t2 | FileCheck %s4// RUN: llvm-readobj --sections %t2 | FileCheck %s
55
6// Test that bss takes no space on disk.6// Test that bss takes no space on disk.
77
deps/lld/test/ELF/bsymbolic-undef.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: ld.lld -shared -Bsymbolic %t.o -o %t.so3# RUN: ld.lld -shared -Bsymbolic %t.o -o %t.so
4# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s4# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
55
6# CHECK: DynamicSymbols [6# CHECK: DynamicSymbols [
7# CHECK-NEXT: Symbol {7# CHECK-NEXT: Symbol {
deps/lld/test/ELF/bsymbolic.s+3-3
...@@ -3,9 +3,9 @@...@@ -3,9 +3,9 @@
3// RUN: ld.lld -shared %t.o -o %t0.so3// RUN: ld.lld -shared %t.o -o %t0.so
4// RUN: ld.lld -shared -Bsymbolic %t.o -o %t1.so4// RUN: ld.lld -shared -Bsymbolic %t.o -o %t1.so
5// RUN: ld.lld -shared -Bsymbolic-functions %t.o -o %t2.so5// RUN: ld.lld -shared -Bsymbolic-functions %t.o -o %t2.so
6// RUN: llvm-readobj -s %t0.so | FileCheck -check-prefix=NOOPTION %s6// RUN: llvm-readobj -S %t0.so | FileCheck -check-prefix=NOOPTION %s
7// RUN: llvm-readobj -s %t1.so | FileCheck -check-prefix=SYMBOLIC %s7// RUN: llvm-readobj -S %t1.so | FileCheck -check-prefix=SYMBOLIC %s
8// RUN: llvm-readobj -s %t2.so | FileCheck -check-prefix=SYMBOLIC %s8// RUN: llvm-readobj -S %t2.so | FileCheck -check-prefix=SYMBOLIC %s
99
10// NOOPTION: Section {10// NOOPTION: Section {
11// NOOPTION: Name: .plt11// NOOPTION: Name: .plt
deps/lld/test/ELF/build-id.s+4-4
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
44
5# RUN: ld.lld --build-id %t -o %t25# RUN: ld.lld --build-id %t -o %t2
6# RUN: llvm-readobj -s %t2 | FileCheck -check-prefix=ALIGN %s6# RUN: llvm-readobj -S %t2 | FileCheck -check-prefix=ALIGN %s
77
8# RUN: ld.lld --build-id %t -o %t2 -threads8# RUN: ld.lld --build-id %t -o %t2 -threads
9# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=DEFAULT %s9# RUN: llvm-objdump -s %t2 | FileCheck -check-prefix=DEFAULT %s
...@@ -65,15 +65,15 @@ _start:...@@ -65,15 +65,15 @@ _start:
65# DEFAULT: Contents of section .note.test:65# DEFAULT: Contents of section .note.test:
66# DEFAULT: Contents of section .note.gnu.build-id:66# DEFAULT: Contents of section .note.gnu.build-id:
67# DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU.67# DEFAULT-NEXT: 04000000 08000000 03000000 474e5500 ............GNU.
68# DEFAULT-NEXT: 894c04e8 fbf5556b68# DEFAULT-NEXT: 95849665 2621c734
6969
70# MD5: Contents of section .note.gnu.build-id:70# MD5: Contents of section .note.gnu.build-id:
71# MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU.71# MD5-NEXT: 04000000 10000000 03000000 474e5500 ............GNU.
72# MD5-NEXT: 6a51bbd7 9e8ee3f9 2e02d213 711cfec972# MD5-NEXT: 1882c01f 71698eed 229b3994 eb554c80
7373
74# SHA1: Contents of section .note.gnu.build-id:74# SHA1: Contents of section .note.gnu.build-id:
75# SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU.75# SHA1-NEXT: 04000000 14000000 03000000 474e5500 ............GNU.
76# SHA1-NEXT: 9a8618b1 d6fd0e5c eda73dd8 76de559676# SHA1-NEXT: 96820adf d90d5470 0a0c32ff a88c4017
7777
78# UUID: Contents of section .note.gnu.build-id:78# UUID: Contents of section .note.gnu.build-id:
79# UUID-NEXT: 04000000 10000000 03000000 474e5500 ............GNU.79# UUID-NEXT: 04000000 10000000 03000000 474e5500 ............GNU.
deps/lld/test/ELF/cgprofile-bad-clusters.s+1-1
...@@ -11,7 +11,7 @@...@@ -11,7 +11,7 @@
11# RUN: echo "G H 5" >> %t.call_graph11# RUN: echo "G H 5" >> %t.call_graph
12# RUN: echo "H I 4" >> %t.call_graph12# RUN: echo "H I 4" >> %t.call_graph
13# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t213# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t2
14# RUN: llvm-readobj -symbols %t2 | FileCheck %s14# RUN: llvm-readobj --symbols %t2 | FileCheck %s
1515
16 .section .text.A,"ax",@progbits16 .section .text.A,"ax",@progbits
17 .globl A17 .globl A
deps/lld/test/ELF/cgprofile-icf.s+2-2
...@@ -6,9 +6,9 @@...@@ -6,9 +6,9 @@
6# RUN: echo "A C 40" >> %t.call_graph6# RUN: echo "A C 40" >> %t.call_graph
7# RUN: echo "C D 61" >> %t.call_graph7# RUN: echo "C D 61" >> %t.call_graph
8# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t.out -icf=all8# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t.out -icf=all
9# RUN: llvm-readobj -symbols %t.out | FileCheck %s9# RUN: llvm-readobj --symbols %t.out | FileCheck %s
10# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t2.out10# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t2.out
11# RUN: llvm-readobj -symbols %t2.out | FileCheck %s --check-prefix=NOICF11# RUN: llvm-readobj --symbols %t2.out | FileCheck %s --check-prefix=NOICF
1212
13 .section .text.D,"ax",@progbits13 .section .text.D,"ax",@progbits
14 .globl D14 .globl D
deps/lld/test/ELF/cgprofile-print.s created+37
...@@ -0,0 +1,37 @@
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 --print-symbol-order=%t3
9# RUN: FileCheck %s --input-file %t3
10
11# CHECK: B
12# CHECK-NEXT: C
13# CHECK-NEXT: D
14# CHECK-NEXT: A
15
16.section .text.A,"ax",@progbits
17.globl A
18A:
19 nop
20
21.section .text.B,"ax",@progbits
22.globl B
23B:
24 nop
25
26.section .text.C,"ax",@progbits
27.globl C
28C:
29 nop
30
31.section .text.D,"ax",@progbits
32.globl D
33D:
34 nop
35
36
37
deps/lld/test/ELF/cgprofile-reproduce.s created+42
...@@ -0,0 +1,42 @@
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 --print-symbol-order=%t3
9# RUN: ld.lld -e A %t --symbol-ordering-file %t3 -o %t2
10# RUN: llvm-readobj --symbols %t2 | FileCheck %s
11
12# CHECK: Name: A
13# CHECK-NEXT: Value: 0x201003
14# CHECK: Name: B
15# CHECK-NEXT: Value: 0x201000
16# CHECK: Name: C
17# CHECK-NEXT: Value: 0x201001
18# CHECK: Name: D
19# CHECK-NEXT: Value: 0x201002
20
21.section .text.A,"ax",@progbits
22.globl A
23A:
24 nop
25
26.section .text.B,"ax",@progbits
27.globl B
28B:
29 nop
30
31.section .text.C,"ax",@progbits
32.globl C
33C:
34 nop
35
36.section .text.D,"ax",@progbits
37.globl D
38D:
39 nop
40
41
42
deps/lld/test/ELF/cgprofile-txt.s+2-2
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4# RUN: ld.lld -e A %t -o %t24# RUN: ld.lld -e A %t -o %t2
5# RUN: llvm-readobj -symbols %t2 | FileCheck %s --check-prefix=NOSORT5# RUN: llvm-readobj --symbols %t2 | FileCheck %s --check-prefix=NOSORT
66
7# RUN: echo "A B 10" > %t.call_graph7# RUN: echo "A B 10" > %t.call_graph
8# RUN: echo "A B 10" >> %t.call_graph8# RUN: echo "A B 10" >> %t.call_graph
...@@ -25,7 +25,7 @@...@@ -25,7 +25,7 @@
25# RUN: echo "TooManyPreds9 TooManyPreds 10" >> %t.call_graph25# RUN: echo "TooManyPreds9 TooManyPreds 10" >> %t.call_graph
26# RUN: echo "TooManyPreds10 TooManyPreds 11" >> %t.call_graph26# RUN: echo "TooManyPreds10 TooManyPreds 11" >> %t.call_graph
27# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t227# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t2
28# RUN: llvm-readobj -symbols %t2 | FileCheck %s28# RUN: llvm-readobj --symbols %t2 | FileCheck %s
2929
30 .section .text.D,"ax",@progbits30 .section .text.D,"ax",@progbits
31D:31D:
deps/lld/test/ELF/cgprofile-txt2.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: echo "C D 40" >> %t.call_graph6# RUN: echo "C D 40" >> %t.call_graph
7# RUN: echo "D B 10" >> %t.call_graph7# RUN: echo "D B 10" >> %t.call_graph
8# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t28# RUN: ld.lld -e A %t --call-graph-ordering-file %t.call_graph -o %t2
9# RUN: llvm-readobj -symbols %t2 | FileCheck %s9# RUN: llvm-readobj --symbols %t2 | FileCheck %s
1010
11# CHECK: Name: A11# CHECK: Name: A
12# CHECK-NEXT: Value: 0x20100312# CHECK-NEXT: Value: 0x201003
deps/lld/test/ELF/color-diagnostics.test+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: not ld.lld -xyz -color-diagnostics=always /nosuchfile 2>&1 \6# RUN: not ld.lld -xyz -color-diagnostics=always /nosuchfile 2>&1 \
7# RUN: | FileCheck -check-prefix=COLOR %s7# RUN: | FileCheck -check-prefix=COLOR %s
88
9# COLOR: {{ld.lld: .\[0;1;31merror: .\[0munknown argument: -xyz}}9# COLOR: {{ld.lld: .\[0;1;31merror: .\[0munknown argument '-xyz'}}
10# COLOR: {{ld.lld: .\[0;1;31merror: .\[0mcannot open /nosuchfile}}10# COLOR: {{ld.lld: .\[0;1;31merror: .\[0mcannot open /nosuchfile}}
1111
12# RUN: not ld.lld -color-diagnostics=foobar 2>&1 | FileCheck -check-prefix=ERR %s12# RUN: not ld.lld -color-diagnostics=foobar 2>&1 | FileCheck -check-prefix=ERR %s
deps/lld/test/ELF/combreloc.s created+48
...@@ -0,0 +1,48 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
4# RUN: echo 'mov aaa@gotpcrel(%rip), %rax' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o
5
6# RUN: ld.lld -shared %t.o %t1.o -o %t.so
7# RUN: llvm-readobj -r --dynamic-table %t.so | FileCheck %s
8# RUN: ld.lld -shared %t.o %t1.o -o %t.so -z combreloc
9# RUN: llvm-readobj -r --dynamic-table %t.so | FileCheck %s
10
11# -z combreloc is the default: sort relocations by (!IsRelative,SymIndex,r_offset),
12# and emit DT_RELACOUNT (except on MIPS) to indicate the number of relative
13# relocations.
14
15# CHECK: Relocations [
16# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
17# CHECK-NEXT: 0x3020 R_X86_64_RELATIVE - 0x3028
18# CHECK-NEXT: 0x20B0 R_X86_64_GLOB_DAT aaa 0x0
19# CHECK-NEXT: 0x3000 R_X86_64_64 aaa 0x0
20# CHECK-NEXT: 0x3018 R_X86_64_64 aaa 0x0
21# CHECK-NEXT: 0x3010 R_X86_64_64 bbb 0x0
22# CHECK-NEXT: 0x3008 R_X86_64_64 ccc 0x0
23# CHECK-NEXT: }
24# CHECK: DynamicSection [
25# CHECK: RELACOUNT 1
26
27# RUN: ld.lld -z nocombreloc -shared %t.o %t1.o -o %t.so
28# RUN: llvm-readobj -r --dynamic-table %t.so | FileCheck --check-prefix=NOCOMB %s
29
30# NOCOMB: Relocations [
31# NOCOMB-NEXT: Section ({{.*}}) .rela.dyn {
32# NOCOMB-NEXT: 0x3000 R_X86_64_64 aaa 0x0
33# NOCOMB-NEXT: 0x3008 R_X86_64_64 ccc 0x0
34# NOCOMB-NEXT: 0x3010 R_X86_64_64 bbb 0x0
35# NOCOMB-NEXT: 0x3018 R_X86_64_64 aaa 0x0
36# NOCOMB-NEXT: 0x3020 R_X86_64_RELATIVE - 0x3028
37# NOCOMB-NEXT: 0x20A0 R_X86_64_GLOB_DAT aaa 0x0
38# NOCOMB-NEXT: }
39# NOCOMB: DynamicSection [
40# NOCOMB-NOT: RELACOUNT
41
42.data
43 .quad aaa
44 .quad ccc
45 .quad bbb
46 .quad aaa
47 .quad relative
48relative:
deps/lld/test/ELF/combrelocs.s deleted-95
...@@ -1,95 +0,0 @@
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 %t.out
5# RUN: llvm-readobj -r --expand-relocs --dynamic-table %t.out | FileCheck %s
6
7# RUN: ld.lld -shared %t.o -o %t.out -z combreloc
8# RUN: llvm-readobj -r --expand-relocs --dynamic-table %t.out | FileCheck %s
9
10# CHECK: Relocations [
11# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
12# CHECK-NEXT: Relocation {
13# CHECK-NEXT: Offset: 0x1000
14# CHECK-NEXT: Type: R_X86_64_64
15# CHECK-NEXT: Symbol: aaa (1)
16# CHECK-NEXT: Addend: 0x0
17# CHECK-NEXT: }
18# CHECK-NEXT: Relocation {
19# CHECK-NEXT: Offset: 0x1018
20# CHECK-NEXT: Type: R_X86_64_64
21# CHECK-NEXT: Symbol: aaa (1)
22# CHECK-NEXT: Addend: 0x0
23# CHECK-NEXT: }
24# CHECK-NEXT: Relocation {
25# CHECK-NEXT: Offset: 0x1010
26# CHECK-NEXT: Type: R_X86_64_64
27# CHECK-NEXT: Symbol: bbb (2)
28# CHECK-NEXT: Addend: 0x0
29# CHECK-NEXT: }
30# CHECK-NEXT: Relocation {
31# CHECK-NEXT: Offset: 0x1008
32# CHECK-NEXT: Type: R_X86_64_64
33# CHECK-NEXT: Symbol: ccc (3)
34# CHECK-NEXT: Addend: 0x0
35# CHECK-NEXT: }
36# CHECK-NEXT: Relocation {
37# CHECK-NEXT: Offset: 0x1020
38# CHECK-NEXT: Type: R_X86_64_64
39# CHECK-NEXT: Symbol: ddd (4)
40# CHECK-NEXT: Addend: 0x0
41# CHECK-NEXT: }
42# CHECK-NEXT: }
43# CHECK-NEXT: ]
44# CHECK: DynamicSection [
45# CHECK-NEXT: Tag
46# CHECK-NOT: RELACOUNT
47
48# RUN: ld.lld -z nocombreloc -shared %t.o -o %t.out
49# RUN: llvm-readobj -r --expand-relocs --dynamic-table %t.out | \
50# RUN: FileCheck --check-prefix=NOCOMB %s
51
52# NOCOMB: Relocations [
53# NOCOMB-NEXT: Section ({{.*}}) .rela.dyn {
54# NOCOMB-NEXT: Relocation {
55# NOCOMB-NEXT: Offset: 0x1000
56# NOCOMB-NEXT: Type: R_X86_64_64
57# NOCOMB-NEXT: Symbol: aaa (1)
58# NOCOMB-NEXT: Addend: 0x0
59# NOCOMB-NEXT: }
60# NOCOMB-NEXT: Relocation {
61# NOCOMB-NEXT: Offset: 0x1008
62# NOCOMB-NEXT: Type: R_X86_64_64
63# NOCOMB-NEXT: Symbol: ccc (3)
64# NOCOMB-NEXT: Addend: 0x0
65# NOCOMB-NEXT: }
66# NOCOMB-NEXT: Relocation {
67# NOCOMB-NEXT: Offset: 0x1010
68# NOCOMB-NEXT: Type: R_X86_64_64
69# NOCOMB-NEXT: Symbol: bbb (2)
70# NOCOMB-NEXT: Addend: 0x0
71# NOCOMB-NEXT: }
72# NOCOMB-NEXT: Relocation {
73# NOCOMB-NEXT: Offset: 0x1018
74# NOCOMB-NEXT: Type: R_X86_64_64
75# NOCOMB-NEXT: Symbol: aaa (1)
76# NOCOMB-NEXT: Addend: 0x0
77# NOCOMB-NEXT: }
78# NOCOMB-NEXT: Relocation {
79# NOCOMB-NEXT: Offset: 0x1020
80# NOCOMB-NEXT: Type: R_X86_64_64
81# NOCOMB-NEXT: Symbol: ddd (4)
82# NOCOMB-NEXT: Addend: 0x0
83# NOCOMB-NEXT: }
84# NOCOMB-NEXT: }
85# NOCOMB-NEXT: ]
86# NOCOMB: DynamicSection [
87# NOCOMB-NEXT: Tag
88# NOCOMB-NOT: RELACOUNT
89
90.data
91 .quad aaa
92 .quad ccc
93 .quad bbb
94 .quad aaa
95 .quad ddd
deps/lld/test/ELF/comdat-discarded-error.s created+28
...@@ -0,0 +1,28 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t1.o
3# RUN: echo '.section .text.foo,"axG",@progbits,foo,comdat; .globl foo; foo:' |\
4# RUN: llvm-mc -filetype=obj -triple=x86_64 - -o %t2.o
5# RUN: echo '.section .text.foo,"axG",@progbits,foo,comdat; .globl bar; bar:' |\
6# RUN: llvm-mc -filetype=obj -triple=x86_64 - -o %t3.o
7
8# RUN: not ld.lld %t2.o %t3.o %t1.o -o /dev/null 2>&1 | FileCheck %s
9
10# CHECK: error: relocation refers to a symbol in a discarded section: bar
11# CHECK-NEXT: >>> defined in {{.*}}3.o
12# CHECK-NEXT: >>> section group signature: foo
13# CHECK-NEXT: >>> prevailing definition is in {{.*}}2.o
14# CHECK-NEXT: >>> referenced by {{.*}}1.o:(.text+0x1)
15
16# CHECK: error: relocation refers to a discarded section: .text.foo
17# CHECK-NEXT: >>> defined in {{.*}}1.o
18# CHECK-NEXT: >>> section group signature: foo
19# CHECK-NEXT: >>> prevailing definition is in {{.*}}2.o
20# CHECK-NEXT: >>> referenced by {{.*}}1.o:(.data+0x0)
21
22.globl _start
23_start:
24 jmp bar
25
26.section .text.foo,"axG",@progbits,foo,comdat
27.data
28 .quad .text.foo
deps/lld/test/ELF/comdat-discarded-gdb-index.s created+63
...@@ -0,0 +1,63 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: ld.lld --gdb-index %t.o %t.o -o %t
4
5## .debug_info has a relocation to .text.foo . The second %t.o is discarded.
6## Check we don't error on the relocation.
7# CHECK: .rela.debug_info {
8# CHECK-NEXT: 0xC R_X86_64_64 .text.foo 0x0
9
10.section .text.foo,"axG",@progbits,foo,comdat
11.globl foo
12.Lfunc_begin0:
13foo:
14 ret
15.Lfunc_end0:
16
17.section .debug_abbrev,"",@progbits
18 .byte 1 # Abbreviation Code
19 .byte 17 # DW_TAG_compile_unit
20 .byte 1 # DW_CHILDREN_yes
21 .byte 17 # DW_AT_low_pc
22 .byte 1 # DW_FORM_addr
23 .byte 18 # DW_AT_high_pc
24 .byte 6 # DW_FORM_data4
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 .quad .Lfunc_begin0 # DW_AT_low_pc
47 .long .Lfunc_end0 - .Lfunc_begin0 # DW_AT_high_pc
48 .byte 2 # Abbrev [2] DW_TAG_subprogram
49 .asciz "foo" # DW_AT_name
50 .byte 0
51.Lcu_end0:
52
53.section .debug_gnu_pubnames,"",@progbits
54 .long .LpubNames_end0 - .LpubNames_begin0
55.LpubNames_begin0:
56 .short 2 # Version
57 .long .Lcu_begin0 # CU Offset
58 .long .Lcu_end0 - .Lcu_begin0
59 .long .Ldie0 - .Lcu_begin0
60 .byte 48 # Attributes: FUNCTION, EXTERNAL
61 .asciz "foo" # External Name
62 .long 0
63.LpubNames_end0:
deps/lld/test/ELF/comdat-discarded-ppc64.s created+17
...@@ -0,0 +1,17 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
3# RUN: ld.lld %t.o %t.o -o /dev/null
4# RUN: ld.lld -r --fatal-warnings %t.o %t.o -o /dev/null
5
6## clang/gcc PPC64 may emit a .rela.toc which references a switch table in a
7## discarded .rodata/.text section. The .toc and the .rela.toc are incorrectly
8## not placed in the comdat.
9## Don't error "relocation refers to a discarded section".
10
11.section .text.foo,"axG",@progbits,foo,comdat
12.globl foo
13foo:
14.L0:
15
16.section .toc,"aw"
17.quad .L0
deps/lld/test/ELF/comdat-discarded-reloc.s+32-7
...@@ -1,17 +1,42 @@...@@ -1,17 +1,42 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# 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/comdat-discarded-reloc.s -o %t2.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/comdat-discarded-reloc.s -o %t2.o
4# RUN: ld.lld -gc-sections %t.o %t2.o -o %t4# RUN: ld.lld -gc-sections --noinhibit-exec %t2.o %t.o -o /dev/null
5# RUN: ld.lld -r %t2.o %t.o -o %t 2>&1 | FileCheck --check-prefix=WARN %s
6# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
57
6## ELF spec doesn't allow a relocation to point to a deduplicated8## ELF spec doesn't allow a relocation to point to a deduplicated
7## COMDAT section. Unfortunately this happens in practice (e.g. .eh_frame)9## COMDAT section. Unfortunately this happens in practice (e.g. .eh_frame)
8## Test case checks we do not crash.10## Test case checks we do not crash.
911
10.global bar, _start12# WARN: warning: relocation refers to a discarded section: .text.bar1
13# WARN-NEXT: >>> referenced by {{.*}}.o:(.rela.text.bar2+0x0)
14# WARN-NOT: warning
1115
12.section .text.foo,"aG",@progbits,group,comdat16# RELOC: .rela.eh_frame {
17# RELOC-NEXT: R_X86_64_NONE
18# RELOC-NEXT: }
19# RELOC-NEXT: .rela.debug_foo {
20# RELOC-NEXT: R_X86_64_NONE
21# RELOC-NEXT: }
22# RELOC-NEXT: .rela.gcc_except_table {
23# RELOC-NEXT: R_X86_64_NONE
24# RELOC-NEXT: }
1325
14.section .text26.section .text.bar1,"aG",@progbits,group,comdat
15_start:27
16 .quad .text.foo28## .text.bar1 in this file is discarded. Warn on the relocation.
17 .quad bar29.section .text.bar2,"ax"
30.globl bar
31bar:
32 .quad .text.bar1
33
34## Don't warn on .eh_frame, .debug*, .zdebug*, or .gcc_except_table
35.section .eh_frame,"a"
36 .quad .text.bar1
37
38.section .debug_foo
39 .quad .text.bar1
40
41.section .gcc_except_table,"a"
42 .quad .text.bar1
deps/lld/test/ELF/comdat.s+4-4
...@@ -1,9 +1,9 @@...@@ -1,9 +1,9 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// 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/comdat.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o
4// RUN: ld.lld -shared %t.o %t.o %t2.o -o %t4// RUN: ld.lld -shared %t.o %t2.o -o %t
5// RUN: llvm-objdump -d %t | FileCheck %s5// RUN: llvm-objdump -d %t | FileCheck %s
6// RUN: llvm-readobj -s -t %t | FileCheck --check-prefix=READ %s6// RUN: llvm-readobj -S --symbols %t | FileCheck --check-prefix=READ %s
77
8// Check that we don't crash with --gc-section and that we print a list of8// Check that we don't crash with --gc-section and that we print a list of
9// reclaimed sections on stderr.9// reclaimed sections on stderr.
...@@ -19,6 +19,7 @@ foo:...@@ -19,6 +19,7 @@ foo:
19 nop19 nop
2020
21// CHECK: Disassembly of section .text2:21// CHECK: Disassembly of section .text2:
22// CHECK-EMPTY:
22// CHECK-NEXT: foo:23// CHECK-NEXT: foo:
23// CHECK-NEXT: 1000: {{.*}} nop24// CHECK-NEXT: 1000: {{.*}} nop
24// CHECK-NOT: nop25// CHECK-NOT: nop
...@@ -27,11 +28,10 @@ foo:...@@ -27,11 +28,10 @@ foo:
27 call foo28 call foo
2829
29// CHECK: Disassembly of section bar:30// CHECK: Disassembly of section bar:
31// CHECK-EMPTY:
30// CHECK-NEXT: bar:32// CHECK-NEXT: bar:
31// 0x1000 - 0x1001 - 5 = -633// 0x1000 - 0x1001 - 5 = -6
32// 0 - 0x1006 - 5 = -4107
33// CHECK-NEXT: 1001: {{.*}} callq -634// CHECK-NEXT: 1001: {{.*}} callq -6
34// CHECK-NEXT: 1006: {{.*}} callq -4107
3535
36 .section .text3,"axG",@progbits,zed,comdat,unique,036 .section .text3,"axG",@progbits,zed,comdat,unique,0
3737
deps/lld/test/ELF/common-gc.s+2-2
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
33
4# RUN: ld.lld %t -o %t24# RUN: ld.lld %t -o %t2
5# RUN: llvm-readobj -sections -symbols %t2 | FileCheck %s --check-prefix=NOGC5# RUN: llvm-readobj --sections --symbols %t2 | FileCheck %s --check-prefix=NOGC
66
7# NOGC: Name: .bss7# NOGC: Name: .bss
8# NOGC-NEXT: Type:8# NOGC-NEXT: Type:
...@@ -18,7 +18,7 @@...@@ -18,7 +18,7 @@
18# NOGC: Name: foo18# NOGC: Name: foo
1919
20# RUN: ld.lld -gc-sections %t -o %t120# RUN: ld.lld -gc-sections %t -o %t1
21# RUN: llvm-readobj -sections -symbols %t1 | FileCheck %s --check-prefix=GC21# RUN: llvm-readobj --sections --symbols %t1 | FileCheck %s --check-prefix=GC
2222
23# GC: Name: .bss23# GC: Name: .bss
24# GC-NEXT: Type:24# GC-NEXT: Type:
deps/lld/test/ELF/common-page.s created+223
...@@ -0,0 +1,223 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4
5# exits with return code 42 on linux
6.globl _start
7_start:
8 nop
9
10# Increase max-page-size to 64k while using the default x86_64 common page size
11# of 4k. If the last loadable segment is executable then lld aligns the next
12# section using the common page size.
13
14# RUN: ld.lld -z max-page-size=0x10000 -z common-page-size=0x1000 %t -o %t2
15# RUN: llvm-readobj --sections -l %t2 | FileCheck --check-prefix=CHECK-MAX %s
16
17# CHECK-MAX: Sections [
18# CHECK-MAX-NEXT: Section {
19# CHECK-MAX-NEXT: Index: 0
20# CHECK-MAX-NEXT: Name: (0)
21# CHECK-MAX-NEXT: Type: SHT_NULL (0x0)
22# CHECK-MAX-NEXT: Flags [ (0x0)
23# CHECK-MAX-NEXT: ]
24# CHECK-MAX-NEXT: Address: 0x0
25# CHECK-MAX-NEXT: Offset: 0x0
26# CHECK-MAX-NEXT: Size: 0
27# CHECK-MAX-NEXT: Link: 0
28# CHECK-MAX-NEXT: Info: 0
29# CHECK-MAX-NEXT: AddressAlignment: 0
30# CHECK-MAX-NEXT: EntrySize: 0
31# CHECK-MAX-NEXT: }
32# CHECK-MAX-NEXT: Section {
33# CHECK-MAX-NEXT: Index: 1
34# CHECK-MAX-NEXT: Name: .text (1)
35# CHECK-MAX-NEXT: Type: SHT_PROGBITS (0x1)
36# CHECK-MAX-NEXT: Flags [ (0x6)
37# CHECK-MAX-NEXT: SHF_ALLOC (0x2)
38# CHECK-MAX-NEXT: SHF_EXECINSTR (0x4)
39# CHECK-MAX-NEXT: ]
40# CHECK-MAX-NEXT: Address: 0x210000
41# CHECK-MAX-NEXT: Offset: 0x10000
42# CHECK-MAX-NEXT: Size: 1
43# CHECK-MAX-NEXT: Link: 0
44# CHECK-MAX-NEXT: Info: 0
45# CHECK-MAX-NEXT: AddressAlignment: 4
46# CHECK-MAX-NEXT: EntrySize: 0
47# CHECK-MAX-NEXT: }
48# CHECK-MAX-NEXT: Section {
49# CHECK-MAX-NEXT: Index: 2
50# CHECK-MAX-NEXT: Name: .comment (7)
51# CHECK-MAX-NEXT: Type: SHT_PROGBITS (0x1)
52# CHECK-MAX-NEXT: Flags [ (0x30)
53# CHECK-MAX-NEXT: SHF_MERGE (0x10)
54# CHECK-MAX-NEXT: SHF_STRINGS (0x20)
55# CHECK-MAX-NEXT: ]
56# CHECK-MAX-NEXT: Address: 0x0
57# CHECK-MAX-NEXT: Offset: 0x11000
58# CHECK-MAX-NEXT: Size: 8
59# CHECK-MAX-NEXT: Link: 0
60# CHECK-MAX-NEXT: Info: 0
61# CHECK-MAX-NEXT: AddressAlignment: 1
62# CHECK-MAX-NEXT: EntrySize: 1
63
64# CHECK-MAX: ProgramHeaders [
65# CHECK-MAX-NEXT: ProgramHeader {
66# CHECK-MAX-NEXT: Type: PT_PHDR (0x6)
67# CHECK-MAX-NEXT: Offset: 0x40
68# CHECK-MAX-NEXT: VirtualAddress: 0x200040
69# CHECK-MAX-NEXT: PhysicalAddress: 0x200040
70# CHECK-MAX-NEXT: FileSize: 224
71# CHECK-MAX-NEXT: MemSize: 224
72# CHECK-MAX-NEXT: Flags [ (0x4)
73# CHECK-MAX-NEXT: PF_R (0x4)
74# CHECK-MAX-NEXT: ]
75# CHECK-MAX-NEXT: Alignment: 8
76# CHECK-MAX-NEXT: }
77# CHECK-MAX-NEXT: ProgramHeader {
78# CHECK-MAX-NEXT: Type: PT_LOAD (0x1)
79# CHECK-MAX-NEXT: Offset: 0x0
80# CHECK-MAX-NEXT: VirtualAddress: 0x200000
81# CHECK-MAX-NEXT: PhysicalAddress: 0x200000
82# CHECK-MAX-NEXT: FileSize: 288
83# CHECK-MAX-NEXT: MemSize: 288
84# CHECK-MAX-NEXT: Flags [ (0x4)
85# CHECK-MAX-NEXT: PF_R (0x4)
86# CHECK-MAX-NEXT: ]
87# CHECK-MAX-NEXT: Alignment: 65536
88# CHECK-MAX-NEXT: }
89# CHECK-MAX-NEXT: ProgramHeader {
90# CHECK-MAX-NEXT: Type: PT_LOAD (0x1)
91# CHECK-MAX-NEXT: Offset: 0x10000
92# CHECK-MAX-NEXT: VirtualAddress: 0x210000
93# CHECK-MAX-NEXT: PhysicalAddress: 0x210000
94# CHECK-MAX-NEXT: FileSize: 4096
95# CHECK-MAX-NEXT: MemSize: 4096
96# CHECK-MAX-NEXT: Flags [ (0x5)
97# CHECK-MAX-NEXT: PF_R (0x4)
98# CHECK-MAX-NEXT: PF_X (0x1)
99# CHECK-MAX-NEXT: ]
100# CHECK-MAX-NEXT: Alignment: 65536
101# CHECK-MAX-NEXT: }
102# CHECK-MAX-NEXT: ProgramHeader {
103# CHECK-MAX-NEXT: Type: PT_GNU_STACK (0x6474E551)
104# CHECK-MAX-NEXT: Offset: 0x0
105# CHECK-MAX-NEXT: VirtualAddress: 0x0
106# CHECK-MAX-NEXT: PhysicalAddress: 0x0
107# CHECK-MAX-NEXT: FileSize: 0
108# CHECK-MAX-NEXT: MemSize: 0
109# CHECK-MAX-NEXT: Flags [ (0x6)
110# CHECK-MAX-NEXT: PF_R (0x4)
111# CHECK-MAX-NEXT: PF_W (0x2)
112# CHECK-MAX-NEXT: ]
113# CHECK-MAX-NEXT: Alignment: 0
114
115# Increase common-page-size to max-page-size. Expect to see a larger offset
116# of the first Section after the executable loadable segment due to the higher
117# alignment requirement.
118
119# RUN: ld.lld -z max-page-size=0x10000 -z common-page-size=0x10000 %t -o %t3
120# RUN: llvm-readobj --sections -l %t3 | FileCheck --check-prefix=CHECK-COMMON %s
121
122# Check that we truncate common-page-size to max-page-size
123
124# RUN: ld.lld -z max-page-size=0x10000 -z common-page-size=0x100000 %t -o %t4
125# RUN: llvm-readobj --sections -l %t4 | FileCheck --check-prefix=CHECK-COMMON %s
126
127# CHECK-COMMON: Sections [
128# CHECK-COMMON-NEXT: Section {
129# CHECK-COMMON-NEXT: Index: 0
130# CHECK-COMMON-NEXT: Name: (0)
131# CHECK-COMMON-NEXT: Type: SHT_NULL (0x0)
132# CHECK-COMMON-NEXT: Flags [ (0x0)
133# CHECK-COMMON-NEXT: ]
134# CHECK-COMMON-NEXT: Address: 0x0
135# CHECK-COMMON-NEXT: Offset: 0x0
136# CHECK-COMMON-NEXT: Size: 0
137# CHECK-COMMON-NEXT: Link: 0
138# CHECK-COMMON-NEXT: Info: 0
139# CHECK-COMMON-NEXT: AddressAlignment: 0
140# CHECK-COMMON-NEXT: EntrySize: 0
141# CHECK-COMMON-NEXT: }
142# CHECK-COMMON-NEXT: Section {
143# CHECK-COMMON-NEXT: Index: 1
144# CHECK-COMMON-NEXT: Name: .text (1)
145# CHECK-COMMON-NEXT: Type: SHT_PROGBITS (0x1)
146# CHECK-COMMON-NEXT: Flags [ (0x6)
147# CHECK-COMMON-NEXT: SHF_ALLOC (0x2)
148# CHECK-COMMON-NEXT: SHF_EXECINSTR (0x4)
149# CHECK-COMMON-NEXT: ]
150# CHECK-COMMON-NEXT: Address: 0x210000
151# CHECK-COMMON-NEXT: Offset: 0x10000
152# CHECK-COMMON-NEXT: Size: 1
153# CHECK-COMMON-NEXT: Link: 0
154# CHECK-COMMON-NEXT: Info: 0
155# CHECK-COMMON-NEXT: AddressAlignment: 4
156# CHECK-COMMON-NEXT: EntrySize: 0
157# CHECK-COMMON-NEXT: }
158# CHECK-COMMON-NEXT: Section {
159# CHECK-COMMON-NEXT: Index: 2
160# CHECK-COMMON-NEXT: Name: .comment (7)
161# CHECK-COMMON-NEXT: Type: SHT_PROGBITS (0x1)
162# CHECK-COMMON-NEXT: Flags [ (0x30)
163# CHECK-COMMON-NEXT: SHF_MERGE (0x10)
164# CHECK-COMMON-NEXT: SHF_STRINGS (0x20)
165# CHECK-COMMON-NEXT: ]
166# CHECK-COMMON-NEXT: Address: 0x0
167# CHECK-COMMON-NEXT: Offset: 0x20000
168# CHECK-COMMON-NEXT: Size: 8
169# CHECK-COMMON-NEXT: Link: 0
170# CHECK-COMMON-NEXT: Info: 0
171# CHECK-COMMON-NEXT: AddressAlignment: 1
172# CHECK-COMMON-NEXT: EntrySize: 1
173
174# CHECK-COMMON: ProgramHeaders [
175# CHECK-COMMON-NEXT: ProgramHeader {
176# CHECK-COMMON-NEXT: Type: PT_PHDR (0x6)
177# CHECK-COMMON-NEXT: Offset: 0x40
178# CHECK-COMMON-NEXT: VirtualAddress: 0x200040
179# CHECK-COMMON-NEXT: PhysicalAddress: 0x200040
180# CHECK-COMMON-NEXT: FileSize: 224
181# CHECK-COMMON-NEXT: MemSize: 224
182# CHECK-COMMON-NEXT: Flags [ (0x4)
183# CHECK-COMMON-NEXT: PF_R (0x4)
184# CHECK-COMMON-NEXT: ]
185# CHECK-COMMON-NEXT: Alignment: 8
186# CHECK-COMMON-NEXT: }
187# CHECK-COMMON-NEXT: ProgramHeader {
188# CHECK-COMMON-NEXT: Type: PT_LOAD (0x1)
189# CHECK-COMMON-NEXT: Offset: 0x0
190# CHECK-COMMON-NEXT: VirtualAddress: 0x200000
191# CHECK-COMMON-NEXT: PhysicalAddress: 0x200000
192# CHECK-COMMON-NEXT: FileSize: 288
193# CHECK-COMMON-NEXT: MemSize: 288
194# CHECK-COMMON-NEXT: Flags [ (0x4)
195# CHECK-COMMON-NEXT: PF_R (0x4)
196# CHECK-COMMON-NEXT: ]
197# CHECK-COMMON-NEXT: Alignment: 65536
198# CHECK-COMMON-NEXT: }
199# CHECK-COMMON-NEXT: ProgramHeader {
200# CHECK-COMMON-NEXT: Type: PT_LOAD (0x1)
201# CHECK-COMMON-NEXT: Offset: 0x10000
202# CHECK-COMMON-NEXT: VirtualAddress: 0x210000
203# CHECK-COMMON-NEXT: PhysicalAddress: 0x210000
204# CHECK-COMMON-NEXT: FileSize: 65536
205# CHECK-COMMON-NEXT: MemSize: 65536
206# CHECK-COMMON-NEXT: Flags [ (0x5)
207# CHECK-COMMON-NEXT: PF_R (0x4)
208# CHECK-COMMON-NEXT: PF_X (0x1)
209# CHECK-COMMON-NEXT: ]
210# CHECK-COMMON-NEXT: Alignment: 65536
211# CHECK-COMMON-NEXT: }
212# CHECK-COMMON-NEXT: ProgramHeader {
213# CHECK-COMMON-NEXT: Type: PT_GNU_STACK (0x6474E551)
214# CHECK-COMMON-NEXT: Offset: 0x0
215# CHECK-COMMON-NEXT: VirtualAddress: 0x0
216# CHECK-COMMON-NEXT: PhysicalAddress: 0x0
217# CHECK-COMMON-NEXT: FileSize: 0
218# CHECK-COMMON-NEXT: MemSize: 0
219# CHECK-COMMON-NEXT: Flags [ (0x6)
220# CHECK-COMMON-NEXT: PF_R (0x4)
221# CHECK-COMMON-NEXT: PF_W (0x2)
222# CHECK-COMMON-NEXT: ]
223# CHECK-COMMON-NEXT: Alignment: 0
deps/lld/test/ELF/common.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// 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/common.s -o %t23// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/common.s -o %t2
4// RUN: ld.lld %t %t2 -o %t34// RUN: ld.lld %t %t2 -o %t3
5// RUN: llvm-readobj -t -s %t3 | FileCheck %s5// RUN: llvm-readobj --symbols -S %t3 | FileCheck %s
66
7// CHECK: Name: .bss7// CHECK: Name: .bss
8// CHECK-NEXT: Type: SHT_NOBITS8// CHECK-NEXT: Type: SHT_NOBITS
deps/lld/test/ELF/compress-debug-sections.s+2-2
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# ZLIBCONTENT: Contents of section .debug_str:7# ZLIBCONTENT: Contents of section .debug_str:
8# ZLIBCONTENT-NOT: AAAAAAAAA8# ZLIBCONTENT-NOT: AAAAAAAAA
99
10# RUN: llvm-readobj -s %t1 | FileCheck %s --check-prefix=ZLIBFLAGS10# RUN: llvm-readobj -S %t1 | FileCheck %s --check-prefix=ZLIBFLAGS
11# ZLIBFLAGS: Section {11# ZLIBFLAGS: Section {
12# ZLIBFLAGS: Index:12# ZLIBFLAGS: Index:
13# ZLIBFLAGS: Name: .debug_str13# ZLIBFLAGS: Name: .debug_str
...@@ -24,7 +24,7 @@...@@ -24,7 +24,7 @@
24## Test alias.24## Test alias.
25# RUN: ld.lld %t.o -o %t2 --compress-debug-sections zlib25# RUN: ld.lld %t.o -o %t2 --compress-debug-sections zlib
26# RUN: llvm-objdump -s %t2 | FileCheck %s --check-prefix=ZLIBCONTENT26# RUN: llvm-objdump -s %t2 | FileCheck %s --check-prefix=ZLIBCONTENT
27# RUN: llvm-readobj -s %t2 | FileCheck %s --check-prefix=ZLIBFLAGS27# RUN: llvm-readobj -S %t2 | FileCheck %s --check-prefix=ZLIBFLAGS
2828
29# RUN: not ld.lld %t.o -o %t1 --compress-debug-sections=zlib-gabi 2>&1 | \29# RUN: not ld.lld %t.o -o %t1 --compress-debug-sections=zlib-gabi 2>&1 | \
30# RUN: FileCheck -check-prefix=ERR %s30# RUN: FileCheck -check-prefix=ERR %s
deps/lld/test/ELF/compressed-debug-conflict.s+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# REQUIRES: x86, zlib1# REQUIRES: x86, zlib
2# RUN: llvm-mc -filetype=obj -triple i686-linux-gnu -compress-debug-sections=zlib %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple i686-linux-gnu -compress-debug-sections=zlib %s -o %t.o
3# RUN: llvm-readobj -sections %t.o | FileCheck -check-prefix=OBJ %s3# RUN: llvm-readobj --sections %t.o | FileCheck -check-prefix=OBJ %s
4# RUN: not ld.lld %t.o %t.o -o /dev/null 2>&1 | FileCheck -check-prefix=ERROR %s4# RUN: not ld.lld %t.o %t.o -o /dev/null 2>&1 | FileCheck -check-prefix=ERROR %s
55
6# OBJ: Sections [6# OBJ: Sections [
deps/lld/test/ELF/compressed-debug-input.s+5-5
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: zlib, x861# REQUIRES: zlib, x86
22
3# RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=x86_64-unknown-linux %s -o %t3# RUN: llvm-mc -compress-debug-sections=zlib -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4# RUN: llvm-readobj -sections %t | FileCheck -check-prefix=ZLIB %s4# RUN: llvm-readobj --sections %t | FileCheck -check-prefix=ZLIB %s
5# ZLIB: Section {5# ZLIB: Section {
6# ZLIB: Index: 26# ZLIB: Index: 2
7# ZLIB: Name: .debug_str7# ZLIB: Name: .debug_str
...@@ -16,12 +16,12 @@...@@ -16,12 +16,12 @@
16# ZLIB-NEXT: Size:16# ZLIB-NEXT: Size:
17# ZLIB-NEXT: Link:17# ZLIB-NEXT: Link:
18# ZLIB-NEXT: Info:18# ZLIB-NEXT: Info:
19# ZLIB-NEXT: AddressAlignment: 119# ZLIB-NEXT: AddressAlignment: 8
20# ZLIB-NEXT: EntrySize: 120# ZLIB-NEXT: EntrySize: 1
21# ZLIB-NEXT: }21# ZLIB-NEXT: }
2222
23# RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=x86_64-unknown-linux %s -o %t223# RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=x86_64-unknown-linux %s -o %t2
24# RUN: llvm-readobj -sections %t2 | FileCheck -check-prefix=GNU %s24# RUN: llvm-readobj --sections %t2 | FileCheck -check-prefix=GNU %s
25# GNU: Section {25# GNU: Section {
26# GNU: Index: 226# GNU: Index: 2
27# GNU: Name: .zdebug_str27# GNU: Name: .zdebug_str
...@@ -40,10 +40,10 @@...@@ -40,10 +40,10 @@
40# GNU-NEXT: }40# GNU-NEXT: }
4141
42# RUN: ld.lld --hash-style=sysv %t -o %t.so -shared42# RUN: ld.lld --hash-style=sysv %t -o %t.so -shared
43# RUN: llvm-readobj -sections -section-data %t.so | FileCheck -check-prefix=DATA %s43# RUN: llvm-readobj --sections --section-data %t.so | FileCheck -check-prefix=DATA %s
4444
45# RUN: ld.lld --hash-style=sysv %t2 -o %t2.so -shared45# RUN: ld.lld --hash-style=sysv %t2 -o %t2.so -shared
46# RUN: llvm-readobj -sections -section-data %t2.so | FileCheck -check-prefix=DATA %s46# RUN: llvm-readobj --sections --section-data %t2.so | FileCheck -check-prefix=DATA %s
4747
48# DATA: Section {48# DATA: Section {
49# DATA: Index: 649# DATA: Index: 6
deps/lld/test/ELF/compressed-input-alignment.test created+67
...@@ -0,0 +1,67 @@
1# REQUIRES: zlib, x86
2
3# RUN: yaml2obj -docnum=1 %s -o %t.o
4# RUN: ld.lld %t.o %t.o -o %t2
5# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s
6
7# RUN: yaml2obj -docnum=2 %s -o %t.o
8# RUN: ld.lld %t.o %t.o -o %t2
9# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s
10
11# CHECK: Name: .debug_info
12# CHECK-NEXT: Type: SHT_PROGBITS
13# CHECK-NEXT: Flags [
14# CHECK-NEXT: ]
15# CHECK-NEXT: Address: 0x0
16# CHECK-NEXT: Offset: 0xE8
17# CHECK-NEXT: Size: 108
18# CHECK-NEXT: Link: 0
19# CHECK-NEXT: Info: 0
20# CHECK-NEXT: AddressAlignment: 1
21# CHECK-NEXT: EntrySize: 0
22# CHECK-NEXT: SectionData (
23# CHECK-NEXT: 0000: {{.*}} |ABCDEFGHIJKLMNOP|
24# CHECK-NEXT: 0010: {{.*}} |QRSTUVWXYZ.ABCDE|
25# CHECK-NEXT: 0020: {{.*}} |FGHIJKLMNOPQRSTU|
26# CHECK-NEXT: 0030: {{.*}} |VWXYZ.ABCDEFGHIJ|
27# CHECK-NEXT: 0040: {{.*}} |KLMNOPQRSTUVWXYZ|
28# CHECK-NEXT: 0050: {{.*}} |.ABCDEFGHIJKLMNO|
29# CHECK-NEXT: 0060: {{.*}} |PQRSTUVWXYZ.|
30# CHECK-NEXT: )
31# CHECK-NEXT: }
32
33## YAML below is produced from the following code. AddressAlign of .debug_info is 8,
34## while compressed header has ch_addralign = 1. LLD had a bug and did not use the
35## value of ch_addralign at all. We produced broken section content.
36##
37## .section .debug_info,"",@progbits
38## .string "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
39## .string "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
40
41--- !ELF
42FileHeader:
43 Class: ELFCLASS64
44 Data: ELFDATA2LSB
45 Type: ET_REL
46 Machine: EM_X86_64
47Sections:
48 - Name: .debug_info
49 Type: SHT_PROGBITS
50 Flags: [ SHF_COMPRESSED ]
51 AddressAlign: 0x0000000000000008
52 Content: 010000000000000036000000000000000100000000000000789C73747276717573F7F0F4F2F6F1F5F30F080C0A0E090D0B8F888C6270C42D0500ADA00FBF
53
54## YAML below is the same as above, with a single change: ch_addralign field of the compressed
55## header was set to 0. This is allowed by the standard, we have to support it.
56--- !ELF
57FileHeader:
58 Class: ELFCLASS64
59 Data: ELFDATA2LSB
60 Type: ET_REL
61 Machine: EM_X86_64
62Sections:
63 - Name: .debug_info
64 Type: SHT_PROGBITS
65 Flags: [ SHF_COMPRESSED ]
66 AddressAlign: 0x0000000000000008
67 Content: 010000000000000036000000000000000000000000000000789C73747276717573F7F0F4F2F6F1F5F30F080C0A0E090D0B8F888C6270C42D0500ADA00FBF
deps/lld/test/ELF/copy-rel-pie.s+7-6
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux3// RUN: llvm-mc %p/Inputs/copy-rel-pie.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
4// RUN: ld.lld %t2.o -o %t2.so -shared4// RUN: ld.lld %t2.o -o %t2.so -shared
5// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t.exe -pie5// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t.exe -pie
6// RUN: llvm-readobj -s -r %t.exe | FileCheck %s6// RUN: llvm-readobj -S -r %t.exe | FileCheck %s
7// RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASM %s7// RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASM %s
88
9.global _start9.global _start
...@@ -27,21 +27,22 @@ _start:...@@ -27,21 +27,22 @@ _start:
27// CHECK-NEXT: SHF_ALLOC27// CHECK-NEXT: SHF_ALLOC
28// CHECK-NEXT: SHF_WRITE28// CHECK-NEXT: SHF_WRITE
29// CHECK-NEXT: ]29// CHECK-NEXT: ]
30// CHECK-NEXT: Address: 0x400030// CHECK-NEXT: Address: 0x3020
3131
32// CHECK: Relocations [32// CHECK: Relocations [
33// CHECK-NEXT: Section (4) .rela.dyn {33// CHECK-NEXT: Section (4) .rela.dyn {
34// CHECK-NEXT: 0x4000 R_X86_64_COPY foo 0x034// CHECK-NEXT: 0x3020 R_X86_64_COPY foo 0x0
35// CHECK-NEXT: }35// CHECK-NEXT: }
36// CHECK-NEXT: Section (5) .rela.plt {36// CHECK-NEXT: Section (5) .rela.plt {
37// CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT bar 0x037// CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT bar 0x0
38// CHECK-NEXT: }38// CHECK-NEXT: }
39// CHECK-NEXT: ]39// CHECK-NEXT: ]
4040
41// (0x1010 + 0x10) - 0x1005 = 2741// (0x1010 + 0x10) - 0x1005 = 27
42// 0x4000 - 0x100a = 1227842// 0x3020 - 0x100a = 8214
4343
44// DISASM: Disassembly of section .text:44// DISASM: Disassembly of section .text:
45// DISASM-EMPTY:
45// DISASM-NEXT: _start:46// DISASM-NEXT: _start:
46// DISASM-NEXT: 1000: e8 1b 00 00 00 callq 2747// DISASM-NEXT: 1000: e8 1b 00 00 00 callq 27
47// DISASM-NEXT: 1005: e8 f6 2f 00 00 callq 12278 <foo>48// DISASM-NEXT: 1005: e8 16 20 00 00 callq 8214 <foo>
deps/lld/test/ELF/copy-rel-version.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// RUN: echo "v1 {}; v2 {};" > %t.ver4// RUN: echo "v1 {}; v2 {};" > %t.ver
5// RUN: ld.lld %t1.o -shared -soname t1.so --version-script=%t.ver -o %t1.so5// RUN: ld.lld %t1.o -shared -soname t1.so --version-script=%t.ver -o %t1.so
6// RUN: ld.lld %t.o %t1.so -o %t6// RUN: ld.lld %t.o %t1.so -o %t
7// RUN: llvm-readobj -t %t | FileCheck %s7// RUN: llvm-readobj --symbols %t | FileCheck %s
88
9.global _start9.global _start
10_start:10_start:
deps/lld/test/ELF/copy-relocation-zero-abs-addr.s+2-2
...@@ -3,8 +3,8 @@...@@ -3,8 +3,8 @@
3// RUN: ld.lld -shared -o %t2.so %t.o3// RUN: ld.lld -shared -o %t2.so %t.o
4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t3.o4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t3.o
5// RUN: ld.lld %t2.so %t3.o -o %t45// RUN: ld.lld %t2.so %t3.o -o %t4
6// RUN: llvm-readobj -symbols %t2.so | FileCheck -check-prefix=ABSADDR %s6// RUN: llvm-readobj --symbols %t2.so | FileCheck -check-prefix=ABSADDR %s
7// RUN: llvm-readobj -s -r --expand-relocs %t4 | FileCheck %s7// RUN: llvm-readobj -S -r --expand-relocs %t4 | FileCheck %s
88
9// This tests that symbols with absolute addresses are properly9// This tests that symbols with absolute addresses are properly
10// handled. Normal DSO symbols are handled as usual.10// handled. Normal DSO symbols are handled as usual.
deps/lld/test/ELF/debug-gnu-pubnames.s+2-2
...@@ -2,12 +2,12 @@...@@ -2,12 +2,12 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
33
4# RUN: ld.lld %t.o -o %t1.exe4# RUN: ld.lld %t.o -o %t1.exe
5# RUN: llvm-readobj -sections %t1.exe | FileCheck %s5# RUN: llvm-readobj --sections %t1.exe | FileCheck %s
6# CHECK: .debug_gnu_pubnames6# CHECK: .debug_gnu_pubnames
7# CHECK: .debug_gnu_pubtypes7# CHECK: .debug_gnu_pubtypes
88
9# RUN: ld.lld -gdb-index %t.o -o %t2.exe9# RUN: ld.lld -gdb-index %t.o -o %t2.exe
10# RUN: llvm-readobj -sections %t2.exe | FileCheck %s --check-prefix=GDB10# RUN: llvm-readobj --sections %t2.exe | FileCheck %s --check-prefix=GDB
11# GDB-NOT: .debug_gnu_pubnames11# GDB-NOT: .debug_gnu_pubnames
12# GDB-NOT: .debug_gnu_pubtypes12# GDB-NOT: .debug_gnu_pubtypes
1313
deps/lld/test/ELF/debug-line-obj.s created+175
...@@ -0,0 +1,175 @@
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# When compiling with -ffunction-sections, .debug_line may contain descriptions
6# of locations from the different text sections. Until relocated such
7# descriptions might contain overlapping offsets. Check LLD is able to report
8# the error locations correctly in this case.
9
10# CHECK: error: undefined symbol: foo()
11# CHECK-NEXT: >>> referenced by test.cpp:2
12# CHECK-NEXT: >>> {{.*}}.o:(bar())
13# CHECK-NEXT: >>> referenced by test.cpp:3
14# CHECK-NEXT: >>> {{.*}}.o:(baz())
15
16# The code below is the reduced version of the output
17# from the following invocation and source:
18#
19# // test.cpp:
20# int foo();
21# int bar() { return foo(); }
22# int baz() { return foo(); }
23#
24# clang -gdwarf-5 -ffunction-sections test.cpp -o test.s -S
25
26.text
27.file "test.cpp"
28.section .text._Z3barv,"ax",@progbits
29.globl _Z3barv
30.type _Z3barv,@function
31_Z3barv:
32.Lfunc_begin0:
33 .file 0 "/path" "test.cpp" md5 0x9ff11a8404ab4d032ee2dd4f5f8c4140
34 .loc 0 2 0 # test.cpp:2:0
35 .loc 0 2 20 prologue_end # test.cpp:2:20
36 callq _Z3foov
37 .loc 0 2 13 is_stmt 0 # test.cpp:2:13
38.Lfunc_end0:
39.size _Z3barv, .Lfunc_end0-_Z3barv
40 # -- End function
41.section .text._Z3bazv,"ax",@progbits
42.globl _Z3bazv # -- Begin function _Z3bazv
43 .type _Z3bazv,@function
44_Z3bazv: # @_Z3bazv
45.Lfunc_begin1:
46 .loc 0 3 0 is_stmt 1 # test.cpp:3:0
47 .loc 0 3 20 prologue_end # test.cpp:3:20
48 callq _Z3foov
49 .loc 0 3 13 is_stmt 0 # test.cpp:3:13
50.Lfunc_end1:
51 .size _Z3bazv, .Lfunc_end1-_Z3bazv
52
53.section .debug_str,"MS",@progbits,1
54.Linfo_string0:
55 .asciz "stub"
56
57.section .debug_str_offsets,"",@progbits
58 .long 8
59 .short 5
60 .short 0
61.Lstr_offsets_base0:
62 .long .Linfo_string0
63
64.section .debug_abbrev,"",@progbits
65 .byte 1 # Abbreviation Code
66 .byte 17 # DW_TAG_compile_unit
67 .byte 1 # DW_CHILDREN_yes
68 .byte 37 # DW_AT_producer
69 .byte 37 # DW_FORM_strx1
70 .byte 19 # DW_AT_language
71 .byte 5 # DW_FORM_data2
72 .byte 3 # DW_AT_name
73 .byte 37 # DW_FORM_strx1
74 .byte 114 # DW_AT_str_offsets_base
75 .byte 23 # DW_FORM_sec_offset
76 .byte 16 # DW_AT_stmt_list
77 .byte 23 # DW_FORM_sec_offset
78 .byte 27 # DW_AT_comp_dir
79 .byte 37 # DW_FORM_strx1
80 .byte 115 # DW_AT_addr_base
81 .byte 23 # DW_FORM_sec_offset
82 .byte 17 # DW_AT_low_pc
83 .byte 1 # DW_FORM_addr
84 .byte 85 # DW_AT_ranges
85 .byte 35 # DW_FORM_rnglistx
86 .byte 116 # DW_AT_rnglists_base
87 .byte 23 # DW_FORM_sec_offset
88 .byte 0 # EOM(1)
89 .byte 0 # EOM(2)
90 .byte 2 # Abbreviation Code
91 .byte 46 # DW_TAG_subprogram
92 .byte 0 # DW_CHILDREN_no
93 .byte 17 # DW_AT_low_pc
94 .byte 27 # DW_FORM_addrx
95 .byte 18 # DW_AT_high_pc
96 .byte 6 # DW_FORM_data4
97 .byte 64 # DW_AT_frame_base
98 .byte 24 # DW_FORM_exprloc
99 .byte 110 # DW_AT_linkage_name
100 .byte 37 # DW_FORM_strx1
101 .byte 3 # DW_AT_name
102 .byte 37 # DW_FORM_strx1
103 .byte 58 # DW_AT_decl_file
104 .byte 11 # DW_FORM_data1
105 .byte 59 # DW_AT_decl_line
106 .byte 11 # DW_FORM_data1
107 .byte 73 # DW_AT_type
108 .byte 19 # DW_FORM_ref4
109 .byte 63 # DW_AT_external
110 .byte 25 # DW_FORM_flag_present
111 .byte 0 # EOM(1)
112 .byte 0 # EOM(2)
113 .byte 3 # Abbreviation Code
114 .byte 36 # DW_TAG_base_type
115 .byte 0 # DW_CHILDREN_no
116 .byte 3 # DW_AT_name
117 .byte 37 # DW_FORM_strx1
118 .byte 62 # DW_AT_encoding
119 .byte 11 # DW_FORM_data1
120 .byte 11 # DW_AT_byte_size
121 .byte 11 # DW_FORM_data1
122 .byte 0 # EOM(1)
123 .byte 0 # EOM(2)
124 .byte 0 # EOM(3)
125
126.section .debug_info,"",@progbits
127.Lcu_begin0:
128 .long .Ldebug_info_end0-.Ldebug_info_start0 # Length of Unit
129.Ldebug_info_start0:
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 .byte 1 # Abbrev [1] 0xc:0x44 DW_TAG_compile_unit
135 .byte 0 # DW_AT_producer
136 .short 4 # DW_AT_language
137 .byte 0 # DW_AT_name
138 .long .Lstr_offsets_base0 # DW_AT_str_offsets_base
139 .long .Lline_table_start0 # DW_AT_stmt_list
140 .byte 2 # DW_AT_comp_dir
141 .long 0 # DW_AT_addr_base
142 .quad 0 # DW_AT_low_pc
143 .byte 0 # DW_AT_ranges
144 .long 0 # DW_AT_rnglists_base
145 .byte 2 # Abbrev [2] 0x2b:0x10 DW_TAG_subprogram
146 .byte 0 # DW_AT_low_pc
147 .long .Lfunc_end0-.Lfunc_begin0 # DW_AT_high_pc
148 .byte 1 # DW_AT_frame_base
149 .byte 86
150 .byte 3 # DW_AT_linkage_name
151 .byte 0 # DW_AT_name
152 .byte 1 # DW_AT_decl_file
153 .byte 2 # DW_AT_decl_line
154 .long 75 # DW_AT_type
155 # DW_AT_external
156 .byte 2 # Abbrev [2] 0x3b:0x10 DW_TAG_subprogram
157 .byte 1 # DW_AT_low_pc
158 .long .Lfunc_end1-.Lfunc_begin1 # DW_AT_high_pc
159 .byte 1 # DW_AT_frame_base
160 .byte 86
161 .byte 6 # DW_AT_linkage_name
162 .byte 0 # DW_AT_name
163 .byte 1 # DW_AT_decl_file
164 .byte 3 # DW_AT_decl_line
165 .long 75 # DW_AT_type
166 # DW_AT_external
167 .byte 3 # Abbrev [3] 0x4b:0x4 DW_TAG_base_type
168 .byte 0 # DW_AT_name
169 .byte 5 # DW_AT_encoding
170 .byte 4 # DW_AT_byte_size
171 .byte 0 # End Of Children Mark
172.Ldebug_info_end0:
173
174.section .debug_line,"",@progbits
175.Lline_table_start0:
deps/lld/test/ELF/debug-line-str.s+1-2
...@@ -27,8 +27,7 @@...@@ -27,8 +27,7 @@
27main:27main:
28.Lfunc_begin0:28.Lfunc_begin0:
29 .file 0 "/home/path" "test.cpp" md5 0x8ed32099ab837bd13543fd3e8102739f29 .file 0 "/home/path" "test.cpp" md5 0x8ed32099ab837bd13543fd3e8102739f
30 .file 1 "test.cpp" md5 0x8ed32099ab837bd13543fd3e8102739f30 .loc 0 3 10 prologue_end
31 .loc 1 3 10 prologue_end
32 jmp _Z3foov31 jmp _Z3foov
33.Lfunc_end0:32.Lfunc_end0:
3433
deps/lld/test/ELF/debug-relocation-none.test+5-4
...@@ -52,7 +52,8 @@ Sections:...@@ -52,7 +52,8 @@ Sections:
52 Content: '0111001017000000'52 Content: '0111001017000000'
5353
54Symbols:54Symbols:
55 Global:55 - Name: _start
56 - Name: _start56 Section: .text
57 Section: .text57 Binding: STB_GLOBAL
58 - Name: bar58 - Name: bar
59 Binding: STB_GLOBAL
deps/lld/test/ELF/defsym-reserved-syms.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -o %t %t.o --defsym=foo2=etext3# RUN: ld.lld -o %t %t.o --defsym=foo2=etext
4# RUN: llvm-readobj -t -s %t | FileCheck %s4# RUN: llvm-readobj --symbols -S %t | FileCheck %s
55
6## Check 'foo2' value is equal to value of 'etext'.6## Check 'foo2' value is equal to value of 'etext'.
7# CHECK: Symbol {7# CHECK: Symbol {
...@@ -14,7 +14,7 @@...@@ -14,7 +14,7 @@
14## Check 'foo2' value set correctly when using14## Check 'foo2' value set correctly when using
15## reserved symbol 'etext' in expression.15## reserved symbol 'etext' in expression.
16# RUN: ld.lld -o %t %t.o --defsym=foo2=etext+216# RUN: ld.lld -o %t %t.o --defsym=foo2=etext+2
17# RUN: llvm-readobj -t -s %t | FileCheck %s --check-prefix=EXPR17# RUN: llvm-readobj --symbols -S %t | FileCheck %s --check-prefix=EXPR
18# EXPR: Symbol {18# EXPR: Symbol {
19# EXPR: Name: foo219# EXPR: Name: foo2
20# EXPR-NEXT: Value: 0x20100720# EXPR-NEXT: Value: 0x201007
deps/lld/test/ELF/defsym.s+5-4
...@@ -1,12 +1,12 @@...@@ -1,12 +1,12 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -o %t %t.o --defsym=foo2=foo13# RUN: ld.lld -o %t %t.o --defsym=foo2=foo1
4# RUN: llvm-readobj -t -s %t | FileCheck %s4# RUN: llvm-readobj --symbols -S %t | FileCheck %s
5# RUN: llvm-objdump -d -print-imm-hex %t | FileCheck %s --check-prefix=USE5# RUN: llvm-objdump -d -print-imm-hex %t | FileCheck %s --check-prefix=USE
66
7## Check that we accept --defsym foo2=foo1 form.7## Check that we accept --defsym foo2=foo1 form.
8# RUN: ld.lld -o %t2 %t.o --defsym foo2=foo18# RUN: ld.lld -o %t2 %t.o --defsym foo2=foo1
9# RUN: llvm-readobj -t -s %t2 | FileCheck %s9# RUN: llvm-readobj --symbols -S %t2 | FileCheck %s
10# RUN: llvm-objdump -d -print-imm-hex %t2 | FileCheck %s --check-prefix=USE10# RUN: llvm-objdump -d -print-imm-hex %t2 | FileCheck %s --check-prefix=USE
1111
12## Check we are reporting the error correctly and don't crash12## Check we are reporting the error correctly and don't crash
...@@ -36,11 +36,12 @@...@@ -36,11 +36,12 @@
3636
37## Check we can use foo2 and it that it is an alias for foo1.37## Check we can use foo2 and it that it is an alias for foo1.
38# USE: Disassembly of section .text:38# USE: Disassembly of section .text:
39# USE-EMPTY:
39# USE-NEXT: _start:40# USE-NEXT: _start:
40# USE-NEXT: movl $0x123, %edx41# USE-NEXT: movl $0x123, %edx
4142
42# RUN: ld.lld -o %t %t.o --defsym=foo2=143# RUN: ld.lld -o %t %t.o --defsym=foo2=1
43# RUN: llvm-readobj -t -s %t | FileCheck %s --check-prefix=ABS44# RUN: llvm-readobj --symbols -S %t | FileCheck %s --check-prefix=ABS
4445
45# ABS: Symbol {46# ABS: Symbol {
46# ABS: Name: foo247# ABS: Name: foo2
...@@ -53,7 +54,7 @@...@@ -53,7 +54,7 @@
53# ABS-NEXT: }54# ABS-NEXT: }
5455
55# RUN: ld.lld -o %t %t.o --defsym=foo2=foo1+556# RUN: ld.lld -o %t %t.o --defsym=foo2=foo1+5
56# RUN: llvm-readobj -t -s %t | FileCheck %s --check-prefix=EXPR57# RUN: llvm-readobj --symbols -S %t | FileCheck %s --check-prefix=EXPR
5758
58# EXPR: Symbol {59# EXPR: Symbol {
59# EXPR: Name: foo160# EXPR: Name: foo1
deps/lld/test/ELF/deplibs-colon-prefix.s created+15
...@@ -0,0 +1,15 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/deplibs-lib_foo.s -o %tfoo.o
5# RUN: rm -rf %t.dir
6# RUN: mkdir -p %t.dir
7# RUN: llvm-ar rc %t.dir/foo.a %tfoo.o
8# RUN: not ld.lld %t.o -o /dev/null -L %t.dir 2>&1 | FileCheck %s -DOBJ=%t.o
9# CHECK: error: [[OBJ]]: unable to find library from dependent library specifier: :foo.a
10
11 .global _start
12_start:
13 call foo
14 .section ".deplibs","MS",@llvm_dependent_libraries,1
15 .asciz ":foo.a"
deps/lld/test/ELF/deplibs-corrupt.s created+8
...@@ -0,0 +1,8 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: not ld.lld %t.o -o /dev/null -L %t.dir 2>&1 | FileCheck %s -DOBJ=%t.o
5# CHECK: error: [[OBJ]]: corrupted dependent libraries section (unterminated string): .deplibs
6
7.section ".deplibs","MS",@llvm_dependent_libraries,1
8 .ascii ":foo.a"
deps/lld/test/ELF/deplibs.s created+56
...@@ -0,0 +1,56 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/deplibs-lib_foo.s -o %tfoo.o
5# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/deplibs-lib_bar.s -o %tbar.o
6# RUN: rm -rf %t.dir %t.cwd
7# RUN: mkdir -p %t.dir
8
9# error if dependent libraries cannot be found
10# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s -DOBJ=%t.o --check-prefix MISSING
11# MISSING: error: [[OBJ]]: unable to find library from dependent library specifier: foo.a
12# MISSING-NEXT: error: [[OBJ]]: unable to find library from dependent library specifier: bar
13
14# can ignore dependent libraries
15# RUN: not ld.lld %t.o -o /dev/null --no-dependent-libraries 2>&1 | FileCheck %s --check-prefix IGNORE
16# IGNORE: error: undefined symbol: foo
17# IGNORE: error: undefined symbol: bar
18
19# -r links preserve dependent libraries
20# RUN: ld.lld %t.o %t.o -r -o %t-r.o
21# RUN: not ld.lld %t-r.o -o /dev/null 2>&1 | sort | FileCheck %s -DOBJ=%t-r.o --check-prefixes MINUSR
22# MINUSR: error: [[OBJ]]: unable to find library from dependent library specifier: bar
23# MINUSR-NEXT: error: [[OBJ]]: unable to find library from dependent library specifier: foo.a
24# MINUSR-NOT: unable to find library from dependent library specifier
25
26# static archives located relative to library search paths
27# RUN: llvm-ar rc %t.dir/foo.a %tfoo.o
28# RUN: llvm-ar rc %t.dir/libbar.a %tbar.o
29# RUN: ld.lld %t.o -o /dev/null -L %t.dir
30
31# shared objects located relative to library search paths
32# RUN: rm %t.dir/libbar.a
33# RUN: ld.lld -shared -o %t.dir/libbar.so %tbar.o
34# RUN: ld.lld -Bdynamic %t.o -o /dev/null -L %t.dir
35
36# dependent libraries searched for symbols after libraries on the command line
37# RUN: mkdir -p %t.cwd
38# RUN: cd %t.cwd
39# RUN: cp %t.dir/foo.a %t.cwd/libcmdline.a
40# RUN: ld.lld %t.o libcmdline.a -o /dev/null -L %t.dir --trace 2>&1 | FileCheck %s -DOBJ=%t.o -DSO=%t.dir --check-prefix CMDLINE --implicit-check-not foo.a
41# CMDLINE: [[OBJ]]
42# CMDLINE-NEXT: {{^libcmdline\.a}}
43# CMDLINE-NEXT: [[SO]]{{[\\/]}}libbar.so
44
45# libraries can be found from specifiers as if the specifiers were listed on on the command-line.
46# RUN: cp %t.dir/foo.a %t.cwd/foo.a
47# RUN: ld.lld %t.o -o /dev/null -L %t.dir --trace 2>&1 | FileCheck %s -DOBJ=%t.o -DSO=%t.dir --check-prefix ASIFCMDLINE --implicit-check-not foo.a
48# ASIFCMDLINE: [[OBJ]]
49# ASIFCMDLINE-NEXT: {{^foo\.a}}
50# ASIFCMDLINE-NEXT: [[SO]]{{[\\/]}}libbar.so
51
52 call foo
53 call bar
54.section ".deplibs","MS",@llvm_dependent_libraries,1
55 .asciz "foo.a"
56 .asciz "bar"
deps/lld/test/ELF/discard-locals.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -save-temp-labels %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -save-temp-labels %s -o %t
3// RUN: ld.lld -discard-locals %t -o %t23// RUN: ld.lld -discard-locals %t -o %t2
4// RUN: llvm-readobj -s -sd -t %t2 | FileCheck %s4// RUN: llvm-readobj -S --section-data --symbols %t2 | FileCheck %s
55
6.global _start6.global _start
7_start:7_start:
deps/lld/test/ELF/discard-merge-locals.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
3// RUN: ld.lld %t -o %t2 -shared3// RUN: ld.lld %t -o %t2 -shared
4// RUN: llvm-readobj -t %t2 | FileCheck %s4// RUN: llvm-readobj --symbols %t2 | FileCheck %s
55
6 leaq .L.str(%rip), %rdi6 leaq .L.str(%rip), %rdi
77
deps/lld/test/ELF/discard-merge-unnamed.s+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1// RUN: ld.lld %p/Inputs/discard-merge-unnamed.o -o %t2 -shared1// RUN: ld.lld %p/Inputs/discard-merge-unnamed.o -o %t2 -shared
2// RUN: llvm-readobj -t %t2 | FileCheck %s2// RUN: llvm-readobj --symbols %t2 | FileCheck %s
33
4// Test that the unnamed symbol is SHF_MERGE is omitted.4// Test that the unnamed symbol is SHF_MERGE is omitted.
55
deps/lld/test/ELF/discard-none.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -save-temp-labels %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux -save-temp-labels %s -o %t
3// RUN: ld.lld -discard-none -shared %t -o %t23// RUN: ld.lld -discard-none -shared %t -o %t2
4// RUN: llvm-readobj -s -sd -t %t2 | FileCheck %s4// RUN: llvm-readobj -S --section-data --symbols %t2 | FileCheck %s
55
6.text6.text
7.Lmyvar:7.Lmyvar:
deps/lld/test/ELF/driver.test+7-3
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1# REQUIRES: x861# REQUIRES: x86
22
3# RUN: not ld.lld --unknown1 --unknown2 -m foo /no/such/file -lnosuchlib \3# RUN: not ld.lld --unknown1 --unkn=own2 -m foo /no/such/file -lnosuchlib \
4# RUN: 2>&1 | FileCheck -check-prefix=UNKNOWN %s4# RUN: 2>&1 | FileCheck -check-prefix=UNKNOWN %s
55
6# UNKNOWN: unknown argument: --unknown16# UNKNOWN: unknown argument '--unknown1'
7# UNKNOWN: unknown argument: --unknown27# UNKNOWN: unknown argument '--unkn=own2'
8# UNKNOWN: unknown emulation: foo8# UNKNOWN: unknown emulation: foo
9# UNKNOWN: cannot open /no/such/file9# UNKNOWN: cannot open /no/such/file
10# UNKNOWN: unable to find library -lnosuchlib10# UNKNOWN: unable to find library -lnosuchlib
...@@ -22,6 +22,9 @@...@@ -22,6 +22,9 @@
22# RUN: not ld.lld -v xyz 2>&1 | FileCheck -check-prefix=VERSION %s22# RUN: not ld.lld -v xyz 2>&1 | FileCheck -check-prefix=VERSION %s
23# VERSION: LLD {{.*}} (compatible with GNU linkers)23# VERSION: LLD {{.*}} (compatible with GNU linkers)
2424
25# RUN: not ld.lld --versin 2>&1 | FileCheck -check-prefix=SPELLVERSION %s
26# SPELLVERSION: unknown argument '--versin', did you mean '--version'
27
25## Attempt to link DSO with -r28## Attempt to link DSO with -r
26# RUN: ld.lld -shared %t -o %t.so29# RUN: ld.lld -shared %t -o %t.so
27# RUN: not ld.lld -r %t.so %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR %s30# RUN: not ld.lld -r %t.so %t -o %tfail 2>&1 | FileCheck -check-prefix=ERR %s
...@@ -60,6 +63,7 @@...@@ -60,6 +63,7 @@
60# ERR9: cannot open output file utput=/no/such/file63# ERR9: cannot open output file utput=/no/such/file
6164
62# RUN: not ld.lld %t -z foo 2>&1 | FileCheck -check-prefix=ERR10 %s65# RUN: not ld.lld %t -z foo 2>&1 | FileCheck -check-prefix=ERR10 %s
66# RUN: not ld.lld %t -z foo --version 2>&1 | FileCheck -check-prefix=ERR10 %s
63# ERR10: unknown -z value: foo67# ERR10: unknown -z value: foo
6468
65## Check we report "unknown -z value" error even with -v.69## Check we report "unknown -z value" error even with -v.
deps/lld/test/ELF/dso-undef-size.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: ld.lld -shared %t1.o -o %t1.so3# RUN: ld.lld -shared %t1.o -o %t1.so
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o
5# RUN: ld.lld -shared %t2.o %t1.so -o %t2.so5# RUN: ld.lld -shared %t2.o %t1.so -o %t2.so
6# RUN: llvm-readobj -symbols -dyn-symbols %t2.so6# RUN: llvm-readobj --symbols --dyn-syms %t2.so
77
8# CHECK: Symbols [8# CHECK: Symbols [
9# CHECK-NEXT: Symbol {9# CHECK-NEXT: Symbol {
deps/lld/test/ELF/dso_handle.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: ld.lld -shared %t.o -o %t4# RUN: ld.lld -shared %t.o -o %t
5# RUN: llvm-readobj -symbols %t | FileCheck %s5# RUN: llvm-readobj --symbols %t | FileCheck %s
6# CHECK: Name: __dso_handle6# CHECK: Name: __dso_handle
7# CHECK-NEXT: Value: 0x07# CHECK-NEXT: Value: 0x0
8# CHECK-NEXT: Size: 08# CHECK-NEXT: Size: 0
deps/lld/test/ELF/dt_flags.s+3-3
...@@ -5,13 +5,13 @@...@@ -5,13 +5,13 @@
55
6# RUN: ld.lld -z global -z initfirst -z interpose -z now -z nodefaultlib \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 %t17# RUN: -z nodelete -z nodlopen -z origin -Bsymbolic %t %t.so -o %t1
8# RUN: llvm-readobj -dynamic-table %t1 | FileCheck -check-prefix=FLAGS %s8# RUN: llvm-readobj --dynamic-table %t1 | FileCheck -check-prefix=FLAGS %s
99
10# RUN: ld.lld %t %t.so -o %t210# RUN: ld.lld %t %t.so -o %t2
11# RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s11# RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s
1212
13# RUN: ld.lld -z lazy %t %t.so -o %t213# RUN: ld.lld -z lazy %t %t.so -o %t2
14# RUN: llvm-readobj -dynamic-table %t2 | FileCheck %s14# RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s
1515
16# FLAGS: DynamicSection [16# FLAGS: DynamicSection [
17# FLAGS: 0x000000000000001E FLAGS ORIGIN SYMBOLIC BIND_NOW17# FLAGS: 0x000000000000001E FLAGS ORIGIN SYMBOLIC BIND_NOW
deps/lld/test/ELF/dt_tags.s+2-2
...@@ -3,8 +3,8 @@...@@ -3,8 +3,8 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %t
4# RUN: ld.lld -shared %t -o %t.so4# RUN: ld.lld -shared %t -o %t.so
5# RUN: ld.lld %t %t.so -o %t.exe5# RUN: ld.lld %t %t.so -o %t.exe
6# RUN: llvm-readobj -dynamic-table %t.so | FileCheck -check-prefix=DSO %s6# RUN: llvm-readobj --dynamic-table %t.so | FileCheck -check-prefix=DSO %s
7# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck -check-prefix=EXE %s7# RUN: llvm-readobj --dynamic-table %t.exe | FileCheck -check-prefix=EXE %s
88
9# EXE: DynamicSection [9# EXE: DynamicSection [
10# EXE: 0x0000000000000015 DEBUG 0x010# EXE: 0x0000000000000015 DEBUG 0x0
deps/lld/test/ELF/dtrace-r.test deleted-8
...@@ -1,8 +0,0 @@
1RUN: ld.lld -r -o %t.o %p/Inputs/dtrace-r.o
2RUN: llvm-readobj -r %t.o | FileCheck %s
3
4CHECK: Relocations [
5CHECK-NEXT: Section ({{.*}}) .rela.text {
6CHECK-NEXT: 0x0 R_X86_64_NONE - 0x0
7CHECK-NEXT: }
8CHECK-NEXT: ]
deps/lld/test/ELF/dynamic-got-rela.s+3-3
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared --apply-dynamic-relocs3// RUN: ld.lld %t.o -o %t.so -shared --apply-dynamic-relocs
4// RUN: llvm-readobj -r -s -l -section-data %t.so | FileCheck -check-prefix CHECK -check-prefix APPLYDYNREL %s4// RUN: llvm-readobj -r -S -l --section-data %t.so | FileCheck -check-prefix CHECK -check-prefix APPLYDYNREL %s
5// RUN: ld.lld %t.o -o %t2.so -shared5// RUN: ld.lld %t.o -o %t2.so -shared
6// RUN: llvm-readobj -r -s -l -section-data %t2.so | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s6// RUN: llvm-readobj -r -S -l --section-data %t2.so | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s
7// RUN: ld.lld %t.o -o %t2.so -shared --no-apply-dynamic-relocs7// RUN: ld.lld %t.o -o %t2.so -shared --no-apply-dynamic-relocs
8// RUN: llvm-readobj -r -s -l -section-data %t2.so | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s8// RUN: llvm-readobj -r -S -l --section-data %t2.so | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s
99
10// APPLYDYNREL: Name: .got10// APPLYDYNREL: Name: .got
11// APPLYDYNREL-NEXT: Type: SHT_PROGBITS11// APPLYDYNREL-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/dynamic-got.s+23-23
...@@ -1,24 +1,7 @@...@@ -1,24 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o
3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
4// RUN: llvm-readobj -s -l -section-data -r %t.so | FileCheck %s4// RUN: llvm-readobj -S -l --section-data -r %t.so | FileCheck %s
5
6// CHECK: Name: .got.plt
7// CHECK-NEXT: Type: SHT_PROGBITS
8// CHECK-NEXT: Flags [
9// CHECK-NEXT: SHF_ALLOC
10// CHECK-NEXT: SHF_WRITE
11// CHECK-NEXT: ]
12// CHECK-NEXT: Address:
13// CHECK-NEXT: Offset:
14// CHECK-NEXT: Size:
15// CHECK-NEXT: Link:
16// CHECK-NEXT: Info:
17// CHECK-NEXT: AddressAlignment:
18// CHECK-NEXT: EntrySize:
19// CHECK-NEXT: SectionData (
20// CHECK-NEXT: 0000: 00300000 00000000 00000000
21// CHECK-NEXT: )
225
23// CHECK: Name: .got6// CHECK: Name: .got
24// CHECK-NEXT: Type: SHT_PROGBITS7// CHECK-NEXT: Type: SHT_PROGBITS
...@@ -34,19 +17,36 @@...@@ -34,19 +17,36 @@
34// CHECK-NEXT: AddressAlignment:17// CHECK-NEXT: AddressAlignment:
35// CHECK-NEXT: EntrySize:18// CHECK-NEXT: EntrySize:
36// CHECK-NEXT: SectionData (19// CHECK-NEXT: SectionData (
37// CHECK-NEXT: 0000: 0030000020// CHECK-NEXT: 0000: 00200000
38// CHECK-NEXT: )21// CHECK-NEXT: )
3922
23// CHECK: Name: .got.plt
24// CHECK-NEXT: Type: SHT_PROGBITS
25// CHECK-NEXT: Flags [
26// CHECK-NEXT: SHF_ALLOC
27// CHECK-NEXT: SHF_WRITE
28// CHECK-NEXT: ]
29// CHECK-NEXT: Address:
30// CHECK-NEXT: Offset:
31// CHECK-NEXT: Size:
32// CHECK-NEXT: Link:
33// CHECK-NEXT: Info:
34// CHECK-NEXT: AddressAlignment:
35// CHECK-NEXT: EntrySize:
36// CHECK-NEXT: SectionData (
37// CHECK-NEXT: 0000: 00200000 00000000 00000000
38// CHECK-NEXT: )
39
40// CHECK: Relocations [40// CHECK: Relocations [
41// CHECK-NEXT: Section ({{.*}}) .rel.dyn {41// CHECK-NEXT: Section ({{.*}}) .rel.dyn {
42// CHECK-NEXT: 0x3050 R_386_RELATIVE - 0x042// CHECK-NEXT: 0x2050 R_386_RELATIVE - 0x0
43// CHECK-NEXT: }43// CHECK-NEXT: }
44// CHECK-NEXT: ]44// CHECK-NEXT: ]
4545
46// CHECK: Type: PT_DYNAMIC46// CHECK: Type: PT_DYNAMIC
47// CHECK-NEXT: Offset: 0x300047// CHECK-NEXT: Offset: 0x2000
48// CHECK-NEXT: VirtualAddress: 0x300048// CHECK-NEXT: VirtualAddress: 0x2000
49// CHECK-NEXT: PhysicalAddress: 0x300049// CHECK-NEXT: PhysicalAddress: 0x2000
5050
51 calll .L0$pb51 calll .L0$pb
52.L0$pb:52.L0$pb:
deps/lld/test/ELF/dynamic-list-preempt-replace-symbol.s created+14
...@@ -0,0 +1,14 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
4# RUN: echo '{ common; };' > %t.list
5# RUN: ld.lld --dynamic-list %t.list -shared %t.o -o %t.so
6
7# RUN: llvm-readobj -r %t.so | FileCheck %s
8
9# CHECK: R_X86_64_GLOB_DAT common 0x0
10
11movq common@gotpcrel(%rip), %rax
12
13.type common,@object
14.comm common,4,4
deps/lld/test/ELF/dynamic-list-preempt.s+7-2
...@@ -5,11 +5,16 @@...@@ -5,11 +5,16 @@
5# RUN: echo "{ global: foo; bar; local: *; };" > %t.vers5# RUN: echo "{ global: foo; bar; local: *; };" > %t.vers
6# RUN: ld.lld --hash-style=sysv -fatal-warnings -dynamic-list %t.list -version-script %t.vers -shared %t.o -o %t.so6# RUN: ld.lld --hash-style=sysv -fatal-warnings -dynamic-list %t.list -version-script %t.vers -shared %t.o -o %t.so
7# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOCS %s7# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOCS %s
8# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=DYNSYMS %s8# RUN: llvm-readobj --dyn-syms %t.so | FileCheck --check-prefix=DYNSYMS %s
9
10# RUN: echo "V1 { global: foo; bar; local: *; };" > %t.vers
11# RUN: ld.lld --hash-style=sysv -fatal-warnings -dynamic-list %t.list -version-script %t.vers -shared %t.o -o %t.so
12# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOCS %s
13# RUN: llvm-readobj --dyn-syms %t.so | FileCheck --check-prefix=DYNSYMS %s
914
10# RELOCS: Relocations [15# RELOCS: Relocations [
11# RELOCS-NEXT: Section ({{.*}}) .rela.plt {16# RELOCS-NEXT: Section ({{.*}}) .rela.plt {
12# RELOCS-NEXT: R_X86_64_JUMP_SLOT foo 0x017# RELOCS-NEXT: R_X86_64_JUMP_SLOT foo{{.*}} 0x0
13# RELOCS-NEXT: R_X86_64_JUMP_SLOT ext 0x018# RELOCS-NEXT: R_X86_64_JUMP_SLOT ext 0x0
14# RELOCS-NEXT: }19# RELOCS-NEXT: }
15# RELOCS-NEXT: ]20# RELOCS-NEXT: ]
deps/lld/test/ELF/dynamic-list-weak-archive.s+1-1
...@@ -10,7 +10,7 @@...@@ -10,7 +10,7 @@
1010
11# CHECK: Relocations [11# CHECK: Relocations [
12# CHECK-NEXT: Section ({{.*}}) .rela.plt {12# CHECK-NEXT: Section ({{.*}}) .rela.plt {
13# CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT foo13# CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT foo
14# CHECK-NEXT: }14# CHECK-NEXT: }
15# CHECK-NEXT: ]15# CHECK-NEXT: ]
1616
deps/lld/test/ELF/dynamic-list-wildcard.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
44
5# RUN: echo "{ foo1*; };" > %t.list5# RUN: echo "{ foo1*; };" > %t.list
6# RUN: ld.lld --hash-style=sysv -pie --dynamic-list %t.list %t -o %t.exe6# RUN: ld.lld --hash-style=sysv -pie --dynamic-list %t.list %t -o %t.exe
7# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s7# RUN: llvm-readobj --dyn-syms %t.exe | FileCheck %s
88
9# CHECK: DynamicSymbols [9# CHECK: DynamicSymbols [
10# CHECK-NEXT: Symbol {10# CHECK-NEXT: Symbol {
deps/lld/test/ELF/dynamic-list.s+8-8
...@@ -7,19 +7,19 @@...@@ -7,19 +7,19 @@
7## Check exporting only one symbol.7## Check exporting only one symbol.
8# RUN: echo "{ foo1; };" > %t.list8# RUN: echo "{ foo1; };" > %t.list
9# RUN: ld.lld --hash-style=sysv --dynamic-list %t.list %t %t2.so -o %t.exe9# RUN: ld.lld --hash-style=sysv --dynamic-list %t.list %t %t2.so -o %t.exe
10# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s10# RUN: llvm-readobj --dyn-syms %t.exe | FileCheck %s
1111
12## And now using quoted strings (the output is the same since it does12## And now using quoted strings (the output is the same since it does
13## use any wildcard character).13## use any wildcard character).
14# RUN: echo "{ \"foo1\"; };" > %t.list14# RUN: echo "{ \"foo1\"; };" > %t.list
15# RUN: ld.lld --hash-style=sysv --dynamic-list %t.list %t %t2.so -o %t.exe15# RUN: ld.lld --hash-style=sysv --dynamic-list %t.list %t %t2.so -o %t.exe
16# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s16# RUN: llvm-readobj --dyn-syms %t.exe | FileCheck %s
1717
18## And now using --export-dynamic-symbol.18## And now using --export-dynamic-symbol.
19# RUN: ld.lld --hash-style=sysv --export-dynamic-symbol foo1 %t %t2.so -o %t.exe19# RUN: ld.lld --hash-style=sysv --export-dynamic-symbol foo1 %t %t2.so -o %t.exe
20# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s20# RUN: llvm-readobj --dyn-syms %t.exe | FileCheck %s
21# RUN: ld.lld --hash-style=sysv --export-dynamic-symbol=foo1 %t %t2.so -o %t.exe21# RUN: ld.lld --hash-style=sysv --export-dynamic-symbol=foo1 %t %t2.so -o %t.exe
22# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck %s22# RUN: llvm-readobj --dyn-syms %t.exe | FileCheck %s
2323
24# CHECK: DynamicSymbols [24# CHECK: DynamicSymbols [
25# CHECK-NEXT: Symbol {25# CHECK-NEXT: Symbol {
...@@ -46,11 +46,11 @@...@@ -46,11 +46,11 @@
46## Now export all the foo1, foo2, and foo31 symbols46## Now export all the foo1, foo2, and foo31 symbols
47# RUN: echo "{ foo1; foo2; foo31; };" > %t.list47# RUN: echo "{ foo1; foo2; foo31; };" > %t.list
48# RUN: ld.lld --hash-style=sysv --dynamic-list %t.list %t %t2.so -o %t.exe48# RUN: ld.lld --hash-style=sysv --dynamic-list %t.list %t %t2.so -o %t.exe
49# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK2 %s49# RUN: llvm-readobj --dyn-syms %t.exe | FileCheck -check-prefix=CHECK2 %s
50# RUN: echo "{ foo1; foo2; };" > %t1.list50# RUN: echo "{ foo1; foo2; };" > %t1.list
51# RUN: echo "{ foo31; };" > %t2.list51# RUN: echo "{ foo31; };" > %t2.list
52# RUN: ld.lld --hash-style=sysv --dynamic-list %t1.list --dynamic-list %t2.list %t %t2.so -o %t.exe52# RUN: ld.lld --hash-style=sysv --dynamic-list %t1.list --dynamic-list %t2.list %t %t2.so -o %t.exe
53# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK2 %s53# RUN: llvm-readobj --dyn-syms %t.exe | FileCheck -check-prefix=CHECK2 %s
5454
55# CHECK2: DynamicSymbols [55# CHECK2: DynamicSymbols [
56# CHECK2-NEXT: Symbol {56# CHECK2-NEXT: Symbol {
...@@ -96,11 +96,11 @@...@@ -96,11 +96,11 @@
96## incomplete dynamic-list still exports everything.96## incomplete dynamic-list still exports everything.
97# RUN: echo "{ foo2; };" > %t.list97# RUN: echo "{ foo2; };" > %t.list
98# RUN: ld.lld --hash-style=sysv --dynamic-list %t.list --export-dynamic %t %t2.so -o %t.exe98# RUN: ld.lld --hash-style=sysv --dynamic-list %t.list --export-dynamic %t %t2.so -o %t.exe
99# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK3 %s99# RUN: llvm-readobj --dyn-syms %t.exe | FileCheck -check-prefix=CHECK3 %s
100100
101## The same with --export-dynamic-symbol.101## The same with --export-dynamic-symbol.
102# RUN: ld.lld --hash-style=sysv --export-dynamic-symbol=foo2 --export-dynamic %t %t2.so -o %t.exe102# RUN: ld.lld --hash-style=sysv --export-dynamic-symbol=foo2 --export-dynamic %t %t2.so -o %t.exe
103# RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck -check-prefix=CHECK3 %s103# RUN: llvm-readobj --dyn-syms %t.exe | FileCheck -check-prefix=CHECK3 %s
104104
105# CHECK3: DynamicSymbols [105# CHECK3: DynamicSymbols [
106# CHECK3-NEXT: Symbol {106# CHECK3-NEXT: Symbol {
deps/lld/test/ELF/dynamic-no-rosegment.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -shared --no-rosegment -z rodynamic -o %t %t.o3# RUN: ld.lld -shared --no-rosegment -z rodynamic -o %t %t.o
4# RUN: llvm-readobj -dynamic-table -s %t | FileCheck %s4# RUN: llvm-readobj --dynamic-table -S %t | FileCheck %s
55
6# CHECK: DynamicSection [ (7 entries)6# CHECK: DynamicSection [ (7 entries)
7# CHECK-NEXT: Tag Type Name/Value7# CHECK-NEXT: Tag Type Name/Value
deps/lld/test/ELF/dynamic-reloc-index.s+1-1
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
99
10// CHECK: Relocations [10// CHECK: Relocations [
11// CHECK-NEXT: Section ({{.*}}) .rela.plt {11// CHECK-NEXT: Section ({{.*}}) .rela.plt {
12// CHECK-NEXT: 0x202018 R_X86_64_JUMP_SLOT bar 0x012// CHECK-NEXT: 0x203018 R_X86_64_JUMP_SLOT bar 0x0
13// CHECK-NEXT: }13// CHECK-NEXT: }
14// CHECK-NEXT: ]14// CHECK-NEXT: ]
1515
deps/lld/test/ELF/dynamic-reloc.s+3-3
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dynamic-reloc.s -o %t3.o4// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/dynamic-reloc.s -o %t3.o
5// RUN: ld.lld -shared %t2.o -o %t2.so5// RUN: ld.lld -shared %t2.o -o %t2.so
6// RUN: ld.lld --hash-style=sysv %t.o %t3.o %t2.so -o %t6// RUN: ld.lld --hash-style=sysv %t.o %t3.o %t2.so -o %t
7// RUN: llvm-readobj -dynamic-table -r --expand-relocs -s %t | FileCheck %s7// RUN: llvm-readobj --dynamic-table -r --expand-relocs -S %t | FileCheck %s
88
9// CHECK: Index: 19// CHECK: Index: 1
10// CHECK-NEXT: Name: .dynsym10// CHECK-NEXT: Name: .dynsym
...@@ -18,7 +18,7 @@...@@ -18,7 +18,7 @@
18// CHECK-NEXT: Offset:18// CHECK-NEXT: Offset:
19// CHECK-NEXT: Size: [[RELASIZE:.*]]19// CHECK-NEXT: Size: [[RELASIZE:.*]]
20// CHECK-NEXT: Link: 120// CHECK-NEXT: Link: 1
21// CHECK-NEXT: Info: 721// CHECK-NEXT: Info: 8
22// CHECK-NEXT: AddressAlignment: 822// CHECK-NEXT: AddressAlignment: 8
23// CHECK-NEXT: EntrySize: 2423// CHECK-NEXT: EntrySize: 24
2424
...@@ -33,7 +33,7 @@...@@ -33,7 +33,7 @@
33// CHECK: Relocations [33// CHECK: Relocations [
34// CHECK-NEXT: Section ({{.*}}) .rela.plt {34// CHECK-NEXT: Section ({{.*}}) .rela.plt {
35// CHECK-NEXT: Relocation {35// CHECK-NEXT: Relocation {
36// CHECK-NEXT: Offset: 0x20201836// CHECK-NEXT: Offset: 0x203018
37// CHECK-NEXT: Type: R_X86_64_JUMP_SLOT37// CHECK-NEXT: Type: R_X86_64_JUMP_SLOT
38// CHECK-NEXT: Symbol: bar38// CHECK-NEXT: Symbol: bar
39// CHECK-NEXT: Addend: 0x039// CHECK-NEXT: Addend: 0x0
deps/lld/test/ELF/dynamic.s+2-2
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4## Check that _DYNAMIC symbol is created when creating dynamic output,4## Check that _DYNAMIC symbol is created when creating dynamic output,
5## and has hidden visibility and address equal to .dynamic section.5## and has hidden visibility and address equal to .dynamic section.
6# RUN: ld.lld -shared %t.o -o %t.so6# RUN: ld.lld -shared %t.o -o %t.so
7# RUN: llvm-readobj -sections -symbols %t.so | FileCheck %s7# RUN: llvm-readobj --sections --symbols %t.so | FileCheck %s
8# CHECK: Section {8# CHECK: Section {
9# CHECK: Index: 59# CHECK: Index: 5
10# CHECK: Name: .dynamic10# CHECK: Name: .dynamic
...@@ -35,7 +35,7 @@...@@ -35,7 +35,7 @@
35# CHECK-NEXT: }35# CHECK-NEXT: }
3636
37# RUN: ld.lld %t.o -o %t237# RUN: ld.lld %t.o -o %t2
38# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=NODYN %s38# RUN: llvm-readobj --sections --symbols %t2 | FileCheck -check-prefix=NODYN %s
39# NODYN: Symbols [39# NODYN: Symbols [
40# NODYN-NOT: Name: _DYNAMIC40# NODYN-NOT: Name: _DYNAMIC
41# NODYN: ]41# NODYN: ]
deps/lld/test/ELF/dynsym-no-rosegment.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -shared --no-rosegment -o %t %t.o3# RUN: ld.lld -shared --no-rosegment -o %t %t.o
4# RUN: llvm-readobj -dyn-symbols -s %t | FileCheck %s4# RUN: llvm-readobj --dyn-syms -S %t | FileCheck %s
55
6# CHECK: DynamicSymbols [6# CHECK: DynamicSymbols [
7# CHECK-NEXT: Symbol {7# CHECK-NEXT: Symbol {
deps/lld/test/ELF/dynsym-pie.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
3# RUN: ld.lld -pie %t -o %t.out3# RUN: ld.lld -pie %t -o %t.out
4# RUN: llvm-readobj -t -dyn-symbols %t.out | FileCheck %s4# RUN: llvm-readobj --symbols --dyn-syms %t.out | FileCheck %s
55
6# CHECK: Symbols [6# CHECK: Symbols [
7# CHECK: Symbol {7# CHECK: Symbol {
deps/lld/test/ELF/edata-etext.s+1-1
...@@ -12,7 +12,7 @@...@@ -12,7 +12,7 @@
12## 3) Address of _end is different from _edata because of 2.12## 3) Address of _end is different from _edata because of 2.
13## 4) Addresses of _edata == edata, _end == end and _etext == etext.13## 4) Addresses of _edata == edata, _end == end and _etext == etext.
14# CHECK: Sections:14# CHECK: Sections:
15# CHECK-NEXT: Idx Name Size Address Type15# CHECK-NEXT: Idx Name Size VMA Type
16# CHECK-NEXT: 0 00000000 000000000000000016# CHECK-NEXT: 0 00000000 0000000000000000
17# CHECK-NEXT: 1 .text 00000001 0000000000201000 TEXT17# CHECK-NEXT: 1 .text 00000001 0000000000201000 TEXT
18# CHECK-NEXT: 2 .data 00000002 0000000000202000 DATA18# CHECK-NEXT: 2 .data 00000002 0000000000202000 DATA
deps/lld/test/ELF/eh-align-cie.s+2-2
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9bar:9bar:
1010
11// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o11// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
12// RUN: llvm-readobj -s -section-data %t.o | FileCheck --check-prefix=OBJ %s12// RUN: llvm-readobj -S --section-data %t.o | FileCheck --check-prefix=OBJ %s
1313
14// Check the size of the CIE (0x18 + 4) an FDE (0x10 + 4)14// Check the size of the CIE (0x18 + 4) an FDE (0x10 + 4)
15// OBJ: Name: .eh_frame15// OBJ: Name: .eh_frame
...@@ -32,7 +32,7 @@ bar:...@@ -32,7 +32,7 @@ bar:
3232
3333
34// RUN: ld.lld --hash-style=sysv %t.o -o %t -shared34// RUN: ld.lld --hash-style=sysv %t.o -o %t -shared
35// RUN: llvm-readobj -s -section-data %t | FileCheck %s35// RUN: llvm-readobj -S --section-data %t | FileCheck %s
3636
37// Check that the size of the CIE was changed to (0x1C + 4) and the FDE one was37// Check that the size of the CIE was changed to (0x1C + 4) and the FDE one was
38// changed to (0x14 + 4)38// changed to (0x14 + 4)
deps/lld/test/ELF/eh-frame-begin-end.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=amd64-unknown-openbsd %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=amd64-unknown-openbsd %s -o %t.o
3// RUN: llvm-mc -filetype=obj -triple=amd64-unknown-openbsd %p/Inputs/eh-frame-end.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=amd64-unknown-openbsd %p/Inputs/eh-frame-end.s -o %t2.o
4// RUN: ld.lld %t.o %t2.o -o %t4// RUN: ld.lld %t.o %t2.o -o %t
5// RUN: llvm-readobj -sections %t | FileCheck %s5// RUN: llvm-readobj --sections %t | FileCheck %s
66
7// CHECK: Name: .eh_frame7// CHECK: Name: .eh_frame
8// CHECK-NEXT: Type: SHT_PROGBITS8// CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/eh-frame-gc.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
3# RUN: ld.lld -shared --gc-sections %t.o -o %t3# RUN: ld.lld -shared --gc-sections %t.o -o %t
4# RUN: llvm-readobj -s %t | FileCheck %s4# RUN: llvm-readobj -S %t | FileCheck %s
55
6## Check that section containing personality is6## Check that section containing personality is
7## not garbage collected.7## not garbage collected.
deps/lld/test/ELF/eh-frame-gc2.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
3// RUN: ld.lld --gc-sections %t.o -o %t3// RUN: ld.lld --gc-sections %t.o -o %t
4// RUN: llvm-readobj -s %t | FileCheck %s4// RUN: llvm-readobj -S %t | FileCheck %s
55
6// Test that the we don't gc the personality function.6// Test that the we don't gc the personality function.
7// CHECK: Name: .foobar7// CHECK: Name: .foobar
deps/lld/test/ELF/eh-frame-hdr-abs-fde.s+9-9
...@@ -1,23 +1,23 @@...@@ -1,23 +1,23 @@
1# REQUIRES: mips1# REQUIRES: x86
2# Check reading PC values of FDEs and writing lookup table in the .eh_frame_hdr2# Check reading PC values of FDEs and writing lookup table in the .eh_frame_hdr
3# if CIE augmentation string has 'L' token and PC values are encoded using3# if CIE augmentation string has 'L' token and PC values are encoded using
4# absolute (not relative) format.4# absolute (not relative) format.
55
6# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o6# RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux %s -o %t.o
7# RUN: ld.lld --eh-frame-hdr %t.o -o %t7# RUN: ld.lld --eh-frame-hdr %t.o -o %t
8# RUN: llvm-objdump -s -dwarf=frames %t | FileCheck %s8# RUN: llvm-objdump -s -dwarf=frames %t | FileCheck %s
99
10# CHECK: Contents of section .eh_frame_hdr:10# CHECK: Contents of section .eh_frame_hdr:
11# CHECK-NEXT: 10128 011b033b 00000010 00000001 0000fed811# CHECK-NEXT: 200190 011b033b 14000000 01000000 700e0000
12# ^-- 0x20000 - 0x1013812# ^-- 0x201000 - 0x200190
13# .text - .eh_frame_hdr13# .text - .eh_frame_hdr
14# CHECK-NEXT: 10138 0000002c14# CHECK-NEXT: 2001a0 30000000
15# CHECK: Contents of section .text:15# CHECK: Contents of section .text:
16# CHECK-NEXT: 20000 0000000016# CHECK-NEXT: 201000 90
1717
18# CHECK: Augmentation: "zLR"18# CHECK: Augmentation: "zLR"
19# CHECK: Augmentation data: 00 0B19# CHECK: Augmentation data: 00 1B
20# ^-- DW_EH_PE_udata4 | DW_EH_PE_signed20# ^-- DW_EH_PE_pcrel | DW_EH_PE_udata4 | DW_EH_PE_signed
2121
22 .text22 .text
23 .globl __start23 .globl __start
deps/lld/test/ELF/eh-frame-hdr-augmentation.s+2-2
...@@ -11,7 +11,7 @@...@@ -11,7 +11,7 @@
11// CHECK-NEXT: Code alignment factor: 111// CHECK-NEXT: Code alignment factor: 1
12// CHECK-NEXT: Data alignment factor: -812// CHECK-NEXT: Data alignment factor: -8
13// CHECK-NEXT: Return address column: 1613// CHECK-NEXT: Return address column: 16
14// CHECK-NEXT: Personality Address: 00000dad14// CHECK-NEXT: Personality Address: 0000000000000dad
15// CHECK-NEXT: Augmentation data:15// CHECK-NEXT: Augmentation data:
1616
17// CHECK: DW_CFA_def_cfa: reg7 +817// CHECK: DW_CFA_def_cfa: reg7 +8
...@@ -20,7 +20,7 @@...@@ -20,7 +20,7 @@
20// CHECK-NEXT: DW_CFA_nop:20// CHECK-NEXT: DW_CFA_nop:
2121
22// CHECK: 00000020 00000014 00000024 FDE cie=00000024 pc=00000d98...00000d9822// CHECK: 00000020 00000014 00000024 FDE cie=00000024 pc=00000d98...00000d98
23// CHECK-NEXT: LSDA Address: 00000d8f23// CHECK-NEXT: LSDA Address: 0000000000000d8f
24// CHECK-NEXT: DW_CFA_nop:24// CHECK-NEXT: DW_CFA_nop:
25// CHECK-NEXT: DW_CFA_nop:25// CHECK-NEXT: DW_CFA_nop:
26// CHECK-NEXT: DW_CFA_nop:26// CHECK-NEXT: DW_CFA_nop:
deps/lld/test/ELF/eh-frame-hdr-icf-fde.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t6# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
7# RUN: ld.lld %t -o %t2 --icf=all --eh-frame-hdr7# RUN: ld.lld %t -o %t2 --icf=all --eh-frame-hdr
8# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=OBJ8# RUN: llvm-readobj -r %t | FileCheck %s --check-prefix=OBJ
9# RUN: llvm-readobj -s -section-data %t2 | FileCheck %s9# RUN: llvm-readobj -S --section-data %t2 | FileCheck %s
1010
11# OBJ: Relocations [11# OBJ: Relocations [
12# OBJ-NEXT: Section {{.*}} .rela.eh_frame {12# OBJ-NEXT: Section {{.*}} .rela.eh_frame {
deps/lld/test/ELF/eh-frame-hdr-no-out2.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld --eh-frame-hdr %t.o -o %t3// RUN: ld.lld --eh-frame-hdr %t.o -o %t
4// RUN: llvm-readobj -s -program-headers %t | FileCheck %s --check-prefix=NOHDR4// RUN: llvm-readobj -S -l %t | FileCheck %s --check-prefix=NOHDR
55
6.section foo,"ax",@progbits6.section foo,"ax",@progbits
7 nop7 nop
deps/lld/test/ELF/eh-frame-hdr.s+17-12
...@@ -2,15 +2,15 @@...@@ -2,15 +2,15 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
33
4// RUN: ld.lld %t.o -o %t4// RUN: ld.lld %t.o -o %t
5// RUN: llvm-readobj -file-headers -s -section-data -program-headers -symbols %t \5// RUN: llvm-readobj --file-headers -S --section-data -l --symbols %t \
6// RUN: | FileCheck %s --check-prefix=NOHDR6// RUN: | FileCheck %s --check-prefix=NOHDR
77
8// RUN: ld.lld -eh-frame-hdr -no-eh-frame-hdr %t.o -o %t8// RUN: ld.lld -eh-frame-hdr -no-eh-frame-hdr %t.o -o %t
9// RUN: llvm-readobj -file-headers -s -section-data -program-headers -symbols %t \9// RUN: llvm-readobj --file-headers -S --section-data -l --symbols %t \
10// RUN: | FileCheck %s --check-prefix=NOHDR10// RUN: | FileCheck %s --check-prefix=NOHDR
1111
12// RUN: ld.lld --eh-frame-hdr %t.o -o %t12// RUN: ld.lld --eh-frame-hdr %t.o -o %t
13// RUN: llvm-readobj -file-headers -s -section-data -program-headers -symbols %t \13// RUN: llvm-readobj --file-headers -S --section-data -l --symbols %t \
14// RUN: | FileCheck %s --check-prefix=HDR14// RUN: | FileCheck %s --check-prefix=HDR
15// RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=HDRDISASM15// RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=HDRDISASM
1616
...@@ -38,15 +38,20 @@ _start:...@@ -38,15 +38,20 @@ _start:
38// NOHDR: ProgramHeaders [38// NOHDR: ProgramHeaders [
39// NOHDR-NOT: PT_GNU_EH_FRAME39// NOHDR-NOT: PT_GNU_EH_FRAME
4040
41//HDRDISASM: Disassembly of section foo:41// HDRDISASM: Disassembly of section foo:
42//HDRDISASM-NEXT: foo:42// HDRDISASM-EMPTY:
43//HDRDISASM-NEXT: 201000: 90 nop43// HDRDISASM-NEXT: foo:
44//HDRDISASM-NEXT: Disassembly of section bar:44// HDRDISASM-NEXT: 201000: 90 nop
45//HDRDISASM-NEXT: bar:45// HDRDISASM-EMPTY:
46//HDRDISASM-NEXT: 201001: 90 nop46// HDRDISASM-NEXT: Disassembly of section bar:
47//HDRDISASM-NEXT: Disassembly of section dah:47// HDRDISASM-EMPTY:
48//HDRDISASM-NEXT: dah:48// HDRDISASM-NEXT: bar:
49//HDRDISASM-NEXT: 201002: 90 nop49// HDRDISASM-NEXT: 201001: 90 nop
50// HDRDISASM-EMPTY:
51// HDRDISASM-NEXT: Disassembly of section dah:
52// HDRDISASM-EMPTY:
53// HDRDISASM-NEXT: dah:
54// HDRDISASM-NEXT: 201002: 90 nop
5055
51// HDR: Section {56// HDR: Section {
52// HDR: Index:57// HDR: Index:
deps/lld/test/ELF/eh-frame-marker.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3// RUN: ld.lld --eh-frame-hdr %t.o -o %t.so -shared3// RUN: ld.lld --eh-frame-hdr %t.o -o %t.so -shared
4// RUN: llvm-readobj -t -s %t.so | FileCheck %s4// RUN: llvm-readobj --symbols -S %t.so | FileCheck %s
5// We used to crash on this.5// We used to crash on this.
66
7// CHECK: Name: .eh_frame_hdr7// CHECK: Name: .eh_frame_hdr
deps/lld/test/ELF/eh-frame-merge.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld --hash-style=sysv %t.o %t.o -o %t -shared3// RUN: ld.lld --hash-style=sysv %t.o %t.o -o %t -shared
4// RUN: llvm-readobj -s -section-data %t | FileCheck %s4// RUN: llvm-readobj -S --section-data %t | FileCheck %s
55
6 .section foo,"ax",@progbits6 .section foo,"ax",@progbits
7 .cfi_startproc7 .cfi_startproc
deps/lld/test/ELF/eh-frame-negative-pcrel-sdata2.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o6# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
7# RUN: echo "SECTIONS { .text : { *(.text) } .eh_frame : { *(.eh_frame) } }" > %t.script7# RUN: echo "SECTIONS { .text : { *(.text) } .eh_frame : { *(.eh_frame) } }" > %t.script
8# RUN: ld.lld --eh-frame-hdr --script %t.script --section-start .text=0x1000 %t.o -o %t8# RUN: ld.lld --eh-frame-hdr --script %t.script --section-start .text=0x1000 %t.o -o %t
9# RUN: llvm-readobj -s -section-data %t | FileCheck %s9# RUN: llvm-readobj -S --section-data %t | FileCheck %s
1010
11# CHECK: Section {11# CHECK: Section {
12# CHECK: Index:12# CHECK: Index:
deps/lld/test/ELF/eh-frame-negative-pcrel-sdata4.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o6# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
7# RUN: echo "SECTIONS { .text : { *(.text) } .eh_frame : { *(.eh_frame) } }" > %t.script7# RUN: echo "SECTIONS { .text : { *(.text) } .eh_frame : { *(.eh_frame) } }" > %t.script
8# RUN: ld.lld --eh-frame-hdr --script %t.script --section-start .text=0x1000 %t.o -o %t8# RUN: ld.lld --eh-frame-hdr --script %t.script --section-start .text=0x1000 %t.o -o %t
9# RUN: llvm-readobj -s -section-data %t | FileCheck %s9# RUN: llvm-readobj -S --section-data %t | FileCheck %s
1010
11# CHECK: Section {11# CHECK: Section {
12# CHECK: Index:12# CHECK: Index:
deps/lld/test/ELF/eh-frame-negative-pcrel-sdata8.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o6# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
7# RUN: echo "SECTIONS { .text : { *(.text) } .eh_frame : { *(.eh_frame) } }" > %t.script7# RUN: echo "SECTIONS { .text : { *(.text) } .eh_frame : { *(.eh_frame) } }" > %t.script
8# RUN: ld.lld --eh-frame-hdr --script %t.script --section-start .text=0x1000 %t.o -o %t8# RUN: ld.lld --eh-frame-hdr --script %t.script --section-start .text=0x1000 %t.o -o %t
9# RUN: llvm-readobj -s -section-data %t | FileCheck %s9# RUN: llvm-readobj -S --section-data %t | FileCheck %s
1010
11# CHECK: Section {11# CHECK: Section {
12# CHECK: Index:12# CHECK: Index:
deps/lld/test/ELF/eh-frame-padding-no-rosegment.s+3-3
...@@ -12,7 +12,7 @@ bar:...@@ -12,7 +12,7 @@ bar:
12// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o12// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
1313
14// Check the size of the CIE (0x18 + 4) and FDE (0x10 + 4)14// Check the size of the CIE (0x18 + 4) and FDE (0x10 + 4)
15// RUN: llvm-readobj -s -section-data %t.o | FileCheck --check-prefix=OBJ %s15// RUN: llvm-readobj -S --section-data %t.o | FileCheck --check-prefix=OBJ %s
1616
17// OBJ: Name: .eh_frame17// OBJ: Name: .eh_frame
18// OBJ-NEXT: Type:18// OBJ-NEXT: Type:
...@@ -35,14 +35,14 @@ bar:...@@ -35,14 +35,14 @@ bar:
35// RUN: ld.lld --hash-style=sysv %t.o -no-rosegment -o %t -shared35// RUN: ld.lld --hash-style=sysv %t.o -no-rosegment -o %t -shared
3636
37// Check that .eh_frame is in the same segment as .text37// Check that .eh_frame is in the same segment as .text
38// RUN: llvm-readobj -l --elf-output-style=GNU %t | FileCheck --check-prefix=PHDR %s38// RUN: llvm-readelf -l %t | FileCheck --check-prefix=PHDR %s
3939
40// PHDR: Segment Sections40// PHDR: Segment Sections
41// PHDR: .eh_frame {{.*}}.text41// PHDR: .eh_frame {{.*}}.text
4242
43// Check that the CIE and FDE are padded with 0x00 and not 0xCC when the43// Check that the CIE and FDE are padded with 0x00 and not 0xCC when the
44// .eh_frame section is placed in the executable segment44// .eh_frame section is placed in the executable segment
45// RUN: llvm-readobj -s -section-data %t | FileCheck %s45// RUN: llvm-readobj -S --section-data %t | FileCheck %s
4646
47// CHECK: Name: .eh_frame47// CHECK: Name: .eh_frame
48// CHECK-NEXT: Type:48// CHECK-NEXT: Type:
deps/lld/test/ELF/eh-frame-type.test+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj %s -o %t.o1# RUN: yaml2obj %s -o %t.o
2# RUN: ld.lld %t.o -o %t -shared2# RUN: ld.lld %t.o -o %t -shared
3# RUN: llvm-readobj -s %t | FileCheck %s3# RUN: llvm-readobj -S %t | FileCheck %s
44
5# CHECK: Name: .eh_frame5# CHECK: Name: .eh_frame
6# CHECK-NEXT: Type: SHT_PROGBITS6# CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/eh-frame-value-format7.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
4# RUN: ld.lld --eh-frame-hdr --section-start .text=0x1000 %t.o -o %t4# RUN: ld.lld --eh-frame-hdr --section-start .text=0x1000 %t.o -o %t
5# RUN: llvm-readobj -s -section-data %t | FileCheck %s5# RUN: llvm-readobj -S --section-data %t | FileCheck %s
66
7## Check we are able to handle DW_EH_PE_udata2 encoding.7## Check we are able to handle DW_EH_PE_udata2 encoding.
88
deps/lld/test/ELF/eh-frame-value-format8.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
4# RUN: ld.lld --eh-frame-hdr --section-start .text=0x1000 %t.o -o %t4# RUN: ld.lld --eh-frame-hdr --section-start .text=0x1000 %t.o -o %t
5# RUN: llvm-readobj -s -section-data %t | FileCheck %s5# RUN: llvm-readobj -S --section-data %t | FileCheck %s
66
7## Check we are able to handle DW_EH_PE_absptr encoding.7## Check we are able to handle DW_EH_PE_absptr encoding.
88
deps/lld/test/ELF/ehdr_start.s+2-2
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: ld.lld %t.o -o %t4# RUN: ld.lld %t.o -o %t
5# RUN: llvm-readobj -symbols %t | FileCheck %s5# RUN: llvm-readobj --symbols %t | FileCheck %s
6# CHECK: Name: __ehdr_start (1)6# CHECK: Name: __ehdr_start (1)
7# CHECK-NEXT: Value: 0x2000007# CHECK-NEXT: Value: 0x200000
8# CHECK-NEXT: Size: 08# CHECK-NEXT: Size: 0
...@@ -30,7 +30,7 @@ _start:...@@ -30,7 +30,7 @@ _start:
30 .quad __executable_start30 .quad __executable_start
3131
32# RUN: ld.lld -r %t.o -o %t.r32# RUN: ld.lld -r %t.o -o %t.r
33# RUN: llvm-readobj -symbols %t.r | FileCheck %s --check-prefix=RELOCATABLE33# RUN: llvm-readobj --symbols %t.r | FileCheck %s --check-prefix=RELOCATABLE
3434
35# RELOCATABLE: Name: __ehdr_start (1)35# RELOCATABLE: Name: __ehdr_start (1)
36# RELOCATABLE-NEXT: Value: 0x036# RELOCATABLE-NEXT: Value: 0x0
deps/lld/test/ELF/ehframe-relocation.s+2-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// 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/ehframe-relocation.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/ehframe-relocation.s -o %t2.o
4// RUN: ld.lld %t.o %t2.o -o %t4// RUN: ld.lld %t.o %t2.o -o %t
5// RUN: llvm-readobj -s %t | FileCheck %s5// RUN: llvm-readobj -S %t | FileCheck %s
6// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s6// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
77
8// CHECK: Name: .eh_frame8// CHECK: Name: .eh_frame
...@@ -18,6 +18,7 @@...@@ -18,6 +18,7 @@
18// 0x200120 = 209744018// 0x200120 = 2097440
19// 0x200120 + 5 = 209744519// 0x200120 + 5 = 2097445
20// DISASM: Disassembly of section .text:20// DISASM: Disassembly of section .text:
21// DISASM-EMPTY:
21// DISASM-NEXT: _start:22// DISASM-NEXT: _start:
22// DISASM-NEXT: 201000: {{.*}} movq 2097440, %rax23// DISASM-NEXT: 201000: {{.*}} movq 2097440, %rax
23// DISASM-NEXT: 201008: {{.*}} movq 2097445, %rax24// DISASM-NEXT: 201008: {{.*}} movq 2097445, %rax
deps/lld/test/ELF/elf-header.s+2-2
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t13# RUN: ld.lld %t.o -o %t1
4# RUN: llvm-readobj -file-headers %t1 | FileCheck %s4# RUN: llvm-readobj --file-headers %t1 | FileCheck %s
55
6# RUN: ld.lld %t.o -no-rosegment -o %t26# RUN: ld.lld %t.o -no-rosegment -o %t2
7# RUN: llvm-readobj -file-headers %t2 | FileCheck %s7# RUN: llvm-readobj --file-headers %t2 | FileCheck %s
88
9# CHECK: ElfHeader {9# CHECK: ElfHeader {
10# CHECK-NEXT: Ident {10# CHECK-NEXT: Ident {
deps/lld/test/ELF/emit-relocs-merge.s+4-4
...@@ -5,12 +5,12 @@...@@ -5,12 +5,12 @@
55
6# CHECK: Relocations [6# CHECK: Relocations [
7# CHECK-NEXT: Section ({{.*}}) .rela.dyn {7# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
8# CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x08# CHECK-NEXT: 0x2000 R_X86_64_64 zed 0x0
9# CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x09# CHECK-NEXT: 0x2008 R_X86_64_64 zed 0x0
10# CHECK-NEXT: }10# CHECK-NEXT: }
11# CHECK-NEXT: Section ({{.*}}) .rela.data {11# CHECK-NEXT: Section ({{.*}}) .rela.data {
12# CHECK-NEXT: 0x1000 R_X86_64_64 zed 0x012# CHECK-NEXT: 0x2000 R_X86_64_64 zed 0x0
13# CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x013# CHECK-NEXT: 0x2008 R_X86_64_64 zed 0x0
14# CHECK-NEXT: }14# CHECK-NEXT: }
15# CHECK-NEXT: ]15# CHECK-NEXT: ]
1616
deps/lld/test/ELF/emit-relocs-mergeable-i386.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t12# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t1
3# RUN: ld.lld --emit-relocs %t1 -o %t23# RUN: ld.lld --emit-relocs %t1 -o %t2
4# RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s4# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s
55
6## Check lf we produce proper relocations when doing merging of SHF_MERGE sections.6## Check lf we produce proper relocations when doing merging of SHF_MERGE sections.
77
deps/lld/test/ELF/emit-relocs-mergeable.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t12# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
3# RUN: ld.lld --emit-relocs %t1 -o %t23# RUN: ld.lld --emit-relocs %t1 -o %t2
4# RUN: llvm-readobj -sections -section-data -r %t2 | FileCheck %s4# RUN: llvm-readobj --sections --section-data -r %t2 | FileCheck %s
55
6## Check if we produce proper relocations when doing merging of SHF_MERGE sections.6## Check if we produce proper relocations when doing merging of SHF_MERGE sections.
77
deps/lld/test/ELF/emit-relocs-mergeable2.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: ld.lld --emit-relocs %t.o -o %t.exe
4# RUN: llvm-readelf --relocations %t.exe | FileCheck %s
5
6# CHECK: 0000000000201004 000000010000000b R_X86_64_32S 0000000000200120 .Lfoo + 8
7
8.globl _start
9_start:
10 movq .Lfoo+8, %rax
11.section .rodata.cst16,"aM",@progbits,16
12.Lfoo:
13 .quad 0
14 .quad 0
deps/lld/test/ELF/emit-relocs-shared.s+2-2
...@@ -8,9 +8,9 @@...@@ -8,9 +8,9 @@
88
9# CHECK: Relocations [9# CHECK: Relocations [
10# CHECK-NEXT: Section {{.*}} .rela.dyn {10# CHECK-NEXT: Section {{.*}} .rela.dyn {
11# CHECK-NEXT: 0x1000 R_X86_64_64 foo 0x011# CHECK-NEXT: 0x2000 R_X86_64_64 foo 0x0
12# CHECK-NEXT: }12# CHECK-NEXT: }
13# CHECK-NEXT: Section {{.*}} .rela.data {13# CHECK-NEXT: Section {{.*}} .rela.data {
14# CHECK-NEXT: 0x1000 R_X86_64_64 foo 0x014# CHECK-NEXT: 0x2000 R_X86_64_64 foo 0x0
15# CHECK-NEXT: }15# CHECK-NEXT: }
16# CHECK-NEXT: ]16# CHECK-NEXT: ]
deps/lld/test/ELF/emit-relocs.s+3-3
...@@ -1,15 +1,15 @@...@@ -1,15 +1,15 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
3# RUN: ld.lld --emit-relocs %t1.o -o %t3# RUN: ld.lld --emit-relocs %t1.o -o %t
4# RUN: llvm-readobj -t -r -s %t | FileCheck %s4# RUN: llvm-readobj --symbols -r -S %t | FileCheck %s
55
6## Check single dash form.6## Check single dash form.
7# RUN: ld.lld -emit-relocs %t1.o -o %t17# RUN: ld.lld -emit-relocs %t1.o -o %t1
8# RUN: llvm-readobj -t -r -s %t1 | FileCheck %s8# RUN: llvm-readobj --symbols -r -S %t1 | FileCheck %s
99
10## Check alias.10## Check alias.
11# RUN: ld.lld -q %t1.o -o %t211# RUN: ld.lld -q %t1.o -o %t2
12# RUN: llvm-readobj -t -r -s %t2 | FileCheck %s12# RUN: llvm-readobj --symbols -r -S %t2 | FileCheck %s
1313
14# CHECK: Section {14# CHECK: Section {
15# CHECK: Index: 215# CHECK: Index: 2
deps/lld/test/ELF/empty-pack-dyn-relocs.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o3// 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 %t4// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.o -o %t
5// RUN: llvm-readobj -sections %t | FileCheck %s5// RUN: llvm-readobj --sections %t | FileCheck %s
66
7.global _start7.global _start
8_start:8_start:
deps/lld/test/ELF/empty-pt-load.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -l --elf-output-style=GNU %t.so | FileCheck %s4// RUN: llvm-readelf -l %t.so | FileCheck %s
55
6// Test that we don't create an empty executable PT_LOAD.6// Test that we don't create an empty executable PT_LOAD.
77
deps/lld/test/ELF/empty-ver.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: cd %t.dir3// RUN: cd %t.dir
4// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux4// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
5// RUN: ld.lld %t.o -o t.so -shared -version-script %p/Inputs/empty-ver.ver5// RUN: ld.lld %t.o -o t.so -shared -version-script %p/Inputs/empty-ver.ver
6// RUN: llvm-readobj -s -section-data -version-info t.so | FileCheck %s6// RUN: llvm-readobj -S --section-data --version-info t.so | FileCheck %s
77
8// CHECK: Name: .dynstr8// CHECK: Name: .dynstr
9// CHECK-NEXT: Type: SHT_STRTAB9// CHECK-NEXT: Type: SHT_STRTAB
deps/lld/test/ELF/empty-ver2.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: cd %t.dir3# RUN: cd %t.dir
4# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux4# RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
5# RUN: ld.lld %t.o -o t.so -shared -version-script %p/Inputs/empty-ver.ver5# RUN: ld.lld %t.o -o t.so -shared -version-script %p/Inputs/empty-ver.ver
6# RUN: llvm-readobj -version-info t.so | FileCheck %s6# RUN: llvm-readobj --version-info t.so | FileCheck %s
77
8# CHECK: Symbols [8# CHECK: Symbols [
9# CHECK-NEXT: Symbol {9# CHECK-NEXT: Symbol {
deps/lld/test/ELF/emulation-aarch64.s+6-6
...@@ -1,16 +1,16 @@...@@ -1,16 +1,16 @@
1# REQUIRES: aarch641# REQUIRES: aarch64
2# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %taarch642# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %taarch64
3# RUN: ld.lld -m aarch64linux %taarch64 -o %t2aarch643# RUN: ld.lld -m aarch64linux %taarch64 -o %t2aarch64
4# RUN: llvm-readobj -file-headers %t2aarch64 | FileCheck --check-prefix=AARCH64 %s4# RUN: llvm-readobj --file-headers %t2aarch64 | FileCheck --check-prefix=AARCH64 %s
5# RUN: ld.lld -m aarch64elf %taarch64 -o %t3aarch645# RUN: ld.lld -m aarch64elf %taarch64 -o %t3aarch64
6# RUN: llvm-readobj -file-headers %t3aarch64 | FileCheck --check-prefix=AARCH64 %s6# RUN: llvm-readobj --file-headers %t3aarch64 | FileCheck --check-prefix=AARCH64 %s
7# RUN: ld.lld -m aarch64_elf64_le_vec %taarch64 -o %t4aarch647# RUN: ld.lld -m aarch64_elf64_le_vec %taarch64 -o %t4aarch64
8# RUN: llvm-readobj -file-headers %t4aarch64 | FileCheck --check-prefix=AARCH64 %s8# RUN: llvm-readobj --file-headers %t4aarch64 | FileCheck --check-prefix=AARCH64 %s
9# RUN: ld.lld %taarch64 -o %t5aarch649# RUN: ld.lld %taarch64 -o %t5aarch64
10# RUN: llvm-readobj -file-headers %t5aarch64 | FileCheck --check-prefix=AARCH64 %s10# RUN: llvm-readobj --file-headers %t5aarch64 | FileCheck --check-prefix=AARCH64 %s
11# RUN: echo 'OUTPUT_FORMAT(elf64-littleaarch64)' > %t4aarch64.script11# RUN: echo 'OUTPUT_FORMAT(elf64-littleaarch64)' > %t4aarch64.script
12# RUN: ld.lld %t4aarch64.script %taarch64 -o %t4aarch6412# RUN: ld.lld %t4aarch64.script %taarch64 -o %t4aarch64
13# RUN: llvm-readobj -file-headers %t4aarch64 | FileCheck --check-prefix=AARCH64 %s13# RUN: llvm-readobj --file-headers %t4aarch64 | FileCheck --check-prefix=AARCH64 %s
14# AARCH64: ElfHeader {14# AARCH64: ElfHeader {
15# AARCH64-NEXT: Ident {15# AARCH64-NEXT: Ident {
16# AARCH64-NEXT: Magic: (7F 45 4C 46)16# AARCH64-NEXT: Magic: (7F 45 4C 46)
...@@ -33,7 +33,7 @@...@@ -33,7 +33,7 @@
33# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %taarch64fbsd33# RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-freebsd %s -o %taarch64fbsd
34# RUN: echo 'OUTPUT_FORMAT(elf64-aarch64-freebsd)' > %taarch64fbsd.script34# RUN: echo 'OUTPUT_FORMAT(elf64-aarch64-freebsd)' > %taarch64fbsd.script
35# RUN: ld.lld %taarch64fbsd.script %taarch64fbsd -o %t2aarch64fbsd35# RUN: ld.lld %taarch64fbsd.script %taarch64fbsd -o %t2aarch64fbsd
36# RUN: llvm-readobj -file-headers %t2aarch64fbsd | FileCheck --check-prefix=AARCH64-FBSD %s36# RUN: llvm-readobj --file-headers %t2aarch64fbsd | FileCheck --check-prefix=AARCH64-FBSD %s
37# AARCH64-FBSD: ElfHeader {37# AARCH64-FBSD: ElfHeader {
38# AARCH64-FBSD-NEXT: Ident {38# AARCH64-FBSD-NEXT: Ident {
39# AARCH64-FBSD-NEXT: Magic: (7F 45 4C 46)39# AARCH64-FBSD-NEXT: Magic: (7F 45 4C 46)
deps/lld/test/ELF/emulation-arm.s+4-4
...@@ -1,14 +1,14 @@...@@ -1,14 +1,14 @@
1# REQUIRES: arm1# REQUIRES: arm
2# RUN: llvm-mc -filetype=obj -triple=armv7-unknown-linux %s -o %tarm2# RUN: llvm-mc -filetype=obj -triple=armv7-unknown-linux %s -o %tarm
3# RUN: ld.lld -m armelf %tarm -o %t2arm3# RUN: ld.lld -m armelf %tarm -o %t2arm
4# RUN: llvm-readobj -file-headers %t2arm | FileCheck --check-prefix=ARM %s4# RUN: llvm-readobj --file-headers %t2arm | FileCheck --check-prefix=ARM %s
5# RUN: ld.lld -m armelf_linux_eabi %tarm -o %t3arm5# RUN: ld.lld -m armelf_linux_eabi %tarm -o %t3arm
6# RUN: llvm-readobj -file-headers %t3arm | FileCheck --check-prefix=ARM %s6# RUN: llvm-readobj --file-headers %t3arm | FileCheck --check-prefix=ARM %s
7# RUN: ld.lld %tarm -o %t4arm7# RUN: ld.lld %tarm -o %t4arm
8# RUN: llvm-readobj -file-headers %t4arm | FileCheck --check-prefix=ARM %s8# RUN: llvm-readobj --file-headers %t4arm | FileCheck --check-prefix=ARM %s
9# RUN: echo 'OUTPUT_FORMAT(elf32-littlearm)' > %t5arm.script9# RUN: echo 'OUTPUT_FORMAT(elf32-littlearm)' > %t5arm.script
10# RUN: ld.lld %t5arm.script %tarm -o %t5arm10# RUN: ld.lld %t5arm.script %tarm -o %t5arm
11# RUN: llvm-readobj -file-headers %t5arm | FileCheck --check-prefix=ARM %s11# RUN: llvm-readobj --file-headers %t5arm | FileCheck --check-prefix=ARM %s
12# ARM: ElfHeader {12# ARM: ElfHeader {
13# ARM-NEXT: Ident {13# ARM-NEXT: Ident {
14# ARM-NEXT: Magic: (7F 45 4C 46)14# ARM-NEXT: Magic: (7F 45 4C 46)
deps/lld/test/ELF/emulation-mips.s+21-21
...@@ -1,15 +1,15 @@...@@ -1,15 +1,15 @@
1# REQUIRES: mips1# REQUIRES: mips
2# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %tmips2# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %tmips
3# RUN: ld.lld -m elf32btsmip -e _start %tmips -o %t2mips3# RUN: ld.lld -m elf32btsmip -e _start %tmips -o %t2mips
4# RUN: llvm-readobj -file-headers %t2mips | FileCheck --check-prefix=MIPS %s4# RUN: llvm-readobj --file-headers %t2mips | FileCheck --check-prefix=MIPS %s
5# RUN: ld.lld %tmips -e _start -o %t3mips5# RUN: ld.lld %tmips -e _start -o %t3mips
6# RUN: llvm-readobj -file-headers %t3mips | FileCheck --check-prefix=MIPS %s6# RUN: llvm-readobj --file-headers %t3mips | FileCheck --check-prefix=MIPS %s
7# RUN: echo 'OUTPUT_FORMAT(elf32-tradbigmips)' > %tmips.script7# RUN: echo 'OUTPUT_FORMAT(elf32-tradbigmips)' > %tmips.script
8# RUN: ld.lld %tmips.script -e _start %tmips -o %t4mips8# RUN: ld.lld %tmips.script -e _start %tmips -o %t4mips
9# RUN: llvm-readobj -file-headers %t4mips | FileCheck --check-prefix=MIPS %s9# RUN: llvm-readobj --file-headers %t4mips | FileCheck --check-prefix=MIPS %s
10# RUN: echo 'OUTPUT_FORMAT(elf32-bigmips)' > %tmips2.script10# RUN: echo 'OUTPUT_FORMAT(elf32-bigmips)' > %tmips2.script
11# RUN: ld.lld %tmips2.script -e _start %tmips -o %t5mips11# RUN: ld.lld %tmips2.script -e _start %tmips -o %t5mips
12# RUN: llvm-readobj -file-headers %t5mips | FileCheck --check-prefix=MIPS %s12# RUN: llvm-readobj --file-headers %t5mips | FileCheck --check-prefix=MIPS %s
13# MIPS: ElfHeader {13# MIPS: ElfHeader {
14# MIPS-NEXT: Ident {14# MIPS-NEXT: Ident {
15# MIPS-NEXT: Magic: (7F 45 4C 46)15# MIPS-NEXT: Magic: (7F 45 4C 46)
...@@ -34,14 +34,14 @@...@@ -34,14 +34,14 @@
3434
35# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %tmipsel35# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %tmipsel
36# RUN: ld.lld -m elf32ltsmip -e _start %tmipsel -o %t2mipsel36# RUN: ld.lld -m elf32ltsmip -e _start %tmipsel -o %t2mipsel
37# RUN: llvm-readobj -file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s37# RUN: llvm-readobj --file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s
38# RUN: ld.lld -melf32ltsmip -e _start %tmipsel -o %t2mipsel38# RUN: ld.lld -melf32ltsmip -e _start %tmipsel -o %t2mipsel
39# RUN: llvm-readobj -file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s39# RUN: llvm-readobj --file-headers %t2mipsel | FileCheck --check-prefix=MIPSEL %s
40# RUN: ld.lld %tmipsel -e _start -o %t3mipsel40# RUN: ld.lld %tmipsel -e _start -o %t3mipsel
41# RUN: llvm-readobj -file-headers %t3mipsel | FileCheck --check-prefix=MIPSEL %s41# RUN: llvm-readobj --file-headers %t3mipsel | FileCheck --check-prefix=MIPSEL %s
42# RUN: echo 'OUTPUT_FORMAT(elf32-tradlittlemips)' > %tmipsel.script42# RUN: echo 'OUTPUT_FORMAT(elf32-tradlittlemips)' > %tmipsel.script
43# RUN: ld.lld %tmipsel.script -e _start %tmipsel -o %t4mipsel43# RUN: ld.lld %tmipsel.script -e _start %tmipsel -o %t4mipsel
44# RUN: llvm-readobj -file-headers %t4mipsel | FileCheck --check-prefix=MIPSEL %s44# RUN: llvm-readobj --file-headers %t4mipsel | FileCheck --check-prefix=MIPSEL %s
45# MIPSEL: ElfHeader {45# MIPSEL: ElfHeader {
46# MIPSEL-NEXT: Ident {46# MIPSEL-NEXT: Ident {
47# MIPSEL-NEXT: Magic: (7F 45 4C 46)47# MIPSEL-NEXT: Magic: (7F 45 4C 46)
...@@ -66,12 +66,12 @@...@@ -66,12 +66,12 @@
6666
67# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux-gnuabin32 %s -o %tmipsn3267# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux-gnuabin32 %s -o %tmipsn32
68# RUN: ld.lld -m elf32btsmipn32 -e _start %tmipsn32 -o %t2mipsn3268# RUN: ld.lld -m elf32btsmipn32 -e _start %tmipsn32 -o %t2mipsn32
69# RUN: llvm-readobj -file-headers %t2mipsn32 | FileCheck --check-prefix=MIPSN32 %s69# RUN: llvm-readobj --file-headers %t2mipsn32 | FileCheck --check-prefix=MIPSN32 %s
70# RUN: ld.lld %tmipsn32 -e _start -o %t3mipsn3270# RUN: ld.lld %tmipsn32 -e _start -o %t3mipsn32
71# RUN: llvm-readobj -file-headers %t3mipsn32 | FileCheck --check-prefix=MIPSN32 %s71# RUN: llvm-readobj --file-headers %t3mipsn32 | FileCheck --check-prefix=MIPSN32 %s
72# RUN: echo 'OUTPUT_FORMAT(elf32-ntradbigmips)' > %tmipsn32.script72# RUN: echo 'OUTPUT_FORMAT(elf32-ntradbigmips)' > %tmipsn32.script
73# RUN: ld.lld %tmipsn32.script -e _start %tmipsn32 -o %t4mipsn3273# RUN: ld.lld %tmipsn32.script -e _start %tmipsn32 -o %t4mipsn32
74# RUN: llvm-readobj -file-headers %t4mipsn32 | FileCheck --check-prefix=MIPSN32 %s74# RUN: llvm-readobj --file-headers %t4mipsn32 | FileCheck --check-prefix=MIPSN32 %s
75# MIPSN32: ElfHeader {75# MIPSN32: ElfHeader {
76# MIPSN32-NEXT: Ident {76# MIPSN32-NEXT: Ident {
77# MIPSN32-NEXT: Magic: (7F 45 4C 46)77# MIPSN32-NEXT: Magic: (7F 45 4C 46)
...@@ -96,14 +96,14 @@...@@ -96,14 +96,14 @@
9696
97# RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux-gnuabin32 %s -o %tmipsn32el97# RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux-gnuabin32 %s -o %tmipsn32el
98# RUN: ld.lld -m elf32ltsmipn32 -e _start %tmipsn32el -o %t2mipsn32el98# RUN: ld.lld -m elf32ltsmipn32 -e _start %tmipsn32el -o %t2mipsn32el
99# RUN: llvm-readobj -file-headers %t2mipsn32el | FileCheck --check-prefix=MIPSN32EL %s99# RUN: llvm-readobj --file-headers %t2mipsn32el | FileCheck --check-prefix=MIPSN32EL %s
100# RUN: ld.lld -melf32ltsmipn32 -e _start %tmipsn32el -o %t2mipsn32el100# RUN: ld.lld -melf32ltsmipn32 -e _start %tmipsn32el -o %t2mipsn32el
101# RUN: llvm-readobj -file-headers %t2mipsn32el | FileCheck --check-prefix=MIPSN32EL %s101# RUN: llvm-readobj --file-headers %t2mipsn32el | FileCheck --check-prefix=MIPSN32EL %s
102# RUN: ld.lld %tmipsn32el -e _start -o %t3mipsn32el102# RUN: ld.lld %tmipsn32el -e _start -o %t3mipsn32el
103# RUN: llvm-readobj -file-headers %t3mipsn32el | FileCheck --check-prefix=MIPSN32EL %s103# RUN: llvm-readobj --file-headers %t3mipsn32el | FileCheck --check-prefix=MIPSN32EL %s
104# RUN: echo 'OUTPUT_FORMAT(elf32-ntradlittlemips)' > %tmipsn32el.script104# RUN: echo 'OUTPUT_FORMAT(elf32-ntradlittlemips)' > %tmipsn32el.script
105# RUN: ld.lld %tmipsn32el.script -e _start %tmipsn32el -o %t4mipsn32el105# RUN: ld.lld %tmipsn32el.script -e _start %tmipsn32el -o %t4mipsn32el
106# RUN: llvm-readobj -file-headers %t4mipsn32el | FileCheck --check-prefix=MIPSN32EL %s106# RUN: llvm-readobj --file-headers %t4mipsn32el | FileCheck --check-prefix=MIPSN32EL %s
107# MIPSN32EL: ElfHeader {107# MIPSN32EL: ElfHeader {
108# MIPSN32EL-NEXT: Ident {108# MIPSN32EL-NEXT: Ident {
109# MIPSN32EL-NEXT: Magic: (7F 45 4C 46)109# MIPSN32EL-NEXT: Magic: (7F 45 4C 46)
...@@ -129,12 +129,12 @@...@@ -129,12 +129,12 @@
129# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -position-independent \129# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -position-independent \
130# RUN: %s -o %tmips64130# RUN: %s -o %tmips64
131# RUN: ld.lld -m elf64btsmip -e _start %tmips64 -o %t2mips64131# RUN: ld.lld -m elf64btsmip -e _start %tmips64 -o %t2mips64
132# RUN: llvm-readobj -file-headers %t2mips64 | FileCheck --check-prefix=MIPS64 %s132# RUN: llvm-readobj --file-headers %t2mips64 | FileCheck --check-prefix=MIPS64 %s
133# RUN: ld.lld %tmips64 -e _start -o %t3mips64133# RUN: ld.lld %tmips64 -e _start -o %t3mips64
134# RUN: llvm-readobj -file-headers %t3mips64 | FileCheck --check-prefix=MIPS64 %s134# RUN: llvm-readobj --file-headers %t3mips64 | FileCheck --check-prefix=MIPS64 %s
135# RUN: echo 'OUTPUT_FORMAT(elf64-tradbigmips)' > %tmips64.script135# RUN: echo 'OUTPUT_FORMAT(elf64-tradbigmips)' > %tmips64.script
136# RUN: ld.lld %tmips64.script -e _start %tmips64 -o %t4mips64136# RUN: ld.lld %tmips64.script -e _start %tmips64 -o %t4mips64
137# RUN: llvm-readobj -file-headers %t4mips64 | FileCheck --check-prefix=MIPS64 %s137# RUN: llvm-readobj --file-headers %t4mips64 | FileCheck --check-prefix=MIPS64 %s
138# MIPS64: ElfHeader {138# MIPS64: ElfHeader {
139# MIPS64-NEXT: Ident {139# MIPS64-NEXT: Ident {
140# MIPS64-NEXT: Magic: (7F 45 4C 46)140# MIPS64-NEXT: Magic: (7F 45 4C 46)
...@@ -160,12 +160,12 @@...@@ -160,12 +160,12 @@
160# RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux \160# RUN: llvm-mc -filetype=obj -triple=mips64el-unknown-linux \
161# RUN: -position-independent %s -o %tmips64el161# RUN: -position-independent %s -o %tmips64el
162# RUN: ld.lld -m elf64ltsmip -e _start %tmips64el -o %t2mips64el162# RUN: ld.lld -m elf64ltsmip -e _start %tmips64el -o %t2mips64el
163# RUN: llvm-readobj -file-headers %t2mips64el | FileCheck --check-prefix=MIPS64EL %s163# RUN: llvm-readobj --file-headers %t2mips64el | FileCheck --check-prefix=MIPS64EL %s
164# RUN: ld.lld %tmips64el -e _start -o %t3mips64el164# RUN: ld.lld %tmips64el -e _start -o %t3mips64el
165# RUN: llvm-readobj -file-headers %t3mips64el | FileCheck --check-prefix=MIPS64EL %s165# RUN: llvm-readobj --file-headers %t3mips64el | FileCheck --check-prefix=MIPS64EL %s
166# RUN: echo 'OUTPUT_FORMAT(elf64-tradlittlemips)' > %tmips64el.script166# RUN: echo 'OUTPUT_FORMAT(elf64-tradlittlemips)' > %tmips64el.script
167# RUN: ld.lld %tmips64el.script -e _start %tmips64el -o %t4mips64el167# RUN: ld.lld %tmips64el.script -e _start %tmips64el -o %t4mips64el
168# RUN: llvm-readobj -file-headers %t4mips64el | FileCheck --check-prefix=MIPS64EL %s168# RUN: llvm-readobj --file-headers %t4mips64el | FileCheck --check-prefix=MIPS64EL %s
169# MIPS64EL: ElfHeader {169# MIPS64EL: ElfHeader {
170# MIPS64EL-NEXT: Ident {170# MIPS64EL-NEXT: Ident {
171# MIPS64EL-NEXT: Magic: (7F 45 4C 46)171# MIPS64EL-NEXT: Magic: (7F 45 4C 46)
deps/lld/test/ELF/emulation-ppc.s+11-11
...@@ -1,12 +1,12 @@...@@ -1,12 +1,12 @@
1# REQUIRES: ppc1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %tppc642# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %tppc64
3# RUN: ld.lld -m elf64ppc %tppc64 -o %t2ppc643# RUN: ld.lld -m elf64ppc %tppc64 -o %t2ppc64
4# RUN: llvm-readobj -file-headers %t2ppc64 | FileCheck --check-prefix=PPC64 %s4# RUN: llvm-readobj --file-headers %t2ppc64 | FileCheck --check-prefix=PPC64 %s
5# RUN: ld.lld %tppc64 -o %t3ppc645# RUN: ld.lld %tppc64 -o %t3ppc64
6# RUN: llvm-readobj -file-headers %t3ppc64 | FileCheck --check-prefix=PPC64 %s6# RUN: llvm-readobj --file-headers %t3ppc64 | FileCheck --check-prefix=PPC64 %s
7# RUN: echo 'OUTPUT_FORMAT(elf64-powerpc)' > %tppc64.script7# RUN: echo 'OUTPUT_FORMAT(elf64-powerpc)' > %tppc64.script
8# RUN: ld.lld %tppc64.script %tppc64 -o %t4ppc648# RUN: ld.lld %tppc64.script %tppc64 -o %t4ppc64
9# RUN: llvm-readobj -file-headers %t4ppc64 | FileCheck --check-prefix=PPC64 %s9# RUN: llvm-readobj --file-headers %t4ppc64 | FileCheck --check-prefix=PPC64 %s
1010
11# PPC64: ElfHeader {11# PPC64: ElfHeader {
12# PPC64-NEXT: Ident {12# PPC64-NEXT: Ident {
...@@ -38,7 +38,7 @@...@@ -38,7 +38,7 @@
38# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-freebsd %s -o %tppc64fbsd38# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-freebsd %s -o %tppc64fbsd
39# RUN: echo 'OUTPUT_FORMAT(elf64-powerpc-freebsd)' > %tppc64fbsd.script39# RUN: echo 'OUTPUT_FORMAT(elf64-powerpc-freebsd)' > %tppc64fbsd.script
40# RUN: ld.lld %tppc64fbsd.script %tppc64fbsd -o %t2ppc64fbsd40# RUN: ld.lld %tppc64fbsd.script %tppc64fbsd -o %t2ppc64fbsd
41# RUN: llvm-readobj -file-headers %t2ppc64fbsd | FileCheck --check-prefix=PPC64-FBSD %s41# RUN: llvm-readobj --file-headers %t2ppc64fbsd | FileCheck --check-prefix=PPC64-FBSD %s
4242
43# PPC64-FBSD: ElfHeader {43# PPC64-FBSD: ElfHeader {
44# PPC64-FBSD-NEXT: Ident {44# PPC64-FBSD-NEXT: Ident {
...@@ -69,12 +69,12 @@...@@ -69,12 +69,12 @@
6969
70# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %tppc64le70# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %tppc64le
71# RUN: ld.lld -m elf64lppc %tppc64le -o %t2ppc64le71# RUN: ld.lld -m elf64lppc %tppc64le -o %t2ppc64le
72# RUN: llvm-readobj -file-headers %t2ppc64le | FileCheck --check-prefix=PPC64LE %s72# RUN: llvm-readobj --file-headers %t2ppc64le | FileCheck --check-prefix=PPC64LE %s
73# RUN: ld.lld %tppc64le -o %t3ppc64le73# RUN: ld.lld %tppc64le -o %t3ppc64le
74# RUN: llvm-readobj -file-headers %t3ppc64le | FileCheck --check-prefix=PPC64LE %s74# RUN: llvm-readobj --file-headers %t3ppc64le | FileCheck --check-prefix=PPC64LE %s
75# RUN: echo 'OUTPUT_FORMAT(elf64-powerpcle)' > %tppc64le.script75# RUN: echo 'OUTPUT_FORMAT(elf64-powerpcle)' > %tppc64le.script
76# RUN: ld.lld %tppc64le.script %tppc64le -o %t4ppc64le76# RUN: ld.lld %tppc64le.script %tppc64le -o %t4ppc64le
77# RUN: llvm-readobj -file-headers %t4ppc64le | FileCheck --check-prefix=PPC64LE %s77# RUN: llvm-readobj --file-headers %t4ppc64le | FileCheck --check-prefix=PPC64LE %s
7878
79# PPC64LE: ElfHeader {79# PPC64LE: ElfHeader {
80# PPC64LE-NEXT: Ident {80# PPC64LE-NEXT: Ident {
...@@ -105,14 +105,14 @@...@@ -105,14 +105,14 @@
105105
106# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-linux %s -o %tppc32106# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-linux %s -o %tppc32
107# RUN: ld.lld -m elf32ppc %tppc32 -o %t2ppc32107# RUN: ld.lld -m elf32ppc %tppc32 -o %t2ppc32
108# RUN: llvm-readobj -file-headers %t2ppc32 | FileCheck --check-prefix=PPC32 %s108# RUN: llvm-readobj --file-headers %t2ppc32 | FileCheck --check-prefix=PPC32 %s
109# RUN: ld.lld %tppc32 -o %t3ppc32109# RUN: ld.lld %tppc32 -o %t3ppc32
110# RUN: llvm-readobj -file-headers %t3ppc32 | FileCheck --check-prefix=PPC32 %s110# RUN: llvm-readobj --file-headers %t3ppc32 | FileCheck --check-prefix=PPC32 %s
111# RUN: echo 'OUTPUT_FORMAT(elf32-powerpc)' > %tppc32.script111# RUN: echo 'OUTPUT_FORMAT(elf32-powerpc)' > %tppc32.script
112# RUN: ld.lld %tppc32.script %tppc32 -o %t4ppc32112# RUN: ld.lld %tppc32.script %tppc32 -o %t4ppc32
113# RUN: llvm-readobj -file-headers %t4ppc32 | FileCheck --check-prefix=PPC32 %s113# RUN: llvm-readobj --file-headers %t4ppc32 | FileCheck --check-prefix=PPC32 %s
114# RUN: ld.lld -m elf32ppclinux %tppc32 -o %t5ppc32114# RUN: ld.lld -m elf32ppclinux %tppc32 -o %t5ppc32
115# RUN: llvm-readobj -file-headers %t5ppc32 | FileCheck --check-prefix=PPC32 %s115# RUN: llvm-readobj --file-headers %t5ppc32 | FileCheck --check-prefix=PPC32 %s
116116
117# PPC32: ElfHeader {117# PPC32: ElfHeader {
118# PPC32-NEXT: Ident {118# PPC32-NEXT: Ident {
deps/lld/test/ELF/emulation-riscv.s created+74
...@@ -0,0 +1,74 @@
1# REQUIRES: riscv
2
3# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.o
4# RUN: ld.lld %t.o -o %t
5# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=RV32 %s
6# RUN: ld.lld -m elf32lriscv %t.o -o %t
7# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=RV32 %s
8# RUN: echo 'OUTPUT_FORMAT(elf32-littleriscv)' > %t.script
9# RUN: ld.lld %t.script %t.o -o %t
10# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=RV32 %s
11
12# RV32: ElfHeader {
13# RV32-NEXT: Ident {
14# RV32-NEXT: Magic: (7F 45 4C 46)
15# RV32-NEXT: Class: 32-bit (0x1)
16# RV32-NEXT: DataEncoding: LittleEndian (0x1)
17# RV32-NEXT: FileVersion: 1
18# RV32-NEXT: OS/ABI: SystemV (0x0)
19# RV32-NEXT: ABIVersion: 0
20# RV32-NEXT: Unused: (00 00 00 00 00 00 00)
21# RV32-NEXT: }
22# RV32-NEXT: Type: Executable (0x2)
23# RV32-NEXT: Machine: EM_RISCV (0xF3)
24# RV32-NEXT: Version: 1
25# RV32-NEXT: Entry:
26# RV32-NEXT: ProgramHeaderOffset: 0x34
27# RV32-NEXT: SectionHeaderOffset:
28# RV32-NEXT: Flags [ (0x0)
29# RV32-NEXT: ]
30# RV32-NEXT: HeaderSize: 52
31# RV32-NEXT: ProgramHeaderEntrySize: 32
32# RV32-NEXT: ProgramHeaderCount:
33# RV32-NEXT: SectionHeaderEntrySize: 40
34# RV32-NEXT: SectionHeaderCount:
35# RV32-NEXT: StringTableSectionIndex:
36# RV32-NEXT: }
37
38# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o
39# RUN: ld.lld %t.o -o %t
40# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=RV64 %s
41# RUN: ld.lld -m elf64lriscv %t.o -o %t
42# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=RV64 %s
43# RUN: echo 'OUTPUT_FORMAT(elf64-littleriscv)' > %t.script
44# RUN: ld.lld %t.script %t.o -o %t
45# RUN: llvm-readobj --file-headers %t | FileCheck --check-prefix=RV64 %s
46
47# RV64: ElfHeader {
48# RV64-NEXT: Ident {
49# RV64-NEXT: Magic: (7F 45 4C 46)
50# RV64-NEXT: Class: 64-bit (0x2)
51# RV64-NEXT: DataEncoding: LittleEndian (0x1)
52# RV64-NEXT: FileVersion: 1
53# RV64-NEXT: OS/ABI: SystemV (0x0)
54# RV64-NEXT: ABIVersion: 0
55# RV64-NEXT: Unused: (00 00 00 00 00 00 00)
56# RV64-NEXT: }
57# RV64-NEXT: Type: Executable (0x2)
58# RV64-NEXT: Machine: EM_RISCV (0xF3)
59# RV64-NEXT: Version: 1
60# RV64-NEXT: Entry:
61# RV64-NEXT: ProgramHeaderOffset: 0x40
62# RV64-NEXT: SectionHeaderOffset:
63# RV64-NEXT: Flags [ (0x0)
64# RV64-NEXT: ]
65# RV64-NEXT: HeaderSize: 64
66# RV64-NEXT: ProgramHeaderEntrySize: 56
67# RV64-NEXT: ProgramHeaderCount:
68# RV64-NEXT: SectionHeaderEntrySize: 64
69# RV64-NEXT: SectionHeaderCount:
70# RV64-NEXT: StringTableSectionIndex:
71# RV64-NEXT: }
72
73.globl _start
74_start:
deps/lld/test/ELF/emulation-x86.s+19-19
...@@ -1,15 +1,15 @@...@@ -1,15 +1,15 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %tx642# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-freebsd %s -o %tx64
3# RUN: ld.lld -m elf_amd64_fbsd %tx64 -o %t2x643# RUN: ld.lld -m elf_amd64_fbsd %tx64 -o %t2x64
4# RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=AMD64 %s4# RUN: llvm-readobj --file-headers %t2x64 | FileCheck --check-prefix=AMD64 %s
5# RUN: ld.lld %tx64 -o %t3x645# RUN: ld.lld %tx64 -o %t3x64
6# RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=AMD64 %s6# 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.sysv7# 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.freebsd8# RUN: ld.lld -m elf_amd64_fbsd %t.sysv -o %t.freebsd
9# RUN: llvm-readobj -file-headers %t.freebsd | FileCheck --check-prefix=AMD64 %s9# RUN: llvm-readobj --file-headers %t.freebsd | FileCheck --check-prefix=AMD64 %s
10# RUN: echo 'OUTPUT_FORMAT(elf64-x86-64-freebsd)' > %t4x64.script10# RUN: echo 'OUTPUT_FORMAT(elf64-x86-64-freebsd)' > %t4x64.script
11# RUN: ld.lld %t4x64.script %tx64 -o %t4x6411# RUN: ld.lld %t4x64.script %tx64 -o %t4x64
12# RUN: llvm-readobj -file-headers %t4x64 | FileCheck --check-prefix=AMD64 %s12# RUN: llvm-readobj --file-headers %t4x64 | FileCheck --check-prefix=AMD64 %s
13# AMD64: ElfHeader {13# AMD64: ElfHeader {
14# AMD64-NEXT: Ident {14# AMD64-NEXT: Ident {
15# AMD64-NEXT: Magic: (7F 45 4C 46)15# AMD64-NEXT: Magic: (7F 45 4C 46)
...@@ -38,13 +38,13 @@...@@ -38,13 +38,13 @@
3838
39# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tx6439# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %tx64
40# RUN: ld.lld -m elf_x86_64 %tx64 -o %t2x6440# RUN: ld.lld -m elf_x86_64 %tx64 -o %t2x64
41# RUN: llvm-readobj -file-headers %t2x64 | FileCheck --check-prefix=X86-64 %s41# RUN: llvm-readobj --file-headers %t2x64 | FileCheck --check-prefix=X86-64 %s
42# RUN: ld.lld %tx64 -o %t3x6442# RUN: ld.lld %tx64 -o %t3x64
43# RUN: llvm-readobj -file-headers %t3x64 | FileCheck --check-prefix=X86-64 %s43# RUN: llvm-readobj --file-headers %t3x64 | FileCheck --check-prefix=X86-64 %s
44# RUN: echo 'OUTPUT_FORMAT(elf64-x86-64)' > %t4x64.script44# RUN: echo 'OUTPUT_FORMAT(elf64-x86-64)' > %t4x64.script
45# RUN: ld.lld %t4x64.script %tx64 -o %t4x6445# RUN: ld.lld %t4x64.script %tx64 -o %t4x64
46# RUN: ld.lld %tx64 -o %t4x64 %t4x64.script46# RUN: ld.lld %tx64 -o %t4x64 %t4x64.script
47# RUN: llvm-readobj -file-headers %t4x64 | FileCheck --check-prefix=X86-64 %s47# RUN: llvm-readobj --file-headers %t4x64 | FileCheck --check-prefix=X86-64 %s
48# X86-64: ElfHeader {48# X86-64: ElfHeader {
49# X86-64-NEXT: Ident {49# X86-64-NEXT: Ident {
50# X86-64-NEXT: Magic: (7F 45 4C 46)50# X86-64-NEXT: Magic: (7F 45 4C 46)
...@@ -73,12 +73,12 @@...@@ -73,12 +73,12 @@
7373
74# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnux32 %s -o %tx3274# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnux32 %s -o %tx32
75# RUN: ld.lld -m elf32_x86_64 %tx32 -o %t2x3275# RUN: ld.lld -m elf32_x86_64 %tx32 -o %t2x32
76# RUN: llvm-readobj -file-headers %t2x32 | FileCheck --check-prefix=X32 %s76# RUN: llvm-readobj --file-headers %t2x32 | FileCheck --check-prefix=X32 %s
77# RUN: ld.lld %tx32 -o %t3x3277# RUN: ld.lld %tx32 -o %t3x32
78# RUN: llvm-readobj -file-headers %t3x32 | FileCheck --check-prefix=X32 %s78# RUN: llvm-readobj --file-headers %t3x32 | FileCheck --check-prefix=X32 %s
79# RUN: echo 'OUTPUT_FORMAT(elf32-x86-64)' > %t4x32.script79# RUN: echo 'OUTPUT_FORMAT(elf32-x86-64)' > %t4x32.script
80# RUN: ld.lld %t4x32.script %tx32 -o %t4x3280# RUN: ld.lld %t4x32.script %tx32 -o %t4x32
81# RUN: llvm-readobj -file-headers %t4x32 | FileCheck --check-prefix=X32 %s81# RUN: llvm-readobj --file-headers %t4x32 | FileCheck --check-prefix=X32 %s
82# X32: ElfHeader {82# X32: ElfHeader {
83# X32-NEXT: Ident {83# X32-NEXT: Ident {
84# X32-NEXT: Magic: (7F 45 4C 46)84# X32-NEXT: Magic: (7F 45 4C 46)
...@@ -107,12 +107,12 @@...@@ -107,12 +107,12 @@
107107
108# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tx86108# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %tx86
109# RUN: ld.lld -m elf_i386 %tx86 -o %t2x86109# RUN: ld.lld -m elf_i386 %tx86 -o %t2x86
110# RUN: llvm-readobj -file-headers %t2x86 | FileCheck --check-prefix=X86 %s110# RUN: llvm-readobj --file-headers %t2x86 | FileCheck --check-prefix=X86 %s
111# RUN: ld.lld %tx86 -o %t3x86111# RUN: ld.lld %tx86 -o %t3x86
112# RUN: llvm-readobj -file-headers %t3x86 | FileCheck --check-prefix=X86 %s112# RUN: llvm-readobj --file-headers %t3x86 | FileCheck --check-prefix=X86 %s
113# RUN: echo 'OUTPUT_FORMAT(elf32-i386)' > %t4x86.script113# RUN: echo 'OUTPUT_FORMAT(elf32-i386)' > %t4x86.script
114# RUN: ld.lld %t4x86.script %tx86 -o %t4x86114# RUN: ld.lld %t4x86.script %tx86 -o %t4x86
115# RUN: llvm-readobj -file-headers %t4x86 | FileCheck --check-prefix=X86 %s115# RUN: llvm-readobj --file-headers %t4x86 | FileCheck --check-prefix=X86 %s
116# X86: ElfHeader {116# X86: ElfHeader {
117# X86-NEXT: Ident {117# X86-NEXT: Ident {
118# X86-NEXT: Magic: (7F 45 4C 46)118# X86-NEXT: Magic: (7F 45 4C 46)
...@@ -141,12 +141,12 @@...@@ -141,12 +141,12 @@
141141
142# RUN: llvm-mc -filetype=obj -triple=i686-unknown-freebsd %s -o %tx86fbsd142# RUN: llvm-mc -filetype=obj -triple=i686-unknown-freebsd %s -o %tx86fbsd
143# RUN: ld.lld -m elf_i386_fbsd %tx86fbsd -o %t2x86fbsd143# RUN: ld.lld -m elf_i386_fbsd %tx86fbsd -o %t2x86fbsd
144# RUN: llvm-readobj -file-headers %t2x86fbsd | FileCheck --check-prefix=X86FBSD %s144# RUN: llvm-readobj --file-headers %t2x86fbsd | FileCheck --check-prefix=X86FBSD %s
145# RUN: ld.lld %tx86fbsd -o %t3x86fbsd145# RUN: ld.lld %tx86fbsd -o %t3x86fbsd
146# RUN: llvm-readobj -file-headers %t3x86fbsd | FileCheck --check-prefix=X86FBSD %s146# RUN: llvm-readobj --file-headers %t3x86fbsd | FileCheck --check-prefix=X86FBSD %s
147# RUN: echo 'OUTPUT_FORMAT(elf32-i386-freebsd)' > %t4x86fbsd.script147# RUN: echo 'OUTPUT_FORMAT(elf32-i386-freebsd)' > %t4x86fbsd.script
148# RUN: ld.lld %t4x86fbsd.script %tx86fbsd -o %t4x86fbsd148# RUN: ld.lld %t4x86fbsd.script %tx86fbsd -o %t4x86fbsd
149# RUN: llvm-readobj -file-headers %t4x86fbsd | FileCheck --check-prefix=X86FBSD %s149# RUN: llvm-readobj --file-headers %t4x86fbsd | FileCheck --check-prefix=X86FBSD %s
150# X86FBSD: ElfHeader {150# X86FBSD: ElfHeader {
151# X86FBSD-NEXT: Ident {151# X86FBSD-NEXT: Ident {
152# X86FBSD-NEXT: Magic: (7F 45 4C 46)152# X86FBSD-NEXT: Magic: (7F 45 4C 46)
...@@ -175,12 +175,12 @@...@@ -175,12 +175,12 @@
175175
176# RUN: llvm-mc -filetype=obj -triple=i586-intel-elfiamcu %s -o %tiamcu176# RUN: llvm-mc -filetype=obj -triple=i586-intel-elfiamcu %s -o %tiamcu
177# RUN: ld.lld -m elf_iamcu %tiamcu -o %t2iamcu177# RUN: ld.lld -m elf_iamcu %tiamcu -o %t2iamcu
178# RUN: llvm-readobj -file-headers %t2iamcu | FileCheck --check-prefix=IAMCU %s178# RUN: llvm-readobj --file-headers %t2iamcu | FileCheck --check-prefix=IAMCU %s
179# RUN: ld.lld %tiamcu -o %t3iamcu179# RUN: ld.lld %tiamcu -o %t3iamcu
180# RUN: llvm-readobj -file-headers %t3iamcu | FileCheck --check-prefix=IAMCU %s180# RUN: llvm-readobj --file-headers %t3iamcu | FileCheck --check-prefix=IAMCU %s
181# RUN: echo 'OUTPUT_FORMAT(elf32-iamcu)' > %t4iamcu.script181# RUN: echo 'OUTPUT_FORMAT(elf32-iamcu)' > %t4iamcu.script
182# RUN: ld.lld %t4iamcu.script %tiamcu -o %t4iamcu182# RUN: ld.lld %t4iamcu.script %tiamcu -o %t4iamcu
183# RUN: llvm-readobj -file-headers %t4iamcu | FileCheck --check-prefix=IAMCU %s183# RUN: llvm-readobj --file-headers %t4iamcu | FileCheck --check-prefix=IAMCU %s
184# IAMCU: ElfHeader {184# IAMCU: ElfHeader {
185# IAMCU-NEXT: Ident {185# IAMCU-NEXT: Ident {
186# IAMCU-NEXT: Magic: (7F 45 4C 46)186# IAMCU-NEXT: Magic: (7F 45 4C 46)
deps/lld/test/ELF/end-update.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
5// RUN: ld.lld %t.o -o %t5// RUN: ld.lld %t.o -o %t
6// RUN: llvm-readobj -sections -symbols %t | FileCheck %s6// RUN: llvm-readobj --sections --symbols %t | FileCheck %s
77
8// CHECK: Sections [8// CHECK: Sections [
9// CHECK: Name: .bss9// CHECK: Name: .bss
deps/lld/test/ELF/end.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6// By default, the .bss section is the latest section of the data segment.6// By default, the .bss section is the latest section of the data segment.
7// RUN: ld.lld %t.o -o %t7// RUN: ld.lld %t.o -o %t
8// RUN: llvm-readobj -sections -symbols %t | FileCheck %s --check-prefix=DEFAULT8// RUN: llvm-readobj --sections --symbols %t | FileCheck %s --check-prefix=DEFAULT
99
10// DEFAULT: Sections [10// DEFAULT: Sections [
11// DEFAULT: Name: .bss11// DEFAULT: Name: .bss
deps/lld/test/ELF/entry.s+7-7
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t12# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
33
4# RUN: ld.lld -e foobar %t1 -o %t2 2>&1 | FileCheck -check-prefix=WARN1 %s4# RUN: ld.lld -e foobar %t1 -o %t2 2>&1 | FileCheck -check-prefix=WARN1 %s
5# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=TEXT %s5# RUN: llvm-readobj --file-headers %t2 | FileCheck -check-prefix=TEXT %s
66
7# WARN1: warning: cannot find entry symbol foobar; defaulting to 0x2010007# WARN1: warning: cannot find entry symbol foobar; defaulting to 0x201000
8# TEXT: Entry: 0x2010008# TEXT: Entry: 0x201000
...@@ -19,7 +19,7 @@...@@ -19,7 +19,7 @@
19# RUN: echo .data > %t.s19# RUN: echo .data > %t.s
20# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -n %t.s -o %t320# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -n %t.s -o %t3
21# RUN: ld.lld %t3 -o %t4 2>&1 | FileCheck -check-prefix=WARN4 %s21# RUN: ld.lld %t3 -o %t4 2>&1 | FileCheck -check-prefix=WARN4 %s
22# RUN: llvm-readobj -file-headers %t4 | FileCheck -check-prefix=NOENTRY %s22# RUN: llvm-readobj --file-headers %t4 | FileCheck -check-prefix=NOENTRY %s
2323
24# WARN4: cannot find entry symbol _start; not setting start address24# WARN4: cannot find entry symbol _start; not setting start address
25# NOENTRY: Entry: 0x025# NOENTRY: Entry: 0x0
...@@ -28,23 +28,23 @@...@@ -28,23 +28,23 @@
28# WARN5-NOT: warning: cannot find entry symbol28# WARN5-NOT: warning: cannot find entry symbol
2929
30# RUN: ld.lld %t1 -o %t2 -e entry30# RUN: ld.lld %t1 -o %t2 -e entry
31# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=SYM %s31# RUN: llvm-readobj --file-headers %t2 | FileCheck -check-prefix=SYM %s
32# SYM: Entry: 0x20100832# SYM: Entry: 0x201008
3333
34# RUN: ld.lld %t1 --fatal-warnings -shared -o %t2 -e entry34# RUN: ld.lld %t1 --fatal-warnings -shared -o %t2 -e entry
35# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=DSO %s35# RUN: llvm-readobj --file-headers %t2 | FileCheck -check-prefix=DSO %s
36# DSO: Entry: 0x100836# DSO: Entry: 0x1008
3737
38# RUN: ld.lld %t1 -o %t2 --entry=409638# RUN: ld.lld %t1 -o %t2 --entry=4096
39# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=DEC %s39# RUN: llvm-readobj --file-headers %t2 | FileCheck -check-prefix=DEC %s
40# DEC: Entry: 0x100040# DEC: Entry: 0x1000
4141
42# RUN: ld.lld %t1 -o %t2 --entry 0xcafe42# RUN: ld.lld %t1 -o %t2 --entry 0xcafe
43# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=HEX %s43# RUN: llvm-readobj --file-headers %t2 | FileCheck -check-prefix=HEX %s
44# HEX: Entry: 0xCAFE44# HEX: Entry: 0xCAFE
4545
46# RUN: ld.lld %t1 -o %t2 -e 077746# RUN: ld.lld %t1 -o %t2 -e 0777
47# RUN: llvm-readobj -file-headers %t2 | FileCheck -check-prefix=OCT %s47# RUN: llvm-readobj --file-headers %t2 | FileCheck -check-prefix=OCT %s
48# OCT: Entry: 0x1FF48# OCT: Entry: 0x1FF
4949
50.globl entry50.globl entry
deps/lld/test/ELF/exclude-discarded-error.s created+15
...@@ -0,0 +1,15 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s
4
5# CHECK: error: relocation refers to a symbol in a discarded section: foo
6# CHECK-NEXT: >>> defined in {{.*}}.o
7# CHECK-NEXT: >>> referenced by {{.*}}.o:(.text+0x1)
8
9.globl _start
10_start:
11 jmp foo
12
13.section .foo,"ae"
14.globl foo
15foo:
deps/lld/test/ELF/exclude-discarded-error2.s created+14
...@@ -0,0 +1,14 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: echo '.section .foo,"ae"; .weak foo; foo:' | \
4# RUN: llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o
5# RUN: not ld.lld %t.o %t1.o -o /dev/null 2>&1 | FileCheck %s
6
7# Because foo defined in %t1.o is weak, it does not override global undefined
8# in %t.o
9# CHECK-NOT: discarded section
10# CHECK: undefined symbol: foo
11
12.globl _start
13_start:
14 jmp foo
deps/lld/test/ELF/exclude-libs.s+8-8
...@@ -9,28 +9,28 @@...@@ -9,28 +9,28 @@
9// RUN: llvm-ar rcs %t.dir/exc.a %t2.o %t3.o9// RUN: llvm-ar rcs %t.dir/exc.a %t2.o %t3.o
1010
11// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe11// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe
12// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=DEFAULT %s12// RUN: llvm-readobj --dyn-syms %t.exe | FileCheck --check-prefix=DEFAULT %s
1313
14// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=foo,bar14// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=foo,bar
15// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=DEFAULT %s15// RUN: llvm-readobj --dyn-syms %t.exe | FileCheck --check-prefix=DEFAULT %s
1616
17// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo,bar,exc.a17// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo,bar,exc.a
18// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s18// RUN: llvm-readobj --dyn-syms %t.exe | FileCheck --check-prefix=EXCLUDE %s
1919
20// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo:bar:exc.a20// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo:bar:exc.a
21// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s21// RUN: llvm-readobj --dyn-syms %t.exe | FileCheck --check-prefix=EXCLUDE %s
2222
23// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL23// RUN: ld.lld -shared %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL
24// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s24// RUN: llvm-readobj --dyn-syms %t.exe | FileCheck --check-prefix=EXCLUDE %s
2525
26// RUN: ld.lld -shared %t.o %t2.o %t3.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL26// RUN: ld.lld -shared %t.o %t2.o %t3.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL
27// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=DEFAULT %s27// RUN: llvm-readobj --dyn-syms %t.exe | FileCheck --check-prefix=DEFAULT %s
2828
29// RUN: ld.lld -shared --whole-archive %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo,bar,exc.a29// RUN: ld.lld -shared --whole-archive %t.o %t.dir/exc.a -o %t.exe --exclude-libs foo,bar,exc.a
30// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s30// RUN: llvm-readobj --dyn-syms %t.exe | FileCheck --check-prefix=EXCLUDE %s
3131
32// RUN: ld.lld -shared --whole-archive %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL32// RUN: ld.lld -shared --whole-archive %t.o %t.dir/exc.a -o %t.exe --exclude-libs=ALL
33// RUN: llvm-readobj -dyn-symbols %t.exe | FileCheck --check-prefix=EXCLUDE %s33// RUN: llvm-readobj --dyn-syms %t.exe | FileCheck --check-prefix=EXCLUDE %s
3434
35// DEFAULT: Name: fn35// DEFAULT: Name: fn
36// DEFAULT: Name: fn236// DEFAULT: Name: fn2
deps/lld/test/ELF/executable-undefined-ignoreall.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6# CHECK: Relocations [6# CHECK: Relocations [
7# CHECK-NEXT: Section ({{.*}}) .rela.plt {7# CHECK-NEXT: Section ({{.*}}) .rela.plt {
8# CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT foo 0x08# CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT foo 0x0
9# CHECK-NEXT: }9# CHECK-NEXT: }
10# CHECK-NEXT: ]10# CHECK-NEXT: ]
1111
deps/lld/test/ELF/executable-undefined-protected-ignoreall.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3# RUN: not ld.lld %t -o /dev/null --unresolved-symbols=ignore-all -pie 2>&1 | FileCheck %s3# RUN: not ld.lld %t -o /dev/null --unresolved-symbols=ignore-all -pie 2>&1 | FileCheck %s
4# CHECK: error: undefined symbol: foo4# CHECK: error: undefined protected symbol: foo
55
6.protected foo6.protected foo
7_start:7_start:
deps/lld/test/ELF/fill-trap-ppc.s+2-2
...@@ -2,12 +2,12 @@...@@ -2,12 +2,12 @@
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-linux %s -o %t.o
4# RUN: ld.lld %t.o -o %t.ppc64le4# RUN: ld.lld %t.o -o %t.ppc64le
5# RUN: llvm-readobj -program-headers %t.ppc64le | FileCheck %s5# RUN: llvm-readobj -l %t.ppc64le | FileCheck %s
6# RUN: od -Ax -t x1 -N16 -j0x10ff0 %t.ppc64le | FileCheck %s -check-prefix=LE6# RUN: od -Ax -t x1 -N16 -j0x10ff0 %t.ppc64le | FileCheck %s -check-prefix=LE
77
8# RUN: llvm-mc -filetype=obj -triple=powerpc64-linux %s -o %t.o8# RUN: llvm-mc -filetype=obj -triple=powerpc64-linux %s -o %t.o
9# RUN: ld.lld %t.o -o %t.ppc649# RUN: ld.lld %t.o -o %t.ppc64
10# RUN: llvm-readobj -program-headers %t.ppc64 | FileCheck %s10# RUN: llvm-readobj -l %t.ppc64 | FileCheck %s
11# RUN: od -Ax -t x1 -N16 -j0x10ff0 %t.ppc64 | FileCheck %s -check-prefix=BE11# RUN: od -Ax -t x1 -N16 -j0x10ff0 %t.ppc64 | FileCheck %s -check-prefix=BE
1212
13# CHECK: ProgramHeader {13# CHECK: ProgramHeader {
deps/lld/test/ELF/fill-trap.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4# RUN: ld.lld %t -o %t24# RUN: ld.lld %t -o %t2
5# RUN: llvm-readobj -program-headers %t2 | FileCheck %s5# RUN: llvm-readobj -l %t2 | FileCheck %s
6# RUN: od -Ax -x -N16 -j0x1ff0 %t2 | FileCheck %s -check-prefix=FILL6# RUN: od -Ax -x -N16 -j0x1ff0 %t2 | FileCheck %s -check-prefix=FILL
77
8# CHECK: ProgramHeader {8# CHECK: ProgramHeader {
deps/lld/test/ELF/format-binary-non-ascii.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t£.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t£.o
33
4# RUN: ld.lld -o %t.elf %t£.o --format=binary %t£.o4# RUN: ld.lld -o %t.elf %t£.o --format=binary %t£.o
5# RUN: llvm-readobj -symbols %t.elf | FileCheck %s5# RUN: llvm-readobj --symbols %t.elf | FileCheck %s
66
7# CHECK: Name: _binary_{{[a-zA-Z0-9_]+}}test_ELF_Output_format_binary_non_ascii_s_tmp_{{[_]+}}o_start7# CHECK: Name: _binary_{{[a-zA-Z0-9_]+}}test_ELF_Output_format_binary_non_ascii_s_tmp_{{[_]+}}o_start
8# CHECK: Name: _binary_{{[a-zA-Z0-9_]+}}test_ELF_Output_format_binary_non_ascii_s_tmp_{{[_]+}}o_end8# CHECK: Name: _binary_{{[a-zA-Z0-9_]+}}test_ELF_Output_format_binary_non_ascii_s_tmp_{{[_]+}}o_end
deps/lld/test/ELF/gc-debuginfo-tls.s+2-2
...@@ -2,8 +2,8 @@...@@ -2,8 +2,8 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o --gc-sections -shared -o %t13# RUN: ld.lld %t.o --gc-sections -shared -o %t1
4# RUN: ld.lld %t.o -shared -o %t24# RUN: ld.lld %t.o -shared -o %t2
5# RUN: llvm-readobj -symbols %t1 | FileCheck %s --check-prefix=GC5# RUN: llvm-readobj --symbols %t1 | FileCheck %s --check-prefix=GC
6# RUN: llvm-readobj -symbols %t2 | FileCheck %s --check-prefix=NOGC6# RUN: llvm-readobj --symbols %t2 | FileCheck %s --check-prefix=NOGC
77
8# NOGC: Symbol {8# NOGC: Symbol {
9# NOGC: Name: patatino9# NOGC: Name: patatino
deps/lld/test/ELF/gc-merge-local-sym.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3// RUN: ld.lld %t.o -o %t.so -shared -O3 --gc-sections3// RUN: ld.lld %t.o -o %t.so -shared -O3 --gc-sections
4// RUN: llvm-readobj -s -section-data -t %t.so | FileCheck %s4// RUN: llvm-readobj -S --section-data --symbols %t.so | FileCheck %s
55
6// CHECK: Name: .rodata6// CHECK: Name: .rodata
7// CHECK-NEXT: Type: SHT_PROGBITS7// CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/gc-sections-alloc.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4# RUN: ld.lld %t -o %t2 --gc-sections -shared4# RUN: ld.lld %t -o %t2 --gc-sections -shared
5# RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s5# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s
66
7# Non alloca section .bar should not keep section .foo alive.7# Non alloca section .bar should not keep section .foo alive.
88
deps/lld/test/ELF/gc-sections-eh.s+2-2
...@@ -3,11 +3,11 @@...@@ -3,11 +3,11 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
44
5# RUN: ld.lld %t -o %t2 --gc-sections5# RUN: ld.lld %t -o %t2 --gc-sections
6# RUN: llvm-readobj -t %t2 | FileCheck %s6# RUN: llvm-readobj --symbols %t2 | FileCheck %s
7# RUN: llvm-objdump --dwarf=frames %t2 | FileCheck --check-prefix=EH %s7# RUN: llvm-objdump --dwarf=frames %t2 | FileCheck --check-prefix=EH %s
88
9# RUN: ld.lld %t -o %t39# RUN: ld.lld %t -o %t3
10# RUN: llvm-readobj -t %t3 | FileCheck --check-prefix=NOGC %s10# RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=NOGC %s
11# RUN: llvm-objdump --dwarf=frames %t3 | FileCheck --check-prefix=EHNOGC %s11# RUN: llvm-objdump --dwarf=frames %t3 | FileCheck --check-prefix=EHNOGC %s
1212
13# CHECK-NOT: foo13# CHECK-NOT: foo
deps/lld/test/ELF/gc-sections-implicit-addend.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %s -o %t.o
4# RUN: ld.lld %t.o -o %t --gc-sections4# RUN: ld.lld %t.o -o %t --gc-sections
5# RUN: llvm-readobj -s %t | FileCheck %s5# RUN: llvm-readobj -S %t | FileCheck %s
6# RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s6# RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
77
8# CHECK: Name: .foo8# CHECK: Name: .foo
deps/lld/test/ELF/gc-sections-keep-shared-start.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4# RUN: ld.lld -shared --gc-sections -o %t1 %t4# RUN: ld.lld -shared --gc-sections -o %t1 %t
5# RUN: llvm-readobj --elf-output-style=GNU --file-headers --symbols %t15# RUN: llvm-readelf --file-headers --symbols %t1
6# | FileCheck %s6# | FileCheck %s
7# CHECK: Entry point address: 0x10007# CHECK: Entry point address: 0x1000
8# CHECK: 0000000000001000 0 FUNC LOCAL HIDDEN 4 _start8# CHECK: 0000000000001000 0 FUNC LOCAL HIDDEN 4 _start
deps/lld/test/ELF/gc-sections-linker-defined-symbol.s+1-1
...@@ -10,7 +10,7 @@...@@ -10,7 +10,7 @@
10# CHECK-NEXT: Binding: Global10# CHECK-NEXT: Binding: Global
11# CHECK-NEXT: Type: None11# CHECK-NEXT: Type: None
12# CHECK-NEXT: Other:12# CHECK-NEXT: Other:
13# CHECK-NEXT: Section: .dynamic13# CHECK-NEXT: Section: .data
1414
15 .data15 .data
16 .globl g16 .globl g
deps/lld/test/ELF/gc-sections-local-sym.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %t2 -shared --gc-sections3// RUN: ld.lld %t -o %t2 -shared --gc-sections
4// RUN: llvm-readobj -t -s -section-data %t2 | FileCheck %s4// RUN: llvm-readobj --symbols -S --section-data %t2 | FileCheck %s
55
6.global foo6.global foo
7foo:7foo:
deps/lld/test/ELF/gc-sections-lsda.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7// precise and gc the entire contents of this file, but test that at least7// precise and gc the entire contents of this file, but test that at least
8// we are consistent: if we keep .abc, we have to keep .foo8// we are consistent: if we keep .abc, we have to keep .foo
99
10// RUN: llvm-readobj -s %t | FileCheck %s10// RUN: llvm-readobj -S %t | FileCheck %s
11// CHECK: Name: .abc11// CHECK: Name: .abc
12// CHECK: Name: .foo12// CHECK: Name: .foo
1313
deps/lld/test/ELF/gc-sections-merge-addend.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3// RUN: ld.lld %t.o -o %t.so -shared --gc-sections3// RUN: ld.lld %t.o -o %t.so -shared --gc-sections
4// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s4// RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
55
66
7// CHECK: Name: .rodata7// CHECK: Name: .rodata
deps/lld/test/ELF/gc-sections-merge-implicit-addend.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=i386-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=i386-pc-linux
3// RUN: ld.lld %t.o -o %t.so -shared --gc-sections3// RUN: ld.lld %t.o -o %t.so -shared --gc-sections
4// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s4// RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
55
66
7// CHECK: Name: .rodata7// CHECK: Name: .rodata
deps/lld/test/ELF/gc-sections-merge.s+2-2
...@@ -2,8 +2,8 @@...@@ -2,8 +2,8 @@
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: ld.lld %t.o -o %t.gc.so -shared --gc-sections4// RUN: ld.lld %t.o -o %t.gc.so -shared --gc-sections
5// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s5// RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
6// RUN: llvm-readobj -s -section-data %t.gc.so | FileCheck --check-prefix=GC %s6// RUN: llvm-readobj -S --section-data %t.gc.so | FileCheck --check-prefix=GC %s
77
88
9// CHECK: Name: .rodata9// CHECK: Name: .rodata
deps/lld/test/ELF/gc-sections-metadata-startstop.s+1-1
...@@ -11,7 +11,7 @@...@@ -11,7 +11,7 @@
11# CHECK-NOT: yy11# CHECK-NOT: yy
1212
13# CHECK: SYMBOL TABLE:13# CHECK: SYMBOL TABLE:
14# CHECK: xx 00000000 __start_xx14# CHECK: xx 00000000 .protected __start_xx
15# CHECK: w *UND* 00000000 __start_yy15# CHECK: w *UND* 00000000 __start_yy
1616
17.weak __start_xx17.weak __start_xx
deps/lld/test/ELF/gc-sections-non-alloc-to-merge.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: ld.lld %t.o -o %t --gc-sections4# RUN: ld.lld %t.o -o %t --gc-sections
5# RUN: llvm-readobj -s --elf-output-style=GNU %t | FileCheck %s5# RUN: llvm-readelf -S %t | FileCheck %s
66
7# CHECK: .merge1 PROGBITS {{[0-9a-z]*}} {{[0-9a-z]*}} 0000047# CHECK: .merge1 PROGBITS {{[0-9a-z]*}} {{[0-9a-z]*}} 000004
88
deps/lld/test/ELF/gc-sections-protected.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3// RUN: ld.lld %t.o -o %t.so -shared --gc-sections3// RUN: ld.lld %t.o -o %t.so -shared --gc-sections
4// RUN: llvm-readobj -s %t.so | FileCheck %s4// RUN: llvm-readobj -S %t.so | FileCheck %s
55
6// CHECK: Name: .text6// CHECK: Name: .text
7// CHECK-NEXT: Type: SHT_PROGBITS7// CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/gc-sections-synthetic.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: ld.lld %t1 -shared -o %t.so6# RUN: ld.lld %t1 -shared -o %t.so
7# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t27# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2
8# RUN: ld.lld %t2 %t.so -build-id -dynamic-linker /foo/bar -o %t.out8# RUN: ld.lld %t2 %t.so -build-id -dynamic-linker /foo/bar -o %t.out
9# RUN: llvm-readobj -sections %t.out | FileCheck %s9# RUN: llvm-readobj --sections %t.out | FileCheck %s
1010
11# CHECK: Name: .interp11# CHECK: Name: .interp
12# CHECK: Name: .note.gnu.build-id12# CHECK: Name: .note.gnu.build-id
deps/lld/test/ELF/gc-sections-undefined.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3# RUN: ld.lld %t -o %t1 --gc-sections --undefined=foo3# RUN: ld.lld %t -o %t1 --gc-sections --undefined=foo
4# RUN: llvm-readobj -t %t1 | FileCheck %s4# RUN: llvm-readobj --symbols %t1 | FileCheck %s
55
6# CHECK: foo6# CHECK: foo
77
deps/lld/test/ELF/gc-sections-weak.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// 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/gc-sections-weak.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/gc-sections-weak.s -o %t2.o
4// RUN: ld.lld %t.o %t2.o -o %t.so -shared --gc-sections4// RUN: ld.lld %t.o %t2.o -o %t.so -shared --gc-sections
5// RUN: llvm-readobj -s %t.so | FileCheck %s5// RUN: llvm-readobj -S %t.so | FileCheck %s
66
7.global foo7.global foo
8foo:8foo:
deps/lld/test/ELF/gc-sections.s+3-3
...@@ -2,11 +2,11 @@...@@ -2,11 +2,11 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4# RUN: ld.lld %t -o %t24# RUN: ld.lld %t -o %t2
5# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=NOGC %s5# RUN: llvm-readobj --sections --symbols %t2 | FileCheck -check-prefix=NOGC %s
6# RUN: ld.lld --gc-sections %t -o %t26# RUN: ld.lld --gc-sections %t -o %t2
7# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=GC1 %s7# RUN: llvm-readobj --sections --symbols %t2 | FileCheck -check-prefix=GC1 %s
8# RUN: ld.lld --export-dynamic --gc-sections %t -o %t28# RUN: ld.lld --export-dynamic --gc-sections %t -o %t2
9# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=GC2 %s9# RUN: llvm-readobj --sections --symbols %t2 | FileCheck -check-prefix=GC2 %s
1010
11# NOGC: Name: .eh_frame11# NOGC: Name: .eh_frame
12# NOGC: Name: .text12# NOGC: Name: .text
deps/lld/test/ELF/gdb-index-invalid-section-index.yaml created+140
...@@ -0,0 +1,140 @@
1# RUN: yaml2obj %s -o %t.o
2# RUN: ld.lld --gdb-index %t.o -o /dev/null
3
4## We used to crash if a DWARFAddressRange has invalid SectionIndex (-1).
5## Such DWARFAddressRange can be produced by clang -c -gdwarf-5 -gmlt before r360678.
6
7--- !ELF
8FileHeader:
9 Class: ELFCLASS64
10 Data: ELFDATA2LSB
11 Type: ET_REL
12 Machine: EM_X86_64
13Sections:
14 - Name: .text
15 Type: SHT_PROGBITS
16 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
17 AddressAlign: 0x0000000000000010
18 Content: 31C0C3
19 - Name: .debug_str_offsets
20 Type: SHT_PROGBITS
21 AddressAlign: 0x0000000000000001
22 Content: '1000000005000000000000000000000000000000'
23 - Name: .rela.debug_str_offsets
24 Type: SHT_RELA
25 Link: .symtab
26 AddressAlign: 0x0000000000000008
27 EntSize: 0x0000000000000018
28 Info: .debug_str_offsets
29 Relocations:
30 - Offset: 0x0000000000000008
31 Symbol: .debug_str
32 Type: R_X86_64_32
33 - Offset: 0x000000000000000C
34 Symbol: .debug_str
35 Type: R_X86_64_32
36 Addend: 1
37 - Offset: 0x0000000000000010
38 Symbol: .debug_str
39 Type: R_X86_64_32
40 Addend: 6
41 - Name: .debug_str
42 Type: SHT_PROGBITS
43 Flags: [ SHF_MERGE, SHF_STRINGS ]
44 AddressAlign: 0x0000000000000001
45 EntSize: 0x0000000000000001
46 Content: 00612E6363002F746D7000
47 - Name: .debug_abbrev
48 Type: SHT_PROGBITS
49 AddressAlign: 0x0000000000000001
50 Content: 011100252513050325721710171B25111B1206000000
51 - Name: .debug_info
52 Type: SHT_PROGBITS
53 AddressAlign: 0x0000000000000001
54 Content: 1B000000050001080000000001000400010000000000000000020003000000
55 - Name: .rela.debug_info
56 Type: SHT_RELA
57 Link: .symtab
58 AddressAlign: 0x0000000000000008
59 EntSize: 0x0000000000000018
60 Info: .debug_info
61 Relocations:
62 - Offset: 0x0000000000000008
63 Symbol: .debug_abbrev
64 Type: R_X86_64_32
65 - Offset: 0x0000000000000011
66 Symbol: .debug_str_offsets
67 Type: R_X86_64_32
68 Addend: 8
69 - Offset: 0x0000000000000015
70 Symbol: .debug_line
71 Type: R_X86_64_32
72 - Name: .debug_addr
73 Type: SHT_PROGBITS
74 AddressAlign: 0x0000000000000001
75 Content: 0C000000050008000000000000000000
76 - Name: .rela.debug_addr
77 Type: SHT_RELA
78 Link: .symtab
79 AddressAlign: 0x0000000000000008
80 EntSize: 0x0000000000000018
81 Info: .debug_addr
82 Relocations:
83 - Offset: 0x0000000000000008
84 Symbol: .text
85 Type: R_X86_64_64
86 - Name: .debug_line
87 Type: SHT_PROGBITS
88 AddressAlign: 0x0000000000000001
89 Content: 2D0000000500080025000000010101FB0E0D00010101010000000100000101011F010000000002011F020F010000000000
90 - Name: .rela.debug_line
91 Type: SHT_RELA
92 Link: .symtab
93 AddressAlign: 0x0000000000000008
94 EntSize: 0x0000000000000018
95 Info: .debug_line
96 Relocations:
97 - Offset: 0x0000000000000022
98 Symbol: .debug_line_str
99 Type: R_X86_64_32
100 - Offset: 0x000000000000002C
101 Symbol: .debug_line_str
102 Type: R_X86_64_32
103 Addend: 5
104 - Name: .debug_line_str
105 Type: SHT_PROGBITS
106 Flags: [ SHF_MERGE, SHF_STRINGS ]
107 AddressAlign: 0x0000000000000001
108 EntSize: 0x0000000000000001
109 Content: 2F746D7000612E636300
110Symbols:
111 - Name: a.ll
112 Type: STT_FILE
113 Index: SHN_ABS
114 - Name: .text
115 Type: STT_SECTION
116 Section: .text
117 - Name: .debug_str_offsets
118 Type: STT_SECTION
119 Section: .debug_str_offsets
120 - Name: .debug_str
121 Type: STT_SECTION
122 Section: .debug_str
123 - Name: .debug_abbrev
124 Type: STT_SECTION
125 Section: .debug_abbrev
126 - Name: .debug_info
127 Type: STT_SECTION
128 Section: .debug_info
129 - Name: .debug_line
130 Type: STT_SECTION
131 Section: .debug_line
132 - Name: .debug_line_str
133 Type: STT_SECTION
134 Section: .debug_line_str
135 - Name: foo
136 Type: STT_FUNC
137 Section: .text
138 Binding: STB_GLOBAL
139 Size: 0x0000000000000003
140...
deps/lld/test/ELF/gdb-index-multiple-cu-2.s+2-2
...@@ -4,8 +4,8 @@...@@ -4,8 +4,8 @@
4# RUN: ld.lld --gdb-index %t.o %t1.o -o %t4# RUN: ld.lld --gdb-index %t.o %t1.o -o %t
5# RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s5# RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s
66
7# %t.o has 2 CUs while %t1 has 1, thus _start in %t1.o should have CuIndex 2.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 = 0x300000028# attributes << 24 | cuIndex = 48 << 24 | 2 = 0x30000002
9# CHECK: Constant pool9# CHECK: Constant pool
10# CHECK-NEXT: 0(0x0): 0x3000000210# CHECK-NEXT: 0(0x0): 0x30000002
1111
deps/lld/test/ELF/gdb-index-multiple-cu.s+6-6
...@@ -3,10 +3,10 @@...@@ -3,10 +3,10 @@
3# RUN: ld.lld --gdb-index %t.o -o %t3# RUN: ld.lld --gdb-index %t.o -o %t
4# RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s4# RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s
55
6# CuIndexAndAttrs of _start:6# cuIndexAndAttrs of _start:
7# Attributes << 24 | CuIndex = 48 << 24 | 0 = 0x300000007# attributes << 24 | cuIndex = 48 << 24 | 0 = 0x30000000
8# CuIndexAndAttrs of foo:8# cuIndexAndAttrs of foo:
9# Attributes << 24 | CuIndex = 48 << 24 | 1 = 0x300000019# attributes << 24 | cuIndex = 48 << 24 | 1 = 0x30000001
10# CHECK: Symbol table10# CHECK: Symbol table
11# CHECK-DAG: String name: _start, CU vector index: 011# CHECK-DAG: String name: _start, CU vector index: 0
12# CHECK-DAG: String name: foo, CU vector index: 112# CHECK-DAG: String name: foo, CU vector index: 1
...@@ -63,7 +63,7 @@ foo:...@@ -63,7 +63,7 @@ foo:
63# Swap sets to test the case where pubnames are in a63# Swap sets to test the case where pubnames are in a
64# different order than the CUs they refer to.64# different order than the CUs they refer to.
65.section .debug_gnu_pubnames,"",@progbits65.section .debug_gnu_pubnames,"",@progbits
66 # CuIndex: 166 # cuIndex: 1
67 .long .LpubNames_end1 - .LpubNames_begin167 .long .LpubNames_end1 - .LpubNames_begin1
68.LpubNames_begin1:68.LpubNames_begin1:
69 .short 2 # Version69 .short 2 # Version
...@@ -75,7 +75,7 @@ foo:...@@ -75,7 +75,7 @@ foo:
75 .long 075 .long 0
76.LpubNames_end1:76.LpubNames_end1:
7777
78 # CuIndex: 078 # cuIndex: 0
79 .long .LpubNames_end0 - .LpubNames_begin079 .long .LpubNames_end0 - .LpubNames_begin0
80.LpubNames_begin0:80.LpubNames_begin0:
81 .short 2 # Version81 .short 2 # Version
deps/lld/test/ELF/gdb-index-ranges-discarded.s created+51
...@@ -0,0 +1,51 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: ld.lld --gdb-index -e main %t.o -o %t
4# RUN: llvm-dwarfdump -gdb-index %t | FileCheck %s
5
6# CHECK: .gdb_index contents:
7# CHECK: Address area offset = 0x28, has 1 entries:
8# CHECK-NEXT: Low/High address = [0x201000, 0x201001) (Size: 0x1), CU id = 0
9
10## .debug_ranges contains 2 entries. .Lfunc_end0 is defined in the discarded
11## .text.foo. Test we resolve it to a non-zero value, otherwise the address area
12## of .gdb_index will not included [.Lfunc_begin1, .Lfunc_end1).
13
14.section .text.foo,"aex",@progbits
15.Lfunc_begin0:
16 ret
17.Lfunc_end0:
18
19.section .text.bar,"ax",@progbits
20.Lfunc_begin1:
21 ret
22.Lfunc_end1:
23
24.section .debug_abbrev,"",@progbits
25 .byte 1 # Abbreviation Code
26 .byte 17 # DW_TAG_compile_unit
27 .byte 0 # DW_CHILDREN_no
28 .byte 85 # DW_AT_ranges
29 .byte 23 # DW_FORM_sec_offset
30 .byte 0 # EOM(1)
31 .byte 0 # EOM(2)
32 .byte 0
33
34.section .debug_info,"",@progbits
35.Lcu_begin0:
36 .long .Lcu_end0 - .Lcu_begin0 - 4
37 .short 4 # DWARF version number
38 .long 0 # Offset Into Abbrev. Section
39 .byte 8 # Address Size
40.Ldie0:
41 .byte 1 # Abbrev [1] DW_TAG_compile_unit
42 .long 0 # DW_AT_ranges
43.Lcu_end0:
44
45.section .debug_ranges,"",@progbits
46 .quad .Lfunc_begin0
47 .quad .Lfunc_end0
48 .quad .Lfunc_begin1
49 .quad .Lfunc_end1
50 .quad 0
51 .quad 0
deps/lld/test/ELF/gdb-index.s+2-1
...@@ -16,6 +16,7 @@...@@ -16,6 +16,7 @@
16# RUN: llvm-readelf -sections %t | FileCheck %s --check-prefix=SECTION16# RUN: llvm-readelf -sections %t | FileCheck %s --check-prefix=SECTION
1717
18# DISASM: Disassembly of section .text:18# DISASM: Disassembly of section .text:
19# DISASM-EMPTY:
19# DISASM: entrypoint:20# DISASM: entrypoint:
20# DISASM-CHECK: 201000: 90 nop21# DISASM-CHECK: 201000: 90 nop
21# DISASM-CHECK: 201001: cc int322# DISASM-CHECK: 201001: cc int3
...@@ -48,7 +49,7 @@...@@ -48,7 +49,7 @@
48# SECTION-NOT: debug_gnu_pubnames49# SECTION-NOT: debug_gnu_pubnames
4950
50# RUN: ld.lld --gdb-index --no-gdb-index %t1.o %t2.o -o %t251# RUN: ld.lld --gdb-index --no-gdb-index %t1.o %t2.o -o %t2
51# RUN: llvm-readobj -sections %t2 | FileCheck -check-prefix=NOGDB %s52# RUN: llvm-readobj --sections %t2 | FileCheck -check-prefix=NOGDB %s
52# NOGDB-NOT: Name: .gdb_index53# NOGDB-NOT: Name: .gdb_index
5354
54## The following section contents are created by this using gcc 7.1.0:55## The following section contents are created by this using gcc 7.1.0:
deps/lld/test/ELF/global-offset-table-position-aarch64.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: aarch641// REQUIRES: aarch64
2// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t2// RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu %s -o %t
3// RUN: ld.lld --hash-style=sysv -shared %t -o %t23// RUN: ld.lld --hash-style=sysv -shared %t -o %t2
4// RUN: llvm-readobj -t %t2 | FileCheck %s4// RUN: llvm-readobj --symbols %t2 | FileCheck %s
5.globl a5.globl a
6.type a,@object6.type a,@object
7.comm a,4,47.comm a,4,4
...@@ -20,7 +20,7 @@ _start:...@@ -20,7 +20,7 @@ _start:
20.long _GLOBAL_OFFSET_TABLE_ - .20.long _GLOBAL_OFFSET_TABLE_ - .
2121
22// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (11)22// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (11)
23// CHECK-NEXT: Value: 0x2000823// CHECK-NEXT: Value: 0x30008
24// CHECK-NEXT: Size: 024// CHECK-NEXT: Size: 0
25// CHECK-NEXT: Binding: Local (0x0)25// CHECK-NEXT: Binding: Local (0x0)
26// CHECK-NEXT: Type: None (0x0)26// CHECK-NEXT: Type: None (0x0)
deps/lld/test/ELF/global-offset-table-position-arm.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: arm1// REQUIRES: arm
2// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t2// RUN: llvm-mc -filetype=obj -triple=armv7a-linux-gnueabihf %s -o %t
3// RUN: ld.lld --hash-style=sysv -shared %t -o %t23// RUN: ld.lld --hash-style=sysv -shared %t -o %t2
4// RUN: llvm-readobj -t %t2 | FileCheck %s4// RUN: llvm-readobj --symbols %t2 | FileCheck %s
55
6// The ARM _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got6// The ARM _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got
7.globl a7.globl a
...@@ -25,7 +25,7 @@ _start:...@@ -25,7 +25,7 @@ _start:
25.data25.data
2626
27// CHECK: Name: _GLOBAL_OFFSET_TABLE_27// CHECK: Name: _GLOBAL_OFFSET_TABLE_
28// CHECK-NEXT: Value: 0x306828// CHECK-NEXT: Value: 0x2068
29// CHECK-NEXT: Size: 029// CHECK-NEXT: Size: 0
30// CHECK-NEXT: Binding: Local30// CHECK-NEXT: Binding: Local
31// CHECK-NEXT: Type: None31// CHECK-NEXT: Type: None
deps/lld/test/ELF/global-offset-table-position-i386.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t
3// RUN: ld.lld --hash-style=sysv -shared %t -o %t23// RUN: ld.lld --hash-style=sysv -shared %t -o %t2
4// RUN: llvm-readobj -t %t2 | FileCheck %s4// RUN: llvm-readobj --symbols %t2 | FileCheck %s
55
6// The X86 _GLOBAL_OFFSET_TABLE_ is defined at the start of the .got.plt6// The X86 _GLOBAL_OFFSET_TABLE_ is defined at the start of the .got.plt
7// section.7// section.
...@@ -22,7 +22,7 @@ addl $_GLOBAL_OFFSET_TABLE_, %eax...@@ -22,7 +22,7 @@ addl $_GLOBAL_OFFSET_TABLE_, %eax
22calll f@PLT22calll f@PLT
2323
24// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (1)24// CHECK: Name: _GLOBAL_OFFSET_TABLE_ (1)
25// CHECK-NEXT: Value: 0x200025// CHECK-NEXT: Value: 0x3000
26// CHECK-NEXT: Size: 026// CHECK-NEXT: Size: 0
27// CHECK-NEXT: Binding: Local (0x0)27// CHECK-NEXT: Binding: Local (0x0)
28// CHECK-NEXT: Type: None (0x0)28// CHECK-NEXT: Type: None (0x0)
deps/lld/test/ELF/global-offset-table-position-mips.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: mips1// REQUIRES: mips
2// RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t
3// RUN: ld.lld -shared %t -o %t23// RUN: ld.lld -shared %t -o %t2
4// RUN: llvm-readobj -t %t2 | FileCheck %s4// RUN: llvm-readobj --symbols %t2 | FileCheck %s
55
6// The Mips _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got6// The Mips _GLOBAL_OFFSET_TABLE_ should be defined at the start of the .got
77
deps/lld/test/ELF/global-offset-table-position.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
3// RUN: ld.lld --hash-style=sysv -shared %t -o %t23// RUN: ld.lld --hash-style=sysv -shared %t -o %t2
4// RUN: llvm-readobj -t %t2 | FileCheck %s4// RUN: llvm-readobj --symbols %t2 | FileCheck %s
55
6// The X86_64 _GLOBAL_OFFSET_TABLE_ is defined at the start of the .got.plt6// The X86_64 _GLOBAL_OFFSET_TABLE_ is defined at the start of the .got.plt
7// section.7// section.
...@@ -22,7 +22,7 @@ callq f@PLT...@@ -22,7 +22,7 @@ callq f@PLT
22.long _GLOBAL_OFFSET_TABLE_ - .22.long _GLOBAL_OFFSET_TABLE_ - .
2323
24// CHECK: Name: _GLOBAL_OFFSET_TABLE_24// CHECK: Name: _GLOBAL_OFFSET_TABLE_
25// CHECK-NEXT: Value: 0x200825// CHECK-NEXT: Value: 0x3008
26// CHECK-NEXT: Size: 026// CHECK-NEXT: Size: 0
27// CHECK-NEXT: Binding: Local27// CHECK-NEXT: Binding: Local
28// CHECK-NEXT: Type: None (0x0)28// CHECK-NEXT: Type: None (0x0)
deps/lld/test/ELF/global_offset_table_shared.s+2-2
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
3// RUN: ld.lld --hash-style=sysv -shared %t -o %t23// RUN: ld.lld --hash-style=sysv -shared %t -o %t2
4// RUN: llvm-readobj -t %t2 | FileCheck %s4// RUN: llvm-readobj --symbols %t2 | FileCheck %s
5.long _GLOBAL_OFFSET_TABLE_ - .5.long _GLOBAL_OFFSET_TABLE_ - .
66
7// CHECK: Name: _GLOBAL_OFFSET_TABLE_7// CHECK: Name: _GLOBAL_OFFSET_TABLE_
8// CHECK-NEXT: Value: 0x20008// CHECK-NEXT: Value: 0x3000
9// CHECK-NEXT: Size: 09// CHECK-NEXT: Size: 0
10// CHECK-NEXT: Binding: Local10// CHECK-NEXT: Binding: Local
11// CHECK-NEXT: Type: None11// CHECK-NEXT: Type: None
deps/lld/test/ELF/gnu-hash-table-rwsegment.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
4# RUN: ld.lld -shared -hash-style=gnu --no-rosegment -o %t.so %t.o4# RUN: ld.lld -shared -hash-style=gnu --no-rosegment -o %t.so %t.o
5# RUN: llvm-readobj -gnu-hash-table %t.so | FileCheck %s5# RUN: llvm-readobj --gnu-hash-table %t.so | FileCheck %s
66
7# CHECK: GnuHashTable {7# CHECK: GnuHashTable {
8# CHECK-NEXT: Num Buckets: 18# CHECK-NEXT: Num Buckets: 1
deps/lld/test/ELF/gnu-hash-table.s+5-5
...@@ -36,15 +36,15 @@...@@ -36,15 +36,15 @@
36# RUN: ld.lld -shared --hash-style both -o %t-ppc64le.so %t-ppc64le.o %t2-ppc64le.a %t3-ppc64le.so36# RUN: ld.lld -shared --hash-style both -o %t-ppc64le.so %t-ppc64le.o %t2-ppc64le.a %t3-ppc64le.so
37# RUN: ld.lld -shared --hash-style both -o %t-ppc64.so %t-ppc64.o %t2-ppc64.a %t3-ppc64.so37# RUN: ld.lld -shared --hash-style both -o %t-ppc64.so %t-ppc64.o %t2-ppc64.a %t3-ppc64.so
3838
39# RUN: llvm-readobj -dyn-symbols -gnu-hash-table %te-i386.so \39# RUN: llvm-readobj --dyn-syms --gnu-hash-table %te-i386.so \
40# RUN: | FileCheck %s -check-prefix=EMPTY40# RUN: | FileCheck %s -check-prefix=EMPTY
41# RUN: llvm-readobj -sections -dyn-symbols -gnu-hash-table %t-i386.so \41# RUN: llvm-readobj --sections --dyn-syms --gnu-hash-table %t-i386.so \
42# RUN: | FileCheck %s -check-prefix=I38642# RUN: | FileCheck %s -check-prefix=I386
43# RUN: llvm-readobj -sections -dyn-symbols -gnu-hash-table %t-x86_64.so \43# RUN: llvm-readobj --sections --dyn-syms --gnu-hash-table %t-x86_64.so \
44# RUN: | FileCheck %s -check-prefix=X86_6444# RUN: | FileCheck %s -check-prefix=X86_64
45# RUN: llvm-readobj -sections -dyn-symbols -gnu-hash-table %t-ppc64le.so \45# RUN: llvm-readobj --sections --dyn-syms --gnu-hash-table %t-ppc64le.so \
46# RUN: | FileCheck %s -check-prefix=PPC6446# RUN: | FileCheck %s -check-prefix=PPC64
47# RUN: llvm-readobj -sections -dyn-symbols -gnu-hash-table %t-ppc64.so \47# RUN: llvm-readobj --sections --dyn-syms --gnu-hash-table %t-ppc64.so \
48# RUN: | FileCheck %s -check-prefix=PPC6448# RUN: | FileCheck %s -check-prefix=PPC64
4949
50# EMPTY: DynamicSymbols [50# EMPTY: DynamicSymbols [
deps/lld/test/ELF/gnu-ifunc-canon.s created+92
...@@ -0,0 +1,92 @@
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 %S/Inputs/gnu-ifunc-canon-ro-pcrel.s -o %t-ro-pcrel.o
4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/gnu-ifunc-canon-ro-abs.s -o %t-ro-abs.o
5// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/gnu-ifunc-canon-rw-addend.s -o %t-rw-addend.o
6// RUN: ld.lld %t.o -o %t1
7// RUN: llvm-readobj -r %t1 | FileCheck --check-prefix=IREL2 %s
8// RUN: ld.lld %t.o %t-ro-pcrel.o -o %t2
9// RUN: llvm-readobj -r %t2 | FileCheck --check-prefix=IREL1 %s
10// RUN: ld.lld %t.o %t-ro-abs.o -o %t3
11// RUN: llvm-readobj -r %t3 | FileCheck --check-prefix=IREL1 %s
12// RUN: ld.lld %t.o %t-rw-addend.o -o %t4
13// RUN: llvm-readobj -r %t4 | FileCheck --check-prefix=IREL1 %s
14// RUN: llvm-objdump -s %t4 | FileCheck --check-prefix=DUMP %s
15// RUN: ld.lld %t.o %t-rw-addend.o -o %t4a -z retpolineplt
16// RUN: llvm-readobj -r %t4a | FileCheck --check-prefix=IREL1 %s
17// RUN: llvm-objdump -s %t4a | FileCheck --check-prefix=DUMP2 %s
18// RUN: ld.lld %t-ro-pcrel.o %t.o -o %t5
19// RUN: llvm-readobj -r %t5 | FileCheck --check-prefix=IREL1 %s
20// RUN: ld.lld %t-ro-abs.o %t.o -o %t6
21// RUN: llvm-readobj -r %t6 | FileCheck --check-prefix=IREL1 %s
22// RUN: ld.lld %t-rw-addend.o %t.o -o %t7
23// RUN: llvm-readobj -r %t7 | FileCheck --check-prefix=IREL1 %s
24// RUN: ld.lld %t.o -o %t8 -pie
25// RUN: llvm-readobj -r %t8 | FileCheck --check-prefix=IREL2 %s
26// RUN: ld.lld %t.o %t-ro-pcrel.o -o %t9 -pie
27// RUN: llvm-readobj -r %t9 | FileCheck --check-prefix=IREL1-REL2 %s
28// RUN: ld.lld %t.o %t-rw-addend.o -o %t10 -pie
29// RUN: llvm-readobj -r %t10 | FileCheck --check-prefix=IREL1-REL3 %s
30// RUN: ld.lld %t-ro-pcrel.o %t.o -o %t11 -pie
31// RUN: llvm-readobj -r %t11 | FileCheck --check-prefix=IREL1-REL2 %s
32// RUN: ld.lld %t-rw-addend.o %t.o -o %t12 -pie
33// RUN: llvm-readobj -r %t12 | FileCheck --check-prefix=IREL1-REL3 %s
34
35// Two relocs, one for the GOT and the other for .data.
36// IREL2-NOT: R_X86_64_
37// IREL2: .rela.plt
38// IREL2-NEXT: R_X86_64_IRELATIVE
39// IREL2-NEXT: R_X86_64_IRELATIVE
40// IREL2-NOT: R_X86_64_
41
42// One reloc for the canonical PLT.
43// IREL1-NOT: R_X86_64_
44// IREL1: .rela.plt
45// IREL1-NEXT: R_X86_64_IRELATIVE
46// IREL1-NOT: R_X86_64_
47
48// One reloc for the canonical PLT and two RELATIVE relocations pointing to it,
49// one in the GOT and one in .data.
50// IREL1-REL2-NOT: R_X86_64_
51// IREL1-REL2: .rela.dyn
52// IREL1-REL2-NEXT: R_X86_64_RELATIVE
53// IREL1-REL2-NEXT: R_X86_64_RELATIVE
54// IREL1-REL2: .rela.plt
55// IREL1-REL2-NEXT: R_X86_64_IRELATIVE
56// IREL1-REL2-NOT: R_X86_64_
57
58// One reloc for the canonical PLT and three RELATIVE relocations pointing to it,
59// one in the GOT and two in .data.
60// IREL1-REL3-NOT: R_X86_64_
61// IREL1-REL3: .rela.dyn
62// IREL1-REL3-NEXT: R_X86_64_RELATIVE
63// IREL1-REL3-NEXT: R_X86_64_RELATIVE
64// IREL1-REL3-NEXT: R_X86_64_RELATIVE
65// IREL1-REL3: .rela.plt
66// IREL1-REL3-NEXT: R_X86_64_IRELATIVE
67// IREL1-REL3-NOT: R_X86_64_
68
69// Make sure the static relocations look right, both with and without headers.
70// DUMP: Contents of section .plt:
71// DUMP-NEXT: 201010
72// DUMP: Contents of section .got:
73// DUMP-NEXT: 202000 10102000 00000000
74// DUMP: Contents of section .data:
75// DUMP-NEXT: 203000 10102000 00000000 11102000 00000000
76
77// DUMP2: Contents of section .plt:
78// DUMP2-NEXT: 201010
79// DUMP2: Contents of section .got:
80// DUMP2-NEXT: 202000 40102000 00000000
81// DUMP2: Contents of section .data:
82// DUMP2-NEXT: 203000 40102000 00000000 41102000 00000000
83
84lea ifunc@gotpcrel(%rip), %rbx
85
86.type ifunc STT_GNU_IFUNC
87.globl ifunc
88ifunc:
89ret
90
91.data
92.8byte ifunc
deps/lld/test/ELF/gnu-ifunc-dso.s+2-2
...@@ -3,10 +3,10 @@...@@ -3,10 +3,10 @@
3# RUN: ld.lld -shared %t1.o -o %t.so3# RUN: ld.lld -shared %t1.o -o %t.so
4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o
5# RUN: ld.lld -shared %t2.o %t.so -o %t5# RUN: ld.lld -shared %t2.o %t.so -o %t
6# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s6# RUN: llvm-readobj --dyn-relocations %t | FileCheck %s
77
8# CHECK: Dynamic Relocations {8# CHECK: Dynamic Relocations {
9# CHECK-NEXT: 0x1000 R_X86_64_64 foo 0x09# CHECK-NEXT: 0x2000 R_X86_64_64 foo 0x0
10# CHECK-NEXT: }10# CHECK-NEXT: }
1111
12.data12.data
deps/lld/test/ELF/gnu-ifunc-dyntags.s+6-6
...@@ -2,14 +2,14 @@...@@ -2,14 +2,14 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -pie %t.o -o %tout3# RUN: ld.lld -pie %t.o -o %tout
4# RUN: llvm-objdump -section-headers %tout | FileCheck %s4# RUN: llvm-objdump -section-headers %tout | FileCheck %s
5# RUN: llvm-readobj -dynamic-table -r %tout | FileCheck %s --check-prefix=TAGS5# RUN: llvm-readobj --dynamic-table -r %tout | FileCheck %s --check-prefix=TAGS
66
7## Check we produce DT_PLTREL/DT_JMPREL/DT_PLTGOT and DT_PLTRELSZ tags7## Check we produce DT_PLTREL/DT_JMPREL/DT_PLTGOT and DT_PLTRELSZ tags
8## when there are no other relocations except R_*_IRELATIVE.8## when there are no other relocations except R_*_IRELATIVE.
99
10# CHECK: Name Size Address10# CHECK: Name Size VMA
11# CHECK: .rela.plt 00000030 000000000000021011# CHECK: .rela.plt 00000030 0000000000000248
12# CHECK: .got.plt 00000010 000000000000200012# CHECK: .got.plt 00000010 0000000000003000
1313
14# TAGS: Relocations [14# TAGS: Relocations [
15# TAGS-NEXT: Section {{.*}} .rela.plt {15# TAGS-NEXT: Section {{.*}} .rela.plt {
...@@ -19,9 +19,9 @@...@@ -19,9 +19,9 @@
19# TAGS-NEXT: ]19# TAGS-NEXT: ]
2020
21# TAGS: Tag Type Name/Value21# TAGS: Tag Type Name/Value
22# TAGS: 0x0000000000000017 JMPREL 0x21022# TAGS: 0x0000000000000017 JMPREL 0x248
23# TAGS: 0x0000000000000002 PLTRELSZ 4823# TAGS: 0x0000000000000002 PLTRELSZ 48
24# TAGS: 0x0000000000000003 PLTGOT 0x200024# TAGS: 0x0000000000000003 PLTGOT 0x3000
25# TAGS: 0x0000000000000014 PLTREL RELA25# TAGS: 0x0000000000000014 PLTREL RELA
2626
27.text27.text
deps/lld/test/ELF/gnu-ifunc-gotpcrel.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: ld.lld -shared %t2.o -o %t2.so3# RUN: ld.lld -shared %t2.o -o %t2.so
4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
5# RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t5# RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t
6# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s6# RUN: llvm-readobj --dyn-relocations %t | FileCheck %s
77
8# CHECK: Dynamic Relocations {8# CHECK: Dynamic Relocations {
9# CHECK-NEXT: 0x2020B0 R_X86_64_GLOB_DAT foo 0x09# CHECK-NEXT: 0x2020B0 R_X86_64_GLOB_DAT foo 0x0
deps/lld/test/ELF/gnu-ifunc-i386.s+34-6
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
3// RUN: ld.lld -static %t.o -o %tout3// RUN: ld.lld -static %t.o -o %tout
4// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM4// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
5// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s5// RUN: llvm-readobj -r --symbols --sections %tout | FileCheck %s
66
7// CHECK: Sections [7// CHECK: Sections [
8// CHECK: Section {8// CHECK: Section {
...@@ -70,39 +70,61 @@...@@ -70,39 +70,61 @@
70// CHECK-NEXT: }70// CHECK-NEXT: }
71// CHECK-NEXT: Symbol {71// CHECK-NEXT: Symbol {
72// CHECK-NEXT: Name: bar72// CHECK-NEXT: Name: bar
73// CHECK-NEXT: Value: 0x401030
74// CHECK-NEXT: Size: 0
75// CHECK-NEXT: Binding: Global
76// CHECK-NEXT: Type: Function
77// CHECK-NEXT: Other: 0
78// CHECK-NEXT: Section: .plt
79// CHECK-NEXT: }
80// CHECK-NEXT: Symbol {
81// CHECK-NEXT: Name: bar_resolver
73// CHECK-NEXT: Value: 0x40100182// CHECK-NEXT: Value: 0x401001
74// CHECK-NEXT: Size: 083// CHECK-NEXT: Size: 0
75// CHECK-NEXT: Binding: Global84// CHECK-NEXT: Binding: Global
76// CHECK-NEXT: Type: GNU_IFunc85// CHECK-NEXT: Type: Function
77// CHECK-NEXT: Other: 086// CHECK-NEXT: Other: 0
78// CHECK-NEXT: Section: .text87// CHECK-NEXT: Section: .text
79// CHECK-NEXT: }88// CHECK-NEXT: }
80// CHECK-NEXT: Symbol {89// CHECK-NEXT: Symbol {
81// CHECK-NEXT: Name: foo90// CHECK-NEXT: Name: foo
91// CHECK-NEXT: Value: 0x401020
92// CHECK-NEXT: Size: 0
93// CHECK-NEXT: Binding: Global
94// CHECK-NEXT: Type: Function
95// CHECK-NEXT: Other: 0
96// CHECK-NEXT: Section: .plt
97// CHECK-NEXT: }
98// CHECK-NEXT: Symbol {
99// CHECK-NEXT: Name: foo_resolver
82// CHECK-NEXT: Value: 0x401000100// CHECK-NEXT: Value: 0x401000
83// CHECK-NEXT: Size: 0101// CHECK-NEXT: Size: 0
84// CHECK-NEXT: Binding: Global102// CHECK-NEXT: Binding: Global
85// CHECK-NEXT: Type: GNU_IFunc103// CHECK-NEXT: Type: Function
86// CHECK-NEXT: Other: 0104// CHECK-NEXT: Other: 0
87// CHECK-NEXT: Section: .text105// CHECK-NEXT: Section: .text
88// CHECK-NEXT: }106// CHECK-NEXT: }
89// CHECK-NEXT:]107// CHECK-NEXT:]
90108
91// DISASM: Disassembly of section .text:109// DISASM: Disassembly of section .text:
92// DISASM-NEXT: foo:110// DISASM-EMPTY:
111// DISASM-NEXT: foo_resolver:
93// DISASM-NEXT: 401000: c3 retl112// DISASM-NEXT: 401000: c3 retl
94// DISASM: bar:113// DISASM: bar_resolver:
95// DISASM-NEXT: 401001: c3 retl114// DISASM-NEXT: 401001: c3 retl
96// DISASM: _start:115// DISASM: _start:
97// DISASM-NEXT: 401002: e8 19 00 00 00 calll 25116// DISASM-NEXT: 401002: e8 19 00 00 00 calll 25
98// DISASM-NEXT: 401007: e8 24 00 00 00 calll 36117// DISASM-NEXT: 401007: e8 24 00 00 00 calll 36
99// DISASM-NEXT: 40100c: ba d4 00 40 00 movl $4194516, %edx118// DISASM-NEXT: 40100c: ba d4 00 40 00 movl $4194516, %edx
100// DISASM-NEXT: 401011: ba e4 00 40 00 movl $4194532, %edx119// DISASM-NEXT: 401011: ba e4 00 40 00 movl $4194532, %edx
120// DISASM-EMPTY:
101// DISASM-NEXT: Disassembly of section .plt:121// DISASM-NEXT: Disassembly of section .plt:
102// DISASM-NEXT: .plt:122// DISASM-EMPTY:
123// DISASM-NEXT: foo:
103// DISASM-NEXT: 401020: ff 25 00 20 40 00 jmpl *4202496124// DISASM-NEXT: 401020: ff 25 00 20 40 00 jmpl *4202496
104// DISASM-NEXT: 401026: 68 10 00 00 00 pushl $16125// DISASM-NEXT: 401026: 68 10 00 00 00 pushl $16
105// DISASM-NEXT: 40102b: e9 e0 ff ff ff jmp -32 <_start+0xe>126// DISASM-NEXT: 40102b: e9 e0 ff ff ff jmp -32 <_start+0xe>
127// DISASM: bar:
106// DISASM-NEXT: 401030: ff 25 04 20 40 00 jmpl *4202500128// DISASM-NEXT: 401030: ff 25 04 20 40 00 jmpl *4202500
107// DISASM-NEXT: 401036: 68 18 00 00 00 pushl $24129// DISASM-NEXT: 401036: 68 18 00 00 00 pushl $24
108// DISASM-NEXT: 40103b: e9 d0 ff ff ff jmp -48 <_start+0xe>130// DISASM-NEXT: 40103b: e9 d0 ff ff ff jmp -48 <_start+0xe>
...@@ -111,11 +133,17 @@...@@ -111,11 +133,17 @@
111.type foo STT_GNU_IFUNC133.type foo STT_GNU_IFUNC
112.globl foo134.globl foo
113foo:135foo:
136.type foo_resolver STT_FUNC
137.globl foo_resolver
138foo_resolver:
114 ret139 ret
115140
116.type bar STT_GNU_IFUNC141.type bar STT_GNU_IFUNC
117.globl bar142.globl bar
118bar:143bar:
144.type bar_resolver STT_FUNC
145.globl bar_resolver
146bar_resolver:
119 ret147 ret
120148
121.globl _start149.globl _start
deps/lld/test/ELF/gnu-ifunc-noplt-i386.s created+71
...@@ -0,0 +1,71 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i686-pc-freebsd %S/Inputs/shared2-x86-64.s -o %t1.o
3// RUN: ld.lld %t1.o --shared -o %t.so
4// RUN: llvm-mc -filetype=obj -triple=i686-pc-freebsd %s -o %t.o
5// RUN: ld.lld -z ifunc-noplt -z notext --hash-style=sysv %t.so %t.o -o %tout
6// RUN: llvm-objdump -d --no-show-raw-insn %tout | FileCheck %s --check-prefix=DISASM
7// RUN: llvm-readobj -r --dynamic-table %tout | FileCheck %s
8
9// Check that we emitted relocations for the ifunc calls
10// CHECK: Relocations [
11// CHECK-NEXT: Section (4) .rel.dyn {
12// CHECK-NEXT: 0x401008 R_386_PLT32 bar
13// CHECK-NEXT: 0x401003 R_386_PLT32 foo
14// CHECK-NEXT: }
15// CHECK-NEXT: Section (5) .rel.plt {
16// CHECK-NEXT: 0x40300C R_386_JUMP_SLOT bar2
17// CHECK-NEXT: 0x403010 R_386_JUMP_SLOT zed2
18// CHECK-NEXT: }
19
20// Check that ifunc call sites still require relocation
21// DISASM: Disassembly of section .text:
22// DISASM-EMPTY:
23// DISASM-NEXT: 00401000 foo:
24// DISASM-NEXT: 401000: retl
25// DISASM-EMPTY:
26// DISASM-NEXT: 00401001 bar:
27// DISASM-NEXT: 401001: retl
28// DISASM-EMPTY:
29// DISASM-NEXT: 00401002 _start:
30// DISASM-NEXT: 401002: calll -4 <_start+0x1>
31// DISASM-NEXT: 401007: calll -4 <_start+0x6>
32// DISASM-NEXT: 40100c: calll 31 <bar2@plt>
33// DISASM-NEXT: 401011: calll 42 <zed2@plt>
34// DISASM-EMPTY:
35// DISASM-NEXT: Disassembly of section .plt:
36// DISASM-EMPTY:
37// DISASM-NEXT: 00401020 .plt:
38// DISASM-NEXT: 401020: pushl 4206596
39// DISASM-NEXT: 401026: jmpl *4206600
40// DISASM-NEXT: 40102c: nop
41// DISASM-NEXT: 40102d: nop
42// DISASM-NEXT: 40102e: nop
43// DISASM-NEXT: 40102f: nop
44// DISASM-EMPTY:
45// DISASM-NEXT: 00401030 bar2@plt:
46// DISASM-NEXT: 401030: jmpl *4206604
47// DISASM-NEXT: 401036: pushl $0
48// DISASM-NEXT: 40103b: jmp -32 <.plt>
49// DISASM-EMPTY:
50// DISASM-NEXT: 00401040 zed2@plt:
51// DISASM-NEXT: 401040: jmpl *4206608
52// DISASM-NEXT: 401046: pushl $8
53// DISASM-NEXT: 40104b: jmp -48 <.plt>
54
55.text
56.type foo STT_GNU_IFUNC
57.globl foo
58foo:
59 ret
60
61.type bar STT_GNU_IFUNC
62.globl bar
63bar:
64 ret
65
66.globl _start
67_start:
68 call foo@plt
69 call bar@plt
70 call bar2@plt
71 call zed2@plt
deps/lld/test/ELF/gnu-ifunc-noplt.s created+68
...@@ -0,0 +1,68 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-freebsd %S/Inputs/shared2-x86-64.s -o %t1.o
3// RUN: ld.lld %t1.o --shared -o %t.so
4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-freebsd %s -o %t.o
5// RUN: ld.lld -z ifunc-noplt -z notext --hash-style=sysv %t.so %t.o -o %tout
6// RUN: llvm-objdump -d --no-show-raw-insn %tout | FileCheck %s --check-prefix=DISASM
7// RUN: llvm-readobj -r --dynamic-table %tout | FileCheck %s
8
9// Check that we emitted relocations for the ifunc calls
10// CHECK: Relocations [
11// CHECK-NEXT: Section (4) .rela.dyn {
12// CHECK-NEXT: 0x201008 R_X86_64_PLT32 bar 0xFFFFFFFFFFFFFFFC
13// CHECK-NEXT: 0x201003 R_X86_64_PLT32 foo 0xFFFFFFFFFFFFFFFC
14// CHECK-NEXT: }
15// CHECK-NEXT: Section (5) .rela.plt {
16// CHECK-NEXT: 0x203018 R_X86_64_JUMP_SLOT bar2 0x0
17// CHECK-NEXT: 0x203020 R_X86_64_JUMP_SLOT zed2 0x0
18// CHECK-NEXT: }
19
20// Check that ifunc call sites still require relocation
21// DISASM: Disassembly of section .text:
22// DISASM-EMPTY:
23// DISASM-NEXT: 0000000000201000 foo:
24// DISASM-NEXT: 201000: retq
25// DISASM-EMPTY:
26// DISASM-NEXT: 0000000000201001 bar:
27// DISASM-NEXT: 201001: retq
28// DISASM-EMPTY:
29// DISASM-NEXT: 0000000000201002 _start:
30// DISASM-NEXT: 201002: callq 0 <_start+0x5>
31// DISASM-NEXT: 201007: callq 0 <_start+0xa>
32// DISASM-NEXT: 20100c: callq 31 <bar2@plt>
33// DISASM-NEXT: 201011: callq 42 <zed2@plt>
34// DISASM-EMPTY:
35// DISASM-NEXT: Disassembly of section .plt:
36// DISASM-EMPTY:
37// DISASM-NEXT: 0000000000201020 .plt:
38// DISASM-NEXT: 201020: pushq 8162(%rip)
39// DISASM-NEXT: 201026: jmpq *8164(%rip)
40// DISASM-NEXT: 20102c: nopl (%rax)
41// DISASM-EMPTY:
42// DISASM-NEXT: 0000000000201030 bar2@plt:
43// DISASM-NEXT: 201030: jmpq *8162(%rip)
44// DISASM-NEXT: 201036: pushq $0
45// DISASM-NEXT: 20103b: jmp -32 <.plt>
46// DISASM-EMPTY:
47// DISASM-NEXT: 0000000000201040 zed2@plt:
48// DISASM-NEXT: 201040: jmpq *8154(%rip)
49// DISASM-NEXT: 201046: pushq $1
50// DISASM-NEXT: 20104b: jmp -48 <.plt>
51
52.text
53.type foo STT_GNU_IFUNC
54.globl foo
55foo:
56 ret
57
58.type bar STT_GNU_IFUNC
59.globl bar
60bar:
61 ret
62
63.globl _start
64_start:
65 call foo
66 call bar
67 call bar2
68 call zed2
deps/lld/test/ELF/gnu-ifunc-nosym-i386.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
3// RUN: ld.lld -static %t.o -o %tout3// RUN: ld.lld -static %t.o -o %tout
4// RUN: llvm-readobj -symbols %tout | FileCheck %s4// RUN: llvm-readobj --symbols %tout | FileCheck %s
55
6// Check that no __rel_iplt_end/__rel_iplt_start6// Check that no __rel_iplt_end/__rel_iplt_start
7// appear in symtab if there is no references to them.7// appear in symtab if there is no references to them.
deps/lld/test/ELF/gnu-ifunc-nosym.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld -static %t.o -o %tout3// RUN: ld.lld -static %t.o -o %tout
4// RUN: llvm-readobj -symbols %tout | FileCheck %s4// RUN: llvm-readobj --symbols %tout | FileCheck %s
55
6// Check that no __rela_iplt_end/__rela_iplt_start6// Check that no __rela_iplt_end/__rela_iplt_start
7// appear in symtab if there is no references to them.7// appear in symtab if there is no references to them.
deps/lld/test/ELF/gnu-ifunc-plt-i386.s+16-13
...@@ -5,21 +5,21 @@...@@ -5,21 +5,21 @@
5// RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout5// RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout
6// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM6// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
7// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT7// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT
8// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s8// RUN: llvm-readobj -r --dynamic-table %tout | FileCheck %s
99
10// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt10// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt
11// CHECK: Relocations [11// CHECK: Relocations [
12// CHECK-NEXT: Section (4) .rel.plt {12// CHECK-NEXT: Section (4) .rel.plt {
13// CHECK-NEXT: 0x40200C R_386_JUMP_SLOT bar213// CHECK-NEXT: 0x40300C R_386_JUMP_SLOT bar2
14// CHECK-NEXT: 0x402010 R_386_JUMP_SLOT zed214// CHECK-NEXT: 0x403010 R_386_JUMP_SLOT zed2
15// CHECK-NEXT: 0x402014 R_386_IRELATIVE15// CHECK-NEXT: 0x403014 R_386_IRELATIVE
16// CHECK-NEXT: 0x402018 R_386_IRELATIVE16// CHECK-NEXT: 0x403018 R_386_IRELATIVE
1717
18// Check that IRELATIVE .got.plt entries point to ifunc resolver and not18// Check that IRELATIVE .got.plt entries point to ifunc resolver and not
19// back to the plt entry + 6.19// back to the plt entry + 6.
20// GOTPLT: Contents of section .got.plt:20// GOTPLT: Contents of section .got.plt:
21// GOTPLT: 402000 00304000 00000000 00000000 3610400021// GOTPLT: 403000 00204000 00000000 00000000 36104000
22// GOTPLT-NEXT: 402010 46104000 00104000 0110400022// GOTPLT-NEXT: 403010 46104000 00104000 01104000
2323
24// Check that the PLTRELSZ tag includes the IRELATIVE relocations24// Check that the PLTRELSZ tag includes the IRELATIVE relocations
25// CHECK: DynamicSection [25// CHECK: DynamicSection [
...@@ -27,6 +27,7 @@...@@ -27,6 +27,7 @@
2727
28// Check that a PLT header is written and the ifunc entries appear last28// Check that a PLT header is written and the ifunc entries appear last
29// DISASM: Disassembly of section .text:29// DISASM: Disassembly of section .text:
30// DISASM-EMPTY:
30// DISASM-NEXT: foo:31// DISASM-NEXT: foo:
31// DISASM-NEXT: 401000: c3 retl32// DISASM-NEXT: 401000: c3 retl
32// DISASM: bar:33// DISASM: bar:
...@@ -36,28 +37,30 @@...@@ -36,28 +37,30 @@
36// DISASM-NEXT: 401007: e8 54 00 00 00 calll 8437// DISASM-NEXT: 401007: e8 54 00 00 00 calll 84
37// DISASM-NEXT: 40100c: e8 1f 00 00 00 calll 3138// DISASM-NEXT: 40100c: e8 1f 00 00 00 calll 31
38// DISASM-NEXT: 401011: e8 2a 00 00 00 calll 4239// DISASM-NEXT: 401011: e8 2a 00 00 00 calll 42
40// DISASM-EMPTY:
39// DISASM-NEXT: Disassembly of section .plt:41// DISASM-NEXT: Disassembly of section .plt:
42// DISASM-EMPTY:
40// DISASM-NEXT: .plt:43// DISASM-NEXT: .plt:
41// DISASM-NEXT: 401020: ff 35 04 20 40 00 pushl 420250044// DISASM-NEXT: 401020: ff 35 04 30 40 00 pushl 4206596
42// DISASM-NEXT: 401026: ff 25 08 20 40 00 jmpl *420250445// DISASM-NEXT: 401026: ff 25 08 30 40 00 jmpl *4206600
43// DISASM-NEXT: 40102c: 90 nop46// DISASM-NEXT: 40102c: 90 nop
44// DISASM-NEXT: 40102d: 90 nop47// DISASM-NEXT: 40102d: 90 nop
45// DISASM-NEXT: 40102e: 90 nop48// DISASM-NEXT: 40102e: 90 nop
46// DISASM-NEXT: 40102f: 90 nop49// DISASM-NEXT: 40102f: 90 nop
47// DISASM-EMPTY:50// DISASM-EMPTY:
48// DISASM-NEXT: bar2@plt:51// DISASM-NEXT: bar2@plt:
49// DISASM-NEXT: 401030: ff 25 0c 20 40 00 jmpl *420250852// DISASM-NEXT: 401030: ff 25 0c 30 40 00 jmpl *4206604
50// DISASM-NEXT: 401036: 68 00 00 00 00 pushl $053// DISASM-NEXT: 401036: 68 00 00 00 00 pushl $0
51// DISASM-NEXT: 40103b: e9 e0 ff ff ff jmp -32 <.plt>54// DISASM-NEXT: 40103b: e9 e0 ff ff ff jmp -32 <.plt>
52// DISASM-EMPTY:55// DISASM-EMPTY:
53// DISASM-NEXT: zed2@plt:56// DISASM-NEXT: zed2@plt:
54// DISASM-NEXT: 401040: ff 25 10 20 40 00 jmpl *420251257// DISASM-NEXT: 401040: ff 25 10 30 40 00 jmpl *4206608
55// DISASM-NEXT: 401046: 68 08 00 00 00 pushl $858// DISASM-NEXT: 401046: 68 08 00 00 00 pushl $8
56// DISASM-NEXT: 40104b: e9 d0 ff ff ff jmp -48 <.plt>59// DISASM-NEXT: 40104b: e9 d0 ff ff ff jmp -48 <.plt>
57// DISASM-NEXT: 401050: ff 25 14 20 40 00 jmpl *420251660// DISASM-NEXT: 401050: ff 25 14 30 40 00 jmpl *4206612
58// DISASM-NEXT: 401056: 68 30 00 00 00 pushl $4861// DISASM-NEXT: 401056: 68 30 00 00 00 pushl $48
59// DISASM-NEXT: 40105b: e9 e0 ff ff ff jmp -32 <zed2@plt>62// DISASM-NEXT: 40105b: e9 e0 ff ff ff jmp -32 <zed2@plt>
60// DISASM-NEXT: 401060: ff 25 18 20 40 00 jmpl *420252063// DISASM-NEXT: 401060: ff 25 18 30 40 00 jmpl *4206616
61// DISASM-NEXT: 401066: 68 38 00 00 00 pushl $5664// DISASM-NEXT: 401066: 68 38 00 00 00 pushl $56
62// DISASM-NEXT: 40106b: e9 d0 ff ff ff jmp -48 <zed2@plt>65// DISASM-NEXT: 40106b: e9 d0 ff ff ff jmp -48 <zed2@plt>
6366
deps/lld/test/ELF/gnu-ifunc-plt.s+18-15
...@@ -5,22 +5,22 @@...@@ -5,22 +5,22 @@
5// RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout5// RUN: ld.lld --hash-style=sysv %t.so %t.o -o %tout
6// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM6// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
7// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT7// RUN: llvm-objdump -s %tout | FileCheck %s --check-prefix=GOTPLT
8// RUN: llvm-readobj -r -dynamic-table %tout | FileCheck %s8// RUN: llvm-readobj -r --dynamic-table %tout | FileCheck %s
99
10// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt10// Check that the IRELATIVE relocations are after the JUMP_SLOT in the plt
11// CHECK: Relocations [11// CHECK: Relocations [
12// CHECK-NEXT: Section (4) .rela.plt {12// CHECK-NEXT: Section (4) .rela.plt {
13// CHECK-NEXT: 0x202018 R_X86_64_JUMP_SLOT bar2 0x013// CHECK-NEXT: 0x203018 R_X86_64_JUMP_SLOT bar2 0x0
14// CHECK-NEXT: 0x202020 R_X86_64_JUMP_SLOT zed2 0x014// CHECK-NEXT: 0x203020 R_X86_64_JUMP_SLOT zed2 0x0
15// CHECK-NEXT: 0x202028 R_X86_64_IRELATIVE - 0x20100015// CHECK-NEXT: 0x203028 R_X86_64_IRELATIVE - 0x201000
16// CHECK-NEXT: 0x202030 R_X86_64_IRELATIVE - 0x20100116// CHECK-NEXT: 0x203030 R_X86_64_IRELATIVE - 0x201001
1717
18// Check that .got.plt entries point back to PLT header18// Check that .got.plt entries point back to PLT header
19// GOTPLT: Contents of section .got.plt:19// GOTPLT: Contents of section .got.plt:
20// GOTPLT-NEXT: 202000 00302000 00000000 00000000 0000000020// GOTPLT-NEXT: 203000 00202000 00000000 00000000 00000000
21// GOTPLT-NEXT: 202010 00000000 00000000 36102000 0000000021// GOTPLT-NEXT: 203010 00000000 00000000 36102000 00000000
22// GOTPLT-NEXT: 202020 46102000 00000000 56102000 0000000022// GOTPLT-NEXT: 203020 46102000 00000000 56102000 00000000
23// GOTPLT-NEXT: 202030 66102000 0000000023// GOTPLT-NEXT: 203030 66102000 00000000
2424
25// Check that the PLTRELSZ tag includes the IRELATIVE relocations25// Check that the PLTRELSZ tag includes the IRELATIVE relocations
26// CHECK: DynamicSection [26// CHECK: DynamicSection [
...@@ -28,6 +28,7 @@...@@ -28,6 +28,7 @@
2828
29// Check that a PLT header is written and the ifunc entries appear last29// Check that a PLT header is written and the ifunc entries appear last
30// DISASM: Disassembly of section .text:30// DISASM: Disassembly of section .text:
31// DISASM-EMPTY:
31// DISASM-NEXT: foo:32// DISASM-NEXT: foo:
32// DISASM-NEXT: 201000: c3 retq33// DISASM-NEXT: 201000: c3 retq
33// DISASM: bar:34// DISASM: bar:
...@@ -37,25 +38,27 @@...@@ -37,25 +38,27 @@
37// DISASM-NEXT: 201007: e8 54 00 00 00 callq 8438// DISASM-NEXT: 201007: e8 54 00 00 00 callq 84
38// DISASM-NEXT: 20100c: e8 1f 00 00 00 callq 3139// DISASM-NEXT: 20100c: e8 1f 00 00 00 callq 31
39// DISASM-NEXT: 201011: e8 2a 00 00 00 callq 4240// DISASM-NEXT: 201011: e8 2a 00 00 00 callq 42
41// DISASM-EMPTY:
40// DISASM-NEXT: Disassembly of section .plt:42// DISASM-NEXT: Disassembly of section .plt:
43// DISASM-EMPTY:
41// DISASM-NEXT: .plt:44// DISASM-NEXT: .plt:
42// DISASM-NEXT: 201020: ff 35 e2 0f 00 00 pushq 4066(%rip)45// DISASM-NEXT: 201020: ff 35 e2 1f 00 00 pushq 8162(%rip)
43// DISASM-NEXT: 201026: ff 25 e4 0f 00 00 jmpq *4068(%rip)46// DISASM-NEXT: 201026: ff 25 e4 1f 00 00 jmpq *8164(%rip)
44// DISASM-NEXT: 20102c: 0f 1f 40 00 nopl (%rax)47// DISASM-NEXT: 20102c: 0f 1f 40 00 nopl (%rax)
45// DISASM-EMPTY:48// DISASM-EMPTY:
46// DISASM-NEXT: bar2@plt:49// DISASM-NEXT: bar2@plt:
47// DISASM-NEXT: 201030: ff 25 e2 0f 00 00 jmpq *4066(%rip)50// DISASM-NEXT: 201030: ff 25 e2 1f 00 00 jmpq *8162(%rip)
48// DISASM-NEXT: 201036: 68 00 00 00 00 pushq $051// DISASM-NEXT: 201036: 68 00 00 00 00 pushq $0
49// DISASM-NEXT: 20103b: e9 e0 ff ff ff jmp -32 <.plt>52// DISASM-NEXT: 20103b: e9 e0 ff ff ff jmp -32 <.plt>
50// DISASM-EMPTY:53// DISASM-EMPTY:
51// DISASM-NEXT: zed2@plt:54// DISASM-NEXT: zed2@plt:
52// DISASM-NEXT: 201040: ff 25 da 0f 00 00 jmpq *4058(%rip)55// DISASM-NEXT: 201040: ff 25 da 1f 00 00 jmpq *8154(%rip)
53// DISASM-NEXT: 201046: 68 01 00 00 00 pushq $156// DISASM-NEXT: 201046: 68 01 00 00 00 pushq $1
54// DISASM-NEXT: 20104b: e9 d0 ff ff ff jmp -48 <.plt>57// DISASM-NEXT: 20104b: e9 d0 ff ff ff jmp -48 <.plt>
55// DISASM-NEXT: 201050: ff 25 d2 0f 00 00 jmpq *4050(%rip)58// DISASM-NEXT: 201050: ff 25 d2 1f 00 00 jmpq *8146(%rip)
56// DISASM-NEXT: 201056: 68 00 00 00 00 pushq $059// DISASM-NEXT: 201056: 68 00 00 00 00 pushq $0
57// DISASM-NEXT: 20105b: e9 e0 ff ff ff jmp -32 <zed2@plt>60// DISASM-NEXT: 20105b: e9 e0 ff ff ff jmp -32 <zed2@plt>
58// DISASM-NEXT: 201060: ff 25 ca 0f 00 00 jmpq *4042(%rip)61// DISASM-NEXT: 201060: ff 25 ca 1f 00 00 jmpq *8138(%rip)
59// DISASM-NEXT: 201066: 68 01 00 00 00 pushq $162// DISASM-NEXT: 201066: 68 01 00 00 00 pushq $1
60// DISASM-NEXT: 20106b: e9 d0 ff ff ff jmp -48 <zed2@plt>63// DISASM-NEXT: 20106b: e9 d0 ff ff ff jmp -48 <zed2@plt>
6164
deps/lld/test/ELF/gnu-ifunc-relative.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: ld.lld --strip-all %t.o -o %t3// RUN: ld.lld --strip-all %t.o -o %t
4// RUN: llvm-readobj -r %t | FileCheck %s4// RUN: llvm-readobj -r %t | FileCheck %s
5// RUN: ld.lld %t.o -o %t5// RUN: ld.lld %t.o -o %t
6// RUN: llvm-readobj -r -t %t | FileCheck %s --check-prefixes=CHECK,SYM6// RUN: llvm-readobj -r --symbols %t | FileCheck %s --check-prefixes=CHECK,SYM
77
8.type foo STT_GNU_IFUNC8.type foo STT_GNU_IFUNC
9.globl foo9.globl foo
deps/lld/test/ELF/gnu-ifunc-shared.s+11-8
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
7// Check that an IRELATIVE relocation is used for a non-preemptible ifunc7// Check that an IRELATIVE relocation is used for a non-preemptible ifunc
8// handler and a JUMP_SLOT is used for a preemptible ifunc8// handler and a JUMP_SLOT is used for a preemptible ifunc
9// DISASM: Disassembly of section .text:9// DISASM: Disassembly of section .text:
10// DISASM-EMPTY:
10// DISASM-NEXT: fct:11// DISASM-NEXT: fct:
11// DISASM-NEXT: 1000: c3 retq12// DISASM-NEXT: 1000: c3 retq
12// DISASM: fct2:13// DISASM: fct2:
...@@ -18,30 +19,32 @@...@@ -18,30 +19,32 @@
18// DISASM-NEXT: 1011: c3 retq19// DISASM-NEXT: 1011: c3 retq
19// DISASM: f2:20// DISASM: f2:
20// DISASM-NEXT: 1012: c3 retq21// DISASM-NEXT: 1012: c3 retq
22// DISASM-EMPTY:
21// DISASM-NEXT: Disassembly of section .plt:23// DISASM-NEXT: Disassembly of section .plt:
24// DISASM-EMPTY:
22// DISASM-NEXT: .plt:25// DISASM-NEXT: .plt:
23// DISASM-NEXT: 1020: ff 35 e2 0f 00 00 pushq 4066(%rip)26// DISASM-NEXT: 1020: ff 35 e2 1f 00 00 pushq 8162(%rip)
24// DISASM-NEXT: 1026: ff 25 e4 0f 00 00 jmpq *4068(%rip)27// DISASM-NEXT: 1026: ff 25 e4 1f 00 00 jmpq *8164(%rip)
25// DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax)28// DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax)
26// DISASM-EMPTY:29// DISASM-EMPTY:
27// DISASM-NEXT: fct2@plt:30// DISASM-NEXT: fct2@plt:
28// DISASM-NEXT: 1030: ff 25 e2 0f 00 00 jmpq *4066(%rip)31// DISASM-NEXT: 1030: ff 25 e2 1f 00 00 jmpq *8162(%rip)
29// DISASM-NEXT: 1036: 68 00 00 00 00 pushq $032// DISASM-NEXT: 1036: 68 00 00 00 00 pushq $0
30// DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>33// DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>
31// DISASM-EMPTY:34// DISASM-EMPTY:
32// DISASM-NEXT: f2@plt:35// DISASM-NEXT: f2@plt:
33// DISASM-NEXT: 1040: ff 25 da 0f 00 00 jmpq *4058(%rip)36// DISASM-NEXT: 1040: ff 25 da 1f 00 00 jmpq *8154(%rip)
34// DISASM-NEXT: 1046: 68 01 00 00 00 pushq $137// DISASM-NEXT: 1046: 68 01 00 00 00 pushq $1
35// DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>38// DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
36// DISASM-NEXT: 1050: ff 25 d2 0f 00 00 jmpq *4050(%rip)39// DISASM-NEXT: 1050: ff 25 d2 1f 00 00 jmpq *8146(%rip)
37// DISASM-NEXT: 1056: 68 00 00 00 00 pushq $040// DISASM-NEXT: 1056: 68 00 00 00 00 pushq $0
38// DISASM-NEXT: 105b: e9 e0 ff ff ff jmp -32 <f2@plt>41// DISASM-NEXT: 105b: e9 e0 ff ff ff jmp -32 <f2@plt>
3942
40// CHECK: Relocations [43// CHECK: Relocations [
41// CHECK-NEXT: Section (4) .rela.plt {44// CHECK-NEXT: Section (4) .rela.plt {
42// CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT fct2 0x045// CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT fct2 0x0
43// CHECK-NEXT: 0x2020 R_X86_64_JUMP_SLOT f2 0x046// CHECK-NEXT: 0x3020 R_X86_64_JUMP_SLOT f2 0x0
44// CHECK-NEXT: 0x2028 R_X86_64_IRELATIVE - 0x100047// CHECK-NEXT: 0x3028 R_X86_64_IRELATIVE - 0x1000
4548
46 // Hidden expect IRELATIVE49 // Hidden expect IRELATIVE
47 .globl fct50 .globl fct
deps/lld/test/ELF/gnu-ifunc.s+4-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld -static %t.o -o %tout3// RUN: ld.lld -static %t.o -o %tout
4// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM4// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DISASM
5// RUN: llvm-readobj -r -symbols -sections %tout | FileCheck %s5// RUN: llvm-readobj -r --symbols --sections %tout | FileCheck %s
66
7// CHECK: Sections [7// CHECK: Sections [
8// CHECK: Section {8// CHECK: Section {
...@@ -90,6 +90,7 @@...@@ -90,6 +90,7 @@
90// CHECK-NEXT: ]90// CHECK-NEXT: ]
9191
92// DISASM: Disassembly of section .text:92// DISASM: Disassembly of section .text:
93// DISASM-EMPTY:
93// DISASM-NEXT: foo:94// DISASM-NEXT: foo:
94// DISASM-NEXT: 201000: {{.*}} retq95// DISASM-NEXT: 201000: {{.*}} retq
95// DISASM: bar:96// DISASM: bar:
...@@ -100,7 +101,9 @@...@@ -100,7 +101,9 @@
100// DISASM-NEXT: 20100c: {{.*}} movl $2097496, %edx101// DISASM-NEXT: 20100c: {{.*}} movl $2097496, %edx
101// DISASM-NEXT: 201011: {{.*}} movl $2097544, %edx102// DISASM-NEXT: 201011: {{.*}} movl $2097544, %edx
102// DISASM-NEXT: 201016: {{.*}} movl $2097545, %edx103// DISASM-NEXT: 201016: {{.*}} movl $2097545, %edx
104// DISASM-EMPTY:
103// DISASM-NEXT: Disassembly of section .plt:105// DISASM-NEXT: Disassembly of section .plt:
106// DISASM-EMPTY:
104// DISASM-NEXT: .plt:107// DISASM-NEXT: .plt:
105// DISASM-NEXT: 201020: {{.*}} jmpq *4058(%rip)108// DISASM-NEXT: 201020: {{.*}} jmpq *4058(%rip)
106// DISASM-NEXT: 201026: {{.*}} pushq $0109// DISASM-NEXT: 201026: {{.*}} pushq $0
deps/lld/test/ELF/gnu-unique.s+3-3
...@@ -2,12 +2,12 @@...@@ -2,12 +2,12 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
3//3//
4// RUN: ld.lld %t -shared -o %tout.so4// RUN: ld.lld %t -shared -o %tout.so
5// RUN: llvm-readobj -dyn-symbols %tout.so | FileCheck -check-prefix=GNU %s5// RUN: llvm-readobj --dyn-syms %tout.so | FileCheck -check-prefix=GNU %s
6// RUN: ld.lld %t -shared -o %tout.so --gnu-unique6// RUN: ld.lld %t -shared -o %tout.so --gnu-unique
7// RUN: llvm-readobj -dyn-symbols %tout.so | FileCheck -check-prefix=GNU %s7// RUN: llvm-readobj --dyn-syms %tout.so | FileCheck -check-prefix=GNU %s
8//8//
9// RUN: ld.lld %t -shared -o %tout.so --no-gnu-unique9// RUN: ld.lld %t -shared -o %tout.so --no-gnu-unique
10// RUN: llvm-readobj -dyn-symbols %tout.so | FileCheck -check-prefix=NO %s10// RUN: llvm-readobj --dyn-syms %tout.so | FileCheck -check-prefix=NO %s
1111
12// Check that STB_GNU_UNIQUE is treated as a global and ends up in the dynamic12// Check that STB_GNU_UNIQUE is treated as a global and ends up in the dynamic
13// symbol table as STB_GNU_UNIQUE.13// symbol table as STB_GNU_UNIQUE.
deps/lld/test/ELF/gnustack.s+3-3
...@@ -2,13 +2,13 @@...@@ -2,13 +2,13 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t12# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
33
4# RUN: ld.lld %t1 -z execstack -o %t4# RUN: ld.lld %t1 -z execstack -o %t
5# RUN: llvm-readobj --program-headers -s %t | FileCheck --check-prefix=RWX %s5# RUN: llvm-readobj --program-headers -S %t | FileCheck --check-prefix=RWX %s
66
7# RUN: ld.lld %t1 -o %t7# RUN: ld.lld %t1 -o %t
8# RUN: llvm-readobj --program-headers -s %t | FileCheck --check-prefix=RW %s8# RUN: llvm-readobj --program-headers -S %t | FileCheck --check-prefix=RW %s
99
10# RUN: ld.lld %t1 -o %t -z noexecstack10# RUN: ld.lld %t1 -o %t -z noexecstack
11# RUN: llvm-readobj --program-headers -s %t | FileCheck --check-prefix=RW %s11# RUN: llvm-readobj --program-headers -S %t | FileCheck --check-prefix=RW %s
1212
13# RW: Type: PT_GNU_STACK13# RW: Type: PT_GNU_STACK
14# RW-NEXT: Offset: 0x014# RW-NEXT: Offset: 0x0
deps/lld/test/ELF/got-aarch64.s deleted-40
...@@ -1,40 +0,0 @@
1// REQUIRES: aarch64
2// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.o
3// RUN: ld.lld --hash-style=sysv -shared %t.o -o %t.so
4// RUN: llvm-readobj -s -r %t.so | FileCheck %s
5// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s
6
7// CHECK: Name: .got
8// CHECK-NEXT: Type: SHT_PROGBITS
9// CHECK-NEXT: Flags [
10// CHECK-NEXT: SHF_ALLOC
11// CHECK-NEXT: SHF_WRITE
12// CHECK-NEXT: ]
13// CHECK-NEXT: Address: 0x30090
14// CHECK-NEXT: Offset:
15// CHECK-NEXT: Size: 8
16// CHECK-NEXT: Link: 0
17// CHECK-NEXT: Info: 0
18// CHECK-NEXT: AddressAlignment: 8
19
20// CHECK: Relocations [
21// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
22// CHECK-NEXT: 0x30090 R_AARCH64_GLOB_DAT dat 0x0
23// CHECK-NEXT: }
24// CHECK-NEXT: ]
25
26// Page(0x20098) - Page(0x10000) = 0x10000 = 65536
27// 0x20098 & 0xff8 = 0x98 = 152
28
29// DISASM: main:
30// DISASM-NEXT: 10000: 00 01 00 90 adrp x0, #131072
31// DISASM-NEXT: 10004: 00 48 40 f9 ldr x0, [x0, #144]
32
33.global main,foo,dat
34.text
35main:
36 adrp x0, :got:dat
37 ldr x0, [x0, :got_lo12:dat]
38.data
39dat:
40 .word 42
deps/lld/test/ELF/got-i386.s+9-8
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t3// RUN: ld.lld %t.o -o %t
4// RUN: llvm-readobj -s -r -t %t | FileCheck %s4// RUN: llvm-readobj -S -r --symbols %t | FileCheck %s
5// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s5// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
66
7// CHECK: Name: .got7// CHECK: Name: .got.plt
8// CHECK-NEXT: Type: SHT_PROGBITS8// CHECK-NEXT: Type: SHT_PROGBITS
9// CHECK-NEXT: Flags [9// CHECK-NEXT: Flags [
10// CHECK-NEXT: SHF_ALLOC10// CHECK-NEXT: SHF_ALLOC
...@@ -12,14 +12,14 @@...@@ -12,14 +12,14 @@
12// CHECK-NEXT: ]12// CHECK-NEXT: ]
13// CHECK-NEXT: Address: 0x40200013// CHECK-NEXT: Address: 0x402000
14// CHECK-NEXT: Offset:14// CHECK-NEXT: Offset:
15// CHECK-NEXT: Size: 015// CHECK-NEXT: Size:
16// CHECK-NEXT: Link:16// CHECK-NEXT: Link:
17// CHECK-NEXT: Info:17// CHECK-NEXT: Info:
18// CHECK-NEXT: AddressAlignment:18// CHECK-NEXT: AddressAlignment:
1919
20// CHECK: Symbol {20// CHECK: Symbol {
21// CHECK: Name: bar21// CHECK: Name: bar
22// CHECK-NEXT: Value: 0x40200022// CHECK-NEXT: Value: 0x40200C
23// CHECK-NEXT: Size: 1023// CHECK-NEXT: Size: 10
24// CHECK-NEXT: Binding: Global24// CHECK-NEXT: Binding: Global
25// CHECK-NEXT: Type: Object25// CHECK-NEXT: Type: Object
...@@ -28,7 +28,7 @@...@@ -28,7 +28,7 @@
28// CHECK-NEXT: }28// CHECK-NEXT: }
29// CHECK-NEXT: Symbol {29// CHECK-NEXT: Symbol {
30// CHECK-NEXT: Name: obj30// CHECK-NEXT: Name: obj
31// CHECK-NEXT: Value: 0x40200A31// CHECK-NEXT: Value: 0x402016
32// CHECK-NEXT: Size: 1032// CHECK-NEXT: Size: 10
33// CHECK-NEXT: Binding: Global33// CHECK-NEXT: Binding: Global
34// CHECK-NEXT: Type: Object34// CHECK-NEXT: Type: Object
...@@ -40,10 +40,11 @@...@@ -40,10 +40,11 @@
40// 0x40200A - 10 = addr(.got) = 0x40200040// 0x40200A - 10 = addr(.got) = 0x402000
41// 0x40200A + 5 - 15 = addr(.got) = 0x40200041// 0x40200A + 5 - 15 = addr(.got) = 0x402000
42// DISASM: Disassembly of section .text:42// DISASM: Disassembly of section .text:
43// DISASM-EMPTY:
43// DISASM-NEXT: _start:44// DISASM-NEXT: _start:
44// DISASM-NEXT: 401000: c7 81 00 00 00 00 01 00 00 00 movl $1, (%ecx)45// DISASM-NEXT: 401000: c7 81 0c 00 00 00 01 00 00 00 movl $1, 12(%ecx)
45// DISASM-NEXT: 40100a: c7 81 0a 00 00 00 02 00 00 00 movl $2, 10(%ecx)46// DISASM-NEXT: 40100a: c7 81 16 00 00 00 02 00 00 00 movl $2, 22(%ecx)
46// DISASM-NEXT: 401014: c7 81 0f 00 00 00 03 00 00 00 movl $3, 15(%ecx)47// DISASM-NEXT: 401014: c7 81 1b 00 00 00 03 00 00 00 movl $3, 27(%ecx)
4748
48.global _start49.global _start
49_start:50_start:
deps/lld/test/ELF/got-plt-header.s+11-11
...@@ -1,31 +1,31 @@...@@ -1,31 +1,31 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s4// RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
55
6 call foo@plt6 call foo@plt
77
8// Check that the first .got.plt entry has the address of the dynamic table.8// Check that the first .got.plt entry has the address of the dynamic table.
99
10// CHECK: Type: SHT_DYNAMIC
11// CHECK-NEXT: Flags [
12// CHECK-NEXT: SHF_ALLOC
13// CHECK-NEXT: SHF_WRITE
14// CHECK-NEXT: ]
15// CHECK-NEXT: Address: 0x2000
16
10// CHECK: Name: .got.plt17// CHECK: Name: .got.plt
11// CHECK-NEXT: Type: SHT_PROGBITS18// CHECK-NEXT: Type: SHT_PROGBITS
12// CHECK-NEXT: Flags [19// CHECK-NEXT: Flags [
13// CHECK-NEXT: SHF_ALLOC20// CHECK-NEXT: SHF_ALLOC
14// CHECK-NEXT: SHF_WRITE21// CHECK-NEXT: SHF_WRITE
15// CHECK-NEXT: ]22// CHECK-NEXT: ]
16// CHECK-NEXT: Address: 0x200023// CHECK-NEXT: Address: 0x3000
17// CHECK-NEXT: Offset: 0x200024// CHECK-NEXT: Offset: 0x3000
18// CHECK-NEXT: Size: 3225// CHECK-NEXT: Size: 32
19// CHECK-NEXT: Link: 026// CHECK-NEXT: Link: 0
20// CHECK-NEXT: Info: 027// CHECK-NEXT: Info: 0
21// CHECK-NEXT: AddressAlignment: 828// CHECK-NEXT: AddressAlignment: 8
22// CHECK-NEXT: EntrySize: 029// CHECK-NEXT: EntrySize: 0
23// CHECK-NEXT: SectionData (30// CHECK-NEXT: SectionData (
24// CHECK-NEXT: 0000: 00300000 00000000 00000000 0000000031// CHECK-NEXT: 0000: 00200000 00000000 00000000 00000000
25
26// CHECK: Type: SHT_DYNAMIC
27// CHECK-NEXT: Flags [
28// CHECK-NEXT: SHF_ALLOC
29// CHECK-NEXT: SHF_WRITE
30// CHECK-NEXT: ]
31// CHECK-NEXT: Address: 0x3000
deps/lld/test/ELF/got.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t2.so4// RUN: ld.lld -shared %t2.o -o %t2.so
5// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t5// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t
6// RUN: llvm-readobj -s -r %t | FileCheck %s6// RUN: llvm-readobj -S -r %t | FileCheck %s
7// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s7// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
88
9// CHECK: Name: .got9// CHECK: Name: .got
deps/lld/test/ELF/got32-i386.s+1-1
...@@ -16,7 +16,7 @@ _start:...@@ -16,7 +16,7 @@ _start:
16# CHECK: _start:16# CHECK: _start:
17# CHECK-NEXT: 401001: 8b 1d {{.*}} movl 4202496, %ebx17# CHECK-NEXT: 401001: 8b 1d {{.*}} movl 4202496, %ebx
18# CHECK: Sections:18# CHECK: Sections:
19# CHECK: Name Size Address19# CHECK: Name Size VMA
20# CHECK: .got 00000004 000000000040200020# CHECK: .got 00000004 0000000000402000
2121
22# RUN: not ld.lld %t.o -o %t -pie 2>&1 | FileCheck %s --check-prefix=ERR22# RUN: not ld.lld %t.o -o %t -pie 2>&1 | FileCheck %s --check-prefix=ERR
deps/lld/test/ELF/got32x-i386.s+6-6
...@@ -33,13 +33,13 @@...@@ -33,13 +33,13 @@
3333
34## 73728 == 0x12000 == ADDR(.got)34## 73728 == 0x12000 == ADDR(.got)
35# CHECK: _start:35# CHECK: _start:
36# CHECK-NEXT: 401001: 8b 05 {{.*}} movl 4206592, %eax36# CHECK-NEXT: 401001: 8b 05 {{.*}} movl 4202496, %eax
37# CHECK-NEXT: 401007: 8b 1d {{.*}} movl 4206592, %ebx37# CHECK-NEXT: 401007: 8b 1d {{.*}} movl 4202496, %ebx
38# CHECK-NEXT: 40100d: 8b 80 {{.*}} movl -4(%eax), %eax38# CHECK-NEXT: 40100d: 8b 80 {{.*}} movl -4096(%eax), %eax
39# CHECK-NEXT: 401013: 8b 83 {{.*}} movl -4(%ebx), %eax39# CHECK-NEXT: 401013: 8b 83 {{.*}} movl -4096(%ebx), %eax
40# CHECK: Sections:40# CHECK: Sections:
41# CHECK: Name Size Address41# CHECK: Name Size VMA
42# CHECK: .got 00000004 000000000040300042# CHECK: .got.plt 0000000c 0000000000403000
4343
44# RUN: not ld.lld %S/Inputs/i386-got32x-baseless.elf -o %t1 -pie 2>&1 | \44# RUN: not ld.lld %S/Inputs/i386-got32x-baseless.elf -o %t1 -pie 2>&1 | \
45# RUN: FileCheck %s --check-prefix=ERR45# RUN: FileCheck %s --check-prefix=ERR
deps/lld/test/ELF/gotpc-relax-nopic.s+16-14
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: ld.lld --hash-style=sysv %t.o -o %t13# RUN: ld.lld --hash-style=sysv %t.o -o %t1
4# RUN: llvm-readobj -symbols -r %t1 | FileCheck --check-prefix=SYMRELOC %s4# RUN: llvm-readobj --symbols -r %t1 | FileCheck --check-prefix=SYMRELOC %s
5# RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s5# RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
66
7## There is no relocations.7## There is no relocations.
...@@ -14,6 +14,7 @@...@@ -14,6 +14,7 @@
1414
15## 2105344 = 0x202000 (bar)15## 2105344 = 0x202000 (bar)
16# DISASM: Disassembly of section .text:16# DISASM: Disassembly of section .text:
17# DISASM-EMPTY:
17# DISASM-NEXT: _start:18# DISASM-NEXT: _start:
18# DISASM-NEXT: 201000: {{.*}} adcq $2105344, %rax19# DISASM-NEXT: 201000: {{.*}} adcq $2105344, %rax
19# DISASM-NEXT: 201007: {{.*}} addq $2105344, %rbx20# DISASM-NEXT: 201007: {{.*}} addq $2105344, %rbx
...@@ -26,7 +27,7 @@...@@ -26,7 +27,7 @@
26# DISASM-NEXT: 201038: {{.*}} testq $2105344, %r1527# DISASM-NEXT: 201038: {{.*}} testq $2105344, %r15
2728
28# RUN: ld.lld --hash-style=sysv -shared %t.o -o %t229# RUN: ld.lld --hash-style=sysv -shared %t.o -o %t2
29# RUN: llvm-readobj -s -r -d %t2 | FileCheck --check-prefix=SEC-PIC %s30# RUN: llvm-readobj -S -r -d %t2 | FileCheck --check-prefix=SEC-PIC %s
30# RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM-PIC %s31# RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM-PIC %s
31# SEC-PIC: Section {32# SEC-PIC: Section {
32# SEC-PIC: Index:33# SEC-PIC: Index:
...@@ -36,8 +37,8 @@...@@ -36,8 +37,8 @@
36# SEC-PIC-NEXT: SHF_ALLOC37# SEC-PIC-NEXT: SHF_ALLOC
37# SEC-PIC-NEXT: SHF_WRITE38# SEC-PIC-NEXT: SHF_WRITE
38# SEC-PIC-NEXT: ]39# SEC-PIC-NEXT: ]
39# SEC-PIC-NEXT: Address: 0x30A040# SEC-PIC-NEXT: Address: 0x20A0
40# SEC-PIC-NEXT: Offset: 0x30A041# SEC-PIC-NEXT: Offset: 0x20A0
41# SEC-PIC-NEXT: Size: 842# SEC-PIC-NEXT: Size: 8
42# SEC-PIC-NEXT: Link:43# SEC-PIC-NEXT: Link:
43# SEC-PIC-NEXT: Info:44# SEC-PIC-NEXT: Info:
...@@ -46,7 +47,7 @@...@@ -46,7 +47,7 @@
46# SEC-PIC-NEXT: }47# SEC-PIC-NEXT: }
47# SEC-PIC: Relocations [48# SEC-PIC: Relocations [
48# SEC-PIC-NEXT: Section ({{.*}}) .rela.dyn {49# SEC-PIC-NEXT: Section ({{.*}}) .rela.dyn {
49# SEC-PIC-NEXT: 0x30A0 R_X86_64_RELATIVE - 0x200050# SEC-PIC-NEXT: 0x20A0 R_X86_64_RELATIVE - 0x3000
50# SEC-PIC-NEXT: }51# SEC-PIC-NEXT: }
51# SEC-PIC-NEXT: ]52# SEC-PIC-NEXT: ]
52# SEC-PIC: 0x000000006FFFFFF9 RELACOUNT 153# SEC-PIC: 0x000000006FFFFFF9 RELACOUNT 1
...@@ -55,16 +56,17 @@...@@ -55,16 +56,17 @@
55## Ex: 0x1000 + 4249 + 7 = 0x20A056## Ex: 0x1000 + 4249 + 7 = 0x20A0
56## 0x102a + 4207 + 7 = 0x20A057## 0x102a + 4207 + 7 = 0x20A0
57# DISASM-PIC: Disassembly of section .text:58# DISASM-PIC: Disassembly of section .text:
59# DISASM-PIC-EMPTY:
58# DISASM-PIC-NEXT: _start:60# DISASM-PIC-NEXT: _start:
59# DISASM-PIC-NEXT: 1000: {{.*}} adcq 8345(%rip), %rax61# DISASM-PIC-NEXT: 1000: {{.*}} adcq 4249(%rip), %rax
60# DISASM-PIC-NEXT: 1007: {{.*}} addq 8338(%rip), %rbx62# DISASM-PIC-NEXT: 1007: {{.*}} addq 4242(%rip), %rbx
61# DISASM-PIC-NEXT: 100e: {{.*}} andq 8331(%rip), %rcx63# DISASM-PIC-NEXT: 100e: {{.*}} andq 4235(%rip), %rcx
62# DISASM-PIC-NEXT: 1015: {{.*}} cmpq 8324(%rip), %rdx64# DISASM-PIC-NEXT: 1015: {{.*}} cmpq 4228(%rip), %rdx
63# DISASM-PIC-NEXT: 101c: {{.*}} orq 8317(%rip), %rdi65# DISASM-PIC-NEXT: 101c: {{.*}} orq 4221(%rip), %rdi
64# DISASM-PIC-NEXT: 1023: {{.*}} sbbq 8310(%rip), %rsi66# DISASM-PIC-NEXT: 1023: {{.*}} sbbq 4214(%rip), %rsi
65# DISASM-PIC-NEXT: 102a: {{.*}} subq 8303(%rip), %rbp67# DISASM-PIC-NEXT: 102a: {{.*}} subq 4207(%rip), %rbp
66# DISASM-PIC-NEXT: 1031: {{.*}} xorq 8296(%rip), %r868# DISASM-PIC-NEXT: 1031: {{.*}} xorq 4200(%rip), %r8
67# DISASM-PIC-NEXT: 1038: {{.*}} testq %r15, 8289(%rip)69# DISASM-PIC-NEXT: 1038: {{.*}} testq %r15, 4193(%rip)
6870
69.data71.data
70.type bar, @object72.type bar, @object
deps/lld/test/ELF/gotpc-relax-und-dso.s+2-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux %S/Inputs/gotpc-relax-und-dso.s -o %tdso.o3# RUN: llvm-mc -filetype=obj -relax-relocations -triple=x86_64-pc-linux %S/Inputs/gotpc-relax-und-dso.s -o %tdso.o
4# RUN: ld.lld -shared %tdso.o -o %t.so4# RUN: ld.lld -shared %tdso.o -o %t.so
5# RUN: ld.lld --hash-style=sysv -shared %t.o %t.so -o %tout5# RUN: ld.lld --hash-style=sysv -shared %t.o %t.so -o %tout
6# RUN: llvm-readobj -r -s %tout | FileCheck --check-prefix=RELOC %s6# RUN: llvm-readobj -r -S %tout | FileCheck --check-prefix=RELOC %s
7# RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s7# RUN: llvm-objdump -d %tout | FileCheck --check-prefix=DISASM %s
88
9# RELOC: Relocations [9# RELOC: Relocations [
...@@ -17,6 +17,7 @@...@@ -17,6 +17,7 @@
17# 0x101e + 7 - 36 = 0x100117# 0x101e + 7 - 36 = 0x1001
18# 0x1025 + 7 - 43 = 0x100118# 0x1025 + 7 - 43 = 0x1001
19# DISASM: Disassembly of section .text:19# DISASM: Disassembly of section .text:
20# DISASM-EMPTY:
20# DISASM-NEXT: foo:21# DISASM-NEXT: foo:
21# DISASM-NEXT: nop22# DISASM-NEXT: nop
22# DISASM: hid:23# DISASM: hid:
deps/lld/test/ELF/gotpc-relax.s+1
...@@ -13,6 +13,7 @@...@@ -13,6 +13,7 @@
13# 0x201011 + 7 - 23 = 0x20100113# 0x201011 + 7 - 23 = 0x201001
14# 0x201018 + 7 - 30 = 0x20100114# 0x201018 + 7 - 30 = 0x201001
15# DISASM: Disassembly of section .text:15# DISASM: Disassembly of section .text:
16# DISASM-EMPTY:
16# DISASM-NEXT: foo:17# DISASM-NEXT: foo:
17# DISASM-NEXT: 201000: 90 nop18# DISASM-NEXT: 201000: 90 nop
18# DISASM: hid:19# DISASM: hid:
deps/lld/test/ELF/gotpcrelx.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: %s -o %t.o3// RUN: %s -o %t.o
4// RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELS %s4// RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELS %s
5// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared5// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
6// RUN: llvm-readobj -s -r %t.so | FileCheck %s6// RUN: llvm-readobj -S -r %t.so | FileCheck %s
77
8movq foo@GOTPCREL(%rip), %rax8movq foo@GOTPCREL(%rip), %rax
9movq bar@GOTPCREL(%rip), %rax9movq bar@GOTPCREL(%rip), %rax
deps/lld/test/ELF/hexagon-shared.s+7-7
...@@ -25,22 +25,22 @@ jumpr r0...@@ -25,22 +25,22 @@ jumpr r0
25# R_HEX_GOT_16_X25# R_HEX_GOT_16_X
26r0 = add(r1,##bar@GOT)26r0 = add(r1,##bar@GOT)
2727
28# PLT: { immext(#6547228# PLT: { immext(#131008
29# PLT: r28 = add(pc,##65488) }29# PLT: r28 = add(pc,##131024) }
30# PLT: { r14 -= add(r28,#16)30# PLT: { r14 -= add(r28,#16)
31# PLT: r15 = memw(r28+#8)31# PLT: r15 = memw(r28+#8)
32# PLT: r28 = memw(r28+#4) }32# PLT: r28 = memw(r28+#4) }
33# PLT: { r14 = asr(r14,#2)33# PLT: { r14 = asr(r14,#2)
34# PLT: jumpr r28 }34# PLT: jumpr r28 }
35# PLT: { trap0(#219) }35# PLT: { trap0(#219) }
36# PLT: immext(#65472)36# PLT: immext(#131008)
37# PLT: r14 = add(pc,##65472) }37# PLT: r14 = add(pc,##131008) }
38# PLT: r28 = memw(r14+#0) }38# PLT: r28 = memw(r14+#0) }
39# PLT: jumpr r28 }39# PLT: jumpr r28 }
4040
41# TEXT: 10000: 00 00 02 00 0002000041# TEXT: 10000: 00 00 01 00 00010000
42# TEXT: { call 0x10050 }42# TEXT: { call 0x10050 }
43# TEXT: r0 = add(r1,##65664) }43# TEXT: r0 = add(r1,##-65408) }
4444
45# GOT: .got:45# GOT: .got:
46# GOT: 30080: 00 00 00 00 00000000 <unknown>46# GOT: 20080: 00 00 00 00 00000000 <unknown>
deps/lld/test/ELF/hidden-shared-err.s+1-1
...@@ -11,7 +11,7 @@...@@ -11,7 +11,7 @@
11# RUN: not ld.lld %t.o %t3.o %t2.so -o %t 2>&1 | FileCheck %s11# RUN: not ld.lld %t.o %t3.o %t2.so -o %t 2>&1 | FileCheck %s
12# RUN: not ld.lld %t3.o %t.o %t2.so -o %t 2>&1 | FileCheck %s12# RUN: not ld.lld %t3.o %t.o %t2.so -o %t 2>&1 | FileCheck %s
1313
14# CHECK: undefined symbol: foo14# CHECK: undefined hidden symbol: foo
1515
16.global _start16.global _start
17_start:17_start:
deps/lld/test/ELF/i386-cet.s created+47
...@@ -0,0 +1,47 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %s -o %t.o
3# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %p/Inputs/i386-cet1.s -o %t1.o
4# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %p/Inputs/i386-cet2.s -o %t2.o
5# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %p/Inputs/i386-cet3.s -o %t3.o
6# RUN: llvm-mc -filetype=obj -triple=i386-unknown-linux %p/Inputs/i386-cet4.s -o %t4.o
7
8# RUN: ld.lld -e func1 %t.o %t1.o -o %t
9# RUN: llvm-readelf -n %t | FileCheck -check-prefix=CET -match-full-lines %s
10
11# RUN: ld.lld -e func1 %t.o %t2.o -o %t
12# RUN: llvm-readelf -n %t | FileCheck -check-prefix=CET -match-full-lines %s
13
14# CET: Properties: x86 feature: IBT, SHSTK
15
16# RUN: ld.lld -e func1 %t.o %t3.o -o %t
17# RUN: llvm-readelf -S %t | FileCheck -check-prefix=NOCET %s
18
19# NOCET: Section Headers
20# NOCET-NOT: .note.gnu.property
21
22# RUN: not ld.lld -e func1 %t.o %t3.o -o %t --require-cet 2>&1 \
23# RUN: | FileCheck -check-prefix=ERROR %s
24# ERROR: i386-cet.s.tmp3.o: --require-cet: file is not compatible with CET
25
26# RUN: ld.lld -e func1 %t.o %t4.o -o %t
27# RUN: llvm-readelf -n %t | FileCheck -check-prefix=NOSHSTK -match-full-lines %s
28
29# Check .note.gnu.protery without property SHSTK.
30# NOSHSTK: Properties: x86 feature: IBT
31
32.section ".note.gnu.property", "a"
33.long 4
34.long 0xc
35.long 0x5
36.asciz "GNU"
37
38.long 0xc0000002
39.long 4
40.long 3
41
42.text
43.globl func1
44.type func1,@function
45func1:
46 call func2
47 ret
deps/lld/test/ELF/i386-debug-noabs.test+2-2
...@@ -29,5 +29,5 @@ Sections:...@@ -29,5 +29,5 @@ Sections:
29 Symbol: _GLOBAL_OFFSET_TABLE_29 Symbol: _GLOBAL_OFFSET_TABLE_
30 Type: R_386_GOTPC30 Type: R_386_GOTPC
31Symbols:31Symbols:
32 Global:32 - Name: _GLOBAL_OFFSET_TABLE_
33 - Name: _GLOBAL_OFFSET_TABLE_33 Binding: STB_GLOBAL
deps/lld/test/ELF/i386-got-and-copy.s+1-1
...@@ -14,8 +14,8 @@...@@ -14,8 +14,8 @@
1414
15# CHECK: Relocations [15# CHECK: Relocations [
16# CHECK-NEXT: Section (4) .rel.dyn {16# CHECK-NEXT: Section (4) .rel.dyn {
17# CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_COPY foo
18# CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_GLOB_DAT foo17# CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_GLOB_DAT foo
18# CHECK-NEXT: 0x{{[0-9A-F]+}} R_386_COPY foo
19# CHECK-NEXT: }19# CHECK-NEXT: }
20# CHECK-NEXT: ]20# CHECK-NEXT: ]
2121
deps/lld/test/ELF/i386-gotoff-shared.s+4-12
...@@ -1,23 +1,15 @@...@@ -1,23 +1,15 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
4// RUN: llvm-readobj -s %t.so | FileCheck %s4// RUN: llvm-readelf -S %t.so | FileCheck %s
5// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s5// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s
66
7bar:7bar:
8 movl bar@GOTOFF(%ebx), %eax8 movl bar@GOTOFF(%ebx), %eax
9 mov bar@GOT, %eax9 mov bar@GOT, %eax
1010
11// CHECK: Name: .got11// CHECK: .got.plt PROGBITS 00003000
12// CHECK-NEXT: Type: SHT_PROGBITS
13// CHECK-NEXT: Flags [
14// CHECK-NEXT: SHF_ALLOC
15// CHECK-NEXT: SHF_WRITE
16// CHECK-NEXT: ]
17// CHECK-NEXT: Address: 0x2050
18// CHECK-NEXT: Offset: 0x2050
19// CHECK-NEXT: Size: 4
2012
21// 0x1000 - (0x2050 + 4) = -418013// 0x1000 - 0x3000 (.got.plt) = -8192
2214
23// DISASM: 1000: {{.*}} movl -4180(%ebx), %eax15// DISASM: 1000: {{.*}} movl -8192(%ebx), %eax
deps/lld/test/ELF/i386-gotpc-dynamic.s+4-19
...@@ -1,28 +1,13 @@...@@ -1,28 +1,13 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
3# RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared3# RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
4# RUN: llvm-readobj -s %t.so | FileCheck %s4# RUN: llvm-readelf -S %t.so | FileCheck %s
5# RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s5# RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s
66
7# CHECK: Section {7# CHECK: .got.plt PROGBITS 00003000
8# CHECK: Index: 7
9# CHECK-NEXT: Name: .got
10# CHECK-NEXT: Type: SHT_PROGBITS
11# CHECK-NEXT: Flags [
12# CHECK-NEXT: SHF_ALLOC
13# CHECK-NEXT: SHF_WRITE
14# CHECK-NEXT: ]
15# CHECK-NEXT: Address: 0x2030
16# CHECK-NEXT: Offset:
17# CHECK-NEXT: Size:
18# CHECK-NEXT: Link:
19# CHECK-NEXT: Info:
20# CHECK-NEXT: AddressAlignment:
21# CHECK-NEXT: EntrySize:
22# CHECK-NEXT: }
238
24## 0x1000 + 4144 = 0x20309## 0x3000 - 0x1000 = 8192
25# DISASM: 1000: {{.*}} movl $4144, %eax10# DISASM: 1000: {{.*}} movl $8192, %eax
2611
27.section .foo,"ax",@progbits12.section .foo,"ax",@progbits
28foo:13foo:
deps/lld/test/ELF/i386-gotpc.s+5-18
...@@ -1,28 +1,15 @@...@@ -1,28 +1,15 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
4// RUN: llvm-readobj -s %t.so | FileCheck %s4// RUN: llvm-readelf -S %t.so | FileCheck %s
5// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s5// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASM %s
66
7movl $_GLOBAL_OFFSET_TABLE_, %eax7movl $_GLOBAL_OFFSET_TABLE_, %eax
88
9// CHECK: Name: .got.plt9// CHECK: .got.plt PROGBITS 00003000
10// CHECK-NEXT: Type: SHT_PROGBITS
11// CHECK-NEXT: Flags [
12// CHECK-NEXT: SHF_ALLOC
13// CHECK-NEXT: SHF_WRITE
14// CHECK-NEXT: ]
15// CHECK-NEXT: Address: 0x2000
16
17// CHECK: Name: .got
18// CHECK-NEXT: Type: SHT_PROGBITS
19// CHECK-NEXT: Flags [
20// CHECK-NEXT: SHF_ALLOC
21// CHECK-NEXT: SHF_WRITE
22// CHECK-NEXT: ]
23// CHECK-NEXT: Address: 0x3030
2410
25// DISASM: Disassembly of section .text:11// DISASM: Disassembly of section .text:
12// DISASM-EMPTY:
26// DISASM-NEXT: .text:13// DISASM-NEXT: .text:
27// DISASM-NEXT: 1000: {{.*}} movl $8240, %eax14// DISASM-NEXT: 1000: {{.*}} movl $8192, %eax
28// 0x3030 - 0x1000 = 0x203015// 0x3000 (.got.plt) - 0x1000 = 8192
deps/lld/test/ELF/i386-merge.s+5-5
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t -shared3// RUN: ld.lld %t.o -o %t -shared
4// RUN: llvm-readobj -s -section-data %t | FileCheck %s4// RUN: llvm-readobj -S --section-data %t | FileCheck %s
55
6// CHECK: Name: .mysec6// CHECK: Name: .mysec
7// CHECK-NEXT: Type:7// CHECK-NEXT: Type:
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9// CHECK-NEXT: SHF_ALLOC9// CHECK-NEXT: SHF_ALLOC
10// CHECK-NEXT: SHF_MERGE10// CHECK-NEXT: SHF_MERGE
11// CHECK-NEXT: ]11// CHECK-NEXT: ]
12// CHECK-NEXT: Address: 0x15812// CHECK-NEXT: Address: 0x178
13// CHECK-NEXT: Offset:13// CHECK-NEXT: Offset:
14// CHECK-NEXT: Size:14// CHECK-NEXT: Size:
15// CHECK-NEXT: Link:15// CHECK-NEXT: Link:
...@@ -27,15 +27,15 @@...@@ -27,15 +27,15 @@
27// CHECK-NEXT: SHF_ALLOC27// CHECK-NEXT: SHF_ALLOC
28// CHECK-NEXT: SHF_WRITE28// CHECK-NEXT: SHF_WRITE
29// CHECK-NEXT: ]29// CHECK-NEXT: ]
30// CHECK-NEXT: Address: 0x100030// CHECK-NEXT: Address: 0x2000
31// CHECK-NEXT: Offset: 0x100031// CHECK-NEXT: Offset: 0x2000
32// CHECK-NEXT: Size: 432// CHECK-NEXT: Size: 4
33// CHECK-NEXT: Link: 033// CHECK-NEXT: Link: 0
34// CHECK-NEXT: Info: 034// CHECK-NEXT: Info: 0
35// CHECK-NEXT: AddressAlignment: 135// CHECK-NEXT: AddressAlignment: 1
36// CHECK-NEXT: EntrySize: 036// CHECK-NEXT: EntrySize: 0
37// CHECK-NEXT: SectionData (37// CHECK-NEXT: SectionData (
38// CHECK-NEXT: 0000: 58010000 |38// CHECK-NEXT: 0000: 78010000 |
39// CHECK-NEXT: )39// CHECK-NEXT: )
4040
41// The content of .data should be the address of .mysec.41// The content of .data should be the address of .mysec.
deps/lld/test/ELF/i386-pc16.test+6-6
...@@ -32,9 +32,9 @@ Sections:...@@ -32,9 +32,9 @@ Sections:
32 Symbol: _start32 Symbol: _start
33 Type: R_386_PC1633 Type: R_386_PC16
34Symbols:34Symbols:
35 Global:35 - Name: _start
36 - Name: _start36 Type: STT_FUNC
37 Type: STT_FUNC37 Section: .text
38 Section: .text38 Value: 0x1234
39 Value: 0x123439 Size: 4
40 Size: 440 Binding: STB_GLOBAL
deps/lld/test/ELF/i386-relax-reloc.s+9-4
...@@ -1,12 +1,17 @@...@@ -1,12 +1,17 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o -relax-relocations2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o -relax-relocations
3// RUN: ld.lld -shared %t.o -o %t.so3// RUN: ld.lld -shared %t.o -o %t.so
4// RUN: llvm-readelf -S %t.so | FileCheck --check-prefix=SEC %s
4// RUN: llvm-objdump -d %t.so | FileCheck %s5// RUN: llvm-objdump -d %t.so | FileCheck %s
56
7// SEC: .got PROGBITS 00002050
8// SEC-NEXT: .got.plt PROGBITS 00003000
9
10// 0x2050 - 0x3000 = -4016
11// CHECK: foo:
12// CHECK-NEXT: movl -4016(%ebx), %eax
13// CHECK-NEXT: movl -4008(%ebx), %eax
14
6foo:15foo:
7 movl bar@GOT(%ebx), %eax16 movl bar@GOT(%ebx), %eax
8 movl bar+8@GOT(%ebx), %eax17 movl bar+8@GOT(%ebx), %eax
9
10// CHECK: foo:
11// CHECK-NEXT: movl -4(%ebx), %eax
12// CHECK-NEXT: movl 4(%ebx), %eax
deps/lld/test/ELF/i386-reloc-16.s+16-11
...@@ -1,15 +1,20 @@...@@ -1,15 +1,20 @@
1// REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i386 %s -o %t.o
23
3// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %S/Inputs/x86-64-reloc-16.s -o %t14# RUN: ld.lld %t.o --defsym=a=0 --defsym=b=32768 -o %t
4// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %S/Inputs/x86-64-reloc-16-error.s -o %t25# RUN: llvm-readelf -x .text %t | FileCheck %s
5// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t6# CHECK: b80080bb ffff
6// RUN: ld.lld -shared %t %t1 -o %t3
7// RUN: llvm-objdump -s %t3 | FileCheck %s
87
9// CHECK: Contents of section .text:8# RUN: not ld.lld %t.o --defsym=a=-1 --defsym=b=0 -o /dev/null 2>&1 | \
10// CHECK-NEXT: 1000 429# RUN: FileCheck --check-prefix=OVERFLOW1 %s
10# OVERFLOW1: relocation R_386_16 out of range: -32769 is not in [-32768, 65535]
1111
12// RUN: not ld.lld -shared %t %t2 -o /dev/null 2>&1 | FileCheck --check-prefix=ERROR %s12# RUN: not ld.lld %t.o --defsym=a=0 --defsym=b=32769 -o /dev/null 2>&1 | \
13// ERROR: relocation R_386_16 out of range: 65536 is not in [-32768, 32767]13# RUN: FileCheck --check-prefix=OVERFLOW2 %s
14# OVERFLOW2: relocation R_386_16 out of range: 65536 is not in [-32768, 65535]
1415
15.short foo16.code16
17.global _start
18_start:
19movw $a-32768, %ax
20movw $b+32767, %bx
deps/lld/test/ELF/i386-reloc-8.s+16-11
...@@ -1,15 +1,20 @@...@@ -1,15 +1,20 @@
1// REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i386 %s -o %t.o
23
3// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %S/Inputs/i386-reloc-8.s -o %t14# RUN: ld.lld %t.o --defsym=a=0 --defsym=b=128 -o %t
4// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %S/Inputs/i386-reloc-8-error.s -o %t25# RUN: llvm-readelf -x .text %t | FileCheck %s
5// RUN: llvm-mc -filetype=obj -triple=i386-pc-linux %s -o %t6# CHECK: b480b7ff
6// RUN: ld.lld -shared %t %t1 -o %t3
7// RUN: llvm-objdump -s %t3 | FileCheck %s
87
9// CHECK: Contents of section .text:8# RUN: not ld.lld %t.o --defsym=a=-1 --defsym=b=0 -o /dev/null 2>&1 | \
10// CHECK-NEXT: 1000 ff9# RUN: FileCheck --check-prefix=OVERFLOW1 %s
10# OVERFLOW1: relocation R_386_8 out of range: -129 is not in [-128, 255]
1111
12// RUN: not ld.lld -shared %t %t2 -o /dev/null 2>&1 | FileCheck --check-prefix=ERROR %s12# RUN: not ld.lld %t.o --defsym=a=0 --defsym=b=129 -o /dev/null 2>&1 | \
13// ERROR: relocation R_386_8 out of range: 256 is not in [-128, 127]13# RUN: FileCheck --check-prefix=OVERFLOW2 %s
14# OVERFLOW2: relocation R_386_8 out of range: 256 is not in [-128, 255]
1415
15.byte foo16.code16
17.globl _start
18_start:
19movb $a-128, %ah
20movb $b+127, %bh
deps/lld/test/ELF/i386-reloc-large-addend.s+1
...@@ -8,6 +8,7 @@...@@ -8,6 +8,7 @@
8// RUN: llvm-objdump -d -triple=i386-pc-linux-code16 %t | FileCheck %s8// RUN: llvm-objdump -d -triple=i386-pc-linux-code16 %t | FileCheck %s
99
10// CHECK: Disassembly of section .text:10// CHECK: Disassembly of section .text:
11// CHECK-EMPTY:
11// CHECK-NEXT: _start:12// CHECK-NEXT: _start:
12// CHECK-NEXT: 7000: e9 fe 1f jmp 819013// CHECK-NEXT: 7000: e9 fe 1f jmp 8190
13// 0x1 + 0x9000 - 0x7003 == 819014// 0x1 + 0x9000 - 0x7003 == 8190
deps/lld/test/ELF/i386-reloc-range.s+1
...@@ -10,6 +10,7 @@...@@ -10,6 +10,7 @@
10// RUN: llvm-objdump -d -triple=i386-pc-linux-code16 %t1 | FileCheck %s10// RUN: llvm-objdump -d -triple=i386-pc-linux-code16 %t1 | FileCheck %s
1111
12// CHECK: Disassembly of section .text:12// CHECK: Disassembly of section .text:
13// CHECK-EMPTY:
13// CHECK-NEXT: _start:14// CHECK-NEXT: _start:
14// CHECK-NEXT: 200: {{.*}} jmp -115// CHECK-NEXT: 200: {{.*}} jmp -1
15// 0x10202 - 0x203 == 0xffff16// 0x10202 - 0x203 == 0xffff
deps/lld/test/ELF/i386-retpoline-nopic-linkerscript.s+5-4
...@@ -13,10 +13,11 @@...@@ -13,10 +13,11 @@
13// RUN: llvm-objdump -d -s %t.exe | FileCheck %s13// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
1414
15// CHECK: Disassembly of section .plt:15// CHECK: Disassembly of section .plt:
16// CHECK-EMPTY:
16// CHECK-NEXT: .plt:17// CHECK-NEXT: .plt:
17// CHECK-NEXT: 10: ff 35 84 00 00 00 pushl 13218// CHECK-NEXT: 10: ff 35 ec 00 00 00 pushl 236
18// CHECK-NEXT: 16: 50 pushl %eax19// CHECK-NEXT: 16: 50 pushl %eax
19// CHECK-NEXT: 17: a1 88 00 00 00 movl 136, %eax20// CHECK-NEXT: 17: a1 f0 00 00 00 movl 240, %eax
20// CHECK-NEXT: 1c: e8 0f 00 00 00 calll 15 <.plt+0x20>21// CHECK-NEXT: 1c: e8 0f 00 00 00 calll 15 <.plt+0x20>
21// CHECK-NEXT: 21: f3 90 pause22// CHECK-NEXT: 21: f3 90 pause
22// CHECK-NEXT: 23: 0f ae e8 lfence23// CHECK-NEXT: 23: 0f ae e8 lfence
...@@ -37,7 +38,7 @@...@@ -37,7 +38,7 @@
37// CHECK-NEXT: 3e: c3 retl38// CHECK-NEXT: 3e: c3 retl
38// CHECK-NEXT: 3f: cc int339// CHECK-NEXT: 3f: cc int3
39// CHECK-NEXT: 40: 50 pushl %eax40// CHECK-NEXT: 40: 50 pushl %eax
40// CHECK-NEXT: 41: a1 8c 00 00 00 movl 140, %eax41// CHECK-NEXT: 41: a1 f4 00 00 00 movl 244, %eax
41// CHECK-NEXT: 46: e8 e5 ff ff ff calll -27 <.plt+0x20>42// CHECK-NEXT: 46: e8 e5 ff ff ff calll -27 <.plt+0x20>
42// CHECK-NEXT: 4b: e9 d1 ff ff ff jmp -47 <.plt+0x11>43// CHECK-NEXT: 4b: e9 d1 ff ff ff jmp -47 <.plt+0x11>
43// CHECK-NEXT: 50: 68 00 00 00 00 pushl $044// CHECK-NEXT: 50: 68 00 00 00 00 pushl $0
...@@ -49,7 +50,7 @@...@@ -49,7 +50,7 @@
49// CHECK-NEXT: 5e: cc int350// CHECK-NEXT: 5e: cc int3
50// CHECK-NEXT: 5f: cc int351// CHECK-NEXT: 5f: cc int3
51// CHECK-NEXT: 60: 50 pushl %eax52// CHECK-NEXT: 60: 50 pushl %eax
52// CHECK-NEXT: 61: a1 90 00 00 00 movl 144, %eax53// CHECK-NEXT: 61: a1 f8 00 00 00 movl 248, %eax
53// CHECK-NEXT: 66: e8 c5 ff ff ff calll -59 <.plt+0x20>54// CHECK-NEXT: 66: e8 c5 ff ff ff calll -59 <.plt+0x20>
54// CHECK-NEXT: 6b: e9 b1 ff ff ff jmp -79 <.plt+0x11>55// CHECK-NEXT: 6b: e9 b1 ff ff ff jmp -79 <.plt+0x11>
55// CHECK-NEXT: 70: 68 08 00 00 00 pushl $856// CHECK-NEXT: 70: 68 08 00 00 00 pushl $8
deps/lld/test/ELF/i386-retpoline-nopic.s+6-5
...@@ -7,10 +7,11 @@...@@ -7,10 +7,11 @@
7// RUN: llvm-objdump -d -s %t.exe | FileCheck %s7// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
88
9// CHECK: Disassembly of section .plt:9// CHECK: Disassembly of section .plt:
10// CHECK-EMPTY:
10// CHECK-NEXT: .plt:11// CHECK-NEXT: .plt:
11// CHECK-NEXT: 401010: ff 35 04 20 40 00 pushl 420250012// CHECK-NEXT: 401010: ff 35 04 30 40 00 pushl 4206596
12// CHECK-NEXT: 401016: 50 pushl %eax13// CHECK-NEXT: 401016: 50 pushl %eax
13// CHECK-NEXT: 401017: a1 08 20 40 00 movl 4202504, %eax14// CHECK-NEXT: 401017: a1 08 30 40 00 movl 4206600, %eax
14// CHECK-NEXT: 40101c: e8 0f 00 00 00 calll 15 <.plt+0x20>15// CHECK-NEXT: 40101c: e8 0f 00 00 00 calll 15 <.plt+0x20>
15// CHECK-NEXT: 401021: f3 90 pause16// CHECK-NEXT: 401021: f3 90 pause
16// CHECK-NEXT: 401023: 0f ae e8 lfence17// CHECK-NEXT: 401023: 0f ae e8 lfence
...@@ -31,7 +32,7 @@...@@ -31,7 +32,7 @@
31// CHECK-NEXT: 40103e: c3 retl32// CHECK-NEXT: 40103e: c3 retl
32// CHECK-NEXT: 40103f: cc int333// CHECK-NEXT: 40103f: cc int3
33// CHECK-NEXT: 401040: 50 pushl %eax34// CHECK-NEXT: 401040: 50 pushl %eax
34// CHECK-NEXT: 401041: a1 0c 20 40 00 movl 4202508, %eax35// CHECK-NEXT: 401041: a1 0c 30 40 00 movl 4206604, %eax
35// CHECK-NEXT: 401046: e8 e5 ff ff ff calll -27 <.plt+0x20>36// 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: 40104b: e9 d1 ff ff ff jmp -47 <.plt+0x11>
37// CHECK-NEXT: 401050: 68 00 00 00 00 pushl $038// CHECK-NEXT: 401050: 68 00 00 00 00 pushl $0
...@@ -43,7 +44,7 @@...@@ -43,7 +44,7 @@
43// CHECK-NEXT: 40105e: cc int344// CHECK-NEXT: 40105e: cc int3
44// CHECK-NEXT: 40105f: cc int345// CHECK-NEXT: 40105f: cc int3
45// CHECK-NEXT: 401060: 50 pushl %eax46// CHECK-NEXT: 401060: 50 pushl %eax
46// CHECK-NEXT: 401061: a1 10 20 40 00 movl 4202512, %eax47// CHECK-NEXT: 401061: a1 10 30 40 00 movl 4206608, %eax
47// CHECK-NEXT: 401066: e8 c5 ff ff ff calll -59 <.plt+0x20>48// 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: 40106b: e9 b1 ff ff ff jmp -79 <.plt+0x11>
49// CHECK-NEXT: 401070: 68 08 00 00 00 pushl $850// CHECK-NEXT: 401070: 68 08 00 00 00 pushl $8
...@@ -56,7 +57,7 @@...@@ -56,7 +57,7 @@
56// CHECK-NEXT: 40107f: cc int357// CHECK-NEXT: 40107f: cc int3
5758
58// CHECK: Contents of section .got.plt:59// CHECK: Contents of section .got.plt:
59// CHECK-NEXT: 00304000 00000000 00000000 5010400060// CHECK-NEXT: 00204000 00000000 00000000 50104000
60// CHECK-NEXT: 7010400061// CHECK-NEXT: 70104000
6162
62.global _start63.global _start
deps/lld/test/ELF/i386-retpoline-pic-linkerscript.s+5-4
...@@ -13,10 +13,11 @@...@@ -13,10 +13,11 @@
13// RUN: llvm-objdump -d -s %t.exe | FileCheck %s13// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
1414
15// CHECK: Disassembly of section .plt:15// CHECK: Disassembly of section .plt:
16// CHECK-EMPTY:
16// CHECK-NEXT: .plt:17// CHECK-NEXT: .plt:
17// CHECK-NEXT: 10: ff b3 84 00 00 00 pushl 132(%ebx)18// CHECK-NEXT: 10: ff b3 04 00 00 00 pushl 4(%ebx)
18// CHECK-NEXT: 16: 50 pushl %eax19// CHECK-NEXT: 16: 50 pushl %eax
19// CHECK-NEXT: 17: 8b 83 88 00 00 00 movl 136(%ebx), %eax20// CHECK-NEXT: 17: 8b 83 08 00 00 00 movl 8(%ebx), %eax
20// CHECK-NEXT: 1d: e8 0e 00 00 00 calll 14 <.plt+0x20>21// CHECK-NEXT: 1d: e8 0e 00 00 00 calll 14 <.plt+0x20>
21// CHECK-NEXT: 22: f3 90 pause22// CHECK-NEXT: 22: f3 90 pause
22// CHECK-NEXT: 24: 0f ae e8 lfence23// CHECK-NEXT: 24: 0f ae e8 lfence
...@@ -36,7 +37,7 @@...@@ -36,7 +37,7 @@
36// CHECK-NEXT: 3e: c3 retl37// CHECK-NEXT: 3e: c3 retl
37// CHECK-NEXT: 3f: cc int338// CHECK-NEXT: 3f: cc int3
38// CHECK-NEXT: 40: 50 pushl %eax39// CHECK-NEXT: 40: 50 pushl %eax
39// CHECK-NEXT: 41: 8b 83 8c 00 00 00 movl 140(%ebx), %eax40// CHECK-NEXT: 41: 8b 83 0c 00 00 00 movl 12(%ebx), %eax
40// CHECK-NEXT: 47: e8 e4 ff ff ff calll -28 <.plt+0x20>41// CHECK-NEXT: 47: e8 e4 ff ff ff calll -28 <.plt+0x20>
41// CHECK-NEXT: 4c: e9 d1 ff ff ff jmp -47 <.plt+0x12>42// CHECK-NEXT: 4c: e9 d1 ff ff ff jmp -47 <.plt+0x12>
42// CHECK-NEXT: 51: 68 00 00 00 00 pushl $043// CHECK-NEXT: 51: 68 00 00 00 00 pushl $0
...@@ -47,7 +48,7 @@...@@ -47,7 +48,7 @@
47// CHECK-NEXT: 5e: cc int348// CHECK-NEXT: 5e: cc int3
48// CHECK-NEXT: 5f: cc int349// CHECK-NEXT: 5f: cc int3
49// CHECK-NEXT: 60: 50 pushl %eax50// CHECK-NEXT: 60: 50 pushl %eax
50// CHECK-NEXT: 61: 8b 83 90 00 00 00 movl 144(%ebx), %eax51// CHECK-NEXT: 61: 8b 83 10 00 00 00 movl 16(%ebx), %eax
51// CHECK-NEXT: 67: e8 c4 ff ff ff calll -60 <.plt+0x20>52// CHECK-NEXT: 67: e8 c4 ff ff ff calll -60 <.plt+0x20>
52// CHECK-NEXT: 6c: e9 b1 ff ff ff jmp -79 <.plt+0x12>53// CHECK-NEXT: 6c: e9 b1 ff ff ff jmp -79 <.plt+0x12>
53// CHECK-NEXT: 71: 68 08 00 00 00 pushl $854// CHECK-NEXT: 71: 68 08 00 00 00 pushl $8
deps/lld/test/ELF/i386-retpoline-pic.s+7-6
...@@ -7,10 +7,11 @@...@@ -7,10 +7,11 @@
7// RUN: llvm-objdump -d -s %t.exe | FileCheck %s7// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
88
9// CHECK: Disassembly of section .plt:9// CHECK: Disassembly of section .plt:
10// CHECK-EMPTY:
10// CHECK-NEXT: .plt:11// CHECK-NEXT: .plt:
11// CHECK-NEXT: 1010: ff b3 04 20 00 00 pushl 8196(%ebx)12// CHECK-NEXT: 1010: ff b3 04 00 00 00 pushl 4(%ebx)
12// CHECK-NEXT: 1016: 50 pushl %eax13// CHECK-NEXT: 1016: 50 pushl %eax
13// CHECK-NEXT: 1017: 8b 83 08 20 00 00 movl 8200(%ebx), %eax14// CHECK-NEXT: 1017: 8b 83 08 00 00 00 movl 8(%ebx), %eax
14// CHECK-NEXT: 101d: e8 0e 00 00 00 calll 14 <.plt+0x20>15// CHECK-NEXT: 101d: e8 0e 00 00 00 calll 14 <.plt+0x20>
15// CHECK-NEXT: 1022: f3 90 pause16// CHECK-NEXT: 1022: f3 90 pause
16// CHECK-NEXT: 1024: 0f ae e8 lfence17// CHECK-NEXT: 1024: 0f ae e8 lfence
...@@ -30,7 +31,7 @@...@@ -30,7 +31,7 @@
30// CHECK-NEXT: 103e: c3 retl31// CHECK-NEXT: 103e: c3 retl
31// CHECK-NEXT: 103f: cc int332// CHECK-NEXT: 103f: cc int3
32// CHECK-NEXT: 1040: 50 pushl %eax33// CHECK-NEXT: 1040: 50 pushl %eax
33// CHECK-NEXT: 1041: 8b 83 0c 20 00 00 movl 8204(%ebx), %eax34// CHECK-NEXT: 1041: 8b 83 0c 00 00 00 movl 12(%ebx), %eax
34// CHECK-NEXT: 1047: e8 e4 ff ff ff calll -28 <.plt+0x20>35// CHECK-NEXT: 1047: e8 e4 ff ff ff calll -28 <.plt+0x20>
35// CHECK-NEXT: 104c: e9 d1 ff ff ff jmp -47 <.plt+0x12>36// CHECK-NEXT: 104c: e9 d1 ff ff ff jmp -47 <.plt+0x12>
36// CHECK-NEXT: 1051: 68 00 00 00 00 pushl $037// CHECK-NEXT: 1051: 68 00 00 00 00 pushl $0
...@@ -41,7 +42,7 @@...@@ -41,7 +42,7 @@
41// CHECK-NEXT: 105e: cc int342// CHECK-NEXT: 105e: cc int3
42// CHECK-NEXT: 105f: cc int343// CHECK-NEXT: 105f: cc int3
43// CHECK-NEXT: 1060: 50 pushl %eax44// CHECK-NEXT: 1060: 50 pushl %eax
44// CHECK-NEXT: 1061: 8b 83 10 20 00 00 movl 8208(%ebx), %eax45// CHECK-NEXT: 1061: 8b 83 10 00 00 00 movl 16(%ebx), %eax
45// CHECK-NEXT: 1067: e8 c4 ff ff ff calll -60 <.plt+0x20>46// CHECK-NEXT: 1067: e8 c4 ff ff ff calll -60 <.plt+0x20>
46// CHECK-NEXT: 106c: e9 b1 ff ff ff jmp -79 <.plt+0x12>47// CHECK-NEXT: 106c: e9 b1 ff ff ff jmp -79 <.plt+0x12>
47// CHECK-NEXT: 1071: 68 08 00 00 00 pushl $848// CHECK-NEXT: 1071: 68 08 00 00 00 pushl $8
...@@ -53,8 +54,8 @@...@@ -53,8 +54,8 @@
53// CHECK-NEXT: 107f: cc int354// CHECK-NEXT: 107f: cc int3
5455
55// CHECK: Contents of section .got.plt:56// CHECK: Contents of section .got.plt:
56// CHECK-NEXT: 2000 00300000 00000000 00000000 5110000057// CHECK-NEXT: 3000 00200000 00000000 00000000 51100000
57// CHECK-NEXT: 2010 7110000058// CHECK-NEXT: 3010 71100000
5859
59.global _start60.global _start
60_start:61_start:
deps/lld/test/ELF/i386-static-tls-model.s created+20
...@@ -0,0 +1,20 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/i386-static-tls-model1.s -o %t.o
4# RUN: ld.lld %t.o -o %t1 -shared
5# RUN: llvm-readobj --dynamic-table %t1 | FileCheck %s
6
7# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/i386-static-tls-model2.s -o %t.o
8# RUN: ld.lld %t.o -o %t2 -shared
9# RUN: llvm-readobj --dynamic-table %t2 | FileCheck %s
10
11# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/i386-static-tls-model3.s -o %t.o
12# RUN: ld.lld %t.o -o %t3 -shared
13# RUN: llvm-readobj --dynamic-table %t3 | FileCheck %s
14
15# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %S/Inputs/i386-static-tls-model4.s -o %t.o
16# RUN: ld.lld %t.o -o %t4 -shared
17# RUN: llvm-readobj --dynamic-table %t4 | FileCheck %s
18
19# CHECK: DynamicSection [
20# CHECK: FLAGS STATIC_TLS
deps/lld/test/ELF/i386-tls-ie-shared.s+28-27
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o3// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o
4// RUN: ld.lld -shared %tso.o -o %tso4// RUN: ld.lld -shared %tso.o -o %tso
5// RUN: ld.lld --hash-style=sysv -shared %t.o %tso -o %t15// RUN: ld.lld --hash-style=sysv -shared %t.o %tso -o %t1
6// RUN: llvm-readobj -s -r -d %t1 | FileCheck --check-prefix=GOTRELSHARED %s6// RUN: llvm-readobj -S -r -d %t1 | FileCheck --check-prefix=GOTRELSHARED %s
7// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s7// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASMSHARED %s
88
9// GOTRELSHARED: Section {9// GOTRELSHARED: Section {
...@@ -14,8 +14,8 @@...@@ -14,8 +14,8 @@
14// GOTRELSHARED-NEXT: SHF_ALLOC14// GOTRELSHARED-NEXT: SHF_ALLOC
15// GOTRELSHARED-NEXT: SHF_WRITE15// GOTRELSHARED-NEXT: SHF_WRITE
16// GOTRELSHARED-NEXT: ]16// GOTRELSHARED-NEXT: ]
17// GOTRELSHARED-NEXT: Address: 0x205817// GOTRELSHARED-NEXT: Address: 0x2060
18// GOTRELSHARED-NEXT: Offset: 0x205818// GOTRELSHARED-NEXT: Offset: 0x2060
19// GOTRELSHARED-NEXT: Size: 1619// GOTRELSHARED-NEXT: Size: 16
20// GOTRELSHARED-NEXT: Link: 020// GOTRELSHARED-NEXT: Link: 0
21// GOTRELSHARED-NEXT: Info: 021// GOTRELSHARED-NEXT: Info: 0
...@@ -32,36 +32,37 @@...@@ -32,36 +32,37 @@
32// GOTRELSHARED-NEXT: 0x102D R_386_RELATIVE - 0x032// GOTRELSHARED-NEXT: 0x102D R_386_RELATIVE - 0x0
33// GOTRELSHARED-NEXT: 0x1036 R_386_RELATIVE - 0x033// GOTRELSHARED-NEXT: 0x1036 R_386_RELATIVE - 0x0
34// GOTRELSHARED-NEXT: 0x103F R_386_RELATIVE - 0x034// GOTRELSHARED-NEXT: 0x103F R_386_RELATIVE - 0x0
35// GOTRELSHARED-NEXT: 0x2058 R_386_TLS_TPOFF tlslocal0 0x035// GOTRELSHARED-NEXT: 0x2060 R_386_TLS_TPOFF tlslocal0 0x0
36// GOTRELSHARED-NEXT: 0x205C R_386_TLS_TPOFF tlslocal1 0x036// GOTRELSHARED-NEXT: 0x2064 R_386_TLS_TPOFF tlslocal1 0x0
37// GOTRELSHARED-NEXT: 0x2060 R_386_TLS_TPOFF tlsshared0 0x037// GOTRELSHARED-NEXT: 0x2068 R_386_TLS_TPOFF tlsshared0 0x0
38// GOTRELSHARED-NEXT: 0x2064 R_386_TLS_TPOFF tlsshared1 0x038// GOTRELSHARED-NEXT: 0x206C R_386_TLS_TPOFF tlsshared1 0x0
39// GOTRELSHARED-NEXT: }39// GOTRELSHARED-NEXT: }
40// GOTRELSHARED-NEXT: ]40// GOTRELSHARED-NEXT: ]
41// GOTRELSHARED: 0x6FFFFFFA RELCOUNT 841// GOTRELSHARED: 0x6FFFFFFA RELCOUNT 8
4242
43// DISASMSHARED: Disassembly of section test:43// DISASMSHARED: Disassembly of section test:
44// DISASMSHARED-EMPTY:
44// DISASMSHARED-NEXT: _start:45// DISASMSHARED-NEXT: _start:
45// (.got)[0] = 0x2058 = 828046// (.got)[0] = 0x2060 = 8288
46// (.got)[1] = 0x205C = 828447// (.got)[1] = 0x2064 = 8292
47// (.got)[2] = 0x2060 = 828848// (.got)[2] = 0x2068 = 8296
48// (.got)[3] = 0x2064 = 829249// (.got)[3] = 0x206C = 8300
49// DISASMSHARED-NEXT: 1000: 8b 0d 58 20 00 00 movl 8280, %ecx50// DISASMSHARED-NEXT: 1000: {{.*}} movl 8288, %ecx
50// DISASMSHARED-NEXT: 1006: 65 8b 01 movl %gs:(%ecx), %eax51// DISASMSHARED-NEXT: 1006: {{.*}} movl %gs:(%ecx), %eax
51// DISASMSHARED-NEXT: 1009: a1 58 20 00 00 movl 8280, %eax52// DISASMSHARED-NEXT: 1009: {{.*}} movl 8288, %eax
52// DISASMSHARED-NEXT: 100e: 65 8b 00 movl %gs:(%eax), %eax53// DISASMSHARED-NEXT: 100e: {{.*}} movl %gs:(%eax), %eax
53// DISASMSHARED-NEXT: 1011: 03 0d 58 20 00 00 addl 8280, %ecx54// DISASMSHARED-NEXT: 1011: {{.*}} addl 8288, %ecx
54// DISASMSHARED-NEXT: 1017: 65 8b 01 movl %gs:(%ecx), %eax55// DISASMSHARED-NEXT: 1017: {{.*}} movl %gs:(%ecx), %eax
55// DISASMSHARED-NEXT: 101a: 8b 0d 5c 20 00 00 movl 8284, %ecx56// DISASMSHARED-NEXT: 101a: {{.*}} movl 8292, %ecx
56// DISASMSHARED-NEXT: 1020: 65 8b 01 movl %gs:(%ecx), %eax57// DISASMSHARED-NEXT: 1020: {{.*}} movl %gs:(%ecx), %eax
57// DISASMSHARED-NEXT: 1023: a1 5c 20 00 00 movl 8284, %eax58// DISASMSHARED-NEXT: 1023: {{.*}} movl 8292, %eax
58// DISASMSHARED-NEXT: 1028: 65 8b 00 movl %gs:(%eax), %eax59// DISASMSHARED-NEXT: 1028: {{.*}} movl %gs:(%eax), %eax
59// DISASMSHARED-NEXT: 102b: 03 0d 5c 20 00 00 addl 8284, %ecx60// DISASMSHARED-NEXT: 102b: {{.*}} addl 8292, %ecx
60// DISASMSHARED-NEXT: 1031: 65 8b 01 movl %gs:(%ecx), %eax61// DISASMSHARED-NEXT: 1031: {{.*}} movl %gs:(%ecx), %eax
61// DISASMSHARED-NEXT: 1034: 8b 0d 60 20 00 00 movl 8288, %ecx62// DISASMSHARED-NEXT: 1034: {{.*}} movl 8296, %ecx
62// DISASMSHARED-NEXT: 103a: 65 8b 01 movl %gs:(%ecx), %eax63// DISASMSHARED-NEXT: 103a: {{.*}} movl %gs:(%ecx), %eax
63// DISASMSHARED-NEXT: 103d: 03 0d 64 20 00 00 addl 8292, %ecx64// DISASMSHARED-NEXT: 103d: {{.*}} addl 8300, %ecx
64// DISASMSHARED-NEXT: 1043: 65 8b 01 movl %gs:(%ecx), %eax65// DISASMSHARED-NEXT: 1043: {{.*}} movl %gs:(%ecx), %eax
6566
66.type tlslocal0,@object67.type tlslocal0,@object
67.section .tbss,"awT",@nobits68.section .tbss,"awT",@nobits
deps/lld/test/ELF/i386-tls-ld-preemptable.s created+18
...@@ -0,0 +1,18 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i386 %s -o %t.o
3# RUN: ld.lld %t.o -shared -o %t.so
4# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s
5
6# CHECK: 100b: movl (%eax), %eax
7
8# We used to error on R_386_TLS_LDO_32 to preemptable symbols.
9# i is STB_GLOBAL and preemptable.
10 leal i@TLSLDM(%ebx), %eax
11 calll __tls_get_addr@PLT
12 movl i@DTPOFF(%eax), %eax # R_386_TLS_LDO_32
13
14.section .tbss,"awT",@nobits
15.globl i
16i:
17 .long 0
18 .size i, 4
deps/lld/test/ELF/i386-tls-le-align.s created+29
...@@ -0,0 +1,29 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i386 %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-objdump -d --no-show-raw-insn --print-imm-hex %t | FileCheck %s
5
6# -alignTo(p_memsz, p_align) = -alignTo(4, 64) = -64
7
8# CHECK: movl %gs:0xffffffc0, %eax
9 movl %gs:a@NTPOFF, %eax
10
11# CHECK-NEXT: subl $0x40, %edx
12 subl $a@tpoff, %edx
13
14# GD to LE relaxation.
15# CHECK-NEXT: movl %gs:0x0, %eax
16# CHECK-NEXT: subl $0x40, %eax
17 leal a@tlsgd(,%ebx,1), %eax
18 call ___tls_get_addr@plt
19 ret
20
21.globl ___tls_get_addr
22.type ___tls_get_addr,@function
23___tls_get_addr:
24
25.section .tbss,"awT"
26.align 64
27a:
28.long 0
29.size a, 4
deps/lld/test/ELF/i386-tls-le-undef.s created+16
...@@ -0,0 +1,16 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i386 %s -o %t.o
3# RUN: ld.lld --noinhibit-exec %t.o -o %t 2>&1
4# RUN: llvm-objdump -d %t | FileCheck %s
5
6## Undefined TLS symbols resolve to 0.
7## In --noinhibit-exec mode, a non-weak undefined symbol is not an error.
8
9# CHECK: subl $0, %eax
10# CHECK: subl $0, %eax
11
12.weak weak_undef
13movl %gs:0, %eax
14subl $weak_undef@tpoff,%eax
15movl %gs:0, %eax
16subl $undef@tpoff,%eax
deps/lld/test/ELF/icf-merged-sections.s+2-2
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: ld.lld %t.o -o %t --icf=all --ignore-data-address-equality --print-icf-sections | FileCheck -allow-empty --check-prefix=NOICF %s4# RUN: ld.lld %t.o -o %t --icf=all --ignore-data-address-equality --print-icf-sections | FileCheck -allow-empty --check-prefix=NOICF %s
5# RUN: llvm-readobj -s -section-data %t | FileCheck %s5# RUN: llvm-readobj -S --section-data %t | FileCheck %s
66
7# Check that merge synthetic sections are not merged by ICF.7# Check that merge synthetic sections are not merged by ICF.
88
...@@ -19,7 +19,7 @@...@@ -19,7 +19,7 @@
19# CHECK-NEXT: Size: 1619# CHECK-NEXT: Size: 16
20# CHECK-NEXT: Link:20# CHECK-NEXT: Link:
21# CHECK-NEXT: Info:21# CHECK-NEXT: Info:
22# CHECK-NEXT: AddressAlignment: 822# CHECK-NEXT: AddressAlignment: 1
23# CHECK-NEXT: EntrySize: 023# CHECK-NEXT: EntrySize: 0
24# CHECK-NEXT: SectionData (24# CHECK-NEXT: SectionData (
25# CHECK-NEXT: 0000: 67452301 10325476 67452301 1032547625# CHECK-NEXT: 0000: 67452301 10325476 67452301 10325476
deps/lld/test/ELF/icf-symbol-type.s+1-1
...@@ -7,8 +7,8 @@...@@ -7,8 +7,8 @@
7# We used to mark bar as absolute.7# We used to mark bar as absolute.
88
9# CHECK: .text PROGBITS 00000000000010009# CHECK: .text PROGBITS 0000000000001000
10# CHECK: 0000000000001001 0 NOTYPE GLOBAL DEFAULT 4 foo
11# CHECK: 0000000000001001 0 NOTYPE GLOBAL DEFAULT 4 bar10# CHECK: 0000000000001001 0 NOTYPE GLOBAL DEFAULT 4 bar
11# CHECK: 0000000000001001 0 NOTYPE GLOBAL DEFAULT 4 foo
1212
13# The nop makes the test more interesting by making the offset of13# The nop makes the test more interesting by making the offset of
14# text.f non zero.14# text.f non zero.
deps/lld/test/ELF/icf10.s created+17
...@@ -0,0 +1,17 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-freebsd %s -o %t.o
4# RUN: ld.lld --icf=all %t.o -o /dev/null --print-icf-sections 2>&1 | FileCheck %s
5
6# Checks that ICF does not merge 2 sections the offset of
7# the relocations of which differ.
8
9# CHECK-NOT: selected
10
11.section .text.foo,"ax"
12 .quad -1
13 .reloc 0, R_X86_64_NONE, 0
14
15.section .text.bar,"ax"
16 .quad -1
17 .reloc 1, R_X86_64_NONE, 0
deps/lld/test/ELF/icf10.test deleted-40
...@@ -1,40 +0,0 @@
1# RUN: yaml2obj %s -o %t.o
2# RUN: ld.lld --icf=all %t.o -o /dev/null --print-icf-sections 2>&1 | FileCheck %s
3
4# Checks that ICF does not merge 2 sections the offset of
5# the relocations of which differ.
6
7# CHECK-NOT: selected
8
9!ELF
10FileHeader:
11 Class: ELFCLASS64
12 Data: ELFDATA2LSB
13 OSABI: ELFOSABI_FREEBSD
14 Type: ET_REL
15 Machine: EM_X86_64
16Sections:
17 - Name: .text.foo
18 Type: SHT_PROGBITS
19 Flags: [ SHF_ALLOC, SHF_EXECINSTR]
20 Content: "FFFFFFFFFFFFFFFF"
21 - Name: .text.bar
22 Type: SHT_PROGBITS
23 Flags: [ SHF_ALLOC, SHF_EXECINSTR]
24 Content: "FFFFFFFFFFFFFFFF"
25 - Name: .rela.text.foo
26 Type: SHT_RELA
27 Link: .symtab
28 Info: .text.foo
29 Relocations:
30 - Offset: 0x0000000000000000
31 Symbol: ''
32 Type: R_X86_64_NONE
33 - Name: .rela.text.bar
34 Type: SHT_RELA
35 Link: .symtab
36 Info: .text.bar
37 Relocations:
38 - Offset: 0x0000000000000001
39 Symbol: ''
40 Type: R_X86_64_NONE
deps/lld/test/ELF/icf11.test+6-7
...@@ -33,7 +33,6 @@ Sections:...@@ -33,7 +33,6 @@ Sections:
33 Info: .text.foo33 Info: .text.foo
34 Relocations:34 Relocations:
35 - Offset: 0x000000000000000035 - Offset: 0x0000000000000000
36 Symbol: ''
37 Type: R_X86_64_NONE36 Type: R_X86_64_NONE
38 - Name: .rela.text.bar37 - Name: .rela.text.bar
39 Type: SHT_RELA38 Type: SHT_RELA
...@@ -44,9 +43,9 @@ Sections:...@@ -44,9 +43,9 @@ Sections:
44 Symbol: zed43 Symbol: zed
45 Type: R_X86_64_6444 Type: R_X86_64_64
46Symbols:45Symbols:
47 Global:46 - Name: zed
48 - Name: zed47 Type: STT_FUNC
49 Type: STT_FUNC48 Section: .text
50 Section: .text49 Value: 0x0
51 Value: 0x050 Size: 8
52 Size: 851 Binding: STB_GLOBAL
deps/lld/test/ELF/image-base.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3# RUN: ld.lld -image-base=0x1000000 %t -o %t13# RUN: ld.lld -image-base=0x1000000 %t -o %t1
4# RUN: llvm-readobj -program-headers %t1 | FileCheck %s4# RUN: llvm-readobj -l %t1 | FileCheck %s
55
6# RUN: not ld.lld -image-base=ABC %t -o %t1 2>&1 | FileCheck --check-prefix=ERR %s6# 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 ABC7# ERR: error: -image-base: number expected, but got ABC
...@@ -11,7 +11,7 @@...@@ -11,7 +11,7 @@
1111
12# Check alias.12# Check alias.
13# RUN: ld.lld -image-base 0x1000000 %t -o %t113# RUN: ld.lld -image-base 0x1000000 %t -o %t1
14# RUN: llvm-readobj -program-headers %t1 | FileCheck %s14# RUN: llvm-readobj -l %t1 | FileCheck %s
1515
16.global _start16.global _start
17_start:17_start:
deps/lld/test/ELF/init-fini-progbits.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
4// RUN: ld.lld %t -o %t.exe4// RUN: ld.lld %t -o %t.exe
5// RUN: llvm-readobj -sections %t.exe | FileCheck %s5// RUN: llvm-readobj --sections %t.exe | FileCheck %s
66
7// CHECK: Name: .init_array7// CHECK: Name: .init_array
8// CHECK-NEXT: Type: SHT_INIT_ARRAY8// CHECK-NEXT: Type: SHT_INIT_ARRAY
deps/lld/test/ELF/init-fini.s+6-6
...@@ -3,25 +3,25 @@...@@ -3,25 +3,25 @@
33
4// Should use "_init" and "_fini" by default when fills dynamic table4// Should use "_init" and "_fini" by default when fills dynamic table
5// RUN: ld.lld -shared %t -o %t25// RUN: ld.lld -shared %t -o %t2
6// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=BYDEF %s6// RUN: llvm-readobj --dynamic-table %t2 | FileCheck --check-prefix=BYDEF %s
7// BYDEF: INIT 0x110107// BYDEF: INIT 0x11010
8// BYDEF: FINI 0x110208// BYDEF: FINI 0x11020
99
10// -init and -fini override symbols to use10// -init and -fini override symbols to use
11// RUN: ld.lld -shared %t -o %t2 -init _foo -fini _bar11// RUN: ld.lld -shared %t -o %t2 -init _foo -fini _bar
12// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=OVR %s12// RUN: llvm-readobj --dynamic-table %t2 | FileCheck --check-prefix=OVR %s
13// OVR: INIT 0x1103013// OVR: INIT 0x11030
14// OVR: FINI 0x1104014// OVR: FINI 0x11040
1515
16// Check aliases as well16// Check aliases as well
17// RUN: ld.lld -shared %t -o %t2 -init=_foo -fini=_bar17// RUN: ld.lld -shared %t -o %t2 -init=_foo -fini=_bar
18// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=OVR %s18// RUN: llvm-readobj --dynamic-table %t2 | FileCheck --check-prefix=OVR %s
1919
20// Don't add an entry for undef. The freebsd dynamic linker doesn't20// Don't add an entry for undef. The freebsd dynamic linker doesn't
21// check if the value is null. If it is, it will just call the21// check if the value is null. If it is, it will just call the
22// load address.22// load address.
23// RUN: ld.lld -shared %t -o %t2 -init=_undef -fini=_undef23// RUN: ld.lld -shared %t -o %t2 -init=_undef -fini=_undef
24// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=UNDEF %s24// RUN: llvm-readobj --dynamic-table %t2 | FileCheck --check-prefix=UNDEF %s
25// UNDEF-NOT: INIT25// UNDEF-NOT: INIT
26// UNDEF-NOT: FINI26// UNDEF-NOT: FINI
2727
...@@ -30,14 +30,14 @@...@@ -30,14 +30,14 @@
30// RUN: echo > %t.s30// RUN: echo > %t.s
31// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t2.o31// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t2.o
32// RUN: ld.lld -shared %t2.o %t.so -o %t232// RUN: ld.lld -shared %t2.o %t.so -o %t2
33// RUN: llvm-readobj -dynamic-table %t2 | FileCheck --check-prefix=SHARED %s33// RUN: llvm-readobj --dynamic-table %t2 | FileCheck --check-prefix=SHARED %s
34// SHARED-NOT: INIT34// SHARED-NOT: INIT
35// SHARED-NOT: FINI35// SHARED-NOT: FINI
3636
37// Should not add new entries to the symbol table37// Should not add new entries to the symbol table
38// and should not require given symbols to be resolved38// and should not require given symbols to be resolved
39// RUN: ld.lld -shared %t -o %t2 -init=_unknown -fini=_unknown39// RUN: ld.lld -shared %t -o %t2 -init=_unknown -fini=_unknown
40// RUN: llvm-readobj -symbols -dynamic-table %t2 | FileCheck --check-prefix=NOENTRY %s40// RUN: llvm-readobj --symbols --dynamic-table %t2 | FileCheck --check-prefix=NOENTRY %s
41// NOENTRY: Symbols [41// NOENTRY: Symbols [
42// NOENTRY-NOT: Name: _unknown42// NOENTRY-NOT: Name: _unknown
43// NOENTRY: ]43// NOENTRY: ]
deps/lld/test/ELF/invalid-relocations.test+2-2
...@@ -17,7 +17,7 @@ Sections:...@@ -17,7 +17,7 @@ Sections:
17 Symbol: lulz17 Symbol: lulz
18 Type: R_X86_64_PC3218 Type: R_X86_64_PC32
19Symbols:19Symbols:
20 Global:20 - Name: lulz
21 - Name: lulz21 Binding: STB_GLOBAL
2222
23# CHECK: invalid relocated section index23# CHECK: invalid relocated section index
deps/lld/test/ELF/invalid-undef-section-symbol.test deleted-27
...@@ -1,27 +0,0 @@
1# RUN: yaml2obj %s -o %t.o
2# RUN: not ld.lld -r %t.o -o /dev/null 2>&1 | FileCheck %s
3
4# We used to crash at this.
5# CHECK: STT_SECTION symbol should be defined
6
7--- !ELF
8FileHeader:
9 Class: ELFCLASS64
10 Data: ELFDATA2LSB
11 Type: ET_REL
12 Machine: EM_X86_64
13Sections:
14 - Name: .text
15 Type: SHT_PROGBITS
16 - Name: .rela.text
17 Type: SHT_RELA
18 AddressAlign: 0x0000000000000008
19 Info: .text
20 Relocations:
21 - Offset: 0x0000000000000000
22 Symbol: .text
23 Type: R_X86_64_NONE
24Symbols:
25 Local:
26 - Name: .text
27 Type: STT_SECTION
deps/lld/test/ELF/invalid/Inputs/binding.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/binding.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/broken-relaxation-x64.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/broken-relaxation-x64.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/common-symbol-alignment.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/common-symbol-alignment.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/common-symbol-alignment2.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/common-symbol-alignment2.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/data-encoding.a deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/data-encoding.a and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/dynamic-section-sh_size.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/dynamic-section-sh_size.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/file-class.a deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/file-class.a and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/invalid-e_shnum.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/invalid-e_shnum.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/mips-invalid-options-descriptor.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/mips-invalid-options-descriptor.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/multiple-eh-relocs.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/multiple-eh-relocs.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/section-alignment-notpow2.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/section-alignment-notpow2.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/section-index.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/section-index.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/symbol-index.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/symbol-index.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/symbol-name-offset.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/symbol-name-offset.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/symtab-sh_info.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/symtab-sh_info.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/symtab-sh_info2.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/symtab-sh_info2.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/symtab-sh_info3.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/symtab-sh_info3.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/tls-symbol.elf deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/tls-symbol.elf and /dev/null differ
deps/lld/test/ELF/invalid/Inputs/undefined-local-symbol-in-dso.so deleted
Binary files a/deps/lld/test/ELF/invalid/Inputs/undefined-local-symbol-in-dso.so and /dev/null differ
deps/lld/test/ELF/invalid/bad-arm-attributes.s created+8
...@@ -0,0 +1,8 @@
1# REQUIRES: arm
2# RUN: llvm-mc -filetype=obj -triple=arm-unknown-linux %s -o %t
3# RUN: ld.lld %t -o /dev/null 2>&1 | FileCheck %s
4
5# CHECK: invalid subsection length 0 at offset 1
6
7.section .ARM.attributes,"a",%0x70000003
8 .quad 0
deps/lld/test/ELF/invalid/bad-arm-attributes2.s created+8
...@@ -0,0 +1,8 @@
1# REQUIRES: arm
2# RUN: llvm-mc -filetype=obj -triple=arm-unknown-linux %s -o %t
3# RUN: ld.lld %t -o /dev/null 2>&1 | FileCheck %s
4
5# CHECK: invalid subsection length 4294967295 at offset 1
6
7.section .ARM.attributes,"a",%0x70000003
8 .byte 0, 0xFF, 0xFF, 0xFF, 0xFF
deps/lld/test/ELF/invalid/bad-reloc-target.test created+76
...@@ -0,0 +1,76 @@
1# RUN: yaml2obj -docnum=1 %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--- !ELF
6FileHeader:
7 Class: ELFCLASS64
8 Data: ELFDATA2LSB
9 Type: ET_REL
10 Machine: EM_X86_64
11Sections:
12 - Name: .text
13 Type: SHT_PROGBITS
14 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
15 - Name: .rela.text
16 Type: SHT_RELA
17 Link: .symtab
18 Info: 0
19 Relocations:
20 - Offset: 0x0000000000000000
21 Symbol: foo
22 Type: R_X86_64_64
23Symbols:
24 - Name: foo
25 Binding: STB_GLOBAL
26
27# RUN: yaml2obj -docnum=2 %s -o %t2.o
28# RUN: not ld.lld %t2.o -o %t2 2>&1 | FileCheck %s --check-prefix=ERR2
29# ERR2: error: {{.*}}.o: invalid relocated section index: 99
30
31--- !ELF
32FileHeader:
33 Class: ELFCLASS64
34 Data: ELFDATA2LSB
35 Type: ET_REL
36 Machine: EM_X86_64
37Sections:
38 - Name: .text
39 Type: SHT_PROGBITS
40 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
41 - Name: .rela.text
42 Type: SHT_RELA
43 Link: .symtab
44 Info: 99
45 Relocations:
46 - Offset: 0x0000000000000000
47 Symbol: foo
48 Type: R_X86_64_64
49Symbols:
50 - Name: foo
51 Binding: STB_GLOBAL
52
53## Relocation refers to a symbol with index larger than
54## symbol table size. Check we report it.
55# RUN: yaml2obj -docnum=3 %s -o %t2.o
56# RUN: not ld.lld %t2.o -o %t2 2>&1 | FileCheck %s --check-prefix=ERR3
57# ERR3: error: {{.*}}.o: invalid symbol index
58
59--- !ELF
60FileHeader:
61 Class: ELFCLASS64
62 Data: ELFDATA2LSB
63 Type: ET_REL
64 Machine: EM_X86_64
65Sections:
66 - Name: .text
67 Type: SHT_PROGBITS
68 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
69 - Name: .rela.text
70 Type: SHT_RELA
71 Link: .symtab
72 Info: .text
73 Relocations:
74 - Offset: 0x0000000000000000
75 Symbol: 255
76 Type: R_X86_64_64
deps/lld/test/ELF/invalid/broken-relaxation-x64.test+7-6
...@@ -38,9 +38,10 @@ Sections:...@@ -38,9 +38,10 @@ Sections:
38 Symbol: foo38 Symbol: foo
39 Type: R_X86_64_GOTTPOFF39 Type: R_X86_64_GOTTPOFF
40Symbols:40Symbols:
41 Global:41 - Name: foo
42 - Name: foo42 Type: STT_TLS
43 Type: STT_TLS43 Section: .text
44 Section: .text44 Value: 0x12345
45 Value: 0x1234545 Size: 4
46 Size: 446 Binding: STB_GLOBAL
47
\ No newline at end of file
deps/lld/test/ELF/invalid/comdat-broken.test+2-2
...@@ -21,5 +21,5 @@ Sections:...@@ -21,5 +21,5 @@ Sections:
21 - SectionOrType: 0xFF21 - SectionOrType: 0xFF
22 - SectionOrType: 322 - SectionOrType: 3
23Symbols:23Symbols:
24 Global:24 - Name: foo
25 - Name: foo25 Binding: STB_GLOBAL
deps/lld/test/ELF/invalid/common-symbol-alignment.s deleted-12
...@@ -1,12 +0,0 @@
1# REQUIRES: x86
2
3## common-symbol-alignment.elf contains common symbol with zero alignment.
4# RUN: not ld.lld %S/Inputs/common-symbol-alignment.elf \
5# RUN: -o %t 2>&1 | FileCheck %s
6# CHECK: common symbol 'bar' has invalid alignment: 0
7
8## common-symbol-alignment2.elf contains common symbol alignment greater
9## than UINT32_MAX.
10# RUN: not ld.lld %S/Inputs/common-symbol-alignment2.elf \
11# RUN: -o %t 2>&1 | FileCheck %s --check-prefix=BIG
12# BIG: common symbol 'bar' has invalid alignment: 271644049215
deps/lld/test/ELF/invalid/common-symbol-alignment.test created+36
...@@ -0,0 +1,36 @@
1## If an object contains a common symbol with zero alignment,
2## check we report it.
3# RUN: yaml2obj -docnum=1 %s -o %t1.o
4# RUN: not ld.lld %t1.o -o %t 2>&1 | FileCheck %s
5# CHECK: common symbol 'bar' has invalid alignment: 0
6
7--- !ELF
8FileHeader:
9 Class: ELFCLASS64
10 Data: ELFDATA2LSB
11 Type: ET_REL
12 Machine: EM_X86_64
13Symbols:
14 - Name: bar
15 Type: STT_FUNC
16 Index: SHN_COMMON
17 Binding: STB_GLOBAL
18
19## If an object contains a common symbol with alignment greater
20## than UINT32_MAX, check we report it.
21# RUN: yaml2obj -docnum=2 %s -o %t2.o
22# RUN: not ld.lld %t2.o -o %t 2>&1 | FileCheck %s --check-prefix=BIG
23# BIG: common symbol 'bar' has invalid alignment: 271644049215
24
25--- !ELF
26FileHeader:
27 Class: ELFCLASS64
28 Data: ELFDATA2LSB
29 Type: ET_REL
30 Machine: EM_X86_64
31Symbols:
32 - Name: bar
33 Type: STT_FUNC
34 Index: SHN_COMMON
35 Value: 0x0000003F3F3F3F3F
36 Binding: STB_GLOBAL
deps/lld/test/ELF/invalid/data-encoding.test created+17
...@@ -0,0 +1,17 @@
1# REQUIRES: x86
2
3# The object in the archive has invalid data encoding.
4# Check we report this.
5
6# RUN: yaml2obj %s -o %t.o
7# RUN: llvm-ar rcs %t.a %t.o
8
9# RUN: not ld.lld --whole-archive %t.a -o /dev/null 2>&1 | FileCheck %s
10# CHECK: {{.*}}.a({{.*}}.o): corrupted ELF file: invalid data encoding
11
12--- !ELF
13FileHeader:
14 Class: ELFCLASS64
15 Data: ELFDATANONE
16 Type: ET_REL
17 Machine: EM_X86_64
deps/lld/test/ELF/invalid/dynamic-section-broken.test created+36
...@@ -0,0 +1,36 @@
1## .dynamic section has invalid sh_entsize, check we report it.
2# RUN: yaml2obj -docnum=1 %s -o %t.so
3# RUN: not ld.lld %t.so -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR1
4# ERR1: error: {{.*}}.so: section [index 1] has an invalid sh_entsize: 291
5
6--- !ELF
7FileHeader:
8 Class: ELFCLASS64
9 Data: ELFDATA2LSB
10 Type: ET_DYN
11 Machine: EM_X86_64
12Sections:
13 - Name: .dynamic
14 Type: SHT_DYNAMIC
15 Flags: [ SHF_ALLOC ]
16 Link: .strtab
17 EntSize: 0x123
18
19## The .dynamic section has invalid sh_size, which is too short and
20## even less than entry size. Check we report it.
21# RUN: yaml2obj -docnum=2 %s -o %t.so
22# RUN: not ld.lld %t.so -o /dev/null 2>&1 | FileCheck %s --check-prefix=ERR2
23# ERR2: error: {{.*}}.so: section [index 1] has an invalid sh_size (1) which is not a multiple of its sh_entsize (16)
24
25--- !ELF
26FileHeader:
27 Class: ELFCLASS64
28 Data: ELFDATA2LSB
29 Type: ET_DYN
30 Machine: EM_X86_64
31Sections:
32 - Name: .dynamic
33 Type: SHT_DYNAMIC
34 Flags: [ SHF_ALLOC ]
35 Link: .strtab
36 Content: "00"
deps/lld/test/ELF/invalid/dynamic-section-size.s deleted-4
...@@ -1,4 +0,0 @@
1## dynamic-section-sh_size.elf has incorrect sh_size of dynamic section.
2# RUN: not ld.lld %p/Inputs/dynamic-section-sh_size.elf -o /dev/null 2>&1 | \
3# RUN: FileCheck %s
4# CHECK: error: {{.*}}: invalid sh_entsize
deps/lld/test/ELF/invalid/ehframe-broken-relocation.test+6-6
...@@ -23,9 +23,9 @@ Sections:...@@ -23,9 +23,9 @@ Sections:
23 Symbol: zed23 Symbol: zed
24 Type: R_X86_64_6424 Type: R_X86_64_64
25Symbols:25Symbols:
26 Global:26 - Name: zed
27 - Name: zed27 Type: STT_FUNC
28 Type: STT_FUNC28 Section: .eh_frame
29 Section: .eh_frame29 Value: 0x0
30 Value: 0x030 Size: 8
31 Size: 831 Binding: STB_GLOBAL
deps/lld/test/ELF/invalid/invalid-binding.test created+19
...@@ -0,0 +1,19 @@
1# RUN: yaml2obj %s -o %t.o
2# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s
3# CHECK: error: {{.*}}.o: unexpected binding: 9
4
5--- !ELF
6FileHeader:
7 Class: ELFCLASS64
8 Data: ELFDATA2LSB
9 OSABI: ELFOSABI_GNU
10 Type: ET_REL
11 Machine: EM_X86_64
12Sections:
13 - Name: .text
14 Type: SHT_PROGBITS
15 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
16Symbols:
17 - Name: foo
18 Section: .text
19 Binding: 0x9
deps/lld/test/ELF/invalid/invalid-debug-relocations.test+6-6
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: yaml2obj %s -o %t.o2# RUN: yaml2obj %s -o %t.o
3# RUN: not ld.lld -gdb-index %t.o -o %t.exe 2>&1 | FileCheck %s3# RUN: not ld.lld -gdb-index %t.o -o %t.exe 2>&1 | FileCheck %s
44
5# CHECK: error: {{.*}}invalid-debug-relocations.test.tmp.o:(.debug_info+0x0): has non-ABS relocation Unknown (255) against symbol '_start'5# CHECK: error: {{.*}}invalid-debug-relocations.test.tmp.o:(.debug_info+0x0): unknown relocation (255) against symbol _start
66
7!ELF7!ELF
8FileHeader:8FileHeader:
...@@ -33,8 +33,8 @@ Sections:...@@ -33,8 +33,8 @@ Sections:
33 Symbol: _start33 Symbol: _start
34 Type: 0xFF34 Type: 0xFF
35Symbols:35Symbols:
36 Global:36 - Name: _start
37 - Name: _start37 Type: STT_FUNC
38 Type: STT_FUNC38 Section: .text
39 Section: .text39 Value: 0x0
40 Value: 0x040 Binding: STB_GLOBAL
deps/lld/test/ELF/invalid/invalid-e_shnum.s deleted-3
...@@ -1,3 +0,0 @@
1## Spec says that "If a file has no section header table, e_shnum holds the value zero.", though
2## in this test case it holds non-zero and lld used to crash.
3# RUN: ld.lld %p/Inputs/invalid-e_shnum.elf -o /dev/null
deps/lld/test/ELF/invalid/invalid-e_shnum.test created+15
...@@ -0,0 +1,15 @@
1## Spec says that "If a file has no section header table, e_shnum holds the value zero.", though
2## in this test case it holds non-zero and lld used to crash.
3
4# RUN: yaml2obj %s -o %t
5# RUN: ld.lld %t -o /dev/null
6
7--- !ELF
8FileHeader:
9 Class: ELFCLASS64
10 Data: ELFDATA2LSB
11 Type: ET_REL
12 Machine: EM_X86_64
13 SHOffset: 0
14 SHNum: 0x1
15 SHStrNdx: 0
deps/lld/test/ELF/invalid/invalid-elf.test+5-28
...@@ -1,28 +1,5 @@...@@ -1,28 +1,5 @@
1# REQUIRES: x861# RUN: rm -rf %t && mkdir -p %t
2# RUN: llvm-mc %s -o %t -filetype=obj -triple x86_64-pc-linux2# RUN: echo > %t/empty.o
33# RUN: llvm-ar --format=gnu cr %t/not-elf.a %t/empty.o
4# RUN: not ld.lld %t %p/Inputs/data-encoding.a -o %t2 2>&1 | \4# RUN: not ld.lld --whole-archive %t/not-elf.a -o %t2 2>&1 | FileCheck %s
5# RUN: FileCheck --check-prefix=INVALID-DATA-ENC %s5# CHECK: not-elf.a(empty.o): not an ELF file
6# INVALID-DATA-ENC: test.o: invalid data encoding
7
8# RUN: not ld.lld %t %p/Inputs/file-class.a -o %t2 2>&1 | \
9# RUN: FileCheck --check-prefix=INVALID-FILE-CLASS %s
10# INVALID-FILE-CLASS: test.o: invalid file class
11
12# RUN: not ld.lld %p/Inputs/symtab-sh_info.elf -o %t2 2>&1 | \
13# RUN: FileCheck --check-prefix=INVALID-SYMTAB-SHINFO %s
14# INVALID-SYMTAB-SHINFO: invalid sh_info in symbol table
15
16# RUN: not ld.lld %p/Inputs/binding.elf -o %t2 2>&1 | \
17# RUN: FileCheck --check-prefix=INVALID-BINDING %s
18# INVALID-BINDING: unexpected binding
19
20# RUN: not ld.lld %p/Inputs/section-index.elf -o %t2 2>&1 | \
21# RUN: FileCheck --check-prefix=INVALID-SECTION-INDEX-LLD %s
22# INVALID-SECTION-INDEX-LLD: invalid section index
23
24# RUN: not ld.lld %p/Inputs/multiple-eh-relocs.elf -o %t2 2>&1 | \
25# RUN: FileCheck --check-prefix=INVALID-EH-RELOCS %s
26# INVALID-EH-RELOCS: multiple relocation sections to one section are not supported
27
28.long foo
deps/lld/test/ELF/invalid/invalid-file-class.test created+19
...@@ -0,0 +1,19 @@
1# REQUIRES: x86
2# RUN: rm -rf %t && mkdir -p %t
3
4## In this test, we check that able to report objects with
5## invalid ELF class type. There are 2 cases we want to check:
6## when the object is a regular input and when it is fetched from the archive.
7
8## Create a broken ELF object with ELFCLASSNONE class using echo. We need to fill
9## first 18 bytes which are used by LLD to check the object.
10## 0x7f, 'E', 'L', 'F', ELFCLASSNONE(0), ELFDATA2LSB(1),
11## EV_CURRENT(1), ELFOSABI_LINUX(3), <padding zero bytes>, ET_REL(1), EM_NONE(0)
12# RUN: echo -e -n "\x7f\x45\x4c\x46\x00\x01\x01\x03\x00\x00\x00\x00\x00\x00\x00\x00\x01\x00" > %t/invalid.o
13
14# RUN: llvm-ar --format=gnu cr %t/invalid-class.a %t/invalid.o
15# RUN: not ld.lld -whole-archive %t/invalid-class.a -o %t2 2>&1 | FileCheck %s
16# CHECK: invalid-class.a(invalid.o): corrupted ELF file: invalid file class
17
18# RUN: not ld.lld %t/invalid.o -o %t2 2>&1 | FileCheck %s --check-prefix=OBJ
19# OBJ: invalid.o: corrupted ELF file: invalid file class
deps/lld/test/ELF/invalid/invalid-relocation-x64.test+4-4
...@@ -3,8 +3,8 @@...@@ -3,8 +3,8 @@
3# RUN: echo ".global foo; foo:" > %t2.s3# RUN: echo ".global foo; foo:" > %t2.s
4# RUN: llvm-mc %t2.s -o %t2.o -filetype=obj -triple x86_64-pc-linux4# RUN: llvm-mc %t2.s -o %t2.o -filetype=obj -triple x86_64-pc-linux
5# RUN: not ld.lld %t1.o %t2.o -o /dev/null 2>&1 | FileCheck %s5# RUN: not ld.lld %t1.o %t2.o -o /dev/null 2>&1 | FileCheck %s
6# CHECK: error: unrecognized reloc 1526# CHECK: error: unknown relocation (152) against symbol foo
7# CHECK: error: unrecognized reloc 1537# CHECK: error: unknown relocation (153) against symbol foo
88
9!ELF9!ELF
10FileHeader:10FileHeader:
...@@ -29,5 +29,5 @@ Sections:...@@ -29,5 +29,5 @@ Sections:
29 Symbol: foo29 Symbol: foo
30 Type: 0x9930 Type: 0x99
31Symbols:31Symbols:
32 Global:32 - Name: foo
33 - Name: foo33 Binding: STB_GLOBAL
deps/lld/test/ELF/invalid/invalid-soname.test+4-1
...@@ -14,5 +14,8 @@ Sections:...@@ -14,5 +14,8 @@ Sections:
14 - Name: .test14 - Name: .test
15 Type: SHT_DYNAMIC15 Type: SHT_DYNAMIC
16 Flags: [ SHF_ALLOC ]16 Flags: [ SHF_ALLOC ]
17 Content: "0e000000000000000000000000000001"
18 Link: .strtab17 Link: .strtab
18 EntSize: 0x0000000000000010
19 Entries:
20 - Tag: DT_SONAME
21 Value: 0x0100000000000000
deps/lld/test/ELF/invalid/mips-invalid-options-descriptor.s deleted-5
...@@ -1,5 +0,0 @@
1## mips-invalid-options-descriptor.elf has option descriptor in
2## .MIPS.options with size of zero.
3# RUN: not ld.lld %p/Inputs/mips-invalid-options-descriptor.elf -o /dev/null 2>&1 | \
4# RUN: FileCheck %s
5# CHECK: error: {{.*}}: invalid section offset
deps/lld/test/ELF/invalid/mips-invalid-options-descriptor.test created+21
...@@ -0,0 +1,21 @@
1# RUN: yaml2obj %s -o %t1.o
2# RUN: not ld.lld %t1.o -o %t 2>&1 | FileCheck %s
3# CHECK: error: {{.*}}1.o: zero option descriptor size
4
5## YAML has a description of ODK_NULL (Undefined) MIPS option,
6## with a size of zero. We do not allow options with a zero size.
7## Check we report it.
8
9--- !ELF
10FileHeader:
11 Class: ELFCLASS64
12 Data: ELFDATA2MSB
13 Type: ET_REL
14 Machine: EM_MIPS
15 Flags: [ EF_MIPS_CPIC, EF_MIPS_ARCH_64 ]
16Sections:
17 - Name: .MIPS.options
18 Type: SHT_MIPS_OPTIONS
19 Flags: [ SHF_ALLOC, SHF_MIPS_NOSTRIP ]
20 AddressAlign: 0x0000000000000008
21 Content: '0000000000000000'
deps/lld/test/ELF/invalid/multiple-relocations-sections.test created+29
...@@ -0,0 +1,29 @@
1# RUN: yaml2obj %s -o %t1.o
2# RUN: not ld.lld %t1.o -o %t 2>&1 | FileCheck %s
3# CHECK: error: {{.*}}1.o: multiple relocation sections to one section are not supported
4
5## The file has two relocation sections referring to a single target section.
6## Multiple relocation sections to one section are not supported, check we report this case.
7
8--- !ELF
9FileHeader:
10 Class: ELFCLASS64
11 Data: ELFDATA2LSB
12 Type: ET_REL
13 Machine: EM_X86_64
14Sections:
15 - Name: .text
16 Type: SHT_PROGBITS
17 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
18 - Name: .rela.text1
19 Type: SHT_RELA
20 Link: .symtab
21 Info: .text
22 - Name: .rela.text2
23 Type: SHT_RELA
24 Link: .symtab
25 Info: .text
26Symbols:
27 - Name: .text
28 Type: STT_SECTION
29 Section: .text
deps/lld/test/ELF/invalid/reloc-section-reordered.test+4
...@@ -28,3 +28,7 @@ Sections:...@@ -28,3 +28,7 @@ Sections:
28 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]28 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
29 AddressAlign: 0x0429 AddressAlign: 0x04
30 Content: "FFFFFFFFFFFFFFFF"30 Content: "FFFFFFFFFFFFFFFF"
31Symbols:
32 - Name: .text
33 Type: STT_SECTION
34 Section: .text
deps/lld/test/ELF/invalid/section-alignment2.s+16-5
...@@ -1,5 +1,16 @@...@@ -1,5 +1,16 @@
1## section-alignment-notpow2.elf has section alignment1# RUN: yaml2obj %s -o %t.o
2## 0xFFFFFFFF which is not a power of 2.2# RUN: not ld.lld %t.o -o %tout 2>&1 | FileCheck %s
3# RUN: not ld.lld %p/Inputs/section-alignment-notpow2.elf -o /dev/null 2>&1 | \3
4# RUN: FileCheck %s4# CHECK: error: {{.*}}.o:(.text): sh_addralign is not a power of 2
5# CHECK: section sh_addralign is not a power of 25
6!ELF
7FileHeader:
8 Class: ELFCLASS64
9 Data: ELFDATA2LSB
10 Type: ET_REL
11 Machine: EM_X86_64
12Sections:
13 - Name: .text
14 Type: SHT_PROGBITS
15 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
16 AddressAlign: 0x3
deps/lld/test/ELF/invalid/section-index.test created+16
...@@ -0,0 +1,16 @@
1## If an object contains a symbol with a broken (too large) st_shndx,
2## check we report it.
3
4# RUN: yaml2obj %s -o %t1.o
5# RUN: not ld.lld %t1.o -o %t 2>&1 | FileCheck %s
6# CHECK: {{.*}}1.o: invalid section index: 256
7
8!ELF
9FileHeader:
10 Class: ELFCLASS32
11 Data: ELFDATA2LSB
12 Type: ET_REL
13 Machine: EM_386
14Symbols:
15 - Name: foo
16 Index: 0x100
deps/lld/test/ELF/invalid/sht-group-wrong-section.test+2-2
...@@ -18,5 +18,5 @@ Sections:...@@ -18,5 +18,5 @@ Sections:
18 - SectionOrType: GRP_COMDAT18 - SectionOrType: GRP_COMDAT
19 - SectionOrType: 1234519 - SectionOrType: 12345
20Symbols:20Symbols:
21 Global:21 - Name: foo
22 - Name: foo22 Binding: STB_GLOBAL
deps/lld/test/ELF/invalid/symbol-index.s deleted-10
...@@ -1,10 +0,0 @@
1## symbol-index.elf has incorrect type of .symtab section.
2## There is no symbol bodies because of that and any symbol index becomes incorrect.
3## Section Headers:
4## [Nr] Name Type Address Off Size ES Flg Lk Inf Al
5## [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
6## ...
7## [ 4] .symtab RELA 0000000000000000 000048 000030 18 1 2 8
8# RUN: not ld.lld %p/Inputs/symbol-index.elf -o /dev/null 2>&1 | \
9# RUN: FileCheck --check-prefix=INVALID-SYMBOL-INDEX %s
10# INVALID-SYMBOL-INDEX: invalid symbol index
deps/lld/test/ELF/invalid/symbol-name.s deleted-7
...@@ -1,7 +0,0 @@
1# REQUIRES: x86
2
3## symbol-name-offset.elf contains symbol with invalid (too large)
4## st_name value.
5# RUN: not ld.lld %S/Inputs/symbol-name-offset.elf \
6# RUN: -o /dev/null 2>&1 | FileCheck %s
7# CHECK: invalid symbol name offset
deps/lld/test/ELF/invalid/symbol-name.test created+15
...@@ -0,0 +1,15 @@
1# RUN: yaml2obj %s -o %t.o
2# RUN: not ld.lld %t.o -o %t.exe 2>&1 | FileCheck %s
3# CHECK: error: {{.*}}.o: invalid symbol name offset
4
5## YAML below contains symbol with name offset in st_name
6## larger than string table size. Check we report it.
7
8!ELF
9FileHeader:
10 Class: ELFCLASS64
11 Data: ELFDATA2LSB
12 Type: ET_REL
13 Machine: EM_X86_64
14Symbols:
15 - NameIndex: 255
deps/lld/test/ELF/invalid/symtab-sh-info.s+59-9
...@@ -1,9 +1,59 @@...@@ -1,9 +1,59 @@
1## sh_info contains zero value. First entry in a symbol table is always completely zeroed,1## .symtab's sh_info contains zero value. First entry in a .symtab is a
2## so sh_info should be at least 1 in a valid ELF.2## zero entry that must exist in a valid object, so sh_info can't be null.
3# RUN: not ld.lld %p/Inputs/symtab-sh_info2.elf -o %t2 2>&1 | FileCheck %s3## Check we report a proper error for that case.
4# CHECK: invalid sh_info in symbol table4# RUN: yaml2obj -docnum=1 %s -o %t.o
55# RUN: not ld.lld %t.o -o %t2 2>&1 | FileCheck %s --check-prefix=ERR1
6## sh_info contains invalid value saying non-local symbol is local.6# ERR1: invalid sh_info in symbol table
7# RUN: not ld.lld %p/Inputs/symtab-sh_info3.elf -o %t2 2>&1 | \7
8# RUN: FileCheck --check-prefix=INVALID-SYMTAB-SHINFO %s8--- !ELF
9# INVALID-SYMTAB-SHINFO: broken object: getLocalSymbols returns a non-local symbol9FileHeader:
10 Class: ELFCLASS64
11 Data: ELFDATA2LSB
12 Type: ET_REL
13 Machine: EM_X86_64
14Sections:
15 - Name: .symtab
16 Info: 0
17 Type: SHT_SYMTAB
18Symbols:
19 - Name: foo
20 Binding: STB_GLOBAL
21
22## sh_info has value 2 what says that non-local symbol `foo` is local.
23## Check we report this case.
24# RUN: yaml2obj -docnum=2 %s -o %t.o
25# RUN: not ld.lld %t.o -o %t2 2>&1 | FileCheck --check-prefix=ERR2 %s
26# ERR2: broken object: getLocalSymbols returns a non-local symbol
27
28--- !ELF
29FileHeader:
30 Class: ELFCLASS64
31 Data: ELFDATA2LSB
32 Type: ET_REL
33 Machine: EM_X86_64
34Sections:
35 - Name: .symtab
36 Info: 2
37 Type: SHT_SYMTAB
38Symbols:
39 - Name: foo
40 Binding: STB_GLOBAL
41
42## sh_info has value 0xff what is larger than number of symbols in a .symtab.
43## Check we report this case.
44# RUN: yaml2obj -docnum=3 %s -o %t.o
45# RUN: not ld.lld %t.o -o %t2 2>&1 | FileCheck --check-prefix=ERR1 %s
46
47--- !ELF
48FileHeader:
49 Class: ELFCLASS64
50 Data: ELFDATA2LSB
51 Type: ET_REL
52 Machine: EM_X86_64
53Sections:
54 - Name: .symtab
55 Info: 0xff
56 Type: SHT_SYMTAB
57Symbols:
58 - Name: foo
59 Binding: STB_GLOBAL
deps/lld/test/ELF/invalid/symtab-symbols.test+2-3
...@@ -20,6 +20,5 @@ Sections:...@@ -20,6 +20,5 @@ Sections:
20 AddressAlign: 0x000000000000001020 AddressAlign: 0x0000000000000010
21 Content: "00000000"21 Content: "00000000"
22Symbols:22Symbols:
23 Local:23 - Type: STT_NOTYPE
24 - Type: STT_NOTYPE24 Section: .symtab
25 Section: .symtab
deps/lld/test/ELF/invalid/tls-symbol.s+22-3
...@@ -1,5 +1,24 @@...@@ -1,5 +1,24 @@
1# REQUIRES: x86
2
3## The test file contains an STT_TLS symbol but has no TLS section.1## The test file contains an STT_TLS symbol but has no TLS section.
4# RUN: not ld.lld %S/Inputs/tls-symbol.elf -o /dev/null 2>&1 | FileCheck %s2## Check we report an error properly.
3
4# RUN: yaml2obj %s -o %t.o
5# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s
6
5# CHECK: has an STT_TLS symbol but doesn't have an SHF_TLS section7# CHECK: has an STT_TLS symbol but doesn't have an SHF_TLS section
8
9--- !ELF
10FileHeader:
11 Class: ELFCLASS64
12 Data: ELFDATA2LSB
13 Type: ET_REL
14 Machine: EM_X86_64
15Sections:
16 - Name: .text
17 Type: SHT_PROGBITS
18 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
19 Content: ''
20Symbols:
21 - Name: bar
22 Type: STT_TLS
23 Section: .text
24 Binding: STB_GLOBAL
deps/lld/test/ELF/invalid/undefined-local-symbol-in-dso.test+16-56
...@@ -8,59 +8,19 @@...@@ -8,59 +8,19 @@
8# STB_LOCAL is a nonsensical combination. Nevertheless, we should warn on such8# STB_LOCAL is a nonsensical combination. Nevertheless, we should warn on such
9# input files instead of crashing.9# input files instead of crashing.
1010
11# We've found actual broken DSOs of this sort in the wild, but for this test, we11# RUN: yaml2obj %s -o %t.so
12# created a reduced broken input file. There are no tools capable of producing a12# RUN: ld.lld %t.so -o %t 2>&1 | FileCheck -check-prefix=WARN %s
13# broken DSO of this nature, so instead we created a valid DSO with an undefined13# WARN: found local symbol 'foo' in global part of symbol table in file {{.*}}.so
14# global symbol in the dynamic symbol table and then manually edited the binary14
15# to make that symbol local. The valid DSO was created as follows:15--- !ELF
1616FileHeader:
17```17 Class: ELFCLASS64
18% cat undef.s18 Data: ELFDATA2LSB
19.hidden bar19 Type: ET_DYN
20bar:20 Machine: EM_X86_64
21 movq foo@GOT, %rax21Sections:
2222 - Name: .dynsym
23% llvm-mc -triple=x86_64-linux-gnu -filetype=obj -o undef.o undef.s23 Info: 1
24% ld.lld --no-rosegment -shared -o undefined-local-symbol-in-dso.so undef.o24 Type: SHT_DYNSYM
25% strip undef.so25DynamicSymbols:
26```26 - Name: foo
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
39int 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/invalid/verdef-no-symtab.test+1-8
...@@ -14,13 +14,6 @@ Sections:...@@ -14,13 +14,6 @@ Sections:
14 Type: SHT_GNU_versym14 Type: SHT_GNU_versym
15 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]15 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
16 AddressAlign: 0x116 AddressAlign: 0x1
17 Content: "00000000"17 Entries: [ 0 ]
18
19 - Name: .verdef
20 Type: SHT_GNU_verdef
21 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
22 AddressAlign: 0x1
23 Content: "00000000"
24
2518
26# CHECK: SHT_GNU_versym should be associated with symbol table19# CHECK: SHT_GNU_versym should be associated with symbol table
deps/lld/test/ELF/invalid/x86-64-tlsdesc-gd.s created+15
...@@ -0,0 +1,15 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: echo '.tbss; .globl a; a:' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o
4# RUN: ld.lld -shared %t1.o -o %t1.so
5
6## GD to LE relaxation.
7# RUN: not ld.lld %t.o %t1.o -o /dev/null 2>&1 | FileCheck -DINPUT=%t.o %s
8## GD to IE relaxation.
9# RUN: not ld.lld %t.o %t1.so -o /dev/null 2>&1 | FileCheck -DINPUT=%t.o %s
10
11# CHECK: error: [[INPUT]]:(.text+0x0): R_X86_64_GOTPC32_TLSDESC must be used in callq *x@tlsdesc(%rip), %rax
12
13leaq a@tlsdesc(%rip), %rdx
14call *a@tlscall(%rdx)
15movl %fs:(%rax), %eax
deps/lld/test/ELF/linkerscript/absolute-expr.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: echo ".global foo; foo = 0x123" | llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t.o2# RUN: echo ".global foo; foo = 0x123" | llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t.o
3# RUN: ld.lld -o %t.so --script %s %t.o -shared3# RUN: ld.lld -o %t.so --script %s %t.o -shared
4# RUN: llvm-readobj -t %t.so | FileCheck %s4# RUN: llvm-readobj --symbols %t.so | FileCheck %s
55
6SECTIONS {6SECTIONS {
7 .text : {7 .text : {
deps/lld/test/ELF/linkerscript/addr-zero.test+10-4
...@@ -1,14 +1,14 @@...@@ -1,14 +1,14 @@
1# REQUIRES: x861# REQUIRES: x86, aarch64
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t.o
3# RUN: ld.lld -o %t.so --script %s %t.o -shared3# RUN: ld.lld -o %t.so --script %s %t.o -shared
4# RUN: llvm-readobj --symbols %t.so | FileCheck %s4# RUN: llvm-readobj --symbols %t.so | FileCheck %s
55
6# Test that the script creates a non absolute symbol with value6## Test that the script creates a non absolute symbol with value
7# 0 I.E., a symbol that refers to the load address.7## 0 I.E., a symbol that refers to the load address.
88
9# CHECK: Symbol {9# CHECK: Symbol {
10# CHECK: Name: foo10# CHECK: Name: foo
11# CHECK-NEXT: Value: 0x7011# CHECK-NEXT: Value: 0x0
12# CHECK-NEXT: Size: 012# CHECK-NEXT: Size: 0
13# CHECK-NEXT: Binding: Global13# CHECK-NEXT: Binding: Global
14# CHECK-NEXT: Type: None14# CHECK-NEXT: Type: None
...@@ -16,6 +16,12 @@...@@ -16,6 +16,12 @@
16# CHECK-NEXT: Section: .text16# CHECK-NEXT: Section: .text
17# CHECK-NEXT: }17# CHECK-NEXT: }
1818
19## Because of a bug we had a different behavior (different symbol 'foo' value)
20## on a platforms that might use thunks, like AArch64. Check that issue is fixed.
21# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-gnu /dev/null -o %t.o
22# RUN: ld.lld -o %t.so --script %s %t.o -shared
23# RUN: llvm-readobj --symbols %t.so | FileCheck %s
24
19SECTIONS {25SECTIONS {
20 foo = ADDR(.text) - ABSOLUTE(ADDR(.text));26 foo = ADDR(.text) - ABSOLUTE(ADDR(.text));
21};27};
deps/lld/test/ELF/linkerscript/addr.test+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-objdump -section-headers %t1 | FileCheck %s4# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
55
6# CHECK: Sections:6# CHECK: Sections:
7# CHECK-NEXT: Idx Name Size Address Type7# CHECK-NEXT: Idx Name Size VMA Type
8# CHECK-NEXT: 0 00000000 00000000000000008# CHECK-NEXT: 0 00000000 0000000000000000
9# CHECK-NEXT: 1 .text 00000000 0000000000001000 TEXT9# CHECK-NEXT: 1 .text 00000000 0000000000001000 TEXT
10# CHECK-NEXT: 2 .foo.1 00000008 0000000000001000 DATA10# CHECK-NEXT: 2 .foo.1 00000008 0000000000001000 DATA
deps/lld/test/ELF/linkerscript/align-empty.test+1-1
...@@ -13,7 +13,7 @@ SECTIONS {...@@ -13,7 +13,7 @@ SECTIONS {
13}13}
1414
15# CHECK: Sections:15# CHECK: Sections:
16# CHECK-NEXT: Idx Name Size Address16# CHECK-NEXT: Idx Name Size VMA
17# CHECK-NEXT: 0 00000000 000000000000000017# CHECK-NEXT: 0 00000000 0000000000000000
18# CHECK-NEXT: 1 .dynsym 00000018 000000000000019018# CHECK-NEXT: 1 .dynsym 00000018 0000000000000190
19# CHECK-NEXT: 2 .gnu.hash 0000001c 00000000000001a819# CHECK-NEXT: 2 .gnu.hash 0000001c 00000000000001a8
deps/lld/test/ELF/linkerscript/align1.test+2-2
...@@ -13,7 +13,7 @@ SECTIONS {...@@ -13,7 +13,7 @@ SECTIONS {
13}13}
1414
15# CHECK: Sections:15# CHECK: Sections:
16# CHECK-NEXT: Idx Name Size Address Type16# CHECK-NEXT: Idx Name Size VMA Type
17# CHECK-NEXT: 0 00000000 000000000000000017# CHECK-NEXT: 0 00000000 0000000000000000
18# CHECK-NEXT: 1 .aaa 00000008 0000000000010000 DATA18# CHECK-NEXT: 1 .aaa 00000008 0000000000010000 DATA
19# CHECK-NEXT: 2 .bbb 00000008 0000000000011000 DATA19# CHECK-NEXT: 2 .bbb 00000008 0000000000011000 DATA
...@@ -25,7 +25,7 @@ SECTIONS {...@@ -25,7 +25,7 @@ SECTIONS {
25# RUN: llvm-objdump -section-headers %t4 | FileCheck %s -check-prefix=ZERO25# RUN: llvm-objdump -section-headers %t4 | FileCheck %s -check-prefix=ZERO
2626
27# ZERO: Sections:27# ZERO: Sections:
28# ZERO-NEXT: Idx Name Size Address Type28# ZERO-NEXT: Idx Name Size VMA Type
29# ZERO-NEXT: 0 00000000 000000000000000029# ZERO-NEXT: 0 00000000 0000000000000000
30# ZERO-NEXT: 1 .aaa 00000008 0000000000000123 DATA30# ZERO-NEXT: 1 .aaa 00000008 0000000000000123 DATA
3131
deps/lld/test/ELF/linkerscript/align2.test+1-1
...@@ -13,7 +13,7 @@ SECTIONS {...@@ -13,7 +13,7 @@ SECTIONS {
13}13}
1414
15# CHECK: Sections:15# CHECK: Sections:
16# CHECK-NEXT: Idx Name Size Address Type16# CHECK-NEXT: Idx Name Size VMA Type
17# CHECK-NEXT: 0 00000000 000000000000000017# CHECK-NEXT: 0 00000000 0000000000000000
18# CHECK-NEXT: 1 .aaa 00000008 0000000000010000 DATA18# CHECK-NEXT: 1 .aaa 00000008 0000000000010000 DATA
19# CHECK-NEXT: 2 .bbb 00000008 0000000000011000 DATA19# CHECK-NEXT: 2 .bbb 00000008 0000000000011000 DATA
deps/lld/test/ELF/linkerscript/align3.test+1-1
...@@ -11,7 +11,7 @@ SECTIONS {...@@ -11,7 +11,7 @@ SECTIONS {
11}11}
1212
13# CHECK: Sections:13# CHECK: Sections:
14# CHECK-NEXT: Idx Name Size Address Type14# CHECK-NEXT: Idx Name Size VMA Type
15# CHECK-NEXT: 0 00000000 000000000000000015# CHECK-NEXT: 0 00000000 0000000000000000
16# CHECK-NEXT: 1 .aaa 00000008 0000000000010000 DATA16# CHECK-NEXT: 1 .aaa 00000008 0000000000010000 DATA
17# CHECK-NEXT: 2 .bbb 00000008 0000000000011000 DATA17# CHECK-NEXT: 2 .bbb 00000008 0000000000011000 DATA
deps/lld/test/ELF/linkerscript/alternate-sections.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: echo "SECTIONS { abc : { *(foo) *(bar) *(zed) } }" > %t.script3# RUN: echo "SECTIONS { abc : { *(foo) *(bar) *(zed) } }" > %t.script
4# RUN: ld.lld -o %t --script %t.script %t.o -shared4# RUN: ld.lld -o %t --script %t.script %t.o -shared
5# RUN: llvm-readobj -s -section-data %t | FileCheck %s5# RUN: llvm-readobj -S --section-data %t | FileCheck %s
66
7# CHECK: Section {7# CHECK: Section {
8# CHECK: Index:8# CHECK: Index:
deps/lld/test/ELF/linkerscript/arm-exidx-order.test+2-2
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: echo ".fnstart; .cantunwind; .fnend" \2# RUN: echo ".fnstart; .cantunwind; .fnend" \
3# RUN: | llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi - -o %t.o3# RUN: | llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi - -o %t.o
4# RUN: ld.lld -T %s %t.o -shared -o %t.so4# RUN: ld.lld -T %s %t.o -shared -o %t.so
5# RUN: llvm-readobj -s %t.so | FileCheck %s5# RUN: llvm-readobj -S %t.so | FileCheck %s
66
7SECTIONS {7SECTIONS {
8 . = SIZEOF_HEADERS;8 . = SIZEOF_HEADERS;
...@@ -13,7 +13,7 @@ SECTIONS {...@@ -13,7 +13,7 @@ SECTIONS {
13# CHECK: Section {13# CHECK: Section {
14# CHECK: Index:14# CHECK: Index:
15# CHECK: Name: .foo15# CHECK: Name: .foo
16# CHECK-NEXT: Type: SHT_NOBITS16# CHECK-NEXT: Type: SHT_PROGBITS
17# CHECK-NEXT: Flags [17# CHECK-NEXT: Flags [
18# CHECK-NEXT: SHF_ALLOC18# CHECK-NEXT: SHF_ALLOC
19# CHECK-NEXT: ]19# CHECK-NEXT: ]
deps/lld/test/ELF/linkerscript/arm-exidx-sentinel-and-assignment.s+1-1
...@@ -8,7 +8,7 @@...@@ -8,7 +8,7 @@
8## was anything but an input section description.8## was anything but an input section description.
9# RUN: ld.lld --no-merge-exidx-entries -T %t.script %t.o -shared -o %t.so9# RUN: ld.lld --no-merge-exidx-entries -T %t.script %t.o -shared -o %t.so
10# RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s10# RUN: llvm-objdump -s -triple=armv7a-none-linux-gnueabi %t.so | FileCheck %s
11# RUN: llvm-readobj -s -t %t.so | FileCheck %s --check-prefix=SYMBOL11# RUN: llvm-readobj -S --symbols %t.so | FileCheck %s --check-prefix=SYMBOL
1212
13 .syntax unified13 .syntax unified
14 .text14 .text
deps/lld/test/ELF/linkerscript/at-addr.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: .ccc : AT(ADDR(.ccc) - 0x500) { *(.ccc) } \6# RUN: .ccc : AT(ADDR(.ccc) - 0x500) { *(.ccc) } \
7# RUN: }" > %t.script7# RUN: }" > %t.script
8# RUN: ld.lld %t --script %t.script -o %t28# RUN: ld.lld %t --script %t.script -o %t2
9# RUN: llvm-readobj -program-headers %t2 | FileCheck %s9# RUN: llvm-readobj -l %t2 | FileCheck %s
1010
11# CHECK: Type: PT_LOAD11# CHECK: Type: PT_LOAD
12# CHECK-NEXT: Offset: 0x100012# CHECK-NEXT: Offset: 0x1000
deps/lld/test/ELF/linkerscript/at-self-reference.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: .bbb : AT(ADDR(.bbb)) { *(.bbb) } \6# RUN: .bbb : AT(ADDR(.bbb)) { *(.bbb) } \
7# RUN: }" > %t.script7# RUN: }" > %t.script
8# RUN: ld.lld %t --script %t.script -o %t28# RUN: ld.lld %t --script %t.script -o %t2
9# RUN: llvm-readobj -program-headers %t2 | FileCheck %s9# RUN: llvm-readobj -l %t2 | FileCheck %s
1010
11# CHECK: ProgramHeaders [11# CHECK: ProgramHeaders [
12# CHECK-NEXT: ProgramHeader {12# CHECK-NEXT: ProgramHeader {
deps/lld/test/ELF/linkerscript/at.s+1-1
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9# RUN: .eee 0x5000 : AT(0x5000) { *(.eee) } \9# RUN: .eee 0x5000 : AT(0x5000) { *(.eee) } \
10# RUN: }" > %t.script10# RUN: }" > %t.script
11# RUN: ld.lld %t --script %t.script -o %t211# RUN: ld.lld %t --script %t.script -o %t2
12# RUN: llvm-readobj -program-headers %t2 | FileCheck %s12# RUN: llvm-readobj -l %t2 | FileCheck %s
1313
14# CHECK: ProgramHeaders [14# CHECK: ProgramHeaders [
15# CHECK-NEXT: ProgramHeader {15# CHECK-NEXT: ProgramHeader {
deps/lld/test/ELF/linkerscript/at2.test+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/at2.s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/at2.s -o %t.o
3# RUN: ld.lld -o %t.exe %t.o --script %s3# RUN: ld.lld -o %t.exe %t.o --script %s
4# RUN: llvm-readobj -program-headers %t.exe | FileCheck %s4# RUN: llvm-readobj -l %t.exe | FileCheck %s
5# RUN: llvm-objdump -section-headers %t.exe | FileCheck %s --check-prefix=SECTIONS5# RUN: llvm-objdump -section-headers %t.exe | FileCheck %s --check-prefix=SECTIONS
66
7MEMORY {7MEMORY {
...@@ -48,7 +48,7 @@ SECTIONS {...@@ -48,7 +48,7 @@ SECTIONS {
48# CHECK-NEXT: }48# CHECK-NEXT: }
4949
50# SECTIONS: Sections:50# SECTIONS: Sections:
51# SECTIONS-NEXT: Idx Name Size Address51# SECTIONS-NEXT: Idx Name Size VMA
52# SECTIONS-NEXT: 0 00000000 000000000000000052# SECTIONS-NEXT: 0 00000000 0000000000000000
53# SECTIONS-NEXT: 1 .foo1 00000008 000000000000200053# SECTIONS-NEXT: 1 .foo1 00000008 0000000000002000
54# SECTIONS-NEXT: 2 .foo2 00000008 000000000000200854# SECTIONS-NEXT: 2 .foo2 00000008 0000000000002008
deps/lld/test/ELF/linkerscript/at4.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: .ccc : { *(.ccc) } \7# RUN: .ccc : { *(.ccc) } \
8# RUN: }" > %t.script8# RUN: }" > %t.script
9# RUN: ld.lld %t --script %t.script -o %t29# RUN: ld.lld %t --script %t.script -o %t2
10# RUN: llvm-readobj -program-headers %t2 | FileCheck %s10# RUN: llvm-readobj -l %t2 | FileCheck %s
1111
12# CHECK: Type: PT_LOAD12# CHECK: Type: PT_LOAD
13# CHECK-NEXT: Offset: 0x100013# CHECK-NEXT: Offset: 0x1000
deps/lld/test/ELF/linkerscript/comdat-gc.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/comdat-gc.s -o %t14# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/comdat-gc.s -o %t1
5# RUN: echo "SECTIONS { .text : { *(.text*) } }" > %t.script5# RUN: echo "SECTIONS { .text : { *(.text*) } }" > %t.script
6# RUN: ld.lld --gc-sections --script %t.script %t %t1 -o %t26# RUN: ld.lld --gc-sections --script %t.script %t %t1 -o %t2
7# RUN: llvm-readobj -sections -symbols %t2 | FileCheck -check-prefix=GC1 %s7# RUN: llvm-readobj --sections --symbols %t2 | FileCheck -check-prefix=GC1 %s
88
9# GC1: Name: .debug_line9# GC1: Name: .debug_line
1010
deps/lld/test/ELF/linkerscript/common-assign.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; pfoo = foo; pbar = bar; }" > %t.script3# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; pfoo = foo; pbar = bar; }" > %t.script
4# RUN: ld.lld -o %t1 --script %t.script %t4# RUN: ld.lld -o %t1 --script %t.script %t
5# RUN: llvm-readobj -symbols %t1 | FileCheck %s5# RUN: llvm-readobj --symbols %t1 | FileCheck %s
66
7# CHECK: Symbol {7# CHECK: Symbol {
8# CHECK: Name: bar8# CHECK: Name: bar
deps/lld/test/ELF/linkerscript/common-exclude.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec2.s -o %tfile2.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec2.s -o %tfile2.o
5# RUN: echo "SECTIONS { .common.incl : { *(EXCLUDE_FILE (*file2.o) COMMON) } .common.excl : { *(COMMON) } }" > %t.script5# RUN: echo "SECTIONS { .common.incl : { *(EXCLUDE_FILE (*file2.o) COMMON) } .common.excl : { *(COMMON) } }" > %t.script
6# RUN: ld.lld -o %t1 --script %t.script %tfile0.o %tfile1.o %tfile2.o6# RUN: ld.lld -o %t1 --script %t.script %tfile0.o %tfile1.o %tfile2.o
7# RUN: llvm-readobj -s -t %t1 | FileCheck %s7# RUN: llvm-readobj -S --symbols %t1 | FileCheck %s
88
9# Commons from file0 and file1 are not excluded, so they must be in .common.incl9# Commons from file0 and file1 are not excluded, so they must be in .common.incl
10# Commons from file2 are excluded from the first rule and should be caught by10# Commons from file2 are excluded from the first rule and should be caught by
deps/lld/test/ELF/linkerscript/common-filespec.test+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec1.s -o %tfile1.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec1.s -o %tfile1.o
5# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec2.s -o %tfile2.o5# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/common-filespec2.s -o %tfile2.o
6# RUN: ld.lld -o %t1 --script %s %tfile0.o %tfile1.o %tfile2.o6# RUN: ld.lld -o %t1 --script %s %tfile0.o %tfile1.o %tfile2.o
7# RUN: llvm-readobj -s -t %t1 | FileCheck %s7# RUN: llvm-readobj -S --symbols %t1 | FileCheck %s
88
9SECTIONS {9SECTIONS {
10 .common_0 : { *file0.o(COMMON) }10 .common_0 : { *file0.o(COMMON) }
deps/lld/test/ELF/linkerscript/common.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .common : { *(COMMON) } }" > %t.script3# RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .common : { *(COMMON) } }" > %t.script
4# RUN: ld.lld -o %t1 --script %t.script %t4# RUN: ld.lld -o %t1 --script %t.script %t
5# RUN: llvm-readobj -s -t %t1 | FileCheck %s5# RUN: llvm-readobj -S --symbols %t1 | FileCheck %s
66
7# CHECK: Section {7# CHECK: Section {
8# CHECK: Index:8# CHECK: Index:
deps/lld/test/ELF/linkerscript/compress-debug-sections.s+2-2
...@@ -11,12 +11,12 @@...@@ -11,12 +11,12 @@
11# RUN: echo "SECTIONS { }" > %t.script11# RUN: echo "SECTIONS { }" > %t.script
12# RUN: ld.lld -O0 %t1.o %t2.o %t.script -o %t1 --compress-debug-sections=zlib12# RUN: ld.lld -O0 %t1.o %t2.o %t.script -o %t1 --compress-debug-sections=zlib
13# RUN: llvm-dwarfdump -a %t1 | FileCheck %s13# RUN: llvm-dwarfdump -a %t1 | FileCheck %s
14# RUN: llvm-readobj -s %t1 | FileCheck %s --check-prefix=ZLIBFLAGS14# RUN: llvm-readobj -S %t1 | FileCheck %s --check-prefix=ZLIBFLAGS
1515
16# RUN: echo "SECTIONS { .debug_str 0 : { *(.debug_str) } }" > %t2.script16# RUN: echo "SECTIONS { .debug_str 0 : { *(.debug_str) } }" > %t2.script
17# RUN: ld.lld -O0 %t1.o %t2.o %t2.script -o %t2 --compress-debug-sections=zlib17# RUN: ld.lld -O0 %t1.o %t2.o %t2.script -o %t2 --compress-debug-sections=zlib
18# RUN: llvm-dwarfdump -a %t2 | FileCheck %s18# RUN: llvm-dwarfdump -a %t2 | FileCheck %s
19# RUN: llvm-readobj -s %t2 | FileCheck %s --check-prefix=ZLIBFLAGS19# RUN: llvm-readobj -S %t2 | FileCheck %s --check-prefix=ZLIBFLAGS
2020
21# CHECK: .debug_str contents:21# CHECK: .debug_str contents:
22# CHECK-NEXT: CCC22# CHECK-NEXT: CCC
deps/lld/test/ELF/linkerscript/copy-rel-symbol-value.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: ld.lld %t2.o -o %t2.so -shared4# RUN: ld.lld %t2.o -o %t2.so -shared
5# RUN: echo "SECTIONS { . = . + SIZEOF_HEADERS; foo = bar; }" > %t.script5# RUN: echo "SECTIONS { . = . + SIZEOF_HEADERS; foo = bar; }" > %t.script
6# RUN: ld.lld %t.o %t2.so --script %t.script -o %t6# RUN: ld.lld %t.o %t2.so --script %t.script -o %t
7# RUN: llvm-readobj -t %t | FileCheck %s7# RUN: llvm-readobj --symbols %t | FileCheck %s
88
9# CHECK: Name: bar9# CHECK: Name: bar
10# CHECK-NEXT: Value: 0x[[VAL:.*]]10# CHECK-NEXT: Value: 0x[[VAL:.*]]
deps/lld/test/ELF/linkerscript/data-segment-relro.test+2-2
...@@ -7,10 +7,10 @@...@@ -7,10 +7,10 @@
7## page boundary.7## page boundary.
88
9# RUN: ld.lld --hash-style=sysv -z norelro %t1.o %t2.so --script %s -o %t9# RUN: ld.lld --hash-style=sysv -z norelro %t1.o %t2.so --script %s -o %t
10# RUN: llvm-readobj -s %t | FileCheck %s10# RUN: llvm-readobj -S %t | FileCheck %s
1111
12# RUN: ld.lld --hash-style=sysv -z relro %t1.o %t2.so --script %s -o %t212# RUN: ld.lld --hash-style=sysv -z relro %t1.o %t2.so --script %s -o %t2
13# RUN: llvm-readobj -s %t2 | FileCheck %s13# RUN: llvm-readobj -S %t2 | FileCheck %s
1414
15SECTIONS {15SECTIONS {
16 . = SIZEOF_HEADERS;16 . = SIZEOF_HEADERS;
deps/lld/test/ELF/linkerscript/defsym.s+2-2
...@@ -7,13 +7,13 @@...@@ -7,13 +7,13 @@
77
8## Check that linker script can override -defsym assignments.8## Check that linker script can override -defsym assignments.
9# RUN: ld.lld %t.o -defsym=foo=0x11 -script %t.script -o %t9# RUN: ld.lld %t.o -defsym=foo=0x11 -script %t.script -o %t
10# RUN: llvm-readobj -t %t | FileCheck %s10# RUN: llvm-readobj --symbols %t | FileCheck %s
11# CHECK: Name: foo11# CHECK: Name: foo
12# CHECK-NEXT: Value: 0x2212# CHECK-NEXT: Value: 0x22
1313
14## Check that -defsym can override linker script. Check that multiple14## Check that -defsym can override linker script. Check that multiple
15## -defsym commands for the same symbol are allowed.15## -defsym commands for the same symbol are allowed.
16# RUN: ld.lld %t.o -script %t.script -defsym=foo=0x11 -defsym=foo=0x33 -o %t16# RUN: ld.lld %t.o -script %t.script -defsym=foo=0x11 -defsym=foo=0x33 -o %t
17# RUN: llvm-readobj -t %t | FileCheck %s --check-prefix=REORDER17# RUN: llvm-readobj --symbols %t | FileCheck %s --check-prefix=REORDER
18# REORDER: Name: foo18# REORDER: Name: foo
19# REORDER-NEXT: Value: 0x3319# REORDER-NEXT: Value: 0x33
deps/lld/test/ELF/linkerscript/discard-interp.test+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/../Inputs/shared.s -o %t2.o3# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/../Inputs/shared.s -o %t2.o
4# RUN: ld.lld -shared %t2.o -o %t2.so4# RUN: ld.lld -shared %t2.o -o %t2.so
5# RUN: ld.lld -dynamic-linker foo -rpath bar -rpath baz --script %s --export-dynamic %t.o %t2.so -o %t5# RUN: ld.lld -dynamic-linker foo -rpath bar -rpath baz --script %s --export-dynamic %t.o %t2.so -o %t
6# RUN: llvm-readobj -s %t | FileCheck %s6# RUN: llvm-readobj -S %t | FileCheck %s
77
8# CHECK-NOT: Name: .interp8# CHECK-NOT: Name: .interp
99
deps/lld/test/ELF/linkerscript/discard-phdr.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: echo "PHDRS { \
4# RUN: exec PT_LOAD FLAGS(0x4 | 0x1); \
5# RUN: } \
6# RUN: SECTIONS { \
7# RUN: .text : { *(.text) } :exec \
8# RUN: .foo : { *(.foo) } \
9# RUN: .bar : { *(.bar) } \
10# RUN: /DISCARD/ : { *(.discard) } :NONE \
11# RUN: }" > %t.script
12# RUN: ld.lld -o %t --script %t.script %t.o
13# RUN: llvm-readelf -S -l %t | FileCheck --implicit-check-not=/DISCARD/ %s
14
15## Check that /DISCARD/ does not interfere with the assignment of segments to
16## sections.
17
18# CHECK: Section Headers
19# CHECK: .text
20# CHECK-NEXT: .foo
21# CHECK-NEXT: .bar
22
23# CHECK: Segment Sections
24# CHECK-NEXT: .text .foo .bar
25
26.section .text,"ax"
27 ret
28
29.section .foo,"a"
30 .byte 0
31
32.section .bar,"ax"
33 ret
34
35.section .discard
36 .byte 0
deps/lld/test/ELF/linkerscript/dot-is-not-abs.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4# RUN: echo "SECTIONS { .text : { *(.text) } foo = .; .bar : { *(.bar) } }" > %t1.script4# RUN: echo "SECTIONS { .text : { *(.text) } foo = .; .bar : { *(.bar) } }" > %t1.script
5# RUN: ld.lld -o %t1 --script %t1.script %t.o -shared5# RUN: ld.lld -o %t1 --script %t1.script %t.o -shared
6# RUN: llvm-readobj -t -s -section-data %t1 | FileCheck %s6# RUN: llvm-readobj --symbols -S --section-data %t1 | FileCheck %s
77
8.hidden foo8.hidden foo
9.long foo - .9.long foo - .
deps/lld/test/ELF/linkerscript/dynamic-sym.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: echo "_DYNAMIC = 0x123;" > %t.script3# RUN: echo "_DYNAMIC = 0x123;" > %t.script
4# RUN: ld.lld -T %t.script %t.o -shared -o %t.so4# RUN: ld.lld -T %t.script %t.o -shared -o %t.so
5# RUN: llvm-readobj -t %t.so | FileCheck %s5# RUN: llvm-readobj --symbols %t.so | FileCheck %s
66
7# CHECK: Symbol {7# CHECK: Symbol {
8# CHECK: Name: _DYNAMIC8# CHECK: Name: _DYNAMIC
deps/lld/test/ELF/linkerscript/dynamic.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6# RUN: echo "SECTIONS { }" > %t.script6# RUN: echo "SECTIONS { }" > %t.script
7# RUN: ld.lld %t1.o %t2.so -o %t7# RUN: ld.lld %t1.o %t2.so -o %t
8# RUN: llvm-readobj -dynamic-table %t | FileCheck %s8# RUN: llvm-readobj --dynamic-table %t | FileCheck %s
99
10# CHECK: DynamicSection [10# CHECK: DynamicSection [
11# CHECK-NEXT: Tag Type Name/Value11# CHECK-NEXT: Tag Type Name/Value
deps/lld/test/ELF/linkerscript/eh-frame-merge.s created+20
...@@ -0,0 +1,20 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: echo "SECTIONS { .eh_frame_hdr : { *(.eh_frame_hdr) *(.eh_frame) } }" > %t.script
4# RUN: ld.lld -o %t --no-threads --eh-frame-hdr --script %t.script %t.o
5# RUN: llvm-readobj -S -u %t | FileCheck %s
6
7# CHECK: Name: .dah
8# CHECK-NOT: Section
9# CHECK: Address: 0x4D
10
11# CHECK: initial_location: 0x4d
12
13.global _start
14_start:
15 nop
16
17.section .dah,"ax",@progbits
18.cfi_startproc
19 nop
20.cfi_endproc
deps/lld/test/ELF/linkerscript/ehdr_start.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: echo "SECTIONS { }" > %t.script4# RUN: echo "SECTIONS { }" > %t.script
5# RUN: ld.lld %t.o -script %t.script -o %t5# RUN: ld.lld %t.o -script %t.script -o %t
6# RUN: llvm-readobj -symbols %t | FileCheck %s6# RUN: llvm-readobj --symbols %t | FileCheck %s
7# CHECK: Name: __ehdr_start (1)7# CHECK: Name: __ehdr_start (1)
8# CHECK-NEXT: Value: 0x08# CHECK-NEXT: Value: 0x0
9# CHECK-NEXT: Size: 09# CHECK-NEXT: Size: 0
deps/lld/test/ELF/linkerscript/emit-reloc.s+2-2
...@@ -9,9 +9,9 @@...@@ -9,9 +9,9 @@
99
10# CHECK: Relocations [10# CHECK: Relocations [
11# CHECK-NEXT: Section ({{.*}}) .rela.dyn {11# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
12# CHECK-NEXT: 0x68 R_X86_64_64 .foo 0x012# CHECK-NEXT: 0xF8 R_X86_64_64 .foo 0x0
13# CHECK-NEXT: }13# CHECK-NEXT: }
14# CHECK-NEXT: Section ({{.*}}) .rela.data {14# CHECK-NEXT: Section ({{.*}}) .rela.data {
15# CHECK-NEXT: 0x68 R_X86_64_64 .foo 0x015# CHECK-NEXT: 0xF8 R_X86_64_64 .foo 0x0
16# CHECK-NEXT: }16# CHECK-NEXT: }
17# CHECK-NEXT: ]17# CHECK-NEXT: ]
deps/lld/test/ELF/linkerscript/empty-link-order.test+1-1
...@@ -11,7 +11,7 @@ SECTIONS {...@@ -11,7 +11,7 @@ SECTIONS {
11# RUN: ld.lld %t.o -o %t --script %s11# RUN: ld.lld %t.o -o %t --script %s
1212
13## Check we do not crash and do not set SHF_LINK_ORDER flag for .foo13## Check we do not crash and do not set SHF_LINK_ORDER flag for .foo
14# RUN: llvm-readobj -s %t | FileCheck %s14# RUN: llvm-readobj -S %t | FileCheck %s
15# CHECK: Section {15# CHECK: Section {
16# CHECK: Index:16# CHECK: Index:
17# CHECK: Name: .foo17# CHECK: Name: .foo
deps/lld/test/ELF/linkerscript/empty-relaplt-dyntags.test created+44
...@@ -0,0 +1,44 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
3# RUN: ld.lld -shared %t.o -T %s -o %t
4# RUN: llvm-readobj --dynamic-table --sections %t | FileCheck %s
5
6## In spite of .rela.plt is empty, it might have been preserved because it is
7## mentioned in the linker script. However, even in that case, we should not
8## produce DT_JMPREL and DT_PLTGOT tags because this can cause a dynamic loader
9## to write into slots in .got.plt it considers reserved to support lazy symbol
10## resolution. In fact, as .got.plt is also empty, that memory might be
11## allocated for something else.
12
13# CHECK: Sections [
14# CHECK: Name: .rela.plt
15# CHECK-NEXT: Type: SHT_RELA
16# CHECK-NEXT: Flags [
17# CHECK-NEXT: SHF_ALLOC
18# CHECK-NEXT: ]
19# CHECK-NEXT: Address:
20# CHECK-NEXT: Offset:
21# CHECK-NEXT: Size: 0
22# CHECK: Name: .got.plt
23# CHECK-NEXT: Type: SHT_PROGBITS
24# CHECK-NEXT: Flags [
25# CHECK-NEXT: SHF_ALLOC
26# CHECK-NEXT: SHF_WRITE
27# CHECK-NEXT: ]
28# CHECK-NEXT: Address:
29# CHECK-NEXT: Offset:
30# CHECK-NEXT: Size: 0
31
32# CHECK: DynamicSection [
33# CHECK-NOT: JMPREL
34# CHECK-NOT: PLTGOT
35
36PHDRS {
37 all PT_LOAD;
38 dyn PT_DYNAMIC;
39}
40SECTIONS {
41 .rela.plt : { *(.rela.plt) }: all
42 .dynamic : { *(.dynamic) }: all : dyn
43 .got.plt : {*(.got.plt)}: all
44}
deps/lld/test/ELF/linkerscript/empty-section-size.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t.o
3# RUN: ld.lld %t.o --script %s -o %t13# RUN: ld.lld %t.o --script %s -o %t1
4# RUN: llvm-readobj -symbols %t1 | FileCheck %s4# RUN: llvm-readobj --symbols %t1 | FileCheck %s
55
6## We had a bug when LLD increased the size of the output section even6## We had a bug when LLD increased the size of the output section even
7## if it was empty. That happened because of empty synthetic sections included.7## if it was empty. That happened because of empty synthetic sections included.
deps/lld/test/ELF/linkerscript/empty-sections-expressions.test created+24
...@@ -0,0 +1,24 @@
1# REQUIRES: x86
2# RUN: echo ".text; nop; .data; .byte 0" \
3# RUN: | llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t.o
4# RUN: ld.lld -o %t --script %s %t.o
5# RUN: llvm-readelf -program-headers %t | FileCheck %s
6
7## Check we do not remove the empty output sections used in LOADADDR/ADDR
8## expressions and hence can evaluate the correct addresses.
9
10# CHECK: Program Headers:
11# CHECK-NEXT: Type Offset VirtAddr PhysAddr
12# CHECK-NEXT: LOAD 0x001000 0x0000000000080000 0x0000000000080000
13# CHECK-NEXT: LOAD 0x001001 0x0000000000080001 0x0000000000082000
14
15# CHECK: Section to Segment mapping:
16# CHECK: 00 .empty .text
17# CHECK-NEXT: 01 .data
18
19SECTIONS {
20 . = 0x00080000;
21 .empty : { *(.empty ) }
22 .text : AT(LOADADDR(.empty) + SIZEOF(.empty)) { *(.text) }
23 .data : AT(ADDR(.empty) + 0x2000) { *(.data) }
24}
deps/lld/test/ELF/linkerscript/empty-synthetic-removed-flags.s+2-2
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: echo "SECTIONS { .foo : { *(.foo) } .bar : { *(.got.plt) BYTE(0x11) }}" > %t.script3# RUN: echo "SECTIONS { .foo : { *(.foo) } .bar : { *(.got.plt) BYTE(0x11) }}" > %t.script
4# RUN: ld.lld -o %t --script %t.script %t.o4# RUN: ld.lld -o %t --script %t.script %t.o
5# RUN: llvm-readobj -s %t | FileCheck %s5# RUN: llvm-readobj -S %t | FileCheck %s
66
7## We have ".got.plt" synthetic section with SHF_ALLOC|SHF_WRITE flags.7## We have ".got.plt" synthetic section with SHF_ALLOC|SHF_WRITE flags.
8## It is empty, so linker removes it, but it has to keep ".got.plt" output8## It is empty, so linker removes it, but it has to keep ".got.plt" output
...@@ -21,7 +21,7 @@...@@ -21,7 +21,7 @@
21## Check flags are not the same if we omit empty synthetic section in script.21## Check flags are not the same if we omit empty synthetic section in script.
22# RUN: echo "SECTIONS { .foo : { *(.foo) } .bar : { BYTE(0x11) }}" > %t.script22# RUN: echo "SECTIONS { .foo : { *(.foo) } .bar : { BYTE(0x11) }}" > %t.script
23# RUN: ld.lld -o %t --script %t.script %t.o23# RUN: ld.lld -o %t --script %t.script %t.o
24# RUN: llvm-readobj -s %t | FileCheck --check-prefix=EMPTY %s24# RUN: llvm-readobj -S %t | FileCheck --check-prefix=EMPTY %s
2525
26# EMPTY: Section {26# EMPTY: Section {
27# EMPTY: Index: 227# EMPTY: Index: 2
deps/lld/test/ELF/linkerscript/entry.s+2-2
...@@ -14,7 +14,7 @@...@@ -14,7 +14,7 @@
14# -e has precedence over linker script's ENTRY.14# -e has precedence over linker script's ENTRY.
15# RUN: echo "ENTRY(_label)" > %t.script15# RUN: echo "ENTRY(_label)" > %t.script
16# RUN: ld.lld -e _start -o %t2 %t.script %t16# RUN: ld.lld -e _start -o %t2 %t.script %t
17# RUN: llvm-readobj -file-headers -symbols %t2 | \17# RUN: llvm-readobj --file-headers --symbols %t2 | \
18# RUN: FileCheck -check-prefix=OVERLOAD %s18# RUN: FileCheck -check-prefix=OVERLOAD %s
1919
20# OVERLOAD: Entry: [[ENTRY:0x[0-9A-F]+]]20# OVERLOAD: Entry: [[ENTRY:0x[0-9A-F]+]]
...@@ -24,7 +24,7 @@...@@ -24,7 +24,7 @@
24# The entry symbol can be a linker-script-defined symbol.24# The entry symbol can be a linker-script-defined symbol.
25# RUN: echo "ENTRY(foo); foo = 1;" > %t.script25# RUN: echo "ENTRY(foo); foo = 1;" > %t.script
26# RUN: ld.lld -o %t2 %t.script %t26# RUN: ld.lld -o %t2 %t.script %t
27# RUN: llvm-readobj -file-headers -symbols %t2 | \27# RUN: llvm-readobj --file-headers --symbols %t2 | \
28# RUN: FileCheck -check-prefix=SCRIPT %s28# RUN: FileCheck -check-prefix=SCRIPT %s
2929
30# SCRIPT: Entry: 0x130# SCRIPT: Entry: 0x1
deps/lld/test/ELF/linkerscript/excludefile.s+3
...@@ -10,6 +10,7 @@...@@ -10,6 +10,7 @@
10# RUN: llvm-objdump -d %t | FileCheck %s10# RUN: llvm-objdump -d %t | FileCheck %s
1111
12# CHECK: Disassembly of section .text:12# CHECK: Disassembly of section .text:
13# CHECK-EMPTY:
13# CHECK: _start:14# CHECK: _start:
14# CHECK-NEXT: : 48 c7 c0 3c 00 00 00 movq $60, %rax15# CHECK-NEXT: : 48 c7 c0 3c 00 00 00 movq $60, %rax
15# CHECK-NEXT: : 48 c7 c7 2a 00 00 00 movq $42, %rdi16# CHECK-NEXT: : 48 c7 c7 2a 00 00 00 movq $42, %rdi
...@@ -30,6 +31,7 @@...@@ -30,6 +31,7 @@
30# RUN: llvm-objdump -d %t4 | FileCheck %s --check-prefix=EXCLUDE31# RUN: llvm-objdump -d %t4 | FileCheck %s --check-prefix=EXCLUDE
3132
32# EXCLUDE: Disassembly of section .patatino:33# EXCLUDE: Disassembly of section .patatino:
34# EXCLUDE-EMPTY:
33# EXCLUDE: _start:35# EXCLUDE: _start:
34# EXCLUDE-NEXT: : 48 c7 c0 3c 00 00 00 movq $60, %rax36# EXCLUDE-NEXT: : 48 c7 c0 3c 00 00 00 movq $60, %rax
35# EXCLUDE-NEXT: : 48 c7 c7 2a 00 00 00 movq $42, %rdi37# EXCLUDE-NEXT: : 48 c7 c7 2a 00 00 00 movq $42, %rdi
...@@ -39,6 +41,7 @@...@@ -39,6 +41,7 @@
39# EXCLUDE-NEXT: : 90 nop41# EXCLUDE-NEXT: : 90 nop
40# EXCLUDE-NEXT: : 90 nop42# EXCLUDE-NEXT: : 90 nop
41# EXCLUDE: Disassembly of section .text:43# EXCLUDE: Disassembly of section .text:
44# EXCLUDE-EMPTY:
42# EXCLUDE: tomato:45# EXCLUDE: tomato:
43# EXCLUDE-NEXT: : b8 01 00 00 00 movl $1, %eax46# EXCLUDE-NEXT: : b8 01 00 00 00 movl $1, %eax
4447
deps/lld/test/ELF/linkerscript/extend-pt-load1.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/extend-pt-load.s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/extend-pt-load.s -o %t.o
3# RUN: ld.lld --hash-style=sysv -o %t1 --script %s %t.o -shared3# RUN: ld.lld --hash-style=sysv -o %t1 --script %s %t.o -shared
4# RUN: llvm-readobj --elf-output-style=GNU -l -s %t1 | FileCheck %s4# RUN: llvm-readelf -S -l %t1 | FileCheck %s
55
6# This test demonstrates an odd consequence of the way we handle sections with just symbol6# This test demonstrates an odd consequence of the way we handle sections with just symbol
7# assignments.7# assignments.
deps/lld/test/ELF/linkerscript/extend-pt-load2.test+3-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/extend-pt-load.s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/extend-pt-load.s -o %t.o
3# RUN: ld.lld --hash-style=sysv -o %t2 --script %s %t.o -shared3# RUN: ld.lld --hash-style=sysv -o %t2 --script %s %t.o -shared
4# RUN: llvm-readobj --elf-output-style=GNU -l -s %t2 | FileCheck %s4# RUN: llvm-readelf -S -l %t2 | FileCheck %s
55
6# Then add the section bar. Note how bar is given AX flags, which causes the PT_LOAD to now6# Then add the section bar. Note how bar is given AX flags, which causes the PT_LOAD to now
7# cover the padding bits created by ALIGN.7# cover the padding bits created by ALIGN.
...@@ -17,8 +17,8 @@ SECTIONS {...@@ -17,8 +17,8 @@ SECTIONS {
17}17}
1818
19# CHECK: .text PROGBITS 00000000000001bc 0001bc 000001 00 AX19# CHECK: .text PROGBITS 00000000000001bc 0001bc 000001 00 AX
20# CHECK-NEXT: bar NOBITS 00000000000001bd 0001bd 000e43 00 AX20# CHECK-NEXT: bar PROGBITS 00000000000001bd 0001bd 000e43 00 AX
21# CHECK-NEXT: .data.rel.ro PROGBITS 0000000000001000 001000 000001 00 WA21# CHECK-NEXT: .data.rel.ro PROGBITS 0000000000001000 001000 000001 00 WA
2222
23# CHECK: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x0001bd 0x001000 R E23# CHECK: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x001000 0x001000 R E
24# CHECK-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000068 0x000068 RW24# CHECK-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 0x000068 0x000068 RW
deps/lld/test/ELF/linkerscript/extend-pt-load3.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/extend-pt-load.s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/extend-pt-load.s -o %t.o
3# RUN: ld.lld --hash-style=sysv -o %t3 --script %s %t.o -shared3# RUN: ld.lld --hash-style=sysv -o %t3 --script %s %t.o -shared
4# RUN: llvm-readobj --elf-output-style=GNU -l -s %t3 | FileCheck --check-prefix=CHECK %s4# RUN: llvm-readelf -S -l %t3 | FileCheck --check-prefix=CHECK %s
55
6# If the current behavior becomes a problem we should consider just moving the commands out6# If the current behavior becomes a problem we should consider just moving the commands out
7# of the section. That is, handle the above like the following test.7# of the section. That is, handle the above like the following test.
deps/lld/test/ELF/linkerscript/fill.test+6-1
...@@ -7,14 +7,19 @@ SECTIONS {...@@ -7,14 +7,19 @@ SECTIONS {
7 .out : {7 .out : {
8 FILL(0x11111111)8 FILL(0x11111111)
9 . += 2;9 . += 2;
10 FILL(0x10101010)
10 *(.aaa)11 *(.aaa)
11 . += 4;12 . += 4;
12 *(.bbb)13 *(.bbb)
13 . += 4;14 . += 4;
14 FILL(0x22222222);15 FILL(0x22220000 + 0x2222);
15 . += 4;16 . += 4;
16 }17 }
17}18}
1819
19# CHECK: Contents of section .out:20# CHECK: Contents of section .out:
20# CHECK-NEXT: 2222aa22 222222bb 22222222 2222222221# CHECK-NEXT: 2222aa22 222222bb 22222222 22222222
22
23# RUN: echo 'SECTIONS { .out : { FILL 0x11111111 } }' > %t.script
24# RUN: not ld.lld -o /dev/null --script %t.script 2>&1 | FileCheck %s --check-prefix=ERR
25# ERR: ( expected, but got 0x11111111
deps/lld/test/ELF/linkerscript/header-addr.test+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
3# RUN: ld.lld --hash-style=sysv -o %t.so --script %s %t.o -shared3# RUN: ld.lld --hash-style=sysv -o %t.so --script %s %t.o -shared
4# RUN: llvm-readobj -program-headers %t.so | FileCheck %s4# RUN: llvm-readobj -l %t.so | FileCheck %s
55
6PHDRS { all PT_LOAD PHDRS; }6PHDRS { all PT_LOAD PHDRS; }
77
...@@ -28,7 +28,7 @@ SECTIONS {...@@ -28,7 +28,7 @@ SECTIONS {
28# CHECK-NEXT: ]28# CHECK-NEXT: ]
2929
30# RUN: ld.lld --hash-style=sysv -o %t2.so --script %s %t.o -shared -z max-page-size=0x200030# RUN: ld.lld --hash-style=sysv -o %t2.so --script %s %t.o -shared -z max-page-size=0x2000
31# RUN: llvm-readobj -program-headers %t2.so \31# RUN: llvm-readobj -l %t2.so \
32# RUN: | FileCheck --check-prefix=MAXPAGE %s32# RUN: | FileCheck --check-prefix=MAXPAGE %s
3333
34# MAXPAGE: ProgramHeaders [34# MAXPAGE: ProgramHeaders [
deps/lld/test/ELF/linkerscript/header-phdr.test+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: echo '.section .zed, "a"; .zero 4' \2# RUN: echo '.section .zed, "a"; .zero 4' \
3# RUN: | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o3# RUN: | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
4# RUN: ld.lld --script %s %t.o -o %t4# RUN: ld.lld --script %s %t.o -o %t
5# RUN: llvm-readelf -l -S -W %t | FileCheck %s5# RUN: llvm-readelf -S -l -W %t | FileCheck %s
66
7# CHECK: [ 1] .abc PROGBITS 0000000000001000 001000 000004 00 A 0 0 17# CHECK: [ 1] .abc PROGBITS 0000000000001000 001000 000004 00 A 0 0 1
8# CHECK: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x001004 0x001004 R E 0x10008# CHECK: LOAD 0x000000 0x0000000000000000 0x0000000000000000 0x001004 0x001004 R E 0x1000
deps/lld/test/ELF/linkerscript/info-section-type.s+9-5
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
66
7# RUN: echo "SECTIONS { .bar : { *(.foo) } };" > %t.script7# RUN: echo "SECTIONS { .bar : { *(.foo) } };" > %t.script
8# RUN: ld.lld -o %t --script %t.script %t.o8# RUN: ld.lld -o %t --script %t.script %t.o
9# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=DEFAULT9# RUN: llvm-readobj --sections %t | FileCheck %s --check-prefix=DEFAULT
10# DEFAULT: Name: .bar10# DEFAULT: Name: .bar
11# DEFAULT: Type: SHT_PROGBITS11# DEFAULT: Type: SHT_PROGBITS
12# DEFAULT-NEXT: Flags [12# DEFAULT-NEXT: Flags [
...@@ -15,7 +15,7 @@...@@ -15,7 +15,7 @@
1515
16# RUN: echo "SECTIONS { .bar (COPY) : { *(.foo) } };" > %t.script16# RUN: echo "SECTIONS { .bar (COPY) : { *(.foo) } };" > %t.script
17# RUN: ld.lld -o %t --script %t.script %t.o17# RUN: ld.lld -o %t --script %t.script %t.o
18# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=NONALLOC18# RUN: llvm-readobj --sections %t | FileCheck %s --check-prefix=NONALLOC
19# NONALLOC: Name: .bar19# NONALLOC: Name: .bar
20# NONALLOC: Type: SHT_PROGBITS20# NONALLOC: Type: SHT_PROGBITS
21# NONALLOC-NEXT: Flags [21# NONALLOC-NEXT: Flags [
...@@ -23,15 +23,19 @@...@@ -23,15 +23,19 @@
2323
24# RUN: echo "SECTIONS { .bar (INFO) : { *(.foo) } };" > %t.script24# RUN: echo "SECTIONS { .bar (INFO) : { *(.foo) } };" > %t.script
25# RUN: ld.lld -o %t --script %t.script %t.o25# RUN: ld.lld -o %t --script %t.script %t.o
26# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=NONALLOC26# RUN: llvm-readobj --sections %t | FileCheck %s --check-prefix=NONALLOC
2727
28# RUN: echo "SECTIONS { .bar (OVERLAY) : { *(.foo) } };" > %t.script28# RUN: echo "SECTIONS { .bar (OVERLAY) : { *(.foo) } };" > %t.script
29# RUN: ld.lld -o %t --script %t.script %t.o29# RUN: ld.lld -o %t --script %t.script %t.o
30# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=NONALLOC30# RUN: llvm-readobj --sections %t | FileCheck %s --check-prefix=NONALLOC
31
32# RUN: echo "SECTIONS { .bar (INFO) : { . += 1; } };" > %t.script
33# RUN: ld.lld -o %t --script %t.script %t.o
34# RUN: llvm-readobj --sections %t | FileCheck %s --check-prefix=NONALLOC
3135
32# RUN: echo "SECTIONS { .bar 0x20000 (INFO) : { *(.foo) } };" > %t.script36# RUN: echo "SECTIONS { .bar 0x20000 (INFO) : { *(.foo) } };" > %t.script
33# RUN: ld.lld -o %t --script %t.script %t.o37# RUN: ld.lld -o %t --script %t.script %t.o
34# RUN: llvm-readobj -sections %t | FileCheck %s --check-prefix=NONALLOC38# RUN: llvm-readobj --sections %t | FileCheck %s --check-prefix=NONALLOC
3539
36# RUN: echo "SECTIONS { .bar 0x20000 (BAR) : { *(.foo) } };" > %t.script40# RUN: echo "SECTIONS { .bar 0x20000 (BAR) : { *(.foo) } };" > %t.script
37# RUN: not ld.lld -o %t --script %t.script %t.o 2>&1 |\41# RUN: not ld.lld -o %t --script %t.script %t.o 2>&1 |\
deps/lld/test/ELF/linkerscript/insert-after.test+1-1
...@@ -16,7 +16,7 @@ SECTIONS {...@@ -16,7 +16,7 @@ SECTIONS {
16# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s16# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s
17# RUN: llvm-objdump -section-headers %t1 | FileCheck %s17# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
18# CHECK: Sections:18# CHECK: Sections:
19# CHECK-NEXT: Idx Name Size Address Type19# CHECK-NEXT: Idx Name Size VMA Type
20# CHECK-NEXT: 0 00000000 000000000000000020# CHECK-NEXT: 0 00000000 0000000000000000
21# CHECK-NEXT: 1 .text 00000008 0000000000000000 TEXT21# CHECK-NEXT: 1 .text 00000008 0000000000000000 TEXT
22# CHECK-NEXT: 2 .foo.text 00000008 0000000000000008 TEXT22# CHECK-NEXT: 2 .foo.text 00000008 0000000000000008 TEXT
deps/lld/test/ELF/linkerscript/insert-before.test+1-1
...@@ -16,7 +16,7 @@ SECTIONS {...@@ -16,7 +16,7 @@ SECTIONS {
16# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s16# RUN: ld.lld %t1.o -o %t1 --script %p/Inputs/insert-after.script --script %s
17# RUN: llvm-objdump -section-headers %t1 | FileCheck %s17# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
18# CHECK: Sections:18# CHECK: Sections:
19# CHECK-NEXT: Idx Name Size Address Type19# CHECK-NEXT: Idx Name Size VMA Type
20# CHECK-NEXT: 0 00000000 000000000000000020# CHECK-NEXT: 0 00000000 0000000000000000
21# CHECK-NEXT: 1 .foo.text 00000008 0000000000000000 TEXT21# CHECK-NEXT: 1 .foo.text 00000008 0000000000000000 TEXT
22# CHECK-NEXT: 2 .text 00000008 0000000000000008 TEXT22# CHECK-NEXT: 2 .text 00000008 0000000000000008 TEXT
deps/lld/test/ELF/linkerscript/lazy-symbols.test+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-ar rcs %tar %t14# RUN: llvm-ar rcs %tar %t1
5# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t25# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t2
6# RUN: ld.lld %t2 %tar --script %s -o %tout6# RUN: ld.lld %t2 %tar --script %s -o %tout
7# RUN: llvm-readobj -symbols %tout | FileCheck %s7# RUN: llvm-readobj --symbols %tout | FileCheck %s
88
9foo = 1;9foo = 1;
1010
deps/lld/test/ELF/linkerscript/linkerscript.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux \
4# RUN: %p/Inputs/libsearch-st.s -o %t2.o4# RUN: %p/Inputs/libsearch-st.s -o %t2.o
55
6# RUN: echo "EXTERN( undef undef2 )" > %t.script6# RUN: echo "EXTERN( undef undef2 \"undef3\" \"undef4@@other\")" > %t.script
7# RUN: ld.lld %t -o %t2 %t.script7# RUN: ld.lld %t -o %t2 %t.script
8# RUN: llvm-readobj %t2 > /dev/null8# RUN: llvm-readobj %t2 > /dev/null
99
deps/lld/test/ELF/linkerscript/locationcountererr2.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: echo ". = 0x150; . = 0x10; .text : {} }" >> %t.script4# RUN: echo ". = 0x150; . = 0x10; .text : {} }" >> %t.script
5# RUN: ld.lld %t.o --script %t.script -o %t -shared5# RUN: ld.lld %t.o --script %t.script -o %t -shared
6# RUN: llvm-objdump -section-headers %t | FileCheck %s6# RUN: llvm-objdump -section-headers %t | FileCheck %s
7# CHECK: Name Size Address7# CHECK: Name Size VMA
8# CHECK: .text 00000000 00000000000000108# CHECK: .text 00000000 0000000000000010
99
10# RUN: echo "SECTIONS { . = 0x20; . = ASSERT(0x1, "foo"); }" > %t2.script10# RUN: echo "SECTIONS { . = 0x20; . = ASSERT(0x1, "foo"); }" > %t2.script
deps/lld/test/ELF/linkerscript/memory-at.test+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: echo '.section .data,"aw"; .quad 0' >> %t.s3# RUN: echo '.section .data,"aw"; .quad 0' >> %t.s
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t
5# RUN: ld.lld %t --script %s -o %t25# RUN: ld.lld %t --script %s -o %t2
6# RUN: llvm-readobj -program-headers %t2 | FileCheck %s6# RUN: llvm-readobj -l %t2 | FileCheck %s
77
8MEMORY {8MEMORY {
9 FLASH (rx) : ORIGIN = 0x1000, LENGTH = 0x1009 FLASH (rx) : ORIGIN = 0x1000, LENGTH = 0x100
deps/lld/test/ELF/linkerscript/memory-region-alignment.test+1-1
...@@ -17,7 +17,7 @@ SECTIONS {...@@ -17,7 +17,7 @@ SECTIONS {
17}17}
1818
19# RUN: ld.lld %t.o -o %t --script %s19# RUN: ld.lld %t.o -o %t --script %s
20# RUN: llvm-readobj -sections %t | FileCheck %s20# RUN: llvm-readobj --sections %t | FileCheck %s
2121
22# CHECK: Name: .foo22# CHECK: Name: .foo
23# CHECK-NEXT: Type: SHT_PROGBITS23# CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/linkerscript/memory3.s+1-1
...@@ -14,7 +14,7 @@...@@ -14,7 +14,7 @@
1414
15## Check we place .text into first defined memory region with appropriate flags.15## Check we place .text into first defined memory region with appropriate flags.
16# CHECK: Sections:16# CHECK: Sections:
17# CHECK: Idx Name Size Address17# CHECK: Idx Name Size VMA
18# CHECK: 0 00000000 000000000000000018# CHECK: 0 00000000 0000000000000000
19# CHECK: 1 .text 00000001 000000000000100019# CHECK: 1 .text 00000001 0000000000001000
2020
deps/lld/test/ELF/linkerscript/memory5.test+2-2
...@@ -5,9 +5,9 @@...@@ -5,9 +5,9 @@
5# RUN: llvm-objdump -section-headers %t.so | FileCheck %s5# RUN: llvm-objdump -section-headers %t.so | FileCheck %s
66
7# CHECK: 1 .text 00000001 00000000000420007# CHECK: 1 .text 00000001 0000000000042000
8# CHECK-NEXT: 2 .data 00000001 00000000000440018# CHECK-NEXT: 2 .data 00000001 0000000000042001
99
10## Test that assign to Dot changes the position in a memory region.10## Test that assigning to Dot does not change the position in a memory region.
1111
12MEMORY {12MEMORY {
13 ram (wxa) : ORIGIN = 0x42000, LENGTH = 0x10000013 ram (wxa) : ORIGIN = 0x42000, LENGTH = 0x100000
deps/lld/test/ELF/linkerscript/merge-sections.s+3-3
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: .foo : { begin = .; *(.foo.*) end = .;} \6# RUN: .foo : { begin = .; *(.foo.*) end = .;} \
7# RUN: }" > %t.script7# RUN: }" > %t.script
8# RUN: ld.lld -o %t1 --script %t.script %t -shared8# RUN: ld.lld -o %t1 --script %t.script %t -shared
9# RUN: llvm-readobj -s -t %t1 | FileCheck %s9# RUN: llvm-readobj -S --symbols %t1 | FileCheck %s
1010
11# CHECK: Name: .foo11# CHECK: Name: .foo
12# CHECK-NEXT: Type: SHT_PROGBITS12# CHECK-NEXT: Type: SHT_PROGBITS
...@@ -32,10 +32,10 @@...@@ -32,10 +32,10 @@
3232
33# Check that we don't crash with --gc-sections33# Check that we don't crash with --gc-sections
34# RUN: ld.lld --gc-sections -o %t2 --script %t.script %t -shared34# RUN: ld.lld --gc-sections -o %t2 --script %t.script %t -shared
35# RUN: llvm-readobj -s -t %t2 | FileCheck %s --check-prefix=GC35# RUN: llvm-readobj -S --symbols %t2 | FileCheck %s --check-prefix=GC
3636
37# GC: Name: .foo37# GC: Name: .foo
38# GC-NEXT: Type: SHT_NOBITS38# GC-NEXT: Type: SHT_PROGBITS
39# GC-NEXT: Flags [39# GC-NEXT: Flags [
40# GC-NEXT: SHF_ALLOC40# GC-NEXT: SHF_ALLOC
41# GC-NEXT: ]41# GC-NEXT: ]
deps/lld/test/ELF/linkerscript/multi-sections-constraint.s+2-2
...@@ -8,7 +8,7 @@...@@ -8,7 +8,7 @@
8# RUN: llvm-objdump -section-headers %t1 | FileCheck %s8# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
99
10# CHECK: Sections:10# CHECK: Sections:
11# CHECK-NEXT: Idx Name Size Address Type11# CHECK-NEXT: Idx Name Size VMA Type
12# CHECK: .aaa 00000010 0000000000002000 DATA12# CHECK: .aaa 00000010 0000000000002000 DATA
1313
1414
...@@ -20,7 +20,7 @@...@@ -20,7 +20,7 @@
20# RUN: llvm-objdump -section-headers %t2 | FileCheck %s --check-prefix=REV20# RUN: llvm-objdump -section-headers %t2 | FileCheck %s --check-prefix=REV
2121
22# REV: Sections:22# REV: Sections:
23# REV-NEXT: Idx Name Size Address Type23# REV-NEXT: Idx Name Size VMA Type
24# REV: .aaa 00000010 0000000000001000 DATA24# REV: .aaa 00000010 0000000000001000 DATA
2525
26.global _start26.global _start
deps/lld/test/ELF/linkerscript/multiple-tbss.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: echo "SECTIONS { }" > %t.script3# RUN: echo "SECTIONS { }" > %t.script
4# RUN: ld.lld -T %t.script %t.o -o %t4# RUN: ld.lld -T %t.script %t.o -o %t
5# RUN: llvm-readobj -l -s %t | FileCheck %s5# RUN: llvm-readobj -S -l %t | FileCheck %s
66
7# CHECK: Name: .tbss7# CHECK: Name: .tbss
8# CHECK-NEXT: Type: SHT_NOBITS8# CHECK-NEXT: Type: SHT_NOBITS
deps/lld/test/ELF/linkerscript/nmagic-alignment.test created+85
...@@ -0,0 +1,85 @@
1# REQUIRES: x86
2
3# Test that mimics a use case of -n to produce a kernel mapped shared-object
4# in a non paged context. We specifically want to test:
5# - We can allocate the headers into the first program header (via PHDRS)
6# typically -n does not allocate headers.
7# - The alignment of the .text section is not page aligned.
8
9# RUN: echo ".text; .globl foo; foo: nop" > %t.s
10# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t.s -o %t.o
11# RUN: ld.lld %t.o -o %t.so --shared --hash-style=sysv --script %s
12# RUN: llvm-readobj --program-headers %t.so | FileCheck %s
13# RUN: ld.lld %t.o -o %t2.so --shared --hash-style=sysv -n --script %s
14# RUN: llvm-readobj --program-headers %t2.so | FileCheck %s --check-prefix=CHECK-N
15
16SECTIONS {
17 . = 0x0 + SIZEOF_HEADERS;
18 .hash : { *(.hash) } :text
19 .dynsym : { *(.dynsym) }
20 .dynstr : { *(.dynstr) }
21 . = ALIGN(4);
22 .text : { *(.text*) }
23 .dynamic : { *(.dynamic) } :text :dynamic
24}
25
26PHDRS {
27 text PT_LOAD FLAGS(5) FILEHDR PHDRS;
28 dynamic PT_DYNAMIC FLAGS(4);
29}
30
31# CHECK: ProgramHeaders [
32# CHECK-NEXT: ProgramHeader {
33# CHECK-NEXT: Type: PT_LOAD
34# CHECK-NEXT: Offset: 0x0
35# CHECK-NEXT: VirtualAddress: 0x0
36# CHECK-NEXT: PhysicalAddress: 0x0
37# CHECK-NEXT: FileSize:
38# CHECK-NEXT: MemSize:
39# CHECK-NEXT: Flags [
40# CHECK-NEXT: PF_R
41# CHECK-NEXT: PF_X
42# CHECK-NEXT: ]
43# CHECK-NEXT: Alignment: 4096
44# CHECK-NEXT: }
45# CHECK-NEXT: ProgramHeader {
46# CHECK-NEXT: Type: PT_DYNAMIC
47# CHECK-NEXT: Offset: 0x108
48# CHECK-NEXT: VirtualAddress: 0x108
49# CHECK-NEXT: PhysicalAddress: 0x108
50# CHECK-NEXT: FileSize:
51# CHECK-NEXT: MemSize:
52# CHECK-NEXT: Flags [
53# CHECK-NEXT: PF_R
54# CHECK-NEXT: ]
55# CHECK-NEXT: Alignment: 8
56# CHECK-NEXT: }
57# CHECK-NEXT: ]
58
59# CHECK-N: ProgramHeaders [
60# CHECK-N-NEXT: ProgramHeader {
61# CHECK-N-NEXT: Type: PT_LOAD
62# CHECK-N-NEXT: Offset: 0x0
63# CHECK-N-NEXT: VirtualAddress: 0x0
64# CHECK-N-NEXT: PhysicalAddress: 0x0
65# CHECK-N-NEXT: FileSize: 360
66# CHECK-N-NEXT: MemSize: 360
67# CHECK-N-NEXT: Flags [
68# CHECK-N-NEXT: PF_R
69# CHECK-N-NEXT: PF_X
70# CHECK-N-NEXT: ]
71# CHECK-N-NEXT: Alignment: 8
72# CHECK-N-NEXT: }
73# CHECK-N-NEXT: ProgramHeader {
74# CHECK-N-NEXT: Type: PT_DYNAMIC
75# CHECK-N-NEXT: Offset: 0x108
76# CHECK-N-NEXT: VirtualAddress: 0x108
77# CHECK-N-NEXT: PhysicalAddress: 0x108
78# CHECK-N-NEXT: FileSize:
79# CHECK-N-NEXT: MemSize:
80# CHECK-N-NEXT: Flags [
81# CHECK-N-NEXT: PF_R
82# CHECK-N-NEXT: ]
83# CHECK-N-NEXT: Alignment: 8
84# CHECK-N-NEXT: }
85# CHECK-N-NEXT: ]
deps/lld/test/ELF/linkerscript/noload.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5# RUN: .data_noload_b (0x10000) (NOLOAD) : { *(.data_noload_b) } \5# RUN: .data_noload_b (0x10000) (NOLOAD) : { *(.data_noload_b) } \
6# RUN: .text (0x20000) : { *(.text) } };" > %t.script6# RUN: .text (0x20000) : { *(.text) } };" > %t.script
7# RUN: ld.lld -o %t --script %t.script %t.o7# RUN: ld.lld -o %t --script %t.script %t.o
8# RUN: llvm-readobj -sections -program-headers %t | FileCheck %s8# RUN: llvm-readobj --sections -l %t | FileCheck %s
99
10# CHECK: Section {10# CHECK: Section {
11# CHECK: Index: 111# CHECK: Index: 1
deps/lld/test/ELF/linkerscript/non-absolute.s+2-1
...@@ -3,11 +3,12 @@...@@ -3,11 +3,12 @@
3# RUN: echo "SECTIONS { A = . - 0x10; B = A + 0x1; }" > %t.script3# RUN: echo "SECTIONS { A = . - 0x10; B = A + 0x1; }" > %t.script
4# RUN: ld.lld -shared %t1.o --script %t.script -o %t4# RUN: ld.lld -shared %t1.o --script %t.script -o %t
5# RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DUMP5# RUN: llvm-objdump -d %t | FileCheck %s --check-prefix=DUMP
6# RUN: llvm-readobj -t %t | FileCheck %s --check-prefix=SYMBOL6# RUN: llvm-readobj --symbols %t | FileCheck %s --check-prefix=SYMBOL
77
8# B = A + 0x1 = -0x10 + 0x1 = -0xf -> 0xFFFFFFFFFFFFFFF18# B = A + 0x1 = -0x10 + 0x1 = -0xf -> 0xFFFFFFFFFFFFFFF1
9# B - (0x94+6) = -0xf - (0x94+6) = -1699# B - (0x94+6) = -0xf - (0x94+6) = -169
10# DUMP: Disassembly of section .text:10# DUMP: Disassembly of section .text:
11# DUMP-EMPTY:
11# DUMP-NEXT: foo:12# DUMP-NEXT: foo:
12# DUMP-NEXT: 94: {{.*}} -169(%rip), %eax13# DUMP-NEXT: 94: {{.*}} -169(%rip), %eax
1314
deps/lld/test/ELF/linkerscript/non-absolute2.test+1-1
...@@ -9,7 +9,7 @@ SECTIONS {...@@ -9,7 +9,7 @@ SECTIONS {
9}9}
1010
11# CHECK: Sections:11# CHECK: Sections:
12# CHECK-NEXT: Idx Name Size Address12# CHECK-NEXT: Idx Name Size VMA
13# CHECK-NEXT: 0 00000000 000000000000000013# CHECK-NEXT: 0 00000000 0000000000000000
14# CHECK-NEXT: 1 .dynsym 00000030 000000000000100014# CHECK-NEXT: 1 .dynsym 00000030 0000000000001000
15# CHECK: 5 .text 00000000 000000000000106c15# CHECK: 5 .text 00000000 000000000000106c
deps/lld/test/ELF/linkerscript/numbers.s+2-2
...@@ -18,7 +18,7 @@...@@ -18,7 +18,7 @@
18# RUN: llvm-objdump -section-headers %t2 | FileCheck %s18# RUN: llvm-objdump -section-headers %t2 | FileCheck %s
1919
20# CHECK: Sections:20# CHECK: Sections:
21# CHECK-NEXT: Idx Name Size Address21# CHECK-NEXT: Idx Name Size VMA
22# CHECK-NEXT: 0 00000000 000000000000000022# CHECK-NEXT: 0 00000000 0000000000000000
23# CHECK-NEXT: 1 .hex1 00000008 000000000000100023# CHECK-NEXT: 1 .hex1 00000008 0000000000001000
24# CHECK-NEXT: 2 .hex2 00000008 000000000000101024# CHECK-NEXT: 2 .hex2 00000008 0000000000001010
...@@ -67,7 +67,7 @@...@@ -67,7 +67,7 @@
67# RUN: ld.lld %t --script %t8.script -o %t667# RUN: ld.lld %t --script %t8.script -o %t6
68# RUN: llvm-objdump -section-headers %t6 | FileCheck -check-prefix=SECADDR %s68# RUN: llvm-objdump -section-headers %t6 | FileCheck -check-prefix=SECADDR %s
69# SECADDR: Sections:69# SECADDR: Sections:
70# SECADDR-NEXT: Idx Name Size Address70# SECADDR-NEXT: Idx Name Size VMA
71# SECADDR-NEXT: 0 00000000 000000000000000071# SECADDR-NEXT: 0 00000000 0000000000000000
72# SECADDR-NEXT: 1 .hex1 00000008 000000000000040072# SECADDR-NEXT: 1 .hex1 00000008 0000000000000400
73# SECADDR-NEXT: 2 .hex2 00000008 000000000000050073# SECADDR-NEXT: 2 .hex2 00000008 0000000000000500
deps/lld/test/ELF/linkerscript/obj-symbol-value.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: echo "SECTIONS { foo = bar; .bar : { *(.bar*) } }" > %t.script3# RUN: echo "SECTIONS { foo = bar; .bar : { *(.bar*) } }" > %t.script
4# RUN: ld.lld %t.o --script %t.script -o %t.so -shared4# RUN: ld.lld %t.o --script %t.script -o %t.so -shared
5# RUN: llvm-readobj -t %t.so | FileCheck %s5# RUN: llvm-readobj --symbols %t.so | FileCheck %s
66
7# CHECK: Symbol {7# CHECK: Symbol {
8# CHECK: Name: bar8# CHECK: Name: bar
deps/lld/test/ELF/linkerscript/openbsd-bootdata.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux /dev/null -o %t.o2# RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux /dev/null -o %t.o
3# RUN: ld.lld --script %s %t.o -o %t3# RUN: ld.lld --script %s %t.o -o %t
4# RUN: llvm-readobj --program-headers -s %t | FileCheck %s4# RUN: llvm-readobj --program-headers -S %t | FileCheck %s
55
6PHDRS { boot PT_OPENBSD_BOOTDATA; }6PHDRS { boot PT_OPENBSD_BOOTDATA; }
77
deps/lld/test/ELF/linkerscript/openbsd-randomize.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5# RUN: .text : { *(.text) } \5# RUN: .text : { *(.text) } \
6# RUN: .openbsd.randomdata : { *(.openbsd.randomdata) } : rand }" > %t.script6# RUN: .openbsd.randomdata : { *(.openbsd.randomdata) } : rand }" > %t.script
7# RUN: ld.lld --script %t.script %t.o -o %t7# RUN: ld.lld --script %t.script %t.o -o %t
8# RUN: llvm-readobj --program-headers -s %t | FileCheck %s8# RUN: llvm-readobj --program-headers -S %t | FileCheck %s
99
10# CHECK: ProgramHeader {10# CHECK: ProgramHeader {
11# CHECK: Type: PT_OPENBSD_RANDOMIZE (0x65A3DBE6)11# CHECK: Type: PT_OPENBSD_RANDOMIZE (0x65A3DBE6)
deps/lld/test/ELF/linkerscript/orphan-first-cmd.test+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: echo '.section .bar, "aw"' \2# RUN: echo '.section .bar, "aw"' \
3# RUN: | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o3# RUN: | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
4# RUN: ld.lld -o %t -T %s %t.o -shared4# RUN: ld.lld -o %t -T %s %t.o -shared
5# RUN: llvm-readobj -s %t | FileCheck %s5# RUN: llvm-readobj -S %t | FileCheck %s
66
7SECTIONS {7SECTIONS {
8 foo = 123;8 foo = 123;
deps/lld/test/ELF/linkerscript/orphan-live-only.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: echo "PHDRS { \
4# RUN: exec PT_LOAD FLAGS(0x4 | 0x1); \
5# RUN: ro PT_LOAD FLAGS(0x4); \
6# RUN: } \
7# RUN: SECTIONS { \
8# RUN: .pad : { QUAD(0); } :exec \
9# RUN: .text : { *(.text) } \
10# RUN: .ro : { *(.ro) } :ro \
11# RUN: }" > %t.script
12# RUN: ld.lld -o %t --script %t.script %t.o
13# RUN: llvm-readelf -S -l %t | FileCheck %s
14
15## The ".pad" section is not "live" and should be ignored by the
16## orphan placement.
17##
18## Check that the orphan section is placed correctly and belongs to
19## the correct segment.
20
21# CHECK: Section Headers
22# CHECK: .pad
23# CHECK-NEXT: .text
24# CHECK-NEXT: .orphan2
25# CHECK-NEXT: .ro
26# CHECK-NEXT: .orphan1
27
28# CHECK: Segment Sections
29# CHECK-NEXT: .pad .text .orphan2
30# CHECK-NEXT: .ro .orphan1
31
32.section .text,"ax"
33 ret
34
35.section .ro,"a"
36 .byte 0
37
38.section .orphan1,"a"
39 .byte 0
40
41.section .orphan2,"ax"
42 ret
deps/lld/test/ELF/linkerscript/orphan-phdrs.s+4-4
...@@ -23,13 +23,13 @@...@@ -23,13 +23,13 @@
2323
24# CHECK: Segment Sections24# CHECK: Segment Sections
25# CHECK-NEXT: .text .orphan25# CHECK-NEXT: .text .orphan
26# CHECK-NEXT: .rw26# CHECK-NEXT: .empty .rw
2727
28.section .text, "ax"28.section .text,"ax"
29 ret29 ret
3030
31.section .rw, "aw"31.section .rw,"aw"
32 .quad 032 .quad 0
3333
34.section .orphan, "ax"34.section .orphan,"ax"
35 ret35 ret
deps/lld/test/ELF/linkerscript/orphan-report.s+2-2
...@@ -27,6 +27,7 @@...@@ -27,6 +27,7 @@
27# REPORT-NEXT: <internal>:(.dynamic) is being placed in '.dynamic'27# REPORT-NEXT: <internal>:(.dynamic) is being placed in '.dynamic'
28# REPORT-NEXT: <internal>:(.dynstr) is being placed in '.dynstr'28# REPORT-NEXT: <internal>:(.dynstr) is being placed in '.dynstr'
29# REPORT-NEXT: <internal>:(.rela.dyn) is being placed in '.rela.dyn'29# REPORT-NEXT: <internal>:(.rela.dyn) is being placed in '.rela.dyn'
30# REPORT-NEXT: <internal>:(.eh_frame) is being placed in '.eh_frame'
30# REPORT-NEXT: <internal>:(.got) is being placed in '.got'31# REPORT-NEXT: <internal>:(.got) is being placed in '.got'
31# REPORT-NEXT: <internal>:(.got.plt) is being placed in '.got.plt'32# REPORT-NEXT: <internal>:(.got.plt) is being placed in '.got.plt'
32# REPORT-NEXT: <internal>:(.got.plt) is being placed in '.got.plt'33# REPORT-NEXT: <internal>:(.got.plt) is being placed in '.got.plt'
...@@ -34,9 +35,8 @@...@@ -34,9 +35,8 @@
34# REPORT-NEXT: <internal>:(.rela.plt) is being placed in '.rela.plt'35# REPORT-NEXT: <internal>:(.rela.plt) is being placed in '.rela.plt'
35# REPORT-NEXT: <internal>:(.plt) is being placed in '.plt'36# REPORT-NEXT: <internal>:(.plt) is being placed in '.plt'
36# REPORT-NEXT: <internal>:(.plt) is being placed in '.plt'37# REPORT-NEXT: <internal>:(.plt) is being placed in '.plt'
37# REPORT-NEXT: <internal>:(.eh_frame) is being placed in '.eh_frame'
38# REPORT-NEXT: <internal>:(.symtab) is being placed in '.symtab'38# REPORT-NEXT: <internal>:(.symtab) is being placed in '.symtab'
39# REPORT-NEXT: <internal>:(.symtab_shndxr) is being placed in '.symtab_shndxr'39# REPORT-NEXT: <internal>:(.symtab_shndx) is being placed in '.symtab_shndx'
40# REPORT-NEXT: <internal>:(.shstrtab) is being placed in '.shstrtab'40# REPORT-NEXT: <internal>:(.shstrtab) is being placed in '.shstrtab'
41# REPORT-NEXT: <internal>:(.strtab) is being placed in '.strtab'41# REPORT-NEXT: <internal>:(.strtab) is being placed in '.strtab'
4242
deps/lld/test/ELF/linkerscript/orphan.s+5-5
...@@ -9,15 +9,15 @@...@@ -9,15 +9,15 @@
9# RUN: ld.lld -o %t1 --script %t.script %t9# RUN: ld.lld -o %t1 --script %t.script %t
10# RUN: llvm-objdump -section-headers %t1 | FileCheck %s10# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
1111
12## .jcr is a relro section and should be placed after other RW sections.12## .jcr is a relro section and should be placed before other RW sections.
13## .bss is SHT_NOBITS section and should be last RW section, so some space13## .bss is SHT_NOBITS section and should be last RW section, so some space
14## in ELF file could be saved.14## in ELF file could be saved.
15# CHECK: 0 00000000 000000000000000015# CHECK: 0 00000000 0000000000000000
16# CHECK-NEXT: 1 .text 00000000 0000000000000000 TEXT16# CHECK-NEXT: 1 .text 00000000 0000000000000000 TEXT
17# CHECK-NEXT: 2 .rw1 00000008 0000000000000000 DATA17# CHECK-NEXT: 2 .jcr 00000008 0000000000000000 DATA
18# CHECK-NEXT: 3 .rw2 00000008 0000000000000008 DATA18# CHECK-NEXT: 3 .rw1 00000008 0000000000000008 DATA
19# CHECK-NEXT: 4 .rw3 00000008 0000000000000010 DATA19# CHECK-NEXT: 4 .rw2 00000008 0000000000000010 DATA
20# CHECK-NEXT: 5 .jcr 00000008 0000000000000018 DATA20# CHECK-NEXT: 5 .rw3 00000008 0000000000000018 DATA
21# CHECK-NEXT: 6 .bss 00000008 0000000000000020 BSS21# CHECK-NEXT: 6 .bss 00000008 0000000000000020 BSS
2222
23.section .rw1, "aw"23.section .rw1, "aw"
deps/lld/test/ELF/linkerscript/out-of-order-section-in-region.test created+20
...@@ -0,0 +1,20 @@
1# REQUIRES: x86
2
3# RUN: echo ".section .aaa, \"a\"; .quad 0; .section .bbb, \"a\"; .quad 0;" \
4# RUN: | llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t
5# RUN: ld.lld %t --script %s -o %t2
6
7# RUN: llvm-objdump -section-headers %t2 | FileCheck %s
8# CHECK: .aaa 00000008 0000000000001008 DATA
9# CHECK: .bbb 00000008 0000000000001000 DATA
10
11MEMORY {
12 REGION (rwx) : ORIGIN = 0x1000, LENGTH = 0x100
13}
14
15SECTIONS {
16 .aaa ORIGIN(REGION) + 0x8 : { *(.aaa) } > REGION
17 _stext = .;
18 .bbb ORIGIN(REGION) : { *(.bbb) } > REGION
19 . = _stext;
20}
deps/lld/test/ELF/linkerscript/out-of-order.s+3-3
...@@ -22,10 +22,10 @@...@@ -22,10 +22,10 @@
22# must take responsibility to make sure this does not happen.22# must take responsibility to make sure this does not happen.
2323
24# CHECK: Sections:24# CHECK: Sections:
25# CHECK-NEXT: Idx Name Size Address Type25# CHECK-NEXT: Idx Name Size VMA Type
26# CHECK-NEXT: 0 00000000 000000000000000026# CHECK-NEXT: 0 00000000 0000000000000000
27# CHECK-NEXT: 1 .data 00000008 000000000000400027# CHECK-NEXT: 1 .dynamic 00000060 0000000000000000
28# CHECK-NEXT: 2 .dynamic 00000060 000000000000400828# CHECK-NEXT: 2 .data 00000008 0000000000004000
29# CHECK-NEXT: 3 .dynsym 00000018 000000000000200029# CHECK-NEXT: 3 .dynsym 00000018 0000000000002000
30# CHECK-NEXT: 4 .dynstr 00000001 000000000000201830# CHECK-NEXT: 4 .dynstr 00000001 0000000000002018
31# CHECK-NEXT: 5 .hash 00000010 000000000000201c31# CHECK-NEXT: 5 .hash 00000010 000000000000201c
deps/lld/test/ELF/linkerscript/output-too-large-32bit.s created+11
...@@ -0,0 +1,11 @@
1# REQUIRES: x86 && !llvm-64-bits
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: echo "SECTIONS { .text : { . = 0x6fffffffffffffff; *(.text*); } }" > %t.script
5# RUN: not ld.lld --no-check-sections --script %t.script %t.o -o /dev/null 2>&1 | FileCheck %s
6
7# CHECK: output file too large
8
9.global _start
10_start:
11 nop
deps/lld/test/ELF/linkerscript/outsections-addr.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: .ddd 0x5001 : { *(.ddd) } \7# RUN: .ddd 0x5001 : { *(.ddd) } \
8# RUN: }" > %t.script8# RUN: }" > %t.script
9# RUN: ld.lld %t --script %t.script -o %tout9# RUN: ld.lld %t --script %t.script -o %tout
10# RUN: llvm-readobj -s %tout | FileCheck %s10# RUN: llvm-readobj -S %tout | FileCheck %s
1111
12## Check:12## Check:
13## 1) Simple constant as address.13## 1) Simple constant as address.
deps/lld/test/ELF/linkerscript/overlapping-sections.s+11-11
...@@ -17,18 +17,18 @@...@@ -17,18 +17,18 @@
1717
18# Verify that the .sec2 was indeed placed in a PT_LOAD where the PhysAddr18# Verify that the .sec2 was indeed placed in a PT_LOAD where the PhysAddr
19# overlaps with where .sec1 is loaded:19# overlaps with where .sec1 is loaded:
20# RUN: llvm-readobj -sections -program-headers -elf-output-style=GNU %t.so | FileCheck %s -check-prefix BAD-LMA20# RUN: llvm-readelf --sections -l %t.so | FileCheck %s -check-prefix BAD-LMA
21# BAD-LMA-LABEL: Section Headers:21# BAD-LMA-LABEL: Section Headers:
22# BAD-LMA: .sec1 PROGBITS 0000000000008000 002000 000100 00 WA 0 0 122# BAD-LMA: .sec1 PROGBITS 0000000000008000 002000 000100 00 WA 0 0 1
23# BAD-LMA: .sec2 PROGBITS 0000000000008800 002800 000100 00 WA 0 0 123# BAD-LMA: .sec2 PROGBITS 0000000000008800 002800 000100 00 WA 0 0 1
24# BAD-LMA-LABEL: Program Headers:24# BAD-LMA-LABEL: Program Headers:
25# BAD-LMA-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align25# BAD-LMA-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
26# BAD-LMA-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000100 0x000100 R E 0x100026# BAD-LMA-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000100 0x000100 R E 0x1000
27# BAD-LMA-NEXT: LOAD 0x001100 0x0000000000000100 0x0000000000000100 0x000070 0x000070 RW 0x1000
27# BAD-LMA-NEXT: LOAD 0x002000 0x0000000000008000 0x0000000000008000 0x000100 0x000100 RW 0x100028# BAD-LMA-NEXT: LOAD 0x002000 0x0000000000008000 0x0000000000008000 0x000100 0x000100 RW 0x1000
28# BAD-LMA-NEXT: LOAD 0x002800 0x0000000000008800 0x0000000000008080 0x000170 0x000170 RW 0x1000
29# BAD-LMA-LABEL: Section to Segment mapping:29# BAD-LMA-LABEL: Section to Segment mapping:
30# BAD-LMA: 01 .sec130# BAD-LMA: 01 .text .dynamic
31# BAD-LMA: 02 .sec2 .dynamic31# BAD-LMA: 02 .sec1
3232
33# Now try a script where the virtual memory addresses overlap but ensure that the33# Now try a script where the virtual memory addresses overlap but ensure that the
34# load addresses don't:34# load addresses don't:
...@@ -43,18 +43,18 @@...@@ -43,18 +43,18 @@
4343
44# Check that the expected binary was created with --noinhibit-exec:44# Check that the expected binary was created with --noinhibit-exec:
45# RUN: ld.lld -o %t.so --script %t-vaddr.script %t.o -shared --noinhibit-exec45# RUN: ld.lld -o %t.so --script %t-vaddr.script %t.o -shared --noinhibit-exec
46# RUN: llvm-readobj -sections -program-headers -elf-output-style=GNU %t.so | FileCheck %s -check-prefix BAD-VADDR46# RUN: llvm-readelf --sections -l %t.so | FileCheck %s -check-prefix BAD-VADDR
47# BAD-VADDR-LABEL: Section Headers:47# BAD-VADDR-LABEL: Section Headers:
48# BAD-VADDR: .sec1 PROGBITS 0000000000008000 002000 000100 00 WA 0 0 148# BAD-VADDR: .sec1 PROGBITS 0000000000008000 002000 000100 00 WA 0 0 1
49# BAD-VADDR: .sec2 PROGBITS 0000000000008020 003020 000100 00 WA 0 0 149# BAD-VADDR: .sec2 PROGBITS 0000000000008020 003020 000100 00 WA 0 0 1
50# BAD-VADDR-LABEL: Program Headers:50# BAD-VADDR-LABEL: Program Headers:
51# BAD-VADDR-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align51# BAD-VADDR-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
52# BAD-VADDR-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000100 0x000100 R E 0x100052# BAD-VADDR-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000100 0x000100 R E 0x1000
53# BAD-VADDR-NEXT: LOAD 0x001100 0x0000000000000100 0x0000000000000100 0x000070 0x000070 RW 0x1000
53# BAD-VADDR-NEXT: LOAD 0x002000 0x0000000000008000 0x0000000000008000 0x000100 0x000100 RW 0x100054# BAD-VADDR-NEXT: LOAD 0x002000 0x0000000000008000 0x0000000000008000 0x000100 0x000100 RW 0x1000
54# BAD-VADDR-NEXT: LOAD 0x003020 0x0000000000008020 0x0000000000008800 0x000170 0x000170 RW 0x1000
55# BAD-VADDR-LABEL: Section to Segment mapping:55# BAD-VADDR-LABEL: Section to Segment mapping:
56# BAD-VADDR: 01 .sec156# BAD-VADDR: 01 .text .dynamic
57# BAD-VADDR: 02 .sec2 .dynamic57# BAD-VADDR: 02 .sec1
5858
59# Finally check the case where both LMA and vaddr overlap59# Finally check the case where both LMA and vaddr overlap
6060
...@@ -91,16 +91,16 @@...@@ -91,16 +91,16 @@
91# Starting here the contents of .sec2 overwrites .sec1:91# Starting here the contents of .sec2 overwrites .sec1:
92# BROKEN-OUTPUT-FILE-NEXT: 8040 02020202 02020202 02020202 0202020292# BROKEN-OUTPUT-FILE-NEXT: 8040 02020202 02020202 02020202 02020202
9393
94# RUN: llvm-readobj -sections -program-headers -elf-output-style=GNU %t.so | FileCheck %s -check-prefix BAD-BOTH94# RUN: llvm-readelf --sections -l %t.so | FileCheck %s -check-prefix BAD-BOTH
95# BAD-BOTH-LABEL: Section Headers:95# BAD-BOTH-LABEL: Section Headers:
96# BAD-BOTH: .sec1 PROGBITS 0000000000008000 002000 000100 00 WA 0 0 196# BAD-BOTH: .sec1 PROGBITS 0000000000008000 002000 000100 00 WA 0 0 1
97# BAD-BOTH: .sec2 PROGBITS 0000000000008040 002040 000100 00 WA 0 0 197# BAD-BOTH: .sec2 PROGBITS 0000000000008040 002040 000100 00 WA 0 0 1
98# BAD-BOTH-LABEL: Program Headers:98# BAD-BOTH-LABEL: Program Headers:
99# BAD-BOTH-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align99# BAD-BOTH-NEXT: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
100# BAD-BOTH-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000100 0x000100 R E 0x1000100# BAD-BOTH-NEXT: LOAD 0x001000 0x0000000000000000 0x0000000000000000 0x000100 0x000100 R E 0x1000
101# BAD-BOTH-NEXT: LOAD 0x002000 0x0000000000008000 0x0000000000008000 0x0001b0 0x0001b0 RW 0x1000101# BAD-BOTH-NEXT: LOAD 0x001100 0x0000000000000100 0x0000000000000100 0x000070 0x000070 RW 0x1000
102# BAD-BOTH-LABEL: Section to Segment mapping:102# BAD-BOTH-LABEL: Section to Segment mapping:
103# BAD-BOTH: 01 .sec1 .sec2 .dynamic103# BAD-BOTH: 01 .text .dynamic
104104
105.section .first_sec,"aw",@progbits105.section .first_sec,"aw",@progbits
106.rept 0x100106.rept 0x100
deps/lld/test/ELF/linkerscript/overlay.test+1-1
...@@ -16,7 +16,7 @@ SECTIONS {...@@ -16,7 +16,7 @@ SECTIONS {
16## .text does not cause overlapping error and that16## .text does not cause overlapping error and that
17## .text's VA is 0x1000 + max(sizeof(.out.big), sizeof(.out.small)).17## .text's VA is 0x1000 + max(sizeof(.out.big), sizeof(.out.small)).
1818
19# RUN: llvm-readobj -sections -program-headers -elf-output-style=GNU %t | FileCheck %s19# RUN: llvm-readelf --sections -l %t | FileCheck %s
2020
21# CHECK: Section Headers:21# CHECK: Section Headers:
22# CHECK: Name Type Address Off Size22# CHECK: Name Type Address Off Size
deps/lld/test/ELF/linkerscript/page-size-align.test+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux /dev/null -o %t.o
3# RUN: ld.lld -T %s -z max-page-size=0x4000 %t.o -o %t.so -shared3# RUN: ld.lld -T %s -z max-page-size=0x4000 %t.o -o %t.so -shared
4# RUN: llvm-readobj -s %t.so | FileCheck %s4# RUN: llvm-readobj -S %t.so | FileCheck %s
55
6SECTIONS {6SECTIONS {
7 . = SIZEOF_HEADERS;7 . = SIZEOF_HEADERS;
deps/lld/test/ELF/linkerscript/page-size.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
33
4# RUN: ld.lld -z max-page-size=0x4000 %t -o %t24# RUN: ld.lld -z max-page-size=0x4000 %t -o %t2
5# RUN: llvm-readobj -program-headers %t2 | FileCheck %s5# RUN: llvm-readobj -l %t2 | FileCheck %s
66
7# CHECK: ProgramHeaders [7# CHECK: ProgramHeaders [
8# CHECK: ProgramHeader {8# CHECK: ProgramHeader {
deps/lld/test/ELF/linkerscript/phdr-check.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4# RUN: echo "SECTIONS { . = 0x10000000 + SIZEOF_HEADERS; .text : {*(.text.*)} }" > %t.script4# RUN: echo "SECTIONS { . = 0x10000000 + SIZEOF_HEADERS; .text : {*(.text.*)} }" > %t.script
5# RUN: ld.lld -o %t1 --script %t.script %t5# RUN: ld.lld -o %t1 --script %t.script %t
6# RUN: llvm-readobj -program-headers %t1 | FileCheck %s6# RUN: llvm-readobj -l %t1 | FileCheck %s
7# CHECK: ProgramHeaders [7# CHECK: ProgramHeaders [
8# CHECK-NEXT: ProgramHeader {8# CHECK-NEXT: ProgramHeader {
9# CHECK-NEXT: Type: PT_PHDR (0x6)9# CHECK-NEXT: Type: PT_PHDR (0x6)
deps/lld/test/ELF/linkerscript/phdrs-flags.s+2-2
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: .foo : {*(.foo.*)} :all \7# RUN: .foo : {*(.foo.*)} :all \
8# RUN: .data : {*(.data.*)} :all}" > %t.script8# RUN: .data : {*(.data.*)} :all}" > %t.script
9# RUN: ld.lld -o %t1 --script %t.script %t9# RUN: ld.lld -o %t1 --script %t.script %t
10# RUN: llvm-readobj -program-headers %t1 | FileCheck %s10# RUN: llvm-readobj -l %t1 | FileCheck %s
1111
12# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS FLAGS (0x1);} \12# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS FLAGS (0x1);} \
13# RUN: SECTIONS { \13# RUN: SECTIONS { \
...@@ -16,7 +16,7 @@...@@ -16,7 +16,7 @@
16# RUN: .foo : {*(.foo.*)} \16# RUN: .foo : {*(.foo.*)} \
17# RUN: .data : {*(.data.*)} }" > %t.script17# RUN: .data : {*(.data.*)} }" > %t.script
18# RUN: ld.lld -o %t1 --script %t.script %t18# RUN: ld.lld -o %t1 --script %t.script %t
19# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s19# RUN: llvm-readobj -l %t1 | FileCheck --check-prefix=DEFHDR %s
2020
21# CHECK: ProgramHeaders [21# CHECK: ProgramHeaders [
22# CHECK-NEXT: ProgramHeader {22# CHECK-NEXT: ProgramHeader {
deps/lld/test/ELF/linkerscript/phdrs.s+5-5
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: .foo : {*(.foo.*)} :all \7# RUN: .foo : {*(.foo.*)} :all \
8# RUN: .data : {*(.data.*)} :all}" > %t.script8# RUN: .data : {*(.data.*)} :all}" > %t.script
9# RUN: ld.lld -o %t1 --script %t.script %t9# RUN: ld.lld -o %t1 --script %t.script %t
10# RUN: llvm-readobj -program-headers %t1 | FileCheck %s10# RUN: llvm-readobj -l %t1 | FileCheck %s
1111
12## Check that program headers are not written, unless we explicitly tell12## Check that program headers are not written, unless we explicitly tell
13## lld to do this.13## lld to do this.
...@@ -18,7 +18,7 @@...@@ -18,7 +18,7 @@
18# RUN: .foo : {*(.foo.*)} :all \18# RUN: .foo : {*(.foo.*)} :all \
19# RUN: }" > %t.script19# RUN: }" > %t.script
20# RUN: ld.lld -o %t1 --script %t.script %t20# RUN: ld.lld -o %t1 --script %t.script %t
21# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=NOPHDR %s21# RUN: llvm-readobj -l %t1 | FileCheck --check-prefix=NOPHDR %s
2222
23## Check the AT(expr)23## Check the AT(expr)
24# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS AT(0x500 + 0x500) ;} \24# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS AT(0x500 + 0x500) ;} \
...@@ -28,7 +28,7 @@...@@ -28,7 +28,7 @@
28# RUN: .foo : {*(.foo.*)} :all \28# RUN: .foo : {*(.foo.*)} :all \
29# RUN: .data : {*(.data.*)} :all}" > %t.script29# RUN: .data : {*(.data.*)} :all}" > %t.script
30# RUN: ld.lld -o %t1 --script %t.script %t30# RUN: ld.lld -o %t1 --script %t.script %t
31# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=AT %s31# RUN: llvm-readobj -l %t1 | FileCheck --check-prefix=AT %s
3232
33# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS ;} \33# RUN: echo "PHDRS {all PT_LOAD FILEHDR PHDRS ;} \
34# RUN: SECTIONS { \34# RUN: SECTIONS { \
...@@ -37,7 +37,7 @@...@@ -37,7 +37,7 @@
37# RUN: .foo : {*(.foo.*)} \37# RUN: .foo : {*(.foo.*)} \
38# RUN: .data : {*(.data.*)} }" > %t.script38# RUN: .data : {*(.data.*)} }" > %t.script
39# RUN: ld.lld -o %t1 --script %t.script %t39# RUN: ld.lld -o %t1 --script %t.script %t
40# RUN: llvm-readobj -program-headers %t1 | FileCheck --check-prefix=DEFHDR %s40# RUN: llvm-readobj -l %t1 | FileCheck --check-prefix=DEFHDR %s
4141
42## Check that error is reported when trying to use phdr which is not listed42## Check that error is reported when trying to use phdr which is not listed
43## inside PHDRS {} block43## inside PHDRS {} block
...@@ -95,7 +95,7 @@...@@ -95,7 +95,7 @@
95# RUN: echo "PHDRS {text PT_LOAD FILEHDR PHDRS; foo 0x11223344; } \95# RUN: echo "PHDRS {text PT_LOAD FILEHDR PHDRS; foo 0x11223344; } \
96# RUN: SECTIONS { . = SIZEOF_HEADERS; .foo : { *(.foo* .text*) } : text : foo}" > %t1.script96# RUN: SECTIONS { . = SIZEOF_HEADERS; .foo : { *(.foo* .text*) } : text : foo}" > %t1.script
97# RUN: ld.lld -o %t2 --script %t1.script %t97# RUN: ld.lld -o %t2 --script %t1.script %t
98# RUN: llvm-readobj -program-headers %t2 | FileCheck --check-prefix=INT-PHDRS %s98# RUN: llvm-readobj -l %t2 | FileCheck --check-prefix=INT-PHDRS %s
9999
100# INT-PHDRS: ProgramHeaders [100# INT-PHDRS: ProgramHeaders [
101# INT-PHDRS: ProgramHeader {101# INT-PHDRS: ProgramHeader {
deps/lld/test/ELF/linkerscript/provide-empty-section.s+4-4
...@@ -8,19 +8,19 @@...@@ -8,19 +8,19 @@
88
9# Case 1: Provided symbol is undefined and not referenced - empty section should be removed.9# Case 1: Provided symbol is undefined and not referenced - empty section should be removed.
10# RUN: ld.lld %tundefined.o -T %t.script -o %t1.elf10# RUN: ld.lld %tundefined.o -T %t.script -o %t1.elf
11# RUN: llvm-readobj -sections %t1.elf | FileCheck %s --check-prefix=NOSECTION11# RUN: llvm-readobj --sections %t1.elf | FileCheck %s --check-prefix=NOSECTION
1212
13# Case 2: Provided symbol is undefined and referenced - empty section should not be removed.13# Case 2: Provided symbol is undefined and referenced - empty section should not be removed.
14# RUN: ld.lld %tundefined.o %treference.o -T %t.script -o %t2.elf14# RUN: ld.lld %tundefined.o %treference.o -T %t.script -o %t2.elf
15# RUN: llvm-readobj -sections %t2.elf | FileCheck %s --check-prefix=SECTION15# RUN: llvm-readobj --sections %t2.elf | FileCheck %s --check-prefix=SECTION
1616
17# Case 3: Provided symbol is defined and not referenced - empty section should be removed.17# Case 3: Provided symbol is defined and not referenced - empty section should be removed.
18# RUN: ld.lld %tdefined.o -T %t.script -o %t3.elf18# RUN: ld.lld %tdefined.o -T %t.script -o %t3.elf
19# RUN: llvm-readobj -sections %t3.elf | FileCheck %s --check-prefix=NOSECTION19# RUN: llvm-readobj --sections %t3.elf | FileCheck %s --check-prefix=NOSECTION
2020
21# Case 4: Provided symbol is defined and referenced - empty section should not be removed.21# Case 4: Provided symbol is defined and referenced - empty section should not be removed.
22# RUN: ld.lld %tdefined.o %treference.o -T %t.script -o %t4.elf22# RUN: ld.lld %tdefined.o %treference.o -T %t.script -o %t4.elf
23# RUN: llvm-readobj -sections %t4.elf | FileCheck %s --check-prefix=SECTION23# RUN: llvm-readobj --sections %t4.elf | FileCheck %s --check-prefix=SECTION
2424
25.global _start25.global _start
26_start:26_start:
deps/lld/test/ELF/linkerscript/provide-shared2.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: ld.lld -o %t --script %t.script %t.o %t2.so6# RUN: ld.lld -o %t --script %t.script %t.o %t2.so
7# RUN: llvm-readelf --dyn-symbols %t | FileCheck %s7# RUN: llvm-readelf --dyn-symbols %t | FileCheck %s
88
9# CHECK: 1 1: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS foo9# CHECK: 1: 000000000000002a 0 NOTYPE GLOBAL DEFAULT ABS foo
1010
11.global _start11.global _start
12_start:12_start:
deps/lld/test/ELF/linkerscript/pt-interp.test+3-3
...@@ -5,17 +5,17 @@...@@ -5,17 +5,17 @@
5## Check we create PT_INTERP program header when it is specified in PHDRS.5## Check we create PT_INTERP program header when it is specified in PHDRS.
6# RUN: echo "PHDRS { interp PT_INTERP; }" > %t1.script6# RUN: echo "PHDRS { interp PT_INTERP; }" > %t1.script
7# RUN: ld.lld -o %t1 --script %t1.script %t.o %t.so --dynamic-linker foo7# RUN: ld.lld -o %t1 --script %t1.script %t.o %t.so --dynamic-linker foo
8# RUN: llvm-readobj -program-headers %t1 | FileCheck %s8# RUN: llvm-readobj -l %t1 | FileCheck %s
9# CHECK: PT_INTERP9# CHECK: PT_INTERP
1010
11## Check we do not create it if it is not specified,11## Check we do not create it if it is not specified,
12## but only if PHDRS is not empty by itself.12## but only if PHDRS is not empty by itself.
13# RUN: echo "PHDRS { ph_text PT_LOAD; }" > %t2.script13# RUN: echo "PHDRS { ph_text PT_LOAD; }" > %t2.script
14# RUN: ld.lld -o %t1 --script %t2.script %t.o %t.so --dynamic-linker foo14# RUN: ld.lld -o %t1 --script %t2.script %t.o %t.so --dynamic-linker foo
15# RUN: llvm-readobj -program-headers %t1 | FileCheck %s --check-prefix=NOINTERP15# RUN: llvm-readobj -l %t1 | FileCheck %s --check-prefix=NOINTERP
16# NOINTERP-NOT: PT_INTERP16# NOINTERP-NOT: PT_INTERP
1717
18## Otherwise, if PHDRS is empty, we create PT_INTERP header.18## Otherwise, if PHDRS is empty, we create PT_INTERP header.
19# RUN: echo "PHDRS {}" > %t3.script19# RUN: echo "PHDRS {}" > %t3.script
20# RUN: ld.lld -o %t1 --script %t3.script %t.o %t.so --dynamic-linker foo20# RUN: ld.lld -o %t1 --script %t3.script %t.o %t.so --dynamic-linker foo
21# RUN: llvm-readobj -program-headers %t1 | FileCheck %s21# RUN: llvm-readobj -l %t1 | FileCheck %s
deps/lld/test/ELF/linkerscript/quoted-section-name.test created+13
...@@ -0,0 +1,13 @@
1# REQUIRES: x86
2
3## Handling of quotes is tricky sometimes. Check we do that right and include
4## "foo bar" section into .data as expected.
5
6# RUN: echo '.section "foo bar", "aw"; nop' | llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t
7# RUN: ld.lld %t --script %s -o %t2 --print-map | FileCheck %s
8# CHECK: .data
9# CHECK-NEXT: {{.*}}(foo bar)
10
11SECTIONS {
12 .data : { *("foo bar") }
13}
deps/lld/test/ELF/linkerscript/relocatable-discard.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: echo "SECTIONS { /DISCARD/ : { *(.discard.*) }}" > %t.script3# RUN: echo "SECTIONS { /DISCARD/ : { *(.discard.*) }}" > %t.script
4# RUN: ld.lld -o %t --script %t.script -r %t.o4# RUN: ld.lld -o %t --script %t.script -r %t.o
5# RUN: llvm-readobj -sections %t | FileCheck %s5# RUN: llvm-readobj --sections %t | FileCheck %s
66
7## Test shows that we do not crash after discarding the .discard.foo with -r.7## Test shows that we do not crash after discarding the .discard.foo with -r.
8## Previously it happened because of 2 reasons:8## Previously it happened because of 2 reasons:
deps/lld/test/ELF/linkerscript/repsection-symbol.s+4-4
...@@ -7,16 +7,16 @@...@@ -7,16 +7,16 @@
7# RUN: .foo : {foo1 = .; *(.foo.*) foo2 = .; *(.bar) foo3 = .;} \7# RUN: .foo : {foo1 = .; *(.foo.*) foo2 = .; *(.bar) foo3 = .;} \
8# RUN: }" > %t.script8# RUN: }" > %t.script
9# RUN: ld.lld --hash-style=sysv -o %t1 --script %t.script %t -shared9# RUN: ld.lld --hash-style=sysv -o %t1 --script %t.script %t -shared
10# RUN: llvm-readobj -t %t1 | FileCheck %s10# RUN: llvm-readobj --symbols %t1 | FileCheck %s
1111
12# CHECK: Name: foo112# CHECK: Name: foo1
13# CHECK-NEXT: Value: 0x22813# CHECK-NEXT: Value: 0x2C0
1414
15# CHECK: Name: foo215# CHECK: Name: foo2
16# CHECK-NEXT: Value: 0x23016# CHECK-NEXT: Value: 0x2C8
1717
18# CHECK: Name: foo318# CHECK: Name: foo3
19# CHECK-NEXT: Value: 0x23419# CHECK-NEXT: Value: 0x2CC
2020
21.section .foo.1,"a"21.section .foo.1,"a"
22 .long 122 .long 1
deps/lld/test/ELF/linkerscript/repsection-va.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5# RUN: ld.lld -o %t1 --script %t.script %t5# RUN: ld.lld -o %t1 --script %t.script %t
6# RUN: llvm-objdump -section-headers %t1 | FileCheck %s6# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
7# CHECK: Sections:7# CHECK: Sections:
8# CHECK-NEXT: Idx Name Size Address Type8# CHECK-NEXT: Idx Name Size VMA Type
9# CHECK-NOT: .foo9# CHECK-NOT: .foo
10# CHECK: .foo 00000008 {{.*}} DATA10# CHECK: .foo 00000008 {{.*}} DATA
11# CHECK-NOT: .foo11# CHECK-NOT: .foo
deps/lld/test/ELF/linkerscript/section-align.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: .ccc : ALIGN(4096 * 8) { *(.ccc) } \7# RUN: .ccc : ALIGN(4096 * 8) { *(.ccc) } \
8# RUN: }" > %t.script8# RUN: }" > %t.script
9# RUN: ld.lld -o %t1 --script %t.script %t9# RUN: ld.lld -o %t1 --script %t.script %t
10# RUN: llvm-readobj -sections %t1 | FileCheck %s10# RUN: llvm-readobj --sections %t1 | FileCheck %s
1111
12.global _start12.global _start
13_start:13_start:
deps/lld/test/ELF/linkerscript/sections-constraint2.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: echo "SECTIONS { zed : ONLY_IF_RO { *(foo) *(bar) } }" > %t.script3# RUN: echo "SECTIONS { zed : ONLY_IF_RO { *(foo) *(bar) } }" > %t.script
4# RUN: ld.lld -T %t.script %t.o -o %t.so -shared4# RUN: ld.lld -T %t.script %t.o -o %t.so -shared
5# RUN: llvm-readobj -s %t.so | FileCheck %s5# RUN: llvm-readobj -S %t.so | FileCheck %s
66
7# CHECK: Sections [7# CHECK: Sections [
8# CHECK-NOT: zed8# CHECK-NOT: zed
deps/lld/test/ELF/linkerscript/sections-constraint3.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: echo "SECTIONS { zed : ONLY_IF_RO { abc = 1; *(foo) } }" > %t.script3# RUN: echo "SECTIONS { zed : ONLY_IF_RO { abc = 1; *(foo) } }" > %t.script
4# RUN: ld.lld -T %t.script %t.o -o %t.so -shared4# RUN: ld.lld -T %t.script %t.o -o %t.so -shared
5# RUN: llvm-readobj -t %t.so | FileCheck %s5# RUN: llvm-readobj --symbols %t.so | FileCheck %s
66
7# CHECK: Symbols [7# CHECK: Symbols [
8# CHECK-NOT: abc8# CHECK-NOT: abc
deps/lld/test/ELF/linkerscript/sections-constraint4.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: .foo : ONLY_IF_RO { *(.foo) } \4# RUN: .foo : ONLY_IF_RO { *(.foo) } \
5# RUN: .bar : {bar1 = .; *(.bar) } }" > %t1.script5# RUN: .bar : {bar1 = .; *(.bar) } }" > %t1.script
6# RUN: ld.lld -o %t1 --script %t1.script %t6# RUN: ld.lld -o %t1 --script %t1.script %t
7# RUN: llvm-readobj -t %t1 | FileCheck %s7# RUN: llvm-readobj --symbols %t1 | FileCheck %s
88
9# CHECK: Name: bar19# CHECK: Name: bar1
1010
deps/lld/test/ELF/linkerscript/sections-constraint5.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: }" > %t.script6# RUN: }" > %t.script
77
8# RUN: ld.lld -o %t -T %t.script %t.o8# RUN: ld.lld -o %t -T %t.script %t.o
9# RUN: llvm-readobj -s -t %t | FileCheck %s9# RUN: llvm-readobj -S --symbols %t | FileCheck %s
1010
11# CHECK: Sections [11# CHECK: Sections [
12# CHECK: Name: bar12# CHECK: Name: bar
deps/lld/test/ELF/linkerscript/sections-gc2.s+1-1
...@@ -8,7 +8,7 @@...@@ -8,7 +8,7 @@
8# RUN: ld.lld -T %t.script -o %t.so %t.o --gc-sections8# RUN: ld.lld -T %t.script -o %t.so %t.o --gc-sections
9# RUN: llvm-objdump -h %t.so | FileCheck %s9# RUN: llvm-objdump -h %t.so | FileCheck %s
1010
11# CHECK: Idx Name Size Address Type11# CHECK: Idx Name Size VMA Type
12# CHECK-NEXT: 012# CHECK-NEXT: 0
13# CHECK-NEXT: used_in_reloc13# CHECK-NEXT: used_in_reloc
14# CHECK-NEXT: .text14# CHECK-NEXT: .text
deps/lld/test/ELF/linkerscript/sections-padding.s+29-4
...@@ -7,11 +7,16 @@...@@ -7,11 +7,16 @@
7# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s7# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s
8# YES: 66000011 22000011 22000011 220000118# YES: 66000011 22000011 22000011 22000011
99
10# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x1100+0x22 }" > %t.script
11# RUN: ld.lld -o %t.out --script %t.script %t
12# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES2 %s
13# YES2: 66000011 22000011 22000011 22000011
14
10## Confirming that address was correct:15## Confirming that address was correct:
11# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99887766 }" > %t.script16# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99887766 }" > %t.script
12# RUN: ld.lld -o %t.out --script %t.script %t17# RUN: ld.lld -o %t.out --script %t.script %t
13# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES2 %s18# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES3 %s
14# YES2: 66998877 66998877 66998877 6699887719# YES3: 66998877 66998877 66998877 66998877
1520
16## Default padding value is 0x00:21## Default padding value is 0x00:
17# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } }" > %t.script22# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } }" > %t.script
...@@ -29,9 +34,9 @@...@@ -29,9 +34,9 @@
29# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99XX }" > %t.script34# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =0x99XX }" > %t.script
30# RUN: not ld.lld -o %t.out --script %t.script %t 2>&1 \35# RUN: not ld.lld -o %t.out --script %t.script %t 2>&1 \
31# RUN: | FileCheck --check-prefix=ERR2 %s36# RUN: | FileCheck --check-prefix=ERR2 %s
32# ERR2: invalid filler expression: 0x99XX37# ERR2: malformed number: 0x99XX
3338
34## Check case with space between '=' and expression:39## Check case with space between '=' and a value:
35# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } = 0x1122 }" > %t.script40# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } = 0x1122 }" > %t.script
36# RUN: ld.lld -o %t.out --script %t.script %t41# RUN: ld.lld -o %t.out --script %t.script %t
37# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s42# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s
...@@ -41,6 +46,26 @@...@@ -41,6 +46,26 @@
41# RUN: ld.lld -o %t.out --script %t.script %t46# RUN: ld.lld -o %t.out --script %t.script %t
42# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s47# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s
4348
49## Check we can use an artbitrary expression as a filler.
50# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } = ((0x11<<8) | 0x22) }" > %t.script
51# RUN: ld.lld -o %t.out --script %t.script %t
52# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s
53
54## Check case with space between '=' and expression:
55# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =((0x11 << 8) | 0x22) }" > %t.script
56# RUN: ld.lld -o %t.out --script %t.script %t
57# RUN: llvm-objdump -s %t.out | FileCheck -check-prefix=YES %s
58
59## Check we report an error if expression value is larger than 32-bits.
60# RUN: echo "SECTIONS { .mysec : { *(.mysec*) } =(0x11 << 32) }" > %t.script
61# RUN: not ld.lld -o %t.out --script %t.script %t 2>&1 | FileCheck --check-prefix=ERR3 %s
62# ERR3: filler expression result does not fit 32-bit: 0x1100000000
63
64## Check we report an error if an expression use a symbol.
65# RUN: echo "SECTIONS { foo = 0x11; .mysec : { *(.mysec*) } = foo }" > %t.script
66# RUN: not ld.lld -o %t.out %t --script %t.script 2>&1 | FileCheck --check-prefix=ERR4 %s
67# ERR4: symbol not found: foo
68
44.section .mysec.1,"a"69.section .mysec.1,"a"
45.align 1670.align 16
46.byte 0x6671.byte 0x66
deps/lld/test/ELF/linkerscript/segment-none.s+1-1
...@@ -23,7 +23,7 @@...@@ -23,7 +23,7 @@
2323
24# CHECK: Section to Segment mapping:24# CHECK: Section to Segment mapping:
25# CHECK-NEXT: Segment Sections...25# CHECK-NEXT: Segment Sections...
26# CHECK-NOT: .foo26# CHECK: None {{.*}}.foo
2727
28# DEFINED: Section to Segment mapping:28# DEFINED: Section to Segment mapping:
29# DEFINED-NEXT: Segment Sections...29# DEFINED-NEXT: Segment Sections...
deps/lld/test/ELF/linkerscript/sort-non-script.s+1-1
...@@ -9,8 +9,8 @@...@@ -9,8 +9,8 @@
9# CHECK-NEXT: .hash {{.*}} A9# CHECK-NEXT: .hash {{.*}} A
10# CHECK-NEXT: .dynstr {{.*}} A10# CHECK-NEXT: .dynstr {{.*}} A
11# CHECK-NEXT: .text {{.*}} AX11# CHECK-NEXT: .text {{.*}} AX
12# CHECK-NEXT: foo {{.*}} WA
13# CHECK-NEXT: .dynamic {{.*}} WA12# CHECK-NEXT: .dynamic {{.*}} WA
13# CHECK-NEXT: foo {{.*}} WA
1414
15.section foo, "aw"15.section foo, "aw"
16.byte 016.byte 0
deps/lld/test/ELF/linkerscript/symbol-alias-relocation.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: echo "aliasto__text = __text; SECTIONS { .text 0x1000 : { __text = . ; *(.text) } }" > %t.script
4# RUN: ld.lld -pie -o %t --script %t.script %t.o
5# RUN: llvm-readobj --symbols %t | FileCheck %s
6
7## Check that alias 'aliasto__text' has the correct value.
8## (It should belong to the section .text and point to it's start).
9
10# CHECK: Symbol {
11# CHECK: Name: __text
12# CHECK-NEXT: Value: 0x1000
13# CHECK-NEXT: Size: 0
14# CHECK-NEXT: Binding: Global
15# CHECK-NEXT: Type: None
16# CHECK-NEXT: Other: 0
17# CHECK-NEXT: Section: .text
18# CHECK-NEXT: }
19
20# CHECK: Symbol {
21# CHECK: Name: aliasto__text
22# CHECK-NEXT: Value: 0x1000
23# CHECK-NEXT: Size: 0
24# CHECK-NEXT: Binding: Global
25# CHECK-NEXT: Type: None
26# CHECK-NEXT: Other: 0
27# CHECK-NEXT: Section: .text
28# CHECK-NEXT: }
29
30.text
31.globl _start
32.type _start, %function
33_start:
34.globl aliasto__text
35 call __text
36 call aliasto__text
deps/lld/test/ELF/linkerscript/symbol-location.s+6-5
...@@ -1,15 +1,16 @@...@@ -1,15 +1,16 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: echo "foo = 1;" > %t.script3# RUN: echo 'foo = _start;' > %t.script
4# RUN: not ld.lld -pie -o %t --script %t.script %t.o 2>&1 | FileCheck %s4# RUN: not ld.lld -shared -T %t.script %t.o -o /dev/null 2>&1 | FileCheck %s
55
6## Here we check that symbol 'foo' location is reported properly.6## Here we check that symbol 'foo' location is reported properly.
77
8# CHECK: error: relocation R_X86_64_PLT32 cannot refer to absolute symbol: foo8# CHECK: error: relocation R_X86_64_PC32 cannot be used against symbol foo
9# CHECK: >>> defined in {{.*}}.script:19# CHECK: >>> defined in {{.*}}.script:1
10# CHECK: >>> referenced by {{.*}}.o:(.text+0x1)10# CHECK: >>> referenced by {{.*}}.o:(.text+0x1)
1111
12.text12.text
13.globl _start13.globl _start
14_start:14_start:
15 call foo@PLT15 .byte 0xe8
16 .long foo - .
deps/lld/test/ELF/linkerscript/symbol-only-align.test created+35
...@@ -0,0 +1,35 @@
1# REQUIRES: x86
2# RUN: echo '.text; ret; .data; .quad 0' > %t.s
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t.s -o %t.o
4# RUN: ld.lld -o %t --script %s %t.o -shared
5# RUN: llvm-readelf -S --symbols -l %t | FileCheck %s
6
7PHDRS {
8 text PT_LOAD FLAGS(0x5);
9 data PT_LOAD FLAGS(0x6);
10}
11
12SECTIONS {
13 . = SIZEOF_HEADERS;
14 .text : { *(.text) } : text
15 . = ALIGN(CONSTANT(MAXPAGESIZE));
16 foo : { __start_foo = .; *(foo); __end_foo = .; } : data
17 .data : { *(.data) }
18 .dynamic : { *(.dynamic) }
19}
20
21## Check that foo, the symbol only section, has the expected aligned address and
22## file offset. Also check that the section's symbols and the data segment's
23## offset and addresses match.
24
25# CHECK: Section Headers
26# CHECK: foo PROGBITS 0000000000[[ADDR:[0-9a-f]*]] [[ADDR]]
27# CHECK-NEXT: .data PROGBITS 0000000000[[ADDR]] [[ADDR]]
28
29# CHECK: Symbol table
30# CHECK: 0000000000[[ADDR]] 0 NOTYPE GLOBAL DEFAULT {{[0-9]+}} __start_foo
31# CHECK: 0000000000[[ADDR]] 0 NOTYPE GLOBAL DEFAULT {{[0-9]+}} __end_foo
32
33# CHECK: Program Headers
34# CHECK: LOAD
35# CHECK-NEXT: LOAD 0x[[ADDR]] 0x0000000000[[ADDR]] 0x0000000000[[ADDR]]
deps/lld/test/ELF/linkerscript/symbol-only-flags.test+2-2
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: echo '.section .tbss,"awT",@nobits; .quad 0' \2# RUN: echo '.section .tbss,"awT",@nobits; .quad 0' \
3# RUN: | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o3# RUN: | llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t.o
4# RUN: ld.lld -o %t --script %s %t.o4# RUN: ld.lld -o %t --script %s %t.o
5# RUN: llvm-readobj -s %t | FileCheck %s5# RUN: llvm-readobj -S %t | FileCheck %s
66
7SECTIONS {7SECTIONS {
8 . = SIZEOF_HEADERS;8 . = SIZEOF_HEADERS;
...@@ -14,7 +14,7 @@ SECTIONS {...@@ -14,7 +14,7 @@ SECTIONS {
14# CHECK: Section {14# CHECK: Section {
15# CHECK: Index:15# CHECK: Index:
16# CHECK: Name: .foo16# CHECK: Name: .foo
17# CHECK-NEXT: Type: SHT_NOBITS17# CHECK-NEXT: Type: SHT_PROGBITS
18# CHECK-NEXT: Flags [18# CHECK-NEXT: Flags [
19# CHECK-NEXT: SHF_ALLOC19# CHECK-NEXT: SHF_ALLOC
20# CHECK-NEXT: SHF_WRITE20# CHECK-NEXT: SHF_WRITE
deps/lld/test/ELF/linkerscript/symbol-only.test+1-1
...@@ -12,7 +12,7 @@ SECTIONS {...@@ -12,7 +12,7 @@ SECTIONS {
12}12}
1313
14# CHECK: Sections:14# CHECK: Sections:
15# CHECK-NEXT: Idx Name Size Address15# CHECK-NEXT: Idx Name Size VMA
16# CHECK-NEXT: 0 00000000 000000000000000016# CHECK-NEXT: 0 00000000 0000000000000000
17# CHECK: abc 00000000 [[ADDR:[0-9a-f]*]]17# CHECK: abc 00000000 [[ADDR:[0-9a-f]*]]
18# CHECK: bar 00000000 000000000000100018# CHECK: bar 00000000 0000000000001000
deps/lld/test/ELF/linkerscript/symbol-pie.s created+19
...@@ -0,0 +1,19 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: echo "SECTIONS { .data 0x2000 : { foo = .; *(.data) } }" > %t.script
5# RUN: ld.lld -pie -o %t --script %t.script %t.o
6# RUN: llvm-readobj -r %t | FileCheck %s
7
8## Position independent executables require dynamic
9## relocations for references to non-absolute script
10## symbols.
11
12# CHECK: Relocations [
13# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
14# CHECK-NEXT: 0x2000 R_X86_64_RELATIVE - 0x2000
15# CHECK-NEXT: }
16# CHECK-NEXT: ]
17
18.data
19.quad foo
deps/lld/test/ELF/linkerscript/tbss.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: bar : { *(bar) } \7# RUN: bar : { *(bar) } \
8# RUN: }" > %t.script8# RUN: }" > %t.script
9# RUN: ld.lld -T %t.script %t.o -o %t9# RUN: ld.lld -T %t.script %t.o -o %t
10# RUN: llvm-readobj -s %t | FileCheck %s10# RUN: llvm-readobj -S %t | FileCheck %s
1111
12# test that a tbss section doesn't use address space.12# test that a tbss section doesn't use address space.
1313
deps/lld/test/ELF/linkerscript/ttext-script.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: echo "SECTIONS { .text 0x200000 : { *(.text) } }" > %t.script3# RUN: echo "SECTIONS { .text 0x200000 : { *(.text) } }" > %t.script
4# RUN: ld.lld -T %t.script -Ttext 0x100000 %t.o -o %t4# RUN: ld.lld -T %t.script -Ttext 0x100000 %t.o -o %t
5# RUN: llvm-readobj --elf-output-style=GNU -s %t | FileCheck %s5# RUN: llvm-readelf -S %t | FileCheck %s
66
7# CHECK: .text PROGBITS 00000000001000007# CHECK: .text PROGBITS 0000000000100000
88
deps/lld/test/ELF/linkerscript/va.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5# RUN: ld.lld -o %t1 --script %t.script %t5# RUN: ld.lld -o %t1 --script %t.script %t
6# RUN: llvm-objdump -section-headers %t1 | FileCheck %s6# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
7# CHECK: Sections:7# CHECK: Sections:
8# CHECK-NEXT: Idx Name Size Address8# CHECK-NEXT: Idx Name Size VMA
9# CHECK-NEXT: 0 00000000 00000000000000009# CHECK-NEXT: 0 00000000 0000000000000000
10# CHECK-NEXT: 1 .foo 00000004 000000000000000010# CHECK-NEXT: 1 .foo 00000004 0000000000000000
11# CHECK-NEXT: 2 .boo 00000004 000000000000000411# CHECK-NEXT: 2 .boo 00000004 0000000000000004
deps/lld/test/ELF/linkerscript/version-linker-symbol.s+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: echo "VER1 { global: _end; foo ; local: * ; } ;" > %t.script3# RUN: echo "VER1 { global: _end; foo ; local: * ; } ;" > %t.script
4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
6# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s6# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
77
8# CHECK: Name: _end@@VER18# CHECK: Name: _end@@VER1
9# CHECK-NEXT: Value: 09# CHECK-NEXT: Value: 0
...@@ -11,7 +11,7 @@...@@ -11,7 +11,7 @@
11# CHECK-NEXT: Binding: Global11# CHECK-NEXT: Binding: Global
12# CHECK-NEXT: Type: None12# CHECK-NEXT: Type: None
13# CHECK-NEXT: Other: 013# CHECK-NEXT: Other: 0
14# CHECK-NEXT: Section: .dynamic14# CHECK-NEXT: Section: .data
1515
16# CHECK: Name: foo@@VER116# CHECK: Name: foo@@VER1
17# CHECK-NEXT: Value: 017# CHECK-NEXT: Value: 0
deps/lld/test/ELF/linkerscript/visibility.s+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4# RUN: echo "SECTIONS { foo = .; }" > %t1.script4# RUN: echo "SECTIONS { foo = .; }" > %t1.script
5# RUN: ld.lld -o %t1 --script %t1.script %t.o -shared5# RUN: ld.lld -o %t1 --script %t1.script %t.o -shared
6# RUN: llvm-readobj -t %t1 | FileCheck %s6# RUN: llvm-readobj --symbols %t1 | FileCheck %s
77
8# CHECK: Symbol {8# CHECK: Symbol {
9# CHECK: Name: foo9# CHECK: Name: foo
...@@ -19,4 +19,4 @@...@@ -19,4 +19,4 @@
1919
20 .data20 .data
21 .hidden foo21 .hidden foo
22 .long foo22 .quad foo
deps/lld/test/ELF/local-dynamic.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// Check that local symbols are not inserted into dynamic table.2// Check that local symbols are not inserted into dynamic table.
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
4// RUN: ld.lld %t -shared -o %t1.so4// RUN: ld.lld %t -shared -o %t1.so
5// RUN: llvm-readobj -t -dyn-symbols %t1.so | FileCheck %s5// RUN: llvm-readobj --symbols --dyn-syms %t1.so | FileCheck %s
66
7// CHECK: Symbols [7// CHECK: Symbols [
8// CHECK-NEXT: Symbol {8// CHECK-NEXT: Symbol {
deps/lld/test/ELF/local-got-pie.s+2-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3// RUN: ld.lld --hash-style=sysv %t.o -o %t -pie3// RUN: ld.lld --hash-style=sysv %t.o -o %t -pie
4// RUN: llvm-readobj -s -r -d %t | FileCheck %s4// RUN: llvm-readobj -S -r -d %t | FileCheck %s
5// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s5// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
66
7.globl _start7.globl _start
...@@ -15,6 +15,7 @@ foo:...@@ -15,6 +15,7 @@ foo:
1515
16// 0x20B0 - 1001 - 5 = 426616// 0x20B0 - 1001 - 5 = 4266
17// DISASM: Disassembly of section .text:17// DISASM: Disassembly of section .text:
18// DISASM-EMPTY:
18// DISASM-NEXT: _start:19// DISASM-NEXT: _start:
19// DISASM-NEXT: 1000: {{.*}} callq 426720// DISASM-NEXT: 1000: {{.*}} callq 4267
20// DISASM: foo:21// DISASM: foo:
deps/lld/test/ELF/local-got-shared.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3// RUN: ld.lld --hash-style=sysv %t.o -o %t -shared3// RUN: ld.lld --hash-style=sysv %t.o -o %t -shared
4// RUN: llvm-readobj -s -r -d %t | FileCheck %s4// RUN: llvm-readobj -S -r -d %t | FileCheck %s
5// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s5// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
66
7bar:7bar:
deps/lld/test/ELF/local-got.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t2.so4// RUN: ld.lld -shared %t2.o -o %t2.so
5// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t5// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t
6// RUN: llvm-readobj -s -r -section-data %t | FileCheck %s6// RUN: llvm-readobj -S -r --section-data %t | FileCheck %s
7// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s7// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
88
9 .globl _start9 .globl _start
deps/lld/test/ELF/local-symbols-order.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o5# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
66
7# RUN: ld.lld -o %t %t1.o %t2.o --emit-relocs7# RUN: ld.lld -o %t %t1.o %t2.o --emit-relocs
8# RUN: llvm-readobj -symbols -sections -elf-output-style=GNU %t | FileCheck %s8# RUN: llvm-readelf --symbols --sections %t | FileCheck %s
99
10## Check we sort local symbols to match the following order: 10## Check we sort local symbols to match the following order:
11## file1, local1, section1, hidden1, file2, local2, section2, hidden2 ...11## file1, local1, section1, hidden1, file2, local2, section2, hidden2 ...
deps/lld/test/ELF/local-undefined-symbol.s+3-5
...@@ -1,10 +1,8 @@...@@ -1,10 +1,8 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: ld.lld %t -o %t13# RUN: not ld.lld %t.o -o %t 2>&1 | FileCheck %s
4# RUN: llvm-readobj -t %t1 | FileCheck %s
54
6# CHECK: Symbols [5# CHECK: error: undefined symbol: foo
7# CHECK-NOT: Name: foo
86
9.global _start7.global _start
10_start:8_start:
deps/lld/test/ELF/local.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// Check that symbol table is correctly populated with local symbols.2// Check that symbol table is correctly populated with local symbols.
3// RUN: llvm-mc -save-temp-labels -filetype=obj -triple=x86_64-pc-linux %s -o %t3// RUN: llvm-mc -save-temp-labels -filetype=obj -triple=x86_64-pc-linux %s -o %t
4// RUN: ld.lld %t -o %t14// RUN: ld.lld %t -o %t1
5// RUN: llvm-readobj -t -s %t1 | FileCheck %s5// RUN: llvm-readobj --symbols -S %t1 | FileCheck %s
66
7// Check that Info is equal to the number of local symbols.7// Check that Info is equal to the number of local symbols.
8// CHECK: Section {8// CHECK: Section {
deps/lld/test/ELF/lto/Inputs/irmover-warning.ll created+10
...@@ -0,0 +1,10 @@
1target triple = "x86_64-unknown-linux-gnu"
2target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
3
4define void @f() {
5 ret void
6}
7
8!0 = !{ i32 2, !"foo", i32 2 }
9
10!llvm.module.flags = !{ !0 }
deps/lld/test/ELF/lto/Inputs/obj-path.ll created+7
...@@ -0,0 +1,7 @@
1target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
2target triple = "x86_64-unknown-linux-gnu"
3
4define void @g() {
5entry:
6 ret void
7}
deps/lld/test/ELF/lto/archive-2.ll+2-2
...@@ -4,9 +4,9 @@...@@ -4,9 +4,9 @@
4; RUN: llvm-ar rcs %t.a %t1.o4; RUN: llvm-ar rcs %t.a %t1.o
5; RUN: llvm-as %s -o %t2.o5; RUN: llvm-as %s -o %t2.o
6; RUN: ld.lld %t2.o %t.a -o %t36; RUN: ld.lld %t2.o %t.a -o %t3
7; RUN: llvm-readobj -t %t3 | FileCheck %s7; RUN: llvm-readobj --symbols %t3 | FileCheck %s
8; RUN: ld.lld %t2.o --whole-archive %t.a -o %t3 -shared8; RUN: ld.lld %t2.o --whole-archive %t.a -o %t3 -shared
9; RUN: llvm-readobj -t %t3 | FileCheck %s9; RUN: llvm-readobj --symbols %t3 | FileCheck %s
1010
11; CHECK: Name: _start (11; CHECK: Name: _start (
12; CHECK-NEXT: Value:12; CHECK-NEXT: Value:
deps/lld/test/ELF/lto/archive-no-index.ll+13-4
...@@ -1,8 +1,6 @@...@@ -1,8 +1,6 @@
1; REQUIRES: x861; REQUIRES: x86
2; Tests that we suggest that LTO symbols missing from an archive index2; Tests that we accept an archive file without symbol table
3; may be the cause of undefined references, but only if we both3; if all the member files are bitcode files.
4; encountered an empty archive index and undefined references (to prevent
5; noisy false alarms).
64
7; RUN: llvm-as -o %t1.o %s5; RUN: llvm-as -o %t1.o %s
8; RUN: llvm-as -o %t2.o %S/Inputs/archive.ll6; RUN: llvm-as -o %t2.o %S/Inputs/archive.ll
...@@ -23,3 +21,14 @@ define i32 @main() {...@@ -23,3 +21,14 @@ define i32 @main() {
23 call void @f()21 call void @f()
24 ret i32 022 ret i32 0
25}23}
24
25; RUN: echo 'f:' | llvm-mc -triple=x86_64-pc-linux -filetype=obj - -o %t3.o
26; RUN: rm -f %t3.a
27; RUN: llvm-ar crS %t3.a %t3.o
28; RUN: not ld.lld -o /dev/null -emain %t1.o %t3.a 2>&1 | FileCheck -check-prefix=ERR1 %s
29; ERR1: error: {{.*}}.a: archive has no index; run ranlib to add one
30
31; RUN: rm -f %t4.a
32; RUN: llvm-ar cr %t4.a
33; RUN: not ld.lld -o /dev/null -emain %t1.o %t4.a 2>&1 | FileCheck -check-prefix=ERR2 %s
34; ERR2: error: undefined symbol: f
deps/lld/test/ELF/lto/archive.ll+2-2
...@@ -4,9 +4,9 @@...@@ -4,9 +4,9 @@
4; RUN: llvm-ar rcs %t.a %t1.o4; RUN: llvm-ar rcs %t.a %t1.o
5; RUN: llvm-as %s -o %t2.o5; RUN: llvm-as %s -o %t2.o
6; RUN: ld.lld %t2.o %t.a -o %t3 -shared6; RUN: ld.lld %t2.o %t.a -o %t3 -shared
7; RUN: llvm-readobj -t %t3 | FileCheck %s7; RUN: llvm-readobj --symbols %t3 | FileCheck %s
8; RUN: ld.lld %t2.o --whole-archive %t.a -o %t3 -shared8; RUN: ld.lld %t2.o --whole-archive %t.a -o %t3 -shared
9; RUN: llvm-readobj -t %t3 | FileCheck %s9; RUN: llvm-readobj --symbols %t3 | FileCheck %s
1010
11; CHECK: Name: g (11; CHECK: Name: g (
12; CHECK-NEXT: Value:12; CHECK-NEXT: Value:
deps/lld/test/ELF/lto/comdat.ll+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1; REQUIRES: x861; REQUIRES: x86
2; RUN: llvm-as %s -o %t.o2; RUN: llvm-as %s -o %t.o
3; RUN: ld.lld %t.o %t.o -o %t.so -shared3; RUN: ld.lld %t.o %t.o -o %t.so -shared
4; RUN: llvm-readobj -t %t.so | FileCheck %s4; RUN: llvm-readobj --symbols %t.so | FileCheck %s
55
6; CHECK: Name: foo6; CHECK: Name: foo
7; CHECK-NEXT: Value:7; CHECK-NEXT: Value:
deps/lld/test/ELF/lto/comdat2.ll+2-2
...@@ -2,9 +2,9 @@...@@ -2,9 +2,9 @@
2; RUN: llvm-as %s -o %t.o2; RUN: llvm-as %s -o %t.o
3; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o -filetype=obj3; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/comdat.s -o %t2.o -filetype=obj
4; RUN: ld.lld %t.o %t2.o -o %t.so -shared4; RUN: ld.lld %t.o %t2.o -o %t.so -shared
5; RUN: llvm-readobj -t %t.so | FileCheck %s5; RUN: llvm-readobj --symbols %t.so | FileCheck %s
6; RUN: ld.lld %t2.o %t.o -o %t2.so -shared6; RUN: ld.lld %t2.o %t.o -o %t2.so -shared
7; RUN: llvm-readobj -t %t2.so | FileCheck %s --check-prefix=OTHER7; RUN: llvm-readobj --symbols %t2.so | FileCheck %s --check-prefix=OTHER
88
99
10target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"10target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
deps/lld/test/ELF/lto/common.ll+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2; RUN: llvm-as %s -o %t1.o2; RUN: llvm-as %s -o %t1.o
3; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/common.s -o %t2.o -filetype=obj3; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/common.s -o %t2.o -filetype=obj
4; RUN: ld.lld %t1.o %t2.o -o %t.so -shared4; RUN: ld.lld %t1.o %t2.o -o %t.so -shared
5; RUN: llvm-readobj -s -t %t.so | FileCheck %s5; RUN: llvm-readobj -S --symbols %t.so | FileCheck %s
66
7; CHECK: Name: .bss7; CHECK: Name: .bss
8; CHECK-NEXT: Type: SHT_NOBITS8; CHECK-NEXT: Type: SHT_NOBITS
deps/lld/test/ELF/lto/common2.ll+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2; RUN: llvm-as %s -o %t1.o2; RUN: llvm-as %s -o %t1.o
3; RUN: ld.lld %t1.o -o %t -shared -save-temps3; RUN: ld.lld %t1.o -o %t -shared -save-temps
4; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s4; RUN: llvm-dis < %t.0.2.internalize.bc | FileCheck %s
5; RUN: llvm-readobj -t %t | FileCheck %s --check-prefix=SHARED5; RUN: llvm-readobj --symbols %t | FileCheck %s --check-prefix=SHARED
66
7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
8target triple = "x86_64-unknown-linux-gnu"8target triple = "x86_64-unknown-linux-gnu"
deps/lld/test/ELF/lto/common4.ll created+21
...@@ -0,0 +1,21 @@
1; REQUIRES: x86
2
3;; Make sure that common symbols are properly internalized.
4;; In this file, @a does not interpose any symbol in a DSO,
5;; so LTO should be able to internelize it.
6
7; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux /dev/null -o %t.so.o
8; RUN: ld.lld -shared -o %t.so %t.so.o
9
10; RUN: llvm-as %s -o %t.o
11; RUN: ld.lld -o %t.exe -save-temps %t.o %t.so
12; RUN: llvm-dis < %t.exe.0.2.internalize.bc | FileCheck %s
13
14; RUN: ld.lld -pie -o %t.exe -save-temps %t.o
15; RUN: llvm-dis < %t.exe.0.2.internalize.bc | FileCheck %s
16
17target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
18target triple = "x86_64-unknown-linux-gnu"
19
20@a = common dso_local local_unnamed_addr global i32 0, align 4
21; CHECK-DAG: @a = internal global i32 0, align 4
deps/lld/test/ELF/lto/ctors.ll+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1; REQUIRES: x861; REQUIRES: x86
2; RUN: llvm-as %s -o %t.o2; RUN: llvm-as %s -o %t.o
3; RUN: ld.lld %t.o -o %t.so -shared3; RUN: ld.lld %t.o -o %t.so -shared
4; RUN: llvm-readobj -sections %t.so | FileCheck %s4; RUN: llvm-readobj --sections %t.so | FileCheck %s
55
6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
7target triple = "x86_64-unknown-linux-gnu"7target triple = "x86_64-unknown-linux-gnu"
deps/lld/test/ELF/lto/defsym.ll+4-10
...@@ -11,7 +11,7 @@...@@ -11,7 +11,7 @@
11; RUN: opt -module-summary %S/Inputs/defsym-bar.ll -o %t1.o11; RUN: opt -module-summary %S/Inputs/defsym-bar.ll -o %t1.o
12; RUN: ld.lld %t.o %t1.o -shared -o %t2.so -defsym=bar2=bar3 -save-temps12; RUN: ld.lld %t.o %t1.o -shared -o %t2.so -defsym=bar2=bar3 -save-temps
13; RUN: llvm-readelf --symbols %t2.so1.lto.o | FileCheck --check-prefix=OBJ %s13; RUN: llvm-readelf --symbols %t2.so1.lto.o | FileCheck --check-prefix=OBJ %s
14; RUN: llvm-objdump -d %t2.so | FileCheck %s --check-prefix=THIN14; RUN: llvm-objdump -d %t2.so | FileCheck %s
1515
16; OBJ: UND bar216; OBJ: UND bar2
1717
...@@ -19,17 +19,11 @@...@@ -19,17 +19,11 @@
19; Symbol bar3 should not be eliminated19; Symbol bar3 should not be eliminated
2020
21; CHECK: foo:21; CHECK: foo:
22; CHECK-NEXT: pushq %rax22; CHECK-NEXT: pushq %rax
23; CHECK-NEXT: callq23; CHECK-NEXT: callq
24; CHECK-NEXT: callq{{.*}}<bar3>24; CHECK-NEXT: callq{{.*}}<bar3>
25; CHECK-NEXT: callq25; CHECK-NEXT: popq %rax
2626; CHECK-NEXT: jmp
27; THIN: foo
28; THIN-NEXT: pushq %rax
29; THIN-NEXT: callq
30; THIN-NEXT: callq{{.*}}<bar3>
31; THIN-NEXT: popq %rax
32; THIN-NEXT: jmp
3327
34target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"28target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
35target triple = "x86_64-unknown-linux-gnu"29target triple = "x86_64-unknown-linux-gnu"
deps/lld/test/ELF/lto/deplibs.s created+15
...@@ -0,0 +1,15 @@
1; REQUIRES: x86
2
3; RUN: llvm-as %s -o %t.o
4; RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s -DOBJ=%t.o
5
6; CHECK: error: [[OBJ]]: unable to find library from dependent library specifier: foo
7; CHECK: error: [[OBJ]]: unable to find library from dependent library specifier: bar
8
9target triple = "x86_64-unknown-linux-gnu"
10target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
11
12!llvm.dependent-libraries = !{!0, !1}
13
14!0 = !{!"foo"}
15!1 = !{!"bar"}
deps/lld/test/ELF/lto/dynamic-list.ll+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2; RUN: llvm-as %s -o %t.o2; RUN: llvm-as %s -o %t.o
3; RUN: echo "{ foo; };" > %t.list3; RUN: echo "{ foo; };" > %t.list
4; RUN: ld.lld -o %t --dynamic-list %t.list -pie %t.o4; RUN: ld.lld -o %t --dynamic-list %t.list -pie %t.o
5; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s5; RUN: llvm-readobj --dyn-syms %t | FileCheck %s
66
7; CHECK: Name: foo7; CHECK: Name: foo
8; CHECK-NEXT: Value: 0x10108; CHECK-NEXT: Value: 0x1010
deps/lld/test/ELF/lto/dynsym.ll+2-2
...@@ -3,12 +3,12 @@...@@ -3,12 +3,12 @@
3; RUN: ld.lld %t.o -o %t.so -shared3; RUN: ld.lld %t.o -o %t.so -shared
4; RUN: llvm-as %s -o %t2.o4; RUN: llvm-as %s -o %t2.o
5; RUN: ld.lld %t2.o %t.so -o %t5; RUN: ld.lld %t2.o %t.so -o %t
6; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s6; RUN: llvm-readobj --dyn-syms %t | FileCheck %s
77
8; Check that we don't crash when gc'ing sections and printing the result.8; Check that we don't crash when gc'ing sections and printing the result.
9; RUN: ld.lld %t2.o %t.so --gc-sections --print-gc-sections \9; RUN: ld.lld %t2.o %t.so --gc-sections --print-gc-sections \
10; RUN: -o %t10; RUN: -o %t
11; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s11; RUN: llvm-readobj --dyn-syms %t | FileCheck %s
1212
13target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"13target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
14target triple = "x86_64-unknown-linux-gnu"14target triple = "x86_64-unknown-linux-gnu"
deps/lld/test/ELF/lto/irmover-warning.ll created+23
...@@ -0,0 +1,23 @@
1; REQUIRES: x86
2; RUN: llvm-as -o %t1.bc %s
3; RUN: llvm-as -o %t2.bc %S/Inputs/irmover-warning.ll
4; RUN: rm -f %t.a
5; RUN: llvm-ar rcs %t.a %t2.bc
6; RUN: ld.lld %t1.bc %t.a -o %t 2>&1 | FileCheck %s
7
8; CHECK: warning: linking module flags 'foo': IDs have conflicting values
9; CHECK-SAME: irmover-warning.ll.tmp.a(irmover-warning.ll.tmp2.bc at {{[0-9]+}})
10
11target triple = "x86_64-unknown-linux-gnu"
12target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
13
14declare void @f()
15
16define void @g() {
17 call void @f()
18 ret void
19}
20
21!0 = !{ i32 2, !"foo", i32 1 }
22
23!llvm.module.flags = !{ !0 }
deps/lld/test/ELF/lto/linker-script-symbols-assign.ll+3-3
...@@ -3,12 +3,12 @@...@@ -3,12 +3,12 @@
33
4; RUN: echo "foo = 1;" > %t.script4; RUN: echo "foo = 1;" > %t.script
5; RUN: ld.lld %t.o -o %t2 --script %t.script -save-temps5; RUN: ld.lld %t.o -o %t2 --script %t.script -save-temps
6; RUN: llvm-readobj -symbols %t2.lto.o | FileCheck %s6; RUN: llvm-readobj --symbols %t2.lto.o | FileCheck %s
77
8; CHECK-NOT: bar8; CHECK-NOT: bar
9; CHECK-NOT: foo9; CHECK-NOT: foo
1010
11; RUN: llvm-readobj -symbols %t2 | FileCheck %s --check-prefix=VAL11; RUN: llvm-readobj --symbols %t2 | FileCheck %s --check-prefix=VAL
12; VAL: Symbol {12; VAL: Symbol {
13; VAL: Name: foo13; VAL: Name: foo
14; VAL-NEXT: Value: 0x114; VAL-NEXT: Value: 0x1
...@@ -21,7 +21,7 @@...@@ -21,7 +21,7 @@
2121
22; RUN: echo "zed = 1;" > %t2.script22; RUN: echo "zed = 1;" > %t2.script
23; RUN: ld.lld %t.o -o %t3 --script %t2.script23; RUN: ld.lld %t.o -o %t3 --script %t2.script
24; RUN: llvm-readobj -symbols %t3 | FileCheck %s --check-prefix=ABS24; RUN: llvm-readobj --symbols %t3 | FileCheck %s --check-prefix=ABS
25; ABS: Symbol {25; ABS: Symbol {
26; ABS: Name: zed26; ABS: Name: zed
27; ABS-NEXT: Value: 0x127; ABS-NEXT: Value: 0x1
deps/lld/test/ELF/lto/linker-script-symbols.ll+2-1
...@@ -3,8 +3,9 @@...@@ -3,8 +3,9 @@
3; RUN: echo "foo = bar;" > %t.script3; RUN: echo "foo = bar;" > %t.script
44
5; RUN: ld.lld %t.o -o %t2 --script %t.script -save-temps5; RUN: ld.lld %t.o -o %t2 --script %t.script -save-temps
6; RUN: llvm-readobj -symbols %t2.lto.o | FileCheck %s6; RUN: llvm-readobj --symbols %t2.lto.o | FileCheck %s
77
8; CHECK: Symbols [
8; CHECK-NOT: zed9; CHECK-NOT: zed
9; CHECK: Symbol {10; CHECK: Symbol {
10; CHECK: Name: bar11; CHECK: Name: bar
deps/lld/test/ELF/lto/lto-start.ll+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1; REQUIRES: x861; REQUIRES: x86
2; RUN: llvm-as %s -o %t.o2; RUN: llvm-as %s -o %t.o
3; RUN: ld.lld %t.o -o %t23; RUN: ld.lld %t.o -o %t2
4; RUN: llvm-readobj -t %t2 | FileCheck %s4; RUN: llvm-readobj --symbols %t2 | FileCheck %s
55
6; CHECK: Format: ELF64-x86-646; CHECK: Format: ELF64-x86-64
7; CHECK-NEXT: Arch: x86_647; CHECK-NEXT: Arch: x86_64
deps/lld/test/ELF/lto/obj-path.ll created+35
...@@ -0,0 +1,35 @@
1; REQUIRES: x86
2
3; RUN: opt -module-summary %s -o %t1.o
4; RUN: opt -module-summary %p/Inputs/obj-path.ll -o %t2.o
5
6; Test to ensure that obj-path creates the ELF file.
7; RUN: rm -f %t4.o
8; RUN: ld.lld --plugin-opt=obj-path=%t4.o -shared %t1.o %t2.o -o %t3
9; RUN: llvm-readobj --symbols %t3 | FileCheck %s
10; RUN: llvm-readobj -h %t4.o1 | FileCheck %s -check-prefix=ELF1
11; RUN: llvm-readobj -h %t4.o2 | FileCheck %s -check-prefix=ELF2
12; RUN: llvm-nm %t4.o1 2>&1 | FileCheck %s -check-prefix=NM1
13; RUN: llvm-nm %t4.o2 2>&1 | FileCheck %s -check-prefix=NM2
14
15; CHECK: Name: g
16; CHECK-NEXT: Value: 0x1010
17; CHECK: Name: f
18; CHECK-NEXT: Value: 0x1000
19
20; NM1: T f
21; ELF1: Format: ELF64-x86-64
22
23; NM2: T g
24; ELF2: Format: ELF64-x86-64
25
26target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
27target triple = "x86_64-unknown-linux-gnu"
28
29declare void @g(...)
30
31define void @f() {
32entry:
33 call void (...) @g()
34 ret void
35}
deps/lld/test/ELF/lto/opt-remarks.ll+9-1
...@@ -8,10 +8,16 @@...@@ -8,10 +8,16 @@
8; RUN: %t.o -o %t -shared8; RUN: %t.o -o %t -shared
9; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML9; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML
10; RUN: cat %t.hot.yaml | FileCheck %s -check-prefix=YAML-HOT10; RUN: cat %t.hot.yaml | FileCheck %s -check-prefix=YAML-HOT
11; RUN: ld.lld --opt-remarks-filename %t1.yaml --opt-remarks-passes inline %t.o \
12; RUN: -o /dev/null -shared
13; RUN: cat %t1.yaml | FileCheck %s -check-prefix=YAML-PASSES
14; RUN: ld.lld --opt-remarks-filename %t1.yaml --opt-remarks-format yaml %t.o \
15; RUN: -o /dev/null -shared
16; RUN: cat %t.yaml | FileCheck %s -check-prefix=YAML
1117
12; Check that @tinkywinky is inlined after optimizations.18; Check that @tinkywinky is inlined after optimizations.
13; CHECK-LABEL: define i32 @main19; CHECK-LABEL: define i32 @main
14; CHECK-NEXT: %a.i = call i32 @patatino()20; CHECK-NEXT: %a.i = {{.*}}call i32 @patatino()
15; CHECK-NEXT: ret i32 %a.i21; CHECK-NEXT: ret i32 %a.i
16; CHECK-NEXT: }22; CHECK-NEXT: }
1723
...@@ -48,6 +54,8 @@...@@ -48,6 +54,8 @@
48; YAML-HOT-NEXT: - String: ')'54; YAML-HOT-NEXT: - String: ')'
49; YAML-HOT-NEXT: ...55; YAML-HOT-NEXT: ...
5056
57; YAML-PASSES: Pass: inline
58
51target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"59target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
52target triple = "x86_64-scei-ps4"60target triple = "x86_64-scei-ps4"
5361
deps/lld/test/ELF/lto/parallel-internalize.ll+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3; RUN: rm -f %t.lto.o %t1.lto.o3; RUN: rm -f %t.lto.o %t1.lto.o
4; RUN: ld.lld --lto-partitions=2 -save-temps -o %t %t.bc \4; RUN: ld.lld --lto-partitions=2 -save-temps -o %t %t.bc \
5; RUN: -e foo --lto-O05; RUN: -e foo --lto-O0
6; RUN: llvm-readobj -t -dyn-symbols %t | FileCheck %s6; RUN: llvm-readobj --symbols --dyn-syms %t | FileCheck %s
7; RUN: llvm-nm %t.lto.o | FileCheck --check-prefix=CHECK0 %s7; RUN: llvm-nm %t.lto.o | FileCheck --check-prefix=CHECK0 %s
8; RUN: llvm-nm %t1.lto.o | FileCheck --check-prefix=CHECK1 %s8; RUN: llvm-nm %t1.lto.o | FileCheck --check-prefix=CHECK1 %s
99
deps/lld/test/ELF/lto/relocatable.ll+3-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1; REQUIRES: x861; REQUIRES: x86
2; RUN: llvm-as %s -o %t1.o2; RUN: llvm-as %s -o %t1.o
3; RUN: ld.lld %t1.o -r -o %t3; RUN: ld.lld %t1.o -r -o %t
4; RUN: llvm-readobj -symbols %t | FileCheck %s4; RUN: llvm-readobj --symbols %t | FileCheck %s
55
6; CHECK: Symbols [6; CHECK: Symbols [
7; CHECK-NEXT: Symbol {7; CHECK-NEXT: Symbol {
...@@ -71,3 +71,5 @@ define void @foo() {...@@ -71,3 +71,5 @@ define void @foo() {
71define internal void @bar() {71define internal void @bar() {
72 ret void72 ret void
73}73}
74
75declare i32 @baz(...)
deps/lld/test/ELF/lto/resolution.ll+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2; RUN: llvm-as %s -o %t1.o2; RUN: llvm-as %s -o %t1.o
3; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/resolution.s -o %t2.o -filetype=obj3; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/resolution.s -o %t2.o -filetype=obj
4; RUN: ld.lld %t1.o %t2.o -o %t.so -shared4; RUN: ld.lld %t1.o %t2.o -o %t.so -shared
5; RUN: llvm-readobj -s --section-data %t.so | FileCheck %s5; RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
66
7; CHECK: Name: .data7; CHECK: Name: .data
8; CHECK-NEXT: Type: SHT_PROGBITS8; CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/lto/riscv32.ll created+10
...@@ -0,0 +1,10 @@
1; REQUIRES: riscv
2
3; RUN: llvm-as %s -o %t.o
4; RUN: ld.lld %t.o -o %t
5target datalayout = "e-m:e-p:32:32-i64:64-n32-S128"
6target triple = "riscv32-unknown-elf"
7
8define void @f() {
9 ret void
10}
deps/lld/test/ELF/lto/riscv64.ll created+10
...@@ -0,0 +1,10 @@
1; REQUIRES: riscv
2
3; RUN: llvm-as %s -o %t.o
4; RUN: ld.lld %t.o -o %t
5target datalayout = "e-m:e-p:64:64-i64:64-i128:128-n64-S128"
6target triple = "riscv64-unknown-elf"
7
8define void @f() {
9 ret void
10}
deps/lld/test/ELF/lto/setting-dso-local.ll+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2; RUN: llvm-as %s -o %t1.o2; RUN: llvm-as %s -o %t1.o
3; RUN: not ld.lld -o %t %t1.o 2>&1 | FileCheck %s3; RUN: not ld.lld -o %t %t1.o 2>&1 | FileCheck %s
44
5; CHECK: undefined symbol: foobar5; CHECK: undefined hidden symbol: foobar
66
7; We used to crash setting foobar to non-dso_local7; We used to crash setting foobar to non-dso_local
88
deps/lld/test/ELF/lto/shlib-undefined.ll+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o4; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %t2.s -o %t2.o
5; RUN: ld.lld -shared %t2.o -o %t2.so5; RUN: ld.lld -shared %t2.o -o %t2.so
6; RUN: ld.lld -o %t %t.o %t2.so6; RUN: ld.lld -o %t %t.o %t2.so
7; RUN: llvm-readobj -dyn-symbols %t | FileCheck %s7; RUN: llvm-readobj --dyn-syms %t | FileCheck %s
88
9; CHECK: Name: __progname9; CHECK: Name: __progname
10; CHECK-NEXT: Value: 0x20101010; CHECK-NEXT: Value: 0x201010
deps/lld/test/ELF/lto/thinlto-cant-write-index.ll+2-1
...@@ -7,8 +7,9 @@...@@ -7,8 +7,9 @@
7; Ensure lld generates error if unable to write to index files7; Ensure lld generates error if unable to write to index files
8; RUN: rm -f %t2.o.thinlto.bc8; RUN: rm -f %t2.o.thinlto.bc
9; RUN: touch %t2.o.thinlto.bc9; RUN: touch %t2.o.thinlto.bc
10; RUN: chmod 400 %t2.o.thinlto.bc10; RUN: chmod u-w %t2.o.thinlto.bc
11; RUN: not ld.lld --plugin-opt=thinlto-index-only -shared %t1.o %t2.o -o %t3 2>&1 | FileCheck %s11; RUN: not ld.lld --plugin-opt=thinlto-index-only -shared %t1.o %t2.o -o %t3 2>&1 | FileCheck %s
12; RUN: chmod u+w %t2.o.thinlto.bc
12; CHECK: cannot open {{.*}}2.o.thinlto.bc: {{P|p}}ermission denied13; CHECK: cannot open {{.*}}2.o.thinlto.bc: {{P|p}}ermission denied
1314
14target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"15target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
deps/lld/test/ELF/lto/thinlto-index-only.ll+4-8
...@@ -38,15 +38,11 @@...@@ -38,15 +38,11 @@
38; RUN: ls %t1.o.thinlto.bc38; RUN: ls %t1.o.thinlto.bc
39; RUN: ls %t1.o.imports39; RUN: ls %t1.o.imports
4040
41; Ensure lld generates an error if unable to write an empty index file41; Ensure LLD generates an empty index for each bitcode file even if all bitcode files are lazy.
42; for lazy object file that is not added to link.
43; RUN: rm -f %t1.o.thinlto.bc
44; RUN: touch %t1.o.thinlto.bc
45; RUN: chmod 400 %t1.o.thinlto.bc
46; RUN: not ld.lld --plugin-opt=thinlto-index-only -shared %t2.o --start-lib %t1.o --end-lib \
47; RUN: -o %t3 2>&1 | FileCheck %s
48; CHECK: cannot open {{.*}}1.o.thinlto.bc: {{P|p}}ermission denied
49; RUN: rm -f %t1.o.thinlto.bc42; RUN: rm -f %t1.o.thinlto.bc
43; RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux-gnu /dev/null -o %tdummy.o
44; RUN: ld.lld --plugin-opt=thinlto-index-only -shared %tdummy.o --start-lib %t1.o --end-lib -o /dev/null
45; RUN: ls %t1.o.thinlto.bc
5046
51; NM: T f47; NM: T f
5248
deps/lld/test/ELF/lto/tls-preserve.ll+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2; REQUIRES: x862; REQUIRES: x86
3; RUN: llvm-as %s -o %t1.o3; RUN: llvm-as %s -o %t1.o
4; RUN: ld.lld -shared %t1.o -o %t14; RUN: ld.lld -shared %t1.o -o %t1
5; RUN: llvm-readobj -t %t1 | FileCheck %s5; RUN: llvm-readobj --symbols %t1 | FileCheck %s
66
7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
8target triple = "x86_64-unknown-linux-gnu"8target triple = "x86_64-unknown-linux-gnu"
deps/lld/test/ELF/lto/undef-mixed.ll+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2; RUN: llvm-mc %p/Inputs/undef-mixed.s -o %t.o -filetype=obj -triple=x86_64-pc-linux2; RUN: llvm-mc %p/Inputs/undef-mixed.s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3; RUN: llvm-as %s -o %t2.o3; RUN: llvm-as %s -o %t2.o
4; RUN: ld.lld %t2.o %t.o -o %t.so -shared4; RUN: ld.lld %t2.o %t.o -o %t.so -shared
5; RUN: llvm-readobj -t %t.so | FileCheck %s5; RUN: llvm-readobj --symbols %t.so | FileCheck %s
66
7; CHECK: Name: bar7; CHECK: Name: bar
8; CHECK-NEXT: Value:8; CHECK-NEXT: Value:
deps/lld/test/ELF/lto/undef-weak.ll+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6; RUN: llvm-as %s -o %t2.o6; RUN: llvm-as %s -o %t2.o
7; RUN: ld.lld %t2.o -o %t2.so %t.a -shared7; RUN: ld.lld %t2.o -o %t2.so %t.a -shared
8; RUN: llvm-readobj -t %t2.so | FileCheck %s8; RUN: llvm-readobj --symbols %t2.so | FileCheck %s
99
10target triple = "x86_64-unknown-linux-gnu"10target triple = "x86_64-unknown-linux-gnu"
11target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"11target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
deps/lld/test/ELF/lto/undef.ll+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1; REQUIRES: x861; REQUIRES: x86
2; RUN: llvm-as %s -o %t.o2; RUN: llvm-as %s -o %t.o
3; RUN: ld.lld %t.o -o %t.so -shared3; RUN: ld.lld %t.o -o %t.so -shared
4; RUN: llvm-readobj -t %t.so | FileCheck %s4; RUN: llvm-readobj --symbols %t.so | FileCheck %s
5target triple = "x86_64-unknown-linux-gnu"5target triple = "x86_64-unknown-linux-gnu"
6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"6target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
77
deps/lld/test/ELF/lto/undefined-puts.ll+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3; RUN: ld.lld %t1.o -o %t1.so -shared3; RUN: ld.lld %t1.o -o %t1.so -shared
4; RUN: llvm-as %s -o %t2.o4; RUN: llvm-as %s -o %t2.o
5; RUN: ld.lld %t1.so %t2.o -o %t5; RUN: ld.lld %t1.so %t2.o -o %t
6; RUN: llvm-readobj -dyn-symbols -dyn-relocations %t | FileCheck %s6; RUN: llvm-readobj --dyn-syms --dyn-relocations %t | FileCheck %s
77
8target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"8target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
9target triple = "x86_64-unknown-linux-gnu"9target triple = "x86_64-unknown-linux-gnu"
...@@ -20,7 +20,7 @@ declare i32 @printf(i8*, ...)...@@ -20,7 +20,7 @@ declare i32 @printf(i8*, ...)
20; Check that puts symbol is present in the dynamic symbol table and20; Check that puts symbol is present in the dynamic symbol table and
21; there's a relocation for it.21; there's a relocation for it.
22; CHECK: Dynamic Relocations {22; CHECK: Dynamic Relocations {
23; CHECK-NEXT: 0x202018 R_X86_64_JUMP_SLOT puts 0x023; CHECK-NEXT: 0x203018 R_X86_64_JUMP_SLOT puts 0x0
24; CHECK-NEXT: }24; CHECK-NEXT: }
2525
26; CHECK: DynamicSymbols [26; CHECK: DynamicSymbols [
deps/lld/test/ELF/lto/version-script.ll+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3; RUN: echo "VERSION_1.0{ global: foo; local: *; }; VERSION_2.0{ global: bar; local: *; };" > %t.script3; RUN: echo "VERSION_1.0{ global: foo; local: *; }; VERSION_2.0{ global: bar; local: *; };" > %t.script
4; RUN: ld.lld %t.o -o %t2 -shared --version-script %t.script -save-temps4; RUN: ld.lld %t.o -o %t2 -shared --version-script %t.script -save-temps
5; RUN: llvm-dis < %t2.0.0.preopt.bc | FileCheck %s5; RUN: llvm-dis < %t2.0.0.preopt.bc | FileCheck %s
6; RUN: llvm-readobj -V -dyn-symbols %t2 | FileCheck --check-prefix=DSO %s6; RUN: llvm-readobj -V --dyn-syms %t2 | FileCheck --check-prefix=DSO %s
77
8target triple = "x86_64-unknown-linux-gnu"8target triple = "x86_64-unknown-linux-gnu"
9target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"9target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
deps/lld/test/ELF/lto/version-script2.ll+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2; RUN: llvm-as %s -o %t.o2; RUN: llvm-as %s -o %t.o
3; RUN: echo "VER1 {};" > %t.script3; RUN: echo "VER1 {};" > %t.script
4; RUN: ld.lld %t.o -o %t.so -shared --version-script %t.script4; RUN: ld.lld %t.o -o %t.so -shared --version-script %t.script
5; RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s5; RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
66
7; test that we have the correct version.7; test that we have the correct version.
8; CHECK: Name: foo@@VER1 (8; CHECK: Name: foo@@VER1 (
deps/lld/test/ELF/lto/visibility.ll+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/visibility.s -o %t2.o -filetype=obj3; RUN: llvm-mc -triple=x86_64-pc-linux %p/Inputs/visibility.s -o %t2.o -filetype=obj
4; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps4; RUN: ld.lld %t1.o %t2.o -o %t.so -shared -save-temps
5; RUN: llvm-dis < %t.so.0.2.internalize.bc | FileCheck --check-prefix=IR %s5; RUN: llvm-dis < %t.so.0.2.internalize.bc | FileCheck --check-prefix=IR %s
6; RUN: llvm-readobj -t %t.so | FileCheck %s6; RUN: llvm-readobj --symbols %t.so | FileCheck %s
77
8; CHECK: Name: g8; CHECK: Name: g
9; CHECK-NEXT: Value: 0x10009; CHECK-NEXT: Value: 0x1000
...@@ -16,7 +16,7 @@...@@ -16,7 +16,7 @@
16; CHECK-NEXT: Section: .text16; CHECK-NEXT: Section: .text
1717
18; CHECK: Name: a18; CHECK: Name: a
19; CHECK-NEXT: Value: 0x200019; CHECK-NEXT: Value: 0x3000
20; CHECK-NEXT: Size: 020; CHECK-NEXT: Size: 0
21; CHECK-NEXT: Binding: Local21; CHECK-NEXT: Binding: Local
22; CHECK-NEXT: Type: None22; CHECK-NEXT: Type: None
deps/lld/test/ELF/lto/weak.ll+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1; REQUIRES: x861; REQUIRES: x86
2; RUN: llvm-as %s -o %t.o2; RUN: llvm-as %s -o %t.o
3; RUN: ld.lld %t.o %t.o -o %t.so -shared3; RUN: ld.lld %t.o %t.o -o %t.so -shared
4; RUN: llvm-readobj -t %t.so | FileCheck %s4; RUN: llvm-readobj --symbols %t.so | FileCheck %s
55
6target triple = "x86_64-unknown-linux-gnu"6target triple = "x86_64-unknown-linux-gnu"
7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"7target datalayout = "e-m:e-i64:64-f80:128-n8:16:32:64-S128"
deps/lld/test/ELF/lto/weakodr-visibility.ll+2-2
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9; but keeps `protected` visibility.9; but keeps `protected` visibility.
1010
11; RUN: ld.lld %t1.o %t2.o -o %t.so -shared11; RUN: ld.lld %t1.o %t2.o -o %t.so -shared
12; RUN: llvm-readobj -t %t.so | FileCheck %s12; RUN: llvm-readobj --symbols %t.so | FileCheck %s
13; RUN: llvm-objdump -d %t.so | FileCheck %s --check-prefix=FIRST13; RUN: llvm-objdump -d %t.so | FileCheck %s --check-prefix=FIRST
14; CHECK: Symbol {14; CHECK: Symbol {
15; CHECK: Name: foo15; CHECK: Name: foo
...@@ -27,7 +27,7 @@...@@ -27,7 +27,7 @@
2727
28; Now swap the files order.28; Now swap the files order.
29; RUN: ld.lld %t2.o %t1.o -o %t.so -shared29; RUN: ld.lld %t2.o %t1.o -o %t.so -shared
30; RUN: llvm-readobj -t %t.so | FileCheck %s30; RUN: llvm-readobj --symbols %t.so | FileCheck %s
31; RUN: llvm-objdump -d %t.so | FileCheck %s --check-prefix=SECOND31; RUN: llvm-objdump -d %t.so | FileCheck %s --check-prefix=SECOND
32; SECOND: foo:32; SECOND: foo:
33; SECOND-NEXT: movl $42, %eax33; SECOND-NEXT: movl $42, %eax
deps/lld/test/ELF/lto/wrap-1.ll+2-2
...@@ -2,13 +2,13 @@...@@ -2,13 +2,13 @@
2; LTO2; LTO
3; RUN: llvm-as %s -o %t.o3; RUN: llvm-as %s -o %t.o
4; RUN: ld.lld %t.o -o %t.out -wrap=bar -save-temps4; RUN: ld.lld %t.o -o %t.out -wrap=bar -save-temps
5; RUN: llvm-readobj -t %t.out | FileCheck %s5; RUN: llvm-readobj --symbols %t.out | FileCheck %s
6; RUN: cat %t.out.resolution.txt | FileCheck -check-prefix=RESOLS %s6; RUN: cat %t.out.resolution.txt | FileCheck -check-prefix=RESOLS %s
77
8; ThinLTO8; ThinLTO
9; RUN: opt -module-summary %s -o %t.o9; RUN: opt -module-summary %s -o %t.o
10; RUN: ld.lld %t.o -o %t.out -wrap=bar -save-temps10; RUN: ld.lld %t.o -o %t.out -wrap=bar -save-temps
11; RUN: llvm-readobj -t %t.out | FileCheck %s11; RUN: llvm-readobj --symbols %t.out | FileCheck %s
12; RUN: cat %t.out.resolution.txt | FileCheck -check-prefix=RESOLS %s12; RUN: cat %t.out.resolution.txt | FileCheck -check-prefix=RESOLS %s
1313
14; CHECK: Name: __wrap_bar14; CHECK: Name: __wrap_bar
deps/lld/test/ELF/lto/wrap-2.ll+5-10
...@@ -4,14 +4,14 @@...@@ -4,14 +4,14 @@
4; RUN: llvm-as %S/Inputs/wrap-bar.ll -o %t1.o4; RUN: llvm-as %S/Inputs/wrap-bar.ll -o %t1.o
5; RUN: ld.lld %t.o %t1.o -shared -o %t.so -wrap=bar5; RUN: ld.lld %t.o %t1.o -shared -o %t.so -wrap=bar
6; RUN: llvm-objdump -d %t.so | FileCheck %s6; RUN: llvm-objdump -d %t.so | FileCheck %s
7; RUN: llvm-readobj -t %t.so | FileCheck -check-prefix=BIND %s7; RUN: llvm-readobj --symbols %t.so | FileCheck -check-prefix=BIND %s
88
9; ThinLTO9; ThinLTO
10; RUN: opt -module-summary %s -o %t.o10; RUN: opt -module-summary %s -o %t.o
11; RUN: opt -module-summary %S/Inputs/wrap-bar.ll -o %t1.o11; RUN: opt -module-summary %S/Inputs/wrap-bar.ll -o %t1.o
12; RUN: ld.lld %t.o %t1.o -shared -o %t.so -wrap=bar12; RUN: ld.lld %t.o %t1.o -shared -o %t.so -wrap=bar
13; RUN: llvm-objdump -d %t.so | FileCheck %s -check-prefix=THIN13; RUN: llvm-objdump -d %t.so | FileCheck %s
14; RUN: llvm-readobj -t %t.so | FileCheck -check-prefix=BIND %s14; RUN: llvm-readobj --symbols %t.so | FileCheck -check-prefix=BIND %s
1515
16; Make sure that calls in foo() are not eliminated and that bar is16; Make sure that calls in foo() are not eliminated and that bar is
17; routed to __wrap_bar and __real_bar is routed to bar.17; routed to __wrap_bar and __real_bar is routed to bar.
...@@ -19,13 +19,8 @@...@@ -19,13 +19,8 @@
19; CHECK: foo:19; CHECK: foo:
20; CHECK-NEXT: pushq %rax20; CHECK-NEXT: pushq %rax
21; CHECK-NEXT: callq{{.*}}<__wrap_bar>21; CHECK-NEXT: callq{{.*}}<__wrap_bar>
22; CHECK-NEXT: callq{{.*}}<bar>22; CHECK-NEXT: popq %rax
2323; CHECK-NEXT: jmp{{.*}}<bar>
24; THIN: foo:
25; THIN-NEXT: pushq %rax
26; THIN-NEXT: callq{{.*}}<__wrap_bar>
27; THIN-NEXT: popq %rax
28; THIN-NEXT: jmp{{.*}}<bar>
2924
30; Check that bar and __wrap_bar retain their original binding.25; Check that bar and __wrap_bar retain their original binding.
31; BIND: Name: bar26; BIND: Name: bar
deps/lld/test/ELF/magic-page-combo-warn.s created+86
...@@ -0,0 +1,86 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3
4# Test that we warn when a page size is set and paging is disabled by -n or -N.
5
6# RUN: ld.lld -z max-page-size=0x10 -z common-page-size=0x10 -N %t -o %t2 2>&1 | FileCheck --check-prefix=WARN %s
7# RUN: llvm-readobj --program-headers %t2 | FileCheck --check-prefix=OMAGIC %s
8# RUN: ld.lld -z max-page-size=0x10 -z common-page-size=0x10 --omagic %t -o %t2 2>&1 | FileCheck --check-prefix=WARN %s
9# RUN: llvm-readobj --program-headers %t2 | FileCheck --check-prefix=OMAGIC %s
10
11# WARN: ld.lld: warning: -z max-page-size set, but paging disabled by omagic or nmagic
12# WARN-NEXT: ld.lld: warning: -z common-page-size set, but paging disabled by omagic or nmagic
13
14# OMAGIC: ProgramHeader {
15# OMAGIC: Type: PT_LOAD
16# OMAGIC-NEXT: Offset: 0xE8
17# OMAGIC-NEXT: VirtualAddress:
18# OMAGIC-NEXT: PhysicalAddress:
19# OMAGIC-NEXT: FileSize:
20# OMAGIC-NEXT: MemSize:
21# OMAGIC-NEXT: Flags [
22# OMAGIC-NEXT: PF_R
23# OMAGIC-NEXT: PF_W
24# OMAGIC-NEXT: PF_X
25# OMAGIC-NEXT: ]
26# OMAGIC-NEXT: Alignment: 8
27# OMAGIC-NEXT: }
28# OMAGIC-NEXT: ProgramHeader {
29# OMAGIC-NEXT: Type: PT_GNU_STACK
30
31# RUN: ld.lld -z max-page-size=0x10 -z common-page-size=0x10 -n %t -o %t3 2>&1 | FileCheck --check-prefix=WARN %s
32# RUN: llvm-readobj --program-headers %t3 | FileCheck --check-prefix=NMAGIC %s
33# RUN: ld.lld -z max-page-size=0x10 -z common-page-size=0x10 --nmagic %t -o %t3 2>&1 | FileCheck --check-prefix=WARN %s
34# RUN: llvm-readobj --program-headers %t3 | FileCheck --check-prefix=NMAGIC %s
35
36# NMAGIC: ProgramHeader {
37# NMAGIC-NEXT: Type: PT_LOAD
38# NMAGIC-NEXT: Offset: 0x158
39# NMAGIC-NEXT: VirtualAddress:
40# NMAGIC-NEXT: PhysicalAddress:
41# NMAGIC-NEXT: FileSize: 1
42# NMAGIC-NEXT: MemSize: 1
43# NMAGIC-NEXT: Flags [
44# NMAGIC-NEXT: PF_R
45# NMAGIC-NEXT: ]
46# NMAGIC-NEXT: Alignment: 8
47# NMAGIC-NEXT: }
48# NMAGIC-NEXT: ProgramHeader {
49# NMAGIC-NEXT: Type: PT_LOAD
50# NMAGIC-NEXT: Offset: 0x15C
51# NMAGIC-NEXT: VirtualAddress:
52# NMAGIC-NEXT: PhysicalAddress:
53# NMAGIC-NEXT: FileSize: 2
54# NMAGIC-NEXT: MemSize: 2
55# NMAGIC-NEXT: Flags [
56# NMAGIC-NEXT: PF_R
57# NMAGIC-NEXT: PF_X
58# NMAGIC-NEXT: ]
59# NMAGIC-NEXT: Alignment: 4
60# NMAGIC-NEXT: }
61# NMAGIC-NEXT: ProgramHeader {
62# NMAGIC-NEXT: Type: PT_LOAD (0x1)
63# NMAGIC-NEXT: Offset: 0x15E
64# NMAGIC-NEXT: VirtualAddress:
65# NMAGIC-NEXT: PhysicalAddress:
66# NMAGIC-NEXT: FileSize: 1
67# NMAGIC-NEXT: MemSize: 1
68# NMAGIC-NEXT: Flags [
69# NMAGIC-NEXT: PF_R
70# NMAGIC-NEXT: PF_W
71# NMAGIC-NEXT: ]
72# NMAGIC-NEXT: Alignment: 1
73# NMAGIC-NEXT: }
74
75.global _start
76_start:
77 nop
78
79.section .ro,"a"
80nop
81
82.section .rw,"aw"
83nop
84
85.section .rx,"ax"
86nop
deps/lld/test/ELF/many-alloc-sections.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t.o
3// RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } }" > %t.script3// RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } }" > %t.script
4// RUN: ld.lld -T %t.script %t.o -o %t4// RUN: ld.lld -T %t.script %t.o -o %t
5// RUN: llvm-readobj -t %t | FileCheck %s5// RUN: llvm-readobj --symbols %t | FileCheck %s
66
7// Test that _start is in the correct section.7// Test that _start is in the correct section.
8// CHECK: Name: _start8// CHECK: Name: _start
deps/lld/test/ELF/many-sections.s+3-3
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t2// RUN: llvm-mc -filetype=obj -triple x86_64-pc-linux-gnu %s -o %t
3// RUN: llvm-readobj -t %t | FileCheck %s3// RUN: llvm-readobj --symbols %t | FileCheck %s
44
5// Verify that the symbol _start is in a section with an index >= SHN_LORESERVE.5// Verify that the symbol _start is in a section with an index >= SHN_LORESERVE.
6// CHECK: Name: _start6// CHECK: Name: _start
...@@ -12,12 +12,12 @@...@@ -12,12 +12,12 @@
12// CHECK-NEXT: Section: dm (0xFF00)12// CHECK-NEXT: Section: dm (0xFF00)
1313
14// RUN: ld.lld %t -o %t214// RUN: ld.lld %t -o %t2
15// RUN: llvm-readobj -t %t2 | FileCheck --check-prefix=LINKED %s15// RUN: llvm-readobj --symbols %t2 | FileCheck --check-prefix=LINKED %s
1616
17// Test also with a linker script.17// Test also with a linker script.
18// RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } }" > %t.script18// RUN: echo "SECTIONS { . = SIZEOF_HEADERS; .text : { *(.text) } }" > %t.script
19// RUN: ld.lld -T %t.script %t -o %t219// RUN: ld.lld -T %t.script %t -o %t2
20// RUN: llvm-readobj -t %t2 | FileCheck --check-prefix=LINKED %s20// RUN: llvm-readobj --symbols %t2 | FileCheck --check-prefix=LINKED %s
2121
22// Test that _start is in the correct section.22// Test that _start is in the correct section.
23// LINKED: Name: _start23// LINKED: Name: _start
deps/lld/test/ELF/map-file.s+27-27
...@@ -41,22 +41,22 @@ abs = 0xAB5...@@ -41,22 +41,22 @@ abs = 0xAB5
41labs = 0x1AB541labs = 0x1AB5
4242
43// CHECK: VMA LMA Size Align Out In Symbol43// CHECK: VMA LMA Size Align Out In Symbol
44// CHECK-NEXT: 2001c8 2001c8 78 8 .dynsym44// CHECK-NEXT: 200200 200200 78 8 .dynsym
45// CHECK-NEXT: 2001c8 2001c8 78 8 <internal>:(.dynsym)45// CHECK-NEXT: 200200 200200 78 8 <internal>:(.dynsym)
46// CHECK-NEXT: 200240 200240 2c 8 .gnu.hash46// CHECK-NEXT: 200278 200278 2c 8 .gnu.hash
47// CHECK-NEXT: 200240 200240 2c 8 <internal>:(.gnu.hash)47// CHECK-NEXT: 200278 200278 2c 8 <internal>:(.gnu.hash)
48// CHECK-NEXT: 20026c 20026c 30 4 .hash48// CHECK-NEXT: 2002a4 2002a4 30 4 .hash
49// CHECK-NEXT: 20026c 20026c 30 4 <internal>:(.hash)49// CHECK-NEXT: 2002a4 2002a4 30 4 <internal>:(.hash)
50// CHECK-NEXT: 20029c 20029c 31 1 .dynstr50// CHECK-NEXT: 2002d4 2002d4 31 1 .dynstr
51// CHECK-NEXT: 20029c 20029c 31 1 <internal>:(.dynstr)51// CHECK-NEXT: 2002d4 2002d4 31 1 <internal>:(.dynstr)
52// CHECK-NEXT: 2002d0 2002d0 30 8 .rela.dyn52// CHECK-NEXT: 200308 200308 30 8 .rela.dyn
53// CHECK-NEXT: 2002d0 2002d0 30 8 <internal>:(.rela.dyn)53// CHECK-NEXT: 200308 200308 30 8 <internal>:(.rela.dyn)
54// CHECK-NEXT: 200300 200300 30 8 .rela.plt54// CHECK-NEXT: 200338 200338 30 8 .rela.plt
55// CHECK-NEXT: 200300 200300 30 8 <internal>:(.rela.plt)55// CHECK-NEXT: 200338 200338 30 8 <internal>:(.rela.plt)
56// CHECK-NEXT: 200330 200330 64 8 .eh_frame56// CHECK-NEXT: 200368 200368 64 8 .eh_frame
57// CHECK-NEXT: 200330 200330 2c 1 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x0)57// CHECK-NEXT: 200368 200368 2c 1 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x0)
58// CHECK-NEXT: 200360 200360 14 1 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x2c)58// CHECK-NEXT: 200398 200398 14 1 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.eh_frame+0x2c)
59// CHECK-NEXT: 200378 200378 18 1 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.eh_frame+0x18)59// CHECK-NEXT: 2003b0 2003b0 18 1 {{.*}}{{/|\\}}map-file.s.tmp2.o:(.eh_frame+0x18)
60// CHECK-NEXT: 201000 201000 2d 4 .text60// CHECK-NEXT: 201000 201000 2d 4 .text
61// CHECK-NEXT: 201000 201000 28 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.text)61// CHECK-NEXT: 201000 201000 28 4 {{.*}}{{/|\\}}map-file.s.tmp1.o:(.text)
62// CHECK-NEXT: 201000 201000 0 1 _start62// CHECK-NEXT: 201000 201000 0 1 _start
...@@ -75,17 +75,17 @@ labs = 0x1AB5...@@ -75,17 +75,17 @@ labs = 0x1AB5
75// CHECK-NEXT: 201030 201030 30 16 <internal>:(.plt)75// CHECK-NEXT: 201030 201030 30 16 <internal>:(.plt)
76// CHECK-NEXT: 201040 201040 0 1 sharedFunc176// CHECK-NEXT: 201040 201040 0 1 sharedFunc1
77// CHECK-NEXT: 201050 201050 0 1 sharedFunc277// CHECK-NEXT: 201050 201050 0 1 sharedFunc2
78// CHECK-NEXT: 202000 202000 28 8 .got.plt78// CHECK-NEXT: 202000 202000 100 8 .dynamic
79// CHECK-NEXT: 202000 202000 28 8 <internal>:(.got.plt)79// CHECK-NEXT: 202000 202000 100 8 <internal>:(.dynamic)
80// CHECK-NEXT: 203000 203000 100 8 .dynamic80// CHECK-NEXT: 203000 203000 28 8 .got.plt
81// CHECK-NEXT: 203000 203000 100 8 <internal>:(.dynamic)81// CHECK-NEXT: 203000 203000 28 8 <internal>:(.got.plt)
82// CHECK-NEXT: 204000 204000 10 16 .bss82// CHECK-NEXT: 203030 203030 10 16 .bss
83// CHECK-NEXT: 204000 204000 4 16 {{.*}}{{/|\\}}map-file.s.tmp1.o:(COMMON)83// CHECK-NEXT: 203030 203030 4 16 {{.*}}{{/|\\}}map-file.s.tmp1.o:(COMMON)
84// CHECK-NEXT: 204000 204000 4 1 common84// CHECK-NEXT: 203030 203030 4 1 common
85// CHECK-NEXT: 204004 204004 4 1 <internal>:(.bss)85// CHECK-NEXT: 203034 203034 4 1 <internal>:(.bss)
86// CHECK-NEXT: 204004 204004 4 1 sharedFoo86// CHECK-NEXT: 203034 203034 4 1 sharedFoo
87// CHECK-NEXT: 204008 204008 8 1 <internal>:(.bss)87// CHECK-NEXT: 203038 203038 8 1 <internal>:(.bss)
88// CHECK-NEXT: 204008 204008 8 1 sharedBar88// CHECK-NEXT: 203038 203038 8 1 sharedBar
89// CHECK-NEXT: 0 0 8 1 .comment89// CHECK-NEXT: 0 0 8 1 .comment
90// CHECK-NEXT: 0 0 8 1 <internal>:(.comment)90// CHECK-NEXT: 0 0 8 1 <internal>:(.comment)
91// CHECK-NEXT: 0 0 198 8 .symtab91// CHECK-NEXT: 0 0 198 8 .symtab
deps/lld/test/ELF/merge-align.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s4// RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
55
6 .section .rodata.foo,"aM",@progbits,16 .section .rodata.foo,"aM",@progbits,1
7 .align 167 .align 16
deps/lld/test/ELF/merge-align2.s created+35
...@@ -0,0 +1,35 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3
4# RUN: ld.lld %t.o -o %t
5# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC %s
6# RUN: llvm-readelf -x .cst8 %t | FileCheck %s
7
8# RUN: ld.lld -O0 -r %t.o -o %t1.o
9# RUN: llvm-readelf -S %t1.o | FileCheck --check-prefix=SEC %s
10# RUN: llvm-readelf -x .cst8 %t1.o | FileCheck %s
11
12## Check that if we have SHF_MERGE sections with the same name, flags and
13## entsize, but different alignments, we combine them with the maximum input
14## alignment as the output alignment.
15
16# SEC: Name Type {{.*}} Size ES Flg Lk Inf Al
17# SEC: .cst8 PROGBITS {{.*}} 000018 08 AM 0 0 8
18
19# CHECK: 0x{{[0-9a-f]+}} 02000000 00000000 01000000 00000000
20# CHECK-NEXT: 0x{{[0-9a-f]+}} 03000000 00000000
21
22.section .cst8,"aM",@progbits,8,unique,0
23.align 4
24.quad 1
25.quad 1
26
27.section .cst8,"aM",@progbits,8,unique,1
28.align 4
29.quad 1
30.quad 2
31
32.section .cst8,"aM",@progbits,8,unique,2
33.align 8
34.quad 1
35.quad 3
deps/lld/test/ELF/merge-entsize.s+8-3
...@@ -1,13 +1,18 @@...@@ -1,13 +1,18 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t3// RUN: ld.lld %t.o -o %t
4// RUN: llvm-readobj -s %t | FileCheck %s4// RUN: llvm-readobj -S %t | FileCheck %s
55
6 .section .rodata.1,"aM",@progbits,16 .section .rodata.1,"aM",@progbits,1
7 .p2align 2
7 .byte 0x428 .byte 0x42
89
9 .section .rodata.2,"aM",@progbits,210// sh_addralign = 4 while sh_entsize = 3.
11// sh_entsize is not necessarily a power of 2 and it can be unrelated to sh_addralign.
12 .section .rodata.2,"aM",@progbits,3
13 .p2align 2
10 .short 0x4214 .short 0x42
15 .byte 0
1116
12// Since the output section has both .rodata.1 and .rodata.2, it17// Since the output section has both .rodata.1 and .rodata.2, it
13// contains elements of different sizes and we use an entsize of 0.18// contains elements of different sizes and we use an entsize of 0.
...@@ -23,5 +28,5 @@...@@ -23,5 +28,5 @@
23// CHECK-NEXT: Size:28// CHECK-NEXT: Size:
24// CHECK-NEXT: Link:29// CHECK-NEXT: Link:
25// CHECK-NEXT: Info:30// CHECK-NEXT: Info:
26// CHECK-NEXT: AddressAlignment:31// CHECK-NEXT: AddressAlignment: 4
27// CHECK-NEXT: EntrySize: 032// CHECK-NEXT: EntrySize: 0
deps/lld/test/ELF/merge-entsize2.s created+49
...@@ -0,0 +1,49 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3
4# RUN: ld.lld %t.o -o %t
5# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC %s
6# RUN: llvm-readelf -x .cst %t | FileCheck --check-prefix=HEX %s
7
8# RUN: ld.lld -O0 -r %t.o -o %t1.o
9# RUN: llvm-readelf -S %t1.o | FileCheck --check-prefix=SEC-R %s
10# RUN: llvm-readelf -x .cst %t1.o | FileCheck --check-prefix=HEX-R %s
11
12## Check that SHF_MERGE sections with the same name, sh_flags and sh_entsize
13## are grouped together and can be merged within the group.
14
15## .cst 0 and .cst 1 are merged (sh_entsize=4). The result and .cst 2 and
16## combined (sh_entsize=8). The output sh_entsize is 0.
17# SEC: Name Type {{.*}} Size ES Flg Lk Inf Al
18# SEC: .cst PROGBITS {{.*}} 000020 00 AM 0 0 8
19
20## .cst 0 and .cst 1 are merged, but emitted as a separate output section.
21# SEC-R: .cst PROGBITS {{.*}} 00000c 04 AM 0 0 4
22# SEC-R: .cst PROGBITS {{.*}} 000010 08 AM 0 0 8
23
24# HEX: Hex dump of section '.cst':
25# HEX-NEXT: 0x{{[0-9a-f]+}} 01000000 00000000 02000000 00000000
26# HEX-NEXT: 0x{{[0-9a-f]+}} 01000000 00000000 03000000 00000000
27
28# HEX-R: Hex dump of section '.cst':
29# HEX-R-NEXT: 0x00000000 01000000 00000000 02000000
30# HEX-R-EMPTY:
31# HEX-R-NEXT: Hex dump of section '.cst':
32# HEX-R-NEXT: 0x00000000 01000000 00000000 03000000 00000000
33
34.section .cst,"aM",@progbits,4,unique,0
35.align 2
36.long 1
37.long 0
38.long 2
39
40.section .cst,"aM",@progbits,4,unique,1
41.align 4
42.long 1
43.long 0
44.long 2
45
46.section .cst,"aM",@progbits,8,unique,2
47.align 8
48.quad 1
49.quad 3
deps/lld/test/ELF/merge-gc-piece.s+3-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t.so -shared --gc-sections3# RUN: ld.lld %t.o -o %t.so -shared --gc-sections
4# RUN: llvm-readobj -s -section-data %t.so | FileCheck %s4# RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
55
66
7# CHECK: Name: .foo7# CHECK: Name: .foo
...@@ -10,7 +10,7 @@...@@ -10,7 +10,7 @@
10# CHECK-NEXT: SHF_ALLOC10# CHECK-NEXT: SHF_ALLOC
11# CHECK-NEXT: SHF_MERGE11# CHECK-NEXT: SHF_MERGE
12# CHECK-NEXT: ]12# CHECK-NEXT: ]
13# CHECK-NEXT: Address: 0x20013# CHECK-NEXT: Address: 0x1FD
1414
15# CHECK: Name: .bar15# CHECK: Name: .bar
16# CHECK-NEXT: Type: SHT_PROGBITS16# CHECK-NEXT: Type: SHT_PROGBITS
...@@ -24,7 +24,7 @@...@@ -24,7 +24,7 @@
24# CHECK-NEXT: AddressAlignment:24# CHECK-NEXT: AddressAlignment:
25# CHECK-NEXT: EntrySize:25# CHECK-NEXT: EntrySize:
26# CHECK-NEXT: SectionData (26# CHECK-NEXT: SectionData (
27# CHECK-NEXT: 0000: 01020000 00000000 02020000 0000000027# CHECK-NEXT: 0000: FE010000 00000000 FF010000 00000000
28# CHECK-NEXT: )28# CHECK-NEXT: )
2929
30 .section .foo,"aM",@progbits,830 .section .foo,"aM",@progbits,8
deps/lld/test/ELF/merge-gc-piece2.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t.so -shared --gc-sections3# RUN: ld.lld %t.o -o %t.so -shared --gc-sections
4# RUN: llvm-readobj -s -section-data %t.so | FileCheck %s4# RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
55
6# CHECK: Name: .bar6# CHECK: Name: .bar
7# CHECK-NEXT: Type: SHT_PROGBITS7# CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/merge-reloc-O0.s deleted-48
...@@ -1,48 +0,0 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -r -o %t2.o -O0
4# RUN: llvm-readobj -s -section-data %t2.o | FileCheck %s
5
6# We combine just the sections with the same name and sh_entsize.
7
8# CHECK: Name: .foo
9# CHECK-NEXT: Type: SHT_PROGBITS
10# CHECK-NEXT: Flags [
11# CHECK-NEXT: SHF_ALLOC
12# CHECK-NEXT: SHF_MERGE
13# CHECK-NEXT: ]
14# CHECK-NEXT: Address:
15# CHECK-NEXT: Offset:
16# CHECK-NEXT: Size: 16
17# CHECK-NEXT: Link:
18# CHECK-NEXT: Info:
19# CHECK-NEXT: AddressAlignment: 8
20# CHECK-NEXT: EntrySize: 8
21# CHECK-NEXT: SectionData (
22# CHECK-NEXT: 0000: 41000000 00000000 42000000 00000000
23# CHECK-NEXT: )
24
25# CHECK: Name: .foo
26# CHECK-NEXT: Type: SHT_PROGBITS
27# CHECK-NEXT: Flags [
28# CHECK-NEXT: SHF_ALLOC
29# CHECK-NEXT: SHF_MERGE
30# CHECK-NEXT: ]
31# CHECK-NEXT: Address:
32# CHECK-NEXT: Offset:
33# CHECK-NEXT: Size: 8
34# CHECK-NEXT: Link:
35# CHECK-NEXT: Info:
36# CHECK-NEXT: AddressAlignment: 4
37# CHECK-NEXT: EntrySize: 4
38# CHECK-NEXT: SectionData (
39# CHECK-NEXT: 0000: 41000000 42000000
40# CHECK-NEXT: )
41
42 .section .foo, "aM",@progbits,8,unique,0
43 .quad 0x41
44 .section .foo, "aM",@progbits,8,unique,1
45 .quad 0x42
46 .section .foo, "aM",@progbits,4,unique,2
47 .long 0x41
48 .long 0x42
deps/lld/test/ELF/merge-reloc.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -r -o %t-rel3# RUN: ld.lld %t.o -r -o %t-rel
4# RUN: llvm-readobj -s -section-data %t-rel | FileCheck %s4# RUN: llvm-readobj -S --section-data %t-rel | FileCheck %s
55
6# When linker generates a relocatable object it does string merging in the same6# When linker generates a relocatable object it does string merging in the same
7# way as for regular link. It should keep SHF_MERGE flag and set proper sh_entsize7# way as for regular link. It should keep SHF_MERGE flag and set proper sh_entsize
deps/lld/test/ELF/merge-section-types.s+3-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld -shared %t.o -o %t3// RUN: ld.lld -shared %t.o -o %t
4// RUN: llvm-readobj -s %t | FileCheck %s4// RUN: llvm-readobj -S %t | FileCheck %s
55
6// CHECK: Name: .foo6// CHECK: Name: .foo
7// CHECK-NEXT: Type: SHT_PROGBITS7// CHECK-NEXT: Type: SHT_PROGBITS
...@@ -9,8 +9,8 @@...@@ -9,8 +9,8 @@
9// CHECK-NEXT: SHF_ALLOC9// CHECK-NEXT: SHF_ALLOC
10// CHECK-NEXT: SHF_WRITE10// CHECK-NEXT: SHF_WRITE
11// CHECK-NEXT: ]11// CHECK-NEXT: ]
12// CHECK-NEXT: Address: 0x100012// CHECK-NEXT: Address: 0x2000
13// CHECK-NEXT: Offset: 0x100013// CHECK-NEXT: Offset: 0x2000
14// CHECK-NEXT: Size: 1614// CHECK-NEXT: Size: 16
1515
16.section .foo, "aw", @progbits, unique, 116.section .foo, "aw", @progbits, unique, 1
deps/lld/test/ELF/merge-shared-str.s+3-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared -O33// RUN: ld.lld %t.o -o %t.so -shared -O3
4// RUN: llvm-readobj -r -s %t.so | FileCheck %s4// RUN: llvm-readobj -r -S %t.so | FileCheck %s
55
66
7 .section foo,"aMS",@progbits,17 .section foo,"aMS",@progbits,1
...@@ -19,10 +19,10 @@...@@ -19,10 +19,10 @@
19// CHECK-NEXT: SHF_MERGE19// CHECK-NEXT: SHF_MERGE
20// CHECK-NEXT: SHF_STRINGS20// CHECK-NEXT: SHF_STRINGS
21// CHECK-NEXT: ]21// CHECK-NEXT: ]
22// CHECK-NEXT: Address: 0x22822// CHECK-NEXT: Address: 0x260
2323
24// CHECK: Relocations [24// CHECK: Relocations [
25// CHECK-NEXT: Section ({{.*}}) .rela.dyn {25// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
26// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x22926// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x261
27// CHECK-NEXT: }27// CHECK-NEXT: }
28// CHECK-NEXT: ]28// CHECK-NEXT: ]
deps/lld/test/ELF/merge-shared.s+3-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -r -s %t.so | FileCheck %s4// RUN: llvm-readobj -r -S %t.so | FileCheck %s
55
6 .section foo,"aM",@progbits,46 .section foo,"aM",@progbits,4
7 .long 427 .long 42
...@@ -17,10 +17,10 @@...@@ -17,10 +17,10 @@
17// CHECK-NEXT: SHF_ALLOC17// CHECK-NEXT: SHF_ALLOC
18// CHECK-NEXT: SHF_MERGE18// CHECK-NEXT: SHF_MERGE
19// CHECK-NEXT: ]19// CHECK-NEXT: ]
20// CHECK-NEXT: Address: 0x22820// CHECK-NEXT: Address: 0x260
2121
22// CHECK: Relocations [22// CHECK: Relocations [
23// CHECK-NEXT: Section ({{.*}}) .rela.dyn {23// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
24// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x22A24// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x262
25// CHECK-NEXT: }25// CHECK-NEXT: }
26// CHECK-NEXT: ]26// CHECK-NEXT: ]
deps/lld/test/ELF/merge-string-align.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s4// RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
55
6 .section .rodata.foo,"aMS",@progbits,16 .section .rodata.foo,"aMS",@progbits,1
7 .align 167 .align 16
deps/lld/test/ELF/merge-string-align2.s created+25
...@@ -0,0 +1,25 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3
4# RUN: ld.lld %t.o -o %t
5# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC %s
6# RUN: llvm-readelf -x .rodata %t | FileCheck %s
7
8# SEC: Name Type {{.*}} Size ES Flg Lk Inf Al
9# SEC: .rodata PROGBITS {{.*}} 000006 01 AMS 0 0 8
10
11## Check there is no extra padding.
12
13# CHECK: a.b.c.
14
15.section .rodata.str1.8,"aMS",@progbits,1
16.align 8
17.asciz "a"
18
19.section .rodata.str1.2,"aMS",@progbits,1
20.align 2
21.asciz "b"
22
23.section .rodata.str1.1,"aMS",@progbits,1
24.align 1
25.asciz "c"
deps/lld/test/ELF/merge-string-error.s+1-1
...@@ -6,6 +6,6 @@...@@ -6,6 +6,6 @@
6 .asciz "abc"6 .asciz "abc"
77
8 .data8 .data
9 .long .rodata.str1.1 + 49 .quad .rodata.str1.1 + 4
1010
11// CHECK: merge-string-error.s.tmp.o:(.rodata.str1.1): offset is outside the section11// CHECK: merge-string-error.s.tmp.o:(.rodata.str1.1): offset is outside the section
deps/lld/test/ELF/merge-string.s+3-3
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld -O 2 %t.o -o %t.so -shared3// RUN: ld.lld -O 2 %t.o -o %t.so -shared
4// RUN: llvm-readobj -s -section-data -t %t.so | FileCheck %s4// RUN: llvm-readobj -S --section-data --symbols %t.so | FileCheck %s
5// RUN: ld.lld -O 1 %t.o -o %t.so -shared5// RUN: ld.lld -O 1 %t.o -o %t.so -shared
6// RUN: llvm-readobj -s -section-data -t %t.so | FileCheck --check-prefix=NOTAIL %s6// RUN: llvm-readobj -S --section-data --symbols %t.so | FileCheck --check-prefix=NOTAIL %s
7// RUN: ld.lld -O 0 %t.o -o %t.so -shared7// RUN: ld.lld -O 0 %t.o -o %t.so -shared
8// RUN: llvm-readobj -s -section-data -t %t.so | FileCheck --check-prefix=NOMERGE %s8// RUN: llvm-readobj -S --section-data --symbols %t.so | FileCheck --check-prefix=NOMERGE %s
99
10 .section .rodata1,"aMS",@progbits,110 .section .rodata1,"aMS",@progbits,1
11 .asciz "abc"11 .asciz "abc"
deps/lld/test/ELF/merge-sym.s+3-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -t -s %t.so | FileCheck %s4// RUN: llvm-readobj --symbols -S %t.so | FileCheck %s
55
6 .section .rodata.cst4,"aM",@progbits,46 .section .rodata.cst4,"aM",@progbits,4
7 .short 07 .short 0
...@@ -15,7 +15,7 @@ foo:...@@ -15,7 +15,7 @@ foo:
15// CHECK-NEXT: SHF_ALLOC15// CHECK-NEXT: SHF_ALLOC
16// CHECK-NEXT: SHF_MERGE16// CHECK-NEXT: SHF_MERGE
17// CHECK-NEXT: ]17// CHECK-NEXT: ]
18// CHECK-NEXT: Address: 0x21018// CHECK-NEXT: Address: 0x20D
1919
20// CHECK: Name: foo20// CHECK: Name: foo
21// CHECK-NEXT: Value: 0x21221// CHECK-NEXT: Value: 0x20F
deps/lld/test/ELF/merge-to-non-alloc.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -s -section-data -t %t.so | FileCheck %s4// RUN: llvm-readobj -S --section-data --symbols %t.so | FileCheck %s
55
6// CHECK: Name: .bar6// CHECK: Name: .bar
7// CHECK-NEXT: Type: SHT_PROGBITS7// CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/merge.s+2-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// 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/merge.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/merge.s -o %t2.o
4// RUN: ld.lld %t.o %t2.o -o %t4// RUN: ld.lld %t.o %t2.o -o %t
5// RUN: llvm-readobj -s -section-data -t %t | FileCheck %s5// RUN: llvm-readobj -S --section-data --symbols %t | FileCheck %s
6// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s6// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
77
8 .section .mysec,"aM",@progbits,48 .section .mysec,"aM",@progbits,4
...@@ -72,6 +72,7 @@ zed:...@@ -72,6 +72,7 @@ zed:
72 .globl _start72 .globl _start
73_start:73_start:
74// DISASM: Disassembly of section .text:74// DISASM: Disassembly of section .text:
75// DISASM-EMPTY:
75// DISASM-NEXT: _start:76// DISASM-NEXT: _start:
7677
77 movl .mysec, %eax78 movl .mysec, %eax
deps/lld/test/ELF/mips-26-mask.s+1
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6# RUN: llvm-objdump -d %t.exe | FileCheck %s6# RUN: llvm-objdump -d %t.exe | FileCheck %s
77
8# CHECK: Disassembly of section .text:8# CHECK: Disassembly of section .text:
9# CHECK-EMPTY:
9# CHECK: __start:10# CHECK: __start:
10# CHECK-NEXT: 20000: 0e 00 80 00 jal 13434880011# CHECK-NEXT: 20000: 0e 00 80 00 jal 134348800
1112
deps/lld/test/ELF/mips-26-n32-n64.s deleted-40
...@@ -1,40 +0,0 @@
1# REQUIRES: mips
2# Check R_MIPS_26 relocation handling in case of N64 ABIs.
3
4# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \
5# RUN: %S/Inputs/mips-dynamic.s -o %t-so.o
6# RUN: ld.lld %t-so.o -shared -o %t.so
7# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
8# RUN: ld.lld %t.o %t.so -o %t.exe
9# RUN: llvm-objdump -d %t.exe | FileCheck %s --check-prefixes=CHECK,DEFAULT
10# RUN: ld.lld %t-so.o -shared -o %t.so -z hazardplt
11# RUN: ld.lld %t.o %t.so -o %t.exe -z hazardplt
12# RUN: llvm-objdump -d %t.exe | FileCheck %s --check-prefixes=CHECK,HAZARDPLT
13
14
15# CHECK: Disassembly of section .text:
16# CHECK-NEXT: __start:
17# CHECK-NEXT: 20000: 0c 00 80 0c jal 131120
18# CHECK-NEXT: 20004: 00 00 00 00 nop
19# CHECK-NEXT: Disassembly of section .plt:
20# CHECK-NEXT: .plt:
21# CHECK-NEXT: 20010: 3c 0e 00 03 lui $14, 3
22# CHECK-NEXT: 20014: dd d9 00 08 ld $25, 8($14)
23# CHECK-NEXT: 20018: 25 ce 00 08 addiu $14, $14, 8
24# CHECK-NEXT: 2001c: 03 0e c0 23 subu $24, $24, $14
25# CHECK-NEXT: 20020: 03 e0 78 25 move $15, $ra
26# CHECK-NEXT: 20024: 00 18 c0 c2 srl $24, $24, 3
27# DEFAULT: 20028: 03 20 f8 09 jalr $25
28# HAZARDPLT: 20028: 03 20 fc 09 jalr.hb $25
29# CHECK-NEXT: 2002c: 27 18 ff fe addiu $24, $24, -2
30# CHECK-NEXT: 20030: 3c 0f 00 03 lui $15, 3
31# CHECK-NEXT: 20034: 8d f9 00 18 lw $25, 24($15)
32# DEFAULT: 20038: 03 20 00 08 jr $25
33# HAZARDPLT: 20038: 03 20 04 08 jr.hb $25
34# CHECK-NEXT: 2003c: 25 f8 00 18 addiu $24, $15, 24
35
36 .text
37 .option pic0
38 .global __start
39__start:
40 jal foo0
deps/lld/test/ELF/mips-26.s+4-1
...@@ -7,10 +7,11 @@...@@ -7,10 +7,11 @@
7# RUN: ld.lld %t2.o -shared -o %t.so7# RUN: ld.lld %t2.o -shared -o %t.so
8# RUN: ld.lld %t1.o %t.so -o %t.exe8# RUN: ld.lld %t1.o %t.so -o %t.exe
9# RUN: llvm-objdump -d %t.exe | FileCheck %s9# RUN: llvm-objdump -d %t.exe | FileCheck %s
10# RUN: llvm-readobj -dynamic-table -s -r -mips-plt-got %t.exe \10# RUN: llvm-readobj --dynamic-table -S -r --mips-plt-got %t.exe \
11# RUN: | FileCheck -check-prefix=REL %s11# RUN: | FileCheck -check-prefix=REL %s
1212
13# CHECK: Disassembly of section .text:13# CHECK: Disassembly of section .text:
14# CHECK-EMPTY:
14# CHECK-NEXT: bar:15# CHECK-NEXT: bar:
15# CHECK-NEXT: 20000: 0c 00 80 06 jal 131096 <loc>16# CHECK-NEXT: 20000: 0c 00 80 06 jal 131096 <loc>
16# CHECK-NEXT: 20004: 00 00 00 00 nop17# CHECK-NEXT: 20004: 00 00 00 00 nop
...@@ -24,7 +25,9 @@...@@ -24,7 +25,9 @@
24#25#
25# CHECK: loc:26# CHECK: loc:
26# CHECK-NEXT: 20018: 00 00 00 00 nop27# CHECK-NEXT: 20018: 00 00 00 00 nop
28# CHECK-EMPTY:
27# CHECK-NEXT: Disassembly of section .plt:29# CHECK-NEXT: Disassembly of section .plt:
30# CHECK-EMPTY:
28# CHECK-NEXT: .plt:31# CHECK-NEXT: .plt:
29# CHECK-NEXT: 20020: 3c 1c 00 03 lui $gp, 332# CHECK-NEXT: 20020: 3c 1c 00 03 lui $gp, 3
30# CHECK-NEXT: 20024: 8f 99 00 04 lw $25, 4($gp)33# CHECK-NEXT: 20024: 8f 99 00 04 lw $25, 4($gp)
deps/lld/test/ELF/mips-32.s+4-6
...@@ -3,16 +3,14 @@...@@ -3,16 +3,14 @@
33
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
5# RUN: ld.lld -shared %t-be.o -o %t-be.so5# RUN: ld.lld -shared %t-be.o -o %t-be.so
6# RUN: llvm-objdump -t -s %t-be.so \6# RUN: llvm-objdump -t -s %t-be.so | FileCheck -check-prefixes=SYM,BE %s
7# RUN: | FileCheck -check-prefix=SYM -check-prefix=BE %s7# RUN: llvm-readobj -r --dynamic-table --mips-plt-got %t-be.so \
8# RUN: llvm-readobj -r -dynamic-table -mips-plt-got %t-be.so \
9# RUN: | FileCheck -check-prefix=REL %s8# RUN: | FileCheck -check-prefix=REL %s
109
11# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o10# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
12# RUN: ld.lld -shared %t-el.o -o %t-el.so11# RUN: ld.lld -shared %t-el.o -o %t-el.so
13# RUN: llvm-objdump -t -s %t-el.so \12# RUN: llvm-objdump -t -s %t-el.so | FileCheck -check-prefixes=SYM,EL %s
14# RUN: | FileCheck -check-prefix=SYM -check-prefix=EL %s13# RUN: llvm-readobj -r --dynamic-table --mips-plt-got %t-el.so \
15# RUN: llvm-readobj -r -dynamic-table -mips-plt-got %t-el.so \
16# RUN: | FileCheck -check-prefix=REL %s14# RUN: | FileCheck -check-prefix=REL %s
1715
18 .globl __start16 .globl __start
deps/lld/test/ELF/mips-64-disp.s+19-54
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: ld.lld %t.so.o -shared -o %t.so7# RUN: ld.lld %t.so.o -shared -o %t.so
8# RUN: ld.lld %t.exe.o %t.so -o %t.exe8# RUN: ld.lld %t.exe.o %t.so -o %t.exe
9# RUN: llvm-objdump -d -t %t.exe | FileCheck %s9# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
10# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s10# RUN: llvm-readelf -r --mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
1111
12# CHECK: __start:12# CHECK: __start:
13# CHECK-NEXT: 20000: 24 42 80 40 addiu $2, $2, -3270413# CHECK-NEXT: 20000: 24 42 80 40 addiu $2, $2, -32704
...@@ -20,59 +20,24 @@...@@ -20,59 +20,24 @@
20# CHECK: 0000000000020000 .text 00000000 __start20# CHECK: 0000000000020000 .text 00000000 __start
21# CHECK: 0000000000000000 g F *UND* 00000000 foo1a21# CHECK: 0000000000000000 g F *UND* 00000000 foo1a
2222
23# GOT: Relocations [23# GOT: Primary GOT:
24# GOT-NEXT: ]24# GOT-NEXT: Canonical gp value: 0000000000038000
25# GOT-NEXT: Primary GOT {25# GOT-EMPTY:
26# GOT-NEXT: Canonical gp value:26# GOT-NEXT: Reserved entries:
27# GOT-NEXT: Reserved entries [27# GOT-NEXT: Address Access Initial Purpose
28# GOT-NEXT: Entry {28# GOT-NEXT: 0000000000030010 -32752(gp) 0000000000000000 Lazy resolver
29# GOT-NEXT: Address:29# GOT-NEXT: 0000000000030018 -32744(gp) 8000000000000000 Module pointer (GNU extension)
30# GOT-NEXT: Access: -3275230# GOT-EMPTY:
31# GOT-NEXT: Initial: 0x031# GOT-NEXT: Local entries:
32# GOT-NEXT: Purpose: Lazy resolver32# GOT-NEXT: Address Access Initial
33# GOT-NEXT: }33# GOT-NEXT: 0000000000030020 -32736(gp) 0000000000020014
34# GOT-NEXT: Entry {34# GOT-NEXT: 0000000000030028 -32728(gp) 0000000000020004
35# GOT-NEXT: Address:35# GOT-NEXT: 0000000000030030 -32720(gp) 0000000000020008
36# GOT-NEXT: Access: -3274436# GOT-NEXT: 0000000000030038 -32712(gp) 000000000002000c
37# GOT-NEXT: Initial: 0x800000000000000037# GOT-EMPTY:
38# GOT-NEXT: Purpose: Module pointer (GNU extension)38# GOT-NEXT: Global entries:
39# GOT-NEXT: }39# GOT-NEXT: Address Access Initial Sym.Val. Type Ndx Name
40# GOT-NEXT: ]40# GOT-NEXT: 0000000000030040 -32704(gp) 0000000000000000 0000000000000000 FUNC UND foo1a
41# GOT-NEXT: Local entries [
42# GOT-NEXT: Entry {
43# GOT-NEXT: Address:
44# GOT-NEXT: Access: -32736
45# GOT-NEXT: Initial: 0x20014
46# GOT-NEXT: }
47# GOT-NEXT: Entry {
48# GOT-NEXT: Address:
49# GOT-NEXT: Access: -32728
50# GOT-NEXT: Initial: 0x20004
51# GOT-NEXT: }
52# GOT-NEXT: Entry {
53# GOT-NEXT: Address:
54# GOT-NEXT: Access: -32720
55# GOT-NEXT: Initial: 0x20008
56# GOT-NEXT: }
57# GOT-NEXT: Entry {
58# GOT-NEXT: Address:
59# GOT-NEXT: Access: -32712
60# GOT-NEXT: Initial: 0x2000C
61# GOT-NEXT: }
62# GOT-NEXT: ]
63# GOT-NEXT: Global entries [
64# GOT-NEXT: Entry {
65# GOT-NEXT: Address:
66# GOT-NEXT: Access: -32704
67# GOT-NEXT: Initial: 0x0
68# GOT-NEXT: Value: 0x0
69# GOT-NEXT: Type: Function
70# GOT-NEXT: Section: Undefined
71# GOT-NEXT: Name: foo1a
72# GOT-NEXT: }
73# GOT-NEXT: ]
74# GOT-NEXT: Number of TLS and multi-GOT entries: 0
75# GOT-NEXT: }
7641
77 .text42 .text
78 .global __start43 .global __start
deps/lld/test/ELF/mips-64-got-overflow.s+27-61
...@@ -6,69 +6,35 @@...@@ -6,69 +6,35 @@
6# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t2.so.o6# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t2.so.o
7# RUN: ld.lld -shared -mips-got-size 32 %t1.so.o %t2.so.o -o %t-sgot.so7# RUN: ld.lld -shared -mips-got-size 32 %t1.so.o %t2.so.o -o %t-sgot.so
8# RUN: ld.lld -shared -mips-got-size 24 %t1.so.o %t2.so.o -o %t-mgot.so8# RUN: ld.lld -shared -mips-got-size 24 %t1.so.o %t2.so.o -o %t-mgot.so
9# RUN: llvm-readobj -r -dt -mips-plt-got %t-sgot.so | FileCheck -check-prefix=SGOT %s9# RUN: llvm-readelf --mips-plt-got %t-sgot.so | FileCheck -check-prefix=SGOT %s
10# RUN: llvm-readobj -r -dt -mips-plt-got %t-mgot.so | FileCheck -check-prefix=MGOT %s10# RUN: llvm-readelf --mips-plt-got %t-mgot.so | FileCheck -check-prefix=MGOT %s
1111
12# SGOT: Primary GOT {12# SGOT: Primary GOT:
13# SGOT-NEXT: Canonical gp value: 0x27FF013# SGOT-NEXT: Canonical gp value: 0000000000027ff0
14# SGOT-NEXT: Reserved entries [14# SGOT-EMPTY:
15# SGOT-NEXT: Entry {15# SGOT-NEXT: Reserved entries:
16# SGOT-NEXT: Address:16# SGOT-NEXT: Address Access Initial Purpose
17# SGOT-NEXT: Access: -3275217# SGOT-NEXT: 0000000000020000 -32752(gp) 0000000000000000 Lazy resolver
18# SGOT-NEXT: Initial: 0x018# SGOT-NEXT: 0000000000020008 -32744(gp) 8000000000000000 Module pointer (GNU extension)
19# SGOT-NEXT: Purpose: Lazy resolver19# SGOT-EMPTY:
20# SGOT-NEXT: }20# SGOT-NEXT: Local entries:
21# SGOT-NEXT: Entry {21# SGOT-NEXT: Address Access Initial
22# SGOT-NEXT: Address:22# SGOT-NEXT: 0000000000020010 -32736(gp) 0000000000020020
23# SGOT-NEXT: Access: -3274423# SGOT-NEXT: 0000000000020018 -32728(gp) 0000000000020030
24# SGOT-NEXT: Initial: 0x80000000
25# SGOT-NEXT: Purpose: Module pointer (GNU extension)
26# SGOT-NEXT: }
27# SGOT-NEXT: ]
28# SGOT-NEXT: Local entries [
29# SGOT-NEXT: Entry {
30# SGOT-NEXT: Address:
31# SGOT-NEXT: Access: -32736
32# SGOT-NEXT: Initial: 0x20020
33# SGOT-NEXT: }
34# SGOT-NEXT: Entry {
35# SGOT-NEXT: Address:
36# SGOT-NEXT: Access: -32728
37# SGOT-NEXT: Initial: 0x20030
38# SGOT-NEXT: }
39# SGOT-NEXT: ]
40# SGOT-NEXT: Global entries [
41# SGOT-NEXT: ]
42# SGOT-NEXT: Number of TLS and multi-GOT entries: 0
43# SGOT-NEXT: }
4424
45# MGOT: Primary GOT {25# MGOT: Primary GOT:
46# MGOT-NEXT: Canonical gp value: 0x27FF026# MGOT-NEXT: Canonical gp value: 0000000000027ff0
47# MGOT-NEXT: Reserved entries [27# MGOT-EMPTY:
48# MGOT-NEXT: Entry {28# MGOT-NEXT: Reserved entries:
49# MGOT-NEXT: Address:29# MGOT-NEXT: Address Access Initial Purpose
50# MGOT-NEXT: Access: -3275230# MGOT-NEXT: 0000000000020000 -32752(gp) 0000000000000000 Lazy resolver
51# MGOT-NEXT: Initial: 0x031# MGOT-NEXT: 0000000000020008 -32744(gp) 8000000000000000 Module pointer (GNU extension)
52# MGOT-NEXT: Purpose: Lazy resolver32# MGOT-EMPTY:
53# MGOT-NEXT: }33# MGOT-NEXT: Local entries:
54# MGOT-NEXT: Entry {34# MGOT-NEXT: Address Access Initial
55# MGOT-NEXT: Address:35# MGOT-NEXT: 0000000000020010 -32736(gp) 0000000000020020
56# MGOT-NEXT: Access: -3274436# MGOT-EMPTY:
57# MGOT-NEXT: Initial: 0x8000000037# MGOT-NEXT: Number of TLS and multi-GOT entries 1
58# MGOT-NEXT: Purpose: Module pointer (GNU extension)
59# MGOT-NEXT: }
60# MGOT-NEXT: ]
61# MGOT-NEXT: Local entries [
62# MGOT-NEXT: Entry {
63# MGOT-NEXT: Address:
64# MGOT-NEXT: Access: -32736
65# MGOT-NEXT: Initial: 0x20020
66# MGOT-NEXT: }
67# MGOT-NEXT: ]
68# MGOT-NEXT: Global entries [
69# MGOT-NEXT: ]
70# MGOT-NEXT: Number of TLS and multi-GOT entries: 1
71# MGOT-NEXT: }
7238
73 .text39 .text
74 .global foo240 .global foo2
deps/lld/test/ELF/mips-64-got.s+20-54
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: ld.lld %t.so.o -shared -o %t.so7# RUN: ld.lld %t.so.o -shared -o %t.so
8# RUN: ld.lld %t.exe.o %t.so -o %t.exe8# RUN: ld.lld %t.exe.o %t.so -o %t.exe
9# RUN: llvm-objdump -d -t %t.exe | FileCheck %s9# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
10# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s10# RUN: llvm-readelf -r --mips-plt-got %t.exe | FileCheck -check-prefix=GOT %s
1111
12# CHECK: __start:12# CHECK: __start:
1313
...@@ -21,59 +21,25 @@...@@ -21,59 +21,25 @@
21# CHECK: 0000000000020000 .text 00000000 __start21# CHECK: 0000000000020000 .text 00000000 __start
22# CHECK: 0000000000020014 .text 00000000 bar22# CHECK: 0000000000020014 .text 00000000 bar
2323
24# GOT: Relocations [24# GOT: There are no relocations in this file.
25# GOT-NEXT: ]25# GOT-NEXT: Primary GOT:
26# GOT-NEXT: Primary GOT {26# GOT-NEXT: Canonical gp value: 0000000000038000
27# GOT-NEXT: Canonical gp value:27# GOT-EMPTY:
28# GOT-NEXT: Reserved entries [28# GOT-NEXT: Reserved entries:
29# GOT-NEXT: Entry {29# GOT-NEXT: Address Access Initial Purpose
30# GOT-NEXT: Address:30# GOT-NEXT: 0000000000030010 -32752(gp) 0000000000000000 Lazy resolver
31# GOT-NEXT: Access: -3275231# GOT-NEXT: 0000000000030018 -32744(gp) 8000000000000000 Module pointer (GNU extension)
32# GOT-NEXT: Initial: 0x032# GOT-EMPTY:
33# GOT-NEXT: Purpose: Lazy resolver33# GOT-NEXT: Local entries:
34# GOT-NEXT: }34# GOT-NEXT: Address Access Initial
35# GOT-NEXT: Entry {35# GOT-NEXT: 0000000000030020 -32736(gp) 0000000000020000
36# GOT-NEXT: Address:36# GOT-NEXT: 0000000000030028 -32728(gp) 0000000000030000
37# GOT-NEXT: Access: -3274437# GOT-NEXT: 0000000000030030 -32720(gp) 0000000000020014
38# GOT-NEXT: Initial: 0x800000000000000038# GOT-NEXT: 0000000000030038 -32712(gp) 0000000000020018
39# GOT-NEXT: Purpose: Module pointer (GNU extension)39# GOT-EMPTY:
40# GOT-NEXT: }40# GOT-NEXT: Global entries:
41# GOT-NEXT: ]41# GOT-NEXT: Address Access Initial Sym.Val. Type Ndx Name
42# GOT-NEXT: Local entries [42# GOT-NEXT: 0000000000030040 -32704(gp) 0000000000000000 0000000000000000 FUNC UND foo1a
43# GOT-NEXT: Entry {
44# GOT-NEXT: Address:
45# GOT-NEXT: Access: -32736
46# GOT-NEXT: Initial: 0x20000
47# GOT-NEXT: }
48# GOT-NEXT: Entry {
49# GOT-NEXT: Address:
50# GOT-NEXT: Access: -32728
51# GOT-NEXT: Initial: 0x30000
52# GOT-NEXT: }
53# GOT-NEXT: Entry {
54# GOT-NEXT: Address:
55# GOT-NEXT: Access: -32720
56# GOT-NEXT: Initial: 0x20014
57# GOT-NEXT: }
58# GOT-NEXT: Entry {
59# GOT-NEXT: Address:
60# GOT-NEXT: Access: -32712
61# GOT-NEXT: Initial: 0x20018
62# GOT-NEXT: }
63# GOT-NEXT: ]
64# GOT-NEXT: Global entries [
65# GOT-NEXT: Entry {
66# GOT-NEXT: Address:
67# GOT-NEXT: Access: -32704
68# GOT-NEXT: Initial: 0x0
69# GOT-NEXT: Value: 0x0
70# GOT-NEXT: Type: Function
71# GOT-NEXT: Section: Undefined
72# GOT-NEXT: Name: foo1a
73# GOT-NEXT: }
74# GOT-NEXT: ]
75# GOT-NEXT: Number of TLS and multi-GOT entries: 0
76# GOT-NEXT: }
7743
78 .text44 .text
79 .global __start, bar45 .global __start, bar
deps/lld/test/ELF/mips-64-gprel-so.s+1
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6# RUN: llvm-objdump -d -t %t.so | FileCheck %s6# RUN: llvm-objdump -d -t %t.so | FileCheck %s
77
8# CHECK: Disassembly of section .text:8# CHECK: Disassembly of section .text:
9# CHECK-EMPTY:
9# CHECK-NEXT: foo:10# CHECK-NEXT: foo:
10# CHECK-NEXT: 10000: 3c 1c 00 01 lui $gp, 111# CHECK-NEXT: 10000: 3c 1c 00 01 lui $gp, 1
11# CHECK-NEXT: 10004: 03 99 e0 2d daddu $gp, $gp, $2512# CHECK-NEXT: 10004: 03 99 e0 2d daddu $gp, $gp, $25
deps/lld/test/ELF/mips-64.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
5# RUN: ld.lld -shared %t.o -o %t.so5# RUN: ld.lld -shared %t.o -o %t.so
6# RUN: llvm-objdump -t %t.so | FileCheck -check-prefix=SYM %s6# RUN: llvm-objdump -t %t.so | FileCheck -check-prefix=SYM %s
7# RUN: llvm-readobj -r -dynamic-table -mips-plt-got %t.so | FileCheck %s7# RUN: llvm-readobj -r --dynamic-table --mips-plt-got %t.so | FileCheck %s
88
9 .global __start9 .global __start
10__start:10__start:
deps/lld/test/ELF/mips-abs-got.s+4-4
...@@ -4,9 +4,9 @@...@@ -4,9 +4,9 @@
44
5# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -o %t.o %s5# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -o %t.o %s
6# RUN: echo "SECTIONS { \6# RUN: echo "SECTIONS { \
7# RUN: zero = 0; foo = 0x11004; bar = 0x22000; }" > %t.script7# RUN: zero1 = 0; zero2 = 0; foo = 0x11004; bar = 0x22000; }" > %t.script
8# RUN: ld.lld --script %t.script -o %t.exe %t.o8# RUN: ld.lld --script %t.script -o %t.exe %t.o
9# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck %s9# RUN: llvm-readobj --mips-plt-got %t.exe | FileCheck %s
1010
11# CHECK: Static GOT {11# CHECK: Static GOT {
12# CHECK: Local entries [12# CHECK: Local entries [
...@@ -30,7 +30,7 @@...@@ -30,7 +30,7 @@
3030
31 .text31 .text
32 nop32 nop
33 .reloc 0, R_MIPS_GOT_PAGE, 033 ld $v0, %got_page(zero1)($gp)
34 ld $v0, %got_page(zero)($gp)34 ld $v0, %got_page(zero2)($gp)
35 ld $v0, %got_page(foo)($gp)35 ld $v0, %got_page(foo)($gp)
36 ld $v0, %got_page(bar+0x10008)($gp)36 ld $v0, %got_page(bar+0x10008)($gp)
deps/lld/test/ELF/mips-call-hilo.s+19-31
...@@ -4,9 +4,10 @@...@@ -4,9 +4,10 @@
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
5# RUN: ld.lld %t.o -shared -o %t.so5# RUN: ld.lld %t.o -shared -o %t.so
6# RUN: llvm-objdump -d %t.so | FileCheck %s6# RUN: llvm-objdump -d %t.so | FileCheck %s
7# RUN: llvm-readobj -r -mips-plt-got %t.so | FileCheck -check-prefix=GOT %s7# RUN: llvm-readelf -r --mips-plt-got %t.so | FileCheck -check-prefix=GOT %s
88
9# CHECK: Disassembly of section .text:9# CHECK: Disassembly of section .text:
10# CHECK-EMPTY:
10# CHECK-NEXT: foo:11# CHECK-NEXT: foo:
11# CHECK-NEXT: 10000: 3c 02 00 00 lui $2, 012# CHECK-NEXT: 10000: 3c 02 00 00 lui $2, 0
12# CHECK-NEXT: 10004: 8c 42 80 20 lw $2, -32736($2)13# CHECK-NEXT: 10004: 8c 42 80 20 lw $2, -32736($2)
...@@ -15,36 +16,23 @@...@@ -15,36 +16,23 @@
15# CHECK-NEXT: 10010: 3c 02 00 00 lui $2, 016# CHECK-NEXT: 10010: 3c 02 00 00 lui $2, 0
16# CHECK-NEXT: 10014: 8c 42 80 1c lw $2, -32740($2)17# CHECK-NEXT: 10014: 8c 42 80 1c lw $2, -32740($2)
1718
18# GOT: Relocations [19# GOT: There are no relocations in this file.
19# GOT-NEXT: ]20# GOT: Primary GOT:
2021# GOT-NEXT: Canonical gp value: 00027ff0
21# GOT: Primary GOT {22# GOT-EMPTY:
22# GOT-NEXT: Canonical gp value: 0x27FF023# GOT-NEXT: Reserved entries:
23# GOT: Local entries [24# GOT-NEXT: Address Access Initial Purpose
24# GOT-NEXT: Entry {25# GOT-NEXT: 00020000 -32752(gp) 00000000 Lazy resolver
25# GOT-NEXT: Address: 0x2000826# GOT-NEXT: 00020004 -32748(gp) 80000000 Module pointer (GNU extension)
26# GOT-NEXT: Access: -3274427# GOT-EMPTY:
27# GOT-NEXT: Initial: 0x1001828# GOT-NEXT: Local entries:
28# GOT-NEXT: }29# GOT-NEXT: Address Access Initial
29# GOT-NEXT: Entry {30# GOT-NEXT: 00020008 -32744(gp) 00010018
30# GOT-NEXT: Address: 0x2000C31# GOT-NEXT: 0002000c -32740(gp) 0001001c
31# GOT-NEXT: Access: -3274032# GOT-EMPTY:
32# GOT-NEXT: Initial: 0x1001C33# GOT-NEXT: Global entries:
33# GOT-NEXT: }34# GOT-NEXT: Address Access Initial Sym.Val. Type Ndx Name
34# GOT-NEXT: ]35# GOT-NEXT: 00020010 -32736(gp) 00000000 00000000 NOTYPE UND bar
35# GOT-NEXT: Global entries [
36# GOT-NEXT: Entry {
37# GOT-NEXT: Address: 0x20010
38# GOT-NEXT: Access: -32736
39# GOT-NEXT: Initial: 0x0
40# GOT-NEXT: Value: 0x0
41# GOT-NEXT: Type: None
42# GOT-NEXT: Section: Undefined
43# GOT-NEXT: Name: bar
44# GOT-NEXT: }
45# GOT-NEXT: ]
46# GOT-NEXT: Number of TLS and multi-GOT entries: 0
47# GOT-NEXT: }
4836
49 .text37 .text
50 .global foo38 .global foo
deps/lld/test/ELF/mips-call16.s+2-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
5# RUN: ld.lld %t.o -shared -o %t.exe5# RUN: ld.lld %t.o -shared -o %t.exe
6# RUN: llvm-objdump -d %t.exe | FileCheck %s6# RUN: llvm-objdump -d %t.exe | FileCheck %s
7# RUN: llvm-readobj -mips-plt-got -symbols %t.exe \7# RUN: llvm-readobj --mips-plt-got --symbols %t.exe \
8# RUN: | FileCheck -check-prefix=GOT %s8# RUN: | FileCheck -check-prefix=GOT %s
99
10 .text10 .text
...@@ -18,6 +18,7 @@ g1:...@@ -18,6 +18,7 @@ g1:
18 nop18 nop
1919
20# CHECK: Disassembly of section .text:20# CHECK: Disassembly of section .text:
21# CHECK-EMPTY:
21# CHECK-NEXT: __start:22# CHECK-NEXT: __start:
22# CHECK-NEXT: 10000: 8f 88 80 18 lw $8, -3274423# CHECK-NEXT: 10000: 8f 88 80 18 lw $8, -32744
2324
deps/lld/test/ELF/mips-dynamic.s+4-4
...@@ -6,19 +6,19 @@...@@ -6,19 +6,19 @@
6# RUN: ld.lld -shared %td.o -o %td.so6# RUN: ld.lld -shared %td.o -o %td.so
77
8# RUN: ld.lld %t.o %td.so -o %t.exe8# RUN: ld.lld %t.o %td.so -o %t.exe
9# RUN: llvm-readobj -sections -dynamic-table %t.exe \9# RUN: llvm-readobj --sections --dynamic-table %t.exe \
10# RUN: | FileCheck -check-prefixes=EXE,NOPIE %s10# RUN: | FileCheck -check-prefixes=EXE,NOPIE %s
1111
12# RUN: ld.lld -pie %t.o %td.so -o %t.so12# RUN: ld.lld -pie %t.o %td.so -o %t.so
13# RUN: llvm-readobj -sections -dyn-symbols -dynamic-table %t.so \13# RUN: llvm-readobj --sections --dyn-syms --dynamic-table %t.so \
14# RUN: | FileCheck -check-prefixes=EXE,PIE %s14# RUN: | FileCheck -check-prefixes=EXE,PIE %s
1515
16# RUN: ld.lld %t.o --image-base=0x123000 %td.so -o %t.exe16# RUN: ld.lld %t.o --image-base=0x123000 %td.so -o %t.exe
17# RUN: llvm-readobj -sections -dynamic-table %t.exe \17# RUN: llvm-readobj --sections --dynamic-table %t.exe \
18# RUN: | FileCheck -check-prefix=IMAGE_BASE %s18# RUN: | FileCheck -check-prefix=IMAGE_BASE %s
1919
20# RUN: ld.lld -shared %t.o %td.so -o %t.so20# RUN: ld.lld -shared %t.o %td.so -o %t.so
21# RUN: llvm-readobj -sections -dyn-symbols -dynamic-table %t.so \21# RUN: llvm-readobj --sections --dyn-syms --dynamic-table %t.so \
22# RUN: | FileCheck -check-prefix=DSO %s22# RUN: | FileCheck -check-prefix=DSO %s
2323
24# EXE: Sections [24# EXE: Sections [
deps/lld/test/ELF/mips-dynsym-sort.s+2-2
...@@ -3,11 +3,11 @@...@@ -3,11 +3,11 @@
33
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
5# RUN: ld.lld -shared %t-be.o -o %t-be.so5# RUN: ld.lld -shared %t-be.o -o %t-be.so
6# RUN: llvm-readobj -symbols -dyn-symbols %t-be.so | FileCheck %s6# RUN: llvm-readobj --symbols --dyn-syms %t-be.so | FileCheck %s
77
8# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o8# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
9# RUN: ld.lld -shared %t-el.o -o %t-el.so9# RUN: ld.lld -shared %t-el.o -o %t-el.so
10# RUN: llvm-readobj -symbols -dyn-symbols %t-el.so | FileCheck %s10# RUN: llvm-readobj --symbols --dyn-syms %t-el.so | FileCheck %s
1111
12 .data12 .data
13 .globl v1,v2,v313 .globl v1,v2,v3
deps/lld/test/ELF/mips-elf-flags.s+7-7
...@@ -4,16 +4,16 @@...@@ -4,16 +4,16 @@
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
5# RUN: %S/Inputs/mips-dynamic.s -o %t-so.o5# RUN: %S/Inputs/mips-dynamic.s -o %t-so.o
6# RUN: ld.lld %t-so.o --gc-sections -shared -o %t.so6# RUN: ld.lld %t-so.o --gc-sections -shared -o %t.so
7# RUN: llvm-readobj -h -mips-abi-flags %t.so | FileCheck -check-prefix=SO %s7# RUN: llvm-readobj -h --mips-abi-flags %t.so | FileCheck -check-prefix=SO %s
88
9# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o9# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
10# RUN: ld.lld %t.o -o %t.exe10# RUN: ld.lld %t.o -o %t.exe
11# RUN: llvm-readobj -h -mips-abi-flags %t.exe | FileCheck -check-prefix=EXE %s11# RUN: llvm-readobj -h --mips-abi-flags %t.exe | FileCheck -check-prefix=EXE %s
1212
13# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \13# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
14# RUN: -mcpu=mips32r2 %s -o %t-r2.o14# RUN: -mcpu=mips32r2 %s -o %t-r2.o
15# RUN: ld.lld %t-r2.o -o %t-r2.exe15# RUN: ld.lld %t-r2.o -o %t-r2.exe
16# RUN: llvm-readobj -h -mips-abi-flags %t-r2.exe \16# RUN: llvm-readobj -h --mips-abi-flags %t-r2.exe \
17# RUN: | FileCheck -check-prefix=EXE-R2 %s17# RUN: | FileCheck -check-prefix=EXE-R2 %s
1818
19# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \19# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
...@@ -21,26 +21,26 @@...@@ -21,26 +21,26 @@
21# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \21# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
22# RUN: -mcpu=mips32r5 %S/Inputs/mips-dynamic.s -o %t-r5.o22# RUN: -mcpu=mips32r5 %S/Inputs/mips-dynamic.s -o %t-r5.o
23# RUN: ld.lld %t-r2.o %t-r5.o -o %t-r5.exe23# RUN: ld.lld %t-r2.o %t-r5.o -o %t-r5.exe
24# RUN: llvm-readobj -h -mips-abi-flags %t-r5.exe \24# RUN: llvm-readobj -h --mips-abi-flags %t-r5.exe \
25# RUN: | FileCheck -check-prefix=EXE-R5 %s25# RUN: | FileCheck -check-prefix=EXE-R5 %s
2626
27# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \27# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
28# RUN: -mcpu=mips32r6 %s -o %t-r6.o28# RUN: -mcpu=mips32r6 %s -o %t-r6.o
29# RUN: ld.lld %t-r6.o -o %t-r6.exe29# RUN: ld.lld %t-r6.o -o %t-r6.exe
30# RUN: llvm-readobj -h -mips-abi-flags %t-r6.exe \30# RUN: llvm-readobj -h --mips-abi-flags %t-r6.exe \
31# RUN: | FileCheck -check-prefix=EXE-R6 %s31# RUN: | FileCheck -check-prefix=EXE-R6 %s
3232
33# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \33# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \
34# RUN: -position-independent -mcpu=octeon %s -o %t.o34# RUN: -position-independent -mcpu=octeon %s -o %t.o
35# RUN: ld.lld %t.o -o %t.exe35# RUN: ld.lld %t.o -o %t.exe
36# RUN: llvm-readobj -h -mips-abi-flags %t.exe \36# RUN: llvm-readobj -h --mips-abi-flags %t.exe \
37# RUN: | FileCheck -check-prefix=OCTEON %s37# RUN: | FileCheck -check-prefix=OCTEON %s
3838
39# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o39# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
40# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \40# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
41# RUN: -mattr=micromips %S/Inputs/mips-fpic.s -o %t-mm.o41# RUN: -mattr=micromips %S/Inputs/mips-fpic.s -o %t-mm.o
42# RUN: ld.lld %t.o %t-mm.o -o %t.exe42# RUN: ld.lld %t.o %t-mm.o -o %t.exe
43# RUN: llvm-readobj -h -mips-abi-flags %t.exe | FileCheck -check-prefix=MICRO %s43# RUN: llvm-readobj -h --mips-abi-flags %t.exe | FileCheck -check-prefix=MICRO %s
4444
45 .text45 .text
46 .globl __start46 .globl __start
deps/lld/test/ELF/mips-got-and-copy.s+1-1
...@@ -10,7 +10,7 @@...@@ -10,7 +10,7 @@
10# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o10# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
11# RUN: ld.lld %t.so.o -shared -o %t.so11# RUN: ld.lld %t.so.o -shared -o %t.so
12# RUN: ld.lld %t.o %t.so -o %t.exe12# RUN: ld.lld %t.o %t.so -o %t.exe
13# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s13# RUN: llvm-readobj -r --mips-plt-got %t.exe | FileCheck %s
1414
15# CHECK: Relocations [15# CHECK: Relocations [
16# CHECK-NEXT: Section (7) .rel.dyn {16# CHECK-NEXT: Section (7) .rel.dyn {
deps/lld/test/ELF/mips-got-extsym.s+1-1
...@@ -9,7 +9,7 @@...@@ -9,7 +9,7 @@
9# RUN: ld.lld -shared %t.so.o -o %t.so9# RUN: ld.lld -shared %t.so.o -o %t.so
10# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o10# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
11# RUN: ld.lld %t.o %t.so -o %t.exe11# RUN: ld.lld %t.o %t.so -o %t.exe
12# RUN: llvm-readobj -dt -t -mips-plt-got %t.exe | FileCheck %s12# RUN: llvm-readobj --dyn-syms --symbols --mips-plt-got %t.exe | FileCheck %s
1313
14# CHECK: Symbols [14# CHECK: Symbols [
15# CHECK: Symbol {15# CHECK: Symbol {
deps/lld/test/ELF/mips-got-hilo.s+2-1
...@@ -4,9 +4,10 @@...@@ -4,9 +4,10 @@
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
5# RUN: ld.lld %t.o -shared -o %t.so5# RUN: ld.lld %t.o -shared -o %t.so
6# RUN: llvm-objdump -d %t.so | FileCheck %s6# RUN: llvm-objdump -d %t.so | FileCheck %s
7# RUN: llvm-readobj -r -mips-plt-got %t.so | FileCheck -check-prefix=GOT %s7# RUN: llvm-readobj -r --mips-plt-got %t.so | FileCheck -check-prefix=GOT %s
88
9# CHECK: Disassembly of section .text:9# CHECK: Disassembly of section .text:
10# CHECK-EMPTY:
10# CHECK-NEXT: foo:11# CHECK-NEXT: foo:
11# CHECK-NEXT: 10000: 3c 02 00 00 lui $2, 012# CHECK-NEXT: 10000: 3c 02 00 00 lui $2, 0
12# CHECK-NEXT: 10004: 8c 42 80 20 lw $2, -32736($2)13# CHECK-NEXT: 10004: 8c 42 80 20 lw $2, -32736($2)
deps/lld/test/ELF/mips-got-page-script.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: .text : { *(.text) } \7# RUN: .text : { *(.text) } \
8# RUN: .data 0x10000 : { *(.data) } }" > %t.script8# RUN: .data 0x10000 : { *(.data) } }" > %t.script
9# RUN: ld.lld -shared --script %t.script -o %t.so %t.o9# RUN: ld.lld -shared --script %t.script -o %t.so %t.o
10# RUN: llvm-readobj -t -mips-plt-got %t.so | FileCheck %s10# RUN: llvm-readobj --symbols --mips-plt-got %t.so | FileCheck %s
1111
12# CHECK: Name: foo112# CHECK: Name: foo1
13# CHECK-NEXT: Value: 0x1000013# CHECK-NEXT: Value: 0x10000
deps/lld/test/ELF/mips-got-page.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
55
6# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -o %t.o %s6# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux -o %t.o %s
7# RUN: ld.lld --section-start .rodata=0x27FFC -shared -o %t.so %t.o7# RUN: ld.lld --section-start .rodata=0x27FFC -shared -o %t.so %t.o
8# RUN: llvm-readobj -t -mips-plt-got %t.so | FileCheck %s8# RUN: llvm-readobj --symbols --mips-plt-got %t.so | FileCheck %s
99
10# CHECK: Name: bar10# CHECK: Name: bar
11# CHECK-NEXT: Value: 0x2800011# CHECK-NEXT: Value: 0x28000
deps/lld/test/ELF/mips-got-redundant.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
5# RUN: ld.lld %t.o -shared -o %t.so5# RUN: ld.lld %t.o -shared -o %t.so
6# RUN: llvm-readobj -mips-plt-got %t.so | FileCheck %s6# RUN: llvm-readobj --mips-plt-got %t.so | FileCheck %s
77
8# CHECK: Local entries [8# CHECK: Local entries [
9# CHECK-NEXT: Entry {9# CHECK-NEXT: Entry {
deps/lld/test/ELF/mips-got-relocs.s+41-74
...@@ -3,33 +3,25 @@...@@ -3,33 +3,25 @@
33
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-be.o
5# RUN: ld.lld %t-be.o -o %t-be.exe5# RUN: ld.lld %t-be.o -o %t-be.exe
6# RUN: llvm-objdump -section-headers -t %t-be.exe | FileCheck -check-prefix=EXE_SYM %s6# RUN: llvm-readobj --sections -r --symbols --mips-plt-got %t-be.exe \
7# RUN: llvm-objdump -s -section=.got %t-be.exe | FileCheck -check-prefix=EXE_GOT_BE %s7# RUN: | FileCheck -check-prefixes=ELF,EXE %s
8# RUN: llvm-objdump -d %t-be.exe | FileCheck -check-prefix=EXE_DIS_BE %s8# RUN: llvm-objdump -d %t-be.exe | FileCheck -check-prefix=DIS %s
9# RUN: llvm-readobj -relocations %t-be.exe | FileCheck -check-prefix=NORELOC %s
10# RUN: llvm-readobj -sections %t-be.exe | FileCheck -check-prefix=SHFLAGS %s
119
12# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o10# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux %s -o %t-el.o
13# RUN: ld.lld %t-el.o -o %t-el.exe11# RUN: ld.lld %t-el.o -o %t-el.exe
14# RUN: llvm-objdump -section-headers -t %t-el.exe | FileCheck -check-prefix=EXE_SYM %s12# RUN: llvm-readobj --sections -r --symbols --mips-plt-got %t-el.exe \
15# RUN: llvm-objdump -s -section=.got %t-el.exe | FileCheck -check-prefix=EXE_GOT_EL %s13# RUN: | FileCheck -check-prefixes=ELF,EXE %s
16# RUN: llvm-objdump -d %t-el.exe | FileCheck -check-prefix=EXE_DIS_EL %s14# RUN: llvm-objdump -d %t-el.exe | FileCheck -check-prefix=DIS %s
17# RUN: llvm-readobj -relocations %t-el.exe | FileCheck -check-prefix=NORELOC %s
18# RUN: llvm-readobj -sections %t-el.exe | FileCheck -check-prefix=SHFLAGS %s
1915
20# RUN: ld.lld -shared %t-be.o -o %t-be.so16# RUN: ld.lld -shared %t-be.o -o %t-be.so
21# RUN: llvm-objdump -section-headers -t %t-be.so | FileCheck -check-prefix=DSO_SYM %s17# RUN: llvm-readobj --sections -r --symbols --mips-plt-got %t-be.so \
22# RUN: llvm-objdump -s -section=.got %t-be.so | FileCheck -check-prefix=DSO_GOT_BE %s18# RUN: | FileCheck -check-prefixes=ELF,DSO %s
23# RUN: llvm-objdump -d %t-be.so | FileCheck -check-prefix=DSO_DIS_BE %s19# RUN: llvm-objdump -d %t-be.so | FileCheck -check-prefix=DIS %s
24# RUN: llvm-readobj -relocations %t-be.so | FileCheck -check-prefix=NORELOC %s
25# RUN: llvm-readobj -sections %t-be.so | FileCheck -check-prefix=SHFLAGS %s
2620
27# RUN: ld.lld -shared %t-el.o -o %t-el.so21# RUN: ld.lld -shared %t-el.o -o %t-el.so
28# RUN: llvm-objdump -section-headers -t %t-el.so | FileCheck -check-prefix=DSO_SYM %s22# RUN: llvm-readobj --sections -r --symbols --mips-plt-got %t-el.so \
29# RUN: llvm-objdump -s -section=.got %t-el.so | FileCheck -check-prefix=DSO_GOT_EL %s23# RUN: | FileCheck -check-prefixes=ELF,DSO %s
30# RUN: llvm-objdump -d %t-el.so | FileCheck -check-prefix=DSO_DIS_EL %s24# RUN: llvm-objdump -d %t-el.so | FileCheck -check-prefix=DIS %s
31# RUN: llvm-readobj -relocations %t-el.so | FileCheck -check-prefix=NORELOC %s
32# RUN: llvm-readobj -sections %t-el.so | FileCheck -check-prefix=SHFLAGS %s
3325
34 .text26 .text
35 .globl __start27 .globl __start
...@@ -43,57 +35,32 @@ __start:...@@ -43,57 +35,32 @@ __start:
43v1:35v1:
44 .word 036 .word 0
4537
46# EXE_SYM: Sections:38# ELF: Section {
47# EXE_SYM: .got 0000000c 0000000000030010 DATA39# ELF: Name: .got
48# EXE_SYM: SYMBOL TABLE:40# ELF: Flags [
49# EXE_SYM: 00038000 .got 00000000 .hidden _gp41# ELF-NEXT: SHF_ALLOC
50# ^-- .got + GP offset (0x7ff0)42# ELF-NEXT: SHF_MIPS_GPREL
51# EXE_SYM: 00030000 g O .data 00000004 v143# ELF-NEXT: SHF_WRITE
5244# ELF-NEXT: ]
5345#
54# EXE_GOT_BE: Contents of section .got:46# ELF: Relocations [
55# EXE_GOT_BE: 30010 00000000 80000000 0003000047# ELF-NEXT: ]
56# ^ ^ ^-- v1 (0x30000)48#
57# | +-- Module pointer (0x80000000)49# ELF: Symbol {
58# +-- Lazy resolver (0x0)50# ELF: Name: v1
5951# ELF-NEXT: Value: 0x[[V1:[0-9A-F]+]]
60# EXE_GOT_EL: Contents of section .got:52#
61# EXE_GOT_EL: 30010 00000000 00000080 0000030053# ELF: {{.*}} GOT {
62# ^ ^ ^-- v1 (0x30000)54# EXE-NEXT: Canonical gp value: 0x38000
63# | +-- Module pointer (0x80000000)55# DSO-NEXT: Canonical gp value: 0x28000
64# +-- Lazy resolver (0x0)56#
6557# ELF: Entry {
66# v1GotAddr (0x3000c) - _gp (0x37ff4) = -0x7fe8 => 0x8018 = 3279258# EXE: Address: 0x30018
67# EXE_DIS_BE: 20000: 3c 02 80 18 lui $2, 3279259# DSO: Address: 0x20018
68# EXE_DIS_EL: 20000: 18 80 02 3c lui $2, 3279260# ELF-NEXT: Access: -32744
6961# ELF-NEXT: Initial: 0x[[V1]]
70# DSO_SYM: Sections:62
71# DSO_SYM: .got 0000000c 0000000000020010 DATA63# "v1 GOT entry address" - _gp
72# DSO_SYM: SYMBOL TABLE:64# exe: 0x30018 - 0x38000 = -0x7fe8 == 0x8018 == 32792
73# DSO_SYM: 00028000 .got 00000000 .hidden _gp65# dso: 0x20018 - 0x28000 = -0x7fe8 == 0x8018 == 32792
74# ^-- .got + GP offset (0x7ff0)66# DIS: {{.*}} lui $2, 32792
75# DSO_SYM: 00020000 g O .data 00000004 v1
76
77# DSO_GOT_BE: Contents of section .got:
78# DSO_GOT_BE: 20010 00000000 80000000 00020000
79# ^ ^ ^-- v1 (0x20000)
80# | +-- Module pointer (0x80000000)
81# +-- Lazy resolver (0x0)
82
83# DSO_GOT_EL: Contents of section .got:
84# DSO_GOT_EL: 20010 00000000 00000080 00000200
85# ^ ^ ^-- v1 (0x20000)
86# | +-- Module pointer (0x80000000)
87# +-- Lazy resolver (0x0)
88
89# v1GotAddr (0x2000c) - _gp (0x27ff4) = -0x7fe8 => 0x8018 = 32792
90# DSO_DIS_BE: 10000: 3c 02 80 18 lui $2, 32792
91# DSO_DIS_EL: 10000: 18 80 02 3c lui $2, 32792
92
93# NORELOC: Relocations [
94# NORELOC-NEXT: ]
95
96# SHFLAGS: Name: .got
97# SHFLAGS-NEXT: Type: SHT_PROGBITS
98# SHFLAGS-NEXT: Flags [ (0x10000003)
99# ^-- SHF_MIPS_GPREL | SHF_ALLOC | SHF_WRITE
deps/lld/test/ELF/mips-got-script.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
5# RUN: echo "SECTIONS { .data : { *(.data.1); . += 0x10000; *(.data.2) } }" > %t.script5# RUN: echo "SECTIONS { .data : { *(.data.1); . += 0x10000; *(.data.2) } }" > %t.script
6# RUN: ld.lld %t.o -shared -o %t.so -T %t.script6# RUN: ld.lld %t.o -shared -o %t.so -T %t.script
7# RUN: llvm-readobj -mips-plt-got -dynamic-table %t.so | FileCheck %s7# RUN: llvm-readobj --mips-plt-got --dynamic-table %t.so | FileCheck %s
88
9# CHECK: 0x7000000A MIPS_LOCAL_GOTNO 49# CHECK: 0x7000000A MIPS_LOCAL_GOTNO 4
10# ^-- 2 * header + 2 local entries10# ^-- 2 * header + 2 local entries
deps/lld/test/ELF/mips-got-string.s+5-13
...@@ -3,20 +3,12 @@...@@ -3,20 +3,12 @@
33
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -o %t.o %s4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -o %t.o %s
5# RUN: ld.lld -shared -o %t.so %t.o5# RUN: ld.lld -shared -o %t.so %t.o
6# RUN: llvm-readobj -t -mips-plt-got %t.so | FileCheck %s6# RUN: llvm-readelf --mips-plt-got %t.so | FileCheck %s
77
8# CHECK: Symbol {8# CHECK: Local entries:
9# CHECK: Name: $.str9# CHECK-NEXT: Address Access Initial
10# CHECK-NEXT: Value: 0x1B110# CHECK-NEXT: {{[0-9a-f]+}} -32744(gp) 00000000
11# CHECK: }11# CHECK-NEXT: {{[0-9a-f]+}} -32740(gp) 00010000
12
13# CHECK: Local entries [
14# CHECK-NEXT: Entry {
15# CHECK-NEXT: Address:
16# CHECK-NEXT: Access: -32744
17# CHECK-NEXT: Initial: 0x0
18# CHECK: }
19# CHECK: ]
2012
21 .text13 .text
22 lw $t9, %got($.str)($gp)14 lw $t9, %got($.str)($gp)
deps/lld/test/ELF/mips-got-weak.s+2-2
...@@ -3,10 +3,10 @@...@@ -3,10 +3,10 @@
33
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
5# RUN: ld.lld %t.o -shared -o %t1.so5# RUN: ld.lld %t.o -shared -o %t1.so
6# RUN: llvm-readobj -r -dt -dynamic-table -mips-plt-got %t1.so \6# RUN: llvm-readobj -r --dyn-syms --dynamic-table --mips-plt-got %t1.so \
7# RUN: | FileCheck -check-prefixes=CHECK,NOSYM %s7# RUN: | FileCheck -check-prefixes=CHECK,NOSYM %s
8# RUN: ld.lld %t.o -shared -Bsymbolic -o %t2.so8# RUN: ld.lld %t.o -shared -Bsymbolic -o %t2.so
9# RUN: llvm-readobj -r -dt -dynamic-table -mips-plt-got %t2.so \9# RUN: llvm-readobj -r --dyn-syms --dynamic-table --mips-plt-got %t2.so \
10# RUN: | FileCheck -check-prefixes=CHECK,SYM %s10# RUN: | FileCheck -check-prefixes=CHECK,SYM %s
1111
12# CHECK: Relocations [12# CHECK: Relocations [
deps/lld/test/ELF/mips-got16-relocatable.s+2
...@@ -9,6 +9,7 @@...@@ -9,6 +9,7 @@
9# RUN: llvm-objdump -d %t.so | FileCheck -check-prefix=SO %s9# RUN: llvm-objdump -d %t.so | FileCheck -check-prefix=SO %s
1010
11# OBJ: Disassembly of section .text:11# OBJ: Disassembly of section .text:
12# OBJ-EMPTY:
12# OBJ-NEXT: .text:13# OBJ-NEXT: .text:
13# OBJ-NEXT: 0: 8f 99 00 00 lw $25, 0($gp)14# OBJ-NEXT: 0: 8f 99 00 00 lw $25, 0($gp)
14# OBJ-NEXT: 00000000: R_MIPS_GOT16 .data15# OBJ-NEXT: 00000000: R_MIPS_GOT16 .data
...@@ -20,6 +21,7 @@...@@ -20,6 +21,7 @@
20# OBJ-NEXT: 00000014: R_MIPS_LO16 .data21# OBJ-NEXT: 00000014: R_MIPS_LO16 .data
2122
22# SO: Disassembly of section .text:23# SO: Disassembly of section .text:
24# SO-EMPTY:
23# SO-NEXT: .text:25# SO-NEXT: .text:
24# SO-NEXT: 10000: 8f 99 80 18 lw $25, -32744($gp)26# SO-NEXT: 10000: 8f 99 80 18 lw $25, -32744($gp)
25# SO-NEXT: 10004: 27 24 00 00 addiu $4, $25, 027# SO-NEXT: 10004: 27 24 00 00 addiu $4, $25, 0
deps/lld/test/ELF/mips-got16.s+24-77
...@@ -4,9 +4,10 @@...@@ -4,9 +4,10 @@
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
5# RUN: ld.lld %t.o -shared -o %t.so5# RUN: ld.lld %t.o -shared -o %t.so
6# RUN: llvm-objdump -d -t %t.so | FileCheck %s6# RUN: llvm-objdump -d -t %t.so | FileCheck %s
7# RUN: llvm-readobj -r -mips-plt-got %t.so | FileCheck -check-prefix=GOT %s7# RUN: llvm-readelf -r --mips-plt-got %t.so | FileCheck -check-prefix=GOT %s
88
9# CHECK: Disassembly of section .text:9# CHECK: Disassembly of section .text:
10# CHECK-EMPTY:
10# CHECK-NEXT: __start:11# CHECK-NEXT: __start:
11# CHECK-NEXT: 10000: 8f 88 80 18 lw $8, -32744($gp)12# CHECK-NEXT: 10000: 8f 88 80 18 lw $8, -32744($gp)
12# CHECK-NEXT: 10004: 21 08 00 2c addi $8, $8, 4413# CHECK-NEXT: 10004: 21 08 00 2c addi $8, $8, 44
...@@ -24,83 +25,29 @@...@@ -24,83 +25,29 @@
24# CHECK: 00041008 .data 00000000 .hidden bar25# CHECK: 00041008 .data 00000000 .hidden bar
25# CHECK: 00000000 *UND* 00000000 foo26# CHECK: 00000000 *UND* 00000000 foo
2627
27# GOT: Relocations [28# GOT: There are no relocations in this file.
28# GOT-NEXT: ]
2929
30# GOT: Primary GOT {30# GOT: Local entries:
31# GOT-NEXT: Canonical gp value:31# GOT-NEXT: Address Access Initial
32# GOT-NEXT: Reserved entries [32# GOT-NEXT: 00041018 -32744(gp) 00010000
33# GOT-NEXT: Entry {33# ^-- (0x1002c + 0x8000) & ~0xffff
34# GOT-NEXT: Address:34# GOT-NEXT: 0004101c -32740(gp) 00020000
35# GOT-NEXT: Access: -3275235# ^-- redundant unused entry
36# GOT-NEXT: Initial: 0x036# GOT-NEXT: 00041020 -32736(gp) 00020000
37# GOT-NEXT: Purpose: Lazy resolver37# ^-- redundant unused entry
38# GOT-NEXT: }38# GOT-NEXT: 00041024 -32732(gp) 00030000
39# GOT-NEXT: Entry {39# ^-- (0x29000 + 0x8000) & ~0xffff
40# GOT-NEXT: Address:40# GOT-NEXT: 00041028 -32728(gp) 00040000
41# GOT-NEXT: Access: -3274841# ^-- (0x29000 + 0x10004 + 0x8000) & ~0xffff
42# GOT-NEXT: Initial: 0x8000000042# ^-- (0x29000 + 0x18004 + 0x8000) & ~0xffff
43# GOT-NEXT: Purpose: Module pointer (GNU extension)43# GOT-NEXT: 0004102c -32724(gp) 00050000
44# GOT-NEXT: }44# ^-- redundant unused entry
45# GOT-NEXT: ]45# GOT-NEXT: 00041030 -32720(gp) 00041008
46# GOT-NEXT: Local entries [46# ^-- 'bar' address
47# GOT-NEXT: Entry {47# GOT-EMPTY:
48# GOT-NEXT: Address:48# GOT-NEXT: Global entries:
49# GOT-NEXT: Access: -3274449# GOT-NEXT: Address Access Initial Sym.Val. Type Ndx Name
50# GOT-NEXT: Initial: 0x1000050# GOT-NEXT: 00041034 -32716(gp) 00000000 00000000 NOTYPE UND foo
51# ^-- (0x1002c + 0x8000) & ~0xffff
52# GOT-NEXT: }
53# GOT-NEXT: Entry {
54# GOT-NEXT: Address:
55# GOT-NEXT: Access: -32740
56# GOT-NEXT: Initial: 0x20000
57# ^-- redundant unused entry
58# GOT-NEXT: }
59# GOT-NEXT: Entry {
60# GOT-NEXT: Address:
61# GOT-NEXT: Access: -32736
62# GOT-NEXT: Initial: 0x20000
63# ^-- redundant unused entry
64# GOT-NEXT: }
65# GOT-NEXT: Entry {
66# GOT-NEXT: Address:
67# GOT-NEXT: Access: -32732
68# GOT-NEXT: Initial: 0x30000
69# ^-- (0x29000 + 0x8000) & ~0xffff
70# GOT-NEXT: }
71# GOT-NEXT: Entry {
72# GOT-NEXT: Address:
73# GOT-NEXT: Access: -32728
74# GOT-NEXT: Initial: 0x40000
75# ^-- (0x29000 + 0x10004 + 0x8000) & ~0xffff
76# ^-- (0x29000 + 0x18004 + 0x8000) & ~0xffff
77# GOT-NEXT: }
78# GOT-NEXT: Entry {
79# GOT-NEXT: Address:
80# GOT-NEXT: Access: -32724
81# GOT-NEXT: Initial: 0x50000
82# ^-- redundant unused entry
83# GOT-NEXT: }
84# GOT-NEXT: Entry {
85# GOT-NEXT: Address:
86# GOT-NEXT: Access: -32720
87# GOT-NEXT: Initial: 0x41008
88# ^-- 'bar' address
89# GOT-NEXT: }
90# GOT-NEXT: ]
91# GOT-NEXT: Global entries [
92# GOT-NEXT: Entry {
93# GOT-NEXT: Address:
94# GOT-NEXT: Access: -32716
95# GOT-NEXT: Initial: 0x0
96# GOT-NEXT: Value: 0x0
97# GOT-NEXT: Type: None
98# GOT-NEXT: Section: Undefined
99# GOT-NEXT: Name: foo
100# GOT-NEXT: }
101# GOT-NEXT: ]
102# GOT-NEXT: Number of TLS and multi-GOT entries: 0
103# GOT-NEXT: }
10451
105 .text52 .text
106 .globl __start53 .globl __start
deps/lld/test/ELF/mips-gp-disp.s+4-3
...@@ -4,11 +4,11 @@...@@ -4,11 +4,11 @@
44
5# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o5# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
6# RUN: ld.lld -shared -o %t.so %t.o %S/Inputs/mips-gp-disp.so6# RUN: ld.lld -shared -o %t.so %t.o %S/Inputs/mips-gp-disp.so
7# RUN: llvm-readobj -symbols %t.so | FileCheck -check-prefix=INT-SO %s7# RUN: llvm-readobj --symbols %t.so | FileCheck -check-prefix=INT-SO %s
8# RUN: llvm-readobj -symbols %S/Inputs/mips-gp-disp.so \8# RUN: llvm-readobj --symbols %S/Inputs/mips-gp-disp.so \
9# RUN: | FileCheck -check-prefix=EXT-SO %s9# RUN: | FileCheck -check-prefix=EXT-SO %s
10# RUN: llvm-objdump -d -t %t.so | FileCheck -check-prefix=DIS %s10# RUN: llvm-objdump -d -t %t.so | FileCheck -check-prefix=DIS %s
11# RUN: llvm-readobj -relocations %t.so | FileCheck -check-prefix=REL %s11# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=REL %s
1212
13# INT-SO: Name: _gp_disp13# INT-SO: Name: _gp_disp
14# INT-SO-NEXT: Value:14# INT-SO-NEXT: Value:
...@@ -19,6 +19,7 @@...@@ -19,6 +19,7 @@
19# EXT-SO-NEXT: Value: 0x2000019# EXT-SO-NEXT: Value: 0x20000
2020
21# DIS: Disassembly of section .text:21# DIS: Disassembly of section .text:
22# DIS-EMPTY:
22# DIS-NEXT: __start:23# DIS-NEXT: __start:
23# DIS-NEXT: 10000: 3c 08 00 01 lui $8, 124# DIS-NEXT: 10000: 3c 08 00 01 lui $8, 1
24# DIS-NEXT: 10004: 21 08 7f f0 addi $8, $8, 3275225# DIS-NEXT: 10004: 21 08 7f f0 addi $8, $8, 32752
deps/lld/test/ELF/mips-gp-local.s+1
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6# RUN: llvm-objdump -d -t %t.exe | FileCheck %s6# RUN: llvm-objdump -d -t %t.exe | FileCheck %s
77
8# CHECK: Disassembly of section .text:8# CHECK: Disassembly of section .text:
9# CHECK-EMPTY:
9# CHECK-NEXT: __start:10# CHECK-NEXT: __start:
10# CHECK-NEXT: 20000: 3c 08 00 03 lui $8, 311# CHECK-NEXT: 20000: 3c 08 00 03 lui $8, 3
11# CHECK-NEXT: 20004: 21 08 7f f0 addi $8, $8, 3275212# CHECK-NEXT: 20004: 21 08 7f f0 addi $8, $8, 32752
deps/lld/test/ELF/mips-gp-lowest.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: .sdata : { *(.sdata) } \7# RUN: .sdata : { *(.sdata) } \
8# RUN: .got : { *(.got) } }" > %t.rel.script8# RUN: .got : { *(.got) } }" > %t.rel.script
9# RUN: ld.lld %t.o --script %t.rel.script -shared -o %t.so9# RUN: ld.lld %t.o --script %t.rel.script -shared -o %t.so
10# RUN: llvm-readobj -s -t %t.so | FileCheck %s10# RUN: llvm-readobj -S --symbols %t.so | FileCheck %s
1111
12 .text12 .text
13 .global foo13 .global foo
deps/lld/test/ELF/mips-gprel-sec.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
5# RUN: ld.lld %t.o -shared -o %t.so5# RUN: ld.lld %t.o -shared -o %t.so
6# RUN: llvm-readobj -s %t.so | FileCheck %s6# RUN: llvm-readobj -S %t.so | FileCheck %s
77
8 .text8 .text
9 nop9 nop
deps/lld/test/ELF/mips-gprel32-relocs-gp0.s+2-2
...@@ -3,10 +3,10 @@...@@ -3,10 +3,10 @@
33
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
5# RUN: ld.lld -r -o %t-rel.o %t.o5# RUN: ld.lld -r -o %t-rel.o %t.o
6# RUN: llvm-readobj -mips-reginfo %t-rel.o | FileCheck --check-prefix=REL %s6# RUN: llvm-readobj --mips-reginfo %t-rel.o | FileCheck --check-prefix=REL %s
77
8# RUN: ld.lld -shared -o %t.so %S/Inputs/mips-gp0-non-zero.o8# RUN: ld.lld -shared -o %t.so %S/Inputs/mips-gp0-non-zero.o
9# RUN: llvm-readobj -mips-reginfo %t.so | FileCheck --check-prefix=DSO %s9# RUN: llvm-readobj --mips-reginfo %t.so | FileCheck --check-prefix=DSO %s
10# RUN: llvm-objdump -s -t %t.so | FileCheck --check-prefix=DUMP %s10# RUN: llvm-objdump -s -t %t.so | FileCheck --check-prefix=DUMP %s
1111
12# REL: GP: 0x012# REL: GP: 0x0
deps/lld/test/ELF/mips-hilo-gp-disp.s+2
...@@ -20,6 +20,7 @@ bar:...@@ -20,6 +20,7 @@ bar:
20 addi $t0,$t0,%lo(_gp_disp)20 addi $t0,$t0,%lo(_gp_disp)
2121
22# EXE: Disassembly of section .text:22# EXE: Disassembly of section .text:
23# EXE-EMPTY:
23# EXE-NEXT: __start:24# EXE-NEXT: __start:
24# EXE-NEXT: 20000: 3c 08 00 02 lui $8, 225# EXE-NEXT: 20000: 3c 08 00 02 lui $8, 2
25# ^-- %hi(0x47ff0-0x20000)26# ^-- %hi(0x47ff0-0x20000)
...@@ -37,6 +38,7 @@ bar:...@@ -37,6 +38,7 @@ bar:
37# EXE: 00020000 .text 00000000 __start38# EXE: 00020000 .text 00000000 __start
3839
39# SO: Disassembly of section .text:40# SO: Disassembly of section .text:
41# SO-EMPTY:
40# SO-NEXT: __start:42# SO-NEXT: __start:
41# SO-NEXT: 10000: 3c 08 00 02 lui $8, 243# SO-NEXT: 10000: 3c 08 00 02 lui $8, 2
42# ^-- %hi(0x28000-0x10000)44# ^-- %hi(0x28000-0x10000)
deps/lld/test/ELF/mips-hilo-hi-only.s+1
...@@ -16,6 +16,7 @@ _label:...@@ -16,6 +16,7 @@ _label:
16# WARN: can't find matching R_MIPS_LO16 relocation for R_MIPS_HI1616# WARN: can't find matching R_MIPS_LO16 relocation for R_MIPS_HI16
1717
18# CHECK: Disassembly of section .text:18# CHECK: Disassembly of section .text:
19# CHECK-EMPTY:
19# CHECK-NEXT: __start:20# CHECK-NEXT: __start:
20# CHECK-NEXT: 20000: 3c 08 00 03 lui $8, 321# CHECK-NEXT: 20000: 3c 08 00 03 lui $8, 3
21# ^-- %hi(__start) w/o addend22# ^-- %hi(__start) w/o addend
deps/lld/test/ELF/mips-hilo.s+1
...@@ -30,6 +30,7 @@ g1:...@@ -30,6 +30,7 @@ g1:
30 .word 030 .word 0
3131
32# CHECK: Disassembly of section .text:32# CHECK: Disassembly of section .text:
33# CHECK-EMPTY:
33# CHECK-NEXT: __start:34# CHECK-NEXT: __start:
34# CHECK-NEXT: 20000: 3c 08 00 02 lui $8, 235# CHECK-NEXT: 20000: 3c 08 00 02 lui $8, 2
35# ^-- %hi(__start+4)36# ^-- %hi(__start+4)
deps/lld/test/ELF/mips-jalr.test+12-13
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: yaml2obj %s -o %t.o3# RUN: yaml2obj %s -o %t.o
4# RUN: ld.lld %t.o -o %t.so -shared4# RUN: ld.lld %t.o -o %t.so -shared
5# RUN: llvm-objdump -d %t.so | FileCheck %s5# RUN: llvm-objdump -d %t.so | FileCheck %s
6# RUN: llvm-readobj -relocations %t.so | FileCheck -check-prefix=REL %s6# RUN: llvm-readobj -r %t.so | FileCheck -check-prefix=REL %s
77
8# REQUIRES: mips8# REQUIRES: mips
99
...@@ -38,15 +38,14 @@ Sections:...@@ -38,15 +38,14 @@ Sections:
38 Type: R_MIPS_JALR38 Type: R_MIPS_JALR
3939
40Symbols:40Symbols:
41 Local:41 - Name: T1
42 - Name: T142 Type: STT_FUNC
43 Type: STT_FUNC43 Section: .text
44 Section: .text44 Value: 0
45 Value: 045 Size: 4
46 Size: 446 - Name: __start
47 Global:47 Type: STT_FUNC
48 - Name: __start48 Section: .text
49 Type: STT_FUNC49 Value: 0
50 Section: .text50 Size: 4
51 Value: 051 Binding: STB_GLOBAL
52 Size: 4
deps/lld/test/ELF/mips-merge-abiflags.s+2-2
...@@ -4,8 +4,8 @@...@@ -4,8 +4,8 @@
44
5# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-freebsd %s -o %t.o5# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-freebsd %s -o %t.o
6# RUN: ld.lld %t.o %p/Inputs/mips-concatenated-abiflags.o -o %t.exe6# RUN: ld.lld %t.o %p/Inputs/mips-concatenated-abiflags.o -o %t.exe
7# RUN: llvm-readobj -sections -mips-abi-flags %t.exe | FileCheck %s7# RUN: llvm-readobj --sections --mips-abi-flags %t.exe | FileCheck %s
8# RUN: llvm-readobj -sections -mips-abi-flags \8# RUN: llvm-readobj --sections --mips-abi-flags \
9# RUN: %p/Inputs/mips-concatenated-abiflags.o | \9# RUN: %p/Inputs/mips-concatenated-abiflags.o | \
10# RUN: FileCheck --check-prefix=INPUT-OBJECT %s10# RUN: FileCheck --check-prefix=INPUT-OBJECT %s
1111
deps/lld/test/ELF/mips-mgot.s+21-21
...@@ -8,14 +8,14 @@...@@ -8,14 +8,14 @@
8# RUN: %p/Inputs/mips-mgot-2.s -o %t2.o8# RUN: %p/Inputs/mips-mgot-2.s -o %t2.o
9# RUN: ld.lld -shared -mips-got-size 52 %t0.o %t1.o %t2.o -o %t.so9# RUN: ld.lld -shared -mips-got-size 52 %t0.o %t1.o %t2.o -o %t.so
10# RUN: llvm-objdump -s -section=.got -t %t.so | FileCheck %s10# RUN: llvm-objdump -s -section=.got -t %t.so | FileCheck %s
11# RUN: llvm-readobj -r -dt -mips-plt-got %t.so | FileCheck -check-prefix=GOT %s11# RUN: llvm-readobj -r --dyn-syms --mips-plt-got %t.so | FileCheck -check-prefix=GOT %s
1212
13# CHECK: Contents of section .got:13# CHECK: Contents of section .got:
14# CHECK-NEXT: 60000 00000000 80000000 00010000 0001003014# CHECK-NEXT: 70000 00000000 80000000 00010000 00010030
15# CHECK-NEXT: 60010 00000000 00000004 00020000 0003000015# CHECK-NEXT: 70010 00000000 00000004 00030000 00040000
16# CHECK-NEXT: 60020 00040000 00050000 00060000 0007000016# CHECK-NEXT: 70020 00050000 00060000 00070000 00080000
17# CHECK-NEXT: 60030 00000000 00000000 00000000 0000000017# CHECK-NEXT: 70030 00000000 00000000 00000000 00000000
18# CHECK-NEXT: 60040 00000000 00000000 0000000018# CHECK-NEXT: 70040 00000000 00000000 00000000
1919
20# CHECK: SYMBOL TABLE:20# CHECK: SYMBOL TABLE:
21# CHECK: 00000000 l O .tdata 00000000 loc021# CHECK: 00000000 l O .tdata 00000000 loc0
...@@ -28,20 +28,20 @@...@@ -28,20 +28,20 @@
2828
29# GOT: Relocations [29# GOT: Relocations [
30# GOT-NEXT: Section (7) .rel.dyn {30# GOT-NEXT: Section (7) .rel.dyn {
31# GOT-NEXT: 0x60018 R_MIPS_REL32 - 0x031# GOT-NEXT: 0x70018 R_MIPS_REL32 - 0x0
32# GOT-NEXT: 0x6001C R_MIPS_REL32 - 0x032# GOT-NEXT: 0x7001C R_MIPS_REL32 - 0x0
33# GOT-NEXT: 0x60020 R_MIPS_REL32 - 0x033# GOT-NEXT: 0x70020 R_MIPS_REL32 - 0x0
34# GOT-NEXT: 0x60024 R_MIPS_REL32 - 0x034# GOT-NEXT: 0x70024 R_MIPS_REL32 - 0x0
35# GOT-NEXT: 0x60028 R_MIPS_REL32 - 0x035# GOT-NEXT: 0x70028 R_MIPS_REL32 - 0x0
36# GOT-NEXT: 0x6002C R_MIPS_REL32 - 0x036# GOT-NEXT: 0x7002C R_MIPS_REL32 - 0x0
37# GOT-NEXT: 0x60030 R_MIPS_REL32 foo0 0x037# GOT-NEXT: 0x70030 R_MIPS_REL32 foo0 0x0
38# GOT-NEXT: 0x60034 R_MIPS_REL32 foo2 0x038# GOT-NEXT: 0x70034 R_MIPS_REL32 foo2 0x0
39# GOT-NEXT: 0x60044 R_MIPS_TLS_DTPMOD32 - 0x039# GOT-NEXT: 0x70044 R_MIPS_TLS_DTPMOD32 - 0x0
40# GOT-NEXT: 0x60010 R_MIPS_TLS_TPREL32 tls0 0x040# GOT-NEXT: 0x70010 R_MIPS_TLS_TPREL32 tls0 0x0
41# GOT-NEXT: 0x60038 R_MIPS_TLS_TPREL32 tls0 0x041# GOT-NEXT: 0x70038 R_MIPS_TLS_TPREL32 tls0 0x0
42# GOT-NEXT: 0x6003C R_MIPS_TLS_DTPMOD32 tls0 0x042# GOT-NEXT: 0x7003C R_MIPS_TLS_DTPMOD32 tls0 0x0
43# GOT-NEXT: 0x60040 R_MIPS_TLS_DTPREL32 tls0 0x043# GOT-NEXT: 0x70040 R_MIPS_TLS_DTPREL32 tls0 0x0
44# GOT-NEXT: 0x60014 R_MIPS_TLS_TPREL32 tls1 0x044# GOT-NEXT: 0x70014 R_MIPS_TLS_TPREL32 tls1 0x0
45# GOT-NEXT: }45# GOT-NEXT: }
46# GOT-NEXT: ]46# GOT-NEXT: ]
4747
...@@ -57,7 +57,7 @@...@@ -57,7 +57,7 @@
57# GOT-NEXT: ]57# GOT-NEXT: ]
5858
59# GOT: Primary GOT {59# GOT: Primary GOT {
60# GOT-NEXT: Canonical gp value: 0x67FF060# GOT-NEXT: Canonical gp value: 0x77FF0
61# GOT-NEXT: Reserved entries [61# GOT-NEXT: Reserved entries [
62# GOT-NEXT: Entry {62# GOT-NEXT: Entry {
63# GOT-NEXT: Address:63# GOT-NEXT: Address:
deps/lld/test/ELF/mips-micro-bad-cross-calls.s created+15
...@@ -0,0 +1,15 @@
1# REQUIRES: mips
2# Check error message for invalid cross-mode branch instructions.
3
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
5# RUN: %S/Inputs/mips-dynamic.s -o %t2.o
6# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t1.o
7# RUN: not ld.lld -o %t.exe %t1.o %t2.o 2>&1 | FileCheck %s
8
9# CHECK: (.text+0x0): unsupported jump/branch instruction between ISA modes referenced by R_MICROMIPS_PC10_S1 relocation
10
11 .text
12 .set micromips
13 .global __start
14__start:
15 b16 foo0
deps/lld/test/ELF/mips-micro-cross-calls.s created+44
...@@ -0,0 +1,44 @@
1# REQUIRES: mips
2# Check various cases of microMIPS - regular code cross-calls.
3
4# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
5# RUN: -mattr=micromips %s -o %t-eb.o
6# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
7# RUN: -position-independent -mattr=micromips \
8# RUN: %S/Inputs/mips-micro.s -o %t-eb-pic.o
9# RUN: ld.lld -o %t-eb.exe %t-eb.o %t-eb-pic.o
10# RUN: llvm-objdump -d -mattr=-micromips %t-eb.exe \
11# RUN: | FileCheck --check-prefix=REG %s
12# RUN: llvm-objdump -d -mattr=+micromips %t-eb.exe \
13# RUN: | FileCheck --check-prefix=MICRO %s
14
15# REG: __start:
16# REG-NEXT: 20000: 74 00 80 04 jalx 131088 <micro>
17# REG-NEXT: 20004: 00 00 00 00 nop
18# REG-NEXT: 20008: 74 00 80 08 jalx 131104 <__microLA25Thunk_foo>
19
20# REG: __LA25Thunk_bar:
21# REG-NEXT: 20030: 3c 19 00 02 lui $25, 2
22# REG-NEXT: 20034: 08 00 80 11 j 131140 <bar>
23
24# MICRO: micro:
25# MICRO-NEXT: 20010: f0 00 80 00 jalx 65536
26# MICRO-NEXT: 20014: 00 00 00 00 nop
27# MICRO-NEXT: 20018: f0 00 80 0c jalx 65560
28
29# MICRO: __microLA25Thunk_foo:
30# MICRO-NEXT: 20020: 41 b9 00 02 lui $25, 2
31# MICRO-NEXT: 20024: d4 01 00 20 j 131136
32
33 .text
34 .set nomicromips
35 .global __start
36__start:
37 jal micro
38 jal foo
39
40 .set micromips
41 .global micro
42micro:
43 jal __start
44 jal bar
deps/lld/test/ELF/mips-micro-got.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: %S/Inputs/mips-dynamic.s -o %t2.o7# RUN: %S/Inputs/mips-dynamic.s -o %t2.o
8# RUN: ld.lld %t2.o -shared -o %t.so8# RUN: ld.lld %t2.o -shared -o %t.so
9# RUN: ld.lld %t1.o %t.so -o %t.exe9# RUN: ld.lld %t1.o %t.so -o %t.exe
10# RUN: llvm-readobj -mips-plt-got %t.exe | FileCheck %s10# RUN: llvm-readobj --mips-plt-got %t.exe | FileCheck %s
1111
12# CHECK: Local entries [12# CHECK: Local entries [
13# CHECK-NEXT: Entry {13# CHECK-NEXT: Entry {
deps/lld/test/ELF/mips-micro-jal.s+7-2
...@@ -8,7 +8,7 @@...@@ -8,7 +8,7 @@
8# RUN: -mattr=micromips %s -o %t2eb.o8# RUN: -mattr=micromips %s -o %t2eb.o
9# RUN: ld.lld -o %teb.exe %t2eb.o %teb.so9# RUN: ld.lld -o %teb.exe %t2eb.o %teb.so
10# RUN: llvm-objdump -d -mattr=micromips %teb.exe | FileCheck --check-prefix=EB %s10# RUN: llvm-objdump -d -mattr=micromips %teb.exe | FileCheck --check-prefix=EB %s
11# RUN: llvm-readobj -mips-plt-got %teb.exe | FileCheck --check-prefix=PLT %s11# RUN: llvm-readobj --mips-plt-got %teb.exe | FileCheck --check-prefix=PLT %s
1212
13# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \13# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \
14# RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1el.o14# RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1el.o
...@@ -17,7 +17,7 @@...@@ -17,7 +17,7 @@
17# RUN: -mattr=micromips %s -o %t2el.o17# RUN: -mattr=micromips %s -o %t2el.o
18# RUN: ld.lld -o %tel.exe %t2el.o %tel.so18# RUN: ld.lld -o %tel.exe %t2el.o %tel.so
19# RUN: llvm-objdump -d -mattr=micromips %tel.exe | FileCheck --check-prefix=EL %s19# RUN: llvm-objdump -d -mattr=micromips %tel.exe | FileCheck --check-prefix=EL %s
20# RUN: llvm-readobj -mips-plt-got %tel.exe | FileCheck --check-prefix=PLT %s20# RUN: llvm-readobj --mips-plt-got %tel.exe | FileCheck --check-prefix=PLT %s
2121
22# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \22# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
23# RUN: -mattr=micromips -mcpu=mips32r6 %S/Inputs/mips-micro.s -o %t1eb.o23# RUN: -mattr=micromips -mcpu=mips32r6 %S/Inputs/mips-micro.s -o %t1eb.o
...@@ -47,6 +47,7 @@...@@ -47,6 +47,7 @@
47# RUN: | FileCheck --check-prefix=MIXED %s47# RUN: | FileCheck --check-prefix=MIXED %s
4848
49# EB: Disassembly of section .plt:49# EB: Disassembly of section .plt:
50# EB-EMPTY:
50# EB-NEXT: .plt:51# EB-NEXT: .plt:
51# EB-NEXT: 20010: 79 80 3f fd addiupc $3, 6552452# EB-NEXT: 20010: 79 80 3f fd addiupc $3, 65524
52# EB-NEXT: 20014: ff 23 00 00 lw $25, 0($3)53# EB-NEXT: 20014: ff 23 00 00 lw $25, 0($3)
...@@ -64,6 +65,7 @@...@@ -64,6 +65,7 @@
64# EB-NEXT: 2003a: 0f 02 move $24, $265# EB-NEXT: 2003a: 0f 02 move $24, $2
6566
66# EL: Disassembly of section .plt:67# EL: Disassembly of section .plt:
68# EL-EMPTY:
67# EL-NEXT: .plt:69# EL-NEXT: .plt:
68# EL-NEXT: 20010: 80 79 fd 3f addiupc $3, 6552470# EL-NEXT: 20010: 80 79 fd 3f addiupc $3, 65524
69# EL-NEXT: 20014: 23 ff 00 00 lw $25, 0($3)71# EL-NEXT: 20014: 23 ff 00 00 lw $25, 0($3)
...@@ -81,6 +83,7 @@...@@ -81,6 +83,7 @@
81# EL-NEXT: 2003a: 02 0f move $24, $283# EL-NEXT: 2003a: 02 0f move $24, $2
8284
83# EBR6: Disassembly of section .plt:85# EBR6: Disassembly of section .plt:
86# EBR6-EMPTY:
84# EBR6-NEXT: .plt:87# EBR6-NEXT: .plt:
85# EBR6-NEXT: 20010: 78 60 3f fd lapc $3, 6552488# EBR6-NEXT: 20010: 78 60 3f fd lapc $3, 65524
86# EBR6-NEXT: 20014: ff 23 00 00 lw $25, 0($3)89# EBR6-NEXT: 20014: ff 23 00 00 lw $25, 0($3)
...@@ -97,6 +100,7 @@...@@ -97,6 +100,7 @@
97# EBR6-NEXT: 2003a: 47 23 jrc16 $25100# EBR6-NEXT: 2003a: 47 23 jrc16 $25
98101
99# ELR6: Disassembly of section .plt:102# ELR6: Disassembly of section .plt:
103# ELR6-EMPTY:
100# ELR6-NEXT: .plt:104# ELR6-NEXT: .plt:
101# ELR6-NEXT: 20010: 60 78 fd 3f lapc $3, 65524105# ELR6-NEXT: 20010: 60 78 fd 3f lapc $3, 65524
102# ELR6-NEXT: 20014: 23 ff 00 00 lw $25, 0($3)106# ELR6-NEXT: 20014: 23 ff 00 00 lw $25, 0($3)
...@@ -113,6 +117,7 @@...@@ -113,6 +117,7 @@
113# ELR6-NEXT: 2003a: 23 47 jrc16 $25117# ELR6-NEXT: 2003a: 23 47 jrc16 $25
114118
115# MIXED: Disassembly of section .plt:119# MIXED: Disassembly of section .plt:
120# MIXED-EMPTY:
116# MIXED-NEXT: .plt:121# MIXED-NEXT: .plt:
117# MIXED-NEXT: 20020: 79 80 3f f9 addiupc $3, 65508122# MIXED-NEXT: 20020: 79 80 3f f9 addiupc $3, 65508
118# MIXED-NEXT: 20024: ff 23 00 00 lw $25, 0($3)123# MIXED-NEXT: 20024: ff 23 00 00 lw $25, 0($3)
deps/lld/test/ELF/mips-micro-plt.s+3-3
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \7# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
8# RUN: -mattr=micromips %s -o %t-exe.o8# RUN: -mattr=micromips %s -o %t-exe.o
9# RUN: ld.lld %t-exe.o %t.so -o %t.exe9# RUN: ld.lld %t-exe.o %t.so -o %t.exe
10# RUN: llvm-readobj -t -dt -mips-plt-got %t.exe | FileCheck %s10# RUN: llvm-readobj --symbols --dyn-syms --mips-plt-got %t.exe | FileCheck %s
11# RUN: llvm-objdump -d -mattr=micromips %t.exe | FileCheck --check-prefix=ASM %s11# RUN: llvm-objdump -d -mattr=micromips %t.exe | FileCheck --check-prefix=ASM %s
1212
13# CHECK: Symbols [13# CHECK: Symbols [
...@@ -87,9 +87,9 @@...@@ -87,9 +87,9 @@
8787
88# ASM: __start:88# ASM: __start:
89# ASM-NEXT: 20000: fd 1c 80 18 lw $8, -32744($gp)89# ASM-NEXT: 20000: fd 1c 80 18 lw $8, -32744($gp)
90# ASM-NEXT: 20004: 11 08 00 10 addi $8, $8, 1690# ASM-NEXT: 20004: 11 08 00 11 addi $8, $8, 17
91# ASM-NEXT: 20008: 41 a8 00 02 lui $8, 291# ASM-NEXT: 20008: 41 a8 00 02 lui $8, 2
92# ASM-NEXT: 2000c: 11 08 00 40 addi $8, $8, 6492# ASM-NEXT: 2000c: 11 08 00 41 addi $8, $8, 65
93#93#
94# ASM: foo:94# ASM: foo:
95# ASM-NEXT: 20010: f4 01 00 20 jal 13113695# ASM-NEXT: 20010: f4 01 00 20 jal 131136
deps/lld/test/ELF/mips-micro-relocs.s+30-7
...@@ -6,20 +6,22 @@...@@ -6,20 +6,22 @@
6# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \6# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
7# RUN: -mattr=micromips %s -o %t2eb.o7# RUN: -mattr=micromips %s -o %t2eb.o
8# RUN: ld.lld -o %teb.exe %t1eb.o %t2eb.o8# RUN: ld.lld -o %teb.exe %t1eb.o %t2eb.o
9# RUN: llvm-objdump -d -t -mattr=micromips %teb.exe \9# RUN: llvm-objdump -d -t -s -mattr=micromips %teb.exe \
10# RUN: | FileCheck --check-prefixes=EB,SYM %s10# RUN: | FileCheck --check-prefixes=EB,SYM %s
11# RUN: llvm-readobj -h %teb.exe | FileCheck --check-prefix=ELF %s
1112
12# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \13# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \
13# RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1el.o14# RUN: -mattr=micromips %S/Inputs/mips-micro.s -o %t1el.o
14# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \15# RUN: llvm-mc -filetype=obj -triple=mipsel-unknown-linux \
15# RUN: -mattr=micromips %s -o %t2el.o16# RUN: -mattr=micromips %s -o %t2el.o
16# RUN: ld.lld -o %tel.exe %t1el.o %t2el.o17# RUN: ld.lld -o %tel.exe %t1el.o %t2el.o
17# RUN: llvm-objdump -d -t -mattr=micromips %tel.exe \18# RUN: llvm-objdump -d -t -s -mattr=micromips %tel.exe \
18# RUN: | FileCheck --check-prefixes=EL,SYM %s19# RUN: | FileCheck --check-prefixes=EL,SYM %s
20# RUN: llvm-readobj -h %tel.exe | FileCheck --check-prefix=ELF %s
1921
20# EB: __start:22# EB: __start:
21# EB-NEXT: 20010: 41 a3 00 01 lui $3, 123# EB-NEXT: 20010: 41 a3 00 01 lui $3, 1
22# EB-NEXT: 20014: 30 63 7f df addiu $3, $3, 3273524# EB-NEXT: 20014: 30 63 7f ef addiu $3, $3, 32751
23# EB-NEXT: 20018: fc 7c 80 18 lw $3, -32744($gp)25# EB-NEXT: 20018: fc 7c 80 18 lw $3, -32744($gp)
24# EB-NEXT: 2001c: fc 63 80 18 lw $3, -32744($3)26# EB-NEXT: 2001c: fc 63 80 18 lw $3, -32744($3)
25# EB-NEXT: 20020: 8f 70 beqz16 $6, -3227# EB-NEXT: 20020: 8f 70 beqz16 $6, -32
...@@ -28,9 +30,15 @@...@@ -28,9 +30,15 @@
28# EB-NEXT: 20028: 00 00 00 00 nop30# EB-NEXT: 20028: 00 00 00 00 nop
29# EB-NEXT: 2002c: 94 00 ff e8 b -4431# EB-NEXT: 2002c: 94 00 ff e8 b -44
3032
33# EB: Contents of section .data:
34# EB-NEXT: 30000 fffe8011
35
36# EB: Contents of section .debug_info
37# EB-NEXT: 0000 00020011
38
31# EL: __start:39# EL: __start:
32# EL-NEXT: 20010: a3 41 01 00 lui $3, 140# EL-NEXT: 20010: a3 41 01 00 lui $3, 1
33# EL-NEXT: 20014: 63 30 df 7f addiu $3, $3, 3273541# EL-NEXT: 20014: 63 30 ef 7f addiu $3, $3, 32751
34# EL-NEXT: 20018: 7c fc 18 80 lw $3, -32744($gp)42# EL-NEXT: 20018: 7c fc 18 80 lw $3, -32744($gp)
35# EL-NEXT: 2001c: 63 fc 18 80 lw $3, -32744($3)43# EL-NEXT: 2001c: 63 fc 18 80 lw $3, -32744($3)
36# EL-NEXT: 20020: 70 8f beqz16 $6, -3244# EL-NEXT: 20020: 70 8f beqz16 $6, -32
...@@ -39,9 +47,18 @@...@@ -39,9 +47,18 @@
39# EL-NEXT: 20028: 00 00 00 00 nop47# EL-NEXT: 20028: 00 00 00 00 nop
40# EL-NEXT: 2002c: 00 94 e8 ff b -4448# EL-NEXT: 2002c: 00 94 e8 ff b -44
4149
42# SYM: 00037ff0 .got 00000000 .hidden _gp50# EL: Contents of section .data:
43# SYM: 00020000 g F .text 00000000 foo51# EL-NEXT: 30000 1180feff
44# SYM: 00020010 .text 00000000 __start52
53# EL: Contents of section .debug_info
54# EL-NEXT: 0000 11000200
55
56# SYM: 00038000 .got 00000000 .hidden _gp
57# SYM: 00020000 g F .text 00000000 0x80 foo
58# SYM: 00020010 .text 00000000 0x80 __start
59
60# ELF: ElfHeader {
61# ELF: Entry: 0x20011
4562
46 .text63 .text
47 .set micromips64 .set micromips
...@@ -56,3 +73,9 @@ __start:...@@ -56,3 +73,9 @@ __start:
56 beqz16 $6, foo # R_MICROMIPS_PC7_S173 beqz16 $6, foo # R_MICROMIPS_PC7_S1
57 b16 foo # R_MICROMIPS_PC10_S174 b16 foo # R_MICROMIPS_PC10_S1
58 b foo # R_MICROMIPS_PC16_S175 b foo # R_MICROMIPS_PC16_S1
76
77 .data
78 .gpword __start # R_MIPS_GPREL32
79
80 .section .debug_info
81 .word __start # R_MIPS_32
deps/lld/test/ELF/mips-micror6-relocs.s+2-2
...@@ -26,8 +26,8 @@...@@ -26,8 +26,8 @@
26# EL-NEXT: 20014: 7f 80 f6 ff beqzc $3, -3626# EL-NEXT: 20014: 7f 80 f6 ff beqzc $3, -36
27# EL-NEXT: 20018: ff b7 f4 ff balc -24 <foo>27# EL-NEXT: 20018: ff b7 f4 ff balc -24 <foo>
2828
29# SYM: 00020000 g F .text 00000000 foo29# SYM: 00020000 g F .text 00000000 0x80 foo
30# SYM: 00020010 .text 00000000 __start30# SYM: 00020010 .text 00000000 0x80 __start
3131
32 .text32 .text
33 .set micromips33 .set micromips
deps/lld/test/ELF/mips-n32-rels.s+1
...@@ -24,6 +24,7 @@ loc:...@@ -24,6 +24,7 @@ loc:
24 .gpword(loc) # R_MIPS_GPREL3224 .gpword(loc) # R_MIPS_GPREL32
2525
26# CHECK: Disassembly of section .text:26# CHECK: Disassembly of section .text:
27# CHECK-EMPTY:
27# CHECK-NEXT: __start:28# CHECK-NEXT: __start:
28# CHECK-NEXT: 20000: 3c 1c 00 01 lui $gp, 129# CHECK-NEXT: 20000: 3c 1c 00 01 lui $gp, 1
29# ^-- 0x20000 - 0x37ff030# ^-- 0x20000 - 0x37ff0
deps/lld/test/ELF/mips-non-zero-gp0.s+2-2
...@@ -34,11 +34,11 @@...@@ -34,11 +34,11 @@
34# lui $gp,%hi(%neg(%gp_rel(foo)))34# lui $gp,%hi(%neg(%gp_rel(foo)))
3535
36# RUN: ld.lld -r -o %t-32.r %S/Inputs/mips-gp0-non-zero.o36# RUN: ld.lld -r -o %t-32.r %S/Inputs/mips-gp0-non-zero.o
37# RUN: llvm-readobj -mips-reginfo %t-32.r | FileCheck --check-prefix=GPVAL %s37# RUN: llvm-readobj --mips-reginfo %t-32.r | FileCheck --check-prefix=GPVAL %s
38# RUN: llvm-objdump -s %t-32.r | FileCheck --check-prefix=ADDEND32 %s38# RUN: llvm-objdump -s %t-32.r | FileCheck --check-prefix=ADDEND32 %s
3939
40# RUN: ld.lld -r -o %t-64.r %S/Inputs/mips-n64-gp0-non-zero.o40# RUN: ld.lld -r -o %t-64.r %S/Inputs/mips-n64-gp0-non-zero.o
41# RUN: llvm-readobj -mips-options %t-64.r | FileCheck --check-prefix=GPVAL %s41# RUN: llvm-readobj --mips-options %t-64.r | FileCheck --check-prefix=GPVAL %s
42# RUN: llvm-readobj -r %S/Inputs/mips-n64-gp0-non-zero.o %t-64.r \42# RUN: llvm-readobj -r %S/Inputs/mips-n64-gp0-non-zero.o %t-64.r \
43# RUN: | FileCheck --check-prefix=ADDEND64 %s43# RUN: | FileCheck --check-prefix=ADDEND64 %s
4444
deps/lld/test/ELF/mips-npic-call-pic-os.s+5
...@@ -14,6 +14,7 @@...@@ -14,6 +14,7 @@
14# RUN: llvm-objdump -d %t.exe | FileCheck %s14# RUN: llvm-objdump -d %t.exe | FileCheck %s
1515
16# CHECK: Disassembly of section .text:16# CHECK: Disassembly of section .text:
17# CHECK-EMPTY:
17# CHECK-NEXT: __LA25Thunk_foo1a:18# CHECK-NEXT: __LA25Thunk_foo1a:
18# CHECK-NEXT: 20000: 3c 19 00 02 lui $25, 219# CHECK-NEXT: 20000: 3c 19 00 02 lui $25, 2
19# CHECK-NEXT: 20004: 08 00 80 08 j 131104 <foo1a>20# CHECK-NEXT: 20004: 08 00 80 08 j 131104 <foo1a>
...@@ -52,7 +53,9 @@...@@ -52,7 +53,9 @@
5253
53# CHECK: fnpic:54# CHECK: fnpic:
54# CHECK-NEXT: 20070: 00 00 00 00 nop55# CHECK-NEXT: 20070: 00 00 00 00 nop
56# CHECK-EMPTY:
55# CHECK-NEXT: Disassembly of section differentos:57# CHECK-NEXT: Disassembly of section differentos:
58# CHECK-EMPTY:
56# CHECK-NEXT: __start:59# CHECK-NEXT: __start:
57# CHECK-NEXT: 20074: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a>60# CHECK-NEXT: 20074: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a>
58# CHECK-NEXT: 20078: 00 00 00 00 nop61# CHECK-NEXT: 20078: 00 00 00 00 nop
...@@ -74,6 +77,7 @@...@@ -74,6 +77,7 @@
74# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=REVERSE %s77# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=REVERSE %s
7578
76# REVERSE: Disassembly of section .text:79# REVERSE: Disassembly of section .text:
80# REVERSE-EMPTY:
77# REVERSE-NEXT: __LA25Thunk_foo1a:81# REVERSE-NEXT: __LA25Thunk_foo1a:
78# REVERSE-NEXT: 20000: 3c 19 00 02 lui $25, 282# REVERSE-NEXT: 20000: 3c 19 00 02 lui $25, 2
79# REVERSE-NEXT: 20004: 08 00 80 08 j 131104 <foo1a>83# REVERSE-NEXT: 20004: 08 00 80 08 j 131104 <foo1a>
...@@ -114,6 +118,7 @@...@@ -114,6 +118,7 @@
114# REVERSE-NEXT: 20070: 00 00 00 00 nop118# REVERSE-NEXT: 20070: 00 00 00 00 nop
115119
116# REVERSE: Disassembly of section differentos:120# REVERSE: Disassembly of section differentos:
121# REVERSE-EMPTY:
117# REVERSE-NEXT: __start:122# REVERSE-NEXT: __start:
118# REVERSE-NEXT: 20074: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a>123# REVERSE-NEXT: 20074: 0c 00 80 00 jal 131072 <__LA25Thunk_foo1a>
119# REVERSE-NEXT: 20078: 00 00 00 00 nop124# REVERSE-NEXT: 20078: 00 00 00 00 nop
deps/lld/test/ELF/mips-npic-call-pic-script.s+5
...@@ -14,6 +14,7 @@...@@ -14,6 +14,7 @@
14# RUN: llvm-objdump -d %t.exe | FileCheck %s14# RUN: llvm-objdump -d %t.exe | FileCheck %s
1515
16# CHECK: Disassembly of section .out:16# CHECK: Disassembly of section .out:
17# CHECK-EMPTY:
17# CHECK-NEXT: __LA25Thunk_foo1a:18# CHECK-NEXT: __LA25Thunk_foo1a:
18# CHECK-NEXT: 20000: 3c 19 00 02 lui $25, 219# CHECK-NEXT: 20000: 3c 19 00 02 lui $25, 2
19# CHECK-NEXT: 20004: 08 00 80 08 j 131104 <foo1a>20# CHECK-NEXT: 20004: 08 00 80 08 j 131104 <foo1a>
...@@ -84,6 +85,7 @@ __start:...@@ -84,6 +85,7 @@ __start:
84# RUN: llvm-objdump -d %t2.exe | FileCheck -check-prefix=ORPH1 %s85# RUN: llvm-objdump -d %t2.exe | FileCheck -check-prefix=ORPH1 %s
8586
86# ORPH1: Disassembly of section .text:87# ORPH1: Disassembly of section .text:
88# ORPH1-EMPTY:
87# ORPH1-NEXT: __start:89# ORPH1-NEXT: __start:
88# ORPH1-NEXT: 20000: 0c 00 80 15 jal 131156 <__LA25Thunk_foo1a>90# ORPH1-NEXT: 20000: 0c 00 80 15 jal 131156 <__LA25Thunk_foo1a>
89# ORPH1-NEXT: 20004: 00 00 00 00 nop91# ORPH1-NEXT: 20004: 00 00 00 00 nop
...@@ -144,6 +146,7 @@ __start:...@@ -144,6 +146,7 @@ __start:
144# RUN: llvm-objdump -d %t3.exe | FileCheck -check-prefix=ORPH2 %s146# RUN: llvm-objdump -d %t3.exe | FileCheck -check-prefix=ORPH2 %s
145147
146# ORPH2: Disassembly of section .out:148# ORPH2: Disassembly of section .out:
149# ORPH2-EMPTY:
147# ORPH2-NEXT: __start:150# ORPH2-NEXT: __start:
148# ORPH2-NEXT: 20000: 0c 00 80 18 jal 131168 <__LA25Thunk_foo1a>151# ORPH2-NEXT: 20000: 0c 00 80 18 jal 131168 <__LA25Thunk_foo1a>
149# ORPH2-NEXT: 20004: 00 00 00 00 nop152# ORPH2-NEXT: 20004: 00 00 00 00 nop
...@@ -169,7 +172,9 @@ __start:...@@ -169,7 +172,9 @@ __start:
169172
170# ORPH2: fnpic:173# ORPH2: fnpic:
171# ORPH2-NEXT: 20050: 00 00 00 00 nop174# ORPH2-NEXT: 20050: 00 00 00 00 nop
175# ORPH2-EMPTY:
172# ORPH2-NEXT: Disassembly of section .text:176# ORPH2-NEXT: Disassembly of section .text:
177# ORPH2-EMPTY:
173178
174# ORPH2-NEXT: __LA25Thunk_foo1a:179# ORPH2-NEXT: __LA25Thunk_foo1a:
175# ORPH2-NEXT: 20060: 3c 19 00 02 lui $25, 2180# ORPH2-NEXT: 20060: 3c 19 00 02 lui $25, 2
deps/lld/test/ELF/mips-npic-call-pic.s+49-23
...@@ -2,18 +2,32 @@...@@ -2,18 +2,32 @@
2# Check LA25 stubs creation. This stub code is necessary when2# Check LA25 stubs creation. This stub code is necessary when
3# non-PIC code calls PIC function.3# non-PIC code calls PIC function.
44
5# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \5# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mcpu=mips32r2 \
6# RUN: %p/Inputs/mips-fpic.s -o %t-fpic.o6# RUN: %p/Inputs/mips-fpic.s -o %t-fpic.o
7# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \7# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mcpu=mips32r2 \
8# RUN: %p/Inputs/mips-fnpic.s -o %t-fnpic.o8# RUN: %p/Inputs/mips-fnpic.s -o %t-fnpic.o
9# RUN: ld.lld -r %t-fpic.o %t-fnpic.o -o %t-sto-pic.o9# RUN: ld.lld -r %t-fpic.o %t-fnpic.o -o %t-sto-pic-r2.o
10# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \10# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mcpu=mips32r2 \
11# RUN: %p/Inputs/mips-pic.s -o %t-pic.o11# RUN: %p/Inputs/mips-pic.s -o %t-pic-r2.o
12# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t-npic.o12# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mcpu=mips32r2 \
13# RUN: ld.lld %t-npic.o %t-pic.o %t-sto-pic.o -o %t.exe13# RUN: %s -o %t-npic-r2.o
14# RUN: llvm-objdump -d %t.exe | FileCheck %s14# RUN: ld.lld %t-npic-r2.o %t-pic-r2.o %t-sto-pic-r2.o -o %t-r2.exe
15# RUN: llvm-objdump -d %t-r2.exe | FileCheck --check-prefixes=CHECK,R2 %s
16
17# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mcpu=mips32r6 \
18# RUN: %p/Inputs/mips-fpic.s -o %t-fpic.o
19# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mcpu=mips32r6 \
20# RUN: %p/Inputs/mips-fnpic.s -o %t-fnpic.o
21# RUN: ld.lld -r %t-fpic.o %t-fnpic.o -o %t-sto-pic-r6.o
22# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mcpu=mips32r6 \
23# RUN: %p/Inputs/mips-pic.s -o %t-pic-r6.o
24# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux -mcpu=mips32r6 \
25# RUN: %s -o %t-npic-r6.o
26# RUN: ld.lld %t-npic-r6.o %t-pic-r6.o %t-sto-pic-r6.o -o %t-r6.exe
27# RUN: llvm-objdump -d %t-r6.exe | FileCheck --check-prefixes=CHECK,R6 %s
1528
16# CHECK: Disassembly of section .text:29# CHECK: Disassembly of section .text:
30# CHECK-EMPTY:
17# CHECK-NEXT: __start:31# CHECK-NEXT: __start:
18# CHECK-NEXT: 20000: 0c 00 80 0c jal 131120 <__LA25Thunk_foo1a>32# CHECK-NEXT: 20000: 0c 00 80 0c jal 131120 <__LA25Thunk_foo1a>
19# CHECK-NEXT: 20004: 00 00 00 00 nop33# CHECK-NEXT: 20004: 00 00 00 00 nop
...@@ -29,13 +43,15 @@...@@ -29,13 +43,15 @@
29# CHECK-NEXT: 2002c: 00 00 00 00 nop43# CHECK-NEXT: 2002c: 00 00 00 00 nop
30#44#
31# CHECK: __LA25Thunk_foo1a:45# CHECK: __LA25Thunk_foo1a:
32# CHECK-NEXT: 20030: 3c 19 00 02 lui $25, 246# R2: 20030: 3c 19 00 02 lui $25, 2
33# CHECK-NEXT: 20034: 08 00 80 14 j 131152 <foo1a>47# R6: 20030: 3c 19 00 02 aui $25, $zero, 2
48# CHECK: 20034: 08 00 80 14 j 131152 <foo1a>
34# CHECK-NEXT: 20038: 27 39 00 50 addiu $25, $25, 8049# CHECK-NEXT: 20038: 27 39 00 50 addiu $25, $25, 80
35# CHECK-NEXT: 2003c: 00 00 00 00 nop50# CHECK-NEXT: 2003c: 00 00 00 00 nop
3651
37# CHECK: __LA25Thunk_foo1b:52# CHECK: __LA25Thunk_foo1b:
38# CHECK-NEXT: 20040: 3c 19 00 02 lui $25, 253# R2: 20040: 3c 19 00 02 lui $25, 2
54# R6: 20040: 3c 19 00 02 aui $25, $zero, 2
39# CHECK-NEXT: 20044: 08 00 80 15 j 131156 <foo1b>55# CHECK-NEXT: 20044: 08 00 80 15 j 131156 <foo1b>
40# CHECK-NEXT: 20048: 27 39 00 54 addiu $25, $25, 8456# CHECK-NEXT: 20048: 27 39 00 54 addiu $25, $25, 84
41# CHECK-NEXT: 2004c: 00 00 00 00 nop57# CHECK-NEXT: 2004c: 00 00 00 00 nop
...@@ -47,7 +63,8 @@...@@ -47,7 +63,8 @@
47# CHECK-NEXT: 20054: 00 00 00 00 nop63# CHECK-NEXT: 20054: 00 00 00 00 nop
4864
49# CHECK: __LA25Thunk_foo2:65# CHECK: __LA25Thunk_foo2:
50# CHECK-NEXT: 20058: 3c 19 00 02 lui $25, 266# R2: 20058: 3c 19 00 02 lui $25, 2
67# R6: 20058: 3c 19 00 02 aui $25, $zero, 2
51# CHECK-NEXT: 2005c: 08 00 80 1c j 131184 <foo2>68# CHECK-NEXT: 2005c: 08 00 80 1c j 131184 <foo2>
52# CHECK-NEXT: 20060: 27 39 00 70 addiu $25, $25, 11269# CHECK-NEXT: 20060: 27 39 00 70 addiu $25, $25, 112
53# CHECK-NEXT: 20064: 00 00 00 00 nop70# CHECK-NEXT: 20064: 00 00 00 00 nop
...@@ -56,7 +73,8 @@...@@ -56,7 +73,8 @@
56# CHECK-NEXT: 20070: 00 00 00 00 nop73# CHECK-NEXT: 20070: 00 00 00 00 nop
5774
58# CHECK: __LA25Thunk_fpic:75# CHECK: __LA25Thunk_fpic:
59# CHECK-NEXT: 20074: 3c 19 00 02 lui $25, 276# R2: 20074: 3c 19 00 02 lui $25, 2
77# R6: 20074: 3c 19 00 02 aui $25, $zero, 2
60# CHECK-NEXT: 20078: 08 00 80 24 j 131216 <fpic>78# CHECK-NEXT: 20078: 08 00 80 24 j 131216 <fpic>
61# CHECK-NEXT: 2007c: 27 39 00 90 addiu $25, $25, 14479# CHECK-NEXT: 2007c: 27 39 00 90 addiu $25, $25, 144
62# CHECK-NEXT: 20080: 00 00 00 00 nop80# CHECK-NEXT: 20080: 00 00 00 00 nop
...@@ -70,19 +88,25 @@...@@ -70,19 +88,25 @@
70# Make sure the thunks are created properly no matter how88# Make sure the thunks are created properly no matter how
71# objects are laid out.89# objects are laid out.
72#90#
73# RUN: ld.lld %t-pic.o %t-npic.o %t-sto-pic.o -o %t.exe91# RUN: ld.lld %t-pic-r2.o %t-npic-r2.o %t-sto-pic-r2.o -o %t.exe
74# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefix=REVERSE %s92# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefixes=REVERSE,REV-R2 %s
93#
94# RUN: ld.lld %t-pic-r6.o %t-npic-r6.o %t-sto-pic-r6.o -o %t.exe
95# RUN: llvm-objdump -d %t.exe | FileCheck -check-prefixes=REVERSE,REV-R6 %s
7596
76# REVERSE: Disassembly of section .text:97# REVERSE: Disassembly of section .text:
98# REVERSE-EMPTY:
77# REVERSE-NEXT: __LA25Thunk_foo1a:99# REVERSE-NEXT: __LA25Thunk_foo1a:
78# REVERSE-NEXT: 20000: 3c 19 00 02 lui $25, 2100# REV-R2: 20000: 3c 19 00 02 lui $25, 2
79# REVERSE-NEXT: 20004: 08 00 80 08 j 131104 <foo1a>101# REV-R6: 20000: 3c 19 00 02 aui $25, $zero, 2
102# REVERSE: 20004: 08 00 80 08 j 131104 <foo1a>
80# REVERSE-NEXT: 20008: 27 39 00 20 addiu $25, $25, 32103# REVERSE-NEXT: 20008: 27 39 00 20 addiu $25, $25, 32
81# REVERSE-NEXT: 2000c: 00 00 00 00 nop104# REVERSE-NEXT: 2000c: 00 00 00 00 nop
82105
83# REVERSE: __LA25Thunk_foo1b:106# REVERSE: __LA25Thunk_foo1b:
84# REVERSE-NEXT: 20010: 3c 19 00 02 lui $25, 2107# REV-R2: 20010: 3c 19 00 02 lui $25, 2
85# REVERSE-NEXT: 20014: 08 00 80 09 j 131108 <foo1b>108# REV-R6: 20010: 3c 19 00 02 aui $25, $zero, 2
109# REVERSE: 20014: 08 00 80 09 j 131108 <foo1b>
86# REVERSE-NEXT: 20018: 27 39 00 24 addiu $25, $25, 36110# REVERSE-NEXT: 20018: 27 39 00 24 addiu $25, $25, 36
87# REVERSE-NEXT: 2001c: 00 00 00 00 nop111# REVERSE-NEXT: 2001c: 00 00 00 00 nop
88112
...@@ -93,8 +117,9 @@...@@ -93,8 +117,9 @@
93# REVERSE-NEXT: 20024: 00 00 00 00 nop117# REVERSE-NEXT: 20024: 00 00 00 00 nop
94118
95# REVERSE: __LA25Thunk_foo2:119# REVERSE: __LA25Thunk_foo2:
96# REVERSE-NEXT: 20028: 3c 19 00 02 lui $25, 2120# REV-R2: 20028: 3c 19 00 02 lui $25, 2
97# REVERSE-NEXT: 2002c: 08 00 80 10 j 131136 <foo2>121# REV-R6: 20028: 3c 19 00 02 aui $25, $zero, 2
122# REVERSE: 2002c: 08 00 80 10 j 131136 <foo2>
98# REVERSE-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64123# REVERSE-NEXT: 20030: 27 39 00 40 addiu $25, $25, 64
99# REVERSE-NEXT: 20034: 00 00 00 00 nop124# REVERSE-NEXT: 20034: 00 00 00 00 nop
100125
...@@ -116,8 +141,9 @@...@@ -116,8 +141,9 @@
116# REVERSE-NEXT: 2007c: 00 00 00 00 nop141# REVERSE-NEXT: 2007c: 00 00 00 00 nop
117142
118# REVERSE: __LA25Thunk_fpic:143# REVERSE: __LA25Thunk_fpic:
119# REVERSE-NEXT: 20080: 3c 19 00 02 lui $25, 2144# REV-R2: 20080: 3c 19 00 02 lui $25, 2
120# REVERSE-NEXT: 20084: 08 00 80 24 j 131216 <fpic>145# REV-R6: 20080: 3c 19 00 02 aui $25, $zero, 2
146# REVERSE: 20084: 08 00 80 24 j 131216 <fpic>
121# REVERSE-NEXT: 20088: 27 39 00 90 addiu $25, $25, 144147# REVERSE-NEXT: 20088: 27 39 00 90 addiu $25, $25, 144
122# REVERSE-NEXT: 2008c: 00 00 00 00 nop148# REVERSE-NEXT: 2008c: 00 00 00 00 nop
123149
deps/lld/test/ELF/mips-options-r.test+1-1
...@@ -11,7 +11,7 @@...@@ -11,7 +11,7 @@
11# % as -mabi=64 -mips64r2 t.s11# % as -mabi=64 -mips64r2 t.s
1212
13# RUN: ld.lld -r %p/Inputs/mips-options.o -o %t.o13# RUN: ld.lld -r %p/Inputs/mips-options.o -o %t.o
14# RUN: llvm-readobj -s %t.o | FileCheck %s14# RUN: llvm-readobj -S %t.o | FileCheck %s
1515
16# REQUIRES: mips16# REQUIRES: mips
1717
deps/lld/test/ELF/mips-options.s+14-1
...@@ -8,7 +8,7 @@...@@ -8,7 +8,7 @@
8# RUN: . = 0x100000000; \8# RUN: . = 0x100000000; \
9# RUN: .got : { *(.got) } }" > %t.rel.script9# RUN: .got : { *(.got) } }" > %t.rel.script
10# RUN: ld.lld %t1.o %t2.o --gc-sections --script %t.rel.script -shared -o %t.so10# RUN: ld.lld %t1.o %t2.o --gc-sections --script %t.rel.script -shared -o %t.so
11# RUN: llvm-readobj -symbols -mips-options %t.so | FileCheck %s11# RUN: llvm-readobj -l --symbols --mips-options %t.so | FileCheck %s
1212
13 .text13 .text
14 .globl __start14 .globl __start
...@@ -18,6 +18,19 @@ __start:...@@ -18,6 +18,19 @@ __start:
18# CHECK: Name: _gp18# CHECK: Name: _gp
19# CHECK-NEXT: Value: 0x[[GP:[0-9A-F]+]]19# CHECK-NEXT: Value: 0x[[GP:[0-9A-F]+]]
2020
21# CHECK: ProgramHeader {
22# CHECK: Type: PT_MIPS_OPTIONS
23# CHECK-NEXT: Offset:
24# CHECK-NEXT: VirtualAddress:
25# CHECK-NEXT: PhysicalAddress:
26# CHECK-NEXT: FileSize:
27# CHECK-NEXT: MemSize:
28# CHECK-NEXT: Flags [
29# CHECK-NEXT: PF_R
30# CHECK-NEXT: ]
31# CHECK-NEXT: Alignment: 8
32# CHECK-NEXT: }
33
21# CHECK: MIPS Options {34# CHECK: MIPS Options {
22# CHECK-NEXT: ODK_REGINFO {35# CHECK-NEXT: ODK_REGINFO {
23# CHECK-NEXT: GP: 0x[[GP]]36# CHECK-NEXT: GP: 0x[[GP]]
deps/lld/test/ELF/mips-pc-relocs.s+1
...@@ -22,6 +22,7 @@ __start:...@@ -22,6 +22,7 @@ __start:
22 .word _foo+8-. # R_MIPS_PC3222 .word _foo+8-. # R_MIPS_PC32
2323
24# CHECK: Disassembly of section .text:24# CHECK: Disassembly of section .text:
25# CHECK-EMPTY:
25# CHECK-NEXT: __start:26# CHECK-NEXT: __start:
26# CHECK-NEXT: 20000: ec c8 00 08 lwpc $6, 3227# CHECK-NEXT: 20000: ec c8 00 08 lwpc $6, 32
27# ^-- (0x20020-0x20000)>>228# ^-- (0x20020-0x20000)>>2
deps/lld/test/ELF/mips-plt-copy.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: %S/Inputs/mips-dynamic.s -o %t.so.o7# RUN: %S/Inputs/mips-dynamic.s -o %t.so.o
8# RUN: ld.lld %t.so.o -shared -o %t.so8# RUN: ld.lld %t.so.o -shared -o %t.so
9# RUN: ld.lld %t.o %t.so -o %t.exe9# RUN: ld.lld %t.o %t.so -o %t.exe
10# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s10# RUN: llvm-readobj -r --mips-plt-got %t.exe | FileCheck %s
1111
12# CHECK: Relocations [12# CHECK: Relocations [
13# CHECK-NEXT: Section ({{.*}}) .rel.dyn {13# CHECK-NEXT: Section ({{.*}}) .rel.dyn {
deps/lld/test/ELF/mips-plt-n32.s+3
...@@ -14,12 +14,15 @@...@@ -14,12 +14,15 @@
14# RUN: llvm-objdump -d %t.exe | FileCheck %s --check-prefixes=HAZARDPLT,CHECK14# RUN: llvm-objdump -d %t.exe | FileCheck %s --check-prefixes=HAZARDPLT,CHECK
1515
16# CHECK: Disassembly of section .text:16# CHECK: Disassembly of section .text:
17# CHECK-EMPTY:
17# CHECK-NEXT: __start:18# CHECK-NEXT: __start:
18# CHECK-NEXT: 20000: 0c 00 80 0c jal 13112019# CHECK-NEXT: 20000: 0c 00 80 0c jal 131120
19# ^-- 0x20030 gotplt[foo0]20# ^-- 0x20030 gotplt[foo0]
20# CHECK-NEXT: 20004: 00 00 00 00 nop21# CHECK-NEXT: 20004: 00 00 00 00 nop
21#22#
23# CHECK-EMPTY:
22# CHECK-NEXT: Disassembly of section .plt:24# CHECK-NEXT: Disassembly of section .plt:
25# CHECK-EMPTY:
23# CHECK-NEXT: .plt:26# CHECK-NEXT: .plt:
24# CHECK-NEXT: 20010: 3c 0e 00 03 lui $14, 327# CHECK-NEXT: 20010: 3c 0e 00 03 lui $14, 3
25# CHECK-NEXT: 20014: 8d d9 00 04 lw $25, 4($14)28# CHECK-NEXT: 20014: 8d d9 00 04 lw $25, 4($14)
deps/lld/test/ELF/mips-plt-n64.s created+42
...@@ -0,0 +1,42 @@
1# REQUIRES: mips
2# Check R_MIPS_26 relocation handling in case of N64 ABIs.
3
4# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux \
5# RUN: %S/Inputs/mips-dynamic.s -o %t-so.o
6# RUN: ld.lld %t-so.o -shared -o %t.so
7# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t.o
8# RUN: ld.lld %t.o %t.so -o %t.exe
9# RUN: llvm-objdump -d %t.exe | FileCheck %s --check-prefixes=CHECK,DEFAULT
10# RUN: ld.lld %t-so.o -shared -o %t.so -z hazardplt
11# RUN: ld.lld %t.o %t.so -o %t.exe -z hazardplt
12# RUN: llvm-objdump -d %t.exe | FileCheck %s --check-prefixes=CHECK,HAZARDPLT
13
14# CHECK: Disassembly of section .text:
15# CHECK-EMPTY:
16# CHECK-NEXT: __start:
17# CHECK-NEXT: 20000: 0c 00 80 0c jal 131120
18# CHECK-NEXT: 20004: 00 00 00 00 nop
19# CHECK-EMPTY:
20# CHECK-NEXT: Disassembly of section .plt:
21# CHECK-EMPTY:
22# CHECK-NEXT: .plt:
23# CHECK-NEXT: 20010: 3c 0e 00 03 lui $14, 3
24# CHECK-NEXT: 20014: dd d9 00 08 ld $25, 8($14)
25# CHECK-NEXT: 20018: 25 ce 00 08 addiu $14, $14, 8
26# CHECK-NEXT: 2001c: 03 0e c0 23 subu $24, $24, $14
27# CHECK-NEXT: 20020: 03 e0 78 25 move $15, $ra
28# CHECK-NEXT: 20024: 00 18 c0 c2 srl $24, $24, 3
29# DEFAULT: 20028: 03 20 f8 09 jalr $25
30# HAZARDPLT: 20028: 03 20 fc 09 jalr.hb $25
31# CHECK-NEXT: 2002c: 27 18 ff fe addiu $24, $24, -2
32# CHECK-NEXT: 20030: 3c 0f 00 03 lui $15, 3
33# CHECK-NEXT: 20034: dd f9 00 18 ld $25, 24($15)
34# DEFAULT: 20038: 03 20 00 08 jr $25
35# HAZARDPLT: 20038: 03 20 04 08 jr.hb $25
36# CHECK-NEXT: 2003c: 65 f8 00 18 daddiu $24, $15, 24
37
38 .text
39 .option pic0
40 .global __start
41__start:
42 jal foo0
deps/lld/test/ELF/mips-plt-r6.s+3
...@@ -13,12 +13,15 @@...@@ -13,12 +13,15 @@
13# RUN: llvm-objdump -d %t.exe | FileCheck %s --check-prefixes=HAZARDPLT,CHECK13# RUN: llvm-objdump -d %t.exe | FileCheck %s --check-prefixes=HAZARDPLT,CHECK
1414
15# CHECK: Disassembly of section .text:15# CHECK: Disassembly of section .text:
16# CHECK-EMPTY:
16# CHECK-NEXT: __start:17# CHECK-NEXT: __start:
17# CHECK-NEXT: 20000: 0c 00 80 0c jal 13112018# CHECK-NEXT: 20000: 0c 00 80 0c jal 131120
18# ^-- 0x20030 gotplt[foo0]19# ^-- 0x20030 gotplt[foo0]
19# CHECK-NEXT: 20004: 00 00 00 00 nop20# CHECK-NEXT: 20004: 00 00 00 00 nop
20#21#
22# CHECK-EMPTY:
21# CHECK-NEXT: Disassembly of section .plt:23# CHECK-NEXT: Disassembly of section .plt:
24# CHECK-EMPTY:
22# CHECK-NEXT: .plt:25# CHECK-NEXT: .plt:
23# CHECK-NEXT: 20010: 3c 1c 00 03 aui $gp, $zero, 326# CHECK-NEXT: 20010: 3c 1c 00 03 aui $gp, $zero, 3
24# CHECK-NEXT: 20014: 8f 99 00 04 lw $25, 4($gp)27# CHECK-NEXT: 20014: 8f 99 00 04 lw $25, 4($gp)
deps/lld/test/ELF/mips-reginfo.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \5# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
6# RUN: %S/Inputs/mips-dynamic.s -o %t2.o6# RUN: %S/Inputs/mips-dynamic.s -o %t2.o
7# RUN: ld.lld %t1.o %t2.o --gc-sections -shared -o %t.so7# RUN: ld.lld %t1.o %t2.o --gc-sections -shared -o %t.so
8# RUN: llvm-readobj -symbols -mips-reginfo %t.so | FileCheck %s8# RUN: llvm-readobj --symbols --mips-reginfo %t.so | FileCheck %s
99
10 .text10 .text
11 .globl __start11 .globl __start
deps/lld/test/ELF/mips-sto-pic-flag.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \7# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux \
8# RUN: %p/Inputs/mips-pic.s -o %t-pic.o8# RUN: %p/Inputs/mips-pic.s -o %t-pic.o
9# RUN: ld.lld -r %t-npic.o %t-pic.o -o %t-rel.o9# RUN: ld.lld -r %t-npic.o %t-pic.o -o %t-rel.o
10# RUN: llvm-readobj -t %t-rel.o | FileCheck %s10# RUN: llvm-readobj --symbols %t-rel.o | FileCheck %s
1111
12# CHECK: Symbol {12# CHECK: Symbol {
13# CHECK: Name: main13# CHECK: Name: main
deps/lld/test/ELF/mips-sto-plt.s+1-1
...@@ -6,7 +6,7 @@...@@ -6,7 +6,7 @@
6# RUN: ld.lld %t.so.o -shared -o %t.so6# RUN: ld.lld %t.so.o -shared -o %t.so
7# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o7# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
8# RUN: ld.lld %t.o %t.so -o %t.exe8# RUN: ld.lld %t.o %t.so -o %t.exe
9# RUN: llvm-readobj -dt -mips-plt-got %t.exe | FileCheck %s9# RUN: llvm-readobj --dyn-syms --mips-plt-got %t.exe | FileCheck %s
1010
11# CHECK: Symbol {11# CHECK: Symbol {
12# CHECK: Name: foo012# CHECK: Name: foo0
deps/lld/test/ELF/mips-tls-64.s+24-24
...@@ -8,11 +8,11 @@...@@ -8,11 +8,11 @@
88
9# RUN: ld.lld %t.o %t.so -o %t.exe9# RUN: ld.lld %t.o %t.so -o %t.exe
10# RUN: llvm-objdump -d -s -t %t.exe | FileCheck -check-prefix=DIS %s10# RUN: llvm-objdump -d -s -t %t.exe | FileCheck -check-prefix=DIS %s
11# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s11# RUN: llvm-readobj -r --mips-plt-got %t.exe | FileCheck %s
1212
13# RUN: ld.lld -shared %t.o %t.so -o %t-out.so13# RUN: ld.lld -shared %t.o %t.so -o %t-out.so
14# RUN: llvm-objdump -d -s -t %t-out.so | FileCheck -check-prefix=DIS-SO %s14# RUN: llvm-objdump -d -s -t %t-out.so | FileCheck -check-prefix=DIS-SO %s
15# RUN: llvm-readobj -r -mips-plt-got %t-out.so | FileCheck -check-prefix=SO %s15# RUN: llvm-readobj -r --mips-plt-got %t-out.so | FileCheck -check-prefix=SO %s
1616
17# DIS: __start:17# DIS: __start:
18# DIS-NEXT: 20000: 24 62 80 30 addiu $2, $3, -3272018# DIS-NEXT: 20000: 24 62 80 30 addiu $2, $3, -32720
...@@ -22,11 +22,11 @@...@@ -22,11 +22,11 @@
22# DIS-NEXT: 20010: 24 62 80 28 addiu $2, $3, -3272822# DIS-NEXT: 20010: 24 62 80 28 addiu $2, $3, -32728
2323
24# DIS: Contents of section .got:24# DIS: Contents of section .got:
25# DIS-NEXT: 30010 00000000 00000000 80000000 0000000025# DIS-NEXT: 40010 00000000 00000000 80000000 00000000
26# DIS-NEXT: 30020 00000000 00000000 ffffffff ffff900426# DIS-NEXT: 40020 00000000 00000000 ffffffff ffff9004
27# DIS-NEXT: 30030 00000000 00000000 00000000 0000000027# DIS-NEXT: 40030 00000000 00000000 00000000 00000000
28# DIS-NEXT: 30040 00000000 00000001 00000000 0000000028# DIS-NEXT: 40040 00000000 00000001 00000000 00000000
29# DIS-NEXT: 30050 00000000 00000001 ffffffff ffff800429# DIS-NEXT: 40050 00000000 00000001 ffffffff ffff8004
3030
31# DIS: 0000000000000000 l O .tdata 00000000 loc31# DIS: 0000000000000000 l O .tdata 00000000 loc
32# DIS: 0000000000000004 g O .tdata 00000000 bar32# DIS: 0000000000000004 g O .tdata 00000000 bar
...@@ -34,13 +34,13 @@...@@ -34,13 +34,13 @@
3434
35# CHECK: Relocations [35# CHECK: Relocations [
36# CHECK-NEXT: Section (7) .rel.dyn {36# CHECK-NEXT: Section (7) .rel.dyn {
37# CHECK-NEXT: 0x30020 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x037# CHECK-NEXT: 0x40020 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
38# CHECK-NEXT: 0x30030 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE foo 0x038# CHECK-NEXT: 0x40030 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
39# CHECK-NEXT: 0x30038 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x039# CHECK-NEXT: 0x40038 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
40# CHECK-NEXT: }40# CHECK-NEXT: }
41# CHECK-NEXT: ]41# CHECK-NEXT: ]
42# CHECK-NEXT: Primary GOT {42# CHECK-NEXT: Primary GOT {
43# CHECK-NEXT: Canonical gp value: 0x3800043# CHECK-NEXT: Canonical gp value: 0x48000
44# CHECK-NEXT: Reserved entries [44# CHECK-NEXT: Reserved entries [
45# CHECK: ]45# CHECK: ]
46# CHECK-NEXT: Local entries [46# CHECK-NEXT: Local entries [
...@@ -58,25 +58,25 @@...@@ -58,25 +58,25 @@
58# ^-- -32680 VA - 0x8000 bar58# ^-- -32680 VA - 0x8000 bar
5959
60# DIS-SO: Contents of section .got:60# DIS-SO: Contents of section .got:
61# DIS-SO-NEXT: 20000 00000000 00000000 80000000 0000000061# DIS-SO-NEXT: 30000 00000000 00000000 80000000 00000000
62# DIS-SO-NEXT: 20010 00000000 00000000 00000000 0000000462# DIS-SO-NEXT: 30010 00000000 00000000 00000000 00000004
63# DIS-SO-NEXT: 20020 00000000 00000000 00000000 0000000063# DIS-SO-NEXT: 30020 00000000 00000000 00000000 00000000
64# DIS-SO-NEXT: 20030 00000000 00000000 00000000 0000000064# DIS-SO-NEXT: 30030 00000000 00000000 00000000 00000000
65# DIS-SO-NEXT: 20040 00000000 00000000 00000000 0000000065# DIS-SO-NEXT: 30040 00000000 00000000 00000000 00000000
6666
67# SO: Relocations [67# SO: Relocations [
68# SO-NEXT: Section (7) .rel.dyn {68# SO-NEXT: Section (7) .rel.dyn {
69# SO-NEXT: 0x20030 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE - 0x069# SO-NEXT: 0x30030 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE - 0x0
70# SO-NEXT: 0x20018 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE bar 0x070# SO-NEXT: 0x30018 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE bar 0x0
71# SO-NEXT: 0x20040 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE bar 0x071# SO-NEXT: 0x30040 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE bar 0x0
72# SO-NEXT: 0x20048 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE bar 0x072# SO-NEXT: 0x30048 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE bar 0x0
73# SO-NEXT: 0x20010 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x073# SO-NEXT: 0x30010 R_MIPS_TLS_TPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
74# SO-NEXT: 0x20020 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE foo 0x074# SO-NEXT: 0x30020 R_MIPS_TLS_DTPMOD64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
75# SO-NEXT: 0x20028 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x075# SO-NEXT: 0x30028 R_MIPS_TLS_DTPREL64/R_MIPS_NONE/R_MIPS_NONE foo 0x0
76# SO-NEXT: }76# SO-NEXT: }
77# SO-NEXT: ]77# SO-NEXT: ]
78# SO-NEXT: Primary GOT {78# SO-NEXT: Primary GOT {
79# SO-NEXT: Canonical gp value: 0x27FF079# SO-NEXT: Canonical gp value: 0x37FF0
80# SO-NEXT: Reserved entries [80# SO-NEXT: Reserved entries [
81# SO: ]81# SO: ]
82# SO-NEXT: Local entries [82# SO-NEXT: Local entries [
deps/lld/test/ELF/mips-tls-hilo.s+2-2
...@@ -5,10 +5,10 @@...@@ -5,10 +5,10 @@
5# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o5# RUN: llvm-mc -filetype=obj -triple=mips-unknown-linux %s -o %t.o
6# RUN: ld.lld %t.o -o %t.exe6# RUN: ld.lld %t.o -o %t.exe
7# RUN: llvm-objdump -d -t %t.exe | FileCheck -check-prefix=DIS %s7# RUN: llvm-objdump -d -t %t.exe | FileCheck -check-prefix=DIS %s
8# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s8# RUN: llvm-readobj -r --mips-plt-got %t.exe | FileCheck %s
99
10# RUN: ld.lld %t.o -shared -o %t.so10# RUN: ld.lld %t.o -shared -o %t.so
11# RUN: llvm-readobj -r -mips-plt-got %t.so | FileCheck -check-prefix=SO %s11# RUN: llvm-readobj -r --mips-plt-got %t.so | FileCheck -check-prefix=SO %s
1212
13# DIS: __start:13# DIS: __start:
14# DIS-NEXT: 20000: 24 62 00 00 addiu $2, $3, 014# DIS-NEXT: 20000: 24 62 00 00 addiu $2, $3, 0
deps/lld/test/ELF/mips-tls-static-64.s+2-2
...@@ -7,8 +7,8 @@...@@ -7,8 +7,8 @@
7# RUN: llvm-objdump -s -t %t.exe | FileCheck %s7# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
88
9# CHECK: Contents of section .data:9# CHECK: Contents of section .data:
10# CHECK-NEXT: 30000 00020004 ffffffff ffff8004 ffffffff10# CHECK-NEXT: 40000 00020004 ffffffff ffff8004 ffffffff
11# CHECK-NEXT: 30010 ffff900411# CHECK-NEXT: 40010 ffff9004
12#12#
13# CHECK: SYMBOL TABLE:13# CHECK: SYMBOL TABLE:
14# CHECK: 0000000000020004 .text 00000000 __tls_get_addr14# CHECK: 0000000000020004 .text 00000000 __tls_get_addr
deps/lld/test/ELF/mips-tls-static.s+3-3
...@@ -7,10 +7,10 @@...@@ -7,10 +7,10 @@
7# RUN: llvm-objdump -s -t %t.exe | FileCheck %s7# RUN: llvm-objdump -s -t %t.exe | FileCheck %s
88
9# CHECK: Contents of section .data:9# CHECK: Contents of section .data:
10# CHECK-NEXT: 30000 0002000c ffff8004 ffff900410# CHECK-NEXT: 40000 0002000c ffff8004 ffff9004
11# CHECK: Contents of section .got:11# CHECK: Contents of section .got:
12# CHECK-NEXT: 30010 00000000 80000000 ffff9000 0000000112# CHECK-NEXT: 40010 00000000 80000000 ffff9000 00000001
13# CHECK-NEXT: 30020 ffff8000 00000001 0000000013# CHECK-NEXT: 40020 ffff8000 00000001 00000000
14#14#
15# CHECK: SYMBOL TABLE:15# CHECK: SYMBOL TABLE:
16# CHECK: 0002000c .text 00000000 __tls_get_addr16# CHECK: 0002000c .text 00000000 __tls_get_addr
deps/lld/test/ELF/mips-tls.s+20-20
...@@ -8,11 +8,11 @@...@@ -8,11 +8,11 @@
88
9# RUN: ld.lld %t.o %t.so -o %t.exe9# RUN: ld.lld %t.o %t.so -o %t.exe
10# RUN: llvm-objdump -d -s -t %t.exe | FileCheck -check-prefix=DIS %s10# RUN: llvm-objdump -d -s -t %t.exe | FileCheck -check-prefix=DIS %s
11# RUN: llvm-readobj -r -mips-plt-got %t.exe | FileCheck %s11# RUN: llvm-readobj -r --mips-plt-got %t.exe | FileCheck %s
1212
13# RUN: ld.lld -shared %t.o %t.so -o %t-out.so13# RUN: ld.lld -shared %t.o %t.so -o %t-out.so
14# RUN: llvm-objdump -d -s -t %t-out.so | FileCheck -check-prefix=DIS-SO %s14# RUN: llvm-objdump -d -s -t %t-out.so | FileCheck -check-prefix=DIS-SO %s
15# RUN: llvm-readobj -r -mips-plt-got %t-out.so | FileCheck -check-prefix=SO %s15# RUN: llvm-readobj -r --mips-plt-got %t-out.so | FileCheck -check-prefix=SO %s
1616
17# DIS: __start:17# DIS: __start:
18# DIS-NEXT: 20000: 24 62 80 20 addiu $2, $3, -3273618# DIS-NEXT: 20000: 24 62 80 20 addiu $2, $3, -32736
...@@ -22,9 +22,9 @@...@@ -22,9 +22,9 @@
22# DIS-NEXT: 20010: 24 62 80 1c addiu $2, $3, -3274022# DIS-NEXT: 20010: 24 62 80 1c addiu $2, $3, -32740
2323
24# DIS: Contents of section .got:24# DIS: Contents of section .got:
25# DIS-NEXT: 30010 00000000 80000000 00000000 ffff900425# DIS-NEXT: 40010 00000000 80000000 00000000 ffff9004
26# DIS-NEXT: 30020 00000000 00000000 00000001 0000000026# DIS-NEXT: 40020 00000000 00000000 00000001 00000000
27# DIS-NEXT: 30030 00000001 ffff800427# DIS-NEXT: 40030 00000001 ffff8004
2828
29# DIS: 00000000 l O .tdata 00000000 loc29# DIS: 00000000 l O .tdata 00000000 loc
30# DIS: 00000004 g O .tdata 00000000 bar30# DIS: 00000004 g O .tdata 00000000 bar
...@@ -32,13 +32,13 @@...@@ -32,13 +32,13 @@
3232
33# CHECK: Relocations [33# CHECK: Relocations [
34# CHECK-NEXT: Section (7) .rel.dyn {34# CHECK-NEXT: Section (7) .rel.dyn {
35# CHECK-NEXT: 0x30018 R_MIPS_TLS_TPREL32 foo 0x035# CHECK-NEXT: 0x40018 R_MIPS_TLS_TPREL32 foo 0x0
36# CHECK-NEXT: 0x30020 R_MIPS_TLS_DTPMOD32 foo 0x036# CHECK-NEXT: 0x40020 R_MIPS_TLS_DTPMOD32 foo 0x0
37# CHECK-NEXT: 0x30024 R_MIPS_TLS_DTPREL32 foo 0x037# CHECK-NEXT: 0x40024 R_MIPS_TLS_DTPREL32 foo 0x0
38# CHECK-NEXT: }38# CHECK-NEXT: }
39# CHECK-NEXT: ]39# CHECK-NEXT: ]
40# CHECK-NEXT: Primary GOT {40# CHECK-NEXT: Primary GOT {
41# CHECK-NEXT: Canonical gp value: 0x3800041# CHECK-NEXT: Canonical gp value: 0x48000
42# CHECK-NEXT: Reserved entries [42# CHECK-NEXT: Reserved entries [
43# CHECK: ]43# CHECK: ]
44# CHECK-NEXT: Local entries [44# CHECK-NEXT: Local entries [
...@@ -56,23 +56,23 @@...@@ -56,23 +56,23 @@
56# ^-- -32716 VA - 0x8000 bar56# ^-- -32716 VA - 0x8000 bar
5757
58# DIS-SO: Contents of section .got:58# DIS-SO: Contents of section .got:
59# DIS-SO-NEXT: 20000 00000000 80000000 00000000 0000000459# DIS-SO-NEXT: 30000 00000000 80000000 00000000 00000004
60# DIS-SO-NEXT: 20010 00000000 00000000 00000000 0000000060# DIS-SO-NEXT: 30010 00000000 00000000 00000000 00000000
61# DIS-SO-NEXT: 20020 00000000 0000000061# DIS-SO-NEXT: 30020 00000000 00000000
6262
63# SO: Relocations [63# SO: Relocations [
64# SO-NEXT: Section (7) .rel.dyn {64# SO-NEXT: Section (7) .rel.dyn {
65# SO-NEXT: 0x20018 R_MIPS_TLS_DTPMOD32 - 0x065# SO-NEXT: 0x30018 R_MIPS_TLS_DTPMOD32 - 0x0
66# SO-NEXT: 0x2000C R_MIPS_TLS_TPREL32 bar 0x066# SO-NEXT: 0x3000C R_MIPS_TLS_TPREL32 bar 0x0
67# SO-NEXT: 0x20020 R_MIPS_TLS_DTPMOD32 bar 0x067# SO-NEXT: 0x30020 R_MIPS_TLS_DTPMOD32 bar 0x0
68# SO-NEXT: 0x20024 R_MIPS_TLS_DTPREL32 bar 0x068# SO-NEXT: 0x30024 R_MIPS_TLS_DTPREL32 bar 0x0
69# SO-NEXT: 0x20008 R_MIPS_TLS_TPREL32 foo 0x069# SO-NEXT: 0x30008 R_MIPS_TLS_TPREL32 foo 0x0
70# SO-NEXT: 0x20010 R_MIPS_TLS_DTPMOD32 foo 0x070# SO-NEXT: 0x30010 R_MIPS_TLS_DTPMOD32 foo 0x0
71# SO-NEXT: 0x20014 R_MIPS_TLS_DTPREL32 foo 0x071# SO-NEXT: 0x30014 R_MIPS_TLS_DTPREL32 foo 0x0
72# SO-NEXT: }72# SO-NEXT: }
73# SO-NEXT: ]73# SO-NEXT: ]
74# SO-NEXT: Primary GOT {74# SO-NEXT: Primary GOT {
75# SO-NEXT: Canonical gp value: 0x27FF075# SO-NEXT: Canonical gp value: 0x37FF0
76# SO-NEXT: Reserved entries [76# SO-NEXT: Reserved entries [
77# SO: ]77# SO: ]
78# SO-NEXT: Local entries [78# SO-NEXT: Local entries [
deps/lld/test/ELF/mips-xgot-order.s+1
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
7# RUN: llvm-objdump -d -s -t %t.exe | FileCheck %s7# RUN: llvm-objdump -d -s -t %t.exe | FileCheck %s
88
9# CHECK: Disassembly of section .text:9# CHECK: Disassembly of section .text:
10# CHECK-EMPTY:
10# CHECK-NEXT: __start:11# CHECK-NEXT: __start:
11# CHECK-NEXT: 20000: 3c 02 00 00 lui $2, 012# CHECK-NEXT: 20000: 3c 02 00 00 lui $2, 0
12# CHECK-NEXT: 20004: 8c 42 80 24 lw $2, -32732($2)13# CHECK-NEXT: 20004: 8c 42 80 24 lw $2, -32732($2)
deps/lld/test/ELF/msp430.s+1
...@@ -13,6 +13,7 @@ foo:...@@ -13,6 +13,7 @@ foo:
13 jmp _start13 jmp _start
1414
15; CHECK: Disassembly of section .text:15; CHECK: Disassembly of section .text:
16; CHECK-EMPTY:
16; CHECK-NEXT: _start:17; CHECK-NEXT: _start:
17; CHECK-NEXT: 8000: {{.*}} nop18; CHECK-NEXT: 8000: {{.*}} nop
18; CHECK: foo:19; CHECK: foo:
deps/lld/test/ELF/new-dtags.test+2-2
...@@ -10,11 +10,11 @@...@@ -10,11 +10,11 @@
10// RUN: llvm-readobj --dynamic-table %t2 | FileCheck --check-prefix=ENABLE %s10// RUN: llvm-readobj --dynamic-table %t2 | FileCheck --check-prefix=ENABLE %s
1111
12// DISABLE: DynamicSection [12// DISABLE: DynamicSection [
13// DISABLE: 0x000000000000000F RPATH /somepath13// DISABLE: 0x000000000000000F RPATH Library rpath: [/somepath]
14// DISABLE-NOT: RUNPATH14// DISABLE-NOT: RUNPATH
15// DISABLE: ]15// DISABLE: ]
1616
17// ENABLE: DynamicSection [17// ENABLE: DynamicSection [
18// ENABLE: 0x000000000000001D RUNPATH /somepath18// ENABLE: 0x000000000000001D RUNPATH Library runpath: [/somepath]
19// ENABLE-NOT: RPATH19// ENABLE-NOT: RPATH
20// ENABLE: ]20// ENABLE: ]
deps/lld/test/ELF/no-discard-this_module.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -save-temp-labels %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-linux-gnu -save-temp-labels %s -o %t
3// RUN: ld.lld %t -o %t23// RUN: ld.lld %t -o %t2
4// RUN: llvm-readobj -s -sd -t %t2 | FileCheck %s4// RUN: llvm-readobj -S --section-data --symbols %t2 | FileCheck %s
55
6.global _start6.global _start
7_start:7_start:
deps/lld/test/ELF/no-inhibit-exec.s+1
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6# RUN: llvm-readobj -r %t2 | FileCheck %s --check-prefix=RELOC6# RUN: llvm-readobj -r %t2 | FileCheck %s --check-prefix=RELOC
77
8# CHECK: Disassembly of section .text:8# CHECK: Disassembly of section .text:
9# CHECK-EMPTY:
9# CHECK-NEXT: _start10# CHECK-NEXT: _start
10# CHECK-NEXT: 201000: {{.*}} callq -210125311# CHECK-NEXT: 201000: {{.*}} callq -2101253
1112
deps/lld/test/ELF/non-abs-reloc.s+1
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
66
7// RUN: llvm-objdump -D %t | FileCheck --check-prefix=DISASM %s7// RUN: llvm-objdump -D %t | FileCheck --check-prefix=DISASM %s
8// DISASM: Disassembly of section .nonalloc:8// DISASM: Disassembly of section .nonalloc:
9// DISASM-EMPTY:
9// DISASM-NEXT: .nonalloc:10// DISASM-NEXT: .nonalloc:
10// DISASM-NEXT: 0: {{.*}} callq {{.*}} <_start>11// DISASM-NEXT: 0: {{.*}} callq {{.*}} <_start>
11// DISASM-NEXT: 5: {{.*}} callq {{.*}} <_start>12// DISASM-NEXT: 5: {{.*}} callq {{.*}} <_start>
deps/lld/test/ELF/non-alloc-link-order-gc.s+1
...@@ -6,6 +6,7 @@...@@ -6,6 +6,7 @@
6## Check that we are able to GC non-allocatable metadata sections without crash.6## Check that we are able to GC non-allocatable metadata sections without crash.
77
8# CHECK: Disassembly of section .stack_sizes:8# CHECK: Disassembly of section .stack_sizes:
9# CHECK-EMPTY:
9# CHECK-NEXT: .stack_sizes:10# CHECK-NEXT: .stack_sizes:
10# CHECK-NEXT: 0111# CHECK-NEXT: 01
1112
deps/lld/test/ELF/noplt-pie.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
4# RUN: ld.lld -shared %t2.o -o %t2.so4# RUN: ld.lld -shared %t2.o -o %t2.so
5# RUN: ld.lld --hash-style=sysv %t1.o %t2.so -o %t.out5# RUN: ld.lld --hash-style=sysv %t1.o %t2.so -o %t.out
6# RUN: llvm-readobj -s -r %t.out | FileCheck %s6# RUN: llvm-readobj -S -r %t.out | FileCheck %s
77
8# CHECK: Section {8# CHECK: Section {
9# CHECK-NOT: Name: .plt9# CHECK-NOT: Name: .plt
deps/lld/test/ELF/note-alignment.s created+36
...@@ -0,0 +1,36 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-readelf -l %t | FileCheck %s
5
6# Check that we don't mix 4-byte and 8-byte aligned notes in one PT_LOAD.
7# The possible 4-byte padding before the 8-byte align note may make consumers
8# fail to parse it.
9
10# CHECK: NOTE {{0x[0-9a-f]+}} {{0x[0-9a-f]+}} {{0x[0-9a-f]+}} 0x000004 0x000004 R 0x4
11# CHECK: NOTE {{0x[0-9a-f]+}} {{0x[0-9a-f]+}} {{0x[0-9a-f]+}} 0x000010 0x000010 R 0x8
12# CHECK: NOTE {{0x[0-9a-f]+}} {{0x[0-9a-f]+}} {{0x[0-9a-f]+}} 0x000008 0x000008 R 0x4
13
14# CHECK: 03 .note.a
15# CHECK-NEXT: 04 .note.b .note.c
16# CHECK-NEXT: 05 .note.d .note.e
17
18.section .note.a, "a", @note
19.align 4
20.long 0
21
22.section .note.b, "a", @note
23.align 8
24.quad 0
25
26.section .note.c, "a", @note
27.align 8
28.quad 0
29
30.section .note.d, "a", @note
31.align 4
32.long 0
33
34.section .note.e, "a", @note
35.align 4
36.long 0
deps/lld/test/ELF/note-contiguous.s+2-2
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
33
4// RUN: ld.lld %t.o -o %t14// RUN: ld.lld %t.o -o %t1
5// RUN: llvm-readobj -program-headers %t1 | FileCheck %s5// RUN: llvm-readobj -l %t1 | FileCheck %s
66
7// CHECK: Type: PT_NOTE7// CHECK: Type: PT_NOTE
8// CHECK-NEXT: Offset:8// CHECK-NEXT: Offset:
...@@ -18,7 +18,7 @@...@@ -18,7 +18,7 @@
1818
19// RUN: echo "SECTIONS { .note : { *(.note.a) *(.note.b) } }" > %t.script19// RUN: echo "SECTIONS { .note : { *(.note.a) *(.note.b) } }" > %t.script
20// RUN: ld.lld %t.o --script %t.script -o %t220// RUN: ld.lld %t.o --script %t.script -o %t2
21// RUN: llvm-readobj -program-headers %t2 | FileCheck -check-prefix=SCRIPT %s21// RUN: llvm-readobj -l %t2 | FileCheck -check-prefix=SCRIPT %s
2222
23// SCRIPT: Type: PT_NOTE23// SCRIPT: Type: PT_NOTE
24// SCRIPT-NEXT: Offset:24// SCRIPT-NEXT: Offset:
deps/lld/test/ELF/note-loadaddr.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5// RUN: .note.b : AT(0x2000) { *(.note.b) } \5// RUN: .note.b : AT(0x2000) { *(.note.b) } \
6// RUN: }" > %t.script6// RUN: }" > %t.script
7// RUN: ld.lld %t.o --script %t.script -o %t7// RUN: ld.lld %t.o --script %t.script -o %t
8// RUN: llvm-readobj -program-headers %t | FileCheck %s8// RUN: llvm-readobj -l %t | FileCheck %s
99
10// CHECK: Type: PT_NOTE10// CHECK: Type: PT_NOTE
11// CHECK-NEXT: Offset: 0x100011// CHECK-NEXT: Offset: 0x1000
deps/lld/test/ELF/note-multiple.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7// RUN: .note.d : { *(.note.d) } \7// RUN: .note.d : { *(.note.d) } \
8// RUN: }" > %t.script8// RUN: }" > %t.script
9// RUN: ld.lld %t.o --script %t.script -o %t9// RUN: ld.lld %t.o --script %t.script -o %t
10// RUN: llvm-readobj -program-headers %t | FileCheck %s10// RUN: llvm-readobj -l %t | FileCheck %s
1111
12// CHECK: Type: PT_NOTE12// CHECK: Type: PT_NOTE
13// CHECK-NEXT: Offset: 0x100013// CHECK-NEXT: Offset: 0x1000
deps/lld/test/ELF/note-noalloc.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t -shared3// RUN: ld.lld %t.o -o %t -shared
4// RUN: llvm-readobj -program-headers -sections %t | FileCheck %s4// RUN: llvm-readobj -l --sections %t | FileCheck %s
55
6// PR37361: A note without SHF_ALLOC should not be included into a PT_NOTE program header.6// PR37361: A note without SHF_ALLOC should not be included into a PT_NOTE program header.
77
deps/lld/test/ELF/note-noalloc2.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-readobj -program-headers %t | FileCheck %s4# RUN: llvm-readobj -l %t | FileCheck %s
55
6## Check we do not create a PT_NOTE segment for non-allocatable note section.6## Check we do not create a PT_NOTE segment for non-allocatable note section.
77
deps/lld/test/ELF/note.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t -shared3// RUN: ld.lld %t.o -o %t -shared
4// RUN: llvm-readobj -program-headers %t | FileCheck %s4// RUN: llvm-readobj -l %t | FileCheck %s
55
6// CHECK: Type: PT_NOTE6// CHECK: Type: PT_NOTE
7// CHECK-NEXT: Offset:7// CHECK-NEXT: Offset:
deps/lld/test/ELF/output-section.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %t23// RUN: ld.lld %t -o %t2
4// RUN: llvm-readobj -t %t2 | FileCheck %s4// RUN: llvm-readobj --symbols %t2 | FileCheck %s
55
6// CHECK: Symbol {6// CHECK: Symbol {
7// CHECK: Name: bar_sym7// CHECK: Name: bar_sym
deps/lld/test/ELF/pack-dyn-relocs-loop.s+12-12
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1// REQUIRES: arm, aarch641// REQUIRES: arm, aarch64
22
3// RUN: llvm-mc -filetype=obj -triple=aarch64-none-linux-android %s -o %t.o3// 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=android4// RUN: ld.lld -shared %t.o -o %t.so --pack-dyn-relocs=android -z norelro
5// RUN: llvm-readobj -s %t.so | FileCheck %s5// RUN: llvm-readobj -S %t.so | FileCheck %s
66
7// This test is making sure the Android packed relocation support doesn't7// This test is making sure the Android packed relocation support doesn't
8// cause an infinite loop due to the size of the section oscillating8// cause an infinite loop due to the size of the section oscillating
...@@ -16,8 +16,8 @@...@@ -16,8 +16,8 @@
16// CHECK-NEXT: Flags [ (0x2)16// CHECK-NEXT: Flags [ (0x2)
17// CHECK-NEXT: SHF_ALLOC (0x2)17// CHECK-NEXT: SHF_ALLOC (0x2)
18// CHECK-NEXT: ]18// CHECK-NEXT: ]
19// CHECK-NEXT: Address: 0x21019// CHECK-NEXT: Address: 0x1D8
20// CHECK-NEXT: Offset: 0x21020// CHECK-NEXT: Offset: 0x1D8
21// CHECK-NEXT: Size: 2121// CHECK-NEXT: Size: 21
2222
23// CHECK: Name: x (43)23// CHECK: Name: x (43)
...@@ -25,9 +25,9 @@...@@ -25,9 +25,9 @@
25// CHECK-NEXT: Flags [ (0x2)25// CHECK-NEXT: Flags [ (0x2)
26// CHECK-NEXT: SHF_ALLOC (0x2)26// CHECK-NEXT: SHF_ALLOC (0x2)
27// CHECK-NEXT: ]27// CHECK-NEXT: ]
28// CHECK-NEXT: Address: 0x22528// CHECK-NEXT: Address: 0x1ED
29// CHECK-NEXT: Offset: 0x22529// CHECK-NEXT: Offset: 0x1ED
30// CHECK-NEXT: Size: 6498030// CHECK-NEXT: Size: 65036
3131
32// CHECK: Name: barr (45)32// CHECK: Name: barr (45)
33// CHECK-NEXT: Type: SHT_PROGBITS (0x1)33// CHECK-NEXT: Type: SHT_PROGBITS (0x1)
...@@ -46,7 +46,7 @@...@@ -46,7 +46,7 @@
46// CHECK-NEXT: ]46// CHECK-NEXT: ]
47// CHECK-NEXT: Address: 0x1000447// CHECK-NEXT: Address: 0x10004
48// CHECK-NEXT: Offset: 0x1000448// CHECK-NEXT: Offset: 0x10004
49// CHECK-NEXT: Size: 1249// CHECK-NEXT: Size: 24
5050
5151
52.data52.data
...@@ -54,12 +54,12 @@...@@ -54,12 +54,12 @@
5454
55.section foo,"aw"55.section foo,"aw"
56foof:56foof:
57.long foof57.quad foof
58.long bar-5358.quad bar-53
59.long bar59.quad bar
6060
61.section x,"a"61.section x,"a"
62.zero 6498062.zero 65036
6363
64.section barr,"a"64.section barr,"a"
65.p2align 165.p2align 1
deps/lld/test/ELF/pack-dyn-relocs-tls-aarch64.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.o3// 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.so4// RUN: ld.lld -shared --pack-dyn-relocs=android %t.o -o %t.so
5// RUN: llvm-readobj -relocations %t.so | FileCheck %s5// RUN: llvm-readobj -r %t.so | FileCheck %s
66
7// Bug 37841: Symbol::getVA must work on TLS symbols during the layout loop in7// Bug 37841: Symbol::getVA must work on TLS symbols during the layout loop in
8// finalizeSections.8// finalizeSections.
deps/lld/test/ELF/pack-dyn-relocs-tls-x86-64.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
22
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o3// 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.so4// RUN: ld.lld -shared --pack-dyn-relocs=android %t.o -o %t.so
5// RUN: llvm-readobj -relocations %t.so | FileCheck %s5// RUN: llvm-readobj -r %t.so | FileCheck %s
66
7// Bug 37841: Symbol::getVA must work on TLS symbols during the layout loop in7// 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 to8// finalizeSections. This test uses an atypical IE access in a shared object to
deps/lld/test/ELF/pack-dyn-relocs.s+192-192
...@@ -4,45 +4,45 @@...@@ -4,45 +4,45 @@
4// RUN: ld.lld -shared %t.a32.so.o -o %t.a32.so4// RUN: ld.lld -shared %t.a32.so.o -o %t.a32.so
5// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.a325// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.a32
6// RUN: ld.lld -pie --pack-dyn-relocs=none %t.a32 %t.a32.so -o %t2.a326// RUN: ld.lld -pie --pack-dyn-relocs=none %t.a32 %t.a32.so -o %t2.a32
7// RUN: llvm-readobj -relocations %t2.a32 | FileCheck --check-prefix=UNPACKED32 %s7// RUN: llvm-readobj -r %t2.a32 | FileCheck --check-prefix=UNPACKED32 %s
88
9// Unpacked should have the relative relocations in their natural order.9// Unpacked should have the relative relocations in their natural order.
10// UNPACKED32: Section ({{.+}}) .rel.dyn {10// UNPACKED32: Section ({{.+}}) .rel.dyn {
11// UNPACKED32-NEXT: 0x1000 R_ARM_RELATIVE - 0x011// UNPACKED32-NEXT: 0x2000 R_ARM_RELATIVE - 0x0
12// UNPACKED32-NEXT: 0x1004 R_ARM_RELATIVE - 0x012// UNPACKED32-NEXT: 0x2004 R_ARM_RELATIVE - 0x0
13// UNPACKED32-NEXT: 0x1008 R_ARM_RELATIVE - 0x013// UNPACKED32-NEXT: 0x2008 R_ARM_RELATIVE - 0x0
14// UNPACKED32-NEXT: 0x100C R_ARM_RELATIVE - 0x014// UNPACKED32-NEXT: 0x200C R_ARM_RELATIVE - 0x0
15// UNPACKED32-NEXT: 0x1010 R_ARM_RELATIVE - 0x015// UNPACKED32-NEXT: 0x2010 R_ARM_RELATIVE - 0x0
16// UNPACKED32-NEXT: 0x1014 R_ARM_RELATIVE - 0x016// UNPACKED32-NEXT: 0x2014 R_ARM_RELATIVE - 0x0
17// UNPACKED32-NEXT: 0x1018 R_ARM_RELATIVE - 0x017// UNPACKED32-NEXT: 0x2018 R_ARM_RELATIVE - 0x0
18// UNPACKED32-NEXT: 0x101C R_ARM_RELATIVE - 0x018// UNPACKED32-NEXT: 0x201C R_ARM_RELATIVE - 0x0
1919
20// UNPACKED32-NEXT: 0x1024 R_ARM_RELATIVE - 0x020// UNPACKED32-NEXT: 0x2024 R_ARM_RELATIVE - 0x0
21// UNPACKED32-NEXT: 0x1028 R_ARM_RELATIVE - 0x021// UNPACKED32-NEXT: 0x2028 R_ARM_RELATIVE - 0x0
22// UNPACKED32-NEXT: 0x102C R_ARM_RELATIVE - 0x022// UNPACKED32-NEXT: 0x202C R_ARM_RELATIVE - 0x0
23// UNPACKED32-NEXT: 0x1030 R_ARM_RELATIVE - 0x023// UNPACKED32-NEXT: 0x2030 R_ARM_RELATIVE - 0x0
24// UNPACKED32-NEXT: 0x1034 R_ARM_RELATIVE - 0x024// UNPACKED32-NEXT: 0x2034 R_ARM_RELATIVE - 0x0
25// UNPACKED32-NEXT: 0x1038 R_ARM_RELATIVE - 0x025// UNPACKED32-NEXT: 0x2038 R_ARM_RELATIVE - 0x0
26// UNPACKED32-NEXT: 0x103C R_ARM_RELATIVE - 0x026// UNPACKED32-NEXT: 0x203C R_ARM_RELATIVE - 0x0
2727
28// UNPACKED32-NEXT: 0x1044 R_ARM_RELATIVE - 0x028// UNPACKED32-NEXT: 0x2044 R_ARM_RELATIVE - 0x0
29// UNPACKED32-NEXT: 0x1048 R_ARM_RELATIVE - 0x029// UNPACKED32-NEXT: 0x2048 R_ARM_RELATIVE - 0x0
30// UNPACKED32-NEXT: 0x104C R_ARM_RELATIVE - 0x030// UNPACKED32-NEXT: 0x204C R_ARM_RELATIVE - 0x0
31// UNPACKED32-NEXT: 0x1050 R_ARM_RELATIVE - 0x031// UNPACKED32-NEXT: 0x2050 R_ARM_RELATIVE - 0x0
32// UNPACKED32-NEXT: 0x1054 R_ARM_RELATIVE - 0x032// UNPACKED32-NEXT: 0x2054 R_ARM_RELATIVE - 0x0
33// UNPACKED32-NEXT: 0x1058 R_ARM_RELATIVE - 0x033// UNPACKED32-NEXT: 0x2058 R_ARM_RELATIVE - 0x0
34// UNPACKED32-NEXT: 0x105C R_ARM_RELATIVE - 0x034// UNPACKED32-NEXT: 0x205C R_ARM_RELATIVE - 0x0
35// UNPACKED32-NEXT: 0x1060 R_ARM_RELATIVE - 0x035// UNPACKED32-NEXT: 0x2060 R_ARM_RELATIVE - 0x0
36// UNPACKED32-NEXT: 0x1064 R_ARM_RELATIVE - 0x036// UNPACKED32-NEXT: 0x2064 R_ARM_RELATIVE - 0x0
3737
38// UNPACKED32-NEXT: 0x1069 R_ARM_RELATIVE - 0x038// UNPACKED32-NEXT: 0x2069 R_ARM_RELATIVE - 0x0
39// UNPACKED32-NEXT: 0x1020 R_ARM_ABS32 bar2 0x039// UNPACKED32-NEXT: 0x2020 R_ARM_ABS32 bar2 0x0
40// UNPACKED32-NEXT: 0x1040 R_ARM_ABS32 zed2 0x040// UNPACKED32-NEXT: 0x2040 R_ARM_ABS32 zed2 0x0
41// UNPACKED32-NEXT: }41// UNPACKED32-NEXT: }
4242
43// RUN: ld.lld -pie --pack-dyn-relocs=android %t.a32 %t.a32.so -o %t3.a3243// RUN: ld.lld -pie --pack-dyn-relocs=android %t.a32 %t.a32.so -o %t3.a32
44// RUN: llvm-readobj -s -dynamic-table %t3.a32 | FileCheck --check-prefix=ANDROID32-HEADERS %s44// RUN: llvm-readobj -S --dynamic-table %t3.a32 | FileCheck --check-prefix=ANDROID32-HEADERS %s
45// RUN: llvm-readobj -relocations %t3.a32 | FileCheck --check-prefix=ANDROID32 %s45// RUN: llvm-readobj -r %t3.a32 | FileCheck --check-prefix=ANDROID32 %s
4646
47// ANDROID32-HEADERS: Index: 147// ANDROID32-HEADERS: Index: 1
48// ANDROID32-HEADERS-NEXT: Name: .dynsym48// ANDROID32-HEADERS-NEXT: Name: .dynsym
...@@ -66,42 +66,42 @@...@@ -66,42 +66,42 @@
66// Packed should have the larger groups of relative relocations first,66// Packed should have the larger groups of relative relocations first,
67// i.e. the 8 and 9 followed by the 7.67// i.e. the 8 and 9 followed by the 7.
68// ANDROID32: Section ({{.+}}) .rel.dyn {68// ANDROID32: Section ({{.+}}) .rel.dyn {
69// ANDROID32-NEXT: 0x1000 R_ARM_RELATIVE - 0x069// ANDROID32-NEXT: 0x2000 R_ARM_RELATIVE - 0x0
70// ANDROID32-NEXT: 0x1004 R_ARM_RELATIVE - 0x070// ANDROID32-NEXT: 0x2004 R_ARM_RELATIVE - 0x0
71// ANDROID32-NEXT: 0x1008 R_ARM_RELATIVE - 0x071// ANDROID32-NEXT: 0x2008 R_ARM_RELATIVE - 0x0
72// ANDROID32-NEXT: 0x100C R_ARM_RELATIVE - 0x072// ANDROID32-NEXT: 0x200C R_ARM_RELATIVE - 0x0
73// ANDROID32-NEXT: 0x1010 R_ARM_RELATIVE - 0x073// ANDROID32-NEXT: 0x2010 R_ARM_RELATIVE - 0x0
74// ANDROID32-NEXT: 0x1014 R_ARM_RELATIVE - 0x074// ANDROID32-NEXT: 0x2014 R_ARM_RELATIVE - 0x0
75// ANDROID32-NEXT: 0x1018 R_ARM_RELATIVE - 0x075// ANDROID32-NEXT: 0x2018 R_ARM_RELATIVE - 0x0
76// ANDROID32-NEXT: 0x101C R_ARM_RELATIVE - 0x076// ANDROID32-NEXT: 0x201C R_ARM_RELATIVE - 0x0
7777
78// ANDROID32-NEXT: 0x1044 R_ARM_RELATIVE - 0x078// ANDROID32-NEXT: 0x2044 R_ARM_RELATIVE - 0x0
79// ANDROID32-NEXT: 0x1048 R_ARM_RELATIVE - 0x079// ANDROID32-NEXT: 0x2048 R_ARM_RELATIVE - 0x0
80// ANDROID32-NEXT: 0x104C R_ARM_RELATIVE - 0x080// ANDROID32-NEXT: 0x204C R_ARM_RELATIVE - 0x0
81// ANDROID32-NEXT: 0x1050 R_ARM_RELATIVE - 0x081// ANDROID32-NEXT: 0x2050 R_ARM_RELATIVE - 0x0
82// ANDROID32-NEXT: 0x1054 R_ARM_RELATIVE - 0x082// ANDROID32-NEXT: 0x2054 R_ARM_RELATIVE - 0x0
83// ANDROID32-NEXT: 0x1058 R_ARM_RELATIVE - 0x083// ANDROID32-NEXT: 0x2058 R_ARM_RELATIVE - 0x0
84// ANDROID32-NEXT: 0x105C R_ARM_RELATIVE - 0x084// ANDROID32-NEXT: 0x205C R_ARM_RELATIVE - 0x0
85// ANDROID32-NEXT: 0x1060 R_ARM_RELATIVE - 0x085// ANDROID32-NEXT: 0x2060 R_ARM_RELATIVE - 0x0
86// ANDROID32-NEXT: 0x1064 R_ARM_RELATIVE - 0x086// ANDROID32-NEXT: 0x2064 R_ARM_RELATIVE - 0x0
8787
88// ANDROID32-NEXT: 0x1024 R_ARM_RELATIVE - 0x088// ANDROID32-NEXT: 0x2024 R_ARM_RELATIVE - 0x0
89// ANDROID32-NEXT: 0x1028 R_ARM_RELATIVE - 0x089// ANDROID32-NEXT: 0x2028 R_ARM_RELATIVE - 0x0
90// ANDROID32-NEXT: 0x102C R_ARM_RELATIVE - 0x090// ANDROID32-NEXT: 0x202C R_ARM_RELATIVE - 0x0
91// ANDROID32-NEXT: 0x1030 R_ARM_RELATIVE - 0x091// ANDROID32-NEXT: 0x2030 R_ARM_RELATIVE - 0x0
92// ANDROID32-NEXT: 0x1034 R_ARM_RELATIVE - 0x092// ANDROID32-NEXT: 0x2034 R_ARM_RELATIVE - 0x0
93// ANDROID32-NEXT: 0x1038 R_ARM_RELATIVE - 0x093// ANDROID32-NEXT: 0x2038 R_ARM_RELATIVE - 0x0
94// ANDROID32-NEXT: 0x103C R_ARM_RELATIVE - 0x094// ANDROID32-NEXT: 0x203C R_ARM_RELATIVE - 0x0
9595
96// ANDROID32-NEXT: 0x1069 R_ARM_RELATIVE - 0x096// ANDROID32-NEXT: 0x2069 R_ARM_RELATIVE - 0x0
97// ANDROID32-NEXT: 0x1020 R_ARM_ABS32 bar2 0x097// ANDROID32-NEXT: 0x2020 R_ARM_ABS32 bar2 0x0
98// ANDROID32-NEXT: 0x1040 R_ARM_ABS32 zed2 0x098// ANDROID32-NEXT: 0x2040 R_ARM_ABS32 zed2 0x0
99// ANDROID32-NEXT: }99// ANDROID32-NEXT: }
100100
101// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a32 %t.a32.so -o %t4.a32101// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a32 %t.a32.so -o %t4.a32
102// RUN: llvm-readobj -s -dynamic-table %t4.a32 | FileCheck --check-prefix=RELR32-HEADERS %s102// RUN: llvm-readobj -S --dynamic-table %t4.a32 | FileCheck --check-prefix=RELR32-HEADERS %s
103// RUN: llvm-readobj -relocations -raw-relr %t4.a32 | FileCheck --check-prefix=RAW-RELR32 %s103// RUN: llvm-readobj -r --raw-relr %t4.a32 | FileCheck --check-prefix=RAW-RELR32 %s
104// RUN: llvm-readobj -relocations %t4.a32 | FileCheck --check-prefix=RELR32 %s104// RUN: llvm-readobj -r %t4.a32 | FileCheck --check-prefix=RELR32 %s
105105
106// RELR32-HEADERS: Index: 1106// RELR32-HEADERS: Index: 1
107// RELR32-HEADERS-NEXT: Name: .dynsym107// RELR32-HEADERS-NEXT: Name: .dynsym
...@@ -126,7 +126,7 @@...@@ -126,7 +126,7 @@
126// SHT_RELR section contains address/bitmap entries126// SHT_RELR section contains address/bitmap entries
127// encoding the offsets for relative relocation.127// encoding the offsets for relative relocation.
128// RAW-RELR32: Section ({{.+}}) .relr.dyn {128// RAW-RELR32: Section ({{.+}}) .relr.dyn {
129// RAW-RELR32-NEXT: 0x1000129// RAW-RELR32-NEXT: 0x2000
130// RAW-RELR32-NEXT: 0x3FEFEFF130// RAW-RELR32-NEXT: 0x3FEFEFF
131// RAW-RELR32-NEXT: }131// RAW-RELR32-NEXT: }
132132
...@@ -134,81 +134,81 @@...@@ -134,81 +134,81 @@
134// but contains only the relative relocations.134// but contains only the relative relocations.
135// Any relative relocations with odd offset stay in SHT_REL.135// Any relative relocations with odd offset stay in SHT_REL.
136// RELR32: Section ({{.+}}) .rel.dyn {136// RELR32: Section ({{.+}}) .rel.dyn {
137// RELR32-NEXT: 0x1069 R_ARM_RELATIVE - 0x0137// RELR32-NEXT: 0x2069 R_ARM_RELATIVE - 0x0
138// RELR32-NEXT: 0x1020 R_ARM_ABS32 bar2 0x0138// RELR32-NEXT: 0x2020 R_ARM_ABS32 bar2 0x0
139// RELR32-NEXT: 0x1040 R_ARM_ABS32 zed2 0x0139// RELR32-NEXT: 0x2040 R_ARM_ABS32 zed2 0x0
140// RELR32-NEXT: }140// RELR32-NEXT: }
141// RELR32-NEXT: Section ({{.+}}) .relr.dyn {141// RELR32-NEXT: Section ({{.+}}) .relr.dyn {
142// RELR32-NEXT: 0x1000 R_ARM_RELATIVE - 0x0142// RELR32-NEXT: 0x2000 R_ARM_RELATIVE - 0x0
143// RELR32-NEXT: 0x1004 R_ARM_RELATIVE - 0x0143// RELR32-NEXT: 0x2004 R_ARM_RELATIVE - 0x0
144// RELR32-NEXT: 0x1008 R_ARM_RELATIVE - 0x0144// RELR32-NEXT: 0x2008 R_ARM_RELATIVE - 0x0
145// RELR32-NEXT: 0x100C R_ARM_RELATIVE - 0x0145// RELR32-NEXT: 0x200C R_ARM_RELATIVE - 0x0
146// RELR32-NEXT: 0x1010 R_ARM_RELATIVE - 0x0146// RELR32-NEXT: 0x2010 R_ARM_RELATIVE - 0x0
147// RELR32-NEXT: 0x1014 R_ARM_RELATIVE - 0x0147// RELR32-NEXT: 0x2014 R_ARM_RELATIVE - 0x0
148// RELR32-NEXT: 0x1018 R_ARM_RELATIVE - 0x0148// RELR32-NEXT: 0x2018 R_ARM_RELATIVE - 0x0
149// RELR32-NEXT: 0x101C R_ARM_RELATIVE - 0x0149// RELR32-NEXT: 0x201C R_ARM_RELATIVE - 0x0
150150
151// RELR32-NEXT: 0x1024 R_ARM_RELATIVE - 0x0151// RELR32-NEXT: 0x2024 R_ARM_RELATIVE - 0x0
152// RELR32-NEXT: 0x1028 R_ARM_RELATIVE - 0x0152// RELR32-NEXT: 0x2028 R_ARM_RELATIVE - 0x0
153// RELR32-NEXT: 0x102C R_ARM_RELATIVE - 0x0153// RELR32-NEXT: 0x202C R_ARM_RELATIVE - 0x0
154// RELR32-NEXT: 0x1030 R_ARM_RELATIVE - 0x0154// RELR32-NEXT: 0x2030 R_ARM_RELATIVE - 0x0
155// RELR32-NEXT: 0x1034 R_ARM_RELATIVE - 0x0155// RELR32-NEXT: 0x2034 R_ARM_RELATIVE - 0x0
156// RELR32-NEXT: 0x1038 R_ARM_RELATIVE - 0x0156// RELR32-NEXT: 0x2038 R_ARM_RELATIVE - 0x0
157// RELR32-NEXT: 0x103C R_ARM_RELATIVE - 0x0157// RELR32-NEXT: 0x203C R_ARM_RELATIVE - 0x0
158158
159// RELR32-NEXT: 0x1044 R_ARM_RELATIVE - 0x0159// RELR32-NEXT: 0x2044 R_ARM_RELATIVE - 0x0
160// RELR32-NEXT: 0x1048 R_ARM_RELATIVE - 0x0160// RELR32-NEXT: 0x2048 R_ARM_RELATIVE - 0x0
161// RELR32-NEXT: 0x104C R_ARM_RELATIVE - 0x0161// RELR32-NEXT: 0x204C R_ARM_RELATIVE - 0x0
162// RELR32-NEXT: 0x1050 R_ARM_RELATIVE - 0x0162// RELR32-NEXT: 0x2050 R_ARM_RELATIVE - 0x0
163// RELR32-NEXT: 0x1054 R_ARM_RELATIVE - 0x0163// RELR32-NEXT: 0x2054 R_ARM_RELATIVE - 0x0
164// RELR32-NEXT: 0x1058 R_ARM_RELATIVE - 0x0164// RELR32-NEXT: 0x2058 R_ARM_RELATIVE - 0x0
165// RELR32-NEXT: 0x105C R_ARM_RELATIVE - 0x0165// RELR32-NEXT: 0x205C R_ARM_RELATIVE - 0x0
166// RELR32-NEXT: 0x1060 R_ARM_RELATIVE - 0x0166// RELR32-NEXT: 0x2060 R_ARM_RELATIVE - 0x0
167// RELR32-NEXT: 0x1064 R_ARM_RELATIVE - 0x0167// RELR32-NEXT: 0x2064 R_ARM_RELATIVE - 0x0
168// RELR32-NEXT: }168// RELR32-NEXT: }
169169
170// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/shared2.s -o %t.a64.so.o170// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %p/Inputs/shared2.s -o %t.a64.so.o
171// RUN: ld.lld -shared %t.a64.so.o -o %t.a64.so171// RUN: ld.lld -shared %t.a64.so.o -o %t.a64.so
172// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.a64172// RUN: llvm-mc -filetype=obj -triple=aarch64-unknown-linux %s -o %t.a64
173// RUN: ld.lld -pie --pack-dyn-relocs=none %t.a64 %t.a64.so -o %t2.a64173// RUN: ld.lld -pie --pack-dyn-relocs=none %t.a64 %t.a64.so -o %t2.a64
174// RUN: llvm-readobj -relocations %t2.a64 | FileCheck --check-prefix=UNPACKED64 %s174// RUN: llvm-readobj -r %t2.a64 | FileCheck --check-prefix=UNPACKED64 %s
175175
176// UNPACKED64: Section ({{.+}}) .rela.dyn {176// UNPACKED64: Section ({{.+}}) .rela.dyn {
177// UNPACKED64-NEXT: 0x10000 R_AARCH64_RELATIVE - 0x1177// UNPACKED64-NEXT: 0x20000 R_AARCH64_RELATIVE - 0x1
178// UNPACKED64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x2178// UNPACKED64-NEXT: 0x20008 R_AARCH64_RELATIVE - 0x2
179// UNPACKED64-NEXT: 0x10010 R_AARCH64_RELATIVE - 0x3179// UNPACKED64-NEXT: 0x20010 R_AARCH64_RELATIVE - 0x3
180// UNPACKED64-NEXT: 0x10018 R_AARCH64_RELATIVE - 0x4180// UNPACKED64-NEXT: 0x20018 R_AARCH64_RELATIVE - 0x4
181// UNPACKED64-NEXT: 0x10020 R_AARCH64_RELATIVE - 0x5181// UNPACKED64-NEXT: 0x20020 R_AARCH64_RELATIVE - 0x5
182// UNPACKED64-NEXT: 0x10028 R_AARCH64_RELATIVE - 0x6182// UNPACKED64-NEXT: 0x20028 R_AARCH64_RELATIVE - 0x6
183// UNPACKED64-NEXT: 0x10030 R_AARCH64_RELATIVE - 0x7183// UNPACKED64-NEXT: 0x20030 R_AARCH64_RELATIVE - 0x7
184// UNPACKED64-NEXT: 0x10038 R_AARCH64_RELATIVE - 0x8184// UNPACKED64-NEXT: 0x20038 R_AARCH64_RELATIVE - 0x8
185185
186// UNPACKED64-NEXT: 0x10048 R_AARCH64_RELATIVE - 0x1186// UNPACKED64-NEXT: 0x20048 R_AARCH64_RELATIVE - 0x1
187// UNPACKED64-NEXT: 0x10050 R_AARCH64_RELATIVE - 0x2187// UNPACKED64-NEXT: 0x20050 R_AARCH64_RELATIVE - 0x2
188// UNPACKED64-NEXT: 0x10058 R_AARCH64_RELATIVE - 0x3188// UNPACKED64-NEXT: 0x20058 R_AARCH64_RELATIVE - 0x3
189// UNPACKED64-NEXT: 0x10060 R_AARCH64_RELATIVE - 0x4189// UNPACKED64-NEXT: 0x20060 R_AARCH64_RELATIVE - 0x4
190// UNPACKED64-NEXT: 0x10068 R_AARCH64_RELATIVE - 0x5190// UNPACKED64-NEXT: 0x20068 R_AARCH64_RELATIVE - 0x5
191// UNPACKED64-NEXT: 0x10070 R_AARCH64_RELATIVE - 0x6191// UNPACKED64-NEXT: 0x20070 R_AARCH64_RELATIVE - 0x6
192// UNPACKED64-NEXT: 0x10078 R_AARCH64_RELATIVE - 0x7192// UNPACKED64-NEXT: 0x20078 R_AARCH64_RELATIVE - 0x7
193193
194// UNPACKED64-NEXT: 0x10088 R_AARCH64_RELATIVE - 0x1194// UNPACKED64-NEXT: 0x20088 R_AARCH64_RELATIVE - 0x1
195// UNPACKED64-NEXT: 0x10090 R_AARCH64_RELATIVE - 0x2195// UNPACKED64-NEXT: 0x20090 R_AARCH64_RELATIVE - 0x2
196// UNPACKED64-NEXT: 0x10098 R_AARCH64_RELATIVE - 0x3196// UNPACKED64-NEXT: 0x20098 R_AARCH64_RELATIVE - 0x3
197// UNPACKED64-NEXT: 0x100A0 R_AARCH64_RELATIVE - 0x4197// UNPACKED64-NEXT: 0x200A0 R_AARCH64_RELATIVE - 0x4
198// UNPACKED64-NEXT: 0x100A8 R_AARCH64_RELATIVE - 0x5198// UNPACKED64-NEXT: 0x200A8 R_AARCH64_RELATIVE - 0x5
199// UNPACKED64-NEXT: 0x100B0 R_AARCH64_RELATIVE - 0x6199// UNPACKED64-NEXT: 0x200B0 R_AARCH64_RELATIVE - 0x6
200// UNPACKED64-NEXT: 0x100B8 R_AARCH64_RELATIVE - 0x7200// UNPACKED64-NEXT: 0x200B8 R_AARCH64_RELATIVE - 0x7
201// UNPACKED64-NEXT: 0x100C0 R_AARCH64_RELATIVE - 0x8201// UNPACKED64-NEXT: 0x200C0 R_AARCH64_RELATIVE - 0x8
202// UNPACKED64-NEXT: 0x100C8 R_AARCH64_RELATIVE - 0x9202// UNPACKED64-NEXT: 0x200C8 R_AARCH64_RELATIVE - 0x9
203203
204// UNPACKED64-NEXT: 0x100D1 R_AARCH64_RELATIVE - 0xA204// UNPACKED64-NEXT: 0x200D1 R_AARCH64_RELATIVE - 0xA
205// UNPACKED64-NEXT: 0x10040 R_AARCH64_ABS64 bar2 0x1205// UNPACKED64-NEXT: 0x20040 R_AARCH64_ABS64 bar2 0x1
206// UNPACKED64-NEXT: 0x10080 R_AARCH64_ABS64 zed2 0x0206// UNPACKED64-NEXT: 0x20080 R_AARCH64_ABS64 zed2 0x0
207// UNPACKED64-NEXT: }207// UNPACKED64-NEXT: }
208208
209// RUN: ld.lld -pie --pack-dyn-relocs=android %t.a64 %t.a64.so -o %t3.a64209// RUN: ld.lld -pie --pack-dyn-relocs=android %t.a64 %t.a64.so -o %t3.a64
210// RUN: llvm-readobj -s -dynamic-table %t3.a64 | FileCheck --check-prefix=ANDROID64-HEADERS %s210// RUN: llvm-readobj -S --dynamic-table %t3.a64 | FileCheck --check-prefix=ANDROID64-HEADERS %s
211// RUN: llvm-readobj -relocations %t3.a64 | FileCheck --check-prefix=ANDROID64 %s211// RUN: llvm-readobj -r %t3.a64 | FileCheck --check-prefix=ANDROID64 %s
212212
213// ANDROID64-HEADERS: Index: 1213// ANDROID64-HEADERS: Index: 1
214// ANDROID64-HEADERS-NEXT: Name: .dynsym214// ANDROID64-HEADERS-NEXT: Name: .dynsym
...@@ -230,42 +230,42 @@...@@ -230,42 +230,42 @@
230// ANDROID64-HEADERS: 0x0000000060000012 ANDROID_RELASZ [[SIZE]]230// ANDROID64-HEADERS: 0x0000000060000012 ANDROID_RELASZ [[SIZE]]
231231
232// ANDROID64: Section ({{.+}}) .rela.dyn {232// ANDROID64: Section ({{.+}}) .rela.dyn {
233// ANDROID64-NEXT: 0x10000 R_AARCH64_RELATIVE - 0x1233// ANDROID64-NEXT: 0x20000 R_AARCH64_RELATIVE - 0x1
234// ANDROID64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x2234// ANDROID64-NEXT: 0x20008 R_AARCH64_RELATIVE - 0x2
235// ANDROID64-NEXT: 0x10010 R_AARCH64_RELATIVE - 0x3235// ANDROID64-NEXT: 0x20010 R_AARCH64_RELATIVE - 0x3
236// ANDROID64-NEXT: 0x10018 R_AARCH64_RELATIVE - 0x4236// ANDROID64-NEXT: 0x20018 R_AARCH64_RELATIVE - 0x4
237// ANDROID64-NEXT: 0x10020 R_AARCH64_RELATIVE - 0x5237// ANDROID64-NEXT: 0x20020 R_AARCH64_RELATIVE - 0x5
238// ANDROID64-NEXT: 0x10028 R_AARCH64_RELATIVE - 0x6238// ANDROID64-NEXT: 0x20028 R_AARCH64_RELATIVE - 0x6
239// ANDROID64-NEXT: 0x10030 R_AARCH64_RELATIVE - 0x7239// ANDROID64-NEXT: 0x20030 R_AARCH64_RELATIVE - 0x7
240// ANDROID64-NEXT: 0x10038 R_AARCH64_RELATIVE - 0x8240// ANDROID64-NEXT: 0x20038 R_AARCH64_RELATIVE - 0x8
241241
242// ANDROID64-NEXT: 0x10088 R_AARCH64_RELATIVE - 0x1242// ANDROID64-NEXT: 0x20088 R_AARCH64_RELATIVE - 0x1
243// ANDROID64-NEXT: 0x10090 R_AARCH64_RELATIVE - 0x2243// ANDROID64-NEXT: 0x20090 R_AARCH64_RELATIVE - 0x2
244// ANDROID64-NEXT: 0x10098 R_AARCH64_RELATIVE - 0x3244// ANDROID64-NEXT: 0x20098 R_AARCH64_RELATIVE - 0x3
245// ANDROID64-NEXT: 0x100A0 R_AARCH64_RELATIVE - 0x4245// ANDROID64-NEXT: 0x200A0 R_AARCH64_RELATIVE - 0x4
246// ANDROID64-NEXT: 0x100A8 R_AARCH64_RELATIVE - 0x5246// ANDROID64-NEXT: 0x200A8 R_AARCH64_RELATIVE - 0x5
247// ANDROID64-NEXT: 0x100B0 R_AARCH64_RELATIVE - 0x6247// ANDROID64-NEXT: 0x200B0 R_AARCH64_RELATIVE - 0x6
248// ANDROID64-NEXT: 0x100B8 R_AARCH64_RELATIVE - 0x7248// ANDROID64-NEXT: 0x200B8 R_AARCH64_RELATIVE - 0x7
249// ANDROID64-NEXT: 0x100C0 R_AARCH64_RELATIVE - 0x8249// ANDROID64-NEXT: 0x200C0 R_AARCH64_RELATIVE - 0x8
250// ANDROID64-NEXT: 0x100C8 R_AARCH64_RELATIVE - 0x9250// ANDROID64-NEXT: 0x200C8 R_AARCH64_RELATIVE - 0x9
251251
252// ANDROID64-NEXT: 0x10048 R_AARCH64_RELATIVE - 0x1252// ANDROID64-NEXT: 0x20048 R_AARCH64_RELATIVE - 0x1
253// ANDROID64-NEXT: 0x10050 R_AARCH64_RELATIVE - 0x2253// ANDROID64-NEXT: 0x20050 R_AARCH64_RELATIVE - 0x2
254// ANDROID64-NEXT: 0x10058 R_AARCH64_RELATIVE - 0x3254// ANDROID64-NEXT: 0x20058 R_AARCH64_RELATIVE - 0x3
255// ANDROID64-NEXT: 0x10060 R_AARCH64_RELATIVE - 0x4255// ANDROID64-NEXT: 0x20060 R_AARCH64_RELATIVE - 0x4
256// ANDROID64-NEXT: 0x10068 R_AARCH64_RELATIVE - 0x5256// ANDROID64-NEXT: 0x20068 R_AARCH64_RELATIVE - 0x5
257// ANDROID64-NEXT: 0x10070 R_AARCH64_RELATIVE - 0x6257// ANDROID64-NEXT: 0x20070 R_AARCH64_RELATIVE - 0x6
258// ANDROID64-NEXT: 0x10078 R_AARCH64_RELATIVE - 0x7258// ANDROID64-NEXT: 0x20078 R_AARCH64_RELATIVE - 0x7
259259
260// ANDROID64-NEXT: 0x100D1 R_AARCH64_RELATIVE - 0xA260// ANDROID64-NEXT: 0x200D1 R_AARCH64_RELATIVE - 0xA
261// ANDROID64-NEXT: 0x10040 R_AARCH64_ABS64 bar2 0x1261// ANDROID64-NEXT: 0x20040 R_AARCH64_ABS64 bar2 0x1
262// ANDROID64-NEXT: 0x10080 R_AARCH64_ABS64 zed2 0x0262// ANDROID64-NEXT: 0x20080 R_AARCH64_ABS64 zed2 0x0
263// ANDROID64-NEXT: }263// ANDROID64-NEXT: }
264264
265// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a64 %t.a64.so -o %t4.a64265// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.a64 %t.a64.so -o %t4.a64
266// RUN: llvm-readobj -s -dynamic-table %t4.a64 | FileCheck --check-prefix=RELR64-HEADERS %s266// RUN: llvm-readobj -S --dynamic-table %t4.a64 | FileCheck --check-prefix=RELR64-HEADERS %s
267// RUN: llvm-readobj -relocations -raw-relr %t4.a64 | FileCheck --check-prefix=RAW-RELR64 %s267// RUN: llvm-readobj -r --raw-relr %t4.a64 | FileCheck --check-prefix=RAW-RELR64 %s
268// RUN: llvm-readobj -relocations %t4.a64 | FileCheck --check-prefix=RELR64 %s268// RUN: llvm-readobj -r %t4.a64 | FileCheck --check-prefix=RELR64 %s
269269
270// RELR64-HEADERS: Index: 1270// RELR64-HEADERS: Index: 1
271// RELR64-HEADERS-NEXT: Name: .dynsym271// RELR64-HEADERS-NEXT: Name: .dynsym
...@@ -290,7 +290,7 @@...@@ -290,7 +290,7 @@
290// SHT_RELR section contains address/bitmap entries290// SHT_RELR section contains address/bitmap entries
291// encoding the offsets for relative relocation.291// encoding the offsets for relative relocation.
292// RAW-RELR64: Section ({{.+}}) .relr.dyn {292// RAW-RELR64: Section ({{.+}}) .relr.dyn {
293// RAW-RELR64-NEXT: 0x10000293// RAW-RELR64-NEXT: 0x20000
294// RAW-RELR64-NEXT: 0x3FEFEFF294// RAW-RELR64-NEXT: 0x3FEFEFF
295// RAW-RELR64-NEXT: }295// RAW-RELR64-NEXT: }
296296
...@@ -298,37 +298,37 @@...@@ -298,37 +298,37 @@
298// but contains only the relative relocations.298// but contains only the relative relocations.
299// Any relative relocations with odd offset stay in SHT_RELA.299// Any relative relocations with odd offset stay in SHT_RELA.
300// RELR64: Section ({{.+}}) .rela.dyn {300// RELR64: Section ({{.+}}) .rela.dyn {
301// RELR64-NEXT: 0x100D1 R_AARCH64_RELATIVE - 0xA301// RELR64-NEXT: 0x200D1 R_AARCH64_RELATIVE - 0xA
302// RELR64-NEXT: 0x10040 R_AARCH64_ABS64 bar2 0x1302// RELR64-NEXT: 0x20040 R_AARCH64_ABS64 bar2 0x1
303// RELR64-NEXT: 0x10080 R_AARCH64_ABS64 zed2 0x0303// RELR64-NEXT: 0x20080 R_AARCH64_ABS64 zed2 0x0
304// RELR64-NEXT: }304// RELR64-NEXT: }
305// RELR64-NEXT: Section ({{.+}}) .relr.dyn {305// RELR64-NEXT: Section ({{.+}}) .relr.dyn {
306// RELR64-NEXT: 0x10000 R_AARCH64_RELATIVE - 0x0306// RELR64-NEXT: 0x20000 R_AARCH64_RELATIVE - 0x0
307// RELR64-NEXT: 0x10008 R_AARCH64_RELATIVE - 0x0307// RELR64-NEXT: 0x20008 R_AARCH64_RELATIVE - 0x0
308// RELR64-NEXT: 0x10010 R_AARCH64_RELATIVE - 0x0308// RELR64-NEXT: 0x20010 R_AARCH64_RELATIVE - 0x0
309// RELR64-NEXT: 0x10018 R_AARCH64_RELATIVE - 0x0309// RELR64-NEXT: 0x20018 R_AARCH64_RELATIVE - 0x0
310// RELR64-NEXT: 0x10020 R_AARCH64_RELATIVE - 0x0310// RELR64-NEXT: 0x20020 R_AARCH64_RELATIVE - 0x0
311// RELR64-NEXT: 0x10028 R_AARCH64_RELATIVE - 0x0311// RELR64-NEXT: 0x20028 R_AARCH64_RELATIVE - 0x0
312// RELR64-NEXT: 0x10030 R_AARCH64_RELATIVE - 0x0312// RELR64-NEXT: 0x20030 R_AARCH64_RELATIVE - 0x0
313// RELR64-NEXT: 0x10038 R_AARCH64_RELATIVE - 0x0313// RELR64-NEXT: 0x20038 R_AARCH64_RELATIVE - 0x0
314314
315// RELR64-NEXT: 0x10048 R_AARCH64_RELATIVE - 0x0315// RELR64-NEXT: 0x20048 R_AARCH64_RELATIVE - 0x0
316// RELR64-NEXT: 0x10050 R_AARCH64_RELATIVE - 0x0316// RELR64-NEXT: 0x20050 R_AARCH64_RELATIVE - 0x0
317// RELR64-NEXT: 0x10058 R_AARCH64_RELATIVE - 0x0317// RELR64-NEXT: 0x20058 R_AARCH64_RELATIVE - 0x0
318// RELR64-NEXT: 0x10060 R_AARCH64_RELATIVE - 0x0318// RELR64-NEXT: 0x20060 R_AARCH64_RELATIVE - 0x0
319// RELR64-NEXT: 0x10068 R_AARCH64_RELATIVE - 0x0319// RELR64-NEXT: 0x20068 R_AARCH64_RELATIVE - 0x0
320// RELR64-NEXT: 0x10070 R_AARCH64_RELATIVE - 0x0320// RELR64-NEXT: 0x20070 R_AARCH64_RELATIVE - 0x0
321// RELR64-NEXT: 0x10078 R_AARCH64_RELATIVE - 0x0321// RELR64-NEXT: 0x20078 R_AARCH64_RELATIVE - 0x0
322322
323// RELR64-NEXT: 0x10088 R_AARCH64_RELATIVE - 0x0323// RELR64-NEXT: 0x20088 R_AARCH64_RELATIVE - 0x0
324// RELR64-NEXT: 0x10090 R_AARCH64_RELATIVE - 0x0324// RELR64-NEXT: 0x20090 R_AARCH64_RELATIVE - 0x0
325// RELR64-NEXT: 0x10098 R_AARCH64_RELATIVE - 0x0325// RELR64-NEXT: 0x20098 R_AARCH64_RELATIVE - 0x0
326// RELR64-NEXT: 0x100A0 R_AARCH64_RELATIVE - 0x0326// RELR64-NEXT: 0x200A0 R_AARCH64_RELATIVE - 0x0
327// RELR64-NEXT: 0x100A8 R_AARCH64_RELATIVE - 0x0327// RELR64-NEXT: 0x200A8 R_AARCH64_RELATIVE - 0x0
328// RELR64-NEXT: 0x100B0 R_AARCH64_RELATIVE - 0x0328// RELR64-NEXT: 0x200B0 R_AARCH64_RELATIVE - 0x0
329// RELR64-NEXT: 0x100B8 R_AARCH64_RELATIVE - 0x0329// RELR64-NEXT: 0x200B8 R_AARCH64_RELATIVE - 0x0
330// RELR64-NEXT: 0x100C0 R_AARCH64_RELATIVE - 0x0330// RELR64-NEXT: 0x200C0 R_AARCH64_RELATIVE - 0x0
331// RELR64-NEXT: 0x100C8 R_AARCH64_RELATIVE - 0x0331// RELR64-NEXT: 0x200C8 R_AARCH64_RELATIVE - 0x0
332// RELR64-NEXT: }332// RELR64-NEXT: }
333333
334.data334.data
deps/lld/test/ELF/pack-dyn-relocs2.s+36-36
...@@ -5,46 +5,46 @@...@@ -5,46 +5,46 @@
55
6// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o6// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
7// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.o %t.so -o %t.exe7// RUN: ld.lld -pie --pack-dyn-relocs=relr %t.o %t.so -o %t.exe
8// RUN: llvm-readobj -relocations %t.exe | FileCheck %s8// RUN: llvm-readobj -r %t.exe | FileCheck %s
99
10// CHECK: Section (5) .relr.dyn {10// CHECK: Section (5) .relr.dyn {
11// CHECK-NEXT: 0x1000 R_ARM_RELATIVE - 0x011// CHECK-NEXT: 0x2000 R_ARM_RELATIVE - 0x0
12// CHECK-NEXT: 0x1004 R_ARM_RELATIVE - 0x012// CHECK-NEXT: 0x2004 R_ARM_RELATIVE - 0x0
13// CHECK-NEXT: 0x1008 R_ARM_RELATIVE - 0x013// CHECK-NEXT: 0x2008 R_ARM_RELATIVE - 0x0
14// CHECK-NEXT: 0x100C R_ARM_RELATIVE - 0x014// CHECK-NEXT: 0x200C R_ARM_RELATIVE - 0x0
15// CHECK-NEXT: 0x1010 R_ARM_RELATIVE - 0x015// CHECK-NEXT: 0x2010 R_ARM_RELATIVE - 0x0
16// CHECK-NEXT: 0x1014 R_ARM_RELATIVE - 0x016// CHECK-NEXT: 0x2014 R_ARM_RELATIVE - 0x0
17// CHECK-NEXT: 0x1018 R_ARM_RELATIVE - 0x017// CHECK-NEXT: 0x2018 R_ARM_RELATIVE - 0x0
18// CHECK-NEXT: 0x101C R_ARM_RELATIVE - 0x018// CHECK-NEXT: 0x201C R_ARM_RELATIVE - 0x0
19// CHECK-NEXT: 0x1020 R_ARM_RELATIVE - 0x019// CHECK-NEXT: 0x2020 R_ARM_RELATIVE - 0x0
20// CHECK-NEXT: 0x1024 R_ARM_RELATIVE - 0x020// CHECK-NEXT: 0x2024 R_ARM_RELATIVE - 0x0
21// CHECK-NEXT: 0x1028 R_ARM_RELATIVE - 0x021// CHECK-NEXT: 0x2028 R_ARM_RELATIVE - 0x0
22// CHECK-NEXT: 0x102C R_ARM_RELATIVE - 0x022// CHECK-NEXT: 0x202C R_ARM_RELATIVE - 0x0
23// CHECK-NEXT: 0x1030 R_ARM_RELATIVE - 0x023// CHECK-NEXT: 0x2030 R_ARM_RELATIVE - 0x0
24// CHECK-NEXT: 0x1034 R_ARM_RELATIVE - 0x024// CHECK-NEXT: 0x2034 R_ARM_RELATIVE - 0x0
25// CHECK-NEXT: 0x1038 R_ARM_RELATIVE - 0x025// CHECK-NEXT: 0x2038 R_ARM_RELATIVE - 0x0
26// CHECK-NEXT: 0x103C R_ARM_RELATIVE - 0x026// CHECK-NEXT: 0x203C R_ARM_RELATIVE - 0x0
27// CHECK-NEXT: 0x1040 R_ARM_RELATIVE - 0x027// CHECK-NEXT: 0x2040 R_ARM_RELATIVE - 0x0
28// CHECK-NEXT: 0x1044 R_ARM_RELATIVE - 0x028// CHECK-NEXT: 0x2044 R_ARM_RELATIVE - 0x0
29// CHECK-NEXT: 0x1048 R_ARM_RELATIVE - 0x029// CHECK-NEXT: 0x2048 R_ARM_RELATIVE - 0x0
30// CHECK-NEXT: 0x104C R_ARM_RELATIVE - 0x030// CHECK-NEXT: 0x204C R_ARM_RELATIVE - 0x0
31// CHECK-NEXT: 0x1050 R_ARM_RELATIVE - 0x031// CHECK-NEXT: 0x2050 R_ARM_RELATIVE - 0x0
32// CHECK-NEXT: 0x1054 R_ARM_RELATIVE - 0x032// CHECK-NEXT: 0x2054 R_ARM_RELATIVE - 0x0
33// CHECK-NEXT: 0x1058 R_ARM_RELATIVE - 0x033// CHECK-NEXT: 0x2058 R_ARM_RELATIVE - 0x0
34// CHECK-NEXT: 0x105C R_ARM_RELATIVE - 0x034// CHECK-NEXT: 0x205C R_ARM_RELATIVE - 0x0
35// CHECK-NEXT: 0x1060 R_ARM_RELATIVE - 0x035// CHECK-NEXT: 0x2060 R_ARM_RELATIVE - 0x0
36// CHECK-NEXT: 0x1064 R_ARM_RELATIVE - 0x036// CHECK-NEXT: 0x2064 R_ARM_RELATIVE - 0x0
37// CHECK-NEXT: 0x1068 R_ARM_RELATIVE - 0x037// CHECK-NEXT: 0x2068 R_ARM_RELATIVE - 0x0
38// CHECK-NEXT: 0x106C R_ARM_RELATIVE - 0x038// CHECK-NEXT: 0x206C R_ARM_RELATIVE - 0x0
39// CHECK-NEXT: 0x1070 R_ARM_RELATIVE - 0x039// CHECK-NEXT: 0x2070 R_ARM_RELATIVE - 0x0
40// CHECK-NEXT: 0x1074 R_ARM_RELATIVE - 0x040// CHECK-NEXT: 0x2074 R_ARM_RELATIVE - 0x0
41// CHECK-NEXT: 0x1078 R_ARM_RELATIVE - 0x041// CHECK-NEXT: 0x2078 R_ARM_RELATIVE - 0x0
42// CHECK-NEXT: 0x107C R_ARM_RELATIVE - 0x042// CHECK-NEXT: 0x207C R_ARM_RELATIVE - 0x0
43// CHECK-NEXT: 0x1080 R_ARM_RELATIVE - 0x043// CHECK-NEXT: 0x2080 R_ARM_RELATIVE - 0x0
44// CHECK-NEXT: 0x1084 R_ARM_RELATIVE - 0x044// CHECK-NEXT: 0x2084 R_ARM_RELATIVE - 0x0
45// CHECK-NEXT: }45// CHECK-NEXT: }
4646
47// RUN: llvm-readobj -s -dynamic-table %t.exe | FileCheck --check-prefix=HEADER %s47// RUN: llvm-readobj -S --dynamic-table %t.exe | FileCheck --check-prefix=HEADER %s
48// HEADER: 0x00000023 RELRSZ 0xC48// HEADER: 0x00000023 RELRSZ 0xC
4949
50.data50.data
deps/lld/test/ELF/partition-errors.s created+23
...@@ -0,0 +1,23 @@
1// REQUIRES: x86, mips
2// RUN: llvm-mc -triple=x86_64-unknown-linux -filetype=obj -o %t.o %s
3// RUN: echo "SECTIONS {}" > %t.script
4// RUN: not ld.lld --export-dynamic %t.o %t.script 2>&1 | FileCheck %s
5// RUN: echo "PHDRS { text PT_LOAD; }" > %t2.script
6// RUN: not ld.lld --export-dynamic %t.o %t2.script 2>&1 | FileCheck %s
7// RUN: not ld.lld --export-dynamic %t.o --section-start .text=0 2>&1 | FileCheck %s
8// RUN: not ld.lld --export-dynamic %t.o -Ttext=0 2>&1 | FileCheck %s
9// RUN: not ld.lld --export-dynamic %t.o -Tdata=0 2>&1 | FileCheck %s
10// RUN: not ld.lld --export-dynamic %t.o -Tbss=0 2>&1 | FileCheck %s
11
12// RUN: llvm-mc -triple=mipsel-unknown-linux -filetype=obj -o %t2.o %s
13// RUN: not ld.lld --export-dynamic %t2.o 2>&1 | FileCheck %s
14
15// CHECK: error: {{.*}}.o: partitions cannot be used
16
17.section .llvm_sympart.f1,"",@llvm_sympart
18.asciz "part1"
19.quad f1
20
21.text
22.globl f1
23f1:
deps/lld/test/ELF/partition-exidx.s created+49
...@@ -0,0 +1,49 @@
1// Test that exidx output sections are created correctly for each partition.
2
3// REQUIRES: arm
4// RUN: llvm-mc -filetype=obj -triple=armv7a-none-linux-gnueabi %s -o %t.o
5// RUN: ld.lld %t.o -o %t -shared --gc-sections
6
7// RUN: llvm-objcopy --extract-main-partition %t %t0
8// RUN: llvm-objcopy --extract-partition=part1 %t %t1
9
10// Change upper case to lower case so that we can match unwind info (which is dumped
11// in upper case) against program headers (which are dumped in lower case).
12// RUN: llvm-readelf -l --unwind %t0 | tr A-Z a-z | FileCheck %s
13// RUN: llvm-readelf -l --unwind %t1 | tr A-Z a-z | FileCheck %s
14
15// Each file should have one exidx section for its text section and one sentinel.
16// CHECK: sectionoffset: 0x[[EXIDX_OFFSET:.*]]
17// CHECK-NEXT: entries [
18// CHECK-NEXT: entry {
19// CHECK-NEXT: functionaddress: 0x[[TEXT_ADDR:.*]]
20// CHECK-NEXT: model: cantunwind
21// CHECK-NEXT: }
22// CHECK-NEXT: entry {
23// CHECK-NEXT: functionaddress:
24// CHECK-NEXT: model: cantunwind
25// CHECK-NEXT: }
26// CHECK-NEXT: ]
27
28// CHECK: load {{[^ ]*}} 0x{{0*}}[[TEXT_ADDR]] {{.*}} r e
29// CHECK: exidx 0x{{0*}}[[EXIDX_OFFSET]] {{.*}} 0x00010 0x00010 r
30
31.section .llvm_sympart,"",%llvm_sympart
32.asciz "part1"
33.4byte p1
34
35.section .text.p0,"ax",%progbits
36.globl p0
37p0:
38.fnstart
39bx lr
40.cantunwind
41.fnend
42
43.section .text.p1,"ax",%progbits
44.globl p1
45p1:
46.fnstart
47bx lr
48.cantunwind
49.fnend
deps/lld/test/ELF/partition-icf.s created+50
...@@ -0,0 +1,50 @@
1// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
3// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections --icf=all
4// RUN: llvm-readelf -S -s %t | FileCheck %s
5
6// CHECK: [[MAIN:[0-9]+]]] .text
7// CHECK: [[P1:[0-9]+]]] .text
8// CHECK: [[P2:[0-9]+]]] .text
9
10// CHECK: Symbol table '.symtab'
11// CHECK: [[P1]] f1
12// CHECK: [[P2]] f2
13// CHECK: [[MAIN]] g1
14// CHECK: [[MAIN]] g2
15
16.section .llvm_sympart.f1,"",@llvm_sympart
17.asciz "part1"
18.quad f1
19
20.section .llvm_sympart.f2,"",@llvm_sympart
21.asciz "part2"
22.quad f2
23
24.section .llvm_sympart.g1,"",@llvm_sympart
25.asciz "part1"
26.quad g1
27
28.section .llvm_sympart.g2,"",@llvm_sympart
29.asciz "part2"
30.quad g2
31
32.section .text.f1,"ax",@progbits
33.globl f1
34f1:
35.byte 1
36
37.section .text.f2,"ax",@progbits
38.globl f2
39f2:
40.byte 2
41
42.section .text.g1,"ax",@progbits
43.globl g1
44g1:
45.byte 3
46
47.section .text.g2,"ax",@progbits
48.globl g2
49g2:
50.byte 3
deps/lld/test/ELF/partition-move-to-main.s created+44
...@@ -0,0 +1,44 @@
1// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
3// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections
4// RUN: llvm-readelf -S -s %t | FileCheck %s
5
6// Ordinarily, the TLS and IFUNC sections would be split into partitions.
7// Make sure that that didn't happen by checking that there is only one
8// of each section.
9
10// CHECK: .ifunc
11// CHECK: .tdata
12
13// CHECK-NOT: .ifunc
14// CHECK-NOT: .tdata
15
16.section .llvm_sympart.f1,"",@llvm_sympart
17.asciz "part1"
18.quad f1
19
20.section .text._start,"ax",@progbits
21.globl _start
22_start:
23call tls1
24call ifunc1
25
26.section .text.f1,"ax",@progbits
27.globl f1
28f1:
29call tls2
30call ifunc2
31
32.section .ifunc,"ax",@progbits,unique,1
33.type ifunc1 STT_GNU_IFUNC
34ifunc1:
35
36.section .ifunc,"ax",@progbits,unique,2
37.type ifunc2 STT_GNU_IFUNC
38ifunc2:
39
40.section .tdata,"awT",@progbits,unique,1
41tls1:
42
43.section .tdata,"awT",@progbits,unique,2
44tls2:
deps/lld/test/ELF/partition-notes.s created+45
...@@ -0,0 +1,45 @@
1// Test that notes (both from object files and synthetic) are duplicated into
2// each partition.
3
4// REQUIRES: x86
5
6// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
7// RUN: ld.lld %t.o -o %t --shared --gc-sections --build-id=sha1
8
9// RUN: llvm-objcopy --extract-main-partition %t %t0
10// RUN: llvm-objcopy --extract-partition=part1 %t %t1
11
12// RUN: llvm-readelf --all %t0 | FileCheck --check-prefixes=CHECK,PART0 %s
13// RUN: llvm-readelf --all %t1 | FileCheck --check-prefixes=CHECK,PART1 %s
14
15// CHECK: Program Headers:
16// CHECK: NOTE 0x{{0*}}[[NOTE_OFFSET:[^ ]*]]
17
18// CHECK: Displaying notes found at file offset 0x{{0*}}[[NOTE_OFFSET]]
19// CHECK-NEXT: Owner
20// CHECK-NEXT: foo 0x00000004 NT_VERSION (version)
21// CHECK-NEXT: Displaying notes
22// CHECK-NEXT: Owner
23// CHECK-NEXT: GNU 0x00000014 NT_GNU_BUILD_ID (unique build ID bitstring)
24// CHECK-NEXT: Build ID: 0f4d5297cbbe52e4bea558eeb792944670de22e1
25
26.section .llvm_sympart,"",@llvm_sympart
27.asciz "part1"
28.quad p1
29
30.section .data.p0,"aw",@progbits
31.globl p0
32p0:
33
34.section .data.p1,"aw",@progbits
35.globl p1
36p1:
37
38.section .note.obj,"a",@note
39.align 4
40.long 2f-1f
41.long 3f-2f
42.long 1
431: .asciz "foo"
442: .asciz "bar"
453:
deps/lld/test/ELF/partition-pack-dyn-relocs.s created+51
...@@ -0,0 +1,51 @@
1// Test that both Android and RELR packed relocation sections are created
2// correctly for each partition.
3
4// REQUIRES: x86
5
6// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
7// RUN: ld.lld %t.o -o %t --shared --gc-sections --pack-dyn-relocs=android+relr
8
9// RUN: llvm-objcopy --extract-main-partition %t %t0
10// RUN: llvm-objcopy --extract-partition=part1 %t %t1
11
12// RUN: llvm-readelf --all %t0 | FileCheck --check-prefixes=CHECK,PART0 %s
13// RUN: llvm-readelf --all %t1 | FileCheck --check-prefixes=CHECK,PART1 %s
14
15// CHECK: Section Headers:
16// CHECK: .rela.dyn ANDROID_RELA {{0*}}[[ANDROID_RELA_ADDR:[^ ]*]]
17// CHECK: .relr.dyn RELR {{0*}}[[RELR_ADDR:[^ ]*]]
18// CHECK: .data PROGBITS 000000000000[[DATA_SEGMENT:.]]000
19
20// CHECK: Relocation section '.rela.dyn'
21// CHECK-NEXT: Offset
22// PART0-NEXT: 000000000000[[DATA_SEGMENT]]008 {{.*}} R_X86_64_64 000000000000[[DATA_SEGMENT]]000 p0 + 0
23// PART1-NEXT: 000000000000[[DATA_SEGMENT]]008 {{.*}} R_X86_64_64 000000000000[[DATA_SEGMENT]]000 p1 + 0
24// CHECK-EMPTY:
25
26// CHECK: Relocation section '.relr.dyn'
27// CHECK-NEXT: Offset
28// CHECK-NEXT: 000000000000[[DATA_SEGMENT]]000 {{.*}} R_X86_64_RELATIVE
29// CHECK-EMPTY:
30
31// CHECK: Dynamic section
32// CHECK: 0x0000000060000011 (ANDROID_RELA) 0x[[ANDROID_RELA_ADDR]]
33// CHECK: 0x0000000000000024 (RELR) 0x[[RELR_ADDR]]
34
35.section .llvm_sympart,"",@llvm_sympart
36.asciz "part1"
37.quad p1
38
39.section .data.p0,"aw",@progbits
40.align 8
41.globl p0
42p0:
43.quad __ehdr_start
44.quad p0
45
46.section .data.p1,"aw",@progbits
47.align 8
48.globl p1
49p1:
50.quad __ehdr_start
51.quad p1
deps/lld/test/ELF/partition-synthetic-sections.s created+241
...@@ -0,0 +1,241 @@
1// Test that synthetic sections are created correctly for each partition.
2
3// REQUIRES: x86
4
5// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/verneed1.s -o %t1.o
6// RUN: echo "v1 {}; v2 {}; v3 { local: *; };" > %t1.script
7// RUN: ld.lld -shared %t1.o --version-script %t1.script -o %t1.so -soname verneed1.so.0
8
9// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
10// RUN: echo "x1 { global: p0; }; x2 { global: p1; p1alias; };" > %t.script
11// RUN: ld.lld %t.o %t1.so --version-script %t.script -o %t --shared --gc-sections --eh-frame-hdr -soname main.so
12
13// RUN: llvm-objcopy --extract-main-partition %t %t0
14// RUN: llvm-objcopy --extract-partition=part1 %t %t1
15
16// RUN: llvm-readelf --all --unwind %t0 | FileCheck --check-prefixes=CHECK,PART0 %s
17// RUN: llvm-readelf --all --unwind %t1 | FileCheck --check-prefixes=CHECK,PART1 %s
18
19// FIXME: llvm-objcopy does not preserve padding (see pr42145) so for now we
20// check the combined output file.
21// RUN: od -Ax -x %t | FileCheck %s -check-prefix=FILL
22
23// RUN: llvm-objdump -s -j .rodata -j .dynstr %t0 | FileCheck --check-prefix=PART-INDEX %s
24
25// CHECK: Section Headers:
26// CHECK-NEXT: Name
27// CHECK-NEXT: NULL
28// CHECK-NEXT: .dynsym DYNSYM {{0*}}[[DYNSYM_ADDR:[^ ]*]]
29// CHECK-NEXT: .gnu.version VERSYM {{0*}}[[VERSYM_ADDR:[^ ]*]]
30// CHECK-NEXT: .gnu.version_d VERDEF {{0*}}[[VERDEF_ADDR:[^ ]*]]
31// CHECK-NEXT: .gnu.version_r VERNEED {{0*}}[[VERNEED_ADDR:[^ ]*]]
32// CHECK-NEXT: .gnu.hash GNU_HASH {{0*}}[[GNU_HASH_ADDR:[^ ]*]]
33// CHECK-NEXT: .hash HASH {{0*}}[[HASH_ADDR:[^ ]*]]
34// CHECK-NEXT: .dynstr STRTAB {{0*}}[[DYNSTR_ADDR:[^ ]*]]
35// CHECK-NEXT: .rela.dyn RELA {{0*}}[[RELA_DYN_ADDR:[^ ]*]]
36// PART0-NEXT: .rela.plt RELA {{0*}}[[RELA_PLT_ADDR:[^ ]*]]
37// CHECK-NEXT: .eh_frame_hdr PROGBITS {{0*}}[[EH_FRAME_HDR_ADDR:[^ ]*]]
38// CHECK-NEXT: .eh_frame PROGBITS {{0*}}[[EH_FRAME_ADDR:[^ ]*]]
39// PART0-NEXT: .rodata PROGBITS
40// CHECK-NEXT: .text PROGBITS {{0*}}[[TEXT_ADDR:[^ ]*]]
41// PART0-NEXT: .plt PROGBITS
42// PART0-NEXT: .init_array INIT_ARRAY {{0*}}[[INIT_ARRAY_ADDR:[^ ]*]]
43// CHECK-NEXT: .dynamic DYNAMIC {{0*}}[[DYNAMIC_ADDR:[^ ]*]]
44// CHECK-NEXT: .data PROGBITS 000000000000[[DATA_SEGMENT:.]]000
45// PART0-NEXT: .got.plt PROGBITS {{0*}}[[GOT_PLT_ADDR:[^ ]*]]
46// PART0-NEXT: .part.end NOBITS {{0*}}[[PART_END_ADDR:[^ ]*]]
47// CHECK-NEXT: .comment PROGBITS
48// CHECK-NEXT: .symtab SYMTAB
49// CHECK-NEXT: .shstrtab STRTAB
50// CHECK-NEXT: .strtab STRTAB
51// CHECK-NEXT: Key to Flags
52
53// CHECK: Relocation section '.rela.dyn'
54// CHECK-NEXT: Offset
55// PART0-NEXT: 000000000000[[DATA_SEGMENT]]000 {{.*}} R_X86_64_64 {{.*}} f1@v3 + 0
56// PART0-NEXT: {{0*}}[[INIT_ARRAY_ADDR]] {{.*}} R_X86_64_64 {{.*}} p0@@x1 + 0
57// PART1-NEXT: 000000000000[[DATA_SEGMENT]]018 {{.*}} R_X86_64_RELATIVE 3000
58// PART1-NEXT: 000000000000[[DATA_SEGMENT]]000 {{.*}} R_X86_64_64 {{.*}} f2@v2 + 0
59// PART1-NEXT: 000000000000[[DATA_SEGMENT]]008 {{.*}} R_X86_64_64 {{.*}} p0@@x1 + 0
60// PART1-NEXT: 000000000000[[DATA_SEGMENT]]010 {{.*}} R_X86_64_64 {{.*}} p0@@x1 + 0
61// CHECK-EMPTY:
62
63// PART0: Relocation section '.rela.plt'
64// PART0-NEXT: Offset
65// PART0-NEXT: 000000000000[[DATA_SEGMENT]]020 {{.*}} R_X86_64_JUMP_SLOT {{.*}} f1@v3 + 0
66// PART0-NEXT: 000000000000[[DATA_SEGMENT]]028 {{.*}} R_X86_64_JUMP_SLOT {{.*}} f2@v2 + 0
67// PART0-EMPTY:
68
69// CHECK: Symbol table '.dynsym'
70// PART0: 1: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND f1@v3
71// PART0: 2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND f2@v2
72// PART0: 3: {{0*}}[[TEXT_ADDR]] 0 NOTYPE GLOBAL DEFAULT {{.*}} p0@@x1
73// PART1: 1: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND f2@v2
74// PART1: 2: 0000000000000000 0 NOTYPE GLOBAL DEFAULT UND p0@@x1
75// PART1: 3: {{0*}}[[TEXT_ADDR]] 0 NOTYPE GLOBAL DEFAULT {{.*}} p1@@x2
76// PART1: 4: {{0*}}[[TEXT_ADDR]] 0 NOTYPE GLOBAL DEFAULT {{.*}} p1alias@@x2
77// CHECK-EMPTY:
78
79// PART0: Symbol table '.symtab'
80// PART0: 000000000000048c 0 NOTYPE LOCAL HIDDEN {{.*}} __part_index_begin
81// PART0: 0000000000000498 0 NOTYPE LOCAL HIDDEN {{.*}} __part_index_end
82
83// PART-INDEX: Contents of section .dynstr:
84// PART-INDEX-NEXT: 03a8 00663100 66320070 30007061 72743100 .f1.f2.p0.part1.
85// PART-INDEX: Contents of section .rodata:
86// 0x48c + 0xffffff26 = 0x3b2
87// 0x490 + 0x3b70 = 0x4000
88// PART-INDEX-NEXT: 048c 26ffffff 703b0000 00400000
89
90// CHECK: {{.*}}EH_FRAME Header
91// CHECK: Address: 0x[[EH_FRAME_HDR_ADDR]]
92// CHECK: eh_frame_ptr: 0x[[EH_FRAME_ADDR]]
93// CHECK: initial_location: 0x[[TEXT_ADDR]]
94// CHECK: address: 0x[[FDE_ADDR:.*]]
95
96// CHECK: .eh_frame section
97// CHECK: 0x[[EH_FRAME_ADDR]]] CIE length=20
98// CHECK-NOT: FDE
99// CHECK: 0x[[FDE_ADDR]]] FDE length=20 cie={{.}}0x[[EH_FRAME_ADDR]]
100// CHECK-NEXT: initial_location: 0x[[TEXT_ADDR]]
101// CHECK-NOT: FDE
102// CHECK: CIE length=0
103
104// CHECK: Dynamic section
105// CHECK-NEXT: Tag
106// CHECK-NEXT: 0x0000000000000001 (NEEDED) Shared library: [verneed1.so.0]
107// PART0-NEXT: 0x000000000000000e (SONAME) Library soname: [main.so]
108// PART1-NEXT: 0x0000000000000001 (NEEDED) Shared library: [main.so]
109// PART1-NEXT: 0x000000000000000e (SONAME) Library soname: [part1]
110// CHECK-NEXT: 0x0000000000000007 (RELA) 0x[[RELA_DYN_ADDR]]
111// CHECK-NEXT: 0x0000000000000008 (RELASZ)
112// CHECK-NEXT: 0x0000000000000009 (RELAENT) 24 (bytes)
113// PART1-NEXT: 0x000000006ffffff9 (RELACOUNT) 1
114// PART0-NEXT: 0x0000000000000017 (JMPREL) 0x[[RELA_PLT_ADDR]]
115// PART0-NEXT: 0x0000000000000002 (PLTRELSZ) 48 (bytes)
116// PART0-NEXT: 0x0000000000000003 (PLTGOT) 0x[[GOT_PLT_ADDR]]
117// PART0-NEXT: 0x0000000000000014 (PLTREL) RELA
118// CHECK-NEXT: 0x0000000000000006 (SYMTAB) 0x[[DYNSYM_ADDR]]
119// CHECK-NEXT: 0x000000000000000b (SYMENT) 24 (bytes)
120// CHECK-NEXT: 0x0000000000000005 (STRTAB) 0x[[DYNSTR_ADDR]]
121// CHECK-NEXT: 0x000000000000000a (STRSZ)
122// CHECK-NEXT: 0x000000006ffffef5 (GNU_HASH) 0x[[GNU_HASH_ADDR]]
123// CHECK-NEXT: 0x0000000000000004 (HASH) 0x[[HASH_ADDR]]
124// PART0-NEXT: 0x0000000000000019 (INIT_ARRAY) 0x[[INIT_ARRAY_ADDR]]
125// PART0-NEXT: 0x000000000000001b (INIT_ARRAYSZ) 8 (bytes)
126// CHECK-NEXT: 0x000000006ffffff0 (VERSYM) 0x[[VERSYM_ADDR]]
127// CHECK-NEXT: 0x000000006ffffffc (VERDEF) 0x[[VERDEF_ADDR]]
128// CHECK-NEXT: 0x000000006ffffffd (VERDEFNUM) 3
129// CHECK-NEXT: 0x000000006ffffffe (VERNEED) 0x[[VERNEED_ADDR]]
130// CHECK-NEXT: 0x000000006fffffff (VERNEEDNUM) 1
131// PART0-NEXT: 0x0000000000000000 (NULL) 0x0
132
133// CHECK: Program Headers:
134// CHECK-NEXT: Type
135// PART0-NEXT: PHDR {{.*}} 0x000230 0x000230 R
136// PART1-NEXT: PHDR {{.*}} 0x0001f8 0x0001f8 R
137// PART0-NEXT: LOAD 0x000000 0x0000000000000000 0x0000000000000000 {{.*}} R 0x1000
138// PART0-NEXT: LOAD 0x001000 0x0000000000001000 0x0000000000001000 {{.*}} R E 0x1000
139// PART0-NEXT: LOAD 0x002000 0x0000000000002000 0x0000000000002000 {{.*}} RW 0x1000
140// PART0-NEXT: LOAD 0x003000 0x0000000000003000 0x0000000000003000 {{.*}} RW 0x1000
141// PART0-NEXT: LOAD 0x004000 0x0000000000008000 0x0000000000008000 0x000000 0x001000 RW 0x1000
142// PART1-NEXT: LOAD 0x000000 0x0000000000004000 0x0000000000004000 {{.*}} R 0x1000
143// PART1-NEXT: LOAD 0x001000 0x0000000000005000 0x0000000000005000 {{.*}} R E 0x1000
144// PART1-NEXT: LOAD 0x002000 0x0000000000006000 0x0000000000006000 {{.*}} RW 0x1000
145// PART1-NEXT: LOAD 0x003000 0x0000000000007000 0x0000000000007000 {{.*}} RW 0x1000
146// CHECK-NEXT: DYNAMIC {{.*}} 0x{{0*}}[[DYNAMIC_ADDR]] 0x{{0*}}[[DYNAMIC_ADDR]] {{.*}} RW 0x8
147// PART0-NEXT: GNU_RELRO 0x002000 0x0000000000002000 0x0000000000002000 {{.*}} R 0x1
148// PART1-NEXT: GNU_RELRO 0x002000 0x0000000000006000 0x0000000000006000 {{.*}} R 0x1
149// CHECK-NEXT: GNU_EH_FRAME {{.*}} 0x{{0*}}[[EH_FRAME_HDR_ADDR]] 0x{{0*}}[[EH_FRAME_HDR_ADDR]] {{.*}} R 0x4
150// CHECK-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x0
151// CHECK-EMPTY:
152
153// CHECK: Version symbols section '.gnu.version'
154// CHECK-NEXT: Addr:
155// PART0-NEXT: 000: 0 (*local*) 4 (v3) 5 (v2) 2 (x1)
156// PART1-NEXT: 000: 0 (*local*) 5 (v2) 2 (x1) 3 (x2)
157
158// CHECK: Version definition section '.gnu.version_d'
159// CHECK-NEXT: Addr:
160// PART0-NEXT: 0x0000: Rev: 1 Flags: BASE Index: 1 Cnt: 1 Name: main.so
161// PART1-NEXT: 0x0000: Rev: 1 Flags: BASE Index: 1 Cnt: 1 Name: part1
162// CHECK-NEXT: 0x001c: Rev: 1 Flags: none Index: 2 Cnt: 1 Name: x1
163// CHECK-NEXT: 0x0038: Rev: 1 Flags: none Index: 3 Cnt: 1 Name: x2
164
165// CHECK: Version needs section '.gnu.version_r'
166// CHECK-NEXT: Addr:
167// CHECK-NEXT: 0x0000: Version: 1 File: verneed1.so.0 Cnt: 2
168// CHECK-NEXT: 0x0010: Name: v2 Flags: none Version: 5
169// CHECK-NEXT: 0x0020: Name: v3 Flags: none Version: 4
170
171// PART0: Histogram for bucket list length (total of 4 buckets)
172// PART0-NEXT: Length Number % of total Coverage
173// PART0-NEXT: 0 1 ( 25.0%) 0.0%
174// PART0-NEXT: 1 3 ( 75.0%) 100.0%
175// PART0-NEXT: Histogram for `.gnu.hash' bucket list length (total of 1 buckets)
176// PART0-NEXT: Length Number % of total Coverage
177// PART0-NEXT: 0 0 ( 0.0%) 0.0%
178// PART0-NEXT: 1 1 (100.0%) 100.0%
179
180// PART1: Histogram for bucket list length (total of 5 buckets)
181// PART1-NEXT: Length Number % of total Coverage
182// PART1-NEXT: 0 3 ( 60.0%) 0.0%
183// PART1-NEXT: 1 2 ( 40.0%) 100.0%
184// PART1-NEXT: Histogram for `.gnu.hash' bucket list length (total of 1 buckets)
185// PART1-NEXT: Length Number % of total Coverage
186// PART1-NEXT: 0 0 ( 0.0%) 0.0%
187// PART1-NEXT: 1 0 ( 0.0%) 0.0%
188// PART1-NEXT: 2 1 (100.0%) 100.0%
189
190// FILL: 001040 cccc cccc cccc cccc cccc cccc cccc cccc
191// FILL-NEXT: *
192// FILL-NEXT: 002000
193
194// FILL: 005010 cccc cccc cccc cccc cccc cccc cccc cccc
195// FILL-NEXT: *
196// FILL-NEXT: 006000
197
198.section .llvm_sympart,"",@llvm_sympart
199.asciz "part1"
200.quad p1
201
202.section .llvm_sympart2,"",@llvm_sympart
203.asciz "part1"
204.quad p1alias
205
206.section .text.p0,"ax",@progbits
207.globl p0
208p0:
209.cfi_startproc
210lea d0(%rip), %rax
211call f1
212ret
213.cfi_endproc
214
215.section .data.d0,"aw",@progbits
216d0:
217.quad f1
218
219.section .text.p1,"ax",@progbits
220.globl p1
221p1:
222.globl p1alias
223p1alias:
224.cfi_startproc
225lea d1(%rip), %rax
226call f2
227ret
228.cfi_endproc
229
230.section .data.d1,"aw",@progbits
231d1:
232.quad f2
233.quad p0
234.quad p0
235.quad d0
236
237.section .init_array,"aw",@init_array
238.quad p0
239
240.globl __part_index_begin
241.globl __part_index_end
deps/lld/test/ELF/partition-thunk-reuse.s created+45
...@@ -0,0 +1,45 @@
1// REQUIRES: arm
2// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=armv7-unknown-linux -arm-add-build-attributes
3// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections
4// RUN: llvm-nm %t | FileCheck %s
5
6// CHECK: __Thumbv7ABSLongThunk__start
7// CHECK: __Thumbv7ABSLongThunk__start
8
9// CHECK: __Thumbv7ABSLongThunk_foo
10// CHECK-NOT: __Thumbv7ABSLongThunk_foo
11
12.thumb
13
14.section .llvm_sympart.g1,"",%llvm_sympart
15.asciz "part1"
16.4byte f1
17
18.section .llvm_sympart.g2,"",%llvm_sympart
19.asciz "part2"
20.4byte f2
21
22.section .text._start,"ax",%progbits
23.globl _start
24_start:
25bx lr
26foo:
27b f0
28.zero 17*1048576
29
30.section .text.f0,"ax",%progbits
31.globl f0
32f0:
33b foo
34
35.section .text.f1,"aw",%progbits
36.globl f1
37f1:
38b _start
39b foo
40
41.section .text.f2,"ax",%progbits
42.globl f2
43f2:
44b _start
45b foo
deps/lld/test/ELF/partitions.s created+63
...@@ -0,0 +1,63 @@
1// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj --triple=x86_64-unknown-linux
3// RUN: ld.lld %t.o -o %t --export-dynamic --gc-sections
4// RUN: llvm-readelf -S -s %t | FileCheck %s
5
6// This is basically lld/docs/partitions.dot in object file form.
7// Test that the sections are correctly allocated to partitions.
8
9// CHECK: [[MAIN:[0-9]+]]] .text
10// CHECK: [[P1:[0-9]+]]] .text
11// CHECK: [[P2:[0-9]+]]] .text
12
13// CHECK: Symbol table '.symtab'
14// CHECK: [[MAIN]] f3
15// CHECK: [[P1]] f4
16// CHECK: [[MAIN]] f5
17// CHECK: [[P2]] f6
18// CHECK: [[MAIN]] _start
19// CHECK: [[P1]] f1
20// CHECK: [[P2]] f2
21
22.section .llvm_sympart.f1,"",@llvm_sympart
23.asciz "part1"
24.quad f1
25
26.section .llvm_sympart.f2,"",@llvm_sympart
27.asciz "part2"
28.quad f2
29
30.section .text._start,"ax",@progbits
31.globl _start
32_start:
33call f3
34
35.section .text.f1,"ax",@progbits
36.globl f1
37f1:
38call f3
39call f4
40call f5
41
42.section .text.f2,"ax",@progbits
43.globl f2
44f2:
45call f3
46call f5
47call f6
48
49.section .text.f3,"ax",@progbits
50f3:
51ret
52
53.section .text.f4,"ax",@progbits
54f4:
55ret
56
57.section .text.f5,"ax",@progbits
58f5:
59ret
60
61.section .text.f6,"ax",@progbits
62f6:
63ret
deps/lld/test/ELF/phdr-align.s+1-1
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
7# RUN: .data : { *(.data) } \7# RUN: .data : { *(.data) } \
8# RUN: .text : { *(.text) } }" > %t.script8# RUN: .text : { *(.text) } }" > %t.script
9# RUN: ld.lld %t.o --script %t.script -o %t9# RUN: ld.lld %t.o --script %t.script -o %t
10# RUN: llvm-readobj -sections -symbols %t | FileCheck %s10# RUN: llvm-readobj --sections --symbols %t | FileCheck %s
1111
12# CHECK: Sections [12# CHECK: Sections [
13# CHECK-NEXT: Section {13# CHECK-NEXT: Section {
deps/lld/test/ELF/pie-weak.s+4-2
...@@ -1,6 +1,8 @@...@@ -1,6 +1,8 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/dummy-shared.s -o %t1.o
3# RUN: ld.lld %t1.o -shared -o %t1.so
2# RUN: llvm-mc -filetype=obj -relax-relocations=false -triple=x86_64-unknown-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -relax-relocations=false -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: ld.lld --hash-style=sysv -pie %t.o -o %t5# RUN: ld.lld --hash-style=sysv -pie %t.o %t1.so -o %t
4# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOCS %s6# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOCS %s
5# RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s7# RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
68
...@@ -15,6 +17,6 @@...@@ -15,6 +17,6 @@
15.globl _start17.globl _start
16_start:18_start:
17# DISASM: _start:19# DISASM: _start:
18# DISASM-NEXT: 1000: 48 8b 05 99 10 00 00 movq 4249(%rip), %rax20# DISASM-NEXT: 1000: 48 8b 05 a9 10 00 00 movq 4265(%rip), %rax
19# ^ .got - (.text + 7)21# ^ .got - (.text + 7)
20mov foo@gotpcrel(%rip), %rax22mov foo@gotpcrel(%rip), %rax
deps/lld/test/ELF/pie.s+5-5
...@@ -3,16 +3,16 @@...@@ -3,16 +3,16 @@
33
4## Default is no PIE.4## Default is no PIE.
5# RUN: ld.lld %t1.o -o %t5# RUN: ld.lld %t1.o -o %t
6# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t \6# RUN: llvm-readobj --file-headers --sections -l --symbols -r %t \
7# RUN: | FileCheck %s --check-prefix=NOPIE7# RUN: | FileCheck %s --check-prefix=NOPIE
88
9## Check -pie.9## Check -pie.
10# RUN: ld.lld -pie %t1.o -o %t10# RUN: ld.lld -pie %t1.o -o %t
11# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s11# RUN: llvm-readobj --file-headers --sections -l --symbols -r %t | FileCheck %s
1212
13## Test --pic-executable alias13## Test --pic-executable alias
14# RUN: ld.lld --pic-executable %t1.o -o %t14# RUN: ld.lld --pic-executable %t1.o -o %t
15# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s15# RUN: llvm-readobj --file-headers --sections -l --symbols -r %t | FileCheck %s
1616
17# CHECK: ElfHeader {17# CHECK: ElfHeader {
18# CHECK-NEXT: Ident {18# CHECK-NEXT: Ident {
...@@ -49,9 +49,9 @@...@@ -49,9 +49,9 @@
4949
50## Check -nopie50## Check -nopie
51# RUN: ld.lld -no-pie %t1.o -o %t251# RUN: ld.lld -no-pie %t1.o -o %t2
52# RUN: llvm-readobj -file-headers -r %t2 | FileCheck %s --check-prefix=NOPIE52# RUN: llvm-readobj --file-headers -r %t2 | FileCheck %s --check-prefix=NOPIE
53# RUN: ld.lld -no-pic-executable %t1.o -o %t253# RUN: ld.lld -no-pic-executable %t1.o -o %t2
54# RUN: llvm-readobj -file-headers -r %t2 | FileCheck %s --check-prefix=NOPIE54# RUN: llvm-readobj --file-headers -r %t2 | FileCheck %s --check-prefix=NOPIE
55# NOPIE-NOT: Type: SharedObject55# NOPIE-NOT: Type: SharedObject
5656
57.globl _start57.globl _start
deps/lld/test/ELF/plt-aarch64.s+36-34
...@@ -4,10 +4,10 @@...@@ -4,10 +4,10 @@
4// RUN: ld.lld -shared %t2.o -o %t2.so4// RUN: ld.lld -shared %t2.o -o %t2.so
5// RUN: ld.lld -shared %t.o %t2.so -o %t.so5// RUN: ld.lld -shared %t.o %t2.so -o %t.so
6// RUN: ld.lld %t.o %t2.so -o %t.exe6// RUN: ld.lld %t.o %t2.so -o %t.exe
7// RUN: llvm-readobj -s -r %t.so | FileCheck --check-prefix=CHECKDSO %s7// RUN: llvm-readobj -S -r %t.so | FileCheck --check-prefix=CHECKDSO %s
8// RUN: llvm-objdump -s -section=.got.plt %t.so | FileCheck --check-prefix=DUMPDSO %s8// RUN: llvm-objdump -s -section=.got.plt %t.so | FileCheck --check-prefix=DUMPDSO %s
9// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASMDSO %s9// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=DISASMDSO %s
10// RUN: llvm-readobj -s -r %t.exe | FileCheck --check-prefix=CHECKEXE %s10// RUN: llvm-readobj -S -r %t.exe | FileCheck --check-prefix=CHECKEXE %s
11// RUN: llvm-objdump -s -section=.got.plt %t.exe | FileCheck --check-prefix=DUMPEXE %s11// RUN: llvm-objdump -s -section=.got.plt %t.exe | FileCheck --check-prefix=DUMPEXE %s
12// RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASMEXE %s12// RUN: llvm-objdump -d %t.exe | FileCheck --check-prefix=DISASMEXE %s
1313
...@@ -30,7 +30,7 @@...@@ -30,7 +30,7 @@
30// CHECKDSO-NEXT: SHF_ALLOC30// CHECKDSO-NEXT: SHF_ALLOC
31// CHECKDSO-NEXT: SHF_WRITE31// CHECKDSO-NEXT: SHF_WRITE
32// CHECKDSO-NEXT: ]32// CHECKDSO-NEXT: ]
33// CHECKDSO-NEXT: Address: 0x2000033// CHECKDSO-NEXT: Address: 0x30000
34// CHECKDSO-NEXT: Offset:34// CHECKDSO-NEXT: Offset:
35// CHECKDSO-NEXT: Size: 4835// CHECKDSO-NEXT: Size: 48
36// CHECKDSO-NEXT: Link:36// CHECKDSO-NEXT: Link:
...@@ -40,23 +40,23 @@...@@ -40,23 +40,23 @@
40// CHECKDSO: Relocations [40// CHECKDSO: Relocations [
41// CHECKDSO-NEXT: Section ({{.*}}) .rela.plt {41// CHECKDSO-NEXT: Section ({{.*}}) .rela.plt {
4242
43// &(.got.plt[3]) = 0x20000 + 3 * 8 = 0x3001843// &(.got.plt[3]) = 0x30000 + 3 * 8 = 0x30018
44// CHECKDSO-NEXT: 0x20018 R_AARCH64_JUMP_SLOT foo44// CHECKDSO-NEXT: 0x30018 R_AARCH64_JUMP_SLOT foo
4545
46// &(.got.plt[4]) = 0x20000 + 4 * 8 = 0x3002046// &(.got.plt[4]) = 0x30000 + 4 * 8 = 0x30020
47// CHECKDSO-NEXT: 0x20020 R_AARCH64_JUMP_SLOT bar47// CHECKDSO-NEXT: 0x30020 R_AARCH64_JUMP_SLOT bar
4848
49// &(.got.plt[5]) = 0x20000 + 5 * 8 = 0x3002849// &(.got.plt[5]) = 0x30000 + 5 * 8 = 0x30028
50// CHECKDSO-NEXT: 0x20028 R_AARCH64_JUMP_SLOT weak50// CHECKDSO-NEXT: 0x30028 R_AARCH64_JUMP_SLOT weak
51// CHECKDSO-NEXT: }51// CHECKDSO-NEXT: }
52// CHECKDSO-NEXT: ]52// CHECKDSO-NEXT: ]
5353
54// DUMPDSO: Contents of section .got.plt:54// DUMPDSO: Contents of section .got.plt:
55// .got.plt[0..2] = 0 (reserved)55// .got.plt[0..2] = 0 (reserved)
56// .got.plt[3..5] = .plt = 0x1001056// .got.plt[3..5] = .plt = 0x10010
57// DUMPDSO-NEXT: 20000 00000000 00000000 00000000 00000000 ................57// DUMPDSO-NEXT: 30000 00000000 00000000 00000000 00000000 ................
58// DUMPDSO-NEXT: 20010 00000000 00000000 10000100 00000000 ................58// DUMPDSO-NEXT: 30010 00000000 00000000 10000100 00000000 ................
59// DUMPDSO-NEXT: 20020 10000100 00000000 10000100 00000000 ................59// DUMPDSO-NEXT: 30020 10000100 00000000 10000100 00000000 ................
6060
61// DISASMDSO: _start:61// DISASMDSO: _start:
62// 0x10030 - 0x10000 = 0x30 = 4862// 0x10030 - 0x10000 = 0x30 = 48
...@@ -70,11 +70,12 @@...@@ -70,11 +70,12 @@
70// DISASMDSO-NEXT: 1000c: 1f 20 03 d5 nop70// DISASMDSO-NEXT: 1000c: 1f 20 03 d5 nop
7171
72// DISASMDSO: Disassembly of section .plt:72// DISASMDSO: Disassembly of section .plt:
73// DISASMDSO-EMPTY:
73// DISASMDSO-NEXT: .plt:74// DISASMDSO-NEXT: .plt:
74// DISASMDSO-NEXT: 10010: f0 7b bf a9 stp x16, x30, [sp, #-16]!75// DISASMDSO-NEXT: 10010: f0 7b bf a9 stp x16, x30, [sp, #-16]!
75// &(.got.plt[2]) = 0x3000 + 2 * 8 = 0x301076// &(.got.plt[2]) = 0x3000 + 2 * 8 = 0x3010
76// Page(0x20010) - Page(0x10014) = 0x20000 - 0x10000 = 0x10000 = 6553677// Page(0x30010) - Page(0x10014) = 0x30000 - 0x10000 = 0x20000 = 131072
77// DISASMDSO-NEXT: 10014: 90 00 00 90 adrp x16, #6553678// DISASMDSO-NEXT: 10014: 10 01 00 90 adrp x16, #131072
78// 0x3010 & 0xFFF = 0x10 = 1679// 0x3010 & 0xFFF = 0x10 = 16
79// DISASMDSO-NEXT: 10018: 11 0a 40 f9 ldr x17, [x16, #16]80// DISASMDSO-NEXT: 10018: 11 0a 40 f9 ldr x17, [x16, #16]
80// DISASMDSO-NEXT: 1001c: 10 42 00 91 add x16, x16, #1681// DISASMDSO-NEXT: 1001c: 10 42 00 91 add x16, x16, #16
...@@ -84,30 +85,30 @@...@@ -84,30 +85,30 @@
84// DISASMDSO-NEXT: 1002c: 1f 20 03 d5 nop85// DISASMDSO-NEXT: 1002c: 1f 20 03 d5 nop
8586
86// foo@plt87// foo@plt
87// Page(0x30018) - Page(0x10030) = 0x20000 - 0x10000 = 0x10000 = 6553688// Page(0x30018) - Page(0x10030) = 0x30000 - 0x10000 = 0x20000 = 131072
88// DISASMDSO-EMPTY:89// DISASMDSO-EMPTY:
89// DISASMDSO-NEXT: foo@plt:90// DISASMDSO-NEXT: foo@plt:
90// DISASMDSO-NEXT: 10030: 90 00 00 90 adrp x16, #6553691// DISASMDSO-NEXT: 10030: 10 01 00 90 adrp x16, #131072
91// 0x3018 & 0xFFF = 0x18 = 2492// 0x3018 & 0xFFF = 0x18 = 24
92// DISASMDSO-NEXT: 10034: 11 0e 40 f9 ldr x17, [x16, #24]93// DISASMDSO-NEXT: 10034: 11 0e 40 f9 ldr x17, [x16, #24]
93// DISASMDSO-NEXT: 10038: 10 62 00 91 add x16, x16, #2494// DISASMDSO-NEXT: 10038: 10 62 00 91 add x16, x16, #24
94// DISASMDSO-NEXT: 1003c: 20 02 1f d6 br x1795// DISASMDSO-NEXT: 1003c: 20 02 1f d6 br x17
9596
96// bar@plt97// bar@plt
97// Page(0x30020) - Page(0x10040) = 0x20000 - 0x10000 = 0x10000 = 6553698// Page(0x30020) - Page(0x10040) = 0x30000 - 0x10000 = 0x20000 = 131072
98// DISASMDSO-EMPTY:99// DISASMDSO-EMPTY:
99// DISASMDSO-NEXT: bar@plt:100// DISASMDSO-NEXT: bar@plt:
100// DISASMDSO-NEXT: 10040: 90 00 00 90 adrp x16, #65536101// DISASMDSO-NEXT: 10040: 10 01 00 90 adrp x16, #131072
101// 0x3020 & 0xFFF = 0x20 = 32102// 0x3020 & 0xFFF = 0x20 = 32
102// DISASMDSO-NEXT: 10044: 11 12 40 f9 ldr x17, [x16, #32]103// DISASMDSO-NEXT: 10044: 11 12 40 f9 ldr x17, [x16, #32]
103// DISASMDSO-NEXT: 10048: 10 82 00 91 add x16, x16, #32104// DISASMDSO-NEXT: 10048: 10 82 00 91 add x16, x16, #32
104// DISASMDSO-NEXT: 1004c: 20 02 1f d6 br x17105// DISASMDSO-NEXT: 1004c: 20 02 1f d6 br x17
105106
106// weak@plt107// weak@plt
107// Page(0x30028) - Page(0x10050) = 0x20000 - 0x10000 = 0x10000 = 65536108// Page(0x30028) - Page(0x10050) = 0x30000 - 0x10000 = 0x20000 = 131072
108// DISASMDSO-EMPTY:109// DISASMDSO-EMPTY:
109// DISASMDSO-NEXT: weak@plt:110// DISASMDSO-NEXT: weak@plt:
110// DISASMDSO-NEXT: 10050: 90 00 00 90 adrp x16, #65536111// DISASMDSO-NEXT: 10050: 10 01 00 90 adrp x16, #131072
111// 0x3028 & 0xFFF = 0x28 = 40112// 0x3028 & 0xFFF = 0x28 = 40
112// DISASMDSO-NEXT: 10054: 11 16 40 f9 ldr x17, [x16, #40]113// DISASMDSO-NEXT: 10054: 11 16 40 f9 ldr x17, [x16, #40]
113// DISASMDSO-NEXT: 10058: 10 a2 00 91 add x16, x16, #40114// DISASMDSO-NEXT: 10058: 10 a2 00 91 add x16, x16, #40
...@@ -132,7 +133,7 @@...@@ -132,7 +133,7 @@
132// CHECKEXE-NEXT: SHF_ALLOC133// CHECKEXE-NEXT: SHF_ALLOC
133// CHECKEXE-NEXT: SHF_WRITE134// CHECKEXE-NEXT: SHF_WRITE
134// CHECKEXE-NEXT: ]135// CHECKEXE-NEXT: ]
135// CHECKEXE-NEXT: Address: 0x220000136// CHECKEXE-NEXT: Address: 0x230000
136// CHECKEXE-NEXT: Offset:137// CHECKEXE-NEXT: Offset:
137// CHECKEXE-NEXT: Size: 40138// CHECKEXE-NEXT: Size: 40
138// CHECKEXE-NEXT: Link:139// CHECKEXE-NEXT: Link:
...@@ -142,20 +143,20 @@...@@ -142,20 +143,20 @@
142// CHECKEXE: Relocations [143// CHECKEXE: Relocations [
143// CHECKEXE-NEXT: Section ({{.*}}) .rela.plt {144// CHECKEXE-NEXT: Section ({{.*}}) .rela.plt {
144145
145// &(.got.plt[3]) = 0x220000 + 3 * 8 = 0x220018146// &(.got.plt[3]) = 0x230000 + 3 * 8 = 0x230018
146// CHECKEXE-NEXT: 0x220018 R_AARCH64_JUMP_SLOT bar 0x0147// CHECKEXE-NEXT: 0x230018 R_AARCH64_JUMP_SLOT bar 0x0
147148
148// &(.got.plt[4]) = 0x220000 + 4 * 8 = 0x220020149// &(.got.plt[4]) = 0x230000 + 4 * 8 = 0x230020
149// CHECKEXE-NEXT: 0x220020 R_AARCH64_JUMP_SLOT weak 0x0150// CHECKEXE-NEXT: 0x230020 R_AARCH64_JUMP_SLOT weak 0x0
150// CHECKEXE-NEXT: }151// CHECKEXE-NEXT: }
151// CHECKEXE-NEXT: ]152// CHECKEXE-NEXT: ]
152153
153// DUMPEXE: Contents of section .got.plt:154// DUMPEXE: Contents of section .got.plt:
154// .got.plt[0..2] = 0 (reserved)155// .got.plt[0..2] = 0 (reserved)
155// .got.plt[3..4] = .plt = 0x40010156// .got.plt[3..4] = .plt = 0x40010
156// DUMPEXE-NEXT: 220000 00000000 00000000 00000000 00000000157// DUMPEXE-NEXT: 230000 00000000 00000000 00000000 00000000
157// DUMPEXE-NEXT: 220010 00000000 00000000 10002100 00000000158// DUMPEXE-NEXT: 230010 00000000 00000000 10002100 00000000
158// DUMPEXE-NEXT: 220020 10002100 00000000159// DUMPEXE-NEXT: 230020 10002100 00000000
159160
160// DISASMEXE: _start:161// DISASMEXE: _start:
161// 0x21000c - 0x210000 = 0xc = 12162// 0x21000c - 0x210000 = 0xc = 12
...@@ -169,11 +170,12 @@...@@ -169,11 +170,12 @@
169// DISASMEXE-NEXT: 21000c: 1f 20 03 d5 nop170// DISASMEXE-NEXT: 21000c: 1f 20 03 d5 nop
170171
171// DISASMEXE: Disassembly of section .plt:172// DISASMEXE: Disassembly of section .plt:
173// DISASMEXE-EMPTY:
172// DISASMEXE-NEXT: .plt:174// DISASMEXE-NEXT: .plt:
173// DISASMEXE-NEXT: 210010: f0 7b bf a9 stp x16, x30, [sp, #-16]!175// DISASMEXE-NEXT: 210010: f0 7b bf a9 stp x16, x30, [sp, #-16]!
174// &(.got.plt[2]) = 0x2200B0 + 2 * 8 = 0x2200C0176// &(.got.plt[2]) = 0x2200B0 + 2 * 8 = 0x2200C0
175// Page(0x220010) - Page(0x210014) = 0x220000 - 0x210000 = 0x10000 = 65536177// Page(0x230010) - Page(0x210014) = 0x230000 - 0x210000 = 0x20000 = 131072
176// DISASMEXE-NEXT: 210014: 90 00 00 90 adrp x16, #65536178// DISASMEXE-NEXT: 210014: 10 01 00 90 adrp x16, #131072
177// 0x120c0 & 0xFFF = 0xC0 = 192179// 0x120c0 & 0xFFF = 0xC0 = 192
178// DISASMEXE-NEXT: 210018: 11 0a 40 f9 ldr x17, [x16, #16]180// DISASMEXE-NEXT: 210018: 11 0a 40 f9 ldr x17, [x16, #16]
179// DISASMEXE-NEXT: 21001c: 10 42 00 91 add x16, x16, #16181// DISASMEXE-NEXT: 21001c: 10 42 00 91 add x16, x16, #16
...@@ -183,19 +185,19 @@...@@ -183,19 +185,19 @@
183// DISASMEXE-NEXT: 21002c: 1f 20 03 d5 nop185// DISASMEXE-NEXT: 21002c: 1f 20 03 d5 nop
184186
185// bar@plt187// bar@plt
186// Page(0x40018) - Page(0x210030) = 0x220000 - 0x210000 = 0x10000 = 65536188// Page(0x230018) - Page(0x210030) = 0x230000 - 0x210000 = 0x20000 = 131072
187// DISASMEXE-EMPTY:189// DISASMEXE-EMPTY:
188// DISASMEXE-NEXT: bar@plt:190// DISASMEXE-NEXT: bar@plt:
189// DISASMEXE-NEXT: 210030: 90 00 00 90 adrp x16, #65536191// DISASMEXE-NEXT: 210030: 10 01 00 90 adrp x16, #131072
190// DISASMEXE-NEXT: 210034: 11 0e 40 f9 ldr x17, [x16, #24]192// DISASMEXE-NEXT: 210034: 11 0e 40 f9 ldr x17, [x16, #24]
191// DISASMEXE-NEXT: 210038: 10 62 00 91 add x16, x16, #24193// DISASMEXE-NEXT: 210038: 10 62 00 91 add x16, x16, #24
192// DISASMEXE-NEXT: 21003c: 20 02 1f d6 br x17194// DISASMEXE-NEXT: 21003c: 20 02 1f d6 br x17
193195
194// weak@plt196// weak@plt
195// Page(0x40020) - Page(0x210040) = 0x220000 - 0x210000 = 0x10000 = 65536197// Page(0x230020) - Page(0x210040) = 0x230000 - 0x210000 = 0x20000 = 131072
196// DISASMEXE-EMPTY:198// DISASMEXE-EMPTY:
197// DISASMEXE-NEXT: weak@plt:199// DISASMEXE-NEXT: weak@plt:
198// DISASMEXE-NEXT: 210040: 90 00 00 90 adrp x16, #65536200// DISASMEXE-NEXT: 210040: 10 01 00 90 adrp x16, #131072
199// DISASMEXE-NEXT: 210044: 11 12 40 f9 ldr x17, [x16, #32]201// DISASMEXE-NEXT: 210044: 11 12 40 f9 ldr x17, [x16, #32]
200// DISASMEXE-NEXT: 210048: 10 82 00 91 add x16, x16, #32202// DISASMEXE-NEXT: 210048: 10 82 00 91 add x16, x16, #32
201// DISASMEXE-NEXT: 21004c: 20 02 1f d6 br x17203// DISASMEXE-NEXT: 21004c: 20 02 1f d6 br x17
deps/lld/test/ELF/plt-i686.s+36-28
...@@ -3,10 +3,10 @@...@@ -3,10 +3,10 @@
3// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t2.so4// RUN: ld.lld -shared %t2.o -o %t2.so
5// RUN: ld.lld %t.o %t2.so -o %t5// RUN: ld.lld %t.o %t2.so -o %t
6// RUN: llvm-readobj -s -r %t | FileCheck %s6// RUN: llvm-readobj -S -r %t | FileCheck %s
7// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s7// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
8// RUN: ld.lld -shared %t.o %t2.so -o %t8// RUN: ld.lld -shared %t.o %t2.so -o %t
9// RUN: llvm-readobj -s -r %t | FileCheck --check-prefix=CHECKSHARED %s9// RUN: llvm-readobj -S -r %t | FileCheck --check-prefix=CHECKSHARED %s
10// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMSHARED %s10// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMSHARED %s
11// RUN: ld.lld -pie %t.o %t2.so -o %t11// RUN: ld.lld -pie %t.o %t2.so -o %t
12// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMPIE %s12// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASMPIE %s
...@@ -30,8 +30,8 @@...@@ -30,8 +30,8 @@
30// CHECK-NEXT: SHF_ALLOC30// CHECK-NEXT: SHF_ALLOC
31// CHECK-NEXT: SHF_WRITE31// CHECK-NEXT: SHF_WRITE
32// CHECK-NEXT: ]32// CHECK-NEXT: ]
33// CHECK-NEXT: Address: 0x40200033// CHECK-NEXT: Address: 0x403000
34// CHECK-NEXT: Offset: 0x200034// CHECK-NEXT: Offset: 0x3000
35// CHECK-NEXT: Size: 2035// CHECK-NEXT: Size: 20
36// CHECK-NEXT: Link: 036// CHECK-NEXT: Link: 0
37// CHECK-NEXT: Info: 037// CHECK-NEXT: Info: 0
...@@ -42,8 +42,8 @@...@@ -42,8 +42,8 @@
42// 0x12000 + got.plt.reserved(12) + 4 = 0x1201042// 0x12000 + got.plt.reserved(12) + 4 = 0x12010
43// CHECK: Relocations [43// CHECK: Relocations [
44// CHECK-NEXT: Section ({{.*}}) .rel.plt {44// CHECK-NEXT: Section ({{.*}}) .rel.plt {
45// CHECK-NEXT: 0x40200C R_386_JUMP_SLOT bar 0x045// CHECK-NEXT: 0x40300C R_386_JUMP_SLOT bar 0x0
46// CHECK-NEXT: 0x402010 R_386_JUMP_SLOT zed 0x046// CHECK-NEXT: 0x403010 R_386_JUMP_SLOT zed 0x0
47// CHECK-NEXT: }47// CHECK-NEXT: }
48// CHECK-NEXT: ]48// CHECK-NEXT: ]
4949
...@@ -67,26 +67,27 @@...@@ -67,26 +67,27 @@
6767
68// 0x401010 - 0x40102b - 5 = -3268// 0x401010 - 0x40102b - 5 = -32
69// 0x401010 - 0x40103b - 5 = -4869// 0x401010 - 0x40103b - 5 = -48
70// 4202500 = 0x402004 = .got.plt (0x402000) + 470// 4206596 = 0x403004 = .got.plt (0x403000) + 4
71// 4202504 = 0x402008 = .got.plt (0x402000) + 871// 4206600 = 0x403008 = .got.plt (0x403000) + 8
72// 4202508 = 0x40200C = .got.plt (0x402000) + got.plt.reserved(12)72// 4206604 = 0x40300C = .got.plt (0x403000) + got.plt.reserved(12)
73// 4202512 = 0x402010 = .got.plt (0x402000) + got.plt.reserved(12) + 473// 4206608 = 0x403010 = .got.plt (0x403000) + got.plt.reserved(12) + 4
74// DISASM: Disassembly of section .plt:74// DISASM: Disassembly of section .plt:
75// DISASM-EMPTY:
75// DISASM-NEXT: .plt:76// DISASM-NEXT: .plt:
76// DISASM-NEXT: 401020: ff 35 04 20 40 00 pushl 420250077// DISASM-NEXT: 401020: ff 35 04 30 40 00 pushl 4206596
77// DISASM-NEXT: 401026: ff 25 08 20 40 00 jmpl *420250478// DISASM-NEXT: 401026: ff 25 08 30 40 00 jmpl *4206600
78// DISASM-NEXT: 40102c: 90 nop79// DISASM-NEXT: 40102c: 90 nop
79// DISASM-NEXT: 40102d: 90 nop80// DISASM-NEXT: 40102d: 90 nop
80// DISASM-NEXT: 40102e: 90 nop81// DISASM-NEXT: 40102e: 90 nop
81// DISASM-NEXT: 40102f: 90 nop82// DISASM-NEXT: 40102f: 90 nop
82// DISASM-EMPTY:83// DISASM-EMPTY:
83// DISASM-NEXT: bar@plt:84// DISASM-NEXT: bar@plt:
84// DISASM-NEXT: 401030: ff 25 0c 20 40 00 jmpl *420250885// DISASM-NEXT: 401030: ff 25 0c 30 40 00 jmpl *4206604
85// DISASM-NEXT: 401036: 68 00 00 00 00 pushl $086// DISASM-NEXT: 401036: 68 00 00 00 00 pushl $0
86// DISASM-NEXT: 40103b: e9 e0 ff ff ff jmp -32 <.plt>87// DISASM-NEXT: 40103b: e9 e0 ff ff ff jmp -32 <.plt>
87// DISASM-EMPTY:88// DISASM-EMPTY:
88// DISASM-NEXT: zed@plt:89// DISASM-NEXT: zed@plt:
89// DISASM-NEXT: 401040: ff 25 10 20 40 00 jmpl *420251290// DISASM-NEXT: 401040: ff 25 10 30 40 00 jmpl *4206608
90// DISASM-NEXT: 401046: 68 08 00 00 00 pushl $891// DISASM-NEXT: 401046: 68 08 00 00 00 pushl $8
91// DISASM-NEXT: 40104b: e9 d0 ff ff ff jmp -48 <.plt>92// DISASM-NEXT: 40104b: e9 d0 ff ff ff jmp -48 <.plt>
9293
...@@ -110,8 +111,8 @@...@@ -110,8 +111,8 @@
110// CHECKSHARED-NEXT: SHF_ALLOC111// CHECKSHARED-NEXT: SHF_ALLOC
111// CHECKSHARED-NEXT: SHF_WRITE112// CHECKSHARED-NEXT: SHF_WRITE
112// CHECKSHARED-NEXT: ]113// CHECKSHARED-NEXT: ]
113// CHECKSHARED-NEXT: Address: 0x2000114// CHECKSHARED-NEXT: Address: 0x3000
114// CHECKSHARED-NEXT: Offset: 0x2000115// CHECKSHARED-NEXT: Offset: 0x3000
115// CHECKSHARED-NEXT: Size: 20116// CHECKSHARED-NEXT: Size: 20
116// CHECKSHARED-NEXT: Link: 0117// CHECKSHARED-NEXT: Link: 0
117// CHECKSHARED-NEXT: Info: 0118// CHECKSHARED-NEXT: Info: 0
...@@ -119,12 +120,12 @@...@@ -119,12 +120,12 @@
119// CHECKSHARED-NEXT: EntrySize: 0120// CHECKSHARED-NEXT: EntrySize: 0
120// CHECKSHARED-NEXT: }121// CHECKSHARED-NEXT: }
121122
122// 0x2000 + got.plt.reserved(12) = 0x200C123// 0x3000 + got.plt.reserved(12) = 0x300C
123// 0x2000 + got.plt.reserved(12) + 4 = 0x2010124// 0x3000 + got.plt.reserved(12) + 4 = 0x3010
124// CHECKSHARED: Relocations [125// CHECKSHARED: Relocations [
125// CHECKSHARED-NEXT: Section ({{.*}}) .rel.plt {126// CHECKSHARED-NEXT: Section ({{.*}}) .rel.plt {
126// CHECKSHARED-NEXT: 0x200C R_386_JUMP_SLOT bar 0x0127// CHECKSHARED-NEXT: 0x300C R_386_JUMP_SLOT bar 0x0
127// CHECKSHARED-NEXT: 0x2010 R_386_JUMP_SLOT zed 0x0128// CHECKSHARED-NEXT: 0x3010 R_386_JUMP_SLOT zed 0x0
128// CHECKSHARED-NEXT: }129// CHECKSHARED-NEXT: }
129// CHECKSHARED-NEXT: ]130// CHECKSHARED-NEXT: ]
130131
...@@ -137,33 +138,40 @@...@@ -137,33 +138,40 @@
137// DISASMSHARED-NEXT: 1009: e9 22 00 00 00 jmp 34138// DISASMSHARED-NEXT: 1009: e9 22 00 00 00 jmp 34
138// DISASMSHARED-NEXT: 100e: e9 2d 00 00 00 jmp 45139// DISASMSHARED-NEXT: 100e: e9 2d 00 00 00 jmp 45
139// DISASMSHARED-NEXT: 1013: e9 e8 ff ff ff jmp -24140// DISASMSHARED-NEXT: 1013: e9 e8 ff ff ff jmp -24
141// DISASMSHARED-EMPTY:
140// DISASMSHARED-NEXT: Disassembly of section .plt:142// DISASMSHARED-NEXT: Disassembly of section .plt:
143// DISASMSHARED-EMPTY:
141// DISASMSHARED-NEXT: .plt:144// DISASMSHARED-NEXT: .plt:
142// DISASMSHARED-NEXT: 1020: ff b3 04 20 00 00 pushl 8196(%ebx)145// DISASMSHARED-NEXT: 1020: ff b3 04 00 00 00 pushl 4(%ebx)
143// DISASMSHARED-NEXT: 1026: ff a3 08 20 00 00 jmpl *8200(%ebx)146// DISASMSHARED-NEXT: 1026: ff a3 08 00 00 00 jmpl *8(%ebx)
144// DISASMSHARED-NEXT: 102c: 90 nop147// DISASMSHARED-NEXT: 102c: 90 nop
145// DISASMSHARED-NEXT: 102d: 90 nop148// DISASMSHARED-NEXT: 102d: 90 nop
146// DISASMSHARED-NEXT: 102e: 90 nop149// DISASMSHARED-NEXT: 102e: 90 nop
147// DISASMSHARED-NEXT: 102f: 90 nop150// DISASMSHARED-NEXT: 102f: 90 nop
148// DISASMSHARED-NEXT: 1030: ff a3 0c 20 00 00 jmpl *8204(%ebx)151// DISASMSHARED: bar@plt:
152// DISASMSHARED-NEXT: 1030: ff a3 0c 00 00 00 jmpl *12(%ebx)
149// DISASMSHARED-NEXT: 1036: 68 00 00 00 00 pushl $0153// DISASMSHARED-NEXT: 1036: 68 00 00 00 00 pushl $0
150// DISASMSHARED-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>154// DISASMSHARED-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>
151// DISASMSHARED-NEXT: 1040: ff a3 10 20 00 00 jmpl *8208(%ebx)155// DISASMSHARED: zed@plt:
156// DISASMSHARED-NEXT: 1040: ff a3 10 00 00 00 jmpl *16(%ebx)
152// DISASMSHARED-NEXT: 1046: 68 08 00 00 00 pushl $8157// DISASMSHARED-NEXT: 1046: 68 08 00 00 00 pushl $8
153// DISASMSHARED-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>158// DISASMSHARED-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
154159
155// DISASMPIE: Disassembly of section .plt:160// DISASMPIE: Disassembly of section .plt:
161// DISASMPIE-EMPTY:
156// DISASMPIE-NEXT: .plt:162// DISASMPIE-NEXT: .plt:
157// DISASMPIE-NEXT: 1020: ff b3 04 20 00 00 pushl 8196(%ebx)163// DISASMPIE-NEXT: 1020: ff b3 04 00 00 00 pushl 4(%ebx)
158// DISASMPIE-NEXT: 1026: ff a3 08 20 00 00 jmpl *8200(%ebx)164// DISASMPIE-NEXT: 1026: ff a3 08 00 00 00 jmpl *8(%ebx)
159// DISASMPIE-NEXT: 102c: 90 nop165// DISASMPIE-NEXT: 102c: 90 nop
160// DISASMPIE-NEXT: 102d: 90 nop166// DISASMPIE-NEXT: 102d: 90 nop
161// DISASMPIE-NEXT: 102e: 90 nop167// DISASMPIE-NEXT: 102e: 90 nop
162// DISASMPIE-NEXT: 102f: 90 nop168// DISASMPIE-NEXT: 102f: 90 nop
163// DISASMPIE-NEXT: 1030: ff a3 0c 20 00 00 jmpl *8204(%ebx)169// DISASMPIE: bar@plt:
170// DISASMPIE-NEXT: 1030: ff a3 0c 00 00 00 jmpl *12(%ebx)
164// DISASMPIE-NEXT: 1036: 68 00 00 00 00 pushl $0171// DISASMPIE-NEXT: 1036: 68 00 00 00 00 pushl $0
165// DISASMPIE-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>172// DISASMPIE-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>
166// DISASMPIE-NEXT: 1040: ff a3 10 20 00 00 jmpl *8208(%ebx)173// DISASMPIE: zed@plt:
174// DISASMPIE-NEXT: 1040: ff a3 10 00 00 00 jmpl *16(%ebx)
167// DISASMPIE-NEXT: 1046: 68 08 00 00 00 pushl $8175// DISASMPIE-NEXT: 1046: 68 08 00 00 00 pushl $8
168// DISASMPIE-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>176// DISASMPIE-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
169177
deps/lld/test/ELF/plt.s+21-19
...@@ -4,9 +4,9 @@...@@ -4,9 +4,9 @@
4// RUN: ld.lld -shared %t2.o -o %t2.so4// RUN: ld.lld -shared %t2.o -o %t2.so
5// RUN: ld.lld -shared %t.o %t2.so -o %t5// RUN: ld.lld -shared %t.o %t2.so -o %t
6// RUN: ld.lld %t.o %t2.so -o %t36// RUN: ld.lld %t.o %t2.so -o %t3
7// RUN: llvm-readobj -s -r %t | FileCheck %s7// RUN: llvm-readobj -S -r %t | FileCheck %s
8// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s8// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
9// RUN: llvm-readobj -s -r %t3 | FileCheck --check-prefix=CHECK2 %s9// RUN: llvm-readobj -S -r %t3 | FileCheck --check-prefix=CHECK2 %s
10// RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM2 %s10// RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM2 %s
1111
12// CHECK: Name: .plt12// CHECK: Name: .plt
...@@ -24,9 +24,9 @@...@@ -24,9 +24,9 @@
2424
25// CHECK: Relocations [25// CHECK: Relocations [
26// CHECK-NEXT: Section ({{.*}}) .rela.plt {26// CHECK-NEXT: Section ({{.*}}) .rela.plt {
27// CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT bar 0x027// CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT bar 0x0
28// CHECK-NEXT: 0x2020 R_X86_64_JUMP_SLOT zed 0x028// CHECK-NEXT: 0x3020 R_X86_64_JUMP_SLOT zed 0x0
29// CHECK-NEXT: 0x2028 R_X86_64_JUMP_SLOT _start 0x029// CHECK-NEXT: 0x3028 R_X86_64_JUMP_SLOT _start 0x0
30// CHECK-NEXT: }30// CHECK-NEXT: }
31// CHECK-NEXT: ]31// CHECK-NEXT: ]
3232
...@@ -45,8 +45,8 @@...@@ -45,8 +45,8 @@
4545
46// CHECK2: Relocations [46// CHECK2: Relocations [
47// CHECK2-NEXT: Section ({{.*}}) .rela.plt {47// CHECK2-NEXT: Section ({{.*}}) .rela.plt {
48// CHECK2-NEXT: 0x202018 R_X86_64_JUMP_SLOT bar 0x048// CHECK2-NEXT: 0x203018 R_X86_64_JUMP_SLOT bar 0x0
49// CHECK2-NEXT: 0x202020 R_X86_64_JUMP_SLOT zed 0x049// CHECK2-NEXT: 0x203020 R_X86_64_JUMP_SLOT zed 0x0
50// CHECK2-NEXT: }50// CHECK2-NEXT: }
51// CHECK2-NEXT: ]51// CHECK2-NEXT: ]
5252
...@@ -64,28 +64,29 @@...@@ -64,28 +64,29 @@
64// DISASM-NEXT: 100a: e9 {{.*}} jmp 4964// DISASM-NEXT: 100a: e9 {{.*}} jmp 49
65// DISASM-NEXT: 100f: e9 {{.*}} jmp 6065// DISASM-NEXT: 100f: e9 {{.*}} jmp 60
6666
67// 0x2018 - 0x1036 = 406667// 0x3018 - 0x1036 = 8162
68// 0x2020 - 0x1046 = 405868// 0x3020 - 0x1046 = 8154
69// 0x2028 - 0x1056 = 405069// 0x3028 - 0x1056 = 8146
7070
71// DISASM: Disassembly of section .plt:71// DISASM: Disassembly of section .plt:
72// DISASM-EMPTY:
72// DISASM-NEXT: .plt:73// DISASM-NEXT: .plt:
73// DISASM-NEXT: 1020: ff 35 e2 0f 00 00 pushq 4066(%rip)74// DISASM-NEXT: 1020: ff 35 e2 1f 00 00 pushq 8162(%rip)
74// DISASM-NEXT: 1026: ff 25 e4 0f 00 00 jmpq *4068(%rip)75// DISASM-NEXT: 1026: ff 25 e4 1f 00 00 jmpq *8164(%rip)
75// DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax)76// DISASM-NEXT: 102c: 0f 1f 40 00 nopl (%rax)
76// DISASM-EMPTY:77// DISASM-EMPTY:
77// DISASM-NEXT: bar@plt:78// DISASM-NEXT: bar@plt:
78// DISASM-NEXT: 1030: ff 25 e2 0f 00 00 jmpq *4066(%rip)79// DISASM-NEXT: 1030: ff 25 e2 1f 00 00 jmpq *8162(%rip)
79// DISASM-NEXT: 1036: 68 00 00 00 00 pushq $080// DISASM-NEXT: 1036: 68 00 00 00 00 pushq $0
80// DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>81// DISASM-NEXT: 103b: e9 e0 ff ff ff jmp -32 <.plt>
81// DISASM-EMPTY:82// DISASM-EMPTY:
82// DISASM-NEXT: zed@plt:83// DISASM-NEXT: zed@plt:
83// DISASM-NEXT: 1040: ff 25 da 0f 00 00 jmpq *4058(%rip)84// DISASM-NEXT: 1040: ff 25 da 1f 00 00 jmpq *8154(%rip)
84// DISASM-NEXT: 1046: 68 01 00 00 00 pushq $185// DISASM-NEXT: 1046: 68 01 00 00 00 pushq $1
85// DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>86// DISASM-NEXT: 104b: e9 d0 ff ff ff jmp -48 <.plt>
86// DISASM-EMPTY:87// DISASM-EMPTY:
87// DISASM-NEXT: _start@plt:88// DISASM-NEXT: _start@plt:
88// DISASM-NEXT: 1050: ff 25 d2 0f 00 00 jmpq *4050(%rip)89// DISASM-NEXT: 1050: ff 25 d2 1f 00 00 jmpq *8146(%rip)
89// DISASM-NEXT: 1056: 68 02 00 00 00 pushq $290// DISASM-NEXT: 1056: 68 02 00 00 00 pushq $2
90// DISASM-NEXT: 105b: e9 c0 ff ff ff jmp -64 <.plt>91// DISASM-NEXT: 105b: e9 c0 ff ff ff jmp -64 <.plt>
9192
...@@ -104,18 +105,19 @@...@@ -104,18 +105,19 @@
104// 0x202020 - 0x201046 = 4058105// 0x202020 - 0x201046 = 4058
105106
106// DISASM2: Disassembly of section .plt:107// DISASM2: Disassembly of section .plt:
108// DISASM2-EMPTY:
107// DISASM2-NEXT: .plt:109// DISASM2-NEXT: .plt:
108// DISASM2-NEXT: 201020: ff 35 e2 0f 00 00 pushq 4066(%rip)110// DISASM2-NEXT: 201020: ff 35 e2 1f 00 00 pushq 8162(%rip)
109// DISASM2-NEXT: 201026: ff 25 e4 0f 00 00 jmpq *4068(%rip)111// DISASM2-NEXT: 201026: ff 25 e4 1f 00 00 jmpq *8164(%rip)
110// DISASM2-NEXT: 20102c: 0f 1f 40 00 nopl (%rax)112// DISASM2-NEXT: 20102c: 0f 1f 40 00 nopl (%rax)
111// DISASM2-EMPTY:113// DISASM2-EMPTY:
112// DISASM2-NEXT: bar@plt:114// DISASM2-NEXT: bar@plt:
113// DISASM2-NEXT: 201030: ff 25 e2 0f 00 00 jmpq *4066(%rip)115// DISASM2-NEXT: 201030: ff 25 e2 1f 00 00 jmpq *8162(%rip)
114// DISASM2-NEXT: 201036: 68 00 00 00 00 pushq $0116// DISASM2-NEXT: 201036: 68 00 00 00 00 pushq $0
115// DISASM2-NEXT: 20103b: e9 e0 ff ff ff jmp -32 <.plt>117// DISASM2-NEXT: 20103b: e9 e0 ff ff ff jmp -32 <.plt>
116// DISASM2-EMPTY:118// DISASM2-EMPTY:
117// DISASM2-NEXT: zed@plt:119// DISASM2-NEXT: zed@plt:
118// DISASM2-NEXT: 201040: ff 25 da 0f 00 00 jmpq *4058(%rip)120// DISASM2-NEXT: 201040: ff 25 da 1f 00 00 jmpq *8154(%rip)
119// DISASM2-NEXT: 201046: 68 01 00 00 00 pushq $1121// DISASM2-NEXT: 201046: 68 01 00 00 00 pushq $1
120// DISASM2-NEXT: 20104b: e9 d0 ff ff ff jmp -48 <.plt>122// DISASM2-NEXT: 20104b: e9 d0 ff ff ff jmp -48 <.plt>
121// DISASM2-NOT: 2010C0123// DISASM2-NOT: 2010C0
deps/lld/test/ELF/ppc-rela.s+1-1
...@@ -7,5 +7,5 @@...@@ -7,5 +7,5 @@
7 .long foo7 .long foo
88
9// CHECK: Section ({{.*}}) .rela.dyn {9// CHECK: Section ({{.*}}) .rela.dyn {
10// CHECK-NEXT: 0x1000 R_PPC_ADDR32 foo 0x010// CHECK-NEXT: 0x20000 R_PPC_ADDR32 foo 0x0
11// CHECK-NEXT: }11// CHECK-NEXT: }
deps/lld/test/ELF/ppc-relocs.s deleted-101
...@@ -1,101 +0,0 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc-unknown-freebsd %s -o %t
3# RUN: ld.lld %t -o %t2
4# RUN: llvm-objdump -d %t2 | FileCheck %s
5
6.section .R_PPC_ADDR16_HA,"ax",@progbits
7.globl _start
8_start:
9 lis 4, msg@ha
10msg:
11 .string "foo"
12 len = . - msg
13
14# CHECK: Disassembly of section .R_PPC_ADDR16_HA:
15# CHECK: _start:
16# CHECK: 11000: 3c 80 00 01 lis 4, 1
17# CHECK: msg:
18# CHECK: 11004: 66 6f 6f 00 oris 15, 19, 28416
19
20.section .R_PPC_ADDR16_HI,"ax",@progbits
21.globl _starti
22_starti:
23 lis 4,msgi@h
24msgi:
25 .string "foo"
26 leni = . - msgi
27
28# CHECK: Disassembly of section .R_PPC_ADDR16_HI:
29# CHECK: _starti:
30# CHECK: 11008: 3c 80 00 01 lis 4, 1
31# CHECK: msgi:
32# CHECK: 1100c: 66 6f 6f 00 oris 15, 19, 28416
33
34.section .R_PPC_ADDR16_LO,"ax",@progbits
35 addi 4, 4, msg@l
36mystr:
37 .asciz "blah"
38 len = . - mystr
39
40# CHECK: Disassembly of section .R_PPC_ADDR16_LO:
41# CHECK: .R_PPC_ADDR16_LO:
42# CHECK: 11010: 38 84 10 04 addi 4, 4, 4100
43# CHECK: mystr:
44# CHECK: 11014: 62 6c 61 68 ori 12, 19, 24936
45
46.align 2
47.section .R_PPC_REL24,"ax",@progbits
48.globl .FR_PPC_REL24
49.FR_PPC_REL24:
50 b .Lfoox
51.section .R_PPC_REL24_2,"ax",@progbits
52.Lfoox:
53
54# CHECK: Disassembly of section .R_PPC_REL24:
55# CHECK: .FR_PPC_REL24:
56# CHECK: 1101c: 48 00 00 04 b .+4
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
69.section .R_PPC_REL32,"ax",@progbits
70.globl .FR_PPC_REL32
71.FR_PPC_REL32:
72 .long .Lfoox3 - .
73.section .R_PPC_REL32_2,"ax",@progbits
74.Lfoox3:
75
76# CHECK: Disassembly of section .R_PPC_REL32:
77# CHECK: .FR_PPC_REL32:
78# CHECK: 11024: 00 00 00 04
79
80.section .R_PPC_ADDR32,"ax",@progbits
81.globl .FR_PPC_ADDR32
82.FR_PPC_ADDR32:
83 .long .Lfoox2
84.section .R_PPC_ADDR32_2,"ax",@progbits
85.Lfoox2:
86
87# CHECK: Disassembly of section .R_PPC_ADDR32:
88# CHECK: .FR_PPC_ADDR32:
89# CHECK: 11028: 00 01 10 2c
90
91.align 2
92.section .R_PPC_PLTREL24,"ax",@progbits
93.globl .R_PPC_PLTREL24
94.FR_PPC_PLTREL24:
95 b .Lfoox4@PLT
96.section .R_PPC_PLTREL24_2,"ax",@progbits
97.Lfoox4:
98
99# CHECK: Disassembly of section .R_PPC_PLTREL24:
100# CHECK: .R_PPC_PLTREL24:
101# CHECK: 1102c: 48 00 00 04 b .+4
deps/lld/test/ELF/ppc32-abs-pic.s created+23
...@@ -0,0 +1,23 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: ld.lld -shared %t.o -o %t.so
4# RUN: llvm-nm %t.so | FileCheck --check-prefix=NM %s
5# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOC %s
6
7## R_PPC_ADDR32 is an absolute relocation type.
8## In PIC mode, it creates a relative relocation if the symbol is non-preemptable.
9
10# NM: 00020004 d b
11
12# RELOC: .rela.dyn {
13# RELOC-NEXT: 0x20004 R_PPC_RELATIVE - 0x20004
14# RELOC-NEXT: 0x20000 R_PPC_ADDR32 a 0
15# RELOC-NEXT: }
16
17.globl a, b
18.hidden b
19
20.data
21.long a
22b:
23.long b
deps/lld/test/ELF/ppc32-call-stub-nopic.s created+81
...@@ -0,0 +1,81 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: echo '.globl f, g, h; f: g: h:' | llvm-mc -filetype=obj -triple=powerpc - -o %t1.o
4# RUN: ld.lld -shared %t1.o -soname t1.so -o %t1.so
5
6## Check we can create PLT entries for -fno-PIE executable.
7# RUN: ld.lld %t.o %t1.so -o %t
8# RUN: llvm-readobj -r -d %t | FileCheck --check-prefix=RELOC %s
9# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC %s
10# RUN: llvm-readelf -x .plt %t | FileCheck --check-prefix=HEX %s
11# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
12
13# RELOC: .rela.plt {
14# RELOC-NEXT: 0x10030000 R_PPC_JMP_SLOT f 0x0
15# RELOC-NEXT: 0x10030004 R_PPC_JMP_SLOT g 0x0
16# RELOC-NEXT: }
17
18# SEC: .got PROGBITS 10020070
19# RELOC: PPC_GOT 0x10020070
20
21## .got2+0x8000-0x10004 = 0x30000+0x8000-0x10004 = 65536*2+32764
22# CHECK-LABEL: _start:
23# CHECK-NEXT: bl .+16
24# CHECK-NEXT: bl .+12
25# CHECK-NEXT: bl .+24
26# CHECK-NEXT: bl .+20
27# CHECK-EMPTY:
28
29## -fno-PIC call stubs of f and g.
30## .plt[0] = 0x10030000 = 65536*4099+0
31## .plt[1] = 0x10030004 = 65536*4099+4
32# CHECK-NEXT: 00000000.plt_call32.f:
33# CHECK-NEXT: lis 11, 4099
34# CHECK-NEXT: lwz 11, 0(11)
35# CHECK-NEXT: mtctr 11
36# CHECK-NEXT: bctr
37# CHECK-EMPTY:
38# CHECK-NEXT: 00000000.plt_call32.g:
39# CHECK-NEXT: lis 11, 4099
40# CHECK-NEXT: lwz 11, 4(11)
41# CHECK-NEXT: mtctr 11
42# CHECK-NEXT: bctr
43# CHECK-EMPTY:
44
45## In Secure PLT ABI, .plt stores function pointers to first instructions of .glink
46# HEX: 0x10030000 10010040 10010044
47
48## These instructions are referenced by .plt entries.
49# CHECK: 10010040 .glink:
50# CHECK-NEXT: b .+8
51# CHECK-NEXT: b .+4
52
53## PLTresolve
54## Operands of lis & lwz: .got+4 = 0x10020070+4 = 65536*4098+116
55## Operands of addis & addi: -.glink = -0x10010040 = 65536*-4097-48
56# CHECK-NEXT: lis 12, 4098
57# CHECK-NEXT: addis 11, 11, -4097
58# CHECK-NEXT: lwz 0, 116(12)
59# CHECK-NEXT: addi 11, 11, -64
60
61# CHECK-NEXT: mtctr 0
62# CHECK-NEXT: add 0, 11, 11
63# CHECK-NEXT: lwz 12, 120(12)
64# CHECK-NEXT: add 11, 0, 11
65# CHECK-NEXT: bctr
66
67## glibc crti.o references _GLOBAL_OFFSET_TABLE_.
68.section .init
69 bcl 20, 31, .+4
70.L:
71 mflr 30
72 addis 30, 30, _GLOBAL_OFFSET_TABLE_-.L@ha
73 addi 30, 30, _GLOBAL_OFFSET_TABLE_-.L@l
74
75.text
76.globl _start
77_start:
78 bl f
79 bl f
80 bl g
81 bl g
deps/lld/test/ELF/ppc32-call-stub-pic.s created+151
...@@ -0,0 +1,151 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: echo '.globl f, g, h; f: g: h:' | llvm-mc -filetype=obj -triple=powerpc - -o %t1.o
4# RUN: ld.lld -shared %t1.o -soname t1.so -o %t1.so
5# RUN: echo 'bl f+0x8000@plt' | llvm-mc -filetype=obj -triple=powerpc - -o %t2.o
6
7## Check we can create PLT entries for -fPIE or -fpie executable.
8# RUN: ld.lld -pie %t.o %t1.so %t2.o -o %t
9# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
10# RUN: llvm-readobj -d %t | FileCheck --check-prefix=DYN %s
11# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SEC %s
12# RUN: llvm-readelf -x .plt %t | FileCheck --check-prefix=HEX %s
13# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=CHECK,PIE %s
14
15## Check we can create PLT entries for -fPIC or -fpic DSO.
16# RUN: ld.lld -shared %t.o %t1.so %t2.o -o %t
17# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
18# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=CHECK,SHARED %s
19
20# RELOC: .rela.dyn {
21# RELOC-NEXT: R_PPC_ADDR32 f 0x0
22# RELOC-NEXT: R_PPC_ADDR32 g 0x0
23# RELOC-NEXT: R_PPC_ADDR32 h 0x0
24# RELOC-NEXT: }
25# RELOC-NEXT: .rela.plt {
26# RELOC-NEXT: R_PPC_JMP_SLOT f 0x0
27# RELOC-NEXT: R_PPC_JMP_SLOT g 0x0
28# RELOC-NEXT: R_PPC_JMP_SLOT h 0x0
29# RELOC-NEXT: }
30
31# SEC: .got PROGBITS 00020088
32# DYN: PPC_GOT 0x20088
33
34## .got2+0x8000-0x10004 = 0x30000+0x8000-0x10004 = 65536*2+32764
35# CHECK-LABEL: _start:
36# CHECK-NEXT: bcl 20, 31, .+4
37# CHECK-NEXT: 10004: mflr 30
38# CHECK-NEXT: addis 30, 30, 2
39# CHECK-NEXT: addi 30, 30, 32764
40
41## Two bl 00008000.got2.plt_pic32.f
42# CHECK-NEXT: bl .+40
43# CHECK-NEXT: bl .+36
44## Two bl 00008000.got2.plt_pic32.g
45# CHECK-NEXT: bl .+48
46# CHECK-NEXT: bl .+44
47## Two bl 00008000.got2.plt_pic32.h
48# CHECK-NEXT: bl .+56
49# CHECK-NEXT: bl .+52
50# CHECK-NEXT: addis 30, 30, {{.*}}
51# CHECK-NEXT: addi 30, 30, {{.*}}
52## bl 00008000.plt_pic32.f
53# CHECK-NEXT: bl .+56
54## bl 00008000.plt_pic32.f
55# CHECK-NEXT: bl .+68
56# CHECK-EMPTY:
57
58## -fPIC call stubs of f and g.
59# CHECK-NEXT: 00008000.got2.plt_pic32.f:
60# CHECK-NEXT: lwz 11, 32760(30)
61# CHECK-NEXT: mtctr 11
62# CHECK-NEXT: bctr
63# CHECK-NEXT: nop
64# CHECK-EMPTY:
65# CHECK-NEXT: 00008000.got2.plt_pic32.g:
66# CHECK-NEXT: lwz 11, 32764(30)
67# CHECK-NEXT: mtctr 11
68# CHECK-NEXT: bctr
69# CHECK-NEXT: nop
70# CHECK-EMPTY:
71
72## The -fPIC call stub of h needs two instructions addis+lwz to represent the offset 65536*1-32768.
73# CHECK-NEXT: 00008000.got2.plt_pic32.h:
74# CHECK-NEXT: addis 11, 30, 1
75# CHECK-NEXT: lwz 11, -32768(11)
76# CHECK-NEXT: mtctr 11
77# CHECK-NEXT: bctr
78# CHECK-EMPTY:
79
80## -fpic call stub of f.
81# CHECK-NEXT: 00000000.plt_pic32.f:
82# CHECK-NEXT: addis 11, 30, 2
83# PIE-NEXT: lwz 11, -144(11)
84# SHARED-NEXT: lwz 11, -136(11)
85# CHECK-NEXT: mtctr 11
86# CHECK-NEXT: bctr
87# CHECK-EMPTY:
88
89## Another -fPIC call stub of f from another object file %t2.o
90## .got2 may have different addresses in different object files,
91## so the call stub cannot be shared.
92# CHECK-NEXT: 00008000.got2.plt_pic32.f:
93
94## In Secure PLT ABI, .plt stores function pointers to first instructions of .glink
95# HEX: 0x0003fff8 00010090 00010094 00010098
96
97## These instructions are referenced by .plt entries.
98# CHECK: 00010090 .glink:
99# CHECK-NEXT: b .+12
100# CHECK-NEXT: b .+8
101# CHECK-NEXT: b .+4
102
103## PLTresolve
104## Operand of addi: 0x100a8-.glink = 24
105# CHECK-NEXT: addis 11, 11, 0
106# CHECK-NEXT: mflr 0
107# CHECK-NEXT: bcl 20, 31, .+4
108# CHECK-NEXT: 100a8: addi 11, 11, 24
109
110# CHECK-NEXT: mflr 12
111# CHECK-NEXT: mtlr 0
112# CHECK-NEXT: subf 11, 12, 11
113
114## Operand of lwz in -pie mode: &.got[1] - 0x100a8 = 0x20088+4 - 0x100a8 = 65536*1-28
115# CHECK-NEXT: addis 12, 12, 1
116# PIE-NEXT: lwz 0, -28(12)
117# SHARED-NEXT: lwz 0, -36(12)
118
119# PIE-NEXT: lwz 12, -24(12)
120# SHARED-NEXT: lwz 12, -32(12)
121# CHECK-NEXT: mtctr 0
122# CHECK-NEXT: add 0, 11, 11
123# CHECK-NEXT: add 11, 0, 11
124# CHECK-NEXT: bctr
125
126.section .got2,"aw"
127.space 65516
128.long f
129.long g
130.long h
131
132.text
133.globl _start
134_start:
135 bcl 20,31,.L
136.L:
137 mflr 30
138 addis 30, 30, .got2+0x8000-.L@ha
139 addi 30, 30, .got2+0x8000-.L@l
140 bl f+0x8000@plt
141 bl f+0x8000@plt
142 bl g+0x8000@plt
143 bl g+0x8000@plt
144 bl h+0x8000@plt
145 bl h+0x8000@plt
146
147## An addend of 0 indicates r30 is stored in _GLOBAL_OFFSET_TABLE_.
148## The existing thunk is incompatible, thus it cannot be reused.
149 addis 30, 30, _GLOBAL_OFFSET_TABLE_-.L@ha
150 addi 30, 30, _GLOBAL_OFFSET_TABLE_-.L@l
151 bl f@plt
deps/lld/test/ELF/ppc32-gnu-ifunc-nonpreemptable.s created+45
...@@ -0,0 +1,45 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
5# RUN: llvm-readelf -s %t | FileCheck --check-prefix=SYM %s
6# RUN: llvm-readelf -x .got2 %t | FileCheck --check-prefix=HEX %s
7# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
8
9# RELOC: .rela.plt {
10# RELOC-NEXT: 0x10020004 R_PPC_IRELATIVE - 0x10010000
11# RELOC-NEXT: }
12
13# SYM: 10010020 0 FUNC GLOBAL DEFAULT {{.*}} func
14# HEX: 0x10020000 10010020
15
16.section .got2,"aw"
17.long func
18
19# CHECK: func_resolver:
20# CHECK-NEXT: 10010000: blr
21# CHECK: _start:
22# CHECK-NEXT: bl .+12
23# CHECK-NEXT: lis 9, 4097
24# CHECK-NEXT: addi 9, 9, 32
25# CHECK-EMPTY:
26# CHECK-NEXT: 00000000.plt_call32.func:
27## 10020004 = 65536*4098+4
28# CHECK-NEXT: lis 11, 4098
29# CHECK-NEXT: lwz 11, 4(11)
30
31.text
32.globl func
33.type func, @gnu_indirect_function
34func:
35.globl func_resolver
36.type func_resolver, @function
37func_resolver:
38 blr
39
40.globl _start
41_start:
42 bl func
43
44 lis 9, func@ha
45 la 9, func@l(9)
deps/lld/test/ELF/ppc32-gnu-ifunc.s created+41
...@@ -0,0 +1,41 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
5# RUN: llvm-readelf -S -s %t | FileCheck --check-prefixes=SEC,SYM %s
6# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
7
8# RELOC: .rela.plt {
9# RELOC-NEXT: 0x10020000 R_PPC_IRELATIVE - 0x10010000
10# RELOC-NEXT: }
11
12# SEC: .rela.plt RELA 100000d4 0000d4 00000c
13# SYM: 10010000 0 FUNC GLOBAL DEFAULT {{.*}} func
14
15# CHECK: func_resolver:
16# CHECK-NEXT: 10010000:
17# CHECK: _start:
18# CHECK-NEXT: bl .+20
19## .rela.plt = 0x100000d4 = 65536*4096+212
20## end(.rela.plt) = 0x100000d4+0xc = 65536*4096+224
21# CHECK-NEXT: lis 9, 4096
22# CHECK-NEXT: lis 8, 4096
23# CHECK-NEXT: addi 9, 9, 212
24# CHECK-NEXT: addi 8, 8, 224
25
26.globl func
27.type func, @gnu_indirect_function
28func:
29.globl func_resolver
30.type func_resolver, @function
31func_resolver:
32 blr
33
34.globl _start
35_start:
36 bl func
37
38 lis 9, __rela_iplt_start@ha
39 lis 8, __rela_iplt_end@ha
40 la 9, __rela_iplt_start@l(9)
41 la 8, __rela_iplt_end@l(8)
deps/lld/test/ELF/ppc32-local-branch.s created+21
...@@ -0,0 +1,21 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: echo '.globl foo; foo: blr' | llvm-mc -filetype=obj -triple=powerpc - -o %t1.o
4# RUN: ld.lld %t.o %t1.o -o %t
5# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
6
7## R_PPC_REL24 and R_PPC_PLTREL24 are converted to PC relative relocations if the
8## symbol is non-preemptable. The addend of R_PPC_PLTREL24 should be ignored.
9
10# CHECK: _start:
11# CHECK-NEXT: b .+12
12# CHECK-NEXT: b .+8
13# CHECK-NEXT: b .+4
14# CHECK-EMPTY:
15# CHECK-NEXT: foo:
16
17.globl _start
18_start:
19 b foo # R_PPC_REL24
20 b foo@plt # R_PPC_PLTREL24
21 b foo+32768@plt #_PPC_PLTREL24 with addend
deps/lld/test/ELF/ppc32-reloc-addr.s created+26
...@@ -0,0 +1,26 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: ld.lld %t.o --defsym=a=0x1234 --defsym=b=0xbcdef -o %t
4# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
5# RUN: llvm-objdump -s --no-show-raw-insn %t | FileCheck --check-prefix=HEX %s
6
7.section .R_PPC_ADDR16_HA,"ax",@progbits
8 lis 4, a@ha
9# CHECK-LABEL: section .R_PPC_ADDR16_HA:
10# CHECK: lis 4, 0
11
12.section .R_PPC_ADDR16_HI,"ax",@progbits
13 lis 4, a@h
14# CHECK-LABEL: section .R_PPC_ADDR16_HI:
15# CHECK: lis 4, 0
16
17.section .R_PPC_ADDR16_LO,"ax",@progbits
18 addi 4, 4, a@l
19# CHECK-LABEL: section .R_PPC_ADDR16_LO:
20# CHECK: addi 4, 4, 4660
21
22.section .R_PPC_ADDR32,"a",@progbits
23 .long a
24 .long b
25# HEX-LABEL: section .R_PPC_ADDR32:
26# HEX-NEXT: 100000b4 00001234 000bcdef
deps/lld/test/ELF/ppc32-reloc-got.s created+36
...@@ -0,0 +1,36 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: echo '.globl b; b:' | llvm-mc -filetype=obj -triple=powerpc - -o %t1.o
4# RUN: ld.lld -shared %t1.o -o %t1.so
5
6# RUN: ld.lld %t.o %t1.so -o %t
7# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
8# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
9# RUN: llvm-readobj -x .got %t | FileCheck --check-prefix=HEX %s
10# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
11
12## Check we can handle R_PPC_GOT16, which may be generated by -fpic code.
13
14# SEC: .got PROGBITS 00020068 020068 000014
15
16# RELOC: .rela.dyn {
17# RELOC-NEXT: 0x10020078 R_PPC_GLOB_DAT b 0x0
18# RELOC-NEXT: }
19
20# NM: 10030000 d a
21
22## The GOT slot of a can be filled at link time.
23# HEX: section '.got':
24# HEX: 0x10020068 {{[0-9a-f]+}} 00000000 00000000 10030000
25
26## a: &.got[3] - _GLOBAL_OFFSET_TABLE_ = 12
27## b: &.got[4] - _GLOBAL_OFFSET_TABLE_ = 16
28# CHECK: lwz 3, 12(30)
29# CHECK: lwz 4, 16(30)
30
31lwz 3,a@got(30)
32lwz 4,b@got(30)
33
34.data
35a:
36.long _GLOBAL_OFFSET_TABLE_
deps/lld/test/ELF/ppc32-reloc-rel.s created+34
...@@ -0,0 +1,34 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
5
6.section .R_PPC_REL14,"ax",@progbits
7 beq 1f
81:
9# CHECK-LABEL: section .R_PPC_REL14:
10# CHECK: bt 2, .+4
11
12.section .R_PPC_REL24,"ax",@progbits
13 b 1f
141:
15# CHECK-LABEL: section .R_PPC_REL24:
16# CHECK: b .+4
17
18.section .R_PPC_REL32,"ax",@progbits
19 .long 1f - .
201:
21# HEX-LABEL: section .R_PPC_REL32:
22# HEX-NEXT: 10010008 00000004
23
24.section .R_PPC_PLTREL24,"ax",@progbits
25 b 1f@PLT+32768
261:
27# CHECK-LABEL: section .R_PPC_PLTREL24:
28# CHECK: b .+4
29
30.section .R_PPC_LOCAL24PC,"ax",@progbits
31 b 1f@local
321:
33# CHECK-LABEL: section .R_PPC_LOCAL24PC:
34# CHECK: b .+4
deps/lld/test/ELF/ppc32-tls-gd.s created+98
...@@ -0,0 +1,98 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: echo '.tbss; .globl b, c; b: .zero 4; c:' | llvm-mc -filetype=obj -triple=powerpc - -o %t1.o
4# RUN: ld.lld -shared -soname=t1.so %t1.o -o %t1.so
5# RUN: echo '.globl __tls_get_addr; __tls_get_addr:' | llvm-mc -filetype=obj -triple=powerpc - -o %tga.o
6
7# RUN: ld.lld -shared %t.o %t1.o -o %t.so
8# RUN: llvm-readobj -d %t.so | FileCheck --check-prefix=GD-DYN %s
9# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=GD-REL %s
10# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=GD %s
11
12# RUN: ld.lld %t.o %t1.o %tga.o -o %t
13# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
14# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
15
16# RUN: ld.lld %t.o %t1.so -o %t
17# RUN: llvm-readobj -r %t | FileCheck --check-prefix=IE-REL %s
18# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=IE %s
19
20## DT_PPC_GOT represents the address of _GLOBAL_OFFSET_TABLE_.
21# GD-DYN: PPC_GOT 0x20078
22
23# GD-REL: .rela.dyn {
24# GD-REL-NEXT: 0x20078 R_PPC_DTPMOD32 a 0x0
25# GD-REL-NEXT: 0x2007C R_PPC_DTPREL32 a 0x0
26# GD-REL-NEXT: 0x20080 R_PPC_DTPMOD32 b 0x0
27# GD-REL-NEXT: 0x20084 R_PPC_DTPREL32 b 0x0
28# GD-REL-NEXT: 0x20088 R_PPC_DTPMOD32 c 0x0
29# GD-REL-NEXT: 0x2008C R_PPC_DTPREL32 c 0x0
30# GD-REL-NEXT: }
31
32## &DTPMOD(a) - _GLOBAL_OFFSET_TABLE_ = 0x20078 - 0x20078 = 0
33# GD: addi 3, 31, 0
34# GD-NEXT: bl .+32
35# GD-NEXT: lwz 3, 0(3)
36
37## &DTPMOD(b) - _GLOBAL_OFFSET_TABLE_ = 0x20080 - 0x20078 = 8
38# GD-NEXT: addi 3, 31, 8
39# GD-NEXT: bl .+20
40# GD-NEXT: lwz 3, 0(3)
41
42## &DTPMOD(c) - _GLOBAL_OFFSET_TABLE_ = 0x20088 - 0x20078 = 16
43# GD-NEXT: addi 3, 9, 16
44# GD-NEXT: bl .+8
45# GD-NEXT: lwz 3, 0(3)
46
47# NOREL: no relocations
48
49## a@tprel = 8-0x7000 = -28664
50# LE: addis 3, 2, 0
51# LE-NEXT: addi 3, 3, -28664
52# LE-NEXT: lwz 3, 0(3)
53## b@tprel = 12-0x7000 = -28660
54# LE-NEXT: addis 3, 2, 0
55# LE-NEXT: addi 3, 3, -28660
56# LE-NEXT: lwz 3, 0(3)
57## c@tprel = 16-0x7000 = -28656
58# LE-NEXT: addis 3, 2, 0
59# LE-NEXT: addi 3, 3, -28656
60# LE-NEXT: lwz 3, 0(3)
61
62# IE-REL: .rela.dyn {
63# IE-REL-NEXT: 0x10020068 R_PPC_TPREL32 b 0x0
64# IE-REL-NEXT: 0x1002006C R_PPC_TPREL32 c 0x0
65# IE-REL-NEXT: }
66
67## a is relaxed to use LE.
68## a@tprel = st_value(a)-0x8000 = -28664
69# IE: addis 3, 2, 0
70# IE-NEXT: addi 3, 3, -28664
71# IE-NEXT: lwz 3, 0(3)
72## &.got[0] - _GLOBAL_OFFSET_TABLE_ = 0
73# IE-NEXT: lwz 3, 0(31)
74# IE-NEXT: add 3, 3, 2
75# IE-NEXT: lwz 3, 0(3)
76## &.got[1] - _GLOBAL_OFFSET_TABLE_ = 4
77# IE-NEXT: lwz 3, 4(9)
78# IE-NEXT: add 3, 3, 2
79# IE-NEXT: lwz 3, 0(3)
80
81addi 3, 31, a@got@tlsgd
82bl __tls_get_addr(a@tlsgd)
83lwz 3, 0(3)
84
85addi 3, 31, b@got@tlsgd
86bl __tls_get_addr(b@tlsgd)
87lwz 3, 0(3)
88
89## -fpic may use a different register (e.g. r9).
90addi 3, 9, c@got@tlsgd
91bl __tls_get_addr(c@tlsgd)
92lwz 3, 0(3)
93
94.section .tbss
95.globl a
96.zero 8
97a:
98.zero 4
deps/lld/test/ELF/ppc32-tls-ie.s created+67
...@@ -0,0 +1,67 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3
4# RUN: ld.lld -shared %t.o -o %t.so
5# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=IE-REL %s
6# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=IE %s
7
8# RUN: ld.lld %t.o -o %t
9# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
10# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
11
12## A non-preemptable symbol (b) has 0 st_shndx.
13# IE-REL: .rela.dyn {
14# IE-REL-NEXT: 0x2005C R_PPC_TPREL32 - 0xC
15# IE-REL-NEXT: 0x20058 R_PPC_TPREL32 a 0x0
16# IE-REL-NEXT: }
17
18## &.got[0] - _GLOBAL_OFFSET_TABLE_ = 0
19# IE: lwz 10, 0(9)
20# IE-NEXT: add 10, 10, 2
21## &.got[1] - _GLOBAL_OFFSET_TABLE_ = 4
22# IE-NEXT: lwz 8, 4(7)
23# IE-NEXT: lbzx 10, 8, 2
24
25# NOREL: no relocations
26
27## a@tprel = st_value(a)-0x7000 = -28664
28## b@tprel = st_value(b)-0x7000 = -28660
29# LE: addis 10, 2, 0
30# LE-NEXT: addi 10, 10, -28664
31# LE-NEXT: addis 8, 2, 0
32# LE-NEXT: lbz 10, -28660(8)
33
34lwz 10, a@got@tprel(9)
35add 10, 10, a@tls
36
37lwz 8, c@got@tprel(7)
38lbzx 10, 8, c@tls
39
40## In IE, these instructions (op rT, rA, x@tls) are not changed.
41# IE-NEXT: lhzx 12, 2, 2
42# IE-NEXT: lwzx 13, 3, 2
43# IE-NEXT: stbx 14, 4, 2
44# IE-NEXT: sthx 15, 5, 2
45# IE-NEXT: stwx 16, 6, 2
46
47## In LE, these X-Form instructions are changed to their corresponding D-Form.
48# LE-NEXT: lhz 12, -28660(2)
49# LE-NEXT: lwz 13, -28660(3)
50# LE-NEXT: stb 14, -28660(4)
51# LE-NEXT: sth 15, -28660(5)
52# LE-NEXT: stw 16, -28660(6)
53
54lhzx 12, 2, s@tls
55lwzx 13, 3, i@tls
56stbx 14, 4, c@tls
57sthx 15, 5, s@tls
58stwx 16, 6, i@tls
59
60.section .tbss
61.globl a
62.zero 8
63a:
64.zero 4
65c:
66s:
67i:
deps/lld/test/ELF/ppc32-tls-ld.s created+82
...@@ -0,0 +1,82 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: echo '.globl __tls_get_addr; __tls_get_addr:' | llvm-mc -filetype=obj -triple=powerpc - -o %tga.o
4
5# RUN: ld.lld -shared %t.o -o %t.so
6# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=LD-REL %s
7# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=LD %s
8
9# RUN: ld.lld %t.o %tga.o -o %t
10# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
11# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
12
13# LD-REL: .rela.dyn {
14# LD-REL-NEXT: 0x20078 R_PPC_DTPMOD32 - 0x0
15# LD-REL-NEXT: }
16
17## .got - _GLOBAL_OFFSET_TABLE_ = 0
18# LD: addi 3, 30, 0
19# LD-NEXT: bl .+40
20## a@dtprel = st_value(a)-0x8000 = 65540-0x8000 = 65536*1-32764
21## b@dtprel = st_value(a)-0x8000 = 131080-0x8000 = 65536*2-32760
22# LD-NEXT: addis 9, 3, 1
23# LD-NEXT: addis 10, 3, 2
24# LD-NEXT: addi 9, 9, -32764
25# LD-NEXT: addi 10, 10, -32760
26## small@dtprel = st_value(small)-0x8000 = 4-0x8000 = -32764
27# LD-NEXT: addi 9, 3, -32764
28
29## Check that b@got@tlsld does not allocate another GOT entry.
30## It shares In.Got->TlsIndexOff allocated when processing a@got@tlsld.
31## .got - _GLOBAL_OFFSET_TABLE_ = 0
32# LD-NEXT: addi 3, 9, 0
33# LD-NEXT: bl .+12
34## b@dtprel = st_value(a)-0x8000 = 131080-0x8000 = 65536*2-32760
35# LD-NEXT: addis 29, 3, 2
36# LD-NEXT: addi 29, 29, -32760
37
38## When producing an executable, the LD code sequence can be relaxed to LE.
39## It is the same as GD->LE.
40## tpoff(_TLS_MODULE_BASE_) = 0, tpoff(a) = -8, tpoff(b) = -4
41
42# NOREL: no relocations
43
44## Set r3 to r2+4096
45# LE: addis 3, 2, 0
46# LE-NEXT: addi 3, 3, 4096
47## a@tprel = 65540-0x7000 = 65536*1-32764
48## b@tprel = 131080-0x7000 = 65536*2-32760
49# LE-NEXT: addis 9, 3, 1
50# LE-NEXT: addis 10, 3, 2
51# LE-NEXT: addi 9, 9, -32764
52# LE-NEXT: addi 10, 10, -32760
53## small@tprel = 4-0x7000 = -32764
54# LE-NEXT: addi 9, 3, -32764
55
56## Set r3 to r2+4096
57# LE-NEXT: addis 3, 2, 0
58# LE-NEXT: addi 3, 3, 4096
59## b@tprel = 131080-0x7000 = 65536*2-32760
60# LE-NEXT: addis 29, 3, 2
61# LE-NEXT: addi 29, 29, -32760
62
63addi 3, 30, a@got@tlsld
64bl __tls_get_addr(a@tlsld)
65addis 9, 3, a@dtprel@ha
66addis 10, 3, b@dtprel@ha
67addi 9, 9, a@dtprel@l
68addi 10, 10, b@dtprel@l
69addi 9, 3, small@dtprel
70
71addi 3, 9, b@got@tlsld
72bl __tls_get_addr(b@tlsld)
73addis 29, 3, b@dtprel@ha
74addi 29, 29, b@dtprel@l
75
76.section .tbss
77.zero 4
78small:
79.zero 65536
80a:
81.zero 65540
82b:
deps/lld/test/ELF/ppc32-tls-le.s created+24
...@@ -0,0 +1,24 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
5
6## a@tprel = st_value(a)-0x7000 = -28664
7## b@tprel = st_value(b)-0x7000 = -28660
8# LE: addis 9, 2, 0
9# LE-NEXT: addi 9, 9, -28664
10# LE-NEXT: addis 10, 2, 0
11# LE-NEXT: lwz 9, -28660(10)
12
13addis 9, 2, a@tprel@ha
14addi 9, 9, a@tprel@l
15
16addis 10, 2, b@tprel@ha
17lwz 9,b@tprel@l(10)
18
19.section .tbss
20.globl a
21.zero 8
22a:
23.zero 4
24b:
deps/lld/test/ELF/ppc32-weak-undef-call.s created+19
...@@ -0,0 +1,19 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=EXE %s
5# RUN: ld.lld -pie %t.o -o %t
6# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=EXE %s
7# RUN: ld.lld -shared %t.o -o %t
8# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=SHARED %s
9
10## It does not really matter how we fixup it, but we cannot overflow and
11## should not generate a call stub (this would waste space).
12# EXE: bl .+0
13
14## With -shared, create a call stub. ld.bfd produces bl .+0
15# SHARED: bl .+4
16# SHARED: 00000000.plt_pic32.foo:
17
18.weak foo
19bl foo
deps/lld/test/ELF/ppc64-abs32-dyn.s created+14
...@@ -0,0 +1,14 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
3# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s
4
5## Test we don't create R_AARCH64_RELATIVE.
6
7# CHECK: error: relocation R_PPC64_ADDR32 cannot be used against symbol hidden; recompile with -fPIC
8
9.globl hidden
10.hidden hidden
11hidden:
12
13.data
14.long hidden
deps/lld/test/ELF/ppc64-abs64-dyn.s created+29
...@@ -0,0 +1,29 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
3# RUN: ld.lld -shared %t.o -o %t.so
4# RUN: llvm-readobj -r %t.so | FileCheck %s
5
6# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
7# RUN: ld.lld -shared %t.o -o %t.so
8# RUN: llvm-readobj -r %t.so | FileCheck %s
9
10## Test that we create R_PPC64_RELATIVE for R_PPC64_ADDR64 to non-preemptable
11## symbols and R_PPC64_TOC in writable sections.
12
13## FIXME the addend for offset 0x20000 should be TOC base+0x8000+1, not 0x80001.
14# CHECK: .rela.dyn {
15# CHECK-NEXT: 0x20000 R_PPC64_RELATIVE - 0x8001
16# CHECK-NEXT: 0x20008 R_PPC64_RELATIVE - 0x20001
17# CHECK-NEXT: 0x20010 R_PPC64_ADDR64 external 0x1
18# CHECK-NEXT: 0x20018 R_PPC64_ADDR64 global 0x1
19# CHECK-NEXT: }
20
21.data
22.globl global
23global:
24local:
25
26.quad .TOC.@tocbase + 1
27.quad local + 1
28.quad external + 1
29.quad global + 1
deps/lld/test/ELF/ppc64-addr16-error.s deleted-13
...@@ -1,13 +0,0 @@
1// REQUIRES: ppc
2
3// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t
4// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-addr16-error.s -o %t2
5// RUN: not ld.lld -shared %t %t2 -o /dev/null 2>&1 | FileCheck %s
6
7// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
8// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-addr16-error.s -o %t2
9// RUN: not ld.lld -shared %t %t2 -o /dev/null 2>&1 | FileCheck %s
10
11.short sym+65539
12
13// CHECK: relocation R_PPC64_ADDR16 out of range: 65539 is not in [-32768, 32767]
deps/lld/test/ELF/ppc64-bsymbolic-toc-restore.s+2-2
...@@ -53,7 +53,7 @@ caller:...@@ -53,7 +53,7 @@ caller:
53# CHECK-LABEL: caller53# CHECK-LABEL: caller
54# CHECK: bl .+4454# CHECK: bl .+44
55# CHECK-NEXT: mr 31, 355# CHECK-NEXT: mr 31, 3
56# CHECK-NEXT: bl .+6710881656# CHECK-NEXT: bl .+44
57# CHECK-NEXT: ld 2, 24(1)57# CHECK-NEXT: ld 2, 24(1)
58# CHECK-NEXT: add 3, 3, 3158# CHECK-NEXT: add 3, 3, 31
59# CHECK-NEXT: addi 1, 1, 3259# CHECK-NEXT: addi 1, 1, 32
...@@ -63,6 +63,6 @@ caller:...@@ -63,6 +63,6 @@ caller:
63# CHECK-EMPTY:63# CHECK-EMPTY:
64# CHECK-NEXT: def:64# CHECK-NEXT: def:
65# CHECK-NEXT: addis 2, 12, 265# CHECK-NEXT: addis 2, 12, 2
66# CHECK-NEXT: addi 2, 2, -3263666# CHECK-NEXT: addi 2, 2, -32616
67# CHECK-NEXT: li 3, 5567# CHECK-NEXT: li 3, 55
68# CHECK-NEXT: blr68# CHECK-NEXT: blr
deps/lld/test/ELF/ppc64-call-reach.s+26-30
...@@ -3,16 +3,16 @@...@@ -3,16 +3,16 @@
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \4# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \
5# RUN: %t.o -o %t5# RUN: %t.o -o %t
6# RUN: llvm-objdump -d %t | FileCheck %s6# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
7# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \7# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \
8# RUN: %t.o -o %t8# RUN: %t.o -o %t
9# RUN: llvm-objdump -d %t | FileCheck %s9# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
10# RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \10# RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \
11# RUN: %t.o -o %t11# RUN: %t.o -o %t
12# RUN: llvm-objdump -d %t | FileCheck --check-prefix=NEGOFFSET %s12# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NEGOFFSET %s
13# RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \13# RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \
14# RUN: %t.o -o %t14# RUN: %t.o -o %t
15# RUN: llvm-objdump -d %t | FileCheck --check-prefix=THUNK %s15# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=THUNK %s
16# RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s16# RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s
17# RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \17# RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \
18# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s18# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s
...@@ -20,16 +20,16 @@...@@ -20,16 +20,16 @@
20# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o20# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
21# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \21# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \
22# RUN: %t.o -o %t22# RUN: %t.o -o %t
23# RUN: llvm-objdump -d %t | FileCheck %s23# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
24# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \24# RUN: ld.lld --defsym callee=0x12010010 --defsym tail_callee=0x12010020 \
25# RUN: %t.o -o %t25# RUN: %t.o -o %t
26# RUN: llvm-objdump -d %t | FileCheck %s26# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
27# RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \27# RUN: ld.lld --defsym callee=0xE010014 --defsym tail_callee=0xE010024 \
28# RUN: %t.o -o %t28# RUN: %t.o -o %t
29# RUN: llvm-objdump -d %t | FileCheck --check-prefix=NEGOFFSET %s29# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NEGOFFSET %s
30# RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \30# RUN: ld.lld --defsym callee=0x12010018 --defsym tail_callee=0x12010028 \
31# RUN: %t.o -o %t31# RUN: %t.o -o %t
32# RUN: llvm-objdump -d %t | FileCheck --check-prefix=THUNK %s32# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=THUNK %s
33# RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s33# RUN: llvm-readelf --sections %t | FileCheck --check-prefix=BRANCHLT %s
34# RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \34# RUN: not ld.lld --defsym callee=0x1001002D --defsym tail_callee=0x1001002F \
35# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s35# RUN: %t.o -o %t 2>&1 | FileCheck --check-prefix=MISSALIGNED %s
...@@ -58,37 +58,33 @@ test:...@@ -58,37 +58,33 @@ test:
58# Check that we are branching to the definitions, and not range-extending58# Check that we are branching to the definitions, and not range-extending
59# thunks.59# thunks.
60# CHECK-LABEL: test60# CHECK-LABEL: test
61# CHECK: 10010014: {{.*}} bl .+3355442861# CHECK: 10010014: bl .+33554428
62# CHECK: 10010024: {{.*}} b .+3355442862# CHECK: 10010024: b .+33554428
6363
64# NEGOFFSET-LABEL: test64# NEGOFFSET-LABEL: test
65# NEGOFFSET: 10010014: {{.*}} bl .+3355443265# NEGOFFSET: 10010014: bl .-33554432
66# NEGOFFSET: 10010024: {{.*}} b .+3355443266# NEGOFFSET: 10010024: b .+33554432
67
68# THUNK-LABEL: test:
69# THUNK: 10010014: bl .+20
70# THUNK: 10010024: b .+20
6771
68# .branch_lt[0]72# .branch_lt[0]
69# THUNK-LABEL: __long_branch_callee:73# THUNK-LABEL: __long_branch_callee:
70# THUNK-NEXT: 10010000: {{.*}} addis 12, 2, -174# THUNK-NEXT: 10010028: addis 12, 2, 1
71# THUNK-NEXT: ld 12, -32768(12)75# THUNK-NEXT: ld 12, -32768(12)
72# THUNK-NEXT: mtctr 1276# THUNK-NEXT: mtctr 12
73# THUNK-NEXT: bctr77# THUNK-NEXT: bctr
7478
75# .branch_lt[1]79# .branch_lt[1]
76# THUNK-LABEL: __long_branch_tail_callee:80# THUNK-LABEL: __long_branch_tail_callee:
77# THUNK-NEXT: 10010010: {{.*}} addis 12, 2, -181# THUNK-NEXT: 10010038: addis 12, 2, 1
78# THUNK-NEXT: ld 12, -32760(12)82# THUNK-NEXT: ld 12, -32760(12)
79# THUNK-NEXT: mtctr 1283# THUNK-NEXT: mtctr 12
80# THUNK-NEXT: bctr84# 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
8885
89# The offset from the TOC to the .branch_lt section is (-1 << 16) - 32768.86# The offset from the TOC to the .branch_lt section is (-1 << 16) - 32768.
90# Name Type Address Off Size87# Name Type Address Off Size
91# BRANCHLT: .branch_lt PROGBITS 0000000010020000 020000 00001088# BRANCHLT: .got PROGBITS 0000000010020000 020000 000008
92# BRANCHLT: .got PROGBITS 0000000010030000 030000 00000889# BRANCHLT: .branch_lt PROGBITS 0000000010030000 030000 000010
93# BRANCHLT-NOT: .plt90# BRANCHLT-NOT: .plt
94
deps/lld/test/ELF/ppc64-dtprel.s+17-46
...@@ -4,15 +4,15 @@...@@ -4,15 +4,15 @@
4// RUN: ld.lld -shared %t.o -o %t.so4// RUN: ld.lld -shared %t.o -o %t.so
5// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s5// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
6// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s6// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s
7// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s7// RUN: llvm-readelf -x .got %t.so | FileCheck --check-prefix=HEX-LE %s
8// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=GotDisLE %s8// RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=Dis %s
99
10// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o10// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
11// RUN: ld.lld -shared %t.o -o %t.so11// RUN: ld.lld -shared %t.o -o %t.so
12// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s12// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
13// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s13// RUN: llvm-readelf -r %t.so | FileCheck --check-prefix=OutputRelocs %s
14// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=Dis %s14// RUN: llvm-readelf -x .got %t.so | FileCheck --check-prefix=HEX-BE %s
15// RUN: llvm-objdump -D %t.so | FileCheck --check-prefix=GotDisBE %s15// RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=Dis %s
1616
17 .text17 .text
18 .abiversion 218 .abiversion 2
...@@ -97,15 +97,6 @@ test_not_adjusted:...@@ -97,15 +97,6 @@ test_not_adjusted:
97 mtlr 097 mtlr 0
98 blr98 blr
9999
100 .globl test_got_dtprel
101 .p2align 4
102 .type test_got_dtprel,@function
103test_got_dtprel:
104 addis 3, 2, i@got@dtprel@ha
105 ld 3, i@got@dtprel@l(3)
106 addis 3, 2, i@got@dtprel@h
107 addi 3, 2, i@got@dtprel
108
109 .section .debug_addr,"",@progbits100 .section .debug_addr,"",@progbits
110 .quad i@dtprel+32768101 .quad i@dtprel+32768
111102
...@@ -137,10 +128,6 @@ k:...@@ -137,10 +128,6 @@ k:
137// InputRelocs: R_PPC64_DTPREL16_HIGHER {{[0-9a-f]+}} k + 0128// InputRelocs: R_PPC64_DTPREL16_HIGHER {{[0-9a-f]+}} k + 0
138// InputRelocs: R_PPC64_DTPREL16_HI {{[0-9a-f]+}} k + 0129// InputRelocs: R_PPC64_DTPREL16_HI {{[0-9a-f]+}} k + 0
139// InputRelocs: R_PPC64_DTPREL16_LO {{[0-9a-f]+}} k + 0130// InputRelocs: R_PPC64_DTPREL16_LO {{[0-9a-f]+}} k + 0
140// InputRelocs: R_PPC64_GOT_DTPREL16_HA {{[0-9a-f]+}} i + 0
141// InputRelocs: R_PPC64_GOT_DTPREL16_LO_DS {{[0-9a-f]+}} i + 0
142// InputRelocs: R_PPC64_GOT_DTPREL16_HI {{[0-9a-f]+}} i + 0
143// InputRelocs: R_PPC64_GOT_DTPREL16_DS {{[0-9a-f]+}} i + 0
144// InputRelocs: Relocation section '.rela.debug_addr'131// InputRelocs: Relocation section '.rela.debug_addr'
145// InputRelocs: R_PPC64_DTPREL64 {{[0-9a-f]+}} i + 8000132// InputRelocs: R_PPC64_DTPREL64 {{[0-9a-f]+}} i + 8000
146133
...@@ -150,10 +137,19 @@ k:...@@ -150,10 +137,19 @@ k:
150// OutputRelocs-NEXT: R_PPC64_DTPMOD64137// OutputRelocs-NEXT: R_PPC64_DTPMOD64
151138
152139
153// i@dtprel --> (1024 - 0x8000) = -31744140// The got entry for i is at .got+8*3 = 0x420510
154// Dis: test:141// i@dtprel = 1024 - 0x8000 = -31744 = 0xffffffffffff8400
155// Dis: addi 4, 3, -31744142// HEX-LE: section '.got':
156// Dis: lwa 4, -31744(3)143// HEX-LE-NEXT: 4204f8 f8844200 00000000 00000000 00000000
144// HEX-LE-NEXT: 420508 00000000 00000000
145
146// HEX-BE: section '.got':
147// HEX-BE-NEXT: 4204f8 00000000 004284f8 00000000 00000000
148// HEX-BE-NEXT: 420508 00000000 00000000
149
150// Dis: test:
151// Dis: addi 4, 3, -31744
152// Dis-NEXT: lwa 4, -31744(3)
157153
158// #k@dtprel(1024 + 4 + 1024 * 1024 * 4) = 0x400404154// #k@dtprel(1024 + 4 + 1024 * 1024 * 4) = 0x400404
159155
...@@ -177,28 +173,3 @@ k:...@@ -177,28 +173,3 @@ k:
177// Dis: oris 4, 4, 63173// Dis: oris 4, 4, 63
178// Dis: ori 4, 4, 33796174// Dis: ori 4, 4, 33796
179175
180// Check for GOT entry for i. There should be a got entry which holds the offset
181// of i relative to the dynamic thread pointer.
182// i@dtprel -> (1024 - 0x8000) = 0xffff8400
183// GotDisBE: Disassembly of section .got:
184// GotDisBE: 4204f8: 00 00 00 00
185// GotDisBE: 4204fc: 00 42 84 f8
186// GotDisBE: 420510: ff ff ff ff
187// GotDisBE: 420514: ff ff 84 00
188
189// GotDisLE: Disassembly of section .got:
190// GotDisLE: 4204f8: f8 84 42 00
191// GotDisLE: 420510: 00 84 ff ff
192// GotDisLE: 420514: ff ff ff ff
193
194// Check that we have the correct offset to the got entry for i@got@dtprel
195// The got entry for i is 0x420510, and the TOC pointer is 0x4284f8.
196// #ha(i@got@dtprel) --> ((0x420510 - 0x4284f8 + 0x8000) >> 16) & 0xffff = 0
197// #lo(i@got@dtprel) --> (0x420510 - 0x4284f8) & 0xffff = -32744
198// #hi(i@got@dtprel) --> ((0x420510 - 0x4284f8) >> 16) & 0xffff = -1
199// i@got@dtprel --> 0x420510 - 0x4284f8 = -32744
200// Dis: test_got_dtprel:
201// Dis: addis 3, 2, 0
202// Dis: ld 3, -32744(3)
203// Dis: addis 3, 2, -1
204// Dis: addi 3, 2, -32744
deps/lld/test/ELF/ppc64-dynamic-relocations.s deleted-50
...@@ -1,50 +0,0 @@
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/shared-ppc64.s -o %t2.o
5// RUN: ld.lld -shared %t2.o -o %t2.so
6// RUN: ld.lld %t.o %t2.so -o %t
7// RUN: llvm-readobj -dyn-relocations %t | FileCheck %s
8// RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=DIS %s
9// RUN: llvm-readelf -dynamic-table %t | FileCheck --check-prefix=DT %s
10
11// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
12// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o
13// RUN: ld.lld -shared %t2.o -o %t2.so
14// RUN: ld.lld %t.o %t2.so -o %t
15// RUN: llvm-readobj -dyn-relocations %t | FileCheck %s
16// RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=DIS %s
17// RUN: llvm-readelf -dynamic-table %t | FileCheck --check-prefix=DT %s
18
19
20// The dynamic relocation for foo should point to 16 bytes past the start of
21// the .plt section.
22// CHECK: Dynamic Relocations {
23// CHECK-NEXT: 0x10030010 R_PPC64_JMP_SLOT foo 0x0
24
25// There should be 2 reserved doublewords before the first entry. The dynamic
26// linker will fill those in with the address of the resolver entry point and
27// the dynamic object identifier.
28// DIS: Idx Name Size Address Type
29// DIS: .plt 00000018 0000000010030000 BSS
30
31// DT_PLTGOT should point to the start of the .plt section.
32// DT: 0x0000000000000003 PLTGOT 0x10030000
33
34 .text
35 .abiversion 2
36 .globl _start
37 .p2align 4
38 .type _start,@function
39_start:
40.Lfunc_begin0:
41.Lfunc_gep0:
42 addis 2, 12, .TOC.-.Lfunc_gep0@ha
43 addi 2, 2, .TOC.-.Lfunc_gep0@l
44.Lfunc_lep0:
45 .localentry _start, .Lfunc_lep0-.Lfunc_gep0
46 bl foo
47 nop
48 li 0, 1
49 sc
50 .size _start, .-.Lfunc_begin0
deps/lld/test/ELF/ppc64-entry-point.s+18-22
...@@ -1,14 +1,14 @@...@@ -1,14 +1,14 @@
1# REQUIRES: ppc1# REQUIRES: ppc
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4# RUN: ld.lld %t -o %t24# RUN: ld.lld %t.o -o %t
5# RUN: llvm-objdump -D %t2 | FileCheck %s5# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
6# RUN: llvm-objdump -D %t2 | FileCheck -check-prefix=CHECK-LE %s6# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
77
8# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t8# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
9# RUN: ld.lld %t -o %t29# RUN: ld.lld %t.o -o %t
10# RUN: llvm-objdump -D %t2 | FileCheck %s10# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
11# RUN: llvm-objdump -D %t2 | FileCheck -check-prefix=CHECK-BE %s11# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
1212
13.text13.text
14.abiversion 214.abiversion 2
...@@ -23,8 +23,8 @@ _start:...@@ -23,8 +23,8 @@ _start:
23 addi 4, 4, .Lfunc_gep0@l23 addi 4, 4, .Lfunc_gep0@l
24 # now r4 should contain the address of _start24 # now r4 should contain the address of _start
2525
26 lis 5, .TOC.-.Lfunc_gep0@ha26 lis 5, .TOC.-.Lfunc_gep0@ha # R_PPC64_REL16_HA
27 addi 5, 5, .TOC.-.Lfunc_gep0@l27 addi 5, 5, .TOC.-.Lfunc_gep0@l # R_PPC64_REL16_LO
28 # now r5 should contain the offset s.t. r4 + r5 = TOC base28 # now r5 should contain the offset s.t. r4 + r5 = TOC base
2929
30 # exit 5530 # exit 55
...@@ -34,16 +34,12 @@ _start:...@@ -34,16 +34,12 @@ _start:
34.Lfunc_end0:34.Lfunc_end0:
35 .size _start, .Lfunc_end0-.Lfunc_begin035 .size _start, .Lfunc_end0-.Lfunc_begin0
3636
37// CHECK: 10010000: {{.*}} lis 4, 409737# NM-DAG: 0000000010028000 d .TOC.
38// CHECK-NEXT: 10010004: {{.*}} addi 4, 4, 038# NM-DAG: 0000000010010000 T _start
39// CHECK-NEXT: 10010008: {{.*}} lis 5, 2
40// CHECK-NEXT: 1001000c: {{.*}} addi 5, 5, -32768
4139
42// CHECK-LE: Disassembly of section .got:40# 0x10010000 = (4097<<16) + 0
43// CHECK-LE-NEXT: .got:41# CHECK: 10010000: lis 4, 4097
44// CHECK-LE-NEXT: 10020000: 00 80 02 1042# CHECK-NEXT: 10010004: addi 4, 4, 0
4543# .TOC. - _start = (2<<16) - 32768
46// CHECK-BE: Disassembly of section .got:44# CHECK-NEXT: 10010008: lis 5, 2
47// CHECK-BE-NEXT: .got:45# CHECK-NEXT: 1001000c: addi 5, 5, -32768
48// CHECK-BE-NEXT: 10020000: 00 00 00 00 {{.*}}
49// CHECK-BE-NEXT: 10020004: 10 02 80 00 {{.*}}
deps/lld/test/ELF/ppc64-func-entry-points.s+2-2
...@@ -73,8 +73,8 @@ glob:...@@ -73,8 +73,8 @@ glob:
73// CHECK: 10010020: {{.*}} bl .+14473// CHECK: 10010020: {{.*}} bl .+144
74// CHECK: 10010034: {{.*}} bl .+8474// CHECK: 10010034: {{.*}} bl .+84
75// CHECK: foo_external_diff:75// CHECK: foo_external_diff:
76// CHECK-NEXT: 10010080: {{.*}} addis 2, 12, 276// CHECK-NEXT: 10010080: {{.*}} addis 2, 12, 1
77// CHECK-NEXT: 10010084: {{.*}} addi 2, 2, 3264077// CHECK-NEXT: 10010084: {{.*}} addi 2, 2, 32640
78// CHECK-NEXT: 10010088: {{.*}} nop78// CHECK-NEXT: 10010088: {{.*}} addis 5, 2, 1
79// CHECK: foo_external_same:79// CHECK: foo_external_same:
80// CHECK-NEXT: 100100b0: {{.*}} add 3, 4, 380// CHECK-NEXT: 100100b0: {{.*}} add 3, 4, 3
deps/lld/test/ELF/ppc64-gd-to-ie.s deleted-104
...@@ -1,104 +0,0 @@
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.s -o %t2.o
5# RUN: ld.lld -shared %t2.o -o %t3.so
6# RUN: ld.lld %t.o %t3.so -o %t
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 -r %t | FileCheck --check-prefix=OutputRelocs %s
10
11# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
12# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-tls.s -o %t2.o
13# RUN: ld.lld -shared %t2.o -o %t3.so
14# RUN: ld.lld %t.o %t3.so -o %t
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 -r %t | FileCheck --check-prefix=OutputRelocs %s
18
19 .text
20 .abiversion 2
21 .globl _start
22 .p2align 4
23 .type _start,@function
24_start:
25.Lfunc_gep0:
26 addis 2, 12, .TOC.-.Lfunc_gep0@ha
27 addi 2, 2, .TOC.-.Lfunc_gep0@l
28.Lfunc_lep0:
29 .localentry _start, .Lfunc_lep0-.Lfunc_gep0
30 mflr 0
31 std 0, 16(1)
32 stdu 1, -32(1)
33 addis 3, 2, a@got@tlsgd@ha
34 addi 3, 3, a@got@tlsgd@l
35 bl __tls_get_addr(a@tlsgd)
36 nop
37 lwa 3, 0(3)
38 addi 1, 1, 32
39 ld 0, 16(1)
40 mtlr 0
41 blr
42
43
44 .globl other_reg
45 .p2align 4
46 .type other_reg,@function
47other_reg:
48.Lfunc_gep1:
49 addis 2, 12, .TOC.-.Lfunc_gep1@ha
50 addi 2, 2, .TOC.-.Lfunc_gep1@l
51.Lfunc_lep1:
52 .localentry other_reg, .Lfunc_lep1-.Lfunc_gep1
53 mflr 0
54 std 0, 16(1)
55 stdu 1, -32(1)
56 addis 5, 2, a@got@tlsgd@ha
57 addi 3, 5, a@got@tlsgd@l
58 bl __tls_get_addr(a@tlsgd)
59 nop
60 lwa 4, 0(3)
61 addis 30, 2, b@got@tlsgd@ha
62 addi 3, 30, b@got@tlsgd@l
63 bl __tls_get_addr(b@tlsgd)
64 nop
65 lwa 3, 0(3)
66 add 3, 4, 3
67 addi 1, 1, 32
68 ld 0, 16(1)
69 mtlr 0
70 blr
71
72 .globl __tls_get_addr
73 .type __tls_get_addr,@function
74__tls_get_addr:
75
76
77# CheckGot: .got 00000018 00000000100200c0 DATA
78# .got is at 0x100200c0 so the toc-base is 100280c0.
79# `a` is at .got[1], we expect the offsets to be:
80# Ha(a) = ((0x100200c8 - 0x100280c0) + 0x8000) >> 16 = 0
81# Lo(a) = (0x100200c8 - 0x100280c0) = -32760
82
83# Dis-LABEL: _start
84# Dis: addis 3, 2, 0
85# Dis-NEXT: ld 3, -32760(3)
86# Dis-NEXT: nop
87# Dis-NEXT: add 3, 3, 13
88
89# Dis-LABEL: other_reg
90# Dis: addis 5, 2, 0
91# Dis-NEXT: ld 3, -32760(5)
92# Dis-NEXT: nop
93# Dis-NEXT: add 3, 3, 13
94# Dis: addis 30, 2, 0
95# Dis: ld 3, -32752(30)
96# Dis-NEXT: nop
97# Dis-NEXT: add 3, 3, 13
98
99# Verify that the only dynamic relocations we emit are TPREL ones rather then
100# the DTPMOD64/DTPREL64 pair for general-dynamic.
101# OutputRelocs: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 2 entries:
102# OutputRelocs-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
103# OutputRelocs-NEXT: {{[0-9a-f]+}} {{[0-9a-f]+}} R_PPC64_TPREL64 {{[0-9a-f]+}} a + 0
104# OutputRelocs-NEXT: {{[0-9a-f]+}} {{[0-9a-f]+}} R_PPC64_TPREL64 {{[0-9a-f]+}} b + 0
deps/lld/test/ELF/ppc64-general-dynamic-tls.s deleted-112
...@@ -1,112 +0,0 @@
1// REQUIRES: ppc
2
3// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4// RUN: ld.lld -shared %t.o -o %t.so
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// RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s
8// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=Dis %s
9
10// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
11// RUN: ld.lld -shared %t.o -o %t.so
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// RUN: llvm-objdump --section-headers %t.so | FileCheck --check-prefix=CheckGot %s
15// RUN: llvm-objdump -d %t.so | FileCheck --check-prefix=Dis %s
16
17 .text
18 .abiversion 2
19 .globl test
20 .p2align 4
21 .type test,@function
22test:
23.Lfunc_gep0:
24 addis 2, 12, .TOC.-.Lfunc_gep0@ha
25 addi 2, 2, .TOC.-.Lfunc_gep0@l
26.Lfunc_lep0:
27 .localentry test, .Lfunc_lep0-.Lfunc_gep0
28 mflr 0
29 std 31, -8(1)
30 std 0, 16(1)
31 stdu 1, -48(1)
32 mr 31, 1
33 std 30, 32(31)
34 addis 3, 2, i@got@tlsgd@ha
35 addi 3, 3, i@got@tlsgd@l
36 bl __tls_get_addr(i@tlsgd)
37 nop
38 lwz 30, 0(3)
39 extsw 3, 30
40 ld 30, 32(31)
41 addi 1, 1, 48
42 ld 0, 16(1)
43 ld 31, -8(1)
44 mtlr 0
45 blr
46
47
48test_hi:
49.Lfunc_gep1:
50 addis 2, 12, .TOC.-.Lfunc_gep1@ha
51 addi 2, 2, .TOC.-.Lfunc_gep1@l
52.Lfunc_lep1:
53 .localentry test2, .Lfunc_lep1-.Lfunc_gep1
54 addis 3, 0, j@got@tlsgd@h
55 blr
56
57test_16:
58.Lfunc_gep2:
59 addis 2, 12, .TOC.-.Lfunc_gep2@ha
60 addi 2, 2, .TOC.-.Lfunc_gep2@l
61.Lfunc_lep2:
62 .localentry test16, .Lfunc_lep2-.Lfunc_gep2
63 addi 3, 0, k@got@tlsgd
64 blr
65
66// Verify that the input has every general-dynamic tls relocation type.
67// InputRelocs: Relocation section '.rela.text'
68// InputRelocs: R_PPC64_GOT_TLSGD16_HA {{0+}} i + 0
69// InputRelocs: R_PPC64_GOT_TLSGD16_LO {{0+}} i + 0
70// InputRelocs: R_PPC64_TLSGD {{0+}} i + 0
71// InputRelocs: R_PPC64_GOT_TLSGD16_HI {{0+}} j + 0
72// InputRelocs: R_PPC64_GOT_TLSGD16 {{0+}} k + 0
73
74// There is 2 got entries for each tls variable that is accessed with the
75// general-dynamic model. The entries can be though of as a structure to be
76// filled in by the dynamic linker:
77// typedef struct {
78// unsigned long int ti_module; --> R_PPC64_DTPMOD64
79// unsigned long int ti_offset; --> R_PPC64_DTPREL64
80//} tls_index;
81// OutputRelocs: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 6 entries:
82// OutputRelocs: R_PPC64_DTPMOD64 {{0+}} i + 0
83// OutputRelocs: R_PPC64_DTPREL64 {{0+}} i + 0
84// OutputRelocs: R_PPC64_DTPMOD64 {{0+}} j + 0
85// OutputRelocs: R_PPC64_DTPREL64 {{0+}} j + 0
86// OutputRelocs: R_PPC64_DTPMOD64 {{0+}} k + 0
87// OutputRelocs: R_PPC64_DTPREL64 {{0+}} k + 0
88
89// Check that the got has 7 entires. (1 for the TOC and 3 structures of
90// 2 entries for the tls variables). Also verify the address so we can check
91// the offsets we calculated for each relocation type.
92// CheckGot: got 00000038 00000000000200f0
93
94// got starts at 0x200f0, so .TOC. will be 0x280f0.
95
96// We are building the address of the first tls_index in the got which starts at
97// 0x200f8 (got[1]).
98// #ha(i@got@tlsgd) --> (0x200f8 - 0x280f0 + 0x8000) >> 16 = 0
99// #lo(i@got@tlsgd) --> (0x200f8 - 0x280f0) & 0xFFFF = -7ff8 = -32760
100// Dis: test:
101// Dis: addis 3, 2, 0
102// Dis: addi 3, 3, -32760
103
104// Second tls_index starts at got[3].
105// #hi(j@got@tlsgd) --> (0x20108 - 0x280f0) >> 16 = -1
106// Dis: test_hi:
107// Dis: lis 3, -1
108
109// Third tls index is at got[5].
110// k@got@tlsgd --> (0x20118 - 0x280f0) = -0x7fd8 = -32728
111// Dis: test_16:
112// Dis: li 3, -32728
deps/lld/test/ELF/ppc64-got-indirect.s deleted-115
...@@ -1,115 +0,0 @@
1# REQUIRES: ppc
2
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-LE %s
5# RUN: ld.lld %t.o -o %t2
6# RUN: llvm-objdump -D %t2 | FileCheck %s --check-prefix=CHECK-LE
7# RUN: llvm-objdump -D %t2 | FileCheck %s
8
9# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
10# RUN: llvm-readobj -relocations %t.o | FileCheck -check-prefix=RELOCS-BE %s
11# RUN: ld.lld %t.o -o %t2
12# RUN: llvm-objdump -D %t2 | FileCheck %s --check-prefix=CHECK-BE
13# RUN: llvm-objdump -D %t2 | FileCheck %s
14
15# Make sure we calculate the offset correctly for a got-indirect access to a
16# global variable as described by the PPC64 ELF V2 abi.
17 .text
18 .abiversion 2
19 .globl _start # -- Begin function _start
20 .p2align 4
21 .type _start,@function
22_start: # @_start
23.Lfunc_begin0:
24.Lfunc_gep0:
25 addis 2, 12, .TOC.-.Lfunc_gep0@ha
26 addi 2, 2, .TOC.-.Lfunc_gep0@l
27.Lfunc_lep0:
28 .localentry _start, .Lfunc_lep0-.Lfunc_gep0
29# %bb.0: # %entry
30 addis 3, 2, .LC0@toc@ha
31 ld 3, .LC0@toc@l(3)
32 li 4, 0
33 stw 4, -12(1)
34 li 0,1
35 lwa 3, 0(3)
36 sc
37 .long 0
38 .quad 0
39.Lfunc_end0:
40 .size _start, .Lfunc_end0-.Lfunc_begin0
41 # -- End function
42 .section .toc,"aw",@progbits
43.LC0:
44 .tc glob[TC],glob
45 .type glob,@object # @glob
46 .data
47 .globl glob
48 .p2align 2
49glob:
50 .long 55 # 0x37
51 .size glob, 4
52
53# Verify the relocations emitted for glob are through the .toc
54
55# RELOCS-LE: Relocations [
56# RELOCS-LE: .rela.text {
57# RELOCS-LE: 0x0 R_PPC64_REL16_HA .TOC. 0x0
58# RELOCS-LE: 0x4 R_PPC64_REL16_LO .TOC. 0x4
59# RELOCS-LE: 0x8 R_PPC64_TOC16_HA .toc 0x0
60# RELOCS-LE: 0xC R_PPC64_TOC16_LO_DS .toc 0x0
61# RELOCS-LE: }
62# RELOCS-LE: .rela.toc {
63# RELOCS-LE: 0x0 R_PPC64_ADDR64 glob 0x0
64# RELOCS-LE: }
65
66# RELOCS-BE: Relocations [
67# RELOCS-BE: .rela.text {
68# RELOCS-BE: 0x2 R_PPC64_REL16_HA .TOC. 0x2
69# RELOCS-BE: 0x6 R_PPC64_REL16_LO .TOC. 0x6
70# RELOCS-BE: 0xA R_PPC64_TOC16_HA .toc 0x0
71# RELOCS-BE: 0xE R_PPC64_TOC16_LO_DS .toc 0x0
72# RELOCS-BE: }
73# RELOCS-BE: .rela.toc {
74# RELOCS-BE: 0x0 R_PPC64_ADDR64 glob 0x0
75# RELOCS-BE: }
76# RELOCS-BE:]
77
78# Verify that the global variable access is done through the correct
79# toc entry:
80# r2 = .TOC. = 0x10038000.
81# r3 = r2 - 32760 = 0x10030008 -> .toc entry for glob.
82
83# CHECK: _start:
84# CHECK-NEXT: 10010000: {{.*}} addis 2, 12, 3
85# CHECK-NEXT: 10010004: {{.*}} addi 2, 2, -32768
86# CHECK-NEXT: 10010008: {{.*}} nop
87# CHECK-NEXT: 1001000c: {{.*}} ld 3, -32760(2)
88# CHECK: 1001001c: {{.*}} lwa 3, 0(3)
89
90# CHECK-LE: Disassembly of section .data:
91# CHECK-LE-NEXT: glob:
92# CHECK-LE-NEXT: 10020000: 37 00 00 00
93
94# CHECK-LE: Disassembly of section .got:
95# CHECK-LE-NEXT: .got:
96# CHECK-LE-NEXT: 10030000: 00 80 03 10
97# CHECK-LE-NEXT: 10030004: 00 00 00 00
98
99# Verify that .toc comes right after .got
100# CHECK-LE: Disassembly of section .toc:
101# CHECK-LE: 10030008: 00 00 02 10
102
103# CHECK-BE: Disassembly of section .data:
104# CHECK-BE-NEXT: glob:
105# CHECK-BE-NEXT: 10020000: 00 00 00 37
106
107# CHECK-BE: Disassembly of section .got:
108# CHECK-BE-NEXT: .got:
109# CHECK-BE-NEXT: 10030000: 00 00 00 00
110# CHECK-BE-NEXT: 10030004: 10 03 80 00
111
112# Verify that .toc comes right after .got
113# CHECK-BE: Disassembly of section .toc:
114# CHECK-BE: 10030008: 00 00 00 00
115# CHECK-BE: 1003000c: 10 02 00 00
deps/lld/test/ELF/ppc64-ifunc.s+46-58
...@@ -1,79 +1,67 @@...@@ -1,79 +1,67 @@
1# REQUIRES: ppc1# REQUIRES: ppc
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o3# 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/shared-ppc64.s -o %t2.o4# RUN: ld.lld %t.o -o %t
5# RUN: ld.lld -shared %t2.o -o %t2.so5# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
6# RUN: ld.lld %t.o %t2.so -o %t6# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SECTIONS %s
7# RUN: llvm-objdump -D %t | FileCheck %s7# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
8# RUN: llvm-readelf -dynamic-table %t | FileCheck --check-prefix=DT %s8# RUN: llvm-readelf -r %t | FileCheck --check-prefix=DYNREL %s
9# RUN: llvm-readelf -dyn-relocations %t | FileCheck --check-prefix=DYNREL %s
109
11# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o10# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
12# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o11# RUN: ld.lld %t.o -o %t
13# RUN: ld.lld -shared %t2.o -o %t2.so12# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
14# RUN: ld.lld %t.o %t2.so -o %t13# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SECTIONS %s
15# RUN: llvm-objdump -D %t | FileCheck %s14# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
16# RUN: llvm-readelf -dynamic-table %t | FileCheck --check-prefix=DT %s15# RUN: llvm-readelf -r %t | FileCheck --check-prefix=DYNREL %s
17# RUN: llvm-readelf -dyn-relocations %t | FileCheck --check-prefix=DYNREL %s
1816
19# CHECK: Disassembly of section .text:17# NM-DAG: 0000000010028000 d .TOC.
18# NM-DAG: 0000000010010000 T ifunc
19# NM-DAG: 0000000010010004 T ifunc2
2020
21# Tocbase + (0 << 16) + 3256021# SECTIONS: .plt NOBITS 0000000010030000
22# 0x100280e0 + 0 + 32560 = 0x10030010 (.plt[2])22
23# CHECK: __plt_foo:23# __plt_ifunc - . = 0x10010020 - 0x10010010 = 16
24# __plt_ifunc2 - . = 0x10010044 - 0x10010018 = 28
25# CHECK: _start:
26# CHECK-NEXT: addis 2, 12, 1
27# CHECK-NEXT: addi 2, 2, 32760
28# CHECK-NEXT: 10010010: bl .+16
29# CHECK-NEXT: ld 2, 24(1)
30# CHECK-NEXT: 10010018: bl .+28
31# CHECK-NEXT: ld 2, 24(1)
32
33# .plt[0] - .TOC. = 0x10030000 - 0x10028000 = (1<<16) - 32768
34# CHECK: __plt_ifunc:
24# CHECK-NEXT: std 2, 24(1)35# CHECK-NEXT: std 2, 24(1)
25# CHECK-NEXT: addis 12, 2, 036# CHECK-NEXT: addis 12, 2, 1
26# CHECK-NEXT: ld 12, 32560(12)37# CHECK-NEXT: ld 12, -32768(12)
27# CHECK-NEXT: mtctr 1238# CHECK-NEXT: mtctr 12
28# CHECK-NEXT: bctr39# CHECK-NEXT: bctr
2940
30# Tocbase + (0 << 16) + 3256841# .plt[1] - .TOC. = 0x10030000+8 - 0x10028000 = (1<<16) - 32760
31# 0x100280e0 + 0 + 32568 = 0x1003018 (.plt[3])42# CHECK: __plt_ifunc2:
32# CHECK: __plt_ifunc:
33# CHECK-NEXT: std 2, 24(1)43# CHECK-NEXT: std 2, 24(1)
34# CHECK-NEXT: addis 12, 2, 044# CHECK-NEXT: addis 12, 2, 1
35# CHECK-NEXT: ld 12, 32568(12)45# CHECK-NEXT: ld 12, -32760(12)
36# CHECK-NEXT: mtctr 1246# CHECK-NEXT: mtctr 12
37# CHECK-NEXT: bctr47# CHECK-NEXT: bctr
3848
39# CHECK: ifunc:49# Check that we emit 2 R_PPC64_IRELATIVE.
40# CHECK-NEXT: 10010028: {{.*}} nop50# DYNREL: R_PPC64_IRELATIVE 10010000
4151# DYNREL: R_PPC64_IRELATIVE 10010004
42# CHECK: _start:
43# CHECK-NEXT: addis 2, 12, 2
44# CHECK-NEXT: addi 2, 2, -32588
45# CHECK-NEXT: bl .+67108812
46# CHECK-NEXT: ld 2, 24(1)
47# CHECK-NEXT: bl .+67108824
48# CHECK-NEXT: ld 2, 24(1)
49
50# Check tocbase
51# CHECK: Disassembly of section .got:
52# CHECK-NEXT: .got:
53# CHECK-NEXT: 100200e0
54
55# Check .plt address
56# DT_PLTGOT should point to the start of the .plt section.
57# DT: 0x0000000000000003 PLTGOT 0x10030000
58
59# Check that we emit the correct dynamic relocation type for an ifunc
60# DYNREL: 'PLT' relocation section at offset 0x{{[0-9a-f]+}} contains 48 bytes:
61# 48 bytes --> 2 Elf64_Rela relocations
62# DYNREL-NEXT: Offset Info Type Symbol's Value Symbol's Name + Addend
63# DYNREL-NEXT: {{[0-9a-f]+}} {{[0-9a-f]+}} R_PPC64_JMP_SLOT {{0+}} foo + 0
64# DYNREL-NEXT: {{[0-9a-f]+}} {{[0-9a-f]+}} R_PPC64_IRELATIVE 10010028
65
66
67 .text
68 .abiversion 2
6952
70.type ifunc STT_GNU_IFUNC53.type ifunc STT_GNU_IFUNC
71.globl ifunc54.globl ifunc
72ifunc:55ifunc:
73 nop56 nop
7457
75 .global _start58.type ifunc2 STT_GNU_IFUNC
76 .type _start,@function59.globl ifunc2
60ifunc2:
61 nop
62
63.global _start
64.type _start,@function
7765
78_start:66_start:
79.Lfunc_gep0:67.Lfunc_gep0:
...@@ -81,7 +69,7 @@ _start:...@@ -81,7 +69,7 @@ _start:
81 addi 2, 2, .TOC.-.Lfunc_gep0@l69 addi 2, 2, .TOC.-.Lfunc_gep0@l
82.Lfunc_lep0:70.Lfunc_lep0:
83 .localentry _start, .Lfunc_lep0-.Lfunc_gep071 .localentry _start, .Lfunc_lep0-.Lfunc_gep0
84 bl foo
85 nop
86 bl ifunc72 bl ifunc
87 nop73 nop
74 bl ifunc2
75 nop
deps/lld/test/ELF/ppc64-initial-exec-tls.s deleted-102
...@@ -1,102 +0,0 @@
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.s -o %t2.o
5// RUN: ld.lld -shared %t2.o -o %t2.so
6// RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.so -o %t
7// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
8// RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s
9// RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=CheckGot %s
10// RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s
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-tls.s -o %t2.o
14// RUN: ld.lld -shared %t2.o -o %t2.so
15// RUN: ld.lld -dynamic-linker /lib64/ld64.so.2 %t.o %t2.so -o %t
16// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
17// RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s
18// RUN: llvm-objdump --section-headers %t | FileCheck --check-prefix=CheckGot %s
19// RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s
20
21 .text
22 .abiversion 2
23 .file "intial_exec.c"
24 .globl test_initial_exec # -- Begin function test_initial_exec
25 .p2align 4
26 .type test_initial_exec,@function
27test_initial_exec: # @test_initial_exec
28.Lfunc_begin0:
29.Lfunc_gep0:
30 addis 2, 12, .TOC.-.Lfunc_gep0@ha
31 addi 2, 2, .TOC.-.Lfunc_gep0@l
32.Lfunc_lep0:
33 .localentry test_initial_exec, .Lfunc_lep0-.Lfunc_gep0
34# %bb.0: # %entry
35 li 3, 0
36 stw 3, -12(1)
37 addis 3, 2, a@got@tprel@ha
38 ld 3, a@got@tprel@l(3)
39 lwzx 4, 3, a@tls
40 extsw 3, 4
41 blr
42
43
44test_hi:
45.Lfunc_gep1:
46 addis 2, 12, .TOC.-.Lfunc_gep1@ha
47 addi 2, 2, .TOC.-.Lfunc_gep1@l
48.Lfunc_lep1:
49 .localentry test2, .Lfunc_lep1-.Lfunc_gep1
50 addis 3, 0, b@got@tprel@h
51 blr
52
53test_ds:
54.Lfunc_gep2:
55 addis 2, 12, .TOC.-.Lfunc_gep2@ha
56 addi 2, 2, .TOC.-.Lfunc_gep2@l
57.Lfunc_lep2:
58 .localentry test16, .Lfunc_lep2-.Lfunc_gep2
59 addi 3, 0, c@got@tprel
60 blr
61
62// Verify that the input has every initial-exec tls relocation type.
63// InputRelocs: Relocation section '.rela.text'
64// InputRelocs: R_PPC64_GOT_TPREL16_HA {{0+}} a + 0
65// InputRelocs: R_PPC64_GOT_TPREL16_LO_DS {{0+}} a + 0
66// InputRelocs: R_PPC64_TLS {{0+}} a + 0
67// InputRelocs: R_PPC64_GOT_TPREL16_HI {{0+}} b + 0
68// InputRelocs: R_PPC64_GOT_TPREL16_DS {{0+}} c + 0
69
70// There is a got entry for each tls variable that is accessed with the
71// initial-exec model to be filled in by the dynamic linker.
72// OutputRelocs: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 3 entries:
73// OutputRelocs: R_PPC64_TPREL64 {{0+}} a + 0
74// OutputRelocs: R_PPC64_TPREL64 {{0+}} b + 0
75// OutputRelocs: R_PPC64_TPREL64 {{0+}} c + 0
76
77// Check that the got has 4 entires. (1 for the TOC and 3 entries for TLS
78// variables). Also verify the address so we can check
79// the offsets we calculated for each relocation type.
80// CheckGot: got 00000020 00000000100200c0
81
82// GOT stats at 0x100200c0, so TOC will be 0x100280c0
83
84// We are building the address of the first TLS got entry which contains the
85// offset of the tls variable relative to the thread pointer.
86// 0x100200c8 (got[1]).
87// #ha(a@got@tprel) --> (0x100200c8 - 0x100280c0 + 0x8000) >> 16 = 0
88// #lo(a@got@tprel)) --> (0x100200c8 - 0x100280c0) & 0xFFFF = -7ff8 = -32760
89// Dis: test_initial_exec:
90// Dis: addis 3, 2, 0
91// Dis: ld 3, -32760(3)
92// Dis: lwzx 4, 3, 13
93
94// Second TLS got entry starts at got[2] 0x100200d0
95// #hi(b@got@tprel) --> (0x100200d0 - 0x100280c0) >> 16 = -1
96// Dis: test_hi:
97// Dis: lis 3, -1
98
99// Third TLS got entry starts at got[3] 0x100200d8.
100// c@got@tprel--> (0x100200d8. - 0x100280c0) = -0x7fe8 = 32744
101// Dis: test_ds:
102// Dis: li 3, -32744
deps/lld/test/ELF/ppc64-ld-got-dtprel.s created+44
...@@ -0,0 +1,44 @@
1# REQUIRES: ppc
2
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
4# RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELOCS %s
5# RUN: ld.lld -shared %t.o -o %t.so
6# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s
7## Check LD->LE relaxation does not affect R_PPC64_GOT_DTPREL16*.
8# RUN: ld.lld %t.o -o %t
9# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
10
11# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o
12# RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=RELOCS %s
13# RUN: ld.lld -shared %t.o -o %t.so
14# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s
15# RUN: ld.lld %t.o -o %t
16# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
17
18# RELOCS: .rela.text {
19# RELOCS-NEXT: R_PPC64_GOT_DTPREL16_HA i 0x0
20# RELOCS-NEXT: R_PPC64_GOT_DTPREL16_LO_DS i 0x0
21# RELOCS-NEXT: R_PPC64_GOT_DTPREL16_HI j 0x0
22# RELOCS-NEXT: R_PPC64_GOT_DTPREL16_DS j 0x0
23# RELOCS-NEXT: }
24
25## ha(i@got@dtprel) = (&.got[0] - (.got+0x8000) + 0x8000 >> 16) & 0xffff = 0
26## lo(i@got@dtprel) = &.got[0] - (.got+0x8000) & 0xffff = -32768
27## hi(j@got@dtprel) = (&.got[1] - (.got+0x8000) >> 16) & 0xffff = -1
28## j@got@dtprel = &.got[1] - (.got+0x8000) = -32760
29# CHECK: addis 3, 2, 0
30# CHECK-NEXT: ld 3, -32768(3)
31# CHECK-NEXT: addis 3, 2, -1
32# CHECK-NEXT: addi 3, 2, -32760
33
34 addis 3, 2, i@got@dtprel@ha
35 ld 3, i@got@dtprel@l(3)
36 addis 3, 2, j@got@dtprel@h
37 addi 3, 2, j@got@dtprel
38
39.section .tbss,"awT",@progbits
40.p2align 2
41i:
42 .long 0
43j:
44 .long 0
deps/lld/test/ELF/ppc64-local-dynamic.s+1-1
...@@ -113,7 +113,7 @@ k:...@@ -113,7 +113,7 @@ k:
113// Dis: test:113// Dis: test:
114// Dis: addis 3, 2, 0114// Dis: addis 3, 2, 0
115// Dis-NEXT: addi 3, 3, -32760115// Dis-NEXT: addi 3, 3, -32760
116// Dis-NEXT: bl .+67108804116// Dis-NEXT: bl .+60
117// Dis-NEXT: ld 2, 24(1)117// Dis-NEXT: ld 2, 24(1)
118// Dis-NEXT: addis 3, 3, 0118// Dis-NEXT: addis 3, 3, 0
119// Dis-NEXT: lwa 3, -32768(3)119// Dis-NEXT: lwa 3, -32768(3)
deps/lld/test/ELF/ppc64-local-entry.s created+47
...@@ -0,0 +1,47 @@
1# REQUIRES: ppc
2
3# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t
4# RUN: ld.lld -r %t -o %t2
5# RUN: llvm-objdump -s -section=.symtab %t2 | FileCheck %s
6
7.text
8.abiversion 2
9.globl _start
10.p2align 2
11.type _start,@function
12
13_start:
14.Lfunc_begin0:
15.Lfunc_gep0:
16 addis 2, 12, .TOC.-.Lfunc_gep0@ha
17 addi 2, 2, .TOC.-.Lfunc_gep0@l
18.Lfunc_lep0:
19 .localentry _start, .Lfunc_lep0-.Lfunc_gep0
20 # The code below is not important, it just needs to access some
21 # global data or function, in order to use the TOC.
22 # In this case, it performs the following:
23 # g += 10;
24 # Also note that this code is not intended to be run, but only
25 # to check if the linker will preserve the localentry info.
26 addis 3, 2, g@toc@ha
27 addi 3, 3, g@toc@l
28 lwz 4, 0(3)
29 addi 4, 4, 10
30 stw 4, 0(3)
31 blr
32 .long 0
33 .quad 0
34.Lfunc_end0:
35 .size _start, .Lfunc_end0-.Lfunc_begin0
36
37 .type g,@object # @g
38 .lcomm g,4,4
39
40// We expect the st_other byte to be 0x60:
41// localentry = 011 (gep + 2 instructions), reserved = 000,
42// visibility = 00 (STV_DEFAULT)
43// Currently, llvm-objdump does not support displaying
44// st_other's PPC64 specific flags, thus we check the
45// result of the hexdump of .symtab section.
46
47// CHECK: 0070 00000000 00000000 00000009 12600001
deps/lld/test/ELF/ppc64-long-branch-init.s created+44
...@@ -0,0 +1,44 @@
1# REQUIRES: ppc
2
3# RUN: llvm-mc -filetype=obj -triple=powerpc64-pc-freebsd13.0 %s -o %t.o
4# RUN: ld.lld %t.o -o %t
5# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
6
7## .init consists of sections from several object files. Sections other than the
8## last one do not have a terminator. Check we do not create a long branch stub
9## in the middle.
10## We currently use thunk section spacing to ensure the stub is in the end. This
11## is not foolproof but good enough to not break in practice.
12
13# CHECK: Disassembly of section .init:
14# CHECK-EMPTY:
15# CHECK-LABEL: _init:
16# CHECK: blr
17# CHECK-EMPTY:
18# CHECK-LABEL: __long_branch_foo:
19
20.globl foo
21foo:
22 .space 0x2000000
23 blr
24
25.section .init,"ax",@progbits,unique,0
26.globl _init
27_init:
28 stdu 1, -48(1)
29 mflr 0
30 std 0, 64(1)
31
32.section .init,"ax",@progbits,unique,1
33 bl foo
34 nop
35
36.section .init,"ax",@progbits,unique,2
37 bl foo
38 nop
39
40.section .init,"ax",@progbits,unique,3
41 ld 1, 0(1)
42 ld 0, 16(1)
43 mtlr 0
44 blr
deps/lld/test/ELF/ppc64-long-branch-localentry-offset.s created+30
...@@ -0,0 +1,30 @@
1# REQUIRES: ppc
2
3# RUN: llvm-mc -filetype=obj -triple=ppc64le %s -o %t.o
4# RUN: ld.lld %t.o -o %t
5# RUN: llvm-nm %t | FileCheck %s
6
7# CHECK-DAG: 0000000010010000 t __long_branch_callee
8# CHECK-DAG: 0000000010010010 T _start
9# CHECK-DAG: 0000000012010008 T callee
10
11# The bl instruction jumps to the local entry. The distance requires a long branch stub:
12# localentry(callee) - _start = 0x12010008+8 - 0x10010010 = 0x2000000
13
14# We used to compute globalentry(callee) - _start and caused a "R_PPC64_REL24
15# out of range" error because we didn't create the stub.
16
17.globl _start
18_start:
19 bl callee
20
21.space 0x1fffff4
22
23.globl callee
24callee:
25.Lgep0:
26 addis 2, 12, .TOC.-.Lgep0@ha
27 addi 2, 2, .TOC.-.Lgep0@l
28.Llep0:
29 .localentry callee, .Llep0-.Lgep0
30 blr
deps/lld/test/ELF/ppc64-long-branch.s+37-64
...@@ -1,22 +1,16 @@...@@ -1,22 +1,16 @@
1# REQUIRES: ppc1# REQUIRES: ppc
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o3# 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.o4# RUN: ld.lld --no-toc-optimize %t.o -o %t
5# RUN: ld.lld -shared %t2.o -o %t3.so5# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
6# RUN: ld.lld --no-toc-optimize %t.o %t3.so -o %t6# RUN: llvm-readelf -x .branch_lt %t | FileCheck %s -check-prefix=BRANCH-LE
7# RUN: llvm-objdump -d -start-address=0x10010000 -stop-address=0x10010018 %t | FileCheck %s -check-prefix=CALLEE_DUMP7# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
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
118
12# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o9# 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.o10# RUN: ld.lld --no-toc-optimize %t.o -o %t
14# RUN: ld.lld -shared %t2.o -o %t3.so11# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
15# RUN: ld.lld --no-toc-optimize %t.o %t3.so -o %t12# RUN: llvm-readelf -x .branch_lt %t | FileCheck %s -check-prefix=BRANCH-BE
16# RUN: llvm-objdump -d -start-address=0x10010000 -stop-address=0x10010018 %t | FileCheck %s -check-prefix=CALLEE_DUMP13# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
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
2014
21 .text15 .text
22 .abiversion 216 .abiversion 2
...@@ -52,24 +46,14 @@ _start:...@@ -52,24 +46,14 @@ _start:
52 std 0, 16(1)46 std 0, 16(1)
53 stdu 1, -32(1)47 stdu 1, -32(1)
54 bl callee48 bl callee
55 bl foo_external_diff49 bl callee
56 nop
57 addi 1, 1, 3250 addi 1, 1, 32
58 ld 0, 16(1)51 ld 0, 16(1)
59 mtlr 052 mtlr 0
6053
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",@progbits54 .section .toc,"aw",@progbits
69.LC0:55.LC0:
70 .tc a[TC],a56 .tc a[TC],a
71.LC1:
72 .tc b[TC],b
7357
7458
75 .data59 .data
...@@ -80,42 +64,31 @@ a:...@@ -80,42 +64,31 @@ a:
80 .long 1164 .long 11
81 .size a, 465 .size a, 4
8266
83 .type b,@object67# NM: 0000000012028000 d .TOC.
84 .global b68
85 .p2align 269# Without --toc-optimize, compute the address of .toc[0] first. .toc[0] stores
86b:70# the address of a.
87 .long 3371# .TOC. - callee = 0x12030000 - 0x10010000 = (514<<16) - 32768
88 .size b, 472# CHECK: callee:
8973# CHECK: 10010000: addis 2, 12, 514
90# Verify address of the callee74# CHECK: 10010004: addi 2, 2, -32768
91# CALLEE_DUMP: callee:75# CHECK: 10010008: addis 4, 2, 0
92# CALLEE_DUMP: 10010000: {{.*}} addis 2, 12, 51576
93# CALLEE_DUMP: 10010004: {{.*}} addi 2, 2, -3254477# __long_branch_callee - . = 0x12010050 - 0x12010034 = 20
94# CALLEE_DUMP: 10010008: {{.*}} addis 4, 2, 078# __long_branch_callee is not a PLT call stub. Calling it does not need TOC
9579# restore, so it doesn't have to be followed by a nop.
96# Verify the address of _start, and the call to the long-branch thunk.80# CHECK: _start:
97# CALLER_DUMP: _start:81# CHECK: 12010034: bl .+20
98# CALLER_DUMP: 12010020: {{.*}} addis 2, 12, 382# CHECK: 12010038: bl .+16
99# CALLER_DUMP: 12010038: {{.*}} bl .+5683
10084# BRANCH-LE: section '.branch_lt':
101# Verify the thunks contents: TOC-pointer + offset = .branch_lt[0]85# BRANCH-LE-NEXT: 0x12030008 08000110 00000000
102# 0x120380e8 + (-2 << 16 + 32552) = 0x1202000886# BRANCH-BE: section '.branch_lt':
103# CALLER_DUMP: __long_branch_callee:87# BRANCH-BE-NEXT: 0x12030008 00000000 10010008
104# CALLER_DUMP: 12010060: {{.*}} addis 12, 2, -288
105# CALLER_DUMP: 12010064: {{.*}} ld 12, 32552(12)89# .branch_lt - .TOC. = 0x12030008 - 0x12028000 = (1<<16) - 32760
106# CALLER_DUMP: 12010068: {{.*}} mtctr 1290# CHECK: __long_branch_callee:
107# CALLER_DUMP: 1201006c: {{.*}} bctr91# CHECK-NEXT: 12010048: addis 12, 2, 1
10892# CHECK-NEXT: ld 12, -32760(12)
109# BRANCH_LT_LE: Disassembly of section .branch_lt:93# CHECK-NEXT: mtctr 12
110# BRANCH_LT_LE-NEXT: .branch_lt:94# CHECK-NEXT: bctr
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-plt-stub.s+36-25
...@@ -1,28 +1,39 @@...@@ -1,28 +1,39 @@
1// REQUIRES: ppc1# REQUIRES: ppc
22
3// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o3# 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/shared-ppc64.s -o %t2.o4# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o
5// RUN: ld.lld -shared %t2.o -o %t2.so5# RUN: ld.lld -shared %t2.o -soname=t2.so -o %t2.so
6// RUN: ld.lld %t.o %t2.so -o %t6# RUN: ld.lld %t.o %t2.so -o %t
7// RUN: llvm-objdump -d %t | FileCheck %s7# RUN: llvm-readelf -S -d %t | FileCheck --check-prefix=SEC %s
88# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
9// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o9
10// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o10# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
11// RUN: ld.lld -shared %t2.o -o %t2.so11# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o
12// RUN: ld.lld %t.o %t2.so -o %t12# RUN: ld.lld -shared %t2.o -soname=t2.so -o %t2.so
13// RUN: llvm-objdump -d %t | FileCheck %s13# RUN: ld.lld %t.o %t2.so -o %t
1414# RUN: llvm-readelf -S -d %t | FileCheck --check-prefix=SEC %s
15// CHECK: Disassembly of section .text:15# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
16// CHECK-NEXT: __plt_foo:16
17// CHECK-NEXT: std 2, 24(1)17## DT_PLTGOT points to .plt
18// CHECK-NEXT: addis 12, 2, 018# SEC: .plt NOBITS 0000000010030000 030000 000018
19// CHECK-NEXT: ld 12, 32560(12)19# SEC: 0x0000000000000003 (PLTGOT) 0x10030000
20// CHECK-NEXT: mtctr 1220
21// CHECK-NEXT: bctr21## .plt[0] holds the address of _dl_runtime_resolve.
2222## .plt[1] holds the link map.
2323## The JMP_SLOT relocation is stored at .plt[2]
24// CHECK: _start:24# RELOC: 0x10030010 R_PPC64_JMP_SLOT foo 0x0
25// CHECK: bl .+6710882425
26# CHECK: _start:
27# CHECK: 10010008: bl .+16
28
29# CHECK-LABEL: 0000000010010018 __plt_foo:
30# CHECK-NEXT: std 2, 24(1)
31# CHECK-NEXT: addis 12, 2, 0
32# CHECK-NEXT: ld 12, 32560(12)
33# CHECK-NEXT: mtctr 12
34# CHECK-NEXT: bctr
35
36
26 .text37 .text
27 .abiversion 238 .abiversion 2
28 .globl _start39 .globl _start
deps/lld/test/ELF/ppc64-rel-calls.s+3-3
...@@ -9,6 +9,7 @@...@@ -9,6 +9,7 @@
9# RUN: llvm-objdump -d %t2 | FileCheck %s9# RUN: llvm-objdump -d %t2 | FileCheck %s
1010
11# CHECK: Disassembly of section .text:11# CHECK: Disassembly of section .text:
12# CHECK-EMPTY:
1213
13.text14.text
14.global _start15.global _start
...@@ -30,9 +31,8 @@ bar:...@@ -30,9 +31,8 @@ bar:
30 nop31 nop
31 blr32 blr
3233
33# FIXME: The printing here is misleading, the branch offset here is negative.34# CHECK: 1001000c: {{.*}} bl .-12
34# CHECK: 1001000c: {{.*}} bl .+67108852
35# CHECK: 10010010: {{.*}} nop35# CHECK: 10010010: {{.*}} nop
36# CHECK: 10010014: {{.*}} bl .+6710884436# CHECK: 10010014: {{.*}} bl .-20
37# CHECK: 10010018: {{.*}} nop37# CHECK: 10010018: {{.*}} nop
38# CHECK: 1001001c: {{.*}} blr38# CHECK: 1001001c: {{.*}} blr
deps/lld/test/ELF/ppc64-reloc-addr.s created+25
...@@ -0,0 +1,25 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le %S/Inputs/abs255.s -o %t255.o
4# RUN: llvm-mc -filetype=obj -triple=powerpc64le %S/Inputs/abs256.s -o %t256.o
5# RUN: llvm-mc -filetype=obj -triple=powerpc64le %S/Inputs/abs257.s -o %t257.o
6
7# RUN: ld.lld %t.o %t256.o -o %t
8# RUN: llvm-readelf -x .data %t | FileCheck %s
9# CHECK: 0x{{[0-9a-f]+}} ffff0080 ffffffff 00000080
10
11# RUN: not ld.lld %t.o %t255.o -o /dev/null 2>&1 | FileCheck --check-prefix=OVERFLOW1 %s
12# OVERFLOW1: relocation R_PPC64_ADDR16 out of range: -32769 is not in [-32768, 65535]
13# OVERFLOW1: relocation R_PPC64_ADDR32 out of range: -2147483649 is not in [-2147483648, 4294967295]
14
15# RUN: not ld.lld %t.o %t257.o -o /dev/null 2>&1 | FileCheck --check-prefix=OVERFLOW2 %s
16# OVERFLOW2: relocation R_PPC64_ADDR16 out of range: 65536 is not in [-32768, 65535]
17# OVERFLOW2: relocation R_PPC64_ADDR32 out of range: 4294967296 is not in [-2147483648, 4294967295]
18
19.globl _start
20_start:
21.data
22.word foo + 0xfeff
23.word foo - 0x8100
24.long foo + 0xfffffeff
25.long foo - 0x80000100
deps/lld/test/ELF/ppc64-relocs.s+66-106
...@@ -1,14 +1,14 @@...@@ -1,14 +1,14 @@
1# REQUIRES: ppc1# REQUIRES: ppc
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4# RUN: ld.lld %t -o %t24# RUN: ld.lld --no-toc-optimize %t.o -o %t
5# RUN: llvm-objdump -D %t2 | FileCheck %s --check-prefix=DATALE5# RUN: llvm-readelf -x .rodata -x .R_PPC64_TOC -x .eh_frame %t | FileCheck %s --check-prefix=DATALE
6# RUN: llvm-objdump -D %t2 | FileCheck %s6# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
77
8# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t8# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
9# RUN: ld.lld %t -o %t29# RUN: ld.lld --no-toc-optimize %t.o -o %t
10# RUN: llvm-objdump -D %t2 | FileCheck %s --check-prefix=DATABE10# RUN: llvm-readelf -x .rodata -x .R_PPC64_TOC -x .eh_frame %t | FileCheck %s --check-prefix=DATABE
11# RUN: llvm-objdump -D %t2 | FileCheck %s11# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
1212
13.text13.text
14.global _start14.global _start
...@@ -30,154 +30,106 @@ _start:...@@ -30,154 +30,106 @@ _start:
30 .tc .LJTI0_0[TC],.LJTI0_030 .tc .LJTI0_0[TC],.LJTI0_0
3131
32.section .R_PPC64_TOC16_LO_DS,"ax",@progbits32.section .R_PPC64_TOC16_LO_DS,"ax",@progbits
33.globl .FR_PPC64_TOC16_LO_DS
34.FR_PPC64_TOC16_LO_DS:
35 ld 1, .L1@toc@l(2)33 ld 1, .L1@toc@l(2)
3634
37# CHECK: Disassembly of section .R_PPC64_TOC16_LO_DS:35# CHECK-LABEL: Disassembly of section .R_PPC64_TOC16_LO_DS:
38# CHECK: .FR_PPC64_TOC16_LO_DS:36# CHECK: 1001000c: ld 1, -32768(2)
39# CHECK: 1001000c: {{.*}} ld 1, -32768(2)
4037
41.section .R_PPC64_TOC16_LO,"ax",@progbits38.section .R_PPC64_TOC16_LO,"ax",@progbits
42.globl .FR_PPC64_TOC16_LO
43.FR_PPC64_TOC16_LO:
44 addi 1, 2, .L1@toc@l39 addi 1, 2, .L1@toc@l
4540
46# CHECK: Disassembly of section .R_PPC64_TOC16_LO:41# CHECK-LABEL: Disassembly of section .R_PPC64_TOC16_LO:
47# CHECK: .FR_PPC64_TOC16_LO:42# CHECK: 10010010: addi 1, 2, -32768
48# CHECK: 10010010: {{.*}} addi 1, 2, -32768
4943
50.section .R_PPC64_TOC16_HI,"ax",@progbits44.section .R_PPC64_TOC16_HI,"ax",@progbits
51.globl .FR_PPC64_TOC16_HI
52.FR_PPC64_TOC16_HI:
53 addis 1, 2, .L1@toc@h45 addis 1, 2, .L1@toc@h
5446
55# CHECK: Disassembly of section .R_PPC64_TOC16_HI:47# CHECK-LABEL: Disassembly of section .R_PPC64_TOC16_HI:
56# CHECK: .FR_PPC64_TOC16_HI:48# CHECK: 10010014: addis 1, 2, -1
57# CHECK: 10010014: {{.*}} addis 1, 2, -1
5849
59.section .R_PPC64_TOC16_HA,"ax",@progbits50.section .R_PPC64_TOC16_HA,"ax",@progbits
60.globl .FR_PPC64_TOC16_HA
61.FR_PPC64_TOC16_HA:
62 addis 1, 2, .L1@toc@ha51 addis 1, 2, .L1@toc@ha
6352
64# CHECK: Disassembly of section .R_PPC64_TOC16_HA:53# CHECK-LABEL: Disassembly of section .R_PPC64_TOC16_HA:
65# CHECK: .FR_PPC64_TOC16_HA:54# CHECK: 10010018: addis 1, 2, 0
66# CHECK: 10010018: {{.*}} nop
6755
68.section .R_PPC64_REL24,"ax",@progbits56.section .R_PPC64_REL24,"ax",@progbits
69.globl .FR_PPC64_REL2457 b 1f
70.FR_PPC64_REL24:581:
71 b .Lfoox
72.section .R_PPC64_REL24_2,"ax",@progbits
73.Lfoox:
7459
75# CHECK: Disassembly of section .R_PPC64_REL24:60# CHECK-LABEL: Disassembly of section .R_PPC64_REL24:
76# CHECK: .FR_PPC64_REL24:61# CHECK: 1001001c: b .+4
77# CHECK: 1001001c: {{.*}} b .+4
7862
79.section .R_PPC64_REL14,"ax",@progbits63.section .R_PPC64_REL14,"ax",@progbits
80.globl .FR_PPC64_REL1464 beq 1f
81.FR_PPC64_REL14:651:
82 beq .Lfooy
83.section .R_PPC64_REL14_2,"ax",@progbits
84.Lfooy:
8566
86# CHECK: Disassembly of section .R_PPC64_REL14:67# CHECK-LABEL: Disassembly of section .R_PPC64_REL14:
87# CHECK: .FR_PPC64_REL14:68# CHECK: 10010020: bt 2, .+4
88# CHECK: 10010020: {{.*}} bt 2, .+4
8969
90.section .R_PPC64_ADDR16_LO,"ax",@progbits70.section .R_PPC64_ADDR16_LO,"ax",@progbits
91.globl .FR_PPC64_ADDR16_LO
92.FR_PPC64_ADDR16_LO:
93 li 1, .Lfoo@l71 li 1, .Lfoo@l
9472
95# CHECK: Disassembly of section .R_PPC64_ADDR16_LO:73# CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_LO:
96# CHECK: .FR_PPC64_ADDR16_LO:74# CHECK: 10010024: li 1, 0
97# CHECK: 10010024: {{.*}} li 1, 0
9875
99.section .R_PPC64_ADDR16_HI,"ax",@progbits76.section .R_PPC64_ADDR16_HI,"ax",@progbits
100.globl .FR_PPC64_ADDR16_HI
101.FR_PPC64_ADDR16_HI:
102 li 1, .Lfoo@h77 li 1, .Lfoo@h
10378
104# CHECK: Disassembly of section .R_PPC64_ADDR16_HI:79# CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HI:
105# CHECK: .FR_PPC64_ADDR16_HI:80# CHECK: 10010028: li 1, 4097
106# CHECK: 10010028: {{.*}} li 1, 4097
10781
108.section .R_PPC64_ADDR16_HA,"ax",@progbits82.section .R_PPC64_ADDR16_HA,"ax",@progbits
109.globl .FR_PPC64_ADDR16_HA
110.FR_PPC64_ADDR16_HA:
111 li 1, .Lfoo@ha83 li 1, .Lfoo@ha
11284
113# CHECK: Disassembly of section .R_PPC64_ADDR16_HA:85# CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HA:
114# CHECK: .FR_PPC64_ADDR16_HA:86# CHECK: 1001002c: li 1, 4097
115# CHECK: 1001002c: {{.*}} li 1, 4097
11687
117.section .R_PPC64_ADDR16_HIGHER,"ax",@progbits88.section .R_PPC64_ADDR16_HIGHER,"ax",@progbits
118.globl .FR_PPC64_ADDR16_HIGHER
119.FR_PPC64_ADDR16_HIGHER:
120 li 1, .Lfoo@higher89 li 1, .Lfoo@higher
12190
122# CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHER:91# CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HIGHER:
123# CHECK: .FR_PPC64_ADDR16_HIGHER:92# CHECK: 10010030: li 1, 0
124# CHECK: 10010030: {{.*}} li 1, 0
12593
126.section .R_PPC64_ADDR16_HIGHERA,"ax",@progbits94.section .R_PPC64_ADDR16_HIGHERA,"ax",@progbits
127.globl .FR_PPC64_ADDR16_HIGHERA
128.FR_PPC64_ADDR16_HIGHERA:
129 li 1, .Lfoo@highera95 li 1, .Lfoo@highera
13096
131# CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHERA:97# CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HIGHERA:
132# CHECK: .FR_PPC64_ADDR16_HIGHERA:98# CHECK: 10010034: li 1, 0
133# CHECK: 10010034: {{.*}} li 1, 0
13499
135.section .R_PPC64_ADDR16_HIGHEST,"ax",@progbits100.section .R_PPC64_ADDR16_HIGHEST,"ax",@progbits
136.globl .FR_PPC64_ADDR16_HIGHEST
137.FR_PPC64_ADDR16_HIGHEST:
138 li 1, .Lfoo@highest101 li 1, .Lfoo@highest
139102
140# CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHEST:103# CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HIGHEST:
141# CHECK: .FR_PPC64_ADDR16_HIGHEST:104# CHECK: 10010038: li 1, 0
142# CHECK: 10010038: {{.*}} li 1, 0
143105
144.section .R_PPC64_ADDR16_HIGHESTA,"ax",@progbits106.section .R_PPC64_ADDR16_HIGHESTA,"ax",@progbits
145.globl .FR_PPC64_ADDR16_HIGHESTA
146.FR_PPC64_ADDR16_HIGHESTA:
147 li 1, .Lfoo@highesta107 li 1, .Lfoo@highesta
148108
149# CHECK: Disassembly of section .R_PPC64_ADDR16_HIGHESTA:109# CHECK-LABEL: Disassembly of section .R_PPC64_ADDR16_HIGHESTA:
150# CHECK: .FR_PPC64_ADDR16_HIGHESTA:110# CHECK: 1001003c: li 1, 0
151# CHECK: 1001003c: {{.*}} li 1, 0
152111
153.section .R_PPC64_REL32, "ax",@progbits112.section .R_PPC64_REL32, "ax",@progbits
154.globl .FR_PPC64_REL32
155.FR_PPC64_REL32:
156 addis 5, 2, .LC0@toc@ha113 addis 5, 2, .LC0@toc@ha
157 ld 5, .LC0@toc@l(5)114 ld 5, .LC0@toc@l(5)
158.LBB0_2:115.LBB0_2:
159 add 3, 3, 4116 add 3, 3, 4
160117
161# DATALE: Disassembly of section .rodata:118# DATALE: '.rodata':
162# DATALE: .rodata:119# DATALE: 0x100001c8 80fe0000
163# DATALE: 10000190: b8 fe 00 00
164120
165# DATABE: Disassembly of section .rodata:121# DATABE: '.rodata':
166# DATABE: .rodata:122# DATABE: 0x100001c8 0000fe80
167# DATABE: 10000190: 00 00 fe b8
168123
169# Address of rodata + value stored at rodata entry124# Address of rodata + value stored at rodata entry
170# should equal address of LBB0_2.125# should equal address of LBB0_2.
171# 0x10000190 + 0xfeb4 = 0x10010044126# 0x10000190 + 0xfeb4 = 0x10010044
172# CHECK: Disassembly of section .R_PPC64_REL32:127# CHECK-LABEL: Disassembly of section .R_PPC64_REL32:
173# CHECK: .FR_PPC64_REL32:128# CHECK: 10010040: addis 5, 2, 0
174# CHECK: 10010040: {{.*}} nop129# CHECK: 10010044: ld 5, -32736(5)
175# CHECK: 10010044: {{.*}} ld 5, -32736(2)130# CHECK: 10010048: add 3, 3, 4
176# CHECK: 10010048: {{.*}} add 3, 3, 4
177131
178.section .R_PPC64_REL64, "ax",@progbits132.section .R_PPC64_REL64, "ax",@progbits
179.globl .FR_PPC64_REL64
180.FR_PPC64_REL64:
181 .cfi_startproc133 .cfi_startproc
182 .cfi_personality 148, __foo134 .cfi_personality 148, __foo
183 li 0, 1135 li 0, 1
...@@ -187,18 +139,26 @@ _start:...@@ -187,18 +139,26 @@ _start:
187__foo:139__foo:
188 li 3,0140 li 3,0
189141
190# Check that address of eh_frame entry + value stored142.section .R_PPC64_TOC,"a",@progbits
191# should equal the address of foo. Since it is not aligned,143 .quad .TOC.@tocbase
192# the entry is not stored exactly at 10000198. It starts at
193# address 0x1000019a and has the value 0xfeaa.
194# 0x100001aa + 0xfeae = 0x10010058
195# DATALE: Disassembly of section .eh_frame:
196# DATALE: .eh_frame:
197# DATALE: 100001a8: {{.*}} ae fe
198144
199# DATABE: Disassembly of section .eh_frame:145# SEC: .got PROGBITS 0000000010020000
200# DATABE: .eh_frame:146
201# DATABE: 100001b0: fe ae {{.*}}147## tocbase = .got+0x8000 = 0x10028000
148# DATALE-LABEL: section '.R_PPC64_TOC':
149# DATALE: 00800210 00000000
150
151# DATABE-LABEL: section '.R_PPC64_TOC':
152# DATABE: 00000000 10028000
153
154# Check that the personality (relocated by R_PPC64_REL64) in the .eh_frame
155# equals the address of __foo.
156# 0x100001ea + 0xfe6e = 0x10010058
157# DATALE: section '.eh_frame':
158# DATALE: 0x100001e8 {{....}}6efe
159
160# DATABE: section '.eh_frame':
161# DATABE: 0x100001e8 {{[0-9a-f]+ [0-9a-f]+}} fe6e{{....}}
202162
203# CHECK: __foo163# CHECK: __foo
204# CHECK-NEXT: 10010058: {{.*}} li 3, 0164# CHECK-NEXT: 10010058: li 3, 0
deps/lld/test/ELF/ppc64-shared-long_branch.s+8-8
...@@ -83,32 +83,32 @@ b:...@@ -83,32 +83,32 @@ b:
8383
84# Verify address of the callee84# Verify address of the callee
85# CALLEE_DUMP: callee:85# CALLEE_DUMP: callee:
86# CALLEE_DUMP: 10000: {{.*}} addis 2, 12, 51586# CALLEE_DUMP: 10000: {{.*}} addis 2, 12, 514
87# CALLEE_DUMP: 10004: {{.*}} addi 2, 2, -3252887# CALLEE_DUMP: 10004: {{.*}} addi 2, 2, -32528
88# CALLEE_DUMP: 10008: {{.*}} addis 4, 2, 088# CALLEE_DUMP: 10008: {{.*}} addis 4, 2, 0
8989
90# Verify the address of _start, and the call to the long-branch thunk.90# Verify the address of _start, and the call to the long-branch thunk.
91# CALLER_DUMP: _start:91# CALLER_DUMP: _start:
92# CALLER_DUMP: 2010020: {{.*}} addis 2, 12, 392# CALLER_DUMP: 2010020: {{.*}} addis 2, 12, 2
93# CALLER_DUMP: 2010038: {{.*}} bl .+5693# CALLER_DUMP: 2010038: {{.*}} bl .+56
9494
95# Verify the thunks contents: TOC-pointer + offset = .branch_lt[0]95# Verify the thunks contents: TOC-pointer + offset = .branch_lt[0]
96# 0x20380F0 + 32552 = 0x204001896# 0x20280F0 + 32560 = 0x2030020
97# CALLER_DUMP: __long_branch_callee:97# CALLER_DUMP: __long_branch_callee:
98# CALLER_DUMP: 2010060: {{.*}} addis 12, 2, 098# CALLER_DUMP: 2010060: {{.*}} addis 12, 2, 0
99# CALLER_DUMP: 2010064: {{.*}} ld 12, 32552(12)99# CALLER_DUMP: 2010064: {{.*}} ld 12, 32560(12)
100# CALLER_DUMP: 2010068: {{.*}} mtctr 12100# CALLER_DUMP: 2010068: {{.*}} mtctr 12
101# CALLER_DUMP: 201006c: {{.*}} bctr101# CALLER_DUMP: 201006c: {{.*}} bctr
102102
103# .got section is at address 0x20300f0 so TOC pointer points to 0x20400F0.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.104# .plt section has a 2 entry header and a single entry for the long branch.
105# [Nr] Name Type Address Off Size105# [Nr] Name Type Address Off Size
106# SECTIONS: [11] .got PROGBITS 00000000020300f0 20300f0 000008106# SECTIONS: [10] .got PROGBITS 00000000020200f0 20200f0 000008
107# SECTIONS: [13] .plt NOBITS 0000000002040000 2030108 000018107# SECTIONS: [13] .plt NOBITS 0000000002030008 2030008 000018
108# SECTIONS: [14] .branch_lt NOBITS 0000000002040018 2030108 000008108# SECTIONS: [14] .branch_lt NOBITS 0000000002030020 2030008 000008
109109
110# There is a relative dynamic relocation for (.plt + 16 bytes), with a base110# There is a relative dynamic relocation for (.plt + 16 bytes), with a base
111# address equal to callees local entry point (0x10000 + 8).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:112# DYNRELOC: Relocation section '.rela.dyn' at offset 0x{{[0-9a-f]+}} contains 3 entries:
113# DYNRELOC: Offset Info Type Symbol's Value113# DYNRELOC: Offset Info Type Symbol's Value
114# DYNRELOC: 0000000002040018 0000000000000016 R_PPC64_RELATIVE 10008114# DYNRELOC: 0000000002030020 0000000000000016 R_PPC64_RELATIVE 10008
deps/lld/test/ELF/ppc64-sort-small-cm-relocs.s created+108
...@@ -0,0 +1,108 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-sort-small-cm-relocs-input2.s -o %t2.o
4# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-sort-small-cm-relocs-input3.s -o %t3.o
5# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-sort-small-cm-relocs-input4.s -o %t4.o
6
7# RUN: ld.lld %t1.o %t2.o %t3.o %t4.o -o %t -Map=%t.map
8# RUN: FileCheck %s < %t.map
9
10# Test an alternate link order.
11# RUN: ld.lld %t2.o %t3.o %t4.o %t1.o -o %t -Map=%t.map
12# RUN: FileCheck %s -check-prefix=ALTERNATE < %t.map
13
14# If a linker script has a sections command then allow that to override the
15# default sorting behavior.
16# RUN: echo "SECTIONS { \
17# RUN: .toc : { \
18# RUN: *ppc64-sort-small-cm-relocs.s.tmp4.o(.toc*) \
19# RUN: *ppc64-sort-small-cm-relocs.s.tmp1.o(.toc*) \
20# RUN: *(.toc*) \
21# RUN: } \
22# RUN: } " > %t.script
23# RUN: ld.lld %t1.o %t2.o %t3.o %t4.o -o %t -script %t.script -Map=%t.map
24# RUN: FileCheck %s -check-prefix=SEC-CMD < %t.map
25
26# RUN: echo "SECTIONS { .text : {*(.text*)} } " > %t.script
27# RUN: ld.lld %t1.o %t2.o %t3.o %t4.o -o %t -script %t.script -Map=%t.map
28# RUN: FileCheck %s -check-prefix=SEC-CMD2 < %t.map
29
30# Default sort if the linker script does not have a sections command.
31# RUN: echo "" > %t.script
32# RUN: ld.lld %t1.o %t2.o %t3.o %t4.o -o %t -script %t.script -Map=%t.map
33# RUN: FileCheck %s -check-prefix=NOSEC < %t.map
34 .text
35
36 .global _start
37 .type _start,@function
38_start:
39 li 3, 55
40 blr
41
42 .type a,@object
43 .data
44 .global a
45a:
46 .long 10
47 .size a, 4
48
49 .type c,@object
50 .data
51 .global c
52c:
53 .long 55
54 .size c, 4
55
56 .type d,@object
57 .global d
58d:
59 .long 33
60 .size d, 4
61
62 # .toc section contains only some constants.
63 .section .toc,"aw",@progbits
64 .quad 0xa1a1a1a1a1a1a1a1
65 .quad 0xb2b2b2b2b2b2b2b2
66
67# Input files tmp3.o and tmp4.o contain small code model relocs.
68
69# CHECK: .got
70# CHECK-NEXT: <internal>:(.got)
71# CHECK-NEXT: .toc
72# CHECK-NEXT: {{.*}}3.o:(.toc)
73# CHECK-NEXT: {{.*}}4.o:(.toc)
74# CHECK-NEXT: {{.*}}1.o:(.toc)
75# CHECK-NEXT: {{.*}}2.o:(.toc)
76
77# ALTERNATE: .got
78# ALTERNATE-NEXT: <internal>:(.got)
79# ALTERNATE-NEXT: .toc
80# ALTERNATE-NEXT: {{.*}}3.o:(.toc)
81# ALTERNATE-NEXT: {{.*}}4.o:(.toc)
82# ALTERNATE-NEXT: {{.*}}2.o:(.toc)
83# ALTERNATE-NEXT: {{.*}}1.o:(.toc)
84
85# SEC-CMD: .got
86# SEC-CMD-NEXT: <internal>:(.got)
87# SEC-CMD-NEXT: .toc
88# SEC-CMD-NEXT: {{.*}}4.o:(.toc)
89# SEC-CMD-NEXT: {{.*}}1.o:(.toc)
90# SEC-CMD-NEXT: {{.*}}2.o:(.toc)
91# SEC-CMD-NEXT: {{.*}}3.o:(.toc)
92
93# SEC-CMD2: .got
94# SEC-CMD2-NEXT: <internal>:(.got)
95# SEC-CMD2-NEXT: .toc
96# SEC-CMD2-NEXT: {{.*}}1.o:(.toc)
97# SEC-CMD2-NEXT: {{.*}}2.o:(.toc)
98# SEC-CMD2-NEXT: {{.*}}3.o:(.toc)
99# SEC-CMD2-NEXT: {{.*}}4.o:(.toc)
100
101# NOSEC: .got
102# NOSEC-NEXT: <internal>:(.got)
103# NOSEC-NEXT: .toc
104# NOSEC-NEXT: {{.*}}3.o:(.toc)
105# NOSEC-NEXT: {{.*}}4.o:(.toc)
106# NOSEC-NEXT: {{.*}}1.o:(.toc)
107# NOSEC-NEXT: {{.*}}2.o:(.toc)
108
deps/lld/test/ELF/ppc64-tls-gd-le-small.s deleted-61
...@@ -1,61 +0,0 @@
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
25test:
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
46a:
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 deleted-83
...@@ -1,83 +0,0 @@
1// REQUIRES: ppc
2
3// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
5// RUN: ld.lld %t.o -o %t
6// RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s
7// RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s
8
9// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
10// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
11// RUN: ld.lld %t.o -o %t
12// RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s
13// RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s
14
15 .text
16 .abiversion 2
17 .globl _start # -- Begin function _start
18 .p2align 4
19 .type _start,@function
20_start: # @_start
21.Lfunc_begin0:
22.Lfunc_gep0:
23 addis 2, 12, .TOC.-.Lfunc_gep0@ha
24 addi 2, 2, .TOC.-.Lfunc_gep0@l
25.Lfunc_lep0:
26 .localentry _start, .Lfunc_lep0-.Lfunc_gep0
27# %bb.0: # %entry
28 mflr 0
29 std 31, -8(1)
30 std 0, 16(1)
31 stdu 1, -64(1)
32 mr 31, 1
33 std 30, 48(31) # 8-byte Folded Spill
34 li 3, 0
35 stw 3, 44(31)
36 addis 3, 2, a@got@tlsgd@ha
37 addi 3, 3, a@got@tlsgd@l
38 bl __tls_get_addr(a@tlsgd)
39 nop
40 lwz 30, 0(3)
41 extsw 3, 30
42 ld 30, 48(31) # 8-byte Folded Reload
43 addi 1, 1, 64
44 ld 0, 16(1)
45 ld 31, -8(1)
46 mtlr 0
47 blr
48 .long 0
49 .quad 0
50.Lfunc_end0:
51 .size _start, .Lfunc_end0-.Lfunc_begin0
52
53.globl __tls_get_addr
54.type __tls_get_addr,@function
55__tls_get_addr:
56
57 # -- End function
58 .type a,@object # @a
59 .section .tdata,"awT",@progbits
60 .globl a
61 .p2align 2
62a:
63 .long 55 # 0x37
64 .size a, 4
65
66// Verify that the input has general-dynamic tls relocation types
67// InputRelocs: Relocation section '.rela.text'
68// InputRelocs: R_PPC64_GOT_TLSGD16_HA {{0+}} a + 0
69// InputRelocs: R_PPC64_GOT_TLSGD16_LO {{0+}} a + 0
70// InputRelocs: R_PPC64_TLSGD {{0+}} a + 0
71
72// Verify that the general-dynamic sequence is relaxed to local exec.
73// #ha(a@tprel) --> (0 - 0x7000 + 0x8000) >> 16 = 0
74// #lo(a@tprel)) --> (0 - 0x7000) & 0xFFFF = -0x7000 = -28672
75// Dis: _start:
76// Dis: nop
77// Dis: addis 3, 13, 0
78// Dis: nop
79// Dis: addi 3, 3, -28672
80
81// Verify that no general-dynamic relocations exist for the dynamic linker.
82// OutputRelocs-NOT: R_PPC64_DTPMOD64
83// OutputRelocs-NOT: R_PPC64_DTPREL64
deps/lld/test/ELF/ppc64-tls-gd.s created+102
...@@ -0,0 +1,102 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
3# RUN: echo '.tbss; .globl b, c; b: .zero 4; c:' | llvm-mc -filetype=obj -triple=powerpc64le - -o %t1.o
4# RUN: ld.lld -shared -soname=t1.so %t1.o -o %t1.so
5
6# RUN: ld.lld -shared %t.o %t1.o -o %t.so
7# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=GD-REL %s
8# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=GD %s
9
10# RUN: ld.lld %t.o %t1.o -o %t
11# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
12# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
13
14# RUN: ld.lld %t.o %t1.so -o %t
15# RUN: llvm-readobj -r %t | FileCheck --check-prefix=IE-REL %s
16# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=IE %s
17
18# GD-REL: .rela.dyn {
19# GD-REL-NEXT: 0x200F0 R_PPC64_DTPMOD64 a 0x0
20# GD-REL-NEXT: 0x200F8 R_PPC64_DTPREL64 a 0x0
21# GD-REL-NEXT: 0x20100 R_PPC64_DTPMOD64 b 0x0
22# GD-REL-NEXT: 0x20108 R_PPC64_DTPREL64 b 0x0
23# GD-REL-NEXT: 0x20110 R_PPC64_DTPMOD64 c 0x0
24# GD-REL-NEXT: 0x20118 R_PPC64_DTPREL64 c 0x0
25# GD-REL-NEXT: }
26
27## &DTPMOD(a) - .TOC. = &.got[0] - (.got+0x8000) = -32768
28# GD: addis 3, 2, 0
29# GD-NEXT: addi 3, 3, -32768
30# GD-NEXT: bl .+40
31# GD-NEXT: ld 2, 24(1)
32
33## &DTPMOD(b) - .TOC. = &.got[2] - (.got+0x8000) = -32752
34# GD-NEXT: addis 3, 2, 0
35# GD-NEXT: addi 3, 3, -32752
36# GD-NEXT: bl .+24
37# GD-NEXT: ld 2, 24(1)
38
39## &DTPMOD(b) - .TOC. = &.got[4] - (.got+0x8000) = -32736
40# GD-NEXT: li 3, -32736
41# GD-NEXT: bl .+12
42# GD-NEXT: ld 2, 24(1)
43
44# NOREL: no relocations
45
46## a@tprel = st_value(a)-0x7000 = -28664
47# LE: nop
48# LE-NEXT: addis 3, 13, 0
49# LE-NEXT: nop
50# LE-NEXT: addi 3, 3, -28664
51## b@tprel = st_value(b)-0x7000 = -28660
52# LE: nop
53# LE-NEXT: addis 3, 13, 0
54# LE-NEXT: nop
55# LE-NEXT: addi 3, 3, -28660
56## c@tprel = st_value(c)-0x7000 = -28656
57# LE-NEXT: addis 3, 13, 0
58# LE-NEXT: nop
59# LE-NEXT: addi 3, 3, -28656
60
61# IE-REL: .rela.dyn {
62# IE-REL-NEXT: 0x100200C0 R_PPC64_TPREL64 b 0x0
63# IE-REL-NEXT: 0x100200C8 R_PPC64_TPREL64 c 0x0
64# IE-REL-NEXT: }
65
66## a is relaxed to use LE.
67## a@tprel = st_value(a)-0x7000 = -28664
68# IE: nop
69# IE-NEXT: addis 3, 13, 0
70# IE-NEXT: nop
71# IE-NEXT: addi 3, 3, -28664
72## &DTPMOD(b) - .TOC. = &.got[0] - (.got+0x8000) = -32768
73# IE-NEXT: addis 3, 2, 0
74# IE-NEXT: ld 3, -32768(3)
75# IE-NEXT: nop
76# IE-NEXT: add 3, 3, 13
77## &DTPMOD(c) - .TOC. = &.got[1] - (.got+0x8000) = -32760
78## r0 is wrong. R_PPC64_GOT_TLS16 cannot be relaxed to IE but the behavior is
79## consistent with ld.bfd
80# IE-NEXT: ld 3, -32760(0)
81# IE-NEXT: nop
82# IE-NEXT: add 3, 3, 13
83
84addis 3, 2, a@got@tlsgd@ha
85addi 3, 3, a@got@tlsgd@l
86bl __tls_get_addr(a@tlsgd)
87nop
88
89addis 3, 2, b@got@tlsgd@ha
90addi 3, 3, b@got@tlsgd@l
91bl __tls_get_addr(b@tlsgd)
92nop
93
94addi 3, 0, c@got@tlsgd
95bl __tls_get_addr(c@tlsgd)
96nop
97
98.section .tbss
99.globl a
100.zero 8
101a:
102.zero 4
deps/lld/test/ELF/ppc64-tls-ie-le.s deleted-140
...@@ -1,140 +0,0 @@
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
19test1: # @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
24test2: # @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
29test3: # @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
34test4: # @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
39test5: # @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
44test6: # @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
49test7: # @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
54test8: # @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
59test9: # @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
64test_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-ie.s created+171
...@@ -0,0 +1,171 @@
1# REQUIRES: ppc
2
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le %s -o %t.o
4# RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=INPUT-REL %s
5## IE
6# RUN: ld.lld -shared %t.o -o %t.so
7# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=IE-REL %s
8# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=IE %s
9## IE -> LE
10# RUN: ld.lld %t.o -o %t
11# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
12# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
13
14# RUN: llvm-mc -filetype=obj -triple=powerpc64 %s -o %t.o
15# RUN: llvm-readobj -r %t.o | FileCheck --check-prefix=INPUT-REL %s
16## IE
17# RUN: ld.lld -shared %t.o -o %t.so
18# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=IE-REL %s
19# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=IE %s
20## IE -> LE
21# RUN: ld.lld %t.o -o %t
22# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
23# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
24
25# IE-REL: .rela.dyn {
26# IE-REL-NEXT: 0x200B0 R_PPC64_TPREL64 c 0x0
27# IE-REL-NEXT: 0x200C0 R_PPC64_TPREL64 i 0x0
28# IE-REL-NEXT: 0x200C8 R_PPC64_TPREL64 l 0x0
29# IE-REL-NEXT: 0x200B8 R_PPC64_TPREL64 s 0x0
30# IE-REL-NEXT: }
31
32# INPUT-REL: R_PPC64_GOT_TPREL16_HA c 0x0
33# INPUT-REL: R_PPC64_GOT_TPREL16_LO_DS c 0x0
34# INPUT-REL: R_PPC64_TLS c 0x0
35## &.got[0] - .TOC. = -32768
36# IE-LABEL: test1:
37# IE-NEXT: addis 3, 2, 0
38# IE-NEXT: ld 3, -32768(3)
39# IE-NEXT: lbzx 3, 3, 13
40# LE-LABEL: test1:
41# LE-NEXT: nop
42# LE-NEXT: addis 3, 13, 0
43# LE-NEXT: lbz 3, -28672(3)
44test1:
45 addis 3, 2, c@got@tprel@ha
46 ld 3, c@got@tprel@l(3)
47 lbzx 3, 3, c@tls
48
49# INPUT-REL: R_PPC64_GOT_TPREL16_HA s 0x0
50# INPUT-REL: R_PPC64_GOT_TPREL16_LO_DS s 0x0
51# INPUT-REL: R_PPC64_TLS s 0x0
52## &.got[1] - .TOC. = -32760
53# IE-LABEL: test2:
54# IE-NEXT: addis 3, 2, 0
55# IE-NEXT: ld 3, -32760(3)
56# IE-NEXT: lhzx 3, 3, 13
57# LE-LABEL: test2:
58# LE-NEXT: nop
59# LE-NEXT: addis 3, 13, 0
60# LE-NEXT: lhz 3, -28670(3)
61test2:
62 addis 3, 2, s@got@tprel@ha
63 ld 3, s@got@tprel@l(3)
64 lhzx 3, 3, s@tls
65
66# INPUT-REL: R_PPC64_GOT_TPREL16_HA i 0x0
67# INPUT-REL: R_PPC64_GOT_TPREL16_LO_DS i 0x0
68# INPUT-REL: R_PPC64_TLS i 0x0
69## &.got[2] - .TOC. = -32752
70# IE-LABEL: test3:
71# IE-NEXT: addis 3, 2, 0
72# IE-NEXT: ld 3, -32752(3)
73# IE-NEXT: lwzx 3, 3, 13
74# LE-LABEL: test3:
75# LE-NEXT: nop
76# LE-NEXT: addis 3, 13, 0
77# LE-NEXT: lwz 3, -28668(3)
78test3:
79 addis 3, 2, i@got@tprel@ha
80 ld 3, i@got@tprel@l(3)
81 lwzx 3, 3, i@tls
82
83# INPUT-REL: R_PPC64_GOT_TPREL16_HA l 0x0
84# INPUT-REL: R_PPC64_GOT_TPREL16_LO_DS l 0x0
85# INPUT-REL: R_PPC64_TLS l 0x0
86## &.got[3] - .TOC. = -32744
87# IE-LABEL: test4:
88# IE-NEXT: addis 3, 2, 0
89# IE-NEXT: ld 3, -32744(3)
90# IE-NEXT: ldx 3, 3, 13
91# LE-LABEL: test4:
92# LE-NEXT: nop
93# LE-NEXT: addis 3, 13, 0
94# LE-NEXT: ld 3, -28664(3)
95test4:
96 addis 3, 2, l@got@tprel@ha
97 ld 3, l@got@tprel@l(3)
98 ldx 3, 3, l@tls
99
100# LE-LABEL: test5:
101# LE-NEXT: nop
102# LE-NEXT: addis 4, 13, 0
103# LE-NEXT: stb 3, -28672(4)
104test5:
105 addis 4, 2, c@got@tprel@ha
106 ld 4, c@got@tprel@l(4)
107 stbx 3, 4, c@tls
108
109
110# LE-LABEL: test6:
111# LE-NEXT: nop
112# LE-NEXT: addis 4, 13, 0
113# LE-NEXT: sth 3, -28670(4)
114test6:
115 addis 4, 2, s@got@tprel@ha
116 ld 4, s@got@tprel@l(4)
117 sthx 3, 4, s@tls
118
119
120# LE-LABEL: test7:
121# LE-NEXT: nop
122# LE-NEXT: addis 4, 13, 0
123# LE-NEXT: stw 3, -28668(4)
124test7:
125 addis 4, 2, i@got@tprel@ha
126 ld 4, i@got@tprel@l(4)
127 stwx 3, 4, i@tls
128
129# LE-LABEL: test8:
130# LE-NEXT: nop
131# LE-NEXT: addis 4, 13, 0
132# LE-NEXT: std 3, -28664(4)
133test8:
134 addis 4, 2, l@got@tprel@ha
135 ld 4, l@got@tprel@l(4)
136 stdx 3, 4, l@tls
137
138# LE-LABEL: test9:
139# LE-NEXT: nop
140# LE-NEXT: addis 3, 13, 0
141# LE-NEXT: addi 3, 3, -28668
142test9:
143 addis 3, 2, i@got@tprel@ha
144 ld 3, i@got@tprel@l(3)
145 add 3, 3, i@tls
146
147# LE-LABEL: test_ds:
148# LE-NEXT: addis 4, 13, 0
149# LE-NEXT: std 3, -28664(4)
150test_ds:
151 ld 4, l@got@tprel(2)
152 stdx 3, 4, l@tls
153
154# NOREL: There are no relocations in this file.
155
156.section .tdata,"awT",@progbits
157.globl c, s, i, l
158c:
159.byte 97
160
161.p2align 1
162s:
163.short 55
164
165.p2align 2
166i:
167.long 55
168
169.p2align 3
170l:
171.quad 55
deps/lld/test/ELF/ppc64-tls-ld-le.s+3-5
...@@ -3,13 +3,13 @@...@@ -3,13 +3,13 @@
3// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o3// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s4// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
5// RUN: ld.lld %t.o -o %t5// RUN: ld.lld %t.o -o %t
6// RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s6// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=Dis %s
7// RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s7// RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s
88
9// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o9// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
10// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s10// RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
11// RUN: ld.lld %t.o -o %t11// RUN: ld.lld %t.o -o %t
12// RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s12// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=Dis %s
13// RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s13// RUN: llvm-readelf -r %t | FileCheck --check-prefix=OutputRelocs %s
1414
15 .text15 .text
...@@ -52,9 +52,7 @@ _start: # @_start...@@ -52,9 +52,7 @@ _start: # @_start
52.Lfunc_end0:52.Lfunc_end0:
53 .size _start, .Lfunc_end0-.Lfunc_begin053 .size _start, .Lfunc_end0-.Lfunc_begin0
54 # -- End function54 # -- End function
55.globl __tls_get_addr55
56.type __tls_get_addr,@function
57__tls_get_addr:
58 .type a,@object # @a56 .type a,@object # @a
59 .section .tdata,"awT",@progbits57 .section .tdata,"awT",@progbits
60 .p2align 258 .p2align 2
deps/lld/test/ELF/ppc64-tls-ld-preemptable.s created+35
...@@ -0,0 +1,35 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=ppc64le %s -o %t.o
3# RUN: ld.lld %t.o -shared -o %t.so
4# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s
5# RUN: llvm-nm %t.so | FileCheck --check-prefix=NM %s
6# RUN: llvm-readelf -x .rodata %t.so | FileCheck --check-prefix=RODATA %s
7
8# 0x2a - 0x8000 = -32726
9# CHECK: addis 4, 3, 0
10# CHECK-NEXT: addi 4, 4, -32726
11# CHECK-NEXT: lis 5, 0
12# CHECK-NEXT: ori 5, 5, 0
13
14# NM: 000000000000002a B i
15# RODATA: 2a000000 00000000
16
17# We used to error on R_PPC64_DTPREL* to preemptable symbols.
18# i is STB_GLOBAL and preemptable.
19.globl foo
20foo:
21 addis 4, 3, i@dtprel@ha # R_PPC64_DTPREL16_HA
22 addi 4, 4, i@dtprel@l # R_PPC64_DTPREL16_LO
23
24 lis 5, i@dtprel@highesta # R_PPC64_DTPREL16_HIGHESTA
25 ori 5, 5, i@dtprel@highera # R_PPC64_DTPREL16_HIGHERA
26
27.section .rodata,"a",@progbits
28 .quad i@dtprel+32768
29
30.section .tbss,"awT",@nobits
31 .space 0x2a
32.globl i
33i:
34 .long 0
35 .size i, 4
deps/lld/test/ELF/ppc64-toc-addis-nop-lqsq.s+2-3
...@@ -6,10 +6,10 @@...@@ -6,10 +6,10 @@
6# RUN: ld.lld -shared %t2.o -o %t2.so6# RUN: ld.lld -shared %t2.o -o %t2.so
77
8# RUN: ld.lld %t2.so %p/Inputs/ppc64le-quadword-ldst.o -o %t8# RUN: ld.lld %t2.so %p/Inputs/ppc64le-quadword-ldst.o -o %t
9# RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s9# RUN: llvm-objdump -d %t | FileCheck --check-prefix=Dis %s
1010
11# RUN: ld.lld --no-toc-optimize %t2.so %p/Inputs/ppc64le-quadword-ldst.o -o %t11# 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 %s12# RUN: llvm-objdump -d %t | FileCheck --check-prefix=NoOpt %s
1313
14# QuadInputRelocs: Relocation section '.rela.text'14# QuadInputRelocs: Relocation section '.rela.text'
15# QuadInputRelocs: R_PPC64_TOC16_LO_DS 0000000000000000 quadLd15# QuadInputRelocs: R_PPC64_TOC16_LO_DS 0000000000000000 quadLd
...@@ -70,4 +70,3 @@...@@ -70,4 +70,3 @@
70# NoOpt-NEXT: addis 3, 2, 070# NoOpt-NEXT: addis 3, 2, 0
71# NoOpt-NEXT: 82 7f 83 f8 <unknown>71# NoOpt-NEXT: 82 7f 83 f8 <unknown>
72# NoOpt-NEXT: blr72# NoOpt-NEXT: blr
73
deps/lld/test/ELF/ppc64-toc-addis-nop.s+11-11
...@@ -1,16 +1,16 @@...@@ -1,16 +1,16 @@
1# REQUIRES: ppc1# REQUIRES: ppc
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o3# 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 %s4# RUN: llvm-readelf -r %t.o | FileCheck --check-prefix=InputRelocs %s
55
6# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o6# 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.so7# RUN: ld.lld -shared %t2.o -o %t2.so
8#8#
9# RUN: ld.lld %t2.so %t.o -o %t9# RUN: ld.lld %t2.so %t.o -o %t
10# RUN: llvm-objdump -D %t | FileCheck --check-prefix=Dis %s10# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=Dis %s
11#11#
12# RUN: ld.lld --no-toc-optimize %t2.so %t.o -o %t12# RUN: ld.lld --no-toc-optimize %t2.so %t.o -o %t
13# RUN: llvm-objdump -D %t | FileCheck --check-prefix=NoOpt %s13# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=NoOpt %s
1414
15# InputRelocs: Relocation section '.rela.text'15# InputRelocs: Relocation section '.rela.text'
16# InputRelocs: R_PPC64_TOC16_HA16# InputRelocs: R_PPC64_TOC16_HA
...@@ -35,7 +35,7 @@ bytes:...@@ -35,7 +35,7 @@ bytes:
35 addis 4, 2, byteSt@toc@ha35 addis 4, 2, byteSt@toc@ha
36 stb 3, byteSt@toc@l(4)36 stb 3, byteSt@toc@l(4)
37 blr37 blr
38# Dis-LABEL: bytes38# Dis-LABEL: bytes:
39# Dis-NEXT: addis39# Dis-NEXT: addis
40# Dis-NEXT: addi40# Dis-NEXT: addi
41# Dis-NEXT: nop41# Dis-NEXT: nop
...@@ -44,7 +44,7 @@ bytes:...@@ -44,7 +44,7 @@ bytes:
44# Dis-NEXT: stb 3, 32625(2)44# Dis-NEXT: stb 3, 32625(2)
45# Dis-NEXT: blr45# Dis-NEXT: blr
4646
47# NoOpt-LABEL: bytes47# NoOpt-LABEL: bytes:
48# NoOpt-NEXT: addis48# NoOpt-NEXT: addis
49# NoOpt-NEXT: addi49# NoOpt-NEXT: addi
50# NoOpt-NEXT: addis 3, 2, 050# NoOpt-NEXT: addis 3, 2, 0
...@@ -69,7 +69,7 @@ halfs:...@@ -69,7 +69,7 @@ halfs:
69 addis 5, 2, halfSt@toc@ha69 addis 5, 2, halfSt@toc@ha
70 sth 4, halfSt@toc@l(5)70 sth 4, halfSt@toc@l(5)
71 blr71 blr
72# Dis-LABEL: halfs72# Dis-LABEL: halfs:
73# Dis-NEXT: addis73# Dis-NEXT: addis
74# Dis-NEXT: addi74# Dis-NEXT: addi
75# Dis-NEXT: nop75# Dis-NEXT: nop
...@@ -80,7 +80,7 @@ halfs:...@@ -80,7 +80,7 @@ halfs:
80# Dis-NEXT: sth 4, 32628(2)80# Dis-NEXT: sth 4, 32628(2)
81# Dis-NEXT: blr81# Dis-NEXT: blr
8282
83# NoOpt-LABEL: halfs83# NoOpt-LABEL: halfs:
84# NoOpt-NEXT: addis84# NoOpt-NEXT: addis
85# NoOpt-NEXT: addi85# NoOpt-NEXT: addi
86# NoOpt-NEXT: addis 3, 2, 086# NoOpt-NEXT: addis 3, 2, 0
...@@ -178,7 +178,7 @@ vec_dq:...@@ -178,7 +178,7 @@ vec_dq:
178 stxv 3, vecSt@toc@l(3)178 stxv 3, vecSt@toc@l(3)
179 blr179 blr
180180
181# Dis-LABEL: vec_dq181# Dis-LABEL: vec_dq:
182# Dis-NEXT: addis182# Dis-NEXT: addis
183# Dis-NEXT: addi183# Dis-NEXT: addi
184# Dis-NEXT: nop184# Dis-NEXT: nop
...@@ -187,7 +187,7 @@ vec_dq:...@@ -187,7 +187,7 @@ vec_dq:
187# Dis-NEXT: stxv 3, 32672(2)187# Dis-NEXT: stxv 3, 32672(2)
188# Dis-NEXT: blr188# Dis-NEXT: blr
189189
190# NoOpt-LABEL: vec_dq190# NoOpt-LABEL: vec_dq:
191# NoOpt-NEXT: addis191# NoOpt-NEXT: addis
192# NoOpt-NEXT: addi192# NoOpt-NEXT: addi
193# NoOpt-NEXT: addis 3, 2, 0193# NoOpt-NEXT: addis 3, 2, 0
...@@ -214,7 +214,7 @@ vec_ds:...@@ -214,7 +214,7 @@ vec_ds:
214 addis 3, 2, vecSt@toc@ha214 addis 3, 2, vecSt@toc@ha
215 stxssp 3, vecSt@toc@l(3)215 stxssp 3, vecSt@toc@l(3)
216 blr216 blr
217# Dis-LABEL: vec_ds217# Dis-LABEL: vec_ds:
218# Dis-NEXT: addis218# Dis-NEXT: addis
219# Dis-NEXT: addi219# Dis-NEXT: addi
220# Dis-NEXT: nop220# Dis-NEXT: nop
...@@ -227,7 +227,7 @@ vec_ds:...@@ -227,7 +227,7 @@ vec_ds:
227# Dis-NEXT: stxssp 3, 32672(2)227# Dis-NEXT: stxssp 3, 32672(2)
228# Dis-NEXT: blr228# Dis-NEXT: blr
229229
230# NoOpt-LABEL: vec_ds230# NoOpt-LABEL: vec_ds:
231# NoOpt-NEXT: addis231# NoOpt-NEXT: addis
232# NoOpt-NEXT: addi232# NoOpt-NEXT: addi
233# NoOpt-NEXT: addis 3, 2, 0233# NoOpt-NEXT: addis 3, 2, 0
deps/lld/test/ELF/ppc64-toc-rel.s+25-30
...@@ -1,16 +1,18 @@...@@ -1,16 +1,18 @@
1# REQUIRES: ppc1# REQUIRES: ppc
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4# RUN: llvm-readobj -relocations %t.o | FileCheck -check-prefix=RELOCS-LE %s4# RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=RELOCS-LE %s
5# RUN: ld.lld %t.o -o %t25# RUN: ld.lld %t.o -o %t
6# RUN: llvm-objdump -D %t2 | FileCheck %s6# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
7# RUN: llvm-objdump -D %t2 | FileCheck -check-prefix=CHECK-LE %s7# RUN: llvm-readelf -x .got %t | FileCheck --check-prefix=HEX-LE %s
8# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=CHECK %s
89
9# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o10# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
10# RUN: llvm-readobj -relocations %t.o | FileCheck -check-prefix=RELOCS-BE %s11# RUN: llvm-readobj -r %t.o | FileCheck -check-prefix=RELOCS-BE %s
11# RUN: ld.lld %t.o -o %t212# RUN: ld.lld %t.o -o %t
12# RUN: llvm-objdump -D %t2 | FileCheck %s13# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
13# RUN: llvm-objdump -D %t2 | FileCheck -check-prefix=CHECK-BE %s14# RUN: llvm-readelf -x .got %t | FileCheck --check-prefix=HEX-BE %s
15# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=CHECK %s
1416
15# Make sure we calculate the offset correctly for a toc-relative access to a17# Make sure we calculate the offset correctly for a toc-relative access to a
16# global variable as described by the PPC64 Elf V2 abi.18# global variable as described by the PPC64 Elf V2 abi.
...@@ -57,26 +59,19 @@ _start:...@@ -57,26 +59,19 @@ _start:
57# RELOCS-BE: 0xA R_PPC64_TOC16_HA global_a 0x059# RELOCS-BE: 0xA R_PPC64_TOC16_HA global_a 0x0
58# RELOCS-BE: 0xE R_PPC64_TOC16_LO global_a 0x060# RELOCS-BE: 0xE R_PPC64_TOC16_LO global_a 0x0
5961
60# Want to check _start for the values used to build the offset from the TOC base62# The .TOC. symbol represents the TOC base address: .got + 0x8000 = 0x10028000,
61# to global_a. The .TOC. symbol is expected at address 0x10030000, and the63# which is stored in the first entry of .got
62# TOC base is address-of(.TOC.) + 0x8000. The expected offset is:64# NM: 0000000010028000 d .TOC.
63# 0x10020000(global_a) - 0x10038000(Toc base) = -0x18000(Offset)65# NM: 0000000010030000 D global_a
64# which gets materialized into r3 as ((-1 << 16) - 32768).66# HEX-LE: section '.got':
67# HEX-LE-NEXT: 0x10020000 00800210 00000000
68# HEX-BE: section '.got':
69# HEX-BE-NEXT: 0x10020000 00000000 10028000
6570
66# CHECK: Disassembly of section .text:71# r2 stores the TOC base address. To access global_a with r3, it
67# CHECK-NEXT: _start:72# computes the address with TOC plus an offset.
68# CHECK: 10010008: {{.*}} addis 3, 2, -173# The offset global_a - .TOC. = 0x10030000 - 0x10028000 = 0x8000
69# CHECK-NEXT: 1001000c: {{.*}} addi 3, 3, -3276874# gets materialized as (1 << 16) - 32768.
7075# CHECK: _start:
71# CHECK: Disassembly of section .data:76# CHECK: 10010008: addis 3, 2, 1
72# CHECK-NEXT: global_a:77# CHECK-NEXT: 1001000c: addi 3, 3, -32768
73# CHECK-NEXT: 10020000: {{.*}}
74
75# CHECK-LE: Disassembly of section .got:
76# CHECK-LE-NEXT: .got:
77# CHECK-LE-NEXT: 10030000: 00 80 03 10
78
79# CHECK-BE: Disassembly of section .got:
80# CHECK-BE-NEXT: .got:
81# CHECK-BE-NEXT: 10030000: 00 00 00 00
82# CHECK-BE-NEXT: 10030004: 10 03 80 00
deps/lld/test/ELF/ppc64-toc-relax-constants.s created+61
...@@ -0,0 +1,61 @@
1# REQUIRES: ppc
2
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unkown-linux %p/Inputs/ppc64-toc-relax-shared.s -o %t.o
4# RUN: ld.lld -shared %t.o -o %t.so
5# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o
6# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-toc-relax.s -o %t2.o
7# RUN: llvm-readobj -r %t1.o | FileCheck --check-prefix=RELOCS %s
8# RUN: ld.lld %t1.o %t2.o %t.so -o %t
9# RUN: llvm-readelf -S %t | FileCheck --check-prefix=SECTIONS %s
10# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
11# RUN: llvm-objdump -D %t | FileCheck %s
12
13# In most cases, .toc contains exclusively addresses relocated by R_PPC64_ADDR16.
14# Rarely .toc contain constants or variables.
15# Test we can still perform toc-indirect to toc-relative relaxation.
16
17# RELOCS: .rela.text {
18# RELOCS-NEXT: 0x0 R_PPC64_TOC16_HA .toc 0x0
19# RELOCS-NEXT: 0x4 R_PPC64_TOC16_LO_DS .toc 0x0
20# RELOCS-NEXT: 0x8 R_PPC64_TOC16_HA .toc 0x8
21# RELOCS-NEXT: 0xC R_PPC64_TOC16_LO_DS .toc 0x8
22# RELOCS-NEXT: 0x10 R_PPC64_TOC16_HA .toc 0x10
23# RELOCS-NEXT: 0x14 R_PPC64_TOC16_LO_DS .toc 0x10
24# RELOCS-NEXT: }
25
26# SECTIONS: .got PROGBITS 0000000010020090
27# SECTIONS: .toc PROGBITS 0000000010020090
28
29# NM: 0000000010030000 D default
30
31# .LCONST1 is .toc[0].
32# .LCONST1 - (.got+0x8000) = 0x10020090 - (0x10020090+0x8000) = -32768
33# CHECK: nop
34# CHECK: lwa 3, -32768(2)
35 addis 3, 2, .LCONST1@toc@ha
36 lwa 3, .LCONST1@toc@l(3)
37
38# .LCONST2 is .toc[1]
39# .LCONST2 - (.got+0x8000) = 0x10020098 - (0x10020090+0x8000) = -32760
40# CHECK: nop
41# CHECK: ld 4, -32760(2)
42 addis 4, 2, .LCONST2@toc@ha
43 ld 4, .LCONST2@toc@l(4)
44
45# .Ldefault is .toc[2]. `default` is not preemptable when producing an executable.
46# After toc-indirection to toc-relative relaxation, it is loaded using an
47# offset relative to r2.
48# CHECK: nop
49# CHECK: addi 5, 2, 32624
50# CHECK: lwa 5, 0(5)
51 addis 5, 2, .Ldefault@toc@ha
52 ld 5, .Ldefault@toc@l(5)
53 lwa 5, 0(5)
54
55.section .toc,"aw",@progbits
56.LCONST1:
57 .quad 11
58.LCONST2:
59 .quad 22
60.Ldefault:
61 .tc default[TC],default
deps/lld/test/ELF/ppc64-toc-relax-jumptable.s created+73
...@@ -0,0 +1,73 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-readelf -S %t | FileCheck --check-prefixes=SECTIONS %s
5# RUN: llvm-readelf -x .toc %t | FileCheck --check-prefixes=HEX-LE %s
6# RUN: llvm-objdump -d %t | FileCheck --check-prefixes=CHECK %s
7
8# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
9# RUN: ld.lld %t.o -o %t
10# RUN: llvm-readelf -S %t | FileCheck --check-prefixes=SECTIONS %s
11# RUN: llvm-readelf -x .toc %t | FileCheck --check-prefixes=HEX-BE %s
12# RUN: llvm-objdump -d %t | FileCheck --check-prefixes=CHECK %s
13
14# .LJT is a local symbol (non-preemptable).
15# Test we can perform the toc-indirect to toc-relative relaxation.
16
17# SECTIONS: .rodata PROGBITS 00000000100001c8
18
19# HEX-LE: section '.toc':
20# HEX-LE-NEXT: 10020008 c8010010 00000000
21
22# HEX-BE: section '.toc':
23# HEX-BE-NEXT: 10020008 00000000 100001c8
24
25# CHECK-LABEL: _start
26# CHECK: clrldi 3, 3, 62
27# CHECK-NEXT: addis 4, 2, -2
28# CHECK-NEXT: addi 4, 4, -32312
29# CHECK-NEXT: sldi 3, 3, 2
30
31 .text
32 .global _start
33 .type _start, @function
34_start:
35.Lstart_gep:
36 addis 2, 12, .TOC.-.Lstart_gep@ha
37 addi 2, 2, .TOC.-.Lstart_gep@l
38.Lstart_lep:
39 .localentry _start, .Lstart_lep-.Lstart_gep
40 rldicl 3, 3, 0, 62
41 addis 4, 2, .LJTI_TE@toc@ha
42 ld 4, .LJTI_TE@toc@l(4)
43 sldi 3, 3, 2
44 lwax 3, 3, 4
45 add 3, 3, 4
46 mtctr 3
47 bctr
48
49.LBB1:
50 li 3, 0
51 blr
52.LBB2:
53 li 3, 10
54 blr
55.LBB3:
56 li 3, 55
57 blr
58.LBB4:
59 li 3, 255
60 blr
61
62 .section .rodata,"a",@progbits
63 .p2align 2
64.LJT:
65 .long .LBB1-.LJT
66 .long .LBB2-.LJT
67 .long .LBB3-.LJT
68 .long .LBB4-.LJT
69
70.section .toc,"aw",@progbits
71# TOC entry for the jumptable address.
72.LJTI_TE:
73 .tc .LJT[TC],.LJT
deps/lld/test/ELF/ppc64-toc-relax.s created+105
...@@ -0,0 +1,105 @@
1# REQUIRES: ppc
2# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-toc-relax-shared.s -o %t.o
3# RUN: ld.lld -shared %t.o -o %t.so
4# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o
5# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-toc-relax.s -o %t2.o
6# RUN: llvm-readobj -r %t1.o | FileCheck --check-prefixes=RELOCS-LE,RELOCS %s
7# RUN: ld.lld %t1.o %t2.o %t.so -o %t
8# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=COMMON,EXE %s
9
10# RUN: ld.lld -shared %t1.o %t2.o %t.so -o %t2.so
11# RUN: llvm-objdump -d --no-show-raw-insn %t2.so | FileCheck --check-prefixes=COMMON,SHARED %s
12
13# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-toc-relax-shared.s -o %t.o
14# RUN: ld.lld -shared %t.o -o %t.so
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-toc-relax.s -o %t2.o
17# RUN: llvm-readobj -r %t1.o | FileCheck --check-prefixes=RELOCS-BE,RELOCS %s
18# RUN: ld.lld %t1.o %t2.o %t.so -o %t
19# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefixes=COMMON,EXE %s
20
21# RUN: ld.lld -shared %t1.o %t2.o %t.so -o %t2.so
22# RUN: llvm-objdump -d --no-show-raw-insn %t2.so | FileCheck --check-prefixes=COMMON,SHARED %s
23
24# RELOCS-LE: .rela.text {
25# RELOCS-LE-NEXT: 0x0 R_PPC64_TOC16_HA .toc 0x0
26# RELOCS-LE-NEXT: 0x4 R_PPC64_TOC16_LO_DS .toc 0x0
27# RELOCS-LE-NEXT: 0xC R_PPC64_TOC16_HA .toc 0x8
28# RELOCS-LE-NEXT: 0x10 R_PPC64_TOC16_LO_DS .toc 0x8
29# RELOCS-LE-NEXT: 0x18 R_PPC64_TOC16_HA .toc 0x10
30# RELOCS-LE-NEXT: 0x1C R_PPC64_TOC16_LO_DS .toc 0x10
31# RELOCS-LE-NEXT: 0x24 R_PPC64_TOC16_HA .toc 0x18
32# RELOCS-LE-NEXT: 0x28 R_PPC64_TOC16_LO_DS .toc 0x18
33# RELOCS-LE-NEXT: }
34
35# RELOCS-BE: .rela.text {
36# RELOCS-BE-NEXT: 0x2 R_PPC64_TOC16_HA .toc 0x0
37# RELOCS-BE-NEXT: 0x6 R_PPC64_TOC16_LO_DS .toc 0x0
38# RELOCS-BE-NEXT: 0xE R_PPC64_TOC16_HA .toc 0x8
39# RELOCS-BE-NEXT: 0x12 R_PPC64_TOC16_LO_DS .toc 0x8
40# RELOCS-BE-NEXT: 0x1A R_PPC64_TOC16_HA .toc 0x10
41# RELOCS-BE-NEXT: 0x1E R_PPC64_TOC16_LO_DS .toc 0x10
42# RELOCS-BE-NEXT: 0x26 R_PPC64_TOC16_HA .toc 0x18
43# RELOCS-BE-NEXT: 0x2A R_PPC64_TOC16_LO_DS .toc 0x18
44# RELOCS-BE-NEXT: }
45
46# RELOCS: .rela.toc {
47# RELOCS-NEXT: 0x0 R_PPC64_ADDR64 hidden 0x0
48# RELOCS-NEXT: 0x8 R_PPC64_ADDR64 hidden2 0x0
49# RELOCS-NEXT: 0x10 R_PPC64_ADDR64 shared 0x0
50# RELOCS-NEXT: 0x18 R_PPC64_ADDR64 default 0x0
51# RELOCS-NEXT: }
52
53# NM-DAG: 0000000010030000 D default
54# NM-DAG: 0000000010030000 d hidden
55# NM-DAG: 0000000010040000 d hidden2
56
57# 'hidden' is non-preemptable. It is relaxed.
58# address(hidden) - (.got+0x8000) = 0x10030000 - (0x100200c0+0x8000) = 32576
59# COMMON: nop
60# COMMON: addi 3, 2, 32576
61# COMMON: lwa 3, 0(3)
62 addis 3, 2, .Lhidden@toc@ha
63 ld 3, .Lhidden@toc@l(3)
64 lwa 3, 0(3)
65
66# address(hidden2) - (.got+0x8000) = 0x10040000 - (0x100200c0+0x8000) = (1<<16)+32576
67# COMMON: addis 3, 2, 1
68# COMMON: addi 3, 3, 32576
69# COMMON: lwa 3, 0(3)
70 addis 3, 2, .Lhidden2@toc@ha
71 ld 3, .Lhidden2@toc@l(3)
72 lwa 3, 0(3)
73
74# 'shared' is not defined in an object file. Its definition is determined at
75# runtime by the dynamic linker, so the extra indirection cannot be relaxed.
76# The first addis can still be relaxed to nop, though.
77# COMMON: nop
78# COMMON: ld 4, -32752(2)
79# COMMON: lwa 4, 0(4)
80 addis 4, 2, .Lshared@toc@ha
81 ld 4, .Lshared@toc@l(4)
82 lwa 4, 0(4)
83
84# 'default' has default visibility. It is non-preemptable when producing an executable.
85# address(default) - (.got+0x8000) = 0x10030000 - (0x100200c0+0x8000) = 32576
86# EXE: nop
87# EXE: addi 5, 2, 32576
88# EXE: lwa 5, 0(5)
89
90# SHARED: nop
91# SHARED: ld 5, -32744(2)
92# SHARED: lwa 5, 0(5)
93 addis 5, 2, .Ldefault@toc@ha
94 ld 5, .Ldefault@toc@l(5)
95 lwa 5, 0(5)
96
97.section .toc,"aw",@progbits
98.Lhidden:
99 .tc hidden[TC], hidden
100.Lhidden2:
101 .tc hidden2[TC], hidden2
102.Lshared:
103 .tc shared[TC], shared
104.Ldefault:
105 .tc default[TC], default
deps/lld/test/ELF/ppc64-toc-restore-recursive-call.s+8-9
...@@ -1,8 +1,8 @@...@@ -1,8 +1,8 @@
1# REQUIRES: ppc1# REQUIRES: ppc
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t1.o3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4# RUN: ld.lld -shared %t1.o -o %t4# RUN: ld.lld -shared %t.o -o %t.so
5# RUN: llvm-objdump -d -r %t | FileCheck %s5# RUN: llvm-objdump -d --no-show-raw-insn -r %t.so | FileCheck %s
66
7# For a recursive call that is interposable the linker calls the plt-stub rather7# 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 and8# then calling the function directly. Since the call is through a plt stub and
...@@ -14,12 +14,11 @@...@@ -14,12 +14,11 @@
14# for recursive calls as well as keeps the logic for recursive calls consistent14# for recursive calls as well as keeps the logic for recursive calls consistent
15# with non-recursive calls.15# with non-recursive calls.
1616
17# CHECK-LABEL: __plt_recursive_func:17# CHECK-LABEL: 0000000000010000 recursive_func:
18# CHECK-NEXT: 10000:18# CHECK: 10028: bl .+32
19# CHECK-LABEL: recursive_func19# CHECK-NEXT: ld 2, 24(1)
20# CHECK-NEXT: 10014:20
21# CHECK: 1003c: {{[0-9a-fA-F ]+}} bl .+6710880421# CHECK-LABEL: 0000000000010048 __plt_recursive_func:
22# CHECK-NEXT: ld 2, 24(1)
2322
24 .abiversion 223 .abiversion 2
25 .section ".text"24 .section ".text"
deps/lld/test/ELF/ppc64-toc-restore.s+17-24
...@@ -5,14 +5,14 @@...@@ -5,14 +5,14 @@
5// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-func.s -o %t3.o5// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/ppc64-func.s -o %t3.o
6// RUN: ld.lld -shared %t2.o -o %t2.so6// RUN: ld.lld -shared %t2.o -o %t2.so
7// RUN: ld.lld %t.o %t2.so %t3.o -o %t7// RUN: ld.lld %t.o %t2.so %t3.o -o %t
8// RUN: llvm-objdump -d %t | FileCheck %s8// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
99
10// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o10// 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/shared-ppc64.s -o %t2.o11// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared-ppc64.s -o %t2.o
12// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-func.s -o %t3.o12// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/ppc64-func.s -o %t3.o
13// RUN: ld.lld -shared %t2.o -o %t2.so13// RUN: ld.lld -shared %t2.o -o %t2.so
14// RUN: ld.lld %t.o %t2.so %t3.o -o %t14// RUN: ld.lld %t.o %t2.so %t3.o -o %t
15// RUN: llvm-objdump -d %t | FileCheck %s15// RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
1616
17 .text17 .text
18 .abiversion 218 .abiversion 2
...@@ -28,16 +28,11 @@ _start:...@@ -28,16 +28,11 @@ _start:
28 bl foo28 bl foo
29 nop29 nop
30 bl bar_local30 bl bar_local
3131// CHECK-LABEL: _start:
3232// CHECK-NEXT: 10010008: bl .+64
33// CHECK: Disassembly of section .text:33// CHECK-NEXT: 1001000c: ld 2, 24(1)
34// CHECK: _start:34// CHECK-NEXT: 10010010: bl .-16
35// CHECK: 1001001c: {{.*}} bl .+6710883635// CHECK-EMPTY:
36// CHECK-NOT: 10010020: {{.*}} nop
37// CHECK: 10010020: {{.*}} ld 2, 24(1)
38// CHECK: 10010024: {{.*}} bl .+67108848
39// CHECK-NOT: 10010028: {{.*}} nop
40// CHECK-NOT: 10010028: {{.*}} ld 2, 24(1)
4136
42# Calling a function in another object file which will have same37# Calling a function in another object file which will have same
43# TOC base does not need a nop. If nop present, do not rewrite to38# TOC base does not need a nop. If nop present, do not rewrite to
...@@ -47,26 +42,24 @@ _diff_object:...@@ -47,26 +42,24 @@ _diff_object:
47 bl foo_not_shared42 bl foo_not_shared
48 bl foo_not_shared43 bl foo_not_shared
49 nop44 nop
5045// CHECK-LABEL: _diff_object:
51// CHECK: _diff_object:46// CHECK-NEXT: 10010014: bl .+28
52// CHECK-NEXT: 10010028: {{.*}} bl .+2447// CHECK-NEXT: 10010018: bl .+24
53// CHECK-NEXT: 1001002c: {{.*}} bl .+2048// CHECK-NEXT: 1001001c: nop
54// CHECK-NEXT: 10010030: {{.*}} nop
5549
56# Branching to a local function does not need a nop50# Branching to a local function does not need a nop
57.global noretbranch51.global noretbranch
58noretbranch:52noretbranch:
59 b bar_local53 b bar_local
60// CHECK: noretbranch:54// CHECK-LABEL: noretbranch:
61// CHECK: 10010034: {{.*}} b .+6710883255// CHECK: 10010020: b .+67108832
62// CHECK-NOT: 10010038: {{.*}} nop56// CHECK-EMPTY:
63// CHECK-NOT: 1001003c: {{.*}} ld 2, 24(1)
6457
65// This should come last to check the end-of-buffer condition.58// This should come last to check the end-of-buffer condition.
66.global last59.global last
67last:60last:
68 bl foo61 bl foo
69 nop62 nop
70// CHECK: last:63// CHECK-LABEL: last:
71// CHECK: 10010038: {{.*}} bl .+6710880864// CHECK-NEXT: 10010024: bl .+36
72// CHECK-NEXT: 1001003c: {{.*}} ld 2, 24(1)65// CHECK-NEXT: 10010028: ld 2, 24(1)
deps/lld/test/ELF/ppc64-weak-undef-call-shared.s+2-2
...@@ -2,11 +2,11 @@...@@ -2,11 +2,11 @@
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
4# RUN: ld.lld -shared %t.o -o %t.so4# RUN: ld.lld -shared %t.o -o %t.so
5# RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s5# RUN: llvm-readobj --symbols -r --dyn-syms %t.so | FileCheck %s
66
7# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o7# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
8# RUN: ld.lld -shared %t.o -o %t.so8# RUN: ld.lld -shared %t.o -o %t.so
9# RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s9# RUN: llvm-readobj --symbols -r --dyn-syms %t.so | FileCheck %s
1010
11.section ".toc","aw"11.section ".toc","aw"
12.quad weakfunc12.quad weakfunc
deps/lld/test/ELF/ppc64-weak-undef-call.s+6-5
...@@ -2,13 +2,14 @@...@@ -2,13 +2,14 @@
22
3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t3# RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t
4# RUN: ld.lld %t -o %t24# RUN: ld.lld %t -o %t2
5# RUN: llvm-objdump -d %t2 | FileCheck %s5# RUN: llvm-objdump -d --no-show-raw-insn %t2 | FileCheck %s
66
7# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t7# RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t
8# RUN: ld.lld %t -o %t28# RUN: ld.lld %t -o %t2
9# RUN: llvm-objdump -d %t2 | FileCheck %s9# RUN: llvm-objdump -d --no-show-raw-insn %t2 | FileCheck %s
1010
11# CHECK: Disassembly of section .text:11# CHECK: Disassembly of section .text:
12# CHECK-EMPTY:
1213
13.text14.text
14.global _start15.global _start
...@@ -23,6 +24,6 @@ _start:...@@ -23,6 +24,6 @@ _start:
23# be unreachable. But, we should link successfully. We should not, however,24# be unreachable. But, we should link successfully. We should not, however,
24# generate a .plt entry (this would be wasted space). For now, we do nothing25# generate a .plt entry (this would be wasted space). For now, we do nothing
25# (leaving the zero relative offset present in the input).26# (leaving the zero relative offset present in the input).
26# CHECK: 10010000: {{.*}} bl .+027# CHECK: 10010000: bl .+0
27# CHECK: 10010004: {{.*}} nop28# CHECK: 10010004: nop
28# CHECK: 10010008: {{.*}} blr29# CHECK: 10010008: blr
deps/lld/test/ELF/pr34660.s+3-2
...@@ -13,11 +13,12 @@...@@ -13,11 +13,12 @@
13# correct symbol.13# correct symbol.
1414
15# DISASM: Disassembly of section .text:15# DISASM: Disassembly of section .text:
16# DISASM-EMPTY:
16# DISASM-NEXT: $x.0:17# DISASM-NEXT: $x.0:
17# DISASM-NEXT: 10000: 28 00 08 58 ldr x8, #6554018# DISASM-NEXT: 10000: 28 00 10 58 ldr x8, #131076
1819
19# SYM: Symbol table '.symtab'20# SYM: Symbol table '.symtab'
20# SYM: 0000000000020004 0 NOTYPE LOCAL DEFAULT 5 patatino21# SYM: 0000000000030004 0 NOTYPE LOCAL DEFAULT 6 patatino
2122
22 ldr x8, patatino23 ldr x8, patatino
23 .data24 .data
deps/lld/test/ELF/pr34872.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc %p/Inputs/undefined-error.s -filetype=obj \3# RUN: llvm-mc %p/Inputs/undefined-error.s -filetype=obj \
4# RUN: -triple=x86_64-pc-linux -o %t2.o4# RUN: -triple=x86_64-pc-linux -o %t2.o
5# RUN: ld.lld -shared %t2.o -o %t2.so5# RUN: ld.lld -shared %t2.o -o %t2.so
6# RUN: not ld.lld %t2.so %t.o -o /dev/null 2>&1 | FileCheck %s6# RUN: not ld.lld --allow-shlib-undefined %t2.so %t.o -o /dev/null 2>&1 | FileCheck %s
77
8# CHECK: undefined symbol: fmod8# CHECK: undefined symbol: fmod
9# Check we're not emitting other diagnostics for this symbol.9# Check we're not emitting other diagnostics for this symbol.
deps/lld/test/ELF/pr36475.s+1-1
...@@ -10,7 +10,7 @@...@@ -10,7 +10,7 @@
10# RUN: echo " .got.plt : { BYTE(42); *(.got); } : ph_data" >> %t.script10# RUN: echo " .got.plt : { BYTE(42); *(.got); } : ph_data" >> %t.script
11# RUN: echo "}" >> %t.script11# RUN: echo "}" >> %t.script
12# RUN: ld.lld -T %t.script %t.o -o %t.elf12# RUN: ld.lld -T %t.script %t.o -o %t.elf
13# RUN: llvm-readobj -l -elf-output-style=GNU %t.elf | FileCheck %s13# RUN: llvm-readelf -l %t.elf | FileCheck %s
1414
15# CHECK: Section to Segment mapping:15# CHECK: Section to Segment mapping:
16# CHECK-NEXT: Segment Sections...16# CHECK-NEXT: Segment Sections...
deps/lld/test/ELF/pre_init_fini_array.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t23// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2
4// RUN: ld.lld %t2 -o %t2.so -shared4// RUN: ld.lld %t2 -o %t2.so -shared
5// RUN: ld.lld %t %t2.so -o %t25// RUN: ld.lld %t %t2.so -o %t2
6// RUN: llvm-readobj -r -symbols -sections -dynamic-table %t2 | FileCheck %s6// RUN: llvm-readobj -r --symbols --sections --dynamic-table %t2 | FileCheck %s
7// RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s7// RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s
88
9.globl _start9.globl _start
deps/lld/test/ELF/pre_init_fini_array_missing.s+2
...@@ -20,6 +20,7 @@ _start:...@@ -20,6 +20,7 @@ _start:
20// ...20// ...
2121
22// CHECK: Disassembly of section .text:22// CHECK: Disassembly of section .text:
23// CHECK-EMPTY:
23// CHECK-NEXT: _start:24// CHECK-NEXT: _start:
24// CHECK-NEXT: 201000: e8 fb ff ff ff callq -525// CHECK-NEXT: 201000: e8 fb ff ff ff callq -5
25// CHECK-NEXT: 201005: e8 f6 ff ff ff callq -1026// CHECK-NEXT: 201005: e8 f6 ff ff ff callq -10
...@@ -31,6 +32,7 @@ _start:...@@ -31,6 +32,7 @@ _start:
31// In position-independent binaries, they resolve to .text too.32// In position-independent binaries, they resolve to .text too.
3233
33// PIE: Disassembly of section .text:34// PIE: Disassembly of section .text:
35// PIE-EMPTY:
34// PIE-NEXT: _start:36// PIE-NEXT: _start:
35// PIE-NEXT: 1000: e8 fb ff ff ff callq -537// PIE-NEXT: 1000: e8 fb ff ff ff callq -5
36// PIE-NEXT: 1005: e8 f6 ff ff ff callq -1038// PIE-NEXT: 1005: e8 f6 ff ff ff callq -10
deps/lld/test/ELF/progname.s+3-3
...@@ -4,18 +4,18 @@...@@ -4,18 +4,18 @@
4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2.o4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t2.s -o %t2.o
5// RUN: ld.lld -shared %t2.o -o %t2.so5// RUN: ld.lld -shared %t2.o -o %t2.so
6// RUN: ld.lld -o %t %t.o %t2.so6// RUN: ld.lld -o %t %t.o %t2.so
7// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s7// RUN: llvm-readobj --dyn-syms %t | FileCheck %s
88
9// RUN: echo "VER_1 { global: bar; };" > %t.script9// RUN: echo "VER_1 { global: bar; };" > %t.script
10// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \10// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \
11// RUN: %p/Inputs/progname-ver.s -o %t-ver.o11// RUN: %p/Inputs/progname-ver.s -o %t-ver.o
12// RUN: ld.lld -shared -o %t.so -version-script %t.script %t-ver.o12// RUN: ld.lld -shared -o %t.so -version-script %t.script %t-ver.o
13// RUN: ld.lld -o %t %t.o %t.so13// RUN: ld.lld -o %t %t.o %t.so
14// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s14// RUN: llvm-readobj --dyn-syms %t | FileCheck %s
1515
16// RUN: echo "{ _start; };" > %t.dynlist16// RUN: echo "{ _start; };" > %t.dynlist
17// RUN: ld.lld -dynamic-list %t.dynlist -o %t %t.o %t.so17// RUN: ld.lld -dynamic-list %t.dynlist -o %t %t.o %t.so
18// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s18// RUN: llvm-readobj --dyn-syms %t | FileCheck %s
1919
20// CHECK: Name: __progname20// CHECK: Name: __progname
21// CHECK-NEXT: Value: 0x20100021// CHECK-NEXT: Value: 0x201000
deps/lld/test/ELF/program-header-layout.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3# RUN: ld.lld %t -o %t23# RUN: ld.lld %t -o %t2
4# RUN: llvm-readobj -sections -program-headers %t2 | FileCheck %s4# RUN: llvm-readobj --sections -l %t2 | FileCheck %s
55
6# Check that different output sections with the same flags are merged into a6# Check that different output sections with the same flags are merged into a
7# single Read/Write PT_LOAD.7# single Read/Write PT_LOAD.
deps/lld/test/ELF/protected-shared.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/protected-shared.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/protected-shared.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t2.so4// RUN: ld.lld -shared %t2.o -o %t2.so
5// RUN: ld.lld %t.o %t2.so -o %t5// RUN: ld.lld %t.o %t2.so -o %t
6// RUN: llvm-readobj -t --dyn-symbols %t | FileCheck %s6// RUN: llvm-readobj --symbols --dyn-symbols %t | FileCheck %s
77
8 .global _start8 .global _start
9_start:9_start:
deps/lld/test/ELF/push-state.s+2-2
...@@ -19,11 +19,11 @@...@@ -19,11 +19,11 @@
19// RUN: ld.lld -shared %t3.o -soname libfoo -o %t.so19// RUN: ld.lld -shared %t3.o -soname libfoo -o %t.so
2020
21// RUN: ld.lld -o %t.exe -push-state -as-needed %t.so %t1.o21// RUN: ld.lld -o %t.exe -push-state -as-needed %t.so %t1.o
22// RUN: llvm-readobj -dynamic-table %t.exe | FileCheck -check-prefix=AS-NEEDED %s22// RUN: llvm-readobj --dynamic-table %t.exe | FileCheck -check-prefix=AS-NEEDED %s
23// AS-NEEDED-NOT: NEEDED Shared library: [libfoo]23// AS-NEEDED-NOT: NEEDED Shared library: [libfoo]
2424
25// RUN: ld.lld -o %t.exe -push-state -as-needed -pop-state %t.so %t1.o25// RUN: ld.lld -o %t.exe -push-state -as-needed -pop-state %t.so %t1.o
26// RUN: llvm-readobj -dynamic-table %t.exe | FileCheck -check-prefix=NO-AS-NEEDED %s26// RUN: llvm-readobj --dynamic-table %t.exe | FileCheck -check-prefix=NO-AS-NEEDED %s
27// NO-AS-NEEDED: NEEDED Shared library: [libfoo]27// NO-AS-NEEDED: NEEDED Shared library: [libfoo]
2828
2929
deps/lld/test/ELF/rel-addend-with-rela-input.s+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# uses Elf_Rela3# uses Elf_Rela
44
5# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t-rela.o5# RUN: llvm-mc -filetype=obj -triple=mips64-unknown-linux %s -o %t-rela.o
6# RUN: llvm-readobj -h -s -section-data -relocations %t-rela.o | FileCheck -check-prefix INPUT-RELA %s6# RUN: llvm-readobj -h -S --section-data -r %t-rela.o | FileCheck -check-prefix INPUT-RELA %s
7# INPUT-RELA: ElfHeader {7# INPUT-RELA: ElfHeader {
8# INPUT-RELA: Class: 64-bit8# INPUT-RELA: Class: 64-bit
9# INPUT-RELA: DataEncoding: BigEndian9# INPUT-RELA: DataEncoding: BigEndian
...@@ -21,7 +21,7 @@...@@ -21,7 +21,7 @@
21# Previously the addend to the dynamic relocation in the .data section was not copied if21# Previously the addend to the dynamic relocation in the .data section was not copied if
22# the input file used RELA and the output uses REL. Check that it works now:22# the input file used RELA and the output uses REL. Check that it works now:
23# RUN: ld.lld -shared -o %t.so %t-rela.o -verbose23# RUN: ld.lld -shared -o %t.so %t-rela.o -verbose
24# RUN: llvm-readobj -h -s -section-data -relocations %t.so | FileCheck -check-prefix RELA-TO-REL %s24# RUN: llvm-readobj -h -S --section-data -r %t.so | FileCheck -check-prefix RELA-TO-REL %s
25# RELA-TO-REL: ElfHeader {25# RELA-TO-REL: ElfHeader {
26# RELA-TO-REL: Class: 64-bit26# RELA-TO-REL: Class: 64-bit
27# RELA-TO-REL: DataEncoding: BigEndian27# RELA-TO-REL: DataEncoding: BigEndian
deps/lld/test/ELF/rel-offset.s+2-2
...@@ -10,6 +10,6 @@...@@ -10,6 +10,6 @@
10 .quad foo10 .quad foo
1111
12// CHECK: Section ({{.*}}) .rela.dyn {12// CHECK: Section ({{.*}}) .rela.dyn {
13// CHECK-NEXT: 0x1000 R_X86_64_64 foo 0x013// CHECK-NEXT: 0x2000 R_X86_64_64 foo 0x0
14// CHECK-NEXT: 0x1008 R_X86_64_64 foo 0x014// CHECK-NEXT: 0x2008 R_X86_64_64 foo 0x0
15// CHECK-NEXT: }15// CHECK-NEXT: }
deps/lld/test/ELF/relative-dynamic-reloc-pie.s+4-4
...@@ -1,14 +1,14 @@...@@ -1,14 +1,14 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: ld.lld -pie %t.o -o %t.pie3# RUN: ld.lld -pie %t.o -o %t.pie
4# RUN: llvm-readobj -r -dyn-symbols %t.pie | FileCheck %s4# RUN: llvm-readobj -r --dyn-syms %t.pie | FileCheck %s
55
6## Test that we create R_X86_64_RELATIVE relocations with -pie.6## Test that we create R_X86_64_RELATIVE relocations with -pie.
7# CHECK: Relocations [7# CHECK: Relocations [
8# CHECK-NEXT: Section ({{.*}}) .rela.dyn {8# CHECK-NEXT: Section ({{.*}}) .rela.dyn {
9# CHECK-NEXT: 0x2000 R_X86_64_RELATIVE - 0x20009# CHECK-NEXT: 0x3000 R_X86_64_RELATIVE - 0x3000
10# CHECK-NEXT: 0x2008 R_X86_64_RELATIVE - 0x200810# CHECK-NEXT: 0x3008 R_X86_64_RELATIVE - 0x3008
11# CHECK-NEXT: 0x2010 R_X86_64_RELATIVE - 0x200911# CHECK-NEXT: 0x3010 R_X86_64_RELATIVE - 0x3009
12# CHECK-NEXT: }12# CHECK-NEXT: }
13# CHECK-NEXT: ]13# CHECK-NEXT: ]
1414
deps/lld/test/ELF/relative-dynamic-reloc-ppc64.s deleted-71
...@@ -1,71 +0,0 @@
1// REQUIRES: ppc
2// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %s -o %t.o
3// RUN: ld.lld -shared %t.o -o %t.so
4// RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s
5
6// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
7// RUN: ld.lld -shared %t.o -o %t.so
8// RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s
9
10// Test that we create R_PPC64_RELATIVE relocations but don't put any
11// symbols in the dynamic symbol table.
12
13// CHECK: Relocations [
14// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
15// CHECK-NEXT: 0x[[FOO_ADDR:.*]] R_PPC64_RELATIVE - 0x[[FOO_ADDR]]
16// CHECK-NEXT: 0x[[BAR_ADDR:.*]] R_PPC64_RELATIVE - 0x[[BAR_ADDR]]
17// CHECK-NEXT: 0x10010 R_PPC64_RELATIVE - 0x10009
18// CHECK-NEXT: 0x{{.*}} R_PPC64_RELATIVE - 0x[[ZED_ADDR:.*]]
19// CHECK-NEXT: 0x{{.*}} R_PPC64_RELATIVE - 0x[[FOO_ADDR]]
20// CHECK-NEXT: 0x10028 R_PPC64_ADDR64 external 0x0
21// CHECK-NEXT: }
22// CHECK-NEXT: ]
23
24// CHECK: Symbols [
25// CHECK: Name: foo
26// CHECK-NEXT: Value: 0x[[FOO_ADDR]]
27// CHECK: Name: bar
28// CHECK-NEXT: Value: 0x[[BAR_ADDR]]
29// CHECK: Name: zed
30// CHECK-NEXT: Value: 0x[[ZED_ADDR]]
31// CHECK: ]
32
33// CHECK: DynamicSymbols [
34// CHECK-NEXT: Symbol {
35// CHECK-NEXT: Name:
36// CHECK-NEXT: Value: 0x0
37// CHECK-NEXT: Size: 0
38// CHECK-NEXT: Binding: Local
39// CHECK-NEXT: Type: None
40// CHECK-NEXT: Other: 0
41// CHECK-NEXT: Section: Undefined
42// CHECK-NEXT: }
43// CHECK-NEXT: Symbol {
44// CHECK-NEXT: Name: external
45// CHECK-NEXT: Value: 0x0
46// CHECK-NEXT: Size: 0
47// CHECK-NEXT: Binding: Global
48// CHECK-NEXT: Type: None
49// CHECK-NEXT: Other: 0
50// CHECK-NEXT: Section: Undefined
51// CHECK-NEXT: }
52// CHECK-NEXT: ]
53
54 .data
55foo:
56 .quad foo
57
58 .hidden bar
59 .global bar
60bar:
61 .quad bar
62 .quad bar + 1
63
64 .hidden zed
65 .comm zed,1
66 .quad zed
67
68 .section abc,"aw"
69 .quad foo
70
71 .quad external
deps/lld/test/ELF/relative-dynamic-reloc.s+3-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3// RUN: ld.lld -shared %t.o -o %t.so3// RUN: ld.lld -shared %t.o -o %t.so
4// RUN: llvm-readobj -t -r -dyn-symbols %t.so | FileCheck %s4// RUN: llvm-readobj --symbols -r --dyn-syms %t.so | FileCheck %s
55
6// Test that we create R_X86_64_RELATIVE relocations but don't put any6// Test that we create R_X86_64_RELATIVE relocations but don't put any
7// symbols in the dynamic symbol table.7// symbols in the dynamic symbol table.
...@@ -10,10 +10,10 @@...@@ -10,10 +10,10 @@
10// CHECK-NEXT: Section ({{.*}}) .rela.dyn {10// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
11// CHECK-NEXT: 0x[[FOO_ADDR:.*]] R_X86_64_RELATIVE - 0x[[FOO_ADDR]]11// CHECK-NEXT: 0x[[FOO_ADDR:.*]] R_X86_64_RELATIVE - 0x[[FOO_ADDR]]
12// CHECK-NEXT: 0x[[BAR_ADDR:.*]] R_X86_64_RELATIVE - 0x[[BAR_ADDR]]12// CHECK-NEXT: 0x[[BAR_ADDR:.*]] R_X86_64_RELATIVE - 0x[[BAR_ADDR]]
13// CHECK-NEXT: 0x1010 R_X86_64_RELATIVE - 0x100913// CHECK-NEXT: 0x2010 R_X86_64_RELATIVE - 0x2009
14// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x[[ZED_ADDR:.*]]14// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x[[ZED_ADDR:.*]]
15// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x[[FOO_ADDR]]15// CHECK-NEXT: 0x{{.*}} R_X86_64_RELATIVE - 0x[[FOO_ADDR]]
16// CHECK-NEXT: 0x1028 R_X86_64_64 external 0x016// CHECK-NEXT: 0x2028 R_X86_64_64 external 0x0
17// CHECK-NEXT: }17// CHECK-NEXT: }
18// CHECK-NEXT: ]18// CHECK-NEXT: ]
1919
deps/lld/test/ELF/relocatable-bss.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
3# RUN: ld.lld -r %t1.o -o %t3# RUN: ld.lld -r %t1.o -o %t
4# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s4# RUN: llvm-readobj --file-headers --sections -l --symbols -r %t | FileCheck %s
55
6## We check here that .bss does not occupy the space in file.6## We check here that .bss does not occupy the space in file.
7## If it would, the SectionHeaderOffset would have offset about 5 megabytes.7## If it would, the SectionHeaderOffset would have offset about 5 megabytes.
deps/lld/test/ELF/relocatable-comdat-multiple.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# 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 %S/Inputs/relocatable-comdat-multiple.s -o %t2.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/relocatable-comdat-multiple.s -o %t2.o
4# RUN: ld.lld -r %t.o %t2.o -o %t4# RUN: ld.lld -r %t.o %t2.o -o %t
5# RUN: llvm-readobj -elf-section-groups %t | FileCheck %s5# RUN: llvm-readobj --elf-section-groups %t | FileCheck %s
66
7# CHECK: Groups {7# CHECK: Groups {
8# CHECK-NEXT: Group {8# CHECK-NEXT: Group {
deps/lld/test/ELF/relocatable-comdat.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -r %t.o %t.o -o %t3# RUN: ld.lld -r %t.o %t.o -o %t
4# RUN: llvm-readobj -elf-section-groups -sections %t | FileCheck %s4# RUN: llvm-readobj --elf-section-groups --sections %t | FileCheck %s
55
6# CHECK: Name: .text.bar6# CHECK: Name: .text.bar
7# CHECK-NEXT: Type: SHT_PROGBITS7# CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/relocatable-comdat2.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -r %t.o -o %t3# RUN: ld.lld -r %t.o -o %t
4# RUN: llvm-readobj -elf-section-groups -s %t | FileCheck %s4# RUN: llvm-readobj --elf-section-groups -S %t | FileCheck %s
55
6## Check .foo was not merged.6## Check .foo was not merged.
7# CHECK: Sections [7# CHECK: Sections [
deps/lld/test/ELF/relocatable-comment.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
3# RUN: ld.lld -r %t1.o -o %t3# RUN: ld.lld -r %t1.o -o %t
4# RUN: llvm-readobj -s -section-data %t | FileCheck %s4# RUN: llvm-readobj -S --section-data %t | FileCheck %s
55
6# CHECK: Name: .comment6# CHECK: Name: .comment
7# CHECK-NEXT: Type: SHT_PROGBITS7# CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/relocatable-common.s+6-6
...@@ -1,17 +1,17 @@...@@ -1,17 +1,17 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o
3# RUN: ld.lld -r %t1.o -o %t3# RUN: ld.lld -r %t1.o -o %t
4# RUN: llvm-readobj -symbols -r %t | FileCheck %s4# RUN: llvm-readobj --symbols -r %t | FileCheck %s
5# RUN: ld.lld -r --no-define-common %t1.o -o %t5# RUN: ld.lld -r --no-define-common %t1.o -o %t
6# RUN: llvm-readobj -symbols -r %t | FileCheck %s6# RUN: llvm-readobj --symbols -r %t | FileCheck %s
7# RUN: ld.lld -r --define-common %t1.o -o %t7# RUN: ld.lld -r --define-common %t1.o -o %t
8# RUN: llvm-readobj -symbols -r %t | FileCheck -check-prefix=DEFCOMM %s8# RUN: llvm-readobj --symbols -r %t | FileCheck -check-prefix=DEFCOMM %s
9# RUN: ld.lld -r -d %t1.o -o %t9# RUN: ld.lld -r -d %t1.o -o %t
10# RUN: llvm-readobj -symbols -r %t | FileCheck -check-prefix=DEFCOMM %s10# RUN: llvm-readobj --symbols -r %t | FileCheck -check-prefix=DEFCOMM %s
11# RUN: ld.lld -r -dc %t1.o -o %t11# RUN: ld.lld -r -dc %t1.o -o %t
12# RUN: llvm-readobj -symbols -r %t | FileCheck -check-prefix=DEFCOMM %s12# RUN: llvm-readobj --symbols -r %t | FileCheck -check-prefix=DEFCOMM %s
13# RUN: ld.lld -r -dp %t1.o -o %t13# RUN: ld.lld -r -dp %t1.o -o %t
14# RUN: llvm-readobj -symbols -r %t | FileCheck -check-prefix=DEFCOMM %s14# RUN: llvm-readobj --symbols -r %t | FileCheck -check-prefix=DEFCOMM %s
1515
16# CHECK: Symbol {16# CHECK: Symbol {
17# CHECK: Name: common17# CHECK: Name: common
deps/lld/test/ELF/relocatable-compressed-input.s+2-2
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1# REQUIRES: x86, zlib1# REQUIRES: x86, zlib
22
3# RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=x86_64-unknown-linux %s -o %t13# RUN: llvm-mc -compress-debug-sections=zlib-gnu -filetype=obj -triple=x86_64-unknown-linux %s -o %t1
4# RUN: llvm-readobj -sections %t1 | FileCheck -check-prefix=GNU %s4# RUN: llvm-readobj --sections %t1 | FileCheck -check-prefix=GNU %s
5# GNU: Name: .zdebug_str5# GNU: Name: .zdebug_str
66
7# RUN: ld.lld %t1 -o %t2 -r7# RUN: ld.lld %t1 -o %t2 -r
8# RUN: llvm-readobj -sections -section-data %t2 | FileCheck %s8# RUN: llvm-readobj --sections --section-data %t2 | FileCheck %s
99
10## Check we uncompress 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# CHECK: Section {11# CHECK: Section {
deps/lld/test/ELF/relocatable-eh-frame-hdr.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld --eh-frame-hdr -r %t.o -o %t3# RUN: ld.lld --eh-frame-hdr -r %t.o -o %t
4# RUN: llvm-readobj -s %t | FileCheck %s4# RUN: llvm-readobj -S %t | FileCheck %s
55
6# CHECK: Sections [6# CHECK: Sections [
7# CHECK-NOT: Name: .eh_frame_hdr7# CHECK-NOT: Name: .eh_frame_hdr
deps/lld/test/ELF/relocatable-eh-frame.s deleted-19
...@@ -1,19 +0,0 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -r %t.o %t.o -o %t
4# RUN: llvm-readobj -r %t | FileCheck %s
5# RUN: ld.lld %t -o %t.so -shared
6# RUN: llvm-objdump -h %t.so | FileCheck --check-prefix=DSO %s
7
8# DSO: .eh_frame 00000034
9
10# CHECK: Relocations [
11# CHECK-NEXT: Section ({{.*}}) .rela.eh_frame {
12# CHECK-NEXT: 0x20 R_X86_64_PC32 .foo 0x0
13# CHECK-NEXT: 0x50 R_X86_64_NONE - 0x0
14# CHECK-NEXT: }
15# CHECK-NEXT: ]
16
17.section .foo,"aG",@progbits,bar,comdat
18.cfi_startproc
19.cfi_endproc
deps/lld/test/ELF/relocatable-ehframe.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t1.o2# 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/relocatable-ehframe.s -o %t2.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable-ehframe.s -o %t2.o
4# RUN: ld.lld -r %t1.o %t2.o -o %t4# RUN: ld.lld -r %t1.o %t2.o -o %t
5# RUN: llvm-readobj -r -s -section-data %t | FileCheck %s5# RUN: llvm-readobj -r -S --section-data %t | FileCheck %s
66
7# CHECK: Name: .strtab7# CHECK: Name: .strtab
8# CHECK-NEXT: Type: SHT_STRTAB8# CHECK-NEXT: Type: SHT_STRTAB
deps/lld/test/ELF/relocatable-empty-archive.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: rm -f %t.a2# RUN: rm -f %t.a
3# RUN: llvm-ar rc %t.a3# RUN: llvm-ar rc %t.a
4# RUN: ld.lld -m elf_x86_64 %t.a -o %t -r4# RUN: ld.lld -m elf_x86_64 %t.a -o %t -r
5# RUN: llvm-readobj -file-headers %t | FileCheck %s5# RUN: llvm-readobj --file-headers %t | FileCheck %s
66
7# CHECK: Format: ELF64-x86-647# CHECK: Format: ELF64-x86-64
8# CHECK: Arch: x86_648# CHECK: Arch: x86_64
deps/lld/test/ELF/relocatable-many-sections.s+8-8
...@@ -7,25 +7,25 @@...@@ -7,25 +7,25 @@
77
8## Check we emit a valid ELF header when8## Check we emit a valid ELF header when
9## sections amount is greater than SHN_LORESERVE.9## sections amount is greater than SHN_LORESERVE.
10# RUN: llvm-readobj -file-headers %t | FileCheck %s --check-prefix=HDR10# RUN: llvm-readobj --file-headers %t | FileCheck %s --check-prefix=HDR
11# HDR: ElfHeader {11# HDR: ElfHeader {
12# HDR: SectionHeaderCount: 0 (65544)12# HDR: SectionHeaderCount: 0 (65544)
13# HDR-NEXT: StringTableSectionIndex: 65535 (65542)13# HDR-NEXT: StringTableSectionIndex: 65535 (65542)
1414
15## Check that:15## Check that:
16## 1) 65541 is the index of .shstrtab section.16## 1) 65541 is the index of .shstrtab section.
17## 2) .symtab_shndxr is linked with .symtab.17## 2) .symtab_shndx is linked with .symtab.
18## 3) .symtab_shndxr entry size and alignment == 4.18## 3) .symtab_shndx entry size and alignment == 4.
19## 4) .symtab_shndxr has size equal to19## 4) .symtab_shndx has size equal to
20## (sizeof(.symtab) / entsize(.symtab)) * entsize(.symtab_shndxr) = 0x4 * 0x180048 / 0x18 == 0x04000c20## (sizeof(.symtab) / entsize(.symtab)) * entsize(.symtab_shndx) = 0x4 * 0x180078 / 0x18 == 0x040014
2121
22# RUN: llvm-readelf -sections -symbols %t | FileCheck %s22# RUN: llvm-readelf -sections -symbols %t | FileCheck %s
23# [Nr] Name Type Address Off Size ES Flg Lk Inf Al23# [Nr] Name Type Address Off Size ES Flg Lk Inf Al
24# CHECK: [65539] .note.GNU-stack PROGBITS 0000000000000000 000040 000000 00 0 0 124# CHECK: [65539] .note.GNU-stack PROGBITS 0000000000000000 000040 000000 00 0 0 1
25# CHECK: [65540] .symtab SYMTAB 0000000000000000 000040 180078 18 65543 65539 825# 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 426# CHECK: [65541] .symtab_shndx SYMTAB SECTION INDICES 0000000000000000 1800b8 040014 04 65540 0 4
27# CHECK: [65542] .shstrtab STRTAB 0000000000000000 1c00cc 0f0045 00 0 0 127# CHECK: [65542] .shstrtab STRTAB 0000000000000000 1c00cc 0f0044 00 0 0 1
28# CHECK: [65543] .strtab STRTAB 0000000000000000 2b0111 00000c 00 0 0 128# CHECK: [65543] .strtab STRTAB 0000000000000000 2b0110 00000c 00 0 0 1
2929
30# 5) Check we are able to represent symbol foo with section (.bar) index > 0xFF00 (SHN_LORESERVE).30# 5) Check we are able to represent symbol foo with section (.bar) index > 0xFF00 (SHN_LORESERVE).
31# CHECK: GLOBAL DEFAULT 65538 foo31# CHECK: GLOBAL DEFAULT 65538 foo
deps/lld/test/ELF/relocatable-rel-iplt.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=i686-- %s -o %t1.o2# RUN: llvm-mc -filetype=obj -triple=i686-- %s -o %t1.o
3# RUN: ld.lld -r %t1.o -o %t2.o3# RUN: ld.lld -r %t1.o -o %t2.o
4# RUN: llvm-readobj -t %t2.o | FileCheck %s4# RUN: llvm-readobj --symbols %t2.o | FileCheck %s
55
6// CHECK: Symbols [6// CHECK: Symbols [
7// CHECK-NEXT: Symbol {7// CHECK-NEXT: Symbol {
...@@ -14,7 +14,7 @@...@@ -14,7 +14,7 @@
14// CHECK-NEXT: Section: Undefined (0x0)14// CHECK-NEXT: Section: Undefined (0x0)
15// CHECK-NEXT: }15// CHECK-NEXT: }
16// CHECK-NEXT: Symbol {16// CHECK-NEXT: Symbol {
17// CHECK-NEXT: Name: (0)17// CHECK-NEXT: Name: .text (0)
18// CHECK-NEXT: Value: 0x018// CHECK-NEXT: Value: 0x0
19// CHECK-NEXT: Size: 019// CHECK-NEXT: Size: 0
20// CHECK-NEXT: Binding: Local (0x0)20// CHECK-NEXT: Binding: Local (0x0)
deps/lld/test/ELF/relocatable-script.s+1-1
...@@ -2,6 +2,6 @@...@@ -2,6 +2,6 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %t1.o %s2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux -o %t1.o %s
3# RUN: echo "SECTIONS { .foo : { BYTE(0x0) } }" > %t.script3# RUN: echo "SECTIONS { .foo : { BYTE(0x0) } }" > %t.script
4# RUN: ld.lld -r %t1.o -script %t.script -o %t2.o4# RUN: ld.lld -r %t1.o -script %t.script -o %t2.o
5# RUN: llvm-readobj -sections %t2.o | FileCheck %s5# RUN: llvm-readobj --sections %t2.o | FileCheck %s
66
7# CHECK: Name: .foo7# CHECK: Name: .foo
deps/lld/test/ELF/relocatable-section-symbol.s+1-1
...@@ -13,7 +13,7 @@...@@ -13,7 +13,7 @@
1313
14# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o14# RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
15# RUN: ld.lld -r -o %t %t.o %t.o15# RUN: ld.lld -r -o %t %t.o %t.o
16# RUN: llvm-readobj -r -s -section-data %t | FileCheck --check-prefix=REL %s16# RUN: llvm-readobj -r -S --section-data %t | FileCheck --check-prefix=REL %s
1717
1818
19# REL: Section {19# REL: Section {
deps/lld/test/ELF/relocatable-symbol-name.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -r %t.o -o %t3# RUN: ld.lld -r %t.o -o %t
4# RUN: llvm-readobj -t %t | FileCheck %s4# RUN: llvm-readobj --symbols %t | FileCheck %s
55
6# Test that the section symbol has st_name equal to zero. GNU objdump6# Test that the section symbol has st_name equal to zero. GNU objdump
7# requires this to print relocations against the section.7# requires this to print relocations against the section.
...@@ -17,7 +17,7 @@...@@ -17,7 +17,7 @@
17# CHECK-NEXT: Section:17# CHECK-NEXT: Section:
18# CHECK-NEXT: }18# CHECK-NEXT: }
19# CHECK-NEXT: Symbol {19# CHECK-NEXT: Symbol {
20# CHECK-NEXT: Name: (0)20# CHECK-NEXT: Name: .text (0)
21# CHECK-NEXT: Value:21# CHECK-NEXT: Value:
22# CHECK-NEXT: Size:22# CHECK-NEXT: Size:
23# CHECK-NEXT: Binding:23# CHECK-NEXT: Binding:
deps/lld/test/ELF/relocatable-symbols.s+5-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: ld.lld -r %t -o %tout3# RUN: ld.lld -r %t -o %tout
4# RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s4# RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s
5# RUN: llvm-readobj -r %t | FileCheck -check-prefix=RELOC %s5# RUN: llvm-readobj -r %t | FileCheck -check-prefix=RELOC %s
6# RUN: llvm-readobj -symbols -r %tout | FileCheck -check-prefix=SYMBOL %s6# RUN: llvm-readobj --symbols -r %tout | FileCheck -check-prefix=SYMBOL %s
77
8# DISASM: _start:8# DISASM: _start:
9# DISASM-NEXT: 0: {{.*}} callq 09# DISASM-NEXT: 0: {{.*}} callq 0
...@@ -18,12 +18,16 @@...@@ -18,12 +18,16 @@
18# DISASM-NEXT: 2d: {{.*}} callq 018# DISASM-NEXT: 2d: {{.*}} callq 0
19# DISASM-NEXT: 32: {{.*}} callq 019# DISASM-NEXT: 32: {{.*}} callq 0
20# DISASM-NEXT: 37: {{.*}} callq 020# DISASM-NEXT: 37: {{.*}} callq 0
21# DISASM-EMPTY:
21# DISASM-NEXT: Disassembly of section foo:22# DISASM-NEXT: Disassembly of section foo:
23# DISASM-EMPTY:
22# DISASM-NEXT: foo:24# DISASM-NEXT: foo:
23# DISASM-NEXT: 0: 90 nop25# DISASM-NEXT: 0: 90 nop
24# DISASM-NEXT: 1: 90 nop26# DISASM-NEXT: 1: 90 nop
25# DISASM-NEXT: 2: 90 nop27# DISASM-NEXT: 2: 90 nop
28# DISASM-EMPTY:
26# DISASM-NEXT: Disassembly of section bar:29# DISASM-NEXT: Disassembly of section bar:
30# DISASM-EMPTY:
27# DISASM-NEXT: bar:31# DISASM-NEXT: bar:
28# DISASM-NEXT: 0: 90 nop32# DISASM-NEXT: 0: 90 nop
29# DISASM-NEXT: 1: 90 nop33# DISASM-NEXT: 1: 90 nop
deps/lld/test/ELF/relocatable-visibility.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: ld.lld -r %t.o -o %t13# RUN: ld.lld -r %t.o -o %t1
4# RUN: llvm-readobj -t %t1 | FileCheck --check-prefix=RELOCATABLE %s4# RUN: llvm-readobj --symbols %t1 | FileCheck --check-prefix=RELOCATABLE %s
55
6# RELOCATABLE: Name: foo6# RELOCATABLE: Name: foo
7# RELOCATABLE-NEXT: Value: 0x07# RELOCATABLE-NEXT: Value: 0x0
deps/lld/test/ELF/relocatable.s+5-4
...@@ -3,18 +3,18 @@...@@ -3,18 +3,18 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable.s -o %t2.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable.s -o %t2.o
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable2.s -o %t3.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/relocatable2.s -o %t3.o
5# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t5# RUN: ld.lld -r %t1.o %t2.o %t3.o -o %t
6# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s6# RUN: llvm-readobj --file-headers --sections -l --symbols -r %t | FileCheck %s
7# RUN: llvm-objdump -section-headers %t | FileCheck -check-prefix=SECTION %s7# RUN: llvm-objdump -section-headers %t | FileCheck -check-prefix=SECTION %s
8# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s8# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s
99
10## Test --relocatable alias10## Test --relocatable alias
11# RUN: ld.lld --relocatable %t1.o %t2.o %t3.o -o %t11# RUN: ld.lld --relocatable %t1.o %t2.o %t3.o -o %t
12# RUN: llvm-readobj -file-headers -sections -program-headers -symbols -r %t | FileCheck %s12# RUN: llvm-readobj --file-headers --sections -l --symbols -r %t | FileCheck %s
13# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s13# RUN: llvm-objdump -s -d %t | FileCheck -check-prefix=CHECKTEXT %s
1414
15## Verify that we can use our relocation output as input to produce executable15## Verify that we can use our relocation output as input to produce executable
16# RUN: ld.lld -e main %t -o %texec16# RUN: ld.lld -e main %t -o %texec
17# RUN: llvm-readobj -file-headers %texec | FileCheck -check-prefix=CHECKEXE %s17# RUN: llvm-readobj --file-headers %texec | FileCheck -check-prefix=CHECKEXE %s
1818
19# CHECK: ElfHeader {19# CHECK: ElfHeader {
20# CHECK-NEXT: Ident {20# CHECK-NEXT: Ident {
...@@ -53,7 +53,7 @@...@@ -53,7 +53,7 @@
53# CHECK-NEXT: }53# CHECK-NEXT: }
5454
55# SECTION: Sections:55# SECTION: Sections:
56# SECTION: Idx Name Size Address Type56# SECTION: Idx Name Size VMA Type
57# SECTION: 0 00000000 000000000000000057# SECTION: 0 00000000 0000000000000000
58# SECTION: 1 .text 00000056 0000000000000000 TEXT58# SECTION: 1 .text 00000056 0000000000000000 TEXT
59# SECTION: 2 .rela.text 00000090 000000000000000059# SECTION: 2 .rela.text 00000090 0000000000000000
...@@ -64,6 +64,7 @@...@@ -64,6 +64,7 @@
64# SECTION: 7 .strtab 0000002d 000000000000000064# SECTION: 7 .strtab 0000002d 0000000000000000
6565
66# CHECKTEXT: Disassembly of section .text:66# CHECKTEXT: Disassembly of section .text:
67# CHECKTEXT-EMPTY:
67# CHECKTEXT-NEXT: main:68# CHECKTEXT-NEXT: main:
68# CHECKTEXT-NEXT: 0: c7 04 25 00 00 00 00 05 00 00 00 movl $5, 069# CHECKTEXT-NEXT: 0: c7 04 25 00 00 00 00 05 00 00 00 movl $5, 0
69# CHECKTEXT-NEXT: b: c7 04 25 00 00 00 00 07 00 00 00 movl $7, 070# CHECKTEXT-NEXT: b: c7 04 25 00 00 00 00 07 00 00 00 movl $7, 0
deps/lld/test/ELF/relocation-b-aarch64.test+9-9
...@@ -8,6 +8,7 @@...@@ -8,6 +8,7 @@
8# immediate. We use this property to overwrite instructions with a branch.8# immediate. We use this property to overwrite instructions with a branch.
99
10# CHECK: Disassembly of section .text:10# CHECK: Disassembly of section .text:
11# CHECK-EMPTY:
11# CHECK-NEXT: foo:12# CHECK-NEXT: foo:
12# CHECK-NEXT: 210000: 01 00 00 14 b #413# CHECK-NEXT: 210000: 01 00 00 14 b #4
13# CHECK: bar:14# CHECK: bar:
...@@ -37,12 +38,11 @@ Sections:...@@ -37,12 +38,11 @@ Sections:
37 Type: R_AARCH64_JUMP2638 Type: R_AARCH64_JUMP26
3839
39Symbols:40Symbols:
40 Local:41 - Type: STT_FUNC
41 - Type: STT_FUNC42 Section: .text
42 Section: .text43 Name: foo
43 Name: foo44 Value: 0
44 Value: 045 - Type: STT_FUNC
45 - Type: STT_FUNC46 Section: .text
46 Section: .text47 Name: bar
47 Name: bar48 Value: 4
48 Value: 4
deps/lld/test/ELF/relocation-before-merge-start.s+1-1
...@@ -4,6 +4,6 @@...@@ -4,6 +4,6 @@
4// CHECK: relocation-before-merge-start.s.tmp.o:(.foo): offset is outside the section4// CHECK: relocation-before-merge-start.s.tmp.o:(.foo): offset is outside the section
55
6.data6.data
7.long .foo - 17.quad .foo - 1
8.section .foo,"aM",@progbits,48.section .foo,"aM",@progbits,4
9.quad 09.quad 0
deps/lld/test/ELF/relocation-copy-align-common.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: %p/Inputs/relocation-copy-align-common.s -o %t2.o4# RUN: %p/Inputs/relocation-copy-align-common.s -o %t2.o
5# RUN: ld.lld -shared %t2.o -o %t.so5# RUN: ld.lld -shared %t2.o -o %t.so
6# RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t36# RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t3
7# RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s7# RUN: llvm-readobj -S -r --expand-relocs %t3 | FileCheck %s
88
9# CHECK: Section {9# CHECK: Section {
10# CHECK: Index:10# CHECK: Index:
deps/lld/test/ELF/relocation-copy-align.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy-align.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy-align.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t.so4// RUN: ld.lld -shared %t2.o -o %t.so
5// RUN: ld.lld %t.o %t.so -o %t35// RUN: ld.lld %t.o %t.so -o %t3
6// RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s6// RUN: llvm-readobj -S -r --expand-relocs %t3 | FileCheck %s
77
8.global _start8.global _start
9_start:9_start:
deps/lld/test/ELF/relocation-copy-flags.s+7-7
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
5// RUN: ld.lld %t2.o -o %t2.so -shared5// RUN: ld.lld %t2.o -o %t2.so -shared
6// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t.exe6// RUN: ld.lld --hash-style=sysv %t.o %t2.so -o %t.exe
7// RUN: llvm-readobj -s -section-data -r %t.exe | FileCheck %s7// RUN: llvm-readobj -S --section-data -r %t.exe | FileCheck %s
88
9 .global _start9 .global _start
10_start:10_start:
...@@ -30,7 +30,7 @@ _start:...@@ -30,7 +30,7 @@ _start:
30// CHECK-NEXT: AddressAlignment: 430// CHECK-NEXT: AddressAlignment: 4
31// CHECK-NEXT: EntrySize: 031// CHECK-NEXT: EntrySize: 0
32// CHECK-NEXT: SectionData (32// CHECK-NEXT: SectionData (
33// CHECK-NEXT: 0000: 0040200033// CHECK-NEXT: 0000: 10302000
34// CHECK-NEXT: )34// CHECK-NEXT: )
3535
36// CHECK: Name: bar36// CHECK: Name: bar
...@@ -39,8 +39,8 @@ _start:...@@ -39,8 +39,8 @@ _start:
39// CHECK-NEXT: SHF_ALLOC39// CHECK-NEXT: SHF_ALLOC
40// CHECK-NEXT: SHF_WRITE40// CHECK-NEXT: SHF_WRITE
41// CHECK-NEXT: ]41// CHECK-NEXT: ]
42// CHECK-NEXT: Address: 0x20200042// CHECK-NEXT: Address: 0x203000
43// CHECK-NEXT: Offset: 0x200043// CHECK-NEXT: Offset: 0x3000
44// CHECK-NEXT: Size: 844// CHECK-NEXT: Size: 8
45// CHECK-NEXT: Link: 045// CHECK-NEXT: Link: 0
46// CHECK-NEXT: Info: 046// CHECK-NEXT: Info: 0
...@@ -55,7 +55,7 @@ _start:...@@ -55,7 +55,7 @@ _start:
55// CHECK-NEXT: Flags [55// CHECK-NEXT: Flags [
56// CHECK-NEXT: ]56// CHECK-NEXT: ]
57// CHECK-NEXT: Address: 0x057// CHECK-NEXT: Address: 0x0
58// CHECK-NEXT: Offset: 0x30B058// CHECK-NEXT: Offset: 0x3008
59// CHECK-NEXT: Size: 859// CHECK-NEXT: Size: 8
60// CHECK-NEXT: Link: 060// CHECK-NEXT: Link: 0
61// CHECK-NEXT: Info: 061// CHECK-NEXT: Info: 0
...@@ -67,7 +67,7 @@ _start:...@@ -67,7 +67,7 @@ _start:
6767
68// CHECK: Relocations [68// CHECK: Relocations [
69// CHECK-NEXT: Section (4) .rela.dyn {69// CHECK-NEXT: Section (4) .rela.dyn {
70// CHECK-NEXT: 0x204000 R_X86_64_COPY x 0x070// CHECK-NEXT: 0x203010 R_X86_64_COPY x 0x0
71// CHECK-NEXT: 0x202000 R_X86_64_64 z 0x071// CHECK-NEXT: 0x203000 R_X86_64_64 z 0x0
72// CHECK-NEXT: }72// CHECK-NEXT: }
73// CHECK-NEXT: ]73// CHECK-NEXT: ]
deps/lld/test/ELF/relocation-copy-i686.s+2-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/relocation-copy.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t.so4// RUN: ld.lld -shared %t2.o -o %t.so
5// RUN: ld.lld -e main %t.o %t.so -o %t35// RUN: ld.lld -e main %t.o %t.so -o %t3
6// RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s6// RUN: llvm-readobj -S -r --expand-relocs %t3 | FileCheck %s
7// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s7// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
88
9.text9.text
...@@ -57,6 +57,7 @@ movl $9, z...@@ -57,6 +57,7 @@ movl $9, z
57// 4206608 = 0x403000 + 1657// 4206608 = 0x403000 + 16
58// 4206612 = 0x403000 + 16 + 458// 4206612 = 0x403000 + 16 + 4
59// CODE: Disassembly of section .text:59// CODE: Disassembly of section .text:
60// CODE-EMPTY:
60// CODE-NEXT: main:61// CODE-NEXT: main:
61// CODE-NEXT: 401000: c7 05 00 30 40 00 05 00 00 00 movl $5, 420659262// 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, 420660863// CODE-NEXT: 40100a: c7 05 10 30 40 00 07 00 00 00 movl $7, 4206608
deps/lld/test/ELF/relocation-copy-relro.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy-relro.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy-relro.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t.so4// RUN: ld.lld -shared %t2.o -o %t.so
5// RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t35// RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t3
6// RUN: llvm-readobj -program-headers -s -r %t3 | FileCheck %s6// RUN: llvm-readobj -S -l -r %t3 | FileCheck %s
77
8// CHECK: Name: .bss.rel.ro (48)8// CHECK: Name: .bss.rel.ro (48)
9// CHECK-NEXT: Type: SHT_NOBITS (0x8)9// CHECK-NEXT: Type: SHT_NOBITS (0x8)
deps/lld/test/ELF/relocation-copy.s+2-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/relocation-copy.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t.so4// RUN: ld.lld -shared %t2.o -o %t.so
5// RUN: ld.lld %t.o %t.so -o %t35// RUN: ld.lld %t.o %t.so -o %t3
6// RUN: llvm-readobj -s -r --expand-relocs %t3 | FileCheck %s6// RUN: llvm-readobj -S -r --expand-relocs %t3 | FileCheck %s
7// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s7// RUN: llvm-objdump -d %t3 | FileCheck -check-prefix=CODE %s
88
9.text9.text
...@@ -58,6 +58,7 @@ movl $z, %edx...@@ -58,6 +58,7 @@ movl $z, %edx
58// 2109456 = 0x203000 + 1658// 2109456 = 0x203000 + 16
59// 2109460 = 0x203000 + 16 + 459// 2109460 = 0x203000 + 16 + 4
60// CODE: Disassembly of section .text:60// CODE: Disassembly of section .text:
61// CODE-EMPTY:
61// CODE-NEXT: _start:62// CODE-NEXT: _start:
62// CODE-NEXT: 201000: {{.*}} movl $5, 210944063// CODE-NEXT: 201000: {{.*}} movl $5, 2109440
63// CODE-NEXT: 20100b: {{.*}} movl $7, 210945664// CODE-NEXT: 20100b: {{.*}} movl $7, 2109456
deps/lld/test/ELF/relocation-dtrace.test deleted-24
...@@ -1,24 +0,0 @@
1# RUN: yaml2obj %s -o %t.o
2# RUN: ld.lld -shared %t.o -o /dev/null
3
4# Test that we can handle R_X86_64_NONE as produced by dtrace.
5
6!ELF
7FileHeader:
8 Class: ELFCLASS64
9 Data: ELFDATA2LSB
10 OSABI: ELFOSABI_FREEBSD
11 Type: ET_REL
12 Machine: EM_X86_64
13Sections:
14 - Name: .text
15 Type: SHT_PROGBITS
16 Flags: [ SHF_ALLOC ]
17 - Name: .rela.text
18 Type: SHT_RELA
19 Link: .symtab
20 Info: .text
21 Relocations:
22 - Offset: 0x0000000000000000
23 Symbol: ''
24 Type: R_X86_64_NONE
deps/lld/test/ELF/relocation-group.test+3-3
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj %s -o %t.o1# RUN: yaml2obj %s -o %t.o
2# RUN: ld.lld %t.o %t.o -o %t -r2# RUN: ld.lld %t.o %t.o -o %t -r
3# RUN: llvm-readobj -s %t | FileCheck %s3# RUN: llvm-readobj -S %t | FileCheck %s
44
5# CHECK: Name: .text.foo5# CHECK: Name: .text.foo
6# CHECK: Name: .rela.text.foo6# CHECK: Name: .rela.text.foo
...@@ -39,5 +39,5 @@ Sections:...@@ -39,5 +39,5 @@ Sections:
39 Symbol: foo39 Symbol: foo
40 Type: R_X86_64_6440 Type: R_X86_64_64
41Symbols:41Symbols:
42 Global:42 - Name: foo
43 - Name: foo43 Binding: STB_GLOBAL
deps/lld/test/ELF/relocation-i686.s+17-14
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t2.so4// RUN: ld.lld -shared %t2.o -o %t2.so
5// RUN: ld.lld --hash-style=sysv %t %t2.so -o %t25// RUN: ld.lld --hash-style=sysv %t %t2.so -o %t2
6// RUN: llvm-readobj -s %t2 | FileCheck --check-prefix=ADDR %s6// RUN: llvm-readobj -S %t2 | FileCheck --check-prefix=ADDR %s
7// RUN: llvm-objdump -d %t2 | FileCheck %s7// RUN: llvm-objdump -d %t2 | FileCheck %s
88
9.global _start9.global _start
...@@ -26,10 +26,12 @@ R_386_PC32_2:...@@ -26,10 +26,12 @@ R_386_PC32_2:
26 nop26 nop
2727
28// CHECK: Disassembly of section .R_386_32:28// CHECK: Disassembly of section .R_386_32:
29// CHECK-EMPTY:
29// CHECK-NEXT: R_386_32:30// CHECK-NEXT: R_386_32:
30// CHECK-NEXT: 401000: {{.*}} movl $4198401, %edx31// CHECK-NEXT: 401000: {{.*}} movl $4198401, %edx
3132
32// CHECK: Disassembly of section .R_386_PC32:33// CHECK: Disassembly of section .R_386_PC32:
34// CHECK-EMPTY:
33// CHECK-NEXT: R_386_PC32:35// CHECK-NEXT: R_386_PC32:
34// CHECK-NEXT: 401005: e8 04 00 00 00 calll 436// CHECK-NEXT: 401005: e8 04 00 00 00 calll 4
3537
...@@ -49,30 +51,32 @@ movl bar@GOT, %eax...@@ -49,30 +51,32 @@ movl bar@GOT, %eax
49// ADDR-NEXT: Offset: 0x104051// ADDR-NEXT: Offset: 0x1040
50// ADDR-NEXT: Size: 3252// ADDR-NEXT: Size: 32
5153
52// ADDR: Name: .got (54// ADDR: Name: .got.plt (
53// ADDR-NEXT: Type: SHT_PROGBITS55// ADDR-NEXT: Type: SHT_PROGBITS
54// ADDR-NEXT: Flags [56// ADDR-NEXT: Flags [
55// ADDR-NEXT: SHF_ALLOC57// ADDR-NEXT: SHF_ALLOC
56// ADDR-NEXT: SHF_WRITE58// ADDR-NEXT: SHF_WRITE
57// ADDR-NEXT: ]59// ADDR-NEXT: ]
58// ADDR-NEXT: Address: 0x40307860// ADDR-NEXT: Address: 0x403000
59// ADDR-NEXT: Offset:61// ADDR-NEXT: Offset:
60// ADDR-NEXT: Size: 862// ADDR-NEXT: Size:
6163
62.section .R_386_GOTPC,"ax",@progbits64.section .R_386_GOTPC,"ax",@progbits
63R_386_GOTPC:65R_386_GOTPC:
64 movl $_GLOBAL_OFFSET_TABLE_, %eax66 movl $_GLOBAL_OFFSET_TABLE_, %eax
6567
66// 0x402078 + 8 - 0x401014 = 420468// 0x403000 (.got.plt) - 0x401014 = 8300
6769
68// CHECK: Disassembly of section .R_386_GOTPC:70// CHECK: Disassembly of section .R_386_GOTPC:
71// CHECK-EMPTY:
69// CHECK-NEXT: R_386_GOTPC:72// CHECK-NEXT: R_386_GOTPC:
70// CHECK-NEXT: 401014: {{.*}} movl $8300, %eax73// CHECK-NEXT: 401014: {{.*}} movl $8172, %eax
7174
72.section .dynamic_reloc, "ax",@progbits75.section .dynamic_reloc, "ax",@progbits
73 call bar76 call bar
74// addr(.plt) + 16 - (0x401019 + 5) = 5077// addr(.plt) + 16 - (0x401019 + 5) = 50
75// CHECK: Disassembly of section .dynamic_reloc:78// CHECK: Disassembly of section .dynamic_reloc:
79// CHECK-EMPTY:
76// CHECK-NEXT: .dynamic_reloc:80// CHECK-NEXT: .dynamic_reloc:
77// CHECK-NEXT: 401019: e8 32 00 00 00 calll 5081// CHECK-NEXT: 401019: e8 32 00 00 00 calll 50
7882
...@@ -84,13 +88,12 @@ R_386_GOT32:...@@ -84,13 +88,12 @@ R_386_GOT32:
84 movl bar+8@GOT, %eax88 movl bar+8@GOT, %eax
85 movl zed+4@GOT, %eax89 movl zed+4@GOT, %eax
8690
87// 4294967288 = 0xFFFFFFF8 = got[0](0x402070) - .got(0x402070) - sizeof(.got)(8)91// 4294963320 = 0xfffff078 = got[0](0x402078) - .got.plt(0x403000)
88// 4294967292 = 0xFFFFFFFC = got[1](0x402074) - .got(0x402070) - sizeof(.got)(8)92// 4294963324 = 0xfffff07c = got[1](0x40207c) - .got(0x403000)
89// 0xFFFFFFF8 + 8 = 0
90// 0xFFFFFFFC + 4 = 0
91// CHECK: Disassembly of section .R_386_GOT32:93// CHECK: Disassembly of section .R_386_GOT32:
94// CHECK-EMPTY:
92// CHECK-NEXT: R_386_GOT32:95// CHECK-NEXT: R_386_GOT32:
93// CHECK-NEXT: 40101e: a1 f8 ff ff ff movl 4294967288, %eax96// CHECK-NEXT: 40101e: a1 78 f0 ff ff movl 4294963320, %eax
94// CHECK-NEXT: 401023: a1 fc ff ff ff movl 4294967292, %eax97// CHECK-NEXT: 401023: a1 7c f0 ff ff movl 4294963324, %eax
95// CHECK-NEXT: 401028: a1 00 00 00 00 movl 0, %eax98// CHECK-NEXT: 401028: a1 80 f0 ff ff movl 4294963328, %eax
96// CHECK-NEXT: 40102d: a1 00 00 00 00 movl 0, %eax99// CHECK-NEXT: 40102d: a1 80 f0 ff ff movl 4294963328, %eax
deps/lld/test/ELF/relocation-local.s+2
...@@ -19,6 +19,7 @@ R_X86_64_32:...@@ -19,6 +19,7 @@ R_X86_64_32:
19// FIXME: this would be far more self evident if llvm-objdump printed19// FIXME: this would be far more self evident if llvm-objdump printed
20// constants in hex.20// constants in hex.
21// CHECK: Disassembly of section .text2:21// CHECK: Disassembly of section .text2:
22// CHECK-EMPTY:
22// CHECK-NEXT: R_X86_64_32:23// CHECK-NEXT: R_X86_64_32:
23// CHECK-NEXT: 201009: {{.*}} movl $2101257, %edx24// CHECK-NEXT: 201009: {{.*}} movl $2101257, %edx
2425
...@@ -27,6 +28,7 @@ R_X86_64_32S:...@@ -27,6 +28,7 @@ R_X86_64_32S:
27 movq lulz - 0x100000, %rdx28 movq lulz - 0x100000, %rdx
2829
29// CHECK: Disassembly of section .R_X86_64_32S:30// CHECK: Disassembly of section .R_X86_64_32S:
31// CHECK-EMPTY:
30// CHECK-NEXT: R_X86_64_32S:32// CHECK-NEXT: R_X86_64_32S:
31// CHECK-NEXT: {{.*}}: {{.*}} movq 1052681, %rdx33// CHECK-NEXT: {{.*}}: {{.*}} movq 1052681, %rdx
3234
deps/lld/test/ELF/relocation-non-alloc.s+12-12
...@@ -2,12 +2,12 @@...@@ -2,12 +2,12 @@
22
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
4// RUN: ld.lld %t -o %t2 -shared --apply-dynamic-relocs4// RUN: ld.lld %t -o %t2 -shared --apply-dynamic-relocs
5// RUN: llvm-readobj -s -section-data -r %t2 | FileCheck -check-prefix CHECK -check-prefix APPLYDYNREL %s5// RUN: llvm-readobj -S --section-data -r %t2 | FileCheck -check-prefix CHECK -check-prefix APPLYDYNREL %s
66
7// RUN: ld.lld %t -o %t2 -shared7// RUN: ld.lld %t -o %t2 -shared
8// RUN: llvm-readobj -s -section-data -r %t2 | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s8// RUN: llvm-readobj -S --section-data -r %t2 | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s
9// RUN: ld.lld %t -o %t2 -shared --no-apply-dynamic-relocs9// RUN: ld.lld %t -o %t2 -shared --no-apply-dynamic-relocs
10// RUN: llvm-readobj -s -section-data -r %t2 | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s10// RUN: llvm-readobj -S --section-data -r %t2 | FileCheck -check-prefix CHECK -check-prefix NOAPPLYDYNREL %s
1111
12// APPLYDYNREL: Name: .data12// APPLYDYNREL: Name: .data
13// APPLYDYNREL-NEXT: Type: SHT_PROGBITS13// APPLYDYNREL-NEXT: Type: SHT_PROGBITS
...@@ -15,15 +15,15 @@...@@ -15,15 +15,15 @@
15// APPLYDYNREL-NEXT: SHF_ALLOC15// APPLYDYNREL-NEXT: SHF_ALLOC
16// APPLYDYNREL-NEXT: SHF_WRITE16// APPLYDYNREL-NEXT: SHF_WRITE
17// APPLYDYNREL-NEXT: ]17// APPLYDYNREL-NEXT: ]
18// APPLYDYNREL-NEXT: Address: 0x100018// APPLYDYNREL-NEXT: Address: 0x2000
19// APPLYDYNREL-NEXT: Offset: 0x100019// APPLYDYNREL-NEXT: Offset: 0x2000
20// APPLYDYNREL-NEXT: Size: 1620// APPLYDYNREL-NEXT: Size: 16
21// APPLYDYNREL-NEXT: Link: 021// APPLYDYNREL-NEXT: Link: 0
22// APPLYDYNREL-NEXT: Info: 022// APPLYDYNREL-NEXT: Info: 0
23// APPLYDYNREL-NEXT: AddressAlignment: 123// APPLYDYNREL-NEXT: AddressAlignment: 1
24// APPLYDYNREL-NEXT: EntrySize: 024// APPLYDYNREL-NEXT: EntrySize: 0
25// APPLYDYNREL-NEXT: SectionData (25// APPLYDYNREL-NEXT: SectionData (
26// APPLYDYNREL-NEXT: 0000: 00100000 00000000 00000000 0000000026// APPLYDYNREL-NEXT: 0000: 00200000 00000000 00000000 00000000
27// APPLYDYNREL-NEXT: )27// APPLYDYNREL-NEXT: )
2828
29// NOAPPLYDYNREL: Name: .data29// NOAPPLYDYNREL: Name: .data
...@@ -32,8 +32,8 @@...@@ -32,8 +32,8 @@
32// NOAPPLYDYNREL-NEXT: SHF_ALLOC32// NOAPPLYDYNREL-NEXT: SHF_ALLOC
33// NOAPPLYDYNREL-NEXT: SHF_WRITE33// NOAPPLYDYNREL-NEXT: SHF_WRITE
34// NOAPPLYDYNREL-NEXT: ]34// NOAPPLYDYNREL-NEXT: ]
35// NOAPPLYDYNREL-NEXT: Address: 0x100035// NOAPPLYDYNREL-NEXT: Address: 0x2000
36// NOAPPLYDYNREL-NEXT: Offset: 0x100036// NOAPPLYDYNREL-NEXT: Offset: 0x2000
37// NOAPPLYDYNREL-NEXT: Size: 1637// NOAPPLYDYNREL-NEXT: Size: 16
38// NOAPPLYDYNREL-NEXT: Link: 038// NOAPPLYDYNREL-NEXT: Link: 0
39// NOAPPLYDYNREL-NEXT: Info: 039// NOAPPLYDYNREL-NEXT: Info: 0
...@@ -55,14 +55,14 @@...@@ -55,14 +55,14 @@
55// CHECK-NEXT: AddressAlignment: 155// CHECK-NEXT: AddressAlignment: 1
56// CHECK-NEXT: EntrySize: 056// CHECK-NEXT: EntrySize: 0
57// CHECK-NEXT: SectionData (57// CHECK-NEXT: SectionData (
58// CHECK-NEXT: 0000: 00100000 00000000 00100000 0000000058// CHECK-NEXT: 0000: 00200000 00000000 00200000 00000000
59// CHECK-NEXT: 0010: 00100000 00000000 00100000 0000000059// CHECK-NEXT: 0010: 00200000 00000000 00200000 00000000
60// CHECK-NEXT: )60// CHECK-NEXT: )
6161
62// CHECK: Relocations [62// CHECK: Relocations [
63// CHECK-NEXT: Section ({{.}}) .rela.dyn {63// CHECK-NEXT: Section ({{.}}) .rela.dyn {
64// CHECK-NEXT: 0x1000 R_X86_64_RELATIVE - 0x100064// CHECK-NEXT: 0x2000 R_X86_64_RELATIVE - 0x2000
65// CHECK-NEXT: 0x1008 R_X86_64_64 zed 0x065// CHECK-NEXT: 0x2008 R_X86_64_64 zed 0x0
66// CHECK-NEXT: }66// CHECK-NEXT: }
67// CHECK-NEXT: ]67// CHECK-NEXT: ]
6868
deps/lld/test/ELF/relocation-none-aarch64.s created+26
...@@ -0,0 +1,26 @@
1# REQUIRES: aarch64
2
3# RUN: llvm-mc -filetype=obj -triple=aarch64-linux-musl %s -o %t.o
4# RUN: ld.lld --gc-sections %t.o -o %t
5# RUN: llvm-readelf -S -r %t | FileCheck %s
6
7# Test that we discard R_AARCH64_NONE, but respect the references it creates
8# among sections.
9
10# CHECK: .data
11# CHECK: There are no relocations in this file.
12
13# RUN: ld.lld -r %t.o -o %t
14# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
15
16# RELOC: Section ({{.*}}) .rela.text {
17# RELOC-NEXT: 0x0 R_AARCH64_NONE .data 0x0
18# RELOC-NEXT: }
19
20.globl _start
21_start:
22 ret
23 .reloc 0, R_AARCH64_NONE, .data
24
25.data
26 .long 0
deps/lld/test/ELF/relocation-none-aarch64.test deleted-24
...@@ -1,24 +0,0 @@
1# REQUIRES: aarch64
2
3# RUN: yaml2obj %s -o %t.o
4# RUN: ld.lld %t.o -o /dev/null
5
6!ELF
7FileHeader:
8 Class: ELFCLASS64
9 Data: ELFDATA2LSB
10 Type: ET_REL
11 Machine: EM_AARCH64
12Sections:
13 - Type: SHT_PROGBITS
14 Name: .text
15 Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
16 Content: "00000000"
17 - Type: SHT_RELA
18 Name: .rela.text
19 Link: .symtab
20 Info: .text
21 Relocations:
22 - Offset: 0
23 Symbol: ''
24 Type: R_AARCH64_NONE
deps/lld/test/ELF/relocation-none-arm.s created+26
...@@ -0,0 +1,26 @@
1# REQUIRES: arm
2
3# RUN: llvm-mc -filetype=obj -triple=armv7-linux-musl %s -o %t.o
4# RUN: ld.lld --gc-sections %t.o -o %t
5# RUN: llvm-readelf -S -r %t | FileCheck %s
6
7# Test that we discard R_ARM_NONE, but respect the references it creates among
8# sections.
9
10# CHECK: .data
11# CHECK: There are no relocations in this file.
12
13# RUN: ld.lld -r %t.o -o %t
14# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
15
16# RELOC: Section ({{.*}}) .rel.text {
17# RELOC-NEXT: 0x0 R_ARM_NONE .data 0x0
18# RELOC-NEXT: }
19
20.globl _start
21_start:
22 nop
23 .reloc 0, R_ARM_NONE, .data
24
25.data
26 .long 0
deps/lld/test/ELF/relocation-none-i386.s created+26
...@@ -0,0 +1,26 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=i386-linux-musl %s -o %t.o
4# RUN: ld.lld --gc-sections %t.o -o %t
5# RUN: llvm-readelf -S -r %t | FileCheck %s
6
7# Test that we discard R_386_NONE, but respect the
8# references it creates among sections.
9
10# CHECK: .data
11# CHECK: There are no relocations in this file.
12
13# RUN: ld.lld -r %t.o -o %t
14# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
15
16# RELOC: Section ({{.*}}) .rel.text {
17# RELOC-NEXT: 0x0 R_386_NONE .data 0x0
18# RELOC-NEXT: }
19
20.globl _start
21_start:
22 ret
23 .reloc 0, R_386_NONE, .data
24
25.data
26 .long 0
deps/lld/test/ELF/relocation-none-i686.test deleted-23
...@@ -1,23 +0,0 @@
1# RUN: yaml2obj %s -o %t.o
2# RUN: ld.lld %t.o -o /dev/null
3
4# Test that we can handle R_386_NONE.
5
6!ELF
7FileHeader:
8 Class: ELFCLASS32
9 Data: ELFDATA2LSB
10 Type: ET_REL
11 Machine: EM_386
12Sections:
13 - Name: .text
14 Type: SHT_PROGBITS
15 Flags: [ SHF_ALLOC ]
16 - Name: .rel.text
17 Type: SHT_RELA
18 Link: .symtab
19 Info: .text
20 Relocations:
21 - Offset: 0x0000000000000000
22 Symbol: ''
23 Type: R_386_NONE
deps/lld/test/ELF/relocation-none-x86-64.s created+26
...@@ -0,0 +1,26 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64-linux-musl %s -o %t.o
4# RUN: ld.lld --gc-sections %t.o -o %t
5# RUN: llvm-readelf -S -r %t | FileCheck %s
6
7# Test that we discard R_X86_64_NONE, but respect the
8# references it creates among sections.
9
10# CHECK: .data
11# CHECK: There are no relocations in this file.
12
13# RUN: ld.lld -r %t.o -o %t
14# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
15
16# RELOC: Section ({{.*}}) .rela.text {
17# RELOC-NEXT: 0x0 R_X86_64_NONE .data 0x0
18# RELOC-NEXT: }
19
20.globl _start
21_start:
22 ret
23 .reloc 0, R_X86_64_NONE, .data
24
25.data
26 .long 0
deps/lld/test/ELF/relocation-past-merge-end.s+1-1
...@@ -4,6 +4,6 @@...@@ -4,6 +4,6 @@
4// CHECK: relocation-past-merge-end.s.tmp.o:(.foo): offset is outside the section4// CHECK: relocation-past-merge-end.s.tmp.o:(.foo): offset is outside the section
55
6.data6.data
7.long .foo + 107.quad .foo + 10
8.section .foo,"aM",@progbits,48.section .foo,"aM",@progbits,4
9.quad 09.quad 0
deps/lld/test/ELF/relocation-relative-synthetic.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t -pie3# RUN: ld.lld %t.o -o %t -pie
4# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s4# RUN: llvm-readobj --dyn-relocations %t | FileCheck %s
55
6# CHECK: Dynamic Relocations {6# CHECK: Dynamic Relocations {
7# CHECK-NEXT: }7# CHECK-NEXT: }
deps/lld/test/ELF/relocation-relative-weak.s+5-3
...@@ -1,10 +1,12 @@...@@ -1,10 +1,12 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/dummy-shared.s -o %t1.o
3# RUN: ld.lld %t1.o -shared -o %t1.so
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t -pie5# RUN: ld.lld %t.o %t1.so -o %t -pie
4# RUN: llvm-readobj -dyn-relocations %t | FileCheck %s6# RUN: llvm-readobj --dyn-relocations %t | FileCheck %s
57
6# CHECK: Dynamic Relocations {8# CHECK: Dynamic Relocations {
7# CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT w 0x09# CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT w 0x0
8# CHECK-NEXT: }10# CHECK-NEXT: }
911
10.globl _start12.globl _start
deps/lld/test/ELF/relocation-shared.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -shared -o %t.so3// RUN: ld.lld %t.o -shared -o %t.so
4// RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s4// RUN: llvm-readobj -r -S --section-data %t.so | FileCheck %s
55
6// CHECK: Name: foo6// CHECK: Name: foo
7// CHECK-NEXT: Type: SHT_PROGBITS7// CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/relocation-size-shared.s+1
...@@ -18,6 +18,7 @@...@@ -18,6 +18,7 @@
18// RELOCSHARED-NEXT:]18// RELOCSHARED-NEXT:]
1919
20// DISASM: Disassembly of section test20// DISASM: Disassembly of section test
21// DISASM-EMPTY:
21// DISASM: _data:22// DISASM: _data:
22// DISASM-NEXT: 201000: 19 0023// DISASM-NEXT: 201000: 19 00
23// DISASM-NEXT: 201002: 00 0024// DISASM-NEXT: 201002: 00 00
deps/lld/test/ELF/relocation-size.s+2
...@@ -11,6 +11,7 @@...@@ -11,6 +11,7 @@
11// NORELOC-NEXT: ]11// NORELOC-NEXT: ]
1212
13// DISASM: Disassembly of section test:13// DISASM: Disassembly of section test:
14// DISASM-EMPTY:
14// DISASM-NEXT: _data:15// DISASM-NEXT: _data:
15// DISASM-NEXT: 201000: 19 0016// DISASM-NEXT: 201000: 19 00
16// DISASM-NEXT: 201002: 00 0017// DISASM-NEXT: 201002: 00 00
...@@ -56,6 +57,7 @@...@@ -56,6 +57,7 @@
56// RELOCSHARED-NEXT: ]57// RELOCSHARED-NEXT: ]
5758
58// DISASMSHARED: Disassembly of section test:59// DISASMSHARED: Disassembly of section test:
60// DISASMSHARED-EMPTY:
59// DISASMSHARED-NEXT: _data:61// DISASMSHARED-NEXT: _data:
60// DISASMSHARED-NEXT: ...62// DISASMSHARED-NEXT: ...
61// DISASMSHARED-NEXT: 1018: 19 0063// DISASMSHARED-NEXT: 1018: 19 00
deps/lld/test/ELF/relocation-undefined-weak.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
3// RUN: ld.lld %t -o %tout3// RUN: ld.lld %t -o %tout
4// RUN: llvm-readobj -sections %tout | FileCheck %s4// RUN: llvm-readobj --sections %tout | FileCheck %s
5// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix DISASM5// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix DISASM
66
7// Check that undefined weak symbols are treated as having a VA of 0.7// Check that undefined weak symbols are treated as having a VA of 0.
deps/lld/test/ELF/relocation.s+21-16
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t23// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/shared.s -o %t2
4// RUN: ld.lld %t2 -soname fixed-length-string.so -o %t2.so -shared4// RUN: ld.lld %t2 -soname fixed-length-string.so -o %t2.so -shared
5// RUN: ld.lld --hash-style=sysv %t %t2.so -o %t35// RUN: ld.lld --hash-style=sysv %t %t2.so -o %t3
6// RUN: llvm-readobj -s %t3 | FileCheck --check-prefix=SEC %s6// RUN: llvm-readobj -S %t3 | FileCheck --check-prefix=SEC %s
7// RUN: llvm-objdump -s -d %t3 | FileCheck %s7// RUN: llvm-objdump -s -d %t3 | FileCheck %s
88
9// SEC: Name: .plt9// SEC: Name: .plt
...@@ -16,35 +16,35 @@...@@ -16,35 +16,35 @@
16// SEC-NEXT: Offset: 0x103016// SEC-NEXT: Offset: 0x1030
17// SEC-NEXT: Size: 4817// SEC-NEXT: Size: 48
1818
19// SEC: Name: .got.plt19// SEC: Name: .got
20// SEC-NEXT: Type: SHT_PROGBITS20// SEC-NEXT: Type: SHT_PROGBITS
21// SEC-NEXT: Flags [21// SEC-NEXT: Flags [
22// SEC-NEXT: SHF_ALLOC22// SEC-NEXT: SHF_ALLOC
23// SEC-NEXT: SHF_WRITE23// SEC-NEXT: SHF_WRITE
24// SEC-NEXT: ]24// SEC-NEXT: ]
25// SEC-NEXT: Address: 0x20200025// SEC-NEXT: Address: 0x2020F0
26// SEC-NEXT: Offset: 0x200026// SEC-NEXT: Offset:
27// SEC-NEXT: Size: 4027// SEC-NEXT: Size: 8
28// SEC-NEXT: Link: 028// SEC-NEXT: Link: 0
29// SEC-NEXT: Info: 029// SEC-NEXT: Info: 0
30// SEC-NEXT: AddressAlignment: 830// SEC-NEXT: AddressAlignment: 8
31// SEC-NEXT: EntrySize: 031// SEC-NEXT: EntrySize: 0
32// SEC-NEXT: }32// SEC-NEXT: }
3333
34// SEC: Name: .got34// SEC: Name: .got.plt
35// SEC-NEXT: Type: SHT_PROGBITS35// SEC-NEXT: Type: SHT_PROGBITS
36// SEC-NEXT: Flags [36// SEC-NEXT: Flags [
37// SEC-NEXT: SHF_ALLOC37// SEC-NEXT: SHF_ALLOC
38// SEC-NEXT: SHF_WRITE38// SEC-NEXT: SHF_WRITE
39// SEC-NEXT: ]39// SEC-NEXT: ]
40// SEC-NEXT: Address: 0x2030F040// SEC-NEXT: Address: 0x203000
41// SEC-NEXT: Offset:41// SEC-NEXT: Offset: 0x3000
42// SEC-NEXT: Size: 842// SEC-NEXT: Size: 40
43// SEC-NEXT: Link: 043// SEC-NEXT: Link: 0
44// SEC-NEXT: Info: 044// SEC-NEXT: Info: 0
45// SEC-NEXT: AddressAlignment: 845// SEC-NEXT: AddressAlignment: 8
46// SEC-NEXT: EntrySize: 046// SEC-NEXT: EntrySize: 0
47// SEC-NEXT: }47// SEC-NEXT: }
4848
49.section .text,"ax",@progbits,unique,149.section .text,"ax",@progbits,unique,1
50.global _start50.global _start
...@@ -58,6 +58,7 @@ lulz:...@@ -58,6 +58,7 @@ lulz:
58 nop58 nop
5959
60// CHECK: Disassembly of section .text:60// CHECK: Disassembly of section .text:
61// CHECK-EMPTY:
61// CHECK-NEXT: _start:62// CHECK-NEXT: _start:
62// CHECK-NEXT: 201000: e8 04 00 00 00 callq 463// CHECK-NEXT: 201000: e8 04 00 00 00 callq 4
63// CHECK-NEXT: 201005:64// CHECK-NEXT: 201005:
...@@ -74,6 +75,7 @@ R_X86_64_32:...@@ -74,6 +75,7 @@ R_X86_64_32:
74// FIXME: this would be far more self evident if llvm-objdump printed75// FIXME: this would be far more self evident if llvm-objdump printed
75// constants in hex.76// constants in hex.
76// CHECK: Disassembly of section .text2:77// CHECK: Disassembly of section .text2:
78// CHECK-EMPTY:
77// CHECK-NEXT: R_X86_64_32:79// CHECK-NEXT: R_X86_64_32:
78// CHECK-NEXT: 20100a: {{.*}} movl $2101258, %edx80// CHECK-NEXT: 20100a: {{.*}} movl $2101258, %edx
7981
...@@ -83,6 +85,7 @@ R_X86_64_32S:...@@ -83,6 +85,7 @@ R_X86_64_32S:
83 movq lulz - 0x100000, %rdx85 movq lulz - 0x100000, %rdx
8486
85// CHECK: Disassembly of section .R_X86_64_32S:87// CHECK: Disassembly of section .R_X86_64_32S:
88// CHECK-EMPTY:
86// CHECK-NEXT: R_X86_64_32S:89// CHECK-NEXT: R_X86_64_32S:
87// CHECK-NEXT: {{.*}}: {{.*}} movq 1052681, %rdx90// CHECK-NEXT: {{.*}}: {{.*}} movq 1052681, %rdx
8891
...@@ -94,6 +97,7 @@ R_X86_64_PC32:...@@ -94,6 +97,7 @@ R_X86_64_PC32:
94//16 is a size of PLT[0]97//16 is a size of PLT[0]
95// 0x201030 + 16 - (0x201017 + 5) = 2098// 0x201030 + 16 - (0x201017 + 5) = 20
96// CHECK: Disassembly of section .R_X86_64_PC32:99// CHECK: Disassembly of section .R_X86_64_PC32:
100// CHECK-EMPTY:
97// CHECK-NEXT: R_X86_64_PC32:101// CHECK-NEXT: R_X86_64_PC32:
98// CHECK-NEXT: 201017: {{.*}} callq 36102// CHECK-NEXT: 201017: {{.*}} callq 36
99// CHECK-NEXT: 20101c: {{.*}} movl $2101312, %eax103// CHECK-NEXT: 20101c: {{.*}} movl $2101312, %eax
...@@ -104,6 +108,7 @@ R_X86_64_32S_2:...@@ -104,6 +108,7 @@ R_X86_64_32S_2:
104 mov bar2, %eax108 mov bar2, %eax
105// plt is at 0x201030. The second plt entry is at 0x201050 == 69712109// plt is at 0x201030. The second plt entry is at 0x201050 == 69712
106// CHECK: Disassembly of section .R_X86_64_32S_2:110// CHECK: Disassembly of section .R_X86_64_32S_2:
111// CHECK-EMPTY:
107// CHECK-NEXT: R_X86_64_32S_2:112// CHECK-NEXT: R_X86_64_32S_2:
108// CHECK-NEXT: 201021: {{.*}} movl 2101328, %eax113// CHECK-NEXT: 201021: {{.*}} movl 2101328, %eax
109114
...@@ -113,16 +118,16 @@ R_X86_64_64:...@@ -113,16 +118,16 @@ R_X86_64_64:
113 .quad R_X86_64_64118 .quad R_X86_64_64
114119
115// CHECK: Contents of section .R_X86_64_64:120// CHECK: Contents of section .R_X86_64_64:
116// CHECK-NEXT: 2002c0 c0022000 00000000121// CHECK-NEXT: 2002f8 f8022000 00000000
117122
118.section .R_X86_64_GOTPCREL,"a",@progbits123.section .R_X86_64_GOTPCREL,"a",@progbits
119.global R_X86_64_GOTPCREL124.global R_X86_64_GOTPCREL
120R_X86_64_GOTPCREL:125R_X86_64_GOTPCREL:
121 .long zed@gotpcrel126 .long zed@gotpcrel
122127
123// 0x2030F0(.got) - 0x2002c8(.R_X86_64_GOTPCREL) = 0x2e28128// 0x2020F0(.got) - 0x2002c8(.R_X86_64_GOTPCREL) = 0x1e28
124// CHECK: Contents of section .R_X86_64_GOTPCREL129// CHECK: Contents of section .R_X86_64_GOTPCREL
125// CHECK-NEXT: 2002c8 282e0000130// CHECK-NEXT: 200300 f01d0000
126131
127.section .R_X86_64_GOT32,"a",@progbits132.section .R_X86_64_GOT32,"a",@progbits
128.global R_X86_64_GOT32133.global R_X86_64_GOT32
...@@ -130,11 +135,11 @@ R_X86_64_GOT32:...@@ -130,11 +135,11 @@ R_X86_64_GOT32:
130 .long zed@got135 .long zed@got
131136
132// CHECK: Contents of section .R_X86_64_GOT32:137// CHECK: Contents of section .R_X86_64_GOT32:
133// CHECK-NEXT: f8ffffff138// CHECK-NEXT: f0f0ffff
134139
135140
136// CHECK: Contents of section .R_X86_64_GOT64:141// CHECK: Contents of section .R_X86_64_GOT64:
137// CHECK-NEXT: f8ffffff ffffffff142// CHECK-NEXT: f0f0ffff ffffffff
138.section .R_X86_64_GOT64,"a",@progbits143.section .R_X86_64_GOT64,"a",@progbits
139.global R_X86_64_GOT64144.global R_X86_64_GOT64
140R_X86_64_GOT64:145R_X86_64_GOT64:
deps/lld/test/ELF/relro-bss.s created+44
...@@ -0,0 +1,44 @@
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-readelf -l %t | FileCheck --check-prefix=SEG %s
5# RUN: llvm-readelf -S %t | FileCheck %s
6
7# We have 2 RW PT_LOAD segments. p_offset p_vaddr p_paddr p_filesz of the first
8# should match PT_GNU_RELRO.
9# Because .bss.rel.ro (nobits) doesn't take space, p_filesz < p_memsz.
10
11# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
12# SEG: LOAD 0x001000 0x0000000000201000 0x0000000000201000 0x000001 0x000001 R E 0x1000
13# SEG-NEXT: LOAD 0x002000 0x0000000000202000 0x0000000000202000 0x000001 0x002001 RW 0x1000
14# SEG-NEXT: LOAD 0x003000 0x0000000000205000 0x0000000000205000 0x000001 0x000002 RW 0x1000
15# SEG-NEXT: GNU_RELRO 0x002000 0x0000000000202000 0x0000000000202000 0x000001 0x003000 R 0x1
16# SEG-NEXT: GNU_STACK 0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW 0x0
17
18# SEG: .text
19# SEG-NEXT: .data.rel.ro .bss.rel.ro
20# SEG-NEXT: .data .bss
21
22# And .data is placed in the next page (sh_offset = alignTo(0x2001, 4096) = 0x3000).
23
24# [Nr] Name Type Address Off Size
25# CHECK: .data.rel.ro PROGBITS 0000000000202000 002000 000001
26# CHECK-NEXT: .bss.rel.ro NOBITS 0000000000202001 002001 002000
27# CHECK-NEXT: .data PROGBITS 0000000000205000 003000 000001
28# CHECK-NEXT: .bss NOBITS 0000000000205001 003001 000001
29
30.globl _start
31_start:
32 ret
33
34.section .data.rel.ro, "aw"
35.space 1
36
37.section .bss.rel.ro, "aw", @nobits
38.space 8192
39
40.section .data, "aw"
41.space 1
42
43.section .bss, "aw"
44.space 1
deps/lld/test/ELF/relro-non-contiguous.s+3-3
...@@ -3,12 +3,12 @@...@@ -3,12 +3,12 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/copy-in-shared.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/copy-in-shared.s -o %t2.o
4// RUN: ld.lld -shared %t.o %t2.o -o %t.so4// RUN: ld.lld -shared %t.o %t2.o -o %t.so
55
6// Place the .got.plt (non relro) immediately after .dynamic. This is the6// Separate RelRo sections .dynamic .bss.rel.ro with non RelRo .got.plt.
7// reverse order of the non-linker script case. The linker created .bss.rel.ro7// This causes the RelRo sections to be non-contiguous.
8// section will be placed after .got.plt causing the relro to be non-contiguous.
9// RUN: echo "SECTIONS { \8// RUN: echo "SECTIONS { \
10// RUN: .dynamic : { *(.dynamic) } \9// RUN: .dynamic : { *(.dynamic) } \
11// RUN: .got.plt : { *(.got.plt) } \10// RUN: .got.plt : { *(.got.plt) } \
11// RUN: .bss.rel.ro : { *(.bss.rel.o) } \
12// RUN: } " > %t.script12// RUN: } " > %t.script
13// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3.o13// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t3.o
1414
deps/lld/test/ELF/relro-omagic.s+2-2
...@@ -2,12 +2,12 @@...@@ -2,12 +2,12 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2# 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/shared.s -o %t2.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/shared.s -o %t2.o
4# RUN: ld.lld -shared %t2.o -o %t2.so -soname relro-omagic.s.tmp2.so4# RUN: ld.lld -shared %t2.o -o %t2.so -soname relro-omagic.s.tmp2.so
5# RUN: ld.lld --hash-style=sysv -N %t.o %t2.so -o %t5# RUN: ld.lld --hash-style=sysv -N %t.o -Bdynamic %t2.so -o %t
6# RUN: llvm-objdump -section-headers %t | FileCheck --check-prefix=NORELRO %s6# RUN: llvm-objdump -section-headers %t | FileCheck --check-prefix=NORELRO %s
7# RUN: llvm-readobj --program-headers %t | FileCheck --check-prefix=NOPHDRS %s7# RUN: llvm-readobj --program-headers %t | FileCheck --check-prefix=NOPHDRS %s
88
9# NORELRO: Sections:9# NORELRO: Sections:
10# NORELRO-NEXT: Idx Name Size Address Type10# NORELRO-NEXT: Idx Name Size VMA Type
11# NORELRO-NEXT: 0 00000000 000000000000000011# NORELRO-NEXT: 0 00000000 0000000000000000
12# NORELRO-NEXT: 1 .dynsym 00000048 000000000020012012# NORELRO-NEXT: 1 .dynsym 00000048 0000000000200120
13# NORELRO-NEXT: 2 .hash 00000020 000000000020016813# NORELRO-NEXT: 2 .hash 00000020 0000000000200168
deps/lld/test/ELF/relro-tls.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %tout3// RUN: ld.lld %t -o %tout
4// RUN: llvm-readobj -program-headers %tout | FileCheck %s4// RUN: llvm-readobj -l %tout | FileCheck %s
55
6// CHECK: Type: PT_GNU_RELRO6// CHECK: Type: PT_GNU_RELRO
7// CHECK-NEXT: Offset:7// CHECK-NEXT: Offset:
deps/lld/test/ELF/relro.s+6-5
...@@ -5,13 +5,13 @@...@@ -5,13 +5,13 @@
5// RUN: ld.lld -shared %t2.o -o %t2.so5// RUN: ld.lld -shared %t2.o -o %t2.so
66
7// RUN: ld.lld %t.o %t2.so -z now -z norelro -z relro -o %t7// RUN: ld.lld %t.o %t2.so -z now -z norelro -z relro -o %t
8// RUN: llvm-readobj -l --elf-output-style=GNU %t | FileCheck --check-prefix=CHECK --check-prefix=FULLRELRO %s8// RUN: llvm-readelf -l %t | FileCheck --check-prefix=CHECK --check-prefix=FULLRELRO %s
99
10// RUN: ld.lld %t.o %t2.so -z norelro -z relro -o %t10// RUN: ld.lld %t.o %t2.so -z norelro -z relro -o %t
11// RUN: llvm-readobj -l --elf-output-style=GNU %t | FileCheck --check-prefix=CHECK --check-prefix=PARTRELRO %s11// RUN: llvm-readelf -l %t | FileCheck --check-prefix=CHECK --check-prefix=PARTRELRO %s
1212
13// RUN: ld.lld %t.o %t2.so -z norelro -o %t13// RUN: ld.lld %t.o %t2.so -z norelro -o %t
14// RUN: llvm-readobj -l --elf-output-style=GNU %t | FileCheck --check-prefix=NORELRO %s14// RUN: llvm-readelf -l %t | FileCheck --check-prefix=NORELRO %s
1515
16// CHECK: Program Headers:16// CHECK: Program Headers:
17// CHECK-NEXT: Type17// CHECK-NEXT: Type
...@@ -19,12 +19,13 @@...@@ -19,12 +19,13 @@
19// CHECK-NEXT: LOAD19// CHECK-NEXT: LOAD
20// CHECK-NEXT: LOAD20// CHECK-NEXT: LOAD
21// CHECK-NEXT: LOAD21// CHECK-NEXT: LOAD
22// CHECK-NEXT: LOAD
22// CHECK-NEXT: DYNAMIC23// CHECK-NEXT: DYNAMIC
23// CHECK-NEXT: GNU_RELRO24// CHECK-NEXT: GNU_RELRO
24// CHECK: Section to Segment mapping:25// CHECK: Section to Segment mapping:
2526
26// FULLRELRO: 05 .openbsd.randomdata .dynamic .got .got.plt {{$}}27// FULLRELRO: 03 .openbsd.randomdata .dynamic .got .got.plt {{$}}
27// PARTRELRO: 05 .openbsd.randomdata .dynamic .got {{$}}28// PARTRELRO: 03 .openbsd.randomdata .dynamic .got {{$}}
2829
2930
30// NORELRO-NOT: GNU_RELRO31// NORELRO-NOT: GNU_RELRO
deps/lld/test/ELF/resolution-end.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/resolution-end.s -o %t2.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/resolution-end.s -o %t2.o
4# RUN: ld.lld -shared -o %t2.so %t2.o4# RUN: ld.lld -shared -o %t2.so %t2.o
5# RUN: ld.lld --hash-style=sysv %t1.o %t2.so -o %t5# RUN: ld.lld --hash-style=sysv %t1.o %t2.so -o %t
6# RUN: llvm-readobj -t -s -section-data %t | FileCheck %s6# RUN: llvm-readobj --symbols -S --section-data %t | FileCheck %s
77
8# Test that we resolve _end to the this executable.8# Test that we resolve _end to the this executable.
99
deps/lld/test/ELF/resolution-shared.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/resolution-shared.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/resolution-shared.s -o %t2.o
4// RUN: ld.lld %t2.o -o %t2.so -shared4// RUN: ld.lld %t2.o -o %t2.so -shared
5// RUN: ld.lld %t.o %t2.so -o %t3 -shared5// RUN: ld.lld %t.o %t2.so -o %t3 -shared
6// RUN: llvm-readobj -t %t3 | FileCheck %s6// RUN: llvm-readobj --symbols %t3 | FileCheck %s
77
8 .weak foo8 .weak foo
9foo:9foo:
deps/lld/test/ELF/resolution.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// 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/resolution.s -o %t23// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/resolution.s -o %t2
4// RUN: ld.lld -discard-all %t %t2 -o %t34// RUN: ld.lld -discard-all %t %t2 -o %t3
5// RUN: llvm-readobj -t %t3 | FileCheck %s5// RUN: llvm-readobj --symbols %t3 | FileCheck %s
66
7// This is an exhaustive test for checking which symbol is kept when two7// This is an exhaustive test for checking which symbol is kept when two
8// have the same name. Each symbol has a different size which is used8// have the same name. Each symbol has a different size which is used
deps/lld/test/ELF/riscv-branch.s created+32
...@@ -0,0 +1,32 @@
1# REQUIRES: riscv
2
3# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax %s -o %t.rv32.o
4# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax %s -o %t.rv64.o
5
6# RUN: ld.lld %t.rv32.o --defsym foo=_start+4 --defsym bar=_start -o %t.rv32
7# RUN: ld.lld %t.rv64.o --defsym foo=_start+4 --defsym bar=_start -o %t.rv64
8# RUN: llvm-objdump -d %t.rv32 | FileCheck %s
9# RUN: llvm-objdump -d %t.rv64 | FileCheck %s
10# CHECK: 63 02 00 00 beqz zero, 4
11# CHECK: e3 1e 00 fe bnez zero, -4
12#
13# RUN: ld.lld %t.rv32.o --defsym foo=_start+0xffe --defsym bar=_start+4-0x1000 -o %t.rv32.limits
14# RUN: ld.lld %t.rv64.o --defsym foo=_start+0xffe --defsym bar=_start+4-0x1000 -o %t.rv64.limits
15# RUN: llvm-objdump -d %t.rv32.limits | FileCheck --check-prefix=LIMITS %s
16# RUN: llvm-objdump -d %t.rv64.limits | FileCheck --check-prefix=LIMITS %s
17# LIMITS: e3 0f 00 7e beqz zero, 4094
18# LIMITS-NEXT: 63 10 00 80 bnez zero, -4096
19
20# RUN: not ld.lld %t.rv32.o --defsym foo=_start+0x1000 --defsym bar=_start+4-0x1002 -o %t 2>&1 | FileCheck --check-prefix=ERROR-RANGE %s
21# RUN: not ld.lld %t.rv64.o --defsym foo=_start+0x1000 --defsym bar=_start+4-0x1002 -o %t 2>&1 | FileCheck --check-prefix=ERROR-RANGE %s
22# ERROR-RANGE: relocation R_RISCV_BRANCH out of range: 2048 is not in [-2048, 2047]
23# ERROR-RANGE-NEXT: relocation R_RISCV_BRANCH out of range: -2049 is not in [-2048, 2047]
24
25# RUN: not ld.lld %t.rv32.o --defsym foo=_start+1 --defsym bar=_start-1 -o %t 2>&1 | FileCheck --check-prefix=ERROR-ALIGN %s
26# RUN: not ld.lld %t.rv64.o --defsym foo=_start+1 --defsym bar=_start-1 -o %t 2>&1 | FileCheck --check-prefix=ERROR-ALIGN %s
27# ERROR-ALIGN: improper alignment for relocation R_RISCV_BRANCH: 0x1 is not aligned to 2 bytes
28
29.global _start
30_start:
31 beq x0, x0, foo
32 bne x0, x0, bar
deps/lld/test/ELF/riscv-branch.test deleted-119
...@@ -1,119 +0,0 @@
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
32FileHeader:
33 Class: ELFCLASS32
34 Data: ELFDATA2LSB
35 Type: ET_REL
36 Machine: EM_RISCV
37 Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
38Sections:
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
95Symbols:
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.s created+32
...@@ -0,0 +1,32 @@
1# REQUIRES: riscv
2
3# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax %s -o %t.rv32.o
4# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax %s -o %t.rv64.o
5
6# RUN: ld.lld %t.rv32.o --defsym foo=_start+8 --defsym bar=_start -o %t.rv32
7# RUN: ld.lld %t.rv64.o --defsym foo=_start+8 --defsym bar=_start -o %t.rv64
8# RUN: llvm-objdump -d %t.rv32 | FileCheck %s
9# RUN: llvm-objdump -d %t.rv64 | FileCheck %s
10# CHECK: 97 00 00 00 auipc ra, 0
11# CHECK-NEXT: e7 80 80 00 jalr 8(ra)
12# CHECK: 97 00 00 00 auipc ra, 0
13# CHECK-NEXT: e7 80 80 ff jalr -8(ra)
14
15# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x7ffff7ff --defsym bar=_start+8-0x80000800 -o %t.rv32.limits
16# RUN: ld.lld %t.rv64.o --defsym foo=_start+0x7ffff7ff --defsym bar=_start+8-0x80000800 -o %t.rv64.limits
17# RUN: llvm-objdump -d %t.rv32.limits | FileCheck --check-prefix=LIMITS %s
18# RUN: llvm-objdump -d %t.rv64.limits | FileCheck --check-prefix=LIMITS %s
19# LIMITS: 97 f0 ff 7f auipc ra, 524287
20# LIMITS-NEXT: e7 80 f0 7f jalr 2047(ra)
21# LIMITS-NEXT: 97 00 00 80 auipc ra, 524288
22# LIMITS-NEXT: e7 80 00 80 jalr -2048(ra)
23
24# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x7ffff800 --defsym bar=_start+8-0x80000801 -o %t
25# RUN: not ld.lld %t.rv64.o --defsym foo=_start+0x7ffff800 --defsym bar=_start+8-0x80000801 -o %t 2>&1 | FileCheck --check-prefix=ERROR %s
26# ERROR: relocation R_RISCV_CALL out of range: 524288 is not in [-524288, 524287]
27# ERROR-NEXT: relocation R_RISCV_CALL out of range: -524289 is not in [-524288, 524287]
28
29.global _start
30_start:
31 call foo
32 call bar
deps/lld/test/ELF/riscv-call.test deleted-95
...@@ -1,95 +0,0 @@
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
28FileHeader:
29 Class: ELFCLASS32
30 Data: ELFDATA2LSB
31 Type: ET_REL
32 Machine: EM_RISCV
33 Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
34Sections:
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
76Symbols:
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-gp-dummy-sdata.s created+25
...@@ -0,0 +1,25 @@
1# REQUIRES: riscv
2# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o
3# RUN: ld.lld -pie %t.32.o -o %t.32
4# RUN: llvm-readelf -S %t.32 | FileCheck --check-prefix=SEC %s
5# RUN: llvm-readelf -s %t.32 | FileCheck --check-prefix=SYM %s
6
7# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
8# RUN: ld.lld -pie %t.64.o -o %t.64
9# RUN: llvm-readelf -S %t.64 | FileCheck --check-prefix=SEC %s
10# RUN: llvm-readelf -s %t.64 | FileCheck --check-prefix=SYM %s
11
12## If there is an undefined reference to __global_pointer$ but .sdata doesn't
13## exist, create a dummy one.
14
15## __global_pointer$ = .sdata+0x800
16# SEC: [ 7] .sdata PROGBITS {{0*}}00003000
17# SYM: {{0*}}00003800 0 NOTYPE GLOBAL DEFAULT 7 __global_pointer$
18
19## If __global_pointer$ is not used, don't create .sdata .
20
21# RUN: llvm-mc -filetype=obj -triple=riscv32 /dev/null -o %t.32.o
22# RUN: ld.lld -pie %t.32.o -o %t.32
23# RUN: llvm-readelf -S %t.32 | FileCheck --implicit-check-not=.sdata /dev/null
24
25lla gp, __global_pointer$
deps/lld/test/ELF/riscv-gp.s created+26
...@@ -0,0 +1,26 @@
1# REQUIRES: riscv
2# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o
3# RUN: ld.lld -pie %t.32.o -o %t.32
4# RUN: llvm-readelf -s %t.32 | FileCheck --check-prefix=SYM %s
5# RUN: llvm-readelf -S %t.32 | FileCheck --check-prefix=SEC %s
6# RUN: not ld.lld -shared %t.32.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s
7
8# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
9# RUN: ld.lld -pie %t.64.o -o %t.64
10# RUN: llvm-readelf -s %t.64 | FileCheck --check-prefix=SYM %s
11# RUN: llvm-readelf -S %t.64 | FileCheck --check-prefix=SEC %s
12# RUN: not ld.lld -shared %t.64.o -o /dev/null 2>&1 | FileCheck --check-prefix=ERR %s
13
14## __global_pointer$ = .sdata+0x800 = 0x3800
15# SEC: [ 7] .sdata PROGBITS {{0*}}00003000
16# SYM: {{0*}}00003800 0 NOTYPE GLOBAL DEFAULT 7 __global_pointer$
17
18## __global_pointer$ - 0x1000 = 4096*3-2048
19# DIS: 1000: auipc gp, 3
20# DIS-NEXT: addi gp, gp, -2048
21
22# ERR: error: relocation R_RISCV_PCREL_HI20 cannot be used against symbol __global_pointer$; recompile with -fPIC
23
24lla gp, __global_pointer$
25
26.section .sdata,"aw"
deps/lld/test/ELF/riscv-hi20-lo12.s created+40
...@@ -0,0 +1,40 @@
1# REQUIRES: riscv
2
3# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax %s -o %t.rv32.o
4# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax %s -o %t.rv64.o
5
6# RUN: ld.lld %t.rv32.o --defsym foo=0 --defsym bar=42 -o %t.rv32
7# RUN: ld.lld %t.rv64.o --defsym foo=0 --defsym bar=42 -o %t.rv64
8# RUN: llvm-objdump -d %t.rv32 | FileCheck %s
9# RUN: llvm-objdump -d %t.rv64 | FileCheck %s
10# CHECK: 37 05 00 00 lui a0, 0
11# CHECK-NEXT: 13 05 05 00 mv a0, a0
12# CHECK-NEXT: 23 20 a5 00 sw a0, 0(a0)
13# CHECK-NEXT: b7 05 00 00 lui a1, 0
14# CHECK-NEXT: 93 85 a5 02 addi a1, a1, 42
15# CHECK-NEXT: 23 a5 b5 02 sw a1, 42(a1)
16
17# RUN: ld.lld %t.rv32.o --defsym foo=0x7ffff7ff --defsym bar=0x7ffff800 -o %t.rv32.limits
18# RUN: ld.lld %t.rv64.o --defsym foo=0x7ffff7ff --defsym bar=0xffffffff7ffff800 -o %t.rv64.limits
19# RUN: llvm-objdump -d %t.rv32.limits | FileCheck --check-prefix=LIMITS %s
20# RUN: llvm-objdump -d %t.rv64.limits | FileCheck --check-prefix=LIMITS %s
21# LIMITS: 37 f5 ff 7f lui a0, 524287
22# LIMITS-NEXT: 13 05 f5 7f addi a0, a0, 2047
23# LIMITS-NEXT: a3 2f a5 7e sw a0, 2047(a0)
24# LIMITS-NEXT: b7 05 00 80 lui a1, 524288
25# LIMITS-NEXT: 93 85 05 80 addi a1, a1, -2048
26# LIMITS-NEXT: 23 a0 b5 80 sw a1, -2048(a1)
27
28# RUN: not ld.lld %t.rv64.o --defsym foo=0x7ffff800 --defsym bar=0xffffffff7ffff7ff -o %t 2>&1 | FileCheck --check-prefix ERROR %s
29# ERROR: relocation R_RISCV_HI20 out of range: 524288 is not in [-524288, 524287]
30# ERROR-NEXT: relocation R_RISCV_HI20 out of range: -524289 is not in [-524288, 524287]
31
32.global _start
33
34_start:
35 lui a0, %hi(foo)
36 addi a0, a0, %lo(foo)
37 sw a0, %lo(foo)(a0)
38 lui a1, %hi(bar)
39 addi a1, a1, %lo(bar)
40 sw a1, %lo(bar)(a1)
deps/lld/test/ELF/riscv-hi20-lo12.test deleted-86
...@@ -1,86 +0,0 @@
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
33FileHeader:
34 Class: ELFCLASS32
35 Data: ELFDATA2LSB
36 Type: ET_REL
37 Machine: EM_RISCV
38 Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
39Sections:
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
64Symbols:
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 deleted-93
...@@ -1,93 +0,0 @@
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
24FileHeader:
25 Class: ELFCLASS32
26 Data: ELFDATA2LSB
27 Type: ET_REL
28 Machine: EM_RISCV
29 Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
30Sections:
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
68Symbols:
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.s created+34
...@@ -0,0 +1,34 @@
1# REQUIRES: riscv
2
3# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax %s -o %t.rv32.o
4# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax %s -o %t.rv64.o
5
6# RUN: ld.lld %t.rv32.o --defsym foo=_start+4 --defsym bar=_start -o %t.rv32
7# RUN: ld.lld %t.rv64.o --defsym foo=_start+4 --defsym bar=_start -o %t.rv64
8# RUN: llvm-objdump -d %t.rv32 | FileCheck %s
9# RUN: llvm-objdump -d %t.rv64 | FileCheck %s
10# CHECK: 6f 00 40 00 j 4
11# CHECK: ef f0 df ff jal -4
12
13# RUN: ld.lld %t.rv32.o --defsym foo=_start+0xffffe --defsym bar=_start+4-0x100000 -o %t.rv32.limits
14# RUN: ld.lld %t.rv64.o --defsym foo=_start+0xffffe --defsym bar=_start+4-0x100000 -o %t.rv64.limits
15# RUN: llvm-objdump -d %t.rv32.limits | FileCheck --check-prefix=LIMITS %s
16# RUN: llvm-objdump -d %t.rv64.limits | FileCheck --check-prefix=LIMITS %s
17# LIMITS: 6f f0 ff 7f j 1048574
18# LIMITS-NEXT: ef 00 00 80 jal -1048576
19
20# RUN: not ld.lld %t.rv32.o --defsym foo=_start+0x100000 --defsym bar=_start+4-0x100002 -o %t 2>&1 | FileCheck --check-prefix=ERROR-RANGE %s
21# RUN: not ld.lld %t.rv64.o --defsym foo=_start+0x100000 --defsym bar=_start+4-0x100002 -o %t 2>&1 | FileCheck --check-prefix=ERROR-RANGE %s
22# ERROR-RANGE: relocation R_RISCV_JAL out of range: 524288 is not in [-524288, 524287]
23# ERROR-RANGE-NEXT: relocation R_RISCV_JAL out of range: -524289 is not in [-524288, 524287]
24
25# RUN: not ld.lld %t.rv32.o --defsym foo=_start+1 --defsym bar=_start+4+3 -o %t 2>&1 | FileCheck --check-prefix=ERROR-ALIGN %s
26# RUN: not ld.lld %t.rv64.o --defsym foo=_start+1 --defsym bar=_start+4+3 -o %t 2>&1 | FileCheck --check-prefix=ERROR-ALIGN %s
27# ERROR-ALIGN: improper alignment for relocation R_RISCV_JAL: 0x1 is not aligned to 2 bytes
28# ERROR-ALIGN-NEXT: improper alignment for relocation R_RISCV_JAL: 0x3 is not aligned to 2 bytes
29
30.global _start
31
32_start:
33 jal x0, foo
34 jal x1, bar
deps/lld/test/ELF/riscv-jal.test deleted-161
...@@ -1,161 +0,0 @@
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
44FileHeader:
45 Class: ELFCLASS32
46 Data: ELFDATA2LSB
47 Type: ET_REL
48 Machine: EM_RISCV
49 Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
50Sections:
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
123Symbols:
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-error.s created+7
...@@ -0,0 +1,7 @@
1# REQUIRES: riscv
2# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o
3# RUN: not ld.lld %t.o --defsym external=0 2>&1 | FileCheck %s
4
5# CHECK: error: R_RISCV_PCREL_LO12 relocation points to an absolute symbol: external
6
7addi sp,sp,%pcrel_lo(external)
deps/lld/test/ELF/riscv-pcrel-hilo.s created+45
...@@ -0,0 +1,45 @@
1# REQUIRES: riscv
2
3# RUN: llvm-mc -filetype=obj -triple=riscv32-unknown-elf -mattr=-relax %s -o %t.rv32.o
4# RUN: llvm-mc -filetype=obj -triple=riscv64-unknown-elf -mattr=-relax %s -o %t.rv64.o
5
6# RUN: ld.lld %t.rv32.o --defsym foo=_start+12 --defsym bar=_start -o %t.rv32
7# RUN: ld.lld %t.rv64.o --defsym foo=_start+12 --defsym bar=_start -o %t.rv64
8# RUN: llvm-objdump -d --no-show-raw-insn %t.rv32 | FileCheck %s
9# RUN: llvm-objdump -d --no-show-raw-insn %t.rv64 | FileCheck %s
10# RUN: ld.lld -pie %t.rv32.o --defsym foo=_start+12 --defsym bar=_start -o %t.rv32
11# RUN: ld.lld -pie %t.rv64.o --defsym foo=_start+12 --defsym bar=_start -o %t.rv64
12# RUN: llvm-objdump -d --no-show-raw-insn %t.rv32 | FileCheck %s
13# RUN: llvm-objdump -d --no-show-raw-insn %t.rv64 | FileCheck %s
14# CHECK: auipc a0, 0
15# CHECK-NEXT: addi a0, a0, 12
16# CHECK-NEXT: sw zero, 12(a0)
17# CHECK: auipc a0, 0
18# CHECK-NEXT: addi a0, a0, -12
19# CHECK-NEXT: sw zero, -12(a0)
20
21# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x7ffff7ff --defsym bar=_start+12-0x80000800 -o %t.rv32.limits
22# RUN: ld.lld %t.rv64.o --defsym foo=_start+0x7ffff7ff --defsym bar=_start+12-0x80000800 -o %t.rv64.limits
23# RUN: llvm-objdump -d --no-show-raw-insn %t.rv32.limits | FileCheck --check-prefix=LIMITS %s
24# RUN: llvm-objdump -d --no-show-raw-insn %t.rv64.limits | FileCheck --check-prefix=LIMITS %s
25# LIMITS: auipc a0, 524287
26# LIMITS-NEXT: addi a0, a0, 2047
27# LIMITS-NEXT: sw zero, 2047(a0)
28# LIMITS: auipc a0, 524288
29# LIMITS-NEXT: addi a0, a0, -2048
30# LIMITS-NEXT: sw zero, -2048(a0)
31
32# RUN: ld.lld %t.rv32.o --defsym foo=_start+0x7ffff800 --defsym bar=_start+12-0x80000801 -o %t
33# RUN: not ld.lld %t.rv64.o --defsym foo=_start+0x7ffff800 --defsym bar=_start+12-0x80000801 -o %t 2>&1 | FileCheck --check-prefix=ERROR %s
34# ERROR: relocation R_RISCV_PCREL_HI20 out of range: 524288 is not in [-524288, 524287]
35# ERROR-NEXT: relocation R_RISCV_PCREL_HI20 out of range: -524289 is not in [-524288, 524287]
36
37.global _start
38_start:
39 auipc a0, %pcrel_hi(foo)
40 addi a0, a0, %pcrel_lo(_start)
41 sw x0, %pcrel_lo(_start)(a0)
42.L1:
43 auipc a0, %pcrel_hi(bar)
44 addi a0, a0, %pcrel_lo(.L1)
45 sw x0, %pcrel_lo(.L1)(a0)
deps/lld/test/ELF/riscv-pcrel-hilo.test deleted-103
...@@ -1,103 +0,0 @@
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
30FileHeader:
31 Class: ELFCLASS32
32 Data: ELFDATA2LSB
33 Type: ET_REL
34 Machine: EM_RISCV
35 Flags: [ EF_RISCV_RVC, EF_RISCV_FLOAT_ABI_SOFT ]
36Sections:
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
84Symbols:
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/riscv-plt.s created+103
...@@ -0,0 +1,103 @@
1# REQUIRES: riscv
2# RUN: echo '.globl bar, weak; .type bar,@function; .type weak,@function; bar: weak:' > %t1.s
3
4# RUN: llvm-mc -filetype=obj -triple=riscv32 %t1.s -o %t1.32.o
5# RUN: ld.lld -shared %t1.32.o -o %t1.32.so
6# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o
7# RUN: ld.lld %t.32.o %t1.32.so -o %t.32
8# RUN: llvm-readelf -S -s %t.32 | FileCheck --check-prefixes=SEC,NM %s
9# RUN: llvm-readobj -r %t.32 | FileCheck --check-prefix=RELOC32 %s
10# RUN: llvm-readelf -x .got.plt %t.32 | FileCheck --check-prefix=GOTPLT32 %s
11# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=DIS,DIS32 %s
12
13# RUN: llvm-mc -filetype=obj -triple=riscv64 %t1.s -o %t1.64.o
14# RUN: ld.lld -shared %t1.64.o -o %t1.64.so
15# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
16# RUN: ld.lld %t.64.o %t1.64.so -o %t.64
17# RUN: llvm-readelf -S -s %t.64 | FileCheck --check-prefixes=SEC,NM %s
18# RUN: llvm-readobj -r %t.64 | FileCheck --check-prefix=RELOC64 %s
19# RUN: llvm-readelf -x .got.plt %t.64 | FileCheck --check-prefix=GOTPLT64 %s
20# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=DIS,DIS64 %s
21
22# SEC: .plt PROGBITS {{0*}}00011030
23
24## A canonical PLT has a non-zero st_value. bar and weak are called but their
25## addresses are not taken, so a canonical PLT is not necessary.
26# NM: {{0*}}00000000 0 FUNC GLOBAL DEFAULT UND bar
27# NM: {{0*}}00000000 0 FUNC WEAK DEFAULT UND weak
28
29## The .got.plt slots relocated by .rela.plt point to .plt
30## This is required by glibc.
31# RELOC32: .rela.plt {
32# RELOC32-NEXT: 0x13008 R_RISCV_JUMP_SLOT bar 0x0
33# RELOC32-NEXT: 0x1300C R_RISCV_JUMP_SLOT weak 0x0
34# RELOC32-NEXT: }
35# GOTPLT32: section '.got.plt'
36# GOTPLT32-NEXT: 0x00013000 00000000 00000000 30100100 30100100
37
38# RELOC64: .rela.plt {
39# RELOC64-NEXT: 0x13010 R_RISCV_JUMP_SLOT bar 0x0
40# RELOC64-NEXT: 0x13018 R_RISCV_JUMP_SLOT weak 0x0
41# RELOC64-NEXT: }
42# GOTPLT64: section '.got.plt'
43# GOTPLT64-NEXT: 0x00013000 00000000 00000000 00000000 00000000
44# GOTPLT64-NEXT: 0x00013010 30100100 00000000 30100100 00000000
45
46# DIS: _start:
47## Direct call
48## foo - . = 0x11020-0x11000 = 32
49# DIS-NEXT: auipc ra, 0
50# DIS-NEXT: 11004: jalr 32(ra)
51## bar@plt - . = 0x11050-0x1100c = 72
52# DIS-NEXT: auipc ra, 0
53# DIS-NEXT: 1100c: jalr 72(ra)
54## bar@plt - . = 0x11050-0x11014 = 64
55# DIS-NEXT: auipc ra, 0
56# DIS-NEXT: 11014: jalr 64(ra)
57## weak@plt - . = 0x11060-0x1101c = 72
58# DIS-NEXT: auipc ra, 0
59# DIS-NEXT: 1101c: jalr 72(ra)
60# DIS: foo:
61# DIS-NEXT: 11020:
62
63# DIS: Disassembly of section .plt:
64# DIS: .plt:
65# DIS-NEXT: auipc t2, 2
66# DIS-NEXT: sub t1, t1, t3
67## .got.plt - .plt = 0x13000 - 0x11030 = 4096*2-48
68# DIS32-NEXT: lw t3, -48(t2)
69# DIS64-NEXT: ld t3, -48(t2)
70# DIS-NEXT: addi t1, t1, -44
71# DIS-NEXT: addi t0, t2, -48
72# DIS32-NEXT: srli t1, t1, 2
73# DIS64-NEXT: srli t1, t1, 1
74# DIS32-NEXT: lw t0, 4(t0)
75# DIS64-NEXT: ld t0, 8(t0)
76# DIS-NEXT: jr t3
77
78## 32-bit: &.got.plt[bar]-. = 0x13008-0x11050 = 4096*2-72
79# DIS: 11050: auipc t3, 2
80# DIS32-NEXT: lw t3, -72(t3)
81# DIS64-NEXT: ld t3, -64(t3)
82# DIS-NEXT: jalr t1, t3
83# DIS-NEXT: nop
84
85## 32-bit: &.got.plt[weak]-. = 0x1300c-0x11060 = 4096*2-84
86# DIS: 11060: auipc t3, 2
87# DIS32-NEXT: lw t3, -84(t3)
88# DIS64-NEXT: ld t3, -72(t3)
89# DIS-NEXT: jalr t1, t3
90# DIS-NEXT: nop
91
92.global _start, foo, bar
93.weak weak
94
95_start:
96 call foo
97 call bar
98 call bar@plt
99 call weak
100
101## foo is local and non-preemptale, no PLT is generated.
102foo:
103 ret
deps/lld/test/ELF/riscv-reloc-64-pic.s created+10
...@@ -0,0 +1,10 @@
1# REQUIRES: riscv
2# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o
3# RUN: not ld.lld -shared %t.o -o %t.so 2>&1 | FileCheck %s
4
5# CHECK: error: relocation R_RISCV_32 cannot be used against symbol a
6
7.globl a
8
9.data
10.long a
deps/lld/test/ELF/riscv-reloc-add.s created+32
...@@ -0,0 +1,32 @@
1# REQUIRES: riscv
2# RUN: llvm-mc -filetype=obj -triple=riscv32 -mattr=+relax %s -o %t.32.o
3# RUN: ld.lld -pie %t.32.o -o %t.32
4# RUN: llvm-readelf -x .rodata %t.32 | FileCheck --check-prefix=HEX %s
5
6# RUN: llvm-mc -filetype=obj -triple=riscv64 -mattr=+relax %s -o %t.64.o
7# RUN: ld.lld -shared %t.64.o -o %t.64
8# RUN: llvm-readelf -x .rodata %t.64 | FileCheck --check-prefix=HEX %s
9
10# HEX: section '.rodata':
11# HEX-NEXT: 0x{{[0-9a-f]+}} 04000000 00000000 04000000 040004
12
13## R_RISCV_ADD* and R_RISCV_SUB* are link-time constants, otherwise they are
14## not allowed in -pie/-shared mode.
15
16.global _start
17_start:
18.L0:
19 ret
20.L1:
21
22.rodata
23.dword .L1 - .L0
24.word .L1 - .L0
25.half .L1 - .L0
26.byte .L1 - .L0
27
28## Debug section may use R_RISCV_ADD64/R_RISCV_SUB64 pairs to measure lengths
29## of code ranges (e.g. DW_AT_high_pc). Check we allow R_RISCV_ADD*/R_RISCV_SUB*
30## in such non-SHF_ALLOC sections in -pie/-shared mode.
31.section .debug_info
32.quad .L1 - .L0
deps/lld/test/ELF/riscv-reloc-copy.s created+23
...@@ -0,0 +1,23 @@
1# REQUIRES: riscv
2# RUN: llvm-mc -filetype=obj -triple=riscv32 %p/Inputs/relocation-copy.s -o %t1.o
3# RUN: ld.lld -shared %t1.o -o %t1.so
4# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.o
5# RUN: ld.lld %t.o %t1.so -o %t
6# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
7# RUN: llvm-nm -S %t | FileCheck --check-prefix=NM32 %s
8
9# RUN: llvm-mc -filetype=obj -triple=riscv64 %p/Inputs/relocation-copy.s -o %t1.o
10# RUN: ld.lld -shared %t1.o -o %t1.so
11# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o
12# RUN: ld.lld %t.o %t1.so -o %t
13# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC %s
14# RUN: llvm-nm -S %t | FileCheck --check-prefix=NM64 %s
15
16# RELOC: .rela.dyn {
17# RELOC-NEXT: 0x13000 R_RISCV_COPY x 0x0
18# RELOC-NEXT: }
19
20# NM32: 00013000 00000004 B x
21# NM64: 0000000000013000 0000000000000004 B x
22
23la a0, x
deps/lld/test/ELF/riscv-reloc-got.s created+65
...@@ -0,0 +1,65 @@
1# REQUIRES: riscv
2# RUN: echo '.globl b; b:' | llvm-mc -filetype=obj -triple=riscv32 - -o %t1.o
3# RUN: ld.lld -shared %t1.o -o %t1.so
4
5# RUN: llvm-mc -filetype=obj -triple=riscv32 -position-independent %s -o %t.o
6# RUN: ld.lld %t.o %t1.so -o %t
7# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC32 %s
8# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
9# RUN: llvm-readobj -x .got %t | FileCheck --check-prefix=HEX32 %s
10# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=DIS32 %s
11
12# RUN: echo '.globl b; b:' | llvm-mc -filetype=obj -triple=riscv64 - -o %t1.o
13# RUN: ld.lld -shared %t1.o -o %t1.so
14
15# RUN: llvm-mc -filetype=obj -triple=riscv64 -position-independent %s -o %t.o
16# RUN: ld.lld %t.o %t1.so -o %t
17# RUN: llvm-readobj -r %t | FileCheck --check-prefix=RELOC64 %s
18# RUN: llvm-nm %t | FileCheck --check-prefix=NM %s
19# RUN: llvm-readobj -x .got %t | FileCheck --check-prefix=HEX64 %s
20# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=DIS64 %s
21
22# SEC: .got PROGBITS 00012060 020060 00000c
23
24# RELOC32: .rela.dyn {
25# RELOC32-NEXT: 0x12068 R_RISCV_32 b 0x0
26# RELOC32-NEXT: }
27
28# RELOC64: .rela.dyn {
29# RELOC64-NEXT: 0x120D0 R_RISCV_64 b 0x0
30# RELOC64-NEXT: }
31
32# NM: 00013000 d a
33
34## .got[0] = _DYNAMIC
35## .got[1] = a (filled at link time)
36## .got[2] = 0 (relocated by R_RISCV_64 at runtime)
37# HEX32: section '.got':
38# HEX32: 0x00012060 00200100 00300100 00000000
39
40# HEX64: section '.got':
41# HEX64: 0x000120c0 00200100 00000000 00300100 00000000
42# HEX64: 0x000120d0 00000000 00000000
43
44## &.got[1]-. = 0x12060-0x11000 = 4096*1+100
45# DIS32: 11000: auipc a0, 1
46# DIS32-NEXT: lw a0, 100(a0)
47## &.got[2]-. = 0x12064-0x11008 = 4096*1+96
48# DIS32: 11008: auipc a0, 1
49# DIS32-NEXT: lw a0, 96(a0)
50
51## &.got[1]-. = 0x120c8-0x11000 = 4096*1+100
52# DIS64: 11000: auipc a0, 1
53# DIS64-NEXT: ld a0, 200(a0)
54## &.got[2]-. = 0x120d0-0x11008 = 4096*1+200
55# DIS64: 11008: auipc a0, 1
56# DIS64-NEXT: ld a0, 200(a0)
57
58la a0,a
59la a0,b
60
61.data
62a:
63## An undefined reference of _GLOBAL_OFFSET_TABLE_ causes .got[0] to be
64## allocated to store _DYNAMIC.
65.long _GLOBAL_OFFSET_TABLE_ - .
deps/lld/test/ELF/riscv-tls-gd.s created+124
...@@ -0,0 +1,124 @@
1# REQUIRES: riscv
2# RUN: echo '.tbss; .globl b, c; b: .zero 4; c:' > %t.s
3# RUN: echo '.globl __tls_get_addr; __tls_get_addr:' > %tga.s
4
5## RISC-V psABI doesn't specify TLS relaxation. Though the code sequences are not
6## relaxed, dynamic relocations can be omitted for GD->LE relaxation.
7
8# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o
9# RUN: llvm-mc -filetype=obj -triple=riscv32 %t.s -o %t1.32.o
10# RUN: ld.lld -shared -soname=t1.so %t1.32.o -o %t1.32.so
11# RUN: llvm-mc -filetype=obj -triple=riscv32 %tga.s -o %tga.32.o
12## rv32 GD
13# RUN: ld.lld -shared %t.32.o %t1.32.o -o %t.32.so
14# RUN: llvm-readobj -r %t.32.so | FileCheck --check-prefix=GD32-REL %s
15# RUN: llvm-objdump -d --no-show-raw-insn %t.32.so | FileCheck --check-prefix=GD32 %s
16## rv32 GD -> LE
17# RUN: ld.lld %t.32.o %t1.32.o %tga.32.o -o %t.32
18# RUN: llvm-readelf -r %t.32 | FileCheck --check-prefix=NOREL %s
19# RUN: llvm-readelf -x .got %t.32 | FileCheck --check-prefix=LE32-GOT %s
20# RUN: ld.lld -pie %t.32.o %t1.32.o %tga.32.o -o %t.32
21# RUN: llvm-readelf -r %t.32 | FileCheck --check-prefix=NOREL %s
22# RUN: llvm-readelf -x .got %t.32 | FileCheck --check-prefix=LE32-GOT %s
23## rv32 GD -> IE
24# RUN: ld.lld %t.32.o %t1.32.so %tga.32.o -o %t.32
25# RUN: llvm-readobj -r %t.32 | FileCheck --check-prefix=IE32-REL %s
26# RUN: llvm-readelf -x .got %t.32 | FileCheck --check-prefix=IE32-GOT %s
27
28# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
29# RUN: llvm-mc -filetype=obj -triple=riscv64 %t.s -o %t1.64.o
30# RUN: ld.lld -shared -soname=t1.so %t1.64.o -o %t1.64.so
31# RUN: llvm-mc -filetype=obj -triple=riscv64 %tga.s -o %tga.64.o
32## rv64 GD
33# RUN: ld.lld -shared %t.64.o %t1.64.o -o %t.64.so
34# RUN: llvm-readobj -r %t.64.so | FileCheck --check-prefix=GD64-REL %s
35# RUN: llvm-objdump -d --no-show-raw-insn %t.64.so | FileCheck --check-prefix=GD64 %s
36## rv64 GD -> LE
37# RUN: ld.lld %t.64.o %t1.64.o %tga.64.o -o %t.64
38# RUN: llvm-readelf -r %t.64 | FileCheck --check-prefix=NOREL %s
39# RUN: llvm-readelf -x .got %t.64 | FileCheck --check-prefix=LE64-GOT %s
40# RUN: ld.lld -pie %t.64.o %t1.64.o %tga.64.o -o %t.64
41# RUN: llvm-readelf -r %t.64 | FileCheck --check-prefix=NOREL %s
42# RUN: llvm-readelf -x .got %t.64 | FileCheck --check-prefix=LE64-GOT %s
43## rv64 GD -> IE
44# RUN: ld.lld %t.64.o %t1.64.so %tga.64.o -o %t.64
45# RUN: llvm-readobj -r %t.64 | FileCheck --check-prefix=IE64-REL %s
46# RUN: llvm-readelf -x .got %t.64 | FileCheck --check-prefix=IE64-GOT %s
47
48# GD32-REL: .rela.dyn {
49# GD32-REL-NEXT: 0x2070 R_RISCV_TLS_DTPMOD32 a 0x0
50# GD32-REL-NEXT: 0x2074 R_RISCV_TLS_DTPREL32 a 0x0
51# GD32-REL-NEXT: 0x2078 R_RISCV_TLS_DTPMOD32 b 0x0
52# GD32-REL-NEXT: 0x207C R_RISCV_TLS_DTPREL32 b 0x0
53# GD32-REL-NEXT: }
54
55## &DTPMOD(a) - . = 0x2070 - 0x1000 = 4096*1+112
56# GD32: 1000: auipc a0, 1
57# GD32-NEXT: addi a0, a0, 112
58# GD32-NEXT: auipc ra, 0
59# GD32-NEXT: jalr 56(ra)
60
61## &DTPMOD(b) - . = 0x2078 - 0x1010 = 4096*1+104
62# GD32: 1010: auipc a0, 1
63# GD32-NEXT: addi a0, a0, 104
64# GD32-NEXT: auipc ra, 0
65# GD32-NEXT: jalr 40(ra)
66
67# GD64-REL: .rela.dyn {
68# GD64-REL-NEXT: 0x20E0 R_RISCV_TLS_DTPMOD64 a 0x0
69# GD64-REL-NEXT: 0x20E8 R_RISCV_TLS_DTPREL64 a 0x0
70# GD64-REL-NEXT: 0x20F0 R_RISCV_TLS_DTPMOD64 b 0x0
71# GD64-REL-NEXT: 0x20F8 R_RISCV_TLS_DTPREL64 b 0x0
72# GD64-REL-NEXT: }
73
74## &DTPMOD(a) - . = 0x20e0 - 0x1000 = 4096*1+224
75# GD64: 1000: auipc a0, 1
76# GD64-NEXT: addi a0, a0, 224
77# GD64-NEXT: auipc ra, 0
78# GD64-NEXT: jalr 56(ra)
79
80## &DTPMOD(b) - . = 0x20f0 - 0x1010 = 4096*1+224
81# GD64: 1010: auipc a0, 1
82# GD64-NEXT: addi a0, a0, 224
83# GD64-NEXT: auipc ra, 0
84# GD64-NEXT: jalr 40(ra)
85
86# NOREL: no relocations
87
88## .got contains pre-populated values: [a@dtpmod, a@dtprel, b@dtpmod, b@dtprel]
89## a@dtprel = st_value(a)-0x800 = 0xfffff808
90## b@dtprel = st_value(b)-0x800 = 0xfffff80c
91# LE32-GOT: section '.got':
92# LE32-GOT-NEXT: 0x{{[0-9a-f]+}} 01000000 08f8ffff 01000000 0cf8ffff
93# LE64-GOT: section '.got':
94# LE64-GOT-NEXT: 0x{{[0-9a-f]+}} 01000000 00000000 08f8ffff ffffffff
95# LE64-GOT-NEXT: 0x{{[0-9a-f]+}} 01000000 00000000 0cf8ffff ffffffff
96
97## a is local - relaxed to LE - its DTPMOD/DTPREL slots are link-time constants.
98## b is external - DTPMOD/DTPREL dynamic relocations are required.
99# IE32-REL: .rela.dyn {
100# IE32-REL-NEXT: 0x12068 R_RISCV_TLS_DTPMOD32 b 0x0
101# IE32-REL-NEXT: 0x1206C R_RISCV_TLS_DTPREL32 b 0x0
102# IE32-REL-NEXT: }
103# IE32-GOT: section '.got':
104# IE32-GOT-NEXT: 0x00012060 01000000 08f8ffff 00000000 00000000
105
106# IE64-REL: .rela.dyn {
107# IE64-REL-NEXT: 0x120D0 R_RISCV_TLS_DTPMOD64 b 0x0
108# IE64-REL-NEXT: 0x120D8 R_RISCV_TLS_DTPREL64 b 0x0
109# IE64-REL-NEXT: }
110# IE64-GOT: section '.got':
111# IE64-GOT-NEXT: 0x000120c0 01000000 00000000 08f8ffff ffffffff
112# IE64-GOT-NEXT: 0x000120d0 00000000 00000000 00000000 00000000
113
114la.tls.gd a0,a
115call __tls_get_addr@plt
116
117la.tls.gd a0,b
118call __tls_get_addr@plt
119
120.section .tbss
121.globl a
122.zero 8
123a:
124.zero 4
deps/lld/test/ELF/riscv-tls-ie.s created+82
...@@ -0,0 +1,82 @@
1# REQUIRES: riscv
2
3# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o
4## rv32 IE
5# RUN: ld.lld -shared %t.32.o -o %t.32.so
6# RUN: llvm-readobj -r -d %t.32.so | FileCheck --check-prefix=IE32-REL %s
7# RUN: llvm-objdump -d --no-show-raw-insn %t.32.so | FileCheck --check-prefixes=IE,IE32 %s
8## rv32 IE -> LE
9# RUN: ld.lld %t.32.o -o %t.32
10# RUN: llvm-readelf -r %t.32 | FileCheck --check-prefix=NOREL %s
11# RUN: llvm-readelf -x .got %t.32 | FileCheck --check-prefix=LE32-GOT %s
12# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=LE,LE32 %s
13
14# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
15## rv64 IE
16# RUN: ld.lld -shared %t.64.o -o %t.64.so
17# RUN: llvm-readobj -r -d %t.64.so | FileCheck --check-prefix=IE64-REL %s
18# RUN: llvm-objdump -d --no-show-raw-insn %t.64.so | FileCheck --check-prefixes=IE,IE64 %s
19## rv64 IE -> LE
20# RUN: ld.lld %t.64.o -o %t.64
21# RUN: llvm-readelf -r %t.64 | FileCheck --check-prefix=NOREL %s
22# RUN: llvm-readelf -x .got %t.64 | FileCheck --check-prefix=LE64-GOT %s
23# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=LE,LE64 %s
24
25# IE32-REL: .rela.dyn {
26# IE32-REL-NEXT: 0x205C R_RISCV_TLS_TPREL32 - 0xC
27# IE32-REL-NEXT: 0x2058 R_RISCV_TLS_TPREL32 a 0x0
28# IE32-REL-NEXT: }
29# IE32-REL: FLAGS STATIC_TLS
30
31# IE64-REL: .rela.dyn {
32# IE64-REL-NEXT: 0x20B8 R_RISCV_TLS_TPREL64 - 0xC
33# IE64-REL-NEXT: 0x20B0 R_RISCV_TLS_TPREL64 a 0x0
34# IE64-REL-NEXT: }
35# IE64-REL: FLAGS STATIC_TLS
36
37## rv32: &.got[1] - . = 0x2058 - . = 4096*1+88
38## rv64: &.got[1] - . = 0x20B0 - . = 4096*1+176
39# IE: 1000: auipc a4, 1
40# IE32-NEXT: lw a4, 88(a4)
41# IE64-NEXT: ld a4, 176(a4)
42# IE-NEXT: add a4, a4, tp
43## rv32: &.got[0] - . = 0x205C - . = 4096*1+80
44## rv64: &.got[0] - . = 0x20B8 - . = 4096*1+172
45# IE: 100c: auipc a5, 1
46# IE32-NEXT: lw a5, 80(a5)
47# IE64-NEXT: ld a5, 172(a5)
48# IE-NEXT: add a5, a5, tp
49
50# NOREL: no relocations
51
52# a@tprel = st_value(a) = 0x8
53# b@tprel = st_value(a) = 0xc
54# LE32-GOT: section '.got':
55# LE32-GOT-NEXT: 0x00012000 08000000 0c000000
56# LE64-GOT: section '.got':
57# LE64-GOT-NEXT: 0x00012000 08000000 00000000 0c000000 00000000
58
59## rv32: &.got[0] - . = 0x12000 - 0x11000 = 4096*1+0
60## rv64: &.got[0] - . = 0x12000 - 0x11000 = 4096*1+0
61# LE: 11000: auipc a4, 1
62# LE32-NEXT: lw a4, 0(a4)
63# LE64-NEXT: ld a4, 0(a4)
64# LE-NEXT: add a4, a4, tp
65## rv32: &.got[1] - . = 0x12004 - 0x1100c = 4096*1-8
66## rv64: &.got[1] - . = 0x12008 - 0x1100c = 4096*1-4
67# LE: 1100c: auipc a5, 1
68# LE32-NEXT: lw a5, -8(a5)
69# LE64-NEXT: ld a5, -4(a5)
70# LE-NEXT: add a5, a5, tp
71
72la.tls.ie a4,a
73add a4,a4,tp
74la.tls.ie a5,b
75add a5,a5,tp
76
77.section .tbss
78.globl a
79.zero 8
80a:
81.zero 4
82b:
deps/lld/test/ELF/riscv-tls-ld.s created+90
...@@ -0,0 +1,90 @@
1# REQUIRES: riscv
2# RUN: echo '.tbss; .globl b, c; b: .zero 4; c:' > %t.s
3# RUN: echo '.globl __tls_get_addr; __tls_get_addr:' > %tga.s
4
5## RISC-V psABI doesn't specify TLS relaxation. Though the code sequences are not
6## relaxed, dynamic relocations can be omitted for LD->LE relaxation.
7## LD uses the same relocation as GD: R_RISCV_GD_HI20, the difference is that it
8## references a local symbol (.LANCHOR0).
9
10# RUN: llvm-mc -filetype=obj -triple=riscv32 -position-independent %s -o %t.32.o
11# RUN: llvm-mc -filetype=obj -triple=riscv32 %tga.s -o %tga.o
12## rv32 LD
13# RUN: ld.lld -shared %t.32.o -o %t.32.so
14# RUN: llvm-readobj -r %t.32.so | FileCheck --check-prefix=LD32-REL %s
15# RUN: llvm-readelf -x .got %t.32.so | FileCheck --check-prefix=LD32-GOT %s
16# RUN: llvm-objdump -d --no-show-raw-insn %t.32.so | FileCheck --check-prefixes=LD,LD32 %s
17## rv32 LD -> LE
18# RUN: ld.lld %t.32.o %tga.o -o %t.32
19# RUN: llvm-readelf -r %t.32 | FileCheck --check-prefix=NOREL %s
20# RUN: llvm-readelf -x .got %t.32 | FileCheck --check-prefix=LE32-GOT %s
21# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=LE,LE32 %s
22
23# RUN: llvm-mc -filetype=obj -triple=riscv64 -position-independent %s -o %t.64.o
24# RUN: llvm-mc -filetype=obj -triple=riscv64 %tga.s -o %tga.o
25## rv64 LD
26# RUN: ld.lld -shared %t.64.o -o %t.64.so
27# RUN: llvm-readobj -r %t.64.so | FileCheck --check-prefix=LD64-REL %s
28# RUN: llvm-readelf -x .got %t.64.so | FileCheck --check-prefix=LD64-GOT %s
29# RUN: llvm-objdump -d --no-show-raw-insn %t.64.so | FileCheck --check-prefixes=LD,LD64 %s
30## rv64 LD -> LE
31# RUN: ld.lld %t.64.o %tga.o -o %t.64
32# RUN: llvm-readelf -r %t.64 | FileCheck --check-prefix=NOREL %s
33# RUN: llvm-readelf -x .got %t.64 | FileCheck --check-prefix=LE64-GOT %s
34# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=LE,LE64 %s
35
36## a@dtprel = st_value(a)-0x800 = 0xfffff808 is a link-time constant.
37# LD32-REL: .rela.dyn {
38# LD32-REL-NEXT: 0x2084
39# LD32-REL-NEXT: 0x207C R_RISCV_TLS_DTPMOD32 - 0x0
40# LD32-REL-NEXT: }
41# LD32-GOT: section '.got':
42# LD32-GOT-NEXT: 0x00002078 00200000 00000000 00f8ffff 00000000
43
44# LD64-REL: .rela.dyn {
45# LD64-REL-NEXT: 0x2108
46# LD64-REL-NEXT: 0x20F8 R_RISCV_TLS_DTPMOD64 - 0x0
47# LD64-REL-NEXT: }
48# LD64-GOT: section '.got':
49# LD64-GOT-NEXT: 0x000020f0 00200000 00000000 00000000 00000000
50# LD64-GOT-NEXT: 0x00002100 00f8ffff ffffffff 00000000 00000000
51
52## rv32: &DTPMOD(a) - . = 0x207c - 0x1000 = 4096*1+124
53## rv64: &DTPMOD(a) - . = 0x20e0 - 0x1000 = 4096*1+248
54# LD: 1000: auipc a0, 1
55# LD32-NEXT: addi a0, a0, 124
56# LD64-NEXT: addi a0, a0, 248
57# LD-NEXT: auipc ra, 0
58# LD-NEXT: jalr 56(ra)
59
60# NOREL: no relocations
61
62## a is local - its DTPMOD/DTPREL slots are link-time constants.
63## a@dtpmod = 1 (main module)
64# LE32-GOT: section '.got':
65# LE32-GOT-NEXT: 0x00012000 00000000 01000000 00f8ffff 00200100
66
67# LE64-GOT: section '.got':
68# LE64-GOT-NEXT: 0x00012000 00000000 00000000 01000000 00000000
69# LE64-GOT-NEXT: 0x00012010 00f8ffff ffffffff 00200100 00000000
70
71## rv32: DTPMOD(.LANCHOR0) - . = 0x12004 - 0x11000 = 4096*1+4
72## rv64: DTPMOD(.LANCHOR0) - . = 0x12008 - 0x11000 = 4096*1+8
73# LE: 11000: auipc a0, 1
74# LE32-NEXT: addi a0, a0, 4
75# LE64-NEXT: addi a0, a0, 8
76# LE-NEXT: auipc ra, 0
77# LE-NEXT: jalr 24(ra)
78
79la.tls.gd a0, .LANCHOR0
80call __tls_get_addr@plt
81lw a4, 0(a0)
82lh a0, 4(a0)
83
84## This is irrelevant to TLS. We use it to take 2 GOT slots to check DTPREL
85## offsets are correct.
86la a5, _GLOBAL_OFFSET_TABLE_
87
88.section .tbss,"awT",@nobits
89.set .LANCHOR0, . + 0
90.zero 8
deps/lld/test/ELF/riscv-tls-le.s created+41
...@@ -0,0 +1,41 @@
1# REQUIRES: riscv
2
3# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.32.o
4# RUN: ld.lld %t.32.o -o %t.32
5# RUN: llvm-nm -p %t.32 | FileCheck --check-prefixes=NM %s
6# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=LE %s
7# RUN: ld.lld -pie %t.32.o -o %t.32
8# RUN: llvm-objdump -d --no-show-raw-insn %t.32 | FileCheck --check-prefixes=LE %s
9
10# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.64.o
11# RUN: ld.lld %t.64.o -o %t.64
12# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=LE %s
13# RUN: ld.lld -pie %t.64.o -o %t.64
14# RUN: llvm-objdump -d --no-show-raw-insn %t.64 | FileCheck --check-prefixes=LE %s
15
16# NM: {{0*}}00000008 b .LANCHOR0
17# NM: {{0*}}0000000c B a
18
19## .LANCHOR0@tprel = 8
20## a@tprel = 12
21# LE: lui a5, 0
22# LE-NEXT: add a5, a5, tp
23# LE-NEXT: addi a5, a5, 8
24# LE-NEXT: lui a5, 0
25# LE-NEXT: add a5, a5, tp
26# LE-NEXT: sw a0, 12(a5)
27
28lui a5, %tprel_hi(.LANCHOR0)
29add a5, a5, tp, %tprel_add(.LANCHOR0)
30addi a5, a5, %tprel_lo(.LANCHOR0)
31
32lui a5, %tprel_hi(a)
33add a5, a5, tp, %tprel_add(a)
34sw a0, %tprel_lo(a)(a5)
35
36.section .tbss
37.space 8
38.LANCHOR0:
39.zero 4
40.globl a
41a:
deps/lld/test/ELF/riscv32-reloc-32-pic.s created+23
...@@ -0,0 +1,23 @@
1# REQUIRES: riscv
2# RUN: llvm-mc -filetype=obj -triple=riscv32 %s -o %t.o
3# RUN: ld.lld -shared %t.o -o %t.so
4# RUN: llvm-nm %t.so | FileCheck --check-prefix=NM %s
5# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOC %s
6
7## R_RISCV_32 is an absolute relocation type.
8## In PIC mode, it creates a relative relocation if the symbol is non-preemptable.
9
10# NM: 00002004 d b
11
12# RELOC: .rela.dyn {
13# RELOC-NEXT: 0x2004 R_RISCV_RELATIVE - 0x2004
14# RELOC-NEXT: 0x2000 R_RISCV_32 a 0
15# RELOC-NEXT: }
16
17.globl a, b
18.hidden b
19
20.data
21.long a
22b:
23.long b
deps/lld/test/ELF/riscv64-reloc-64-pic.s created+23
...@@ -0,0 +1,23 @@
1# REQUIRES: riscv
2# RUN: llvm-mc -filetype=obj -triple=riscv64 %s -o %t.o
3# RUN: ld.lld -shared %t.o -o %t.so
4# RUN: llvm-nm %t.so | FileCheck --check-prefix=NM %s
5# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=RELOC %s
6
7## R_RISCV_64 is an absolute relocation type.
8## In PIC mode, it creates a relative relocation if the symbol is non-preemptable.
9
10# NM: 0000000000002008 d b
11
12# RELOC: .rela.dyn {
13# RELOC-NEXT: 0x2008 R_RISCV_RELATIVE - 0x2008
14# RELOC-NEXT: 0x2000 R_RISCV_64 a 0
15# RELOC-NEXT: }
16
17.globl a, b
18.hidden b
19
20.data
21.quad a
22b:
23.quad b
deps/lld/test/ELF/rodynamic.s+4-4
...@@ -4,13 +4,13 @@...@@ -4,13 +4,13 @@
44
5# RUN: ld.lld -shared %t.so.o -o %t.so5# RUN: ld.lld -shared %t.so.o -o %t.so
6# RUN: ld.lld %t.o %t.so -o %t.exe6# RUN: ld.lld %t.o %t.so -o %t.exe
7# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck -check-prefix=DEFDEBUG %s7# RUN: llvm-readobj --dynamic-table %t.exe | FileCheck -check-prefix=DEFDEBUG %s
8# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=DEFSEC %s8# RUN: llvm-readobj --sections %t.exe | FileCheck -check-prefix=DEFSEC %s
99
10# RUN: ld.lld -shared -z rodynamic %t.so.o -o %t.so10# RUN: ld.lld -shared -z rodynamic %t.so.o -o %t.so
11# RUN: ld.lld -z rodynamic %t.o %t.so -o %t.exe11# RUN: ld.lld -z rodynamic %t.o %t.so -o %t.exe
12# RUN: llvm-readobj -dynamic-table %t.exe | FileCheck -check-prefix=RODEBUG %s12# RUN: llvm-readobj --dynamic-table %t.exe | FileCheck -check-prefix=RODEBUG %s
13# RUN: llvm-readobj -sections %t.exe | FileCheck -check-prefix=ROSEC %s13# RUN: llvm-readobj --sections %t.exe | FileCheck -check-prefix=ROSEC %s
1414
15.globl _start15.globl _start
16_start:16_start:
deps/lld/test/ELF/section-align-0.test+3-3
...@@ -15,6 +15,6 @@ Sections:...@@ -15,6 +15,6 @@ Sections:
15 AddressAlign: 015 AddressAlign: 0
1616
17Symbols:17Symbols:
18 Global:18 - Name: _start
19 - Name: _start19 Section: .text
20 Section: .text20 Binding: STB_GLOBAL
deps/lld/test/ELF/section-layout.s+5-4
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3# RUN: ld.lld %t -o %tout3# RUN: ld.lld %t -o %tout
4# RUN: llvm-readobj -sections %tout | FileCheck %s4# RUN: llvm-readobj --sections %tout | FileCheck %s
55
6# Check that sections are laid out in the correct order.6# Check that sections are laid out in the correct order.
77
...@@ -32,6 +32,7 @@ _start:...@@ -32,6 +32,7 @@ _start:
32// For non-executable and non-writable sections, PROGBITS appear after others.32// For non-executable and non-writable sections, PROGBITS appear after others.
33// CHECK: Name: a33// CHECK: Name: a
34// CHECK: Name: b34// CHECK: Name: b
35
35// CHECK: Name: c36// CHECK: Name: c
36// CHECK: Name: d37// CHECK: Name: d
3738
...@@ -40,13 +41,13 @@ _start:...@@ -40,13 +41,13 @@ _start:
40// CHECK: Name: k41// CHECK: Name: k
41// CHECK: Name: l42// CHECK: Name: l
4243
43// Writable sections appear before TLS and other relro sections.
44// CHECK: Name: i
45
46// TLS sections are only sorted on NOBITS.44// TLS sections are only sorted on NOBITS.
47// CHECK: Name: e45// CHECK: Name: e
48// CHECK: Name: g46// CHECK: Name: g
4947
48// Writable sections appear after TLS and other relro sections.
49// CHECK: Name: i
50
50// CHECK: Name: j51// CHECK: Name: j
5152
52// Non allocated sections are in input order.53// Non allocated sections are in input order.
deps/lld/test/ELF/section-name.s+6-6
...@@ -45,12 +45,12 @@ _start:...@@ -45,12 +45,12 @@ _start:
45// CHECK: 1 .rodata 0000000245// CHECK: 1 .rodata 00000002
46// CHECK: 2 .gcc_except_table 0000000146// CHECK: 2 .gcc_except_table 00000001
47// CHECK: 3 .text 0000000247// CHECK: 3 .text 00000002
48// CHECK: 4 .data 0000000248// CHECK: 4 .tdata 00000001
49// CHECK: 5 .foo.a 0000000149// CHECK: 5 .tbss 00000001
50// CHECK: 6 .foo 0000000150// CHECK: 6 .data.rel.ro 00000004
51// CHECK: 7 .tdata 0000000151// CHECK: 7 .data 00000002
52// CHECK: 8 .tbss 0000000152// CHECK: 8 .foo.a 00000001
53// CHECK: 9 .data.rel.ro 0000000453// CHECK: 9 .foo 00000001
54// CHECK: 10 .bss 0000000254// CHECK: 10 .bss 00000002
55// CHECK: 11 .comment 0000000855// CHECK: 11 .comment 00000008
56// CHECK: 12 .symtab 0000003056// CHECK: 12 .symtab 00000030
deps/lld/test/ELF/section-symbol.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
3// RUN: ld.lld %t -o %t.so -shared -discard-none3// RUN: ld.lld %t -o %t.so -shared -discard-none
4// RUN: llvm-readobj -t %t.so | FileCheck %s4// RUN: llvm-readobj --symbols %t.so | FileCheck %s
55
6// Test that we don't include the section symbols from the .o in the .so6// Test that we don't include the section symbols from the .o in the .so
77
deps/lld/test/ELF/section-symbols.test+8-9
...@@ -24,12 +24,11 @@ Sections:...@@ -24,12 +24,11 @@ Sections:
24 Info: .text24 Info: .text
25 Relocations:25 Relocations:
26Symbols:26Symbols:
27 Local:27 - Type: STT_SECTION
28 - Type: STT_SECTION28 Section: .rela.text
29 Section: .rela.text29 - Type: STT_SECTION
30 - Type: STT_SECTION30 Section: .shstrtab
31 Section: .shstrtab31 - Type: STT_SECTION
32 - Type: STT_SECTION32 Section: .symtab
33 Section: .symtab33 - Type: STT_SECTION
34 - Type: STT_SECTION34 Section: .strtab
35 Section: .strtab
deps/lld/test/ELF/sectionstart-noallochdr.s+1-1
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5# RUN: llvm-objdump -section-headers %t1 | FileCheck %s5# RUN: llvm-objdump -section-headers %t1 | FileCheck %s
66
7# CHECK: Sections:7# CHECK: Sections:
8# CHECK-NEXT: Idx Name Size Address Type8# CHECK-NEXT: Idx Name Size VMA Type
9# CHECK-NEXT: 0 00000000 00000000000000009# CHECK-NEXT: 0 00000000 0000000000000000
10# CHECK-NEXT: 1 .text 00000001 0000000000000010 TEXT10# CHECK-NEXT: 1 .text 00000001 0000000000000010 TEXT
11# CHECK-NEXT: 2 .data 00000004 0000000000000020 DATA11# CHECK-NEXT: 2 .data 00000004 0000000000000020 DATA
deps/lld/test/ELF/sectionstart.s+4-4
...@@ -5,7 +5,7 @@...@@ -5,7 +5,7 @@
5# RUN: llvm-objdump -section-headers %t | FileCheck %s5# RUN: llvm-objdump -section-headers %t | FileCheck %s
66
7# CHECK: Sections:7# CHECK: Sections:
8# CHECK-NEXT: Idx Name Size Address Type8# CHECK-NEXT: Idx Name Size VMA Type
9# CHECK-NEXT: 0 00000000 00000000000000009# CHECK-NEXT: 0 00000000 0000000000000000
10# CHECK-NEXT: 1 .text 00000001 0000000000100000 TEXT10# CHECK-NEXT: 1 .text 00000001 0000000000100000 TEXT
11# CHECK-NEXT: 2 .data 00000004 0000000000110000 DATA11# CHECK-NEXT: 2 .data 00000004 0000000000110000 DATA
...@@ -45,15 +45,15 @@...@@ -45,15 +45,15 @@
4545
46# RUN: not ld.lld %t.o -Ttext=1w0000 -o %t6 2>&1 \46# RUN: not ld.lld %t.o -Ttext=1w0000 -o %t6 2>&1 \
47# RUN: | FileCheck -check-prefix=ERR3 %s47# RUN: | FileCheck -check-prefix=ERR3 %s
48# ERR3: invalid argument: --Ttext 1w000048# ERR3: invalid argument: -Ttext=1w0000
4949
50# RUN: not ld.lld %t.o -Tbss=1w0000 -o %t6 2>&1 \50# RUN: not ld.lld %t.o -Tbss=1w0000 -o %t6 2>&1 \
51# RUN: | FileCheck -check-prefix=ERR4 %s51# RUN: | FileCheck -check-prefix=ERR4 %s
52# ERR4: invalid argument: --Tbss 1w000052# ERR4: invalid argument: -Tbss=1w0000
5353
54# RUN: not ld.lld %t.o -Tdata=1w0000 -o %t6 2>&1 \54# RUN: not ld.lld %t.o -Tdata=1w0000 -o %t6 2>&1 \
55# RUN: | FileCheck -check-prefix=ERR5 %s55# RUN: | FileCheck -check-prefix=ERR5 %s
56# ERR5: invalid argument: --Tdata 1w000056# ERR5: invalid argument: -Tdata=1w0000
5757
58.text58.text
59.globl _start59.globl _start
deps/lld/test/ELF/segments.s+46-2
...@@ -84,7 +84,7 @@...@@ -84,7 +84,7 @@
8484
85# OMAGIC: ProgramHeader {85# OMAGIC: ProgramHeader {
86# OMAGIC: Type: PT_LOAD86# OMAGIC: Type: PT_LOAD
87# OMAGIC-NEXT: Offset: 0x087# OMAGIC-NEXT: Offset: 0xE8
88# OMAGIC-NEXT: VirtualAddress:88# OMAGIC-NEXT: VirtualAddress:
89# OMAGIC-NEXT: PhysicalAddress:89# OMAGIC-NEXT: PhysicalAddress:
90# OMAGIC-NEXT: FileSize:90# OMAGIC-NEXT: FileSize:
...@@ -94,11 +94,55 @@...@@ -94,11 +94,55 @@
94# OMAGIC-NEXT: PF_W94# OMAGIC-NEXT: PF_W
95# OMAGIC-NEXT: PF_X95# OMAGIC-NEXT: PF_X
96# OMAGIC-NEXT: ]96# OMAGIC-NEXT: ]
97# OMAGIC-NEXT: Alignment: 409697# OMAGIC-NEXT: Alignment: 8
98# OMAGIC-NEXT: }98# OMAGIC-NEXT: }
99# OMAGIC-NEXT: ProgramHeader {99# OMAGIC-NEXT: ProgramHeader {
100# OMAGIC-NEXT: Type: PT_GNU_STACK100# OMAGIC-NEXT: Type: PT_GNU_STACK
101101
102# RUN: ld.lld -n %t -o %t4
103# RUN: llvm-readobj --program-headers %t4 | FileCheck --check-prefix=NMAGIC %s
104# RUN: ld.lld --nmagic %t -o %t4
105# RUN: llvm-readobj --program-headers %t4 | FileCheck --check-prefix=NMAGIC %s
106
107# NMAGIC: ProgramHeader {
108# NMAGIC-NEXT: Type: PT_LOAD
109# NMAGIC-NEXT: Offset: 0x158
110# NMAGIC-NEXT: VirtualAddress:
111# NMAGIC-NEXT: PhysicalAddress:
112# NMAGIC-NEXT: FileSize: 1
113# NMAGIC-NEXT: MemSize: 1
114# NMAGIC-NEXT: Flags [
115# NMAGIC-NEXT: PF_R
116# NMAGIC-NEXT: ]
117# NMAGIC-NEXT: Alignment: 8
118# NMAGIC-NEXT: }
119# NMAGIC-NEXT: ProgramHeader {
120# NMAGIC-NEXT: Type: PT_LOAD
121# NMAGIC-NEXT: Offset: 0x15C
122# NMAGIC-NEXT: VirtualAddress:
123# NMAGIC-NEXT: PhysicalAddress:
124# NMAGIC-NEXT: FileSize: 2
125# NMAGIC-NEXT: MemSize: 2
126# NMAGIC-NEXT: Flags [
127# NMAGIC-NEXT: PF_R
128# NMAGIC-NEXT: PF_X
129# NMAGIC-NEXT: ]
130# NMAGIC-NEXT: Alignment: 4
131# NMAGIC-NEXT: }
132# NMAGIC-NEXT: ProgramHeader {
133# NMAGIC-NEXT: Type: PT_LOAD (0x1)
134# NMAGIC-NEXT: Offset: 0x15E
135# NMAGIC-NEXT: VirtualAddress:
136# NMAGIC-NEXT: PhysicalAddress:
137# NMAGIC-NEXT: FileSize: 1
138# NMAGIC-NEXT: MemSize: 1
139# NMAGIC-NEXT: Flags [
140# NMAGIC-NEXT: PF_R
141# NMAGIC-NEXT: PF_W
142# NMAGIC-NEXT: ]
143# NMAGIC-NEXT: Alignment: 1
144# NMAGIC-NEXT: }
145
102.global _start146.global _start
103_start:147_start:
104 nop148 nop
deps/lld/test/ELF/shared-ppc64.s+5-5
...@@ -4,13 +4,13 @@...@@ -4,13 +4,13 @@
4// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared.s -o %t2.o4// RUN: llvm-mc -filetype=obj -triple=powerpc64le-unknown-linux %p/Inputs/shared.s -o %t2.o
5// RUN: ld.lld -shared %t2.o -o %t2.so5// RUN: ld.lld -shared %t2.o -o %t2.so
6// RUN: ld.lld -dynamic-linker /lib64/ld64.so.1 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t6// RUN: ld.lld -dynamic-linker /lib64/ld64.so.1 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t
7// RUN: llvm-readobj --dynamic-table -s %t | FileCheck %s7// RUN: llvm-readobj --dynamic-table -S %t | FileCheck %s
88
9// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o9// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %s -o %t.o
10// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared.s -o %t2.o10// RUN: llvm-mc -filetype=obj -triple=powerpc64-unknown-linux %p/Inputs/shared.s -o %t2.o
11// RUN: ld.lld -shared %t2.o -o %t2.so11// RUN: ld.lld -shared %t2.o -o %t2.so
12// RUN: ld.lld -dynamic-linker /lib64/ld64.so.1 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t12// RUN: ld.lld -dynamic-linker /lib64/ld64.so.1 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t
13// RUN: llvm-readobj --dynamic-table -s %t | FileCheck %s13// RUN: llvm-readobj --dynamic-table -S %t | FileCheck %s
1414
15// CHECK: Name: .rela.dyn15// CHECK: Name: .rela.dyn
16// CHECK-NEXT: Type: SHT_REL16// CHECK-NEXT: Type: SHT_REL
...@@ -27,7 +27,7 @@...@@ -27,7 +27,7 @@
2727
28// CHECK: DynamicSection [28// CHECK: DynamicSection [
29// CHECK-NEXT: Tag Type Name/Value29// CHECK-NEXT: Tag Type Name/Value
30// CHECK-NEXT: 0x000000000000001D RUNPATH foo:bar30// CHECK-NEXT: 0x000000000000001D RUNPATH Library runpath: [foo:bar]
31// CHECK-NEXT: 0x0000000000000001 NEEDED Shared library: [{{.*}}2.so]31// CHECK-NEXT: 0x0000000000000001 NEEDED Shared library: [{{.*}}2.so]
32// CHECK-NEXT: 0x0000000000000015 DEBUG 0x032// CHECK-NEXT: 0x0000000000000015 DEBUG 0x0
33// CHECK-NEXT: 0x0000000000000007 RELA [[RELADDR]]33// CHECK-NEXT: 0x0000000000000007 RELA [[RELADDR]]
...@@ -39,6 +39,6 @@...@@ -39,6 +39,6 @@
39.global _start39.global _start
40_start:40_start:
41.data41.data
42.long bar42.quad bar
43.long zed43.quad zed
4444
deps/lld/test/ELF/shared.s+5-5
...@@ -2,11 +2,11 @@...@@ -2,11 +2,11 @@
2// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %s -o %t.o
3// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/shared.s -o %t2.o
4// RUN: ld.lld --hash-style=sysv -shared %t2.o -o %t2.so4// RUN: ld.lld --hash-style=sysv -shared %t2.o -o %t2.so
5// RUN: llvm-readobj -s %t2.so | FileCheck --check-prefix=SO %s5// RUN: llvm-readobj -S %t2.so | FileCheck --check-prefix=SO %s
6// RUN: ld.lld --hash-style=sysv -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t6// RUN: ld.lld --hash-style=sysv -dynamic-linker /lib64/ld-linux-x86-64.so.2 -rpath foo -rpath bar --export-dynamic %t.o %t2.so -o %t
7// RUN: llvm-readobj --program-headers --dynamic-table -t -s -dyn-symbols -section-data -hash-table %t | FileCheck %s7// RUN: llvm-readobj --program-headers --dynamic-table --symbols -S --dyn-syms --section-data --hash-table %t | FileCheck %s
8// RUN: ld.lld --hash-style=sysv %t.o %t2.so %t2.so -o %t28// RUN: ld.lld --hash-style=sysv %t.o %t2.so %t2.so -o %t2
9// RUN: llvm-readobj -dyn-symbols %t2 | FileCheck --check-prefix=DONT_EXPORT %s9// RUN: llvm-readobj --dyn-syms %t2 | FileCheck --check-prefix=DONT_EXPORT %s
1010
11// Make sure .symtab is properly aligned.11// Make sure .symtab is properly aligned.
12// SO: Name: .symtab12// SO: Name: .symtab
...@@ -46,7 +46,7 @@...@@ -46,7 +46,7 @@
46// CHECK-NEXT: SHF_ALLOC46// CHECK-NEXT: SHF_ALLOC
47// CHECK-NEXT: ]47// CHECK-NEXT: ]
48// CHECK-NEXT: Address: [[DYNSYMADDR:.*]]48// CHECK-NEXT: Address: [[DYNSYMADDR:.*]]
49// CHECK-NEXT: Offset: 0x15049// CHECK-NEXT: Offset: 0x170
50// CHECK-NEXT: Size:50// CHECK-NEXT: Size:
51// CHECK-NEXT: Link: [[DYNSTR:.*]]51// CHECK-NEXT: Link: [[DYNSTR:.*]]
52// CHECK-NEXT: Info: 152// CHECK-NEXT: Info: 1
...@@ -250,7 +250,7 @@...@@ -250,7 +250,7 @@
250250
251// CHECK: DynamicSection [251// CHECK: DynamicSection [
252// CHECK-NEXT: Tag Type Name/Value252// CHECK-NEXT: Tag Type Name/Value
253// CHECK-NEXT: 0x0000001D RUNPATH foo:bar253// CHECK-NEXT: 0x0000001D RUNPATH Library runpath: [foo:bar]
254// CHECK-NEXT: 0x00000001 NEEDED Shared library: [{{.*}}2.so]254// CHECK-NEXT: 0x00000001 NEEDED Shared library: [{{.*}}2.so]
255// CHECK-NEXT: 0x00000015 DEBUG 0x0255// CHECK-NEXT: 0x00000015 DEBUG 0x0
256// CHECK-NEXT: 0x00000011 REL [[RELADDR]]256// CHECK-NEXT: 0x00000011 REL [[RELADDR]]
deps/lld/test/ELF/shf-info-link.test+3-3
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# RUN: yaml2obj %s -o %t.o1# RUN: yaml2obj %s -o %t.o
2# RUN: yaml2obj %S/Inputs/shf-info-link.test -o %t2.o2# RUN: yaml2obj %S/Inputs/shf-info-link.test -o %t2.o
3# RUN: ld.lld %t.o %t2.o -o %t3.o -r3# RUN: ld.lld %t.o %t2.o -o %t3.o -r
4# RUN: llvm-readobj -s %t3.o | FileCheck %s4# RUN: llvm-readobj -S %t3.o | FileCheck %s
55
6# CHECK-NOT: Name: .rela.text6# CHECK-NOT: Name: .rela.text
7# CHECK: Name: .rela.text7# CHECK: Name: .rela.text
...@@ -28,5 +28,5 @@ Sections:...@@ -28,5 +28,5 @@ Sections:
28 Symbol: foo28 Symbol: foo
29 Type: R_X86_64_6429 Type: R_X86_64_64
30Symbols:30Symbols:
31 Global:31 - Name: foo
32 - Name: foo32 Binding: STB_GLOBAL
deps/lld/test/ELF/sht-group-empty.test+5-5
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: yaml2obj %s -o %t.o1# RUN: yaml2obj %s -o %t.o
2# RUN: ld.lld %t.o %t.o -o %t -r2# RUN: ld.lld %t.o %t.o -o %t -r
3# RUN: llvm-readobj -s %t | FileCheck %s3# RUN: llvm-readobj -S %t | FileCheck %s
44
5# CHECK: Name: .text.foo5# CHECK: Name: .text.foo
6# CHECK: Name: .rela.text.foo6# CHECK: Name: .rela.text.foo
...@@ -49,7 +49,7 @@ Sections:...@@ -49,7 +49,7 @@ Sections:
49 Symbol: bar49 Symbol: bar
50 Type: R_X86_64_6450 Type: R_X86_64_64
51Symbols:51Symbols:
52 Global:52 - Name: foo
53 - Name: foo53 Binding: STB_GLOBAL
54 - Name: bar54 - Name: bar
5555 Binding: STB_GLOBAL
deps/lld/test/ELF/silent-ignore.test+3
...@@ -6,8 +6,11 @@ RUN: -no-allow-shlib-undefined \...@@ -6,8 +6,11 @@ RUN: -no-allow-shlib-undefined \
6RUN: -no-copy-dt-needed-entries \6RUN: -no-copy-dt-needed-entries \
7RUN: -no-ctors-in-init-array \7RUN: -no-ctors-in-init-array \
8RUN: -no-keep-memory \8RUN: -no-keep-memory \
9RUN: -no-pipeline-knowledge \
9RUN: -no-warn-common \10RUN: -no-warn-common \
10RUN: -no-warn-mismatch \11RUN: -no-warn-mismatch \
12RUN: -p \
13RUN: -secure-plt \
11RUN: -sort-common \14RUN: -sort-common \
12RUN: -stats \15RUN: -stats \
13RUN: -warn-execstack \16RUN: -warn-execstack \
deps/lld/test/ELF/sort-norosegment.s+1-1
...@@ -8,8 +8,8 @@...@@ -8,8 +8,8 @@
8# CHECK-NEXT: .hash {{.*}} A8# CHECK-NEXT: .hash {{.*}} A
9# CHECK-NEXT: .dynstr {{.*}} A9# CHECK-NEXT: .dynstr {{.*}} A
10# CHECK-NEXT: .text {{.*}} AX10# CHECK-NEXT: .text {{.*}} AX
11# CHECK-NEXT: foo {{.*}} WA
12# CHECK-NEXT: .dynamic {{.*}} WA11# CHECK-NEXT: .dynamic {{.*}} WA
12# CHECK-NEXT: foo {{.*}} WA
1313
14.section foo, "aw"14.section foo, "aw"
15.byte 015.byte 0
deps/lld/test/ELF/start-lib-comdat.s+2-2
...@@ -4,9 +4,9 @@...@@ -4,9 +4,9 @@
4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux \
5// RUN: %p/Inputs/start-lib-comdat.s -o %t2.o5// RUN: %p/Inputs/start-lib-comdat.s -o %t2.o
6// RUN: ld.lld -shared -o %t3 %t1.o --start-lib %t2.o --end-lib6// RUN: ld.lld -shared -o %t3 %t1.o --start-lib %t2.o --end-lib
7// RUN: llvm-readobj -t %t3 | FileCheck %s7// RUN: llvm-readobj --symbols %t3 | FileCheck %s
8// RUN: ld.lld -shared -o %t3 --start-lib %t2.o --end-lib %t1.o8// RUN: ld.lld -shared -o %t3 --start-lib %t2.o --end-lib %t1.o
9// RUN: llvm-readobj -t %t3 | FileCheck %s9// RUN: llvm-readobj --symbols %t3 | FileCheck %s
1010
11// CHECK: Name: zed11// CHECK: Name: zed
12// CHECK-NEXT: Value:12// CHECK-NEXT: Value:
deps/lld/test/ELF/startstop-gccollect.s+4
...@@ -20,10 +20,14 @@...@@ -20,10 +20,14 @@
20# DISASM: _start:20# DISASM: _start:
21# DISASM-NEXT: 201000: e8 05 00 00 00 callq 5 <__start_foo>21# DISASM-NEXT: 201000: e8 05 00 00 00 callq 5 <__start_foo>
22# DISASM-NEXT: 201005: e8 02 00 00 00 callq 2 <__stop_bar>22# DISASM-NEXT: 201005: e8 02 00 00 00 callq 2 <__stop_bar>
23# DISASM-EMPTY:
23# DISASM-NEXT: Disassembly of section foo:24# DISASM-NEXT: Disassembly of section foo:
25# DISASM-EMPTY:
24# DISASM-NEXT: __start_foo:26# DISASM-NEXT: __start_foo:
25# DISASM-NEXT: 20100a: 90 nop27# DISASM-NEXT: 20100a: 90 nop
28# DISASM-EMPTY:
26# DISASM-NEXT: Disassembly of section bar:29# DISASM-NEXT: Disassembly of section bar:
30# DISASM-EMPTY:
27# DISASM-NEXT: bar:31# DISASM-NEXT: bar:
28# DISASM-NEXT: 20100b: 90 nop32# DISASM-NEXT: 20100b: 90 nop
2933
deps/lld/test/ELF/startstop-shared.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -r -t %t.so | FileCheck %s4// RUN: llvm-readobj -r --symbols %t.so | FileCheck %s
55
6 .data6 .data
7 .quad __start_foo7 .quad __start_foo
deps/lld/test/ELF/startstop.s+5-3
...@@ -2,18 +2,20 @@...@@ -2,18 +2,20 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld --hash-style=sysv %t -o %tout -shared3// RUN: ld.lld --hash-style=sysv %t -o %tout -shared
4// RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s4// RUN: llvm-objdump -d %tout | FileCheck -check-prefix=DISASM %s
5// RUN: llvm-readobj -symbols -r %tout | FileCheck -check-prefix=SYMBOL %s5// RUN: llvm-readobj --symbols -r %tout | FileCheck -check-prefix=SYMBOL %s
66
7// DISASM: _start:7// DISASM: _start:
8// DISASM: 1000: {{.*}} callq 108// DISASM: 1000: {{.*}} callq 10
9// DISASM: 1005: {{.*}} callq 89// DISASM: 1005: {{.*}} callq 8
10// DISASM: 100a: {{.*}} callq 310// DISASM: 100a: {{.*}} callq 3
11// DISASM: Disassembly of section foo:11// DISASM: Disassembly of section foo:
12// DISASM-EMPTY:
12// DISASM: __start_foo:13// DISASM: __start_foo:
13// DISASM: 100f: 90 nop14// DISASM: 100f: 90 nop
14// DISASM: 1010: 90 nop15// DISASM: 1010: 90 nop
15// DISASM: 1011: 90 nop16// DISASM: 1011: 90 nop
16// DISASM: Disassembly of section bar:17// DISASM: Disassembly of section bar:
18// DISASM-EMPTY:
17// DISASM: __start_bar:19// DISASM: __start_bar:
18// DISASM: 1012: 90 nop20// DISASM: 1012: 90 nop
19// DISASM: 1013: 90 nop21// DISASM: 1013: 90 nop
...@@ -50,13 +52,13 @@...@@ -50,13 +52,13 @@
5052
51// SYMBOL: Symbol {53// SYMBOL: Symbol {
52// SYMBOL: Name: __stop_zed154// SYMBOL: Name: __stop_zed1
53// SYMBOL: Value: 0x201055// SYMBOL: Value: 0x3010
54// SYMBOL: STV_PROTECTED56// SYMBOL: STV_PROTECTED
55// SYMBOL: Section: zed157// SYMBOL: Section: zed1
56// SYMBOL: }58// SYMBOL: }
57// SYMBOL: Symbol {59// SYMBOL: Symbol {
58// SYMBOL: Name: __stop_zed260// SYMBOL: Name: __stop_zed2
59// SYMBOL: Value: 0x202061// SYMBOL: Value: 0x3020
60// SYMBOL: STV_PROTECTED62// SYMBOL: STV_PROTECTED
61// SYMBOL: Section: zed263// SYMBOL: Section: zed2
62// SYMBOL: }64// SYMBOL: }
deps/lld/test/ELF/static-with-export-dynamic.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i686-unknown-cloudabi %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i686-unknown-cloudabi %s -o %t.o
3// RUN: ld.lld --export-dynamic %t.o -o %t3// RUN: ld.lld --export-dynamic %t.o -o %t
4// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s4// RUN: llvm-readobj --dyn-syms %t | FileCheck %s
55
6// Ensure that a dynamic symbol table is present when --export-dynamic6// Ensure that a dynamic symbol table is present when --export-dynamic
7// is passed in, even when creating statically linked executables.7// is passed in, even when creating statically linked executables.
deps/lld/test/ELF/stdout.s created+15
...@@ -0,0 +1,15 @@
1# REQUIRES: x86
2
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: ld.lld %t.o -o - > %t1
5# RUN: llvm-objdump -d %t1 | FileCheck %s
6
7# CHECK: 0000000000201000 _start:
8# CHECK: 201000: 90 nop
9
10# RUN: ld.lld %t.o -o %t2
11# RUN: diff %t1 %t2
12
13.globl _start
14_start:
15 nop
deps/lld/test/ELF/string-gc.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t --gc-sections3// RUN: ld.lld %t.o -o %t --gc-sections
4// RUN: llvm-readobj -symbols %t | FileCheck %s4// RUN: llvm-readobj --symbols %t | FileCheck %s
55
6// CHECK: Symbols [6// CHECK: Symbols [
7// CHECK-NEXT: Symbol {7// CHECK-NEXT: Symbol {
deps/lld/test/ELF/string-table.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %t23// RUN: ld.lld %t -o %t2
4// RUN: llvm-readobj -sections %t2 | FileCheck %s4// RUN: llvm-readobj --sections %t2 | FileCheck %s
55
6.global _start6.global _start
7_start:7_start:
deps/lld/test/ELF/strip-debug.s+3-3
...@@ -1,11 +1,11 @@...@@ -1,11 +1,11 @@
1# REQUIRES: x86, zlib1# REQUIRES: x86, zlib
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3# RUN: ld.lld %t -o %t2 --strip-debug3# RUN: ld.lld %t -o %t2 --strip-debug
4# RUN: llvm-readobj -sections %t2 | FileCheck %s4# RUN: llvm-readobj --sections %t2 | FileCheck %s
5# RUN: ld.lld %t -o %t2 -S5# RUN: ld.lld %t -o %t2 -S
6# RUN: llvm-readobj -sections %t2 | FileCheck %s6# RUN: llvm-readobj --sections %t2 | FileCheck %s
7# RUN: ld.lld %t -o %t2 --strip-all7# RUN: ld.lld %t -o %t2 --strip-all
8# RUN: llvm-readobj -sections %t2 | FileCheck %s8# RUN: llvm-readobj --sections %t2 | FileCheck %s
99
10# CHECK-NOT: Foo10# CHECK-NOT: Foo
11# CHECK-NOT: Bar11# CHECK-NOT: Bar
deps/lld/test/ELF/symbol-ordering-file-cgprofile-conflicts.s created+66
...@@ -0,0 +1,66 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3// RUN: ld.lld -e A %t.o --no-call-graph-profile-sort -o %t
4// RUN: llvm-nm --numeric-sort %t | FileCheck %s --check-prefix=NO_ORDERING
5// NO_ORDERING: 0000000000201000 t D
6// NO_ORDERING-NEXT: 0000000000201001 T C
7// NO_ORDERING-NEXT: 0000000000201002 T B
8// NO_ORDERING-NEXT: 0000000000201003 T A
9
10// RUN: ld.lld -e A %t.o -o %t
11// RUN: llvm-nm --numeric-sort %t | FileCheck %s --check-prefix=CALL_GRAPH
12// CALL_GRAPH: 0000000000201000 T A
13// CALL_GRAPH-NEXT: 0000000000201000 t Aa
14// CALL_GRAPH-NEXT: 0000000000201001 T B
15// CALL_GRAPH-NEXT: 0000000000201002 T C
16// CALL_GRAPH-NEXT: 0000000000201003 t D
17
18// RUN: rm -f %t.symbol_order
19// RUN: echo "C" >> %t.symbol_order
20// RUN: echo "B" >> %t.symbol_order
21// RUN: echo "D" >> %t.symbol_order
22// RUN: echo "A" >> %t.symbol_order
23
24// RUN: ld.lld -e A %t.o --symbol-ordering-file %t.symbol_order -o %t
25// RUN: llvm-nm --numeric-sort %t | FileCheck %s --check-prefix=SYMBOL_ORDER
26// SYMBOL_ORDER: 0000000000201000 T C
27// SYMBOL_ORDER-NEXT: 0000000000201001 T B
28// SYMBOL_ORDER-NEXT: 0000000000201002 t D
29// SYMBOL_ORDER-NEXT: 0000000000201003 T A
30
31// RUN: rm -f %t.call_graph
32// RUN: echo "A B 5" > %t.call_graph
33// RUN: echo "B C 50" >> %t.call_graph
34// RUN: echo "C D 40" >> %t.call_graph
35// RUN: echo "D B 10" >> %t.call_graph
36
37// RUN: not ld.lld -e A %t.o --symbol-ordering-file %t.symbol_order --call-graph-ordering-file %t.call_graph -o %t 2>&1 | FileCheck %s
38// RUN: not ld.lld -e A %t.o --call-graph-ordering-file %t.call_graph --symbol-ordering-file %t.symbol_order -o %t 2>&1 | FileCheck %s
39// CHECK: error: --symbol-ordering-file and --call-graph-order-file may not be used together
40
41 .section .text.D,"ax",@progbits
42D:
43 retq
44
45 .section .text.C,"ax",@progbits
46 .globl C
47C:
48 retq
49
50 .section .text.B,"ax",@progbits
51 .globl B
52B:
53 retq
54
55 .section .text.A,"ax",@progbits
56 .globl A
57A:
58Aa:
59 retq
60
61 .cg_profile A, B, 10
62 .cg_profile A, B, 10
63 .cg_profile Aa, B, 80
64 .cg_profile A, C, 40
65 .cg_profile B, C, 30
66 .cg_profile C, D, 90
deps/lld/test/ELF/symbol-override.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/symbol-override.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/symbol-override.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t2.so4// RUN: ld.lld -shared %t2.o -o %t2.so
5// RUN: ld.lld %t1.o %t2.so -o %t5// RUN: ld.lld %t1.o %t2.so -o %t
6// RUN: llvm-readobj -dyn-symbols %t | FileCheck %s6// RUN: llvm-readobj --dyn-syms %t | FileCheck %s
77
8// CHECK: DynamicSymbols [8// CHECK: DynamicSymbols [
9// CHECK-NEXT: Symbol {9// CHECK-NEXT: Symbol {
deps/lld/test/ELF/symbols.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %t23// RUN: ld.lld %t -o %t2
4// RUN: llvm-readobj -symbols -sections %t2 | FileCheck %s4// RUN: llvm-readobj --symbols --sections %t2 | FileCheck %s
55
6.type _start, @function6.type _start, @function
7.globl _start7.globl _start
deps/lld/test/ELF/synthetic-got.s+7-7
...@@ -7,13 +7,13 @@...@@ -7,13 +7,13 @@
7# RUN: | FileCheck %s --check-prefix=GOTDATA7# RUN: | FileCheck %s --check-prefix=GOTDATA
88
9# GOT: Sections:9# GOT: Sections:
10# GOT: 8 .got.plt 00000020 00000000000000e0 DATA10# GOT: 9 .got 00000008 00000000000001b0 DATA
11# GOT: 10 .got 00000008 00000000000001d0 DATA11# GOT: 10 .got.plt 00000020 00000000000001b8 DATA
12# GOTDATA: Contents of section .got.plt:12# GOTDATA: Contents of section .got:
13# GOTDATA-NEXT: 00e0 00010000 00000000 00000000 0000000013# GOTDATA-NEXT: 01b0 00000000 00000000
14# GOTDATA-NEXT: 00f0 00000000 00000000 d6000000 0000000014# GOTDATA-NEXT: Contents of section .got.plt:
15# GOTDATA-NEXT: Contents of section .got:15# GOTDATA-NEXT: 01b8 e0000000 00000000 00000000 00000000
16# GOTDATA-NEXT: 01d0 00000000 0000000016# GOTDATA-NEXT: 01c8 00000000 00000000 d6000000 00000000
1717
18# RUN: echo "SECTIONS { .mygot : { *(.got) *(.got.plt) } }" > %t1.script18# RUN: echo "SECTIONS { .mygot : { *(.got) *(.got.plt) } }" > %t1.script
19# RUN: ld.lld --hash-style=sysv -shared %t.o -o %t1.out --script %t1.script19# RUN: ld.lld --hash-style=sysv -shared %t.o -o %t1.out --script %t1.script
deps/lld/test/ELF/sysv-hash-no-rosegment.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld -shared --no-rosegment -o %t %t.o3# RUN: ld.lld -shared --no-rosegment -o %t %t.o
4# RUN: llvm-readobj -hash-table %t | FileCheck %s4# RUN: llvm-readobj --hash-table %t | FileCheck %s
55
6# CHECK: HashTable {6# CHECK: HashTable {
7# CHECK-NEXT: Num Buckets: 27# CHECK-NEXT: Num Buckets: 2
deps/lld/test/ELF/tail-merge-string-align.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared -O33// RUN: ld.lld %t.o -o %t.so -shared -O3
4// RUN: llvm-readobj -s -section-data %t.so | FileCheck %s4// RUN: llvm-readobj -S --section-data %t.so | FileCheck %s
55
6 .section .rodata.4a,"aMS",@progbits,16 .section .rodata.4a,"aMS",@progbits,1
7 .align 47 .align 4
deps/lld/test/ELF/tls-align.s deleted-21
...@@ -1,21 +0,0 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %tout -shared
4// RUN: llvm-readobj -program-headers %tout | FileCheck %s
5
6 .section .tbss,"awT",@nobits
7 .align 8
8 .long 0
9
10// CHECK: ProgramHeader {
11// CHECK: Type: PT_TLS
12// CHECK-NEXT: Offset:
13// CHECK-NEXT: VirtualAddress:
14// CHECK-NEXT: PhysicalAddress:
15// CHECK-NEXT: FileSize: 0
16// CHECK-NEXT: MemSize: 8
17// CHECK-NEXT: Flags [
18// CHECK-NEXT: PF_R (0x4)
19// CHECK-NEXT: ]
20// CHECK-NEXT: Alignment: 8
21// CHECK-NEXT: }
deps/lld/test/ELF/tls-dynamic-i686.s+26-25
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t
3// RUN: ld.lld --hash-style=sysv -shared %t -o %tout3// RUN: ld.lld --hash-style=sysv -shared -z norelro %t -o %tout
4// RUN: llvm-readobj -sections -relocations %tout | FileCheck %s4// RUN: llvm-readobj --sections -r %tout | FileCheck %s
5// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS5// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS
66
7.type tls0,@object7.type tls0,@object
...@@ -56,8 +56,8 @@ addl tls1@gotntpoff(%ebx),%eax...@@ -56,8 +56,8 @@ addl tls1@gotntpoff(%ebx),%eax
56// CHECK-NEXT: SHF_ALLOC56// CHECK-NEXT: SHF_ALLOC
57// CHECK-NEXT: SHF_WRITE57// CHECK-NEXT: SHF_WRITE
58// CHECK-NEXT: ]58// CHECK-NEXT: ]
59// CHECK-NEXT: Address: 0x306859// CHECK-NEXT: Address: 0x2070
60// CHECK-NEXT: Offset: 0x306860// CHECK-NEXT: Offset: 0x2070
61// CHECK-NEXT: Size: 3261// CHECK-NEXT: Size: 32
62// CHECK-NEXT: Link: 062// CHECK-NEXT: Link: 0
63// CHECK-NEXT: Info: 063// CHECK-NEXT: Info: 0
...@@ -66,34 +66,35 @@ addl tls1@gotntpoff(%ebx),%eax...@@ -66,34 +66,35 @@ addl tls1@gotntpoff(%ebx),%eax
6666
67// CHECK: Relocations [67// CHECK: Relocations [
68// CHECK: Section ({{.+}}) .rel.dyn {68// CHECK: Section ({{.+}}) .rel.dyn {
69// CHECK-NEXT: 0x3078 R_386_TLS_DTPMOD32 - 0x069// CHECK-NEXT: 0x2080 R_386_TLS_DTPMOD32 - 0x0
70// CHECK-NEXT: 0x3068 R_386_TLS_DTPMOD32 tls0 0x070// CHECK-NEXT: 0x2070 R_386_TLS_DTPMOD32 tls0 0x0
71// CHECK-NEXT: 0x306C R_386_TLS_DTPOFF32 tls0 0x071// CHECK-NEXT: 0x2074 R_386_TLS_DTPOFF32 tls0 0x0
72// CHECK-NEXT: 0x3080 R_386_TLS_TPOFF tls0 0x072// CHECK-NEXT: 0x2088 R_386_TLS_TPOFF tls0 0x0
73// CHECK-NEXT: 0x3070 R_386_TLS_DTPMOD32 tls1 0x073// CHECK-NEXT: 0x2078 R_386_TLS_DTPMOD32 tls1 0x0
74// CHECK-NEXT: 0x3074 R_386_TLS_DTPOFF32 tls1 0x074// CHECK-NEXT: 0x207C R_386_TLS_DTPOFF32 tls1 0x0
75// CHECK-NEXT: 0x3084 R_386_TLS_TPOFF tls1 0x075// CHECK-NEXT: 0x208C R_386_TLS_TPOFF tls1 0x0
76// CHECK-NEXT: }76// CHECK-NEXT: }
7777
78// DIS: Disassembly of section .text:78// DIS: Disassembly of section .text:
79// DIS-EMPTY:
79// DIS-NEXT: _start:80// DIS-NEXT: _start:
80// General dynamic model:81// General dynamic model:
81// -32 and -24 are first and second GOT entries offsets.82// -32 and -24 are first and second GOT entries offsets.
82// Each one is a pair of records.83// Each one is a pair of records.
83// DIS-NEXT: 1000: 8d 04 1d e0 ff ff ff leal -32(,%ebx), %eax84// DIS-NEXT: 1000: {{.*}} leal -32(,%ebx), %eax
84// DIS-NEXT: 1007: e8 64 00 00 00 calll 10085// DIS-NEXT: 1007: {{.*}} calll 100
85// DIS-NEXT: 100c: 8d 04 1d e8 ff ff ff leal -24(,%ebx), %eax86// DIS-NEXT: 100c: {{.*}} leal -24(,%ebx), %eax
86// DIS-NEXT: 1013: e8 58 00 00 00 calll 8887// DIS-NEXT: 1013: {{.*}} calll 88
87// Local dynamic model:88// Local dynamic model:
88// -16 is a local module tls index offset.89// -16 is a local module tls index offset.
89// DIS-NEXT: 1018: 8d 83 f0 ff ff ff leal -16(%ebx), %eax90// DIS-NEXT: 1018: {{.*}} leal -16(%ebx), %eax
90// DIS-NEXT: 101e: e8 4d 00 00 00 calll 7791// DIS-NEXT: 101e: {{.*}} calll 77
91// DIS-NEXT: 1023: 8d 90 08 00 00 00 leal 8(%eax), %edx92// DIS-NEXT: 1023: {{.*}} leal 8(%eax), %edx
92// DIS-NEXT: 1029: 8d 83 f0 ff ff ff leal -16(%ebx), %eax93// DIS-NEXT: 1029: {{.*}} leal -16(%ebx), %eax
93// DIS-NEXT: 102f: e8 3c 00 00 00 calll 6094// DIS-NEXT: 102f: {{.*}} calll 60
94// DIS-NEXT: 1034: 8d 90 0c 00 00 00 leal 12(%eax), %edx95// DIS-NEXT: 1034: {{.*}} leal 12(%eax), %edx
95// Initial exec model:96// Initial exec model:
96// DIS-NEXT: 103a: 65 a1 00 00 00 00 movl %gs:0, %eax97// DIS-NEXT: 103a: {{.*}} movl %gs:0, %eax
97// DIS-NEXT: 1040: 03 83 f8 ff ff ff addl -8(%ebx), %eax98// DIS-NEXT: 1040: {{.*}} addl -8(%ebx), %eax
98// DIS-NEXT: 1046: 65 a1 00 00 00 00 movl %gs:0, %eax99// DIS-NEXT: 1046: {{.*}} movl %gs:0, %eax
99// DIS-NEXT: 104c: 03 83 fc ff ff ff addl -4(%ebx), %eax100// DIS-NEXT: 104c: {{.*}} addl -4(%ebx), %eax
deps/lld/test/ELF/tls-dynamic.s+15-14
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld --hash-style=sysv -shared %t -o %tout3// RUN: ld.lld --hash-style=sysv -shared %t -o %tout
4// RUN: llvm-readobj -sections -relocations %tout | FileCheck %s4// RUN: llvm-readobj --sections -r %tout | FileCheck %s
5// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS5// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS
66
7 leaq a@tlsld(%rip), %rdi7 leaq a@tlsld(%rip), %rdi
...@@ -48,28 +48,29 @@ c:...@@ -48,28 +48,29 @@ c:
48// CHECK-NEXT: SHF_ALLOC48// CHECK-NEXT: SHF_ALLOC
49// CHECK-NEXT: SHF_WRITE49// CHECK-NEXT: SHF_WRITE
50// CHECK-NEXT: ]50// CHECK-NEXT: ]
51// CHECK-NEXT: Address: 0x30D051// CHECK-NEXT: Address: 0x20E0
52// CHECK-NEXT: Offset:52// CHECK-NEXT: Offset:
53// CHECK-NEXT: Size: 4053// CHECK-NEXT: Size: 40
5454
55// CHECK: Relocations [55// CHECK: Relocations [
56// CHECK: Section ({{.+}}) .rela.dyn {56// CHECK: Section ({{.+}}) .rela.dyn {
57// CHECK-NEXT: 0x30D0 R_X86_64_DTPMOD64 - 0x057// CHECK-NEXT: 0x20E0 R_X86_64_DTPMOD64 - 0x0
58// CHECK-NEXT: 0x30E0 R_X86_64_DTPMOD64 c 0x058// CHECK-NEXT: 0x20F0 R_X86_64_DTPMOD64 c 0x0
59// CHECK-NEXT: 0x30E8 R_X86_64_DTPOFF64 c 0x059// CHECK-NEXT: 0x20F8 R_X86_64_DTPOFF64 c 0x0
60// CHECK-NEXT: 0x30F0 R_X86_64_TPOFF64 c 0x060// CHECK-NEXT: 0x2100 R_X86_64_TPOFF64 c 0x0
61// CHECK-NEXT: }61// CHECK-NEXT: }
6262
63// 4297 = (0x20D0 + -4) - (0x1000 + 3) // PC relative offset to got entry.63// 4313 = (0x20E0 + -4) - (0x1000 + 3) // PC relative offset to got entry.
64// 4285 = (0x20D0 + -4) - (0x100c + 3) // PC relative offset to got entry.64// 4301 = (0x20F0 + -4) - (0x100c + 3) // PC relative offset to got entry.
65// 4267 = (0x20E0 + -4) - (0x102e + 3) // PC relative offset to got entry.65// 4283 = (0x20F8 + -4) - (0x102e + 3) // PC relative offset to got entry.
66// 4263 = (0x20F0 + -4) - (0x1042 + 3) // PC relative offset to got entry.66// 4279 = (0x2100 + -4) - (0x1042 + 3) // PC relative offset to got entry.
6767
68// DIS: Disassembly of section .text:68// DIS: Disassembly of section .text:
69// DIS-EMPTY:
69// DIS-NEXT: .text:70// DIS-NEXT: .text:
70// DIS-NEXT: 1000: {{.+}} leaq 8393(%rip), %rdi71// DIS-NEXT: 1000: {{.+}} leaq 4313(%rip), %rdi
71// DIS-NEXT: 1007: {{.+}} callq72// DIS-NEXT: 1007: {{.+}} callq
72// DIS-NEXT: 100c: {{.+}} leaq 8381(%rip), %rdi73// DIS-NEXT: 100c: {{.+}} leaq 4301(%rip), %rdi
73// DIS-NEXT: 1013: {{.+}} callq74// DIS-NEXT: 1013: {{.+}} callq
74// DIS-NEXT: 1018: {{.+}} leaq (%rax), %rcx75// DIS-NEXT: 1018: {{.+}} leaq (%rax), %rcx
75// DIS-NEXT: 101f: {{.+}} leaq 4(%rax), %rcx76// DIS-NEXT: 101f: {{.+}} leaq 4(%rax), %rcx
...@@ -77,10 +78,10 @@ c:...@@ -77,10 +78,10 @@ c:
77// DIS-NEXT: 1028: 00 0078// DIS-NEXT: 1028: 00 00
78// DIS-NEXT: 102a: 00 0079// DIS-NEXT: 102a: 00 00
79// DIS-NEXT: 102c: 00 0080// DIS-NEXT: 102c: 00 00
80// DIS-NEXT: 102e: {{.+}} leaq 8363(%rip), %rdi81// DIS-NEXT: 102e: {{.+}} leaq 4283(%rip), %rdi
81// DIS-NEXT: 1035: {{.+}} callq82// DIS-NEXT: 1035: {{.+}} callq
82// DIS-NEXT: 103b: {{.+}} leaq (%rax), %rcx83// DIS-NEXT: 103b: {{.+}} leaq (%rax), %rcx
83// DIS-NEXT: 1042: {{.+}} movq 8359(%rip), %rax84// DIS-NEXT: 1042: {{.+}} movq 4279(%rip), %rax
84// DIS-NEXT: 1049: {{.+}} movq %fs:(%rax), %rax85// DIS-NEXT: 1049: {{.+}} movq %fs:(%rax), %rax
85// DIS-NEXT: 104d: {{.+}} movabsq $0, %rax86// DIS-NEXT: 104d: {{.+}} movabsq $0, %rax
86// DIS-NEXT: 1057: {{.+}} movabsq $4, %rax87// DIS-NEXT: 1057: {{.+}} movabsq $4, %rax
deps/lld/test/ELF/tls-got.s+17-16
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-got.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-got.s -o %t2.o
4// RUN: ld.lld -shared %t2.o -o %t2.so4// RUN: ld.lld -shared %t2.o -o %t2.so
5// RUN: ld.lld --hash-style=sysv -e main %t1.o %t2.so -o %t35// RUN: ld.lld --hash-style=sysv -e main %t1.o %t2.so -o %t3
6// RUN: llvm-readobj -s -r %t3 | FileCheck %s6// RUN: llvm-readobj -S -r %t3 | FileCheck %s
7// RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM %s7// RUN: llvm-objdump -d %t3 | FileCheck --check-prefix=DISASM %s
88
9// CHECK: Section {9// CHECK: Section {
...@@ -15,7 +15,7 @@...@@ -15,7 +15,7 @@
15// CHECK-NEXT: SHF_WRITE15// CHECK-NEXT: SHF_WRITE
16// CHECK-NEXT: ]16// CHECK-NEXT: ]
17// CHECK-NEXT: Address: [[ADDR:.*]]17// CHECK-NEXT: Address: [[ADDR:.*]]
18// CHECK-NEXT: Offset: 0x20B018// CHECK-NEXT: Offset: 0x20C0
19// CHECK-NEXT: Size: 1619// CHECK-NEXT: Size: 16
20// CHECK-NEXT: Link: 020// CHECK-NEXT: Link: 0
21// CHECK-NEXT: Info: 021// CHECK-NEXT: Info: 0
...@@ -25,23 +25,24 @@...@@ -25,23 +25,24 @@
2525
26// CHECK: Relocations [26// CHECK: Relocations [
27// CHECK-NEXT: Section (4) .rela.dyn {27// CHECK-NEXT: Section (4) .rela.dyn {
28// CHECK-NEXT: 0x2020B8 R_X86_64_TPOFF64 tls0 0x028// CHECK-NEXT: 0x2020C8 R_X86_64_TPOFF64 tls0 0x0
29// CHECK-NEXT: 0x2020B0 R_X86_64_TPOFF64 tls1 0x029// CHECK-NEXT: [[ADDR]] R_X86_64_TPOFF64 tls1 0x0
30// CHECK-NEXT: }30// CHECK-NEXT: }
31// CHECK-NEXT: ]31// CHECK-NEXT: ]
3232
33//0x201000 + 4265 + 7 = 0x2020B033// 0x201000 + 4281 + 7 = 0x2020C0
34//0x20100A + 4263 + 7 = 0x2020B834// 0x20100A + 4279 + 7 = 0x2020C8
35//0x201014 + 4253 + 7 = 0x2020B835// 0x201014 + 4269 + 7 = 0x2020C8
36//DISASM: Disassembly of section .text:36// DISASM: Disassembly of section .text:
37//DISASM-NEXT: main:37// DISASM-EMPTY:
38//DISASM-NEXT: 201000: 48 8b 05 a9 10 00 00 movq 4265(%rip), %rax38// DISASM-NEXT: main:
39//DISASM-NEXT: 201007: 64 8b 00 movl %fs:(%rax), %eax39// DISASM-NEXT: 201000: {{.*}} movq 4281(%rip), %rax
40//DISASM-NEXT: 20100a: 48 8b 05 a7 10 00 00 movq 4263(%rip), %rax40// DISASM-NEXT: 201007: {{.*}} movl %fs:(%rax), %eax
41//DISASM-NEXT: 201011: 64 8b 00 movl %fs:(%rax), %eax41// DISASM-NEXT: 20100a: {{.*}} movq 4279(%rip), %rax
42//DISASM-NEXT: 201014: 48 8b 05 9d 10 00 00 movq 4253(%rip), %rax42// DISASM-NEXT: 201011: {{.*}} movl %fs:(%rax), %eax
43//DISASM-NEXT: 20101b: 64 8b 00 movl %fs:(%rax), %eax43// DISASM-NEXT: 201014: {{.*}} movq 4269(%rip), %rax
44//DISASM-NEXT: 20101e: c3 retq44// DISASM-NEXT: 20101b: {{.*}} movl %fs:(%rax), %eax
45// DISASM-NEXT: 20101e: {{.*}} retq
4546
46.section .tdata,"awT",@progbits47.section .tdata,"awT",@progbits
4748
deps/lld/test/ELF/tls-i686.s+2
...@@ -31,6 +31,7 @@ _start:...@@ -31,6 +31,7 @@ _start:
31 leal var1@ntpoff+123(%ecx), %eax31 leal var1@ntpoff+123(%ecx), %eax
3232
33// DIS: Disassembly of section test:33// DIS: Disassembly of section test:
34// DIS-EMPTY:
34// DIS-NEXT: _start:35// DIS-NEXT: _start:
35// DIS-NEXT: 401000: ba 08 00 00 00 movl $8, %edx36// 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, %ecx37// DIS-NEXT: 401005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
...@@ -47,6 +48,7 @@ _start:...@@ -47,6 +48,7 @@ _start:
47// RELOC-NEXT: ]48// RELOC-NEXT: ]
4849
49// DISSHARED: Disassembly of section test:50// DISSHARED: Disassembly of section test:
51// DISSHARED-EMPTY:
50// DISSHARED-NEXT: _start:52// DISSHARED-NEXT: _start:
51// DISSHARED-NEXT: 1000: ba 00 00 00 00 movl $0, %edx53// DISSHARED-NEXT: 1000: ba 00 00 00 00 movl $0, %edx
52// DISSHARED-NEXT: 1005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx54// DISSHARED-NEXT: 1005: 65 8b 0d 00 00 00 00 movl %gs:0, %ecx
deps/lld/test/ELF/tls-initial-exec-local.s+9-8
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld --hash-style=sysv -shared %t.o -o %t3// RUN: ld.lld --hash-style=sysv -shared %t.o -o %t
4// RUN: llvm-readobj -r -s %t | FileCheck %s4// RUN: llvm-readobj -r -S %t | FileCheck %s
5// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s5// RUN: llvm-objdump -d %t | FileCheck --check-prefix=DISASM %s
66
7// CHECK: Name: .got7// CHECK: Name: .got
...@@ -10,21 +10,22 @@...@@ -10,21 +10,22 @@
10// CHECK-NEXT: SHF_ALLOC (0x2)10// CHECK-NEXT: SHF_ALLOC (0x2)
11// CHECK-NEXT: SHF_WRITE (0x1)11// CHECK-NEXT: SHF_WRITE (0x1)
12// CHECK-NEXT: ]12// CHECK-NEXT: ]
13// CHECK-NEXT: Address: 0x209013// CHECK-NEXT: Address: 0x20A0
1414
15// CHECK: Relocations [15// CHECK: Relocations [
16// CHECK-NEXT: Section ({{.*}}) .rela.dyn {16// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
17// CHECK-NEXT: 0x2090 R_X86_64_TPOFF64 - 0x017// CHECK-NEXT: 0x20A0 R_X86_64_TPOFF64 - 0x0
18// CHECK-NEXT: 0x2098 R_X86_64_TPOFF64 - 0x418// CHECK-NEXT: 0x20A8 R_X86_64_TPOFF64 - 0x4
19// CHECK-NEXT: }19// CHECK-NEXT: }
20// CHECK-NEXT: ]20// CHECK-NEXT: ]
2121
22// 0x1007 + 4233 = 0x209022// 0x1007 + 4249 = 0x20A0
23// 0x100e + 4234 = 0x209823// 0x100e + 4250 = 0x20A8
24// DISASM: Disassembly of section .text:24// DISASM: Disassembly of section .text:
25// DISASM-EMPTY:
25// DISASM-NEXT: .text:26// DISASM-NEXT: .text:
26// DISASM-NEXT: 1000: {{.*}} addq 4233(%rip), %rax27// DISASM-NEXT: 1000: {{.*}} addq 4249(%rip), %rax
27// DISASM-NEXT: 1007: {{.*}} addq 4234(%rip), %rax28// DISASM-NEXT: 1007: {{.*}} addq 4250(%rip), %rax
2829
29 addq foo@GOTTPOFF(%rip), %rax30 addq foo@GOTTPOFF(%rip), %rax
30 addq bar@GOTTPOFF(%rip), %rax31 addq bar@GOTTPOFF(%rip), %rax
deps/lld/test/ELF/tls-offset.s+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %tout3// RUN: ld.lld %t -o %tout
4// RUN: llvm-readobj -s %tout | FileCheck %s4// RUN: llvm-readobj -S %tout | FileCheck %s
5// RUN: echo "SECTIONS { \5// RUN: echo "SECTIONS { \
6// RUN: . = 0x201000; \6// RUN: . = 0x201000; \
7// RUN: .text : { *(.text) } \7// RUN: .text : { *(.text) } \
...@@ -12,7 +12,7 @@...@@ -12,7 +12,7 @@
12// RUN: }" > %t.script12// RUN: }" > %t.script
13// RUN: ld.lld -T %t.script %t -o %tout213// RUN: ld.lld -T %t.script %t -o %tout2
14// RUN: echo SCRIPT14// RUN: echo SCRIPT
15// RUN: llvm-readobj -s %tout2 | FileCheck %s15// RUN: llvm-readobj -S %tout2 | FileCheck %s
16 .global _start16 .global _start
17_start:17_start:
18 retq18 retq
deps/lld/test/ELF/tls-opt-gdie.s+2-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/tls-opt-gdie.s -o %tso.o
4// RUN: ld.lld -shared %tso.o -o %t.so4// RUN: ld.lld -shared %tso.o -o %t.so
5// RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t15// RUN: ld.lld --hash-style=sysv %t.o %t.so -o %t1
6// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=RELOC %s6// RUN: llvm-readobj -S -r %t1 | FileCheck --check-prefix=RELOC %s
7// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s7// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
88
9//RELOC: Section {9//RELOC: Section {
...@@ -32,6 +32,7 @@...@@ -32,6 +32,7 @@
32//0x201009 + (4256 + 7) = 0x2020B032//0x201009 + (4256 + 7) = 0x2020B0
33//0x201019 + (4248 + 7) = 0x2020B833//0x201019 + (4248 + 7) = 0x2020B8
34// DISASM: Disassembly of section .text:34// DISASM: Disassembly of section .text:
35// DISASM-EMPTY:
35// DISASM-NEXT: _start:36// DISASM-NEXT: _start:
36// DISASM-NEXT: 201000: {{.*}} movq %fs:0, %rax37// DISASM-NEXT: 201000: {{.*}} movq %fs:0, %rax
37// DISASM-NEXT: 201009: {{.*}} addq 4256(%rip), %rax38// DISASM-NEXT: 201009: {{.*}} addq 4256(%rip), %rax
deps/lld/test/ELF/tls-opt-gdiele-i686.s+4-3
...@@ -14,11 +14,12 @@...@@ -14,11 +14,12 @@
14// NORELOC-NEXT: ]14// NORELOC-NEXT: ]
1515
16// DISASM: Disassembly of section .text:16// DISASM: Disassembly of section .text:
17// DISASM-EMPTY:
17// DISASM-NEXT: _start:18// DISASM-NEXT: _start:
18// DISASM-NEXT: 401000: 65 a1 00 00 00 00 movl %gs:0, %eax19// 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), %eax20// DISASM-NEXT: 401006: 03 83 58 f0 ff ff addl -4008(%ebx), %eax
20// DISASM-NEXT: 40100c: 65 a1 00 00 00 00 movl %gs:0, %eax21// 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), %eax22// DISASM-NEXT: 401012: 03 83 5c f0 ff ff addl -4004(%ebx), %eax
22// DISASM-NEXT: 401018: 65 a1 00 00 00 00 movl %gs:0, %eax23// 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, %eax24// 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, %eax25// DISASM-NEXT: 401024: 65 a1 00 00 00 00 movl %gs:0, %eax
...@@ -53,7 +54,7 @@ leal tlsshared0@tlsgd(,%ebx,1),%eax...@@ -53,7 +54,7 @@ leal tlsshared0@tlsgd(,%ebx,1),%eax
53call ___tls_get_addr@plt54call ___tls_get_addr@plt
54leal tlsshared1@tlsgd(,%ebx,1),%eax55leal tlsshared1@tlsgd(,%ebx,1),%eax
55call ___tls_get_addr@plt56call ___tls_get_addr@plt
56//GD->IE57//GD->LE
57leal tlsexe1@tlsgd(,%ebx,1),%eax58leal tlsexe1@tlsgd(,%ebx,1),%eax
58call ___tls_get_addr@plt59call ___tls_get_addr@plt
59leal tlsexe2@tlsgd(,%ebx,1),%eax60leal tlsexe2@tlsgd(,%ebx,1),%eax
deps/lld/test/ELF/tls-opt-i686.s+1
...@@ -8,6 +8,7 @@...@@ -8,6 +8,7 @@
8// NORELOC-NEXT: ]8// NORELOC-NEXT: ]
99
10// DISASM: Disassembly of section .text:10// DISASM: Disassembly of section .text:
11// DISASM-EMPTY:
11// DISASM-NEXT: _start:12// DISASM-NEXT: _start:
12// LD -> LE:13// LD -> LE:
13// DISASM-NEXT: 401000: 65 a1 00 00 00 00 movl %gs:0, %eax14// DISASM-NEXT: 401000: 65 a1 00 00 00 00 movl %gs:0, %eax
deps/lld/test/ELF/tls-opt-iele-i686-nopic.s+24-23
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o3// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %p/Inputs/tls-opt-iele-i686-nopic.s -o %tso.o
4// RUN: ld.lld -shared %tso.o -o %tso4// RUN: ld.lld -shared %tso.o -o %tso
5// RUN: ld.lld --hash-style=sysv %t.o %tso -o %t15// RUN: ld.lld --hash-style=sysv %t.o %tso -o %t1
6// RUN: llvm-readobj -s -r %t1 | FileCheck --check-prefix=GOTREL %s6// RUN: llvm-readobj -S -r %t1 | FileCheck --check-prefix=GOTREL %s
7// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s7// RUN: llvm-objdump -d %t1 | FileCheck --check-prefix=DISASM %s
88
9// GOTREL: Section {9// GOTREL: Section {
...@@ -14,8 +14,8 @@...@@ -14,8 +14,8 @@
14// GOTREL-NEXT: SHF_ALLOC14// GOTREL-NEXT: SHF_ALLOC
15// GOTREL-NEXT: SHF_WRITE15// GOTREL-NEXT: SHF_WRITE
16// GOTREL-NEXT: ]16// GOTREL-NEXT: ]
17// GOTREL-NEXT: Address: 0x40205817// GOTREL-NEXT: Address: 0x402060
18// GOTREL-NEXT: Offset: 0x205818// GOTREL-NEXT: Offset: 0x2060
19// GOTREL-NEXT: Size: 819// GOTREL-NEXT: Size: 8
20// GOTREL-NEXT: Link: 020// GOTREL-NEXT: Link: 0
21// GOTREL-NEXT: Info: 021// GOTREL-NEXT: Info: 0
...@@ -24,33 +24,34 @@...@@ -24,33 +24,34 @@
24// GOTREL-NEXT: }24// GOTREL-NEXT: }
25// GOTREL: Relocations [25// GOTREL: Relocations [
26// GOTREL-NEXT: Section ({{.*}}) .rel.dyn {26// GOTREL-NEXT: Section ({{.*}}) .rel.dyn {
27// GOTREL-NEXT: 0x402058 R_386_TLS_TPOFF tlsshared0 0x027// GOTREL-NEXT: 0x402060 R_386_TLS_TPOFF tlsshared0 0x0
28// GOTREL-NEXT: 0x40205C R_386_TLS_TPOFF tlsshared1 0x028// GOTREL-NEXT: 0x402064 R_386_TLS_TPOFF tlsshared1 0x0
29// GOTREL-NEXT: }29// GOTREL-NEXT: }
30// GOTREL-NEXT: ]30// GOTREL-NEXT: ]
3131
32// DISASM: Disassembly of section .text:32// DISASM: Disassembly of section .text:
33// DISASM-EMPTY:
33// DISASM-NEXT: _start:34// DISASM-NEXT: _start:
34// 4294967288 = 0xFFFFFFF835// 4294967288 = 0xFFFFFFF8
35// 4294967292 = 0xFFFFFFFC36// 4294967292 = 0xFFFFFFFC
36// 4202584 = (.got)[0] = 0x40205837// 4202592 = (.got)[0] = 0x402060
37// 4202588 = (.got)[1] = 0x40205C38// 4202596 = (.got)[1] = 0x402064
38// DISASM-NEXT: 401000: c7 c1 f8 ff ff ff movl $4294967288, %ecx39// DISASM-NEXT: 401000: {{.*}} movl $4294967288, %ecx
39// DISASM-NEXT: 401006: 65 8b 01 movl %gs:(%ecx), %eax40// DISASM-NEXT: 401006: {{.*}} movl %gs:(%ecx), %eax
40// DISASM-NEXT: 401009: b8 f8 ff ff ff movl $4294967288, %eax41// DISASM-NEXT: 401009: {{.*}} movl $4294967288, %eax
41// DISASM-NEXT: 40100e: 65 8b 00 movl %gs:(%eax), %eax42// DISASM-NEXT: 40100e: {{.*}} movl %gs:(%eax), %eax
42// DISASM-NEXT: 401011: 81 c1 f8 ff ff ff addl $4294967288, %ecx43// DISASM-NEXT: 401011: {{.*}} addl $4294967288, %ecx
43// DISASM-NEXT: 401017: 65 8b 01 movl %gs:(%ecx), %eax44// DISASM-NEXT: 401017: {{.*}} movl %gs:(%ecx), %eax
44// DISASM-NEXT: 40101a: c7 c1 fc ff ff ff movl $4294967292, %ecx45// DISASM-NEXT: 40101a: {{.*}} movl $4294967292, %ecx
45// DISASM-NEXT: 401020: 65 8b 01 movl %gs:(%ecx), %eax46// DISASM-NEXT: 401020: {{.*}} movl %gs:(%ecx), %eax
46// DISASM-NEXT: 401023: b8 fc ff ff ff movl $4294967292, %eax47// DISASM-NEXT: 401023: {{.*}} movl $4294967292, %eax
47// DISASM-NEXT: 401028: 65 8b 00 movl %gs:(%eax), %eax48// DISASM-NEXT: 401028: {{.*}} movl %gs:(%eax), %eax
48// DISASM-NEXT: 40102b: 81 c1 fc ff ff ff addl $4294967292, %ecx49// DISASM-NEXT: 40102b: {{.*}} addl $4294967292, %ecx
49// DISASM-NEXT: 401031: 65 8b 01 movl %gs:(%ecx), %eax50// DISASM-NEXT: 401031: {{.*}} movl %gs:(%ecx), %eax
50// DISASM-NEXT: 401034: 8b 0d 58 20 40 00 movl 4202584, %ecx51// DISASM-NEXT: 401034: {{.*}} movl 4202592, %ecx
51// DISASM-NEXT: 40103a: 65 8b 01 movl %gs:(%ecx), %eax52// DISASM-NEXT: 40103a: {{.*}} movl %gs:(%ecx), %eax
52// DISASM-NEXT: 40103d: 03 0d 5c 20 40 00 addl 4202588, %ecx53// DISASM-NEXT: 40103d: {{.*}} addl 4202596, %ecx
53// DISASM-NEXT: 401043: 65 8b 01 movl %gs:(%ecx), %eax54// DISASM-NEXT: 401043: {{.*}} movl %gs:(%ecx), %eax
5455
55.type tlslocal0,@object56.type tlslocal0,@object
56.section .tbss,"awT",@nobits57.section .tbss,"awT",@nobits
deps/lld/test/ELF/tls-opt-local.s+1
...@@ -8,6 +8,7 @@...@@ -8,6 +8,7 @@
8// NORELOC-NEXT: ]8// NORELOC-NEXT: ]
99
10// DISASM: Disassembly of section .text:10// DISASM: Disassembly of section .text:
11// DISASM-EMPTY:
11// DISASM-NEXT: _start:12// DISASM-NEXT: _start:
12// DISASM-NEXT: 201000: 48 c7 c0 f8 ff ff ff movq $-8, %rax13// DISASM-NEXT: 201000: 48 c7 c0 f8 ff ff ff movq $-8, %rax
13// DISASM-NEXT: 201007: 49 c7 c7 f8 ff ff ff movq $-8, %r1514// DISASM-NEXT: 201007: 49 c7 c7 f8 ff ff ff movq $-8, %r15
deps/lld/test/ELF/tls-opt-no-plt.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/tls-opt-gdie.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/tls-opt-gdie.s -o %t2.o
4// RUN: ld.lld %t2.o -o %t2.so -shared4// RUN: ld.lld %t2.o -o %t2.so -shared
5// RUN: ld.lld %t.o %t2.so -o %t.exe5// RUN: ld.lld %t.o %t2.so -o %t.exe
6// RUN: llvm-readobj -s %t.exe | FileCheck %s6// RUN: llvm-readobj -S %t.exe | FileCheck %s
77
8// CHECK-NOT: .plt8// CHECK-NOT: .plt
99
deps/lld/test/ELF/tls-relocatable.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=i686-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -r -o %tr.o3// RUN: ld.lld %t.o -r -o %tr.o
4// RUN: ld.lld %tr.o -shared -o %t14// RUN: ld.lld %tr.o -shared -o %t1
5// RUN: llvm-readobj -t %t1 | FileCheck %s5// RUN: llvm-readobj --symbols %t1 | FileCheck %s
66
7// CHECK: Symbol {7// CHECK: Symbol {
8// CHECK: Name: tls08// CHECK: Name: tls0
deps/lld/test/ELF/tls.s+2-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3// RUN: ld.lld %t -o %tout3// RUN: ld.lld %t -o %tout
4// RUN: llvm-readobj -symbols -sections -program-headers %tout | FileCheck %s4// RUN: llvm-readobj --symbols --sections -l %tout | FileCheck %s
5// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS5// RUN: llvm-objdump -d %tout | FileCheck %s --check-prefix=DIS
66
7.global _start7.global _start
...@@ -163,6 +163,7 @@ d:...@@ -163,6 +163,7 @@ d:
163// CHECK-NEXT: }163// CHECK-NEXT: }
164164
165// DIS: Disassembly of section .text:165// DIS: Disassembly of section .text:
166// DIS-EMPTY:
166// DIS-NEXT: _start:167// DIS-NEXT: _start:
167// DIS-NEXT: 201000: {{.+}} movl %fs:-8, %eax168// DIS-NEXT: 201000: {{.+}} movl %fs:-8, %eax
168// DIS-NEXT: 201008: {{.+}} movl %fs:-16, %eax169// DIS-NEXT: 201008: {{.+}} movl %fs:-16, %eax
deps/lld/test/ELF/trace-symbols.s+16-11
...@@ -14,46 +14,51 @@...@@ -14,46 +14,51 @@
14# RUN: llvm-ar rcs %t2.a %t214# RUN: llvm-ar rcs %t2.a %t2
1515
16# RUN: ld.lld -y foo -trace-symbol common -trace-symbol=hsymbol \16# RUN: ld.lld -y foo -trace-symbol common -trace-symbol=hsymbol \
17# RUN: %t %t1 %t2 -o %t3 2>&1 | FileCheck -check-prefix=OBJECTRFOO %s17# RUN: %t %t1 %t2 -o %t3 | FileCheck -check-prefix=OBJECTRFOO %s
18# OBJECTRFOO: trace-symbols.s.tmp: reference to foo18# OBJECTRFOO: trace-symbols.s.tmp: reference to foo
1919
20# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \20# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \
21# RUN: %t %t1 %t2 -o %t3 2>&1 | FileCheck -check-prefix=OBJECTDCOMMON %s21# RUN: %t %t1 %t2 -o %t3 | FileCheck -check-prefix=OBJECTDCOMMON %s
22# OBJECTDCOMMON: trace-symbols.s.tmp1: common definition of common22# OBJECTDCOMMON: trace-symbols.s.tmp1: common definition of common
2323
24# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \24# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \
25# RUN: %t %t1 %t2 -o %t3 2>&1 | FileCheck -check-prefix=OBJECTD1FOO %s25# RUN: %t %t1 %t2 -o %t3 | FileCheck -check-prefix=OBJECTD1FOO %s
26# OBJECTD1FOO: trace-symbols.s.tmp: reference to foo26# OBJECTD1FOO: trace-symbols.s.tmp: reference to foo
27# OBJECTD1FOO: trace-symbols.s.tmp1: common definition of common27# OBJECTD1FOO: trace-symbols.s.tmp1: common definition of common
28# OBJECTD1FOO: trace-symbols.s.tmp1: definition of foo28# OBJECTD1FOO: trace-symbols.s.tmp1: definition of foo
29# OBJECTD1FOO: trace-symbols.s.tmp2: definition of foo29# OBJECTD1FOO: trace-symbols.s.tmp2: definition of foo
3030
31# RUN: ld.lld -y foo %t1 %t2 %t -o %t3 | FileCheck -check-prefix=REFLAST %s
32# REFLAST: trace-symbols.s.tmp1: definition of foo
33# REFLAST: trace-symbols.s.tmp2: definition of foo
34# REFLAST: trace-symbols.s.tmp: reference to foo
35
31# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \36# RUN: ld.lld -y foo -trace-symbol=common -trace-symbol=hsymbol \
32# RUN: %t %t1 %t2 -o %t3 2>&1 | FileCheck -check-prefix=OBJECTD2FOO %s37# RUN: %t %t1 %t2 -o %t3 | FileCheck -check-prefix=OBJECTD2FOO %s
33# RUN: ld.lld -y foo -y common --trace-symbol=hsymbol \38# RUN: ld.lld -y foo -y common --trace-symbol=hsymbol \
34# RUN: %t %t2 %t1 -o /dev/null 2>&1 | FileCheck -check-prefix=OBJECTD2FOO %s39# RUN: %t %t2 %t1 -o %t3 | FileCheck -check-prefix=OBJECTD2FOO %s
35# RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 2>&1 | \40# RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 | \
36# RUN: FileCheck -check-prefix=OBJECTD2FOO %s41# RUN: FileCheck -check-prefix=OBJECTD2FOO %s
37# OBJECTD2FOO: trace-symbols.s.tmp2: definition of foo42# OBJECTD2FOO: trace-symbols.s.tmp2: definition of foo
3843
39# RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 2>&1 | \44# RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 | \
40# RUN: FileCheck -check-prefix=FOO_AND_COMMON %s45# RUN: FileCheck -check-prefix=FOO_AND_COMMON %s
41# FOO_AND_COMMON: trace-symbols.s.tmp: reference to foo46# FOO_AND_COMMON: trace-symbols.s.tmp: reference to foo
42# FOO_AND_COMMON: trace-symbols.s.tmp2: definition of foo47# FOO_AND_COMMON: trace-symbols.s.tmp2: definition of foo
43# FOO_AND_COMMON: trace-symbols.s.tmp1.a: lazy definition of common48# FOO_AND_COMMON: trace-symbols.s.tmp1.a: lazy definition of common
4449
45# RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 2>&1 | \50# RUN: ld.lld -y foo -y common %t %t1.so %t2 -o %t3 | \
46# RUN: FileCheck -check-prefix=SHLIBDCOMMON %s51# RUN: FileCheck -check-prefix=SHLIBDCOMMON %s
47# SHLIBDCOMMON: trace-symbols.s.tmp1.so: shared definition of common52# SHLIBDCOMMON: trace-symbols.s.tmp1.so: shared definition of common
4853
49# RUN: ld.lld -y foo -y common %t %t2.so %t1.so -o %t3 2>&1 | \54# RUN: ld.lld -y foo -y common %t %t2.so %t1.so -o %t3 | \
50# RUN: FileCheck -check-prefix=SHLIBD2FOO %s55# RUN: FileCheck -check-prefix=SHLIBD2FOO %s
51# RUN: ld.lld -y foo %t %t1.a %t2.so -o %t3 | \56# RUN: ld.lld -y foo %t %t1.a %t2.so -o %t3 | \
52# RUN: FileCheck -check-prefix=NO-SHLIBD2FOO %s57# RUN: FileCheck -check-prefix=NO-SHLIBD2FOO %s
53# SHLIBD2FOO: trace-symbols.s.tmp2.so: shared definition of foo58# SHLIBD2FOO: trace-symbols.s.tmp2.so: shared definition of foo
54# NO-SHLIBD2FOO-NOT: trace-symbols.s.tmp2.so: definition of foo59# NO-SHLIBD2FOO-NOT: trace-symbols.s.tmp2.so: definition of foo
5560
56# RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 2>&1 | \61# RUN: ld.lld -y foo -y common %t %t2 %t1.a -o %t3 | \
57# RUN: FileCheck -check-prefix=ARCHIVEDCOMMON %s62# RUN: FileCheck -check-prefix=ARCHIVEDCOMMON %s
58# ARCHIVEDCOMMON-NOT: trace-symbols.s.tmp1.a(trace-symbols.s.tmp1): definition of \63# ARCHIVEDCOMMON-NOT: trace-symbols.s.tmp1.a(trace-symbols.s.tmp1): definition of \
59# common64# common
...@@ -79,7 +84,7 @@...@@ -79,7 +84,7 @@
79# STARTLIB: trace-symbols.s.tmp1: reference to bar84# STARTLIB: trace-symbols.s.tmp1: reference to bar
8085
81## Check we do not crash when trying to trace special symbol.86## Check we do not crash when trying to trace special symbol.
82# RUN: not ld.lld -trace-symbol=_end %t -o /dev/null87# RUN: ld.lld -trace-symbol=_end %t %t1 %t2 -o /dev/null
8388
84.hidden hsymbol89.hidden hsymbol
85.globl _start90.globl _start
deps/lld/test/ELF/trace.s+1-1
...@@ -6,4 +6,4 @@...@@ -6,4 +6,4 @@
6# CHECK: {{.*}}.foo.o6# CHECK: {{.*}}.foo.o
77
8## Check --trace alias8## Check --trace alias
9# RUN: ld.lld -shared %t.foo.o -o %t.so -t 2>&1 | FileCheck %s9# RUN: ld.lld -shared %t.foo.o -o %t.so --trace 2>&1 | FileCheck %s
deps/lld/test/ELF/ttext-tdata-tbss.s+4-4
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4## Show what regular output gives to us.4## Show what regular output gives to us.
5# RUN: ld.lld %t.o -o %t15# RUN: ld.lld %t.o -o %t1
6# RUN: llvm-readobj --elf-output-style=GNU -l -s %t1 | FileCheck %s6# RUN: llvm-readelf -S -l %t1 | FileCheck %s
7# CHECK: .rodata PROGBITS 0000000000200158 000158 0000087# CHECK: .rodata PROGBITS 0000000000200158 000158 000008
8# CHECK-NEXT: .text PROGBITS 0000000000201000 001000 0000018# CHECK-NEXT: .text PROGBITS 0000000000201000 001000 000001
9# CHECK-NEXT: .aw PROGBITS 0000000000202000 002000 0000089# CHECK-NEXT: .aw PROGBITS 0000000000202000 002000 000008
...@@ -15,7 +15,7 @@...@@ -15,7 +15,7 @@
1515
16## With .text at 0 there is no space to allocate the headers.16## With .text at 0 there is no space to allocate the headers.
17# RUN: ld.lld -Ttext 0x0 -Tdata 0x4000 -Tbss 0x8000 %t.o -o %t217# RUN: ld.lld -Ttext 0x0 -Tdata 0x4000 -Tbss 0x8000 %t.o -o %t2
18# RUN: llvm-readobj --elf-output-style=GNU -l -s %t2 | FileCheck %s --check-prefix=USER118# RUN: llvm-readelf -S -l %t2 | FileCheck %s --check-prefix=USER1
19# USER1: .text PROGBITS 0000000000000000 001000 00000119# USER1: .text PROGBITS 0000000000000000 001000 000001
20# USER1-NEXT: .data PROGBITS 0000000000004000 002000 00000820# USER1-NEXT: .data PROGBITS 0000000000004000 002000 000008
21# USER1-NEXT: .bss NOBITS 0000000000008000 002008 00000821# USER1-NEXT: .bss NOBITS 0000000000008000 002008 000008
...@@ -26,7 +26,7 @@...@@ -26,7 +26,7 @@
2626
27## With .text at 0x1000 there is space to allocate the headers.27## With .text at 0x1000 there is space to allocate the headers.
28# RUN: ld.lld -Ttext 0x1000 -Tdata 0x4000 -Tbss 0x8000 %t.o -o %t328# RUN: ld.lld -Ttext 0x1000 -Tdata 0x4000 -Tbss 0x8000 %t.o -o %t3
29# RUN: llvm-readobj --elf-output-style=GNU -l -s %t3 | FileCheck %s --check-prefix=USER229# RUN: llvm-readelf -S -l %t3 | FileCheck %s --check-prefix=USER2
30# USER2: .text PROGBITS 0000000000001000 001000 00000130# USER2: .text PROGBITS 0000000000001000 001000 000001
31# USER2-NEXT: .data PROGBITS 0000000000004000 002000 00000831# USER2-NEXT: .data PROGBITS 0000000000004000 002000 000008
32# USER2-NEXT: .bss NOBITS 0000000000008000 002008 00000832# USER2-NEXT: .bss NOBITS 0000000000008000 002008 000008
...@@ -38,7 +38,7 @@...@@ -38,7 +38,7 @@
3838
39## With .text well above 200000 we don't need to change the image base39## With .text well above 200000 we don't need to change the image base
40# RUN: ld.lld -Ttext 0x201000 %t.o -o %t440# RUN: ld.lld -Ttext 0x201000 %t.o -o %t4
41# RUN: llvm-readobj --elf-output-style=GNU -l -s %t4 | FileCheck %s --check-prefix=USER341# RUN: llvm-readelf -S -l %t4 | FileCheck %s --check-prefix=USER3
42# USER3: .text PROGBITS 0000000000201000 001000 00000142# USER3: .text PROGBITS 0000000000201000 001000 000001
43# USER3-NEX: .rodata PROGBITS 0000000000202000 002000 00000843# USER3-NEX: .rodata PROGBITS 0000000000202000 002000 000008
44# USER3-NEX: .aw PROGBITS 0000000000203000 003000 00000844# USER3-NEX: .aw PROGBITS 0000000000203000 003000 000008
deps/lld/test/ELF/undef-broken-debug.test+16-9
...@@ -1,12 +1,12 @@...@@ -1,12 +1,12 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: yaml2obj %s -o %t.o2# RUN: yaml2obj %s -o %t.o
3# RUN: not ld.lld %t.o -o /dev/null 2>&1 | FileCheck %s3# RUN: not ld.lld %t.o -o /dev/null
44
5# The debug info has a broken relocation. Check that we don't crash5# The debug info has a broken relocation. Check that we don't crash.
6# and still report the undefined symbol.
76
8# CHECK: error: {{.*}}.o: relocation R_X86_64_64 at 0x29 has unsupported target7# We used to dereference null Target in DWARF.cpp:findAux while reporting a duplicate symbol error,
9# CHECK: error: undefined symbol: bar8# because Target wasn't initialized yet.
9# RUN: not ld.lld %t.o %t.o -o /dev/null
1010
11--- !ELF11--- !ELF
12FileHeader:12FileHeader:
...@@ -62,7 +62,14 @@ Sections:...@@ -62,7 +62,14 @@ Sections:
62 Content: '0111001017000000'62 Content: '0111001017000000'
6363
64Symbols:64Symbols:
65 Global:65 - Name: .debug_abbrev
66 - Name: _start66 Type: STT_SECTION
67 Section: .text67 Section: .debug_abbrev
68 - Name: bar68 - Name: .debug_line
69 Type: STT_SECTION
70 Section: .debug_line
71 - Name: _start
72 Section: .text
73 Binding: STB_GLOBAL
74 - Name: bar
75 Binding: STB_GLOBAL
deps/lld/test/ELF/undef-multi.s created+65
...@@ -0,0 +1,65 @@
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/undef.s -o %t2.o
4# RUN: not ld.lld %t.o %t2.o -o /dev/null 2>&1 | FileCheck %s
5
6# CHECK: error: undefined symbol: zed2
7# CHECK-NEXT: >>> referenced by undef-multi.s
8# CHECK-NEXT: >>> {{.*}}:(.text+0x1)
9# CHECK-NEXT: >>> referenced by undef-multi.s
10# CHECK-NEXT: >>> {{.*}}:(.text+0x6)
11# CHECK-NEXT: >>> referenced by undef-multi.s
12# CHECK-NEXT: >>> {{.*}}:(.text+0xB)
13# CHECK-NEXT: >>> referenced by undef-multi.s
14# CHECK-NEXT: >>> {{.*}}:(.text+0x10)
15# CHECK-NEXT: >>> referenced by {{.*}}tmp2.o:(.text+0x0)
16
17# All references to a single undefined symbol count as a single error -- but
18# at most 10 references are printed.
19# RUN: echo ".globl _bar" > %t.moreref.s
20# RUN: echo "_bar:" >> %t.moreref.s
21# RUN: echo " call zed2" >> %t.moreref.s
22# RUN: echo " call zed2" >> %t.moreref.s
23# RUN: echo " call zed2" >> %t.moreref.s
24# RUN: echo " call zed2" >> %t.moreref.s
25# RUN: echo " call zed2" >> %t.moreref.s
26# RUN: echo " call zed2" >> %t.moreref.s
27# RUN: echo " call zed2" >> %t.moreref.s
28# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %t.moreref.s -o %t3.o
29# RUN: not ld.lld %t.o %t2.o %t3.o -o /dev/null -error-limit=2 2>&1 | \
30# RUN: FileCheck --check-prefix=LIMIT %s
31
32# LIMIT: error: undefined symbol: zed2
33# LIMIT-NEXT: >>> referenced by undef-multi.s
34# LIMIT-NEXT: >>> {{.*}}:(.text+0x1)
35# LIMIT-NEXT: >>> referenced by undef-multi.s
36# LIMIT-NEXT: >>> {{.*}}:(.text+0x6)
37# LIMIT-NEXT: >>> referenced by undef-multi.s
38# LIMIT-NEXT: >>> {{.*}}:(.text+0xB)
39# LIMIT-NEXT: >>> referenced by undef-multi.s
40# LIMIT-NEXT: >>> {{.*}}:(.text+0x10)
41# LIMIT-NEXT: >>> referenced by {{.*}}tmp2.o:(.text+0x0)
42# LIMIT-NEXT: >>> referenced by {{.*}}tmp3.o:(.text+0x1)
43# LIMIT-NEXT: >>> referenced by {{.*}}tmp3.o:(.text+0x6)
44# LIMIT-NEXT: >>> referenced by {{.*}}tmp3.o:(.text+0xB)
45# LIMIT-NEXT: >>> referenced by {{.*}}tmp3.o:(.text+0x10)
46# LIMIT-NEXT: >>> referenced by {{.*}}tmp3.o:(.text+0x15)
47# LIMIT-NEXT: >>> referenced 2 more times
48
49.file "undef-multi.s"
50
51 .globl _start
52_start:
53 call zed2
54
55 .globl _f
56_f:
57 call zed2
58
59 .globl _g
60_g:
61 call zed2
62
63 .globl _h
64_h:
65 call zed2
deps/lld/test/ELF/undef-shared.s+3-3
...@@ -2,17 +2,17 @@...@@ -2,17 +2,17 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: not ld.lld %t.o -o /dev/null -shared 2>&1 | FileCheck %s3# RUN: not ld.lld %t.o -o /dev/null -shared 2>&1 | FileCheck %s
44
5# CHECK: error: undefined symbol: hidden5# CHECK: error: undefined hidden symbol: hidden
6# CHECK: >>> referenced by {{.*}}:(.data+0x0)6# CHECK: >>> referenced by {{.*}}:(.data+0x0)
7.global hidden7.global hidden
8.hidden hidden8.hidden hidden
99
10# CHECK: error: undefined symbol: internal10# CHECK: error: undefined internal symbol: internal
11# CHECK: >>> referenced by {{.*}}:(.data+0x8)11# CHECK: >>> referenced by {{.*}}:(.data+0x8)
12.global internal12.global internal
13.internal internal13.internal internal
1414
15# CHECK: error: undefined symbol: protected15# CHECK: error: undefined protected symbol: protected
16# CHECK: >>> referenced by {{.*}}:(.data+0x10)16# CHECK: >>> referenced by {{.*}}:(.data+0x10)
17.global protected17.global protected
18.protected protected18.protected protected
deps/lld/test/ELF/undef-shared2.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: not ld.lld %t.o %t2.o -o %t.so -shared 2>&1 | FileCheck %s4# RUN: not ld.lld %t.o %t2.o -o %t.so -shared 2>&1 | FileCheck %s
5# RUN: not ld.lld %t2.o %t.o -o %t.so -shared 2>&1 | FileCheck %s5# RUN: not ld.lld %t2.o %t.o -o %t.so -shared 2>&1 | FileCheck %s
66
7# CHECK: error: undefined symbol: foo7# CHECK: error: undefined protected symbol: foo
88
9.data9.data
10.quad foo10.quad foo
deps/lld/test/ELF/undef-version-script.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3# RUN: echo "{ local: *; };" > %t.script3# RUN: echo "{ local: *; };" > %t.script
4# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so4# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
5# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s5# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
66
7# CHECK: DynamicSymbols [7# CHECK: DynamicSymbols [
8# CHECK-NEXT: Symbol {8# CHECK-NEXT: Symbol {
deps/lld/test/ELF/undef-with-plt-addr-i686.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/undef-with-plt-addr.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=i686-unknown-linux %p/Inputs/undef-with-plt-addr.s -o %t2.o
4// RUN: ld.lld %t2.o -o %t2.so -shared4// RUN: ld.lld %t2.o -o %t2.so -shared
5// RUN: ld.lld %t.o %t2.so -o %t35// RUN: ld.lld %t.o %t2.so -o %t3
6// RUN: llvm-readobj -t -s %t3 | FileCheck %s6// RUN: llvm-readobj --symbols -S %t3 | FileCheck %s
77
8.globl _start8.globl _start
9_start:9_start:
deps/lld/test/ELF/undef-with-plt-addr.s+3-3
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/undef-with-plt-addr.s -o %t2.o3// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/undef-with-plt-addr.s -o %t2.o
4// RUN: ld.lld %t2.o -o %t2.so -shared4// RUN: ld.lld %t2.o -o %t2.so -shared
5// RUN: ld.lld %t.o %t2.so -o %t35// RUN: ld.lld %t.o %t2.so -o %t3
6// RUN: llvm-readobj -t -s -r %t3 | FileCheck %s6// RUN: llvm-readobj --symbols -S -r %t3 | FileCheck %s
77
8// Test that -z nocopyreloc doesn't prevent the plt hack.8// Test that -z nocopyreloc doesn't prevent the plt hack.
9// RUN: ld.lld %t.o %t2.so -o %t3 -z nocopyreloc9// RUN: ld.lld %t.o %t2.so -o %t3 -z nocopyreloc
...@@ -25,10 +25,10 @@ movabsq $set_data, %rax...@@ -25,10 +25,10 @@ movabsq $set_data, %rax
25// CHECK-NEXT: Address: 0x20101025// CHECK-NEXT: Address: 0x201010
2626
27// CHECK: Section ({{.*}}) .rela.dyn {27// CHECK: Section ({{.*}}) .rela.dyn {
28// CHECK-NEXT: 0x202000 R_X86_64_64 foo 0x028// CHECK-NEXT: 0x203000 R_X86_64_64 foo 0x0
29// CHECK-NEXT: }29// CHECK-NEXT: }
30// CHECK-NEXT: Section ({{.*}}) .rela.plt {30// CHECK-NEXT: Section ({{.*}}) .rela.plt {
31// CHECK-NEXT: 0x202020 R_X86_64_JUMP_SLOT set_data 0x031// CHECK-NEXT: 0x203020 R_X86_64_JUMP_SLOT set_data 0x0
32// CHECK-NEXT: }32// CHECK-NEXT: }
3333
34// CHECK: Name: foo34// CHECK: Name: foo
deps/lld/test/ELF/undefined-glob.s created+58
...@@ -0,0 +1,58 @@
1# REQUIRES: x86
2
3# RUN: echo '.globl foo1; foo1:' | \
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t1.o
5# RUN: echo '.globl foo2; foo2:' | \
6# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t2.o
7# RUN: echo '.globl foo32; foo32:' | \
8# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t3.o
9# RUN: echo '.globl bar; bar:' | \
10# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux - -o %t4.o
11# RUN: rm -f %t.a
12# RUN: llvm-ar rcs %t.a %t1.o %t2.o %t3.o %t4.o
13
14# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
15
16# RUN: ld.lld -o %t.exe %t.o %t.a
17# RUN: llvm-readobj --symbols %t.exe | FileCheck --check-prefix=NO-OPT %s
18
19# NO-OPT-NOT: foo
20# NO-OPT-NOT: bar
21
22# RUN: ld.lld -o %t.exe %t.o %t.a --undefined-glob foo1
23# RUN: llvm-readobj --symbols %t.exe | FileCheck --check-prefix=FOO1 %s
24
25# FOO1: foo1
26# FOO1-NOT: foo2
27
28# RUN: ld.lld -o %t.exe %t.o %t.a --undefined-glob 'foo*'
29# RUN: llvm-readobj --symbols %t.exe | FileCheck --check-prefix=FOO-STAR %s
30
31# FOO-STAR: foo1
32# FOO-STAR: foo2
33# FOO-STAR: foo32
34# FOO-STAR-NOT: bar
35
36# RUN: ld.lld -o %t.exe %t.o %t.a --undefined-glob 'foo?'
37# RUN: llvm-readobj --symbols %t.exe | FileCheck --check-prefix=FOO-Q %s
38
39# FOO-Q: foo1
40# FOO-Q: foo2
41# FOO-Q-NOT: foo32
42# FOO-Q-NOT: bar
43
44# RUN: ld.lld -o %t.exe %t.o %t.a --undefined-glob 'foo[13]*'
45# RUN: llvm-readobj --symbols %t.exe | FileCheck --check-prefix=FOO13 %s
46
47# FOO13: foo1
48# FOO13-NOT: foo2
49# FOO13: foo32
50# FOO13-NOT: bar
51
52# RUN: not ld.lld -o %t.exe %t.o %t.a --undefined-glob '[' 2>&1 | \
53# RUN: FileCheck -check-prefix=BAD-PATTERN %s
54
55# BAD-PATTERN: --undefined-glob: invalid glob pattern: [
56
57.globl _start
58_start:
deps/lld/test/ELF/undefined-opt.s+1-1
...@@ -40,7 +40,7 @@...@@ -40,7 +40,7 @@
40# TWO-UNDEFINED: Name: zed40# TWO-UNDEFINED: Name: zed
41# TWO-UNDEFINED: ]41# TWO-UNDEFINED: ]
42# Now the same logic but linker script is used to set undefines42# Now the same logic but linker script is used to set undefines
43# RUN: echo "EXTERN( bar abs )" > %t.script43# RUN: echo "EXTERN( bar \"abs\" )" > %t.script
44# RUN: ld.lld -o %t3 %t.o %tar.a %t.script44# RUN: ld.lld -o %t3 %t.o %tar.a %t.script
45# RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TWO-UNDEFINED %s45# RUN: llvm-readobj --symbols %t3 | FileCheck --check-prefix=TWO-UNDEFINED %s
4646
deps/lld/test/ELF/undefined-versioned-symbol.s+6-6
...@@ -15,21 +15,21 @@...@@ -15,21 +15,21 @@
1515
16// CHECK: Section ({{.*}}) .rela.dyn {16// CHECK: Section ({{.*}}) .rela.dyn {
17// CHECK-NEXT: Relocation {17// CHECK-NEXT: Relocation {
18// CHECK-NEXT: Offset: 0x100018// CHECK-NEXT: Offset: 0x2000
19// CHECK-NEXT: Type: R_X86_64_64 (1)19// CHECK-NEXT: Type: R_X86_64_64 (1)
20// CHECK-NEXT: Symbol: basename (1)20// CHECK-NEXT: Symbol: basename@FBSD_1.1 (1)
21// CHECK-NEXT: Addend: 0x021// CHECK-NEXT: Addend: 0x0
22// CHECK-NEXT: }22// CHECK-NEXT: }
23// CHECK-NEXT: Relocation {23// CHECK-NEXT: Relocation {
24// CHECK-NEXT: Offset: 0x100824// CHECK-NEXT: Offset: 0x2008
25// CHECK-NEXT: Type: R_X86_64_64 (1)25// CHECK-NEXT: Type: R_X86_64_64 (1)
26// CHECK-NEXT: Symbol: basename (2)26// CHECK-NEXT: Symbol: basename@FBSD_1.0 (2)
27// CHECK-NEXT: Addend: 0x027// CHECK-NEXT: Addend: 0x0
28// CHECK-NEXT: }28// CHECK-NEXT: }
29// CHECK-NEXT: Relocation {29// CHECK-NEXT: Relocation {
30// CHECK-NEXT: Offset: 0x101030// CHECK-NEXT: Offset: 0x2010
31// CHECK-NEXT: Type: R_X86_64_64 (1)31// CHECK-NEXT: Type: R_X86_64_64 (1)
32// CHECK-NEXT: Symbol: basename (3)32// CHECK-NEXT: Symbol: basename@FBSD_1.1 (3)
33// CHECK-NEXT: Addend: 0x033// CHECK-NEXT: Addend: 0x0
34// CHECK-NEXT: }34// CHECK-NEXT: }
35// CHECK-NEXT: }35// CHECK-NEXT: }
deps/lld/test/ELF/unresolved-symbols.s+3-3
...@@ -27,21 +27,21 @@...@@ -27,21 +27,21 @@
27# ERRUND: >>> referenced by {{.*}}:(.text+0x1)27# ERRUND: >>> referenced by {{.*}}:(.text+0x1)
2828
29## Also ignore all should not produce error for symbols from DSOs.29## Also ignore all should not produce error for symbols from DSOs.
30# RUN: ld.lld %t1.o %t.so -o %t1_3 --unresolved-symbols=ignore-all30# RUN: ld.lld %t1.o %t.so -o %t1_3 --allow-shlib-undefined --unresolved-symbols=ignore-all
31# RUN: llvm-readobj %t1_3 > /dev/null 2>&131# RUN: llvm-readobj %t1_3 > /dev/null 2>&1
3232
33## Ignoring undefines in objects should not produce error for symbol from object.33## Ignoring undefines in objects should not produce error for symbol from object.
34# RUN: ld.lld %t1.o %t2.o -o %t2 --unresolved-symbols=ignore-in-object-files34# RUN: ld.lld %t1.o %t2.o -o %t2 --unresolved-symbols=ignore-in-object-files
35# RUN: llvm-readobj %t2 > /dev/null 2>&135# RUN: llvm-readobj %t2 > /dev/null 2>&1
36## And still should not should produce for undefines from DSOs.36## And still should not should produce for undefines from DSOs.
37# RUN: ld.lld %t1.o %t.so -o /dev/null --unresolved-symbols=ignore-in-object-files37# RUN: ld.lld %t1.o %t.so -o /dev/null --allow-shlib-undefined --unresolved-symbols=ignore-in-object-files
38# RUN: llvm-readobj %t2 > /dev/null 2>&138# RUN: llvm-readobj %t2 > /dev/null 2>&1
3939
40## Ignoring undefines in shared should produce error for symbol from object.40## Ignoring undefines in shared should produce error for symbol from object.
41# RUN: not ld.lld %t2.o -o /dev/null --unresolved-symbols=ignore-in-shared-libs 2>&1 | \41# RUN: not ld.lld %t2.o -o /dev/null --unresolved-symbols=ignore-in-shared-libs 2>&1 | \
42# RUN: FileCheck -check-prefix=ERRUND %s42# RUN: FileCheck -check-prefix=ERRUND %s
43## And should not produce errors for symbols from DSO.43## And should not produce errors for symbols from DSO.
44# RUN: ld.lld %t1.o %t.so -o %t3_1 --unresolved-symbols=ignore-in-shared-libs44# RUN: ld.lld %t1.o %t.so -o %t3_1 --allow-shlib-undefined --unresolved-symbols=ignore-in-shared-libs
45# RUN: llvm-readobj %t3_1 > /dev/null 2>&145# RUN: llvm-readobj %t3_1 > /dev/null 2>&1
4646
47## Ignoring undefines in shared libs should not produce error for symbol from object47## Ignoring undefines in shared libs should not produce error for symbol from object
deps/lld/test/ELF/verdef-defaultver.s+18-16
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: echo "V1 { global: a; local: *; };" > %t.script4# RUN: echo "V1 { global: a; local: *; };" > %t.script
5# RUN: echo "V2 { global: b; c; } V1;" >> %t.script5# RUN: echo "V2 { global: b; c; } V1;" >> %t.script
6# RUN: ld.lld --hash-style=sysv -shared -soname shared %t1 --version-script %t.script -o %t.so6# RUN: ld.lld --hash-style=sysv -shared -soname shared %t1 --version-script %t.script -o %t.so
7# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s7# RUN: llvm-readobj -V --dyn-syms %t.so | FileCheck --check-prefix=DSO %s
88
9# DSO: DynamicSymbols [9# DSO: DynamicSymbols [
10# DSO-NEXT: Symbol {10# DSO-NEXT: Symbol {
...@@ -108,7 +108,7 @@...@@ -108,7 +108,7 @@
108## Check that we can link against DSO produced.108## Check that we can link against DSO produced.
109# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2109# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2
110# RUN: ld.lld --hash-style=sysv %t2 %t.so -o %t3110# RUN: ld.lld --hash-style=sysv %t2 %t.so -o %t3
111# RUN: llvm-readobj -V -dyn-symbols %t3 | FileCheck --check-prefix=EXE %s111# RUN: llvm-readobj -V --dyn-syms %t3 | FileCheck --check-prefix=EXE %s
112112
113# EXE: DynamicSymbols [113# EXE: DynamicSymbols [
114# EXE-NEXT: Symbol {114# EXE-NEXT: Symbol {
...@@ -150,8 +150,8 @@...@@ -150,8 +150,8 @@
150# EXE-NEXT: ]150# EXE-NEXT: ]
151# EXE-NEXT: Version symbols {151# EXE-NEXT: Version symbols {
152# EXE-NEXT: Section Name: .gnu.version152# EXE-NEXT: Section Name: .gnu.version
153# EXE-NEXT: Address: 0x200228153# EXE-NEXT: Address: 0x200260
154# EXE-NEXT: Offset: 0x228154# EXE-NEXT: Offset: 0x260
155# EXE-NEXT: Link: 1155# EXE-NEXT: Link: 1
156# EXE-NEXT: Symbols [156# EXE-NEXT: Symbols [
157# EXE-NEXT: Symbol {157# EXE-NEXT: Symbol {
...@@ -179,18 +179,20 @@...@@ -179,18 +179,20 @@
179# EXE-NEXT: Version: 1179# EXE-NEXT: Version: 1
180# EXE-NEXT: Count: 2180# EXE-NEXT: Count: 2
181# EXE-NEXT: FileName: shared181# EXE-NEXT: FileName: shared
182# EXE-NEXT: Entry {182# EXE-NEXT: Entries [
183# EXE-NEXT: Hash: 1425183# EXE-NEXT: Entry {
184# EXE-NEXT: Flags: 0x0184# EXE-NEXT: Hash: 1425
185# EXE-NEXT: Index: 2185# EXE-NEXT: Flags: 0x0
186# EXE-NEXT: Name: V1186# EXE-NEXT: Index: 2
187# EXE-NEXT: }187# EXE-NEXT: Name: V1
188# EXE-NEXT: Entry {188# EXE-NEXT: }
189# EXE-NEXT: Hash: 1426189# EXE-NEXT: Entry {
190# EXE-NEXT: Flags: 0x0190# EXE-NEXT: Hash: 1426
191# EXE-NEXT: Index: 3191# EXE-NEXT: Flags: 0x0
192# EXE-NEXT: Name: V2192# EXE-NEXT: Index: 3
193# EXE-NEXT: }193# EXE-NEXT: Name: V2
194# EXE-NEXT: }
195# EXE-NEXT: ]
194# EXE-NEXT: }196# EXE-NEXT: }
195# EXE-NEXT: }197# EXE-NEXT: }
196198
deps/lld/test/ELF/verdef-dependency.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: echo "LIBSAMPLE_2.0 { global: b; local: *; } LIBSAMPLE_1.0;" >> %t.script4# RUN: echo "LIBSAMPLE_2.0 { global: b; local: *; } LIBSAMPLE_1.0;" >> %t.script
5# RUN: echo "LIBSAMPLE_3.0 { global: c; } LIBSAMPLE_2.0;" >> %t.script5# RUN: echo "LIBSAMPLE_3.0 { global: c; } LIBSAMPLE_2.0;" >> %t.script
6# RUN: ld.lld --version-script %t.script -shared -soname shared %t.o -o %t.so6# RUN: ld.lld --version-script %t.script -shared -soname shared %t.o -o %t.so
7# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s7# RUN: llvm-readobj -V --dyn-syms %t.so | FileCheck --check-prefix=DSO %s
88
9# DSO: SHT_GNU_verdef {9# DSO: SHT_GNU_verdef {
10# DSO-NEXT: Definition {10# DSO-NEXT: Definition {
deps/lld/test/ELF/verdef.s+4-4
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: echo "LIBSAMPLE_2.0 { global: b; local: *; };" >> %t.script4# RUN: echo "LIBSAMPLE_2.0 { global: b; local: *; };" >> %t.script
5# RUN: echo "LIBSAMPLE_3.0 { global: c; local: *; };" >> %t.script5# RUN: echo "LIBSAMPLE_3.0 { global: c; local: *; };" >> %t.script
6# RUN: ld.lld --hash-style=sysv --version-script %t.script -shared -soname shared %t.o -o %t.so6# RUN: ld.lld --hash-style=sysv --version-script %t.script -shared -soname shared %t.o -o %t.so
7# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s7# RUN: llvm-readobj -V --dyn-syms %t.so | FileCheck --check-prefix=DSO %s
88
9# DSO: Version symbols {9# DSO: Version symbols {
10# DSO-NEXT: Section Name: .gnu.version10# DSO-NEXT: Section Name: .gnu.version
...@@ -70,8 +70,8 @@...@@ -70,8 +70,8 @@
7070
71# MAIN: Version symbols {71# MAIN: Version symbols {
72# MAIN-NEXT: Section Name: .gnu.version72# MAIN-NEXT: Section Name: .gnu.version
73# MAIN-NEXT: Address: 0x20022873# MAIN-NEXT: Address: 0x200260
74# MAIN-NEXT: Offset: 0x22874# MAIN-NEXT: Offset: 0x260
75# MAIN-NEXT: Link: 175# MAIN-NEXT: Link: 1
76# MAIN-NEXT: Symbols [76# MAIN-NEXT: Symbols [
77# MAIN-NEXT: Symbol {77# MAIN-NEXT: Symbol {
...@@ -101,7 +101,7 @@...@@ -101,7 +101,7 @@
101# RUN: echo "LIBSAMPLE_3.0 { global: c; local: *; };" >> %t.script101# RUN: echo "LIBSAMPLE_3.0 { global: c; local: *; };" >> %t.script
102# RUN: echo "}" >> %t.script102# RUN: echo "}" >> %t.script
103# RUN: ld.lld --hash-style=sysv --script %t.script -shared -soname shared %t.o -o %t2.so103# RUN: ld.lld --hash-style=sysv --script %t.script -shared -soname shared %t.o -o %t2.so
104# RUN: llvm-readobj -V -dyn-symbols %t2.so | FileCheck --check-prefix=DSO %s104# RUN: llvm-readobj -V --dyn-syms %t2.so | FileCheck --check-prefix=DSO %s
105105
106.globl a106.globl a
107.type a,@function107.type a,@function
deps/lld/test/ELF/verneed.s+31-27
...@@ -7,7 +7,7 @@...@@ -7,7 +7,7 @@
77
8# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o8# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
9# RUN: ld.lld --hash-style=sysv %t.o %t1.so %t2.so -o %t9# RUN: ld.lld --hash-style=sysv %t.o %t1.so %t2.so -o %t
10# RUN: llvm-readobj -V -sections -section-data -dyn-symbols -dynamic-table %t | FileCheck %s10# RUN: llvm-readobj -V --sections --section-data --dyn-syms --dynamic-table %t | FileCheck %s
1111
12# CHECK: Section {12# CHECK: Section {
13# CHECK: Index: 113# CHECK: Index: 1
...@@ -16,8 +16,8 @@...@@ -16,8 +16,8 @@
16# CHECK-NEXT: Flags [ (0x2)16# CHECK-NEXT: Flags [ (0x2)
17# CHECK-NEXT: SHF_ALLOC (0x2)17# CHECK-NEXT: SHF_ALLOC (0x2)
18# CHECK-NEXT: ]18# CHECK-NEXT: ]
19# CHECK-NEXT: Address: 0x2001C819# CHECK-NEXT: Address: 0x200200
20# CHECK-NEXT: Offset: 0x1C820# CHECK-NEXT: Offset: 0x200
21# CHECK-NEXT: Size: 9621# CHECK-NEXT: Size: 96
22# CHECK-NEXT: Link: [[DYNSTR:.*]]22# CHECK-NEXT: Link: [[DYNSTR:.*]]
23# CHECK-NEXT: Info: 123# CHECK-NEXT: Info: 1
...@@ -47,7 +47,7 @@...@@ -47,7 +47,7 @@
47# CHECK-NEXT: SHF_ALLOC (0x2)47# CHECK-NEXT: SHF_ALLOC (0x2)
48# CHECK-NEXT: ]48# CHECK-NEXT: ]
49# CHECK-NEXT: Address: [[VERNEED:.*]]49# CHECK-NEXT: Address: [[VERNEED:.*]]
50# CHECK-NEXT: Offset: 0x23050# CHECK-NEXT: Offset: 0x268
51# CHECK-NEXT: Size: 8051# CHECK-NEXT: Size: 80
52# CHECK-NEXT: Link: 552# CHECK-NEXT: Link: 5
53# CHECK-NEXT: Info: 253# CHECK-NEXT: Info: 2
...@@ -60,17 +60,17 @@...@@ -60,17 +60,17 @@
60# CHECK-NEXT: Flags [ (0x2)60# CHECK-NEXT: Flags [ (0x2)
61# CHECK-NEXT: SHF_ALLOC (0x2)61# CHECK-NEXT: SHF_ALLOC (0x2)
62# CHECK-NEXT: ]62# CHECK-NEXT: ]
63# CHECK-NEXT: Address: 0x2002A863# CHECK-NEXT: Address: 0x2002E0
64# CHECK-NEXT: Offset: 0x2A864# CHECK-NEXT: Offset: 0x2E0
65# CHECK-NEXT: Size: 4765# CHECK-NEXT: Size: 47
66# CHECK-NEXT: Link: 066# CHECK-NEXT: Link: 0
67# CHECK-NEXT: Info: 067# CHECK-NEXT: Info: 0
68# CHECK-NEXT: AddressAlignment: 168# CHECK-NEXT: AddressAlignment: 1
69# CHECK-NEXT: EntrySize: 069# CHECK-NEXT: EntrySize: 0
70# CHECK-NEXT: SectionData (70# CHECK-NEXT: SectionData (
71# CHECK-NEXT: 0000: 00766572 6E656564 312E736F 2E300076 |.verneed1.so.0.v|71# CHECK-NEXT: 0000: 00663100 66320067 31007665 726E6565 |.f1.f2.g1.vernee|
72# CHECK-NEXT: 0010: 65726E65 6564322E 736F2E30 00663100 |erneed2.so.0.f1.|72# CHECK-NEXT: 0010: 64312E73 6F2E3000 76320076 33007665 |d1.so.0.v2.v3.ve|
73# CHECK-NEXT: 0020: 76330066 32007632 00673100 763100 |v3.f2.v2.g1.v1.|73# CHECK-NEXT: 0020: 726E6565 64322E73 6F2E3000 763100 |rneed2.so.0.v1.|
74# CHECK-NEXT: )74# CHECK-NEXT: )
75# CHECK-NEXT: }75# CHECK-NEXT: }
7676
...@@ -148,29 +148,33 @@...@@ -148,29 +148,33 @@
148# CHECK-NEXT: Version: 1148# CHECK-NEXT: Version: 1
149# CHECK-NEXT: Count: 2149# CHECK-NEXT: Count: 2
150# CHECK-NEXT: FileName: verneed1.so.0150# CHECK-NEXT: FileName: verneed1.so.0
151# CHECK-NEXT: Entry {151# CHECK-NEXT: Entries [
152# CHECK-NEXT: Hash: 1938152# CHECK-NEXT: Entry {
153# CHECK-NEXT: Flags: 0x0153# CHECK-NEXT: Hash: 1938
154# CHECK-NEXT: Index: 3154# CHECK-NEXT: Flags: 0x0
155# CHECK-NEXT: Name: v2155# CHECK-NEXT: Index: 3
156# CHECK-NEXT: }156# CHECK-NEXT: Name: v2
157# CHECK-NEXT: Entry {157# CHECK-NEXT: }
158# CHECK-NEXT: Hash: 1939158# CHECK-NEXT: Entry {
159# CHECK-NEXT: Flags: 0x0159# CHECK-NEXT: Hash: 1939
160# CHECK-NEXT: Index: 2160# CHECK-NEXT: Flags: 0x0
161# CHECK-NEXT: Name: v3161# CHECK-NEXT: Index: 2
162# CHECK-NEXT: }162# CHECK-NEXT: Name: v3
163# CHECK-NEXT: }
164# CHECK-NEXT: ]
163# CHECK-NEXT: }165# CHECK-NEXT: }
164# CHECK-NEXT: Dependency {166# CHECK-NEXT: Dependency {
165# CHECK-NEXT: Version: 1167# CHECK-NEXT: Version: 1
166# CHECK-NEXT: Count: 1168# CHECK-NEXT: Count: 1
167# CHECK-NEXT: FileName: verneed2.so.0169# CHECK-NEXT: FileName: verneed2.so.0
168# CHECK-NEXT: Entry {170# CHECK-NEXT: Entries [
169# CHECK-NEXT: Hash: 1937171# CHECK-NEXT: Entry {
170# CHECK-NEXT: Flags: 0x0172# CHECK-NEXT: Hash: 1937
171# CHECK-NEXT: Index: 4173# CHECK-NEXT: Flags: 0x0
172# CHECK-NEXT: Name: v1174# CHECK-NEXT: Index: 4
173# CHECK-NEXT: }175# CHECK-NEXT: Name: v1
176# CHECK-NEXT: }
177# CHECK-NEXT: ]
174# CHECK-NEXT: }178# CHECK-NEXT: }
175# CHECK-NEXT: }179# CHECK-NEXT: }
176180
deps/lld/test/ELF/version-exclude-libs.s+2-2
...@@ -4,8 +4,8 @@...@@ -4,8 +4,8 @@
4// RUN: llvm-ar -r %t.a %t.o4// RUN: llvm-ar -r %t.a %t.o
5// RUN: llvm-mc %s -o %t2.o -filetype=obj -triple=x86_64-pc-linux5// RUN: llvm-mc %s -o %t2.o -filetype=obj -triple=x86_64-pc-linux
6// RUN: ld.lld %t2.o %t.a --shared --exclude-libs ALL -o %t.so6// RUN: ld.lld %t2.o %t.a --shared --exclude-libs ALL -o %t.so
7// RUN: llvm-readobj -symbols %t.so | FileCheck %s7// RUN: llvm-readobj --symbols %t.so | FileCheck %s
8// RUN: llvm-readobj -dyn-symbols %t.so | FileCheck -check-prefix CHECK-DYN %s8// RUN: llvm-readobj --dyn-syms %t.so | FileCheck -check-prefix CHECK-DYN %s
9// RUN: not ld.lld %t2.o %t.a --shared -o %t.so 2>&1 | FileCheck -check-prefix=CHECK-ERR %s9// RUN: not ld.lld %t2.o %t.a --shared -o %t.so 2>&1 | FileCheck -check-prefix=CHECK-ERR %s
1010
11// Test that we do not give an error message for undefined versions when the11// Test that we do not give an error message for undefined versions when the
deps/lld/test/ELF/version-script-anonymous-local.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4# RUN: echo "{ global: foo; local: bar; };" > %t.script4# RUN: echo "{ global: foo; local: bar; };" > %t.script
5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
6# RUN: llvm-readobj -dyn-symbols -t %t.so | FileCheck %s6# RUN: llvm-readobj --dyn-syms --symbols %t.so | FileCheck %s
77
8# CHECK: Symbols [8# CHECK: Symbols [
9# CHECK: Name: bar9# CHECK: Name: bar
deps/lld/test/ELF/version-script-copy-rel.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: ld.lld --version-script %t.script -shared %t1.o -o %t.so4# RUN: ld.lld --version-script %t.script -shared %t1.o -o %t.so
5# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o5# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2.o
6# RUN: ld.lld %t2.o %t.so -o %tout6# RUN: ld.lld %t2.o %t.so -o %tout
7# RUN: llvm-readobj -dyn-symbols %tout | FileCheck %s7# RUN: llvm-readobj --dyn-syms %tout | FileCheck %s
88
9# CHECK: DynamicSymbols [9# CHECK: DynamicSymbols [
10# CHECK: Symbol {10# CHECK: Symbol {
deps/lld/test/ELF/version-script-extern-exact.s+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
4# RUN: echo "FOO { global: extern \"C++\" { \"aaa*\"; }; };" > %t.script4# RUN: echo "FOO { global: extern \"C++\" { \"aaa*\"; }; };" > %t.script
5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
6# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s --check-prefix=NOMATCH6# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s --check-prefix=NOMATCH
77
8# NOMATCH: DynamicSymbols [8# NOMATCH: DynamicSymbols [
9# NOMATCH-NOT: _Z3aaaPf@@FOO9# NOMATCH-NOT: _Z3aaaPf@@FOO
...@@ -12,7 +12,7 @@...@@ -12,7 +12,7 @@
1212
13# RUN: echo "FOO { global: extern \"C++\" { \"aaa*\"; aaa*; }; };" > %t2.script13# RUN: echo "FOO { global: extern \"C++\" { \"aaa*\"; aaa*; }; };" > %t2.script
14# RUN: ld.lld --version-script %t2.script -shared %t.o -o %t2.so14# RUN: ld.lld --version-script %t2.script -shared %t.o -o %t2.so
15# RUN: llvm-readobj -dyn-symbols %t2.so | FileCheck %s --check-prefix=MATCH15# RUN: llvm-readobj --dyn-syms %t2.so | FileCheck %s --check-prefix=MATCH
16# MATCH: DynamicSymbols [16# MATCH: DynamicSymbols [
17# MATCH: _Z3aaaPf@@FOO17# MATCH: _Z3aaaPf@@FOO
18# MATCH: _Z3aaaPi@@FOO18# MATCH: _Z3aaaPi@@FOO
deps/lld/test/ELF/version-script-extern-wildcards-anon.s+1-1
...@@ -12,7 +12,7 @@...@@ -12,7 +12,7 @@
12# RUN: local: *; \12# RUN: local: *; \
13# RUN: }; ' > %t.script13# RUN: }; ' > %t.script
14# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so14# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
15# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s15# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
1616
17# CHECK: DynamicSymbols [17# CHECK: DynamicSymbols [
18# CHECK-NEXT: Symbol {18# CHECK-NEXT: Symbol {
deps/lld/test/ELF/version-script-extern-wildcards.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: echo "FOO { global: extern \"C++\" { foo*; }; };" > %t.script4# RUN: echo "FOO { global: extern \"C++\" { foo*; }; };" > %t.script
5# RUN: echo "BAR { global: extern \"C++\" { zed*; bar; }; };" >> %t.script5# RUN: echo "BAR { global: extern \"C++\" { zed*; bar; }; };" >> %t.script
6# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so6# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
7# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck %s7# RUN: llvm-readobj -V --dyn-syms %t.so | FileCheck %s
88
9# CHECK: Version symbols {9# CHECK: Version symbols {
10# CHECK: Symbols [10# CHECK: Symbols [
deps/lld/test/ELF/version-script-extern.s+1-1
...@@ -8,7 +8,7 @@...@@ -8,7 +8,7 @@
8# RUN: echo ' extern "C" { _Z3bari; };' >> %t.script8# RUN: echo ' extern "C" { _Z3bari; };' >> %t.script
9# RUN: echo "};" >> %t.script9# RUN: echo "};" >> %t.script
10# RUN: ld.lld --hash-style=sysv --version-script %t.script -soname fixed-length-string -shared %t.o -o %t.so10# RUN: ld.lld --hash-style=sysv --version-script %t.script -soname fixed-length-string -shared %t.o -o %t.so
11# RUN: llvm-readobj -V -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s11# RUN: llvm-readobj -V --dyn-syms %t.so | FileCheck --check-prefix=DSO %s
1212
13# DSO: DynamicSymbols [13# DSO: DynamicSymbols [
14# DSO-NEXT: Symbol {14# DSO-NEXT: Symbol {
deps/lld/test/ELF/version-script-glob.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: echo "{ global: foo*; bar*; local: *; };" > %t.script3# RUN: echo "{ global: foo*; bar*; local: *; };" > %t.script
4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
5# RUN: ld.lld -shared --version-script %t.script %t.o -o %t.so5# RUN: ld.lld -shared --version-script %t.script %t.o -o %t.so
6# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s6# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
77
8 .globl foo18 .globl foo1
9foo1:9foo1:
deps/lld/test/ELF/version-script-hide-so-symbol.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: ld.lld -shared %t.o -o %t2.so4# RUN: ld.lld -shared %t.o -o %t2.so
5# RUN: echo "{ local: *; };" > %t.script5# RUN: echo "{ local: *; };" > %t.script
6# RUN: ld.lld --version-script %t.script -shared %t.o %t2.so -o %t.so6# RUN: ld.lld --version-script %t.script -shared %t.o %t2.so -o %t.so
7# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s7# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
88
9# The symbol foo must be hidden. This matches bfd and gold and is9# The symbol foo must be hidden. This matches bfd and gold and is
10# required to make it possible for a c++ library to hide its own10# required to make it possible for a c++ library to hide its own
deps/lld/test/ELF/version-script-locals.s+3-3
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
33
4# RUN: echo "VERSION_1.0 { local: foo1; };" > %t.script4# RUN: echo "VERSION_1.0 { local: foo1; };" > %t.script
5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
6# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=EXACT %s6# RUN: llvm-readobj --dyn-syms %t.so | FileCheck --check-prefix=EXACT %s
7# EXACT: DynamicSymbols [7# EXACT: DynamicSymbols [
8# EXACT: _start8# EXACT: _start
9# EXACT-NOT: foo19# EXACT-NOT: foo1
...@@ -12,7 +12,7 @@...@@ -12,7 +12,7 @@
1212
13# RUN: echo "VERSION_1.0 { local: foo*; };" > %t.script13# RUN: echo "VERSION_1.0 { local: foo*; };" > %t.script
14# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so14# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
15# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=WC %s15# RUN: llvm-readobj --dyn-syms %t.so | FileCheck --check-prefix=WC %s
16# WC: DynamicSymbols [16# WC: DynamicSymbols [
17# WC: _start17# WC: _start
18# WC-NOT: foo118# WC-NOT: foo1
...@@ -21,7 +21,7 @@...@@ -21,7 +21,7 @@
2121
22# RUN: echo "VERSION_1.0 { global: *; local: foo*; };" > %t.script22# RUN: echo "VERSION_1.0 { global: *; local: foo*; };" > %t.script
23# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so23# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
24# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=MIX %s24# RUN: llvm-readobj --dyn-syms %t.so | FileCheck --check-prefix=MIX %s
25# MIX: DynamicSymbols [25# MIX: DynamicSymbols [
26# MIX: _start@@VERSION_1.026# MIX: _start@@VERSION_1.0
27# MIX-NOT: foo127# MIX-NOT: foo1
deps/lld/test/ELF/version-script-reassign.s created+36
...@@ -0,0 +1,36 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: echo '{ local: foo; };' > %tl.ver
4# RUN: echo '{ global: foo; local: *; };' > %tg.ver
5# RUN: echo 'V1 { global: foo; };' > %t1.ver
6# RUN: echo 'V2 { global: foo; };' > %t2.ver
7# RUN: echo 'V2 { global: notexist; local: f*; };' > %t2w.ver
8
9## Note, ld.bfd errors on the two cases.
10# RUN: ld.lld -shared %t.o --version-script %tl.ver --version-script %t1.ver \
11# RUN: -o %t.so 2>&1 | FileCheck --check-prefix=LOCAL %s
12# RUN: llvm-readelf --dyn-syms %t.so | FileCheck --check-prefix=LOCAL-SYM %s
13# RUN: ld.lld -shared %t.o --version-script %tg.ver --version-script %t1.ver \
14# RUN: -o %t.so 2>&1 | FileCheck --check-prefix=GLOBAL %s
15# RUN: llvm-readelf --dyn-syms %t.so | FileCheck --check-prefix=GLOBAL-SYM %s
16
17## Note, ld.bfd silently accepts this case.
18# RUN: ld.lld -shared %t.o --version-script %t1.ver --version-script %t2.ver \
19# RUN: -o %t.so 2>&1 | FileCheck --check-prefix=V1-WARN %s
20# RUN: llvm-readelf --dyn-syms %t.so | FileCheck --check-prefix=V1-SYM %s
21
22# RUN: ld.lld -shared %t.o --version-script %t1.ver --version-script %t2w.ver \
23# RUN: -o %t.so --fatal-warnings
24# RUN: llvm-readelf --dyn-syms %t.so | FileCheck --check-prefix=V1-SYM %s
25
26# LOCAL: warning: attempt to reassign symbol 'foo' of VER_NDX_LOCAL to version 'V1'
27# LOCAL-SYM-NOT: foo
28
29# GLOBAL: warning: attempt to reassign symbol 'foo' of VER_NDX_GLOBAL to version 'V1'
30# GLOBAL-SYM: foo{{$}}
31
32# V1-WARN: warning: attempt to reassign symbol 'foo' of version 'V1' to version 'V2'
33# V1-SYM: foo@@V1
34
35.globl foo
36foo:
deps/lld/test/ELF/version-script-twice.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: echo "FBSD_1.1 {}; FBSD_1.2 {};" > %t.ver3# RUN: echo "FBSD_1.1 {}; FBSD_1.2 {};" > %t.ver
4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
5# RUN: ld.lld -shared %t.o -o %t.so --version-script=%t.ver5# RUN: ld.lld -shared %t.o -o %t.so --version-script=%t.ver
6# RUN: llvm-readobj --dyn-symbols --elf-output-style=GNU %t.so | FileCheck %s6# RUN: llvm-readelf --dyn-symbols %t.so | FileCheck %s
77
8 .weak openat8 .weak openat
9openat:9openat:
deps/lld/test/ELF/version-script-weak.s+2-2
...@@ -6,11 +6,11 @@...@@ -6,11 +6,11 @@
6# RUN: llvm-ar rcs %t.a %tmp.o6# RUN: llvm-ar rcs %t.a %tmp.o
7# RUN: echo "{ local: *; };" > %t.script7# RUN: echo "{ local: *; };" > %t.script
8# RUN: ld.lld -shared --version-script %t.script %t.o %t.a -o %t.so8# RUN: ld.lld -shared --version-script %t.script %t.o %t.a -o %t.so
9# RUN: llvm-readobj -dyn-symbols -r %t.so | FileCheck %s9# RUN: llvm-readobj --dyn-syms -r %t.so | FileCheck %s
1010
11# CHECK: Relocations [11# CHECK: Relocations [
12# CHECK-NEXT: Section ({{.*}}) .rela.plt {12# CHECK-NEXT: Section ({{.*}}) .rela.plt {
13# CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT foo13# CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT foo
14# CHECK-NEXT: }14# CHECK-NEXT: }
15# CHECK-NEXT: ]15# CHECK-NEXT: ]
16# CHECK: Symbol {16# CHECK: Symbol {
deps/lld/test/ELF/version-script.s+6-12
...@@ -6,19 +6,19 @@...@@ -6,19 +6,19 @@
6# RUN: echo "{ global: foo1; foo3; local: *; };" > %t.script6# RUN: echo "{ global: foo1; foo3; local: *; };" > %t.script
7# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o7# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
8# RUN: ld.lld --version-script %t.script -shared %t.o %t2.so -o %t.so8# RUN: ld.lld --version-script %t.script -shared %t.o %t2.so -o %t.so
9# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=DSO %s9# RUN: llvm-readobj --dyn-syms %t.so | FileCheck --check-prefix=DSO %s
1010
11# RUN: echo "# comment" > %t3.script11# RUN: echo "# comment" > %t3.script
12# RUN: echo "{ local: *; # comment" >> %t3.script12# RUN: echo "{ local: *; # comment" >> %t3.script
13# RUN: echo -n "}; # comment" >> %t3.script13# RUN: echo -n "}; # comment" >> %t3.script
14# RUN: ld.lld --version-script %t3.script -shared %t.o %t2.so -o %t3.so14# RUN: ld.lld --version-script %t3.script -shared %t.o %t2.so -o %t3.so
15# RUN: llvm-readobj -dyn-symbols %t3.so | FileCheck --check-prefix=DSO2 %s15# RUN: llvm-readobj --dyn-syms %t3.so | FileCheck --check-prefix=DSO2 %s
1616
17## Also check that both "global:" and "global :" forms are accepted17## Also check that both "global:" and "global :" forms are accepted
18# RUN: echo "VERSION_1.0 { global : foo1; local : *; };" > %t4.script18# RUN: echo "VERSION_1.0 { global : foo1; local : *; };" > %t4.script
19# RUN: echo "VERSION_2.0 { global: foo3; local: *; };" >> %t4.script19# RUN: echo "VERSION_2.0 { global: foo3; local: *; };" >> %t4.script
20# RUN: ld.lld --version-script %t4.script -shared %t.o %t2.so -o %t4.so20# RUN: ld.lld --version-script %t4.script -shared %t.o %t2.so -o %t4.so
21# RUN: llvm-readobj -dyn-symbols %t4.so | FileCheck --check-prefix=VERDSO %s21# RUN: llvm-readobj --dyn-syms %t4.so | FileCheck --check-prefix=VERDSO %s
2222
23# RUN: echo "VERSION_1.0 { global: foo1; local: *; };" > %t5.script23# RUN: echo "VERSION_1.0 { global: foo1; local: *; };" > %t5.script
24# RUN: echo "{ global: foo3; local: *; };" >> %t5.script24# RUN: echo "{ global: foo3; local: *; };" >> %t5.script
...@@ -32,12 +32,6 @@...@@ -32,12 +32,6 @@
32# RUN: FileCheck -check-prefix=ERR2 %s32# RUN: FileCheck -check-prefix=ERR2 %s
33# ERR2: EOF expected, but got VERSION_2.033# ERR2: EOF expected, but got VERSION_2.0
3434
35# RUN: echo "VERSION_1.0 { global: foo1; local: *; };" > %t6.script
36# RUN: echo "VERSION_2.0 { global: foo1; local: *; };" >> %t6.script
37# RUN: not ld.lld --version-script %t6.script -shared %t.o %t2.so -o /dev/null 2>&1 | \
38# RUN: FileCheck -check-prefix=ERR3 %s
39# ERR3: duplicate symbol 'foo1' in version script
40
41# RUN: echo "{ foo1; foo2; };" > %t.list35# RUN: echo "{ foo1; foo2; };" > %t.list
42# RUN: ld.lld --version-script %t.script --dynamic-list %t.list %t.o %t2.so -o %t236# RUN: ld.lld --version-script %t.script --dynamic-list %t.list %t.o %t2.so -o %t2
43# RUN: llvm-readobj %t2 > /dev/null37# RUN: llvm-readobj %t2 > /dev/null
...@@ -46,7 +40,7 @@...@@ -46,7 +40,7 @@
46# RUN: echo "VERSION_1.0 { global : foo1; local : *; };" > %t7a.script40# RUN: echo "VERSION_1.0 { global : foo1; local : *; };" > %t7a.script
47# RUN: echo "VERSION_2.0 { global: foo3; local: *; };" > %t7b.script41# RUN: echo "VERSION_2.0 { global: foo3; local: *; };" > %t7b.script
48# RUN: ld.lld --version-script %t7a.script --version-script %t7b.script -shared %t.o %t2.so -o %t7.so42# RUN: ld.lld --version-script %t7a.script --version-script %t7b.script -shared %t.o %t2.so -o %t7.so
49# RUN: llvm-readobj -dyn-symbols %t7.so | FileCheck --check-prefix=VERDSO %s43# RUN: llvm-readobj --dyn-syms %t7.so | FileCheck --check-prefix=VERDSO %s
5044
51# DSO: DynamicSymbols [45# DSO: DynamicSymbols [
52# DSO-NEXT: Symbol {46# DSO-NEXT: Symbol {
...@@ -149,12 +143,12 @@...@@ -149,12 +143,12 @@
149143
150# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o144# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
151# RUN: ld.lld --hash-style=sysv -shared %t.o %t2.so -o %t.so145# RUN: ld.lld --hash-style=sysv -shared %t.o %t2.so -o %t.so
152# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s146# RUN: llvm-readobj --dyn-syms %t.so | FileCheck --check-prefix=ALL %s
153147
154# RUN: echo "{ global: foo1; foo3; };" > %t2.script148# RUN: echo "{ global: foo1; foo3; };" > %t2.script
155# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o149# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
156# RUN: ld.lld --hash-style=sysv --version-script %t2.script -shared %t.o %t2.so -o %t.so150# RUN: ld.lld --hash-style=sysv --version-script %t2.script -shared %t.o %t2.so -o %t.so
157# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck --check-prefix=ALL %s151# RUN: llvm-readobj --dyn-syms %t.so | FileCheck --check-prefix=ALL %s
158152
159# ALL: DynamicSymbols [153# ALL: DynamicSymbols [
160# ALL-NEXT: Symbol {154# ALL-NEXT: Symbol {
deps/lld/test/ELF/version-use.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3// RUN: ld.lld %t.o %p/Inputs/version-use.so -o %t.so -shared -z defs3// RUN: ld.lld %t.o %p/Inputs/version-use.so -o %t.so -shared -z defs
4// RUN: llvm-readobj -s %t.so | FileCheck %s4// RUN: llvm-readobj -S %t.so | FileCheck %s
55
66
7 call bar@PLT7 call bar@PLT
deps/lld/test/ELF/version-wildcard.test+2-2
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
4# RUN: echo "VERSION_1.0 { global: foo*; local: *; };" > %t.script4# RUN: echo "VERSION_1.0 { global: foo*; local: *; };" > %t.script
5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so5# RUN: ld.lld --version-script %t.script -shared %t.o -o %t.so
6# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s6# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
77
8# CHECK: DynamicSymbols [8# CHECK: DynamicSymbols [
9# CHECK-NEXT: Symbol {9# CHECK-NEXT: Symbol {
...@@ -48,7 +48,7 @@...@@ -48,7 +48,7 @@
48# RUN: echo "VERSION_1.0 { global: foo2; local: *; };" > %t2.script48# RUN: echo "VERSION_1.0 { global: foo2; local: *; };" > %t2.script
49# RUN: echo "VERSION_2.0 { global: foo*; };" >> %t2.script49# RUN: echo "VERSION_2.0 { global: foo*; };" >> %t2.script
50# RUN: ld.lld --version-script %t2.script -shared %t.o -o %t2.so50# RUN: ld.lld --version-script %t2.script -shared %t.o -o %t2.so
51# RUN: llvm-readobj -dyn-symbols %t2.so | FileCheck --check-prefix=MIX %s51# RUN: llvm-readobj --dyn-syms %t2.so | FileCheck --check-prefix=MIX %s
5252
53# MIX: DynamicSymbols [53# MIX: DynamicSymbols [
54# MIX-NEXT: Symbol {54# MIX-NEXT: Symbol {
deps/lld/test/ELF/visibility.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// 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/visibility.s -o %t23// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/visibility.s -o %t2
4// RUN: ld.lld -shared %t %t2 -o %t34// RUN: ld.lld -shared %t %t2 -o %t3
5// RUN: llvm-readobj -t -dyn-symbols %t3 | FileCheck %s5// RUN: llvm-readobj --symbols --dyn-syms %t3 | FileCheck %s
66
7// CHECK: Symbols [7// CHECK: Symbols [
8// CHECK-NEXT: Symbol {8// CHECK-NEXT: Symbol {
deps/lld/test/ELF/vs-diagnostics-duplicate.s created+63
...@@ -0,0 +1,63 @@
1// REQUIRES: x86
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 %S/Inputs/vs-diagnostics-duplicate2.s -o %t2.o
4// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %S/Inputs/vs-diagnostics-duplicate3.s -o %t3.o
5// RUN: not ld.lld --vs-diagnostics %t1.o %t2.o %t3.o -o %tout 2>&1 | FileCheck %s
6
7// Case 1. Both symbols have full source location.
8// CHECK: duplicate.s(15): error: duplicate symbol: bar
9// CHECK-NEXT: >>> defined at duplicate.s:15
10// CHECK-NEXT: >>>{{.*}}1.o:(.text+0x{{.+}})
11// CHECK: >>> defined at duplicate2.s:20
12// CHECK: >>>{{.*}}2.o:(.text+0x{{.+}})
13
14// Case 2. The source locations are unknown for both symbols.
15// CHECK: {{.*}}ld.lld{{.*}}: error: duplicate symbol: foo
16// CHECK-NEXT: >>> defined at {{.*}}1.o:(.text+0x{{.+}})
17// CHECK-NEXT: >>> defined at {{.*}}2.o:(.text+0x{{.+}})
18
19// Case 3. For the second definition of `baz` we know only the source file found in a STT_FILE symbol.
20// CHECK: duplicate.s(30): error: duplicate symbol: baz
21// CHECK-NEXT: >>> defined at duplicate.s:30
22// CHECK-NEXT: >>> {{.*}}1.o:(.text+0x{{.+}})
23// CHECK-NEXT: >>> defined at duplicate3.s
24// CHECK-NEXT: >>> {{.*}}3.o:(.text+0x{{.+}})
25
26.global _start, foo, bar, baz
27.text
28_start:
29 nop
30
31foo:
32 nop
33
34.file 1 "duplicate.s"
35.loc 1 15
36
37bar:
38 nop
39
40.loc 1 30
41baz:
42 nop
43
44.section .debug_abbrev,"",@progbits
45 .byte 1 # Abbreviation Code
46 .byte 17 # DW_TAG_compile_unit
47 .byte 0 # DW_CHILDREN_no
48 .byte 16 # DW_AT_stmt_list
49 .byte 23 # DW_FORM_sec_offset
50 .byte 0 # EOM(1)
51 .byte 0 # EOM(2)
52 .byte 0 # EOM(3)
53
54.section .debug_info,"",@progbits
55 .long .Lend0 - .Lbegin0 # Length of Unit
56.Lbegin0:
57 .short 4 # DWARF version number
58 .long .debug_abbrev # Offset Into Abbrev. Section
59 .byte 8 # Address Size (in bytes)
60 .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
61 .long .debug_line # DW_AT_stmt_list
62.Lend0:
63 .section .debug_line,"",@progbits
deps/lld/test/ELF/vs-diagnostics-dynamic-relocation.s created+35
...@@ -0,0 +1,35 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: not ld.lld -shared --vs-diagnostics %t.o -o /dev/null 2>&1 | FileCheck %s
4
5// CHECK: dyn.s(15): error: can't create dynamic relocation R_X86_64_64 against local symbol in readonly segment; recompile object files with -fPIC or pass '-Wl,-z,notext' to allow text relocations in the output
6// CHECK-NEXT: >>> defined in {{.*}}.o
7// CHECK-NEXT: >>> referenced by dyn.s:15
8// CHECK-NEXT: >>>{{.*}}.o:(.text+0x{{.+}})
9
10.file 1 "dyn.s"
11.loc 1 15
12
13foo:
14.quad foo
15
16.section .debug_abbrev,"",@progbits
17 .byte 1 # Abbreviation Code
18 .byte 17 # DW_TAG_compile_unit
19 .byte 0 # DW_CHILDREN_no
20 .byte 16 # DW_AT_stmt_list
21 .byte 23 # DW_FORM_sec_offset
22 .byte 0 # EOM(1)
23 .byte 0 # EOM(2)
24 .byte 0 # EOM(3)
25
26.section .debug_info,"",@progbits
27 .long .Lend0 - .Lbegin0 # Length of Unit
28.Lbegin0:
29 .short 4 # DWARF version number
30 .long .debug_abbrev # Offset Into Abbrev. Section
31 .byte 8 # Address Size (in bytes)
32 .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
33 .long .debug_line # DW_AT_stmt_list
34.Lend0:
35 .section .debug_line,"",@progbits
deps/lld/test/ELF/vs-diagnostics-undefined-symbol-1.s created+15
...@@ -0,0 +1,15 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
3// RUN: not ld.lld --vs-diagnostics %t1.o -o %tout 2>&1 \
4// RUN: | FileCheck -check-prefix=ERR -check-prefix=CHECK -DFILE=%t1.o %s
5// RUN: ld.lld --vs-diagnostics --warn-unresolved-symbols %t1.o -o %tout 2>&1 \
6// RUN: | FileCheck -check-prefix=WARN -check-prefix=CHECK -DFILE=%t1.o %s
7
8// ERR: [[FILE]]: error: undefined symbol: foo
9// WARN: [[FILE]]: warning: undefined symbol: foo
10// CHECK-NEXT: >>> referenced by {{.*}}1.o:(.text+0x{{.+}})
11
12.global _start, foo
13.text
14_start:
15 jmp foo
\ No newline at end of file
deps/lld/test/ELF/vs-diagnostics-undefined-symbol-2.s created+18
...@@ -0,0 +1,18 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
3// RUN: not ld.lld --vs-diagnostics %t1.o -o %tout 2>&1 \
4// RUN: | FileCheck -check-prefix=ERR -check-prefix=CHECK %s
5// RUN: ld.lld --vs-diagnostics --warn-unresolved-symbols %t1.o -o %tout 2>&1 \
6// RUN: | FileCheck -check-prefix=WARN -check-prefix=CHECK %s
7
8// ERR: {{.*}}ld.lld{{.*}}: error: undefined symbol: foo
9// WARN: {{.*}}ld.lld{{.*}}: warning: undefined symbol: foo
10// CHECK-NEXT: >>> referenced by undef2.s
11// CHECK-NEXT: >>> {{.*}}1.o:(.text+0x{{.+}})
12
13.file "undef2.s"
14
15.global _start, foo
16.text
17_start:
18 jmp foo
deps/lld/test/ELF/vs-diagnostics-undefined-symbol-3.s created+40
...@@ -0,0 +1,40 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
3// RUN: not ld.lld --vs-diagnostics %t1.o -o %tout 2>&1 \
4// RUN: | FileCheck -check-prefix=ERR -check-prefix=CHECK %s
5// RUN: ld.lld --vs-diagnostics --warn-unresolved-symbols %t1.o -o %tout 2>&1 \
6// RUN: | FileCheck -check-prefix=WARN -check-prefix=CHECK %s
7
8// ERR: undef3.s(15): error: undefined symbol: foo
9// WARN: undef3.s(15): warning: undefined symbol: foo
10// CHECK: >>> referenced by undef3.s:15
11// CHECK-NEXT: >>> {{.*}}1.o:(.text+0x{{.+}})
12
13.file 1 "undef3.s"
14
15.global _start, foo
16.text
17_start:
18.loc 1 15
19 jmp foo
20
21.section .debug_abbrev,"",@progbits
22 .byte 1 # Abbreviation Code
23 .byte 17 # DW_TAG_compile_unit
24 .byte 0 # DW_CHILDREN_no
25 .byte 16 # DW_AT_stmt_list
26 .byte 23 # DW_FORM_sec_offset
27 .byte 0 # EOM(1)
28 .byte 0 # EOM(2)
29 .byte 0 # EOM(3)
30
31.section .debug_info,"",@progbits
32 .long .Lend0 - .Lbegin0 # Length of Unit
33.Lbegin0:
34 .short 4 # DWARF version number
35 .long .debug_abbrev # Offset Into Abbrev. Section
36 .byte 8 # Address Size (in bytes)
37 .byte 1 # Abbrev [1] 0xb:0x1f DW_TAG_compile_unit
38 .long .debug_line # DW_AT_stmt_list
39.Lend0:
40 .section .debug_line,"",@progbits
deps/lld/test/ELF/vs-diagnostics-versionscript.s created+5
...@@ -0,0 +1,5 @@
1# RUN: echo "\"" > %/terr1.script
2# RUN: not ld.lld --vs-diagnostics --version-script %/terr1.script 2>&1 | \
3# RUN: FileCheck %s -DSCRIPT="%/terr1.script"
4
5# CHECK: [[SCRIPT]](1): error: [[SCRIPT]]:1: unclosed quote
deps/lld/test/ELF/warn-unresolved-symbols-hidden.s+2-2
...@@ -3,8 +3,8 @@...@@ -3,8 +3,8 @@
3# RUN: not ld.lld -shared %t.o -o /dev/null -z defs --warn-unresolved-symbols 2>&1| FileCheck %s3# RUN: not ld.lld -shared %t.o -o /dev/null -z defs --warn-unresolved-symbols 2>&1| FileCheck %s
44
5# CHECK: warning: undefined symbol: foo5# CHECK: warning: undefined symbol: foo
6# CHECK: error: undefined symbol: bar6# CHECK: error: undefined hidden symbol: bar
7# CHECK: error: undefined symbol: zed7# CHECK: error: undefined protected symbol: zed
88
9.data9.data
10.quad foo10.quad foo
deps/lld/test/ELF/weak-undef-export.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
44
5# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o5# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
6# RUN: ld.lld --export-dynamic %t.o -o %t6# RUN: ld.lld --export-dynamic %t.o -o %t
7# RUN: llvm-readobj -dyn-symbols %t | FileCheck %s7# RUN: llvm-readobj --dyn-syms %t | FileCheck %s
88
9# CHECK: DynamicSymbols [9# CHECK: DynamicSymbols [
10# CHECK-NEXT: Symbol {10# CHECK-NEXT: Symbol {
deps/lld/test/ELF/weak-undef-hidden.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s4// RUN: llvm-readobj -r -S --section-data %t.so | FileCheck %s
55
6.data6.data
7.weak g7.weak g
deps/lld/test/ELF/weak-undef-lib.s+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t2.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux - -o %t2.o
55
6# RUN: ld.lld -shared -o %t.so %t1.o --start-lib %t2.o6# RUN: ld.lld -shared -o %t.so %t1.o --start-lib %t2.o
7# RUN: llvm-readobj -dyn-symbols %t.so | FileCheck %s7# RUN: llvm-readobj --dyn-syms %t.so | FileCheck %s
88
9# CHECK: Name: foo9# CHECK: Name: foo
10# CHECK-NEXT: Value: 0x010# CHECK-NEXT: Value: 0x0
deps/lld/test/ELF/weak-undef-no-shared-libs.s created+28
...@@ -0,0 +1,28 @@
1// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
3// RUN: ld.lld -pie %t.o -o %t
4// RUN: llvm-readobj -V --dyn-syms %t | FileCheck %s
5
6 .globl _start
7_start:
8 .type foo,@function
9 .weak foo
10 .long foo@gotpcrel
11
12// Test that an entry for weak undefined symbols is NOT emitted in .dynsym as
13// the PIE was not linked with any shared libraries. There are other tests which
14// ensure that the weak undefined symbols do get emitted in .dynsym for PIEs
15// linked against dynamic libraries.
16
17
18// CHECK: DynamicSymbols [
19// CHECK-NEXT: Symbol {
20// CHECK-NEXT: Name:
21// CHECK-NEXT: Value: 0x0
22// CHECK-NEXT: Size: 0
23// CHECK-NEXT: Binding: Local (0x0)
24// CHECK-NEXT: Type: None (0x0)
25// CHECK-NEXT: Other: 0
26// CHECK-NEXT: Section: Undefined (0x0)
27// CHECK-NEXT: }
28// CHECK-NEXT: ]
deps/lld/test/ELF/weak-undef-rw.s+6-2
...@@ -1,9 +1,13 @@...@@ -1,9 +1,13 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t --export-dynamic3# RUN: ld.lld %t.o -o %t --export-dynamic
4# RUN: llvm-readobj -r %t | FileCheck %s4# RUN: llvm-readelf -r %t | FileCheck %s
55
6# CHECK: R_X86_64_64 foobar 0x06## gABI leaves the behavior of weak undefined references implementation defined.
7## We choose to resolve it statically and not create a dynamic relocation for
8## implementation simplicity. This also matches ld.bfd and gold.
9
10# CHECK: no relocations
711
8 .global _start12 .global _start
9_start:13_start:
deps/lld/test/ELF/weak-undef-shared.s+35-17
...@@ -1,19 +1,37 @@...@@ -1,19 +1,37 @@
1// REQUIRES: x861# REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3// RUN: llvm-mc %p/Inputs/shared.s -o %t2.o -filetype=obj -triple=x86_64-pc-linux3# RUN: ld.lld -shared %t.o -o %t.so
4// RUN: ld.lld %t2.o -o %t2.so -shared
5// RUN: ld.lld %t.o %t2.so -o %t.exe
6// RUN: llvm-readobj -t %t.exe | FileCheck %s
74
8// CHECK: Name: bar5# RUN: echo '.data; .weak foo; .quad foo' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o
9// CHECK-NEXT: Value: 0x2010206# RUN: echo '.data; .quad foo' | llvm-mc -filetype=obj -triple=x86_64 - -o %t2.o
10// CHECK-NEXT: Size: 07# RUN: ld.lld -shared %t2.o -o %t2.so
11// CHECK-NEXT: Binding: Weak
12// CHECK-NEXT: Type: Function
13// CHECK-NEXT: Other: 0
14// CHECK-NEXT: Section: Undefined
158
16.global _start9## If the first undefined reference is weak, the binding changes to
17_start:10## STB_WEAK.
18 .weak bar11# RUN: ld.lld %t1.o %t.so -o %t
19 .quad bar12# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=WEAK %s
13# RUN: ld.lld %t.so %t1.o -o %t
14# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=WEAK %s
15
16## The binding remains STB_WEAK if there is no STB_GLOBAL undefined reference.
17# RUN: ld.lld %t1.o %t.so %t1.o -o %t
18# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=WEAK %s
19# RUN: ld.lld %t.so %t1.o %t1.o -o %t
20# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=WEAK %s
21
22## The binding changes back to STB_GLOBAL if there is a STB_GLOBAL undefined reference.
23# RUN: ld.lld %t1.o %t.so %t2.o -o %t
24# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=GLOBAL %s
25# RUN: ld.lld %t2.o %t.so %t1.o -o %t
26# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=GLOBAL %s
27
28## Check the binding (weak) is not affected by the STB_GLOBAL undefined
29## reference in %t2.so
30# RUN: ld.lld %t1.o %t2.so -o %t
31# RUN: llvm-readelf --dyn-syms %t | FileCheck --check-prefix=WEAK %s
32
33# WEAK: NOTYPE WEAK DEFAULT UND foo
34# GLOBAL: NOTYPE GLOBAL DEFAULT UND foo
35
36.globl foo
37foo:
deps/lld/test/ELF/weak-undef-shared2.s created+21
...@@ -0,0 +1,21 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: echo '.globl f; f:' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o
4# RUN: echo '.weak f; .data; .quad f' | llvm-mc -filetype=obj -triple=x86_64 - -o %t2.o
5# RUN: ld.lld -shared %t1.o -o %t1.so
6# RUN: ld.lld -shared %t2.o -o %t2.so
7
8## The undefined reference is STB_GLOBAL in %t.o while STB_WEAK in %t2.so.
9## Check the binding of the result is STB_GLOBAL.
10
11# RUN: ld.lld %t.o %t1.so %t2.so -o %t
12# RUN: llvm-readelf --dyn-syms %t | FileCheck %s
13# RUN: ld.lld %t1.so %t.o %t2.so -o %t
14# RUN: llvm-readelf --dyn-syms %t | FileCheck %s
15# RUN: ld.lld %t1.so %t2.so %t.o -o %t
16# RUN: llvm-readelf --dyn-syms %t | FileCheck %s
17
18# CHECK: NOTYPE GLOBAL DEFAULT UND f
19
20.data
21.quad f
deps/lld/test/ELF/weak-undef-val.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t --export-dynamic3# RUN: ld.lld %t.o -o %t --export-dynamic
4# RUN: llvm-readobj -s -section-data %t | FileCheck %s4# RUN: llvm-readobj -S --section-data %t | FileCheck %s
55
6# CHECK: Name: .text6# CHECK: Name: .text
7# CHECK-NEXT: Type: SHT_PROGBITS7# CHECK-NEXT: Type: SHT_PROGBITS
deps/lld/test/ELF/weak-undef.s+4-2
...@@ -1,7 +1,9 @@...@@ -1,7 +1,9 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/dummy-shared.s -o %t1.o
3# RUN: ld.lld %t1.o -shared -o %t1.so
2# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o4# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3# RUN: ld.lld %t.o -o %t -pie5# RUN: ld.lld %t.o -o %t %t1.so -pie
4# RUN: llvm-readobj -dyn-symbols %t | FileCheck %s6# RUN: llvm-readobj --dyn-syms %t | FileCheck %s
57
6# CHECK: DynamicSymbols [8# CHECK: DynamicSymbols [
7# CHECK-NEXT: Symbol {9# CHECK-NEXT: Symbol {
deps/lld/test/ELF/wrap-dynamic-undef.s+1-1
...@@ -3,7 +3,7 @@...@@ -3,7 +3,7 @@
3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/wrap-dynamic-undef.s -o %t2.o3# RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/wrap-dynamic-undef.s -o %t2.o
4# RUN: ld.lld %t2.o -o %t2.so -shared4# RUN: ld.lld %t2.o -o %t2.so -shared
5# RUN: ld.lld %t1.o %t2.so -o %t --wrap foo5# RUN: ld.lld %t1.o %t2.so -o %t --wrap foo
6# RUN: llvm-readobj -dyn-symbols --elf-output-style=GNU %t | FileCheck %s6# RUN: llvm-readelf --dyn-syms %t | FileCheck %s
77
8# Test that the dynamic relocation uses foo. We used to produce a8# Test that the dynamic relocation uses foo. We used to produce a
9# relocation with __real_foo.9# relocation with __real_foo.
deps/lld/test/ELF/wrap-entry.s+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
33
4// RUN: ld.lld -o %t.exe %t.o -wrap=_start4// RUN: ld.lld -o %t.exe %t.o -wrap=_start
5// RUN: llvm-readobj -file-headers %t.exe | FileCheck %s5// RUN: llvm-readobj --file-headers %t.exe | FileCheck %s
66
7// CHECK: Entry: 0x2010017// CHECK: Entry: 0x201001
88
deps/lld/test/ELF/wrap-plt.s+3-3
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
33
4// RUN: ld.lld -o %t2 %t -wrap foo -shared4// RUN: ld.lld -o %t2 %t -wrap foo -shared
5// RUN: llvm-readobj -s -r %t2 | FileCheck %s5// RUN: llvm-readobj -S -r %t2 | FileCheck %s
6// RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s6// RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s
77
8// CHECK: Name: .plt8// CHECK: Name: .plt
...@@ -20,8 +20,8 @@...@@ -20,8 +20,8 @@
2020
21// CHECK: Relocations [21// CHECK: Relocations [
22// CHECK-NEXT: Section ({{.*}}) .rela.plt {22// CHECK-NEXT: Section ({{.*}}) .rela.plt {
23// CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT __wrap_foo 0x023// CHECK-NEXT: 0x3018 R_X86_64_JUMP_SLOT __wrap_foo 0x0
24// CHECK-NEXT: 0x2020 R_X86_64_JUMP_SLOT _start 0x024// CHECK-NEXT: 0x3020 R_X86_64_JUMP_SLOT _start 0x0
25// CHECK-NEXT: }25// CHECK-NEXT: }
26// CHECK-NEXT: ]26// CHECK-NEXT: ]
2727
deps/lld/test/ELF/wrap.s+1-1
...@@ -14,7 +14,7 @@...@@ -14,7 +14,7 @@
14// CHECK-NEXT: movl $0x11010, %edx14// CHECK-NEXT: movl $0x11010, %edx
15// CHECK-NEXT: movl $0x11000, %edx15// CHECK-NEXT: movl $0x11000, %edx
1616
17// RUN: llvm-readobj -t %t3 > %t4.dump17// RUN: llvm-readobj --symbols %t3 > %t4.dump
18// RUN: FileCheck --check-prefix=SYM1 %s < %t4.dump18// RUN: FileCheck --check-prefix=SYM1 %s < %t4.dump
19// RUN: FileCheck --check-prefix=SYM2 %s < %t4.dump19// RUN: FileCheck --check-prefix=SYM2 %s < %t4.dump
20// RUN: FileCheck --check-prefix=SYM3 %s < %t4.dump20// RUN: FileCheck --check-prefix=SYM3 %s < %t4.dump
deps/lld/test/ELF/x86-64-cet.s created+48
...@@ -0,0 +1,48 @@
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/x86-64-cet1.s -o %t1.o
4# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-cet2.s -o %t2.o
5# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-cet3.s -o %t3.o
6# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %p/Inputs/x86-64-cet4.s -o %t4.o
7
8# RUN: ld.lld -e func1 %t.o %t1.o -o %t
9# RUN: llvm-readelf -n %t | FileCheck -check-prefix=CET -match-full-lines %s
10
11# RUN: ld.lld -e func1 %t.o %t2.o -o %t
12# RUN: llvm-readelf -n %t | FileCheck -check-prefix=CET -match-full-lines %s
13
14# CET: Properties: x86 feature: IBT, SHSTK
15
16# RUN: ld.lld -e func1 %t.o %t3.o -o %t
17# RUN: llvm-readelf -S %t | FileCheck -check-prefix=NOCET %s
18
19# NOCET: Section Headers
20# NOCET-NOT: .note.gnu.property
21
22# RUN: not ld.lld -e func1 %t.o %t3.o -o %t --require-cet 2>&1 \
23# RUN: | FileCheck -check-prefix=ERROR %s
24# ERROR: x86-64-cet.s.tmp3.o: --require-cet: file is not compatible with CET
25
26# RUN: ld.lld -e func1 %t.o %t4.o -o %t
27# RUN: llvm-readelf -n %t | FileCheck -check-prefix=NOSHSTK -match-full-lines %s
28
29# Check .note.gnu.protery without property SHSTK.
30# NOSHSTK: Properties: x86 feature: IBT
31
32.section ".note.gnu.property", "a"
33.long 4
34.long 0x10
35.long 0x5
36.asciz "GNU"
37
38.long 0xc0000002
39.long 4
40.long 3
41.long 0
42
43.text
44.globl func1
45.type func1,@function
46func1:
47 call func2
48 ret
deps/lld/test/ELF/x86-64-dyn-rel-error5.s created+26
...@@ -0,0 +1,26 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: not ld.lld -pie %t.o -o /dev/null 2>&1 | FileCheck %s
4# RUN: not ld.lld -shared %t.o -o /dev/null 2>&1 | FileCheck %s
5
6## Check we don't create dynamic relocations in a writable section,
7## if the number of bits is smaller than the wordsize.
8
9.globl hidden
10.hidden hidden
11local:
12hidden:
13
14# CHECK: error: relocation R_X86_64_8 cannot be used against local symbol; recompile with -fPIC
15# CHECK-NEXT: >>> defined in {{.*}}.o
16# CHECK-NEXT: >>> referenced by {{.*}}.o:(.data+0x0)
17# CHECK: error: relocation R_X86_64_16 cannot be used against local symbol; recompile with -fPIC
18# CHECK: error: relocation R_X86_64_32 cannot be used against local symbol; recompile with -fPIC
19# CHECK: error: relocation R_X86_64_32 cannot be used against symbol hidden; recompile with -fPIC
20
21.data
22.byte local # R_X86_64_8
23.short local # R_X86_64_16
24.long local # R_X86_64_32
25
26.long hidden # R_X86_64_32
deps/lld/test/ELF/x86-64-pcrel.s created+23
...@@ -0,0 +1,23 @@
1// REQUIRES: x86
2
3// This is a test for R_X86_64_PC8 and R_X86_64_PC16.
4
5// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t1.o
6// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %p/Inputs/x86-64-pcrel.s -o %t2.o
7// RUN: ld.lld -o %t.exe %t1.o %t2.o
8// RUN: llvm-objdump -s %t.exe | FileCheck %s
9
10// CHECK: Contents of section .text:
11// CHECK-NEXT: 2000cccc cccccccc cccccccc cccccccc
12// CHECK-NEXT: 20cccccc cccccccc cccccccc cccccccc
13// CHECK-NEXT: e0ffcccc cccccccc cccccccc cccccccc
14// CHECK-NEXT: e0cccccc cccccccc cccccccc cccccccc
15
16.globl _start
17_start:
18
19.word foo - _start
20.fill 14,1,0xcc
21
22.byte foo - _start
23.fill 15,1,0xcc
deps/lld/test/ELF/x86-64-plt-high-addr.s+4-4
...@@ -8,16 +8,16 @@...@@ -8,16 +8,16 @@
8// RUN: llvm-objdump -s -j .got.plt %t1.exe | FileCheck %s8// RUN: llvm-objdump -s -j .got.plt %t1.exe | FileCheck %s
99
10// CHECK: Contents of section .got.plt:10// CHECK: Contents of section .got.plt:
11// CHECK-NEXT: cafe00002000 00300000 feca0000 00000000 0000000011// CHECK-NEXT: cafe00003000 00200000 feca0000 00000000 00000000
12// CHECK-NEXT: cafe00002010 00000000 00000000 26100000 feca000012// CHECK-NEXT: cafe00003010 00000000 00000000 26100000 feca0000
1313
14// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o14// RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2.o
15// RUN: ld.lld -o %t2.exe %t2.o %t.so -image-base=0xcafe00000000 -z retpolineplt15// RUN: ld.lld -o %t2.exe %t2.o %t.so -image-base=0xcafe00000000 -z retpolineplt
16// RUN: llvm-objdump -s -j .got.plt %t2.exe | FileCheck -check-prefix=RETPOLINE %s16// RUN: llvm-objdump -s -j .got.plt %t2.exe | FileCheck -check-prefix=RETPOLINE %s
1717
18// RETPOLINE: Contents of section .got.plt:18// RETPOLINE: Contents of section .got.plt:
19// RETPOLINE-NEXT: cafe00002000 00300000 feca0000 00000000 0000000019// RETPOLINE-NEXT: cafe00003000 00200000 feca0000 00000000 00000000
20// RETPOLINE-NEXT: cafe00002010 00000000 00000000 51100000 feca000020// RETPOLINE-NEXT: cafe00003010 00000000 00000000 51100000 feca0000
2121
22.global _start22.global _start
23_start:23_start:
deps/lld/test/ELF/x86-64-rela.s+2-2
...@@ -1,10 +1,10 @@...@@ -1,10 +1,10 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o2// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t.o
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -dynamic-table %t.so | FileCheck %s4// RUN: llvm-readobj --dynamic-table %t.so | FileCheck %s
5// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux-gnux32 %s -o %t.o5// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux-gnux32 %s -o %t.o
6// RUN: ld.lld %t.o -o %t.so -shared6// RUN: ld.lld %t.o -o %t.so -shared
7// RUN: llvm-readobj -dynamic-table %t.so | FileCheck %s7// RUN: llvm-readobj --dynamic-table %t.so | FileCheck %s
88
9 call foo@plt9 call foo@plt
1010
deps/lld/test/ELF/x86-64-reloc-16.s deleted-14
...@@ -1,14 +0,0 @@
1// REQUIRES: x86
2
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/x86-64-reloc-16.s -o %t1
4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/x86-64-reloc-16-error.s -o %t2
5// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
6// RUN: ld.lld -shared %t %t1 -o /dev/null
7
8// CHECK: Contents of section .text:
9// CHECK-NEXT: 200000 42
10
11// RUN: not ld.lld -shared %t %t2 -o /dev/null 2>&1 | FileCheck --check-prefix=ERROR %s
12// ERROR: relocation R_X86_64_16 out of range: 65536 is not in [0, 65535]
13
14.short foo
deps/lld/test/ELF/x86-64-reloc-8-16.s created+25
...@@ -0,0 +1,25 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/abs255.s -o %t255.o
4# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/abs256.s -o %t256.o
5# RUN: llvm-mc -filetype=obj -triple=x86_64 %S/Inputs/abs257.s -o %t257.o
6
7# RUN: ld.lld %t.o %t256.o -o %t
8# RUN: llvm-readelf -x .data %t | FileCheck %s
9# CHECK: 0x{{[0-9a-f]+}} ff80ffff 0080
10
11# RUN: not ld.lld %t.o %t255.o -o /dev/null 2>&1 | FileCheck --check-prefix=OVERFLOW1 %s
12# OVERFLOW1: relocation R_X86_64_8 out of range: -129 is not in [-128, 255]
13# OVERFLOW1: relocation R_X86_64_16 out of range: -32769 is not in [-32768, 65535]
14
15# RUN: not ld.lld %t.o %t257.o -o /dev/null 2>&1 | FileCheck --check-prefix=OVERFLOW2 %s
16# OVERFLOW2: relocation R_X86_64_8 out of range: 256 is not in [-128, 255]
17# OVERFLOW2: relocation R_X86_64_16 out of range: 65536 is not in [-32768, 65535]
18
19.globl _start
20_start:
21.data
22.byte foo - 1
23.byte foo - 384
24.word foo + 0xfeff
25.word foo - 0x8100
deps/lld/test/ELF/x86-64-reloc-8.s deleted-14
...@@ -1,14 +0,0 @@
1// REQUIRES: x86
2
3// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/x86-64-reloc-8.s -o %t1
4// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %S/Inputs/x86-64-reloc-8-error.s -o %t2
5// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
6// RUN: ld.lld -shared %t %t1 -o /dev/null
7
8// CHECK: Contents of section .text:
9// CHECK-NEXT: 200000 42
10
11// RUN: not ld.lld -shared %t %t2 -o /dev/null 2>&1 | FileCheck --check-prefix=ERROR %s
12// ERROR: relocation R_X86_64_8 out of range: 256 is not in [0, 255]
13
14.byte foo
deps/lld/test/ELF/x86-64-reloc-gotoff64.s+6-12
...@@ -4,14 +4,8 @@...@@ -4,14 +4,8 @@
4// RUN: llvm-readelf -S %t.so | FileCheck %s -check-prefix=SECTION4// RUN: llvm-readelf -S %t.so | FileCheck %s -check-prefix=SECTION
5// RUN: llvm-objdump -d %t.so | FileCheck %s5// RUN: llvm-objdump -d %t.so | FileCheck %s
66
7// SECTION: .dynamic DYNAMIC 00000000000030007// SECTION: .dynamic DYNAMIC 0000000000002000
8// SECTION: .got PROGBITS 0000000000003070 003070 0000008// SECTION: .got.plt PROGBITS 0000000000003000 003000 000018
9
10// All the _GLOBAL_OFFSET_TABLE_ occurrences below refer to the address
11// of GOT base, not the address of the symbol _GLOBAL_OFFSET_TABLE_. These
12// instructions are special and produce GOT base relative relocations. We
13// currently use .got end as the GOT base, which is not equal to
14// the address of the special symbol _GLOBAL_OFFSET_TABLE_.
159
16// The assembly is generated by10// The assembly is generated by
17// gcc -O2 -S -mcmodel=medium -fPIC a.c11// gcc -O2 -S -mcmodel=medium -fPIC a.c
...@@ -20,10 +14,10 @@...@@ -20,10 +14,10 @@
20// extern long _DYNAMIC[] __attribute__((visibility("hidden")));14// extern long _DYNAMIC[] __attribute__((visibility("hidden")));
21// long* dynamic() { return _DYNAMIC; }15// long* dynamic() { return _DYNAMIC; }
2216
23// 0x3070 (.got end) - 0x1007 = 829717// 0x3000 (.got.plt) - 0x1007 = 8185
24// 0x3000 (_DYNAMIC) - 0x3070 (.got end) = -11218// 0x2000 (_DYNAMIC) - 0x3000 (.got.plt) = -4096
25// CHECK: 1000: {{.*}} leaq 8297(%rip), %rdx19// CHECK: 1000: {{.*}} leaq 8185(%rip), %rdx
26// CHECK-NEXT: 1007: {{.*}} movabsq $-112, %rax20// CHECK-NEXT: 1007: {{.*}} movabsq $-4096, %rax
27.global dynamic21.global dynamic
28dynamic:22dynamic:
29 leaq _GLOBAL_OFFSET_TABLE_(%rip), %rdx23 leaq _GLOBAL_OFFSET_TABLE_(%rip), %rdx
deps/lld/test/ELF/x86-64-reloc-gotpc64.s+3-3
...@@ -4,11 +4,11 @@...@@ -4,11 +4,11 @@
4// RUN: llvm-readelf -S %t.so | FileCheck %s -check-prefix=SECTION4// RUN: llvm-readelf -S %t.so | FileCheck %s -check-prefix=SECTION
5// RUN: llvm-objdump -d %t.so | FileCheck %s5// RUN: llvm-objdump -d %t.so | FileCheck %s
66
7// SECTION: .got PROGBITS 0000000000003070 003070 0000007// SECTION: .got.plt PROGBITS 0000000000003000 003000 000018
88
9// 0x3070 (.got end) - 0x1000 = 83049// 0x3000 (.got.plt) - 0x1000 = 8192
10// CHECK: gotpc64:10// CHECK: gotpc64:
11// CHECK-NEXT: 1000: {{.*}} movabsq $8304, %r1111// CHECK-NEXT: 1000: {{.*}} movabsq $8192, %r11
12.global gotpc6412.global gotpc64
13gotpc64:13gotpc64:
14 movabsq $_GLOBAL_OFFSET_TABLE_-., %r1114 movabsq $_GLOBAL_OFFSET_TABLE_-., %r11
deps/lld/test/ELF/x86-64-retpoline-linkerscript.s+5-4
...@@ -13,9 +13,10 @@...@@ -13,9 +13,10 @@
13// RUN: llvm-objdump -d -s %t.exe | FileCheck %s13// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
1414
15// CHECK: Disassembly of section .plt:15// CHECK: Disassembly of section .plt:
16// CHECK-EMPTY:
16// CHECK-NEXT: .plt:17// CHECK-NEXT: .plt:
17// CHECK-NEXT: 10: ff 35 72 00 00 00 pushq 114(%rip)18// CHECK-NEXT: 10: ff 35 32 01 00 00 pushq 306(%rip)
18// CHECK-NEXT: 16: 4c 8b 1d 73 00 00 00 movq 115(%rip), %r1119// CHECK-NEXT: 16: 4c 8b 1d 33 01 00 00 movq 307(%rip), %r11
19// CHECK-NEXT: 1d: e8 0e 00 00 00 callq 14 <.plt+0x20>20// CHECK-NEXT: 1d: e8 0e 00 00 00 callq 14 <.plt+0x20>
20// CHECK-NEXT: 22: f3 90 pause21// CHECK-NEXT: 22: f3 90 pause
21// CHECK-NEXT: 24: 0f ae e8 lfence22// CHECK-NEXT: 24: 0f ae e8 lfence
...@@ -40,7 +41,7 @@...@@ -40,7 +41,7 @@
40// CHECK-NEXT: 3d: cc int341// CHECK-NEXT: 3d: cc int3
41// CHECK-NEXT: 3e: cc int342// CHECK-NEXT: 3e: cc int3
42// CHECK-NEXT: 3f: cc int343// CHECK-NEXT: 3f: cc int3
43// CHECK-NEXT: 40: 4c 8b 1d 51 00 00 00 movq 81(%rip), %r1144// CHECK-NEXT: 40: 4c 8b 1d 11 01 00 00 movq 273(%rip), %r11
44// CHECK-NEXT: 47: e8 e4 ff ff ff callq -28 <.plt+0x20>45// CHECK-NEXT: 47: e8 e4 ff ff ff callq -28 <.plt+0x20>
45// CHECK-NEXT: 4c: e9 d1 ff ff ff jmp -47 <.plt+0x12>46// CHECK-NEXT: 4c: e9 d1 ff ff ff jmp -47 <.plt+0x12>
46// CHECK-NEXT: 51: 68 00 00 00 00 pushq $047// CHECK-NEXT: 51: 68 00 00 00 00 pushq $0
...@@ -50,7 +51,7 @@...@@ -50,7 +51,7 @@
50// CHECK-NEXT: 5d: cc int351// CHECK-NEXT: 5d: cc int3
51// CHECK-NEXT: 5e: cc int352// CHECK-NEXT: 5e: cc int3
52// CHECK-NEXT: 5f: cc int353// CHECK-NEXT: 5f: cc int3
53// CHECK-NEXT: 60: 4c 8b 1d 39 00 00 00 movq 57(%rip), %r1154// CHECK-NEXT: 60: 4c 8b 1d f9 00 00 00 movq 249(%rip), %r11
54// CHECK-NEXT: 67: e8 c4 ff ff ff callq -60 <.plt+0x20>55// CHECK-NEXT: 67: e8 c4 ff ff ff callq -60 <.plt+0x20>
55// CHECK-NEXT: 6c: e9 b1 ff ff ff jmp -79 <.plt+0x12>56// CHECK-NEXT: 6c: e9 b1 ff ff ff jmp -79 <.plt+0x12>
56// CHECK-NEXT: 71: 68 01 00 00 00 pushq $157// CHECK-NEXT: 71: 68 01 00 00 00 pushq $1
deps/lld/test/ELF/x86-64-retpoline-znow-linkerscript.s+1
...@@ -13,6 +13,7 @@...@@ -13,6 +13,7 @@
13// RUN: llvm-objdump -d -s %t.exe | FileCheck %s13// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
1414
15// CHECK: Disassembly of section .plt:15// CHECK: Disassembly of section .plt:
16// CHECK-EMPTY:
16// CHECK-NEXT: .plt:17// CHECK-NEXT: .plt:
17// CHECK-NEXT: 10: e8 0b 00 00 00 callq 11 <.plt+0x10>18// CHECK-NEXT: 10: e8 0b 00 00 00 callq 11 <.plt+0x10>
18// CHECK-NEXT: 15: f3 90 pause19// CHECK-NEXT: 15: f3 90 pause
deps/lld/test/ELF/x86-64-retpoline-znow.s+1
...@@ -7,6 +7,7 @@...@@ -7,6 +7,7 @@
7// RUN: llvm-objdump -d -s %t.exe | FileCheck %s7// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
88
9// CHECK: Disassembly of section .plt:9// CHECK: Disassembly of section .plt:
10// CHECK-EMPTY:
10// CHECK-NEXT: .plt:11// CHECK-NEXT: .plt:
11// CHECK-NEXT: 1010: e8 0b 00 00 00 callq 11 <.plt+0x10>12// CHECK-NEXT: 1010: e8 0b 00 00 00 callq 11 <.plt+0x10>
12// CHECK-NEXT: 1015: f3 90 pause13// CHECK-NEXT: 1015: f3 90 pause
deps/lld/test/ELF/x86-64-retpoline.s+8-7
...@@ -7,9 +7,10 @@...@@ -7,9 +7,10 @@
7// RUN: llvm-objdump -d -s %t.exe | FileCheck %s7// RUN: llvm-objdump -d -s %t.exe | FileCheck %s
88
9// CHECK: Disassembly of section .plt:9// CHECK: Disassembly of section .plt:
10// CHECK-EMPTY:
10// CHECK-NEXT: .plt:11// CHECK-NEXT: .plt:
11// CHECK-NEXT: 1010: ff 35 f2 0f 00 00 pushq 4082(%rip)12// CHECK-NEXT: 1010: ff 35 f2 1f 00 00 pushq 8178(%rip)
12// CHECK-NEXT: 1016: 4c 8b 1d f3 0f 00 00 movq 4083(%rip), %r1113// CHECK-NEXT: 1016: 4c 8b 1d f3 1f 00 00 movq 8179(%rip), %r11
13// CHECK-NEXT: 101d: e8 0e 00 00 00 callq 14 <.plt+0x20>14// CHECK-NEXT: 101d: e8 0e 00 00 00 callq 14 <.plt+0x20>
14// CHECK-NEXT: 1022: f3 90 pause15// CHECK-NEXT: 1022: f3 90 pause
15// CHECK-NEXT: 1024: 0f ae e8 lfence16// CHECK-NEXT: 1024: 0f ae e8 lfence
...@@ -34,7 +35,7 @@...@@ -34,7 +35,7 @@
34// CHECK-NEXT: 103d: cc int335// CHECK-NEXT: 103d: cc int3
35// CHECK-NEXT: 103e: cc int336// CHECK-NEXT: 103e: cc int3
36// CHECK-NEXT: 103f: cc int337// CHECK-NEXT: 103f: cc int3
37// CHECK-NEXT: 1040: 4c 8b 1d d1 0f 00 00 movq 4049(%rip), %r1138// CHECK-NEXT: 1040: 4c 8b 1d d1 1f 00 00 movq 8145(%rip), %r11
38// CHECK-NEXT: 1047: e8 e4 ff ff ff callq -28 <.plt+0x20>39// CHECK-NEXT: 1047: e8 e4 ff ff ff callq -28 <.plt+0x20>
39// CHECK-NEXT: 104c: e9 d1 ff ff ff jmp -47 <.plt+0x12>40// CHECK-NEXT: 104c: e9 d1 ff ff ff jmp -47 <.plt+0x12>
40// CHECK-NEXT: 1051: 68 00 00 00 00 pushq $041// CHECK-NEXT: 1051: 68 00 00 00 00 pushq $0
...@@ -44,7 +45,7 @@...@@ -44,7 +45,7 @@
44// CHECK-NEXT: 105d: cc int345// CHECK-NEXT: 105d: cc int3
45// CHECK-NEXT: 105e: cc int346// CHECK-NEXT: 105e: cc int3
46// CHECK-NEXT: 105f: cc int347// CHECK-NEXT: 105f: cc int3
47// CHECK-NEXT: 1060: 4c 8b 1d b9 0f 00 00 movq 4025(%rip), %r1148// CHECK-NEXT: 1060: 4c 8b 1d b9 1f 00 00 movq 8121(%rip), %r11
48// CHECK-NEXT: 1067: e8 c4 ff ff ff callq -60 <.plt+0x20>49// CHECK-NEXT: 1067: e8 c4 ff ff ff callq -60 <.plt+0x20>
49// CHECK-NEXT: 106c: e9 b1 ff ff ff jmp -79 <.plt+0x12>50// CHECK-NEXT: 106c: e9 b1 ff ff ff jmp -79 <.plt+0x12>
50// CHECK-NEXT: 1071: 68 01 00 00 00 pushq $151// CHECK-NEXT: 1071: 68 01 00 00 00 pushq $1
...@@ -56,9 +57,9 @@...@@ -56,9 +57,9 @@
56// CHECK-NEXT: 107f: cc int357// CHECK-NEXT: 107f: cc int3
5758
58// CHECK: Contents of section .got.plt:59// CHECK: Contents of section .got.plt:
59// CHECK-NEXT: 2000 00300000 00000000 00000000 0000000060// CHECK-NEXT: 3000 00200000 00000000 00000000 00000000
60// CHECK-NEXT: 2010 00000000 00000000 51100000 0000000061// CHECK-NEXT: 3010 00000000 00000000 51100000 00000000
61// CHECK-NEXT: 2020 71100000 0000000062// CHECK-NEXT: 3020 71100000 00000000
6263
63.global _start64.global _start
64_start:65_start:
deps/lld/test/ELF/x86-64-static-tls-model.s created+18
...@@ -0,0 +1,18 @@
1# REQUIRES: x86
2
3## In this test R_X86_64_GOTTPOFF is a IE relocation (static TLS model),
4## test check we add STATIC_TLS flag.
5
6# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.o
7# RUN: ld.lld %t.o -o %t1 -shared
8# RUN: llvm-readobj --dynamic-table %t1 | FileCheck %s
9
10# CHECK: DynamicSection [
11# CHECK: FLAGS STATIC_TLS
12
13.section ".tdata", "awT", @progbits
14.globl var
15var:
16
17movq var@GOTTPOFF(%rip), %rax # R_X86_64_GOTTPOFF
18movl %fs:0(%rax), %eax
deps/lld/test/ELF/x86-64-tls-gd-local.s+5-5
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared3// RUN: ld.lld --hash-style=sysv %t.o -o %t.so -shared
4// RUN: llvm-readobj -r -s -section-data %t.so | FileCheck %s4// RUN: llvm-readobj -r -S --section-data %t.so | FileCheck %s
55
6 .byte 0x666 .byte 0x66
7 leaq foo@tlsgd(%rip), %rdi7 leaq foo@tlsgd(%rip), %rdi
...@@ -34,8 +34,8 @@ bar:...@@ -34,8 +34,8 @@ bar:
34// CHECK-NEXT: SHF_ALLOC (0x2)34// CHECK-NEXT: SHF_ALLOC (0x2)
35// CHECK-NEXT: SHF_WRITE (0x1)35// CHECK-NEXT: SHF_WRITE (0x1)
36// CHECK-NEXT: ]36// CHECK-NEXT: ]
37// CHECK-NEXT: Address: 0x30D037// CHECK-NEXT: Address: 0x20D0
38// CHECK-NEXT: Offset: 0x30D038// CHECK-NEXT: Offset: 0x20D0
39// CHECK-NEXT: Size: 3239// CHECK-NEXT: Size: 32
40// CHECK-NEXT: Link: 040// CHECK-NEXT: Link: 0
41// CHECK-NEXT: Info: 041// CHECK-NEXT: Info: 0
...@@ -47,6 +47,6 @@ bar:...@@ -47,6 +47,6 @@ bar:
47// CHECK-NEXT: )47// CHECK-NEXT: )
4848
49// CHECK: Section ({{.*}}) .rela.dyn {49// CHECK: Section ({{.*}}) .rela.dyn {
50// CHECK-NEXT: 0x30D0 R_X86_64_DTPMOD64 - 0x050// CHECK-NEXT: 0x20D0 R_X86_64_DTPMOD64 - 0x0
51// CHECK-NEXT: 0x30E0 R_X86_64_DTPMOD64 - 0x051// CHECK-NEXT: 0x20E0 R_X86_64_DTPMOD64 - 0x0
52// CHECK-NEXT: }52// CHECK-NEXT: }
deps/lld/test/ELF/x86-64-tls-ld-local.s+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1// REQUIRES: x861// REQUIRES: x86
2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux2// RUN: llvm-mc %s -o %t.o -filetype=obj -triple=x86_64-pc-linux
3// RUN: ld.lld %t.o -o %t.so -shared3// RUN: ld.lld %t.o -o %t.so -shared
4// RUN: llvm-readobj -r -s %t.so | FileCheck %s4// RUN: llvm-readobj -r -S %t.so | FileCheck %s
55
6// CHECK: Relocations [6// CHECK: Relocations [
7// CHECK-NEXT: Section ({{.*}}) .rela.dyn {7// CHECK-NEXT: Section ({{.*}}) .rela.dyn {
deps/lld/test/ELF/x86-64-tls-ld-preemptable.s created+20
...@@ -0,0 +1,20 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: ld.lld %t.o -shared -o %t.so
4# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck %s
5
6# CHECK: 100c: leaq (%rax), %rax
7# CHECK-NEXT: 1013: movabsq 0, %rax
8
9# We used to error on R_X86_64_DTPOFF{32,64} to preemptable symbols.
10# i is STB_GLOBAL and preemptable.
11 leaq i@TLSLD(%rip), %rdi
12 callq __tls_get_addr@PLT
13 leaq i@DTPOFF(%rax), %rax # R_X86_64_DTPOFF32
14 movabsq i@DTPOFF, %rax # R_X86_64_DTPOFF64
15
16.section .tbss,"awT",@nobits
17.globl i
18i:
19 .long 0
20 .size i, 4
deps/lld/test/ELF/x86-64-tls-le-align.s created+16
...@@ -0,0 +1,16 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: ld.lld %t.o -o %t
4# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck %s
5
6# -alignTo(p_memsz, p_align) = -alignTo(4, 64) = -64
7
8# CHECK: movl %fs:-64, %eax
9
10 movl %fs:a@TPOFF, %eax
11
12.section .tbss,"awT"
13.align 64
14a:
15.long 0
16.size a, 4
deps/lld/test/ELF/x86-64-tls-le-undef.s created+15
...@@ -0,0 +1,15 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: ld.lld --noinhibit-exec %t.o -o %t 2>&1
4# RUN: llvm-objdump -d %t | FileCheck %s
5
6## Undefined TLS symbols resolve to 0.
7## In --noinhibit-exec mode, a non-weak undefined symbol is not an error.
8
9# CHECK: leaq 16(%rax), %rdx
10# CHECK-NEXT: leaq 32(%rax), %rdx
11
12.weak weak
13movq %fs:0, %rax
14leaq weak@tpoff+16(%rax), %rdx
15leaq global@tpoff+32(%rax), %rdx
deps/lld/test/ELF/x86-64-tlsdesc-gd.s created+69
...@@ -0,0 +1,69 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3# RUN: echo '.tbss; .globl b; b:' | llvm-mc -filetype=obj -triple=x86_64 - -o %t1.o
4# RUN: ld.lld -shared -soname=t1.so %t1.o -o %t1.so
5
6# RUN: ld.lld -shared %t.o %t1.o -o %t.so
7# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=GD-REL %s
8# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=GD %s
9
10# RUN: ld.lld %t.o %t1.o -o %t
11# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
12# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
13
14# RUN: ld.lld %t.o %t1.so -o %t
15# RUN: llvm-readobj -r %t | FileCheck --check-prefix=IE-REL %s
16# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=IE %s
17
18# GD-REL: .rela.dyn {
19# GD-REL-NEXT: 0x20A0 R_X86_64_TLSDESC a 0x0
20# GD-REL-NEXT: 0x20B0 R_X86_64_TLSDESC b 0x0
21# GD-REL-NEXT: }
22
23# 0x20a0-0x1007 = 4249
24# GD: leaq 4249(%rip), %rax
25# GD-NEXT: 1007: callq *(%rax)
26# GD-NEXT: movl %fs:(%rax), %eax
27
28# 0x20b0-0x1013 = 4253
29# GD-NEXT: leaq 4253(%rip), %rax
30# GD-NEXT: 1013: callq *(%rax)
31# GD-NEXT: movl %fs:(%rax), %eax
32
33# NOREL: no relocations
34
35## offset(a) = -4
36# LE: movq $-4, %rax
37# LE-NEXT: nop
38# LE-NEXT: movl %fs:(%rax), %eax
39## offset(b) = 0
40# LE: movq $0, %rax
41# LE-NEXT: nop
42# LE-NEXT: movl %fs:(%rax), %eax
43
44# IE-REL: .rela.dyn {
45# IE-REL-NEXT: 0x2020C0 R_X86_64_TPOFF64 b 0x0
46# IE-REL-NEXT: }
47
48## a is relaxed to use LE.
49# IE: movq $-4, %rax
50# IE-NEXT: nop
51# IE-NEXT: movl %fs:(%rax), %eax
52## 0x2020C0 - 0x201013 = 4269
53# IE-NEXT: movq 4269(%rip), %rax
54# IE-NEXT: 201013: nop
55# IE-NEXT: movl %fs:(%rax), %eax
56
57leaq a@tlsdesc(%rip), %rax
58call *a@tlscall(%rax)
59movl %fs:(%rax), %eax
60
61leaq b@tlsdesc(%rip), %rax
62call *b@tlscall(%rax)
63movl %fs:(%rax), %eax
64
65.section .tbss
66.globl a
67.zero 8
68a:
69.zero 4
deps/lld/test/ELF/x86-64-tlsdesc-ld.s created+45
...@@ -0,0 +1,45 @@
1# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64 %s -o %t.o
3
4# RUN: ld.lld -shared %t.o -o %t.so
5# RUN: llvm-readobj -r %t.so | FileCheck --check-prefix=LD-REL %s
6# RUN: llvm-objdump -d --no-show-raw-insn %t.so | FileCheck --check-prefix=LD %s
7
8# RUN: ld.lld %t.o -o %t
9# RUN: llvm-readelf -r %t | FileCheck --check-prefix=NOREL %s
10# RUN: llvm-objdump -d --no-show-raw-insn %t | FileCheck --check-prefix=LE %s
11
12## Check _TLS_MODULE_BASE_ used by LD produces a dynamic relocation with a value of 0.
13# LD-REL: .rela.dyn {
14# LD-REL-NEXT: 0x20A0 R_X86_64_TLSDESC - 0x0
15# LD-REL-NEXT: }
16
17## 0x20a0-0x1007 = 4249
18## dtpoff(a) = 8, dtpoff(b) = 12
19# LD: leaq 4249(%rip), %rax
20# LD-NEXT: 1007: callq *(%rax)
21# LD-NEXT: movl %fs:8(%rax), %edx
22# LD-NEXT: addl %fs:12(%rax), %edx
23
24## When producing an executable, the LD code sequence can be relaxed to LE.
25## It is the same as GD->LE.
26## tpoff(_TLS_MODULE_BASE_) = 0, tpoff(a) = -8, tpoff(b) = -4
27
28# NOREL: no relocations
29
30# LE: movq $0, %rax
31# LE-NEXT: nop
32# LE-NEXT: movl %fs:-8(%rax), %edx
33# LE-NEXT: addl %fs:-4(%rax), %edx
34
35leaq _TLS_MODULE_BASE_@tlsdesc(%rip), %rax
36call *_TLS_MODULE_BASE_@tlscall(%rax)
37movl %fs:a@dtpoff(%rax), %edx
38addl %fs:b@dtpoff(%rax), %edx
39
40.section .tbss
41.zero 8
42a:
43.zero 4
44b:
45.zero 4
deps/lld/test/ELF/x86-property-relocatable.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 -r %t.o -o %t2.o
4# RUN: llvm-readelf -n %t2.o | FileCheck -match-full-lines %s
5
6## Test that .note.gnu.property is passed through -r, and that we can handle
7## more than one FEATURE_AND in the same object file. This is logically the
8## same as if the features were combined in a single FEATURE_AND as the rule
9## states that the bit in the output pr_data field if it is set in all
10.text
11ret
12
13.section ".note.gnu.property", "a"
14.p2align 3
15.long 4
16.long 0x10
17.long 0x5
18.asciz "GNU"
19
20.long 0xc0000002 // GNU_PROPERTY_X86_FEATURE_1_AND
21.long 4
22.long 1 // GNU_PROPERTY_X86_FEATURE_1_IBT
23.long 0
24
25.long 4
26.long 0x10
27.long 0x5
28.asciz "GNU"
29.long 0xc0000002 // GNU_PROPERTY_X86_FEATURE_1_AND
30.long 4
31.long 2 // GNU_PROPERTY_X86_FEATURE_1_SHSTK
32.long 0
33
34# CHECK: Owner Data size Description
35# CHECK-NEXT: GNU 0x00000010 NT_GNU_PROPERTY_TYPE_0 (property note)
36# CHECK-NEXT: Properties: x86 feature: IBT, SHSTK
deps/lld/test/ELF/znotext-plt-relocations.s+2-1
...@@ -16,5 +16,6 @@...@@ -16,5 +16,6 @@
1616
17.text17.text
18_start:18_start:
19callq atexit19.byte 0xe8
20.long atexit - . - 4
20.quad foo21.quad foo
deps/lld/test/ELF/zstack-size.s+3-3
...@@ -1,13 +1,13 @@...@@ -1,13 +1,13 @@
1# REQUIRES: x861# REQUIRES: x86
2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t2# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t
3# RUN: ld.lld -z stack-size=0x1000 %t -o %t13# RUN: ld.lld -z stack-size=0x1000 %t -o %t1
4# RUN: llvm-readobj -program-headers %t1 | FileCheck %s -check-prefix=CHECK14# RUN: llvm-readobj -l %t1 | FileCheck %s -check-prefix=CHECK1
55
6# RUN: ld.lld -z stack-size=0 %t -o %t26# RUN: ld.lld -z stack-size=0 %t -o %t2
7# RUN: llvm-readobj -program-headers %t2 | FileCheck %s -check-prefix=CHECK27# RUN: llvm-readobj -l %t2 | FileCheck %s -check-prefix=CHECK2
88
9# RUN: ld.lld -z stack-size=0x2000 -z stack-size=0x1000 %t -o %t39# 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=CHECK110# RUN: llvm-readobj -l %t3 | FileCheck %s -check-prefix=CHECK1
1111
12.global _start12.global _start
13_start:13_start:
deps/lld/test/ELF/ztext.s+3-3
...@@ -4,11 +4,11 @@...@@ -4,11 +4,11 @@
4# RUN: ld.lld %t2.o -o %t2.so -shared4# RUN: ld.lld %t2.o -o %t2.so -shared
55
6# RUN: ld.lld -z notext %t.o %t2.so -o %t -shared6# RUN: ld.lld -z notext %t.o %t2.so -o %t -shared
7# RUN: llvm-readobj -dynamic-table -r %t | FileCheck %s7# RUN: llvm-readobj --dynamic-table -r %t | FileCheck %s
8# RUN: ld.lld -z notext %t.o %t2.so -o %t2 -pie8# RUN: ld.lld -z notext %t.o %t2.so -o %t2 -pie
9# RUN: llvm-readobj -dynamic-table -r %t2 | FileCheck %s9# RUN: llvm-readobj --dynamic-table -r %t2 | FileCheck %s
10# RUN: ld.lld -z notext %t.o %t2.so -o %t310# RUN: ld.lld -z notext %t.o %t2.so -o %t3
11# RUN: llvm-readobj -dynamic-table -r %t3 | FileCheck --check-prefix=STATIC %s11# RUN: llvm-readobj --dynamic-table -r %t3 | FileCheck --check-prefix=STATIC %s
1212
13# RUN: not ld.lld %t.o %t2.so -o %t -shared 2>&1 | FileCheck --check-prefix=ERR %s13# RUN: not ld.lld %t.o %t2.so -o %t -shared 2>&1 | FileCheck --check-prefix=ERR %s
14# RUN: not ld.lld -z text %t.o %t2.so -o %t -shared 2>&1 | FileCheck --check-prefix=ERR %s14# RUN: not ld.lld -z text %t.o %t2.so -o %t -shared 2>&1 | FileCheck --check-prefix=ERR %s
deps/lld/test/MinGW/driver.test+49
...@@ -4,6 +4,9 @@ X86-SAME: -machine:x86...@@ -4,6 +4,9 @@ X86-SAME: -machine:x86
4X86-SAME: -alternatename:__image_base__=___ImageBase4X86-SAME: -alternatename:__image_base__=___ImageBase
5X86-SAME: foo.o5X86-SAME: foo.o
66
7RUN: echo "-### foo.o -m i386pe" > %t.rsp
8RUN: ld.lld @%t.rsp | FileCheck -check-prefix=X86 %s
9
7RUN: ld.lld -### foo.o -m i386pep | FileCheck -check-prefix=X64 %s10RUN: ld.lld -### foo.o -m i386pep | FileCheck -check-prefix=X64 %s
8X64: -out:a.exe11X64: -out:a.exe
9X64-SAME: -machine:x6412X64-SAME: -machine:x64
...@@ -54,8 +57,24 @@ MLLVM: -mllvm:bar -mllvm:baz...@@ -54,8 +57,24 @@ MLLVM: -mllvm:bar -mllvm:baz
5457
55RUN: ld.lld -### foo.o -m i386pep -subsystem console | FileCheck -check-prefix=SUBSYSTEM %s58RUN: ld.lld -### foo.o -m i386pep -subsystem console | FileCheck -check-prefix=SUBSYSTEM %s
56RUN: ld.lld -### foo.o -m i386pep --subsystem console | FileCheck -check-prefix=SUBSYSTEM %s59RUN: ld.lld -### foo.o -m i386pep --subsystem console | FileCheck -check-prefix=SUBSYSTEM %s
60RUN: ld.lld -### foo.o -m i386pep -subsystem=console | FileCheck -check-prefix=SUBSYSTEM %s
61RUN: ld.lld -### foo.o -m i386pep --subsystem=console | FileCheck -check-prefix=SUBSYSTEM %s
57SUBSYSTEM: -subsystem:console62SUBSYSTEM: -subsystem:console
5863
64RUN: ld.lld -### foo.o -m i386pep --major-os-version 7 --minor-os-version 8 | FileCheck -check-prefix=SUBSYSTEM_VERSION %s
65RUN: ld.lld -### foo.o -m i386pep --major-subsystem-version 7 --minor-subsystem-version 8 | FileCheck -check-prefix=SUBSYSTEM_VERSION %s
66RUN: ld.lld -### foo.o -m i386pep --major-os-version=7 --minor-os-version=8 --major-subsystem-version=7 --minor-subsystem-version=8 | FileCheck -check-prefix=SUBSYSTEM_VERSION %s
67SUBSYSTEM_VERSION: -subsystem:default,7.8
68
69RUN: ld.lld -### foo.o -m i386pep --minor-subsystem-version 8 | FileCheck -check-prefix=SUBSYSTEM_DEFAULT_MAJOR %s
70SUBSYSTEM_DEFAULT_MAJOR: -subsystem:default,6.8
71
72RUN: ld.lld -### foo.o -m i386pep --major-subsystem-version 7 | FileCheck -check-prefix=SUBSYSTEM_DEFAULT_MINOR %s
73SUBSYSTEM_DEFAULT_MINOR: -subsystem:default,7
74
75RUN: ld.lld -### foo.o -m i386pep --subsystem windows --major-os-version 7 --minor-os-version 8 | FileCheck -check-prefix=SUBSYSTEM_WINDOWS %s
76SUBSYSTEM_WINDOWS: -subsystem:windows,7.8
77
59RUN: ld.lld -### foo.o -m i386pep -stack 4194304,8192 | FileCheck -check-prefix=STACK %s78RUN: ld.lld -### foo.o -m i386pep -stack 4194304,8192 | FileCheck -check-prefix=STACK %s
60RUN: ld.lld -### foo.o -m i386pep --stack 4194304,8192 | FileCheck -check-prefix=STACK %s79RUN: ld.lld -### foo.o -m i386pep --stack 4194304,8192 | FileCheck -check-prefix=STACK %s
61STACK: -stack:4194304,819280STACK: -stack:4194304,8192
...@@ -74,6 +93,9 @@ WHOLE-ARCHIVE: foo.o -wholearchive:bar.a baz.a...@@ -74,6 +93,9 @@ WHOLE-ARCHIVE: foo.o -wholearchive:bar.a baz.a
74RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix MINGW-FLAG %s93RUN: ld.lld -### -m i386pep foo.o | FileCheck -check-prefix MINGW-FLAG %s
75MINGW-FLAG: -lldmingw94MINGW-FLAG: -lldmingw
7695
96RUN: ld.lld -### -m i386pep foo.o --exclude-all-symbols | FileCheck -check-prefix EXCLUDE-ALL %s
97EXCLUDE-ALL: -exclude-all-symbols
98
77RUN: ld.lld -### -m i386pep foo.o --export-all-symbols | FileCheck -check-prefix EXPORT-ALL %s99RUN: ld.lld -### -m i386pep foo.o --export-all-symbols | FileCheck -check-prefix EXPORT-ALL %s
78EXPORT-ALL: -export-all-symbols100EXPORT-ALL: -export-all-symbols
79101
...@@ -96,9 +118,14 @@ STRIP-DEBUG: -debug:symtab...@@ -96,9 +118,14 @@ STRIP-DEBUG: -debug:symtab
96STRIP-DEBUG-NOT: -debug:dwarf118STRIP-DEBUG-NOT: -debug:dwarf
97119
98RUN: ld.lld -### -m i386pep foo.o -pdb out.pdb | FileCheck -check-prefix PDB %s120RUN: ld.lld -### -m i386pep foo.o -pdb out.pdb | FileCheck -check-prefix PDB %s
121RUN: ld.lld -### -m i386pep foo.o -pdb=out.pdb | FileCheck -check-prefix PDB %s
99PDB: -debug -pdb:out.pdb122PDB: -debug -pdb:out.pdb
100PDB-NOT: -debug:dwarf123PDB-NOT: -debug:dwarf
101124
125RUN: ld.lld -### -m i386pep foo.o -pdb= | FileCheck -check-prefix PDB-DEFAULT %s
126PDB-DEFAULT: -debug
127PDB-DEFAULT-NOT: -pdb:{{.*}}
128
102RUN: ld.lld -### -m i386pep foo.o --large-address-aware | FileCheck -check-prefix LARGE-ADDRESS-AWARE %s129RUN: ld.lld -### -m i386pep foo.o --large-address-aware | FileCheck -check-prefix LARGE-ADDRESS-AWARE %s
103LARGE-ADDRESS-AWARE: -largeaddressaware130LARGE-ADDRESS-AWARE: -largeaddressaware
104131
...@@ -149,5 +176,27 @@ MAP: -lldmap:bar.map...@@ -149,5 +176,27 @@ MAP: -lldmap:bar.map
149RUN: ld.lld -### foo.o -m i386pe -require-defined _foo --require-defined _bar -require-defined=_baz --require-defined=_foo2 | FileCheck -check-prefix=REQUIRE-DEFINED %s176RUN: ld.lld -### foo.o -m i386pe -require-defined _foo --require-defined _bar -require-defined=_baz --require-defined=_foo2 | FileCheck -check-prefix=REQUIRE-DEFINED %s
150REQUIRE-DEFINED: -include:_foo -include:_bar -include:_baz -include:_foo2177REQUIRE-DEFINED: -include:_foo -include:_bar -include:_baz -include:_foo2
151178
179RUN: ld.lld -### foo.o -m i386pe -u _foo --undefined _bar -undefined=_baz --undefined=_foo2 | FileCheck -check-prefix=UNDEFINED %s
180UNDEFINED: -includeoptional:_foo -includeoptional:_bar -includeoptional:_baz -includeoptional:_foo2
181
152RUN: ld.lld -### -m i386pep foo.o -Llibpath | FileCheck -check-prefix LIBPATH %s182RUN: ld.lld -### -m i386pep foo.o -Llibpath | FileCheck -check-prefix LIBPATH %s
153LIBPATH: -libpath:libpath183LIBPATH: -libpath:libpath
184
185RUN: ld.lld -### -m i386pep foo.o --no-insert-timestamp | FileCheck -check-prefix NOTIMESTAMP %s
186RUN: ld.lld -### -m i386pep foo.o --insert-timestamp --no-insert-timestamp | FileCheck -check-prefix NOTIMESTAMP %s
187NOTIMESTAMP: -timestamp:0
188RUN: ld.lld -### -m i386pep foo.o --no-insert-timestamp --insert-timestamp | FileCheck -check-prefix TIMESTAMP %s
189TIMESTAMP-NOT: -timestamp:0
190
191RUN: ld.lld -### -m i386pep foo.o -appcontainer | FileCheck -check-prefix APPCONTAINER %s
192RUN: ld.lld -### -m i386pep foo.o --appcontainer | FileCheck -check-prefix APPCONTAINER %s
193APPCONTAINER: -appcontainer
194
195# RUN: ld.lld -m i386pep --version 2>&1 | FileCheck -check-prefix=VERSION %s
196# RUN: ld.lld -m i386pep -v 2>&1 | FileCheck -check-prefix=VERSION %s
197# RUN: not ld.lld -m i386pep -v xyz 2>&1 | FileCheck -check-prefix=VERSION %s
198# VERSION: LLD {{.*}} (compatible with GNU linkers)
199
200# RUN: ld.lld -m i386pep --help 2>&1 | FileCheck -check-prefix=HELP %s
201# HELP: USAGE:
202# HELP: --enable-auto-import
deps/lld/test/lit.cfg.py+6-3
...@@ -87,16 +87,19 @@ config.environment['LLD_IN_TEST'] = '1'...@@ -87,16 +87,19 @@ config.environment['LLD_IN_TEST'] = '1'
87# Indirectly check if the mt.exe Microsoft utility exists by searching for87# Indirectly check if the mt.exe Microsoft utility exists by searching for
88# cvtres, which always accompanies it. Alternatively, check if we can use88# cvtres, which always accompanies it. Alternatively, check if we can use
89# libxml2 to merge manifests.89# libxml2 to merge manifests.
90if (lit.util.which('cvtres', config.environment['PATH'])) or \90if (lit.util.which('cvtres', config.environment['PATH']) or
91 (config.llvm_libxml2_enabled == '1'):91 config.llvm_libxml2_enabled):
92 config.available_features.add('manifest_tool')92 config.available_features.add('manifest_tool')
9393
94if (config.llvm_libxml2_enabled == '1'):94if config.llvm_libxml2_enabled:
95 config.available_features.add('libxml2')95 config.available_features.add('libxml2')
9696
97if config.have_dia_sdk:97if config.have_dia_sdk:
98 config.available_features.add("diasdk")98 config.available_features.add("diasdk")
9999
100if config.sizeof_void_p == 8:
101 config.available_features.add("llvm-64-bits")
102
100tar_executable = lit.util.which('tar', config.environment['PATH'])103tar_executable = lit.util.which('tar', config.environment['PATH'])
101if tar_executable:104if tar_executable:
102 tar_version = subprocess.Popen(105 tar_version = subprocess.Popen(
deps/lld/test/lit.site.cfg.py.in+2-1
...@@ -7,7 +7,7 @@ config.llvm_src_root = "@LLVM_SOURCE_DIR@"...@@ -7,7 +7,7 @@ config.llvm_src_root = "@LLVM_SOURCE_DIR@"
7config.llvm_obj_root = "@LLVM_BINARY_DIR@"7config.llvm_obj_root = "@LLVM_BINARY_DIR@"
8config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"8config.llvm_tools_dir = "@LLVM_TOOLS_DIR@"
9config.llvm_libs_dir = "@LLVM_LIBS_DIR@"9config.llvm_libs_dir = "@LLVM_LIBS_DIR@"
10config.llvm_libxml2_enabled = "@LLVM_LIBXML2_ENABLED@"10config.llvm_libxml2_enabled = @LLVM_LIBXML2_ENABLED@
11config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"11config.lit_tools_dir = "@LLVM_LIT_TOOLS_DIR@"
12config.lld_obj_root = "@LLD_BINARY_DIR@"12config.lld_obj_root = "@LLD_BINARY_DIR@"
13config.lld_libs_dir = "@LLVM_LIBRARY_OUTPUT_INTDIR@"13config.lld_libs_dir = "@LLVM_LIBRARY_OUTPUT_INTDIR@"
...@@ -15,6 +15,7 @@ config.lld_tools_dir = "@LLVM_RUNTIME_OUTPUT_INTDIR@"...@@ -15,6 +15,7 @@ config.lld_tools_dir = "@LLVM_RUNTIME_OUTPUT_INTDIR@"
15config.target_triple = "@TARGET_TRIPLE@"15config.target_triple = "@TARGET_TRIPLE@"
16config.python_executable = "@PYTHON_EXECUTABLE@"16config.python_executable = "@PYTHON_EXECUTABLE@"
17config.have_zlib = @HAVE_LIBZ@17config.have_zlib = @HAVE_LIBZ@
18config.sizeof_void_p = @CMAKE_SIZEOF_VOID_P@
1819
19# Support substitution of the tools and libs dirs with user parameters. This is20# Support substitution of the tools and libs dirs with user parameters. This is
20# used when we can't determine the tool dir at configuration time.21# used when we can't determine the tool dir at configuration time.
deps/lld/test/mach-o/arm-interworking.yaml+1-1
...@@ -2,7 +2,7 @@...@@ -2,7 +2,7 @@
2# RUN: %p/Inputs/arm-interworking.yaml -o %t | FileCheck %s \2# RUN: %p/Inputs/arm-interworking.yaml -o %t | FileCheck %s \
3# RUN: && ld64.lld -arch armv7 -dylib -print_atoms \3# RUN: && ld64.lld -arch armv7 -dylib -print_atoms \
4# RUN: %p/Inputs/armv7/libSystem.yaml %t -o %t2 | FileCheck %s \4# RUN: %p/Inputs/armv7/libSystem.yaml %t -o %t2 | FileCheck %s \
5# RUN: && llvm-readobj -s -sd %t2 | FileCheck -check-prefix=CODE %s5# RUN: && llvm-readobj -S --section-data %t2 | FileCheck -check-prefix=CODE %s
6#6#
7# Test thumb and arm branches round trip through -r.7# Test thumb and arm branches round trip through -r.
8# Test bl/blx instructions are fixed up properly.8# Test bl/blx instructions are fixed up properly.
deps/lld/test/mach-o/arm-shims.yaml+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: ld64.lld -arch armv7 %s %p/Inputs/arm-shims.yaml \1# RUN: ld64.lld -arch armv7 %s %p/Inputs/arm-shims.yaml \
2# RUN: -dylib %p/Inputs/armv7/libSystem.yaml -o %t2# RUN: -dylib %p/Inputs/armv7/libSystem.yaml -o %t
3# RUN: llvm-readobj -s -sd %t | FileCheck %s3# RUN: llvm-readobj -S --section-data %t | FileCheck %s
4#4#
5# Test b from arm to thumb or vice versa has shims added.s5# Test b from arm to thumb or vice versa has shims added.s
6#6#
deps/lld/test/mach-o/exe-offsets.yaml+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# RUN: ld64.lld -arch x86_64 %s -o %t -e start %p/Inputs/x86_64/libSystem.yaml1# RUN: ld64.lld -arch x86_64 %s -o %t -e start %p/Inputs/x86_64/libSystem.yaml
2# RUN: llvm-readobj -sections %t | FileCheck %s2# RUN: llvm-readobj --sections %t | FileCheck %s
33
4# Make sure data gets put at offset4# Make sure data gets put at offset
55
deps/lld/test/mach-o/exe-segment-overlap.yaml+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# RUN: ld64.lld -arch x86_64 %s -o %t %p/Inputs/x86_64/libSystem.yaml1# RUN: ld64.lld -arch x86_64 %s -o %t %p/Inputs/x86_64/libSystem.yaml
2# RUN: llvm-readobj -sections -section-data %t | FileCheck %s2# RUN: llvm-readobj --sections --section-data %t | FileCheck %s
33
4--- !native4--- !native
5defined-atoms:5defined-atoms:
deps/lld/test/mach-o/executable-exports.yaml+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: ld64.lld -arch x86_64 -macosx_version_min 10.8 \1# RUN: ld64.lld -arch x86_64 -macosx_version_min 10.8 \
2# RUN: %s %p/Inputs/x86_64/libSystem.yaml -o %t && \2# RUN: %s %p/Inputs/x86_64/libSystem.yaml -o %t && \
3# RUN: llvm-objdump -exports-trie %t | FileCheck %s3# RUN: llvm-objdump -macho -exports-trie %t | FileCheck %s
4#4#
5#5#
6# Tests that exports trie builds properly.6# Tests that exports trie builds properly.
deps/lld/test/mach-o/export-trie-order.yaml+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# RUN: ld64.lld -arch i386 %s %p/Inputs/hello-world-x86.yaml -o %t1# RUN: ld64.lld -arch i386 %s %p/Inputs/hello-world-x86.yaml -o %t
2# RUN: llvm-objdump -exports-trie %t | FileCheck %s2# RUN: llvm-objdump -macho -exports-trie %t | FileCheck %s
3#3#
4# Test that the export trie is emitted in order.4# Test that the export trie is emitted in order.
5#5#
deps/lld/test/mach-o/got-order.yaml+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: ld64.lld -arch x86_64 %s %p/Inputs/got-order.yaml \1# RUN: ld64.lld -arch x86_64 %s %p/Inputs/got-order.yaml \
2# RUN: %p/Inputs/got-order2.yaml -o %t %p/Inputs/x86_64/libSystem.yaml2# RUN: %p/Inputs/got-order2.yaml -o %t %p/Inputs/x86_64/libSystem.yaml
3# RUN: llvm-objdump -bind %t | FileCheck %s3# RUN: llvm-objdump -macho -bind %t | FileCheck %s
4#4#
5# Test that GOT slots are sorted by name5# Test that GOT slots are sorted by name
6#6#
deps/lld/test/mach-o/image-base.yaml+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# RUN: ld64.lld -arch x86_64 -macosx_version_min 10.9 %s -o %t -image_base 31415926000 %p/Inputs/x86_64/libSystem.yaml1# RUN: ld64.lld -arch x86_64 -macosx_version_min 10.9 %s -o %t -image_base 31415926000 %p/Inputs/x86_64/libSystem.yaml
2# RUN: llvm-readobj -macho-segment %t | FileCheck %s2# RUN: llvm-readobj --macho-segment %t | FileCheck %s
3# RUN: not ld64.lld -arch x86_64 -image_base 0x31415926530 %s >/dev/null 2> %t3# RUN: not ld64.lld -arch x86_64 -image_base 0x31415926530 %s >/dev/null 2> %t
4# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-MISPAGED4# RUN: FileCheck < %t %s --check-prefix=CHECK-ERROR-MISPAGED
5# RUN: not ld64.lld -arch x86_64 -image_base 1000 %s >/dev/null 2> %t5# RUN: not ld64.lld -arch x86_64 -image_base 1000 %s >/dev/null 2> %t
deps/lld/test/mach-o/lazy-bind-x86_64.yaml+1-1
...@@ -4,7 +4,7 @@...@@ -4,7 +4,7 @@
4# RUN: %p/Inputs/lazy-bind-x86_64.yaml %p/Inputs/lazy-bind-x86_64-2.yaml \4# RUN: %p/Inputs/lazy-bind-x86_64.yaml %p/Inputs/lazy-bind-x86_64-2.yaml \
5# RUN: %p/Inputs/lazy-bind-x86_64-3.yaml -o %t \5# RUN: %p/Inputs/lazy-bind-x86_64-3.yaml -o %t \
6# RUN: %p/Inputs/x86_64/libSystem.yaml6# RUN: %p/Inputs/x86_64/libSystem.yaml
7# RUN: llvm-objdump -lazy-bind %t | FileCheck %s7# RUN: llvm-objdump -macho -lazy-bind %t | FileCheck %s
8# RUN: llvm-nm -m %t | FileCheck --check-prefix=CHECK-NM %s8# RUN: llvm-nm -m %t | FileCheck --check-prefix=CHECK-NM %s
9# RUN: llvm-objdump -disassemble %t | FileCheck --check-prefix=CHECK-HELPERS %s9# RUN: llvm-objdump -disassemble %t | FileCheck --check-prefix=CHECK-HELPERS %s
10# RUN: llvm-objdump -private-headers %t | FileCheck --check-prefix=CHECK-DYLIBS %s10# RUN: llvm-objdump -private-headers %t | FileCheck --check-prefix=CHECK-DYLIBS %s
deps/lld/test/mach-o/load-commands-size.yaml created+305
...@@ -0,0 +1,305 @@
1# RUN: ld64.lld -arch x86_64 %s -o %t -dylib \
2# RUN: -macosx_version_min 10.10 -sdk_version 10.10 \
3# RUN: -install_name /usr/lib/foo.dylib \
4# RUN: %p/Inputs/x86_64/libSystem.yaml && \
5# RUN: llvm-readobj %t
6
7# (Tests that lld doesn't crash or produce an invalid file.)
8
9--- !native
10path: '<linker-internal>'
11defined-atoms:
12 - name: _foo
13 scope: global
14 type: unknown
15 content: [ 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
16 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
17 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
18 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
19 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
20 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
21 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
22 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
23 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
24 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
25 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
26 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
27 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
28 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
29 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
30 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
31 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
32 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
33 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
34 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
35 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
36 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
37 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
38 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
39 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
40 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
41 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
42 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
43 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
44 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
45 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
46 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
47 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
48 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
49 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
50 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
51 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
52 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
53 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
54 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
55 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
56 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
57 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
58 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
59 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
60 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
61 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
62 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
63 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
64 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
65 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
66 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
67 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
68 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
69 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
70 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
71 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
72 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
73 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
74 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
75 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
76 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
77 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
78 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
79 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
80 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
81 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
82 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
83 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
84 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
85 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
86 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
87 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
88 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
89 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
90 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
91 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
92 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
93 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
94 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
95 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
96 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
97 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
98 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
99 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
100 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
101 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
102 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
103 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
104 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
105 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
106 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
107 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
108 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
109 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
110 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
111 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
112 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
113 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
114 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
115 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
116 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
117 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
118 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
119 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
120 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
121 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
122 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
123 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
124 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
125 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
126 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
127 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
128 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
129 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
130 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
131 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
132 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
133 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
134 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
135 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
136 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
137 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
138 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
139 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
140 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
141 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
142 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
143 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
144 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
145 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
146 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
147 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
148 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
149 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
150 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
151 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
152 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
153 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
154 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
155 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
156 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
157 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
158 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
159 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
160 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
161 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
162 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
163 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
164 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
165 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
166 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
167 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
168 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
169 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
170 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
171 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
172 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
173 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
174 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
175 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
176 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
177 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
178 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
179 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
180 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
181 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
182 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
183 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
184 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
185 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
186 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
187 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
188 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
189 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
190 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
191 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
192 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
193 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
194 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
195 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
196 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
197 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
198 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
199 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
200 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
201 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
202 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
203 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
204 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
205 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
206 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
207 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
208 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
209 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
210 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
211 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
212 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
213 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
214 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
215 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
216 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
217 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
218 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
219 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
220 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
221 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
222 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
223 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
224 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
225 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
226 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
227 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
228 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
229 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
230 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
231 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
232 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
233 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
234 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
235 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
236 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
237 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
238 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
239 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
240 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
241 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
242 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
243 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
244 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
245 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
246 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
247 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
248 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
249 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
250 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
251 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
252 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
253 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
254 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
255 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
256 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
257 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
258 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
259 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
260 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
261 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
262 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
263 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
264 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
265 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
266 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
267 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
268 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
269 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
270 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
271 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
272 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
273 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
274 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
275 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
276 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
277 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
278 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
279 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
280 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
281 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
282 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
283 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
284 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
285 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
286 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
287 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
288 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
289 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
290 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
291 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
292 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
293 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
294 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
295 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
296 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
297 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
298 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
299 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
300 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
301 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00,
302 00, 00, 00, 00 ]
303 alignment: 16
304 section-choice: custom-required
305 section-name: '__TEXT/__foo'
deps/lld/test/mach-o/sectalign.yaml+1-1
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1# RUN: ld64.lld -arch x86_64 -macosx_version_min 10.8 %s -dylib \1# RUN: ld64.lld -arch x86_64 -macosx_version_min 10.8 %s -dylib \
2# RUN: -sectalign __DATA __custom 0x800 -sectalign __TEXT __text 0x400 \2# RUN: -sectalign __DATA __custom 0x800 -sectalign __TEXT __text 0x400 \
3# RUN: %p/Inputs/x86_64/libSystem.yaml -o %t \3# RUN: %p/Inputs/x86_64/libSystem.yaml -o %t \
4# RUN: && llvm-readobj -sections %t | FileCheck %s4# RUN: && llvm-readobj --sections %t | FileCheck %s
5#5#
6# Test -sectalign option on __text and a custom section.6# Test -sectalign option on __text and a custom section.
7#7#
deps/lld/test/mach-o/subsections-via-symbols-default.yaml+1-1
...@@ -1,5 +1,5 @@...@@ -1,5 +1,5 @@
1# RUN: ld64.lld -ios_simulator_version_min 5.0 -arch x86_64 -r %s -o %t1# RUN: ld64.lld -ios_simulator_version_min 5.0 -arch x86_64 -r %s -o %t
2# RUN: llvm-readobj -file-headers %t | FileCheck %s2# RUN: llvm-readobj --file-headers %t | FileCheck %s
33
4# Make sure that we have an objc image info in the output. It should have4# Make sure that we have an objc image info in the output. It should have
5# been generated by the objc pass.5# been generated by the objc pass.
deps/lld/test/mach-o/write-final-sections.yaml+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1# RUN: ld64.lld -arch x86_64 %s %p/Inputs/write-final-sections.yaml \1# RUN: ld64.lld -arch x86_64 %s %p/Inputs/write-final-sections.yaml \
2# RUN: -o %t -e _foo2# RUN: -o %t -e _foo
3# RUN: llvm-readobj -sections -section-data %t | FileCheck %s3# RUN: llvm-readobj --sections --section-data %t | FileCheck %s
44
5--- !native5--- !native
6defined-atoms:6defined-atoms:
deps/lld/test/wasm/Inputs/call-ret32.ll created+11
...@@ -0,0 +1,11 @@
1target triple = "wasm32-unknown-unknown"
2
3@ret32_address = global i32 (float)* @ret32, align 4
4
5define hidden i32* @call_ret32() {
6entry:
7 %call1 = call i32 @ret32(float 0.000000e+00)
8 ret i32* bitcast (i32 (float)** @ret32_address to i32*)
9}
10
11declare i32 @ret32(float)
deps/lld/test/wasm/Inputs/comdat1.ll+16-7
...@@ -1,13 +1,22 @@...@@ -1,13 +1,22 @@
1target triple = "wasm32-unknown-unknown"1target triple = "wasm32-unknown-unknown"
22
3$inlineFn = comdat any3$foo = comdat any
4@constantData = weak_odr constant [3 x i8] c"abc", comdat($inlineFn)4
5define linkonce_odr i32 @inlineFn() comdat {5@constantData = constant [3 x i8] c"abc", comdat($foo)
6entry:6
7define i32 @comdatFn() comdat($foo) {
7 ret i32 ptrtoint ([3 x i8]* @constantData to i32)8 ret i32 ptrtoint ([3 x i8]* @constantData to i32)
8}9}
910
10define i32 @callInline1() {11define internal void @do_init() comdat($foo) {
11entry:12 ret void
12 ret i32 ptrtoint (i32 ()* @inlineFn to i32)13}
14
15%0 = type { i32, void ()*, i8* }
16@llvm.global_ctors = appending global [1 x %0 ] [%0 { i32 65535, void ()* @do_init, i8* null }]
17
18; Everything above this is part of the `foo` comdat group
19
20define i32 @callComdatFn1() {
21 ret i32 ptrtoint (i32 ()* @comdatFn to i32)
13}22}
deps/lld/test/wasm/Inputs/comdat2.ll+16-7
...@@ -1,13 +1,22 @@...@@ -1,13 +1,22 @@
1target triple = "wasm32-unknown-unknown"1target triple = "wasm32-unknown-unknown"
22
3$inlineFn = comdat any3$foo = comdat any
4@constantData = weak_odr constant [3 x i8] c"abc", comdat($inlineFn)4
5define linkonce_odr i32 @inlineFn() comdat {5@constantData = constant [3 x i8] c"abc", comdat($foo)
6entry:6
7define i32 @comdatFn() comdat($foo) {
7 ret i32 ptrtoint ([3 x i8]* @constantData to i32)8 ret i32 ptrtoint ([3 x i8]* @constantData to i32)
8}9}
910
10define i32 @callInline2() {11define internal void @do_init() comdat($foo) {
11entry:12 ret void
12 ret i32 ptrtoint (i32 ()* @inlineFn to i32)13}
14
15%0 = type { i32, void ()*, i8* }
16@llvm.global_ctors = appending global [1 x %0] [ %0 { i32 65535, void ()* @do_init, i8* getelementptr inbounds ([3 x i8], [3 x i8]* @constantData, i32 0, i32 0) }]
17
18; Everything above this is part of the `foo` comdat group
19
20define i32 @callComdatFn2() {
21 ret i32 ptrtoint (i32 ()* @comdatFn to i32)
13}22}
deps/lld/test/wasm/Inputs/disallow-feature-foo.yaml created+13
...@@ -0,0 +1,13 @@
1--- !WASM
2FileHeader:
3 Version: 0x00000001
4Sections:
5 - Type: CUSTOM
6 Name: linking
7 Version: 2
8 - Type: CUSTOM
9 Name: target_features
10 Features:
11 - Prefix: DISALLOWED
12 Name: "foo"
13...
deps/lld/test/wasm/Inputs/explicit-section.ll created+4
...@@ -0,0 +1,4 @@
1target triple = "wasm32-unknown-unknown"
2
3@var1 = global i32 42, section "mysection", align 4
4@var2 = global i32 43, section "mysection", align 4
deps/lld/test/wasm/Inputs/globals.yaml+1-1
...@@ -29,7 +29,7 @@ Sections:...@@ -29,7 +29,7 @@ Sections:
29 Locals:29 Locals:
30 Body: 2381808080000B30 Body: 2381808080000B
31 Relocations:31 Relocations:
32 - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB32 - Type: R_WASM_GLOBAL_INDEX_LEB
33 Index: 133 Index: 1
34 Offset: 0x0000000434 Offset: 0x00000004
35 - Type: CUSTOM35 - Type: CUSTOM
deps/lld/test/wasm/Inputs/no-feature-foo.yaml created+11
...@@ -0,0 +1,11 @@
1--- !WASM
2FileHeader:
3 Version: 0x00000001
4Sections:
5 - Type: CUSTOM
6 Name: linking
7 Version: 2
8 - Type: CUSTOM
9 Name: target_features
10 Features: [ ]
11...
deps/lld/test/wasm/Inputs/require-feature-foo.yaml created+13
...@@ -0,0 +1,13 @@
1--- !WASM
2FileHeader:
3 Version: 0x00000001
4Sections:
5 - Type: CUSTOM
6 Name: linking
7 Version: 2
8 - Type: CUSTOM
9 Name: target_features
10 Features:
11 - Prefix: REQUIRED
12 Name: "foo"
13...
deps/lld/test/wasm/Inputs/undefined-globals.yaml+1-1
...@@ -27,7 +27,7 @@ Sections:...@@ -27,7 +27,7 @@ Sections:
27 Locals:27 Locals:
28 Body: 2381808080000B28 Body: 2381808080000B
29 Relocations:29 Relocations:
30 - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB30 - Type: R_WASM_GLOBAL_INDEX_LEB
31 Index: 131 Index: 1
32 Offset: 0x0000000432 Offset: 0x00000004
33 - Type: CUSTOM33 - Type: CUSTOM
deps/lld/test/wasm/Inputs/use-feature-foo.yaml created+13
...@@ -0,0 +1,13 @@
1--- !WASM
2FileHeader:
3 Version: 0x00000001
4Sections:
5 - Type: CUSTOM
6 Name: linking
7 Version: 2
8 - Type: CUSTOM
9 Name: target_features
10 Features:
11 - Prefix: USED
12 Name: "foo"
13...
deps/lld/test/wasm/alias.ll+3-26
...@@ -22,7 +22,7 @@ entry:...@@ -22,7 +22,7 @@ entry:
22; CHECK-NEXT: ReturnType: NORESULT22; CHECK-NEXT: ReturnType: NORESULT
23; CHECK-NEXT: ParamTypes:23; CHECK-NEXT: ParamTypes:
24; CHECK-NEXT: - Type: FUNCTION24; CHECK-NEXT: - Type: FUNCTION
25; CHECK-NEXT: FunctionTypes: [ 0, 0 ]25; CHECK-NEXT: FunctionTypes: [ 0 ]
26; CHECK-NEXT: - Type: TABLE26; CHECK-NEXT: - Type: TABLE
27; CHECK-NEXT: Tables:27; CHECK-NEXT: Tables:
28; CHECK-NEXT: - ElemType: FUNCREF28; CHECK-NEXT: - ElemType: FUNCREF
...@@ -41,48 +41,25 @@ entry:...@@ -41,48 +41,25 @@ entry:
41; CHECK-NEXT: InitExpr:41; CHECK-NEXT: InitExpr:
42; CHECK-NEXT: Opcode: I32_CONST42; CHECK-NEXT: Opcode: I32_CONST
43; CHECK-NEXT: Value: 6656043; CHECK-NEXT: Value: 66560
44; CHECK-NEXT: - Index: 1
45; CHECK-NEXT: Type: I32
46; CHECK-NEXT: Mutable: false
47; CHECK-NEXT: InitExpr:
48; CHECK-NEXT: Opcode: I32_CONST
49; CHECK-NEXT: Value: 66560
50; CHECK-NEXT: - Index: 2
51; CHECK-NEXT: Type: I32
52; CHECK-NEXT: Mutable: false
53; CHECK-NEXT: InitExpr:
54; CHECK-NEXT: Opcode: I32_CONST
55; CHECK-NEXT: Value: 1024
56; CHECK-NEXT: - Type: EXPORT44; CHECK-NEXT: - Type: EXPORT
57; CHECK-NEXT: Exports:45; CHECK-NEXT: Exports:
58; CHECK-NEXT: - Name: memory46; CHECK-NEXT: - Name: memory
59; CHECK-NEXT: Kind: MEMORY47; CHECK-NEXT: Kind: MEMORY
60; CHECK-NEXT: Index: 048; CHECK-NEXT: Index: 0
61; CHECK-NEXT: - Name: __heap_base
62; CHECK-NEXT: Kind: GLOBAL
63; CHECK-NEXT: Index: 1
64; CHECK-NEXT: - Name: __data_end
65; CHECK-NEXT: Kind: GLOBAL
66; CHECK-NEXT: Index: 2
67; CHECK-NEXT: - Name: _start49; CHECK-NEXT: - Name: _start
68; CHECK-NEXT: Kind: FUNCTION50; CHECK-NEXT: Kind: FUNCTION
69; CHECK-NEXT: Index: 151; CHECK-NEXT: Index: 0
70; CHECK-NEXT: - Name: start_alias52; CHECK-NEXT: - Name: start_alias
71; CHECK-NEXT: Kind: FUNCTION53; CHECK-NEXT: Kind: FUNCTION
72; CHECK-NEXT: Index: 154; CHECK-NEXT: Index: 0
73; CHECK-NEXT: - Type: CODE55; CHECK-NEXT: - Type: CODE
74; CHECK-NEXT: Functions:56; CHECK-NEXT: Functions:
75; CHECK-NEXT: - Index: 057; CHECK-NEXT: - Index: 0
76; CHECK-NEXT: Locals:58; CHECK-NEXT: Locals:
77; CHECK-NEXT: Body: 0B59; CHECK-NEXT: Body: 0B
78; CHECK-NEXT: - Index: 1
79; CHECK-NEXT: Locals:
80; CHECK-NEXT: Body: 0B
81; CHECK-NEXT: - Type: CUSTOM60; CHECK-NEXT: - Type: CUSTOM
82; CHECK-NEXT: Name: name61; CHECK-NEXT: Name: name
83; CHECK-NEXT: FunctionNames:62; CHECK-NEXT: FunctionNames:
84; CHECK-NEXT: - Index: 063; CHECK-NEXT: - Index: 0
85; CHECK-NEXT: Name: __wasm_call_ctors
86; CHECK-NEXT: - Index: 1
87; CHECK-NEXT: Name: _start64; CHECK-NEXT: Name: _start
88; CHECK-NEXT: ...65; CHECK-NEXT: ...
deps/lld/test/wasm/archive-export.ll+5-17
...@@ -14,37 +14,25 @@ CHECK: Exports:...@@ -14,37 +14,25 @@ CHECK: Exports:
14CHECK-NEXT: - Name: memory14CHECK-NEXT: - Name: memory
15CHECK-NEXT: Kind: MEMORY15CHECK-NEXT: Kind: MEMORY
16CHECK-NEXT: Index: 016CHECK-NEXT: Index: 0
17CHECK-NEXT: - Name: __heap_base
18CHECK-NEXT: Kind: GLOBAL
19CHECK-NEXT: Index: 1
20CHECK-NEXT: - Name: __data_end
21CHECK-NEXT: Kind: GLOBAL
22CHECK-NEXT: Index: 2
23CHECK-NEXT: - Name: foo17CHECK-NEXT: - Name: foo
24CHECK-NEXT: Kind: FUNCTION18CHECK-NEXT: Kind: FUNCTION
25CHECK-NEXT: Index: 219CHECK-NEXT: Index: 1
26CHECK-NEXT: - Name: bar20CHECK-NEXT: - Name: bar
27CHECK-NEXT: Kind: FUNCTION21CHECK-NEXT: Kind: FUNCTION
28CHECK-NEXT: Index: 322CHECK-NEXT: Index: 2
29CHECK-NEXT: - Name: archive2_symbol23CHECK-NEXT: - Name: archive2_symbol
30CHECK-NEXT: Kind: FUNCTION24CHECK-NEXT: Kind: FUNCTION
31CHECK-NEXT: Index: 425CHECK-NEXT: Index: 3
32CHECK-NEXT: - Name: _start26CHECK-NEXT: - Name: _start
33CHECK-NEXT: Kind: FUNCTION27CHECK-NEXT: Kind: FUNCTION
34CHECK-NEXT: Index: 128CHECK-NEXT: Index: 0
35CHECK-NEXT: - Type: CODE29CHECK-NEXT: - Type: CODE
3630
37NOEXPORT: Exports:31NOEXPORT: Exports:
38NOEXPORT-NEXT: - Name: memory32NOEXPORT-NEXT: - Name: memory
39NOEXPORT-NEXT: Kind: MEMORY33NOEXPORT-NEXT: Kind: MEMORY
40NOEXPORT-NEXT: Index: 034NOEXPORT-NEXT: Index: 0
41NOEXPORT-NEXT: - Name: __heap_base
42NOEXPORT-NEXT: Kind: GLOBAL
43NOEXPORT-NEXT: Index: 1
44NOEXPORT-NEXT: - Name: __data_end
45NOEXPORT-NEXT: Kind: GLOBAL
46NOEXPORT-NEXT: Index: 2
47NOEXPORT-NEXT: - Name: _start35NOEXPORT-NEXT: - Name: _start
48NOEXPORT-NEXT: Kind: FUNCTION36NOEXPORT-NEXT: Kind: FUNCTION
49NOEXPORT-NEXT: Index: 137NOEXPORT-NEXT: Index: 0
50NOEXPORT-NEXT: - Type: CODE38NOEXPORT-NEXT: - Type: CODE
deps/lld/test/wasm/archive-no-index.ll created+13
...@@ -0,0 +1,13 @@
1; Tests error on archive file without a symbol table
2; RUN: llvm-as -o %t.o %s
3; RUN: llvm-as -o %t.archive.o %S/Inputs/archive1.ll
4; RUN: rm -f %t.a
5; RUN: llvm-ar crS %t.a %t.archive.o
6
7; RUN: not wasm-ld -o out.wasm %t.o %t.a 2>&1 | FileCheck %s
8
9define i32 @_start() {
10 ret i32 0
11}
12
13; CHECK: archive has no index; run ranlib to add one
deps/lld/test/wasm/archive-weak-undefined.ll created+19
...@@ -0,0 +1,19 @@
1; RUN: llc -filetype=obj %s -o %t.o
2; RUN: llc -filetype=obj %S/Inputs/ret32.ll -o %t.a1.o
3; RUN: rm -f %t.a
4; RUN: llvm-ar rcs %t.a %t.a1.o
5; RUN: wasm-ld %t.o %t.a -o %t.wasm
6; RUN: obj2yaml %t.wasm | FileCheck %s
7
8target triple = "wasm32-unknown-unknown"
9
10declare extern_weak i32 @ret32()
11
12define void @_start() {
13entry:
14 %call1 = call i32 @ret32()
15 ret void
16}
17
18; CHECK: Name: 'undefined:ret32'
19; CHECK-NOT: Name: ret32
deps/lld/test/wasm/archive.ll+5-3
...@@ -33,10 +33,10 @@ entry:...@@ -33,10 +33,10 @@ entry:
33; TODO(ncw): Update LLD so that the symbol table is written out for33; TODO(ncw): Update LLD so that the symbol table is written out for
34; non-relocatable output (with an option to strip it)34; non-relocatable output (with an option to strip it)
3535
36; CHECK: 00000004 T _start36; CHECK: 00000016 T _start
37; CHECK-NEXT: 00000002 T archive2_symbol37; CHECK-NEXT: 0000000a T archive2_symbol
38; CHECK-NEXT: 00000001 T bar38; CHECK-NEXT: 00000001 T bar
39; CHECK-NEXT: 00000003 T foo39; CHECK-NEXT: 0000000d T foo
40; CHECK-NEXT: U missing_func40; CHECK-NEXT: U missing_func
4141
42; Verify that symbols from unused objects don't appear in the symbol table42; Verify that symbols from unused objects don't appear in the symbol table
...@@ -47,6 +47,8 @@ entry:...@@ -47,6 +47,8 @@ entry:
4747
48; Verfiy errors include library name48; Verfiy errors include library name
49; RUN: not wasm-ld -u archive2_symbol -u archive3_symbol %t.a %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-DUP %s49; RUN: not wasm-ld -u archive2_symbol -u archive3_symbol %t.a %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-DUP %s
50; And that this also works with --whole-archive
51; RUN: not wasm-ld -u archive2_symbol -u archive3_symbol --whole-archive %t.a %t.o -o %t.wasm 2>&1 | FileCheck -check-prefix=CHECK-DUP %s
50; CHECK-DUP: error: duplicate symbol: bar52; CHECK-DUP: error: duplicate symbol: bar
51; CHECK-DUP: >>> defined in {{.*}}.a({{.*}}.a2.o)53; CHECK-DUP: >>> defined in {{.*}}.a({{.*}}.a2.o)
52; CHECK-DUP: >>> defined in {{.*}}.a({{.*}}.a3.o)54; CHECK-DUP: >>> defined in {{.*}}.a({{.*}}.a3.o)
deps/lld/test/wasm/call-indirect.ll+17-40
...@@ -57,7 +57,7 @@ define void @call_ptr(i64 (i64)* %arg) {...@@ -57,7 +57,7 @@ define void @call_ptr(i64 (i64)* %arg) {
57; CHECK-NEXT: ParamTypes:57; CHECK-NEXT: ParamTypes:
58; CHECK-NEXT: - I3258; CHECK-NEXT: - I32
59; CHECK-NEXT: - Type: FUNCTION59; CHECK-NEXT: - Type: FUNCTION
60; CHECK-NEXT: FunctionTypes: [ 3, 0, 3, 1, 3, 4 ]60; CHECK-NEXT: FunctionTypes: [ 0, 3, 1, 3, 4 ]
61; CHECK-NEXT: - Type: TABLE61; CHECK-NEXT: - Type: TABLE
62; CHECK-NEXT: Tables:62; CHECK-NEXT: Tables:
63; CHECK-NEXT: - ElemType: FUNCREF63; CHECK-NEXT: - ElemType: FUNCREF
...@@ -81,80 +81,59 @@ define void @call_ptr(i64 (i64)* %arg) {...@@ -81,80 +81,59 @@ define void @call_ptr(i64 (i64)* %arg) {
81; CHECK-NEXT: Mutable: false81; CHECK-NEXT: Mutable: false
82; CHECK-NEXT: InitExpr:82; CHECK-NEXT: InitExpr:
83; CHECK-NEXT: Opcode: I32_CONST83; CHECK-NEXT: Opcode: I32_CONST
84; CHECK-NEXT: Value: 66576
85; CHECK-NEXT: - Index: 2
86; CHECK-NEXT: Type: I32
87; CHECK-NEXT: Mutable: false
88; CHECK-NEXT: InitExpr:
89; CHECK-NEXT: Opcode: I32_CONST
90; CHECK-NEXT: Value: 1036
91; CHECK-NEXT: - Index: 3
92; CHECK-NEXT: Type: I32
93; CHECK-NEXT: Mutable: false
94; CHECK-NEXT: InitExpr:
95; CHECK-NEXT: Opcode: I32_CONST
96; CHECK-NEXT: Value: 103284; CHECK-NEXT: Value: 1032
97; CHECK-NEXT: - Type: EXPORT85; CHECK-NEXT: - Type: EXPORT
98; CHECK-NEXT: Exports:86; CHECK-NEXT: Exports:
99; CHECK-NEXT: - Name: memory87; CHECK-NEXT: - Name: memory
100; CHECK-NEXT: Kind: MEMORY88; CHECK-NEXT: Kind: MEMORY
101; CHECK-NEXT: Index: 089; CHECK-NEXT: Index: 0
102; CHECK-NEXT: - Name: __heap_base
103; CHECK-NEXT: Kind: GLOBAL
104; CHECK-NEXT: Index: 1
105; CHECK-NEXT: - Name: __data_end
106; CHECK-NEXT: Kind: GLOBAL
107; CHECK-NEXT: Index: 2
108; CHECK-NEXT: - Name: bar90; CHECK-NEXT: - Name: bar
109; CHECK-NEXT: Kind: FUNCTION91; CHECK-NEXT: Kind: FUNCTION
110; CHECK-NEXT: Index: 192; CHECK-NEXT: Index: 0
111; CHECK-NEXT: - Name: call_bar_indirect93; CHECK-NEXT: - Name: call_bar_indirect
112; CHECK-NEXT: Kind: FUNCTION94; CHECK-NEXT: Kind: FUNCTION
113; CHECK-NEXT: Index: 295; CHECK-NEXT: Index: 1
114; CHECK-NEXT: - Name: foo96; CHECK-NEXT: - Name: foo
115; CHECK-NEXT: Kind: FUNCTION97; CHECK-NEXT: Kind: FUNCTION
116; CHECK-NEXT: Index: 398; CHECK-NEXT: Index: 2
117; CHECK-NEXT: - Name: _start99; CHECK-NEXT: - Name: _start
118; CHECK-NEXT: Kind: FUNCTION100; CHECK-NEXT: Kind: FUNCTION
119; CHECK-NEXT: Index: 4101; CHECK-NEXT: Index: 3
120; CHECK-NEXT: - Name: indirect_func102; CHECK-NEXT: - Name: indirect_func
121; CHECK-NEXT: Kind: GLOBAL103; CHECK-NEXT: Kind: GLOBAL
122; CHECK-NEXT: Index: 3104; CHECK-NEXT: Index: 1
123; CHECK-NEXT: - Name: call_ptr105; CHECK-NEXT: - Name: call_ptr
124; CHECK-NEXT: Kind: FUNCTION106; CHECK-NEXT: Kind: FUNCTION
125; CHECK-NEXT: Index: 5107; CHECK-NEXT: Index: 4
126; CHECK-NEXT: - Type: ELEM108; CHECK-NEXT: - Type: ELEM
127; CHECK-NEXT: Segments:109; CHECK-NEXT: Segments:
128; CHECK-NEXT: - Offset:110; CHECK-NEXT: - Offset:
129; CHECK-NEXT: Opcode: I32_CONST111; CHECK-NEXT: Opcode: I32_CONST
130; CHECK-NEXT: Value: 1112; CHECK-NEXT: Value: 1
131; CHECK-NEXT: Functions: [ 1, 3 ]113; CHECK-NEXT: Functions: [ 0, 2 ]
132; CHECK-NEXT: - Type: CODE114; CHECK-NEXT: - Type: CODE
133; CHECK-NEXT: Functions:115; CHECK-NEXT: Functions:
134; CHECK-NEXT: - Index: 0116; CHECK-NEXT: - Index: 0
135; CHECK-NEXT: Locals:117; CHECK-NEXT: Locals:
136; CHECK-NEXT: Body: 0B
137; CHECK-NEXT: - Index: 1
138; CHECK-NEXT: Locals:
139; CHECK-NEXT: Body: 42010B118; CHECK-NEXT: Body: 42010B
140; CHECK-NEXT: - Index: 2119; CHECK-NEXT: - Index: 1
141; CHECK-NEXT: Locals:120; CHECK-NEXT: Locals:
142; CHECK-NEXT: - Type: I32121; CHECK-NEXT: - Type: I32
143; CHECK-NEXT: Count: 1122; CHECK-NEXT: Count: 1
144; CHECK-NEXT: Body: 4100280284888080002100410028028088808000118080808000001A2000118180808000001A0B123; CHECK-NEXT: Body: 4100280284888080002100410028028088808000118080808000001A2000118180808000001A0B
145; CHECK-NEXT: - Index: 3124; CHECK-NEXT: - Index: 2
146; CHECK-NEXT: Locals:125; CHECK-NEXT: Locals:
147; CHECK-NEXT: Body: 41020B126; CHECK-NEXT: Body: 41020B
148; CHECK-NEXT: - Index: 4127; CHECK-NEXT: - Index: 3
149; CHECK-NEXT: Locals:128; CHECK-NEXT: Locals:
150; CHECK-NEXT: Body: 410028028888808000118180808000001A0B129; CHECK-NEXT: Body: 410028028888808000118180808000001A0B
151; CHECK-NEXT: - Index: 5130; CHECK-NEXT: - Index: 4
152; CHECK-NEXT: Locals:131; CHECK-NEXT: Locals:
153; CHECK-NEXT: Body: 42012000118280808000001A0B132; CHECK-NEXT: Body: 42012000118280808000001A0B
154; CHECK-NEXT: - Type: DATA133; CHECK-NEXT: - Type: DATA
155; CHECK-NEXT: Segments:134; CHECK-NEXT: Segments:
156; CHECK-NEXT: - SectionOffset: 7135; CHECK-NEXT: - SectionOffset: 7
157; CHECK-NEXT: MemoryIndex: 0136; CHECK-NEXT: InitFlags: 0
158; CHECK-NEXT: Offset:137; CHECK-NEXT: Offset:
159; CHECK-NEXT: Opcode: I32_CONST138; CHECK-NEXT: Opcode: I32_CONST
160; CHECK-NEXT: Value: 1024139; CHECK-NEXT: Value: 1024
...@@ -163,15 +142,13 @@ define void @call_ptr(i64 (i64)* %arg) {...@@ -163,15 +142,13 @@ define void @call_ptr(i64 (i64)* %arg) {
163; CHECK-NEXT: Name: name142; CHECK-NEXT: Name: name
164; CHECK-NEXT: FunctionNames:143; CHECK-NEXT: FunctionNames:
165; CHECK-NEXT: - Index: 0144; CHECK-NEXT: - Index: 0
166; CHECK-NEXT: Name: __wasm_call_ctors
167; CHECK-NEXT: - Index: 1
168; CHECK-NEXT: Name: bar145; CHECK-NEXT: Name: bar
169; CHECK-NEXT: - Index: 2146; CHECK-NEXT: - Index: 1
170; CHECK-NEXT: Name: call_bar_indirect147; CHECK-NEXT: Name: call_bar_indirect
171; CHECK-NEXT: - Index: 3148; CHECK-NEXT: - Index: 2
172; CHECK-NEXT: Name: foo149; CHECK-NEXT: Name: foo
173; CHECK-NEXT: - Index: 4150; CHECK-NEXT: - Index: 3
174; CHECK-NEXT: Name: _start151; CHECK-NEXT: Name: _start
175; CHECK-NEXT: - Index: 5152; CHECK-NEXT: - Index: 4
176; CHECK-NEXT: Name: call_ptr153; CHECK-NEXT: Name: call_ptr
177; CHECK-NEXT: ...154; CHECK-NEXT: ...
deps/lld/test/wasm/comdats.ll+18-31
...@@ -6,11 +6,13 @@...@@ -6,11 +6,13 @@
66
7target triple = "wasm32-unknown-unknown"7target triple = "wasm32-unknown-unknown"
88
9declare i32 @inlineFn()9declare void @__wasm_call_ctors()
10declare i32 @comdatFn()
1011
11define void @_start() local_unnamed_addr {12define void @_start() {
12entry:13entry:
13 %call = call i32 @inlineFn()14 call void @__wasm_call_ctors()
15 %call = call i32 @comdatFn()
14 ret void16 ret void
15}17}
1618
...@@ -27,45 +29,27 @@ entry:...@@ -27,45 +29,27 @@ entry:
27; CHECK-NEXT: Mutable: false29; CHECK-NEXT: Mutable: false
28; CHECK-NEXT: InitExpr:30; CHECK-NEXT: InitExpr:
29; CHECK-NEXT: Opcode: I32_CONST31; CHECK-NEXT: Opcode: I32_CONST
30; CHECK-NEXT: Value: 66576
31; CHECK-NEXT: - Index: 2
32; CHECK-NEXT: Type: I32
33; CHECK-NEXT: Mutable: false
34; CHECK-NEXT: InitExpr:
35; CHECK-NEXT: Opcode: I32_CONST
36; CHECK-NEXT: Value: 1027
37; CHECK-NEXT: - Index: 3
38; CHECK-NEXT: Type: I32
39; CHECK-NEXT: Mutable: false
40; CHECK-NEXT: InitExpr:
41; CHECK-NEXT: Opcode: I32_CONST
42; CHECK-NEXT: Value: 102432; CHECK-NEXT: Value: 1024
43; CHECK-NEXT: - Type: EXPORT33; CHECK-NEXT: - Type: EXPORT
44; CHECK-NEXT: Exports:34; CHECK-NEXT: Exports:
45; CHECK-NEXT: - Name: memory35; CHECK-NEXT: - Name: memory
46; CHECK-NEXT: Kind: MEMORY36; CHECK-NEXT: Kind: MEMORY
47; CHECK-NEXT: Index: 037; CHECK-NEXT: Index: 0
48; CHECK-NEXT: - Name: __heap_base
49; CHECK-NEXT: Kind: GLOBAL
50; CHECK-NEXT: Index: 1
51; CHECK-NEXT: - Name: __data_end
52; CHECK-NEXT: Kind: GLOBAL
53; CHECK-NEXT: Index: 2
54; CHECK-NEXT: - Name: _start38; CHECK-NEXT: - Name: _start
55; CHECK-NEXT: Kind: FUNCTION39; CHECK-NEXT: Kind: FUNCTION
56; CHECK-NEXT: Index: 140; CHECK-NEXT: Index: 1
57; CHECK-NEXT: - Name: inlineFn41; CHECK-NEXT: - Name: comdatFn
58; CHECK-NEXT: Kind: FUNCTION42; CHECK-NEXT: Kind: FUNCTION
59; CHECK-NEXT: Index: 243; CHECK-NEXT: Index: 2
60; CHECK-NEXT: - Name: constantData44; CHECK-NEXT: - Name: constantData
61; CHECK-NEXT: Kind: GLOBAL45; CHECK-NEXT: Kind: GLOBAL
62; CHECK-NEXT: Index: 346; CHECK-NEXT: Index: 1
63; CHECK-NEXT: - Name: callInline147; CHECK-NEXT: - Name: callComdatFn1
64; CHECK-NEXT: Kind: FUNCTION
65; CHECK-NEXT: Index: 3
66; CHECK-NEXT: - Name: callInline2
67; CHECK-NEXT: Kind: FUNCTION48; CHECK-NEXT: Kind: FUNCTION
68; CHECK-NEXT: Index: 449; CHECK-NEXT: Index: 4
50; CHECK-NEXT: - Name: callComdatFn2
51; CHECK-NEXT: Kind: FUNCTION
52; CHECK-NEXT: Index: 5
69; CHECK-NEXT: - Type: ELEM53; CHECK-NEXT: - Type: ELEM
70; CHECK-NEXT: Segments:54; CHECK-NEXT: Segments:
71; CHECK-NEXT: - Offset:55; CHECK-NEXT: - Offset:
...@@ -76,23 +60,26 @@ entry:...@@ -76,23 +60,26 @@ entry:
76; CHECK-NEXT: Functions:60; CHECK-NEXT: Functions:
77; CHECK-NEXT: - Index: 061; CHECK-NEXT: - Index: 0
78; CHECK-NEXT: Locals:62; CHECK-NEXT: Locals:
79; CHECK-NEXT: Body: 0B63; CHECK-NEXT: Body: 10030B
80; CHECK-NEXT: - Index: 164; CHECK-NEXT: - Index: 1
81; CHECK-NEXT: Locals:65; CHECK-NEXT: Locals:
82; CHECK-NEXT: Body: 1082808080001A0B66; CHECK-NEXT: Body: 1080808080001082808080001A0B
83; CHECK-NEXT: - Index: 267; CHECK-NEXT: - Index: 2
84; CHECK-NEXT: Locals:68; CHECK-NEXT: Locals:
85; CHECK-NEXT: Body: 4180888080000B69; CHECK-NEXT: Body: 4180888080000B
86; CHECK-NEXT: - Index: 370; CHECK-NEXT: - Index: 3
87; CHECK-NEXT: Locals:71; CHECK-NEXT: Locals:
88; CHECK-NEXT: Body: 4181808080000B72; CHECK-NEXT: Body: 0B
89; CHECK-NEXT: - Index: 473; CHECK-NEXT: - Index: 4
90; CHECK-NEXT: Locals:74; CHECK-NEXT: Locals:
91; CHECK-NEXT: Body: 4181808080000B75; CHECK-NEXT: Body: 4181808080000B
76; CHECK-NEXT: - Index: 5
77; CHECK-NEXT: Locals:
78; CHECK-NEXT: Body: 4181808080000B
92; CHECK-NEXT: - Type: DATA79; CHECK-NEXT: - Type: DATA
93; CHECK-NEXT: Segments:80; CHECK-NEXT: Segments:
94; CHECK-NEXT: - SectionOffset: 781; CHECK-NEXT: - SectionOffset: 7
95; CHECK-NEXT: MemoryIndex: 082; CHECK-NEXT: InitFlags: 0
96; CHECK-NEXT: Offset:83; CHECK-NEXT: Offset:
97; CHECK-NEXT: Opcode: I32_CONST84; CHECK-NEXT: Opcode: I32_CONST
98; CHECK-NEXT: Value: 102485; CHECK-NEXT: Value: 1024
deps/lld/test/wasm/corrupted.wasm.test created
Binary files /dev/null and b/deps/lld/test/wasm/corrupted.wasm.test differ
deps/lld/test/wasm/cxx-mangling.ll+8-19
...@@ -26,43 +26,32 @@ define void @_start() {...@@ -26,43 +26,32 @@ define void @_start() {
26; CHECK-NEXT: - Name: memory26; CHECK-NEXT: - Name: memory
27; CHECK-NEXT: Kind: MEMORY27; CHECK-NEXT: Kind: MEMORY
28; CHECK-NEXT: Index: 028; CHECK-NEXT: Index: 0
29; CHECK-NEXT: - Name: __heap_base
30; CHECK-NEXT: Kind: GLOBAL
31; CHECK-NEXT: Index: 1
32; CHECK-NEXT: - Name: __data_end
33; CHECK-NEXT: Kind: GLOBAL
34; CHECK-NEXT: Index: 2
35; CHECK-NEXT: - Name: _Z3fooi29; CHECK-NEXT: - Name: _Z3fooi
36; CHECK-NEXT: Kind: FUNCTION30; CHECK-NEXT: Kind: FUNCTION
37; CHECK-NEXT: Index: 231; CHECK-NEXT: Index: 1
38; CHECK-NEXT: - Name: _start32; CHECK-NEXT: - Name: _start
39; CHECK-NEXT: Kind: FUNCTION33; CHECK-NEXT: Kind: FUNCTION
40; CHECK-NEXT: Index: 334; CHECK-NEXT: Index: 2
41; CHECK-NEXT: - Type: CODE35; CHECK-NEXT: - Type: CODE
42; CHECK-NEXT: Functions:36; CHECK-NEXT: Functions:
43; CHECK-NEXT: - Index: 037; CHECK-NEXT: - Index: 0
44; CHECK-NEXT: Locals:38; CHECK-NEXT: Locals:
45; CHECK-NEXT: Body: 0B
46; CHECK-NEXT: - Index: 1
47; CHECK-NEXT: Locals:
48; CHECK-NEXT: Body: 000B39; CHECK-NEXT: Body: 000B
49; CHECK-NEXT: - Index: 240; CHECK-NEXT: - Index: 1
50; CHECK-NEXT: Locals:41; CHECK-NEXT: Locals:
51; CHECK-NEXT: Body: 0B42; CHECK-NEXT: Body: 0B
52; CHECK-NEXT: - Index: 343; CHECK-NEXT: - Index: 2
53; CHECK-NEXT: Locals:44; CHECK-NEXT: Locals:
54; CHECK-NEXT: Body: 410110828080800041011081808080000B45; CHECK-NEXT: Body: 410110818080800041011080808080000B
55; CHECK-NEXT: - Type: CUSTOM46; CHECK-NEXT: - Type: CUSTOM
56; CHECK-NEXT: Name: name47; CHECK-NEXT: Name: name
57; CHECK-NEXT: FunctionNames:48; CHECK-NEXT: FunctionNames:
58; CHECK-NEXT: - Index: 049; CHECK-NEXT: - Index: 0
59; CHECK-NEXT: Name: __wasm_call_ctors50; DEMANGLE-NEXT: Name: 'undefined:bar(int)'
51; MANGLE-NEXT: Name: 'undefined:_Z3bari'
60; CHECK-NEXT: - Index: 152; CHECK-NEXT: - Index: 1
61; DEMANGLE-NEXT: Name: 'undefined function bar(int)'
62; MANGLE-NEXT: Name: undefined function _Z3bari
63; CHECK-NEXT: - Index: 2
64; DEMANGLE-NEXT: Name: 'foo(int)'53; DEMANGLE-NEXT: Name: 'foo(int)'
65; MANGLE-NEXT: Name: _Z3fooi54; MANGLE-NEXT: Name: _Z3fooi
66; CHECK-NEXT: - Index: 355; CHECK-NEXT: - Index: 2
67; CHECK-NEXT: Name: _start56; CHECK-NEXT: Name: _start
68; CHECK-NEXT: ...57; CHECK-NEXT: ...
deps/lld/test/wasm/data-layout.ll+23-17
...@@ -13,7 +13,7 @@ target triple = "wasm32-unknown-unknown"...@@ -13,7 +13,7 @@ target triple = "wasm32-unknown-unknown"
13@local_struct = hidden global %struct.s zeroinitializer, align 413@local_struct = hidden global %struct.s zeroinitializer, align 4
14@local_struct_internal_ptr = hidden local_unnamed_addr global i32* getelementptr inbounds (%struct.s, %struct.s* @local_struct, i32 0, i32 1), align 414@local_struct_internal_ptr = hidden local_unnamed_addr global i32* getelementptr inbounds (%struct.s, %struct.s* @local_struct, i32 0, i32 1), align 4
1515
16; RUN: wasm-ld -no-gc-sections --allow-undefined --no-entry -o %t.wasm %t.o %t.hello.o16; RUN: wasm-ld -no-gc-sections --export=__data_end --export=__heap_base --allow-undefined --no-entry -o %t.wasm %t.o %t.hello.o
17; RUN: obj2yaml %t.wasm | FileCheck %s17; RUN: obj2yaml %t.wasm | FileCheck %s
1818
19; CHECK: - Type: MEMORY19; CHECK: - Type: MEMORY
...@@ -32,25 +32,31 @@ target triple = "wasm32-unknown-unknown"...@@ -32,25 +32,31 @@ target triple = "wasm32-unknown-unknown"
32; CHECK-NEXT: Mutable: false32; CHECK-NEXT: Mutable: false
33; CHECK-NEXT: InitExpr:33; CHECK-NEXT: InitExpr:
34; CHECK-NEXT: Opcode: I32_CONST34; CHECK-NEXT: Opcode: I32_CONST
35; CHECK-NEXT: Value: 1071
36; CHECK-NEXT: - Index: 2
37; CHECK-NEXT: Type: I32
38; CHECK-NEXT: Mutable: false
39; CHECK-NEXT: InitExpr:
40; CHECK-NEXT: Opcode: I32_CONST
35; CHECK-NEXT: Value: 6660841; CHECK-NEXT: Value: 66608
3642
37; CHECK: - Type: DATA43; CHECK: - Type: DATA
38; CHECK-NEXT: Segments:44; CHECK-NEXT: Segments:
39; CHECK-NEXT: - SectionOffset: 745; CHECK-NEXT: - SectionOffset: 7
40; CHECK-NEXT: MemoryIndex: 046; CHECK-NEXT: InitFlags: 0
41; CHECK-NEXT: Offset:47; CHECK-NEXT: Offset:
42; CHECK-NEXT: Opcode: I32_CONST48; CHECK-NEXT: Opcode: I32_CONST
43; CHECK-NEXT: Value: 102449; CHECK-NEXT: Value: 1024
44; CHECK-NEXT: Content: '0100000000000000000000000000000003000000000000002804000024040000'50; CHECK-NEXT: Content: '0100000000000000000000000000000003000000000000002804000024040000'
45; CHECK-NEXT: - SectionOffset: 4551; CHECK-NEXT: - SectionOffset: 45
46; CHECK-NEXT: MemoryIndex: 052; CHECK-NEXT: InitFlags: 0
47; CHECK-NEXT: Offset:53; CHECK-NEXT: Offset:
48; CHECK-NEXT: Opcode: I32_CONST54; CHECK-NEXT: Opcode: I32_CONST
49; CHECK-NEXT: Value: 105655; CHECK-NEXT: Value: 1056
50; CHECK-NEXT: Content: '0000000000000000'56; CHECK-NEXT: Content: '0000000000000000'
51; CHECK-NEXT: - SectionOffset: 5957; CHECK-NEXT: - SectionOffset: 59
52; CHECK-NEXT: MemoryIndex: 058; CHECK-NEXT: InitFlags: 0
53; CHECK-NEXT: Offset: 59; CHECK-NEXT: Offset:
54; CHECK-NEXT: Opcode: I32_CONST60; CHECK-NEXT: Opcode: I32_CONST
55; CHECK-NEXT: Value: 106461; CHECK-NEXT: Value: 1064
56; CHECK-NEXT: Content: 68656C6C6F0A0062; CHECK-NEXT: Content: 68656C6C6F0A00
...@@ -70,7 +76,7 @@ target triple = "wasm32-unknown-unknown"...@@ -70,7 +76,7 @@ target triple = "wasm32-unknown-unknown"
7076
71; RUN: wasm-ld -no-gc-sections --allow-undefined --no-entry --shared-memory \77; 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 \78; RUN: --initial-memory=131072 --max-memory=131072 -o %t_max.wasm %t.o \
73; RUN: %t.hello.o79; RUN: --active-segments %t.hello.o
74; RUN: obj2yaml %t_max.wasm | FileCheck %s -check-prefix=CHECK-SHARED80; RUN: obj2yaml %t_max.wasm | FileCheck %s -check-prefix=CHECK-SHARED
7581
76; CHECK-SHARED: - Type: MEMORY82; CHECK-SHARED: - Type: MEMORY
...@@ -84,46 +90,46 @@ target triple = "wasm32-unknown-unknown"...@@ -84,46 +90,46 @@ target triple = "wasm32-unknown-unknown"
8490
85; RELOC: - Type: DATA91; RELOC: - Type: DATA
86; RELOC-NEXT: Relocations:92; RELOC-NEXT: Relocations:
87; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I3293; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_I32
88; RELOC-NEXT: Index: 394; RELOC-NEXT: Index: 3
89; RELOC-NEXT: Offset: 0x0000001895; RELOC-NEXT: Offset: 0x00000018
90; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I3296; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_I32
91; RELOC-NEXT: Index: 497; RELOC-NEXT: Index: 4
92; RELOC-NEXT: Offset: 0x0000002E98; RELOC-NEXT: Offset: 0x0000002E
93; RELOC-NEXT: Addend: 499; RELOC-NEXT: Addend: 4
94; RELOC-NEXT: Segments:100; RELOC-NEXT: Segments:
95; RELOC-NEXT: - SectionOffset: 6101; RELOC-NEXT: - SectionOffset: 6
96; RELOC-NEXT: MemoryIndex: 0102; RELOC-NEXT: InitFlags: 0
97; RELOC-NEXT: Offset:103; RELOC-NEXT: Offset:
98; RELOC-NEXT: Opcode: I32_CONST104; RELOC-NEXT: Opcode: I32_CONST
99; RELOC-NEXT: Value: 0105; RELOC-NEXT: Value: 0
100; RELOC-NEXT: Content: '01000000'106; RELOC-NEXT: Content: '01000000'
101; RELOC-NEXT: - SectionOffset: 15107; RELOC-NEXT: - SectionOffset: 15
102; RELOC-NEXT: MemoryIndex: 0108; RELOC-NEXT: InitFlags: 0
103; RELOC-NEXT: Offset:109; RELOC-NEXT: Offset:
104; RELOC-NEXT: Opcode: I32_CONST110; RELOC-NEXT: Opcode: I32_CONST
105; RELOC-NEXT: Value: 16111; RELOC-NEXT: Value: 16
106; RELOC-NEXT: Content: '03000000'112; RELOC-NEXT: Content: '03000000'
107; RELOC-NEXT: - SectionOffset: 24113; RELOC-NEXT: - SectionOffset: 24
108; RELOC-NEXT: MemoryIndex: 0114; RELOC-NEXT: InitFlags: 0
109; RELOC-NEXT: Offset:115; RELOC-NEXT: Offset:
110; RELOC-NEXT: Opcode: I32_CONST116; RELOC-NEXT: Opcode: I32_CONST
111; RELOC-NEXT: Value: 24117; RELOC-NEXT: Value: 24
112; RELOC-NEXT: Content: '28000000'118; RELOC-NEXT: Content: '28000000'
113; RELOC-NEXT: - SectionOffset: 33119; RELOC-NEXT: - SectionOffset: 33
114; RELOC-NEXT: MemoryIndex: 0120; RELOC-NEXT: InitFlags: 0
115; RELOC-NEXT: Offset: 121; RELOC-NEXT: Offset:
116; RELOC-NEXT: Opcode: I32_CONST122; RELOC-NEXT: Opcode: I32_CONST
117; RELOC-NEXT: Value: 28123; RELOC-NEXT: Value: 28
118; RELOC-NEXT: Content: '0000000000000000'124; RELOC-NEXT: Content: '0000000000000000'
119; RELOC-NEXT: - SectionOffset: 46125; RELOC-NEXT: - SectionOffset: 46
120; RELOC-NEXT: MemoryIndex: 0126; RELOC-NEXT: InitFlags: 0
121; RELOC-NEXT: Offset: 127; RELOC-NEXT: Offset:
122; RELOC-NEXT: Opcode: I32_CONST128; RELOC-NEXT: Opcode: I32_CONST
123; RELOC-NEXT: Value: 36129; RELOC-NEXT: Value: 36
124; RELOC-NEXT: Content: '20000000'130; RELOC-NEXT: Content: '20000000'
125; RELOC-NEXT: - SectionOffset: 55131; RELOC-NEXT: - SectionOffset: 55
126; RELOC-NEXT: MemoryIndex: 0132; RELOC-NEXT: InitFlags: 0
127; RELOC-NEXT: Offset:133; RELOC-NEXT: Offset:
128; RELOC-NEXT: Opcode: I32_CONST134; RELOC-NEXT: Opcode: I32_CONST
129; RELOC-NEXT: Value: 40135; RELOC-NEXT: Value: 40
deps/lld/test/wasm/data-segment-merging.ll+110-17
...@@ -8,24 +8,117 @@ target triple = "wasm32-unknown-unknown"...@@ -8,24 +8,117 @@ target triple = "wasm32-unknown-unknown"
8@e = private constant [9 x i8] c"constant\00", align 18@e = private constant [9 x i8] c"constant\00", align 1
9@f = private constant i8 43, align 49@f = private constant i8 43, align 4
1010
11; RUN: llc -filetype=obj %s -o %t.data-segment-merging.o11; RUN: llc -mattr=+bulk-memory -filetype=obj %s -o %t.o
1212
13; RUN: wasm-ld -no-gc-sections --no-entry -o %t.merged.wasm %t.data-segment-merging.o13; RUN: wasm-ld -no-gc-sections --no-entry -o %t.merged.wasm %t.o
14; RUN: obj2yaml %t.merged.wasm | FileCheck %s --check-prefix=MERGE14; RUN: obj2yaml %t.merged.wasm | FileCheck %s --check-prefix=MERGE
15; MERGE: - Type: DATA
16; MERGE: Segments:
17; MERGE: Content: 68656C6C6F00676F6F6462796500776861746576657200002A000000
18; MERGE: Content: 636F6E7374616E74000000002B
19; MERGE-NOT: Content:
2015
21; RUN: wasm-ld -no-gc-sections --no-entry --no-merge-data-segments -o %t.separate.wasm %t.data-segment-merging.o16; MERGE-LABEL: - Type: DATA
17; MERGE-NEXT: Segments:
18; MERGE-NEXT: - SectionOffset: 7
19; MERGE-NEXT: InitFlags: 0
20; MERGE-NEXT: Offset:
21; MERGE: Content: 68656C6C6F00676F6F6462796500776861746576657200002A000000
22; MERGE-NEXT: - SectionOffset: 41
23; MERGE-NEXT: InitFlags: 0
24; MERGE-NEXT: Offset:
25; MERGE: Content: 636F6E7374616E74000000002B
26; MERGE-NEXT: - Type: CUSTOM
27; MERGE-NEXT: Name: name
28; MERGE-NEXT: FunctionNames:
29; MERGE-NEXT: - Index: 0
30; MERGE-NEXT: Name: __wasm_call_ctors
31; MERGE-NOT: - Index:
32
33; RUN: wasm-ld -no-gc-sections --no-entry --no-merge-data-segments -o %t.separate.wasm %t.o
22; RUN: obj2yaml %t.separate.wasm | FileCheck %s --check-prefix=SEPARATE34; RUN: obj2yaml %t.separate.wasm | FileCheck %s --check-prefix=SEPARATE
23; SEPARATE: - Type: DATA35
24; SEPARATE: Segments:36; SEPARATE-NOT: DATACOUNT
25; SEPARATE: Content: 68656C6C6F0037; SEPARATE-LABEL: - Type: DATA
26; SEPARATE: Content: 676F6F646279650038; SEPARATE-NEXT: Segments:
27; SEPARATE: Content: '776861746576657200'39; SEPARATE-NEXT: - SectionOffset: 7
28; SEPARATE: Content: 2A00000040; SEPARATE-NEXT: InitFlags: 0
29; SEPARATE: Content: 636F6E7374616E740041; SEPARATE-NEXT: Offset:
30; SEPARATE: Content: 2B42; SEPARATE: Content: 68656C6C6F00
31; SEPARATE-NOT: Content:43; SEPARATE-NEXT: - SectionOffset: 19
44; SEPARATE-NEXT: InitFlags: 0
45; SEPARATE-NEXT: Offset:
46; SEPARATE: Content: 676F6F6462796500
47; SEPARATE-NEXT: - SectionOffset: 33
48; SEPARATE-NEXT: InitFlags: 0
49; SEPARATE-NEXT: Offset:
50; SEPARATE: Content: '776861746576657200'
51; SEPARATE-NEXT: - SectionOffset: 48
52; SEPARATE-NEXT: InitFlags: 0
53; SEPARATE-NEXT: Offset:
54; SEPARATE: Content: 2A000000
55; SEPARATE-NEXT: - SectionOffset: 58
56; SEPARATE-NEXT: InitFlags: 0
57; SEPARATE-NEXT: Offset:
58; SEPARATE: Content: 636F6E7374616E7400
59; SEPARATE-NEXT: - SectionOffset: 73
60; SEPARATE-NEXT: InitFlags: 0
61; SEPARATE-NEXT: Offset:
62; SEPARATE: Content: 2B
63; SEPARATE-NEXT: - Type: CUSTOM
64; SEPARATE-NEXT: Name: name
65; SEPARATE-NEXT: FunctionNames:
66; SEPARATE-NEXT: - Index: 0
67; SEPARATE-NEXT: Name: __wasm_call_ctors
68; SEPARATE-NOT: - Index:
69
70; RUN: wasm-ld -no-gc-sections --no-entry --passive-segments -o %t.merged.passive.wasm %t.o
71; RUN: obj2yaml %t.merged.passive.wasm | FileCheck %s --check-prefix=PASSIVE-MERGE
72
73; PASSIVE-MERGE-LABEL: - Type: DATACOUNT
74; PASSIVE-MERGE-NEXT: Count: 2
75; PASSIVE-MERGE-LABEL: - Type: DATA
76; PASSIVE-MERGE-NEXT: Segments:
77; PASSIVE-MERGE-NEXT: - SectionOffset: 3
78; PASSIVE-MERGE-NEXT: InitFlags: 1
79; PASSIVE-MERGE-NEXT: Content: 68656C6C6F00676F6F6462796500776861746576657200002A000000
80; PASSIVE-MERGE-NEXT: - SectionOffset: 33
81; PASSIVE-MERGE-NEXT: InitFlags: 1
82; PASSIVE-MERGE-NEXT: Content: 636F6E7374616E74000000002B
83; PASSIVE-MERGE-NEXT: - Type: CUSTOM
84; PASSIVE-MERGE-NEXT: Name: name
85; PASSIVE-MERGE-NEXT: FunctionNames:
86; PASSIVE-MERGE-NEXT: - Index: 0
87; PASSIVE-MERGE-NEXT: Name: __wasm_call_ctors
88; PASSIVE-MERGE-NEXT: - Index: 1
89; PASSIVE-MERGE-NEXT: Name: __wasm_init_memory
90; PASSIVE-MERGE-NOT: - Index:
91
92; RUN: wasm-ld -no-gc-sections --no-entry --passive-segments -no-merge-data-segments -o %t.separate.passive.wasm %t.o
93; RUN: obj2yaml %t.separate.passive.wasm | FileCheck %s --check-prefix=PASSIVE-SEPARATE
94
95; PASSIVE-SEPARATE-LABEL: - Type: DATACOUNT
96; PASSIVE-SEPARATE-NEXT: Count: 6
97; PASSIVE-SEPARATE-LABEL: - Type: DATA
98; PASSIVE-SEPARATE-NEXT: Segments:
99; PASSIVE-SEPARATE-NEXT: - SectionOffset: 3
100; PASSIVE-SEPARATE-NEXT: InitFlags: 1
101; PASSIVE-SEPARATE-NEXT: Content: 68656C6C6F00
102; PASSIVE-SEPARATE-NEXT: - SectionOffset: 11
103; PASSIVE-SEPARATE-NEXT: InitFlags: 1
104; PASSIVE-SEPARATE-NEXT: Content: 676F6F6462796500
105; PASSIVE-SEPARATE-NEXT: - SectionOffset: 21
106; PASSIVE-SEPARATE-NEXT: InitFlags: 1
107; PASSIVE-SEPARATE-NEXT: Content: '776861746576657200'
108; PASSIVE-SEPARATE-NEXT: - SectionOffset: 32
109; PASSIVE-SEPARATE-NEXT: InitFlags: 1
110; PASSIVE-SEPARATE-NEXT: Content: 2A000000
111; PASSIVE-SEPARATE-NEXT: - SectionOffset: 38
112; PASSIVE-SEPARATE-NEXT: InitFlags: 1
113; PASSIVE-SEPARATE-NEXT: Content: 636F6E7374616E7400
114; PASSIVE-SEPARATE-NEXT: - SectionOffset: 49
115; PASSIVE-SEPARATE-NEXT: InitFlags: 1
116; PASSIVE-SEPARATE-NEXT: Content: 2B
117; PASSIVE-SEPARATE-NEXT: - Type: CUSTOM
118; PASSIVE-SEPARATE-NEXT: Name: name
119; PASSIVE-SEPARATE-NEXT: FunctionNames:
120; PASSIVE-SEPARATE-NEXT: - Index: 0
121; PASSIVE-SEPARATE-NEXT: Name: __wasm_call_ctors
122; PASSIVE-SEPARATE-NEXT: - Index: 1
123; PASSIVE-SEPARATE-NEXT: Name: __wasm_init_memory
124; PASSIVE-SEPARATE-NOT: - Index
deps/lld/test/wasm/data-segments.ll created+119
...@@ -0,0 +1,119 @@
1; RUN: llc -filetype=obj %s -o %t.atomics.o -mattr=+atomics
2; RUN: llc -filetype=obj %s -o %t.bulk-mem.o -mattr=+bulk-memory
3; RUN: llc -filetype=obj %s -o %t.atomics.bulk-mem.o -mattr=+atomics,+bulk-memory
4
5; atomics => error
6; RUN: not wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 %t.atomics.o -o %t.atomics.wasm 2>&1 | FileCheck %s --check-prefix ERROR
7
8; atomics, active segments => active segments
9; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --active-segments %t.atomics.o -o %t.atomics.active.wasm
10; RUN: obj2yaml %t.atomics.active.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS
11
12; atomics, passive segments => error
13; RUN: not wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --passive-segments %t.atomics.o -o %t.atomics.passive.wasm 2>&1 | FileCheck %s --check-prefix ERROR
14
15; bulk memory => active segments
16; RUN: wasm-ld -no-gc-sections --no-entry %t.bulk-mem.o -o %t.bulk-mem.wasm
17; RUN: obj2yaml %t.bulk-mem.wasm | FileCheck %s --check-prefix ACTIVE
18
19; bulk-memory, active segments => active segments
20; RUN: wasm-ld -no-gc-sections --no-entry --active-segments %t.bulk-mem.o -o %t.bulk-mem.active.wasm
21; RUN: obj2yaml %t.bulk-mem.active.wasm | FileCheck %s --check-prefix ACTIVE
22
23; bulk memory, passive segments => passive segments
24; RUN: wasm-ld -no-gc-sections --no-entry --passive-segments %t.bulk-mem.o -o %t.bulk-mem.passive.wasm
25; RUN: obj2yaml %t.bulk-mem.passive.wasm | FileCheck %s --check-prefix PASSIVE
26
27; atomics, bulk memory => passive segments
28; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.wasm
29; RUN: obj2yaml %t.atomics.bulk-mem.wasm | FileCheck %s --check-prefixes PASSIVE,PASSIVE-TLS
30
31; atomics, bulk memory, active segments => active segments
32; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --active-segments %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.active.wasm
33; RUN: obj2yaml %t.atomics.bulk-mem.active.wasm | FileCheck %s --check-prefixes ACTIVE,ACTIVE-TLS
34
35; atomics, bulk memory, passive segments => passive segments
36; RUN: wasm-ld -no-gc-sections --no-entry --shared-memory --max-memory=131072 --passive-segments %t.atomics.bulk-mem.o -o %t.atomics.bulk-mem.passive.wasm
37; RUN: obj2yaml %t.atomics.bulk-mem.passive.wasm | FileCheck %s --check-prefixes PASSIVE,PASSIVE-TLS
38
39target triple = "wasm32-unknown-unknown"
40
41@a = hidden global [6 x i8] c"hello\00", align 1
42@b = hidden global [8 x i8] c"goodbye\00", align 1
43@c = hidden global [10000 x i8] zeroinitializer, align 1
44@d = hidden global i32 42, align 4
45
46@e = private constant [9 x i8] c"constant\00", align 1
47@f = private constant i8 43, align 4
48
49; ERROR: 'bulk-memory' feature must be used in order to emit passive segments
50
51; ACTIVE-LABEL: - Type: CODE
52; ACTIVE-NEXT: Functions:
53; ACTIVE-NEXT: - Index: 0
54; ACTIVE-NEXT: Locals: []
55; ACTIVE-NEXT: Body: 0B
56; ACTIVE-TLS-NEXT: - Index: 1
57; ACTIVE-TLS-NEXT: Locals: []
58; ACTIVE-TLS-NEXT: Body: 0B
59; ACTIVE-NEXT: - Type: DATA
60; ACTIVE-NEXT: Segments:
61; ACTIVE-NEXT: - SectionOffset: 7
62; ACTIVE-NEXT: InitFlags: 0
63; ACTIVE-NEXT: Offset:
64; ACTIVE-NEXT: Opcode: I32_CONST
65; ACTIVE-NEXT: Value: 1024
66; ACTIVE-NEXT: Content: 68656C6C6F00676F6F646279650000002A000000
67; ACTIVE-NEXT: - SectionOffset: 34
68; ACTIVE-NEXT: InitFlags: 0
69; ACTIVE-NEXT: Offset:
70; ACTIVE-NEXT: Opcode: I32_CONST
71; ACTIVE-NEXT: Value: 1044
72; ACTIVE-NEXT: Content: '0000000000
73; ACTIVE-SAME: 0000000000'
74; ACTIVE-NEXT: - SectionOffset: 10041
75; ACTIVE-NEXT: InitFlags: 0
76; ACTIVE-NEXT: Offset:
77; ACTIVE-NEXT: Opcode: I32_CONST
78; ACTIVE-NEXT: Value: 11044
79; ACTIVE-NEXT: Content: 636F6E7374616E74000000002B
80; ACTIVE-NEXT: - Type: CUSTOM
81; ACTIVE-NEXT: Name: name
82; ACTIVE-NEXT: FunctionNames:
83; ACTIVE-NEXT: - Index: 0
84; ACTIVE-NEXT: Name: __wasm_call_ctors
85; ACTIVE-TLS-NEXT: - Index: 1
86; ACTIVE-TLS-NEXT: Name: __wasm_init_tls
87
88; PASSIVE-LABEL: - Type: CODE
89; PASSIVE-NEXT: Functions:
90; PASSIVE-NEXT: - Index: 0
91; PASSIVE-NEXT: Locals: []
92; PASSIVE-NEXT: Body: 10010B
93; PASSIVE-NEXT: - Index: 1
94; PASSIVE-NEXT: Locals: []
95; PASSIVE-NEXT: Body: 41800841004114FC080000FC090041940841004190CE00FC080100FC090141A4D6004100410DFC080200FC09020B
96; PASSIVE-TLS-NEXT: - Index: 2
97; PASSIVE-TLS-NEXT: Locals: []
98; PASSIVE-TLS-NEXT: Body: 0B
99; PASSIVE-NEXT: - Type: DATA
100; PASSIVE-NEXT: Segments:
101; PASSIVE-NEXT: - SectionOffset: 3
102; PASSIVE-NEXT: InitFlags: 1
103; PASSIVE-NEXT: Content: 68656C6C6F00676F6F646279650000002A000000
104; PASSIVE-NEXT: - SectionOffset: 26
105; PASSIVE-NEXT: InitFlags: 1
106; PASSIVE-NEXT: Content: '0000000000
107; PASSIVE-SAME: 0000000000'
108; PASSIVE-NEXT: - SectionOffset: 10028
109; PASSIVE-NEXT: InitFlags: 1
110; PASSIVE-NEXT: Content: 636F6E7374616E74000000002B
111; PASSIVE-NEXT: - Type: CUSTOM
112; PASSIVE-NEXT: Name: name
113; PASSIVE-NEXT: FunctionNames:
114; PASSIVE-NEXT: - Index: 0
115; PASSIVE-NEXT: Name: __wasm_call_ctors
116; PASSIVE-NEXT: - Index: 1
117; PASSIVE-NEXT: Name: __wasm_init_memory
118; PASSIVE-TLS-NEXT: - Index: 2
119; PASSIVE-TLS-NEXT: Name: __wasm_init_tls
deps/lld/test/wasm/emit-relocs-fpic.s created+20
...@@ -0,0 +1,20 @@
1# RUN: llvm-mc -triple=wasm32-unknown-unknown -filetype=obj -o %t.o < %s
2# RUN: llc --relocation-model=pic -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
3# RUN: wasm-ld -pie --export-all --no-gc-sections --no-entry --emit-relocs -o %t.wasm %t.o %t.ret32.o
4# RUN: obj2yaml %t.wasm | FileCheck %s
5
6load_hidden_data:
7 .functype load_hidden_data () -> (i32)
8 i32.const .L.hidden_data@MBREL
9 end_function
10
11.section .rodata.hidden_data,"",@
12.L.hidden_data:
13 .int8 100
14 .size .L.hidden_data, 1
15
16# We just want to make sure that processing this relocation doesn't
17# cause corrupt output. We get most of the way there, by just checking
18# that obj2yaml doesn't fail. Here we just make sure that the relocation
19# survived the trip.
20# CHECK: R_WASM_MEMORY_ADDR_REL_SLEB
deps/lld/test/wasm/emit-relocs.ll created+39
...@@ -0,0 +1,39 @@
1; RUN: llc -filetype=obj %s -o %t.o
2; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
3; RUN: wasm-ld --emit-relocs -o %t.wasm %t.o %t.ret32.o
4; RUN: obj2yaml %t.wasm | FileCheck %s
5
6target triple = "wasm32-unknown-unknown"
7
8declare i32 @ret32(float)
9
10define void @unused_function() {
11 ret void
12}
13
14define hidden void @_start() local_unnamed_addr #0 {
15entry:
16 call i32 @ret32(float 0.0)
17 ret void
18}
19
20; CHECK: - Type: CODE
21; CHECK-NEXT: Relocations:
22; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
23; CHECK-NEXT: Index: 1
24; CHECK-NEXT: Offset: 0x00000009
25
26; CHECK: - Type: CUSTOM
27; CHECK-NEXT: Name: linking
28; CHECK-NEXT: Version: 2
29; CHECK-NEXT: SymbolTable:
30; CHECK-NEXT: - Index: 0
31; CHECK-NEXT: Kind: FUNCTION
32; CHECK-NEXT: Name: _start
33; CHECK-NEXT: Flags: [ ]
34; CHECK-NEXT: Function: 0
35; CHECK-NEXT: - Index: 1
36; CHECK-NEXT: Kind: FUNCTION
37; CHECK-NEXT: Name: ret32
38; CHECK-NEXT: Flags: [ VISIBILITY_HIDDEN ]
39; CHECK-NEXT: Function: 1
deps/lld/test/wasm/entry.ll+1-13
...@@ -17,15 +17,9 @@ entry:...@@ -17,15 +17,9 @@ entry:
17; CHECK-NEXT: - Name: memory17; CHECK-NEXT: - Name: memory
18; CHECK-NEXT: Kind: MEMORY18; CHECK-NEXT: Kind: MEMORY
19; CHECK-NEXT: Index: 019; CHECK-NEXT: Index: 0
20; CHECK-NEXT: - Name: __heap_base
21; CHECK-NEXT: Kind: GLOBAL
22; CHECK-NEXT: Index: 1
23; CHECK-NEXT: - Name: __data_end
24; CHECK-NEXT: Kind: GLOBAL
25; CHECK-NEXT: Index: 2
26; CHECK-NEXT: - Name: entry20; CHECK-NEXT: - Name: entry
27; CHECK-NEXT: Kind: FUNCTION21; CHECK-NEXT: Kind: FUNCTION
28; CHECK-NEXT: Index: 122; CHECK-NEXT: Index: 0
29; CHECK-NEXT: - Type:23; CHECK-NEXT: - Type:
3024
31; The __wasm_call_ctors is somewhat special since its created by the linker.25; The __wasm_call_ctors is somewhat special since its created by the linker.
...@@ -41,10 +35,4 @@ entry:...@@ -41,10 +35,4 @@ entry:
41; CHECK-CTOR-NEXT: - Name: __wasm_call_ctors35; CHECK-CTOR-NEXT: - Name: __wasm_call_ctors
42; CHECK-CTOR-NEXT: Kind: FUNCTION36; CHECK-CTOR-NEXT: Kind: FUNCTION
43; CHECK-CTOR-NEXT: Index: 037; CHECK-CTOR-NEXT: Index: 0
44; CHECK-CTOR-NEXT: - Name: __heap_base
45; CHECK-CTOR-NEXT: Kind: GLOBAL
46; CHECK-CTOR-NEXT: Index: 1
47; CHECK-CTOR-NEXT: - Name: __data_end
48; CHECK-CTOR-NEXT: Kind: GLOBAL
49; CHECK-CTOR-NEXT: Index: 2
50; CHECK-CTOR-NEXT: - Type:38; CHECK-CTOR-NEXT: - Type:
deps/lld/test/wasm/export.ll+21-6
...@@ -3,13 +3,29 @@...@@ -3,13 +3,29 @@
3; RUN: wasm-ld --export=hidden_function -o %t.wasm %t.o3; RUN: wasm-ld --export=hidden_function -o %t.wasm %t.o
4; RUN: obj2yaml %t.wasm | FileCheck %s4; RUN: obj2yaml %t.wasm | FileCheck %s
55
6@llvm.used = appending global [1 x i8*] [i8* bitcast (i32 ()* @used_function to i8*)], section "llvm.metadata"
7
6target triple = "wasm32-unknown-unknown"8target triple = "wasm32-unknown-unknown"
79
10; Not exported by default, but forced via commandline
8define hidden i32 @hidden_function() local_unnamed_addr {11define hidden i32 @hidden_function() local_unnamed_addr {
9entry:12entry:
10 ret i32 013 ret i32 0
11}14}
1215
16; Not exported by default
17define i32 @default_function() local_unnamed_addr {
18entry:
19 ret i32 0
20}
21
22; Exported because its part of llvm.used
23define i32 @used_function() local_unnamed_addr {
24entry:
25 ret i32 0
26}
27
28; Exported by default
13define void @_start() local_unnamed_addr {29define void @_start() local_unnamed_addr {
14entry:30entry:
15 ret void31 ret void
...@@ -17,19 +33,18 @@ entry:...@@ -17,19 +33,18 @@ entry:
1733
18; CHECK-ERROR: error: symbol exported via --export not found: missing34; CHECK-ERROR: error: symbol exported via --export not found: missing
1935
36; CHECK-NOT: - Name: default_function
37
20; CHECK: - Type: EXPORT38; CHECK: - Type: EXPORT
21; CHECK-NEXT: Exports:39; CHECK-NEXT: Exports:
22; CHECK-NEXT: - Name: memory40; CHECK-NEXT: - Name: memory
23; CHECK-NEXT: Kind: MEMORY41; CHECK-NEXT: Kind: MEMORY
24; CHECK-NEXT: Index: 042; CHECK-NEXT: Index: 0
25; CHECK-NEXT: - Name: __heap_base
26; CHECK-NEXT: Kind: GLOBAL
27; CHECK-NEXT: Index: 1
28; CHECK-NEXT: - Name: __data_end
29; CHECK-NEXT: Kind: GLOBAL
30; CHECK-NEXT: Index: 2
31; CHECK-NEXT: - Name: hidden_function43; CHECK-NEXT: - Name: hidden_function
32; CHECK-NEXT: Kind: FUNCTION44; CHECK-NEXT: Kind: FUNCTION
45; CHECK-NEXT: Index: 0
46; CHECK-NEXT: - Name: used_function
47; CHECK-NEXT: Kind: FUNCTION
33; CHECK-NEXT: Index: 148; CHECK-NEXT: Index: 1
34; CHECK-NEXT: - Name: _start49; CHECK-NEXT: - Name: _start
35; CHECK-NEXT: Kind: FUNCTION50; CHECK-NEXT: Kind: FUNCTION
deps/lld/test/wasm/fatal-warnings.ll+2-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1; RUN: llc -filetype=obj %s -o %t.main.o1; RUN: llc -filetype=obj %s -o %t.main.o
2; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o2; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
3; RUN: lld -flavor wasm -o %t.wasm %t.main.o %t.ret32.o 2>&1 | FileCheck %s -check-prefix=CHECK-WARN3; RUN: wasm-ld -o %t.wasm %t.main.o %t.ret32.o 2>&1 | FileCheck %s -check-prefix=CHECK-WARN
4; RUN: not lld -flavor wasm --fatal-warnings -o %t.wasm %t.main.o %t.ret32.o 2>&1 | FileCheck %s -check-prefix=CHECK-FATAL4; RUN: not wasm-ld --fatal-warnings -o %t.wasm %t.main.o %t.ret32.o 2>&1 | FileCheck %s -check-prefix=CHECK-FATAL
55
6; CHECK-WARN: warning: function signature mismatch: ret326; CHECK-WARN: warning: function signature mismatch: ret32
7; CHECK-FATAL: error: function signature mismatch: ret327; CHECK-FATAL: error: function signature mismatch: ret32
deps/lld/test/wasm/function-imports-first.ll+3-8
...@@ -24,25 +24,20 @@ declare i32 @ret32(float) local_unnamed_addr #1...@@ -24,25 +24,20 @@ declare i32 @ret32(float) local_unnamed_addr #1
24; CHECK-NEXT: ParamTypes:24; CHECK-NEXT: ParamTypes:
25; CHECK-NEXT: - F3225; CHECK-NEXT: - F32
26; CHECK: - Type: FUNCTION26; CHECK: - Type: FUNCTION
27; CHECK-NEXT: FunctionTypes: [ 0, 0, 1 ]27; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
28; CHECK: - Type: CODE28; CHECK: - Type: CODE
29; CHECK-NEXT: Functions:29; CHECK-NEXT: Functions:
30; CHECK-NEXT: - Index: 030; CHECK-NEXT: - Index: 0
31; CHECK-NEXT: Locals:31; CHECK-NEXT: Locals:
32; CHECK-NEXT: Body: 0B32; CHECK-NEXT: Body: 43000000001081808080001A0B
33; CHECK-NEXT: - Index: 133; CHECK-NEXT: - Index: 1
34; CHECK-NEXT: Locals:34; CHECK-NEXT: Locals:
35; CHECK-NEXT: Body: 43000000001082808080001A0B
36; CHECK-NEXT: - Index: 2
37; CHECK-NEXT: Locals:
38; CHECK-NEXT: Body: 41000B35; CHECK-NEXT: Body: 41000B
39; CHECK-NEXT: - Type: CUSTOM36; CHECK-NEXT: - Type: CUSTOM
40; CHECK-NEXT: Name: name37; CHECK-NEXT: Name: name
41; CHECK-NEXT: FunctionNames:38; CHECK-NEXT: FunctionNames:
42; CHECK-NEXT: - Index: 039; CHECK-NEXT: - Index: 0
43; CHECK-NEXT: Name: __wasm_call_ctors
44; CHECK-NEXT: - Index: 1
45; CHECK-NEXT: Name: _start40; CHECK-NEXT: Name: _start
46; CHECK-NEXT: - Index: 241; CHECK-NEXT: - Index: 1
47; CHECK-NEXT: Name: ret3242; CHECK-NEXT: Name: ret32
48; CHECK-NEXT: ...43; CHECK-NEXT: ...
deps/lld/test/wasm/function-imports.ll+5-8
...@@ -18,25 +18,22 @@ declare i32 @ret32(float) local_unnamed_addr #1...@@ -18,25 +18,22 @@ declare i32 @ret32(float) local_unnamed_addr #1
18; CHECK: - Type: TYPE18; CHECK: - Type: TYPE
19; CHECK-NEXT: Signatures:19; CHECK-NEXT: Signatures:
20; CHECK-NEXT: - Index: 020; CHECK-NEXT: - Index: 0
21; CHECK-NEXT: ReturnType: NORESULT
22; CHECK-NEXT: ParamTypes:
23; CHECK-NEXT: - Index: 1
24; CHECK-NEXT: ReturnType: I3221; CHECK-NEXT: ReturnType: I32
25; CHECK-NEXT: ParamTypes:22; CHECK-NEXT: ParamTypes:
26; CHECK-NEXT: - F3223; CHECK-NEXT: - F32
24; CHECK-NEXT: - Index: 1
25; CHECK-NEXT: ReturnType: NORESULT
26; CHECK-NEXT: ParamTypes:
27; CHECK-NEXT: - Type: FUNCTION27; CHECK-NEXT: - Type: FUNCTION
28; CHECK-NEXT: FunctionTypes: [ 0, 1, 0 ]28; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
29; CHECK: - Type: CODE29; CHECK: - Type: CODE
30; CHECK-NEXT: Functions:30; CHECK-NEXT: Functions:
31; CHECK: - Index: 031; CHECK: - Index: 0
32; CHECK: - Index: 132; CHECK: - Index: 1
33; CHECK: - Index: 2
34; CHECK: Name: name33; CHECK: Name: name
35; CHECK-NEXT: FunctionNames:34; CHECK-NEXT: FunctionNames:
36; CHECK-NEXT: - Index: 035; CHECK-NEXT: - Index: 0
37; CHECK-NEXT: Name: __wasm_call_ctors
38; CHECK-NEXT: - Index: 1
39; CHECK-NEXT: Name: ret3236; CHECK-NEXT: Name: ret32
40; CHECK-NEXT: - Index: 237; CHECK-NEXT: - Index: 1
41; CHECK-NEXT: Name: _start38; CHECK-NEXT: Name: _start
42; CHECK-NEXT: ...39; CHECK-NEXT: ...
deps/lld/test/wasm/gc-imports.ll+1-3
...@@ -43,10 +43,8 @@ entry:...@@ -43,10 +43,8 @@ entry:
43; CHECK-NEXT: - Index: 043; CHECK-NEXT: - Index: 0
44; CHECK-NEXT: Name: used_undef_function44; CHECK-NEXT: Name: used_undef_function
45; CHECK-NEXT: - Index: 145; CHECK-NEXT: - Index: 1
46; CHECK-NEXT: Name: __wasm_call_ctors
47; CHECK-NEXT: - Index: 2
48; CHECK-NEXT: Name: _start46; CHECK-NEXT: Name: _start
49; CHECK-NEXT: - Index: 347; CHECK-NEXT: - Index: 2
50; CHECK-NEXT: Name: use_undef_global48; CHECK-NEXT: Name: use_undef_global
51; CHECK-NEXT: ...49; CHECK-NEXT: ...
5250
deps/lld/test/wasm/gc-sections.ll+8-10
...@@ -38,10 +38,10 @@ entry:...@@ -38,10 +38,10 @@ entry:
38; CHECK: - Type: TYPE38; CHECK: - Type: TYPE
39; CHECK-NEXT: Signatures:39; CHECK-NEXT: Signatures:
40; CHECK-NEXT: - Index: 040; CHECK-NEXT: - Index: 0
41; CHECK-NEXT: ReturnType: NORESULT41; CHECK-NEXT: ReturnType: I32
42; CHECK-NEXT: ParamTypes:42; CHECK-NEXT: ParamTypes:
43; CHECK-NEXT: - Index: 143; CHECK-NEXT: - Index: 1
44; CHECK-NEXT: ReturnType: I3244; CHECK-NEXT: ReturnType: NORESULT
45; CHECK-NEXT: ParamTypes:45; CHECK-NEXT: ParamTypes:
46; CHECK-NEXT: - Index: 246; CHECK-NEXT: - Index: 2
47; CHECK-NEXT: ReturnType: I6447; CHECK-NEXT: ReturnType: I64
...@@ -66,8 +66,8 @@ entry:...@@ -66,8 +66,8 @@ entry:
66; CHECK: - Type: DATA66; CHECK: - Type: DATA
67; CHECK-NEXT: Segments: 67; CHECK-NEXT: Segments:
68; CHECK-NEXT: - SectionOffset: 768; CHECK-NEXT: - SectionOffset: 7
69; CHECK-NEXT: MemoryIndex: 069; CHECK-NEXT: InitFlags: 0
70; CHECK-NEXT: Offset: 70; CHECK-NEXT: Offset:
71; CHECK-NEXT: Opcode: I32_CONST71; CHECK-NEXT: Opcode: I32_CONST
72; CHECK-NEXT: Value: 102472; CHECK-NEXT: Value: 1024
73; CHECK-NEXT: Content: '02000000'73; CHECK-NEXT: Content: '02000000'
...@@ -75,12 +75,10 @@ entry:...@@ -75,12 +75,10 @@ entry:
75; CHECK-NEXT: Name: name75; CHECK-NEXT: Name: name
76; CHECK-NEXT: FunctionNames:76; CHECK-NEXT: FunctionNames:
77; CHECK-NEXT: - Index: 077; CHECK-NEXT: - Index: 0
78; CHECK-NEXT: Name: __wasm_call_ctors
79; CHECK-NEXT: - Index: 1
80; CHECK-NEXT: Name: used_function78; CHECK-NEXT: Name: used_function
81; CHECK-NEXT: - Index: 279; CHECK-NEXT: - Index: 1
82; CHECK-NEXT: Name: _start80; CHECK-NEXT: Name: _start
83; CHECK-NEXT: - Index: 381; CHECK-NEXT: - Index: 2
84; CHECK-NEXT: Name: use_global82; CHECK-NEXT: Name: use_global
85; CHECK-NEXT: ...83; CHECK-NEXT: ...
8684
...@@ -129,8 +127,8 @@ entry:...@@ -129,8 +127,8 @@ entry:
129; NO-GC: - Type: DATA127; NO-GC: - Type: DATA
130; NO-GC-NEXT: Segments: 128; NO-GC-NEXT: Segments:
131; NO-GC-NEXT: - SectionOffset: 7129; NO-GC-NEXT: - SectionOffset: 7
132; NO-GC-NEXT: MemoryIndex: 0130; NO-GC-NEXT: InitFlags: 0
133; NO-GC-NEXT: Offset: 131; NO-GC-NEXT: Offset:
134; NO-GC-NEXT: Opcode: I32_CONST132; NO-GC-NEXT: Opcode: I32_CONST
135; NO-GC-NEXT: Value: 1024133; NO-GC-NEXT: Value: 1024
136; NO-GC-NEXT: Content: '010000000000000002000000'134; NO-GC-NEXT: Content: '010000000000000002000000'
deps/lld/test/wasm/global-base.test created+71
...@@ -0,0 +1,71 @@
1RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.o
2
3RUN: wasm-ld --export=__global_base --export=__data_end --allow-undefined -o %t.wasm %t.o
4RUN: obj2yaml %t.wasm | FileCheck %s -check-prefix=CHECK-1024
5CHECK-1024: - Type: GLOBAL
6CHECK-1024-NEXT: Globals:
7CHECK-1024-NEXT: - Index: 0
8CHECK-1024-NEXT: Type: I32
9CHECK-1024-NEXT: Mutable: true
10CHECK-1024-NEXT: InitExpr:
11CHECK-1024-NEXT: Opcode: I32_CONST
12CHECK-1024-NEXT: Value: 66560
13CHECK-1024-NEXT: - Index: 1
14CHECK-1024-NEXT: Type: I32
15CHECK-1024-NEXT: Mutable: false
16CHECK-1024-NEXT: InitExpr:
17CHECK-1024-NEXT: Opcode: I32_CONST
18CHECK-1024-NEXT: Value: 1024
19CHECK-1024-NEXT: - Index: 2
20CHECK-1024-NEXT: Type: I32
21CHECK-1024-NEXT: Mutable: false
22CHECK-1024-NEXT: InitExpr:
23CHECK-1024-NEXT: Opcode: I32_CONST
24CHECK-1024-NEXT: Value: 1024
25
26CHECK-1024: - Type: EXPORT
27CHECK-1024-NEXT: Exports:
28CHECK-1024-NEXT: - Name: memory
29CHECK-1024-NEXT: Kind: MEMORY
30CHECK-1024-NEXT: Index: 0
31CHECK-1024-NEXT: - Name: __data_end
32CHECK-1024-NEXT: Kind: GLOBAL
33CHECK-1024-NEXT: Index: 1
34CHECK-1024-NEXT: - Name: __global_base
35CHECK-1024-NEXT: Kind: GLOBAL
36CHECK-1024-NEXT: Index: 2
37
38RUN: wasm-ld --export=__global_base --export=__data_end --allow-undefined --global-base=16777216 -o %t.wasm %t.o
39RUN: obj2yaml %t.wasm | FileCheck %s -check-prefix=CHECK-16777216
40CHECK-16777216: - Type: GLOBAL
41CHECK-16777216-NEXT: Globals:
42CHECK-16777216-NEXT: - Index: 0
43CHECK-16777216-NEXT: Type: I32
44CHECK-16777216-NEXT: Mutable: true
45CHECK-16777216-NEXT: InitExpr:
46CHECK-16777216-NEXT: Opcode: I32_CONST
47CHECK-16777216-NEXT: Value: 16842752
48CHECK-16777216-NEXT: - Index: 1
49CHECK-16777216-NEXT: Type: I32
50CHECK-16777216-NEXT: Mutable: false
51CHECK-16777216-NEXT: InitExpr:
52CHECK-16777216-NEXT: Opcode: I32_CONST
53CHECK-16777216-NEXT: Value: 16777216
54CHECK-16777216-NEXT: - Index: 2
55CHECK-16777216-NEXT: Type: I32
56CHECK-16777216-NEXT: Mutable: false
57CHECK-16777216-NEXT: InitExpr:
58CHECK-16777216-NEXT: Opcode: I32_CONST
59CHECK-16777216-NEXT: Value: 16777216
60
61CHECK-16777216: - Type: EXPORT
62CHECK-16777216-NEXT: Exports:
63CHECK-16777216-NEXT: - Name: memory
64CHECK-16777216-NEXT: Kind: MEMORY
65CHECK-16777216-NEXT: Index: 0
66CHECK-16777216-NEXT: - Name: __data_end
67CHECK-16777216-NEXT: Kind: GLOBAL
68CHECK-16777216-NEXT: Index: 1
69CHECK-16777216-NEXT: - Name: __global_base
70CHECK-16777216-NEXT: Kind: GLOBAL
71CHECK-16777216-NEXT: Index: 2
deps/lld/test/wasm/import-memory.test+2-2
...@@ -32,8 +32,8 @@...@@ -32,8 +32,8 @@
32# CHECK-MAX-NEXT: Maximum: 0x0000000532# CHECK-MAX-NEXT: Maximum: 0x00000005
33# CHECK-MAX-NEXT: - Type:33# CHECK-MAX-NEXT: - Type:
3434
35# RUN: wasm-ld --import-memory --shared-memory --initial-memory=262144 \35# RUN: wasm-ld --import-memory --shared-memory --active-segments \
36# RUN: --max-memory=327680 -o %t.max.wasm %t.start.o36# RUN: --initial-memory=262144 --max-memory=327680 -o %t.max.wasm %t.start.o
37# RUN: obj2yaml %t.max.wasm | FileCheck -check-prefix=CHECK-SHARED %s37# RUN: obj2yaml %t.max.wasm | FileCheck -check-prefix=CHECK-SHARED %s
3838
39# Verify the --shared-memory flag works with imports39# Verify the --shared-memory flag works with imports
deps/lld/test/wasm/init-fini-gc.ll created+48
...@@ -0,0 +1,48 @@
1; RUN: llc -filetype=obj -o %t.o %s
2; RUN: wasm-ld %t.o -o %t.wasm
3; RUN: obj2yaml %t.wasm | FileCheck %s
4
5; RUN: wasm-ld %t.o -o %t.wasm
6; RUN: obj2yaml %t.wasm | FileCheck %s
7
8; RUN: wasm-ld --export=__wasm_call_ctors %t.o -o %t.export.wasm
9; RUN: obj2yaml %t.export.wasm | FileCheck %s -check-prefix=EXPORT
10
11; Test that the __wasm_call_ctor function if not referenced
12
13target triple = "wasm32-unknown-unknown"
14
15define hidden void @_start() {
16entry:
17 ret void
18}
19
20define hidden void @func1() {
21entry:
22 ret void
23}
24
25define hidden void @func2() {
26entry:
27 ret void
28}
29
30define i32 @__cxa_atexit(i32 %func, i32 %arg, i32 %dso_handle) {
31 ret i32 0
32}
33
34@llvm.global_ctors = appending global [1 x { i32, void ()*, i8* }] [
35 { i32, void ()*, i8* } { i32 1, void ()* @func1, i8* null }
36]
37
38@llvm.global_dtors = appending global [1 x { i32, void ()*, i8* }] [
39 { i32, void ()*, i8* } { i32 1, void ()* @func2, i8* null }
40]
41
42; CHECK-NOT: __cxa_atexit
43; CHECK-NOT: __wasm_call_ctors
44
45; EXPORT: __wasm_call_ctors
46; EXPORT: func1
47; EXPORT: func2
48; EXPORT: __cxa_atexit
deps/lld/test/wasm/init-fini.ll+20-198
...@@ -25,6 +25,7 @@ entry:...@@ -25,6 +25,7 @@ entry:
2525
26declare hidden void @externCtor()26declare hidden void @externCtor()
27declare hidden void @externDtor()27declare hidden void @externDtor()
28declare hidden void @__wasm_call_ctors()
2829
29define i32 @__cxa_atexit(i32 %func, i32 %arg, i32 %dso_handle) {30define i32 @__cxa_atexit(i32 %func, i32 %arg, i32 %dso_handle) {
30 ret i32 031 ret i32 0
...@@ -32,6 +33,7 @@ define i32 @__cxa_atexit(i32 %func, i32 %arg, i32 %dso_handle) {...@@ -32,6 +33,7 @@ define i32 @__cxa_atexit(i32 %func, i32 %arg, i32 %dso_handle) {
3233
33define hidden void @_start() {34define hidden void @_start() {
34entry:35entry:
36 call void @__wasm_call_ctors();
35 ret void37 ret void
36}38}
3739
...@@ -75,7 +77,7 @@ entry:...@@ -75,7 +77,7 @@ entry:
75; CHECK-NEXT: Body: 10031004100A100F1012100F10141003100C100F10161001100E0B77; CHECK-NEXT: Body: 10031004100A100F1012100F10141003100C100F10161001100E0B
76; CHECK: - Index: 2278; CHECK: - Index: 22
77; CHECK-NEXT: Locals:79; CHECK-NEXT: Locals:
78; CHECK-NEXT: Body: 024041868080800041004180888080001087808080000D000F0B00000B80; CHECK-NEXT: Body: 02404186808080004100418088808000108780808000450D0000000B0B
79; CHECK-NEXT: - Type: CUSTOM81; CHECK-NEXT: - Type: CUSTOM
80; CHECK-NEXT: Name: name82; CHECK-NEXT: Name: name
81; CHECK-NEXT: FunctionNames:83; CHECK-NEXT: FunctionNames:
...@@ -127,202 +129,22 @@ entry:...@@ -127,202 +129,22 @@ entry:
127; CHECK-NEXT: Name: .Lregister_call_dtors.2002129; CHECK-NEXT: Name: .Lregister_call_dtors.2002
128; CHECK-NEXT: ...130; CHECK-NEXT: ...
129131
130
131; RUN: wasm-ld -r %t.o %t.global-ctor-dtor.o -o %t.reloc.wasm132; RUN: wasm-ld -r %t.o %t.global-ctor-dtor.o -o %t.reloc.wasm
132; RUN: obj2yaml %t.reloc.wasm | FileCheck -check-prefix=RELOC %s133; RUN: llvm-readobj --symbols --sections %t.reloc.wasm | FileCheck -check-prefix=RELOC %s
133134
134; RELOC: SymbolTable:135; RELOC: Name: linking
135; RELOC-NEXT: - Index: 0136; RELOC-NEXT: InitFunctions [
136; RELOC-NEXT: Kind: FUNCTION137; RELOC-NEXT: 0 (priority=101)
137; RELOC-NEXT: Name: func1138; RELOC-NEXT: 1 (priority=101)
138; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]139; RELOC-NEXT: 14 (priority=101)
139; RELOC-NEXT: Function: 2140; RELOC-NEXT: 10 (priority=101)
140; RELOC-NEXT: - Index: 1141; RELOC-NEXT: 20 (priority=101)
141; RELOC-NEXT: Kind: FUNCTION142; RELOC-NEXT: 10 (priority=202)
142; RELOC-NEXT: Name: func2143; RELOC-NEXT: 22 (priority=202)
143; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]144; RELOC-NEXT: 0 (priority=1001)
144; RELOC-NEXT: Function: 3145; RELOC-NEXT: 16 (priority=1001)
145; RELOC-NEXT: - Index: 2146; RELOC-NEXT: 10 (priority=2002)
146; RELOC-NEXT: Kind: FUNCTION147; RELOC-NEXT: 24 (priority=2002)
147; RELOC-NEXT: Name: func3148; RELOC-NEXT: 9 (priority=4000)
148; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]149; RELOC-NEXT: 18 (priority=4000)
149; RELOC-NEXT: Function: 4150; RELOC-NEXT: ]
150; RELOC-NEXT: - Index: 3
151; RELOC-NEXT: Kind: FUNCTION
152; RELOC-NEXT: Name: func4
153; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
154; RELOC-NEXT: Function: 5
155; RELOC-NEXT: - Index: 4
156; RELOC-NEXT: Kind: FUNCTION
157; RELOC-NEXT: Name: __cxa_atexit
158; RELOC-NEXT: Flags: [ ]
159; RELOC-NEXT: Function: 6
160; RELOC-NEXT: - Index: 5
161; RELOC-NEXT: Kind: FUNCTION
162; RELOC-NEXT: Name: _start
163; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
164; RELOC-NEXT: Function: 7
165; RELOC-NEXT: - Index: 6
166; RELOC-NEXT: Kind: DATA
167; RELOC-NEXT: Name: __dso_handle
168; RELOC-NEXT: Flags: [ BINDING_WEAK, VISIBILITY_HIDDEN, UNDEFINED ]
169; RELOC-NEXT: - Index: 7
170; RELOC-NEXT: Kind: FUNCTION
171; RELOC-NEXT: Name: externDtor
172; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN, UNDEFINED ]
173; RELOC-NEXT: Function: 0
174; RELOC-NEXT: - Index: 8
175; RELOC-NEXT: Kind: FUNCTION
176; RELOC-NEXT: Name: externCtor
177; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN, UNDEFINED ]
178; RELOC-NEXT: Function: 1
179; RELOC-NEXT: - Index: 9
180; RELOC-NEXT: Kind: FUNCTION
181; RELOC-NEXT: Name: myctor
182; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
183; RELOC-NEXT: Function: 14
184; RELOC-NEXT: - Index: 10
185; RELOC-NEXT: Kind: FUNCTION
186; RELOC-NEXT: Name: mydtor
187; RELOC-NEXT: Flags: [ VISIBILITY_HIDDEN ]
188; RELOC-NEXT: Function: 15
189; RELOC-NEXT: - Index: 11
190; RELOC-NEXT: Kind: GLOBAL
191; RELOC-NEXT: Name: __stack_pointer
192; RELOC-NEXT: Flags: [ UNDEFINED ]
193; RELOC-NEXT: Global: 0
194; RELOC-NEXT: - Index: 12
195; RELOC-NEXT: Kind: FUNCTION
196; RELOC-NEXT: Name: .Lcall_dtors.101
197; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
198; RELOC-NEXT: Function: 8
199; RELOC-NEXT: - Index: 13
200; RELOC-NEXT: Kind: FUNCTION
201; RELOC-NEXT: Name: .Lregister_call_dtors.101
202; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
203; RELOC-NEXT: Function: 9
204; RELOC-NEXT: - Index: 14
205; RELOC-NEXT: Kind: FUNCTION
206; RELOC-NEXT: Name: .Lcall_dtors.1001
207; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
208; RELOC-NEXT: Function: 10
209; RELOC-NEXT: - Index: 15
210; RELOC-NEXT: Kind: FUNCTION
211; RELOC-NEXT: Name: .Lregister_call_dtors.1001
212; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
213; RELOC-NEXT: Function: 11
214; RELOC-NEXT: - Index: 16
215; RELOC-NEXT: Kind: FUNCTION
216; RELOC-NEXT: Name: .Lcall_dtors.4000
217; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
218; RELOC-NEXT: Function: 12
219; RELOC-NEXT: - Index: 17
220; RELOC-NEXT: Kind: FUNCTION
221; RELOC-NEXT: Name: .Lregister_call_dtors.4000
222; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
223; RELOC-NEXT: Function: 13
224; RELOC-NEXT: - Index: 18
225; RELOC-NEXT: Kind: FUNCTION
226; RELOC-NEXT: Name: .Lcall_dtors.101
227; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
228; RELOC-NEXT: Function: 16
229; RELOC-NEXT: - Index: 19
230; RELOC-NEXT: Kind: FUNCTION
231; RELOC-NEXT: Name: .Lregister_call_dtors.101
232; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
233; RELOC-NEXT: Function: 17
234; RELOC-NEXT: - Index: 20
235; RELOC-NEXT: Kind: FUNCTION
236; RELOC-NEXT: Name: .Lcall_dtors.202
237; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
238; RELOC-NEXT: Function: 18
239; RELOC-NEXT: - Index: 21
240; RELOC-NEXT: Kind: FUNCTION
241; RELOC-NEXT: Name: .Lregister_call_dtors.202
242; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
243; RELOC-NEXT: Function: 19
244; RELOC-NEXT: - Index: 22
245; RELOC-NEXT: Kind: FUNCTION
246; RELOC-NEXT: Name: .Lcall_dtors.2002
247; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
248; RELOC-NEXT: Function: 20
249; RELOC-NEXT: - Index: 23
250; RELOC-NEXT: Kind: FUNCTION
251; RELOC-NEXT: Name: .Lregister_call_dtors.2002
252; RELOC-NEXT: Flags: [ BINDING_LOCAL ]
253; RELOC-NEXT: Function: 21
254; RELOC-NEXT: InitFunctions:
255; RELOC-NEXT: - Priority: 101
256; RELOC-NEXT: Symbol: 0
257; RELOC-NEXT: - Priority: 101
258; RELOC-NEXT: Symbol: 1
259; RELOC-NEXT: - Priority: 101
260; RELOC-NEXT: Symbol: 13
261; RELOC-NEXT: - Priority: 101
262; RELOC-NEXT: Symbol: 9
263; RELOC-NEXT: - Priority: 101
264; RELOC-NEXT: Symbol: 19
265; RELOC-NEXT: - Priority: 202
266; RELOC-NEXT: Symbol: 9
267; RELOC-NEXT: - Priority: 202
268; RELOC-NEXT: Symbol: 21
269; RELOC-NEXT: - Priority: 1001
270; RELOC-NEXT: Symbol: 0
271; RELOC-NEXT: - Priority: 1001
272; RELOC-NEXT: Symbol: 15
273; RELOC-NEXT: - Priority: 2002
274; RELOC-NEXT: Symbol: 9
275; RELOC-NEXT: - Priority: 2002
276; RELOC-NEXT: Symbol: 23
277; RELOC-NEXT: - Priority: 4000
278; RELOC-NEXT: Symbol: 8
279; RELOC-NEXT: - Priority: 4000
280; RELOC-NEXT: Symbol: 17
281; RELOC-NEXT: - Type: CUSTOM
282; RELOC-NEXT: Name: name
283; RELOC-NEXT: FunctionNames:
284; RELOC-NEXT: - Index: 0
285; RELOC-NEXT: Name: externDtor
286; RELOC-NEXT: - Index: 1
287; RELOC-NEXT: Name: externCtor
288; RELOC-NEXT: - Index: 2
289; RELOC-NEXT: Name: func1
290; RELOC-NEXT: - Index: 3
291; RELOC-NEXT: Name: func2
292; RELOC-NEXT: - Index: 4
293; RELOC-NEXT: Name: func3
294; RELOC-NEXT: - Index: 5
295; RELOC-NEXT: Name: func4
296; RELOC-NEXT: - Index: 6
297; RELOC-NEXT: Name: __cxa_atexit
298; RELOC-NEXT: - Index: 7
299; RELOC-NEXT: Name: _start
300; RELOC-NEXT: - Index: 8
301; RELOC-NEXT: Name: .Lcall_dtors.101
302; RELOC-NEXT: - Index: 9
303; RELOC-NEXT: Name: .Lregister_call_dtors.101
304; RELOC-NEXT: - Index: 10
305; RELOC-NEXT: Name: .Lcall_dtors.1001
306; RELOC-NEXT: - Index: 11
307; RELOC-NEXT: Name: .Lregister_call_dtors.1001
308; RELOC-NEXT: - Index: 12
309; RELOC-NEXT: Name: .Lcall_dtors.4000
310; RELOC-NEXT: - Index: 13
311; RELOC-NEXT: Name: .Lregister_call_dtors.4000
312; RELOC-NEXT: - Index: 14
313; RELOC-NEXT: Name: myctor
314; RELOC-NEXT: - Index: 15
315; RELOC-NEXT: Name: mydtor
316; RELOC-NEXT: - Index: 16
317; RELOC-NEXT: Name: .Lcall_dtors.101
318; RELOC-NEXT: - Index: 17
319; RELOC-NEXT: Name: .Lregister_call_dtors.101
320; RELOC-NEXT: - Index: 18
321; RELOC-NEXT: Name: .Lcall_dtors.202
322; RELOC-NEXT: - Index: 19
323; RELOC-NEXT: Name: .Lregister_call_dtors.202
324; RELOC-NEXT: - Index: 20
325; RELOC-NEXT: Name: .Lcall_dtors.2002
326; RELOC-NEXT: - Index: 21
327; RELOC-NEXT: Name: .Lregister_call_dtors.2002
328; RELOC-NEXT: ...
deps/lld/test/wasm/large-memory.test created+5
...@@ -0,0 +1,5 @@
1RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.o
2
3; Verify we can parse large integers such as when we ask for 2G of total
4; memory.
5RUN: wasm-ld %t.o -o %t.wasm --max-memory=2147483648
deps/lld/test/wasm/lit.local.cfg+1-1
...@@ -1,4 +1,4 @@...@@ -1,4 +1,4 @@
1if 'wasm' not in config.available_features:1if 'wasm' not in config.available_features:
2 config.unsupported = True2 config.unsupported = True
33
4config.suffixes = ['.test', '.yaml', '.ll']4config.suffixes = ['.test', '.yaml', '.ll', '.s']
deps/lld/test/wasm/local-symbols.ll+9-32
...@@ -27,13 +27,13 @@ entry:...@@ -27,13 +27,13 @@ entry:
27; CHECK-NEXT: - Type: TYPE27; CHECK-NEXT: - Type: TYPE
28; CHECK-NEXT: Signatures:28; CHECK-NEXT: Signatures:
29; CHECK-NEXT: - Index: 029; CHECK-NEXT: - Index: 0
30; CHECK-NEXT: ReturnType: NORESULT30; CHECK-NEXT: ReturnType: I32
31; CHECK-NEXT: ParamTypes:31; CHECK-NEXT: ParamTypes:
32; CHECK-NEXT: - Index: 132; CHECK-NEXT: - Index: 1
33; CHECK-NEXT: ReturnType: I3233; CHECK-NEXT: ReturnType: NORESULT
34; CHECK-NEXT: ParamTypes:34; CHECK-NEXT: ParamTypes:
35; CHECK-NEXT: - Type: FUNCTION35; CHECK-NEXT: - Type: FUNCTION
36; CHECK-NEXT: FunctionTypes: [ 0, 1, 0 ]36; CHECK-NEXT: FunctionTypes: [ 0, 1 ]
37; CHECK-NEXT: - Type: TABLE37; CHECK-NEXT: - Type: TABLE
38; CHECK-NEXT: Tables:38; CHECK-NEXT: Tables:
39; CHECK-NEXT: - ElemType: FUNCREF39; CHECK-NEXT: - ElemType: FUNCREF
...@@ -57,51 +57,30 @@ entry:...@@ -57,51 +57,30 @@ entry:
57; CHECK-NEXT: Mutable: false57; CHECK-NEXT: Mutable: false
58; CHECK-NEXT: InitExpr:58; CHECK-NEXT: InitExpr:
59; CHECK-NEXT: Opcode: I32_CONST59; CHECK-NEXT: Opcode: I32_CONST
60; CHECK-NEXT: Value: 66576
61; CHECK-NEXT: - Index: 2
62; CHECK-NEXT: Type: I32
63; CHECK-NEXT: Mutable: false
64; CHECK-NEXT: InitExpr:
65; CHECK-NEXT: Opcode: I32_CONST
66; CHECK-NEXT: Value: 1032
67; CHECK-NEXT: - Index: 3
68; CHECK-NEXT: Type: I32
69; CHECK-NEXT: Mutable: false
70; CHECK-NEXT: InitExpr:
71; CHECK-NEXT: Opcode: I32_CONST
72; CHECK-NEXT: Value: 102460; CHECK-NEXT: Value: 1024
73; CHECK-NEXT: - Type: EXPORT61; CHECK-NEXT: - Type: EXPORT
74; CHECK-NEXT: Exports:62; CHECK-NEXT: Exports:
75; CHECK-NEXT: - Name: memory63; CHECK-NEXT: - Name: memory
76; CHECK-NEXT: Kind: MEMORY64; CHECK-NEXT: Kind: MEMORY
77; CHECK-NEXT: Index: 065; CHECK-NEXT: Index: 0
78; CHECK-NEXT: - Name: __heap_base
79; CHECK-NEXT: Kind: GLOBAL
80; CHECK-NEXT: Index: 1
81; CHECK-NEXT: - Name: __data_end
82; CHECK-NEXT: Kind: GLOBAL
83; CHECK-NEXT: Index: 2
84; CHECK-NEXT: - Name: _start66; CHECK-NEXT: - Name: _start
85; CHECK-NEXT: Kind: FUNCTION67; CHECK-NEXT: Kind: FUNCTION
86; CHECK-NEXT: Index: 268; CHECK-NEXT: Index: 1
87; CHECK-NEXT: - Name: foo69; CHECK-NEXT: - Name: foo
88; CHECK-NEXT: Kind: GLOBAL70; CHECK-NEXT: Kind: GLOBAL
89; CHECK-NEXT: Index: 371; CHECK-NEXT: Index: 1
90; CHECK-NEXT: - Type: CODE72; CHECK-NEXT: - Type: CODE
91; CHECK-NEXT: Functions:73; CHECK-NEXT: Functions:
92; CHECK-NEXT: - Index: 074; CHECK-NEXT: - Index: 0
93; CHECK-NEXT: Locals:75; CHECK-NEXT: Locals:
94; CHECK-NEXT: Body: 0B
95; CHECK-NEXT: - Index: 1
96; CHECK-NEXT: Locals:
97; CHECK-NEXT: Body: 4100280284888080000B76; CHECK-NEXT: Body: 4100280284888080000B
98; CHECK-NEXT: - Index: 277; CHECK-NEXT: - Index: 1
99; CHECK-NEXT: Locals:78; CHECK-NEXT: Locals:
100; CHECK-NEXT: Body: 1081808080001A0B79; CHECK-NEXT: Body: 1080808080001A0B
101; CHECK-NEXT: - Type: DATA80; CHECK-NEXT: - Type: DATA
102; CHECK-NEXT: Segments:81; CHECK-NEXT: Segments:
103; CHECK-NEXT: - SectionOffset: 782; CHECK-NEXT: - SectionOffset: 7
104; CHECK-NEXT: MemoryIndex: 083; CHECK-NEXT: InitFlags: 0
105; CHECK-NEXT: Offset:84; CHECK-NEXT: Offset:
106; CHECK-NEXT: Opcode: I32_CONST85; CHECK-NEXT: Opcode: I32_CONST
107; CHECK-NEXT: Value: 102486; CHECK-NEXT: Value: 1024
...@@ -110,9 +89,7 @@ entry:...@@ -110,9 +89,7 @@ entry:
110; CHECK-NEXT: Name: name89; CHECK-NEXT: Name: name
111; CHECK-NEXT: FunctionNames:90; CHECK-NEXT: FunctionNames:
112; CHECK-NEXT: - Index: 091; CHECK-NEXT: - Index: 0
113; CHECK-NEXT: Name: __wasm_call_ctors
114; CHECK-NEXT: - Index: 1
115; CHECK-NEXT: Name: baz92; CHECK-NEXT: Name: baz
116; CHECK-NEXT: - Index: 293; CHECK-NEXT: - Index: 1
117; CHECK-NEXT: Name: _start94; CHECK-NEXT: Name: _start
118; CHECK-NEXT: ...95; CHECK-NEXT: ...
deps/lld/test/wasm/locals-duplicate.test+66-92
...@@ -10,14 +10,11 @@...@@ -10,14 +10,11 @@
10; CHECK-NEXT: - Type: TYPE10; CHECK-NEXT: - Type: TYPE
11; CHECK-NEXT: Signatures:11; CHECK-NEXT: Signatures:
12; CHECK-NEXT: - Index: 012; CHECK-NEXT: - Index: 0
13; CHECK-NEXT: ReturnType: NORESULT
14; CHECK-NEXT: ParamTypes:
15; CHECK-NEXT: - Index: 1
16; CHECK-NEXT: ReturnType: I3213; CHECK-NEXT: ReturnType: I32
17; CHECK-NEXT: ParamTypes:14; CHECK-NEXT: ParamTypes:
18; CHECK-NEXT: - Type: FUNCTION15; CHECK-NEXT: - Type: FUNCTION
19; CHECK-NEXT: FunctionTypes: [ 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,16; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
20; CHECK-NEXT: 1, 1, 1 ]17; CHECK-NEXT: 0, 0 ]
21; CHECK-NEXT: - Type: TABLE18; CHECK-NEXT: - Type: TABLE
22; CHECK-NEXT: Tables:19; CHECK-NEXT: Tables:
23; CHECK-NEXT: - ElemType: FUNCREF20; CHECK-NEXT: - ElemType: FUNCREF
...@@ -41,20 +38,8 @@...@@ -41,20 +38,8 @@
41; CHECK-NEXT: Mutable: false38; CHECK-NEXT: Mutable: false
42; CHECK-NEXT: InitExpr:39; CHECK-NEXT: InitExpr:
43; CHECK-NEXT: Opcode: I32_CONST40; CHECK-NEXT: Opcode: I32_CONST
44; CHECK-NEXT: Value: 66592
45; CHECK-NEXT: - Index: 2
46; CHECK-NEXT: Type: I32
47; CHECK-NEXT: Mutable: false
48; CHECK-NEXT: InitExpr:
49; CHECK-NEXT: Opcode: I32_CONST
50; CHECK-NEXT: Value: 1048
51; CHECK-NEXT: - Index: 3
52; CHECK-NEXT: Type: I32
53; CHECK-NEXT: Mutable: false
54; CHECK-NEXT: InitExpr:
55; CHECK-NEXT: Opcode: I32_CONST
56; CHECK-NEXT: Value: 102841; CHECK-NEXT: Value: 1028
57; CHECK-NEXT: - Index: 442; CHECK-NEXT: - Index: 2
58; CHECK-NEXT: Type: I3243; CHECK-NEXT: Type: I32
59; CHECK-NEXT: Mutable: false44; CHECK-NEXT: Mutable: false
60; CHECK-NEXT: InitExpr:45; CHECK-NEXT: InitExpr:
...@@ -65,71 +50,65 @@...@@ -65,71 +50,65 @@
65; CHECK-NEXT: - Name: memory50; CHECK-NEXT: - Name: memory
66; CHECK-NEXT: Kind: MEMORY51; CHECK-NEXT: Kind: MEMORY
67; CHECK-NEXT: Index: 052; CHECK-NEXT: Index: 0
68; CHECK-NEXT: - Name: __heap_base
69; CHECK-NEXT: Kind: GLOBAL
70; CHECK-NEXT: Index: 1
71; CHECK-NEXT: - Name: __data_end
72; CHECK-NEXT: Kind: GLOBAL
73; CHECK-NEXT: Index: 2
74; CHECK-NEXT: - Name: colliding_func253; CHECK-NEXT: - Name: colliding_func2
75; CHECK-NEXT: Kind: FUNCTION54; CHECK-NEXT: Kind: FUNCTION
76; CHECK-NEXT: Index: 255; CHECK-NEXT: Index: 1
77; CHECK-NEXT: - Name: get_global1A56; CHECK-NEXT: - Name: get_global1A
78; CHECK-NEXT: Kind: FUNCTION57; CHECK-NEXT: Kind: FUNCTION
79; CHECK-NEXT: Index: 458; CHECK-NEXT: Index: 3
80; CHECK-NEXT: - Name: get_global2A59; CHECK-NEXT: - Name: get_global2A
81; CHECK-NEXT: Kind: FUNCTION60; CHECK-NEXT: Kind: FUNCTION
82; CHECK-NEXT: Index: 561; CHECK-NEXT: Index: 4
83; CHECK-NEXT: - Name: colliding_global262; CHECK-NEXT: - Name: colliding_global2
84; CHECK-NEXT: Kind: GLOBAL63; CHECK-NEXT: Kind: GLOBAL
85; CHECK-NEXT: Index: 364; CHECK-NEXT: Index: 1
86; CHECK-NEXT: - Name: get_global3A65; CHECK-NEXT: - Name: get_global3A
87; CHECK-NEXT: Kind: FUNCTION66; CHECK-NEXT: Kind: FUNCTION
88; CHECK-NEXT: Index: 667; CHECK-NEXT: Index: 5
89; CHECK-NEXT: - Name: get_func1A68; CHECK-NEXT: - Name: get_func1A
90; CHECK-NEXT: Kind: FUNCTION69; CHECK-NEXT: Kind: FUNCTION
91; CHECK-NEXT: Index: 770; CHECK-NEXT: Index: 6
92; CHECK-NEXT: - Name: get_func2A71; CHECK-NEXT: - Name: get_func2A
93; CHECK-NEXT: Kind: FUNCTION72; CHECK-NEXT: Kind: FUNCTION
94; CHECK-NEXT: Index: 873; CHECK-NEXT: Index: 7
95; CHECK-NEXT: - Name: get_func3A74; CHECK-NEXT: - Name: get_func3A
96; CHECK-NEXT: Kind: FUNCTION75; CHECK-NEXT: Kind: FUNCTION
97; CHECK-NEXT: Index: 976; CHECK-NEXT: Index: 8
98; CHECK-NEXT: - Name: colliding_func177; CHECK-NEXT: - Name: colliding_func1
99; CHECK-NEXT: Kind: FUNCTION78; CHECK-NEXT: Kind: FUNCTION
100; CHECK-NEXT: Index: 1079; CHECK-NEXT: Index: 9
101; CHECK-NEXT: - Name: get_global1B80; CHECK-NEXT: - Name: get_global1B
102; CHECK-NEXT: Kind: FUNCTION81; CHECK-NEXT: Kind: FUNCTION
103; CHECK-NEXT: Index: 1382; CHECK-NEXT: Index: 12
104; CHECK-NEXT: - Name: colliding_global183; CHECK-NEXT: - Name: colliding_global1
105; CHECK-NEXT: Kind: GLOBAL84; CHECK-NEXT: Kind: GLOBAL
106; CHECK-NEXT: Index: 485; CHECK-NEXT: Index: 2
107; CHECK-NEXT: - Name: get_global2B86; CHECK-NEXT: - Name: get_global2B
108; CHECK-NEXT: Kind: FUNCTION87; CHECK-NEXT: Kind: FUNCTION
109; CHECK-NEXT: Index: 1488; CHECK-NEXT: Index: 13
110; CHECK-NEXT: - Name: get_global3B89; CHECK-NEXT: - Name: get_global3B
111; CHECK-NEXT: Kind: FUNCTION90; CHECK-NEXT: Kind: FUNCTION
112; CHECK-NEXT: Index: 1591; CHECK-NEXT: Index: 14
113; CHECK-NEXT: - Name: get_func1B92; CHECK-NEXT: - Name: get_func1B
114; CHECK-NEXT: Kind: FUNCTION93; CHECK-NEXT: Kind: FUNCTION
115; CHECK-NEXT: Index: 1694; CHECK-NEXT: Index: 15
116; CHECK-NEXT: - Name: get_func2B95; CHECK-NEXT: - Name: get_func2B
117; CHECK-NEXT: Kind: FUNCTION96; CHECK-NEXT: Kind: FUNCTION
118; CHECK-NEXT: Index: 1797; CHECK-NEXT: Index: 16
119; CHECK-NEXT: - Name: get_func3B98; CHECK-NEXT: - Name: get_func3B
120; CHECK-NEXT: Kind: FUNCTION99; CHECK-NEXT: Kind: FUNCTION
121; CHECK-NEXT: Index: 18100; CHECK-NEXT: Index: 17
122; CHECK-NEXT: - Type: ELEM101; CHECK-NEXT: - Type: ELEM
123; CHECK-NEXT: Segments:102; CHECK-NEXT: Segments:
124; CHECK-NEXT: - Offset:103; CHECK-NEXT: - Offset:
125; CHECK-NEXT: Opcode: I32_CONST104; CHECK-NEXT: Opcode: I32_CONST
126; CHECK-NEXT: Value: 1105; CHECK-NEXT: Value: 1
127; CHECK-NEXT: Functions: [ 1, 2, 3, 10, 11, 12 ]106; CHECK-NEXT: Functions: [ 0, 1, 2, 9, 10, 11 ]
128; CHECK-NEXT: - Type: CODE107; CHECK-NEXT: - Type: CODE
129; CHECK-NEXT: Functions:108; CHECK-NEXT: Functions:
130; CHECK-NEXT: - Index: 0109; CHECK-NEXT: - Index: 0
131; CHECK-NEXT: Locals:110; CHECK-NEXT: Locals:
132; CHECK-NEXT: Body: 0B111; CHECK-NEXT: Body: 41020B
133; CHECK-NEXT: - Index: 1112; CHECK-NEXT: - Index: 1
134; CHECK-NEXT: Locals:113; CHECK-NEXT: Locals:
135; CHECK-NEXT: Body: 41020B114; CHECK-NEXT: Body: 41020B
...@@ -138,25 +117,25 @@...@@ -138,25 +117,25 @@
138; CHECK-NEXT: Body: 41020B117; CHECK-NEXT: Body: 41020B
139; CHECK-NEXT: - Index: 3118; CHECK-NEXT: - Index: 3
140; CHECK-NEXT: Locals:119; CHECK-NEXT: Locals:
141; CHECK-NEXT: Body: 41020B120; CHECK-NEXT: Body: 4180888080000B
142; CHECK-NEXT: - Index: 4121; CHECK-NEXT: - Index: 4
143; CHECK-NEXT: Locals:122; CHECK-NEXT: Locals:
144; CHECK-NEXT: Body: 4180888080000B123; CHECK-NEXT: Body: 4184888080000B
145; CHECK-NEXT: - Index: 5124; CHECK-NEXT: - Index: 5
146; CHECK-NEXT: Locals:125; CHECK-NEXT: Locals:
147; CHECK-NEXT: Body: 4184888080000B126; CHECK-NEXT: Body: 4188888080000B
148; CHECK-NEXT: - Index: 6127; CHECK-NEXT: - Index: 6
149; CHECK-NEXT: Locals:128; CHECK-NEXT: Locals:
150; CHECK-NEXT: Body: 4188888080000B129; CHECK-NEXT: Body: 4181808080000B
151; CHECK-NEXT: - Index: 7130; CHECK-NEXT: - Index: 7
152; CHECK-NEXT: Locals:131; CHECK-NEXT: Locals:
153; CHECK-NEXT: Body: 4181808080000B132; CHECK-NEXT: Body: 4182808080000B
154; CHECK-NEXT: - Index: 8133; CHECK-NEXT: - Index: 8
155; CHECK-NEXT: Locals:134; CHECK-NEXT: Locals:
156; CHECK-NEXT: Body: 4182808080000B135; CHECK-NEXT: Body: 4183808080000B
157; CHECK-NEXT: - Index: 9136; CHECK-NEXT: - Index: 9
158; CHECK-NEXT: Locals:137; CHECK-NEXT: Locals:
159; CHECK-NEXT: Body: 4183808080000B138; CHECK-NEXT: Body: 41020B
160; CHECK-NEXT: - Index: 10139; CHECK-NEXT: - Index: 10
161; CHECK-NEXT: Locals:140; CHECK-NEXT: Locals:
162; CHECK-NEXT: Body: 41020B141; CHECK-NEXT: Body: 41020B
...@@ -165,29 +144,26 @@...@@ -165,29 +144,26 @@
165; CHECK-NEXT: Body: 41020B144; CHECK-NEXT: Body: 41020B
166; CHECK-NEXT: - Index: 12145; CHECK-NEXT: - Index: 12
167; CHECK-NEXT: Locals:146; CHECK-NEXT: Locals:
168; CHECK-NEXT: Body: 41020B
169; CHECK-NEXT: - Index: 13
170; CHECK-NEXT: Locals:
171; CHECK-NEXT: Body: 418C888080000B147; CHECK-NEXT: Body: 418C888080000B
172; CHECK-NEXT: - Index: 14148; CHECK-NEXT: - Index: 13
173; CHECK-NEXT: Locals:149; CHECK-NEXT: Locals:
174; CHECK-NEXT: Body: 4190888080000B150; CHECK-NEXT: Body: 4190888080000B
175; CHECK-NEXT: - Index: 15151; CHECK-NEXT: - Index: 14
176; CHECK-NEXT: Locals:152; CHECK-NEXT: Locals:
177; CHECK-NEXT: Body: 4194888080000B153; CHECK-NEXT: Body: 4194888080000B
178; CHECK-NEXT: - Index: 16154; CHECK-NEXT: - Index: 15
179; CHECK-NEXT: Locals:155; CHECK-NEXT: Locals:
180; CHECK-NEXT: Body: 4184808080000B156; CHECK-NEXT: Body: 4184808080000B
181; CHECK-NEXT: - Index: 17157; CHECK-NEXT: - Index: 16
182; CHECK-NEXT: Locals:158; CHECK-NEXT: Locals:
183; CHECK-NEXT: Body: 4185808080000B159; CHECK-NEXT: Body: 4185808080000B
184; CHECK-NEXT: - Index: 18160; CHECK-NEXT: - Index: 17
185; CHECK-NEXT: Locals:161; CHECK-NEXT: Locals:
186; CHECK-NEXT: Body: 4186808080000B162; CHECK-NEXT: Body: 4186808080000B
187; CHECK-NEXT: - Type: DATA163; CHECK-NEXT: - Type: DATA
188; CHECK-NEXT: Segments:164; CHECK-NEXT: Segments:
189; CHECK-NEXT: - SectionOffset: 7165; CHECK-NEXT: - SectionOffset: 7
190; CHECK-NEXT: MemoryIndex: 0166; CHECK-NEXT: InitFlags: 0
191; CHECK-NEXT: Offset:167; CHECK-NEXT: Offset:
192; CHECK-NEXT: Opcode: I32_CONST168; CHECK-NEXT: Opcode: I32_CONST
193; CHECK-NEXT: Value: 1024169; CHECK-NEXT: Value: 1024
...@@ -196,42 +172,40 @@...@@ -196,42 +172,40 @@
196; CHECK-NEXT: Name: name172; CHECK-NEXT: Name: name
197; CHECK-NEXT: FunctionNames:173; CHECK-NEXT: FunctionNames:
198; CHECK-NEXT: - Index: 0174; CHECK-NEXT: - Index: 0
199; CHECK-NEXT: Name: __wasm_call_ctors
200; CHECK-NEXT: - Index: 1
201; CHECK-NEXT: Name: colliding_func1175; CHECK-NEXT: Name: colliding_func1
202; CHECK-NEXT: - Index: 2176; CHECK-NEXT: - Index: 1
203; CHECK-NEXT: Name: colliding_func2177; CHECK-NEXT: Name: colliding_func2
204; CHECK-NEXT: - Index: 3178; CHECK-NEXT: - Index: 2
205; CHECK-NEXT: Name: colliding_func3179; CHECK-NEXT: Name: colliding_func3
206; CHECK-NEXT: - Index: 4180; CHECK-NEXT: - Index: 3
207; CHECK-NEXT: Name: get_global1A181; CHECK-NEXT: Name: get_global1A
208; CHECK-NEXT: - Index: 5182; CHECK-NEXT: - Index: 4
209; CHECK-NEXT: Name: get_global2A183; CHECK-NEXT: Name: get_global2A
210; CHECK-NEXT: - Index: 6184; CHECK-NEXT: - Index: 5
211; CHECK-NEXT: Name: get_global3A185; CHECK-NEXT: Name: get_global3A
212; CHECK-NEXT: - Index: 7186; CHECK-NEXT: - Index: 6
213; CHECK-NEXT: Name: get_func1A187; CHECK-NEXT: Name: get_func1A
214; CHECK-NEXT: - Index: 8188; CHECK-NEXT: - Index: 7
215; CHECK-NEXT: Name: get_func2A189; CHECK-NEXT: Name: get_func2A
216; CHECK-NEXT: - Index: 9190; CHECK-NEXT: - Index: 8
217; CHECK-NEXT: Name: get_func3A191; CHECK-NEXT: Name: get_func3A
218; CHECK-NEXT: - Index: 10192; CHECK-NEXT: - Index: 9
219; CHECK-NEXT: Name: colliding_func1193; CHECK-NEXT: Name: colliding_func1
220; CHECK-NEXT: - Index: 11194; CHECK-NEXT: - Index: 10
221; CHECK-NEXT: Name: colliding_func2195; CHECK-NEXT: Name: colliding_func2
222; CHECK-NEXT: - Index: 12196; CHECK-NEXT: - Index: 11
223; CHECK-NEXT: Name: colliding_func3197; CHECK-NEXT: Name: colliding_func3
224; CHECK-NEXT: - Index: 13198; CHECK-NEXT: - Index: 12
225; CHECK-NEXT: Name: get_global1B199; CHECK-NEXT: Name: get_global1B
226; CHECK-NEXT: - Index: 14200; CHECK-NEXT: - Index: 13
227; CHECK-NEXT: Name: get_global2B201; CHECK-NEXT: Name: get_global2B
228; CHECK-NEXT: - Index: 15202; CHECK-NEXT: - Index: 14
229; CHECK-NEXT: Name: get_global3B203; CHECK-NEXT: Name: get_global3B
230; CHECK-NEXT: - Index: 16204; CHECK-NEXT: - Index: 15
231; CHECK-NEXT: Name: get_func1B205; CHECK-NEXT: Name: get_func1B
232; CHECK-NEXT: - Index: 17206; CHECK-NEXT: - Index: 16
233; CHECK-NEXT: Name: get_func2B207; CHECK-NEXT: Name: get_func2B
234; CHECK-NEXT: - Index: 18208; CHECK-NEXT: - Index: 17
235; CHECK-NEXT: Name: get_func3B209; CHECK-NEXT: Name: get_func3B
236; CHECK-NEXT: ...210; CHECK-NEXT: ...
237211
...@@ -269,40 +243,40 @@...@@ -269,40 +243,40 @@
269; RELOC-NEXT: Functions: [ 0, 1, 2, 9, 10, 11 ]243; RELOC-NEXT: Functions: [ 0, 1, 2, 9, 10, 11 ]
270; RELOC-NEXT: - Type: CODE244; RELOC-NEXT: - Type: CODE
271; RELOC-NEXT: Relocations:245; RELOC-NEXT: Relocations:
272; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB246; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
273; RELOC-NEXT: Index: 18247; RELOC-NEXT: Index: 18
274; RELOC-NEXT: Offset: 0x00000013248; RELOC-NEXT: Offset: 0x00000013
275; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB249; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
276; RELOC-NEXT: Index: 3250; RELOC-NEXT: Index: 3
277; RELOC-NEXT: Offset: 0x0000001C251; RELOC-NEXT: Offset: 0x0000001C
278; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB252; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
279; RELOC-NEXT: Index: 19253; RELOC-NEXT: Index: 19
280; RELOC-NEXT: Offset: 0x00000025254; RELOC-NEXT: Offset: 0x00000025
281; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB255; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
282; RELOC-NEXT: Index: 16256; RELOC-NEXT: Index: 16
283; RELOC-NEXT: Offset: 0x0000002E257; RELOC-NEXT: Offset: 0x0000002E
284; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB258; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
285; RELOC-NEXT: Index: 0259; RELOC-NEXT: Index: 0
286; RELOC-NEXT: Offset: 0x00000037260; RELOC-NEXT: Offset: 0x00000037
287; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB261; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
288; RELOC-NEXT: Index: 17262; RELOC-NEXT: Index: 17
289; RELOC-NEXT: Offset: 0x00000040263; RELOC-NEXT: Offset: 0x00000040
290; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB264; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
291; RELOC-NEXT: Index: 10265; RELOC-NEXT: Index: 10
292; RELOC-NEXT: Offset: 0x00000058266; RELOC-NEXT: Offset: 0x00000058
293; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB267; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
294; RELOC-NEXT: Index: 22268; RELOC-NEXT: Index: 22
295; RELOC-NEXT: Offset: 0x00000061269; RELOC-NEXT: Offset: 0x00000061
296; RELOC-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB270; RELOC-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
297; RELOC-NEXT: Index: 23271; RELOC-NEXT: Index: 23
298; RELOC-NEXT: Offset: 0x0000006A272; RELOC-NEXT: Offset: 0x0000006A
299; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB273; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
300; RELOC-NEXT: Index: 8274; RELOC-NEXT: Index: 8
301; RELOC-NEXT: Offset: 0x00000073275; RELOC-NEXT: Offset: 0x00000073
302; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB276; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
303; RELOC-NEXT: Index: 20277; RELOC-NEXT: Index: 20
304; RELOC-NEXT: Offset: 0x0000007C278; RELOC-NEXT: Offset: 0x0000007C
305; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB279; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
306; RELOC-NEXT: Index: 21280; RELOC-NEXT: Index: 21
307; RELOC-NEXT: Offset: 0x00000085281; RELOC-NEXT: Offset: 0x00000085
308; RELOC-NEXT: Functions:282; RELOC-NEXT: Functions:
...@@ -363,19 +337,19 @@...@@ -363,19 +337,19 @@
363; RELOC-NEXT: - Type: DATA337; RELOC-NEXT: - Type: DATA
364; RELOC-NEXT: Segments:338; RELOC-NEXT: Segments:
365; RELOC-NEXT: - SectionOffset: 6339; RELOC-NEXT: - SectionOffset: 6
366; RELOC-NEXT: MemoryIndex: 0340; RELOC-NEXT: InitFlags: 0
367; RELOC-NEXT: Offset:341; RELOC-NEXT: Offset:
368; RELOC-NEXT: Opcode: I32_CONST342; RELOC-NEXT: Opcode: I32_CONST
369; RELOC-NEXT: Value: 0343; RELOC-NEXT: Value: 0
370; RELOC-NEXT: Content: '0000000000000000'344; RELOC-NEXT: Content: '0000000000000000'
371; RELOC-NEXT: - SectionOffset: 19345; RELOC-NEXT: - SectionOffset: 19
372; RELOC-NEXT: MemoryIndex: 0346; RELOC-NEXT: InitFlags: 0
373; RELOC-NEXT: Offset:347; RELOC-NEXT: Offset:
374; RELOC-NEXT: Opcode: I32_CONST348; RELOC-NEXT: Opcode: I32_CONST
375; RELOC-NEXT: Value: 8349; RELOC-NEXT: Value: 8
376; RELOC-NEXT: Content: '0000000000000000'350; RELOC-NEXT: Content: '0000000000000000'
377; RELOC-NEXT: - SectionOffset: 32351; RELOC-NEXT: - SectionOffset: 32
378; RELOC-NEXT: MemoryIndex: 0352; RELOC-NEXT: InitFlags: 0
379; RELOC-NEXT: Offset:353; RELOC-NEXT: Offset:
380; RELOC-NEXT: Opcode: I32_CONST354; RELOC-NEXT: Opcode: I32_CONST
381; RELOC-NEXT: Value: 16355; RELOC-NEXT: Value: 16
deps/lld/test/wasm/lto/archive.ll+1-3
...@@ -18,8 +18,6 @@ declare void @f()...@@ -18,8 +18,6 @@ declare void @f()
18; CHECK: Name: name18; CHECK: Name: name
19; CHECK-NEXT: FunctionNames:19; CHECK-NEXT: FunctionNames:
20; CHECK-NEXT: - Index: 020; CHECK-NEXT: - Index: 0
21; CHECK-NEXT: Name: __wasm_call_ctors
22; CHECK-NEXT: - Index: 1
23; CHECK-NEXT: Name: _start21; CHECK-NEXT: Name: _start
24; CHECK-NEXT: - Index: 222; CHECK-NEXT: - Index: 1
25; CHECK-NEXT: Name: f23; CHECK-NEXT: Name: f
deps/lld/test/wasm/lto/atomics.ll+3-2
...@@ -1,7 +1,8 @@...@@ -1,7 +1,8 @@
1; RUN: llvm-as %s -o %t.o1; RUN: llvm-as %s -o %t.o
2; RUN: wasm-ld %t.o -o %t.wasm -lto-O02; RUN: wasm-ld %t.o -o %t.wasm -lto-O0
3; Atomic operations with fail to compile if the ThreadModel is not3
4; correctly set to Single (i.e. if atomics are not lowered to regular ops).4; Atomic operations will not fail to compile if atomics are not
5; enabled because LLVM atomics will be lowered to regular ops.
56
6target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"7target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
7target triple = "wasm32-unknown-unknown-wasm"8target triple = "wasm32-unknown-unknown-wasm"
deps/lld/test/wasm/lto/comdat.ll created+17
...@@ -0,0 +1,17 @@
1; Verify that comdat symbols can be defined in LTO objects. We had a
2; regression where the comdat handling code was causing symbol in the lto object
3; to be ignored.
4; RUN: llvm-as %s -o %t.bc
5; RUN: llc -filetype=obj %s -o %t.o
6; RUN: wasm-ld %t.bc %t.o -o %t.wasm
7; RUN: wasm-ld %t.o %t.bc -o %t.wasm
8
9target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
10target triple = "wasm32-unknown-unknown"
11
12$foo = comdat any
13
14define void @_start() comdat($foo) {
15entry:
16 ret void
17}
deps/lld/test/wasm/lto/export.ll+2-8
...@@ -23,16 +23,10 @@ entry:...@@ -23,16 +23,10 @@ entry:
23; CHECK-NEXT: - Name: memory23; CHECK-NEXT: - Name: memory
24; CHECK-NEXT: Kind: MEMORY24; CHECK-NEXT: Kind: MEMORY
25; CHECK-NEXT: Index: 025; CHECK-NEXT: Index: 0
26; CHECK-NEXT: - Name: __heap_base
27; CHECK-NEXT: Kind: GLOBAL
28; CHECK-NEXT: Index: 1
29; CHECK-NEXT: - Name: __data_end
30; CHECK-NEXT: Kind: GLOBAL
31; CHECK-NEXT: Index: 2
32; CHECK-NEXT: - Name: hidden_function26; CHECK-NEXT: - Name: hidden_function
33; CHECK-NEXT: Kind: FUNCTION27; CHECK-NEXT: Kind: FUNCTION
34; CHECK-NEXT: Index: 128; CHECK-NEXT: Index: 0
35; CHECK-NEXT: - Name: _start29; CHECK-NEXT: - Name: _start
36; CHECK-NEXT: Kind: FUNCTION30; CHECK-NEXT: Kind: FUNCTION
37; CHECK-NEXT: Index: 231; CHECK-NEXT: Index: 1
38; CHECK-NEXT: - Type: CODE32; CHECK-NEXT: - Type: CODE
deps/lld/test/wasm/lto/lto-start.ll-2
...@@ -6,8 +6,6 @@...@@ -6,8 +6,6 @@
6; CHECK-NEXT: Name: name6; CHECK-NEXT: Name: name
7; CHECK-NEXT: FunctionNames: 7; CHECK-NEXT: FunctionNames:
8; CHECK-NEXT: - Index: 08; CHECK-NEXT: - Index: 0
9; CHECK-NEXT: Name: __wasm_call_ctors
10; CHECK-NEXT: - Index: 1
11; CHECK-NEXT: Name: _start9; CHECK-NEXT: Name: _start
1210
13target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"11target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
deps/lld/test/wasm/lto/opt-level.ll+2-2
...@@ -7,11 +7,11 @@...@@ -7,11 +7,11 @@
7; RUN: obj2yaml %t2a | FileCheck --check-prefix=CHECK-O2 %s7; RUN: obj2yaml %t2a | FileCheck --check-prefix=CHECK-O2 %s
88
9; Reject invalid optimization levels.9; Reject invalid optimization levels.
10; RUN: not ld.lld -o %t3 -e main --lto-O6 %t.o 2>&1 | \10; RUN: not wasm-ld -o %t3 -e main --lto-O6 %t.o 2>&1 | \
11; RUN: FileCheck --check-prefix=INVALID %s11; RUN: FileCheck --check-prefix=INVALID %s
12; INVALID: invalid optimization level for LTO: 612; INVALID: invalid optimization level for LTO: 6
1313
14; RUN: not ld.lld -o %t3 -m elf_x86_64 -e main --lto-O-1 %t.o 2>&1 | \14; RUN: not wasm-ld -o %t3 -m elf_x86_64 -e main --lto-O-1 %t.o 2>&1 | \
15; RUN: FileCheck --check-prefix=INVALIDNEGATIVE %s15; RUN: FileCheck --check-prefix=INVALIDNEGATIVE %s
16; INVALIDNEGATIVE: invalid optimization level for LTO: 429496729516; INVALIDNEGATIVE: invalid optimization level for LTO: 4294967295
1717
deps/lld/test/wasm/lto/relocatable.ll created+27
...@@ -0,0 +1,27 @@
1; RUN: llvm-as %s -o %t1.o
2; RUN: wasm-ld %t1.o -r -o %t
3; RUN: llvm-readobj --symbols %t | FileCheck %s
4
5; CHECK: Symbols [
6; CHECK-NEXT: Symbol {
7; CHECK-NEXT: Name: foo
8; CHECK-NEXT: Type: FUNCTION (0x0)
9; CHECK-NEXT: Flags [ (0x0)
10; CHECK-NEXT: ]
11; CHECK-NEXT: ElementIndex: 0x0
12; CHECK-NEXT: }
13; CHECK-NEXT: ]
14
15target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
16target triple = "wasm32-unknown-unknown"
17
18define void @foo() {
19 call void @bar()
20 ret void
21}
22
23define internal void @bar() {
24 ret void
25}
26
27declare i32 @baz(...)
deps/lld/test/wasm/lto/signature-mismatch.ll+1
...@@ -15,5 +15,6 @@ define void @_start() {...@@ -15,5 +15,6 @@ define void @_start() {
15 ret void15 ret void
16}16}
1717
18; CHECK: error: function signature mismatch: f
18; CHECK: >>> defined as (i32) -> void in {{.*}}signature-mismatch.ll.tmp1.o19; CHECK: >>> defined as (i32) -> void in {{.*}}signature-mismatch.ll.tmp1.o
19; CHECK: >>> defined as () -> void in lto.tmp20; CHECK: >>> defined as () -> void in lto.tmp
deps/lld/test/wasm/lto/undef.ll+18-2
...@@ -5,10 +5,22 @@...@@ -5,10 +5,22 @@
5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6target triple = "wasm32-unknown-unknown"6target triple = "wasm32-unknown-unknown"
77
8declare void @bar()8declare i32 @bar()
9
10; Symbols such as foo which are only called indirectly are handled slightly
11; differently with resepect to signature checking.
12declare i32 @foo()
13
14@ptr = global i8* bitcast (i32 ()* @foo to i8*), align 8
15; Ensure access to ptr is not inlined below, even under LTO
16@llvm.used = appending global [1 x i8**] [i8** @ptr], section "llvm.metadata"
917
10define void @_start() {18define void @_start() {
11 call void @bar()19 call i32 @bar()
20
21 %addr = load i32 ()*, i32 ()** bitcast (i8** @ptr to i32 ()**), align 8
22 call i32 %addr()
23
12 ret void24 ret void
13}25}
1426
...@@ -18,3 +30,7 @@ define void @_start() {...@@ -18,3 +30,7 @@ define void @_start() {
18; CHECK-NEXT: Field: bar30; CHECK-NEXT: Field: bar
19; CHECK-NEXT: Kind: FUNCTION31; CHECK-NEXT: Kind: FUNCTION
20; CHECK-NEXT: SigIndex: 032; CHECK-NEXT: SigIndex: 0
33; CHECK-NEXT: - Module: env
34; CHECK-NEXT: Field: foo
35; CHECK-NEXT: Kind: FUNCTION
36; CHECK-NEXT: SigIndex: 0
deps/lld/test/wasm/lto/used.ll+2-4
...@@ -28,7 +28,7 @@ return:...@@ -28,7 +28,7 @@ return:
28; CHECK: - Type: DATA28; CHECK: - Type: DATA
29; CHECK-NEXT: Segments:29; CHECK-NEXT: Segments:
30; CHECK-NEXT: - SectionOffset: 730; CHECK-NEXT: - SectionOffset: 7
31; CHECK-NEXT: MemoryIndex: 031; CHECK-NEXT: InitFlags: 0
32; CHECK-NEXT: Offset:32; CHECK-NEXT: Offset:
33; CHECK-NEXT: Opcode: I32_CONST33; CHECK-NEXT: Opcode: I32_CONST
34; CHECK-NEXT: Value: 102434; CHECK-NEXT: Value: 1024
...@@ -38,8 +38,6 @@ return:...@@ -38,8 +38,6 @@ return:
38; CHECK-NEXT: Name: name38; CHECK-NEXT: Name: name
39; CHECK-NEXT: FunctionNames: 39; CHECK-NEXT: FunctionNames:
40; CHECK-NEXT: - Index: 040; CHECK-NEXT: - Index: 0
41; CHECK-NEXT: Name: __wasm_call_ctors
42; CHECK-NEXT: - Index: 1
43; CHECK-NEXT: Name: _start41; CHECK-NEXT: Name: _start
44; CHECK-NEXT: - Index: 242; CHECK-NEXT: - Index: 1
45; CHECK-NEXT: Name: bar43; CHECK-NEXT: Name: bar
deps/lld/test/wasm/lto/weak-undefined.ll created+20
...@@ -0,0 +1,20 @@
1; RUN: llvm-as %s -o %t.o
2; RUN: wasm-ld %t.o -o %t.wasm
3; RUN: obj2yaml %t.wasm | FileCheck %s
4
5; Test that undefined weak external functions are handled in the LTO case
6; We had a bug where stub function generation was failing because functions
7; that are in bitcode (pre-LTO) don't have signatures assigned.
8
9target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
10target triple = "wasm32-unknown-unknown"
11
12declare extern_weak i32 @foo()
13
14define void @_start() #0 {
15entry:
16 %call2 = call i32 @foo()
17 ret void
18}
19
20; CHECK: Name: 'undefined:foo'
deps/lld/test/wasm/lto/weak.ll+5-2
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1; RUN: llvm-as %s -o %t.o1; RUN: llvm-as %s -o %t.o
2; RUN: wasm-ld %t.o %t.o -o %t.wasm -r2; RUN: wasm-ld %t.o %t.o -o %t.wasm -r
3; RUN: llvm-readobj -t %t.wasm | FileCheck %s3; RUN: llvm-readobj --symbols %t.wasm | FileCheck %s
44
5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"5target datalayout = "e-m:e-p:32:32-i64:64-n32:64-S128"
6target triple = "wasm32-unknown-unknown-wasm"6target triple = "wasm32-unknown-unknown-wasm"
...@@ -12,5 +12,8 @@ define weak void @f() {...@@ -12,5 +12,8 @@ define weak void @f() {
12; CHECK: Symbol {12; CHECK: Symbol {
13; CHECK-NEXT: Name: f13; CHECK-NEXT: Name: f
14; CHECK-NEXT: Type: FUNCTION (0x0)14; CHECK-NEXT: Type: FUNCTION (0x0)
15; CHECK-NEXT: Flags: 0x115; CHECK-NEXT: Flags [ (0x1)
16; CHECK-NEXT: BINDING_WEAK (0x1)
17; CHECK-NEXT: ]
18; CHECK-NEXT: ElementIndex: 0x0
16; CHECK-NEXT: }19; CHECK-NEXT: }
deps/lld/test/wasm/many-functions.ll+132-132
...@@ -18,394 +18,394 @@ entry:...@@ -18,394 +18,394 @@ entry:
1818
19; CHECK: - Type: CODE19; CHECK: - Type: CODE
20; CHECK-NEXT: Relocations:20; CHECK-NEXT: Relocations:
21; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB21; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
22; CHECK-NEXT: Index: 122; CHECK-NEXT: Index: 1
23; CHECK-NEXT: Offset: 0x0000000823; CHECK-NEXT: Offset: 0x00000008
24; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB24; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
25; CHECK-NEXT: Index: 125; CHECK-NEXT: Index: 1
26; CHECK-NEXT: Offset: 0x0000001426; CHECK-NEXT: Offset: 0x00000014
27; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB27; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
28; CHECK-NEXT: Index: 128; CHECK-NEXT: Index: 1
29; CHECK-NEXT: Offset: 0x0000002029; CHECK-NEXT: Offset: 0x00000020
30; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB30; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
31; CHECK-NEXT: Index: 131; CHECK-NEXT: Index: 1
32; CHECK-NEXT: Offset: 0x0000002C32; CHECK-NEXT: Offset: 0x0000002C
33; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB33; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
34; CHECK-NEXT: Index: 134; CHECK-NEXT: Index: 1
35; CHECK-NEXT: Offset: 0x0000003835; CHECK-NEXT: Offset: 0x00000038
36; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB36; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
37; CHECK-NEXT: Index: 137; CHECK-NEXT: Index: 1
38; CHECK-NEXT: Offset: 0x0000004438; CHECK-NEXT: Offset: 0x00000044
39; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB39; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
40; CHECK-NEXT: Index: 140; CHECK-NEXT: Index: 1
41; CHECK-NEXT: Offset: 0x0000005041; CHECK-NEXT: Offset: 0x00000050
42; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB42; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
43; CHECK-NEXT: Index: 143; CHECK-NEXT: Index: 1
44; CHECK-NEXT: Offset: 0x0000005C44; CHECK-NEXT: Offset: 0x0000005C
45; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB45; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
46; CHECK-NEXT: Index: 146; CHECK-NEXT: Index: 1
47; CHECK-NEXT: Offset: 0x0000006847; CHECK-NEXT: Offset: 0x00000068
48; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB48; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
49; CHECK-NEXT: Index: 149; CHECK-NEXT: Index: 1
50; CHECK-NEXT: Offset: 0x0000007450; CHECK-NEXT: Offset: 0x00000074
51; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB51; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
52; CHECK-NEXT: Index: 152; CHECK-NEXT: Index: 1
53; CHECK-NEXT: Offset: 0x0000008053; CHECK-NEXT: Offset: 0x00000080
54; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB54; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
55; CHECK-NEXT: Index: 155; CHECK-NEXT: Index: 1
56; CHECK-NEXT: Offset: 0x0000008C56; CHECK-NEXT: Offset: 0x0000008C
57; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB57; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
58; CHECK-NEXT: Index: 158; CHECK-NEXT: Index: 1
59; CHECK-NEXT: Offset: 0x0000009859; CHECK-NEXT: Offset: 0x00000098
60; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB60; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
61; CHECK-NEXT: Index: 161; CHECK-NEXT: Index: 1
62; CHECK-NEXT: Offset: 0x000000A462; CHECK-NEXT: Offset: 0x000000A4
63; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB63; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
64; CHECK-NEXT: Index: 164; CHECK-NEXT: Index: 1
65; CHECK-NEXT: Offset: 0x000000B065; CHECK-NEXT: Offset: 0x000000B0
66; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB66; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
67; CHECK-NEXT: Index: 167; CHECK-NEXT: Index: 1
68; CHECK-NEXT: Offset: 0x000000BC68; CHECK-NEXT: Offset: 0x000000BC
69; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB69; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
70; CHECK-NEXT: Index: 170; CHECK-NEXT: Index: 1
71; CHECK-NEXT: Offset: 0x000000C871; CHECK-NEXT: Offset: 0x000000C8
72; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB72; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
73; CHECK-NEXT: Index: 173; CHECK-NEXT: Index: 1
74; CHECK-NEXT: Offset: 0x000000D474; CHECK-NEXT: Offset: 0x000000D4
75; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB75; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
76; CHECK-NEXT: Index: 176; CHECK-NEXT: Index: 1
77; CHECK-NEXT: Offset: 0x000000E077; CHECK-NEXT: Offset: 0x000000E0
78; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB78; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
79; CHECK-NEXT: Index: 179; CHECK-NEXT: Index: 1
80; CHECK-NEXT: Offset: 0x000000EC80; CHECK-NEXT: Offset: 0x000000EC
81; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB81; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
82; CHECK-NEXT: Index: 182; CHECK-NEXT: Index: 1
83; CHECK-NEXT: Offset: 0x000000F883; CHECK-NEXT: Offset: 0x000000F8
84; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB84; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
85; CHECK-NEXT: Index: 185; CHECK-NEXT: Index: 1
86; CHECK-NEXT: Offset: 0x0000010486; CHECK-NEXT: Offset: 0x00000104
87; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB87; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
88; CHECK-NEXT: Index: 188; CHECK-NEXT: Index: 1
89; CHECK-NEXT: Offset: 0x0000011089; CHECK-NEXT: Offset: 0x00000110
90; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB90; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
91; CHECK-NEXT: Index: 191; CHECK-NEXT: Index: 1
92; CHECK-NEXT: Offset: 0x0000011C92; CHECK-NEXT: Offset: 0x0000011C
93; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB93; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
94; CHECK-NEXT: Index: 194; CHECK-NEXT: Index: 1
95; CHECK-NEXT: Offset: 0x0000012895; CHECK-NEXT: Offset: 0x00000128
96; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB96; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
97; CHECK-NEXT: Index: 197; CHECK-NEXT: Index: 1
98; CHECK-NEXT: Offset: 0x0000013498; CHECK-NEXT: Offset: 0x00000134
99; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB99; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
100; CHECK-NEXT: Index: 1100; CHECK-NEXT: Index: 1
101; CHECK-NEXT: Offset: 0x00000140101; CHECK-NEXT: Offset: 0x00000140
102; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB102; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
103; CHECK-NEXT: Index: 1103; CHECK-NEXT: Index: 1
104; CHECK-NEXT: Offset: 0x0000014C104; CHECK-NEXT: Offset: 0x0000014C
105; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB105; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
106; CHECK-NEXT: Index: 1106; CHECK-NEXT: Index: 1
107; CHECK-NEXT: Offset: 0x00000158107; CHECK-NEXT: Offset: 0x00000158
108; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB108; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
109; CHECK-NEXT: Index: 1109; CHECK-NEXT: Index: 1
110; CHECK-NEXT: Offset: 0x00000164110; CHECK-NEXT: Offset: 0x00000164
111; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB111; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
112; CHECK-NEXT: Index: 1112; CHECK-NEXT: Index: 1
113; CHECK-NEXT: Offset: 0x00000170113; CHECK-NEXT: Offset: 0x00000170
114; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB114; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
115; CHECK-NEXT: Index: 1115; CHECK-NEXT: Index: 1
116; CHECK-NEXT: Offset: 0x0000017C116; CHECK-NEXT: Offset: 0x0000017C
117; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB117; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
118; CHECK-NEXT: Index: 1118; CHECK-NEXT: Index: 1
119; CHECK-NEXT: Offset: 0x00000188119; CHECK-NEXT: Offset: 0x00000188
120; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB120; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
121; CHECK-NEXT: Index: 1121; CHECK-NEXT: Index: 1
122; CHECK-NEXT: Offset: 0x00000194122; CHECK-NEXT: Offset: 0x00000194
123; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB123; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
124; CHECK-NEXT: Index: 1124; CHECK-NEXT: Index: 1
125; CHECK-NEXT: Offset: 0x000001A0125; CHECK-NEXT: Offset: 0x000001A0
126; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB126; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
127; CHECK-NEXT: Index: 1127; CHECK-NEXT: Index: 1
128; CHECK-NEXT: Offset: 0x000001AC128; CHECK-NEXT: Offset: 0x000001AC
129; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB129; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
130; CHECK-NEXT: Index: 1130; CHECK-NEXT: Index: 1
131; CHECK-NEXT: Offset: 0x000001B8131; CHECK-NEXT: Offset: 0x000001B8
132; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB132; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
133; CHECK-NEXT: Index: 1133; CHECK-NEXT: Index: 1
134; CHECK-NEXT: Offset: 0x000001C4134; CHECK-NEXT: Offset: 0x000001C4
135; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB135; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
136; CHECK-NEXT: Index: 1136; CHECK-NEXT: Index: 1
137; CHECK-NEXT: Offset: 0x000001D0137; CHECK-NEXT: Offset: 0x000001D0
138; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB138; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
139; CHECK-NEXT: Index: 1139; CHECK-NEXT: Index: 1
140; CHECK-NEXT: Offset: 0x000001DC140; CHECK-NEXT: Offset: 0x000001DC
141; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB141; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
142; CHECK-NEXT: Index: 1142; CHECK-NEXT: Index: 1
143; CHECK-NEXT: Offset: 0x000001E8143; CHECK-NEXT: Offset: 0x000001E8
144; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB144; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
145; CHECK-NEXT: Index: 1145; CHECK-NEXT: Index: 1
146; CHECK-NEXT: Offset: 0x000001F4146; CHECK-NEXT: Offset: 0x000001F4
147; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB147; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
148; CHECK-NEXT: Index: 1148; CHECK-NEXT: Index: 1
149; CHECK-NEXT: Offset: 0x00000200149; CHECK-NEXT: Offset: 0x00000200
150; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB150; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
151; CHECK-NEXT: Index: 1151; CHECK-NEXT: Index: 1
152; CHECK-NEXT: Offset: 0x0000020C152; CHECK-NEXT: Offset: 0x0000020C
153; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB153; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
154; CHECK-NEXT: Index: 1154; CHECK-NEXT: Index: 1
155; CHECK-NEXT: Offset: 0x00000218155; CHECK-NEXT: Offset: 0x00000218
156; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB156; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
157; CHECK-NEXT: Index: 1157; CHECK-NEXT: Index: 1
158; CHECK-NEXT: Offset: 0x00000224158; CHECK-NEXT: Offset: 0x00000224
159; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB159; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
160; CHECK-NEXT: Index: 1160; CHECK-NEXT: Index: 1
161; CHECK-NEXT: Offset: 0x00000230161; CHECK-NEXT: Offset: 0x00000230
162; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB162; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
163; CHECK-NEXT: Index: 1163; CHECK-NEXT: Index: 1
164; CHECK-NEXT: Offset: 0x0000023C164; CHECK-NEXT: Offset: 0x0000023C
165; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB165; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
166; CHECK-NEXT: Index: 1166; CHECK-NEXT: Index: 1
167; CHECK-NEXT: Offset: 0x00000248167; CHECK-NEXT: Offset: 0x00000248
168; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB168; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
169; CHECK-NEXT: Index: 1169; CHECK-NEXT: Index: 1
170; CHECK-NEXT: Offset: 0x00000254170; CHECK-NEXT: Offset: 0x00000254
171; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB171; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
172; CHECK-NEXT: Index: 1172; CHECK-NEXT: Index: 1
173; CHECK-NEXT: Offset: 0x00000260173; CHECK-NEXT: Offset: 0x00000260
174; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB174; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
175; CHECK-NEXT: Index: 1175; CHECK-NEXT: Index: 1
176; CHECK-NEXT: Offset: 0x0000026C176; CHECK-NEXT: Offset: 0x0000026C
177; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB177; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
178; CHECK-NEXT: Index: 1178; CHECK-NEXT: Index: 1
179; CHECK-NEXT: Offset: 0x00000278179; CHECK-NEXT: Offset: 0x00000278
180; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB180; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
181; CHECK-NEXT: Index: 1181; CHECK-NEXT: Index: 1
182; CHECK-NEXT: Offset: 0x00000284182; CHECK-NEXT: Offset: 0x00000284
183; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB183; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
184; CHECK-NEXT: Index: 1184; CHECK-NEXT: Index: 1
185; CHECK-NEXT: Offset: 0x00000290185; CHECK-NEXT: Offset: 0x00000290
186; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB186; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
187; CHECK-NEXT: Index: 1187; CHECK-NEXT: Index: 1
188; CHECK-NEXT: Offset: 0x0000029C188; CHECK-NEXT: Offset: 0x0000029C
189; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB189; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
190; CHECK-NEXT: Index: 1190; CHECK-NEXT: Index: 1
191; CHECK-NEXT: Offset: 0x000002A8191; CHECK-NEXT: Offset: 0x000002A8
192; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB192; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
193; CHECK-NEXT: Index: 1193; CHECK-NEXT: Index: 1
194; CHECK-NEXT: Offset: 0x000002B4194; CHECK-NEXT: Offset: 0x000002B4
195; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB195; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
196; CHECK-NEXT: Index: 1196; CHECK-NEXT: Index: 1
197; CHECK-NEXT: Offset: 0x000002C0197; CHECK-NEXT: Offset: 0x000002C0
198; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB198; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
199; CHECK-NEXT: Index: 1199; CHECK-NEXT: Index: 1
200; CHECK-NEXT: Offset: 0x000002CC200; CHECK-NEXT: Offset: 0x000002CC
201; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB201; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
202; CHECK-NEXT: Index: 1202; CHECK-NEXT: Index: 1
203; CHECK-NEXT: Offset: 0x000002D8203; CHECK-NEXT: Offset: 0x000002D8
204; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB204; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
205; CHECK-NEXT: Index: 1205; CHECK-NEXT: Index: 1
206; CHECK-NEXT: Offset: 0x000002E4206; CHECK-NEXT: Offset: 0x000002E4
207; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB207; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
208; CHECK-NEXT: Index: 1208; CHECK-NEXT: Index: 1
209; CHECK-NEXT: Offset: 0x000002F0209; CHECK-NEXT: Offset: 0x000002F0
210; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB210; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
211; CHECK-NEXT: Index: 1211; CHECK-NEXT: Index: 1
212; CHECK-NEXT: Offset: 0x000002FC212; CHECK-NEXT: Offset: 0x000002FC
213; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB213; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
214; CHECK-NEXT: Index: 1214; CHECK-NEXT: Index: 1
215; CHECK-NEXT: Offset: 0x00000308215; CHECK-NEXT: Offset: 0x00000308
216; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB216; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
217; CHECK-NEXT: Index: 1217; CHECK-NEXT: Index: 1
218; CHECK-NEXT: Offset: 0x00000314218; CHECK-NEXT: Offset: 0x00000314
219; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB219; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
220; CHECK-NEXT: Index: 1220; CHECK-NEXT: Index: 1
221; CHECK-NEXT: Offset: 0x00000320221; CHECK-NEXT: Offset: 0x00000320
222; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB222; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
223; CHECK-NEXT: Index: 1223; CHECK-NEXT: Index: 1
224; CHECK-NEXT: Offset: 0x0000032C224; CHECK-NEXT: Offset: 0x0000032C
225; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB225; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
226; CHECK-NEXT: Index: 1226; CHECK-NEXT: Index: 1
227; CHECK-NEXT: Offset: 0x00000338227; CHECK-NEXT: Offset: 0x00000338
228; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB228; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
229; CHECK-NEXT: Index: 1229; CHECK-NEXT: Index: 1
230; CHECK-NEXT: Offset: 0x00000344230; CHECK-NEXT: Offset: 0x00000344
231; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB231; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
232; CHECK-NEXT: Index: 1232; CHECK-NEXT: Index: 1
233; CHECK-NEXT: Offset: 0x00000350233; CHECK-NEXT: Offset: 0x00000350
234; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB234; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
235; CHECK-NEXT: Index: 1235; CHECK-NEXT: Index: 1
236; CHECK-NEXT: Offset: 0x0000035C236; CHECK-NEXT: Offset: 0x0000035C
237; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB237; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
238; CHECK-NEXT: Index: 1238; CHECK-NEXT: Index: 1
239; CHECK-NEXT: Offset: 0x00000368239; CHECK-NEXT: Offset: 0x00000368
240; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB240; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
241; CHECK-NEXT: Index: 1241; CHECK-NEXT: Index: 1
242; CHECK-NEXT: Offset: 0x00000374242; CHECK-NEXT: Offset: 0x00000374
243; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB243; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
244; CHECK-NEXT: Index: 1244; CHECK-NEXT: Index: 1
245; CHECK-NEXT: Offset: 0x00000380245; CHECK-NEXT: Offset: 0x00000380
246; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB246; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
247; CHECK-NEXT: Index: 1247; CHECK-NEXT: Index: 1
248; CHECK-NEXT: Offset: 0x0000038C248; CHECK-NEXT: Offset: 0x0000038C
249; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB249; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
250; CHECK-NEXT: Index: 1250; CHECK-NEXT: Index: 1
251; CHECK-NEXT: Offset: 0x00000398251; CHECK-NEXT: Offset: 0x00000398
252; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB252; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
253; CHECK-NEXT: Index: 1253; CHECK-NEXT: Index: 1
254; CHECK-NEXT: Offset: 0x000003A4254; CHECK-NEXT: Offset: 0x000003A4
255; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB255; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
256; CHECK-NEXT: Index: 1256; CHECK-NEXT: Index: 1
257; CHECK-NEXT: Offset: 0x000003B0257; CHECK-NEXT: Offset: 0x000003B0
258; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB258; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
259; CHECK-NEXT: Index: 1259; CHECK-NEXT: Index: 1
260; CHECK-NEXT: Offset: 0x000003BC260; CHECK-NEXT: Offset: 0x000003BC
261; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB261; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
262; CHECK-NEXT: Index: 1262; CHECK-NEXT: Index: 1
263; CHECK-NEXT: Offset: 0x000003C8263; CHECK-NEXT: Offset: 0x000003C8
264; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB264; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
265; CHECK-NEXT: Index: 1265; CHECK-NEXT: Index: 1
266; CHECK-NEXT: Offset: 0x000003D4266; CHECK-NEXT: Offset: 0x000003D4
267; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB267; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
268; CHECK-NEXT: Index: 1268; CHECK-NEXT: Index: 1
269; CHECK-NEXT: Offset: 0x000003E0269; CHECK-NEXT: Offset: 0x000003E0
270; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB270; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
271; CHECK-NEXT: Index: 1271; CHECK-NEXT: Index: 1
272; CHECK-NEXT: Offset: 0x000003EC272; CHECK-NEXT: Offset: 0x000003EC
273; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB273; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
274; CHECK-NEXT: Index: 1274; CHECK-NEXT: Index: 1
275; CHECK-NEXT: Offset: 0x000003F8275; CHECK-NEXT: Offset: 0x000003F8
276; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB276; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
277; CHECK-NEXT: Index: 1277; CHECK-NEXT: Index: 1
278; CHECK-NEXT: Offset: 0x00000404278; CHECK-NEXT: Offset: 0x00000404
279; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB279; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
280; CHECK-NEXT: Index: 1280; CHECK-NEXT: Index: 1
281; CHECK-NEXT: Offset: 0x00000410281; CHECK-NEXT: Offset: 0x00000410
282; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB282; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
283; CHECK-NEXT: Index: 1283; CHECK-NEXT: Index: 1
284; CHECK-NEXT: Offset: 0x0000041C284; CHECK-NEXT: Offset: 0x0000041C
285; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB285; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
286; CHECK-NEXT: Index: 1286; CHECK-NEXT: Index: 1
287; CHECK-NEXT: Offset: 0x00000428287; CHECK-NEXT: Offset: 0x00000428
288; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB288; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
289; CHECK-NEXT: Index: 1289; CHECK-NEXT: Index: 1
290; CHECK-NEXT: Offset: 0x00000434290; CHECK-NEXT: Offset: 0x00000434
291; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB291; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
292; CHECK-NEXT: Index: 1292; CHECK-NEXT: Index: 1
293; CHECK-NEXT: Offset: 0x00000440293; CHECK-NEXT: Offset: 0x00000440
294; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB294; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
295; CHECK-NEXT: Index: 1295; CHECK-NEXT: Index: 1
296; CHECK-NEXT: Offset: 0x0000044C296; CHECK-NEXT: Offset: 0x0000044C
297; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB297; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
298; CHECK-NEXT: Index: 1298; CHECK-NEXT: Index: 1
299; CHECK-NEXT: Offset: 0x00000458299; CHECK-NEXT: Offset: 0x00000458
300; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB300; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
301; CHECK-NEXT: Index: 1301; CHECK-NEXT: Index: 1
302; CHECK-NEXT: Offset: 0x00000464302; CHECK-NEXT: Offset: 0x00000464
303; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB303; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
304; CHECK-NEXT: Index: 1304; CHECK-NEXT: Index: 1
305; CHECK-NEXT: Offset: 0x00000470305; CHECK-NEXT: Offset: 0x00000470
306; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB306; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
307; CHECK-NEXT: Index: 1307; CHECK-NEXT: Index: 1
308; CHECK-NEXT: Offset: 0x0000047C308; CHECK-NEXT: Offset: 0x0000047C
309; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB309; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
310; CHECK-NEXT: Index: 1310; CHECK-NEXT: Index: 1
311; CHECK-NEXT: Offset: 0x00000488311; CHECK-NEXT: Offset: 0x00000488
312; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB312; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
313; CHECK-NEXT: Index: 1313; CHECK-NEXT: Index: 1
314; CHECK-NEXT: Offset: 0x00000494314; CHECK-NEXT: Offset: 0x00000494
315; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB315; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
316; CHECK-NEXT: Index: 1316; CHECK-NEXT: Index: 1
317; CHECK-NEXT: Offset: 0x000004A0317; CHECK-NEXT: Offset: 0x000004A0
318; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB318; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
319; CHECK-NEXT: Index: 1319; CHECK-NEXT: Index: 1
320; CHECK-NEXT: Offset: 0x000004AC320; CHECK-NEXT: Offset: 0x000004AC
321; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB321; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
322; CHECK-NEXT: Index: 1322; CHECK-NEXT: Index: 1
323; CHECK-NEXT: Offset: 0x000004B8323; CHECK-NEXT: Offset: 0x000004B8
324; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB324; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
325; CHECK-NEXT: Index: 1325; CHECK-NEXT: Index: 1
326; CHECK-NEXT: Offset: 0x000004C4326; CHECK-NEXT: Offset: 0x000004C4
327; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB327; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
328; CHECK-NEXT: Index: 1328; CHECK-NEXT: Index: 1
329; CHECK-NEXT: Offset: 0x000004D0329; CHECK-NEXT: Offset: 0x000004D0
330; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB330; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
331; CHECK-NEXT: Index: 1331; CHECK-NEXT: Index: 1
332; CHECK-NEXT: Offset: 0x000004DC332; CHECK-NEXT: Offset: 0x000004DC
333; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB333; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
334; CHECK-NEXT: Index: 1334; CHECK-NEXT: Index: 1
335; CHECK-NEXT: Offset: 0x000004E8335; CHECK-NEXT: Offset: 0x000004E8
336; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB336; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
337; CHECK-NEXT: Index: 1337; CHECK-NEXT: Index: 1
338; CHECK-NEXT: Offset: 0x000004F4338; CHECK-NEXT: Offset: 0x000004F4
339; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB339; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
340; CHECK-NEXT: Index: 1340; CHECK-NEXT: Index: 1
341; CHECK-NEXT: Offset: 0x00000500341; CHECK-NEXT: Offset: 0x00000500
342; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB342; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
343; CHECK-NEXT: Index: 1343; CHECK-NEXT: Index: 1
344; CHECK-NEXT: Offset: 0x0000050C344; CHECK-NEXT: Offset: 0x0000050C
345; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB345; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
346; CHECK-NEXT: Index: 1346; CHECK-NEXT: Index: 1
347; CHECK-NEXT: Offset: 0x00000518347; CHECK-NEXT: Offset: 0x00000518
348; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB348; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
349; CHECK-NEXT: Index: 1349; CHECK-NEXT: Index: 1
350; CHECK-NEXT: Offset: 0x00000524350; CHECK-NEXT: Offset: 0x00000524
351; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB351; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
352; CHECK-NEXT: Index: 1352; CHECK-NEXT: Index: 1
353; CHECK-NEXT: Offset: 0x00000530353; CHECK-NEXT: Offset: 0x00000530
354; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB354; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
355; CHECK-NEXT: Index: 1355; CHECK-NEXT: Index: 1
356; CHECK-NEXT: Offset: 0x0000053C356; CHECK-NEXT: Offset: 0x0000053C
357; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB357; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
358; CHECK-NEXT: Index: 1358; CHECK-NEXT: Index: 1
359; CHECK-NEXT: Offset: 0x00000548359; CHECK-NEXT: Offset: 0x00000548
360; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB360; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
361; CHECK-NEXT: Index: 1361; CHECK-NEXT: Index: 1
362; CHECK-NEXT: Offset: 0x00000554362; CHECK-NEXT: Offset: 0x00000554
363; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB363; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
364; CHECK-NEXT: Index: 1364; CHECK-NEXT: Index: 1
365; CHECK-NEXT: Offset: 0x00000560365; CHECK-NEXT: Offset: 0x00000560
366; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB366; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
367; CHECK-NEXT: Index: 1367; CHECK-NEXT: Index: 1
368; CHECK-NEXT: Offset: 0x0000056C368; CHECK-NEXT: Offset: 0x0000056C
369; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB369; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
370; CHECK-NEXT: Index: 1370; CHECK-NEXT: Index: 1
371; CHECK-NEXT: Offset: 0x00000578371; CHECK-NEXT: Offset: 0x00000578
372; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB372; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
373; CHECK-NEXT: Index: 1373; CHECK-NEXT: Index: 1
374; CHECK-NEXT: Offset: 0x00000584374; CHECK-NEXT: Offset: 0x00000584
375; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB375; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
376; CHECK-NEXT: Index: 1376; CHECK-NEXT: Index: 1
377; CHECK-NEXT: Offset: 0x00000590377; CHECK-NEXT: Offset: 0x00000590
378; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB378; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
379; CHECK-NEXT: Index: 1379; CHECK-NEXT: Index: 1
380; CHECK-NEXT: Offset: 0x0000059C380; CHECK-NEXT: Offset: 0x0000059C
381; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB381; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
382; CHECK-NEXT: Index: 1382; CHECK-NEXT: Index: 1
383; CHECK-NEXT: Offset: 0x000005A8383; CHECK-NEXT: Offset: 0x000005A8
384; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB384; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
385; CHECK-NEXT: Index: 1385; CHECK-NEXT: Index: 1
386; CHECK-NEXT: Offset: 0x000005B4386; CHECK-NEXT: Offset: 0x000005B4
387; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB387; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
388; CHECK-NEXT: Index: 1388; CHECK-NEXT: Index: 1
389; CHECK-NEXT: Offset: 0x000005C0389; CHECK-NEXT: Offset: 0x000005C0
390; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB390; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
391; CHECK-NEXT: Index: 1391; CHECK-NEXT: Index: 1
392; CHECK-NEXT: Offset: 0x000005CC392; CHECK-NEXT: Offset: 0x000005CC
393; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB393; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
394; CHECK-NEXT: Index: 1394; CHECK-NEXT: Index: 1
395; CHECK-NEXT: Offset: 0x000005D8395; CHECK-NEXT: Offset: 0x000005D8
396; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB396; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
397; CHECK-NEXT: Index: 1397; CHECK-NEXT: Index: 1
398; CHECK-NEXT: Offset: 0x000005E4398; CHECK-NEXT: Offset: 0x000005E4
399; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB399; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
400; CHECK-NEXT: Index: 1400; CHECK-NEXT: Index: 1
401; CHECK-NEXT: Offset: 0x000005F0401; CHECK-NEXT: Offset: 0x000005F0
402; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB402; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
403; CHECK-NEXT: Index: 129403; CHECK-NEXT: Index: 129
404; CHECK-NEXT: Offset: 0x000005FC404; CHECK-NEXT: Offset: 0x000005FC
405; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_LEB405; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_LEB
406; CHECK-NEXT: Index: 129406; CHECK-NEXT: Index: 129
407; CHECK-NEXT: Offset: 0x00000608407; CHECK-NEXT: Offset: 0x00000608
408; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB408; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
409; CHECK-NEXT: Index: 131409; CHECK-NEXT: Index: 131
410; CHECK-NEXT: Offset: 0x00000611410; CHECK-NEXT: Offset: 0x00000611
411; CHECK-NEXT: Functions:411; CHECK-NEXT: Functions:
...@@ -802,13 +802,13 @@ entry:...@@ -802,13 +802,13 @@ entry:
802; CHECK-NEXT: - Type: DATA802; CHECK-NEXT: - Type: DATA
803; CHECK-NEXT: Segments:803; CHECK-NEXT: Segments:
804; CHECK-NEXT: - SectionOffset: 6804; CHECK-NEXT: - SectionOffset: 6
805; CHECK-NEXT: MemoryIndex: 0805; CHECK-NEXT: InitFlags: 0
806; CHECK-NEXT: Offset:806; CHECK-NEXT: Offset:
807; CHECK-NEXT: Opcode: I32_CONST807; CHECK-NEXT: Opcode: I32_CONST
808; CHECK-NEXT: Value: 0808; CHECK-NEXT: Value: 0
809; CHECK-NEXT: Content: '01000000'809; CHECK-NEXT: Content: '01000000'
810; CHECK-NEXT: - SectionOffset: 15810; CHECK-NEXT: - SectionOffset: 15
811; CHECK-NEXT: MemoryIndex: 0811; CHECK-NEXT: InitFlags: 0
812; CHECK-NEXT: Offset:812; CHECK-NEXT: Offset:
813; CHECK-NEXT: Opcode: I32_CONST813; CHECK-NEXT: Opcode: I32_CONST
814; CHECK-NEXT: Value: 4814; CHECK-NEXT: Value: 4
deps/lld/test/wasm/pie.ll created+58
...@@ -0,0 +1,58 @@
1; RUN: llc -relocation-model=pic -filetype=obj %s -o %t.o
2; RUN: wasm-ld --no-gc-sections --allow-undefined -pie -o %t.wasm %t.o
3; RUN: obj2yaml %t.wasm | FileCheck %s
4
5target triple = "wasm32-unknown-emscripten"
6
7@data = global i32 2, align 4
8@data_external = external global i32
9@indirect_func = local_unnamed_addr global i32 ()* @foo, align 4
10
11@data_addr = local_unnamed_addr global i32* @data, align 4
12@data_addr_external = local_unnamed_addr global i32* @data_external, align 4
13
14define hidden i32 @foo() {
15entry:
16 ; To ensure we use __stack_pointer
17 %ptr = alloca i32
18 %0 = load i32, i32* @data, align 4
19 %1 = load i32 ()*, i32 ()** @indirect_func, align 4
20 call i32 %1()
21 ret i32 %0
22}
23
24define default i32** @get_data_address() {
25entry:
26 ret i32** @data_addr_external
27}
28
29define void @_start() {
30 ret void
31}
32
33; CHECK: - Type: IMPORT
34; CHECK-NEXT: Imports:
35; CHECK-NEXT: - Module: env
36; CHECK-NEXT: Field: __indirect_function_table
37; CHECK-NEXT: Kind: TABLE
38; CHECK-NEXT: Table:
39; CHECK-NEXT: ElemType: FUNCREF
40; CHECK-NEXT: Limits:
41; CHECK-NEXT: Initial: 0x00000001
42; CHECK-NEXT: - Module: env
43; CHECK-NEXT: Field: __stack_pointer
44; CHECK-NEXT: Kind: GLOBAL
45; CHECK-NEXT: GlobalType: I32
46; CHECK-NEXT: GlobalMutable: true
47; CHECK-NEXT: - Module: env
48; CHECK-NEXT: Field: __memory_base
49; CHECK-NEXT: Kind: GLOBAL
50; CHECK-NEXT: GlobalType: I32
51; CHECK-NEXT: GlobalMutable: false
52; CHECK-NEXT: - Module: env
53; CHECK-NEXT: Field: __table_base
54; CHECK-NEXT: Kind: GLOBAL
55; CHECK-NEXT: GlobalType: I32
56; CHECK-NEXT: GlobalMutable: false
57
58
deps/lld/test/wasm/reloc-addend.ll+1-1
...@@ -13,7 +13,7 @@ target triple = "wasm32-unknown-unknown"...@@ -13,7 +13,7 @@ target triple = "wasm32-unknown-unknown"
1313
14; CHECK: - Type: DATA14; CHECK: - Type: DATA
15; CHECK-NEXT: Relocations: 15; CHECK-NEXT: Relocations:
16; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I3216; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_I32
17; CHECK-NEXT: Index: 017; CHECK-NEXT: Index: 0
18; CHECK-NEXT: Offset: 0x0000013D18; CHECK-NEXT: Offset: 0x0000013D
19; CHECK-NEXT: Addend: 6419; CHECK-NEXT: Addend: 64
deps/lld/test/wasm/relocatable.ll+15-15
...@@ -79,19 +79,19 @@ entry:...@@ -79,19 +79,19 @@ entry:
79; CHECK-NEXT: Functions: [ 4, 1, 2 ]79; CHECK-NEXT: Functions: [ 4, 1, 2 ]
80; CHECK-NEXT: - Type: CODE80; CHECK-NEXT: - Type: CODE
81; CHECK-NEXT: Relocations:81; CHECK-NEXT: Relocations:
82; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB82; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
83; CHECK-NEXT: Index: 183; CHECK-NEXT: Index: 1
84; CHECK-NEXT: Offset: 0x0000000484; CHECK-NEXT: Offset: 0x00000004
85; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB85; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
86; CHECK-NEXT: Index: 286; CHECK-NEXT: Index: 2
87; CHECK-NEXT: Offset: 0x0000000A87; CHECK-NEXT: Offset: 0x0000000A
88; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB88; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
89; CHECK-NEXT: Index: 489; CHECK-NEXT: Index: 4
90; CHECK-NEXT: Offset: 0x0000001390; CHECK-NEXT: Offset: 0x00000013
91; CHECK-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB91; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
92; CHECK-NEXT: Index: 592; CHECK-NEXT: Index: 5
93; CHECK-NEXT: Offset: 0x0000001A93; CHECK-NEXT: Offset: 0x0000001A
94; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_SLEB94; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_SLEB
95; CHECK-NEXT: Index: 795; CHECK-NEXT: Index: 7
96; CHECK-NEXT: Offset: 0x0000002696; CHECK-NEXT: Offset: 0x00000026
97; CHECK-NEXT: Functions:97; CHECK-NEXT: Functions:
...@@ -106,51 +106,51 @@ entry:...@@ -106,51 +106,51 @@ entry:
106; CHECK-NEXT: Body: 419C808080000B106; CHECK-NEXT: Body: 419C808080000B
107; CHECK-NEXT: - Type: DATA107; CHECK-NEXT: - Type: DATA
108; CHECK-NEXT: Relocations:108; CHECK-NEXT: Relocations:
109; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32109; CHECK-NEXT: - Type: R_WASM_TABLE_INDEX_I32
110; CHECK-NEXT: Index: 3110; CHECK-NEXT: Index: 3
111; CHECK-NEXT: Offset: 0x00000012111; CHECK-NEXT: Offset: 0x00000012
112; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32112; CHECK-NEXT: - Type: R_WASM_TABLE_INDEX_I32
113; CHECK-NEXT: Index: 4113; CHECK-NEXT: Index: 4
114; CHECK-NEXT: Offset: 0x0000001B114; CHECK-NEXT: Offset: 0x0000001B
115; CHECK-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_I32115; CHECK-NEXT: - Type: R_WASM_TABLE_INDEX_I32
116; CHECK-NEXT: Index: 5116; CHECK-NEXT: Index: 5
117; CHECK-NEXT: Offset: 0x00000024117; CHECK-NEXT: Offset: 0x00000024
118; CHECK-NEXT: - Type: R_WEBASSEMBLY_MEMORY_ADDR_I32118; CHECK-NEXT: - Type: R_WASM_MEMORY_ADDR_I32
119; CHECK-NEXT: Index: 12119; CHECK-NEXT: Index: 12
120; CHECK-NEXT: Offset: 0x0000002D120; CHECK-NEXT: Offset: 0x0000002D
121; CHECK-NEXT: Segments:121; CHECK-NEXT: Segments:
122; CHECK-NEXT: - SectionOffset: 6122; CHECK-NEXT: - SectionOffset: 6
123; CHECK-NEXT: MemoryIndex: 0123; CHECK-NEXT: InitFlags: 0
124; CHECK-NEXT: Offset:124; CHECK-NEXT: Offset:
125; CHECK-NEXT: Opcode: I32_CONST125; CHECK-NEXT: Opcode: I32_CONST
126; CHECK-NEXT: Value: 0126; CHECK-NEXT: Value: 0
127; CHECK-NEXT: Content: 68656C6C6F0A00127; CHECK-NEXT: Content: 68656C6C6F0A00
128; CHECK-NEXT: - SectionOffset: 18128; CHECK-NEXT: - SectionOffset: 18
129; CHECK-NEXT: MemoryIndex: 0129; CHECK-NEXT: InitFlags: 0
130; CHECK-NEXT: Offset:130; CHECK-NEXT: Offset:
131; CHECK-NEXT: Opcode: I32_CONST131; CHECK-NEXT: Opcode: I32_CONST
132; CHECK-NEXT: Value: 8132; CHECK-NEXT: Value: 8
133; CHECK-NEXT: Content: '01000000'133; CHECK-NEXT: Content: '01000000'
134; CHECK-NEXT: - SectionOffset: 27134; CHECK-NEXT: - SectionOffset: 27
135; CHECK-NEXT: MemoryIndex: 0135; CHECK-NEXT: InitFlags: 0
136; CHECK-NEXT: Offset:136; CHECK-NEXT: Offset:
137; CHECK-NEXT: Opcode: I32_CONST137; CHECK-NEXT: Opcode: I32_CONST
138; CHECK-NEXT: Value: 12138; CHECK-NEXT: Value: 12
139; CHECK-NEXT: Content: '02000000'139; CHECK-NEXT: Content: '02000000'
140; CHECK-NEXT: - SectionOffset: 36140; CHECK-NEXT: - SectionOffset: 36
141; CHECK-NEXT: MemoryIndex: 0141; CHECK-NEXT: InitFlags: 0
142; CHECK-NEXT: Offset:142; CHECK-NEXT: Offset:
143; CHECK-NEXT: Opcode: I32_CONST143; CHECK-NEXT: Opcode: I32_CONST
144; CHECK-NEXT: Value: 16144; CHECK-NEXT: Value: 16
145; CHECK-NEXT: Content: '03000000'145; CHECK-NEXT: Content: '03000000'
146; CHECK-NEXT: - SectionOffset: 45146; CHECK-NEXT: - SectionOffset: 45
147; CHECK-NEXT: MemoryIndex: 0147; CHECK-NEXT: InitFlags: 0
148; CHECK-NEXT: Offset:148; CHECK-NEXT: Offset:
149; CHECK-NEXT: Opcode: I32_CONST149; CHECK-NEXT: Opcode: I32_CONST
150; CHECK-NEXT: Value: 24150; CHECK-NEXT: Value: 24
151; CHECK-NEXT: Content: '00000000'151; CHECK-NEXT: Content: '00000000'
152; CHECK-NEXT: - SectionOffset: 54152; CHECK-NEXT: - SectionOffset: 54
153; CHECK-NEXT: MemoryIndex: 0153; CHECK-NEXT: InitFlags: 0
154; CHECK-NEXT: Offset:154; CHECK-NEXT: Offset:
155; CHECK-NEXT: Opcode: I32_CONST155; CHECK-NEXT: Opcode: I32_CONST
156; CHECK-NEXT: Value: 28156; CHECK-NEXT: Value: 28
deps/lld/test/wasm/reproduce.ll created+27
...@@ -0,0 +1,27 @@
1; REQUIRES: shell
2; RUN: rm -rf %t.dir
3; RUN: mkdir -p %t.dir
4; RUN: llc -filetype=obj %s -o %t.dir/foo.o
5; RUN: wasm-ld --reproduce=%t.dir/repro.tar -o %t.dir/out.wasm %t.dir/foo.o
6
7; RUN: cd %t.dir
8; RUN: tar tf repro.tar | FileCheck --check-prefix=TAR %s
9
10; TAR: repro/response.txt
11; TAR: repro/version.txt
12; TAR: repro/{{.*}}/foo.o
13
14; RUN: tar xf repro.tar
15; RUN: FileCheck --check-prefix=RSP %s < repro/response.txt
16
17; RSP: -o {{.*}}out.wasm
18; RSP: {{.*}}/foo.o
19
20; RUN: FileCheck %s --check-prefix=VERSION < repro/version.txt
21; VERSION: LLD
22
23target triple = "wasm32-unknown-unknown"
24
25define void @_start() {
26 ret void
27}
deps/lld/test/wasm/section-symbol-relocs.yaml created+61
...@@ -0,0 +1,61 @@
1# RUN: yaml2obj %s -o %t.o
2# RUN: llc -filetype=obj %S/Inputs/custom.ll -o %t2.o
3# RUN: wasm-ld --no-entry -o - %t2.o %t.o | obj2yaml | FileCheck %s
4# RUN: wasm-ld -r --no-entry -o - %t2.o %t.o | obj2yaml | FileCheck %s -check-prefix=RELOC
5
6--- !WASM
7FileHeader:
8 Version: 0x00000001
9Sections:
10 - Type: CUSTOM
11 Name: green
12 Payload: 'AA0000000000000000'
13 Relocations:
14 - Type: R_WASM_SECTION_OFFSET_I32
15 Index: 0
16 Offset: 0x00000001
17 - Type: R_WASM_SECTION_OFFSET_I32
18 Index: 1
19 Offset: 0x00000005
20 - Type: CUSTOM
21 Name: red
22 Payload: 'BB0000000000000000'
23 - Type: CUSTOM
24 Name: linking
25 Version: 2
26 SymbolTable:
27 - Index: 0
28 Kind: SECTION
29 Section: 0
30 Flags: [ BINDING_LOCAL ]
31 - Index: 1
32 Kind: SECTION
33 Section: 1
34 Flags: [ BINDING_LOCAL ]
35...
36
37# CHECK: Name: green
38# CHECK-NEXT: Payload: 626172717578AA0600000003000000
39# CHECK: Name: red
40# CHECK-NEXT: Payload: 666F6FBB0000000000000000
41
42# RELOC: Relocations:
43# RELOC-NEXT: - Type: R_WASM_SECTION_OFFSET_I32
44# RELOC-NEXT: Index: 0
45# RELOC-NEXT: Offset: 0x00000007
46# RELOC-NEXT: Addend: 6
47# RELOC-NEXT: - Type: R_WASM_SECTION_OFFSET_I32
48# RELOC-NEXT: Index: 1
49# RELOC-NEXT: Offset: 0x0000000B
50# RELOC-NEXT: Addend: 3
51# RELOC-NEXT: Name: green
52#
53# RELOC: SymbolTable:
54# RELOC-NEXT: - Index: 0
55# RELOC-NEXT: Kind: SECTION
56# RELOC-NEXT: Flags: [ BINDING_LOCAL ]
57# RELOC-NEXT: Section: 2
58# RELOC-NEXT: - Index: 1
59# RELOC-NEXT: Kind: SECTION
60# RELOC-NEXT: Flags: [ BINDING_LOCAL ]
61# RELOC-NEXT: Section: 3
deps/lld/test/wasm/shared-memory-no-atomics.yaml created+60
...@@ -0,0 +1,60 @@
1# RUN: yaml2obj %s -o %t1.o
2
3# RUN: wasm-ld --no-entry %t1.o -o - | obj2yaml | FileCheck %s --check-prefix NO-SHARED
4
5# RUN: not wasm-ld --no-entry --shared-memory --max-memory=131072 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED
6
7--- !WASM
8FileHeader:
9 Version: 0x00000001
10Sections:
11 - Type: IMPORT
12 Imports:
13 - Module: env
14 Field: __linear_memory
15 Kind: MEMORY
16 Memory:
17 Initial: 0x00000001
18 - Module: env
19 Field: __indirect_function_table
20 Kind: TABLE
21 Table:
22 ElemType: FUNCREF
23 Limits:
24 Initial: 0x00000000
25 - Type: DATA
26 Segments:
27 - SectionOffset: 6
28 InitFlags: 0
29 Offset:
30 Opcode: I32_CONST
31 Value: 0
32 Content: 68656C6C6F0A00
33 - Type: CUSTOM
34 Name: linking
35 Version: 2
36 SymbolTable:
37 - Index: 0
38 Kind: DATA
39 Name: hello_str
40 Flags: [ ]
41 Segment: 0
42 Size: 7
43 SegmentInfo:
44 - Index: 0
45 Name: .rodata.hello_str
46 Alignment: 0
47 Flags: [ ]
48 - Type: CUSTOM
49 Name: target_features
50 Features:
51 - Prefix: DISALLOWED
52 Name: "atomics"
53...
54
55# NO-SHARED: - Type: MEMORY
56# NO-SHARED-NEXT: Memories:
57# NO-SHARED-NEXT: - Initial: 0x00000002
58# NO-SHARED-NOT: Maximum:
59
60# SHARED: 'atomics' feature is disallowed by {{.*}}shared-memory-no-atomics.yaml.tmp1.o, so --shared-memory must not be used{{$}}
deps/lld/test/wasm/shared-memory.yaml created+75
...@@ -0,0 +1,75 @@
1# RUN: yaml2obj %s -o %t1.o
2
3# RUN: not wasm-ld --no-entry --shared-memory --active-segments %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-NO-MAX
4
5# RUN: not wasm-ld --no-entry --shared-memory --active-segments --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix SHARED-UNALIGNED
6
7# RUN: wasm-ld --no-entry --shared-memory --active-segments --max-memory=131072 %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
8
9# RUN: not wasm-ld --no-entry --features=atomics %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-NO-SHARED
10
11# RUN: not wasm-ld --no-entry --features=atomics --shared-memory --active-segments %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-NO-MAX
12
13# RUN: not wasm-ld --no-entry --features=atomics --shared-memory --active-segments --max-memory=100000 %t1.o -o - 2>&1 | FileCheck %s --check-prefix ATOMICS-UNALIGNED
14
15# RUN: wasm-ld --no-entry --features=atomics --shared-memory --active-segments --max-memory=131072 %t1.o -o - | obj2yaml | FileCheck %s --check-prefix SHARED
16
17
18--- !WASM
19FileHeader:
20 Version: 0x00000001
21Sections:
22 - Type: IMPORT
23 Imports:
24 - Module: env
25 Field: __linear_memory
26 Kind: MEMORY
27 Memory:
28 Initial: 0x00000001
29 - Module: env
30 Field: __indirect_function_table
31 Kind: TABLE
32 Table:
33 ElemType: FUNCREF
34 Limits:
35 Initial: 0x00000000
36 - Type: DATA
37 Segments:
38 - SectionOffset: 6
39 InitFlags: 0
40 Offset:
41 Opcode: I32_CONST
42 Value: 0
43 Content: 68656C6C6F0A00
44 - Type: CUSTOM
45 Name: linking
46 Version: 2
47 SymbolTable:
48 - Index: 0
49 Kind: DATA
50 Name: hello_str
51 Flags: [ ]
52 Segment: 0
53 Size: 7
54 SegmentInfo:
55 - Index: 0
56 Name: .rodata.hello_str
57 Alignment: 0
58 Flags: [ ]
59...
60
61# SHARED-NO-MAX: maximum memory too small, 66560 bytes needed{{$}}
62
63# SHARED-UNALIGNED: maximum memory must be 65536-byte aligned{{$}}
64
65# SHARED: - Type: MEMORY
66# SHARED-NEXT: Memories:
67# SHARED-NEXT: - Flags: [ HAS_MAX, IS_SHARED ]
68# SHARED-NEXT: Initial: 0x00000002
69# SHARED-NEXT: Maximum: 0x00000002
70
71# ATOMICS-NO-SHARED: 'atomics' feature is used, so --shared-memory must be used{{$}}
72
73# ATOMICS-NO-MAX: maximum memory too small, 66560 bytes needed{{$}}
74
75# ATOMICS-UNALIGNED: maximum memory must be 65536-byte aligned{{$}}
deps/lld/test/wasm/shared-needed.ll created+38
...@@ -0,0 +1,38 @@
1; RUN: llc -filetype=obj %s -o %t.o
2; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
3
4; RUN: wasm-ld -shared -o %t1.so %t.o
5; RUN: obj2yaml %t1.so | FileCheck %s -check-prefix=SO1
6
7; RUN: wasm-ld -shared -o %t2.so %t1.so %t.ret32.o
8; RUN: obj2yaml %t2.so | FileCheck %s -check-prefix=SO2
9
10target triple = "wasm32-unknown-unknown"
11
12@data = global i32 2, align 4
13
14define default void @foo() {
15entry:
16 ret void
17}
18
19; SO1: Sections:
20; SO1-NEXT: - Type: CUSTOM
21; SO1-NEXT: Name: dylink
22; SO1-NEXT: MemorySize: 4
23; SO1-NEXT: MemoryAlignment: 2
24; SO1-NEXT: TableSize: 0
25; SO1-NEXT: TableAlignment: 0
26; SO1-NEXT: Needed: []
27; SO1-NEXT: - Type: TYPE
28
29; SO2: Sections:
30; SO2-NEXT: - Type: CUSTOM
31; SO2-NEXT: Name: dylink
32; SO2-NEXT: MemorySize: 0
33; SO2-NEXT: MemoryAlignment: 0
34; SO2-NEXT: TableSize: 0
35; SO2-NEXT: TableAlignment: 0
36; SO2-NEXT: Needed:
37; SO2-NEXT: - shared-needed.ll.tmp1.so
38; SO2-NEXT: - Type: TYPE
deps/lld/test/wasm/shared.ll+87-14
...@@ -1,44 +1,74 @@...@@ -1,44 +1,74 @@
1; RUN: llc -O0 -filetype=obj %s -o %t.o1; RUN: llc -relocation-model=pic -filetype=obj %s -o %t.o
2; RUN: wasm-ld -shared -o %t.wasm %t.o2; RUN: wasm-ld -shared -o %t.wasm %t.o
3; RUN: obj2yaml %t.wasm | FileCheck %s3; RUN: obj2yaml %t.wasm | FileCheck %s
44
5target triple = "wasm32-unknown-unknown"5target triple = "wasm32-unknown-emscripten"
66
7@data = hidden global i32 2, align 47@data = hidden global i32 2, align 4
8@indirect_func = local_unnamed_addr global void ()* @foo, align 48@data_external = external global i32
9@indirect_func = local_unnamed_addr global i32 ()* @foo, align 4
9@indirect_func_external = local_unnamed_addr global void ()* @func_external, align 410@indirect_func_external = local_unnamed_addr global void ()* @func_external, align 4
1011
11define default void @foo() {12; Test data relocations
13@data_addr = local_unnamed_addr global i32* @data, align 4
14; .. against external symbols
15@data_addr_external = local_unnamed_addr global i32* @data_external, align 4
16; .. including addends
17%struct.s = type { i32, i32 }
18@extern_struct = external global %struct.s
19@extern_struct_internal_ptr = local_unnamed_addr global i32* getelementptr inbounds (%struct.s, %struct.s* @extern_struct, i32 0, i32 1), align 4
20
21define hidden i32 @foo() {
12entry:22entry:
13 ; To ensure we use __stack_pointer23 ; To ensure we use __stack_pointer
14 %ptr = alloca i3224 %ptr = alloca i32
15 %0 = load i32, i32* @data, align 425 %0 = load i32, i32* @data, align 4
16 %1 = load i32, i32* @data_external, align 426 %1 = load i32 ()*, i32 ()** @indirect_func, align 4
17 %2 = load void ()*, void ()** @indirect_func, align 427 call i32 %1()
18 call void %2()28 ret i32 %0
19 ret void
20}29}
2130
22declare void @func_external()31define hidden i32* @get_data_address() {
32entry:
33 ret i32* @data_external
34}
2335
24@data_external = external global i3236define hidden i8* @get_func_address() {
37entry:
38 ret i8* bitcast (void ()* @func_external to i8*)
39}
2540
41define default i8* @get_local_func_address() {
42entry:
43 ; Verify that a function which is otherwise not address taken *is* added to
44 ; the wasm table with referenced via R_WASM_TABLE_INDEX_REL_SLEB
45 ret i8* bitcast (i8* ()* @get_func_address to i8*)
46}
47
48declare void @func_external()
2649
27; check for dylink section at start50; check for dylink section at start
2851
29; CHECK: Sections:52; CHECK: Sections:
30; CHECK-NEXT: - Type: CUSTOM53; CHECK-NEXT: - Type: CUSTOM
31; CHECK-NEXT: Name: dylink54; CHECK-NEXT: Name: dylink
32; CHECK-NEXT: MemorySize: 855; CHECK-NEXT: MemorySize: 24
33; CHECK-NEXT: MemoryAlignment: 256; CHECK-NEXT: MemoryAlignment: 2
34; CHECK-NEXT: TableSize: 257; CHECK-NEXT: TableSize: 2
35; CHECK-NEXT: TableAlignment: 058; CHECK-NEXT: TableAlignment: 0
59; CHECK-NEXT: Needed: []
60; CHECK-NEXT: - Type: TYPE
3661
37; check for import of __table_base and __memory_base globals62; check for import of __table_base and __memory_base globals
3863
39; CHECK: - Type: IMPORT64; CHECK: - Type: IMPORT
40; CHECK-NEXT: Imports:65; CHECK-NEXT: Imports:
41; CHECK-NEXT: - Module: env66; CHECK-NEXT: - Module: env
67; CHECK-NEXT: Field: memory
68; CHECK-NEXT: Kind: MEMORY
69; CHECK-NEXT: Memory:
70; CHECK-NEXT: Initial: 0x0000000
71; CHECK-NEXT: - Module: env
42; CHECK-NEXT: Field: __indirect_function_table72; CHECK-NEXT: Field: __indirect_function_table
43; CHECK-NEXT: Kind: TABLE73; CHECK-NEXT: Kind: TABLE
44; CHECK-NEXT: Table:74; CHECK-NEXT: Table:
...@@ -60,6 +90,37 @@ declare void @func_external()...@@ -60,6 +90,37 @@ declare void @func_external()
60; CHECK-NEXT: Kind: GLOBAL90; CHECK-NEXT: Kind: GLOBAL
61; CHECK-NEXT: GlobalType: I3291; CHECK-NEXT: GlobalType: I32
62; CHECK-NEXT: GlobalMutable: false92; CHECK-NEXT: GlobalMutable: false
93; CHECK-NEXT: - Module: env
94; CHECK-NEXT: Field: func_external
95; CHECK-NEXT: Kind: FUNCTION
96; CHECK-NEXT: SigIndex: 1
97; CHECK-NEXT: - Module: GOT.mem
98; CHECK-NEXT: Field: indirect_func
99; CHECK-NEXT: Kind: GLOBAL
100; CHECK-NEXT: GlobalType: I32
101; CHECK-NEXT: GlobalMutable: true
102; CHECK-NEXT: - Module: GOT.func
103; CHECK-NEXT: Field: func_external
104; CHECK-NEXT: Kind: GLOBAL
105; CHECK-NEXT: GlobalType: I32
106; CHECK-NEXT: GlobalMutable: true
107; CHECK-NEXT: - Module: GOT.mem
108; CHECK-NEXT: Field: data_external
109; CHECK-NEXT: Kind: GLOBAL
110; CHECK-NEXT: GlobalType: I32
111; CHECK-NEXT: GlobalMutable: true
112; CHECK-NEXT: - Module: GOT.mem
113; CHECK-NEXT: Field: extern_struct
114; CHECK-NEXT: Kind: GLOBAL
115; CHECK-NEXT: GlobalType: I32
116; CHECK-NEXT: GlobalMutable: true
117; CHECK-NEXT: - Type: FUNCTION
118
119; CHECK: - Type: EXPORT
120; CHECK-NEXT: Exports:
121; CHECK-NEXT: - Name: __wasm_call_ctors
122; CHECK-NEXT: Kind: FUNCTION
123; CHECK-NEXT: Index: 1
63124
64; check for elem segment initialized with __table_base global as offset125; check for elem segment initialized with __table_base global as offset
65126
...@@ -68,15 +129,27 @@ declare void @func_external()...@@ -68,15 +129,27 @@ declare void @func_external()
68; CHECK-NEXT: - Offset:129; CHECK-NEXT: - Offset:
69; CHECK-NEXT: Opcode: GLOBAL_GET130; CHECK-NEXT: Opcode: GLOBAL_GET
70; CHECK-NEXT: Index: 2131; CHECK-NEXT: Index: 2
71; CHECK-NEXT: Functions: [ 2, 0 ]132; CHECK-NEXT: Functions: [ 4, 3 ]
133
134; check the generated code in __wasm_call_ctors and __wasm_apply_relocs functions
135; TODO(sbc): Disassemble and verify instructions.
136
137; CHECK: - Type: CODE
138; CHECK-NEXT: Functions:
139; CHECK-NEXT: - Index: 1
140; CHECK-NEXT: Locals: []
141; CHECK-NEXT: Body: 10020B
142; CHECK-NEXT: - Index: 2
143; CHECK-NEXT: Locals: []
144; CHECK-NEXT: Body: 230141046A230241016A360200230141086A23043602002301410C6A230141006A360200230141106A2305360200230141146A230641046A3602000B
72145
73; check the data segment initialized with __memory_base global as offset146; check the data segment initialized with __memory_base global as offset
74147
75; CHECK: - Type: DATA148; CHECK: - Type: DATA
76; CHECK-NEXT: Segments:149; CHECK-NEXT: Segments:
77; CHECK-NEXT: - SectionOffset: 6150; CHECK-NEXT: - SectionOffset: 6
78; CHECK-NEXT: MemoryIndex: 0151; CHECK-NEXT: InitFlags: 0
79; CHECK-NEXT: Offset:152; CHECK-NEXT: Offset:
80; CHECK-NEXT: Opcode: GLOBAL_GET153; CHECK-NEXT: Opcode: GLOBAL_GET
81; CHECK-NEXT: Index: 1154; CHECK-NEXT: Index: 1
82; CHECK-NEXT: Content: '0000000001000000'155; CHECK-NEXT: Content: '020000000100000000000000000000000000000000000000'
deps/lld/test/wasm/signature-mismatch-export.ll created+30
...@@ -0,0 +1,30 @@
1; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
2; RUN: llc -filetype=obj %s -o %t.main.o
3; RUN: wasm-ld --export=ret32 -o %t.wasm %t.main.o %t.ret32.o
4; RUN: obj2yaml %t.wasm | FileCheck %s
5
6target triple = "wasm32-unknown-unknown"
7
8declare i32 @ret32(i32)
9
10define void @_start() {
11entry:
12 %call1 = call i32 @ret32(i32 0)
13 ret void
14}
15
16; CHECK: - Type: EXPORT
17; CHECK: - Name: ret32
18; CHECK-NEXT: Kind: FUNCTION
19; CHECK-NEXT: Index: 2
20
21; CHECK: - Type: CUSTOM
22; CHECK-NEXT: Name: name
23; CHECK-NEXT: FunctionNames:
24; CHECK-NEXT: - Index: 0
25; CHECK-NEXT: Name: 'unreachable:ret32'
26; CHECK-NEXT: - Index: 1
27; CHECK-NEXT: Name: _start
28; CHECK-NEXT: - Index: 2
29; CHECK-NEXT: Name: ret32
30; CHECK-NEXT: ...
deps/lld/test/wasm/signature-mismatch-unknown.ll created+19
...@@ -0,0 +1,19 @@
1; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
2; RUN: llc -filetype=obj %s -o %t.main.o
3; RUN: wasm-ld --fatal-warnings -o %t.wasm %t.ret32.o %t.main.o
4; RUN: wasm-ld --fatal-warnings -o %t.wasm %t.main.o %t.ret32.o
5
6target triple = "wasm32-unknown-unknown"
7
8; Function declartion with incorrect signature.
9declare dso_local void @ret32()
10
11; Simply taking the address of the function should *not* generate the
12; the signature mismatch warning.
13@ptr = dso_local global i8* bitcast (void ()* @ret32 to i8*), align 8
14
15define hidden void @_start() local_unnamed_addr {
16 %addr = load i32 ()*, i32 ()** bitcast (i8** @ptr to i32 ()**), align 8
17 call i32 %addr()
18 ret void
19}
deps/lld/test/wasm/signature-mismatch.ll+39-14
...@@ -1,26 +1,51 @@...@@ -1,26 +1,51 @@
1; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o1; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
2; RUN: llc -filetype=obj %p/Inputs/call-ret32.ll -o %t.call.o
2; RUN: llc -filetype=obj %s -o %t.main.o3; RUN: llc -filetype=obj %s -o %t.main.o
3; RUN: not wasm-ld --fatal-warnings -o %t.wasm %t.main.o %t.ret32.o 2>&1 | FileCheck %s4; RUN: wasm-ld --export=call_ret32 --export=ret32 -o %t.wasm %t.main.o %t.ret32.o %t.call.o 2>&1 | FileCheck %s -check-prefix=WARN
4; Run the test again by with the object files in the other order to verify5; RUN: obj2yaml %t.wasm | FileCheck %s -check-prefix=YAML
5; the check works when the undefined symbol is resolved by an existing defined6; RUN: not wasm-ld --fatal-warnings -o %t.wasm %t.main.o %t.ret32.o %t.call.o 2>&1 | FileCheck %s -check-prefix=ERROR
6; one.
7; RUN: not wasm-ld --fatal-warnings -o %t.wasm %t.ret32.o %t.main.o 2>&1 | FileCheck %s -check-prefix=REVERSE
87
9target triple = "wasm32-unknown-unknown"8target triple = "wasm32-unknown-unknown"
109
10@ret32_address_main = global i32 (i32, i64, i32)* @ret32, align 4
11
11; Function Attrs: nounwind12; Function Attrs: nounwind
12define hidden void @_start() local_unnamed_addr #0 {13define hidden void @_start() local_unnamed_addr {
13entry:14entry:
14 %call = tail call i32 @ret32(i32 1, i64 2, i32 3) #215 %call1 = call i32 @ret32(i32 1, i64 2, i32 3)
16 %addr = load i32 (i32, i64, i32)*, i32 (i32, i64, i32)** @ret32_address_main, align 4
17 %call2 = call i32 %addr(i32 1, i64 2, i32 3)
15 ret void18 ret void
16}19}
1720
18declare i32 @ret32(i32, i64, i32) local_unnamed_addr #121declare i32 @ret32(i32, i64, i32) local_unnamed_addr
22
23; WARN: warning: function signature mismatch: ret32
24; WARN-NEXT: >>> defined as (i32, i64, i32) -> i32 in {{.*}}.main.o
25; WARN-NEXT: >>> defined as (f32) -> i32 in {{.*}}.ret32.o
26
27; ERROR: error: function signature mismatch: ret32
28; ERROR-NEXT: >>> defined as (i32, i64, i32) -> i32 in {{.*}}.main.o
29; ERROR-NEXT: >>> defined as (f32) -> i32 in {{.*}}.ret32.o
30
31; YAML: - Type: EXPORT
32; YAML: - Name: ret32
33; YAML-NEXT: Kind: FUNCTION
34; YAML-NEXT: Index: 2
35; YAML-NEXT: - Name: call_ret32
36; YAML-NEXT: Kind: FUNCTION
37; YAML-NEXT: Index: 3
1938
20; CHECK: error: function signature mismatch: ret3239; YAML: - Type: CUSTOM
21; CHECK-NEXT: >>> defined as (i32, i64, i32) -> i32 in {{.*}}.main.o40; YAML-NEXT: Name: name
22; CHECK-NEXT: >>> defined as (f32) -> i32 in {{.*}}.ret32.o41; YAML-NEXT: FunctionNames:
42; YAML-NEXT: - Index: 0
43; YAML-NEXT: Name: 'unreachable:ret32'
44; YAML-NEXT: - Index: 1
45; YAML-NEXT: Name: _start
46; YAML-NEXT: - Index: 2
47; YAML-NEXT: Name: ret32
48; YAML-NEXT: - Index: 3
49; YAML-NEXT: Name: call_ret32
50; YAML-NEXT: ...
2351
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
deps/lld/test/wasm/stack-first.test+6-5
...@@ -4,8 +4,7 @@...@@ -4,8 +4,7 @@
4; global should be initialized to 512.4; global should be initialized to 512.
55
6RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.o6RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.o
77RUN: wasm-ld -z stack-size=512 --stack-first --export=__data_end --export=__heap_base -o %t.wasm %t.o
8RUN: wasm-ld -z stack-size=512 --stack-first --allow-undefined -o %t.wasm %t.o
9RUN: obj2yaml %t.wasm | FileCheck %s8RUN: obj2yaml %t.wasm | FileCheck %s
109
11CHECK: - Type: GLOBAL10CHECK: - Type: GLOBAL
...@@ -33,10 +32,12 @@ CHECK-NEXT: Exports:...@@ -33,10 +32,12 @@ CHECK-NEXT: Exports:
33CHECK-NEXT: - Name: memory32CHECK-NEXT: - Name: memory
34CHECK-NEXT: Kind: MEMORY33CHECK-NEXT: Kind: MEMORY
35CHECK-NEXT: Index: 034CHECK-NEXT: Index: 0
36CHECK-NEXT: - Name: __heap_base35CHECK-NEXT: - Name: __data_end
37CHECK-NEXT: Kind: GLOBAL36CHECK-NEXT: Kind: GLOBAL
38CHECK-NEXT: Index: 137CHECK-NEXT: Index: 1
39CHECK-NEXT: - Name: __data_end38CHECK-NEXT: - Name: __heap_base
40CHECK-NEXT: Kind: GLOBAL39CHECK-NEXT: Kind: GLOBAL
41CHECK-NEXT: Index: 240CHECK-NEXT: Index: 2
4241CHECK-NEXT: - Name: _start
42CHECK-NEXT: Kind: FUNCTION
43CHECK-NEXT: Index: 0
deps/lld/test/wasm/stack-pointer.ll+1-1
...@@ -41,7 +41,7 @@ entry:...@@ -41,7 +41,7 @@ entry:
41; CHECK-NEXT: - Initial: 0x0000000041; CHECK-NEXT: - Initial: 0x00000000
42; CHECK-NEXT: - Type: CODE42; CHECK-NEXT: - Type: CODE
43; CHECK-NEXT: Relocations:43; CHECK-NEXT: Relocations:
44; CHECK-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB44; CHECK-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
45; CHECK-NEXT: Index: 145; CHECK-NEXT: Index: 1
46; CHECK-NEXT: Offset: 0x0000000446; CHECK-NEXT: Offset: 0x00000004
47; CHECK-NEXT: Functions:47; CHECK-NEXT: Functions:
deps/lld/test/wasm/startstop.ll created+53
...@@ -0,0 +1,53 @@
1; RUN: llc -filetype=obj -o %t.o %s
2; RUN: llc -filetype=obj %p/Inputs/explicit-section.ll -o %t2.o
3; RUN: wasm-ld --export=get_start --export=get_end --export=foo --export=var1 %t.o %t2.o -o %t.wasm
4; RUN: obj2yaml %t.wasm | FileCheck %s
5
6target triple = "wasm32-unknown-unknown"
7
8@foo = global i32 3, section "mysection", align 4
9@bar = global i32 4, section "mysection", align 4
10
11@__start_mysection = external global i8*
12@__stop_mysection = external global i8*
13
14define i8** @get_start() {
15 ret i8** @__start_mysection
16}
17
18define i8** @get_end() {
19 ret i8** @__stop_mysection
20}
21
22define void @_start() {
23entry:
24 ret void
25}
26; CHECK: - Type: CODE
27; CHECK-NEXT: Functions:
28; CHECK-NEXT: - Index: 0
29; CHECK-NEXT: Locals: []
30; CHECK-NEXT: Body: 4180888080000B
31; CHECK-NEXT: - Index: 1
32; CHECK-NEXT: Locals: []
33; CHECK-NEXT: Body: 4190888080000B
34; CHECK-NEXT: - Index: 2
35; CHECK-NEXT: Locals: []
36; CHECK-NEXT: Body: 0B
37; CHECK-NEXT: - Type: DATA
38; CHECK-NEXT: Segments:
39; CHECK-NEXT: - SectionOffset: 7
40; CHECK-NEXT: InitFlags: 0
41; CHECK-NEXT: Offset:
42; CHECK-NEXT: Opcode: I32_CONST
43; CHECK-NEXT: Value: 1024
44; CHECK-NEXT: Content: 03000000040000002A0000002B000000
45; CHECK-NEXT: - Type: CUSTOM
46; CHECK-NEXT: Name: name
47; CHECK-NEXT: FunctionNames:
48; CHECK-NEXT: - Index: 0
49; CHECK-NEXT: Name: get_start
50; CHECK-NEXT: - Index: 1
51; CHECK-NEXT: Name: get_end
52; CHECK-NEXT: - Index: 2
53; CHECK-NEXT: Name: _start
deps/lld/test/wasm/target-feature-disallowed.yaml created+72
...@@ -0,0 +1,72 @@
1# RUN: yaml2obj %s -o %t1.o
2
3# RUN: wasm-ld --no-entry --features=foo,bar,baz -o %t.specified.wasm %t1.o
4# RUN: obj2yaml %t.specified.wasm | FileCheck %s --check-prefix SPECIFIED
5
6# RUN: wasm-ld --no-entry --features=bar,baz,quux -o %t.unspecified.wasm %t1.o
7# RUN: obj2yaml %t.unspecified.wasm | FileCheck %s --check-prefix UNSPECIFIED
8
9# RUN: yaml2obj %S/Inputs/disallow-feature-foo.yaml -o %t.disallowed.o
10# RUN: wasm-ld --no-entry -o - %t1.o %t.disallowed.o | obj2yaml | FileCheck %s --check-prefix DISALLOWED
11
12# RUN: yaml2obj %S/Inputs/no-feature-foo.yaml -o %t.none.o
13# RUN: wasm-ld --no-entry -o - %t1.o %t.none.o | obj2yaml | FileCheck %s --check-prefix NONE
14
15# Check that the following combinations of feature linkage policies
16# give the expected results:
17#
18# DISALLOWED x DISALLOWED => NONE
19# DISALLOWED x NONE => NONE
20
21--- !WASM
22FileHeader:
23 Version: 0x00000001
24Sections:
25 - Type: CUSTOM
26 Name: linking
27 Version: 2
28 - Type: CUSTOM
29 Name: target_features
30 Features:
31 - Prefix: DISALLOWED
32 Name: "foo"
33 # included so output has target features section
34 - Prefix: USED
35 Name: "bar"
36...
37
38# SPECIFIED: - Type: CUSTOM
39# SPECIFIED-NEXT: Name: target_features
40# SPECIFIED-NEXT: Features:
41# SPECIFIED-NEXT: - Prefix: USED
42# SPECIFIED-NEXT: Name: bar
43# SPECIFIED-NEXT: - Prefix: USED
44# SPECIFIED-NEXT: Name: baz
45# SPECIFIED-NEXT: - Prefix: USED
46# SPECIFIED-NEXT: Name: foo
47# SPECIFIED-NEXT: ...
48
49# UNSPECIFIED: - Type: CUSTOM
50# UNSPECIFIED-NEXT: Name: target_features
51# UNSPECIFIED-NEXT: Features:
52# UNSPECIFIED-NEXT: - Prefix: USED
53# UNSPECIFIED-NEXT: Name: bar
54# UNSPECIFIED-NEXT: - Prefix: USED
55# UNSPECIFIED-NEXT: Name: baz
56# UNSPECIFIED-NEXT: - Prefix: USED
57# UNSPECIFIED-NEXT: Name: quux
58# UNSPECIFIED-NEXT: ...
59
60# DISALLOWED: - Type: CUSTOM
61# DISALLOWED-NEXT: Name: target_features
62# DISALLOWED-NEXT: Features:
63# DISALLOWED-NEXT: - Prefix: USED
64# DISALLOWED-NEXT: Name: bar
65# DISALLOWED-NEXT: ...
66
67# NONE: - Type: CUSTOM
68# NONE-NEXT: Name: target_features
69# NONE-NEXT: Features:
70# NONE-NEXT: - Prefix: USED
71# NONE-NEXT: Name: bar
72# NONE-NEXT: ...
deps/lld/test/wasm/target-feature-none.yaml created+33
...@@ -0,0 +1,33 @@
1# RUN: yaml2obj %s -o %t1.o
2
3# RUN: wasm-ld --no-entry -o - %t1.o | obj2yaml | FileCheck %s --check-prefix EMPTY
4
5# RUN: wasm-ld --no-entry --features= -o - %t1.o | obj2yaml | FileCheck %s --check-prefix EMPTY
6
7# RUN: wasm-ld --no-entry --features=foo,bar,baz -o - %t1.o | obj2yaml | FileCheck %s --check-prefix SPECIFIED
8
9--- !WASM
10FileHeader:
11 Version: 0x00000001
12Sections:
13 - Type: CUSTOM
14 Name: linking
15 Version: 2
16 - Type: CUSTOM
17 Name: target_features
18 Features: [ ]
19...
20
21# section is not emitted if it would be empty
22# EMPTY-NOT: target_features
23
24# SPECIFIED: - Type: CUSTOM
25# SPECIFIED-NEXT: Name: target_features
26# SPECIFIED-NEXT: Features:
27# SPECIFIED-NEXT: - Prefix: USED
28# SPECIFIED-NEXT: Name: bar
29# SPECIFIED-NEXT: - Prefix: USED
30# SPECIFIED-NEXT: Name: baz
31# SPECIFIED-NEXT: - Prefix: USED
32# SPECIFIED-NEXT: Name: foo
33# SPECIFIED-NEXT: ...
deps/lld/test/wasm/target-feature-required.yaml created+90
...@@ -0,0 +1,90 @@
1# RUN: yaml2obj %s -o %t1.o
2
3# RUN: wasm-ld --no-entry --features=foo,bar,baz -o - %t1.o | obj2yaml | FileCheck %s --check-prefix SPECIFIED
4
5# RUN: not wasm-ld --no-entry --features=bar,baz,quux -o /dev/null %t1.o 2>&1 | FileCheck %s --check-prefix UNSPECIFIED
6
7# RUN: wasm-ld --no-entry --no-check-features --features=bar,baz,quux -o - %t1.o | obj2yaml | FileCheck %s --check-prefix UNSPECIFIED-NOCHECK
8
9# RUN: yaml2obj %S/Inputs/require-feature-foo.yaml -o %t.required.o
10# RUN: wasm-ld --no-entry -o - %t1.o %t.required.o | obj2yaml | FileCheck %s --check-prefix REQUIRED
11
12# RUN: yaml2obj %S/Inputs/disallow-feature-foo.yaml -o %t.disallowed.o
13# RUN: not wasm-ld --no-entry -o /dev/null %t1.o %t.disallowed.o 2>&1 | FileCheck %s --check-prefix DISALLOWED
14
15# RUN: wasm-ld --no-entry --no-check-features -o - %t1.o %t.disallowed.o | obj2yaml | FileCheck %s --check-prefix DISALLOWED-NOCHECK
16
17# RUN: yaml2obj %S/Inputs/no-feature-foo.yaml -o %t.none.o
18# RUN: not wasm-ld --no-entry -o /dev/null %t1.o %t.none.o 2>&1 | FileCheck %s --check-prefix NONE
19
20# RUN: wasm-ld --no-entry --no-check-features -o - %t1.o %t.none.o | obj2yaml | FileCheck %s --check-prefix NONE-NOCHECK
21
22# Check that the following combinations of feature linkage policies
23# give the expected results:
24#
25# REQUIRED x REQUIRED => USED
26# REQUIRED x DISALLOWED => Error
27# REQUIRED x NONE => Error
28
29--- !WASM
30FileHeader:
31 Version: 0x00000001
32Sections:
33 - Type: CUSTOM
34 Name: linking
35 Version: 2
36 - Type: CUSTOM
37 Name: target_features
38 Features:
39 - Prefix: REQUIRED
40 Name: "foo"
41...
42
43# SPECIFIED: - Type: CUSTOM
44# SPECIFIED-NEXT: Name: target_features
45# SPECIFIED-NEXT: Features:
46# SPECIFIED-NEXT: - Prefix: USED
47# SPECIFIED-NEXT: Name: bar
48# SPECIFIED-NEXT: - Prefix: USED
49# SPECIFIED-NEXT: Name: baz
50# SPECIFIED-NEXT: - Prefix: USED
51# SPECIFIED-NEXT: Name: foo
52# SPECIFIED-NEXT: ...
53
54# UNSPECIFIED: Target feature 'foo' used by {{.*}}target-feature-required.yaml.tmp1.o is not allowed.{{$}}
55
56# UNSPECIFIED-NOCHECK: - Type: CUSTOM
57# UNSPECIFIED-NOCHECK-NEXT: Name: target_features
58# UNSPECIFIED-NOCHECK-NEXT: Features:
59# UNSPECIFIED-NOCHECK-NEXT: - Prefix: USED
60# UNSPECIFIED-NOCHECK-NEXT: Name: bar
61# UNSPECIFIED-NOCHECK-NEXT: - Prefix: USED
62# UNSPECIFIED-NOCHECK-NEXT: Name: baz
63# UNSPECIFIED-NOCHECK-NEXT: - Prefix: USED
64# UNSPECIFIED-NOCHECK-NEXT: Name: quux
65# UNSPECIFIED-NOCHECK-NEXT: ...
66
67# REQUIRED: - Type: CUSTOM
68# REQUIRED-NEXT: Name: target_features
69# REQUIRED-NEXT: Features:
70# REQUIRED-NEXT: - Prefix: USED
71# REQUIRED-NEXT: Name: foo
72# REQUIRED-NEXT: ...
73
74# DISALLOWED: Target feature 'foo' used in {{.*}}target-feature-required.yaml.tmp1.o is disallowed by {{.*}}target-feature-required.yaml.tmp.disallowed.o. Use --no-check-features to suppress.{{$}}
75
76# DISALLOWED-NOCHECK: - Type: CUSTOM
77# DISALLOWED-NOCHECK-NEXT: Name: target_features
78# DISALLOWED-NOCHECK-NEXT: Features:
79# DISALLOWED-NOCHECK-NEXT: - Prefix: USED
80# DISALLOWED-NOCHECK-NEXT: Name: foo
81# DISALLOWED-NOCHECK-NEXT: ...
82
83# NONE: Missing target feature 'foo' in {{.*}}target-feature-required.yaml.tmp.none.o, required by {{.*}}target-feature-required.yaml.tmp1.o. Use --no-check-features to suppress.{{$}}
84
85# NONE-NOCHECK: - Type: CUSTOM
86# NONE-NOCHECK-NEXT: Name: target_features
87# NONE-NOCHECK-NEXT: Features:
88# NONE-NOCHECK-NEXT: - Prefix: USED
89# NONE-NOCHECK-NEXT: Name: foo
90# NONE-NOCHECK-NEXT: ...
deps/lld/test/wasm/target-feature-used.yaml created+97
...@@ -0,0 +1,97 @@
1# RUN: yaml2obj %s -o %t1.o
2
3# RUN: wasm-ld --no-entry --features=foo,bar,baz -o - %t1.o | obj2yaml | FileCheck %s --check-prefix SPECIFIED
4
5# RUN: not wasm-ld --no-entry --features=bar,baz,quux -o /dev/null %t1.o 2>&1 | FileCheck %s --check-prefix UNSPECIFIED
6
7# RUN: wasm-ld --no-entry --no-check-features --features=bar,baz,quux -o - %t1.o | obj2yaml | FileCheck %s --check-prefix UNSPECIFIED-NOCHECK
8
9# RUN: yaml2obj %S/Inputs/use-feature-foo.yaml -o %t.used.o
10# RUN: wasm-ld --no-entry -o - %t1.o %t.used.o | obj2yaml | FileCheck %s --check-prefix USED
11
12# RUN: yaml2obj %S/Inputs/require-feature-foo.yaml -o %t.required.o
13# RUN: wasm-ld --no-entry -o - %t1.o %t.required.o | obj2yaml | FileCheck %s --check-prefix REQUIRED
14
15# RUN: yaml2obj %S/Inputs/disallow-feature-foo.yaml -o %t.disallowed.o
16# RUN: not wasm-ld --no-entry -o /dev/null %t1.o %t.disallowed.o 2>&1 | FileCheck %s --check-prefix DISALLOWED
17
18# RUN: wasm-ld --no-entry --no-check-features -o - %t1.o %t.disallowed.o | obj2yaml | FileCheck %s --check-prefix DISALLOWED-NOCHECK
19
20# RUN: yaml2obj %S/Inputs/no-feature-foo.yaml -o %t.none.o
21# RUN: wasm-ld --no-entry -o - %t1.o %t.none.o | obj2yaml | FileCheck %s --check-prefix NONE
22
23# Check that the following combinations of feature linkage policies
24# give the expected results:
25#
26# USED x USED => USED
27# USED x REQUIRED => USED
28# USED x DISALLOWED => Error
29# USED x NONE => USED
30
31--- !WASM
32FileHeader:
33 Version: 0x00000001
34Sections:
35 - Type: CUSTOM
36 Name: linking
37 Version: 2
38 - Type: CUSTOM
39 Name: target_features
40 Features:
41 - Prefix: USED
42 Name: "foo"
43...
44
45# SPECIFIED: - Type: CUSTOM
46# SPECIFIED-NEXT: Name: target_features
47# SPECIFIED-NEXT: Features:
48# SPECIFIED-NEXT: - Prefix: USED
49# SPECIFIED-NEXT: Name: bar
50# SPECIFIED-NEXT: - Prefix: USED
51# SPECIFIED-NEXT: Name: baz
52# SPECIFIED-NEXT: - Prefix: USED
53# SPECIFIED-NEXT: Name: foo
54# SPECIFIED-NEXT: ...
55
56# UNSPECIFIED: Target feature 'foo' used by {{.*}}target-feature-used.yaml.tmp1.o is not allowed.{{$}}
57
58# UNSPECIFIED-NOCHECK: - Type: CUSTOM
59# UNSPECIFIED-NOCHECK-NEXT: Name: target_features
60# UNSPECIFIED-NOCHECK-NEXT: Features:
61# UNSPECIFIED-NOCHECK-NEXT: - Prefix: USED
62# UNSPECIFIED-NOCHECK-NEXT: Name: bar
63# UNSPECIFIED-NOCHECK-NEXT: - Prefix: USED
64# UNSPECIFIED-NOCHECK-NEXT: Name: baz
65# UNSPECIFIED-NOCHECK-NEXT: - Prefix: USED
66# UNSPECIFIED-NOCHECK-NEXT: Name: quux
67# UNSPECIFIED-NOCHECK-NEXT: ...
68
69# USED: - Type: CUSTOM
70# USED-NEXT: Name: target_features
71# USED-NEXT: Features:
72# USED-NEXT: - Prefix: USED
73# USED-NEXT: Name: foo
74# USED-NEXT: ...
75
76# REQUIRED: - Type: CUSTOM
77# REQUIRED-NEXT: Name: target_features
78# REQUIRED-NEXT: Features:
79# REQUIRED-NEXT: - Prefix: USED
80# REQUIRED-NEXT: Name: foo
81# REQUIRED-NEXT: ...
82
83# DISALLOWED: Target feature 'foo' used in {{.*}}target-feature-used.yaml.tmp1.o is disallowed by {{.*}}target-feature-used.yaml.tmp.disallowed.o. Use --no-check-features to suppress.{{$}}
84
85# DISALLOWED-NOCHECK: - Type: CUSTOM
86# DISALLOWED-NOCHECK-NEXT: Name: target_features
87# DISALLOWED-NOCHECK-NEXT: Features:
88# DISALLOWED-NOCHECK-NEXT: - Prefix: USED
89# DISALLOWED-NOCHECK-NEXT: Name: foo
90# DISALLOWED-NOCHECK-NEXT: ...
91
92# NONE: - Type: CUSTOM
93# NONE-NEXT: Name: target_features
94# NONE-NEXT: Features:
95# NONE-NEXT: - Prefix: USED
96# NONE-NEXT: Name: foo
97# NONE-NEXT: ...
deps/lld/test/wasm/tls.ll created+79
...@@ -0,0 +1,79 @@
1; RUN: llc -mattr=+bulk-memory -filetype=obj %s -o %t.o
2
3target triple = "wasm32-unknown-unknown"
4
5@no_tls = global i32 0, align 4
6@tls1 = thread_local(localexec) global i32 1, align 4
7@tls2 = thread_local(localexec) global i32 1, align 4
8
9define i32* @tls1_addr() {
10 ret i32* @tls1
11}
12
13define i32* @tls2_addr() {
14 ret i32* @tls2
15}
16
17; RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 --no-entry -o %t.wasm %t.o
18; RUN: obj2yaml %t.wasm | FileCheck %s
19
20; RUN: wasm-ld -no-gc-sections --shared-memory --max-memory=131072 --no-merge-data-segments --no-entry -o %t.wasm %t.o
21; RUN: obj2yaml %t.wasm | FileCheck %s
22
23; CHECK: - Type: GLOBAL
24; CHECK-NEXT: Globals:
25; CHECK-NEXT: - Index: 0
26; CHECK-NEXT: Type: I32
27; CHECK-NEXT: Mutable: true
28; CHECK-NEXT: InitExpr:
29; CHECK-NEXT: Opcode: I32_CONST
30; CHECK-NEXT: Value: 66576
31; CHECK-NEXT: - Index: 1
32; CHECK-NEXT: Type: I32
33; CHECK-NEXT: Mutable: true
34; CHECK-NEXT: InitExpr:
35; CHECK-NEXT: Opcode: I32_CONST
36; CHECK-NEXT: Value: 0
37; CHECK-NEXT: - Index: 2
38; CHECK-NEXT: Type: I32
39; CHECK-NEXT: Mutable: false
40; CHECK-NEXT: InitExpr:
41; CHECK-NEXT: Opcode: I32_CONST
42; CHECK-NEXT: Value: 8
43
44
45; CHECK: - Type: CODE
46; CHECK-NEXT: Functions:
47; Skip __wasm_call_ctors and __wasm_init_memory
48; CHECK: - Index: 2
49; CHECK-NEXT: Locals: []
50; CHECK-NEXT: Body: 20002401200041004108FC0801000B
51
52; Expected body of __wasm_init_tls:
53; local.get 0
54; global.set 1
55; local.get 0
56; i32.const 0
57; i32.const 8
58; memory.init 1, 0
59; end
60
61; CHECK-NEXT: - Index: 3
62; CHECK-NEXT: Locals: []
63; CHECK-NEXT: Body: 2381808080004180808080006A0B
64
65; Expected body of tls1_addr:
66; global.get 1
67; i32.const 0
68; i32.add
69; end
70
71; CHECK-NEXT: - Index: 4
72; CHECK-NEXT: Locals: []
73; CHECK-NEXT: Body: 2381808080004184808080006A0B
74
75; Expected body of tls1_addr:
76; global.get 1
77; i32.const 4
78; i32.add
79; end
deps/lld/test/wasm/trace-symbol.ll created+28
...@@ -0,0 +1,28 @@
1; RUN: llc -filetype=obj %p/Inputs/ret32.ll -o %t.ret32.o
2; RUN: llc -filetype=obj -o %t.start.o %s
3; RUN: wasm-ld -o %t.wasm %t.start.o %t.ret32.o -y ret32 -y _start | FileCheck %s -check-prefix=BOTH
4; RUN: wasm-ld -o %t.wasm %t.ret32.o %t.start.o -y ret32 -y _start | FileCheck %s -check-prefix=REVERSED
5
6; check alias
7; RUN: wasm-ld -o %t.wasm %t.start.o %t.ret32.o -trace-symbol=_start | FileCheck %s -check-prefixes=JUST-START
8
9target triple = "wasm32-unknown-unknown"
10
11declare i32 @ret32(float %arg)
12
13define void @_start() {
14entry:
15 %call1 = call i32 @ret32(float 0.0)
16 ret void
17}
18
19; BOTH: start.o: definition of _start
20; BOTH-NEXT: start.o: reference to ret32
21; BOTH-NEXT: ret32.o: definition of ret32
22
23; REVERSED: ret32.o: definition of ret32
24; REVERSED-NEXT: start.o: definition of _start
25; REVERSED-NEXT: start.o: reference to ret32
26
27; JUST-START: start.o: definition of _start
28; JUST-START-NOT: ret32
deps/lld/test/wasm/trace.test created+8
...@@ -0,0 +1,8 @@
1RUN: llc -filetype=obj %p/Inputs/start.ll -o %t.foo.o
2
3# Check -t
4RUN: wasm-ld %t.foo.o -o %t.t.out.wasm -t 2>&1 | FileCheck %s
5CHECK: {{.*}}.foo.o
6
7# Check --trace alias
8RUN: wasm-ld %t.foo.o -o %t.trace.out.wasm --trace 2>&1 | FileCheck %s
deps/lld/test/wasm/undefined-data.ll created+17
...@@ -0,0 +1,17 @@
1; RUN: llc -filetype=obj %s -o %t.o
2; RUN: not wasm-ld -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=UNDEF
3; RUN: not wasm-ld --allow-undefined -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=UNDEF
4; RUN: not wasm-ld --shared -o %t.wasm %t.o 2>&1 | FileCheck %s -check-prefix=SHARED
5
6target triple = "wasm32-unknown-unknown"
7
8@data_external = external global i32
9
10define i32 @_start() {
11entry:
12 %0 = load i32, i32* @data_external, align 4
13 ret i32 %0
14}
15
16; UNDEF: error: {{.*}}undefined-data.ll.tmp.o: undefined symbol: data_external
17; SHARED: error: {{.*}}undefined-data.ll.tmp.o: relocation R_WASM_MEMORY_ADDR_LEB cannot be used against symbol data_external; recompile with -fPIC
deps/lld/test/wasm/undefined-weak-call.ll+7-30
...@@ -42,7 +42,7 @@ define i32 @callWeakFuncs() {...@@ -42,7 +42,7 @@ define i32 @callWeakFuncs() {
42; CHECK-NEXT: ReturnType: I3242; CHECK-NEXT: ReturnType: I32
43; CHECK-NEXT: ParamTypes:43; CHECK-NEXT: ParamTypes:
44; CHECK-NEXT: - Type: FUNCTION44; CHECK-NEXT: - Type: FUNCTION
45; CHECK-NEXT: FunctionTypes: [ 0, 0, 0, 1, 2 ]45; CHECK-NEXT: FunctionTypes: [ 0, 0, 1, 2 ]
46; CHECK-NEXT: - Type: TABLE46; CHECK-NEXT: - Type: TABLE
47; CHECK-NEXT: Tables:47; CHECK-NEXT: Tables:
48; CHECK-NEXT: - ElemType: FUNCREF48; CHECK-NEXT: - ElemType: FUNCREF
...@@ -61,37 +61,19 @@ define i32 @callWeakFuncs() {...@@ -61,37 +61,19 @@ define i32 @callWeakFuncs() {
61; CHECK-NEXT: InitExpr:61; CHECK-NEXT: InitExpr:
62; CHECK-NEXT: Opcode: I32_CONST62; CHECK-NEXT: Opcode: I32_CONST
63; CHECK-NEXT: Value: 6656063; CHECK-NEXT: Value: 66560
64; CHECK-NEXT: - Index: 1
65; CHECK-NEXT: Type: I32
66; CHECK-NEXT: Mutable: false
67; CHECK-NEXT: InitExpr:
68; CHECK-NEXT: Opcode: I32_CONST
69; CHECK-NEXT: Value: 66560
70; CHECK-NEXT: - Index: 2
71; CHECK-NEXT: Type: I32
72; CHECK-NEXT: Mutable: false
73; CHECK-NEXT: InitExpr:
74; CHECK-NEXT: Opcode: I32_CONST
75; CHECK-NEXT: Value: 1024
76; CHECK-NEXT: - Type: EXPORT64; CHECK-NEXT: - Type: EXPORT
77; CHECK-NEXT: Exports:65; CHECK-NEXT: Exports:
78; CHECK-NEXT: - Name: memory66; CHECK-NEXT: - Name: memory
79; CHECK-NEXT: Kind: MEMORY67; CHECK-NEXT: Kind: MEMORY
80; CHECK-NEXT: Index: 068; CHECK-NEXT: Index: 0
81; CHECK-NEXT: - Name: __heap_base
82; CHECK-NEXT: Kind: GLOBAL
83; CHECK-NEXT: Index: 1
84; CHECK-NEXT: - Name: __data_end
85; CHECK-NEXT: Kind: GLOBAL
86; CHECK-NEXT: Index: 2
87; CHECK-NEXT: - Name: callWeakFuncs69; CHECK-NEXT: - Name: callWeakFuncs
88; CHECK-NEXT: Kind: FUNCTION70; CHECK-NEXT: Kind: FUNCTION
89; CHECK-NEXT: Index: 471; CHECK-NEXT: Index: 3
90; CHECK-NEXT: - Type: CODE72; CHECK-NEXT: - Type: CODE
91; CHECK-NEXT: Functions:73; CHECK-NEXT: Functions:
92; CHECK-NEXT: - Index: 074; CHECK-NEXT: - Index: 0
93; CHECK-NEXT: Locals:75; CHECK-NEXT: Locals:
94; CHECK-NEXT: Body: 0B76; CHECK-NEXT: Body: 000B
95; CHECK-NEXT: - Index: 177; CHECK-NEXT: - Index: 1
96; CHECK-NEXT: Locals:78; CHECK-NEXT: Locals:
97; CHECK-NEXT: Body: 000B79; CHECK-NEXT: Body: 000B
...@@ -100,21 +82,16 @@ define i32 @callWeakFuncs() {...@@ -100,21 +82,16 @@ define i32 @callWeakFuncs() {
100; CHECK-NEXT: Body: 000B82; CHECK-NEXT: Body: 000B
101; CHECK-NEXT: - Index: 383; CHECK-NEXT: - Index: 3
102; CHECK-NEXT: Locals:84; CHECK-NEXT: Locals:
103; CHECK-NEXT: Body: 000B85; CHECK-NEXT: Body: 10808080800010818080800041021082808080004180808080004180808080006A0B
104; CHECK-NEXT: - Index: 4
105; CHECK-NEXT: Locals:
106; CHECK-NEXT: Body: 10818080800010828080800041021083808080004180808080004180808080006A0B
107; CHECK-NEXT: - Type: CUSTOM86; CHECK-NEXT: - Type: CUSTOM
108; CHECK-NEXT: Name: name87; CHECK-NEXT: Name: name
109; CHECK-NEXT: FunctionNames:88; CHECK-NEXT: FunctionNames:
110; CHECK-NEXT: - Index: 089; CHECK-NEXT: - Index: 0
111; CHECK-NEXT: Name: __wasm_call_ctors90; CHECK-NEXT: Name: 'undefined:weakFunc1'
112; CHECK-NEXT: - Index: 191; CHECK-NEXT: - Index: 1
113; CHECK-NEXT: Name: undefined function weakFunc192; CHECK-NEXT: Name: 'undefined:weakFunc2'
114; CHECK-NEXT: - Index: 293; CHECK-NEXT: - Index: 2
115; CHECK-NEXT: Name: undefined function weakFunc294; CHECK-NEXT: Name: 'undefined:weakFunc3'
116; CHECK-NEXT: - Index: 395; CHECK-NEXT: - Index: 3
117; CHECK-NEXT: Name: undefined function weakFunc3
118; CHECK-NEXT: - Index: 4
119; CHECK-NEXT: Name: callWeakFuncs96; CHECK-NEXT: Name: callWeakFuncs
120; CHECK-NEXT: ...97; CHECK-NEXT: ...
deps/lld/test/wasm/undefined.ll+3-2
...@@ -1,7 +1,7 @@...@@ -1,7 +1,7 @@
1; RUN: llc -filetype=obj %s -o %t.o1; RUN: llc -filetype=obj %s -o %t.o
2; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o2; RUN: wasm-ld --allow-undefined -o %t.wasm %t.o
33
4; Fails due to undefined 'foo' 4; Fails due to undefined 'foo'
5; RUN: not wasm-ld --undefined=baz -o %t.wasm %t.o 2>&1 | FileCheck %s5; RUN: not wasm-ld --undefined=baz -o %t.wasm %t.o 2>&1 | FileCheck %s
6; CHECK: error: {{.*}}.o: undefined symbol: foo6; CHECK: error: {{.*}}.o: undefined symbol: foo
7; CHECK-NOT: undefined symbol: baz7; CHECK-NOT: undefined symbol: baz
...@@ -16,7 +16,8 @@...@@ -16,7 +16,8 @@
16target triple = "wasm32-unknown-unknown"16target triple = "wasm32-unknown-unknown"
1717
18; Takes the address of the external foo() resulting in undefined external18; Takes the address of the external foo() resulting in undefined external
19@bar = hidden local_unnamed_addr global i8* bitcast (i32 ()* @foo to i8*), align 419@bar = global i8* bitcast (i32 ()* @foo to i8*), align 4
20@llvm.used = appending global [1 x i8**] [i8** @bar], section "llvm.metadata"
2021
21declare i32 @foo() #022declare i32 @foo() #0
2223
deps/lld/test/wasm/version.ll+1-1
...@@ -1,6 +1,6 @@...@@ -1,6 +1,6 @@
1; RUN: llc -filetype=obj %s -o %t.o1; RUN: llc -filetype=obj %s -o %t.o
2; RUN: wasm-ld -o %t.wasm %t.o2; RUN: wasm-ld -o %t.wasm %t.o
3; RUN: llvm-readobj -file-headers %t.wasm | FileCheck %s3; RUN: llvm-readobj --file-headers %t.wasm | FileCheck %s
44
5target triple = "wasm32-unknown-unknown"5target triple = "wasm32-unknown-unknown"
66
deps/lld/test/wasm/visibility-hidden.ll+4-16
...@@ -43,21 +43,15 @@ entry:...@@ -43,21 +43,15 @@ entry:
43; CHECK-NEXT: - Name: memory43; CHECK-NEXT: - Name: memory
44; CHECK-NEXT: Kind: MEMORY44; CHECK-NEXT: Kind: MEMORY
45; CHECK-NEXT: Index: 045; CHECK-NEXT: Index: 0
46; CHECK-NEXT: - Name: __heap_base
47; CHECK-NEXT: Kind: GLOBAL
48; CHECK-NEXT: Index: 1
49; CHECK-NEXT: - Name: __data_end
50; CHECK-NEXT: Kind: GLOBAL
51; CHECK-NEXT: Index: 2
52; CHECK-NEXT: - Name: objectDefault46; CHECK-NEXT: - Name: objectDefault
53; CHECK-NEXT: Kind: FUNCTION47; CHECK-NEXT: Kind: FUNCTION
54; CHECK-NEXT: Index: 248; CHECK-NEXT: Index: 1
55; CHECK-NEXT: - Name: _start49; CHECK-NEXT: - Name: _start
56; CHECK-NEXT: Kind: FUNCTION50; CHECK-NEXT: Kind: FUNCTION
57; CHECK-NEXT: Index: 351; CHECK-NEXT: Index: 2
58; CHECK-NEXT: - Name: archiveDefault52; CHECK-NEXT: - Name: archiveDefault
59; CHECK-NEXT: Kind: FUNCTION53; CHECK-NEXT: Kind: FUNCTION
60; CHECK-NEXT: Index: 554; CHECK-NEXT: Index: 4
61; CHECK-NEXT: - Type:55; CHECK-NEXT: - Type:
6256
6357
...@@ -66,13 +60,7 @@ entry:...@@ -66,13 +60,7 @@ entry:
66; NO-DEFAULT-NEXT: - Name: memory60; NO-DEFAULT-NEXT: - Name: memory
67; NO-DEFAULT-NEXT: Kind: MEMORY61; NO-DEFAULT-NEXT: Kind: MEMORY
68; NO-DEFAULT-NEXT: Index: 062; 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: _start63; NO-DEFAULT-NEXT: - Name: _start
76; NO-DEFAULT-NEXT: Kind: FUNCTION64; NO-DEFAULT-NEXT: Kind: FUNCTION
77; NO-DEFAULT-NEXT: Index: 365; NO-DEFAULT-NEXT: Index: 2
78; NO-DEFAULT-NEXT: - Type:66; NO-DEFAULT-NEXT: - Type:
deps/lld/test/wasm/weak-alias-overide.ll+25-48
...@@ -26,13 +26,13 @@ entry:...@@ -26,13 +26,13 @@ entry:
26; CHECK-NEXT: - Type: TYPE26; CHECK-NEXT: - Type: TYPE
27; CHECK-NEXT: Signatures:27; CHECK-NEXT: Signatures:
28; CHECK-NEXT: - Index: 028; CHECK-NEXT: - Index: 0
29; CHECK-NEXT: ReturnType: NORESULT29; CHECK-NEXT: ReturnType: I32
30; CHECK-NEXT: ParamTypes:30; CHECK-NEXT: ParamTypes:
31; CHECK-NEXT: - Index: 131; CHECK-NEXT: - Index: 1
32; CHECK-NEXT: ReturnType: I3232; CHECK-NEXT: ReturnType: NORESULT
33; CHECK-NEXT: ParamTypes:33; CHECK-NEXT: ParamTypes:
34; CHECK-NEXT: - Type: FUNCTION34; CHECK-NEXT: - Type: FUNCTION
35; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 1, 1, 1, 1, 1 ]35; CHECK-NEXT: FunctionTypes: [ 0, 1, 0, 0, 0, 0, 0 ]
36; CHECK-NEXT: - Type: TABLE36; CHECK-NEXT: - Type: TABLE
37; CHECK-NEXT: Tables:37; CHECK-NEXT: Tables:
38; CHECK-NEXT: - ElemType: FUNCREF38; CHECK-NEXT: - ElemType: FUNCREF
...@@ -51,103 +51,80 @@ entry:...@@ -51,103 +51,80 @@ entry:
51; CHECK-NEXT: InitExpr:51; CHECK-NEXT: InitExpr:
52; CHECK-NEXT: Opcode: I32_CONST52; CHECK-NEXT: Opcode: I32_CONST
53; CHECK-NEXT: Value: 6656053; CHECK-NEXT: Value: 66560
54; CHECK-NEXT: - Index: 1
55; CHECK-NEXT: Type: I32
56; CHECK-NEXT: Mutable: false
57; CHECK-NEXT: InitExpr:
58; CHECK-NEXT: Opcode: I32_CONST
59; CHECK-NEXT: Value: 66560
60; CHECK-NEXT: - Index: 2
61; CHECK-NEXT: Type: I32
62; CHECK-NEXT: Mutable: false
63; CHECK-NEXT: InitExpr:
64; CHECK-NEXT: Opcode: I32_CONST
65; CHECK-NEXT: Value: 1024
66; CHECK-NEXT: - Type: EXPORT54; CHECK-NEXT: - Type: EXPORT
67; CHECK-NEXT: Exports:55; CHECK-NEXT: Exports:
68; CHECK-NEXT: - Name: memory56; CHECK-NEXT: - Name: memory
69; CHECK-NEXT: Kind: MEMORY57; CHECK-NEXT: Kind: MEMORY
70; CHECK-NEXT: Index: 058; CHECK-NEXT: Index: 0
71; CHECK-NEXT: - Name: __heap_base
72; CHECK-NEXT: Kind: GLOBAL
73; CHECK-NEXT: Index: 1
74; CHECK-NEXT: - Name: __data_end
75; CHECK-NEXT: Kind: GLOBAL
76; CHECK-NEXT: Index: 2
77; CHECK-NEXT: - Name: alias_fn59; CHECK-NEXT: - Name: alias_fn
78; CHECK-NEXT: Kind: FUNCTION60; CHECK-NEXT: Kind: FUNCTION
79; CHECK-NEXT: Index: 161; CHECK-NEXT: Index: 0
80; CHECK-NEXT: - Name: _start62; CHECK-NEXT: - Name: _start
81; CHECK-NEXT: Kind: FUNCTION63; CHECK-NEXT: Kind: FUNCTION
82; CHECK-NEXT: Index: 264; CHECK-NEXT: Index: 1
83; CHECK-NEXT: - Name: direct_fn65; CHECK-NEXT: - Name: direct_fn
84; CHECK-NEXT: Kind: FUNCTION66; CHECK-NEXT: Kind: FUNCTION
85; CHECK-NEXT: Index: 367; CHECK-NEXT: Index: 2
86; CHECK-NEXT: - Name: call_direct68; CHECK-NEXT: - Name: call_direct
87; CHECK-NEXT: Kind: FUNCTION69; CHECK-NEXT: Kind: FUNCTION
88; CHECK-NEXT: Index: 470; CHECK-NEXT: Index: 3
89; CHECK-NEXT: - Name: call_alias71; CHECK-NEXT: - Name: call_alias
90; CHECK-NEXT: Kind: FUNCTION72; CHECK-NEXT: Kind: FUNCTION
91; CHECK-NEXT: Index: 573; CHECK-NEXT: Index: 4
92; CHECK-NEXT: - Name: call_alias_ptr74; CHECK-NEXT: - Name: call_alias_ptr
93; CHECK-NEXT: Kind: FUNCTION75; CHECK-NEXT: Kind: FUNCTION
94; CHECK-NEXT: Index: 676; CHECK-NEXT: Index: 5
95; CHECK-NEXT: - Name: call_direct_ptr77; CHECK-NEXT: - Name: call_direct_ptr
96; CHECK-NEXT: Kind: FUNCTION78; CHECK-NEXT: Kind: FUNCTION
97; CHECK-NEXT: Index: 779; CHECK-NEXT: Index: 6
98; CHECK-NEXT: - Type: ELEM80; CHECK-NEXT: - Type: ELEM
99; CHECK-NEXT: Segments:81; CHECK-NEXT: Segments:
100; CHECK-NEXT: - Offset:82; CHECK-NEXT: - Offset:
101; CHECK-NEXT: Opcode: I32_CONST83; CHECK-NEXT: Opcode: I32_CONST
102; CHECK-NEXT: Value: 184; CHECK-NEXT: Value: 1
103; CHECK-NEXT: Functions: [ 1, 3 ]85; CHECK-NEXT: Functions: [ 0, 2 ]
104; CHECK-NEXT: - Type: CODE86; CHECK-NEXT: - Type: CODE
105; CHECK-NEXT: Functions:87; CHECK-NEXT: Functions:
106; CHECK-NEXT: - Index: 088; CHECK-NEXT: - Index: 0
107; CHECK-NEXT: Locals:89; CHECK-NEXT: Locals:
108; CHECK-NEXT: Body: 0B90; CHECK-NEXT: Body: 41010B
109; CHECK-NEXT: - Index: 191; CHECK-NEXT: - Index: 1
110; CHECK-NEXT: Locals:92; CHECK-NEXT: Locals:
111; CHECK-NEXT: Body: 41010B93; CHECK-NEXT: Body: 1080808080001A0B
112; CHECK-NEXT: - Index: 294; CHECK-NEXT: - Index: 2
113; CHECK-NEXT: Locals:95; CHECK-NEXT: Locals:
114; CHECK-NEXT: Body: 1081808080001A0B96; CHECK-NEXT: Body: 41000B
115; CHECK-NEXT: - Index: 397; CHECK-NEXT: - Index: 3
116; CHECK-NEXT: Locals:98; CHECK-NEXT: Locals:
117; CHECK-NEXT: Body: 41000B99; CHECK-NEXT: Body: 1082808080000B
118; CHECK-NEXT: - Index: 4100; CHECK-NEXT: - Index: 4
119; CHECK-NEXT: Locals:101; CHECK-NEXT: Locals:
120; CHECK-NEXT: Body: 1083808080000B102; CHECK-NEXT: Body: 1080808080000B
121; CHECK-NEXT: - Index: 5103; CHECK-NEXT: - Index: 5
122; CHECK-NEXT: Locals:104; CHECK-NEXT: Locals:
123; CHECK-NEXT: Body: 1081808080000B
124; CHECK-NEXT: - Index: 6
125; CHECK-NEXT: Locals:
126; CHECK-NEXT: - Type: I32105; CHECK-NEXT: - Type: I32
127; CHECK-NEXT: Count: 2106; CHECK-NEXT: Count: 2
128; CHECK-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B107; CHECK-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081080808080002101200041106A24808080800020010B
129; CHECK-NEXT: - Index: 7108; CHECK-NEXT: - Index: 6
130; CHECK-NEXT: Locals:109; CHECK-NEXT: Locals:
131; CHECK-NEXT: - Type: I32110; CHECK-NEXT: - Type: I32
132; CHECK-NEXT: Count: 2111; CHECK-NEXT: Count: 2
133; CHECK-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081083808080002101200041106A24808080800020010B112; CHECK-NEXT: Body: 23808080800041106B220024808080800020004182808080003602081082808080002101200041106A24808080800020010B
134; CHECK-NEXT: - Type: CUSTOM113; CHECK-NEXT: - Type: CUSTOM
135; CHECK-NEXT: Name: name114; CHECK-NEXT: Name: name
136; CHECK-NEXT: FunctionNames:115; CHECK-NEXT: FunctionNames:
137; CHECK-NEXT: - Index: 0116; CHECK-NEXT: - Index: 0
138; CHECK-NEXT: Name: __wasm_call_ctors
139; CHECK-NEXT: - Index: 1
140; CHECK-NEXT: Name: alias_fn117; CHECK-NEXT: Name: alias_fn
141; CHECK-NEXT: - Index: 2118; CHECK-NEXT: - Index: 1
142; CHECK-NEXT: Name: _start119; CHECK-NEXT: Name: _start
143; CHECK-NEXT: - Index: 3120; CHECK-NEXT: - Index: 2
144; CHECK-NEXT: Name: direct_fn121; CHECK-NEXT: Name: direct_fn
145; CHECK-NEXT: - Index: 4122; CHECK-NEXT: - Index: 3
146; CHECK-NEXT: Name: call_direct123; CHECK-NEXT: Name: call_direct
147; CHECK-NEXT: - Index: 5124; CHECK-NEXT: - Index: 4
148; CHECK-NEXT: Name: call_alias125; CHECK-NEXT: Name: call_alias
149; CHECK-NEXT: - Index: 6126; CHECK-NEXT: - Index: 5
150; CHECK-NEXT: Name: call_alias_ptr127; CHECK-NEXT: Name: call_alias_ptr
151; CHECK-NEXT: - Index: 7128; CHECK-NEXT: - Index: 6
152; CHECK-NEXT: Name: call_direct_ptr129; CHECK-NEXT: Name: call_direct_ptr
153; CHECK-NEXT: ...130; CHECK-NEXT: ...
deps/lld/test/wasm/weak-alias.ll+34-57
...@@ -29,7 +29,7 @@ entry:...@@ -29,7 +29,7 @@ entry:
29; CHECK-NEXT: ReturnType: I3229; CHECK-NEXT: ReturnType: I32
30; CHECK-NEXT: ParamTypes:30; CHECK-NEXT: ParamTypes:
31; CHECK-NEXT: - Type: FUNCTION31; CHECK-NEXT: - Type: FUNCTION
32; CHECK-NEXT: FunctionTypes: [ 0, 0, 1, 1, 1, 1, 1 ]32; CHECK-NEXT: FunctionTypes: [ 0, 1, 1, 1, 1, 1 ]
33; CHECK-NEXT: - Type: TABLE33; CHECK-NEXT: - Type: TABLE
34; CHECK-NEXT: Tables:34; CHECK-NEXT: Tables:
35; CHECK-NEXT: - ElemType: FUNCREF35; CHECK-NEXT: - ElemType: FUNCREF
...@@ -48,99 +48,76 @@ entry:...@@ -48,99 +48,76 @@ entry:
48; CHECK-NEXT: InitExpr:48; CHECK-NEXT: InitExpr:
49; CHECK-NEXT: Opcode: I32_CONST49; CHECK-NEXT: Opcode: I32_CONST
50; CHECK-NEXT: Value: 6656050; CHECK-NEXT: Value: 66560
51; CHECK-NEXT: - Index: 1
52; CHECK-NEXT: Type: I32
53; CHECK-NEXT: Mutable: false
54; CHECK-NEXT: InitExpr:
55; CHECK-NEXT: Opcode: I32_CONST
56; CHECK-NEXT: Value: 66560
57; CHECK-NEXT: - Index: 2
58; CHECK-NEXT: Type: I32
59; CHECK-NEXT: Mutable: false
60; CHECK-NEXT: InitExpr:
61; CHECK-NEXT: Opcode: I32_CONST
62; CHECK-NEXT: Value: 1024
63; CHECK-NEXT: - Type: EXPORT51; CHECK-NEXT: - Type: EXPORT
64; CHECK-NEXT: Exports:52; CHECK-NEXT: Exports:
65; CHECK-NEXT: - Name: memory53; CHECK-NEXT: - Name: memory
66; CHECK-NEXT: Kind: MEMORY54; CHECK-NEXT: Kind: MEMORY
67; CHECK-NEXT: Index: 055; CHECK-NEXT: Index: 0
68; CHECK-NEXT: - Name: __heap_base
69; CHECK-NEXT: Kind: GLOBAL
70; CHECK-NEXT: Index: 1
71; CHECK-NEXT: - Name: __data_end
72; CHECK-NEXT: Kind: GLOBAL
73; CHECK-NEXT: Index: 2
74; CHECK-NEXT: - Name: _start56; CHECK-NEXT: - Name: _start
75; CHECK-NEXT: Kind: FUNCTION57; CHECK-NEXT: Kind: FUNCTION
76; CHECK-NEXT: Index: 158; CHECK-NEXT: Index: 0
77; CHECK-NEXT: - Name: alias_fn59; CHECK-NEXT: - Name: alias_fn
78; CHECK-NEXT: Kind: FUNCTION60; CHECK-NEXT: Kind: FUNCTION
79; CHECK-NEXT: Index: 261; CHECK-NEXT: Index: 1
80; CHECK-NEXT: - Name: direct_fn62; CHECK-NEXT: - Name: direct_fn
81; CHECK-NEXT: Kind: FUNCTION63; CHECK-NEXT: Kind: FUNCTION
82; CHECK-NEXT: Index: 264; CHECK-NEXT: Index: 1
83; CHECK-NEXT: - Name: call_direct65; CHECK-NEXT: - Name: call_direct
84; CHECK-NEXT: Kind: FUNCTION66; CHECK-NEXT: Kind: FUNCTION
85; CHECK-NEXT: Index: 367; CHECK-NEXT: Index: 2
86; CHECK-NEXT: - Name: call_alias68; CHECK-NEXT: - Name: call_alias
87; CHECK-NEXT: Kind: FUNCTION69; CHECK-NEXT: Kind: FUNCTION
88; CHECK-NEXT: Index: 470; CHECK-NEXT: Index: 3
89; CHECK-NEXT: - Name: call_alias_ptr71; CHECK-NEXT: - Name: call_alias_ptr
90; CHECK-NEXT: Kind: FUNCTION72; CHECK-NEXT: Kind: FUNCTION
91; CHECK-NEXT: Index: 573; CHECK-NEXT: Index: 4
92; CHECK-NEXT: - Name: call_direct_ptr74; CHECK-NEXT: - Name: call_direct_ptr
93; CHECK-NEXT: Kind: FUNCTION75; CHECK-NEXT: Kind: FUNCTION
94; CHECK-NEXT: Index: 676; CHECK-NEXT: Index: 5
95; CHECK-NEXT: - Type: ELEM77; CHECK-NEXT: - Type: ELEM
96; CHECK-NEXT: Segments:78; CHECK-NEXT: Segments:
97; CHECK-NEXT: - Offset:79; CHECK-NEXT: - Offset:
98; CHECK-NEXT: Opcode: I32_CONST80; CHECK-NEXT: Opcode: I32_CONST
99; CHECK-NEXT: Value: 181; CHECK-NEXT: Value: 1
100; CHECK-NEXT: Functions: [ 2 ]82; CHECK-NEXT: Functions: [ 1 ]
101; CHECK-NEXT: - Type: CODE83; CHECK-NEXT: - Type: CODE
102; CHECK-NEXT: Functions:84; CHECK-NEXT: Functions:
103; CHECK-NEXT: - Index: 085; CHECK-NEXT: - Index: 0
104; CHECK-NEXT: Locals:86; CHECK-NEXT: Locals:
105; CHECK-NEXT: Body: 0B87; CHECK-NEXT: Body: 1081808080001A0B
106; CHECK-NEXT: - Index: 188; CHECK-NEXT: - Index: 1
107; CHECK-NEXT: Locals:89; CHECK-NEXT: Locals:
108; CHECK-NEXT: Body: 1082808080001A0B90; CHECK-NEXT: Body: 41000B
109; CHECK-NEXT: - Index: 291; CHECK-NEXT: - Index: 2
110; CHECK-NEXT: Locals:92; CHECK-NEXT: Locals:
111; CHECK-NEXT: Body: 41000B93; CHECK-NEXT: Body: 1081808080000B
112; CHECK-NEXT: - Index: 394; CHECK-NEXT: - Index: 3
113; CHECK-NEXT: Locals:95; CHECK-NEXT: Locals:
114; CHECK-NEXT: Body: 1082808080000B96; CHECK-NEXT: Body: 1081808080000B
115; CHECK-NEXT: - Index: 497; CHECK-NEXT: - Index: 4
116; CHECK-NEXT: Locals:98; CHECK-NEXT: Locals:
117; CHECK-NEXT: Body: 1082808080000B
118; CHECK-NEXT: - Index: 5
119; CHECK-NEXT: Locals:
120; CHECK-NEXT: - Type: I3299; CHECK-NEXT: - Type: I32
121; CHECK-NEXT: Count: 2100; CHECK-NEXT: Count: 2
122; CHECK-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081082808080002101200041106A24808080800020010B101; CHECK-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B
123; CHECK-NEXT: - Index: 6102; CHECK-NEXT: - Index: 5
124; CHECK-NEXT: Locals:103; CHECK-NEXT: Locals:
125; CHECK-NEXT: - Type: I32104; CHECK-NEXT: - Type: I32
126; CHECK-NEXT: Count: 2105; CHECK-NEXT: Count: 2
127; CHECK-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081082808080002101200041106A24808080800020010B106; CHECK-NEXT: Body: 23808080800041106B220024808080800020004181808080003602081081808080002101200041106A24808080800020010B
128; CHECK-NEXT: - Type: CUSTOM107; CHECK-NEXT: - Type: CUSTOM
129; CHECK-NEXT: Name: name108; CHECK-NEXT: Name: name
130; CHECK-NEXT: FunctionNames:109; CHECK-NEXT: FunctionNames:
131; CHECK-NEXT: - Index: 0110; CHECK-NEXT: - Index: 0
132; CHECK-NEXT: Name: __wasm_call_ctors
133; CHECK-NEXT: - Index: 1
134; CHECK-NEXT: Name: _start111; CHECK-NEXT: Name: _start
135; CHECK-NEXT: - Index: 2112; CHECK-NEXT: - Index: 1
136; CHECK-NEXT: Name: direct_fn113; CHECK-NEXT: Name: direct_fn
137; CHECK-NEXT: - Index: 3114; CHECK-NEXT: - Index: 2
138; CHECK-NEXT: Name: call_direct115; CHECK-NEXT: Name: call_direct
139; CHECK-NEXT: - Index: 4116; CHECK-NEXT: - Index: 3
140; CHECK-NEXT: Name: call_alias117; CHECK-NEXT: Name: call_alias
141; CHECK-NEXT: - Index: 5118; CHECK-NEXT: - Index: 4
142; CHECK-NEXT: Name: call_alias_ptr119; CHECK-NEXT: Name: call_alias_ptr
143; CHECK-NEXT: - Index: 6120; CHECK-NEXT: - Index: 5
144; CHECK-NEXT: Name: call_direct_ptr121; CHECK-NEXT: Name: call_direct_ptr
145; CHECK-NEXT: ...122; CHECK-NEXT: ...
146123
...@@ -186,43 +163,43 @@ entry:...@@ -186,43 +163,43 @@ entry:
186; RELOC-NEXT: Functions: [ 1 ]163; RELOC-NEXT: Functions: [ 1 ]
187; RELOC-NEXT: - Type: CODE164; RELOC-NEXT: - Type: CODE
188; RELOC-NEXT: Relocations:165; RELOC-NEXT: Relocations:
189; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB166; RELOC-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
190; RELOC-NEXT: Index: 1167; RELOC-NEXT: Index: 1
191; RELOC-NEXT: Offset: 0x00000004168; RELOC-NEXT: Offset: 0x00000004
192; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB169; RELOC-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
193; RELOC-NEXT: Index: 2170; RELOC-NEXT: Index: 2
194; RELOC-NEXT: Offset: 0x00000013171; RELOC-NEXT: Offset: 0x00000013
195; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB172; RELOC-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
196; RELOC-NEXT: Index: 1173; RELOC-NEXT: Index: 1
197; RELOC-NEXT: Offset: 0x0000001C174; RELOC-NEXT: Offset: 0x0000001C
198; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB175; RELOC-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
199; RELOC-NEXT: Index: 6176; RELOC-NEXT: Index: 6
200; RELOC-NEXT: Offset: 0x00000027177; RELOC-NEXT: Offset: 0x00000027
201; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB178; RELOC-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
202; RELOC-NEXT: Index: 6179; RELOC-NEXT: Index: 6
203; RELOC-NEXT: Offset: 0x00000032180; RELOC-NEXT: Offset: 0x00000032
204; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB181; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
205; RELOC-NEXT: Index: 1182; RELOC-NEXT: Index: 1
206; RELOC-NEXT: Offset: 0x0000003A183; RELOC-NEXT: Offset: 0x0000003A
207; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB184; RELOC-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
208; RELOC-NEXT: Index: 1185; RELOC-NEXT: Index: 1
209; RELOC-NEXT: Offset: 0x00000043186; RELOC-NEXT: Offset: 0x00000043
210; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB187; RELOC-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
211; RELOC-NEXT: Index: 6188; RELOC-NEXT: Index: 6
212; RELOC-NEXT: Offset: 0x00000050189; RELOC-NEXT: Offset: 0x00000050
213; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB190; RELOC-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
214; RELOC-NEXT: Index: 6191; RELOC-NEXT: Index: 6
215; RELOC-NEXT: Offset: 0x0000005D192; RELOC-NEXT: Offset: 0x0000005D
216; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB193; RELOC-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
217; RELOC-NEXT: Index: 6194; RELOC-NEXT: Index: 6
218; RELOC-NEXT: Offset: 0x00000068195; RELOC-NEXT: Offset: 0x00000068
219; RELOC-NEXT: - Type: R_WEBASSEMBLY_TABLE_INDEX_SLEB196; RELOC-NEXT: - Type: R_WASM_TABLE_INDEX_SLEB
220; RELOC-NEXT: Index: 2197; RELOC-NEXT: Index: 2
221; RELOC-NEXT: Offset: 0x00000070198; RELOC-NEXT: Offset: 0x00000070
222; RELOC-NEXT: - Type: R_WEBASSEMBLY_FUNCTION_INDEX_LEB199; RELOC-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
223; RELOC-NEXT: Index: 2200; RELOC-NEXT: Index: 2
224; RELOC-NEXT: Offset: 0x00000079201; RELOC-NEXT: Offset: 0x00000079
225; RELOC-NEXT: - Type: R_WEBASSEMBLY_GLOBAL_INDEX_LEB202; RELOC-NEXT: - Type: R_WASM_GLOBAL_INDEX_LEB
226; RELOC-NEXT: Index: 6203; RELOC-NEXT: Index: 6
227; RELOC-NEXT: Offset: 0x00000086204; RELOC-NEXT: Offset: 0x00000086
228; RELOC-NEXT: Functions:205; RELOC-NEXT: Functions:
deps/lld/test/wasm/weak-symbols.ll+14-37
...@@ -29,7 +29,7 @@ entry:...@@ -29,7 +29,7 @@ entry:
29; CHECK-NEXT: ReturnType: I3229; CHECK-NEXT: ReturnType: I32
30; CHECK-NEXT: ParamTypes:30; CHECK-NEXT: ParamTypes:
31; CHECK-NEXT: - Type: FUNCTION31; CHECK-NEXT: - Type: FUNCTION
32; CHECK-NEXT: FunctionTypes: [ 0, 0, 1, 1, 1 ]32; CHECK-NEXT: FunctionTypes: [ 0, 1, 1, 1 ]
33; CHECK-NEXT: - Type: TABLE33; CHECK-NEXT: - Type: TABLE
34; CHECK-NEXT: Tables:34; CHECK-NEXT: Tables:
35; CHECK-NEXT: - ElemType: FUNCREF35; CHECK-NEXT: - ElemType: FUNCREF
...@@ -53,72 +53,51 @@ entry:...@@ -53,72 +53,51 @@ entry:
53; CHECK-NEXT: Mutable: false53; CHECK-NEXT: Mutable: false
54; CHECK-NEXT: InitExpr:54; CHECK-NEXT: InitExpr:
55; CHECK-NEXT: Opcode: I32_CONST55; CHECK-NEXT: Opcode: I32_CONST
56; CHECK-NEXT: Value: 66576
57; CHECK-NEXT: - Index: 2
58; CHECK-NEXT: Type: I32
59; CHECK-NEXT: Mutable: false
60; CHECK-NEXT: InitExpr:
61; CHECK-NEXT: Opcode: I32_CONST
62; CHECK-NEXT: Value: 1028
63; CHECK-NEXT: - Index: 3
64; CHECK-NEXT: Type: I32
65; CHECK-NEXT: Mutable: false
66; CHECK-NEXT: InitExpr:
67; CHECK-NEXT: Opcode: I32_CONST
68; CHECK-NEXT: Value: 102456; CHECK-NEXT: Value: 1024
69; CHECK-NEXT: - Type: EXPORT57; CHECK-NEXT: - Type: EXPORT
70; CHECK-NEXT: Exports:58; CHECK-NEXT: Exports:
71; CHECK-NEXT: - Name: memory59; CHECK-NEXT: - Name: memory
72; CHECK-NEXT: Kind: MEMORY60; CHECK-NEXT: Kind: MEMORY
73; CHECK-NEXT: Index: 061; CHECK-NEXT: Index: 0
74; CHECK-NEXT: - Name: __heap_base
75; CHECK-NEXT: Kind: GLOBAL
76; CHECK-NEXT: Index: 1
77; CHECK-NEXT: - Name: __data_end
78; CHECK-NEXT: Kind: GLOBAL
79; CHECK-NEXT: Index: 2
80; CHECK-NEXT: - Name: _start62; CHECK-NEXT: - Name: _start
81; CHECK-NEXT: Kind: FUNCTION63; CHECK-NEXT: Kind: FUNCTION
82; CHECK-NEXT: Index: 164; CHECK-NEXT: Index: 0
83; CHECK-NEXT: - Name: weakFn65; CHECK-NEXT: - Name: weakFn
84; CHECK-NEXT: Kind: FUNCTION66; CHECK-NEXT: Kind: FUNCTION
85; CHECK-NEXT: Index: 267; CHECK-NEXT: Index: 1
86; CHECK-NEXT: - Name: exportWeak168; CHECK-NEXT: - Name: exportWeak1
87; CHECK-NEXT: Kind: FUNCTION69; CHECK-NEXT: Kind: FUNCTION
88; CHECK-NEXT: Index: 370; CHECK-NEXT: Index: 2
89; CHECK-NEXT: - Name: weakGlobal71; CHECK-NEXT: - Name: weakGlobal
90; CHECK-NEXT: Kind: GLOBAL72; CHECK-NEXT: Kind: GLOBAL
91; CHECK-NEXT: Index: 373; CHECK-NEXT: Index: 1
92; CHECK-NEXT: - Name: exportWeak274; CHECK-NEXT: - Name: exportWeak2
93; CHECK-NEXT: Kind: FUNCTION75; CHECK-NEXT: Kind: FUNCTION
94; CHECK-NEXT: Index: 476; CHECK-NEXT: Index: 3
95; CHECK-NEXT: - Type: ELEM77; CHECK-NEXT: - Type: ELEM
96; CHECK-NEXT: Segments:78; CHECK-NEXT: Segments:
97; CHECK-NEXT: - Offset:79; CHECK-NEXT: - Offset:
98; CHECK-NEXT: Opcode: I32_CONST80; CHECK-NEXT: Opcode: I32_CONST
99; CHECK-NEXT: Value: 181; CHECK-NEXT: Value: 1
100; CHECK-NEXT: Functions: [ 2 ]82; CHECK-NEXT: Functions: [ 1 ]
101; CHECK-NEXT: - Type: CODE83; CHECK-NEXT: - Type: CODE
102; CHECK-NEXT: Functions:84; CHECK-NEXT: Functions:
103; CHECK-NEXT: - Index: 085; CHECK-NEXT: - Index: 0
104; CHECK-NEXT: Locals:86; CHECK-NEXT: Locals:
105; CHECK-NEXT: Body: 0B87; CHECK-NEXT: Body: 1081808080001A0B
106; CHECK-NEXT: - Index: 188; CHECK-NEXT: - Index: 1
107; CHECK-NEXT: Locals:89; CHECK-NEXT: Locals:
108; CHECK-NEXT: Body: 1082808080001A0B
109; CHECK-NEXT: - Index: 2
110; CHECK-NEXT: Locals:
111; CHECK-NEXT: Body: 41010B90; CHECK-NEXT: Body: 41010B
112; CHECK-NEXT: - Index: 391; CHECK-NEXT: - Index: 2
113; CHECK-NEXT: Locals:92; CHECK-NEXT: Locals:
114; CHECK-NEXT: Body: 4181808080000B93; CHECK-NEXT: Body: 4181808080000B
115; CHECK-NEXT: - Index: 494; CHECK-NEXT: - Index: 3
116; CHECK-NEXT: Locals:95; CHECK-NEXT: Locals:
117; CHECK-NEXT: Body: 4181808080000B96; CHECK-NEXT: Body: 4181808080000B
118; CHECK-NEXT: - Type: DATA97; CHECK-NEXT: - Type: DATA
119; CHECK-NEXT: Segments:98; CHECK-NEXT: Segments:
120; CHECK-NEXT: - SectionOffset: 799; CHECK-NEXT: - SectionOffset: 7
121; CHECK-NEXT: MemoryIndex: 0100; CHECK-NEXT: InitFlags: 0
122; CHECK-NEXT: Offset:101; CHECK-NEXT: Offset:
123; CHECK-NEXT: Opcode: I32_CONST102; CHECK-NEXT: Opcode: I32_CONST
124; CHECK-NEXT: Value: 1024103; CHECK-NEXT: Value: 1024
...@@ -127,13 +106,11 @@ entry:...@@ -127,13 +106,11 @@ entry:
127; CHECK-NEXT: Name: name106; CHECK-NEXT: Name: name
128; CHECK-NEXT: FunctionNames:107; CHECK-NEXT: FunctionNames:
129; CHECK-NEXT: - Index: 0108; CHECK-NEXT: - Index: 0
130; CHECK-NEXT: Name: __wasm_call_ctors
131; CHECK-NEXT: - Index: 1
132; CHECK-NEXT: Name: _start109; CHECK-NEXT: Name: _start
133; CHECK-NEXT: - Index: 2110; CHECK-NEXT: - Index: 1
134; CHECK-NEXT: Name: weakFn111; CHECK-NEXT: Name: weakFn
135; CHECK-NEXT: - Index: 3112; CHECK-NEXT: - Index: 2
136; CHECK-NEXT: Name: exportWeak1113; CHECK-NEXT: Name: exportWeak1
137; CHECK-NEXT: - Index: 4114; CHECK-NEXT: - Index: 3
138; CHECK-NEXT: Name: exportWeak2115; CHECK-NEXT: Name: exportWeak2
139; CHECK-NEXT: ...116; CHECK-NEXT: ...
deps/lld/test/wasm/weak-undefined.ll+6-27
...@@ -34,13 +34,13 @@ entry:...@@ -34,13 +34,13 @@ entry:
34; CHECK-NEXT: - Type: TYPE34; CHECK-NEXT: - Type: TYPE
35; CHECK-NEXT: Signatures:35; CHECK-NEXT: Signatures:
36; CHECK-NEXT: - Index: 036; CHECK-NEXT: - Index: 0
37; CHECK-NEXT: ReturnType: NORESULT37; CHECK-NEXT: ReturnType: I32
38; CHECK-NEXT: ParamTypes:38; CHECK-NEXT: ParamTypes:
39; CHECK-NEXT: - Index: 139; CHECK-NEXT: - Index: 1
40; CHECK-NEXT: ReturnType: I3240; CHECK-NEXT: ReturnType: NORESULT
41; CHECK-NEXT: ParamTypes:41; CHECK-NEXT: ParamTypes:
42; CHECK-NEXT: - Type: FUNCTION42; CHECK-NEXT: - Type: FUNCTION
43; CHECK-NEXT: FunctionTypes: [ 0, 1, 1, 0 ]43; CHECK-NEXT: FunctionTypes: [ 0, 0, 1 ]
44; CHECK-NEXT: - Type: TABLE44; CHECK-NEXT: - Type: TABLE
45; CHECK-NEXT: Tables:45; CHECK-NEXT: Tables:
46; CHECK-NEXT: - ElemType: FUNCREF46; CHECK-NEXT: - ElemType: FUNCREF
...@@ -59,44 +59,23 @@ entry:...@@ -59,44 +59,23 @@ entry:
59; CHECK-NEXT: InitExpr:59; CHECK-NEXT: InitExpr:
60; CHECK-NEXT: Opcode: I32_CONST60; CHECK-NEXT: Opcode: I32_CONST
61; CHECK-NEXT: Value: 6656061; CHECK-NEXT: Value: 66560
62; CHECK-NEXT: - Index: 1
63; CHECK-NEXT: Type: I32
64; CHECK-NEXT: Mutable: false
65; CHECK-NEXT: InitExpr:
66; CHECK-NEXT: Opcode: I32_CONST
67; CHECK-NEXT: Value: 66560
68; CHECK-NEXT: - Index: 2
69; CHECK-NEXT: Type: I32
70; CHECK-NEXT: Mutable: false
71; CHECK-NEXT: InitExpr:
72; CHECK-NEXT: Opcode: I32_CONST
73; CHECK-NEXT: Value: 1024
74; CHECK-NEXT: - Type: EXPORT62; CHECK-NEXT: - Type: EXPORT
75; CHECK-NEXT: Exports:63; CHECK-NEXT: Exports:
76; CHECK-NEXT: - Name: memory64; CHECK-NEXT: - Name: memory
77; CHECK-NEXT: Kind: MEMORY65; CHECK-NEXT: Kind: MEMORY
78; CHECK-NEXT: Index: 066; CHECK-NEXT: Index: 0
79; CHECK-NEXT: - Name: __heap_base
80; CHECK-NEXT: Kind: GLOBAL
81; CHECK-NEXT: Index: 1
82; CHECK-NEXT: - Name: __data_end
83; CHECK-NEXT: Kind: GLOBAL
84; CHECK-NEXT: Index: 2
85; CHECK-NEXT: - Name: _start67; CHECK-NEXT: - Name: _start
86; CHECK-NEXT: Kind: FUNCTION68; CHECK-NEXT: Kind: FUNCTION
87; CHECK-NEXT: Index: 369; CHECK-NEXT: Index: 2
88; CHECK-NEXT: - Type: CODE70; CHECK-NEXT: - Type: CODE
89; CHECK-NEXT: Functions:71; CHECK-NEXT: Functions:
90; CHECK-NEXT: - Index: 072; CHECK-NEXT: - Index: 0
91; CHECK-NEXT: Locals:73; CHECK-NEXT: Locals:
92; CHECK-NEXT: Body: 0B74; CHECK-NEXT: Body: 4180808080000B
93; CHECK-NEXT: - Index: 175; CHECK-NEXT: - Index: 1
94; CHECK-NEXT: Locals:76; CHECK-NEXT: Locals:
95; CHECK-NEXT: Body: 4180808080000B77; CHECK-NEXT: Body: 4180808080000B
96; CHECK-NEXT: - Index: 278; CHECK-NEXT: - Index: 2
97; CHECK-NEXT: Locals:79; CHECK-NEXT: Locals:
98; CHECK-NEXT: Body: 4180808080000B80; CHECK-NEXT: Body: 1081808080001A1080808080001A0B
99; CHECK-NEXT: - Index: 3
100; CHECK-NEXT: Locals:
101; CHECK-NEXT: Body: 1082808080001A1081808080001A0B
102; CHECK-NEXT: ...81; CHECK-NEXT: ...
deps/lld/test/wasm/wrap.ll created+40
...@@ -0,0 +1,40 @@
1; RUN: llc -filetype=obj %s -o %t.o
2; RUN: wasm-ld -wrap nosuchsym -wrap foo -o %t.wasm %t.o
3; RUN: wasm-ld -emit-relocs -wrap foo -o %t.wasm %t.o
4; RUN: obj2yaml %t.wasm | FileCheck %s
5
6target triple = "wasm32-unknown-unknown"
7
8define i32 @foo() {
9 ret i32 1
10}
11
12define void @_start() {
13entry:
14 call i32 @foo()
15 ret void
16}
17
18declare i32 @__real_foo()
19
20define i32 @__wrap_foo() {
21 %rtn = call i32 @__real_foo()
22 ret i32 %rtn
23}
24
25; CHECK: - Type: CODE
26; CHECK-NEXT: Relocations:
27; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
28; CHECK-NEXT: Index: 2
29; CHECK-NEXT: Offset: 0x00000009
30; CHECK-NEXT: - Type: R_WASM_FUNCTION_INDEX_LEB
31; CHECK-NEXT: Index: 0
32; CHECK-NEXT: Offset: 0x00000013
33
34; CHECK: FunctionNames:
35; CHECK-NEXT: - Index: 0
36; CHECK-NEXT: Name: foo
37; CHECK-NEXT: - Index: 1
38; CHECK-NEXT: Name: _start
39; CHECK-NEXT: - Index: 2
40; CHECK-NEXT: Name: __wrap_foo
deps/lld/tools/lld/CMakeLists.txt+1
...@@ -8,6 +8,7 @@ add_lld_tool(lld...@@ -8,6 +8,7 @@ add_lld_tool(lld
88
9target_link_libraries(lld9target_link_libraries(lld
10 PRIVATE10 PRIVATE
11 lldCommon
11 lldCOFF12 lldCOFF
12 lldDriver13 lldDriver
13 lldELF14 lldELF
deps/lld/tools/lld/lld.cpp+64-43
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- tools/lld/lld.cpp - Linker Driver Dispatcher -----------------------===//1//===- tools/lld/lld.cpp - Linker Driver Dispatcher -----------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -27,9 +26,13 @@...@@ -27,9 +26,13 @@
27//===----------------------------------------------------------------------===//26//===----------------------------------------------------------------------===//
2827
29#include "lld/Common/Driver.h"28#include "lld/Common/Driver.h"
29#include "lld/Common/Memory.h"
30#include "llvm/ADT/STLExtras.h"30#include "llvm/ADT/STLExtras.h"
31#include "llvm/ADT/SmallVector.h"
31#include "llvm/ADT/StringSwitch.h"32#include "llvm/ADT/StringSwitch.h"
33#include "llvm/ADT/Triple.h"
32#include "llvm/ADT/Twine.h"34#include "llvm/ADT/Twine.h"
35#include "llvm/Support/CommandLine.h"
33#include "llvm/Support/InitLLVM.h"36#include "llvm/Support/InitLLVM.h"
34#include "llvm/Support/Path.h"37#include "llvm/Support/Path.h"
35#include <cstdlib>38#include <cstdlib>
...@@ -46,13 +49,13 @@ enum Flavor {...@@ -46,13 +49,13 @@ enum Flavor {
46 Wasm, // -flavor wasm49 Wasm, // -flavor wasm
47};50};
4851
49LLVM_ATTRIBUTE_NORETURN static void die(const Twine &S) {52LLVM_ATTRIBUTE_NORETURN static void die(const Twine &s) {
50 errs() << S << "\n";53 errs() << s << "\n";
51 exit(1);54 exit(1);
52}55}
5356
54static Flavor getFlavor(StringRef S) {57static Flavor getFlavor(StringRef s) {
55 return StringSwitch<Flavor>(S)58 return StringSwitch<Flavor>(s)
56 .CasesLower("ld", "ld.lld", "gnu", Gnu)59 .CasesLower("ld", "ld.lld", "gnu", Gnu)
57 .CasesLower("wasm", "ld-wasm", Wasm)60 .CasesLower("wasm", "ld-wasm", Wasm)
58 .CaseLower("link", WinLink)61 .CaseLower("link", WinLink)
...@@ -60,55 +63,73 @@ static Flavor getFlavor(StringRef S) {...@@ -60,55 +63,73 @@ static Flavor getFlavor(StringRef S) {
60 .Default(Invalid);63 .Default(Invalid);
61}64}
6265
63static bool isPETarget(const std::vector<const char *> &V) {66static cl::TokenizerCallback getDefaultQuotingStyle() {
64 for (auto It = V.begin(); It + 1 != V.end(); ++It) {67 if (Triple(sys::getProcessTriple()).getOS() == Triple::Win32)
65 if (StringRef(*It) != "-m")68 return cl::TokenizeWindowsCommandLine;
69 return cl::TokenizeGNUCommandLine;
70}
71
72static bool isPETargetName(StringRef s) {
73 return s == "i386pe" || s == "i386pep" || s == "thumb2pe" || s == "arm64pe";
74}
75
76static bool isPETarget(std::vector<const char *> &v) {
77 for (auto it = v.begin(); it + 1 != v.end(); ++it) {
78 if (StringRef(*it) != "-m")
79 continue;
80 return isPETargetName(*(it + 1));
81 }
82 // Expand response files (arguments in the form of @<filename>)
83 // to allow detecting the -m argument from arguments in them.
84 SmallVector<const char *, 256> expandedArgs(v.data(), v.data() + v.size());
85 cl::ExpandResponseFiles(saver, getDefaultQuotingStyle(), expandedArgs);
86 for (auto it = expandedArgs.begin(); it + 1 != expandedArgs.end(); ++it) {
87 if (StringRef(*it) != "-m")
66 continue;88 continue;
67 StringRef S = *(It + 1);89 return isPETargetName(*(it + 1));
68 return S == "i386pe" || S == "i386pep" || S == "thumb2pe" || S == "arm64pe";
69 }90 }
70 return false;91 return false;
71}92}
7293
73static Flavor parseProgname(StringRef Progname) {94static Flavor parseProgname(StringRef progname) {
74#if __APPLE__95#if __APPLE__
75 // Use Darwin driver for "ld" on Darwin.96 // Use Darwin driver for "ld" on Darwin.
76 if (Progname == "ld")97 if (progname == "ld")
77 return Darwin;98 return Darwin;
78#endif99#endif
79100
80#if LLVM_ON_UNIX101#if LLVM_ON_UNIX
81 // Use GNU driver for "ld" on other Unix-like system.102 // Use GNU driver for "ld" on other Unix-like system.
82 if (Progname == "ld")103 if (progname == "ld")
83 return Gnu;104 return Gnu;
84#endif105#endif
85106
86 // Progname may be something like "lld-gnu". Parse it.107 // Progname may be something like "lld-gnu". Parse it.
87 SmallVector<StringRef, 3> V;108 SmallVector<StringRef, 3> v;
88 Progname.split(V, "-");109 progname.split(v, "-");
89 for (StringRef S : V)110 for (StringRef s : v)
90 if (Flavor F = getFlavor(S))111 if (Flavor f = getFlavor(s))
91 return F;112 return f;
92 return Invalid;113 return Invalid;
93}114}
94115
95static Flavor parseFlavor(std::vector<const char *> &V) {116static Flavor parseFlavor(std::vector<const char *> &v) {
96 // Parse -flavor option.117 // Parse -flavor option.
97 if (V.size() > 1 && V[1] == StringRef("-flavor")) {118 if (v.size() > 1 && v[1] == StringRef("-flavor")) {
98 if (V.size() <= 2)119 if (v.size() <= 2)
99 die("missing arg value for '-flavor'");120 die("missing arg value for '-flavor'");
100 Flavor F = getFlavor(V[2]);121 Flavor f = getFlavor(v[2]);
101 if (F == Invalid)122 if (f == Invalid)
102 die("Unknown flavor: " + StringRef(V[2]));123 die("Unknown flavor: " + StringRef(v[2]));
103 V.erase(V.begin() + 1, V.begin() + 3);124 v.erase(v.begin() + 1, v.begin() + 3);
104 return F;125 return f;
105 }126 }
106127
107 // Deduct the flavor from argv[0].128 // Deduct the flavor from argv[0].
108 StringRef Arg0 = path::filename(V[0]);129 StringRef arg0 = path::filename(v[0]);
109 if (Arg0.endswith_lower(".exe"))130 if (arg0.endswith_lower(".exe"))
110 Arg0 = Arg0.drop_back(4);131 arg0 = arg0.drop_back(4);
111 return parseProgname(Arg0);132 return parseProgname(arg0);
112}133}
113134
114// If this function returns true, lld calls _exit() so that it quickly135// If this function returns true, lld calls _exit() so that it quickly
...@@ -121,21 +142,21 @@ static bool canExitEarly() { return StringRef(getenv("LLD_IN_TEST")) != "1"; }...@@ -121,21 +142,21 @@ static bool canExitEarly() { return StringRef(getenv("LLD_IN_TEST")) != "1"; }
121142
122/// Universal linker main(). This linker emulates the gnu, darwin, or143/// Universal linker main(). This linker emulates the gnu, darwin, or
123/// windows linker based on the argv[0] or -flavor option.144/// windows linker based on the argv[0] or -flavor option.
124int main(int Argc, const char **Argv) {145int main(int argc, const char **argv) {
125 InitLLVM X(Argc, Argv);146 InitLLVM x(argc, argv);
126147
127 std::vector<const char *> Args(Argv, Argv + Argc);148 std::vector<const char *> args(argv, argv + argc);
128 switch (parseFlavor(Args)) {149 switch (parseFlavor(args)) {
129 case Gnu:150 case Gnu:
130 if (isPETarget(Args))151 if (isPETarget(args))
131 return !mingw::link(Args);152 return !mingw::link(args);
132 return !elf::link(Args, canExitEarly());153 return !elf::link(args, canExitEarly());
133 case WinLink:154 case WinLink:
134 return !coff::link(Args, canExitEarly());155 return !coff::link(args, canExitEarly());
135 case Darwin:156 case Darwin:
136 return !mach_o::link(Args, canExitEarly());157 return !mach_o::link(args, canExitEarly());
137 case Wasm:158 case Wasm:
138 return !wasm::link(Args, canExitEarly());159 return !wasm::link(args, canExitEarly());
139 default:160 default:
140 die("lld is a generic driver.\n"161 die("lld is a generic driver.\n"
141 "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld"162 "Invoke ld.lld (Unix), ld64.lld (macOS), lld-link (Windows), wasm-ld"
deps/lld/unittests/DriverTests/DarwinLdDriverTest.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/unittest/DarwinLdDriverTest.cpp --------------------------------===//1//===- lld/unittest/DarwinLdDriverTest.cpp --------------------------------===//
2//2//
3// The LLVM Compiler Infrastructure3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9///8///
deps/lld/unittests/MachOTests/MachONormalizedFileBinaryReaderTests.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/unittest/MachOTests/MachONormalizedFileBinaryReaderTests.cpp ---===//1//===- lld/unittest/MachOTests/MachONormalizedFileBinaryReaderTests.cpp ---===//
2//2//
3// The LLVM Compiler Infrastructure3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/unittests/MachOTests/MachONormalizedFileBinaryWriterTests.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/unittest/MachOTests/MachONormalizedFileBinaryWriterTests.cpp ---===//1//===- lld/unittest/MachOTests/MachONormalizedFileBinaryWriterTests.cpp ---===//
2//2//
3// The LLVM Compiler Infrastructure3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/unittests/MachOTests/MachONormalizedFileToAtomsTests.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/unittest/MachOTests/MachONormalizedFileToAtomsTests.cpp --------===//1//===- lld/unittest/MachOTests/MachONormalizedFileToAtomsTests.cpp --------===//
2//2//
3// The LLVM Compiler Infrastructure3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/unittests/MachOTests/MachONormalizedFileYAMLTests.cpp+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- lld/unittest/MachOTests/MachONormalizedFileYAMLTests.cpp -----------===//1//===- lld/unittest/MachOTests/MachONormalizedFileYAMLTests.cpp -----------===//
2//2//
3// The LLVM Compiler Infrastructure3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/utils/benchmark.py+12-8
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1#!/usr/bin/env python1#!/usr/bin/env python
2#2#
3# The LLVM Compiler Infrastructure3# Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4#4# See https://llvm.org/LICENSE.txt for license information.
5# This file is distributed under the University of Illinois Open Source5# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6# License. See LICENSE.TXT for details.
7#6#
8# ==------------------------------------------------------------------------==#7# ==------------------------------------------------------------------------==#
98
...@@ -14,8 +13,13 @@ import subprocess...@@ -14,8 +13,13 @@ import subprocess
14import json13import json
15import datetime14import datetime
16import argparse15import argparse
17import urllib16try:
18import urllib217 from urllib.parse import urlencode
18 from urllib.request import urlopen, Request
19except ImportError:
20 from urllib import urlencode
21 from urllib2 import urlopen, Request
22
1923
20parser = argparse.ArgumentParser()24parser = argparse.ArgumentParser()
21parser.add_argument('benchmark_directory')25parser.add_argument('benchmark_directory')
...@@ -127,8 +131,8 @@ def buildLntJson(benchmarks):...@@ -127,8 +131,8 @@ def buildLntJson(benchmarks):
127 return json.dumps(ret, sort_keys=True, indent=4)131 return json.dumps(ret, sort_keys=True, indent=4)
128132
129def submitToServer(data):133def submitToServer(data):
130 data2 = urllib.urlencode({ 'input_data' : data }).encode('ascii')134 data2 = urlencode({ 'input_data' : data }).encode('ascii')
131 urllib2.urlopen(urllib2.Request(args.url, data2))135 urlopen(Request(args.url, data2))
132136
133os.chdir(args.benchmark_directory)137os.chdir(args.benchmark_directory)
134data = buildLntJson(getBenchmarks())138data = buildLntJson(getBenchmarks())
deps/lld/wasm/CMakeLists.txt+3-1
...@@ -13,8 +13,10 @@ add_lld_library(lldWasm...@@ -13,8 +13,10 @@ add_lld_library(lldWasm
13 LTO.cpp13 LTO.cpp
14 MarkLive.cpp14 MarkLive.cpp
15 OutputSections.cpp15 OutputSections.cpp
16 Relocations.cpp
16 SymbolTable.cpp17 SymbolTable.cpp
17 Symbols.cpp18 Symbols.cpp
19 SyntheticSections.cpp
18 Writer.cpp20 Writer.cpp
19 WriterUtils.cpp21 WriterUtils.cpp
2022
...@@ -35,4 +37,4 @@ add_lld_library(lldWasm...@@ -35,4 +37,4 @@ add_lld_library(lldWasm
35 DEPENDS37 DEPENDS
36 WasmOptionsTableGen38 WasmOptionsTableGen
37 ${tablegen_deps}39 ${tablegen_deps}
38 )
\ No newline at end of file
40 )
deps/lld/wasm/Config.h+53-40
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Config.h -------------------------------------------------*- C++ -*-===//1//===- Config.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -18,49 +17,63 @@...@@ -18,49 +17,63 @@
18namespace lld {17namespace lld {
19namespace wasm {18namespace wasm {
2019
20// This struct contains the global configuration for the linker.
21// Most fields are direct mapping from the command line options
22// and such fields have the same name as the corresponding options.
23// Most fields are initialized by the driver.
21struct Configuration {24struct Configuration {
22 bool AllowUndefined;25 bool allowUndefined;
23 bool CompressRelocations;26 bool checkFeatures;
24 bool Demangle;27 bool compressRelocations;
25 bool DisableVerify;28 bool demangle;
26 bool ExportAll;29 bool disableVerify;
27 bool ExportDynamic;30 bool emitRelocs;
28 bool ExportTable;31 bool exportAll;
29 bool GcSections;32 bool exportDynamic;
30 bool ImportMemory;33 bool exportTable;
31 bool SharedMemory;34 bool gcSections;
32 bool ImportTable;35 bool importMemory;
33 bool MergeDataSegments;36 bool sharedMemory;
34 bool Pie;37 bool passiveSegments;
35 bool PrintGcSections;38 bool importTable;
36 bool Relocatable;39 bool mergeDataSegments;
37 bool SaveTemps;40 bool pie;
38 bool Shared;41 bool printGcSections;
39 bool StripAll;42 bool relocatable;
40 bool StripDebug;43 bool saveTemps;
41 bool StackFirst;44 bool shared;
42 uint32_t GlobalBase;45 bool stripAll;
43 uint32_t InitialMemory;46 bool stripDebug;
44 uint32_t MaxMemory;47 bool stackFirst;
45 uint32_t ZStackSize;48 bool trace;
46 unsigned LTOPartitions;49 uint32_t globalBase;
47 unsigned LTOO;50 uint32_t initialMemory;
48 unsigned Optimize;51 uint32_t maxMemory;
49 unsigned ThinLTOJobs;52 uint32_t zStackSize;
50 llvm::StringRef Entry;53 unsigned ltoPartitions;
51 llvm::StringRef OutputFile;54 unsigned ltoo;
52 llvm::StringRef ThinLTOCacheDir;55 unsigned optimize;
56 unsigned thinLTOJobs;
57
58 llvm::StringRef entry;
59 llvm::StringRef outputFile;
60 llvm::StringRef thinLTOCacheDir;
61
62 llvm::StringSet<> allowUndefinedSymbols;
63 llvm::StringSet<> exportedSymbols;
64 std::vector<llvm::StringRef> searchPaths;
65 llvm::CachePruningPolicy thinLTOCachePolicy;
66 llvm::Optional<std::vector<std::string>> features;
5367
54 llvm::StringSet<> AllowUndefinedSymbols;68 // The following config options do not directly correspond to any
55 std::vector<llvm::StringRef> SearchPaths;69 // particualr command line options.
56 llvm::CachePruningPolicy ThinLTOCachePolicy;
5770
58 // True if we are creating position-independent code.71 // True if we are creating position-independent code.
59 bool Pic;72 bool isPic;
60};73};
6174
62// The only instance of Configuration struct.75// The only instance of Configuration struct.
63extern Configuration *Config;76extern Configuration *config;
6477
65} // namespace wasm78} // namespace wasm
66} // namespace lld79} // namespace lld
deps/lld/wasm/Driver.cpp+498-325
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Driver.cpp ---------------------------------------------------------===//1//===- Driver.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -17,15 +16,18 @@...@@ -17,15 +16,18 @@
17#include "lld/Common/Args.h"16#include "lld/Common/Args.h"
18#include "lld/Common/ErrorHandler.h"17#include "lld/Common/ErrorHandler.h"
19#include "lld/Common/Memory.h"18#include "lld/Common/Memory.h"
19#include "lld/Common/Reproduce.h"
20#include "lld/Common/Strings.h"20#include "lld/Common/Strings.h"
21#include "lld/Common/Threads.h"21#include "lld/Common/Threads.h"
22#include "lld/Common/Version.h"22#include "lld/Common/Version.h"
23#include "llvm/ADT/Twine.h"23#include "llvm/ADT/Twine.h"
24#include "llvm/Object/Wasm.h"24#include "llvm/Object/Wasm.h"
25#include "llvm/Option/Arg.h"
25#include "llvm/Option/ArgList.h"26#include "llvm/Option/ArgList.h"
26#include "llvm/Support/CommandLine.h"27#include "llvm/Support/CommandLine.h"
27#include "llvm/Support/Path.h"28#include "llvm/Support/Path.h"
28#include "llvm/Support/Process.h"29#include "llvm/Support/Process.h"
30#include "llvm/Support/TarWriter.h"
29#include "llvm/Support/TargetSelect.h"31#include "llvm/Support/TargetSelect.h"
3032
31#define DEBUG_TYPE "lld"33#define DEBUG_TYPE "lld"
...@@ -38,7 +40,7 @@ using namespace llvm::wasm;...@@ -38,7 +40,7 @@ using namespace llvm::wasm;
38using namespace lld;40using namespace lld;
39using namespace lld::wasm;41using namespace lld::wasm;
4042
41Configuration *lld::wasm::Config;43Configuration *lld::wasm::config;
4244
43namespace {45namespace {
4446
...@@ -63,39 +65,39 @@ static void initLLVM() {...@@ -63,39 +65,39 @@ static void initLLVM() {
6365
64class LinkerDriver {66class LinkerDriver {
65public:67public:
66 void link(ArrayRef<const char *> ArgsArr);68 void link(ArrayRef<const char *> argsArr);
6769
68private:70private:
69 void createFiles(opt::InputArgList &Args);71 void createFiles(opt::InputArgList &args);
70 void addFile(StringRef Path);72 void addFile(StringRef path);
71 void addLibrary(StringRef Name);73 void addLibrary(StringRef name);
7274
73 // True if we are in --whole-archive and --no-whole-archive.75 // True if we are in --whole-archive and --no-whole-archive.
74 bool InWholeArchive = false;76 bool inWholeArchive = false;
7577
76 std::vector<InputFile *> Files;78 std::vector<InputFile *> files;
77};79};
78} // anonymous namespace80} // anonymous namespace
7981
80bool lld::wasm::link(ArrayRef<const char *> Args, bool CanExitEarly,82bool lld::wasm::link(ArrayRef<const char *> args, bool canExitEarly,
81 raw_ostream &Error) {83 raw_ostream &error) {
82 errorHandler().LogName = args::getFilenameWithoutExe(Args[0]);84 errorHandler().logName = args::getFilenameWithoutExe(args[0]);
83 errorHandler().ErrorOS = &Error;85 errorHandler().errorOS = &error;
84 errorHandler().ColorDiagnostics = Error.has_colors();86 errorHandler().colorDiagnostics = error.has_colors();
85 errorHandler().ErrorLimitExceededMsg =87 errorHandler().errorLimitExceededMsg =
86 "too many errors emitted, stopping now (use "88 "too many errors emitted, stopping now (use "
87 "-error-limit=0 to see all errors)";89 "-error-limit=0 to see all errors)";
8890
89 Config = make<Configuration>();91 config = make<Configuration>();
90 Symtab = make<SymbolTable>();92 symtab = make<SymbolTable>();
9193
92 initLLVM();94 initLLVM();
93 LinkerDriver().link(Args);95 LinkerDriver().link(args);
9496
95 // Exit immediately if we don't need to return to the caller.97 // Exit immediately if we don't need to return to the caller.
96 // This saves time because the overhead of calling destructors98 // This saves time because the overhead of calling destructors
97 // for all globally-allocated objects is not negligible.99 // for all globally-allocated objects is not negligible.
98 if (CanExitEarly)100 if (canExitEarly)
99 exitLld(errorCount() ? 1 : 0);101 exitLld(errorCount() ? 1 : 0);
100102
101 freeArena();103 freeArena();
...@@ -108,7 +110,7 @@ bool lld::wasm::link(ArrayRef<const char *> Args, bool CanExitEarly,...@@ -108,7 +110,7 @@ bool lld::wasm::link(ArrayRef<const char *> Args, bool CanExitEarly,
108#undef PREFIX110#undef PREFIX
109111
110// Create table mapping all options defined in Options.td112// Create table mapping all options defined in Options.td
111static const opt::OptTable::Info OptInfo[] = {113static const opt::OptTable::Info optInfo[] = {
112#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \114#define OPTION(X1, X2, ID, KIND, GROUP, ALIAS, X7, X8, X9, X10, X11, X12) \
113 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \115 {X1, X2, X10, X11, OPT_##ID, opt::Option::KIND##Class, \
114 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},116 X9, X8, OPT_##GROUP, OPT_##ALIAS, X7, X12},
...@@ -119,57 +121,57 @@ static const opt::OptTable::Info OptInfo[] = {...@@ -119,57 +121,57 @@ static const opt::OptTable::Info OptInfo[] = {
119namespace {121namespace {
120class WasmOptTable : public llvm::opt::OptTable {122class WasmOptTable : public llvm::opt::OptTable {
121public:123public:
122 WasmOptTable() : OptTable(OptInfo) {}124 WasmOptTable() : OptTable(optInfo) {}
123 opt::InputArgList parse(ArrayRef<const char *> Argv);125 opt::InputArgList parse(ArrayRef<const char *> argv);
124};126};
125} // namespace127} // namespace
126128
127// Set color diagnostics according to -color-diagnostics={auto,always,never}129// Set color diagnostics according to -color-diagnostics={auto,always,never}
128// or -no-color-diagnostics flags.130// or -no-color-diagnostics flags.
129static void handleColorDiagnostics(opt::InputArgList &Args) {131static void handleColorDiagnostics(opt::InputArgList &args) {
130 auto *Arg = Args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,132 auto *arg = args.getLastArg(OPT_color_diagnostics, OPT_color_diagnostics_eq,
131 OPT_no_color_diagnostics);133 OPT_no_color_diagnostics);
132 if (!Arg)134 if (!arg)
133 return;135 return;
134 if (Arg->getOption().getID() == OPT_color_diagnostics) {136 if (arg->getOption().getID() == OPT_color_diagnostics) {
135 errorHandler().ColorDiagnostics = true;137 errorHandler().colorDiagnostics = true;
136 } else if (Arg->getOption().getID() == OPT_no_color_diagnostics) {138 } else if (arg->getOption().getID() == OPT_no_color_diagnostics) {
137 errorHandler().ColorDiagnostics = false;139 errorHandler().colorDiagnostics = false;
138 } else {140 } else {
139 StringRef S = Arg->getValue();141 StringRef s = arg->getValue();
140 if (S == "always")142 if (s == "always")
141 errorHandler().ColorDiagnostics = true;143 errorHandler().colorDiagnostics = true;
142 else if (S == "never")144 else if (s == "never")
143 errorHandler().ColorDiagnostics = false;145 errorHandler().colorDiagnostics = false;
144 else if (S != "auto")146 else if (s != "auto")
145 error("unknown option: --color-diagnostics=" + S);147 error("unknown option: --color-diagnostics=" + s);
146 }148 }
147}149}
148150
149// Find a file by concatenating given paths.151// Find a file by concatenating given paths.
150static Optional<std::string> findFile(StringRef Path1, const Twine &Path2) {152static Optional<std::string> findFile(StringRef path1, const Twine &path2) {
151 SmallString<128> S;153 SmallString<128> s;
152 path::append(S, Path1, Path2);154 path::append(s, path1, path2);
153 if (fs::exists(S))155 if (fs::exists(s))
154 return S.str().str();156 return s.str().str();
155 return None;157 return None;
156}158}
157159
158opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) {160opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> argv) {
159 SmallVector<const char *, 256> Vec(Argv.data(), Argv.data() + Argv.size());161 SmallVector<const char *, 256> vec(argv.data(), argv.data() + argv.size());
160162
161 unsigned MissingIndex;163 unsigned missingIndex;
162 unsigned MissingCount;164 unsigned missingCount;
163165
164 // Expand response files (arguments in the form of @<filename>)166 // Expand response files (arguments in the form of @<filename>)
165 cl::ExpandResponseFiles(Saver, cl::TokenizeGNUCommandLine, Vec);167 cl::ExpandResponseFiles(saver, cl::TokenizeGNUCommandLine, vec);
166168
167 opt::InputArgList Args = this->ParseArgs(Vec, MissingIndex, MissingCount);169 opt::InputArgList args = this->ParseArgs(vec, missingIndex, missingCount);
168170
169 handleColorDiagnostics(Args);171 handleColorDiagnostics(args);
170 for (auto *Arg : Args.filtered(OPT_UNKNOWN))172 for (auto *arg : args.filtered(OPT_UNKNOWN))
171 error("unknown argument: " + Arg->getSpelling());173 error("unknown argument: " + arg->getAsString(args));
172 return Args;174 return args;
173}175}
174176
175// Currently we allow a ".imports" to live alongside a library. This can177// Currently we allow a ".imports" to live alongside a library. This can
...@@ -179,149 +181,188 @@ opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) {...@@ -179,149 +181,188 @@ opt::InputArgList WasmOptTable::parse(ArrayRef<const char *> Argv) {
179// In the long run this information would be better stored as a symbol181// In the long run this information would be better stored as a symbol
180// attribute/flag in the object file itself.182// attribute/flag in the object file itself.
181// See: https://github.com/WebAssembly/tool-conventions/issues/35183// See: https://github.com/WebAssembly/tool-conventions/issues/35
182static void readImportFile(StringRef Filename) {184static void readImportFile(StringRef filename) {
183 if (Optional<MemoryBufferRef> Buf = readFile(Filename))185 if (Optional<MemoryBufferRef> buf = readFile(filename))
184 for (StringRef Sym : args::getLines(*Buf))186 for (StringRef sym : args::getLines(*buf))
185 Config->AllowUndefinedSymbols.insert(Sym);187 config->allowUndefinedSymbols.insert(sym);
186}188}
187189
188// Returns slices of MB by parsing MB as an archive file.190// Returns slices of MB by parsing MB as an archive file.
189// Each slice consists of a member file in the archive.191// Each slice consists of a member file in the archive.
190std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef MB) {192std::vector<MemoryBufferRef> static getArchiveMembers(MemoryBufferRef mb) {
191 std::unique_ptr<Archive> File =193 std::unique_ptr<Archive> file =
192 CHECK(Archive::create(MB),194 CHECK(Archive::create(mb),
193 MB.getBufferIdentifier() + ": failed to parse archive");195 mb.getBufferIdentifier() + ": failed to parse archive");
194196
195 std::vector<MemoryBufferRef> V;197 std::vector<MemoryBufferRef> v;
196 Error Err = Error::success();198 Error err = Error::success();
197 for (const ErrorOr<Archive::Child> &COrErr : File->children(Err)) {199 for (const ErrorOr<Archive::Child> &cOrErr : file->children(err)) {
198 Archive::Child C =200 Archive::Child c =
199 CHECK(COrErr, MB.getBufferIdentifier() +201 CHECK(cOrErr, mb.getBufferIdentifier() +
200 ": could not get the child of the archive");202 ": could not get the child of the archive");
201 MemoryBufferRef MBRef =203 MemoryBufferRef mbref =
202 CHECK(C.getMemoryBufferRef(),204 CHECK(c.getMemoryBufferRef(),
203 MB.getBufferIdentifier() +205 mb.getBufferIdentifier() +
204 ": could not get the buffer for a child of the archive");206 ": could not get the buffer for a child of the archive");
205 V.push_back(MBRef);207 v.push_back(mbref);
206 }208 }
207 if (Err)209 if (err)
208 fatal(MB.getBufferIdentifier() +210 fatal(mb.getBufferIdentifier() +
209 ": Archive::children failed: " + toString(std::move(Err)));211 ": Archive::children failed: " + toString(std::move(err)));
210212
211 // Take ownership of memory buffers created for members of thin archives.213 // Take ownership of memory buffers created for members of thin archives.
212 for (std::unique_ptr<MemoryBuffer> &MB : File->takeThinBuffers())214 for (std::unique_ptr<MemoryBuffer> &mb : file->takeThinBuffers())
213 make<std::unique_ptr<MemoryBuffer>>(std::move(MB));215 make<std::unique_ptr<MemoryBuffer>>(std::move(mb));
214216
215 return V;217 return v;
216}218}
217219
218void LinkerDriver::addFile(StringRef Path) {220void LinkerDriver::addFile(StringRef path) {
219 Optional<MemoryBufferRef> Buffer = readFile(Path);221 Optional<MemoryBufferRef> buffer = readFile(path);
220 if (!Buffer.hasValue())222 if (!buffer.hasValue())
221 return;223 return;
222 MemoryBufferRef MBRef = *Buffer;224 MemoryBufferRef mbref = *buffer;
223225
224 switch (identify_magic(MBRef.getBuffer())) {226 switch (identify_magic(mbref.getBuffer())) {
225 case file_magic::archive: {227 case file_magic::archive: {
228 SmallString<128> importFile = path;
229 path::replace_extension(importFile, ".imports");
230 if (fs::exists(importFile))
231 readImportFile(importFile.str());
232
226 // Handle -whole-archive.233 // Handle -whole-archive.
227 if (InWholeArchive) {234 if (inWholeArchive) {
228 for (MemoryBufferRef &M : getArchiveMembers(MBRef))235 for (MemoryBufferRef &m : getArchiveMembers(mbref))
229 Files.push_back(createObjectFile(M));236 files.push_back(createObjectFile(m, path));
230 return;237 return;
231 }238 }
232239
233 SmallString<128> ImportFile = Path;240 std::unique_ptr<Archive> file =
234 path::replace_extension(ImportFile, ".imports");241 CHECK(Archive::create(mbref), path + ": failed to parse archive");
235 if (fs::exists(ImportFile))242
236 readImportFile(ImportFile.str());243 if (!file->isEmpty() && !file->hasSymbolTable()) {
244 error(mbref.getBufferIdentifier() +
245 ": archive has no index; run ranlib to add one");
246 }
237247
238 Files.push_back(make<ArchiveFile>(MBRef));248 files.push_back(make<ArchiveFile>(mbref));
239 return;249 return;
240 }250 }
241 case file_magic::bitcode:251 case file_magic::bitcode:
242 case file_magic::wasm_object:252 case file_magic::wasm_object:
243 Files.push_back(createObjectFile(MBRef));253 files.push_back(createObjectFile(mbref));
244 break;254 break;
245 default:255 default:
246 error("unknown file type: " + MBRef.getBufferIdentifier());256 error("unknown file type: " + mbref.getBufferIdentifier());
247 }257 }
248}258}
249259
250// Add a given library by searching it from input search paths.260// Add a given library by searching it from input search paths.
251void LinkerDriver::addLibrary(StringRef Name) {261void LinkerDriver::addLibrary(StringRef name) {
252 for (StringRef Dir : Config->SearchPaths) {262 for (StringRef dir : config->searchPaths) {
253 if (Optional<std::string> S = findFile(Dir, "lib" + Name + ".a")) {263 if (Optional<std::string> s = findFile(dir, "lib" + name + ".a")) {
254 addFile(*S);264 addFile(*s);
255 return;265 return;
256 }266 }
257 }267 }
258268
259 error("unable to find library -l" + Name);269 error("unable to find library -l" + name);
260}270}
261271
262void LinkerDriver::createFiles(opt::InputArgList &Args) {272void LinkerDriver::createFiles(opt::InputArgList &args) {
263 for (auto *Arg : Args) {273 for (auto *arg : args) {
264 switch (Arg->getOption().getUnaliasedOption().getID()) {274 switch (arg->getOption().getID()) {
265 case OPT_l:275 case OPT_l:
266 addLibrary(Arg->getValue());276 addLibrary(arg->getValue());
267 break;277 break;
268 case OPT_INPUT:278 case OPT_INPUT:
269 addFile(Arg->getValue());279 addFile(arg->getValue());
270 break;280 break;
271 case OPT_whole_archive:281 case OPT_whole_archive:
272 InWholeArchive = true;282 inWholeArchive = true;
273 break;283 break;
274 case OPT_no_whole_archive:284 case OPT_no_whole_archive:
275 InWholeArchive = false;285 inWholeArchive = false;
276 break;286 break;
277 }287 }
278 }288 }
279}289}
280290
281static StringRef getEntry(opt::InputArgList &Args, StringRef Default) {291static StringRef getEntry(opt::InputArgList &args) {
282 auto *Arg = Args.getLastArg(OPT_entry, OPT_no_entry);292 auto *arg = args.getLastArg(OPT_entry, OPT_no_entry);
283 if (!Arg)293 if (!arg) {
284 return Default;294 if (args.hasArg(OPT_relocatable))
285 if (Arg->getOption().getID() == OPT_no_entry)295 return "";
296 if (args.hasArg(OPT_shared))
297 return "__wasm_call_ctors";
298 return "_start";
299 }
300 if (arg->getOption().getID() == OPT_no_entry)
286 return "";301 return "";
287 return Arg->getValue();302 return arg->getValue();
288}303}
289304
290static const uint8_t UnreachableFn[] = {305// Initializes Config members by the command line options.
291 0x03 /* ULEB length */, 0x00 /* ULEB num locals */,306static void readConfigs(opt::InputArgList &args) {
292 0x00 /* opcode unreachable */, 0x0b /* opcode end */307 config->allowUndefined = args.hasArg(OPT_allow_undefined);
293};308 config->checkFeatures =
294309 args.hasFlag(OPT_check_features, OPT_no_check_features, true);
295// For weak undefined functions, there may be "call" instructions that reference310 config->compressRelocations = args.hasArg(OPT_compress_relocations);
296// the symbol. In this case, we need to synthesise a dummy/stub function that311 config->demangle = args.hasFlag(OPT_demangle, OPT_no_demangle, true);
297// will abort at runtime, so that relocations can still provided an operand to312 config->disableVerify = args.hasArg(OPT_disable_verify);
298// the call instruction that passes Wasm validation.313 config->emitRelocs = args.hasArg(OPT_emit_relocs);
299static void handleWeakUndefines() {314 config->entry = getEntry(args);
300 for (Symbol *Sym : Symtab->getSymbols()) {315 config->exportAll = args.hasArg(OPT_export_all);
301 if (!Sym->isUndefined() || !Sym->isWeak())316 config->exportDynamic = args.hasFlag(OPT_export_dynamic,
302 continue;317 OPT_no_export_dynamic, false);
303 auto *FuncSym = dyn_cast<FunctionSymbol>(Sym);318 config->exportTable = args.hasArg(OPT_export_table);
304 if (!FuncSym)319 errorHandler().fatalWarnings =
305 continue;320 args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);
306321 config->importMemory = args.hasArg(OPT_import_memory);
307 // It is possible for undefined functions not to have a signature (eg. if322 config->sharedMemory = args.hasArg(OPT_shared_memory);
308 // added via "--undefined"), but weak undefined ones do have a signature.323 config->passiveSegments = args.hasFlag(
309 assert(FuncSym->Signature);324 OPT_passive_segments, OPT_active_segments, config->sharedMemory);
310 const WasmSignature &Sig = *FuncSym->Signature;325 config->importTable = args.hasArg(OPT_import_table);
311326 config->ltoo = args::getInteger(args, OPT_lto_O, 2);
312 // Add a synthetic dummy for weak undefined functions. These dummies will327 config->ltoPartitions = args::getInteger(args, OPT_lto_partitions, 1);
313 // be GC'd if not used as the target of any "call" instructions.328 config->optimize = args::getInteger(args, OPT_O, 0);
314 std::string SymName = toString(*Sym);329 config->outputFile = args.getLastArgValue(OPT_o);
315 StringRef DebugName = Saver.save("undefined function " + SymName);330 config->relocatable = args.hasArg(OPT_relocatable);
316 auto *Func = make<SyntheticFunction>(Sig, Sym->getName(), DebugName);331 config->gcSections =
317 Func->setBody(UnreachableFn);332 args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !config->relocatable);
318 // Ensure it compares equal to the null pointer, and so that table relocs333 config->mergeDataSegments =
319 // don't pull in the stub body (only call-operand relocs should do that).334 args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments,
320 Func->setTableIndex(0);335 !config->relocatable);
321 Symtab->SyntheticFunctions.emplace_back(Func);336 config->pie = args.hasFlag(OPT_pie, OPT_no_pie, false);
322 // Hide our dummy to prevent export.337 config->printGcSections =
323 uint32_t Flags = WASM_SYMBOL_VISIBILITY_HIDDEN;338 args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
324 replaceSymbol<DefinedFunction>(Sym, Sym->getName(), Flags, nullptr, Func);339 config->saveTemps = args.hasArg(OPT_save_temps);
340 config->searchPaths = args::getStrings(args, OPT_L);
341 config->shared = args.hasArg(OPT_shared);
342 config->stripAll = args.hasArg(OPT_strip_all);
343 config->stripDebug = args.hasArg(OPT_strip_debug);
344 config->stackFirst = args.hasArg(OPT_stack_first);
345 config->trace = args.hasArg(OPT_trace);
346 config->thinLTOCacheDir = args.getLastArgValue(OPT_thinlto_cache_dir);
347 config->thinLTOCachePolicy = CHECK(
348 parseCachePruningPolicy(args.getLastArgValue(OPT_thinlto_cache_policy)),
349 "--thinlto-cache-policy: invalid cache policy");
350 config->thinLTOJobs = args::getInteger(args, OPT_thinlto_jobs, -1u);
351 errorHandler().verbose = args.hasArg(OPT_verbose);
352 LLVM_DEBUG(errorHandler().verbose = true);
353 threadsEnabled = args.hasFlag(OPT_threads, OPT_no_threads, true);
354
355 config->initialMemory = args::getInteger(args, OPT_initial_memory, 0);
356 config->globalBase = args::getInteger(args, OPT_global_base, 1024);
357 config->maxMemory = args::getInteger(args, OPT_max_memory, 0);
358 config->zStackSize =
359 args::getZOptionValue(args, OPT_z, "stack-size", WasmPageSize);
360
361 if (auto *arg = args.getLastArg(OPT_features)) {
362 config->features =
363 llvm::Optional<std::vector<std::string>>(std::vector<std::string>());
364 for (StringRef s : arg->getValues())
365 config->features->push_back(s);
325 }366 }
326}367}
327368
...@@ -329,286 +370,418 @@ static void handleWeakUndefines() {...@@ -329,286 +370,418 @@ static void handleWeakUndefines() {
329// command line options, but computed based on other Config values.370// command line options, but computed based on other Config values.
330// This function initialize such members. See Config.h for the details371// This function initialize such members. See Config.h for the details
331// of these values.372// of these values.
332static void setConfigs(opt::InputArgList &Args) {373static void setConfigs() {
333 Config->AllowUndefined = Args.hasArg(OPT_allow_undefined);374 config->isPic = config->pie || config->shared;
334 Config->CompressRelocations = Args.hasArg(OPT_compress_relocations);375
335 Config->Demangle = Args.hasFlag(OPT_demangle, OPT_no_demangle, true);376 if (config->isPic) {
336 Config->DisableVerify = Args.hasArg(OPT_disable_verify);377 if (config->exportTable)
337 Config->Entry = getEntry(Args, Args.hasArg(OPT_relocatable) ? "" : "_start");378 error("-shared/-pie is incompatible with --export-table");
338 Config->ExportAll = Args.hasArg(OPT_export_all);379 config->importTable = true;
339 Config->ExportDynamic = Args.hasFlag(OPT_export_dynamic,380 }
340 OPT_no_export_dynamic, false);381
341 Config->ExportTable = Args.hasArg(OPT_export_table);382 if (config->shared) {
342 errorHandler().FatalWarnings =383 config->importMemory = true;
343 Args.hasFlag(OPT_fatal_warnings, OPT_no_fatal_warnings, false);384 config->exportDynamic = true;
344 Config->ImportMemory = Args.hasArg(OPT_import_memory);385 config->allowUndefined = true;
345 Config->SharedMemory = Args.hasArg(OPT_shared_memory);386 }
346 Config->ImportTable = Args.hasArg(OPT_import_table);
347 Config->LTOO = args::getInteger(Args, OPT_lto_O, 2);
348 Config->LTOPartitions = args::getInteger(Args, OPT_lto_partitions, 1);
349 Config->Optimize = args::getInteger(Args, OPT_O, 0);
350 Config->OutputFile = Args.getLastArgValue(OPT_o);
351 Config->Relocatable = Args.hasArg(OPT_relocatable);
352 Config->GcSections =
353 Args.hasFlag(OPT_gc_sections, OPT_no_gc_sections, !Config->Relocatable);
354 Config->MergeDataSegments =
355 Args.hasFlag(OPT_merge_data_segments, OPT_no_merge_data_segments,
356 !Config->Relocatable);
357 Config->Pie = Args.hasFlag(OPT_pie, OPT_no_pie, false);
358 Config->PrintGcSections =
359 Args.hasFlag(OPT_print_gc_sections, OPT_no_print_gc_sections, false);
360 Config->SaveTemps = Args.hasArg(OPT_save_temps);
361 Config->SearchPaths = args::getStrings(Args, OPT_L);
362 Config->Shared = Args.hasArg(OPT_shared);
363 Config->StripAll = Args.hasArg(OPT_strip_all);
364 Config->StripDebug = Args.hasArg(OPT_strip_debug);
365 Config->StackFirst = Args.hasArg(OPT_stack_first);
366 Config->ThinLTOCacheDir = Args.getLastArgValue(OPT_thinlto_cache_dir);
367 Config->ThinLTOCachePolicy = CHECK(
368 parseCachePruningPolicy(Args.getLastArgValue(OPT_thinlto_cache_policy)),
369 "--thinlto-cache-policy: invalid cache policy");
370 Config->ThinLTOJobs = args::getInteger(Args, OPT_thinlto_jobs, -1u);
371 errorHandler().Verbose = Args.hasArg(OPT_verbose);
372 ThreadsEnabled = Args.hasFlag(OPT_threads, OPT_no_threads, true);
373
374 Config->InitialMemory = args::getInteger(Args, OPT_initial_memory, 0);
375 Config->GlobalBase = args::getInteger(Args, OPT_global_base, 1024);
376 Config->MaxMemory = args::getInteger(Args, OPT_max_memory, 0);
377 Config->ZStackSize =
378 args::getZOptionValue(Args, OPT_z, "stack-size", WasmPageSize);
379}387}
380388
381// Some command line options or some combinations of them are not allowed.389// Some command line options or some combinations of them are not allowed.
382// This function checks for such errors.390// This function checks for such errors.
383static void checkOptions(opt::InputArgList &Args) {391static void checkOptions(opt::InputArgList &args) {
384 if (!Config->StripDebug && !Config->StripAll && Config->CompressRelocations)392 if (!config->stripDebug && !config->stripAll && config->compressRelocations)
385 error("--compress-relocations is incompatible with output debug"393 error("--compress-relocations is incompatible with output debug"
386 " information. Please pass --strip-debug or --strip-all");394 " information. Please pass --strip-debug or --strip-all");
387395
388 if (Config->LTOO > 3)396 if (config->ltoo > 3)
389 error("invalid optimization level for LTO: " + Twine(Config->LTOO));397 error("invalid optimization level for LTO: " + Twine(config->ltoo));
390 if (Config->LTOPartitions == 0)398 if (config->ltoPartitions == 0)
391 error("--lto-partitions: number of threads must be > 0");399 error("--lto-partitions: number of threads must be > 0");
392 if (Config->ThinLTOJobs == 0)400 if (config->thinLTOJobs == 0)
393 error("--thinlto-jobs: number of threads must be > 0");401 error("--thinlto-jobs: number of threads must be > 0");
394402
395 if (Config->Pie && Config->Shared)403 if (config->pie && config->shared)
396 error("-shared and -pie may not be used together");404 error("-shared and -pie may not be used together");
397405
398 if (Config->OutputFile.empty())406 if (config->outputFile.empty())
399 error("no output file specified");407 error("no output file specified");
400408
401 if (Config->ImportTable && Config->ExportTable)409 if (config->importTable && config->exportTable)
402 error("--import-table and --export-table may not be used together");410 error("--import-table and --export-table may not be used together");
403411
404 if (Config->Relocatable) {412 if (config->relocatable) {
405 if (!Config->Entry.empty())413 if (!config->entry.empty())
406 error("entry point specified for relocatable output file");414 error("entry point specified for relocatable output file");
407 if (Config->GcSections)415 if (config->gcSections)
408 error("-r and --gc-sections may not be used together");416 error("-r and --gc-sections may not be used together");
409 if (Config->CompressRelocations)417 if (config->compressRelocations)
410 error("-r -and --compress-relocations may not be used together");418 error("-r -and --compress-relocations may not be used together");
411 if (Args.hasArg(OPT_undefined))419 if (args.hasArg(OPT_undefined))
412 error("-r -and --undefined may not be used together");420 error("-r -and --undefined may not be used together");
413 if (Config->Pie)421 if (config->pie)
414 error("-r and -pie may not be used together");422 error("-r and -pie may not be used together");
415 }423 }
416}424}
417425
418// Force Sym to be entered in the output. Used for -u or equivalent.426// Force Sym to be entered in the output. Used for -u or equivalent.
419static Symbol *handleUndefined(StringRef Name) {427static Symbol *handleUndefined(StringRef name) {
420 Symbol *Sym = Symtab->find(Name);428 Symbol *sym = symtab->find(name);
421 if (!Sym)429 if (!sym)
422 return nullptr;430 return nullptr;
423431
424 // Since symbol S may not be used inside the program, LTO may432 // Since symbol S may not be used inside the program, LTO may
425 // eliminate it. Mark the symbol as "used" to prevent it.433 // eliminate it. Mark the symbol as "used" to prevent it.
426 Sym->IsUsedInRegularObj = true;434 sym->isUsedInRegularObj = true;
427435
428 if (auto *LazySym = dyn_cast<LazySymbol>(Sym))436 if (auto *lazySym = dyn_cast<LazySymbol>(sym))
429 LazySym->fetch();437 lazySym->fetch();
430438
431 return Sym;439 return sym;
432}440}
433441
434static UndefinedGlobal *442static UndefinedGlobal *
435createUndefinedGlobal(StringRef Name, llvm::wasm::WasmGlobalType *Type) {443createUndefinedGlobal(StringRef name, llvm::wasm::WasmGlobalType *type) {
436 auto *Sym =444 auto *sym =
437 cast<UndefinedGlobal>(Symtab->addUndefinedGlobal(Name, Name,445 cast<UndefinedGlobal>(symtab->addUndefinedGlobal(name, name,
438 DefaultModule, 0,446 defaultModule, 0,
439 nullptr, Type));447 nullptr, type));
440 Config->AllowUndefinedSymbols.insert(Sym->getName());448 config->allowUndefinedSymbols.insert(sym->getName());
441 Sym->IsUsedInRegularObj = true;449 sym->isUsedInRegularObj = true;
442 return Sym;450 return sym;
443}451}
444452
445// Create ABI-defined synthetic symbols453// Create ABI-defined synthetic symbols
446static void createSyntheticSymbols() {454static void createSyntheticSymbols() {
447 static WasmSignature NullSignature = {{}, {}};455 static WasmSignature nullSignature = {{}, {}};
448 static llvm::wasm::WasmGlobalType GlobalTypeI32 = {WASM_TYPE_I32, false};456 static WasmSignature i32ArgSignature = {{}, {ValType::I32}};
449 static llvm::wasm::WasmGlobalType MutableGlobalTypeI32 = {WASM_TYPE_I32,457 static llvm::wasm::WasmGlobalType globalTypeI32 = {WASM_TYPE_I32, false};
458 static llvm::wasm::WasmGlobalType mutableGlobalTypeI32 = {WASM_TYPE_I32,
450 true};459 true};
451460
452 if (!Config->Relocatable)461 if (!config->relocatable) {
453 WasmSym::CallCtors = Symtab->addSyntheticFunction(462 WasmSym::callCtors = symtab->addSyntheticFunction(
454 "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,463 "__wasm_call_ctors", WASM_SYMBOL_VISIBILITY_HIDDEN,
455 make<SyntheticFunction>(NullSignature, "__wasm_call_ctors"));464 make<SyntheticFunction>(nullSignature, "__wasm_call_ctors"));
465
466 if (config->passiveSegments) {
467 // Passive segments are used to avoid memory being reinitialized on each
468 // thread's instantiation. These passive segments are initialized and
469 // dropped in __wasm_init_memory, which is the first function called from
470 // __wasm_call_ctors.
471 WasmSym::initMemory = symtab->addSyntheticFunction(
472 "__wasm_init_memory", WASM_SYMBOL_VISIBILITY_HIDDEN,
473 make<SyntheticFunction>(nullSignature, "__wasm_init_memory"));
474 }
456475
457 // The __stack_pointer is imported in the shared library case, and exported476 if (config->isPic) {
458 // in the non-shared (executable) case.477 // For PIC code we create a synthetic function __wasm_apply_relocs which
459 if (Config->Shared) {478 // is called from __wasm_call_ctors before the user-level constructors.
460 WasmSym::StackPointer =479 WasmSym::applyRelocs = symtab->addSyntheticFunction(
461 createUndefinedGlobal("__stack_pointer", &MutableGlobalTypeI32);480 "__wasm_apply_relocs", WASM_SYMBOL_VISIBILITY_HIDDEN,
462 } else {481 make<SyntheticFunction>(nullSignature, "__wasm_apply_relocs"));
463 llvm::wasm::WasmGlobal Global;482 }
464 Global.Type = {WASM_TYPE_I32, true};
465 Global.InitExpr.Value.Int32 = 0;
466 Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
467 Global.SymbolName = "__stack_pointer";
468 auto *StackPointer = make<InputGlobal>(Global, nullptr);
469 StackPointer->Live = true;
470 // For non-PIC code
471 // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global
472 // spec proposal is implemented in all major browsers.
473 // See: https://github.com/WebAssembly/mutable-global
474 WasmSym::StackPointer = Symtab->addSyntheticGlobal(
475 "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, StackPointer);
476 WasmSym::HeapBase = Symtab->addSyntheticDataSymbol("__heap_base", 0);
477 WasmSym::DataEnd = Symtab->addSyntheticDataSymbol("__data_end", 0);
478
479 // These two synthetic symbols exist purely for the embedder so we always
480 // want to export them.
481 WasmSym::HeapBase->ForceExport = true;
482 WasmSym::DataEnd->ForceExport = true;
483 }483 }
484484
485 if (Config->Pic) {485 if (!config->shared)
486 WasmSym::dataEnd = symtab->addOptionalDataSymbol("__data_end");
487
488 if (config->isPic) {
489 WasmSym::stackPointer =
490 createUndefinedGlobal("__stack_pointer", &mutableGlobalTypeI32);
486 // For PIC code, we import two global variables (__memory_base and491 // For PIC code, we import two global variables (__memory_base and
487 // __table_base) from the environment and use these as the offset at492 // __table_base) from the environment and use these as the offset at
488 // which to load our static data and function table.493 // which to load our static data and function table.
489 // See:494 // See:
490 // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md495 // https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
491 WasmSym::MemoryBase =496 WasmSym::memoryBase =
492 createUndefinedGlobal("__memory_base", &GlobalTypeI32);497 createUndefinedGlobal("__memory_base", &globalTypeI32);
493 WasmSym::TableBase = createUndefinedGlobal("__table_base", &GlobalTypeI32);498 WasmSym::tableBase = createUndefinedGlobal("__table_base", &globalTypeI32);
494 WasmSym::MemoryBase->markLive();499 WasmSym::memoryBase->markLive();
495 WasmSym::TableBase->markLive();500 WasmSym::tableBase->markLive();
501 } else {
502 llvm::wasm::WasmGlobal global;
503 global.Type = {WASM_TYPE_I32, true};
504 global.InitExpr.Value.Int32 = 0;
505 global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
506 global.SymbolName = "__stack_pointer";
507 auto *stackPointer = make<InputGlobal>(global, nullptr);
508 stackPointer->live = true;
509 // For non-PIC code
510 // TODO(sbc): Remove WASM_SYMBOL_VISIBILITY_HIDDEN when the mutable global
511 // spec proposal is implemented in all major browsers.
512 // See: https://github.com/WebAssembly/mutable-global
513 WasmSym::stackPointer = symtab->addSyntheticGlobal(
514 "__stack_pointer", WASM_SYMBOL_VISIBILITY_HIDDEN, stackPointer);
515 WasmSym::globalBase = symtab->addOptionalDataSymbol("__global_base");
516 WasmSym::heapBase = symtab->addOptionalDataSymbol("__heap_base");
496 }517 }
497518
498 WasmSym::DsoHandle = Symtab->addSyntheticDataSymbol(519 if (config->sharedMemory && !config->shared) {
520 llvm::wasm::WasmGlobal tlsBaseGlobal;
521 tlsBaseGlobal.Type = {WASM_TYPE_I32, true};
522 tlsBaseGlobal.InitExpr.Value.Int32 = 0;
523 tlsBaseGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
524 tlsBaseGlobal.SymbolName = "__tls_base";
525 WasmSym::tlsBase =
526 symtab->addSyntheticGlobal("__tls_base", WASM_SYMBOL_VISIBILITY_HIDDEN,
527 make<InputGlobal>(tlsBaseGlobal, nullptr));
528
529 llvm::wasm::WasmGlobal tlsSizeGlobal;
530 tlsSizeGlobal.Type = {WASM_TYPE_I32, false};
531 tlsSizeGlobal.InitExpr.Value.Int32 = 0;
532 tlsSizeGlobal.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
533 tlsSizeGlobal.SymbolName = "__tls_size";
534 WasmSym::tlsSize =
535 symtab->addSyntheticGlobal("__tls_size", WASM_SYMBOL_VISIBILITY_HIDDEN,
536 make<InputGlobal>(tlsSizeGlobal, nullptr));
537
538 WasmSym::initTLS = symtab->addSyntheticFunction(
539 "__wasm_init_tls", WASM_SYMBOL_VISIBILITY_HIDDEN,
540 make<SyntheticFunction>(i32ArgSignature, "__wasm_init_tls"));
541 }
542
543 WasmSym::dsoHandle = symtab->addSyntheticDataSymbol(
499 "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN);544 "__dso_handle", WASM_SYMBOL_VISIBILITY_HIDDEN);
500}545}
501546
502void LinkerDriver::link(ArrayRef<const char *> ArgsArr) {547// Reconstructs command line arguments so that so that you can re-run
503 WasmOptTable Parser;548// the same command with the same inputs. This is for --reproduce.
504 opt::InputArgList Args = Parser.parse(ArgsArr.slice(1));549static std::string createResponseFile(const opt::InputArgList &args) {
550 SmallString<0> data;
551 raw_svector_ostream os(data);
552
553 // Copy the command line to the output while rewriting paths.
554 for (auto *arg : args) {
555 switch (arg->getOption().getID()) {
556 case OPT_reproduce:
557 break;
558 case OPT_INPUT:
559 os << quote(relativeToRoot(arg->getValue())) << "\n";
560 break;
561 case OPT_o:
562 // If -o path contains directories, "lld @response.txt" will likely
563 // fail because the archive we are creating doesn't contain empty
564 // directories for the output path (-o doesn't create directories).
565 // Strip directories to prevent the issue.
566 os << "-o " << quote(sys::path::filename(arg->getValue())) << "\n";
567 break;
568 default:
569 os << toString(*arg) << "\n";
570 }
571 }
572 return data.str();
573}
574
575// The --wrap option is a feature to rename symbols so that you can write
576// wrappers for existing functions. If you pass `-wrap=foo`, all
577// occurrences of symbol `foo` are resolved to `wrap_foo` (so, you are
578// expected to write `wrap_foo` function as a wrapper). The original
579// symbol becomes accessible as `real_foo`, so you can call that from your
580// wrapper.
581//
582// This data structure is instantiated for each -wrap option.
583struct WrappedSymbol {
584 Symbol *sym;
585 Symbol *real;
586 Symbol *wrap;
587};
588
589static Symbol *addUndefined(StringRef name) {
590 return symtab->addUndefinedFunction(name, "", "", 0, nullptr, nullptr, false);
591}
592
593// Handles -wrap option.
594//
595// This function instantiates wrapper symbols. At this point, they seem
596// like they are not being used at all, so we explicitly set some flags so
597// that LTO won't eliminate them.
598static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
599 std::vector<WrappedSymbol> v;
600 DenseSet<StringRef> seen;
601
602 for (auto *arg : args.filtered(OPT_wrap)) {
603 StringRef name = arg->getValue();
604 if (!seen.insert(name).second)
605 continue;
606
607 Symbol *sym = symtab->find(name);
608 if (!sym)
609 continue;
610
611 Symbol *real = addUndefined(saver.save("__real_" + name));
612 Symbol *wrap = addUndefined(saver.save("__wrap_" + name));
613 v.push_back({sym, real, wrap});
614
615 // We want to tell LTO not to inline symbols to be overwritten
616 // because LTO doesn't know the final symbol contents after renaming.
617 real->canInline = false;
618 sym->canInline = false;
619
620 // Tell LTO not to eliminate these symbols.
621 sym->isUsedInRegularObj = true;
622 wrap->isUsedInRegularObj = true;
623 real->isUsedInRegularObj = false;
624 }
625 return v;
626}
627
628// Do renaming for -wrap by updating pointers to symbols.
629//
630// When this function is executed, only InputFiles and symbol table
631// contain pointers to symbol objects. We visit them to replace pointers,
632// so that wrapped symbols are swapped as instructed by the command line.
633static void wrapSymbols(ArrayRef<WrappedSymbol> wrapped) {
634 DenseMap<Symbol *, Symbol *> map;
635 for (const WrappedSymbol &w : wrapped) {
636 map[w.sym] = w.wrap;
637 map[w.real] = w.sym;
638 }
639
640 // Update pointers in input files.
641 parallelForEach(symtab->objectFiles, [&](InputFile *file) {
642 MutableArrayRef<Symbol *> syms = file->getMutableSymbols();
643 for (size_t i = 0, e = syms.size(); i != e; ++i)
644 if (Symbol *s = map.lookup(syms[i]))
645 syms[i] = s;
646 });
647
648 // Update pointers in the symbol table.
649 for (const WrappedSymbol &w : wrapped)
650 symtab->wrap(w.sym, w.real, w.wrap);
651}
652
653void LinkerDriver::link(ArrayRef<const char *> argsArr) {
654 WasmOptTable parser;
655 opt::InputArgList args = parser.parse(argsArr.slice(1));
505656
506 // Handle --help657 // Handle --help
507 if (Args.hasArg(OPT_help)) {658 if (args.hasArg(OPT_help)) {
508 Parser.PrintHelp(outs(),659 parser.PrintHelp(outs(),
509 (std::string(ArgsArr[0]) + " [options] file...").c_str(),660 (std::string(argsArr[0]) + " [options] file...").c_str(),
510 "LLVM Linker", false);661 "LLVM Linker", false);
511 return;662 return;
512 }663 }
513664
514 // Handle --version665 // Handle --version
515 if (Args.hasArg(OPT_version) || Args.hasArg(OPT_v)) {666 if (args.hasArg(OPT_version) || args.hasArg(OPT_v)) {
516 outs() << getLLDVersion() << "\n";667 outs() << getLLDVersion() << "\n";
517 return;668 return;
518 }669 }
519670
671 // Handle --reproduce
672 if (auto *arg = args.getLastArg(OPT_reproduce)) {
673 StringRef path = arg->getValue();
674 Expected<std::unique_ptr<TarWriter>> errOrWriter =
675 TarWriter::create(path, path::stem(path));
676 if (errOrWriter) {
677 tar = std::move(*errOrWriter);
678 tar->append("response.txt", createResponseFile(args));
679 tar->append("version.txt", getLLDVersion() + "\n");
680 } else {
681 error("--reproduce: " + toString(errOrWriter.takeError()));
682 }
683 }
684
520 // Parse and evaluate -mllvm options.685 // Parse and evaluate -mllvm options.
521 std::vector<const char *> V;686 std::vector<const char *> v;
522 V.push_back("wasm-ld (LLVM option parsing)");687 v.push_back("wasm-ld (LLVM option parsing)");
523 for (auto *Arg : Args.filtered(OPT_mllvm))688 for (auto *arg : args.filtered(OPT_mllvm))
524 V.push_back(Arg->getValue());689 v.push_back(arg->getValue());
525 cl::ParseCommandLineOptions(V.size(), V.data());690 cl::ParseCommandLineOptions(v.size(), v.data());
526691
527 errorHandler().ErrorLimit = args::getInteger(Args, OPT_error_limit, 20);692 errorHandler().errorLimit = args::getInteger(args, OPT_error_limit, 20);
528693
529 setConfigs(Args);694 readConfigs(args);
530 checkOptions(Args);695 setConfigs();
696 checkOptions(args);
531697
532 if (auto *Arg = Args.getLastArg(OPT_allow_undefined_file))698 if (auto *arg = args.getLastArg(OPT_allow_undefined_file))
533 readImportFile(Arg->getValue());699 readImportFile(arg->getValue());
534700
535 if (!Args.hasArg(OPT_INPUT)) {701 if (!args.hasArg(OPT_INPUT)) {
536 error("no input files");702 error("no input files");
537 return;703 return;
538 }704 }
539705
540 Config->Pic = Config->Pie || Config->Shared;706 // Handle --trace-symbol.
541707 for (auto *arg : args.filtered(OPT_trace_symbol))
542 if (Config->Pic) {708 symtab->trace(arg->getValue());
543 if (Config->ExportTable)
544 error("-shared/-pie is incompatible with --export-table");
545 Config->ImportTable = true;
546 }
547709
548 if (Config->Shared) {710 for (auto *arg : args.filtered(OPT_export))
549 Config->ExportDynamic = true;711 config->exportedSymbols.insert(arg->getValue());
550 Config->AllowUndefined = true;
551 }
552712
553 if (!Config->Relocatable)713 if (!config->relocatable)
554 createSyntheticSymbols();714 createSyntheticSymbols();
555715
556 createFiles(Args);716 createFiles(args);
557 if (errorCount())717 if (errorCount())
558 return;718 return;
559719
560 // Add all files to the symbol table. This will add almost all720 // Add all files to the symbol table. This will add almost all
561 // symbols that we need to the symbol table.721 // symbols that we need to the symbol table.
562 for (InputFile *F : Files)722 for (InputFile *f : files)
563 Symtab->addFile(F);723 symtab->addFile(f);
564 if (errorCount())724 if (errorCount())
565 return;725 return;
566726
567 // Handle the `--undefined <sym>` options.727 // Handle the `--undefined <sym>` options.
568 for (auto *Arg : Args.filtered(OPT_undefined))728 for (auto *arg : args.filtered(OPT_undefined))
569 handleUndefined(Arg->getValue());729 handleUndefined(arg->getValue());
570730
571 // Handle the `--export <sym>` options731 // Handle the `--export <sym>` options
572 // This works like --undefined but also exports the symbol if its found732 // This works like --undefined but also exports the symbol if its found
573 for (auto *Arg : Args.filtered(OPT_export)) {733 for (auto *arg : args.filtered(OPT_export))
574 Symbol *Sym = handleUndefined(Arg->getValue());734 handleUndefined(arg->getValue());
575 if (Sym && Sym->isDefined())735
576 Sym->ForceExport = true;736 Symbol *entrySym = nullptr;
577 else if (!Config->AllowUndefined)737 if (!config->relocatable && !config->entry.empty()) {
578 error(Twine("symbol exported via --export not found: ") +738 entrySym = handleUndefined(config->entry);
579 Arg->getValue());739 if (entrySym && entrySym->isDefined())
580 }740 entrySym->forceExport = true;
581741 else
582 Symbol *EntrySym = nullptr;742 error("entry symbol not defined (pass --no-entry to supress): " +
583 if (!Config->Relocatable) {743 config->entry);
584 // Add synthetic dummies for weak undefined functions.
585 handleWeakUndefines();
586
587 if (!Config->Shared && !Config->Entry.empty()) {
588 EntrySym = handleUndefined(Config->Entry);
589 if (EntrySym && EntrySym->isDefined())
590 EntrySym->ForceExport = true;
591 else
592 error("entry symbol not defined (pass --no-entry to supress): " +
593 Config->Entry);
594 }
595
596 // Make sure we have resolved all symbols.
597 if (!Config->AllowUndefined)
598 Symtab->reportRemainingUndefines();
599 }744 }
600745
601 if (errorCount())746 if (errorCount())
602 return;747 return;
603748
749 // Create wrapped symbols for -wrap option.
750 std::vector<WrappedSymbol> wrapped = addWrappedSymbols(args);
751
604 // Do link-time optimization if given files are LLVM bitcode files.752 // Do link-time optimization if given files are LLVM bitcode files.
605 // This compiles bitcode files into real object files.753 // This compiles bitcode files into real object files.
606 Symtab->addCombinedLTOObject();754 symtab->addCombinedLTOObject();
607 if (errorCount())755 if (errorCount())
608 return;756 return;
609757
610 if (EntrySym)758 // Resolve any variant symbols that were created due to signature
611 EntrySym->setHidden(false);759 // mismatchs.
760 symtab->handleSymbolVariants();
761 if (errorCount())
762 return;
763
764 // Apply symbol renames for -wrap.
765 if (!wrapped.empty())
766 wrapSymbols(wrapped);
767
768 for (auto *arg : args.filtered(OPT_export)) {
769 Symbol *sym = symtab->find(arg->getValue());
770 if (sym && sym->isDefined())
771 sym->forceExport = true;
772 else if (!config->allowUndefined)
773 error(Twine("symbol exported via --export not found: ") +
774 arg->getValue());
775 }
776
777 if (!config->relocatable) {
778 // Add synthetic dummies for weak undefined functions. Must happen
779 // after LTO otherwise functions may not yet have signatures.
780 symtab->handleWeakUndefines();
781 }
782
783 if (entrySym)
784 entrySym->setHidden(false);
612785
613 if (errorCount())786 if (errorCount())
614 return;787 return;
deps/lld/wasm/InputChunks.cpp+214-158
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputChunks.cpp ----------------------------------------------------===//1//===- InputChunks.cpp ----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -23,8 +22,8 @@ using namespace llvm::support::endian;...@@ -23,8 +22,8 @@ using namespace llvm::support::endian;
23using namespace lld;22using namespace lld;
24using namespace lld::wasm;23using namespace lld::wasm;
2524
26static StringRef reloctTypeToString(uint8_t RelocType) {25StringRef lld::relocTypeToString(uint8_t relocType) {
27 switch (RelocType) {26 switch (relocType) {
28#define WASM_RELOC(NAME, REL) \27#define WASM_RELOC(NAME, REL) \
29 case REL: \28 case REL: \
30 return #NAME;29 return #NAME;
...@@ -34,62 +33,67 @@ static StringRef reloctTypeToString(uint8_t RelocType) {...@@ -34,62 +33,67 @@ static StringRef reloctTypeToString(uint8_t RelocType) {
34 llvm_unreachable("unknown reloc type");33 llvm_unreachable("unknown reloc type");
35}34}
3635
37std::string lld::toString(const InputChunk *C) {36std::string lld::toString(const InputChunk *c) {
38 return (toString(C->File) + ":(" + C->getName() + ")").str();37 return (toString(c->file) + ":(" + c->getName() + ")").str();
39}38}
4039
41StringRef InputChunk::getComdatName() const {40StringRef InputChunk::getComdatName() const {
42 uint32_t Index = getComdat();41 uint32_t index = getComdat();
43 if (Index == UINT32_MAX)42 if (index == UINT32_MAX)
44 return StringRef();43 return StringRef();
45 return File->getWasmObj()->linkingData().Comdats[Index];44 return file->getWasmObj()->linkingData().Comdats[index];
46}45}
4746
48void InputChunk::verifyRelocTargets() const {47void InputChunk::verifyRelocTargets() const {
49 for (const WasmRelocation &Rel : Relocations) {48 for (const WasmRelocation &rel : relocations) {
50 uint32_t ExistingValue;49 uint32_t existingValue;
51 unsigned BytesRead = 0;50 unsigned bytesRead = 0;
52 uint32_t Offset = Rel.Offset - getInputSectionOffset();51 uint32_t offset = rel.Offset - getInputSectionOffset();
53 const uint8_t *Loc = data().data() + Offset;52 const uint8_t *loc = data().data() + offset;
54 switch (Rel.Type) {53 switch (rel.Type) {
55 case R_WEBASSEMBLY_TYPE_INDEX_LEB:54 case R_WASM_TYPE_INDEX_LEB:
56 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:55 case R_WASM_FUNCTION_INDEX_LEB:
57 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:56 case R_WASM_GLOBAL_INDEX_LEB:
58 case R_WEBASSEMBLY_EVENT_INDEX_LEB:57 case R_WASM_EVENT_INDEX_LEB:
59 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:58 case R_WASM_MEMORY_ADDR_LEB:
60 ExistingValue = decodeULEB128(Loc, &BytesRead);59 existingValue = decodeULEB128(loc, &bytesRead);
61 break;60 break;
62 case R_WEBASSEMBLY_TABLE_INDEX_SLEB:61 case R_WASM_TABLE_INDEX_SLEB:
63 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:62 case R_WASM_TABLE_INDEX_REL_SLEB:
64 ExistingValue = static_cast<uint32_t>(decodeSLEB128(Loc, &BytesRead));63 case R_WASM_MEMORY_ADDR_SLEB:
64 case R_WASM_MEMORY_ADDR_REL_SLEB:
65 existingValue = static_cast<uint32_t>(decodeSLEB128(loc, &bytesRead));
65 break;66 break;
66 case R_WEBASSEMBLY_TABLE_INDEX_I32:67 case R_WASM_TABLE_INDEX_I32:
67 case R_WEBASSEMBLY_MEMORY_ADDR_I32:68 case R_WASM_MEMORY_ADDR_I32:
68 case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:69 case R_WASM_FUNCTION_OFFSET_I32:
69 case R_WEBASSEMBLY_SECTION_OFFSET_I32:70 case R_WASM_SECTION_OFFSET_I32:
70 ExistingValue = static_cast<uint32_t>(read32le(Loc));71 existingValue = static_cast<uint32_t>(read32le(loc));
71 break;72 break;
72 default:73 default:
73 llvm_unreachable("unknown relocation type");74 llvm_unreachable("unknown relocation type");
74 }75 }
7576
76 if (BytesRead && BytesRead != 5)77 if (bytesRead && bytesRead != 5)
77 warn("expected LEB at relocation site be 5-byte padded");78 warn("expected LEB at relocation site be 5-byte padded");
78 uint32_t ExpectedValue = File->calcExpectedValue(Rel);79
79 if (ExpectedValue != ExistingValue)80 if (rel.Type != R_WASM_GLOBAL_INDEX_LEB) {
80 warn("unexpected existing value for " + reloctTypeToString(Rel.Type) +81 uint32_t expectedValue = file->calcExpectedValue(rel);
81 ": existing=" + Twine(ExistingValue) +82 if (expectedValue != existingValue)
82 " expected=" + Twine(ExpectedValue));83 warn("unexpected existing value for " + relocTypeToString(rel.Type) +
84 ": existing=" + Twine(existingValue) +
85 " expected=" + Twine(expectedValue));
86 }
83 }87 }
84}88}
8589
86// Copy this input chunk to an mmap'ed output file and apply relocations.90// Copy this input chunk to an mmap'ed output file and apply relocations.
87void InputChunk::writeTo(uint8_t *Buf) const {91void InputChunk::writeTo(uint8_t *buf) const {
88 // Copy contents92 // Copy contents
89 memcpy(Buf + OutputOffset, data().data(), data().size());93 memcpy(buf + outputOffset, data().data(), data().size());
9094
91 // Apply relocations95 // Apply relocations
92 if (Relocations.empty())96 if (relocations.empty())
93 return;97 return;
9498
95#ifndef NDEBUG99#ifndef NDEBUG
...@@ -97,34 +101,38 @@ void InputChunk::writeTo(uint8_t *Buf) const {...@@ -97,34 +101,38 @@ void InputChunk::writeTo(uint8_t *Buf) const {
97#endif101#endif
98102
99 LLVM_DEBUG(dbgs() << "applying relocations: " << getName()103 LLVM_DEBUG(dbgs() << "applying relocations: " << getName()
100 << " count=" << Relocations.size() << "\n");104 << " count=" << relocations.size() << "\n");
101 int32_t Off = OutputOffset - getInputSectionOffset();105 int32_t off = outputOffset - getInputSectionOffset();
102106
103 for (const WasmRelocation &Rel : Relocations) {107 for (const WasmRelocation &rel : relocations) {
104 uint8_t *Loc = Buf + Rel.Offset + Off;108 uint8_t *loc = buf + rel.Offset + off;
105 uint32_t Value = File->calcNewValue(Rel);109 uint32_t value = file->calcNewValue(rel);
106 LLVM_DEBUG(dbgs() << "apply reloc: type=" << reloctTypeToString(Rel.Type)110 LLVM_DEBUG(dbgs() << "apply reloc: type=" << relocTypeToString(rel.Type));
107 << " addend=" << Rel.Addend << " index=" << Rel.Index111 if (rel.Type != R_WASM_TYPE_INDEX_LEB)
108 << " value=" << Value << " offset=" << Rel.Offset112 LLVM_DEBUG(dbgs() << " sym=" << file->getSymbols()[rel.Index]->getName());
113 LLVM_DEBUG(dbgs() << " addend=" << rel.Addend << " index=" << rel.Index
114 << " value=" << value << " offset=" << rel.Offset
109 << "\n");115 << "\n");
110116
111 switch (Rel.Type) {117 switch (rel.Type) {
112 case R_WEBASSEMBLY_TYPE_INDEX_LEB:118 case R_WASM_TYPE_INDEX_LEB:
113 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:119 case R_WASM_FUNCTION_INDEX_LEB:
114 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:120 case R_WASM_GLOBAL_INDEX_LEB:
115 case R_WEBASSEMBLY_EVENT_INDEX_LEB:121 case R_WASM_EVENT_INDEX_LEB:
116 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:122 case R_WASM_MEMORY_ADDR_LEB:
117 encodeULEB128(Value, Loc, 5);123 encodeULEB128(value, loc, 5);
118 break;124 break;
119 case R_WEBASSEMBLY_TABLE_INDEX_SLEB:125 case R_WASM_TABLE_INDEX_SLEB:
120 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:126 case R_WASM_TABLE_INDEX_REL_SLEB:
121 encodeSLEB128(static_cast<int32_t>(Value), Loc, 5);127 case R_WASM_MEMORY_ADDR_SLEB:
128 case R_WASM_MEMORY_ADDR_REL_SLEB:
129 encodeSLEB128(static_cast<int32_t>(value), loc, 5);
122 break;130 break;
123 case R_WEBASSEMBLY_TABLE_INDEX_I32:131 case R_WASM_TABLE_INDEX_I32:
124 case R_WEBASSEMBLY_MEMORY_ADDR_I32:132 case R_WASM_MEMORY_ADDR_I32:
125 case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:133 case R_WASM_FUNCTION_OFFSET_I32:
126 case R_WEBASSEMBLY_SECTION_OFFSET_I32:134 case R_WASM_SECTION_OFFSET_I32:
127 write32le(Loc, Value);135 write32le(loc, value);
128 break;136 break;
129 default:137 default:
130 llvm_unreachable("unknown relocation type");138 llvm_unreachable("unknown relocation type");
...@@ -135,82 +143,75 @@ void InputChunk::writeTo(uint8_t *Buf) const {...@@ -135,82 +143,75 @@ void InputChunk::writeTo(uint8_t *Buf) const {
135// Copy relocation entries to a given output stream.143// Copy relocation entries to a given output stream.
136// This function is used only when a user passes "-r". For a regular link,144// This function is used only when a user passes "-r". For a regular link,
137// we consume relocations instead of copying them to an output file.145// we consume relocations instead of copying them to an output file.
138void InputChunk::writeRelocations(raw_ostream &OS) const {146void InputChunk::writeRelocations(raw_ostream &os) const {
139 if (Relocations.empty())147 if (relocations.empty())
140 return;148 return;
141149
142 int32_t Off = OutputOffset - getInputSectionOffset();150 int32_t off = outputOffset - getInputSectionOffset();
143 LLVM_DEBUG(dbgs() << "writeRelocations: " << File->getName()151 LLVM_DEBUG(dbgs() << "writeRelocations: " << file->getName()
144 << " offset=" << Twine(Off) << "\n");152 << " offset=" << Twine(off) << "\n");
145153
146 for (const WasmRelocation &Rel : Relocations) {154 for (const WasmRelocation &rel : relocations) {
147 writeUleb128(OS, Rel.Type, "reloc type");155 writeUleb128(os, rel.Type, "reloc type");
148 writeUleb128(OS, Rel.Offset + Off, "reloc offset");156 writeUleb128(os, rel.Offset + off, "reloc offset");
149 writeUleb128(OS, File->calcNewIndex(Rel), "reloc index");157 writeUleb128(os, file->calcNewIndex(rel), "reloc index");
150158
151 switch (Rel.Type) {159 if (relocTypeHasAddend(rel.Type))
152 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:160 writeSleb128(os, file->calcNewAddend(rel), "reloc addend");
153 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:
154 case R_WEBASSEMBLY_MEMORY_ADDR_I32:
155 case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:
156 case R_WEBASSEMBLY_SECTION_OFFSET_I32:
157 writeSleb128(OS, File->calcNewAddend(Rel), "reloc addend");
158 break;
159 }
160 }161 }
161}162}
162163
163void InputFunction::setFunctionIndex(uint32_t Index) {164void InputFunction::setFunctionIndex(uint32_t index) {
164 LLVM_DEBUG(dbgs() << "InputFunction::setFunctionIndex: " << getName()165 LLVM_DEBUG(dbgs() << "InputFunction::setFunctionIndex: " << getName()
165 << " -> " << Index << "\n");166 << " -> " << index << "\n");
166 assert(!hasFunctionIndex());167 assert(!hasFunctionIndex());
167 FunctionIndex = Index;168 functionIndex = index;
168}169}
169170
170void InputFunction::setTableIndex(uint32_t Index) {171void InputFunction::setTableIndex(uint32_t index) {
171 LLVM_DEBUG(dbgs() << "InputFunction::setTableIndex: " << getName() << " -> "172 LLVM_DEBUG(dbgs() << "InputFunction::setTableIndex: " << getName() << " -> "
172 << Index << "\n");173 << index << "\n");
173 assert(!hasTableIndex());174 assert(!hasTableIndex());
174 TableIndex = Index;175 tableIndex = index;
175}176}
176177
177// Write a relocation value without padding and return the number of bytes178// Write a relocation value without padding and return the number of bytes
178// witten.179// witten.
179static unsigned writeCompressedReloc(uint8_t *Buf, const WasmRelocation &Rel,180static unsigned writeCompressedReloc(uint8_t *buf, const WasmRelocation &rel,
180 uint32_t Value) {181 uint32_t value) {
181 switch (Rel.Type) {182 switch (rel.Type) {
182 case R_WEBASSEMBLY_TYPE_INDEX_LEB:183 case R_WASM_TYPE_INDEX_LEB:
183 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:184 case R_WASM_FUNCTION_INDEX_LEB:
184 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:185 case R_WASM_GLOBAL_INDEX_LEB:
185 case R_WEBASSEMBLY_EVENT_INDEX_LEB:186 case R_WASM_EVENT_INDEX_LEB:
186 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:187 case R_WASM_MEMORY_ADDR_LEB:
187 return encodeULEB128(Value, Buf);188 return encodeULEB128(value, buf);
188 case R_WEBASSEMBLY_TABLE_INDEX_SLEB:189 case R_WASM_TABLE_INDEX_SLEB:
189 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:190 case R_WASM_MEMORY_ADDR_SLEB:
190 return encodeSLEB128(static_cast<int32_t>(Value), Buf);191 return encodeSLEB128(static_cast<int32_t>(value), buf);
191 default:192 default:
192 llvm_unreachable("unexpected relocation type");193 llvm_unreachable("unexpected relocation type");
193 }194 }
194}195}
195196
196static unsigned getRelocWidthPadded(const WasmRelocation &Rel) {197static unsigned getRelocWidthPadded(const WasmRelocation &rel) {
197 switch (Rel.Type) {198 switch (rel.Type) {
198 case R_WEBASSEMBLY_TYPE_INDEX_LEB:199 case R_WASM_TYPE_INDEX_LEB:
199 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:200 case R_WASM_FUNCTION_INDEX_LEB:
200 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:201 case R_WASM_GLOBAL_INDEX_LEB:
201 case R_WEBASSEMBLY_EVENT_INDEX_LEB:202 case R_WASM_EVENT_INDEX_LEB:
202 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:203 case R_WASM_MEMORY_ADDR_LEB:
203 case R_WEBASSEMBLY_TABLE_INDEX_SLEB:204 case R_WASM_TABLE_INDEX_SLEB:
204 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:205 case R_WASM_MEMORY_ADDR_SLEB:
205 return 5;206 return 5;
206 default:207 default:
207 llvm_unreachable("unexpected relocation type");208 llvm_unreachable("unexpected relocation type");
208 }209 }
209}210}
210211
211static unsigned getRelocWidth(const WasmRelocation &Rel, uint32_t Value) {212static unsigned getRelocWidth(const WasmRelocation &rel, uint32_t value) {
212 uint8_t Buf[5];213 uint8_t buf[5];
213 return writeCompressedReloc(Buf, Rel, Value);214 return writeCompressedReloc(buf, rel, value);
214}215}
215216
216// Relocations of type LEB and SLEB in the code section are padded to 5 bytes217// Relocations of type LEB and SLEB in the code section are padded to 5 bytes
...@@ -224,69 +225,124 @@ static unsigned getRelocWidth(const WasmRelocation &Rel, uint32_t Value) {...@@ -224,69 +225,124 @@ static unsigned getRelocWidth(const WasmRelocation &Rel, uint32_t Value) {
224// This function only computes the final output size. It must be called225// This function only computes the final output size. It must be called
225// before getSize() is used to calculate of layout of the code section.226// before getSize() is used to calculate of layout of the code section.
226void InputFunction::calculateSize() {227void InputFunction::calculateSize() {
227 if (!File || !Config->CompressRelocations)228 if (!file || !config->compressRelocations)
228 return;229 return;
229230
230 LLVM_DEBUG(dbgs() << "calculateSize: " << getName() << "\n");231 LLVM_DEBUG(dbgs() << "calculateSize: " << getName() << "\n");
231232
232 const uint8_t *SecStart = File->CodeSection->Content.data();233 const uint8_t *secStart = file->codeSection->Content.data();
233 const uint8_t *FuncStart = SecStart + getInputSectionOffset();234 const uint8_t *funcStart = secStart + getInputSectionOffset();
234 uint32_t FunctionSizeLength;235 uint32_t functionSizeLength;
235 decodeULEB128(FuncStart, &FunctionSizeLength);236 decodeULEB128(funcStart, &functionSizeLength);
236237
237 uint32_t Start = getInputSectionOffset();238 uint32_t start = getInputSectionOffset();
238 uint32_t End = Start + Function->Size;239 uint32_t end = start + function->Size;
239240
240 uint32_t LastRelocEnd = Start + FunctionSizeLength;241 uint32_t lastRelocEnd = start + functionSizeLength;
241 for (const WasmRelocation &Rel : Relocations) {242 for (const WasmRelocation &rel : relocations) {
242 LLVM_DEBUG(dbgs() << " region: " << (Rel.Offset - LastRelocEnd) << "\n");243 LLVM_DEBUG(dbgs() << " region: " << (rel.Offset - lastRelocEnd) << "\n");
243 CompressedFuncSize += Rel.Offset - LastRelocEnd;244 compressedFuncSize += rel.Offset - lastRelocEnd;
244 CompressedFuncSize += getRelocWidth(Rel, File->calcNewValue(Rel));245 compressedFuncSize += getRelocWidth(rel, file->calcNewValue(rel));
245 LastRelocEnd = Rel.Offset + getRelocWidthPadded(Rel);246 lastRelocEnd = rel.Offset + getRelocWidthPadded(rel);
246 }247 }
247 LLVM_DEBUG(dbgs() << " final region: " << (End - LastRelocEnd) << "\n");248 LLVM_DEBUG(dbgs() << " final region: " << (end - lastRelocEnd) << "\n");
248 CompressedFuncSize += End - LastRelocEnd;249 compressedFuncSize += end - lastRelocEnd;
249250
250 // Now we know how long the resulting function is we can add the encoding251 // Now we know how long the resulting function is we can add the encoding
251 // of its length252 // of its length
252 uint8_t Buf[5];253 uint8_t buf[5];
253 CompressedSize = CompressedFuncSize + encodeULEB128(CompressedFuncSize, Buf);254 compressedSize = compressedFuncSize + encodeULEB128(compressedFuncSize, buf);
254255
255 LLVM_DEBUG(dbgs() << " calculateSize orig: " << Function->Size << "\n");256 LLVM_DEBUG(dbgs() << " calculateSize orig: " << function->Size << "\n");
256 LLVM_DEBUG(dbgs() << " calculateSize new: " << CompressedSize << "\n");257 LLVM_DEBUG(dbgs() << " calculateSize new: " << compressedSize << "\n");
257}258}
258259
259// Override the default writeTo method so that we can (optionally) write the260// Override the default writeTo method so that we can (optionally) write the
260// compressed version of the function.261// compressed version of the function.
261void InputFunction::writeTo(uint8_t *Buf) const {262void InputFunction::writeTo(uint8_t *buf) const {
262 if (!File || !Config->CompressRelocations)263 if (!file || !config->compressRelocations)
263 return InputChunk::writeTo(Buf);264 return InputChunk::writeTo(buf);
264265
265 Buf += OutputOffset;266 buf += outputOffset;
266 uint8_t *Orig = Buf;267 uint8_t *orig = buf;
267 (void)Orig;268 (void)orig;
268269
269 const uint8_t *SecStart = File->CodeSection->Content.data();270 const uint8_t *secStart = file->codeSection->Content.data();
270 const uint8_t *FuncStart = SecStart + getInputSectionOffset();271 const uint8_t *funcStart = secStart + getInputSectionOffset();
271 const uint8_t *End = FuncStart + Function->Size;272 const uint8_t *end = funcStart + function->Size;
272 uint32_t Count;273 uint32_t count;
273 decodeULEB128(FuncStart, &Count);274 decodeULEB128(funcStart, &count);
274 FuncStart += Count;275 funcStart += count;
275276
276 LLVM_DEBUG(dbgs() << "write func: " << getName() << "\n");277 LLVM_DEBUG(dbgs() << "write func: " << getName() << "\n");
277 Buf += encodeULEB128(CompressedFuncSize, Buf);278 buf += encodeULEB128(compressedFuncSize, buf);
278 const uint8_t *LastRelocEnd = FuncStart;279 const uint8_t *lastRelocEnd = funcStart;
279 for (const WasmRelocation &Rel : Relocations) {280 for (const WasmRelocation &rel : relocations) {
280 unsigned ChunkSize = (SecStart + Rel.Offset) - LastRelocEnd;281 unsigned chunkSize = (secStart + rel.Offset) - lastRelocEnd;
281 LLVM_DEBUG(dbgs() << " write chunk: " << ChunkSize << "\n");282 LLVM_DEBUG(dbgs() << " write chunk: " << chunkSize << "\n");
282 memcpy(Buf, LastRelocEnd, ChunkSize);283 memcpy(buf, lastRelocEnd, chunkSize);
283 Buf += ChunkSize;284 buf += chunkSize;
284 Buf += writeCompressedReloc(Buf, Rel, File->calcNewValue(Rel));285 buf += writeCompressedReloc(buf, rel, file->calcNewValue(rel));
285 LastRelocEnd = SecStart + Rel.Offset + getRelocWidthPadded(Rel);286 lastRelocEnd = secStart + rel.Offset + getRelocWidthPadded(rel);
286 }287 }
287288
288 unsigned ChunkSize = End - LastRelocEnd;289 unsigned chunkSize = end - lastRelocEnd;
289 LLVM_DEBUG(dbgs() << " write final chunk: " << ChunkSize << "\n");290 LLVM_DEBUG(dbgs() << " write final chunk: " << chunkSize << "\n");
290 memcpy(Buf, LastRelocEnd, ChunkSize);291 memcpy(buf, lastRelocEnd, chunkSize);
291 LLVM_DEBUG(dbgs() << " total: " << (Buf + ChunkSize - Orig) << "\n");292 LLVM_DEBUG(dbgs() << " total: " << (buf + chunkSize - orig) << "\n");
293}
294
295// Generate code to apply relocations to the data section at runtime.
296// This is only called when generating shared libaries (PIC) where address are
297// not known at static link time.
298void InputSegment::generateRelocationCode(raw_ostream &os) const {
299 LLVM_DEBUG(dbgs() << "generating runtime relocations: " << getName()
300 << " count=" << relocations.size() << "\n");
301
302 // TODO(sbc): Encode the relocations in the data section and write a loop
303 // here to apply them.
304 uint32_t segmentVA = outputSeg->startVA + outputSegmentOffset;
305 for (const WasmRelocation &rel : relocations) {
306 uint32_t offset = rel.Offset - getInputSectionOffset();
307 uint32_t outputOffset = segmentVA + offset;
308
309 LLVM_DEBUG(dbgs() << "gen reloc: type=" << relocTypeToString(rel.Type)
310 << " addend=" << rel.Addend << " index=" << rel.Index
311 << " output offset=" << outputOffset << "\n");
312
313 // Get __memory_base
314 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
315 writeUleb128(os, WasmSym::memoryBase->getGlobalIndex(), "memory_base");
316
317 // Add the offset of the relocation
318 writeU8(os, WASM_OPCODE_I32_CONST, "I32_CONST");
319 writeSleb128(os, outputOffset, "offset");
320 writeU8(os, WASM_OPCODE_I32_ADD, "ADD");
321
322 Symbol *sym = file->getSymbol(rel);
323 // Now figure out what we want to store
324 if (sym->hasGOTIndex()) {
325 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
326 writeUleb128(os, sym->getGOTIndex(), "global index");
327 if (rel.Addend) {
328 writeU8(os, WASM_OPCODE_I32_CONST, "CONST");
329 writeSleb128(os, rel.Addend, "addend");
330 writeU8(os, WASM_OPCODE_I32_ADD, "ADD");
331 }
332 } else {
333 const GlobalSymbol* baseSymbol = WasmSym::memoryBase;
334 if (rel.Type == R_WASM_TABLE_INDEX_I32)
335 baseSymbol = WasmSym::tableBase;
336 writeU8(os, WASM_OPCODE_GLOBAL_GET, "GLOBAL_GET");
337 writeUleb128(os, baseSymbol->getGlobalIndex(), "base");
338 writeU8(os, WASM_OPCODE_I32_CONST, "CONST");
339 writeSleb128(os, file->calcNewValue(rel), "offset");
340 writeU8(os, WASM_OPCODE_I32_ADD, "ADD");
341 }
342
343 // Store that value at the virtual address
344 writeU8(os, WASM_OPCODE_I32_STORE, "I32_STORE");
345 writeUleb128(os, 2, "align");
346 writeUleb128(os, 0, "offset");
347 }
292}348}
deps/lld/wasm/InputChunks.h+86-77
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputChunks.h --------------------------------------------*- C++ -*-===//1//===- InputChunks.h --------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -32,20 +31,21 @@ namespace wasm {...@@ -32,20 +31,21 @@ namespace wasm {
3231
33class ObjFile;32class ObjFile;
34class OutputSegment;33class OutputSegment;
34class OutputSection;
3535
36class InputChunk {36class InputChunk {
37public:37public:
38 enum Kind { DataSegment, Function, SyntheticFunction, Section };38 enum Kind { DataSegment, Function, SyntheticFunction, Section };
3939
40 Kind kind() const { return SectionKind; }40 Kind kind() const { return sectionKind; }
4141
42 virtual uint32_t getSize() const { return data().size(); }42 virtual uint32_t getSize() const { return data().size(); }
43 virtual uint32_t getInputSize() const { return getSize(); };43 virtual uint32_t getInputSize() const { return getSize(); };
4444
45 virtual void writeTo(uint8_t *SectionStart) const;45 virtual void writeTo(uint8_t *sectionStart) const;
4646
47 ArrayRef<WasmRelocation> getRelocations() const { return Relocations; }47 ArrayRef<WasmRelocation> getRelocations() const { return relocations; }
48 void setRelocations(ArrayRef<WasmRelocation> Rs) { Relocations = Rs; }48 void setRelocations(ArrayRef<WasmRelocation> rs) { relocations = rs; }
4949
50 virtual StringRef getName() const = 0;50 virtual StringRef getName() const = 0;
51 virtual StringRef getDebugName() const = 0;51 virtual StringRef getDebugName() const = 0;
...@@ -53,20 +53,23 @@ public:...@@ -53,20 +53,23 @@ public:
53 StringRef getComdatName() const;53 StringRef getComdatName() const;
54 virtual uint32_t getInputSectionOffset() const = 0;54 virtual uint32_t getInputSectionOffset() const = 0;
5555
56 size_t NumRelocations() const { return Relocations.size(); }56 size_t getNumRelocations() const { return relocations.size(); }
57 void writeRelocations(llvm::raw_ostream &OS) const;57 void writeRelocations(llvm::raw_ostream &os) const;
5858
59 ObjFile *File;59 ObjFile *file;
60 int32_t OutputOffset = 0;60 int32_t outputOffset = 0;
6161
62 // Signals that the section is part of the output. The garbage collector,62 // Signals that the section is part of the output. The garbage collector,
63 // and COMDAT handling can set a sections' Live bit.63 // and COMDAT handling can set a sections' Live bit.
64 // If GC is disabled, all sections start out as live by default.64 // If GC is disabled, all sections start out as live by default.
65 unsigned Live : 1;65 unsigned live : 1;
66
67 // Signals the chunk was discarded by COMDAT handling.
68 unsigned discarded : 1;
6669
67protected:70protected:
68 InputChunk(ObjFile *F, Kind K)71 InputChunk(ObjFile *f, Kind k)
69 : File(F), Live(!Config->GcSections), SectionKind(K) {}72 : file(f), live(!config->gcSections), discarded(false), sectionKind(k) {}
70 virtual ~InputChunk() = default;73 virtual ~InputChunk() = default;
71 virtual ArrayRef<uint8_t> data() const = 0;74 virtual ArrayRef<uint8_t> data() const = 0;
7275
...@@ -74,8 +77,8 @@ protected:...@@ -74,8 +77,8 @@ protected:
74 // This is performed only debug builds as an extra sanity check.77 // This is performed only debug builds as an extra sanity check.
75 void verifyRelocTargets() const;78 void verifyRelocTargets() const;
7679
77 ArrayRef<WasmRelocation> Relocations;80 ArrayRef<WasmRelocation> relocations;
78 Kind SectionKind;81 Kind sectionKind;
79};82};
8083
81// Represents a WebAssembly data segment which can be included as part of84// Represents a WebAssembly data segment which can be included as part of
...@@ -88,63 +91,65 @@ protected:...@@ -88,63 +91,65 @@ protected:
88// each global variable.91// each global variable.
89class InputSegment : public InputChunk {92class InputSegment : public InputChunk {
90public:93public:
91 InputSegment(const WasmSegment &Seg, ObjFile *F)94 InputSegment(const WasmSegment &seg, ObjFile *f)
92 : InputChunk(F, InputChunk::DataSegment), Segment(Seg) {}95 : InputChunk(f, InputChunk::DataSegment), segment(seg) {}
96
97 static bool classof(const InputChunk *c) { return c->kind() == DataSegment; }
9398
94 static bool classof(const InputChunk *C) { return C->kind() == DataSegment; }99 void generateRelocationCode(raw_ostream &os) const;
95100
96 uint32_t getAlignment() const { return Segment.Data.Alignment; }101 uint32_t getAlignment() const { return segment.Data.Alignment; }
97 StringRef getName() const override { return Segment.Data.Name; }102 StringRef getName() const override { return segment.Data.Name; }
98 StringRef getDebugName() const override { return StringRef(); }103 StringRef getDebugName() const override { return StringRef(); }
99 uint32_t getComdat() const override { return Segment.Data.Comdat; }104 uint32_t getComdat() const override { return segment.Data.Comdat; }
100 uint32_t getInputSectionOffset() const override {105 uint32_t getInputSectionOffset() const override {
101 return Segment.SectionOffset;106 return segment.SectionOffset;
102 }107 }
103108
104 const OutputSegment *OutputSeg = nullptr;109 const OutputSegment *outputSeg = nullptr;
105 int32_t OutputSegmentOffset = 0;110 int32_t outputSegmentOffset = 0;
106111
107protected:112protected:
108 ArrayRef<uint8_t> data() const override { return Segment.Data.Content; }113 ArrayRef<uint8_t> data() const override { return segment.Data.Content; }
109114
110 const WasmSegment &Segment;115 const WasmSegment &segment;
111};116};
112117
113// Represents a single wasm function within and input file. These are118// Represents a single wasm function within and input file. These are
114// combined to create the final output CODE section.119// combined to create the final output CODE section.
115class InputFunction : public InputChunk {120class InputFunction : public InputChunk {
116public:121public:
117 InputFunction(const WasmSignature &S, const WasmFunction *Func, ObjFile *F)122 InputFunction(const WasmSignature &s, const WasmFunction *func, ObjFile *f)
118 : InputChunk(F, InputChunk::Function), Signature(S), Function(Func) {}123 : InputChunk(f, InputChunk::Function), signature(s), function(func) {}
119124
120 static bool classof(const InputChunk *C) {125 static bool classof(const InputChunk *c) {
121 return C->kind() == InputChunk::Function ||126 return c->kind() == InputChunk::Function ||
122 C->kind() == InputChunk::SyntheticFunction;127 c->kind() == InputChunk::SyntheticFunction;
123 }128 }
124129
125 void writeTo(uint8_t *SectionStart) const override;130 void writeTo(uint8_t *sectionStart) const override;
126 StringRef getName() const override { return Function->SymbolName; }131 StringRef getName() const override { return function->SymbolName; }
127 StringRef getDebugName() const override { return Function->DebugName; }132 StringRef getDebugName() const override { return function->DebugName; }
128 uint32_t getComdat() const override { return Function->Comdat; }133 uint32_t getComdat() const override { return function->Comdat; }
129 uint32_t getFunctionInputOffset() const { return getInputSectionOffset(); }134 uint32_t getFunctionInputOffset() const { return getInputSectionOffset(); }
130 uint32_t getFunctionCodeOffset() const { return Function->CodeOffset; }135 uint32_t getFunctionCodeOffset() const { return function->CodeOffset; }
131 uint32_t getSize() const override {136 uint32_t getSize() const override {
132 if (Config->CompressRelocations && File) {137 if (config->compressRelocations && file) {
133 assert(CompressedSize);138 assert(compressedSize);
134 return CompressedSize;139 return compressedSize;
135 }140 }
136 return data().size();141 return data().size();
137 }142 }
138 uint32_t getInputSize() const override { return Function->Size; }143 uint32_t getInputSize() const override { return function->Size; }
139 uint32_t getFunctionIndex() const { return FunctionIndex.getValue(); }144 uint32_t getFunctionIndex() const { return functionIndex.getValue(); }
140 bool hasFunctionIndex() const { return FunctionIndex.hasValue(); }145 bool hasFunctionIndex() const { return functionIndex.hasValue(); }
141 void setFunctionIndex(uint32_t Index);146 void setFunctionIndex(uint32_t index);
142 uint32_t getInputSectionOffset() const override {147 uint32_t getInputSectionOffset() const override {
143 return Function->CodeSectionOffset;148 return function->CodeSectionOffset;
144 }149 }
145 uint32_t getTableIndex() const { return TableIndex.getValue(); }150 uint32_t getTableIndex() const { return tableIndex.getValue(); }
146 bool hasTableIndex() const { return TableIndex.hasValue(); }151 bool hasTableIndex() const { return tableIndex.hasValue(); }
147 void setTableIndex(uint32_t Index);152 void setTableIndex(uint32_t index);
148153
149 // The size of a given input function can depend on the values of the154 // The size of a given input function can depend on the values of the
150 // LEB relocations within it. This finalizeContents method is called after155 // LEB relocations within it. This finalizeContents method is called after
...@@ -152,73 +157,77 @@ public:...@@ -152,73 +157,77 @@ public:
152 // called.157 // called.
153 void calculateSize();158 void calculateSize();
154159
155 const WasmSignature &Signature;160 const WasmSignature &signature;
156161
157protected:162protected:
158 ArrayRef<uint8_t> data() const override {163 ArrayRef<uint8_t> data() const override {
159 assert(!Config->CompressRelocations);164 assert(!config->compressRelocations);
160 return File->CodeSection->Content.slice(getInputSectionOffset(),165 return file->codeSection->Content.slice(getInputSectionOffset(),
161 Function->Size);166 function->Size);
162 }167 }
163168
164 const WasmFunction *Function;169 const WasmFunction *function;
165 llvm::Optional<uint32_t> FunctionIndex;170 llvm::Optional<uint32_t> functionIndex;
166 llvm::Optional<uint32_t> TableIndex;171 llvm::Optional<uint32_t> tableIndex;
167 uint32_t CompressedFuncSize = 0;172 uint32_t compressedFuncSize = 0;
168 uint32_t CompressedSize = 0;173 uint32_t compressedSize = 0;
169};174};
170175
171class SyntheticFunction : public InputFunction {176class SyntheticFunction : public InputFunction {
172public:177public:
173 SyntheticFunction(const WasmSignature &S, StringRef Name,178 SyntheticFunction(const WasmSignature &s, StringRef name,
174 StringRef DebugName = {})179 StringRef debugName = {})
175 : InputFunction(S, nullptr, nullptr), Name(Name), DebugName(DebugName) {180 : InputFunction(s, nullptr, nullptr), name(name), debugName(debugName) {
176 SectionKind = InputChunk::SyntheticFunction;181 sectionKind = InputChunk::SyntheticFunction;
177 }182 }
178183
179 static bool classof(const InputChunk *C) {184 static bool classof(const InputChunk *c) {
180 return C->kind() == InputChunk::SyntheticFunction;185 return c->kind() == InputChunk::SyntheticFunction;
181 }186 }
182187
183 StringRef getName() const override { return Name; }188 StringRef getName() const override { return name; }
184 StringRef getDebugName() const override { return DebugName; }189 StringRef getDebugName() const override { return debugName; }
185 uint32_t getComdat() const override { return UINT32_MAX; }190 uint32_t getComdat() const override { return UINT32_MAX; }
186191
187 void setBody(ArrayRef<uint8_t> Body_) { Body = Body_; }192 void setBody(ArrayRef<uint8_t> body_) { body = body_; }
188193
189protected:194protected:
190 ArrayRef<uint8_t> data() const override { return Body; }195 ArrayRef<uint8_t> data() const override { return body; }
191196
192 StringRef Name;197 StringRef name;
193 StringRef DebugName;198 StringRef debugName;
194 ArrayRef<uint8_t> Body;199 ArrayRef<uint8_t> body;
195};200};
196201
197// Represents a single Wasm Section within an input file.202// Represents a single Wasm Section within an input file.
198class InputSection : public InputChunk {203class InputSection : public InputChunk {
199public:204public:
200 InputSection(const WasmSection &S, ObjFile *F)205 InputSection(const WasmSection &s, ObjFile *f)
201 : InputChunk(F, InputChunk::Section), Section(S) {206 : InputChunk(f, InputChunk::Section), section(s) {
202 assert(Section.Type == llvm::wasm::WASM_SEC_CUSTOM);207 assert(section.Type == llvm::wasm::WASM_SEC_CUSTOM);
203 }208 }
204209
205 StringRef getName() const override { return Section.Name; }210 StringRef getName() const override { return section.Name; }
206 StringRef getDebugName() const override { return StringRef(); }211 StringRef getDebugName() const override { return StringRef(); }
207 uint32_t getComdat() const override { return UINT32_MAX; }212 uint32_t getComdat() const override { return UINT32_MAX; }
208213
214 OutputSection *outputSec = nullptr;
215
209protected:216protected:
210 ArrayRef<uint8_t> data() const override { return Section.Content; }217 ArrayRef<uint8_t> data() const override { return section.Content; }
211218
212 // Offset within the input section. This is only zero since this chunk219 // Offset within the input section. This is only zero since this chunk
213 // type represents an entire input section, not part of one.220 // type represents an entire input section, not part of one.
214 uint32_t getInputSectionOffset() const override { return 0; }221 uint32_t getInputSectionOffset() const override { return 0; }
215222
216 const WasmSection &Section;223 const WasmSection &section;
217};224};
218225
219} // namespace wasm226} // namespace wasm
220227
221std::string toString(const wasm::InputChunk *);228std::string toString(const wasm::InputChunk *);
229StringRef relocTypeToString(uint8_t relocType);
230
222} // namespace lld231} // namespace lld
223232
224#endif // LLD_WASM_INPUT_CHUNKS_H233#endif // LLD_WASM_INPUT_CHUNKS_H
deps/lld/wasm/InputEvent.h+18-19
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputEvent.h ---------------------------------------------*- C++ -*-===//1//===- InputEvent.h ---------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -29,33 +28,33 @@ namespace wasm {...@@ -29,33 +28,33 @@ namespace wasm {
29// form the final EVENTS section.28// form the final EVENTS section.
30class InputEvent {29class InputEvent {
31public:30public:
32 InputEvent(const WasmSignature &S, const WasmEvent &E, ObjFile *F)31 InputEvent(const WasmSignature &s, const WasmEvent &e, ObjFile *f)
33 : File(F), Event(E), Signature(S), Live(!Config->GcSections) {}32 : file(f), event(e), signature(s), live(!config->gcSections) {}
3433
35 StringRef getName() const { return Event.SymbolName; }34 StringRef getName() const { return event.SymbolName; }
36 const WasmEventType &getType() const { return Event.Type; }35 const WasmEventType &getType() const { return event.Type; }
3736
38 uint32_t getEventIndex() const { return EventIndex.getValue(); }37 uint32_t getEventIndex() const { return eventIndex.getValue(); }
39 bool hasEventIndex() const { return EventIndex.hasValue(); }38 bool hasEventIndex() const { return eventIndex.hasValue(); }
40 void setEventIndex(uint32_t Index) {39 void setEventIndex(uint32_t index) {
41 assert(!hasEventIndex());40 assert(!hasEventIndex());
42 EventIndex = Index;41 eventIndex = index;
43 }42 }
4443
45 ObjFile *File;44 ObjFile *file;
46 WasmEvent Event;45 WasmEvent event;
47 const WasmSignature &Signature;46 const WasmSignature &signature;
4847
49 bool Live = false;48 bool live = false;
5049
51protected:50protected:
52 llvm::Optional<uint32_t> EventIndex;51 llvm::Optional<uint32_t> eventIndex;
53};52};
5453
55} // namespace wasm54} // namespace wasm
5655
57inline std::string toString(const wasm::InputEvent *E) {56inline std::string toString(const wasm::InputEvent *e) {
58 return (toString(E->File) + ":(" + E->getName() + ")").str();57 return (toString(e->file) + ":(" + e->getName() + ")").str();
59}58}
6059
61} // namespace lld60} // namespace lld
deps/lld/wasm/InputFiles.cpp+353-289
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputFiles.cpp -----------------------------------------------------===//1//===- InputFiles.cpp -----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -15,8 +14,10 @@...@@ -15,8 +14,10 @@
15#include "SymbolTable.h"14#include "SymbolTable.h"
16#include "lld/Common/ErrorHandler.h"15#include "lld/Common/ErrorHandler.h"
17#include "lld/Common/Memory.h"16#include "lld/Common/Memory.h"
17#include "lld/Common/Reproduce.h"
18#include "llvm/Object/Binary.h"18#include "llvm/Object/Binary.h"
19#include "llvm/Object/Wasm.h"19#include "llvm/Object/Wasm.h"
20#include "llvm/Support/TarWriter.h"
20#include "llvm/Support/raw_ostream.h"21#include "llvm/Support/raw_ostream.h"
2122
22#define DEBUG_TYPE "lld"23#define DEBUG_TYPE "lld"
...@@ -28,62 +29,77 @@ using namespace llvm;...@@ -28,62 +29,77 @@ using namespace llvm;
28using namespace llvm::object;29using namespace llvm::object;
29using namespace llvm::wasm;30using namespace llvm::wasm;
3031
31Optional<MemoryBufferRef> lld::wasm::readFile(StringRef Path) {32std::unique_ptr<llvm::TarWriter> lld::wasm::tar;
32 log("Loading: " + Path);33
34Optional<MemoryBufferRef> lld::wasm::readFile(StringRef path) {
35 log("Loading: " + path);
3336
34 auto MBOrErr = MemoryBuffer::getFile(Path);37 auto mbOrErr = MemoryBuffer::getFile(path);
35 if (auto EC = MBOrErr.getError()) {38 if (auto ec = mbOrErr.getError()) {
36 error("cannot open " + Path + ": " + EC.message());39 error("cannot open " + path + ": " + ec.message());
37 return None;40 return None;
38 }41 }
39 std::unique_ptr<MemoryBuffer> &MB = *MBOrErr;42 std::unique_ptr<MemoryBuffer> &mb = *mbOrErr;
40 MemoryBufferRef MBRef = MB->getMemBufferRef();43 MemoryBufferRef mbref = mb->getMemBufferRef();
41 make<std::unique_ptr<MemoryBuffer>>(std::move(MB)); // take MB ownership44 make<std::unique_ptr<MemoryBuffer>>(std::move(mb)); // take MB ownership
4245
43 return MBRef;46 if (tar)
47 tar->append(relativeToRoot(path), mbref.getBuffer());
48 return mbref;
44}49}
4550
46InputFile *lld::wasm::createObjectFile(MemoryBufferRef MB) {51InputFile *lld::wasm::createObjectFile(MemoryBufferRef mb,
47 file_magic Magic = identify_magic(MB.getBuffer());52 StringRef archiveName) {
48 if (Magic == file_magic::wasm_object)53 file_magic magic = identify_magic(mb.getBuffer());
49 return make<ObjFile>(MB);54 if (magic == file_magic::wasm_object) {
55 std::unique_ptr<Binary> bin =
56 CHECK(createBinary(mb), mb.getBufferIdentifier());
57 auto *obj = cast<WasmObjectFile>(bin.get());
58 if (obj->isSharedObject())
59 return make<SharedFile>(mb);
60 return make<ObjFile>(mb, archiveName);
61 }
5062
51 if (Magic == file_magic::bitcode)63 if (magic == file_magic::bitcode)
52 return make<BitcodeFile>(MB);64 return make<BitcodeFile>(mb, archiveName);
5365
54 fatal("unknown file type: " + MB.getBufferIdentifier());66 fatal("unknown file type: " + mb.getBufferIdentifier());
55}67}
5668
57void ObjFile::dumpInfo() const {69void ObjFile::dumpInfo() const {
58 log("info for: " + getName() +70 log("info for: " + toString(this) +
59 "\n Symbols : " + Twine(Symbols.size()) +71 "\n Symbols : " + Twine(symbols.size()) +
60 "\n Function Imports : " + Twine(WasmObj->getNumImportedFunctions()) +72 "\n Function Imports : " + Twine(wasmObj->getNumImportedFunctions()) +
61 "\n Global Imports : " + Twine(WasmObj->getNumImportedGlobals()) +73 "\n Global Imports : " + Twine(wasmObj->getNumImportedGlobals()) +
62 "\n Event Imports : " + Twine(WasmObj->getNumImportedEvents()));74 "\n Event Imports : " + Twine(wasmObj->getNumImportedEvents()));
63}75}
6476
65// Relocations contain either symbol or type indices. This function takes a77// Relocations contain either symbol or type indices. This function takes a
66// relocation and returns relocated index (i.e. translates from the input78// relocation and returns relocated index (i.e. translates from the input
67// symbol/type space to the output symbol/type space).79// symbol/type space to the output symbol/type space).
68uint32_t ObjFile::calcNewIndex(const WasmRelocation &Reloc) const {80uint32_t ObjFile::calcNewIndex(const WasmRelocation &reloc) const {
69 if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) {81 if (reloc.Type == R_WASM_TYPE_INDEX_LEB) {
70 assert(TypeIsUsed[Reloc.Index]);82 assert(typeIsUsed[reloc.Index]);
71 return TypeMap[Reloc.Index];83 return typeMap[reloc.Index];
72 }84 }
73 return Symbols[Reloc.Index]->getOutputSymbolIndex();85 const Symbol *sym = symbols[reloc.Index];
86 if (auto *ss = dyn_cast<SectionSymbol>(sym))
87 sym = ss->getOutputSectionSymbol();
88 return sym->getOutputSymbolIndex();
74}89}
7590
76// Relocations can contain addend for combined sections. This function takes a91// Relocations can contain addend for combined sections. This function takes a
77// relocation and returns updated addend by offset in the output section.92// relocation and returns updated addend by offset in the output section.
78uint32_t ObjFile::calcNewAddend(const WasmRelocation &Reloc) const {93uint32_t ObjFile::calcNewAddend(const WasmRelocation &reloc) const {
79 switch (Reloc.Type) {94 switch (reloc.Type) {
80 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:95 case R_WASM_MEMORY_ADDR_LEB:
81 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:96 case R_WASM_MEMORY_ADDR_SLEB:
82 case R_WEBASSEMBLY_MEMORY_ADDR_I32:97 case R_WASM_MEMORY_ADDR_REL_SLEB:
83 case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:98 case R_WASM_MEMORY_ADDR_I32:
84 return Reloc.Addend;99 case R_WASM_FUNCTION_OFFSET_I32:
85 case R_WEBASSEMBLY_SECTION_OFFSET_I32:100 return reloc.Addend;
86 return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend;101 case R_WASM_SECTION_OFFSET_I32:
102 return getSectionSymbol(reloc.Index)->section->outputOffset + reloc.Addend;
87 default:103 default:
88 llvm_unreachable("unexpected relocation type");104 llvm_unreachable("unexpected relocation type");
89 }105 }
...@@ -92,39 +108,42 @@ uint32_t ObjFile::calcNewAddend(const WasmRelocation &Reloc) const {...@@ -92,39 +108,42 @@ uint32_t ObjFile::calcNewAddend(const WasmRelocation &Reloc) const {
92// Calculate the value we expect to find at the relocation location.108// Calculate the value we expect to find at the relocation location.
93// This is used as a sanity check before applying a relocation to a given109// This is used as a sanity check before applying a relocation to a given
94// location. It is useful for catching bugs in the compiler and linker.110// location. It is useful for catching bugs in the compiler and linker.
95uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const {111uint32_t ObjFile::calcExpectedValue(const WasmRelocation &reloc) const {
96 switch (Reloc.Type) {112 switch (reloc.Type) {
97 case R_WEBASSEMBLY_TABLE_INDEX_I32:113 case R_WASM_TABLE_INDEX_I32:
98 case R_WEBASSEMBLY_TABLE_INDEX_SLEB: {114 case R_WASM_TABLE_INDEX_SLEB:
99 const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index];115 case R_WASM_TABLE_INDEX_REL_SLEB: {
100 return TableEntries[Sym.Info.ElementIndex];116 const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
117 return tableEntries[sym.Info.ElementIndex];
101 }118 }
102 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:119 case R_WASM_MEMORY_ADDR_SLEB:
103 case R_WEBASSEMBLY_MEMORY_ADDR_I32:120 case R_WASM_MEMORY_ADDR_I32:
104 case R_WEBASSEMBLY_MEMORY_ADDR_LEB: {121 case R_WASM_MEMORY_ADDR_LEB:
105 const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index];122 case R_WASM_MEMORY_ADDR_REL_SLEB: {
106 if (Sym.isUndefined())123 const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
124 if (sym.isUndefined())
107 return 0;125 return 0;
108 const WasmSegment &Segment =126 const WasmSegment &segment =
109 WasmObj->dataSegments()[Sym.Info.DataRef.Segment];127 wasmObj->dataSegments()[sym.Info.DataRef.Segment];
110 return Segment.Data.Offset.Value.Int32 + Sym.Info.DataRef.Offset +128 return segment.Data.Offset.Value.Int32 + sym.Info.DataRef.Offset +
111 Reloc.Addend;129 reloc.Addend;
112 }130 }
113 case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:131 case R_WASM_FUNCTION_OFFSET_I32: {
114 if (auto *Sym = dyn_cast<DefinedFunction>(getFunctionSymbol(Reloc.Index))) {132 const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
115 return Sym->Function->getFunctionInputOffset() +133 InputFunction *f =
116 Sym->Function->getFunctionCodeOffset() + Reloc.Addend;134 functions[sym.Info.ElementIndex - wasmObj->getNumImportedFunctions()];
117 }135 return f->getFunctionInputOffset() + f->getFunctionCodeOffset() +
118 return 0;136 reloc.Addend;
119 case R_WEBASSEMBLY_SECTION_OFFSET_I32:137 }
120 return Reloc.Addend;138 case R_WASM_SECTION_OFFSET_I32:
121 case R_WEBASSEMBLY_TYPE_INDEX_LEB:139 return reloc.Addend;
122 return Reloc.Index;140 case R_WASM_TYPE_INDEX_LEB:
123 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:141 return reloc.Index;
124 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:142 case R_WASM_FUNCTION_INDEX_LEB:
125 case R_WEBASSEMBLY_EVENT_INDEX_LEB: {143 case R_WASM_GLOBAL_INDEX_LEB:
126 const WasmSymbol &Sym = WasmObj->syms()[Reloc.Index];144 case R_WASM_EVENT_INDEX_LEB: {
127 return Sym.Info.ElementIndex;145 const WasmSymbol &sym = wasmObj->syms()[reloc.Index];
146 return sym.Info.ElementIndex;
128 }147 }
129 default:148 default:
130 llvm_unreachable("unknown relocation type");149 llvm_unreachable("unknown relocation type");
...@@ -132,260 +151,299 @@ uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const {...@@ -132,260 +151,299 @@ uint32_t ObjFile::calcExpectedValue(const WasmRelocation &Reloc) const {
132}151}
133152
134// Translate from the relocation's index into the final linked output value.153// Translate from the relocation's index into the final linked output value.
135uint32_t ObjFile::calcNewValue(const WasmRelocation &Reloc) const {154uint32_t ObjFile::calcNewValue(const WasmRelocation &reloc) const {
136 switch (Reloc.Type) {155 const Symbol* sym = nullptr;
137 case R_WEBASSEMBLY_TABLE_INDEX_I32:156 if (reloc.Type != R_WASM_TYPE_INDEX_LEB) {
138 case R_WEBASSEMBLY_TABLE_INDEX_SLEB:157 sym = symbols[reloc.Index];
139 return getFunctionSymbol(Reloc.Index)->getTableIndex();158
140 case R_WEBASSEMBLY_MEMORY_ADDR_SLEB:159 // We can end up with relocations against non-live symbols. For example
141 case R_WEBASSEMBLY_MEMORY_ADDR_I32:160 // in debug sections.
142 case R_WEBASSEMBLY_MEMORY_ADDR_LEB:161 if ((isa<FunctionSymbol>(sym) || isa<DataSymbol>(sym)) && !sym->isLive())
143 if (auto *Sym = dyn_cast<DefinedData>(getDataSymbol(Reloc.Index)))162 return 0;
144 if (Sym->isLive())163 }
145 return Sym->getVirtualAddress() + Reloc.Addend;164
146 return 0;165 switch (reloc.Type) {
147 case R_WEBASSEMBLY_TYPE_INDEX_LEB:166 case R_WASM_TABLE_INDEX_I32:
148 return TypeMap[Reloc.Index];167 case R_WASM_TABLE_INDEX_SLEB:
149 case R_WEBASSEMBLY_FUNCTION_INDEX_LEB:168 case R_WASM_TABLE_INDEX_REL_SLEB:
150 return getFunctionSymbol(Reloc.Index)->getFunctionIndex();169 if (config->isPic && !getFunctionSymbol(reloc.Index)->hasTableIndex())
151 case R_WEBASSEMBLY_GLOBAL_INDEX_LEB:170 return 0;
152 return getGlobalSymbol(Reloc.Index)->getGlobalIndex();171 return getFunctionSymbol(reloc.Index)->getTableIndex();
153 case R_WEBASSEMBLY_EVENT_INDEX_LEB:172 case R_WASM_MEMORY_ADDR_SLEB:
154 return getEventSymbol(Reloc.Index)->getEventIndex();173 case R_WASM_MEMORY_ADDR_I32:
155 case R_WEBASSEMBLY_FUNCTION_OFFSET_I32:174 case R_WASM_MEMORY_ADDR_LEB:
156 if (auto *Sym = dyn_cast<DefinedFunction>(getFunctionSymbol(Reloc.Index))) {175 case R_WASM_MEMORY_ADDR_REL_SLEB:
157 if (Sym->isLive())176 if (isa<UndefinedData>(sym))
158 return Sym->Function->OutputOffset +177 return 0;
159 Sym->Function->getFunctionCodeOffset() + Reloc.Addend;178 return cast<DefinedData>(sym)->getVirtualAddress() + reloc.Addend;
160 }179 case R_WASM_TYPE_INDEX_LEB:
161 return 0;180 return typeMap[reloc.Index];
162 case R_WEBASSEMBLY_SECTION_OFFSET_I32:181 case R_WASM_FUNCTION_INDEX_LEB:
163 return getSectionSymbol(Reloc.Index)->Section->OutputOffset + Reloc.Addend;182 return getFunctionSymbol(reloc.Index)->getFunctionIndex();
183 case R_WASM_GLOBAL_INDEX_LEB:
184 if (auto gs = dyn_cast<GlobalSymbol>(sym))
185 return gs->getGlobalIndex();
186 return sym->getGOTIndex();
187 case R_WASM_EVENT_INDEX_LEB:
188 return getEventSymbol(reloc.Index)->getEventIndex();
189 case R_WASM_FUNCTION_OFFSET_I32: {
190 auto *f = cast<DefinedFunction>(sym);
191 return f->function->outputOffset + f->function->getFunctionCodeOffset() +
192 reloc.Addend;
193 }
194 case R_WASM_SECTION_OFFSET_I32:
195 return getSectionSymbol(reloc.Index)->section->outputOffset + reloc.Addend;
164 default:196 default:
165 llvm_unreachable("unknown relocation type");197 llvm_unreachable("unknown relocation type");
166 }198 }
167}199}
168200
169template <class T>201template <class T>
170static void setRelocs(const std::vector<T *> &Chunks,202static void setRelocs(const std::vector<T *> &chunks,
171 const WasmSection *Section) {203 const WasmSection *section) {
172 if (!Section)204 if (!section)
173 return;205 return;
174206
175 ArrayRef<WasmRelocation> Relocs = Section->Relocations;207 ArrayRef<WasmRelocation> relocs = section->Relocations;
176 assert(std::is_sorted(Relocs.begin(), Relocs.end(),208 assert(std::is_sorted(relocs.begin(), relocs.end(),
177 [](const WasmRelocation &R1, const WasmRelocation &R2) {209 [](const WasmRelocation &r1, const WasmRelocation &r2) {
178 return R1.Offset < R2.Offset;210 return r1.Offset < r2.Offset;
179 }));211 }));
180 assert(std::is_sorted(212 assert(std::is_sorted(
181 Chunks.begin(), Chunks.end(), [](InputChunk *C1, InputChunk *C2) {213 chunks.begin(), chunks.end(), [](InputChunk *c1, InputChunk *c2) {
182 return C1->getInputSectionOffset() < C2->getInputSectionOffset();214 return c1->getInputSectionOffset() < c2->getInputSectionOffset();
183 }));215 }));
184216
185 auto RelocsNext = Relocs.begin();217 auto relocsNext = relocs.begin();
186 auto RelocsEnd = Relocs.end();218 auto relocsEnd = relocs.end();
187 auto RelocLess = [](const WasmRelocation &R, uint32_t Val) {219 auto relocLess = [](const WasmRelocation &r, uint32_t val) {
188 return R.Offset < Val;220 return r.Offset < val;
189 };221 };
190 for (InputChunk *C : Chunks) {222 for (InputChunk *c : chunks) {
191 auto RelocsStart = std::lower_bound(RelocsNext, RelocsEnd,223 auto relocsStart = std::lower_bound(relocsNext, relocsEnd,
192 C->getInputSectionOffset(), RelocLess);224 c->getInputSectionOffset(), relocLess);
193 RelocsNext = std::lower_bound(225 relocsNext = std::lower_bound(
194 RelocsStart, RelocsEnd, C->getInputSectionOffset() + C->getInputSize(),226 relocsStart, relocsEnd, c->getInputSectionOffset() + c->getInputSize(),
195 RelocLess);227 relocLess);
196 C->setRelocations(ArrayRef<WasmRelocation>(RelocsStart, RelocsNext));228 c->setRelocations(ArrayRef<WasmRelocation>(relocsStart, relocsNext));
197 }229 }
198}230}
199231
200void ObjFile::parse() {232void ObjFile::parse(bool ignoreComdats) {
201 // Parse a memory buffer as a wasm file.233 // Parse a memory buffer as a wasm file.
202 LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");234 LLVM_DEBUG(dbgs() << "Parsing object: " << toString(this) << "\n");
203 std::unique_ptr<Binary> Bin = CHECK(createBinary(MB), toString(this));235 std::unique_ptr<Binary> bin = CHECK(createBinary(mb), toString(this));
204236
205 auto *Obj = dyn_cast<WasmObjectFile>(Bin.get());237 auto *obj = dyn_cast<WasmObjectFile>(bin.get());
206 if (!Obj)238 if (!obj)
207 fatal(toString(this) + ": not a wasm file");239 fatal(toString(this) + ": not a wasm file");
208 if (!Obj->isRelocatableObject())240 if (!obj->isRelocatableObject())
209 fatal(toString(this) + ": not a relocatable wasm file");241 fatal(toString(this) + ": not a relocatable wasm file");
210242
211 Bin.release();243 bin.release();
212 WasmObj.reset(Obj);244 wasmObj.reset(obj);
213245
214 // Build up a map of function indices to table indices for use when246 // Build up a map of function indices to table indices for use when
215 // verifying the existing table index relocations247 // verifying the existing table index relocations
216 uint32_t TotalFunctions =248 uint32_t totalFunctions =
217 WasmObj->getNumImportedFunctions() + WasmObj->functions().size();249 wasmObj->getNumImportedFunctions() + wasmObj->functions().size();
218 TableEntries.resize(TotalFunctions);250 tableEntries.resize(totalFunctions);
219 for (const WasmElemSegment &Seg : WasmObj->elements()) {251 for (const WasmElemSegment &seg : wasmObj->elements()) {
220 if (Seg.Offset.Opcode != WASM_OPCODE_I32_CONST)252 if (seg.Offset.Opcode != WASM_OPCODE_I32_CONST)
221 fatal(toString(this) + ": invalid table elements");253 fatal(toString(this) + ": invalid table elements");
222 uint32_t Offset = Seg.Offset.Value.Int32;254 uint32_t offset = seg.Offset.Value.Int32;
223 for (uint32_t Index = 0; Index < Seg.Functions.size(); Index++) {255 for (uint32_t index = 0; index < seg.Functions.size(); index++) {
224256
225 uint32_t FunctionIndex = Seg.Functions[Index];257 uint32_t functionIndex = seg.Functions[index];
226 TableEntries[FunctionIndex] = Offset + Index;258 tableEntries[functionIndex] = offset + index;
227 }259 }
228 }260 }
229261
230 // Find the code and data sections. Wasm objects can have at most one code262 uint32_t sectionIndex = 0;
231 // and one data section.263
232 uint32_t SectionIndex = 0;264 // Bool for each symbol, true if called directly. This allows us to implement
233 for (const SectionRef &Sec : WasmObj->sections()) {265 // a weaker form of signature checking where undefined functions that are not
234 const WasmSection &Section = WasmObj->getWasmSection(Sec);266 // called directly (i.e. only address taken) don't have to match the defined
235 if (Section.Type == WASM_SEC_CODE) {267 // function's signature. We cannot do this for directly called functions
236 CodeSection = &Section;268 // because those signatures are checked at validation times.
237 } else if (Section.Type == WASM_SEC_DATA) {269 // See https://bugs.llvm.org/show_bug.cgi?id=40412
238 DataSection = &Section;270 std::vector<bool> isCalledDirectly(wasmObj->getNumberOfSymbols(), false);
239 } else if (Section.Type == WASM_SEC_CUSTOM) {271 for (const SectionRef &sec : wasmObj->sections()) {
240 CustomSections.emplace_back(make<InputSection>(Section, this));272 const WasmSection &section = wasmObj->getWasmSection(sec);
241 CustomSections.back()->setRelocations(Section.Relocations);273 // Wasm objects can have at most one code and one data section.
242 CustomSectionsByIndex[SectionIndex] = CustomSections.back();274 if (section.Type == WASM_SEC_CODE) {
275 assert(!codeSection);
276 codeSection = &section;
277 } else if (section.Type == WASM_SEC_DATA) {
278 assert(!dataSection);
279 dataSection = &section;
280 } else if (section.Type == WASM_SEC_CUSTOM) {
281 customSections.emplace_back(make<InputSection>(section, this));
282 customSections.back()->setRelocations(section.Relocations);
283 customSectionsByIndex[sectionIndex] = customSections.back();
243 }284 }
244 SectionIndex++;285 sectionIndex++;
286 // Scans relocations to dermine determine if a function symbol is called
287 // directly
288 for (const WasmRelocation &reloc : section.Relocations)
289 if (reloc.Type == R_WASM_FUNCTION_INDEX_LEB)
290 isCalledDirectly[reloc.Index] = true;
245 }291 }
246292
247 TypeMap.resize(getWasmObj()->types().size());293 typeMap.resize(getWasmObj()->types().size());
248 TypeIsUsed.resize(getWasmObj()->types().size(), false);294 typeIsUsed.resize(getWasmObj()->types().size(), false);
249295
250 ArrayRef<StringRef> Comdats = WasmObj->linkingData().Comdats;296 ArrayRef<StringRef> comdats = wasmObj->linkingData().Comdats;
251 UsedComdats.resize(Comdats.size());297 for (StringRef comdat : comdats) {
252 for (unsigned I = 0; I < Comdats.size(); ++I)298 bool isNew = ignoreComdats || symtab->addComdat(comdat);
253 UsedComdats[I] = Symtab->addComdat(Comdats[I]);299 keptComdats.push_back(isNew);
300 }
254301
255 // Populate `Segments`.302 // Populate `Segments`.
256 for (const WasmSegment &S : WasmObj->dataSegments())303 for (const WasmSegment &s : wasmObj->dataSegments()) {
257 Segments.emplace_back(make<InputSegment>(S, this));304 auto* seg = make<InputSegment>(s, this);
258 setRelocs(Segments, DataSection);305 seg->discarded = isExcludedByComdat(seg);
306 segments.emplace_back(seg);
307 }
308 setRelocs(segments, dataSection);
259309
260 // Populate `Functions`.310 // Populate `Functions`.
261 ArrayRef<WasmFunction> Funcs = WasmObj->functions();311 ArrayRef<WasmFunction> funcs = wasmObj->functions();
262 ArrayRef<uint32_t> FuncTypes = WasmObj->functionTypes();312 ArrayRef<uint32_t> funcTypes = wasmObj->functionTypes();
263 ArrayRef<WasmSignature> Types = WasmObj->types();313 ArrayRef<WasmSignature> types = wasmObj->types();
264 Functions.reserve(Funcs.size());314 functions.reserve(funcs.size());
265315
266 for (size_t I = 0, E = Funcs.size(); I != E; ++I)316 for (size_t i = 0, e = funcs.size(); i != e; ++i) {
267 Functions.emplace_back(317 auto* func = make<InputFunction>(types[funcTypes[i]], &funcs[i], this);
268 make<InputFunction>(Types[FuncTypes[I]], &Funcs[I], this));318 func->discarded = isExcludedByComdat(func);
269 setRelocs(Functions, CodeSection);319 functions.emplace_back(func);
320 }
321 setRelocs(functions, codeSection);
270322
271 // Populate `Globals`.323 // Populate `Globals`.
272 for (const WasmGlobal &G : WasmObj->globals())324 for (const WasmGlobal &g : wasmObj->globals())
273 Globals.emplace_back(make<InputGlobal>(G, this));325 globals.emplace_back(make<InputGlobal>(g, this));
274326
275 // Populate `Events`.327 // Populate `Events`.
276 for (const WasmEvent &E : WasmObj->events())328 for (const WasmEvent &e : wasmObj->events())
277 Events.emplace_back(make<InputEvent>(Types[E.Type.SigIndex], E, this));329 events.emplace_back(make<InputEvent>(types[e.Type.SigIndex], e, this));
278330
279 // Populate `Symbols` based on the WasmSymbols in the object.331 // Populate `Symbols` based on the symbols in the object.
280 Symbols.reserve(WasmObj->getNumberOfSymbols());332 symbols.reserve(wasmObj->getNumberOfSymbols());
281 for (const SymbolRef &Sym : WasmObj->symbols()) {333 for (const SymbolRef &sym : wasmObj->symbols()) {
282 const WasmSymbol &WasmSym = WasmObj->getWasmSymbol(Sym.getRawDataRefImpl());334 const WasmSymbol &wasmSym = wasmObj->getWasmSymbol(sym.getRawDataRefImpl());
283 if (Symbol *Sym = createDefined(WasmSym))335 if (wasmSym.isDefined()) {
284 Symbols.push_back(Sym);336 // createDefined may fail if the symbol is comdat excluded in which case
285 else337 // we fall back to creating an undefined symbol
286 Symbols.push_back(createUndefined(WasmSym));338 if (Symbol *d = createDefined(wasmSym)) {
339 symbols.push_back(d);
340 continue;
341 }
342 }
343 size_t idx = symbols.size();
344 symbols.push_back(createUndefined(wasmSym, isCalledDirectly[idx]));
287 }345 }
288}346}
289347
290bool ObjFile::isExcludedByComdat(InputChunk *Chunk) const {348bool ObjFile::isExcludedByComdat(InputChunk *chunk) const {
291 uint32_t C = Chunk->getComdat();349 uint32_t c = chunk->getComdat();
292 if (C == UINT32_MAX)350 if (c == UINT32_MAX)
293 return false;351 return false;
294 return !UsedComdats[C];352 return !keptComdats[c];
295}353}
296354
297FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t Index) const {355FunctionSymbol *ObjFile::getFunctionSymbol(uint32_t index) const {
298 return cast<FunctionSymbol>(Symbols[Index]);356 return cast<FunctionSymbol>(symbols[index]);
299}357}
300358
301GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t Index) const {359GlobalSymbol *ObjFile::getGlobalSymbol(uint32_t index) const {
302 return cast<GlobalSymbol>(Symbols[Index]);360 return cast<GlobalSymbol>(symbols[index]);
303}361}
304362
305EventSymbol *ObjFile::getEventSymbol(uint32_t Index) const {363EventSymbol *ObjFile::getEventSymbol(uint32_t index) const {
306 return cast<EventSymbol>(Symbols[Index]);364 return cast<EventSymbol>(symbols[index]);
307}365}
308366
309SectionSymbol *ObjFile::getSectionSymbol(uint32_t Index) const {367SectionSymbol *ObjFile::getSectionSymbol(uint32_t index) const {
310 return cast<SectionSymbol>(Symbols[Index]);368 return cast<SectionSymbol>(symbols[index]);
311}369}
312370
313DataSymbol *ObjFile::getDataSymbol(uint32_t Index) const {371DataSymbol *ObjFile::getDataSymbol(uint32_t index) const {
314 return cast<DataSymbol>(Symbols[Index]);372 return cast<DataSymbol>(symbols[index]);
315}373}
316374
317Symbol *ObjFile::createDefined(const WasmSymbol &Sym) {375Symbol *ObjFile::createDefined(const WasmSymbol &sym) {
318 if (!Sym.isDefined())376 StringRef name = sym.Info.Name;
319 return nullptr;377 uint32_t flags = sym.Info.Flags;
320
321 StringRef Name = Sym.Info.Name;
322 uint32_t Flags = Sym.Info.Flags;
323378
324 switch (Sym.Info.Kind) {379 switch (sym.Info.Kind) {
325 case WASM_SYMBOL_TYPE_FUNCTION: {380 case WASM_SYMBOL_TYPE_FUNCTION: {
326 InputFunction *Func =381 InputFunction *func =
327 Functions[Sym.Info.ElementIndex - WasmObj->getNumImportedFunctions()];382 functions[sym.Info.ElementIndex - wasmObj->getNumImportedFunctions()];
328 if (isExcludedByComdat(Func)) {383 if (sym.isBindingLocal())
329 Func->Live = false;384 return make<DefinedFunction>(name, flags, this, func);
385 if (func->discarded)
330 return nullptr;386 return nullptr;
331 }387 return symtab->addDefinedFunction(name, flags, this, func);
332
333 if (Sym.isBindingLocal())
334 return make<DefinedFunction>(Name, Flags, this, Func);
335 return Symtab->addDefinedFunction(Name, Flags, this, Func);
336 }388 }
337 case WASM_SYMBOL_TYPE_DATA: {389 case WASM_SYMBOL_TYPE_DATA: {
338 InputSegment *Seg = Segments[Sym.Info.DataRef.Segment];390 InputSegment *seg = segments[sym.Info.DataRef.Segment];
339 if (isExcludedByComdat(Seg)) {391 uint32_t offset = sym.Info.DataRef.Offset;
340 Seg->Live = false;392 uint32_t size = sym.Info.DataRef.Size;
393 if (sym.isBindingLocal())
394 return make<DefinedData>(name, flags, this, seg, offset, size);
395 if (seg->discarded)
341 return nullptr;396 return nullptr;
342 }397 return symtab->addDefinedData(name, flags, this, seg, offset, size);
343
344 uint32_t Offset = Sym.Info.DataRef.Offset;
345 uint32_t Size = Sym.Info.DataRef.Size;
346
347 if (Sym.isBindingLocal())
348 return make<DefinedData>(Name, Flags, this, Seg, Offset, Size);
349 return Symtab->addDefinedData(Name, Flags, this, Seg, Offset, Size);
350 }398 }
351 case WASM_SYMBOL_TYPE_GLOBAL: {399 case WASM_SYMBOL_TYPE_GLOBAL: {
352 InputGlobal *Global =400 InputGlobal *global =
353 Globals[Sym.Info.ElementIndex - WasmObj->getNumImportedGlobals()];401 globals[sym.Info.ElementIndex - wasmObj->getNumImportedGlobals()];
354 if (Sym.isBindingLocal())402 if (sym.isBindingLocal())
355 return make<DefinedGlobal>(Name, Flags, this, Global);403 return make<DefinedGlobal>(name, flags, this, global);
356 return Symtab->addDefinedGlobal(Name, Flags, this, Global);404 return symtab->addDefinedGlobal(name, flags, this, global);
357 }405 }
358 case WASM_SYMBOL_TYPE_SECTION: {406 case WASM_SYMBOL_TYPE_SECTION: {
359 InputSection *Section = CustomSectionsByIndex[Sym.Info.ElementIndex];407 InputSection *section = customSectionsByIndex[sym.Info.ElementIndex];
360 assert(Sym.isBindingLocal());408 assert(sym.isBindingLocal());
361 return make<SectionSymbol>(Name, Flags, Section, this);409 return make<SectionSymbol>(flags, section, this);
362 }410 }
363 case WASM_SYMBOL_TYPE_EVENT: {411 case WASM_SYMBOL_TYPE_EVENT: {
364 InputEvent *Event =412 InputEvent *event =
365 Events[Sym.Info.ElementIndex - WasmObj->getNumImportedEvents()];413 events[sym.Info.ElementIndex - wasmObj->getNumImportedEvents()];
366 if (Sym.isBindingLocal())414 if (sym.isBindingLocal())
367 return make<DefinedEvent>(Name, Flags, this, Event);415 return make<DefinedEvent>(name, flags, this, event);
368 return Symtab->addDefinedEvent(Name, Flags, this, Event);416 return symtab->addDefinedEvent(name, flags, this, event);
369 }417 }
370 }418 }
371 llvm_unreachable("unknown symbol kind");419 llvm_unreachable("unknown symbol kind");
372}420}
373421
374Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {422Symbol *ObjFile::createUndefined(const WasmSymbol &sym, bool isCalledDirectly) {
375 StringRef Name = Sym.Info.Name;423 StringRef name = sym.Info.Name;
376 uint32_t Flags = Sym.Info.Flags;424 uint32_t flags = sym.Info.Flags;
377425
378 switch (Sym.Info.Kind) {426 switch (sym.Info.Kind) {
379 case WASM_SYMBOL_TYPE_FUNCTION:427 case WASM_SYMBOL_TYPE_FUNCTION:
380 return Symtab->addUndefinedFunction(Name, Sym.Info.ImportName,428 if (sym.isBindingLocal())
381 Sym.Info.ImportModule, Flags, this,429 return make<UndefinedFunction>(name, sym.Info.ImportName,
382 Sym.Signature);430 sym.Info.ImportModule, flags, this,
431 sym.Signature, isCalledDirectly);
432 return symtab->addUndefinedFunction(name, sym.Info.ImportName,
433 sym.Info.ImportModule, flags, this,
434 sym.Signature, isCalledDirectly);
383 case WASM_SYMBOL_TYPE_DATA:435 case WASM_SYMBOL_TYPE_DATA:
384 return Symtab->addUndefinedData(Name, Flags, this);436 if (sym.isBindingLocal())
437 return make<UndefinedData>(name, flags, this);
438 return symtab->addUndefinedData(name, flags, this);
385 case WASM_SYMBOL_TYPE_GLOBAL:439 case WASM_SYMBOL_TYPE_GLOBAL:
386 return Symtab->addUndefinedGlobal(Name, Sym.Info.ImportName,440 if (sym.isBindingLocal())
387 Sym.Info.ImportModule, Flags, this,441 return make<UndefinedGlobal>(name, sym.Info.ImportName,
388 Sym.GlobalType);442 sym.Info.ImportModule, flags, this,
443 sym.GlobalType);
444 return symtab->addUndefinedGlobal(name, sym.Info.ImportName,
445 sym.Info.ImportModule, flags, this,
446 sym.GlobalType);
389 case WASM_SYMBOL_TYPE_SECTION:447 case WASM_SYMBOL_TYPE_SECTION:
390 llvm_unreachable("section symbols cannot be undefined");448 llvm_unreachable("section symbols cannot be undefined");
391 }449 }
...@@ -395,42 +453,41 @@ Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {...@@ -395,42 +453,41 @@ Symbol *ObjFile::createUndefined(const WasmSymbol &Sym) {
395void ArchiveFile::parse() {453void ArchiveFile::parse() {
396 // Parse a MemoryBufferRef as an archive file.454 // Parse a MemoryBufferRef as an archive file.
397 LLVM_DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");455 LLVM_DEBUG(dbgs() << "Parsing library: " << toString(this) << "\n");
398 File = CHECK(Archive::create(MB), toString(this));456 file = CHECK(Archive::create(mb), toString(this));
399457
400 // Read the symbol table to construct Lazy symbols.458 // Read the symbol table to construct Lazy symbols.
401 int Count = 0;459 int count = 0;
402 for (const Archive::Symbol &Sym : File->symbols()) {460 for (const Archive::Symbol &sym : file->symbols()) {
403 Symtab->addLazy(this, &Sym);461 symtab->addLazy(this, &sym);
404 ++Count;462 ++count;
405 }463 }
406 LLVM_DEBUG(dbgs() << "Read " << Count << " symbols\n");464 LLVM_DEBUG(dbgs() << "Read " << count << " symbols\n");
407}465}
408466
409void ArchiveFile::addMember(const Archive::Symbol *Sym) {467void ArchiveFile::addMember(const Archive::Symbol *sym) {
410 const Archive::Child &C =468 const Archive::Child &c =
411 CHECK(Sym->getMember(),469 CHECK(sym->getMember(),
412 "could not get the member for symbol " + Sym->getName());470 "could not get the member for symbol " + sym->getName());
413471
414 // Don't try to load the same member twice (this can happen when members472 // Don't try to load the same member twice (this can happen when members
415 // mutually reference each other).473 // mutually reference each other).
416 if (!Seen.insert(C.getChildOffset()).second)474 if (!seen.insert(c.getChildOffset()).second)
417 return;475 return;
418476
419 LLVM_DEBUG(dbgs() << "loading lazy: " << Sym->getName() << "\n");477 LLVM_DEBUG(dbgs() << "loading lazy: " << sym->getName() << "\n");
420 LLVM_DEBUG(dbgs() << "from archive: " << toString(this) << "\n");478 LLVM_DEBUG(dbgs() << "from archive: " << toString(this) << "\n");
421479
422 MemoryBufferRef MB =480 MemoryBufferRef mb =
423 CHECK(C.getMemoryBufferRef(),481 CHECK(c.getMemoryBufferRef(),
424 "could not get the buffer for the member defining symbol " +482 "could not get the buffer for the member defining symbol " +
425 Sym->getName());483 sym->getName());
426484
427 InputFile *Obj = createObjectFile(MB);485 InputFile *obj = createObjectFile(mb, getName());
428 Obj->ArchiveName = getName();486 symtab->addFile(obj);
429 Symtab->addFile(Obj);
430}487}
431488
432static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {489static uint8_t mapVisibility(GlobalValue::VisibilityTypes gvVisibility) {
433 switch (GvVisibility) {490 switch (gvVisibility) {
434 case GlobalValue::DefaultVisibility:491 case GlobalValue::DefaultVisibility:
435 return WASM_SYMBOL_VISIBILITY_DEFAULT;492 return WASM_SYMBOL_VISIBILITY_DEFAULT;
436 case GlobalValue::HiddenVisibility:493 case GlobalValue::HiddenVisibility:
...@@ -440,45 +497,52 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {...@@ -440,45 +497,52 @@ static uint8_t mapVisibility(GlobalValue::VisibilityTypes GvVisibility) {
440 llvm_unreachable("unknown visibility");497 llvm_unreachable("unknown visibility");
441}498}
442499
443static Symbol *createBitcodeSymbol(const lto::InputFile::Symbol &ObjSym,500static Symbol *createBitcodeSymbol(const std::vector<bool> &keptComdats,
444 BitcodeFile &F) {501 const lto::InputFile::Symbol &objSym,
445 StringRef Name = Saver.save(ObjSym.getName());502 BitcodeFile &f) {
503 StringRef name = saver.save(objSym.getName());
504
505 uint32_t flags = objSym.isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0;
506 flags |= mapVisibility(objSym.getVisibility());
446507
447 uint32_t Flags = ObjSym.isWeak() ? WASM_SYMBOL_BINDING_WEAK : 0;508 int c = objSym.getComdatIndex();
448 Flags |= mapVisibility(ObjSym.getVisibility());509 bool excludedByComdat = c != -1 && !keptComdats[c];
449510
450 if (ObjSym.isUndefined()) {511 if (objSym.isUndefined() || excludedByComdat) {
451 if (ObjSym.isExecutable())512 if (objSym.isExecutable())
452 return Symtab->addUndefinedFunction(Name, Name, DefaultModule, Flags, &F,513 return symtab->addUndefinedFunction(name, name, defaultModule, flags, &f,
453 nullptr);514 nullptr, true);
454 return Symtab->addUndefinedData(Name, Flags, &F);515 return symtab->addUndefinedData(name, flags, &f);
455 }516 }
456517
457 if (ObjSym.isExecutable())518 if (objSym.isExecutable())
458 return Symtab->addDefinedFunction(Name, Flags, &F, nullptr);519 return symtab->addDefinedFunction(name, flags, &f, nullptr);
459 return Symtab->addDefinedData(Name, Flags, &F, nullptr, 0, 0);520 return symtab->addDefinedData(name, flags, &f, nullptr, 0, 0);
460}521}
461522
462void BitcodeFile::parse() {523void BitcodeFile::parse() {
463 Obj = check(lto::InputFile::create(MemoryBufferRef(524 obj = check(lto::InputFile::create(MemoryBufferRef(
464 MB.getBuffer(), Saver.save(ArchiveName + MB.getBufferIdentifier()))));525 mb.getBuffer(), saver.save(archiveName + mb.getBufferIdentifier()))));
465 Triple T(Obj->getTargetTriple());526 Triple t(obj->getTargetTriple());
466 if (T.getArch() != Triple::wasm32) {527 if (t.getArch() != Triple::wasm32) {
467 error(toString(MB.getBufferIdentifier()) + ": machine type must be wasm32");528 error(toString(mb.getBufferIdentifier()) + ": machine type must be wasm32");
468 return;529 return;
469 }530 }
531 std::vector<bool> keptComdats;
532 for (StringRef s : obj->getComdatTable())
533 keptComdats.push_back(symtab->addComdat(s));
470534
471 for (const lto::InputFile::Symbol &ObjSym : Obj->symbols())535 for (const lto::InputFile::Symbol &objSym : obj->symbols())
472 Symbols.push_back(createBitcodeSymbol(ObjSym, *this));536 symbols.push_back(createBitcodeSymbol(keptComdats, objSym, *this));
473}537}
474538
475// Returns a string in the format of "foo.o" or "foo.a(bar.o)".539// Returns a string in the format of "foo.o" or "foo.a(bar.o)".
476std::string lld::toString(const wasm::InputFile *File) {540std::string lld::toString(const wasm::InputFile *file) {
477 if (!File)541 if (!file)
478 return "<internal>";542 return "<internal>";
479543
480 if (File->ArchiveName.empty())544 if (file->archiveName.empty())
481 return File->getName();545 return file->getName();
482546
483 return (File->ArchiveName + "(" + File->getName() + ")").str();547 return (file->archiveName + "(" + file->getName() + ")").str();
484}548}
deps/lld/wasm/InputFiles.h+85-61
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputFiles.h ---------------------------------------------*- C++ -*-===//1//===- InputFiles.h ---------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -20,6 +19,10 @@...@@ -20,6 +19,10 @@
20#include "llvm/Support/MemoryBuffer.h"19#include "llvm/Support/MemoryBuffer.h"
21#include <vector>20#include <vector>
2221
22namespace llvm {
23class TarWriter;
24}
25
23namespace lld {26namespace lld {
24namespace wasm {27namespace wasm {
2528
...@@ -30,10 +33,15 @@ class InputGlobal;...@@ -30,10 +33,15 @@ class InputGlobal;
30class InputEvent;33class InputEvent;
31class InputSection;34class InputSection;
3235
36// If --reproduce option is given, all input files are written
37// to this tar archive.
38extern std::unique_ptr<llvm::TarWriter> tar;
39
33class InputFile {40class InputFile {
34public:41public:
35 enum Kind {42 enum Kind {
36 ObjectKind,43 ObjectKind,
44 SharedKind,
37 ArchiveKind,45 ArchiveKind,
38 BitcodeKind,46 BitcodeKind,
39 };47 };
...@@ -41,113 +49,129 @@ public:...@@ -41,113 +49,129 @@ public:
41 virtual ~InputFile() {}49 virtual ~InputFile() {}
4250
43 // Returns the filename.51 // Returns the filename.
44 StringRef getName() const { return MB.getBufferIdentifier(); }52 StringRef getName() const { return mb.getBufferIdentifier(); }
4553
46 // Reads a file (the constructor doesn't do that).54 Kind kind() const { return fileKind; }
47 virtual void parse() = 0;
48
49 Kind kind() const { return FileKind; }
5055
51 // An archive file name if this file is created from an archive.56 // An archive file name if this file is created from an archive.
52 StringRef ArchiveName;57 StringRef archiveName;
58
59 ArrayRef<Symbol *> getSymbols() const { return symbols; }
5360
54 ArrayRef<Symbol *> getSymbols() const { return Symbols; }61 MutableArrayRef<Symbol *> getMutableSymbols() { return symbols; }
5562
56protected:63protected:
57 InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {}64 InputFile(Kind k, MemoryBufferRef m) : mb(m), fileKind(k) {}
58 MemoryBufferRef MB;65 MemoryBufferRef mb;
5966
60 // List of all symbols referenced or defined by this file.67 // List of all symbols referenced or defined by this file.
61 std::vector<Symbol *> Symbols;68 std::vector<Symbol *> symbols;
6269
63private:70private:
64 const Kind FileKind;71 const Kind fileKind;
65};72};
6673
67// .a file (ar archive)74// .a file (ar archive)
68class ArchiveFile : public InputFile {75class ArchiveFile : public InputFile {
69public:76public:
70 explicit ArchiveFile(MemoryBufferRef M) : InputFile(ArchiveKind, M) {}77 explicit ArchiveFile(MemoryBufferRef m) : InputFile(ArchiveKind, m) {}
71 static bool classof(const InputFile *F) { return F->kind() == ArchiveKind; }78 static bool classof(const InputFile *f) { return f->kind() == ArchiveKind; }
7279
73 void addMember(const llvm::object::Archive::Symbol *Sym);80 void addMember(const llvm::object::Archive::Symbol *sym);
7481
75 void parse() override;82 void parse();
7683
77private:84private:
78 std::unique_ptr<llvm::object::Archive> File;85 std::unique_ptr<llvm::object::Archive> file;
79 llvm::DenseSet<uint64_t> Seen;86 llvm::DenseSet<uint64_t> seen;
80};87};
8188
82// .o file (wasm object file)89// .o file (wasm object file)
83class ObjFile : public InputFile {90class ObjFile : public InputFile {
84public:91public:
85 explicit ObjFile(MemoryBufferRef M) : InputFile(ObjectKind, M) {}92 explicit ObjFile(MemoryBufferRef m, StringRef archiveName)
86 static bool classof(const InputFile *F) { return F->kind() == ObjectKind; }93 : InputFile(ObjectKind, m) {
94 this->archiveName = archiveName;
95 }
96 static bool classof(const InputFile *f) { return f->kind() == ObjectKind; }
8797
88 void parse() override;98 void parse(bool ignoreComdats = false);
8999
90 // Returns the underlying wasm file.100 // Returns the underlying wasm file.
91 const WasmObjectFile *getWasmObj() const { return WasmObj.get(); }101 const WasmObjectFile *getWasmObj() const { return wasmObj.get(); }
92102
93 void dumpInfo() const;103 void dumpInfo() const;
94104
95 uint32_t calcNewIndex(const WasmRelocation &Reloc) const;105 uint32_t calcNewIndex(const WasmRelocation &reloc) const;
96 uint32_t calcNewValue(const WasmRelocation &Reloc) const;106 uint32_t calcNewValue(const WasmRelocation &reloc) const;
97 uint32_t calcNewAddend(const WasmRelocation &Reloc) const;107 uint32_t calcNewAddend(const WasmRelocation &reloc) const;
98 uint32_t calcExpectedValue(const WasmRelocation &Reloc) const;108 uint32_t calcExpectedValue(const WasmRelocation &reloc) const;
109 Symbol *getSymbol(const WasmRelocation &reloc) const {
110 return symbols[reloc.Index];
111 };
99112
100 const WasmSection *CodeSection = nullptr;113 const WasmSection *codeSection = nullptr;
101 const WasmSection *DataSection = nullptr;114 const WasmSection *dataSection = nullptr;
102115
103 // Maps input type indices to output type indices116 // Maps input type indices to output type indices
104 std::vector<uint32_t> TypeMap;117 std::vector<uint32_t> typeMap;
105 std::vector<bool> TypeIsUsed;118 std::vector<bool> typeIsUsed;
106 // Maps function indices to table indices119 // Maps function indices to table indices
107 std::vector<uint32_t> TableEntries;120 std::vector<uint32_t> tableEntries;
108 std::vector<bool> UsedComdats;121 std::vector<bool> keptComdats;
109 std::vector<InputSegment *> Segments;122 std::vector<InputSegment *> segments;
110 std::vector<InputFunction *> Functions;123 std::vector<InputFunction *> functions;
111 std::vector<InputGlobal *> Globals;124 std::vector<InputGlobal *> globals;
112 std::vector<InputEvent *> Events;125 std::vector<InputEvent *> events;
113 std::vector<InputSection *> CustomSections;126 std::vector<InputSection *> customSections;
114 llvm::DenseMap<uint32_t, InputSection *> CustomSectionsByIndex;127 llvm::DenseMap<uint32_t, InputSection *> customSectionsByIndex;
115128
116 Symbol *getSymbol(uint32_t Index) const { return Symbols[Index]; }129 Symbol *getSymbol(uint32_t index) const { return symbols[index]; }
117 FunctionSymbol *getFunctionSymbol(uint32_t Index) const;130 FunctionSymbol *getFunctionSymbol(uint32_t index) const;
118 DataSymbol *getDataSymbol(uint32_t Index) const;131 DataSymbol *getDataSymbol(uint32_t index) const;
119 GlobalSymbol *getGlobalSymbol(uint32_t Index) const;132 GlobalSymbol *getGlobalSymbol(uint32_t index) const;
120 SectionSymbol *getSectionSymbol(uint32_t Index) const;133 SectionSymbol *getSectionSymbol(uint32_t index) const;
121 EventSymbol *getEventSymbol(uint32_t Index) const;134 EventSymbol *getEventSymbol(uint32_t index) const;
122135
123private:136private:
124 Symbol *createDefined(const WasmSymbol &Sym);137 Symbol *createDefined(const WasmSymbol &sym);
125 Symbol *createUndefined(const WasmSymbol &Sym);138 Symbol *createUndefined(const WasmSymbol &sym, bool isCalledDirectly);
126139
127 bool isExcludedByComdat(InputChunk *Chunk) const;140 bool isExcludedByComdat(InputChunk *chunk) const;
128141
129 std::unique_ptr<WasmObjectFile> WasmObj;142 std::unique_ptr<WasmObjectFile> wasmObj;
130};143};
131144
132class BitcodeFile : public InputFile {145// .so file.
146class SharedFile : public InputFile {
133public:147public:
134 explicit BitcodeFile(MemoryBufferRef M) : InputFile(BitcodeKind, M) {}148 explicit SharedFile(MemoryBufferRef m) : InputFile(SharedKind, m) {}
135 static bool classof(const InputFile *F) { return F->kind() == BitcodeKind; }149 static bool classof(const InputFile *f) { return f->kind() == SharedKind; }
150};
136151
137 void parse() override;152// .bc file
138 std::unique_ptr<llvm::lto::InputFile> Obj;153class BitcodeFile : public InputFile {
154public:
155 explicit BitcodeFile(MemoryBufferRef m, StringRef archiveName)
156 : InputFile(BitcodeKind, m) {
157 this->archiveName = archiveName;
158 }
159 static bool classof(const InputFile *f) { return f->kind() == BitcodeKind; }
160
161 void parse();
162 std::unique_ptr<llvm::lto::InputFile> obj;
139};163};
140164
141// Will report a fatal() error if the input buffer is not a valid bitcode165// Will report a fatal() error if the input buffer is not a valid bitcode
142// or was object file.166// or wasm object file.
143InputFile *createObjectFile(MemoryBufferRef MB);167InputFile *createObjectFile(MemoryBufferRef mb, StringRef archiveName = "");
144168
145// Opens a given file.169// Opens a given file.
146llvm::Optional<MemoryBufferRef> readFile(StringRef Path);170llvm::Optional<MemoryBufferRef> readFile(StringRef path);
147171
148} // namespace wasm172} // namespace wasm
149173
150std::string toString(const wasm::InputFile *File);174std::string toString(const wasm::InputFile *file);
151175
152} // namespace lld176} // namespace lld
153177
deps/lld/wasm/InputGlobal.h+17-18
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- InputGlobal.h --------------------------------------------*- C++ -*-===//1//===- InputGlobal.h --------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -23,32 +22,32 @@ namespace wasm {...@@ -23,32 +22,32 @@ namespace wasm {
23// combined to form the final GLOBALS section.22// combined to form the final GLOBALS section.
24class InputGlobal {23class InputGlobal {
25public:24public:
26 InputGlobal(const WasmGlobal &G, ObjFile *F)25 InputGlobal(const WasmGlobal &g, ObjFile *f)
27 : File(F), Global(G), Live(!Config->GcSections) {}26 : file(f), global(g), live(!config->gcSections) {}
2827
29 StringRef getName() const { return Global.SymbolName; }28 StringRef getName() const { return global.SymbolName; }
30 const WasmGlobalType &getType() const { return Global.Type; }29 const WasmGlobalType &getType() const { return global.Type; }
3130
32 uint32_t getGlobalIndex() const { return GlobalIndex.getValue(); }31 uint32_t getGlobalIndex() const { return globalIndex.getValue(); }
33 bool hasGlobalIndex() const { return GlobalIndex.hasValue(); }32 bool hasGlobalIndex() const { return globalIndex.hasValue(); }
34 void setGlobalIndex(uint32_t Index) {33 void setGlobalIndex(uint32_t index) {
35 assert(!hasGlobalIndex());34 assert(!hasGlobalIndex());
36 GlobalIndex = Index;35 globalIndex = index;
37 }36 }
3837
39 ObjFile *File;38 ObjFile *file;
40 WasmGlobal Global;39 WasmGlobal global;
4140
42 bool Live = false;41 bool live = false;
4342
44protected:43protected:
45 llvm::Optional<uint32_t> GlobalIndex;44 llvm::Optional<uint32_t> globalIndex;
46};45};
4746
48} // namespace wasm47} // namespace wasm
4948
50inline std::string toString(const wasm::InputGlobal *G) {49inline std::string toString(const wasm::InputGlobal *g) {
51 return (toString(G->File) + ":(" + G->getName() + ")").str();50 return (toString(g->file) + ":(" + g->getName() + ")").str();
52}51}
5352
54} // namespace lld53} // namespace lld
deps/lld/wasm/LTO.cpp+82-79
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- LTO.cpp ------------------------------------------------------------===//1//===- LTO.cpp ------------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -11,6 +10,7 @@...@@ -11,6 +10,7 @@
11#include "Config.h"10#include "Config.h"
12#include "InputFiles.h"11#include "InputFiles.h"
13#include "Symbols.h"12#include "Symbols.h"
13#include "lld/Common/Args.h"
14#include "lld/Common/ErrorHandler.h"14#include "lld/Common/ErrorHandler.h"
15#include "lld/Common/Strings.h"15#include "lld/Common/Strings.h"
16#include "lld/Common/TargetOptionsCommandFlags.h"16#include "lld/Common/TargetOptionsCommandFlags.h"
...@@ -40,124 +40,127 @@ using namespace lld;...@@ -40,124 +40,127 @@ using namespace lld;
40using namespace lld::wasm;40using namespace lld::wasm;
4141
42static std::unique_ptr<lto::LTO> createLTO() {42static std::unique_ptr<lto::LTO> createLTO() {
43 lto::Config C;43 lto::Config c;
44 C.Options = InitTargetOptionsFromCodeGenFlags();44 c.Options = initTargetOptionsFromCodeGenFlags();
4545
46 // Always emit a section per function/data with LTO.46 // Always emit a section per function/data with LTO.
47 C.Options.FunctionSections = true;47 c.Options.FunctionSections = true;
48 C.Options.DataSections = true;48 c.Options.DataSections = true;
4949
50 // Wasm currently only supports ThreadModel::Single50 c.DisableVerify = config->disableVerify;
51 C.Options.ThreadModel = ThreadModel::Single;51 c.DiagHandler = diagnosticHandler;
5252 c.OptLevel = config->ltoo;
53 C.DisableVerify = Config->DisableVerify;53 c.MAttrs = getMAttrs();
54 C.DiagHandler = diagnosticHandler;54 c.CGOptLevel = args::getCGOptLevel(config->ltoo);
55 C.OptLevel = Config->LTOO;55
56 C.MAttrs = GetMAttrs();56 if (config->relocatable)
5757 c.RelocModel = None;
58 if (Config->Relocatable)58 else if (config->isPic)
59 C.RelocModel = None;59 c.RelocModel = Reloc::PIC_;
60 else if (Config->Pic)
61 C.RelocModel = Reloc::PIC_;
62 else60 else
63 C.RelocModel = Reloc::Static;61 c.RelocModel = Reloc::Static;
6462
65 if (Config->SaveTemps)63 if (config->saveTemps)
66 checkError(C.addSaveTemps(Config->OutputFile.str() + ".",64 checkError(c.addSaveTemps(config->outputFile.str() + ".",
67 /*UseInputModulePath*/ true));65 /*UseInputModulePath*/ true));
6866
69 lto::ThinBackend Backend;67 lto::ThinBackend backend;
70 if (Config->ThinLTOJobs != -1U)68 if (config->thinLTOJobs != -1U)
71 Backend = lto::createInProcessThinBackend(Config->ThinLTOJobs);69 backend = lto::createInProcessThinBackend(config->thinLTOJobs);
72 return llvm::make_unique<lto::LTO>(std::move(C), Backend,70 return llvm::make_unique<lto::LTO>(std::move(c), backend,
73 Config->LTOPartitions);71 config->ltoPartitions);
74}72}
7573
76BitcodeCompiler::BitcodeCompiler() : LTOObj(createLTO()) {}74BitcodeCompiler::BitcodeCompiler() : ltoObj(createLTO()) {}
7775
78BitcodeCompiler::~BitcodeCompiler() = default;76BitcodeCompiler::~BitcodeCompiler() = default;
7977
80static void undefine(Symbol *S) {78static void undefine(Symbol *s) {
81 if (auto F = dyn_cast<DefinedFunction>(S))79 if (auto f = dyn_cast<DefinedFunction>(s))
82 replaceSymbol<UndefinedFunction>(F, F->getName(), F->getName(),80 replaceSymbol<UndefinedFunction>(f, f->getName(), f->getName(),
83 DefaultModule, 0,81 defaultModule, 0,
84 F->getFile(), F->Signature);82 f->getFile(), f->signature);
85 else if (isa<DefinedData>(S))83 else if (isa<DefinedData>(s))
86 replaceSymbol<UndefinedData>(S, S->getName(), 0, S->getFile());84 replaceSymbol<UndefinedData>(s, s->getName(), 0, s->getFile());
87 else85 else
88 llvm_unreachable("unexpected symbol kind");86 llvm_unreachable("unexpected symbol kind");
89}87}
9088
91void BitcodeCompiler::add(BitcodeFile &F) {89void BitcodeCompiler::add(BitcodeFile &f) {
92 lto::InputFile &Obj = *F.Obj;90 lto::InputFile &obj = *f.obj;
93 unsigned SymNum = 0;91 unsigned symNum = 0;
94 ArrayRef<Symbol *> Syms = F.getSymbols();92 ArrayRef<Symbol *> syms = f.getSymbols();
95 std::vector<lto::SymbolResolution> Resols(Syms.size());93 std::vector<lto::SymbolResolution> resols(syms.size());
9694
97 // Provide a resolution to the LTO API for each symbol.95 // Provide a resolution to the LTO API for each symbol.
98 for (const lto::InputFile::Symbol &ObjSym : Obj.symbols()) {96 for (const lto::InputFile::Symbol &objSym : obj.symbols()) {
99 Symbol *Sym = Syms[SymNum];97 Symbol *sym = syms[symNum];
100 lto::SymbolResolution &R = Resols[SymNum];98 lto::SymbolResolution &r = resols[symNum];
101 ++SymNum;99 ++symNum;
102100
103 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile101 // Ideally we shouldn't check for SF_Undefined but currently IRObjectFile
104 // reports two symbols for module ASM defined. Without this check, lld102 // reports two symbols for module ASM defined. Without this check, lld
105 // flags an undefined in IR with a definition in ASM as prevailing.103 // flags an undefined in IR with a definition in ASM as prevailing.
106 // Once IRObjectFile is fixed to report only one symbol this hack can104 // Once IRObjectFile is fixed to report only one symbol this hack can
107 // be removed.105 // be removed.
108 R.Prevailing = !ObjSym.isUndefined() && Sym->getFile() == &F;106 r.Prevailing = !objSym.isUndefined() && sym->getFile() == &f;
109 R.VisibleToRegularObj = Config->Relocatable || Sym->IsUsedInRegularObj ||107 r.VisibleToRegularObj = config->relocatable || sym->isUsedInRegularObj ||
110 (R.Prevailing && Sym->isExported());108 (r.Prevailing && sym->isExported());
111 if (R.Prevailing)109 if (r.Prevailing)
112 undefine(Sym);110 undefine(sym);
111
112 // We tell LTO to not apply interprocedural optimization for wrapped
113 // (with --wrap) symbols because otherwise LTO would inline them while
114 // their values are still not final.
115 r.LinkerRedefined = !sym->canInline;
113 }116 }
114 checkError(LTOObj->add(std::move(F.Obj), Resols));117 checkError(ltoObj->add(std::move(f.obj), resols));
115}118}
116119
117// Merge all the bitcode files we have seen, codegen the result120// Merge all the bitcode files we have seen, codegen the result
118// and return the resulting objects.121// and return the resulting objects.
119std::vector<StringRef> BitcodeCompiler::compile() {122std::vector<StringRef> BitcodeCompiler::compile() {
120 unsigned MaxTasks = LTOObj->getMaxTasks();123 unsigned maxTasks = ltoObj->getMaxTasks();
121 Buf.resize(MaxTasks);124 buf.resize(maxTasks);
122 Files.resize(MaxTasks);125 files.resize(maxTasks);
123126
124 // The --thinlto-cache-dir option specifies the path to a directory in which127 // The --thinlto-cache-dir option specifies the path to a directory in which
125 // to cache native object files for ThinLTO incremental builds. If a path was128 // to cache native object files for ThinLTO incremental builds. If a path was
126 // specified, configure LTO to use it as the cache directory.129 // specified, configure LTO to use it as the cache directory.
127 lto::NativeObjectCache Cache;130 lto::NativeObjectCache cache;
128 if (!Config->ThinLTOCacheDir.empty())131 if (!config->thinLTOCacheDir.empty())
129 Cache = check(132 cache = check(
130 lto::localCache(Config->ThinLTOCacheDir,133 lto::localCache(config->thinLTOCacheDir,
131 [&](size_t Task, std::unique_ptr<MemoryBuffer> MB) {134 [&](size_t task, std::unique_ptr<MemoryBuffer> mb) {
132 Files[Task] = std::move(MB);135 files[task] = std::move(mb);
133 }));136 }));
134137
135 checkError(LTOObj->run(138 checkError(ltoObj->run(
136 [&](size_t Task) {139 [&](size_t task) {
137 return llvm::make_unique<lto::NativeObjectStream>(140 return llvm::make_unique<lto::NativeObjectStream>(
138 llvm::make_unique<raw_svector_ostream>(Buf[Task]));141 llvm::make_unique<raw_svector_ostream>(buf[task]));
139 },142 },
140 Cache));143 cache));
141144
142 if (!Config->ThinLTOCacheDir.empty())145 if (!config->thinLTOCacheDir.empty())
143 pruneCache(Config->ThinLTOCacheDir, Config->ThinLTOCachePolicy);146 pruneCache(config->thinLTOCacheDir, config->thinLTOCachePolicy);
144147
145 std::vector<StringRef> Ret;148 std::vector<StringRef> ret;
146 for (unsigned I = 0; I != MaxTasks; ++I) {149 for (unsigned i = 0; i != maxTasks; ++i) {
147 if (Buf[I].empty())150 if (buf[i].empty())
148 continue;151 continue;
149 if (Config->SaveTemps) {152 if (config->saveTemps) {
150 if (I == 0)153 if (i == 0)
151 saveBuffer(Buf[I], Config->OutputFile + ".lto.o");154 saveBuffer(buf[i], config->outputFile + ".lto.o");
152 else155 else
153 saveBuffer(Buf[I], Config->OutputFile + Twine(I) + ".lto.o");156 saveBuffer(buf[i], config->outputFile + Twine(i) + ".lto.o");
154 }157 }
155 Ret.emplace_back(Buf[I].data(), Buf[I].size());158 ret.emplace_back(buf[i].data(), buf[i].size());
156 }159 }
157160
158 for (std::unique_ptr<MemoryBuffer> &File : Files)161 for (std::unique_ptr<MemoryBuffer> &file : files)
159 if (File)162 if (file)
160 Ret.push_back(File->getBuffer());163 ret.push_back(file->getBuffer());
161164
162 return Ret;165 return ret;
163}166}
deps/lld/wasm/LTO.h+7-8
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- LTO.h ----------------------------------------------------*- C++ -*-===//1//===- LTO.h ----------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -44,13 +43,13 @@ public:...@@ -44,13 +43,13 @@ public:
44 BitcodeCompiler();43 BitcodeCompiler();
45 ~BitcodeCompiler();44 ~BitcodeCompiler();
4645
47 void add(BitcodeFile &F);46 void add(BitcodeFile &f);
48 std::vector<StringRef> compile();47 std::vector<StringRef> compile();
4948
50private:49private:
51 std::unique_ptr<llvm::lto::LTO> LTOObj;50 std::unique_ptr<llvm::lto::LTO> ltoObj;
52 std::vector<SmallString<0>> Buf;51 std::vector<SmallString<0>> buf;
53 std::vector<std::unique_ptr<MemoryBuffer>> Files;52 std::vector<std::unique_ptr<MemoryBuffer>> files;
54};53};
55} // namespace wasm54} // namespace wasm
56} // namespace lld55} // namespace lld
deps/lld/wasm/MarkLive.cpp+75-56
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MarkLive.cpp -------------------------------------------------------===//1//===- MarkLive.cpp -------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
9//8//
...@@ -33,48 +32,68 @@ using namespace llvm;...@@ -33,48 +32,68 @@ using namespace llvm;
33using namespace llvm::wasm;32using namespace llvm::wasm;
3433
35void lld::wasm::markLive() {34void lld::wasm::markLive() {
36 if (!Config->GcSections)35 if (!config->gcSections)
37 return;36 return;
3837
39 LLVM_DEBUG(dbgs() << "markLive\n");38 LLVM_DEBUG(dbgs() << "markLive\n");
40 SmallVector<InputChunk *, 256> Q;39 SmallVector<InputChunk *, 256> q;
4140
42 auto Enqueue = [&](Symbol *Sym) {41 std::function<void(Symbol*)> enqueue = [&](Symbol *sym) {
43 if (!Sym || Sym->isLive())42 if (!sym || sym->isLive())
44 return;43 return;
45 LLVM_DEBUG(dbgs() << "markLive: " << Sym->getName() << "\n");44 LLVM_DEBUG(dbgs() << "markLive: " << sym->getName() << "\n");
46 Sym->markLive();45 sym->markLive();
47 if (InputChunk *Chunk = Sym->getChunk())46 if (InputChunk *chunk = sym->getChunk())
48 Q.push_back(Chunk);47 q.push_back(chunk);
48
49 // The ctor functions are all referenced by the synthetic callCtors
50 // function. However, this function does not contain relocations so we
51 // have to manually mark the ctors as live if callCtors itself is live.
52 if (sym == WasmSym::callCtors) {
53 if (config->passiveSegments)
54 enqueue(WasmSym::initMemory);
55 if (config->isPic)
56 enqueue(WasmSym::applyRelocs);
57 for (const ObjFile *obj : symtab->objectFiles) {
58 const WasmLinkingData &l = obj->getWasmObj()->linkingData();
59 for (const WasmInitFunc &f : l.InitFunctions) {
60 auto* initSym = obj->getFunctionSymbol(f.Symbol);
61 if (!initSym->isDiscarded())
62 enqueue(initSym);
63 }
64 }
65 }
49 };66 };
5067
51 // Add GC root symbols.68 // Add GC root symbols.
52 if (!Config->Entry.empty())69 if (!config->entry.empty())
53 Enqueue(Symtab->find(Config->Entry));70 enqueue(symtab->find(config->entry));
54 Enqueue(WasmSym::CallCtors);
5571
56 // We need to preserve any exported symbol72 // We need to preserve any exported symbol
57 for (Symbol *Sym : Symtab->getSymbols())73 for (Symbol *sym : symtab->getSymbols())
58 if (Sym->isExported())74 if (sym->isExported())
59 Enqueue(Sym);75 enqueue(sym);
6076
61 // The ctor functions are all used in the synthetic __wasm_call_ctors77 // For relocatable output, we need to preserve all the ctor functions
62 // function, but since this function is created in-place it doesn't contain78 if (config->relocatable) {
63 // relocations which mean we have to manually mark the ctors.79 for (const ObjFile *obj : symtab->objectFiles) {
64 for (const ObjFile *Obj : Symtab->ObjectFiles) {80 const WasmLinkingData &l = obj->getWasmObj()->linkingData();
65 const WasmLinkingData &L = Obj->getWasmObj()->linkingData();81 for (const WasmInitFunc &f : l.InitFunctions)
66 for (const WasmInitFunc &F : L.InitFunctions)82 enqueue(obj->getFunctionSymbol(f.Symbol));
67 Enqueue(Obj->getFunctionSymbol(F.Symbol));83 }
68 }84 }
6985
86 if (config->isPic)
87 enqueue(WasmSym::callCtors);
88
70 // Follow relocations to mark all reachable chunks.89 // Follow relocations to mark all reachable chunks.
71 while (!Q.empty()) {90 while (!q.empty()) {
72 InputChunk *C = Q.pop_back_val();91 InputChunk *c = q.pop_back_val();
7392
74 for (const WasmRelocation Reloc : C->getRelocations()) {93 for (const WasmRelocation reloc : c->getRelocations()) {
75 if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB)94 if (reloc.Type == R_WASM_TYPE_INDEX_LEB)
76 continue;95 continue;
77 Symbol *Sym = C->File->getSymbol(Reloc.Index);96 Symbol *sym = c->file->getSymbol(reloc.Index);
7897
79 // If the function has been assigned the special index zero in the table,98 // If the function has been assigned the special index zero in the table,
80 // the relocation doesn't pull in the function body, since the function99 // the relocation doesn't pull in the function body, since the function
...@@ -83,38 +102,38 @@ void lld::wasm::markLive() {...@@ -83,38 +102,38 @@ void lld::wasm::markLive() {
83 // zero is only reachable via "call", not via "call_indirect". The stub102 // zero is only reachable via "call", not via "call_indirect". The stub
84 // functions used for weak-undefined symbols have this behaviour (compare103 // functions used for weak-undefined symbols have this behaviour (compare
85 // equal to null pointer, only reachable via direct call).104 // equal to null pointer, only reachable via direct call).
86 if (Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_SLEB ||105 if (reloc.Type == R_WASM_TABLE_INDEX_SLEB ||
87 Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_I32) {106 reloc.Type == R_WASM_TABLE_INDEX_I32) {
88 auto *FuncSym = cast<FunctionSymbol>(Sym);107 auto *funcSym = cast<FunctionSymbol>(sym);
89 if (FuncSym->hasTableIndex() && FuncSym->getTableIndex() == 0)108 if (funcSym->hasTableIndex() && funcSym->getTableIndex() == 0)
90 continue;109 continue;
91 }110 }
92111
93 Enqueue(Sym);112 enqueue(sym);
94 }113 }
95 }114 }
96115
97 // Report garbage-collected sections.116 // Report garbage-collected sections.
98 if (Config->PrintGcSections) {117 if (config->printGcSections) {
99 for (const ObjFile *Obj : Symtab->ObjectFiles) {118 for (const ObjFile *obj : symtab->objectFiles) {
100 for (InputChunk *C : Obj->Functions)119 for (InputChunk *c : obj->functions)
101 if (!C->Live)120 if (!c->live)
102 message("removing unused section " + toString(C));121 message("removing unused section " + toString(c));
103 for (InputChunk *C : Obj->Segments)122 for (InputChunk *c : obj->segments)
104 if (!C->Live)123 if (!c->live)
105 message("removing unused section " + toString(C));124 message("removing unused section " + toString(c));
106 for (InputGlobal *G : Obj->Globals)125 for (InputGlobal *g : obj->globals)
107 if (!G->Live)126 if (!g->live)
108 message("removing unused section " + toString(G));127 message("removing unused section " + toString(g));
109 for (InputEvent *E : Obj->Events)128 for (InputEvent *e : obj->events)
110 if (!E->Live)129 if (!e->live)
111 message("removing unused section " + toString(E));130 message("removing unused section " + toString(e));
112 }131 }
113 for (InputChunk *C : Symtab->SyntheticFunctions)132 for (InputChunk *c : symtab->syntheticFunctions)
114 if (!C->Live)133 if (!c->live)
115 message("removing unused section " + toString(C));134 message("removing unused section " + toString(c));
116 for (InputGlobal *G : Symtab->SyntheticGlobals)135 for (InputGlobal *g : symtab->syntheticGlobals)
117 if (!G->Live)136 if (!g->live)
118 message("removing unused section " + toString(G));137 message("removing unused section " + toString(g));
119 }138 }
120}139}
deps/lld/wasm/MarkLive.h+3-4
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- MarkLive.h -----------------------------------------------*- C++ -*-===//1//===- MarkLive.h -----------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
deps/lld/wasm/Options.td+26
...@@ -31,6 +31,8 @@ defm demangle: B<"demangle",...@@ -31,6 +31,8 @@ defm demangle: B<"demangle",
31 "Demangle symbol names",31 "Demangle symbol names",
32 "Do not demangle symbol names">;32 "Do not demangle symbol names">;
3333
34def emit_relocs: F<"emit-relocs">, HelpText<"Generate relocations in output">;
35
34defm export_dynamic: B<"export-dynamic",36defm export_dynamic: B<"export-dynamic",
35 "Put symbols in the dynamic symbol table",37 "Put symbols in the dynamic symbol table",
36 "Do not put symbols in the dynamic symbol table (default)">;38 "Do not put symbols in the dynamic symbol table (default)">;
...@@ -85,6 +87,8 @@ defm print_gc_sections: B<"print-gc-sections",...@@ -85,6 +87,8 @@ defm print_gc_sections: B<"print-gc-sections",
8587
86def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">;88def relocatable: F<"relocatable">, HelpText<"Create relocatable object file">;
8789
90defm reproduce: Eq<"reproduce", "Dump linker invocation and input files for debugging">;
91
88def shared: F<"shared">, HelpText<"Build a shared object">;92def shared: F<"shared">, HelpText<"Build a shared object">;
8993
90def strip_all: F<"strip-all">, HelpText<"Strip all symbols">;94def strip_all: F<"strip-all">, HelpText<"Strip all symbols">;
...@@ -93,6 +97,10 @@ def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">;...@@ -93,6 +97,10 @@ def strip_debug: F<"strip-debug">, HelpText<"Strip debugging information">;
9397
94def threads: F<"threads">, HelpText<"Run the linker multi-threaded">;98def threads: F<"threads">, HelpText<"Run the linker multi-threaded">;
9599
100def trace: F<"trace">, HelpText<"Print the names of the input files">;
101
102defm trace_symbol: Eq<"trace-symbol", "Trace references to symbols">;
103
96defm undefined: Eq<"undefined", "Force undefined symbol during linking">;104defm undefined: Eq<"undefined", "Force undefined symbol during linking">;
97105
98def v: Flag<["-"], "v">, HelpText<"Display the version number">;106def v: Flag<["-"], "v">, HelpText<"Display the version number">;
...@@ -104,6 +112,9 @@ def version: F<"version">, HelpText<"Display the version number and exit">;...@@ -104,6 +112,9 @@ def version: F<"version">, HelpText<"Display the version number and exit">;
104def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,112def z: JoinedOrSeparate<["-"], "z">, MetaVarName<"<option>">,
105 HelpText<"Linker option extensions">;113 HelpText<"Linker option extensions">;
106114
115defm wrap: Eq<"wrap", "Use wrapper functions for symbol">,
116 MetaVarName<"<symbol>=<symbol>">;
117
107// The follow flags are unique to wasm118// The follow flags are unique to wasm
108119
109def allow_undefined: F<"allow-undefined">,120def allow_undefined: F<"allow-undefined">,
...@@ -132,6 +143,12 @@ def import_memory: F<"import-memory">,...@@ -132,6 +143,12 @@ def import_memory: F<"import-memory">,
132def shared_memory: F<"shared-memory">,143def shared_memory: F<"shared-memory">,
133 HelpText<"Use shared linear memory">;144 HelpText<"Use shared linear memory">;
134145
146def active_segments: F<"active-segments">,
147 HelpText<"Force segments to be active (default with unshared memory)">;
148
149def passive_segments: F<"passive-segments">,
150 HelpText<"Force segments to be passive (default with shared memory)">;
151
135def import_table: F<"import-table">,152def import_table: F<"import-table">,
136 HelpText<"Import function table from the environment">;153 HelpText<"Import function table from the environment">;
137154
...@@ -151,6 +168,13 @@ defm whole_archive: B<"whole-archive",...@@ -151,6 +168,13 @@ defm whole_archive: B<"whole-archive",
151 "Force load of all members in a static library",168 "Force load of all members in a static library",
152 "Do not force load of all members in a static library (default)">;169 "Do not force load of all members in a static library (default)">;
153170
171defm check_features: B<"check-features",
172 "Check feature compatibility of linked objects (default)",
173 "Ignore feature compatibility of linked objects">;
174
175def features: CommaJoined<["--", "-"], "features=">,
176 HelpText<"Comma-separated used features, inferred from input objects by default.">;
177
154// Aliases178// Aliases
155def: JoinedOrSeparate<["-"], "e">, Alias<entry>;179def: JoinedOrSeparate<["-"], "e">, Alias<entry>;
156def: J<"entry=">, Alias<entry>;180def: J<"entry=">, Alias<entry>;
...@@ -160,6 +184,8 @@ def: Flag<["-"], "m">, Alias<max_memory>;...@@ -160,6 +184,8 @@ def: Flag<["-"], "m">, Alias<max_memory>;
160def: Flag<["-"], "r">, Alias<relocatable>;184def: Flag<["-"], "r">, Alias<relocatable>;
161def: Flag<["-"], "s">, Alias<strip_all>, HelpText<"Alias for --strip-all">;185def: Flag<["-"], "s">, Alias<strip_all>, HelpText<"Alias for --strip-all">;
162def: Flag<["-"], "S">, Alias<strip_debug>, HelpText<"Alias for --strip-debug">;186def: Flag<["-"], "S">, Alias<strip_debug>, HelpText<"Alias for --strip-debug">;
187def: Flag<["-"], "t">, Alias<trace>, HelpText<"Alias for --trace">;
188def: JoinedOrSeparate<["-"], "y">, Alias<trace_symbol>, HelpText<"Alias for --trace-symbol">;
163def: JoinedOrSeparate<["-"], "u">, Alias<undefined>;189def: JoinedOrSeparate<["-"], "u">, Alias<undefined>;
164190
165// LTO-related options.191// LTO-related options.
deps/lld/wasm/OutputSections.cpp+136-135
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- OutputSections.cpp -------------------------------------------------===//1//===- OutputSections.cpp -------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -24,8 +23,8 @@ using namespace llvm::wasm;...@@ -24,8 +23,8 @@ using namespace llvm::wasm;
24using namespace lld;23using namespace lld;
25using namespace lld::wasm;24using namespace lld::wasm;
2625
27static StringRef sectionTypeToString(uint32_t SectionType) {26static StringRef sectionTypeToString(uint32_t sectionType) {
28 switch (SectionType) {27 switch (sectionType) {
29 case WASM_SEC_CUSTOM:28 case WASM_SEC_CUSTOM:
30 return "CUSTOM";29 return "CUSTOM";
31 case WASM_SEC_TYPE:30 case WASM_SEC_TYPE:
...@@ -52,198 +51,200 @@ static StringRef sectionTypeToString(uint32_t SectionType) {...@@ -52,198 +51,200 @@ static StringRef sectionTypeToString(uint32_t SectionType) {
52 return "CODE";51 return "CODE";
53 case WASM_SEC_DATA:52 case WASM_SEC_DATA:
54 return "DATA";53 return "DATA";
54 case WASM_SEC_DATACOUNT:
55 return "DATACOUNT";
55 default:56 default:
56 fatal("invalid section type");57 fatal("invalid section type");
57 }58 }
58}59}
5960
60// Returns a string, e.g. "FUNCTION(.text)".61// Returns a string, e.g. "FUNCTION(.text)".
61std::string lld::toString(const OutputSection &Sec) {62std::string lld::toString(const OutputSection &sec) {
62 if (!Sec.Name.empty())63 if (!sec.name.empty())
63 return (Sec.getSectionName() + "(" + Sec.Name + ")").str();64 return (sec.getSectionName() + "(" + sec.name + ")").str();
64 return Sec.getSectionName();65 return sec.getSectionName();
65}66}
6667
67StringRef OutputSection::getSectionName() const {68StringRef OutputSection::getSectionName() const {
68 return sectionTypeToString(Type);69 return sectionTypeToString(type);
69}70}
7071
71void OutputSection::createHeader(size_t BodySize) {72void OutputSection::createHeader(size_t bodySize) {
72 raw_string_ostream OS(Header);73 raw_string_ostream os(header);
73 debugWrite(OS.tell(), "section type [" + getSectionName() + "]");74 debugWrite(os.tell(), "section type [" + getSectionName() + "]");
74 encodeULEB128(Type, OS);75 encodeULEB128(type, os);
75 writeUleb128(OS, BodySize, "section size");76 writeUleb128(os, bodySize, "section size");
76 OS.flush();77 os.flush();
77 log("createHeader: " + toString(*this) + " body=" + Twine(BodySize) +78 log("createHeader: " + toString(*this) + " body=" + Twine(bodySize) +
78 " total=" + Twine(getSize()));79 " total=" + Twine(getSize()));
79}80}
8081
81CodeSection::CodeSection(ArrayRef<InputFunction *> Functions)82void CodeSection::finalizeContents() {
82 : OutputSection(WASM_SEC_CODE), Functions(Functions) {83 raw_string_ostream os(codeSectionHeader);
83 assert(Functions.size() > 0);84 writeUleb128(os, functions.size(), "function count");
8485 os.flush();
85 raw_string_ostream OS(CodeSectionHeader);86 bodySize = codeSectionHeader.size();
86 writeUleb128(OS, Functions.size(), "function count");
87 OS.flush();
88 BodySize = CodeSectionHeader.size();
8987
90 for (InputFunction *Func : Functions) {88 for (InputFunction *func : functions) {
91 Func->OutputOffset = BodySize;89 func->outputOffset = bodySize;
92 Func->calculateSize();90 func->calculateSize();
93 BodySize += Func->getSize();91 bodySize += func->getSize();
94 }92 }
9593
96 createHeader(BodySize);94 createHeader(bodySize);
97}95}
9896
99void CodeSection::writeTo(uint8_t *Buf) {97void CodeSection::writeTo(uint8_t *buf) {
100 log("writing " + toString(*this));98 log("writing " + toString(*this));
101 log(" size=" + Twine(getSize()));99 log(" size=" + Twine(getSize()));
102 log(" headersize=" + Twine(Header.size()));100 log(" headersize=" + Twine(header.size()));
103 log(" codeheadersize=" + Twine(CodeSectionHeader.size()));101 log(" codeheadersize=" + Twine(codeSectionHeader.size()));
104 Buf += Offset;102 buf += offset;
105103
106 // Write section header104 // Write section header
107 memcpy(Buf, Header.data(), Header.size());105 memcpy(buf, header.data(), header.size());
108 Buf += Header.size();106 buf += header.size();
109107
110 // Write code section headers108 // Write code section headers
111 memcpy(Buf, CodeSectionHeader.data(), CodeSectionHeader.size());109 memcpy(buf, codeSectionHeader.data(), codeSectionHeader.size());
112110
113 // Write code section bodies111 // Write code section bodies
114 for (const InputChunk *Chunk : Functions)112 for (const InputChunk *chunk : functions)
115 Chunk->writeTo(Buf);113 chunk->writeTo(buf);
116}114}
117115
118uint32_t CodeSection::numRelocations() const {116uint32_t CodeSection::getNumRelocations() const {
119 uint32_t Count = 0;117 uint32_t count = 0;
120 for (const InputChunk *Func : Functions)118 for (const InputChunk *func : functions)
121 Count += Func->NumRelocations();119 count += func->getNumRelocations();
122 return Count;120 return count;
123}121}
124122
125void CodeSection::writeRelocations(raw_ostream &OS) const {123void CodeSection::writeRelocations(raw_ostream &os) const {
126 for (const InputChunk *C : Functions)124 for (const InputChunk *c : functions)
127 C->writeRelocations(OS);125 c->writeRelocations(os);
128}126}
129127
130DataSection::DataSection(ArrayRef<OutputSegment *> Segments)128void DataSection::finalizeContents() {
131 : OutputSection(WASM_SEC_DATA), Segments(Segments) {129 raw_string_ostream os(dataSectionHeader);
132 raw_string_ostream OS(DataSectionHeader);130
133131 writeUleb128(os, segments.size(), "data segment count");
134 writeUleb128(OS, Segments.size(), "data segment count");132 os.flush();
135 OS.flush();133 bodySize = dataSectionHeader.size();
136 BodySize = DataSectionHeader.size();134
137135 assert((!config->isPic || segments.size() <= 1) &&
138 for (OutputSegment *Segment : Segments) {136 "Currenly only a single data segment is supported in PIC mode");
139 raw_string_ostream OS(Segment->Header);137
140 writeUleb128(OS, 0, "memory index");138 for (OutputSegment *segment : segments) {
141 WasmInitExpr InitExpr;139 raw_string_ostream os(segment->header);
142 if (Config->Pic) {140 writeUleb128(os, segment->initFlags, "init flags");
143 assert(Segments.size() <= 1 &&141 if (segment->initFlags & WASM_SEGMENT_HAS_MEMINDEX)
144 "Currenly only a single data segment is supported in PIC mode");142 writeUleb128(os, 0, "memory index");
145 InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET;143 if ((segment->initFlags & WASM_SEGMENT_IS_PASSIVE) == 0) {
146 InitExpr.Value.Global = WasmSym::MemoryBase->getGlobalIndex();144 WasmInitExpr initExpr;
147 } else {145 if (config->isPic) {
148 InitExpr.Opcode = WASM_OPCODE_I32_CONST;146 initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
149 InitExpr.Value.Int32 = Segment->StartVA;147 initExpr.Value.Global = WasmSym::memoryBase->getGlobalIndex();
148 } else {
149 initExpr.Opcode = WASM_OPCODE_I32_CONST;
150 initExpr.Value.Int32 = segment->startVA;
151 }
152 writeInitExpr(os, initExpr);
150 }153 }
151 writeInitExpr(OS, InitExpr);154 writeUleb128(os, segment->size, "segment size");
152 writeUleb128(OS, Segment->Size, "segment size");155 os.flush();
153 OS.flush();
154156
155 Segment->SectionOffset = BodySize;157 segment->sectionOffset = bodySize;
156 BodySize += Segment->Header.size() + Segment->Size;158 bodySize += segment->header.size() + segment->size;
157 log("Data segment: size=" + Twine(Segment->Size));159 log("Data segment: size=" + Twine(segment->size) + ", startVA=" +
160 Twine::utohexstr(segment->startVA) + ", name=" + segment->name);
158161
159 for (InputSegment *InputSeg : Segment->InputSegments)162 for (InputSegment *inputSeg : segment->inputSegments)
160 InputSeg->OutputOffset = Segment->SectionOffset + Segment->Header.size() +163 inputSeg->outputOffset = segment->sectionOffset + segment->header.size() +
161 InputSeg->OutputSegmentOffset;164 inputSeg->outputSegmentOffset;
162 }165 }
163166
164 createHeader(BodySize);167 createHeader(bodySize);
165}168}
166169
167void DataSection::writeTo(uint8_t *Buf) {170void DataSection::writeTo(uint8_t *buf) {
168 log("writing " + toString(*this) + " size=" + Twine(getSize()) +171 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
169 " body=" + Twine(BodySize));172 " body=" + Twine(bodySize));
170 Buf += Offset;173 buf += offset;
171174
172 // Write section header175 // Write section header
173 memcpy(Buf, Header.data(), Header.size());176 memcpy(buf, header.data(), header.size());
174 Buf += Header.size();177 buf += header.size();
175178
176 // Write data section headers179 // Write data section headers
177 memcpy(Buf, DataSectionHeader.data(), DataSectionHeader.size());180 memcpy(buf, dataSectionHeader.data(), dataSectionHeader.size());
178181
179 for (const OutputSegment *Segment : Segments) {182 for (const OutputSegment *segment : segments) {
180 // Write data segment header183 // Write data segment header
181 uint8_t *SegStart = Buf + Segment->SectionOffset;184 uint8_t *segStart = buf + segment->sectionOffset;
182 memcpy(SegStart, Segment->Header.data(), Segment->Header.size());185 memcpy(segStart, segment->header.data(), segment->header.size());
183186
184 // Write segment data payload187 // Write segment data payload
185 for (const InputChunk *Chunk : Segment->InputSegments)188 for (const InputChunk *chunk : segment->inputSegments)
186 Chunk->writeTo(Buf);189 chunk->writeTo(buf);
187 }190 }
188}191}
189192
190uint32_t DataSection::numRelocations() const {193uint32_t DataSection::getNumRelocations() const {
191 uint32_t Count = 0;194 uint32_t count = 0;
192 for (const OutputSegment *Seg : Segments)195 for (const OutputSegment *seg : segments)
193 for (const InputChunk *InputSeg : Seg->InputSegments)196 for (const InputChunk *inputSeg : seg->inputSegments)
194 Count += InputSeg->NumRelocations();197 count += inputSeg->getNumRelocations();
195 return Count;198 return count;
196}199}
197200
198void DataSection::writeRelocations(raw_ostream &OS) const {201void DataSection::writeRelocations(raw_ostream &os) const {
199 for (const OutputSegment *Seg : Segments)202 for (const OutputSegment *seg : segments)
200 for (const InputChunk *C : Seg->InputSegments)203 for (const InputChunk *c : seg->inputSegments)
201 C->writeRelocations(OS);204 c->writeRelocations(os);
202}205}
203206
204CustomSection::CustomSection(std::string Name,207void CustomSection::finalizeContents() {
205 ArrayRef<InputSection *> InputSections)208 raw_string_ostream os(nameData);
206 : OutputSection(WASM_SEC_CUSTOM, Name), PayloadSize(0),209 encodeULEB128(name.size(), os);
207 InputSections(InputSections) {210 os << name;
208 raw_string_ostream OS(NameData);211 os.flush();
209 encodeULEB128(Name.size(), OS);
210 OS << Name;
211 OS.flush();
212212
213 for (InputSection *Section : InputSections) {213 for (InputSection *section : inputSections) {
214 Section->OutputOffset = PayloadSize;214 section->outputOffset = payloadSize;
215 PayloadSize += Section->getSize();215 section->outputSec = this;
216 payloadSize += section->getSize();
216 }217 }
217218
218 createHeader(PayloadSize + NameData.size());219 createHeader(payloadSize + nameData.size());
219}220}
220221
221void CustomSection::writeTo(uint8_t *Buf) {222void CustomSection::writeTo(uint8_t *buf) {
222 log("writing " + toString(*this) + " size=" + Twine(getSize()) +223 log("writing " + toString(*this) + " size=" + Twine(getSize()) +
223 " chunks=" + Twine(InputSections.size()));224 " chunks=" + Twine(inputSections.size()));
224225
225 assert(Offset);226 assert(offset);
226 Buf += Offset;227 buf += offset;
227228
228 // Write section header229 // Write section header
229 memcpy(Buf, Header.data(), Header.size());230 memcpy(buf, header.data(), header.size());
230 Buf += Header.size();231 buf += header.size();
231 memcpy(Buf, NameData.data(), NameData.size());232 memcpy(buf, nameData.data(), nameData.size());
232 Buf += NameData.size();233 buf += nameData.size();
233234
234 // Write custom sections payload235 // Write custom sections payload
235 for (const InputSection *Section : InputSections)236 for (const InputSection *section : inputSections)
236 Section->writeTo(Buf);237 section->writeTo(buf);
237}238}
238239
239uint32_t CustomSection::numRelocations() const {240uint32_t CustomSection::getNumRelocations() const {
240 uint32_t Count = 0;241 uint32_t count = 0;
241 for (const InputSection *InputSect : InputSections)242 for (const InputSection *inputSect : inputSections)
242 Count += InputSect->NumRelocations();243 count += inputSect->getNumRelocations();
243 return Count;244 return count;
244}245}
245246
246void CustomSection::writeRelocations(raw_ostream &OS) const {247void CustomSection::writeRelocations(raw_ostream &os) const {
247 for (const InputSection *S : InputSections)248 for (const InputSection *s : inputSections)
248 S->writeRelocations(OS);249 s->writeRelocations(os);
249}250}
deps/lld/wasm/OutputSections.h+56-73
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- OutputSections.h -----------------------------------------*- C++ -*-===//1//===- OutputSections.h -----------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -21,7 +20,7 @@ namespace lld {...@@ -21,7 +20,7 @@ namespace lld {
21namespace wasm {20namespace wasm {
22class OutputSection;21class OutputSection;
23}22}
24std::string toString(const wasm::OutputSection &Section);23std::string toString(const wasm::OutputSection &section);
2524
26namespace wasm {25namespace wasm {
2726
...@@ -29,86 +28,67 @@ class OutputSegment;...@@ -29,86 +28,67 @@ class OutputSegment;
2928
30class OutputSection {29class OutputSection {
31public:30public:
32 OutputSection(uint32_t Type, std::string Name = "")31 OutputSection(uint32_t type, std::string name = "")
33 : Type(Type), Name(Name) {}32 : type(type), name(name) {}
34 virtual ~OutputSection() = default;33 virtual ~OutputSection() = default;
3534
36 StringRef getSectionName() const;35 StringRef getSectionName() const;
37 void setOffset(size_t NewOffset) {36 void setOffset(size_t newOffset) {
38 log("setOffset: " + toString(*this) + ": " + Twine(NewOffset));37 log("setOffset: " + toString(*this) + ": " + Twine(newOffset));
39 Offset = NewOffset;38 offset = newOffset;
40 }39 }
41 void createHeader(size_t BodySize);40 void createHeader(size_t bodySize);
41 virtual bool isNeeded() const { return true; }
42 virtual size_t getSize() const = 0;42 virtual size_t getSize() const = 0;
43 virtual void writeTo(uint8_t *Buf) = 0;43 virtual void writeTo(uint8_t *buf) = 0;
44 virtual void finalizeContents() {}44 virtual void finalizeContents() = 0;
45 virtual uint32_t numRelocations() const { return 0; }45 virtual uint32_t getNumRelocations() const { return 0; }
46 virtual void writeRelocations(raw_ostream &OS) const {}46 virtual void writeRelocations(raw_ostream &os) const {}
47
48 std::string Header;
49 uint32_t Type;
50 std::string Name;
51
52protected:
53 size_t Offset = 0;
54};
55
56class SyntheticSection : public OutputSection {
57public:
58 SyntheticSection(uint32_t Type, std::string Name = "")
59 : OutputSection(Type, Name), BodyOutputStream(Body) {
60 if (!Name.empty())
61 writeStr(BodyOutputStream, Name, "section name");
62 }
6347
64 void writeTo(uint8_t *Buf) override {48 std::string header;
65 assert(Offset);49 uint32_t type;
66 log("writing " + toString(*this));50 uint32_t sectionIndex = UINT32_MAX;
67 memcpy(Buf + Offset, Header.data(), Header.size());51 std::string name;
68 memcpy(Buf + Offset + Header.size(), Body.data(), Body.size());52 OutputSectionSymbol *sectionSym = nullptr;
69 }
70
71 size_t getSize() const override { return Header.size() + Body.size(); }
72
73 void finalizeContents() override {
74 BodyOutputStream.flush();
75 createHeader(Body.size());
76 }
77
78 raw_ostream &getStream() { return BodyOutputStream; }
79
80 std::string Body;
8153
82protected:54protected:
83 llvm::raw_string_ostream BodyOutputStream;55 size_t offset = 0;
84};56};
8557
86class CodeSection : public OutputSection {58class CodeSection : public OutputSection {
87public:59public:
88 explicit CodeSection(ArrayRef<InputFunction *> Functions);60 explicit CodeSection(ArrayRef<InputFunction *> functions)
89 size_t getSize() const override { return Header.size() + BodySize; }61 : OutputSection(llvm::wasm::WASM_SEC_CODE), functions(functions) {}
90 void writeTo(uint8_t *Buf) override;62
91 uint32_t numRelocations() const override;63 size_t getSize() const override { return header.size() + bodySize; }
92 void writeRelocations(raw_ostream &OS) const override;64 void writeTo(uint8_t *buf) override;
65 uint32_t getNumRelocations() const override;
66 void writeRelocations(raw_ostream &os) const override;
67 bool isNeeded() const override { return functions.size() > 0; }
68 void finalizeContents() override;
9369
94protected:70protected:
95 ArrayRef<InputFunction *> Functions;71 ArrayRef<InputFunction *> functions;
96 std::string CodeSectionHeader;72 std::string codeSectionHeader;
97 size_t BodySize = 0;73 size_t bodySize = 0;
98};74};
9975
100class DataSection : public OutputSection {76class DataSection : public OutputSection {
101public:77public:
102 explicit DataSection(ArrayRef<OutputSegment *> Segments);78 explicit DataSection(ArrayRef<OutputSegment *> segments)
103 size_t getSize() const override { return Header.size() + BodySize; }79 : OutputSection(llvm::wasm::WASM_SEC_DATA), segments(segments) {}
104 void writeTo(uint8_t *Buf) override;80
105 uint32_t numRelocations() const override;81 size_t getSize() const override { return header.size() + bodySize; }
106 void writeRelocations(raw_ostream &OS) const override;82 void writeTo(uint8_t *buf) override;
83 uint32_t getNumRelocations() const override;
84 void writeRelocations(raw_ostream &os) const override;
85 bool isNeeded() const override { return segments.size() > 0; }
86 void finalizeContents() override;
10787
108protected:88protected:
109 ArrayRef<OutputSegment *> Segments;89 ArrayRef<OutputSegment *> segments;
110 std::string DataSectionHeader;90 std::string dataSectionHeader;
111 size_t BodySize = 0;91 size_t bodySize = 0;
112};92};
11393
114// Represents a custom section in the output file. Wasm custom sections are94// Represents a custom section in the output file. Wasm custom sections are
...@@ -120,18 +100,21 @@ protected:...@@ -120,18 +100,21 @@ protected:
120// separately and are instead synthesized by the linker.100// separately and are instead synthesized by the linker.
121class CustomSection : public OutputSection {101class CustomSection : public OutputSection {
122public:102public:
123 CustomSection(std::string Name, ArrayRef<InputSection *> InputSections);103 CustomSection(std::string name, ArrayRef<InputSection *> inputSections)
104 : OutputSection(llvm::wasm::WASM_SEC_CUSTOM, name),
105 inputSections(inputSections) {}
124 size_t getSize() const override {106 size_t getSize() const override {
125 return Header.size() + NameData.size() + PayloadSize;107 return header.size() + nameData.size() + payloadSize;
126 }108 }
127 void writeTo(uint8_t *Buf) override;109 void writeTo(uint8_t *buf) override;
128 uint32_t numRelocations() const override;110 uint32_t getNumRelocations() const override;
129 void writeRelocations(raw_ostream &OS) const override;111 void writeRelocations(raw_ostream &os) const override;
112 void finalizeContents() override;
130113
131protected:114protected:
132 size_t PayloadSize;115 size_t payloadSize = 0;
133 ArrayRef<InputSection *> InputSections;116 ArrayRef<InputSection *> inputSections;
134 std::string NameData;117 std::string nameData;
135};118};
136119
137} // namespace wasm120} // namespace wasm
deps/lld/wasm/OutputSegment.h+21-21
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- OutputSegment.h ------------------------------------------*- C++ -*-===//1//===- OutputSegment.h ------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -21,29 +20,30 @@ class InputSegment;...@@ -21,29 +20,30 @@ class InputSegment;
2120
22class OutputSegment {21class OutputSegment {
23public:22public:
24 OutputSegment(StringRef N, uint32_t Index) : Name(N), Index(Index) {}23 OutputSegment(StringRef n, uint32_t index) : name(n), index(index) {}
2524
26 void addInputSegment(InputSegment *InSeg) {25 void addInputSegment(InputSegment *inSeg) {
27 Alignment = std::max(Alignment, InSeg->getAlignment());26 alignment = std::max(alignment, inSeg->getAlignment());
28 InputSegments.push_back(InSeg);27 inputSegments.push_back(inSeg);
29 Size = llvm::alignTo(Size, 1 << InSeg->getAlignment());28 size = llvm::alignTo(size, 1ULL << inSeg->getAlignment());
30 InSeg->OutputSeg = this;29 inSeg->outputSeg = this;
31 InSeg->OutputSegmentOffset = Size;30 inSeg->outputSegmentOffset = size;
32 Size += InSeg->getSize();31 size += inSeg->getSize();
33 }32 }
3433
35 StringRef Name;34 StringRef name;
36 const uint32_t Index;35 const uint32_t index;
37 uint32_t SectionOffset = 0;36 uint32_t initFlags = 0;
38 uint32_t Alignment = 0;37 uint32_t sectionOffset = 0;
39 uint32_t StartVA = 0;38 uint32_t alignment = 0;
40 std::vector<InputSegment *> InputSegments;39 uint32_t startVA = 0;
40 std::vector<InputSegment *> inputSegments;
4141
42 // Sum of the size of the all the input segments42 // Sum of the size of the all the input segments
43 uint32_t Size = 0;43 uint32_t size = 0;
4444
45 // Segment header45 // Segment header
46 std::string Header;46 std::string header;
47};47};
4848
49} // namespace wasm49} // namespace wasm
deps/lld/wasm/Relocations.cpp created+101
...@@ -0,0 +1,101 @@
1//===- Relocations.cpp ----------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "Relocations.h"
10
11#include "InputChunks.h"
12#include "SyntheticSections.h"
13
14using namespace llvm;
15using namespace llvm::wasm;
16
17using namespace lld;
18using namespace lld::wasm;
19
20static bool requiresGOTAccess(const Symbol *sym) {
21 return config->isPic && !sym->isHidden() && !sym->isLocal();
22}
23
24static bool allowUndefined(const Symbol* sym) {
25 // Historically --allow-undefined doesn't work for data symbols since we don't
26 // have any way to represent these as imports in the final binary. The idea
27 // behind allowing undefined symbols is to allow importing these symbols from
28 // the embedder and we can't do this for data symbols (at least not without
29 // compiling with -fPIC)
30 if (isa<DataSymbol>(sym))
31 return false;
32 return (config->allowUndefined ||
33 config->allowUndefinedSymbols.count(sym->getName()) != 0);
34}
35
36static void reportUndefined(const Symbol* sym) {
37 assert(sym->isUndefined());
38 assert(!sym->isWeak());
39 if (!allowUndefined(sym))
40 error(toString(sym->getFile()) + ": undefined symbol: " + toString(*sym));
41}
42
43void lld::wasm::scanRelocations(InputChunk *chunk) {
44 if (!chunk->live)
45 return;
46 ObjFile *file = chunk->file;
47 ArrayRef<WasmSignature> types = file->getWasmObj()->types();
48 for (const WasmRelocation &reloc : chunk->getRelocations()) {
49 if (reloc.Type == R_WASM_TYPE_INDEX_LEB) {
50 // Mark target type as live
51 file->typeMap[reloc.Index] =
52 out.typeSec->registerType(types[reloc.Index]);
53 file->typeIsUsed[reloc.Index] = true;
54 continue;
55 }
56
57 // Other relocation types all have a corresponding symbol
58 Symbol *sym = file->getSymbols()[reloc.Index];
59
60 switch (reloc.Type) {
61 case R_WASM_TABLE_INDEX_I32:
62 case R_WASM_TABLE_INDEX_SLEB:
63 case R_WASM_TABLE_INDEX_REL_SLEB:
64 if (requiresGOTAccess(sym))
65 break;
66 out.elemSec->addEntry(cast<FunctionSymbol>(sym));
67 break;
68 case R_WASM_GLOBAL_INDEX_LEB:
69 if (!isa<GlobalSymbol>(sym))
70 out.importSec->addGOTEntry(sym);
71 break;
72 }
73
74 if (config->isPic) {
75 switch (reloc.Type) {
76 case R_WASM_TABLE_INDEX_SLEB:
77 case R_WASM_MEMORY_ADDR_SLEB:
78 case R_WASM_MEMORY_ADDR_LEB:
79 // Certain relocation types can't be used when building PIC output,
80 // since they would require absolute symbol addresses at link time.
81 error(toString(file) + ": relocation " + relocTypeToString(reloc.Type) +
82 " cannot be used against symbol " + toString(*sym) +
83 "; recompile with -fPIC");
84 break;
85 case R_WASM_TABLE_INDEX_I32:
86 case R_WASM_MEMORY_ADDR_I32:
87 // These relocation types are only present in the data section and
88 // will be converted into code by `generateRelocationCode`. This code
89 // requires the symbols to have GOT entires.
90 if (requiresGOTAccess(sym))
91 out.importSec->addGOTEntry(sym);
92 break;
93 }
94 } else {
95 // Report undefined symbols
96 if (sym->isUndefined() && !config->relocatable && !sym->isWeak())
97 reportUndefined(sym);
98 }
99
100 }
101}
deps/lld/wasm/Relocations.h created+22
...@@ -0,0 +1,22 @@
1//===- Relocations.h -------------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLD_WASM_RELOCATIONS_H
10#define LLD_WASM_RELOCATIONS_H
11
12namespace lld {
13namespace wasm {
14
15class InputChunk;
16
17void scanRelocations(InputChunk *chunk);
18
19} // namespace wasm
20} // namespace lld
21
22#endif
deps/lld/wasm/SymbolTable.cpp+541-255
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- SymbolTable.cpp ----------------------------------------------------===//1//===- SymbolTable.cpp ----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -25,17 +24,37 @@ using namespace llvm::object;...@@ -25,17 +24,37 @@ using namespace llvm::object;
25using namespace lld;24using namespace lld;
26using namespace lld::wasm;25using namespace lld::wasm;
2726
28SymbolTable *lld::wasm::Symtab;27SymbolTable *lld::wasm::symtab;
2928
30void SymbolTable::addFile(InputFile *File) {29void SymbolTable::addFile(InputFile *file) {
31 log("Processing: " + toString(File));30 log("Processing: " + toString(file));
32 File->parse();31
32 // .a file
33 if (auto *f = dyn_cast<ArchiveFile>(file)) {
34 f->parse();
35 return;
36 }
37
38 // .so file
39 if (auto *f = dyn_cast<SharedFile>(file)) {
40 sharedFiles.push_back(f);
41 return;
42 }
43
44 if (config->trace)
45 message(toString(file));
3346
34 // LLVM bitcode file47 // LLVM bitcode file
35 if (auto *F = dyn_cast<BitcodeFile>(File))48 if (auto *f = dyn_cast<BitcodeFile>(file)) {
36 BitcodeFiles.push_back(F);49 f->parse();
37 else if (auto *F = dyn_cast<ObjFile>(File))50 bitcodeFiles.push_back(f);
38 ObjectFiles.push_back(F);51 return;
52 }
53
54 // Regular object file
55 auto *f = cast<ObjFile>(file);
56 f->parse(false);
57 objectFiles.push_back(f);
39}58}
4059
41// This function is where all the optimizations of link-time60// This function is where all the optimizations of link-time
...@@ -46,353 +65,620 @@ void SymbolTable::addFile(InputFile *File) {...@@ -46,353 +65,620 @@ void SymbolTable::addFile(InputFile *File) {
46// Because all bitcode files that the program consists of are passed65// Because all bitcode files that the program consists of are passed
47// to the compiler at once, it can do whole-program optimization.66// to the compiler at once, it can do whole-program optimization.
48void SymbolTable::addCombinedLTOObject() {67void SymbolTable::addCombinedLTOObject() {
49 if (BitcodeFiles.empty())68 if (bitcodeFiles.empty())
50 return;69 return;
5170
52 // Compile bitcode files and replace bitcode symbols.71 // Compile bitcode files and replace bitcode symbols.
53 LTO.reset(new BitcodeCompiler);72 lto.reset(new BitcodeCompiler);
54 for (BitcodeFile *F : BitcodeFiles)73 for (BitcodeFile *f : bitcodeFiles)
55 LTO->add(*F);74 lto->add(*f);
5675
57 for (StringRef Filename : LTO->compile()) {76 for (StringRef filename : lto->compile()) {
58 auto *Obj = make<ObjFile>(MemoryBufferRef(Filename, "lto.tmp"));77 auto *obj = make<ObjFile>(MemoryBufferRef(filename, "lto.tmp"), "");
59 Obj->parse();78 obj->parse(true);
60 ObjectFiles.push_back(Obj);79 objectFiles.push_back(obj);
61 }80 }
62}81}
6382
64void SymbolTable::reportRemainingUndefines() {83Symbol *SymbolTable::find(StringRef name) {
65 for (Symbol *Sym : SymVector) {84 auto it = symMap.find(CachedHashStringRef(name));
66 if (!Sym->isUndefined() || Sym->isWeak())85 if (it == symMap.end() || it->second == -1)
67 continue;86 return nullptr;
68 if (Config->AllowUndefinedSymbols.count(Sym->getName()) != 0)87 return symVector[it->second];
69 continue;
70 if (!Sym->IsUsedInRegularObj)
71 continue;
72 error(toString(Sym->getFile()) + ": undefined symbol: " + toString(*Sym));
73 }
74}88}
7589
76Symbol *SymbolTable::find(StringRef Name) {90void SymbolTable::replace(StringRef name, Symbol* sym) {
77 return SymMap.lookup(CachedHashStringRef(Name));91 auto it = symMap.find(CachedHashStringRef(name));
92 symVector[it->second] = sym;
78}93}
7994
80std::pair<Symbol *, bool> SymbolTable::insert(StringRef Name, InputFile *File) {95std::pair<Symbol *, bool> SymbolTable::insertName(StringRef name) {
81 bool Inserted = false;96 bool trace = false;
82 Symbol *&Sym = SymMap[CachedHashStringRef(Name)];97 auto p = symMap.insert({CachedHashStringRef(name), (int)symVector.size()});
83 if (!Sym) {98 int &symIndex = p.first->second;
84 Sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());99 bool isNew = p.second;
85 Sym->IsUsedInRegularObj = false;100 if (symIndex == -1) {
86 SymVector.emplace_back(Sym);101 symIndex = symVector.size();
87 Inserted = true;102 trace = true;
103 isNew = true;
88 }104 }
89 if (!File || File->kind() == InputFile::ObjectKind)
90 Sym->IsUsedInRegularObj = true;
91 return {Sym, Inserted};
92}
93105
94static void reportTypeError(const Symbol *Existing, const InputFile *File,106 if (!isNew)
95 llvm::wasm::WasmSymbolType Type) {107 return {symVector[symIndex], false};
96 error("symbol type mismatch: " + toString(*Existing) + "\n>>> defined as " +108
97 toString(Existing->getWasmType()) + " in " +109 Symbol *sym = reinterpret_cast<Symbol *>(make<SymbolUnion>());
98 toString(Existing->getFile()) + "\n>>> defined as " + toString(Type) +110 sym->isUsedInRegularObj = false;
99 " in " + toString(File));111 sym->canInline = true;
112 sym->traced = trace;
113 symVector.emplace_back(sym);
114 return {sym, true};
100}115}
101116
102// Check the type of new symbol matches that of the symbol is replacing.117std::pair<Symbol *, bool> SymbolTable::insert(StringRef name,
103// For functions this can also involve verifying that the signatures match.118 const InputFile *file) {
104static void checkFunctionType(Symbol *Existing, const InputFile *File,119 Symbol *s;
105 const WasmSignature *NewSig) {120 bool wasInserted;
106 auto ExistingFunction = dyn_cast<FunctionSymbol>(Existing);121 std::tie(s, wasInserted) = insertName(name);
107 if (!ExistingFunction) {
108 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_FUNCTION);
109 return;
110 }
111122
112 if (!NewSig)123 if (!file || file->kind() == InputFile::ObjectKind)
113 return;124 s->isUsedInRegularObj = true;
114125
115 const WasmSignature *OldSig = ExistingFunction->Signature;126 return {s, wasInserted};
116 if (!OldSig) {127}
117 ExistingFunction->Signature = NewSig;
118 return;
119 }
120128
121 if (*NewSig != *OldSig)129static void reportTypeError(const Symbol *existing, const InputFile *file,
122 warn("function signature mismatch: " + Existing->getName() +130 llvm::wasm::WasmSymbolType type) {
123 "\n>>> defined as " + toString(*OldSig) + " in " +131 error("symbol type mismatch: " + toString(*existing) + "\n>>> defined as " +
124 toString(Existing->getFile()) + "\n>>> defined as " +132 toString(existing->getWasmType()) + " in " +
125 toString(*NewSig) + " in " + toString(File));133 toString(existing->getFile()) + "\n>>> defined as " + toString(type) +
134 " in " + toString(file));
126}135}
127136
128static void checkGlobalType(const Symbol *Existing, const InputFile *File,137// Check the type of new symbol matches that of the symbol is replacing.
129 const WasmGlobalType *NewType) {138// Returns true if the function types match, false is there is a singature
130 if (!isa<GlobalSymbol>(Existing)) {139// mismatch.
131 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_GLOBAL);140static bool signatureMatches(FunctionSymbol *existing,
141 const WasmSignature *newSig) {
142 const WasmSignature *oldSig = existing->signature;
143
144 // If either function is missing a signature (this happend for bitcode
145 // symbols) then assume they match. Any mismatch will be reported later
146 // when the LTO objects are added.
147 if (!newSig || !oldSig)
148 return true;
149
150 return *newSig == *oldSig;
151}
152
153static void checkGlobalType(const Symbol *existing, const InputFile *file,
154 const WasmGlobalType *newType) {
155 if (!isa<GlobalSymbol>(existing)) {
156 reportTypeError(existing, file, WASM_SYMBOL_TYPE_GLOBAL);
132 return;157 return;
133 }158 }
134159
135 const WasmGlobalType *OldType = cast<GlobalSymbol>(Existing)->getGlobalType();160 const WasmGlobalType *oldType = cast<GlobalSymbol>(existing)->getGlobalType();
136 if (*NewType != *OldType) {161 if (*newType != *oldType) {
137 error("Global type mismatch: " + Existing->getName() + "\n>>> defined as " +162 error("Global type mismatch: " + existing->getName() + "\n>>> defined as " +
138 toString(*OldType) + " in " + toString(Existing->getFile()) +163 toString(*oldType) + " in " + toString(existing->getFile()) +
139 "\n>>> defined as " + toString(*NewType) + " in " + toString(File));164 "\n>>> defined as " + toString(*newType) + " in " + toString(file));
140 }165 }
141}166}
142167
143static void checkEventType(const Symbol *Existing, const InputFile *File,168static void checkEventType(const Symbol *existing, const InputFile *file,
144 const WasmEventType *NewType,169 const WasmEventType *newType,
145 const WasmSignature *NewSig) {170 const WasmSignature *newSig) {
146 auto ExistingEvent = dyn_cast<EventSymbol>(Existing);171 auto existingEvent = dyn_cast<EventSymbol>(existing);
147 if (!isa<EventSymbol>(Existing)) {172 if (!isa<EventSymbol>(existing)) {
148 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_EVENT);173 reportTypeError(existing, file, WASM_SYMBOL_TYPE_EVENT);
149 return;174 return;
150 }175 }
151176
152 const WasmEventType *OldType = cast<EventSymbol>(Existing)->getEventType();177 const WasmEventType *oldType = cast<EventSymbol>(existing)->getEventType();
153 const WasmSignature *OldSig = ExistingEvent->Signature;178 const WasmSignature *oldSig = existingEvent->signature;
154 if (NewType->Attribute != OldType->Attribute)179 if (newType->Attribute != oldType->Attribute)
155 error("Event type mismatch: " + Existing->getName() + "\n>>> defined as " +180 error("Event type mismatch: " + existing->getName() + "\n>>> defined as " +
156 toString(*OldType) + " in " + toString(Existing->getFile()) +181 toString(*oldType) + " in " + toString(existing->getFile()) +
157 "\n>>> defined as " + toString(*NewType) + " in " + toString(File));182 "\n>>> defined as " + toString(*newType) + " in " + toString(file));
158 if (*NewSig != *OldSig)183 if (*newSig != *oldSig)
159 warn("Event signature mismatch: " + Existing->getName() +184 warn("Event signature mismatch: " + existing->getName() +
160 "\n>>> defined as " + toString(*OldSig) + " in " +185 "\n>>> defined as " + toString(*oldSig) + " in " +
161 toString(Existing->getFile()) + "\n>>> defined as " +186 toString(existing->getFile()) + "\n>>> defined as " +
162 toString(*NewSig) + " in " + toString(File));187 toString(*newSig) + " in " + toString(file));
188}
189
190static void checkDataType(const Symbol *existing, const InputFile *file) {
191 if (!isa<DataSymbol>(existing))
192 reportTypeError(existing, file, WASM_SYMBOL_TYPE_DATA);
163}193}
164194
165static void checkDataType(const Symbol *Existing, const InputFile *File) {195DefinedFunction *SymbolTable::addSyntheticFunction(StringRef name,
166 if (!isa<DataSymbol>(Existing))196 uint32_t flags,
167 reportTypeError(Existing, File, WASM_SYMBOL_TYPE_DATA);197 InputFunction *function) {
198 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << name << "\n");
199 assert(!find(name));
200 syntheticFunctions.emplace_back(function);
201 return replaceSymbol<DefinedFunction>(insertName(name).first, name,
202 flags, nullptr, function);
168}203}
169204
170DefinedFunction *SymbolTable::addSyntheticFunction(StringRef Name,205// Adds an optional, linker generated, data symbols. The symbol will only be
171 uint32_t Flags,206// added if there is an undefine reference to it, or if it is explictly exported
172 InputFunction *Function) {207// via the --export flag. Otherwise we don't add the symbol and return nullptr.
173 LLVM_DEBUG(dbgs() << "addSyntheticFunction: " << Name << "\n");208DefinedData *SymbolTable::addOptionalDataSymbol(StringRef name, uint32_t value,
174 assert(!find(Name));209 uint32_t flags) {
175 SyntheticFunctions.emplace_back(Function);210 Symbol *s = find(name);
176 return replaceSymbol<DefinedFunction>(insert(Name, nullptr).first, Name,211 if (!s && (config->exportAll || config->exportedSymbols.count(name) != 0))
177 Flags, nullptr, Function);212 s = insertName(name).first;
213 else if (!s || s->isDefined())
214 return nullptr;
215 LLVM_DEBUG(dbgs() << "addOptionalDataSymbol: " << name << "\n");
216 auto *rtn = replaceSymbol<DefinedData>(s, name, flags);
217 rtn->setVirtualAddress(value);
218 rtn->referenced = true;
219 return rtn;
178}220}
179221
180DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef Name,222DefinedData *SymbolTable::addSyntheticDataSymbol(StringRef name,
181 uint32_t Flags) {223 uint32_t flags) {
182 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << Name << "\n");224 LLVM_DEBUG(dbgs() << "addSyntheticDataSymbol: " << name << "\n");
183 assert(!find(Name));225 assert(!find(name));
184 return replaceSymbol<DefinedData>(insert(Name, nullptr).first, Name, Flags);226 return replaceSymbol<DefinedData>(insertName(name).first, name, flags);
185}227}
186228
187DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef Name, uint32_t Flags,229DefinedGlobal *SymbolTable::addSyntheticGlobal(StringRef name, uint32_t flags,
188 InputGlobal *Global) {230 InputGlobal *global) {
189 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << Name << " -> " << Global231 LLVM_DEBUG(dbgs() << "addSyntheticGlobal: " << name << " -> " << global
190 << "\n");232 << "\n");
191 assert(!find(Name));233 assert(!find(name));
192 SyntheticGlobals.emplace_back(Global);234 syntheticGlobals.emplace_back(global);
193 return replaceSymbol<DefinedGlobal>(insert(Name, nullptr).first, Name, Flags,235 return replaceSymbol<DefinedGlobal>(insertName(name).first, name, flags,
194 nullptr, Global);236 nullptr, global);
195}237}
196238
197static bool shouldReplace(const Symbol *Existing, InputFile *NewFile,239static bool shouldReplace(const Symbol *existing, InputFile *newFile,
198 uint32_t NewFlags) {240 uint32_t newFlags) {
199 // If existing symbol is undefined, replace it.241 // If existing symbol is undefined, replace it.
200 if (!Existing->isDefined()) {242 if (!existing->isDefined()) {
201 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: "243 LLVM_DEBUG(dbgs() << "resolving existing undefined symbol: "
202 << Existing->getName() << "\n");244 << existing->getName() << "\n");
203 return true;245 return true;
204 }246 }
205247
206 // Now we have two defined symbols. If the new one is weak, we can ignore it.248 // Now we have two defined symbols. If the new one is weak, we can ignore it.
207 if ((NewFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {249 if ((newFlags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK) {
208 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n");250 LLVM_DEBUG(dbgs() << "existing symbol takes precedence\n");
209 return false;251 return false;
210 }252 }
211253
212 // If the existing symbol is weak, we should replace it.254 // If the existing symbol is weak, we should replace it.
213 if (Existing->isWeak()) {255 if (existing->isWeak()) {
214 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n");256 LLVM_DEBUG(dbgs() << "replacing existing weak symbol\n");
215 return true;257 return true;
216 }258 }
217259
218 // Neither symbol is week. They conflict.260 // Neither symbol is week. They conflict.
219 error("duplicate symbol: " + toString(*Existing) + "\n>>> defined in " +261 error("duplicate symbol: " + toString(*existing) + "\n>>> defined in " +
220 toString(Existing->getFile()) + "\n>>> defined in " +262 toString(existing->getFile()) + "\n>>> defined in " +
221 toString(NewFile));263 toString(newFile));
222 return true;264 return true;
223}265}
224266
225Symbol *SymbolTable::addDefinedFunction(StringRef Name, uint32_t Flags,267Symbol *SymbolTable::addDefinedFunction(StringRef name, uint32_t flags,
226 InputFile *File,268 InputFile *file,
227 InputFunction *Function) {269 InputFunction *function) {
228 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << Name << " ["270 LLVM_DEBUG(dbgs() << "addDefinedFunction: " << name << " ["
229 << (Function ? toString(Function->Signature) : "none")271 << (function ? toString(function->signature) : "none")
230 << "]\n");272 << "]\n");
231 Symbol *S;273 Symbol *s;
232 bool WasInserted;274 bool wasInserted;
233 std::tie(S, WasInserted) = insert(Name, File);275 std::tie(s, wasInserted) = insert(name, file);
234276
235 if (WasInserted || S->isLazy()) {277 auto replaceSym = [&](Symbol *sym) {
236 replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function);278 // If the new defined function doesn't have signture (i.e. bitcode
237 return S;279 // functions) but the old symbol does, then preserve the old signature
280 const WasmSignature *oldSig = s->getSignature();
281 auto* newSym = replaceSymbol<DefinedFunction>(sym, name, flags, file, function);
282 if (!newSym->signature)
283 newSym->signature = oldSig;
284 };
285
286 if (wasInserted || s->isLazy()) {
287 replaceSym(s);
288 return s;
238 }289 }
239290
240 if (Function)291 auto existingFunction = dyn_cast<FunctionSymbol>(s);
241 checkFunctionType(S, File, &Function->Signature);292 if (!existingFunction) {
293 reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION);
294 return s;
295 }
242296
243 if (shouldReplace(S, File, Flags)) {297 bool checkSig = true;
244 // If the new defined function doesn't have signture (i.e. bitcode298 if (auto ud = dyn_cast<UndefinedFunction>(existingFunction))
245 // functions) but the old symbols does then preserve the old signature299 checkSig = ud->isCalledDirectly;
246 const WasmSignature *OldSig = nullptr;300
247 if (auto* F = dyn_cast<FunctionSymbol>(S))301 if (checkSig && function && !signatureMatches(existingFunction, &function->signature)) {
248 OldSig = F->Signature;302 Symbol* variant;
249 auto NewSym = replaceSymbol<DefinedFunction>(S, Name, Flags, File, Function);303 if (getFunctionVariant(s, &function->signature, file, &variant))
250 if (!NewSym->Signature)304 // New variant, always replace
251 NewSym->Signature = OldSig;305 replaceSym(variant);
306 else if (shouldReplace(s, file, flags))
307 // Variant already exists, replace it after checking shouldReplace
308 replaceSym(variant);
309
310 // This variant we found take the place in the symbol table as the primary
311 // variant.
312 replace(name, variant);
313 return variant;
252 }314 }
253 return S;315
316 // Existing function with matching signature.
317 if (shouldReplace(s, file, flags))
318 replaceSym(s);
319
320 return s;
254}321}
255322
256Symbol *SymbolTable::addDefinedData(StringRef Name, uint32_t Flags,323Symbol *SymbolTable::addDefinedData(StringRef name, uint32_t flags,
257 InputFile *File, InputSegment *Segment,324 InputFile *file, InputSegment *segment,
258 uint32_t Address, uint32_t Size) {325 uint32_t address, uint32_t size) {
259 LLVM_DEBUG(dbgs() << "addDefinedData:" << Name << " addr:" << Address326 LLVM_DEBUG(dbgs() << "addDefinedData:" << name << " addr:" << address
260 << "\n");327 << "\n");
261 Symbol *S;328 Symbol *s;
262 bool WasInserted;329 bool wasInserted;
263 std::tie(S, WasInserted) = insert(Name, File);330 std::tie(s, wasInserted) = insert(name, file);
331
332 auto replaceSym = [&]() {
333 replaceSymbol<DefinedData>(s, name, flags, file, segment, address, size);
334 };
264335
265 if (WasInserted || S->isLazy()) {336 if (wasInserted || s->isLazy()) {
266 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size);337 replaceSym();
267 return S;338 return s;
268 }339 }
269340
270 checkDataType(S, File);341 checkDataType(s, file);
271342
272 if (shouldReplace(S, File, Flags))343 if (shouldReplace(s, file, flags))
273 replaceSymbol<DefinedData>(S, Name, Flags, File, Segment, Address, Size);344 replaceSym();
274 return S;345 return s;
275}346}
276347
277Symbol *SymbolTable::addDefinedGlobal(StringRef Name, uint32_t Flags,348Symbol *SymbolTable::addDefinedGlobal(StringRef name, uint32_t flags,
278 InputFile *File, InputGlobal *Global) {349 InputFile *file, InputGlobal *global) {
279 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << Name << "\n");350 LLVM_DEBUG(dbgs() << "addDefinedGlobal:" << name << "\n");
280351
281 Symbol *S;352 Symbol *s;
282 bool WasInserted;353 bool wasInserted;
283 std::tie(S, WasInserted) = insert(Name, File);354 std::tie(s, wasInserted) = insert(name, file);
284355
285 if (WasInserted || S->isLazy()) {356 auto replaceSym = [&]() {
286 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global);357 replaceSymbol<DefinedGlobal>(s, name, flags, file, global);
287 return S;358 };
359
360 if (wasInserted || s->isLazy()) {
361 replaceSym();
362 return s;
288 }363 }
289364
290 checkGlobalType(S, File, &Global->getType());365 checkGlobalType(s, file, &global->getType());
291366
292 if (shouldReplace(S, File, Flags))367 if (shouldReplace(s, file, flags))
293 replaceSymbol<DefinedGlobal>(S, Name, Flags, File, Global);368 replaceSym();
294 return S;369 return s;
295}370}
296371
297Symbol *SymbolTable::addDefinedEvent(StringRef Name, uint32_t Flags,372Symbol *SymbolTable::addDefinedEvent(StringRef name, uint32_t flags,
298 InputFile *File, InputEvent *Event) {373 InputFile *file, InputEvent *event) {
299 LLVM_DEBUG(dbgs() << "addDefinedEvent:" << Name << "\n");374 LLVM_DEBUG(dbgs() << "addDefinedEvent:" << name << "\n");
375
376 Symbol *s;
377 bool wasInserted;
378 std::tie(s, wasInserted) = insert(name, file);
300379
301 Symbol *S;380 auto replaceSym = [&]() {
302 bool WasInserted;381 replaceSymbol<DefinedEvent>(s, name, flags, file, event);
303 std::tie(S, WasInserted) = insert(Name, File);382 };
304383
305 if (WasInserted || S->isLazy()) {384 if (wasInserted || s->isLazy()) {
306 replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event);385 replaceSym();
307 return S;386 return s;
308 }387 }
309388
310 checkEventType(S, File, &Event->getType(), &Event->Signature);389 checkEventType(s, file, &event->getType(), &event->signature);
311390
312 if (shouldReplace(S, File, Flags))391 if (shouldReplace(s, file, flags))
313 replaceSymbol<DefinedEvent>(S, Name, Flags, File, Event);392 replaceSym();
314 return S;393 return s;
315}394}
316395
317Symbol *SymbolTable::addUndefinedFunction(StringRef Name, StringRef ImportName,396Symbol *SymbolTable::addUndefinedFunction(StringRef name, StringRef importName,
318 StringRef ImportModule,397 StringRef importModule,
319 uint32_t Flags, InputFile *File,398 uint32_t flags, InputFile *file,
320 const WasmSignature *Sig) {399 const WasmSignature *sig,
321 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << Name <<400 bool isCalledDirectly) {
322 " [" << (Sig ? toString(*Sig) : "none") << "]\n");401 LLVM_DEBUG(dbgs() << "addUndefinedFunction: " << name << " ["
402 << (sig ? toString(*sig) : "none")
403 << "] IsCalledDirectly:" << isCalledDirectly << "\n");
404
405 Symbol *s;
406 bool wasInserted;
407 std::tie(s, wasInserted) = insert(name, file);
408 if (s->traced)
409 printTraceSymbolUndefined(name, file);
410
411 auto replaceSym = [&]() {
412 replaceSymbol<UndefinedFunction>(s, name, importName, importModule, flags,
413 file, sig, isCalledDirectly);
414 };
415
416 if (wasInserted)
417 replaceSym();
418 else if (auto *lazy = dyn_cast<LazySymbol>(s))
419 lazy->fetch();
420 else {
421 auto existingFunction = dyn_cast<FunctionSymbol>(s);
422 if (!existingFunction) {
423 reportTypeError(s, file, WASM_SYMBOL_TYPE_FUNCTION);
424 return s;
425 }
426 if (!existingFunction->signature && sig)
427 existingFunction->signature = sig;
428 if (isCalledDirectly && !signatureMatches(existingFunction, sig))
429 if (getFunctionVariant(s, sig, file, &s))
430 replaceSym();
431 }
323432
324 Symbol *S;433 return s;
325 bool WasInserted;434}
326 std::tie(S, WasInserted) = insert(Name, File);
327435
328 if (WasInserted)436Symbol *SymbolTable::addUndefinedData(StringRef name, uint32_t flags,
329 replaceSymbol<UndefinedFunction>(S, Name, ImportName, ImportModule, Flags,437 InputFile *file) {
330 File, Sig);438 LLVM_DEBUG(dbgs() << "addUndefinedData: " << name << "\n");
331 else if (auto *Lazy = dyn_cast<LazySymbol>(S))439
332 Lazy->fetch();440 Symbol *s;
333 else441 bool wasInserted;
334 checkFunctionType(S, File, Sig);442 std::tie(s, wasInserted) = insert(name, file);
443 if (s->traced)
444 printTraceSymbolUndefined(name, file);
445
446 if (wasInserted)
447 replaceSymbol<UndefinedData>(s, name, flags, file);
448 else if (auto *lazy = dyn_cast<LazySymbol>(s))
449 lazy->fetch();
450 else if (s->isDefined())
451 checkDataType(s, file);
452 return s;
453}
335454
336 return S;455Symbol *SymbolTable::addUndefinedGlobal(StringRef name, StringRef importName,
456 StringRef importModule, uint32_t flags,
457 InputFile *file,
458 const WasmGlobalType *type) {
459 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << name << "\n");
460
461 Symbol *s;
462 bool wasInserted;
463 std::tie(s, wasInserted) = insert(name, file);
464 if (s->traced)
465 printTraceSymbolUndefined(name, file);
466
467 if (wasInserted)
468 replaceSymbol<UndefinedGlobal>(s, name, importName, importModule, flags,
469 file, type);
470 else if (auto *lazy = dyn_cast<LazySymbol>(s))
471 lazy->fetch();
472 else if (s->isDefined())
473 checkGlobalType(s, file, type);
474 return s;
337}475}
338476
339Symbol *SymbolTable::addUndefinedData(StringRef Name, uint32_t Flags,477void SymbolTable::addLazy(ArchiveFile *file, const Archive::Symbol *sym) {
340 InputFile *File) {478 LLVM_DEBUG(dbgs() << "addLazy: " << sym->getName() << "\n");
341 LLVM_DEBUG(dbgs() << "addUndefinedData: " << Name << "\n");479 StringRef name = sym->getName();
342480
343 Symbol *S;481 Symbol *s;
344 bool WasInserted;482 bool wasInserted;
345 std::tie(S, WasInserted) = insert(Name, File);483 std::tie(s, wasInserted) = insertName(name);
346484
347 if (WasInserted)485 if (wasInserted) {
348 replaceSymbol<UndefinedData>(S, Name, Flags, File);486 replaceSymbol<LazySymbol>(s, name, 0, file, *sym);
349 else if (auto *Lazy = dyn_cast<LazySymbol>(S))487 return;
350 Lazy->fetch();488 }
351 else if (S->isDefined())
352 checkDataType(S, File);
353 return S;
354}
355489
356Symbol *SymbolTable::addUndefinedGlobal(StringRef Name, StringRef ImportName,490 if (!s->isUndefined())
357 StringRef ImportModule, uint32_t Flags,491 return;
358 InputFile *File,
359 const WasmGlobalType *Type) {
360 LLVM_DEBUG(dbgs() << "addUndefinedGlobal: " << Name << "\n");
361492
362 Symbol *S;493 // The existing symbol is undefined, load a new one from the archive,
363 bool WasInserted;494 // unless the the existing symbol is weak in which case replace the undefined
364 std::tie(S, WasInserted) = insert(Name, File);495 // symbols with a LazySymbol.
496 if (s->isWeak()) {
497 const WasmSignature *oldSig = nullptr;
498 // In the case of an UndefinedFunction we need to preserve the expected
499 // signature.
500 if (auto *f = dyn_cast<UndefinedFunction>(s))
501 oldSig = f->signature;
502 LLVM_DEBUG(dbgs() << "replacing existing weak undefined symbol\n");
503 auto newSym = replaceSymbol<LazySymbol>(s, name, WASM_SYMBOL_BINDING_WEAK,
504 file, *sym);
505 newSym->signature = oldSig;
506 return;
507 }
365508
366 if (WasInserted)509 LLVM_DEBUG(dbgs() << "replacing existing undefined\n");
367 replaceSymbol<UndefinedGlobal>(S, Name, ImportName, ImportModule, Flags,510 file->addMember(sym);
368 File, Type);
369 else if (auto *Lazy = dyn_cast<LazySymbol>(S))
370 Lazy->fetch();
371 else if (S->isDefined())
372 checkGlobalType(S, File, Type);
373 return S;
374}511}
375512
376void SymbolTable::addLazy(ArchiveFile *File, const Archive::Symbol *Sym) {513bool SymbolTable::addComdat(StringRef name) {
377 LLVM_DEBUG(dbgs() << "addLazy: " << Sym->getName() << "\n");514 return comdatGroups.insert(CachedHashStringRef(name)).second;
378 StringRef Name = Sym->getName();515}
379516
380 Symbol *S;517// The new signature doesn't match. Create a variant to the symbol with the
381 bool WasInserted;518// signature encoded in the name and return that instead. These symbols are
382 std::tie(S, WasInserted) = insert(Name, nullptr);519// then unified later in handleSymbolVariants.
520bool SymbolTable::getFunctionVariant(Symbol* sym, const WasmSignature *sig,
521 const InputFile *file, Symbol **out) {
522 LLVM_DEBUG(dbgs() << "getFunctionVariant: " << sym->getName() << " -> "
523 << " " << toString(*sig) << "\n");
524 Symbol *variant = nullptr;
525
526 // Linear search through symbol variants. Should never be more than two
527 // or three entries here.
528 auto &variants = symVariants[CachedHashStringRef(sym->getName())];
529 if (variants.empty())
530 variants.push_back(sym);
531
532 for (Symbol* v : variants) {
533 if (*v->getSignature() == *sig) {
534 variant = v;
535 break;
536 }
537 }
383538
384 if (WasInserted) {539 bool wasAdded = !variant;
385 replaceSymbol<LazySymbol>(S, Name, File, *Sym);540 if (wasAdded) {
386 return;541 // Create a new variant;
542 LLVM_DEBUG(dbgs() << "added new variant\n");
543 variant = reinterpret_cast<Symbol *>(make<SymbolUnion>());
544 variants.push_back(variant);
545 } else {
546 LLVM_DEBUG(dbgs() << "variant already exists: " << toString(*variant) << "\n");
547 assert(*variant->getSignature() == *sig);
387 }548 }
388549
389 // If there is an existing undefined symbol, load a new one from the archive.550 *out = variant;
390 if (S->isUndefined()) {551 return wasAdded;
391 LLVM_DEBUG(dbgs() << "replacing existing undefined\n");552}
392 File->addMember(Sym);553
554// Set a flag for --trace-symbol so that we can print out a log message
555// if a new symbol with the same name is inserted into the symbol table.
556void SymbolTable::trace(StringRef name) {
557 symMap.insert({CachedHashStringRef(name), -1});
558}
559
560void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
561 // Swap symbols as instructed by -wrap.
562 int &origIdx = symMap[CachedHashStringRef(sym->getName())];
563 int &realIdx= symMap[CachedHashStringRef(real->getName())];
564 int &wrapIdx = symMap[CachedHashStringRef(wrap->getName())];
565 LLVM_DEBUG(dbgs() << "wrap: " << sym->getName() << "\n");
566
567 // Anyone looking up __real symbols should get the original
568 realIdx = origIdx;
569 // Anyone looking up the original should get the __wrap symbol
570 origIdx = wrapIdx;
571}
572
573static const uint8_t unreachableFn[] = {
574 0x03 /* ULEB length */, 0x00 /* ULEB num locals */,
575 0x00 /* opcode unreachable */, 0x0b /* opcode end */
576};
577
578// Replace the given symbol body with an unreachable function.
579// This is used by handleWeakUndefines in order to generate a callable
580// equivalent of an undefined function and also handleSymbolVariants for
581// undefined functions that don't match the signature of the definition.
582InputFunction *SymbolTable::replaceWithUnreachable(Symbol *sym,
583 const WasmSignature &sig,
584 StringRef debugName) {
585 auto *func = make<SyntheticFunction>(sig, sym->getName(), debugName);
586 func->setBody(unreachableFn);
587 syntheticFunctions.emplace_back(func);
588 replaceSymbol<DefinedFunction>(sym, sym->getName(), sym->getFlags(), nullptr,
589 func);
590 return func;
591}
592
593// For weak undefined functions, there may be "call" instructions that reference
594// the symbol. In this case, we need to synthesise a dummy/stub function that
595// will abort at runtime, so that relocations can still provided an operand to
596// the call instruction that passes Wasm validation.
597void SymbolTable::handleWeakUndefines() {
598 for (Symbol *sym : getSymbols()) {
599 if (!sym->isUndefWeak())
600 continue;
601
602 const WasmSignature *sig = sym->getSignature();
603 if (!sig) {
604 // It is possible for undefined functions not to have a signature (eg. if
605 // added via "--undefined"), but weak undefined ones do have a signature.
606 // Lazy symbols may not be functions and therefore Sig can still be null
607 // in some circumstantce.
608 assert(!isa<FunctionSymbol>(sym));
609 continue;
610 }
611
612 // Add a synthetic dummy for weak undefined functions. These dummies will
613 // be GC'd if not used as the target of any "call" instructions.
614 StringRef debugName = saver.save("undefined:" + toString(*sym));
615 InputFunction* func = replaceWithUnreachable(sym, *sig, debugName);
616 // Ensure it compares equal to the null pointer, and so that table relocs
617 // don't pull in the stub body (only call-operand relocs should do that).
618 func->setTableIndex(0);
619 // Hide our dummy to prevent export.
620 sym->setHidden(true);
393 }621 }
394}622}
395623
396bool SymbolTable::addComdat(StringRef Name) {624static void reportFunctionSignatureMismatch(StringRef symName,
397 return Comdats.insert(CachedHashStringRef(Name)).second;625 FunctionSymbol *a,
626 FunctionSymbol *b, bool isError) {
627 std::string msg = ("function signature mismatch: " + symName +
628 "\n>>> defined as " + toString(*a->signature) + " in " +
629 toString(a->getFile()) + "\n>>> defined as " +
630 toString(*b->signature) + " in " + toString(b->getFile()))
631 .str();
632 if (isError)
633 error(msg);
634 else
635 warn(msg);
636}
637
638// Remove any variant symbols that were created due to function signature
639// mismatches.
640void SymbolTable::handleSymbolVariants() {
641 for (auto pair : symVariants) {
642 // Push the initial symbol onto the list of variants.
643 StringRef symName = pair.first.val();
644 std::vector<Symbol *> &variants = pair.second;
645
646#ifndef NDEBUG
647 LLVM_DEBUG(dbgs() << "symbol with (" << variants.size()
648 << ") variants: " << symName << "\n");
649 for (auto *s: variants) {
650 auto *f = cast<FunctionSymbol>(s);
651 LLVM_DEBUG(dbgs() << " variant: " + f->getName() << " "
652 << toString(*f->signature) << "\n");
653 }
654#endif
655
656 // Find the one definition.
657 DefinedFunction *defined = nullptr;
658 for (auto *symbol : variants) {
659 if (auto f = dyn_cast<DefinedFunction>(symbol)) {
660 defined = f;
661 break;
662 }
663 }
664
665 // If there are no definitions, and the undefined symbols disagree on
666 // the signature, there is not we can do since we don't know which one
667 // to use as the signature on the import.
668 if (!defined) {
669 reportFunctionSignatureMismatch(symName,
670 cast<FunctionSymbol>(variants[0]),
671 cast<FunctionSymbol>(variants[1]), true);
672 return;
673 }
674
675 for (auto *symbol : variants) {
676 if (symbol != defined) {
677 auto *f = cast<FunctionSymbol>(symbol);
678 reportFunctionSignatureMismatch(symName, f, defined, false);
679 StringRef debugName = saver.save("unreachable:" + toString(*f));
680 replaceWithUnreachable(f, *f->signature, debugName);
681 }
682 }
683 }
398}684}
deps/lld/wasm/SymbolTable.h+69-41
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- SymbolTable.h --------------------------------------------*- C++ -*-===//1//===- SymbolTable.h --------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -36,60 +35,89 @@ class InputSegment;...@@ -36,60 +35,89 @@ class InputSegment;
36// There is one add* function per symbol type.35// There is one add* function per symbol type.
37class SymbolTable {36class SymbolTable {
38public:37public:
39 void addFile(InputFile *File);38 void wrap(Symbol *sym, Symbol *real, Symbol *wrap);
39
40 void addFile(InputFile *file);
41
40 void addCombinedLTOObject();42 void addCombinedLTOObject();
4143
42 std::vector<ObjFile *> ObjectFiles;44 ArrayRef<Symbol *> getSymbols() const { return symVector; }
43 std::vector<BitcodeFile *> BitcodeFiles;45
44 std::vector<InputFunction *> SyntheticFunctions;46 Symbol *find(StringRef name);
45 std::vector<InputGlobal *> SyntheticGlobals;
4647
47 void reportRemainingUndefines();48 void replace(StringRef name, Symbol* sym);
4849
49 ArrayRef<Symbol *> getSymbols() const { return SymVector; }50 void trace(StringRef name);
50 Symbol *find(StringRef Name);
5151
52 Symbol *addDefinedFunction(StringRef Name, uint32_t Flags, InputFile *File,52 Symbol *addDefinedFunction(StringRef name, uint32_t flags, InputFile *file,
53 InputFunction *Function);53 InputFunction *function);
54 Symbol *addDefinedData(StringRef Name, uint32_t Flags, InputFile *File,54 Symbol *addDefinedData(StringRef name, uint32_t flags, InputFile *file,
55 InputSegment *Segment, uint32_t Address,55 InputSegment *segment, uint32_t address,
56 uint32_t Size);56 uint32_t size);
57 Symbol *addDefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,57 Symbol *addDefinedGlobal(StringRef name, uint32_t flags, InputFile *file,
58 InputGlobal *G);58 InputGlobal *g);
59 Symbol *addDefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,59 Symbol *addDefinedEvent(StringRef name, uint32_t flags, InputFile *file,
60 InputEvent *E);60 InputEvent *e);
6161
62 Symbol *addUndefinedFunction(StringRef Name, StringRef ImportName,62 Symbol *addUndefinedFunction(StringRef name, StringRef importName,
63 StringRef ImportModule, uint32_t Flags,63 StringRef importModule, uint32_t flags,
64 InputFile *File, const WasmSignature *Signature);64 InputFile *file, const WasmSignature *signature,
65 Symbol *addUndefinedData(StringRef Name, uint32_t Flags, InputFile *File);65 bool isCalledDirectly);
66 Symbol *addUndefinedGlobal(StringRef Name, StringRef ImportName,66 Symbol *addUndefinedData(StringRef name, uint32_t flags, InputFile *file);
67 StringRef ImportModule, uint32_t Flags,67 Symbol *addUndefinedGlobal(StringRef name, StringRef importName,
68 InputFile *File, const WasmGlobalType *Type);68 StringRef importModule, uint32_t flags,
69 InputFile *file, const WasmGlobalType *type);
6970
70 void addLazy(ArchiveFile *F, const llvm::object::Archive::Symbol *Sym);71 void addLazy(ArchiveFile *f, const llvm::object::Archive::Symbol *sym);
7172
72 bool addComdat(StringRef Name);73 bool addComdat(StringRef name);
7374
74 DefinedData *addSyntheticDataSymbol(StringRef Name, uint32_t Flags);75 DefinedData *addSyntheticDataSymbol(StringRef name, uint32_t flags);
75 DefinedGlobal *addSyntheticGlobal(StringRef Name, uint32_t Flags,76 DefinedGlobal *addSyntheticGlobal(StringRef name, uint32_t flags,
76 InputGlobal *Global);77 InputGlobal *global);
77 DefinedFunction *addSyntheticFunction(StringRef Name, uint32_t Flags,78 DefinedFunction *addSyntheticFunction(StringRef name, uint32_t flags,
78 InputFunction *Function);79 InputFunction *function);
80 DefinedData *addOptionalDataSymbol(StringRef name, uint32_t value = 0,
81 uint32_t flags = 0);
82
83 void handleSymbolVariants();
84 void handleWeakUndefines();
85
86 std::vector<ObjFile *> objectFiles;
87 std::vector<SharedFile *> sharedFiles;
88 std::vector<BitcodeFile *> bitcodeFiles;
89 std::vector<InputFunction *> syntheticFunctions;
90 std::vector<InputGlobal *> syntheticGlobals;
7991
80private:92private:
81 std::pair<Symbol *, bool> insert(StringRef Name, InputFile *File);93 std::pair<Symbol *, bool> insert(StringRef name, const InputFile *file);
94 std::pair<Symbol *, bool> insertName(StringRef name);
95
96 bool getFunctionVariant(Symbol* sym, const WasmSignature *sig,
97 const InputFile *file, Symbol **out);
98 InputFunction *replaceWithUnreachable(Symbol *sym, const WasmSignature &sig,
99 StringRef debugName);
100
101 // Maps symbol names to index into the symVector. -1 means that symbols
102 // is to not yet in the vector but it should have tracing enabled if it is
103 // ever added.
104 llvm::DenseMap<llvm::CachedHashStringRef, int> symMap;
105 std::vector<Symbol *> symVector;
82106
83 llvm::DenseMap<llvm::CachedHashStringRef, Symbol *> SymMap;107 // For certain symbols types, e.g. function symbols, we allow for muliple
84 std::vector<Symbol *> SymVector;108 // variants of the same symbol with different signatures.
109 llvm::DenseMap<llvm::CachedHashStringRef, std::vector<Symbol *>> symVariants;
85110
86 llvm::DenseSet<llvm::CachedHashStringRef> Comdats;111 // Comdat groups define "link once" sections. If two comdat groups have the
112 // same name, only one of them is linked, and the other is ignored. This set
113 // is used to uniquify them.
114 llvm::DenseSet<llvm::CachedHashStringRef> comdatGroups;
87115
88 // For LTO.116 // For LTO.
89 std::unique_ptr<BitcodeCompiler> LTO;117 std::unique_ptr<BitcodeCompiler> lto;
90};118};
91119
92extern SymbolTable *Symtab;120extern SymbolTable *symtab;
93121
94} // namespace wasm122} // namespace wasm
95} // namespace lld123} // namespace lld
deps/lld/wasm/Symbols.cpp+193-140
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Symbols.cpp --------------------------------------------------------===//1//===- Symbols.cpp --------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -13,6 +12,7 @@...@@ -13,6 +12,7 @@
13#include "InputEvent.h"12#include "InputEvent.h"
14#include "InputFiles.h"13#include "InputFiles.h"
15#include "InputGlobal.h"14#include "InputGlobal.h"
15#include "OutputSections.h"
16#include "OutputSegment.h"16#include "OutputSegment.h"
17#include "lld/Common/ErrorHandler.h"17#include "lld/Common/ErrorHandler.h"
18#include "lld/Common/Strings.h"18#include "lld/Common/Strings.h"
...@@ -24,13 +24,19 @@ using namespace llvm::wasm;...@@ -24,13 +24,19 @@ using namespace llvm::wasm;
24using namespace lld;24using namespace lld;
25using namespace lld::wasm;25using namespace lld::wasm;
2626
27DefinedFunction *WasmSym::CallCtors;27DefinedFunction *WasmSym::callCtors;
28DefinedData *WasmSym::DsoHandle;28DefinedFunction *WasmSym::initMemory;
29DefinedData *WasmSym::DataEnd;29DefinedFunction *WasmSym::applyRelocs;
30DefinedData *WasmSym::HeapBase;30DefinedFunction *WasmSym::initTLS;
31GlobalSymbol *WasmSym::StackPointer;31DefinedData *WasmSym::dsoHandle;
32UndefinedGlobal *WasmSym::TableBase;32DefinedData *WasmSym::dataEnd;
33UndefinedGlobal *WasmSym::MemoryBase;33DefinedData *WasmSym::globalBase;
34DefinedData *WasmSym::heapBase;
35GlobalSymbol *WasmSym::stackPointer;
36GlobalSymbol *WasmSym::tlsBase;
37GlobalSymbol *WasmSym::tlsSize;
38UndefinedGlobal *WasmSym::tableBase;
39UndefinedGlobal *WasmSym::memoryBase;
3440
35WasmSymbolType Symbol::getWasmType() const {41WasmSymbolType Symbol::getWasmType() const {
36 if (isa<FunctionSymbol>(this))42 if (isa<FunctionSymbol>(this))
...@@ -41,238 +47,260 @@ WasmSymbolType Symbol::getWasmType() const {...@@ -41,238 +47,260 @@ WasmSymbolType Symbol::getWasmType() const {
41 return WASM_SYMBOL_TYPE_GLOBAL;47 return WASM_SYMBOL_TYPE_GLOBAL;
42 if (isa<EventSymbol>(this))48 if (isa<EventSymbol>(this))
43 return WASM_SYMBOL_TYPE_EVENT;49 return WASM_SYMBOL_TYPE_EVENT;
44 if (isa<SectionSymbol>(this))50 if (isa<SectionSymbol>(this) || isa<OutputSectionSymbol>(this))
45 return WASM_SYMBOL_TYPE_SECTION;51 return WASM_SYMBOL_TYPE_SECTION;
46 llvm_unreachable("invalid symbol kind");52 llvm_unreachable("invalid symbol kind");
47}53}
4854
55const WasmSignature *Symbol::getSignature() const {
56 if (auto* f = dyn_cast<FunctionSymbol>(this))
57 return f->signature;
58 if (auto *l = dyn_cast<LazySymbol>(this))
59 return l->signature;
60 return nullptr;
61}
62
49InputChunk *Symbol::getChunk() const {63InputChunk *Symbol::getChunk() const {
50 if (auto *F = dyn_cast<DefinedFunction>(this))64 if (auto *f = dyn_cast<DefinedFunction>(this))
51 return F->Function;65 return f->function;
52 if (auto *D = dyn_cast<DefinedData>(this))66 if (auto *d = dyn_cast<DefinedData>(this))
53 return D->Segment;67 return d->segment;
54 return nullptr;68 return nullptr;
55}69}
5670
71bool Symbol::isDiscarded() const {
72 if (InputChunk *c = getChunk())
73 return c->discarded;
74 return false;
75}
76
57bool Symbol::isLive() const {77bool Symbol::isLive() const {
58 if (auto *G = dyn_cast<DefinedGlobal>(this))78 if (auto *g = dyn_cast<DefinedGlobal>(this))
59 return G->Global->Live;79 return g->global->live;
60 if (auto *E = dyn_cast<DefinedEvent>(this))80 if (auto *e = dyn_cast<DefinedEvent>(this))
61 return E->Event->Live;81 return e->event->live;
62 if (InputChunk *C = getChunk())82 if (InputChunk *c = getChunk())
63 return C->Live;83 return c->live;
64 return Referenced;84 return referenced;
65}85}
6686
67void Symbol::markLive() {87void Symbol::markLive() {
68 if (auto *G = dyn_cast<DefinedGlobal>(this))88 assert(!isDiscarded());
69 G->Global->Live = true;89 if (auto *g = dyn_cast<DefinedGlobal>(this))
70 if (auto *E = dyn_cast<DefinedEvent>(this))90 g->global->live = true;
71 E->Event->Live = true;91 if (auto *e = dyn_cast<DefinedEvent>(this))
72 if (InputChunk *C = getChunk())92 e->event->live = true;
73 C->Live = true;93 if (InputChunk *c = getChunk())
74 Referenced = true;94 c->live = true;
95 referenced = true;
75}96}
7697
77uint32_t Symbol::getOutputSymbolIndex() const {98uint32_t Symbol::getOutputSymbolIndex() const {
78 assert(OutputSymbolIndex != INVALID_INDEX);99 assert(outputSymbolIndex != INVALID_INDEX);
79 return OutputSymbolIndex;100 return outputSymbolIndex;
80}101}
81102
82void Symbol::setOutputSymbolIndex(uint32_t Index) {103void Symbol::setOutputSymbolIndex(uint32_t index) {
83 LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << Name << " -> " << Index104 LLVM_DEBUG(dbgs() << "setOutputSymbolIndex " << name << " -> " << index
84 << "\n");105 << "\n");
85 assert(OutputSymbolIndex == INVALID_INDEX);106 assert(outputSymbolIndex == INVALID_INDEX);
86 OutputSymbolIndex = Index;107 outputSymbolIndex = index;
108}
109
110void Symbol::setGOTIndex(uint32_t index) {
111 LLVM_DEBUG(dbgs() << "setGOTIndex " << name << " -> " << index << "\n");
112 assert(gotIndex == INVALID_INDEX);
113 // Any symbol that is assigned a GOT entry must be exported othewise the
114 // dynamic linker won't be able create the entry that contains it.
115 forceExport = true;
116 gotIndex = index;
87}117}
88118
89bool Symbol::isWeak() const {119bool Symbol::isWeak() const {
90 return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK;120 return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_WEAK;
91}121}
92122
93bool Symbol::isLocal() const {123bool Symbol::isLocal() const {
94 return (Flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL;124 return (flags & WASM_SYMBOL_BINDING_MASK) == WASM_SYMBOL_BINDING_LOCAL;
95}125}
96126
97bool Symbol::isHidden() const {127bool Symbol::isHidden() const {
98 return (Flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;128 return (flags & WASM_SYMBOL_VISIBILITY_MASK) == WASM_SYMBOL_VISIBILITY_HIDDEN;
99}129}
100130
101void Symbol::setHidden(bool IsHidden) {131void Symbol::setHidden(bool isHidden) {
102 LLVM_DEBUG(dbgs() << "setHidden: " << Name << " -> " << IsHidden << "\n");132 LLVM_DEBUG(dbgs() << "setHidden: " << name << " -> " << isHidden << "\n");
103 Flags &= ~WASM_SYMBOL_VISIBILITY_MASK;133 flags &= ~WASM_SYMBOL_VISIBILITY_MASK;
104 if (IsHidden)134 if (isHidden)
105 Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;135 flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
106 else136 else
107 Flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;137 flags |= WASM_SYMBOL_VISIBILITY_DEFAULT;
108}138}
109139
110bool Symbol::isExported() const {140bool Symbol::isExported() const {
111 if (!isDefined() || isLocal())141 if (!isDefined() || isLocal())
112 return false;142 return false;
113143
114 if (ForceExport || Config->ExportAll)144 if (forceExport || config->exportAll)
115 return true;145 return true;
116146
117 if (Config->ExportDynamic && !isHidden())147 if (config->exportDynamic && !isHidden())
118 return true;148 return true;
119149
120 return false;150 return flags & WASM_SYMBOL_EXPORTED;
121}151}
122152
123uint32_t FunctionSymbol::getFunctionIndex() const {153uint32_t FunctionSymbol::getFunctionIndex() const {
124 if (auto *F = dyn_cast<DefinedFunction>(this))154 if (auto *f = dyn_cast<DefinedFunction>(this))
125 return F->Function->getFunctionIndex();155 return f->function->getFunctionIndex();
126 assert(FunctionIndex != INVALID_INDEX);156 assert(functionIndex != INVALID_INDEX);
127 return FunctionIndex;157 return functionIndex;
128}158}
129159
130void FunctionSymbol::setFunctionIndex(uint32_t Index) {160void FunctionSymbol::setFunctionIndex(uint32_t index) {
131 LLVM_DEBUG(dbgs() << "setFunctionIndex " << Name << " -> " << Index << "\n");161 LLVM_DEBUG(dbgs() << "setFunctionIndex " << name << " -> " << index << "\n");
132 assert(FunctionIndex == INVALID_INDEX);162 assert(functionIndex == INVALID_INDEX);
133 FunctionIndex = Index;163 functionIndex = index;
134}164}
135165
136bool FunctionSymbol::hasFunctionIndex() const {166bool FunctionSymbol::hasFunctionIndex() const {
137 if (auto *F = dyn_cast<DefinedFunction>(this))167 if (auto *f = dyn_cast<DefinedFunction>(this))
138 return F->Function->hasFunctionIndex();168 return f->function->hasFunctionIndex();
139 return FunctionIndex != INVALID_INDEX;169 return functionIndex != INVALID_INDEX;
140}170}
141171
142uint32_t FunctionSymbol::getTableIndex() const {172uint32_t FunctionSymbol::getTableIndex() const {
143 if (auto *F = dyn_cast<DefinedFunction>(this))173 if (auto *f = dyn_cast<DefinedFunction>(this))
144 return F->Function->getTableIndex();174 return f->function->getTableIndex();
145 assert(TableIndex != INVALID_INDEX);175 assert(tableIndex != INVALID_INDEX);
146 return TableIndex;176 return tableIndex;
147}177}
148178
149bool FunctionSymbol::hasTableIndex() const {179bool FunctionSymbol::hasTableIndex() const {
150 if (auto *F = dyn_cast<DefinedFunction>(this))180 if (auto *f = dyn_cast<DefinedFunction>(this))
151 return F->Function->hasTableIndex();181 return f->function->hasTableIndex();
152 return TableIndex != INVALID_INDEX;182 return tableIndex != INVALID_INDEX;
153}183}
154184
155void FunctionSymbol::setTableIndex(uint32_t Index) {185void FunctionSymbol::setTableIndex(uint32_t index) {
156 // For imports, we set the table index here on the Symbol; for defined186 // For imports, we set the table index here on the Symbol; for defined
157 // functions we set the index on the InputFunction so that we don't export187 // functions we set the index on the InputFunction so that we don't export
158 // the same thing twice (keeps the table size down).188 // the same thing twice (keeps the table size down).
159 if (auto *F = dyn_cast<DefinedFunction>(this)) {189 if (auto *f = dyn_cast<DefinedFunction>(this)) {
160 F->Function->setTableIndex(Index);190 f->function->setTableIndex(index);
161 return;191 return;
162 }192 }
163 LLVM_DEBUG(dbgs() << "setTableIndex " << Name << " -> " << Index << "\n");193 LLVM_DEBUG(dbgs() << "setTableIndex " << name << " -> " << index << "\n");
164 assert(TableIndex == INVALID_INDEX);194 assert(tableIndex == INVALID_INDEX);
165 TableIndex = Index;195 tableIndex = index;
166}196}
167197
168DefinedFunction::DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F,198DefinedFunction::DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
169 InputFunction *Function)199 InputFunction *function)
170 : FunctionSymbol(Name, DefinedFunctionKind, Flags, F,200 : FunctionSymbol(name, DefinedFunctionKind, flags, f,
171 Function ? &Function->Signature : nullptr),201 function ? &function->signature : nullptr),
172 Function(Function) {}202 function(function) {}
173203
174uint32_t DefinedData::getVirtualAddress() const {204uint32_t DefinedData::getVirtualAddress() const {
175 LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");205 LLVM_DEBUG(dbgs() << "getVirtualAddress: " << getName() << "\n");
176 if (Segment)206 if (segment) {
177 return Segment->OutputSeg->StartVA + Segment->OutputSegmentOffset + Offset;207 // For thread local data, the symbol location is relative to the start of
178 return Offset;208 // the .tdata section, since they are used as offsets from __tls_base.
209 // Hence, we do not add in segment->outputSeg->startVA.
210 if (segment->outputSeg->name == ".tdata")
211 return segment->outputSegmentOffset + offset;
212 return segment->outputSeg->startVA + segment->outputSegmentOffset + offset;
213 }
214 return offset;
179}215}
180216
181void DefinedData::setVirtualAddress(uint32_t Value) {217void DefinedData::setVirtualAddress(uint32_t value) {
182 LLVM_DEBUG(dbgs() << "setVirtualAddress " << Name << " -> " << Value << "\n");218 LLVM_DEBUG(dbgs() << "setVirtualAddress " << name << " -> " << value << "\n");
183 assert(!Segment);219 assert(!segment);
184 Offset = Value;220 offset = value;
185}221}
186222
187uint32_t DefinedData::getOutputSegmentOffset() const {223uint32_t DefinedData::getOutputSegmentOffset() const {
188 LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");224 LLVM_DEBUG(dbgs() << "getOutputSegmentOffset: " << getName() << "\n");
189 return Segment->OutputSegmentOffset + Offset;225 return segment->outputSegmentOffset + offset;
190}226}
191227
192uint32_t DefinedData::getOutputSegmentIndex() const {228uint32_t DefinedData::getOutputSegmentIndex() const {
193 LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n");229 LLVM_DEBUG(dbgs() << "getOutputSegmentIndex: " << getName() << "\n");
194 return Segment->OutputSeg->Index;230 return segment->outputSeg->index;
195}231}
196232
197uint32_t GlobalSymbol::getGlobalIndex() const {233uint32_t GlobalSymbol::getGlobalIndex() const {
198 if (auto *F = dyn_cast<DefinedGlobal>(this))234 if (auto *f = dyn_cast<DefinedGlobal>(this))
199 return F->Global->getGlobalIndex();235 return f->global->getGlobalIndex();
200 assert(GlobalIndex != INVALID_INDEX);236 assert(globalIndex != INVALID_INDEX);
201 return GlobalIndex;237 return globalIndex;
202}238}
203239
204void GlobalSymbol::setGlobalIndex(uint32_t Index) {240void GlobalSymbol::setGlobalIndex(uint32_t index) {
205 LLVM_DEBUG(dbgs() << "setGlobalIndex " << Name << " -> " << Index << "\n");241 LLVM_DEBUG(dbgs() << "setGlobalIndex " << name << " -> " << index << "\n");
206 assert(GlobalIndex == INVALID_INDEX);242 assert(globalIndex == INVALID_INDEX);
207 GlobalIndex = Index;243 globalIndex = index;
208}244}
209245
210bool GlobalSymbol::hasGlobalIndex() const {246bool GlobalSymbol::hasGlobalIndex() const {
211 if (auto *F = dyn_cast<DefinedGlobal>(this))247 if (auto *f = dyn_cast<DefinedGlobal>(this))
212 return F->Global->hasGlobalIndex();248 return f->global->hasGlobalIndex();
213 return GlobalIndex != INVALID_INDEX;249 return globalIndex != INVALID_INDEX;
214}250}
215251
216DefinedGlobal::DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,252DefinedGlobal::DefinedGlobal(StringRef name, uint32_t flags, InputFile *file,
217 InputGlobal *Global)253 InputGlobal *global)
218 : GlobalSymbol(Name, DefinedGlobalKind, Flags, File,254 : GlobalSymbol(name, DefinedGlobalKind, flags, file,
219 Global ? &Global->getType() : nullptr),255 global ? &global->getType() : nullptr),
220 Global(Global) {}256 global(global) {}
221257
222uint32_t EventSymbol::getEventIndex() const {258uint32_t EventSymbol::getEventIndex() const {
223 if (auto *F = dyn_cast<DefinedEvent>(this))259 if (auto *f = dyn_cast<DefinedEvent>(this))
224 return F->Event->getEventIndex();260 return f->event->getEventIndex();
225 assert(EventIndex != INVALID_INDEX);261 assert(eventIndex != INVALID_INDEX);
226 return EventIndex;262 return eventIndex;
227}263}
228264
229void EventSymbol::setEventIndex(uint32_t Index) {265void EventSymbol::setEventIndex(uint32_t index) {
230 LLVM_DEBUG(dbgs() << "setEventIndex " << Name << " -> " << Index << "\n");266 LLVM_DEBUG(dbgs() << "setEventIndex " << name << " -> " << index << "\n");
231 assert(EventIndex == INVALID_INDEX);267 assert(eventIndex == INVALID_INDEX);
232 EventIndex = Index;268 eventIndex = index;
233}269}
234270
235bool EventSymbol::hasEventIndex() const {271bool EventSymbol::hasEventIndex() const {
236 if (auto *F = dyn_cast<DefinedEvent>(this))272 if (auto *f = dyn_cast<DefinedEvent>(this))
237 return F->Event->hasEventIndex();273 return f->event->hasEventIndex();
238 return EventIndex != INVALID_INDEX;274 return eventIndex != INVALID_INDEX;
239}275}
240276
241DefinedEvent::DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,277DefinedEvent::DefinedEvent(StringRef name, uint32_t flags, InputFile *file,
242 InputEvent *Event)278 InputEvent *event)
243 : EventSymbol(Name, DefinedEventKind, Flags, File,279 : EventSymbol(name, DefinedEventKind, flags, file,
244 Event ? &Event->getType() : nullptr,280 event ? &event->getType() : nullptr,
245 Event ? &Event->Signature : nullptr),281 event ? &event->signature : nullptr),
246 Event(Event) {}282 event(event) {}
247
248uint32_t SectionSymbol::getOutputSectionIndex() const {
249 LLVM_DEBUG(dbgs() << "getOutputSectionIndex: " << getName() << "\n");
250 assert(OutputSectionIndex != INVALID_INDEX);
251 return OutputSectionIndex;
252}
253283
254void SectionSymbol::setOutputSectionIndex(uint32_t Index) {284const OutputSectionSymbol *SectionSymbol::getOutputSectionSymbol() const {
255 LLVM_DEBUG(dbgs() << "setOutputSectionIndex: " << getName() << " -> " << Index285 assert(section->outputSec && section->outputSec->sectionSym);
256 << "\n");286 return section->outputSec->sectionSym;
257 assert(Index != INVALID_INDEX);
258 OutputSectionIndex = Index;
259}287}
260288
261void LazySymbol::fetch() { cast<ArchiveFile>(File)->addMember(&ArchiveSymbol); }289void LazySymbol::fetch() { cast<ArchiveFile>(file)->addMember(&archiveSymbol); }
262290
263std::string lld::toString(const wasm::Symbol &Sym) {291std::string lld::toString(const wasm::Symbol &sym) {
264 return lld::maybeDemangleSymbol(Sym.getName());292 return lld::maybeDemangleSymbol(sym.getName());
265}293}
266294
267std::string lld::maybeDemangleSymbol(StringRef Name) {295std::string lld::maybeDemangleSymbol(StringRef name) {
268 if (Config->Demangle)296 if (config->demangle)
269 if (Optional<std::string> S = demangleItanium(Name))297 if (Optional<std::string> s = demangleItanium(name))
270 return *S;298 return *s;
271 return Name;299 return name;
272}300}
273301
274std::string lld::toString(wasm::Symbol::Kind Kind) {302std::string lld::toString(wasm::Symbol::Kind kind) {
275 switch (Kind) {303 switch (kind) {
276 case wasm::Symbol::DefinedFunctionKind:304 case wasm::Symbol::DefinedFunctionKind:
277 return "DefinedFunction";305 return "DefinedFunction";
278 case wasm::Symbol::DefinedDataKind:306 case wasm::Symbol::DefinedDataKind:
...@@ -291,6 +319,31 @@ std::string lld::toString(wasm::Symbol::Kind Kind) {...@@ -291,6 +319,31 @@ std::string lld::toString(wasm::Symbol::Kind Kind) {
291 return "LazyKind";319 return "LazyKind";
292 case wasm::Symbol::SectionKind:320 case wasm::Symbol::SectionKind:
293 return "SectionKind";321 return "SectionKind";
322 case wasm::Symbol::OutputSectionKind:
323 return "OutputSectionKind";
294 }324 }
295 llvm_unreachable("invalid symbol kind");325 llvm_unreachable("invalid symbol kind");
296}326}
327
328
329void lld::wasm::printTraceSymbolUndefined(StringRef name, const InputFile* file) {
330 message(toString(file) + ": reference to " + name);
331}
332
333// Print out a log message for --trace-symbol.
334void lld::wasm::printTraceSymbol(Symbol *sym) {
335 // Undefined symbols are traced via printTraceSymbolUndefined
336 if (sym->isUndefined())
337 return;
338
339 std::string s;
340 if (sym->isLazy())
341 s = ": lazy definition of ";
342 else
343 s = ": definition of ";
344
345 message(toString(sym->getFile()) + s + sym->getName());
346}
347
348const char *lld::wasm::defaultModule = "env";
349const char *lld::wasm::functionTableName = "__indirect_function_table";
deps/lld/wasm/Symbols.h+273-155
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Symbols.h ------------------------------------------------*- C++ -*-===//1//===- Symbols.h ------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -18,6 +17,14 @@...@@ -18,6 +17,14 @@
18namespace lld {17namespace lld {
19namespace wasm {18namespace wasm {
2019
20// Shared string constants
21
22// The default module name to use for symbol imports.
23extern const char *defaultModule;
24
25// The name under which to import or export the wasm table.
26extern const char *functionTableName;
27
21using llvm::wasm::WasmSymbolType;28using llvm::wasm::WasmSymbolType;
2229
23class InputFile;30class InputFile;
...@@ -27,48 +34,58 @@ class InputFunction;...@@ -27,48 +34,58 @@ class InputFunction;
27class InputGlobal;34class InputGlobal;
28class InputEvent;35class InputEvent;
29class InputSection;36class InputSection;
37class OutputSection;
3038
31#define INVALID_INDEX UINT32_MAX39#define INVALID_INDEX UINT32_MAX
3240
33// The base class for real symbol classes.41// The base class for real symbol classes.
34class Symbol {42class Symbol {
35public:43public:
36 enum Kind {44 enum Kind : uint8_t {
37 DefinedFunctionKind,45 DefinedFunctionKind,
38 DefinedDataKind,46 DefinedDataKind,
39 DefinedGlobalKind,47 DefinedGlobalKind,
40 DefinedEventKind,48 DefinedEventKind,
41 SectionKind,49 SectionKind,
50 OutputSectionKind,
42 UndefinedFunctionKind,51 UndefinedFunctionKind,
43 UndefinedDataKind,52 UndefinedDataKind,
44 UndefinedGlobalKind,53 UndefinedGlobalKind,
45 LazyKind,54 LazyKind,
46 };55 };
4756
48 Kind kind() const { return SymbolKind; }57 Kind kind() const { return symbolKind; }
4958
50 bool isDefined() const {59 bool isDefined() const { return !isLazy() && !isUndefined(); }
51 return SymbolKind == DefinedFunctionKind || SymbolKind == DefinedDataKind ||
52 SymbolKind == DefinedGlobalKind || SymbolKind == DefinedEventKind ||
53 SymbolKind == SectionKind;
54 }
5560
56 bool isUndefined() const {61 bool isUndefined() const {
57 return SymbolKind == UndefinedFunctionKind ||62 return symbolKind == UndefinedFunctionKind ||
58 SymbolKind == UndefinedDataKind || SymbolKind == UndefinedGlobalKind;63 symbolKind == UndefinedDataKind || symbolKind == UndefinedGlobalKind;
59 }64 }
6065
61 bool isLazy() const { return SymbolKind == LazyKind; }66 bool isLazy() const { return symbolKind == LazyKind; }
6267
63 bool isLocal() const;68 bool isLocal() const;
64 bool isWeak() const;69 bool isWeak() const;
65 bool isHidden() const;70 bool isHidden() const;
6671
72 // Returns true if this symbol exists in a discarded (due to COMDAT) section
73 bool isDiscarded() const;
74
75 // True if this is an undefined weak symbol. This only works once
76 // all input files have been added.
77 bool isUndefWeak() const {
78 // See comment on lazy symbols for details.
79 return isWeak() && (isUndefined() || isLazy());
80 }
81
67 // Returns the symbol name.82 // Returns the symbol name.
68 StringRef getName() const { return Name; }83 StringRef getName() const { return name; }
6984
70 // Returns the file from which this symbol was created.85 // Returns the file from which this symbol was created.
71 InputFile *getFile() const { return File; }86 InputFile *getFile() const { return file; }
87
88 uint32_t getFlags() const { return flags; }
7289
73 InputChunk *getChunk() const;90 InputChunk *getChunk() const;
7491
...@@ -80,205 +97,249 @@ public:...@@ -80,205 +97,249 @@ public:
80 // final image.97 // final image.
81 void markLive();98 void markLive();
8299
83 void setHidden(bool IsHidden);100 void setHidden(bool isHidden);
84101
85 // Get/set the index in the output symbol table. This is only used for102 // Get/set the index in the output symbol table. This is only used for
86 // relocatable output.103 // relocatable output.
87 uint32_t getOutputSymbolIndex() const;104 uint32_t getOutputSymbolIndex() const;
88 void setOutputSymbolIndex(uint32_t Index);105 void setOutputSymbolIndex(uint32_t index);
89106
90 WasmSymbolType getWasmType() const;107 WasmSymbolType getWasmType() const;
91 bool isExported() const;108 bool isExported() const;
92109
93 // True if this symbol was referenced by a regular (non-bitcode) object.110 const WasmSignature* getSignature() const;
94 unsigned IsUsedInRegularObj : 1;111
95 unsigned ForceExport : 1;112 bool isInGOT() const { return gotIndex != INVALID_INDEX; }
113
114 uint32_t getGOTIndex() const {
115 assert(gotIndex != INVALID_INDEX);
116 return gotIndex;
117 }
118
119 void setGOTIndex(uint32_t index);
120 bool hasGOTIndex() const { return gotIndex != INVALID_INDEX; }
96121
97protected:122protected:
98 Symbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F)123 Symbol(StringRef name, Kind k, uint32_t flags, InputFile *f)
99 : IsUsedInRegularObj(false), ForceExport(false), Name(Name),124 : name(name), file(f), flags(flags), symbolKind(k),
100 SymbolKind(K), Flags(Flags), File(F), Referenced(!Config->GcSections) {}125 referenced(!config->gcSections), isUsedInRegularObj(false),
101126 forceExport(false), canInline(false), traced(false) {}
102 StringRef Name;127
103 Kind SymbolKind;128 StringRef name;
104 uint32_t Flags;129 InputFile *file;
105 InputFile *File;130 uint32_t flags;
106 uint32_t OutputSymbolIndex = INVALID_INDEX;131 uint32_t outputSymbolIndex = INVALID_INDEX;
107 bool Referenced;132 uint32_t gotIndex = INVALID_INDEX;
133 Kind symbolKind;
134
135public:
136 bool referenced : 1;
137
138 // True if the symbol was used for linking and thus need to be added to the
139 // output file's symbol table. This is true for all symbols except for
140 // unreferenced DSO symbols, lazy (archive) symbols, and bitcode symbols that
141 // are unreferenced except by other bitcode objects.
142 bool isUsedInRegularObj : 1;
143
144 // True if ths symbol is explicity marked for export (i.e. via the -e/--export
145 // command line flag)
146 bool forceExport : 1;
147
148 // False if LTO shouldn't inline whatever this symbol points to. If a symbol
149 // is overwritten after LTO, LTO shouldn't inline the symbol because it
150 // doesn't know the final contents of the symbol.
151 bool canInline : 1;
152
153 // True if this symbol is specified by --trace-symbol option.
154 bool traced : 1;
108};155};
109156
110class FunctionSymbol : public Symbol {157class FunctionSymbol : public Symbol {
111public:158public:
112 static bool classof(const Symbol *S) {159 static bool classof(const Symbol *s) {
113 return S->kind() == DefinedFunctionKind ||160 return s->kind() == DefinedFunctionKind ||
114 S->kind() == UndefinedFunctionKind;161 s->kind() == UndefinedFunctionKind;
115 }162 }
116163
117 // Get/set the table index164 // Get/set the table index
118 void setTableIndex(uint32_t Index);165 void setTableIndex(uint32_t index);
119 uint32_t getTableIndex() const;166 uint32_t getTableIndex() const;
120 bool hasTableIndex() const;167 bool hasTableIndex() const;
121168
122 // Get/set the function index169 // Get/set the function index
123 uint32_t getFunctionIndex() const;170 uint32_t getFunctionIndex() const;
124 void setFunctionIndex(uint32_t Index);171 void setFunctionIndex(uint32_t index);
125 bool hasFunctionIndex() const;172 bool hasFunctionIndex() const;
126173
127 const WasmSignature *Signature;174 const WasmSignature *signature;
128175
129protected:176protected:
130 FunctionSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,177 FunctionSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
131 const WasmSignature *Sig)178 const WasmSignature *sig)
132 : Symbol(Name, K, Flags, F), Signature(Sig) {}179 : Symbol(name, k, flags, f), signature(sig) {}
133180
134 uint32_t TableIndex = INVALID_INDEX;181 uint32_t tableIndex = INVALID_INDEX;
135 uint32_t FunctionIndex = INVALID_INDEX;182 uint32_t functionIndex = INVALID_INDEX;
136};183};
137184
138class DefinedFunction : public FunctionSymbol {185class DefinedFunction : public FunctionSymbol {
139public:186public:
140 DefinedFunction(StringRef Name, uint32_t Flags, InputFile *F,187 DefinedFunction(StringRef name, uint32_t flags, InputFile *f,
141 InputFunction *Function);188 InputFunction *function);
142189
143 static bool classof(const Symbol *S) {190 static bool classof(const Symbol *s) {
144 return S->kind() == DefinedFunctionKind;191 return s->kind() == DefinedFunctionKind;
145 }192 }
146193
147 InputFunction *Function;194 InputFunction *function;
148};195};
149196
150class UndefinedFunction : public FunctionSymbol {197class UndefinedFunction : public FunctionSymbol {
151public:198public:
152 UndefinedFunction(StringRef Name, StringRef ImportName,199 UndefinedFunction(StringRef name, StringRef importName,
153 StringRef ImportModule, uint32_t Flags,200 StringRef importModule, uint32_t flags,
154 InputFile *File = nullptr,201 InputFile *file = nullptr,
155 const WasmSignature *Type = nullptr)202 const WasmSignature *type = nullptr,
156 : FunctionSymbol(Name, UndefinedFunctionKind, Flags, File, Type),203 bool isCalledDirectly = true)
157 ImportName(ImportName), ImportModule(ImportModule) {}204 : FunctionSymbol(name, UndefinedFunctionKind, flags, file, type),
158205 importName(importName), importModule(importModule), isCalledDirectly(isCalledDirectly) {}
159 static bool classof(const Symbol *S) {206
160 return S->kind() == UndefinedFunctionKind;207 static bool classof(const Symbol *s) {
208 return s->kind() == UndefinedFunctionKind;
161 }209 }
162210
163 StringRef ImportName;211 StringRef importName;
164 StringRef ImportModule;212 StringRef importModule;
213 bool isCalledDirectly;
165};214};
166215
167class SectionSymbol : public Symbol {216// Section symbols for output sections are different from those for input
217// section. These are generated by the linker and point the OutputSection
218// rather than an InputSection.
219class OutputSectionSymbol : public Symbol {
168public:220public:
169 static bool classof(const Symbol *S) { return S->kind() == SectionKind; }221 OutputSectionSymbol(const OutputSection *s)
222 : Symbol("", OutputSectionKind, llvm::wasm::WASM_SYMBOL_BINDING_LOCAL,
223 nullptr),
224 section(s) {}
170225
171 SectionSymbol(StringRef Name, uint32_t Flags, const InputSection *S,226 static bool classof(const Symbol *s) {
172 InputFile *F = nullptr)227 return s->kind() == OutputSectionKind;
173 : Symbol(Name, SectionKind, Flags, F), Section(S) {}228 }
174229
175 const InputSection *Section;230 const OutputSection *section;
231};
176232
177 uint32_t getOutputSectionIndex() const;233class SectionSymbol : public Symbol {
178 void setOutputSectionIndex(uint32_t Index);234public:
235 SectionSymbol(uint32_t flags, const InputSection *s, InputFile *f = nullptr)
236 : Symbol("", SectionKind, flags, f), section(s) {}
179237
180protected:238 static bool classof(const Symbol *s) { return s->kind() == SectionKind; }
181 uint32_t OutputSectionIndex = INVALID_INDEX;239
240 const OutputSectionSymbol *getOutputSectionSymbol() const;
241
242 const InputSection *section;
182};243};
183244
184class DataSymbol : public Symbol {245class DataSymbol : public Symbol {
185public:246public:
186 static bool classof(const Symbol *S) {247 static bool classof(const Symbol *s) {
187 return S->kind() == DefinedDataKind || S->kind() == UndefinedDataKind;248 return s->kind() == DefinedDataKind || s->kind() == UndefinedDataKind;
188 }249 }
189250
190protected:251protected:
191 DataSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F)252 DataSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f)
192 : Symbol(Name, K, Flags, F) {}253 : Symbol(name, k, flags, f) {}
193};254};
194255
195class DefinedData : public DataSymbol {256class DefinedData : public DataSymbol {
196public:257public:
197 // Constructor for regular data symbols originating from input files.258 // Constructor for regular data symbols originating from input files.
198 DefinedData(StringRef Name, uint32_t Flags, InputFile *F,259 DefinedData(StringRef name, uint32_t flags, InputFile *f,
199 InputSegment *Segment, uint32_t Offset, uint32_t Size)260 InputSegment *segment, uint32_t offset, uint32_t size)
200 : DataSymbol(Name, DefinedDataKind, Flags, F), Segment(Segment),261 : DataSymbol(name, DefinedDataKind, flags, f), segment(segment),
201 Offset(Offset), Size(Size) {}262 offset(offset), size(size) {}
202263
203 // Constructor for linker synthetic data symbols.264 // Constructor for linker synthetic data symbols.
204 DefinedData(StringRef Name, uint32_t Flags)265 DefinedData(StringRef name, uint32_t flags)
205 : DataSymbol(Name, DefinedDataKind, Flags, nullptr) {}266 : DataSymbol(name, DefinedDataKind, flags, nullptr) {}
206267
207 static bool classof(const Symbol *S) { return S->kind() == DefinedDataKind; }268 static bool classof(const Symbol *s) { return s->kind() == DefinedDataKind; }
208269
209 // Returns the output virtual address of a defined data symbol.270 // Returns the output virtual address of a defined data symbol.
210 uint32_t getVirtualAddress() const;271 uint32_t getVirtualAddress() const;
211 void setVirtualAddress(uint32_t VA);272 void setVirtualAddress(uint32_t va);
212273
213 // Returns the offset of a defined data symbol within its OutputSegment.274 // Returns the offset of a defined data symbol within its OutputSegment.
214 uint32_t getOutputSegmentOffset() const;275 uint32_t getOutputSegmentOffset() const;
215 uint32_t getOutputSegmentIndex() const;276 uint32_t getOutputSegmentIndex() const;
216 uint32_t getSize() const { return Size; }277 uint32_t getSize() const { return size; }
217278
218 InputSegment *Segment = nullptr;279 InputSegment *segment = nullptr;
219280
220protected:281protected:
221 uint32_t Offset = 0;282 uint32_t offset = 0;
222 uint32_t Size = 0;283 uint32_t size = 0;
223};284};
224285
225class UndefinedData : public DataSymbol {286class UndefinedData : public DataSymbol {
226public:287public:
227 UndefinedData(StringRef Name, uint32_t Flags, InputFile *File = nullptr)288 UndefinedData(StringRef name, uint32_t flags, InputFile *file = nullptr)
228 : DataSymbol(Name, UndefinedDataKind, Flags, File) {}289 : DataSymbol(name, UndefinedDataKind, flags, file) {}
229 static bool classof(const Symbol *S) {290 static bool classof(const Symbol *s) {
230 return S->kind() == UndefinedDataKind;291 return s->kind() == UndefinedDataKind;
231 }292 }
232};293};
233294
234class GlobalSymbol : public Symbol {295class GlobalSymbol : public Symbol {
235public:296public:
236 static bool classof(const Symbol *S) {297 static bool classof(const Symbol *s) {
237 return S->kind() == DefinedGlobalKind || S->kind() == UndefinedGlobalKind;298 return s->kind() == DefinedGlobalKind || s->kind() == UndefinedGlobalKind;
238 }299 }
239300
240 const WasmGlobalType *getGlobalType() const { return GlobalType; }301 const WasmGlobalType *getGlobalType() const { return globalType; }
241302
242 // Get/set the global index303 // Get/set the global index
243 uint32_t getGlobalIndex() const;304 uint32_t getGlobalIndex() const;
244 void setGlobalIndex(uint32_t Index);305 void setGlobalIndex(uint32_t index);
245 bool hasGlobalIndex() const;306 bool hasGlobalIndex() const;
246307
247protected:308protected:
248 GlobalSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,309 GlobalSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
249 const WasmGlobalType *GlobalType)310 const WasmGlobalType *globalType)
250 : Symbol(Name, K, Flags, F), GlobalType(GlobalType) {}311 : Symbol(name, k, flags, f), globalType(globalType) {}
251312
252 const WasmGlobalType *GlobalType;313 const WasmGlobalType *globalType;
253 uint32_t GlobalIndex = INVALID_INDEX;314 uint32_t globalIndex = INVALID_INDEX;
254};315};
255316
256class DefinedGlobal : public GlobalSymbol {317class DefinedGlobal : public GlobalSymbol {
257public:318public:
258 DefinedGlobal(StringRef Name, uint32_t Flags, InputFile *File,319 DefinedGlobal(StringRef name, uint32_t flags, InputFile *file,
259 InputGlobal *Global);320 InputGlobal *global);
260321
261 static bool classof(const Symbol *S) {322 static bool classof(const Symbol *s) {
262 return S->kind() == DefinedGlobalKind;323 return s->kind() == DefinedGlobalKind;
263 }324 }
264325
265 InputGlobal *Global;326 InputGlobal *global;
266};327};
267328
268class UndefinedGlobal : public GlobalSymbol {329class UndefinedGlobal : public GlobalSymbol {
269public:330public:
270 UndefinedGlobal(StringRef Name, StringRef ImportName, StringRef ImportModule,331 UndefinedGlobal(StringRef name, StringRef importName, StringRef importModule,
271 uint32_t Flags, InputFile *File = nullptr,332 uint32_t flags, InputFile *file = nullptr,
272 const WasmGlobalType *Type = nullptr)333 const WasmGlobalType *type = nullptr)
273 : GlobalSymbol(Name, UndefinedGlobalKind, Flags, File, Type),334 : GlobalSymbol(name, UndefinedGlobalKind, flags, file, type),
274 ImportName(ImportName), ImportModule(ImportModule) {}335 importName(importName), importModule(importModule) {}
275336
276 static bool classof(const Symbol *S) {337 static bool classof(const Symbol *s) {
277 return S->kind() == UndefinedGlobalKind;338 return s->kind() == UndefinedGlobalKind;
278 }339 }
279340
280 StringRef ImportName;341 StringRef importName;
281 StringRef ImportModule;342 StringRef importModule;
282};343};
283344
284// Wasm events are features that suspend the current execution and transfer the345// Wasm events are features that suspend the current execution and transfer the
...@@ -295,100 +356,149 @@ public:...@@ -295,100 +356,149 @@ public:
295// are used, and has name '__cpp_exception' for linking.356// are used, and has name '__cpp_exception' for linking.
296class EventSymbol : public Symbol {357class EventSymbol : public Symbol {
297public:358public:
298 static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; }359 static bool classof(const Symbol *s) { return s->kind() == DefinedEventKind; }
299360
300 const WasmEventType *getEventType() const { return EventType; }361 const WasmEventType *getEventType() const { return eventType; }
301362
302 // Get/set the event index363 // Get/set the event index
303 uint32_t getEventIndex() const;364 uint32_t getEventIndex() const;
304 void setEventIndex(uint32_t Index);365 void setEventIndex(uint32_t index);
305 bool hasEventIndex() const;366 bool hasEventIndex() const;
306367
307 const WasmSignature *Signature;368 const WasmSignature *signature;
308369
309protected:370protected:
310 EventSymbol(StringRef Name, Kind K, uint32_t Flags, InputFile *F,371 EventSymbol(StringRef name, Kind k, uint32_t flags, InputFile *f,
311 const WasmEventType *EventType, const WasmSignature *Sig)372 const WasmEventType *eventType, const WasmSignature *sig)
312 : Symbol(Name, K, Flags, F), Signature(Sig), EventType(EventType) {}373 : Symbol(name, k, flags, f), signature(sig), eventType(eventType) {}
313374
314 const WasmEventType *EventType;375 const WasmEventType *eventType;
315 uint32_t EventIndex = INVALID_INDEX;376 uint32_t eventIndex = INVALID_INDEX;
316};377};
317378
318class DefinedEvent : public EventSymbol {379class DefinedEvent : public EventSymbol {
319public:380public:
320 DefinedEvent(StringRef Name, uint32_t Flags, InputFile *File,381 DefinedEvent(StringRef name, uint32_t flags, InputFile *file,
321 InputEvent *Event);382 InputEvent *event);
322383
323 static bool classof(const Symbol *S) { return S->kind() == DefinedEventKind; }384 static bool classof(const Symbol *s) { return s->kind() == DefinedEventKind; }
324385
325 InputEvent *Event;386 InputEvent *event;
326};387};
327388
389// LazySymbol represents a symbol that is not yet in the link, but we know where
390// to find it if needed. If the resolver finds both Undefined and Lazy for the
391// same name, it will ask the Lazy to load a file.
392//
393// A special complication is the handling of weak undefined symbols. They should
394// not load a file, but we have to remember we have seen both the weak undefined
395// and the lazy. We represent that with a lazy symbol with a weak binding. This
396// means that code looking for undefined symbols normally also has to take lazy
397// symbols into consideration.
328class LazySymbol : public Symbol {398class LazySymbol : public Symbol {
329public:399public:
330 LazySymbol(StringRef Name, InputFile *File,400 LazySymbol(StringRef name, uint32_t flags, InputFile *file,
331 const llvm::object::Archive::Symbol &Sym)401 const llvm::object::Archive::Symbol &sym)
332 : Symbol(Name, LazyKind, 0, File), ArchiveSymbol(Sym) {}402 : Symbol(name, LazyKind, flags, file), archiveSymbol(sym) {}
333403
334 static bool classof(const Symbol *S) { return S->kind() == LazyKind; }404 static bool classof(const Symbol *s) { return s->kind() == LazyKind; }
335 void fetch();405 void fetch();
336406
407 // Lazy symbols can have a signature because they can replace an
408 // UndefinedFunction which which case we need to be able to preserve the
409 // signture.
410 // TODO(sbc): This repetition of the signature field is inelegant. Revisit
411 // the use of class hierarchy to represent symbol taxonomy.
412 const WasmSignature *signature = nullptr;
413
337private:414private:
338 llvm::object::Archive::Symbol ArchiveSymbol;415 llvm::object::Archive::Symbol archiveSymbol;
339};416};
340417
341// linker-generated symbols418// linker-generated symbols
342struct WasmSym {419struct WasmSym {
420 // __global_base
421 // Symbol marking the start of the global section.
422 static DefinedData *globalBase;
423
343 // __stack_pointer424 // __stack_pointer
344 // Global that holds the address of the top of the explicit value stack in425 // Global that holds the address of the top of the explicit value stack in
345 // linear memory.426 // linear memory.
346 static GlobalSymbol *StackPointer;427 static GlobalSymbol *stackPointer;
428
429 // __tls_base
430 // Global that holds the address of the base of the current thread's
431 // TLS block.
432 static GlobalSymbol *tlsBase;
433
434 // __tls_size
435 // Symbol whose value is the size of the TLS block.
436 static GlobalSymbol *tlsSize;
347437
348 // __data_end438 // __data_end
349 // Symbol marking the end of the data and bss.439 // Symbol marking the end of the data and bss.
350 static DefinedData *DataEnd;440 static DefinedData *dataEnd;
351441
352 // __heap_base442 // __heap_base
353 // Symbol marking the end of the data, bss and explicit stack. Any linear443 // Symbol marking the end of the data, bss and explicit stack. Any linear
354 // memory following this address is not used by the linked code and can444 // memory following this address is not used by the linked code and can
355 // therefore be used as a backing store for brk()/malloc() implementations.445 // therefore be used as a backing store for brk()/malloc() implementations.
356 static DefinedData *HeapBase;446 static DefinedData *heapBase;
357447
358 // __wasm_call_ctors448 // __wasm_call_ctors
359 // Function that directly calls all ctors in priority order.449 // Function that directly calls all ctors in priority order.
360 static DefinedFunction *CallCtors;450 static DefinedFunction *callCtors;
451
452 // __wasm_init_memory
453 // Function that initializes passive data segments post-instantiation.
454 static DefinedFunction *initMemory;
455
456 // __wasm_apply_relocs
457 // Function that applies relocations to data segment post-instantiation.
458 static DefinedFunction *applyRelocs;
459
460 // __wasm_init_tls
461 // Function that allocates thread-local storage and initializes it.
462 static DefinedFunction *initTLS;
361463
362 // __dso_handle464 // __dso_handle
363 // Symbol used in calls to __cxa_atexit to determine current DLL465 // Symbol used in calls to __cxa_atexit to determine current DLL
364 static DefinedData *DsoHandle;466 static DefinedData *dsoHandle;
365467
366 // __table_base468 // __table_base
367 // Used in PIC code for offset of indirect function table469 // Used in PIC code for offset of indirect function table
368 static UndefinedGlobal *TableBase;470 static UndefinedGlobal *tableBase;
369471
370 // __memory_base472 // __memory_base
371 // Used in PIC code for offset of global data473 // Used in PIC code for offset of global data
372 static UndefinedGlobal *MemoryBase;474 static UndefinedGlobal *memoryBase;
373};475};
374476
375// A buffer class that is large enough to hold any Symbol-derived477// A buffer class that is large enough to hold any Symbol-derived
376// object. We allocate memory using this class and instantiate a symbol478// object. We allocate memory using this class and instantiate a symbol
377// using the placement new.479// using the placement new.
378union SymbolUnion {480union SymbolUnion {
379 alignas(DefinedFunction) char A[sizeof(DefinedFunction)];481 alignas(DefinedFunction) char a[sizeof(DefinedFunction)];
380 alignas(DefinedData) char B[sizeof(DefinedData)];482 alignas(DefinedData) char b[sizeof(DefinedData)];
381 alignas(DefinedGlobal) char C[sizeof(DefinedGlobal)];483 alignas(DefinedGlobal) char c[sizeof(DefinedGlobal)];
382 alignas(DefinedEvent) char D[sizeof(DefinedEvent)];484 alignas(DefinedEvent) char d[sizeof(DefinedEvent)];
383 alignas(LazySymbol) char E[sizeof(LazySymbol)];485 alignas(LazySymbol) char e[sizeof(LazySymbol)];
384 alignas(UndefinedFunction) char F[sizeof(UndefinedFunction)];486 alignas(UndefinedFunction) char f[sizeof(UndefinedFunction)];
385 alignas(UndefinedData) char G[sizeof(UndefinedData)];487 alignas(UndefinedData) char g[sizeof(UndefinedData)];
386 alignas(UndefinedGlobal) char H[sizeof(UndefinedGlobal)];488 alignas(UndefinedGlobal) char h[sizeof(UndefinedGlobal)];
387 alignas(SectionSymbol) char I[sizeof(SectionSymbol)];489 alignas(SectionSymbol) char i[sizeof(SectionSymbol)];
388};490};
389491
492// It is important to keep the size of SymbolUnion small for performance and
493// memory usage reasons. 96 bytes is a soft limit based on the size of
494// UndefinedFunction on a 64-bit system.
495static_assert(sizeof(SymbolUnion) <= 96, "SymbolUnion too large");
496
497void printTraceSymbol(Symbol *sym);
498void printTraceSymbolUndefined(StringRef name, const InputFile* file);
499
390template <typename T, typename... ArgT>500template <typename T, typename... ArgT>
391T *replaceSymbol(Symbol *S, ArgT &&... Arg) {501T *replaceSymbol(Symbol *s, ArgT &&... arg) {
392 static_assert(std::is_trivially_destructible<T>(),502 static_assert(std::is_trivially_destructible<T>(),
393 "Symbol types must be trivially destructible");503 "Symbol types must be trivially destructible");
394 static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");504 static_assert(sizeof(T) <= sizeof(SymbolUnion), "SymbolUnion too small");
...@@ -397,20 +507,28 @@ T *replaceSymbol(Symbol *S, ArgT &&... Arg) {...@@ -397,20 +507,28 @@ T *replaceSymbol(Symbol *S, ArgT &&... Arg) {
397 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&507 assert(static_cast<Symbol *>(static_cast<T *>(nullptr)) == nullptr &&
398 "Not a Symbol");508 "Not a Symbol");
399509
400 Symbol SymCopy = *S;510 Symbol symCopy = *s;
511
512 T *s2 = new (s) T(std::forward<ArgT>(arg)...);
513 s2->isUsedInRegularObj = symCopy.isUsedInRegularObj;
514 s2->forceExport = symCopy.forceExport;
515 s2->canInline = symCopy.canInline;
516 s2->traced = symCopy.traced;
517
518 // Print out a log message if --trace-symbol was specified.
519 // This is for debugging.
520 if (s2->traced)
521 printTraceSymbol(s2);
401522
402 T *S2 = new (S) T(std::forward<ArgT>(Arg)...);523 return s2;
403 S2->IsUsedInRegularObj = SymCopy.IsUsedInRegularObj;
404 S2->ForceExport = SymCopy.ForceExport;
405 return S2;
406}524}
407525
408} // namespace wasm526} // namespace wasm
409527
410// Returns a symbol name for an error message.528// Returns a symbol name for an error message.
411std::string toString(const wasm::Symbol &Sym);529std::string toString(const wasm::Symbol &sym);
412std::string toString(wasm::Symbol::Kind Kind);530std::string toString(wasm::Symbol::Kind kind);
413std::string maybeDemangleSymbol(StringRef Name);531std::string maybeDemangleSymbol(StringRef name);
414532
415} // namespace lld533} // namespace lld
416534
deps/lld/wasm/SyntheticSections.cpp created+547
...@@ -0,0 +1,547 @@
1//===- SyntheticSections.cpp ----------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// This file contains linker-synthesized sections.
10//
11//===----------------------------------------------------------------------===//
12
13#include "SyntheticSections.h"
14
15#include "InputChunks.h"
16#include "InputEvent.h"
17#include "InputGlobal.h"
18#include "OutputSegment.h"
19#include "SymbolTable.h"
20#include "llvm/Support/Path.h"
21
22using namespace llvm;
23using namespace llvm::wasm;
24
25using namespace lld;
26using namespace lld::wasm;
27
28OutStruct lld::wasm::out;
29
30namespace {
31
32// Some synthetic sections (e.g. "name" and "linking") have subsections.
33// Just like the synthetic sections themselves these need to be created before
34// they can be written out (since they are preceded by their length). This
35// class is used to create subsections and then write them into the stream
36// of the parent section.
37class SubSection {
38public:
39 explicit SubSection(uint32_t type) : type(type) {}
40
41 void writeTo(raw_ostream &to) {
42 os.flush();
43 writeUleb128(to, type, "subsection type");
44 writeUleb128(to, body.size(), "subsection size");
45 to.write(body.data(), body.size());
46 }
47
48private:
49 uint32_t type;
50 std::string body;
51
52public:
53 raw_string_ostream os{body};
54};
55
56} // namespace
57
58void DylinkSection::writeBody() {
59 raw_ostream &os = bodyOutputStream;
60
61 writeUleb128(os, memSize, "MemSize");
62 writeUleb128(os, memAlign, "MemAlign");
63 writeUleb128(os, out.elemSec->numEntries(), "TableSize");
64 writeUleb128(os, 0, "TableAlign");
65 writeUleb128(os, symtab->sharedFiles.size(), "Needed");
66 for (auto *so : symtab->sharedFiles)
67 writeStr(os, llvm::sys::path::filename(so->getName()), "so name");
68}
69
70uint32_t TypeSection::registerType(const WasmSignature &sig) {
71 auto pair = typeIndices.insert(std::make_pair(sig, types.size()));
72 if (pair.second) {
73 LLVM_DEBUG(llvm::dbgs() << "type " << toString(sig) << "\n");
74 types.push_back(&sig);
75 }
76 return pair.first->second;
77}
78
79uint32_t TypeSection::lookupType(const WasmSignature &sig) {
80 auto it = typeIndices.find(sig);
81 if (it == typeIndices.end()) {
82 error("type not found: " + toString(sig));
83 return 0;
84 }
85 return it->second;
86}
87
88void TypeSection::writeBody() {
89 writeUleb128(bodyOutputStream, types.size(), "type count");
90 for (const WasmSignature *sig : types)
91 writeSig(bodyOutputStream, *sig);
92}
93
94uint32_t ImportSection::getNumImports() const {
95 assert(isSealed);
96 uint32_t numImports = importedSymbols.size() + gotSymbols.size();
97 if (config->importMemory)
98 ++numImports;
99 if (config->importTable)
100 ++numImports;
101 return numImports;
102}
103
104void ImportSection::addGOTEntry(Symbol *sym) {
105 assert(!isSealed);
106 if (sym->hasGOTIndex())
107 return;
108 sym->setGOTIndex(numImportedGlobals++);
109 gotSymbols.push_back(sym);
110}
111
112void ImportSection::addImport(Symbol *sym) {
113 assert(!isSealed);
114 importedSymbols.emplace_back(sym);
115 if (auto *f = dyn_cast<FunctionSymbol>(sym))
116 f->setFunctionIndex(numImportedFunctions++);
117 else if (auto *g = dyn_cast<GlobalSymbol>(sym))
118 g->setGlobalIndex(numImportedGlobals++);
119 else
120 cast<EventSymbol>(sym)->setEventIndex(numImportedEvents++);
121}
122
123void ImportSection::writeBody() {
124 raw_ostream &os = bodyOutputStream;
125
126 writeUleb128(os, getNumImports(), "import count");
127
128 if (config->importMemory) {
129 WasmImport import;
130 import.Module = defaultModule;
131 import.Field = "memory";
132 import.Kind = WASM_EXTERNAL_MEMORY;
133 import.Memory.Flags = 0;
134 import.Memory.Initial = out.memorySec->numMemoryPages;
135 if (out.memorySec->maxMemoryPages != 0 || config->sharedMemory) {
136 import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
137 import.Memory.Maximum = out.memorySec->maxMemoryPages;
138 }
139 if (config->sharedMemory)
140 import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;
141 writeImport(os, import);
142 }
143
144 if (config->importTable) {
145 uint32_t tableSize = out.elemSec->elemOffset + out.elemSec->numEntries();
146 WasmImport import;
147 import.Module = defaultModule;
148 import.Field = functionTableName;
149 import.Kind = WASM_EXTERNAL_TABLE;
150 import.Table.ElemType = WASM_TYPE_FUNCREF;
151 import.Table.Limits = {0, tableSize, 0};
152 writeImport(os, import);
153 }
154
155 for (const Symbol *sym : importedSymbols) {
156 WasmImport import;
157 if (auto *f = dyn_cast<UndefinedFunction>(sym)) {
158 import.Field = f->importName;
159 import.Module = f->importModule;
160 } else if (auto *g = dyn_cast<UndefinedGlobal>(sym)) {
161 import.Field = g->importName;
162 import.Module = g->importModule;
163 } else {
164 import.Field = sym->getName();
165 import.Module = defaultModule;
166 }
167
168 if (auto *functionSym = dyn_cast<FunctionSymbol>(sym)) {
169 import.Kind = WASM_EXTERNAL_FUNCTION;
170 import.SigIndex = out.typeSec->lookupType(*functionSym->signature);
171 } else if (auto *globalSym = dyn_cast<GlobalSymbol>(sym)) {
172 import.Kind = WASM_EXTERNAL_GLOBAL;
173 import.Global = *globalSym->getGlobalType();
174 } else {
175 auto *eventSym = cast<EventSymbol>(sym);
176 import.Kind = WASM_EXTERNAL_EVENT;
177 import.Event.Attribute = eventSym->getEventType()->Attribute;
178 import.Event.SigIndex = out.typeSec->lookupType(*eventSym->signature);
179 }
180 writeImport(os, import);
181 }
182
183 for (const Symbol *sym : gotSymbols) {
184 WasmImport import;
185 import.Kind = WASM_EXTERNAL_GLOBAL;
186 import.Global = {WASM_TYPE_I32, true};
187 if (isa<DataSymbol>(sym))
188 import.Module = "GOT.mem";
189 else
190 import.Module = "GOT.func";
191 import.Field = sym->getName();
192 writeImport(os, import);
193 }
194}
195
196void FunctionSection::writeBody() {
197 raw_ostream &os = bodyOutputStream;
198
199 writeUleb128(os, inputFunctions.size(), "function count");
200 for (const InputFunction *func : inputFunctions)
201 writeUleb128(os, out.typeSec->lookupType(func->signature), "sig index");
202}
203
204void FunctionSection::addFunction(InputFunction *func) {
205 if (!func->live)
206 return;
207 uint32_t functionIndex =
208 out.importSec->getNumImportedFunctions() + inputFunctions.size();
209 inputFunctions.emplace_back(func);
210 func->setFunctionIndex(functionIndex);
211}
212
213void TableSection::writeBody() {
214 uint32_t tableSize = out.elemSec->elemOffset + out.elemSec->numEntries();
215
216 raw_ostream &os = bodyOutputStream;
217 writeUleb128(os, 1, "table count");
218 WasmLimits limits = {WASM_LIMITS_FLAG_HAS_MAX, tableSize, tableSize};
219 writeTableType(os, WasmTable{WASM_TYPE_FUNCREF, limits});
220}
221
222void MemorySection::writeBody() {
223 raw_ostream &os = bodyOutputStream;
224
225 bool hasMax = maxMemoryPages != 0 || config->sharedMemory;
226 writeUleb128(os, 1, "memory count");
227 unsigned flags = 0;
228 if (hasMax)
229 flags |= WASM_LIMITS_FLAG_HAS_MAX;
230 if (config->sharedMemory)
231 flags |= WASM_LIMITS_FLAG_IS_SHARED;
232 writeUleb128(os, flags, "memory limits flags");
233 writeUleb128(os, numMemoryPages, "initial pages");
234 if (hasMax)
235 writeUleb128(os, maxMemoryPages, "max pages");
236}
237
238void GlobalSection::writeBody() {
239 raw_ostream &os = bodyOutputStream;
240
241 writeUleb128(os, numGlobals(), "global count");
242 for (const InputGlobal *g : inputGlobals)
243 writeGlobal(os, g->global);
244 for (const DefinedData *sym : definedFakeGlobals) {
245 WasmGlobal global;
246 global.Type = {WASM_TYPE_I32, false};
247 global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
248 global.InitExpr.Value.Int32 = sym->getVirtualAddress();
249 writeGlobal(os, global);
250 }
251}
252
253void GlobalSection::addGlobal(InputGlobal *global) {
254 if (!global->live)
255 return;
256 uint32_t globalIndex =
257 out.importSec->getNumImportedGlobals() + inputGlobals.size();
258 LLVM_DEBUG(dbgs() << "addGlobal: " << globalIndex << "\n");
259 global->setGlobalIndex(globalIndex);
260 out.globalSec->inputGlobals.push_back(global);
261}
262
263void EventSection::writeBody() {
264 raw_ostream &os = bodyOutputStream;
265
266 writeUleb128(os, inputEvents.size(), "event count");
267 for (InputEvent *e : inputEvents) {
268 e->event.Type.SigIndex = out.typeSec->lookupType(e->signature);
269 writeEvent(os, e->event);
270 }
271}
272
273void EventSection::addEvent(InputEvent *event) {
274 if (!event->live)
275 return;
276 uint32_t eventIndex =
277 out.importSec->getNumImportedEvents() + inputEvents.size();
278 LLVM_DEBUG(dbgs() << "addEvent: " << eventIndex << "\n");
279 event->setEventIndex(eventIndex);
280 inputEvents.push_back(event);
281}
282
283void ExportSection::writeBody() {
284 raw_ostream &os = bodyOutputStream;
285
286 writeUleb128(os, exports.size(), "export count");
287 for (const WasmExport &export_ : exports)
288 writeExport(os, export_);
289}
290
291void ElemSection::addEntry(FunctionSymbol *sym) {
292 if (sym->hasTableIndex())
293 return;
294 sym->setTableIndex(elemOffset + indirectFunctions.size());
295 indirectFunctions.emplace_back(sym);
296}
297
298void ElemSection::writeBody() {
299 raw_ostream &os = bodyOutputStream;
300
301 writeUleb128(os, 1, "segment count");
302 writeUleb128(os, 0, "table index");
303 WasmInitExpr initExpr;
304 if (config->isPic) {
305 initExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
306 initExpr.Value.Global = WasmSym::tableBase->getGlobalIndex();
307 } else {
308 initExpr.Opcode = WASM_OPCODE_I32_CONST;
309 initExpr.Value.Int32 = elemOffset;
310 }
311 writeInitExpr(os, initExpr);
312 writeUleb128(os, indirectFunctions.size(), "elem count");
313
314 uint32_t tableIndex = elemOffset;
315 for (const FunctionSymbol *sym : indirectFunctions) {
316 assert(sym->getTableIndex() == tableIndex);
317 writeUleb128(os, sym->getFunctionIndex(), "function index");
318 ++tableIndex;
319 }
320}
321
322void DataCountSection::writeBody() {
323 writeUleb128(bodyOutputStream, numSegments, "data count");
324}
325
326bool DataCountSection::isNeeded() const {
327 return numSegments && config->passiveSegments;
328}
329
330static uint32_t getWasmFlags(const Symbol *sym) {
331 uint32_t flags = 0;
332 if (sym->isLocal())
333 flags |= WASM_SYMBOL_BINDING_LOCAL;
334 if (sym->isWeak())
335 flags |= WASM_SYMBOL_BINDING_WEAK;
336 if (sym->isHidden())
337 flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
338 if (sym->isUndefined())
339 flags |= WASM_SYMBOL_UNDEFINED;
340 if (auto *f = dyn_cast<UndefinedFunction>(sym)) {
341 if (f->getName() != f->importName)
342 flags |= WASM_SYMBOL_EXPLICIT_NAME;
343 } else if (auto *g = dyn_cast<UndefinedGlobal>(sym)) {
344 if (g->getName() != g->importName)
345 flags |= WASM_SYMBOL_EXPLICIT_NAME;
346 }
347 return flags;
348}
349
350void LinkingSection::writeBody() {
351 raw_ostream &os = bodyOutputStream;
352
353 writeUleb128(os, WasmMetadataVersion, "Version");
354
355 if (!symtabEntries.empty()) {
356 SubSection sub(WASM_SYMBOL_TABLE);
357 writeUleb128(sub.os, symtabEntries.size(), "num symbols");
358
359 for (const Symbol *sym : symtabEntries) {
360 assert(sym->isDefined() || sym->isUndefined());
361 WasmSymbolType kind = sym->getWasmType();
362 uint32_t flags = getWasmFlags(sym);
363
364 writeU8(sub.os, kind, "sym kind");
365 writeUleb128(sub.os, flags, "sym flags");
366
367 if (auto *f = dyn_cast<FunctionSymbol>(sym)) {
368 writeUleb128(sub.os, f->getFunctionIndex(), "index");
369 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
370 writeStr(sub.os, sym->getName(), "sym name");
371 } else if (auto *g = dyn_cast<GlobalSymbol>(sym)) {
372 writeUleb128(sub.os, g->getGlobalIndex(), "index");
373 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
374 writeStr(sub.os, sym->getName(), "sym name");
375 } else if (auto *e = dyn_cast<EventSymbol>(sym)) {
376 writeUleb128(sub.os, e->getEventIndex(), "index");
377 if (sym->isDefined() || (flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
378 writeStr(sub.os, sym->getName(), "sym name");
379 } else if (isa<DataSymbol>(sym)) {
380 writeStr(sub.os, sym->getName(), "sym name");
381 if (auto *dataSym = dyn_cast<DefinedData>(sym)) {
382 writeUleb128(sub.os, dataSym->getOutputSegmentIndex(), "index");
383 writeUleb128(sub.os, dataSym->getOutputSegmentOffset(),
384 "data offset");
385 writeUleb128(sub.os, dataSym->getSize(), "data size");
386 }
387 } else {
388 auto *s = cast<OutputSectionSymbol>(sym);
389 writeUleb128(sub.os, s->section->sectionIndex, "sym section index");
390 }
391 }
392
393 sub.writeTo(os);
394 }
395
396 if (dataSegments.size()) {
397 SubSection sub(WASM_SEGMENT_INFO);
398 writeUleb128(sub.os, dataSegments.size(), "num data segments");
399 for (const OutputSegment *s : dataSegments) {
400 writeStr(sub.os, s->name, "segment name");
401 writeUleb128(sub.os, s->alignment, "alignment");
402 writeUleb128(sub.os, 0, "flags");
403 }
404 sub.writeTo(os);
405 }
406
407 if (!initFunctions.empty()) {
408 SubSection sub(WASM_INIT_FUNCS);
409 writeUleb128(sub.os, initFunctions.size(), "num init functions");
410 for (const WasmInitEntry &f : initFunctions) {
411 writeUleb128(sub.os, f.priority, "priority");
412 writeUleb128(sub.os, f.sym->getOutputSymbolIndex(), "function index");
413 }
414 sub.writeTo(os);
415 }
416
417 struct ComdatEntry {
418 unsigned kind;
419 uint32_t index;
420 };
421 std::map<StringRef, std::vector<ComdatEntry>> comdats;
422
423 for (const InputFunction *f : out.functionSec->inputFunctions) {
424 StringRef comdat = f->getComdatName();
425 if (!comdat.empty())
426 comdats[comdat].emplace_back(
427 ComdatEntry{WASM_COMDAT_FUNCTION, f->getFunctionIndex()});
428 }
429 for (uint32_t i = 0; i < dataSegments.size(); ++i) {
430 const auto &inputSegments = dataSegments[i]->inputSegments;
431 if (inputSegments.empty())
432 continue;
433 StringRef comdat = inputSegments[0]->getComdatName();
434#ifndef NDEBUG
435 for (const InputSegment *isec : inputSegments)
436 assert(isec->getComdatName() == comdat);
437#endif
438 if (!comdat.empty())
439 comdats[comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, i});
440 }
441
442 if (!comdats.empty()) {
443 SubSection sub(WASM_COMDAT_INFO);
444 writeUleb128(sub.os, comdats.size(), "num comdats");
445 for (const auto &c : comdats) {
446 writeStr(sub.os, c.first, "comdat name");
447 writeUleb128(sub.os, 0, "comdat flags"); // flags for future use
448 writeUleb128(sub.os, c.second.size(), "num entries");
449 for (const ComdatEntry &entry : c.second) {
450 writeU8(sub.os, entry.kind, "entry kind");
451 writeUleb128(sub.os, entry.index, "entry index");
452 }
453 }
454 sub.writeTo(os);
455 }
456}
457
458void LinkingSection::addToSymtab(Symbol *sym) {
459 sym->setOutputSymbolIndex(symtabEntries.size());
460 symtabEntries.emplace_back(sym);
461}
462
463unsigned NameSection::numNames() const {
464 unsigned numNames = out.importSec->getNumImportedFunctions();
465 for (const InputFunction *f : out.functionSec->inputFunctions)
466 if (!f->getName().empty() || !f->getDebugName().empty())
467 ++numNames;
468
469 return numNames;
470}
471
472// Create the custom "name" section containing debug symbol names.
473void NameSection::writeBody() {
474 SubSection sub(WASM_NAMES_FUNCTION);
475 writeUleb128(sub.os, numNames(), "name count");
476
477 // Names must appear in function index order. As it happens importedSymbols
478 // and inputFunctions are numbered in order with imported functions coming
479 // first.
480 for (const Symbol *s : out.importSec->importedSymbols) {
481 if (auto *f = dyn_cast<FunctionSymbol>(s)) {
482 writeUleb128(sub.os, f->getFunctionIndex(), "func index");
483 writeStr(sub.os, toString(*s), "symbol name");
484 }
485 }
486 for (const InputFunction *f : out.functionSec->inputFunctions) {
487 if (!f->getName().empty()) {
488 writeUleb128(sub.os, f->getFunctionIndex(), "func index");
489 if (!f->getDebugName().empty()) {
490 writeStr(sub.os, f->getDebugName(), "symbol name");
491 } else {
492 writeStr(sub.os, maybeDemangleSymbol(f->getName()), "symbol name");
493 }
494 }
495 }
496
497 sub.writeTo(bodyOutputStream);
498}
499
500void ProducersSection::addInfo(const WasmProducerInfo &info) {
501 for (auto &producers :
502 {std::make_pair(&info.Languages, &languages),
503 std::make_pair(&info.Tools, &tools), std::make_pair(&info.SDKs, &sDKs)})
504 for (auto &producer : *producers.first)
505 if (producers.second->end() ==
506 llvm::find_if(*producers.second,
507 [&](std::pair<std::string, std::string> seen) {
508 return seen.first == producer.first;
509 }))
510 producers.second->push_back(producer);
511}
512
513void ProducersSection::writeBody() {
514 auto &os = bodyOutputStream;
515 writeUleb128(os, fieldCount(), "field count");
516 for (auto &field :
517 {std::make_pair("language", languages),
518 std::make_pair("processed-by", tools), std::make_pair("sdk", sDKs)}) {
519 if (field.second.empty())
520 continue;
521 writeStr(os, field.first, "field name");
522 writeUleb128(os, field.second.size(), "number of entries");
523 for (auto &entry : field.second) {
524 writeStr(os, entry.first, "producer name");
525 writeStr(os, entry.second, "producer version");
526 }
527 }
528}
529
530void TargetFeaturesSection::writeBody() {
531 SmallVector<std::string, 8> emitted(features.begin(), features.end());
532 llvm::sort(emitted);
533 auto &os = bodyOutputStream;
534 writeUleb128(os, emitted.size(), "feature count");
535 for (auto &feature : emitted) {
536 writeU8(os, WASM_FEATURE_PREFIX_USED, "feature used prefix");
537 writeStr(os, feature, "feature name");
538 }
539}
540
541void RelocSection::writeBody() {
542 uint32_t count = sec->getNumRelocations();
543 assert(sec->sectionIndex != UINT32_MAX);
544 writeUleb128(bodyOutputStream, sec->sectionIndex, "reloc section");
545 writeUleb128(bodyOutputStream, count, "reloc count");
546 sec->writeRelocations(bodyOutputStream);
547}
deps/lld/wasm/SyntheticSections.h created+339
...@@ -0,0 +1,339 @@
1//===- SyntheticSection.h ---------------------------------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Synthetic sections represent chunks of linker-created data. If you
10// need to create a chunk of data that to be included in some section
11// in the result, you probably want to create that as a synthetic section.
12//
13//===----------------------------------------------------------------------===//
14
15#ifndef LLD_WASM_SYNTHETIC_SECTIONS_H
16#define LLD_WASM_SYNTHETIC_SECTIONS_H
17
18#include "OutputSections.h"
19
20#include "llvm/ADT/SmallSet.h"
21#include "llvm/ADT/StringMap.h"
22#include "llvm/Object/WasmTraits.h"
23
24#define DEBUG_TYPE "lld"
25
26namespace lld {
27namespace wasm {
28
29// An init entry to be written to either the synthetic init func or the
30// linking metadata.
31struct WasmInitEntry {
32 const FunctionSymbol *sym;
33 uint32_t priority;
34};
35
36class SyntheticSection : public OutputSection {
37public:
38 SyntheticSection(uint32_t type, std::string name = "")
39 : OutputSection(type, name), bodyOutputStream(body) {
40 if (!name.empty())
41 writeStr(bodyOutputStream, name, "section name");
42 }
43
44 void writeTo(uint8_t *buf) override {
45 assert(offset);
46 log("writing " + toString(*this));
47 memcpy(buf + offset, header.data(), header.size());
48 memcpy(buf + offset + header.size(), body.data(), body.size());
49 }
50
51 size_t getSize() const override { return header.size() + body.size(); }
52
53 virtual void writeBody() {}
54
55 void finalizeContents() override {
56 writeBody();
57 bodyOutputStream.flush();
58 createHeader(body.size());
59 }
60
61 raw_ostream &getStream() { return bodyOutputStream; }
62
63 std::string body;
64
65protected:
66 llvm::raw_string_ostream bodyOutputStream;
67};
68
69// Create the custom "dylink" section containing information for the dynamic
70// linker.
71// See
72// https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
73class DylinkSection : public SyntheticSection {
74public:
75 DylinkSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "dylink") {}
76 bool isNeeded() const override { return config->isPic; }
77 void writeBody() override;
78
79 uint32_t memAlign = 0;
80 uint32_t memSize = 0;
81};
82
83class TypeSection : public SyntheticSection {
84public:
85 TypeSection() : SyntheticSection(llvm::wasm::WASM_SEC_TYPE) {}
86
87 bool isNeeded() const override { return types.size() > 0; };
88 void writeBody() override;
89 uint32_t registerType(const WasmSignature &sig);
90 uint32_t lookupType(const WasmSignature &sig);
91
92protected:
93 std::vector<const WasmSignature *> types;
94 llvm::DenseMap<WasmSignature, int32_t> typeIndices;
95};
96
97class ImportSection : public SyntheticSection {
98public:
99 ImportSection() : SyntheticSection(llvm::wasm::WASM_SEC_IMPORT) {}
100 bool isNeeded() const override { return getNumImports() > 0; }
101 void writeBody() override;
102 void addImport(Symbol *sym);
103 void addGOTEntry(Symbol *sym);
104 void seal() { isSealed = true; }
105 uint32_t getNumImports() const;
106 uint32_t getNumImportedGlobals() const {
107 assert(isSealed);
108 return numImportedGlobals;
109 }
110 uint32_t getNumImportedFunctions() const {
111 assert(isSealed);
112 return numImportedFunctions;
113 }
114 uint32_t getNumImportedEvents() const {
115 assert(isSealed);
116 return numImportedEvents;
117 }
118
119 std::vector<const Symbol *> importedSymbols;
120
121protected:
122 bool isSealed = false;
123 unsigned numImportedGlobals = 0;
124 unsigned numImportedFunctions = 0;
125 unsigned numImportedEvents = 0;
126 std::vector<const Symbol *> gotSymbols;
127};
128
129class FunctionSection : public SyntheticSection {
130public:
131 FunctionSection() : SyntheticSection(llvm::wasm::WASM_SEC_FUNCTION) {}
132
133 bool isNeeded() const override { return inputFunctions.size() > 0; };
134 void writeBody() override;
135 void addFunction(InputFunction *func);
136
137 std::vector<InputFunction *> inputFunctions;
138
139protected:
140};
141
142class MemorySection : public SyntheticSection {
143public:
144 MemorySection() : SyntheticSection(llvm::wasm::WASM_SEC_MEMORY) {}
145
146 bool isNeeded() const override { return !config->importMemory; }
147 void writeBody() override;
148
149 uint32_t numMemoryPages = 0;
150 uint32_t maxMemoryPages = 0;
151};
152
153class TableSection : public SyntheticSection {
154public:
155 TableSection() : SyntheticSection(llvm::wasm::WASM_SEC_TABLE) {}
156
157 bool isNeeded() const override {
158 // Always output a table section (or table import), even if there are no
159 // indirect calls. There are two reasons for this:
160 // 1. For executables it is useful to have an empty table slot at 0
161 // which can be filled with a null function call handler.
162 // 2. If we don't do this, any program that contains a call_indirect but
163 // no address-taken function will fail at validation time since it is
164 // a validation error to include a call_indirect instruction if there
165 // is not table.
166 return !config->importTable;
167 }
168
169 void writeBody() override;
170};
171
172class GlobalSection : public SyntheticSection {
173public:
174 GlobalSection() : SyntheticSection(llvm::wasm::WASM_SEC_GLOBAL) {}
175 uint32_t numGlobals() const {
176 return inputGlobals.size() + definedFakeGlobals.size();
177 }
178 bool isNeeded() const override { return numGlobals() > 0; }
179 void writeBody() override;
180 void addGlobal(InputGlobal *global);
181
182 std::vector<const DefinedData *> definedFakeGlobals;
183 std::vector<InputGlobal *> inputGlobals;
184};
185
186// The event section contains a list of declared wasm events associated with the
187// module. Currently the only supported event kind is exceptions. A single event
188// entry represents a single event with an event tag. All C++ exceptions are
189// represented by a single event. An event entry in this section contains
190// information on what kind of event it is (e.g. exception) and the type of
191// values contained in a single event object. (In wasm, an event can contain
192// multiple values of primitive types. But for C++ exceptions, we just throw a
193// pointer which is an i32 value (for wasm32 architecture), so the signature of
194// C++ exception is (i32)->(void), because all event types are assumed to have
195// void return type to share WasmSignature with functions.)
196class EventSection : public SyntheticSection {
197public:
198 EventSection() : SyntheticSection(llvm::wasm::WASM_SEC_EVENT) {}
199 void writeBody() override;
200 bool isNeeded() const override { return inputEvents.size() > 0; }
201 void addEvent(InputEvent *event);
202
203 std::vector<InputEvent *> inputEvents;
204};
205
206class ExportSection : public SyntheticSection {
207public:
208 ExportSection() : SyntheticSection(llvm::wasm::WASM_SEC_EXPORT) {}
209 bool isNeeded() const override { return exports.size() > 0; }
210 void writeBody() override;
211
212 std::vector<llvm::wasm::WasmExport> exports;
213};
214
215class ElemSection : public SyntheticSection {
216public:
217 ElemSection(uint32_t offset)
218 : SyntheticSection(llvm::wasm::WASM_SEC_ELEM), elemOffset(offset) {}
219 bool isNeeded() const override { return indirectFunctions.size() > 0; };
220 void writeBody() override;
221 void addEntry(FunctionSymbol *sym);
222 uint32_t numEntries() const { return indirectFunctions.size(); }
223 uint32_t elemOffset;
224
225protected:
226 std::vector<const FunctionSymbol *> indirectFunctions;
227};
228
229class DataCountSection : public SyntheticSection {
230public:
231 DataCountSection(uint32_t numSegments)
232 : SyntheticSection(llvm::wasm::WASM_SEC_DATACOUNT),
233 numSegments(numSegments) {}
234 bool isNeeded() const override;
235 void writeBody() override;
236
237protected:
238 uint32_t numSegments;
239};
240
241// Create the custom "linking" section containing linker metadata.
242// This is only created when relocatable output is requested.
243class LinkingSection : public SyntheticSection {
244public:
245 LinkingSection(const std::vector<WasmInitEntry> &initFunctions,
246 const std::vector<OutputSegment *> &dataSegments)
247 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "linking"),
248 initFunctions(initFunctions), dataSegments(dataSegments) {}
249 bool isNeeded() const override {
250 return config->relocatable || config->emitRelocs;
251 }
252 void writeBody() override;
253 void addToSymtab(Symbol *sym);
254
255protected:
256 std::vector<const Symbol *> symtabEntries;
257 llvm::StringMap<uint32_t> sectionSymbolIndices;
258 const std::vector<WasmInitEntry> &initFunctions;
259 const std::vector<OutputSegment *> &dataSegments;
260};
261
262// Create the custom "name" section containing debug symbol names.
263class NameSection : public SyntheticSection {
264public:
265 NameSection() : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "name") {}
266 bool isNeeded() const override {
267 return !config->stripDebug && !config->stripAll && numNames() > 0;
268 }
269 void writeBody() override;
270 unsigned numNames() const;
271};
272
273class ProducersSection : public SyntheticSection {
274public:
275 ProducersSection()
276 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "producers") {}
277 bool isNeeded() const override {
278 return !config->stripAll && fieldCount() > 0;
279 }
280 void writeBody() override;
281 void addInfo(const llvm::wasm::WasmProducerInfo &info);
282
283protected:
284 int fieldCount() const {
285 return int(!languages.empty()) + int(!tools.empty()) + int(!sDKs.empty());
286 }
287 SmallVector<std::pair<std::string, std::string>, 8> languages;
288 SmallVector<std::pair<std::string, std::string>, 8> tools;
289 SmallVector<std::pair<std::string, std::string>, 8> sDKs;
290};
291
292class TargetFeaturesSection : public SyntheticSection {
293public:
294 TargetFeaturesSection()
295 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, "target_features") {}
296 bool isNeeded() const override {
297 return !config->stripAll && features.size() > 0;
298 }
299 void writeBody() override;
300
301 llvm::SmallSet<std::string, 8> features;
302};
303
304class RelocSection : public SyntheticSection {
305public:
306 RelocSection(StringRef name, OutputSection *sec)
307 : SyntheticSection(llvm::wasm::WASM_SEC_CUSTOM, name), sec(sec) {}
308 void writeBody() override;
309 bool isNeeded() const override { return sec->getNumRelocations() > 0; };
310
311protected:
312 OutputSection *sec;
313};
314
315// Linker generated output sections
316struct OutStruct {
317 DylinkSection *dylinkSec;
318 TypeSection *typeSec;
319 FunctionSection *functionSec;
320 ImportSection *importSec;
321 TableSection *tableSec;
322 MemorySection *memorySec;
323 GlobalSection *globalSec;
324 EventSection *eventSec;
325 ExportSection *exportSec;
326 ElemSection *elemSec;
327 DataCountSection *dataCountSec;
328 LinkingSection *linkingSec;
329 NameSection *nameSec;
330 ProducersSection *producersSec;
331 TargetFeaturesSection *targetFeaturesSec;
332};
333
334extern OutStruct out;
335
336} // namespace wasm
337} // namespace lld
338
339#endif
deps/lld/wasm/Writer.cpp+659-909
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Writer.cpp ---------------------------------------------------------===//1//===- Writer.cpp ---------------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -14,13 +13,17 @@...@@ -14,13 +13,17 @@
14#include "InputGlobal.h"13#include "InputGlobal.h"
15#include "OutputSections.h"14#include "OutputSections.h"
16#include "OutputSegment.h"15#include "OutputSegment.h"
16#include "Relocations.h"
17#include "SymbolTable.h"17#include "SymbolTable.h"
18#include "SyntheticSections.h"
18#include "WriterUtils.h"19#include "WriterUtils.h"
19#include "lld/Common/ErrorHandler.h"20#include "lld/Common/ErrorHandler.h"
20#include "lld/Common/Memory.h"21#include "lld/Common/Memory.h"
21#include "lld/Common/Strings.h"22#include "lld/Common/Strings.h"
22#include "lld/Common/Threads.h"23#include "lld/Common/Threads.h"
23#include "llvm/ADT/DenseSet.h"24#include "llvm/ADT/DenseSet.h"
25#include "llvm/ADT/SmallSet.h"
26#include "llvm/ADT/SmallVector.h"
24#include "llvm/ADT/StringMap.h"27#include "llvm/ADT/StringMap.h"
25#include "llvm/BinaryFormat/Wasm.h"28#include "llvm/BinaryFormat/Wasm.h"
26#include "llvm/Object/WasmTraits.h"29#include "llvm/Object/WasmTraits.h"
...@@ -39,19 +42,10 @@ using namespace llvm::wasm;...@@ -39,19 +42,10 @@ using namespace llvm::wasm;
39using namespace lld;42using namespace lld;
40using namespace lld::wasm;43using namespace lld::wasm;
4144
42static constexpr int StackAlignment = 16;45static constexpr int stackAlignment = 16;
43static constexpr const char *FunctionTableName = "__indirect_function_table";
44const char *lld::wasm::DefaultModule = "env";
4546
46namespace {47namespace {
4748
48// An init entry to be written to either the synthetic init func or the
49// linking metadata.
50struct WasmInitEntry {
51 const FunctionSymbol *Sym;
52 uint32_t Priority;
53};
54
55// The writer writes a SymbolTable result to a file.49// The writer writes a SymbolTable result to a file.
56class Writer {50class Writer {
57public:51public:
...@@ -60,613 +54,145 @@ public:...@@ -60,613 +54,145 @@ public:
60private:54private:
61 void openFile();55 void openFile();
6256
63 uint32_t lookupType(const WasmSignature &Sig);57 void createInitMemoryFunction();
64 uint32_t registerType(const WasmSignature &Sig);58 void createApplyRelocationsFunction();
59 void createCallCtorsFunction();
60 void createInitTLSFunction();
6561
66 void createCtorFunction();
67 void calculateInitFunctions();
68 void assignIndexes();62 void assignIndexes();
63 void populateSymtab();
64 void populateProducers();
65 void populateTargetFeatures();
66 void calculateInitFunctions();
69 void calculateImports();67 void calculateImports();
70 void calculateExports();68 void calculateExports();
71 void calculateCustomSections();69 void calculateCustomSections();
72 void assignSymtab();
73 void calculateTypes();70 void calculateTypes();
74 void createOutputSegments();71 void createOutputSegments();
75 void layoutMemory();72 void layoutMemory();
76 void createHeader();73 void createHeader();
77 void createSections();74
78 SyntheticSection *createSyntheticSection(uint32_t Type, StringRef Name = "");75 void addSection(OutputSection *sec);
7976
80 // Builtin sections77 void addSections();
81 void createTypeSection();78
82 void createFunctionSection();
83 void createTableSection();
84 void createGlobalSection();
85 void createEventSection();
86 void createExportSection();
87 void createImportSection();
88 void createMemorySection();
89 void createElemSection();
90 void createCodeSection();
91 void createDataSection();
92 void createCustomSections();79 void createCustomSections();
80 void createSyntheticSections();
81 void finalizeSections();
9382
94 // Custom sections83 // Custom sections
95 void createDylinkSection();
96 void createRelocSections();84 void createRelocSections();
97 void createLinkingSection();
98 void createNameSection();
9985
100 void writeHeader();86 void writeHeader();
101 void writeSections();87 void writeSections();
10288
103 uint64_t FileSize = 0;89 uint64_t fileSize = 0;
104 uint32_t TableBase = 0;90 uint32_t tableBase = 0;
105 uint32_t NumMemoryPages = 0;91
106 uint32_t MaxMemoryPages = 0;92 std::vector<WasmInitEntry> initFunctions;
107 // Memory size and aligment. Written to the "dylink" section93 llvm::StringMap<std::vector<InputSection *>> customSectionMapping;
108 // when build with -shared or -pie.
109 uint32_t MemAlign = 0;
110 uint32_t MemSize = 0;
111
112 std::vector<const WasmSignature *> Types;
113 DenseMap<WasmSignature, int32_t> TypeIndices;
114 std::vector<const Symbol *> ImportedSymbols;
115 unsigned NumImportedFunctions = 0;
116 unsigned NumImportedGlobals = 0;
117 unsigned NumImportedEvents = 0;
118 std::vector<WasmExport> Exports;
119 std::vector<const DefinedData *> DefinedFakeGlobals;
120 std::vector<InputGlobal *> InputGlobals;
121 std::vector<InputFunction *> InputFunctions;
122 std::vector<InputEvent *> InputEvents;
123 std::vector<const FunctionSymbol *> IndirectFunctions;
124 std::vector<const Symbol *> SymtabEntries;
125 std::vector<WasmInitEntry> InitFunctions;
126
127 llvm::StringMap<std::vector<InputSection *>> CustomSectionMapping;
128 llvm::StringMap<SectionSymbol *> CustomSectionSymbols;
12994
130 // Elements that are used to construct the final output95 // Elements that are used to construct the final output
131 std::string Header;96 std::string header;
132 std::vector<OutputSection *> OutputSections;97 std::vector<OutputSection *> outputSections;
13398
134 std::unique_ptr<FileOutputBuffer> Buffer;99 std::unique_ptr<FileOutputBuffer> buffer;
135100
136 std::vector<OutputSegment *> Segments;101 std::vector<OutputSegment *> segments;
137 llvm::SmallDenseMap<StringRef, OutputSegment *> SegmentMap;102 llvm::SmallDenseMap<StringRef, OutputSegment *> segmentMap;
138};103};
139104
140} // anonymous namespace105} // anonymous namespace
141106
142void Writer::createImportSection() {
143 uint32_t NumImports = ImportedSymbols.size();
144 if (Config->ImportMemory)
145 ++NumImports;
146 if (Config->ImportTable)
147 ++NumImports;
148
149 if (NumImports == 0)
150 return;
151
152 SyntheticSection *Section = createSyntheticSection(WASM_SEC_IMPORT);
153 raw_ostream &OS = Section->getStream();
154
155 writeUleb128(OS, NumImports, "import count");
156
157 if (Config->ImportMemory) {
158 WasmImport Import;
159 Import.Module = DefaultModule;
160 Import.Field = "memory";
161 Import.Kind = WASM_EXTERNAL_MEMORY;
162 Import.Memory.Flags = 0;
163 Import.Memory.Initial = NumMemoryPages;
164 if (MaxMemoryPages != 0) {
165 Import.Memory.Flags |= WASM_LIMITS_FLAG_HAS_MAX;
166 Import.Memory.Maximum = MaxMemoryPages;
167 }
168 if (Config->SharedMemory)
169 Import.Memory.Flags |= WASM_LIMITS_FLAG_IS_SHARED;
170 writeImport(OS, Import);
171 }
172
173 if (Config->ImportTable) {
174 uint32_t TableSize = TableBase + IndirectFunctions.size();
175 WasmImport Import;
176 Import.Module = DefaultModule;
177 Import.Field = FunctionTableName;
178 Import.Kind = WASM_EXTERNAL_TABLE;
179 Import.Table.ElemType = WASM_TYPE_FUNCREF;
180 Import.Table.Limits = {0, TableSize, 0};
181 writeImport(OS, Import);
182 }
183
184 for (const Symbol *Sym : ImportedSymbols) {
185 WasmImport Import;
186 if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
187 Import.Field = F->ImportName;
188 Import.Module = F->ImportModule;
189 } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
190 Import.Field = G->ImportName;
191 Import.Module = G->ImportModule;
192 } else {
193 Import.Field = Sym->getName();
194 Import.Module = DefaultModule;
195 }
196
197 if (auto *FunctionSym = dyn_cast<FunctionSymbol>(Sym)) {
198 Import.Kind = WASM_EXTERNAL_FUNCTION;
199 Import.SigIndex = lookupType(*FunctionSym->Signature);
200 } else if (auto *GlobalSym = dyn_cast<GlobalSymbol>(Sym)) {
201 Import.Kind = WASM_EXTERNAL_GLOBAL;
202 Import.Global = *GlobalSym->getGlobalType();
203 } else {
204 auto *EventSym = cast<EventSymbol>(Sym);
205 Import.Kind = WASM_EXTERNAL_EVENT;
206 Import.Event.Attribute = EventSym->getEventType()->Attribute;
207 Import.Event.SigIndex = lookupType(*EventSym->Signature);
208 }
209 writeImport(OS, Import);
210 }
211}
212
213void Writer::createTypeSection() {
214 SyntheticSection *Section = createSyntheticSection(WASM_SEC_TYPE);
215 raw_ostream &OS = Section->getStream();
216 writeUleb128(OS, Types.size(), "type count");
217 for (const WasmSignature *Sig : Types)
218 writeSig(OS, *Sig);
219}
220
221void Writer::createFunctionSection() {
222 if (InputFunctions.empty())
223 return;
224
225 SyntheticSection *Section = createSyntheticSection(WASM_SEC_FUNCTION);
226 raw_ostream &OS = Section->getStream();
227
228 writeUleb128(OS, InputFunctions.size(), "function count");
229 for (const InputFunction *Func : InputFunctions)
230 writeUleb128(OS, lookupType(Func->Signature), "sig index");
231}
232
233void Writer::createMemorySection() {
234 if (Config->ImportMemory)
235 return;
236
237 SyntheticSection *Section = createSyntheticSection(WASM_SEC_MEMORY);
238 raw_ostream &OS = Section->getStream();
239
240 bool HasMax = MaxMemoryPages != 0;
241 writeUleb128(OS, 1, "memory count");
242 unsigned Flags = 0;
243 if (HasMax)
244 Flags |= WASM_LIMITS_FLAG_HAS_MAX;
245 if (Config->SharedMemory)
246 Flags |= WASM_LIMITS_FLAG_IS_SHARED;
247 writeUleb128(OS, Flags, "memory limits flags");
248 writeUleb128(OS, NumMemoryPages, "initial pages");
249 if (HasMax)
250 writeUleb128(OS, MaxMemoryPages, "max pages");
251}
252
253void Writer::createGlobalSection() {
254 unsigned NumGlobals = InputGlobals.size() + DefinedFakeGlobals.size();
255 if (NumGlobals == 0)
256 return;
257
258 SyntheticSection *Section = createSyntheticSection(WASM_SEC_GLOBAL);
259 raw_ostream &OS = Section->getStream();
260
261 writeUleb128(OS, NumGlobals, "global count");
262 for (const InputGlobal *G : InputGlobals)
263 writeGlobal(OS, G->Global);
264 for (const DefinedData *Sym : DefinedFakeGlobals) {
265 WasmGlobal Global;
266 Global.Type = {WASM_TYPE_I32, false};
267 Global.InitExpr.Opcode = WASM_OPCODE_I32_CONST;
268 Global.InitExpr.Value.Int32 = Sym->getVirtualAddress();
269 writeGlobal(OS, Global);
270 }
271}
272
273// The event section contains a list of declared wasm events associated with the
274// module. Currently the only supported event kind is exceptions. A single event
275// entry represents a single event with an event tag. All C++ exceptions are
276// represented by a single event. An event entry in this section contains
277// information on what kind of event it is (e.g. exception) and the type of
278// values contained in a single event object. (In wasm, an event can contain
279// multiple values of primitive types. But for C++ exceptions, we just throw a
280// pointer which is an i32 value (for wasm32 architecture), so the signature of
281// C++ exception is (i32)->(void), because all event types are assumed to have
282// void return type to share WasmSignature with functions.)
283void Writer::createEventSection() {
284 unsigned NumEvents = InputEvents.size();
285 if (NumEvents == 0)
286 return;
287
288 SyntheticSection *Section = createSyntheticSection(WASM_SEC_EVENT);
289 raw_ostream &OS = Section->getStream();
290
291 writeUleb128(OS, NumEvents, "event count");
292 for (InputEvent *E : InputEvents) {
293 E->Event.Type.SigIndex = lookupType(E->Signature);
294 writeEvent(OS, E->Event);
295 }
296}
297
298void Writer::createTableSection() {
299 if (Config->ImportTable)
300 return;
301
302 // Always output a table section (or table import), even if there are no
303 // indirect calls. There are two reasons for this:
304 // 1. For executables it is useful to have an empty table slot at 0
305 // which can be filled with a null function call handler.
306 // 2. If we don't do this, any program that contains a call_indirect but
307 // no address-taken function will fail at validation time since it is
308 // a validation error to include a call_indirect instruction if there
309 // is not table.
310 uint32_t TableSize = TableBase + IndirectFunctions.size();
311
312 SyntheticSection *Section = createSyntheticSection(WASM_SEC_TABLE);
313 raw_ostream &OS = Section->getStream();
314
315 writeUleb128(OS, 1, "table count");
316 WasmLimits Limits = {WASM_LIMITS_FLAG_HAS_MAX, TableSize, TableSize};
317 writeTableType(OS, WasmTable{WASM_TYPE_FUNCREF, Limits});
318}
319
320void Writer::createExportSection() {
321 if (!Exports.size())
322 return;
323
324 SyntheticSection *Section = createSyntheticSection(WASM_SEC_EXPORT);
325 raw_ostream &OS = Section->getStream();
326
327 writeUleb128(OS, Exports.size(), "export count");
328 for (const WasmExport &Export : Exports)
329 writeExport(OS, Export);
330}
331
332void Writer::calculateCustomSections() {107void Writer::calculateCustomSections() {
333 log("calculateCustomSections");108 log("calculateCustomSections");
334 bool StripDebug = Config->StripDebug || Config->StripAll;109 bool stripDebug = config->stripDebug || config->stripAll;
335 for (ObjFile *File : Symtab->ObjectFiles) {110 for (ObjFile *file : symtab->objectFiles) {
336 for (InputSection *Section : File->CustomSections) {111 for (InputSection *section : file->customSections) {
337 StringRef Name = Section->getName();112 StringRef name = section->getName();
338 // These custom sections are known the linker and synthesized rather than113 // These custom sections are known the linker and synthesized rather than
339 // blindly copied114 // blindly copied
340 if (Name == "linking" || Name == "name" || Name.startswith("reloc."))115 if (name == "linking" || name == "name" || name == "producers" ||
116 name == "target_features" || name.startswith("reloc."))
341 continue;117 continue;
342 // .. or it is a debug section118 // .. or it is a debug section
343 if (StripDebug && Name.startswith(".debug_"))119 if (stripDebug && name.startswith(".debug_"))
344 continue;120 continue;
345 CustomSectionMapping[Name].push_back(Section);121 customSectionMapping[name].push_back(section);
346 }122 }
347 }123 }
348}124}
349125
350void Writer::createCustomSections() {126void Writer::createCustomSections() {
351 log("createCustomSections");127 log("createCustomSections");
352 for (auto &Pair : CustomSectionMapping) {128 for (auto &pair : customSectionMapping) {
353 StringRef Name = Pair.first();129 StringRef name = pair.first();
354130 LLVM_DEBUG(dbgs() << "createCustomSection: " << name << "\n");
355 auto P = CustomSectionSymbols.find(Name);131
356 if (P != CustomSectionSymbols.end()) {132 OutputSection *sec = make<CustomSection>(name, pair.second);
357 uint32_t SectionIndex = OutputSections.size();133 if (config->relocatable || config->emitRelocs) {
358 P->second->setOutputSectionIndex(SectionIndex);134 auto *sym = make<OutputSectionSymbol>(sec);
135 out.linkingSec->addToSymtab(sym);
136 sec->sectionSym = sym;
359 }137 }
360138 addSection(sec);
361 LLVM_DEBUG(dbgs() << "createCustomSection: " << Name << "\n");
362 OutputSections.push_back(make<CustomSection>(Name, Pair.second));
363 }139 }
364}140}
365141
366void Writer::createElemSection() {
367 if (IndirectFunctions.empty())
368 return;
369
370 SyntheticSection *Section = createSyntheticSection(WASM_SEC_ELEM);
371 raw_ostream &OS = Section->getStream();
372
373 writeUleb128(OS, 1, "segment count");
374 writeUleb128(OS, 0, "table index");
375 WasmInitExpr InitExpr;
376 if (Config->Pic) {
377 InitExpr.Opcode = WASM_OPCODE_GLOBAL_GET;
378 InitExpr.Value.Global = WasmSym::TableBase->getGlobalIndex();
379 } else {
380 InitExpr.Opcode = WASM_OPCODE_I32_CONST;
381 InitExpr.Value.Int32 = TableBase;
382 }
383 writeInitExpr(OS, InitExpr);
384 writeUleb128(OS, IndirectFunctions.size(), "elem count");
385
386 uint32_t TableIndex = TableBase;
387 for (const FunctionSymbol *Sym : IndirectFunctions) {
388 assert(Sym->getTableIndex() == TableIndex);
389 writeUleb128(OS, Sym->getFunctionIndex(), "function index");
390 ++TableIndex;
391 }
392}
393
394void Writer::createCodeSection() {
395 if (InputFunctions.empty())
396 return;
397
398 log("createCodeSection");
399
400 auto Section = make<CodeSection>(InputFunctions);
401 OutputSections.push_back(Section);
402}
403
404void Writer::createDataSection() {
405 if (!Segments.size())
406 return;
407
408 log("createDataSection");
409 auto Section = make<DataSection>(Segments);
410 OutputSections.push_back(Section);
411}
412
413// Create relocations sections in the final output.142// Create relocations sections in the final output.
414// These are only created when relocatable output is requested.143// These are only created when relocatable output is requested.
415void Writer::createRelocSections() {144void Writer::createRelocSections() {
416 log("createRelocSections");145 log("createRelocSections");
417 // Don't use iterator here since we are adding to OutputSection146 // Don't use iterator here since we are adding to OutputSection
418 size_t OrigSize = OutputSections.size();147 size_t origSize = outputSections.size();
419 for (size_t I = 0; I < OrigSize; I++) {148 for (size_t i = 0; i < origSize; i++) {
420 OutputSection *OSec = OutputSections[I];149 LLVM_DEBUG(dbgs() << "check section " << i << "\n");
421 uint32_t Count = OSec->numRelocations();150 OutputSection *sec = outputSections[i];
422 if (!Count)151
152 // Count the number of needed sections.
153 uint32_t count = sec->getNumRelocations();
154 if (!count)
423 continue;155 continue;
424156
425 StringRef Name;157 StringRef name;
426 if (OSec->Type == WASM_SEC_DATA)158 if (sec->type == WASM_SEC_DATA)
427 Name = "reloc.DATA";159 name = "reloc.DATA";
428 else if (OSec->Type == WASM_SEC_CODE)160 else if (sec->type == WASM_SEC_CODE)
429 Name = "reloc.CODE";161 name = "reloc.CODE";
430 else if (OSec->Type == WASM_SEC_CUSTOM)162 else if (sec->type == WASM_SEC_CUSTOM)
431 Name = Saver.save("reloc." + OSec->Name);163 name = saver.save("reloc." + sec->name);
432 else164 else
433 llvm_unreachable(165 llvm_unreachable(
434 "relocations only supported for code, data, or custom sections");166 "relocations only supported for code, data, or custom sections");
435167
436 SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, Name);168 addSection(make<RelocSection>(name, sec));
437 raw_ostream &OS = Section->getStream();
438 writeUleb128(OS, I, "reloc section");
439 writeUleb128(OS, Count, "reloc count");
440 OSec->writeRelocations(OS);
441 }
442}
443
444static uint32_t getWasmFlags(const Symbol *Sym) {
445 uint32_t Flags = 0;
446 if (Sym->isLocal())
447 Flags |= WASM_SYMBOL_BINDING_LOCAL;
448 if (Sym->isWeak())
449 Flags |= WASM_SYMBOL_BINDING_WEAK;
450 if (Sym->isHidden())
451 Flags |= WASM_SYMBOL_VISIBILITY_HIDDEN;
452 if (Sym->isUndefined())
453 Flags |= WASM_SYMBOL_UNDEFINED;
454 if (auto *F = dyn_cast<UndefinedFunction>(Sym)) {
455 if (F->getName() != F->ImportName)
456 Flags |= WASM_SYMBOL_EXPLICIT_NAME;
457 } else if (auto *G = dyn_cast<UndefinedGlobal>(Sym)) {
458 if (G->getName() != G->ImportName)
459 Flags |= WASM_SYMBOL_EXPLICIT_NAME;
460 }169 }
461 return Flags;
462}170}
463171
464// Some synthetic sections (e.g. "name" and "linking") have subsections.172void Writer::populateProducers() {
465// Just like the synthetic sections themselves these need to be created before173 for (ObjFile *file : symtab->objectFiles) {
466// they can be written out (since they are preceded by their length). This174 const WasmProducerInfo &info = file->getWasmObj()->getProducerInfo();
467// class is used to create subsections and then write them into the stream175 out.producersSec->addInfo(info);
468// of the parent section.
469class SubSection {
470public:
471 explicit SubSection(uint32_t Type) : Type(Type) {}
472
473 void writeTo(raw_ostream &To) {
474 OS.flush();
475 writeUleb128(To, Type, "subsection type");
476 writeUleb128(To, Body.size(), "subsection size");
477 To.write(Body.data(), Body.size());
478 }176 }
479
480private:
481 uint32_t Type;
482 std::string Body;
483
484public:
485 raw_string_ostream OS{Body};
486};
487
488// Create the custom "dylink" section containing information for the dynamic
489// linker.
490// See
491// https://github.com/WebAssembly/tool-conventions/blob/master/DynamicLinking.md
492void Writer::createDylinkSection() {
493 SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "dylink");
494 raw_ostream &OS = Section->getStream();
495
496 writeUleb128(OS, MemSize, "MemSize");
497 writeUleb128(OS, MemAlign, "MemAlign");
498 writeUleb128(OS, IndirectFunctions.size(), "TableSize");
499 writeUleb128(OS, 0, "TableAlign");
500 writeUleb128(OS, 0, "Needed"); // TODO: Support "needed" shared libraries
501}
502
503// Create the custom "linking" section containing linker metadata.
504// This is only created when relocatable output is requested.
505void Writer::createLinkingSection() {
506 SyntheticSection *Section =
507 createSyntheticSection(WASM_SEC_CUSTOM, "linking");
508 raw_ostream &OS = Section->getStream();
509
510 writeUleb128(OS, WasmMetadataVersion, "Version");
511
512 if (!SymtabEntries.empty()) {
513 SubSection Sub(WASM_SYMBOL_TABLE);
514 writeUleb128(Sub.OS, SymtabEntries.size(), "num symbols");
515
516 for (const Symbol *Sym : SymtabEntries) {
517 assert(Sym->isDefined() || Sym->isUndefined());
518 WasmSymbolType Kind = Sym->getWasmType();
519 uint32_t Flags = getWasmFlags(Sym);
520
521 writeU8(Sub.OS, Kind, "sym kind");
522 writeUleb128(Sub.OS, Flags, "sym flags");
523
524 if (auto *F = dyn_cast<FunctionSymbol>(Sym)) {
525 writeUleb128(Sub.OS, F->getFunctionIndex(), "index");
526 if (Sym->isDefined() ||
527 (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
528 writeStr(Sub.OS, Sym->getName(), "sym name");
529 } else if (auto *G = dyn_cast<GlobalSymbol>(Sym)) {
530 writeUleb128(Sub.OS, G->getGlobalIndex(), "index");
531 if (Sym->isDefined() ||
532 (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
533 writeStr(Sub.OS, Sym->getName(), "sym name");
534 } else if (auto *E = dyn_cast<EventSymbol>(Sym)) {
535 writeUleb128(Sub.OS, E->getEventIndex(), "index");
536 if (Sym->isDefined() ||
537 (Flags & WASM_SYMBOL_EXPLICIT_NAME) != 0)
538 writeStr(Sub.OS, Sym->getName(), "sym name");
539 } else if (isa<DataSymbol>(Sym)) {
540 writeStr(Sub.OS, Sym->getName(), "sym name");
541 if (auto *DataSym = dyn_cast<DefinedData>(Sym)) {
542 writeUleb128(Sub.OS, DataSym->getOutputSegmentIndex(), "index");
543 writeUleb128(Sub.OS, DataSym->getOutputSegmentOffset(),
544 "data offset");
545 writeUleb128(Sub.OS, DataSym->getSize(), "data size");
546 }
547 } else {
548 auto *S = cast<SectionSymbol>(Sym);
549 writeUleb128(Sub.OS, S->getOutputSectionIndex(), "sym section index");
550 }
551 }
552
553 Sub.writeTo(OS);
554 }
555
556 if (Segments.size()) {
557 SubSection Sub(WASM_SEGMENT_INFO);
558 writeUleb128(Sub.OS, Segments.size(), "num data segments");
559 for (const OutputSegment *S : Segments) {
560 writeStr(Sub.OS, S->Name, "segment name");
561 writeUleb128(Sub.OS, S->Alignment, "alignment");
562 writeUleb128(Sub.OS, 0, "flags");
563 }
564 Sub.writeTo(OS);
565 }
566
567 if (!InitFunctions.empty()) {
568 SubSection Sub(WASM_INIT_FUNCS);
569 writeUleb128(Sub.OS, InitFunctions.size(), "num init functions");
570 for (const WasmInitEntry &F : InitFunctions) {
571 writeUleb128(Sub.OS, F.Priority, "priority");
572 writeUleb128(Sub.OS, F.Sym->getOutputSymbolIndex(), "function index");
573 }
574 Sub.writeTo(OS);
575 }
576
577 struct ComdatEntry {
578 unsigned Kind;
579 uint32_t Index;
580 };
581 std::map<StringRef, std::vector<ComdatEntry>> Comdats;
582
583 for (const InputFunction *F : InputFunctions) {
584 StringRef Comdat = F->getComdatName();
585 if (!Comdat.empty())
586 Comdats[Comdat].emplace_back(
587 ComdatEntry{WASM_COMDAT_FUNCTION, F->getFunctionIndex()});
588 }
589 for (uint32_t I = 0; I < Segments.size(); ++I) {
590 const auto &InputSegments = Segments[I]->InputSegments;
591 if (InputSegments.empty())
592 continue;
593 StringRef Comdat = InputSegments[0]->getComdatName();
594#ifndef NDEBUG
595 for (const InputSegment *IS : InputSegments)
596 assert(IS->getComdatName() == Comdat);
597#endif
598 if (!Comdat.empty())
599 Comdats[Comdat].emplace_back(ComdatEntry{WASM_COMDAT_DATA, I});
600 }
601
602 if (!Comdats.empty()) {
603 SubSection Sub(WASM_COMDAT_INFO);
604 writeUleb128(Sub.OS, Comdats.size(), "num comdats");
605 for (const auto &C : Comdats) {
606 writeStr(Sub.OS, C.first, "comdat name");
607 writeUleb128(Sub.OS, 0, "comdat flags"); // flags for future use
608 writeUleb128(Sub.OS, C.second.size(), "num entries");
609 for (const ComdatEntry &Entry : C.second) {
610 writeU8(Sub.OS, Entry.Kind, "entry kind");
611 writeUleb128(Sub.OS, Entry.Index, "entry index");
612 }
613 }
614 Sub.writeTo(OS);
615 }
616}
617
618// Create the custom "name" section containing debug symbol names.
619void Writer::createNameSection() {
620 unsigned NumNames = NumImportedFunctions;
621 for (const InputFunction *F : InputFunctions)
622 if (!F->getName().empty() || !F->getDebugName().empty())
623 ++NumNames;
624
625 if (NumNames == 0)
626 return;
627
628 SyntheticSection *Section = createSyntheticSection(WASM_SEC_CUSTOM, "name");
629
630 SubSection Sub(WASM_NAMES_FUNCTION);
631 writeUleb128(Sub.OS, NumNames, "name count");
632
633 // Names must appear in function index order. As it happens ImportedSymbols
634 // and InputFunctions are numbered in order with imported functions coming
635 // first.
636 for (const Symbol *S : ImportedSymbols) {
637 if (auto *F = dyn_cast<FunctionSymbol>(S)) {
638 writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
639 writeStr(Sub.OS, toString(*S), "symbol name");
640 }
641 }
642 for (const InputFunction *F : InputFunctions) {
643 if (!F->getName().empty()) {
644 writeUleb128(Sub.OS, F->getFunctionIndex(), "func index");
645 if (!F->getDebugName().empty()) {
646 writeStr(Sub.OS, F->getDebugName(), "symbol name");
647 } else {
648 writeStr(Sub.OS, maybeDemangleSymbol(F->getName()), "symbol name");
649 }
650 }
651 }
652
653 Sub.writeTo(Section->getStream());
654}177}
655178
656void Writer::writeHeader() {179void Writer::writeHeader() {
657 memcpy(Buffer->getBufferStart(), Header.data(), Header.size());180 memcpy(buffer->getBufferStart(), header.data(), header.size());
658}181}
659182
660void Writer::writeSections() {183void Writer::writeSections() {
661 uint8_t *Buf = Buffer->getBufferStart();184 uint8_t *buf = buffer->getBufferStart();
662 parallelForEach(OutputSections, [Buf](OutputSection *S) { S->writeTo(Buf); });185 parallelForEach(outputSections, [buf](OutputSection *s) {
186 assert(s->isNeeded());
187 s->writeTo(buf);
188 });
663}189}
664190
665// Fix the memory layout of the output binary. This assigns memory offsets191// Fix the memory layout of the output binary. This assigns memory offsets
666// to each of the input data sections as well as the explicit stack region.192// to each of the input data sections as well as the explicit stack region.
667// The default memory layout is as follows, from low to high.193// The default memory layout is as follows, from low to high.
668//194//
669// - initialized data (starting at Config->GlobalBase)195// - initialized data (starting at Config->globalBase)
670// - BSS data (not currently implemented in llvm)196// - BSS data (not currently implemented in llvm)
671// - explicit stack (Config->ZStackSize)197// - explicit stack (Config->ZStackSize)
672// - heap start / unallocated198// - heap start / unallocated
...@@ -676,264 +202,349 @@ void Writer::writeSections() {...@@ -676,264 +202,349 @@ void Writer::writeSections() {
676// rather than overwriting global data, but also increases code size since all202// rather than overwriting global data, but also increases code size since all
677// static data loads and stores requires larger offsets.203// static data loads and stores requires larger offsets.
678void Writer::layoutMemory() {204void Writer::layoutMemory() {
679 createOutputSegments();205 uint32_t memoryPtr = 0;
680206
681 uint32_t MemoryPtr = 0;207 auto placeStack = [&]() {
682208 if (config->relocatable || config->isPic)
683 auto PlaceStack = [&]() {
684 if (Config->Relocatable || Config->Shared)
685 return;209 return;
686 MemoryPtr = alignTo(MemoryPtr, StackAlignment);210 memoryPtr = alignTo(memoryPtr, stackAlignment);
687 if (Config->ZStackSize != alignTo(Config->ZStackSize, StackAlignment))211 if (config->zStackSize != alignTo(config->zStackSize, stackAlignment))
688 error("stack size must be " + Twine(StackAlignment) + "-byte aligned");212 error("stack size must be " + Twine(stackAlignment) + "-byte aligned");
689 log("mem: stack size = " + Twine(Config->ZStackSize));213 log("mem: stack size = " + Twine(config->zStackSize));
690 log("mem: stack base = " + Twine(MemoryPtr));214 log("mem: stack base = " + Twine(memoryPtr));
691 MemoryPtr += Config->ZStackSize;215 memoryPtr += config->zStackSize;
692 auto *SP = cast<DefinedGlobal>(WasmSym::StackPointer);216 auto *sp = cast<DefinedGlobal>(WasmSym::stackPointer);
693 SP->Global->Global.InitExpr.Value.Int32 = MemoryPtr;217 sp->global->global.InitExpr.Value.Int32 = memoryPtr;
694 log("mem: stack top = " + Twine(MemoryPtr));218 log("mem: stack top = " + Twine(memoryPtr));
695 };219 };
696220
697 if (Config->StackFirst) {221 if (config->stackFirst) {
698 PlaceStack();222 placeStack();
699 } else {223 } else {
700 MemoryPtr = Config->GlobalBase;224 memoryPtr = config->globalBase;
701 log("mem: global base = " + Twine(Config->GlobalBase));225 log("mem: global base = " + Twine(config->globalBase));
702 }226 }
703227
704 uint32_t DataStart = MemoryPtr;228 if (WasmSym::globalBase)
229 WasmSym::globalBase->setVirtualAddress(config->globalBase);
230
231 uint32_t dataStart = memoryPtr;
705232
706 // Arbitrarily set __dso_handle handle to point to the start of the data233 // Arbitrarily set __dso_handle handle to point to the start of the data
707 // segments.234 // segments.
708 if (WasmSym::DsoHandle)235 if (WasmSym::dsoHandle)
709 WasmSym::DsoHandle->setVirtualAddress(DataStart);236 WasmSym::dsoHandle->setVirtualAddress(dataStart);
710237
711 MemAlign = 0;238 out.dylinkSec->memAlign = 0;
712 for (OutputSegment *Seg : Segments) {239 for (OutputSegment *seg : segments) {
713 MemAlign = std::max(MemAlign, Seg->Alignment);240 out.dylinkSec->memAlign = std::max(out.dylinkSec->memAlign, seg->alignment);
714 MemoryPtr = alignTo(MemoryPtr, 1 << Seg->Alignment);241 memoryPtr = alignTo(memoryPtr, 1ULL << seg->alignment);
715 Seg->StartVA = MemoryPtr;242 seg->startVA = memoryPtr;
716 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", Seg->Name,243 log(formatv("mem: {0,-15} offset={1,-8} size={2,-8} align={3}", seg->name,
717 MemoryPtr, Seg->Size, Seg->Alignment));244 memoryPtr, seg->size, seg->alignment));
718 MemoryPtr += Seg->Size;245 memoryPtr += seg->size;
246
247 if (WasmSym::tlsSize && seg->name == ".tdata") {
248 auto *tlsSize = cast<DefinedGlobal>(WasmSym::tlsSize);
249 tlsSize->global->global.InitExpr.Value.Int32 = seg->size;
250 }
719 }251 }
720252
721 // TODO: Add .bss space here.253 // TODO: Add .bss space here.
722 if (WasmSym::DataEnd)254 if (WasmSym::dataEnd)
723 WasmSym::DataEnd->setVirtualAddress(MemoryPtr);255 WasmSym::dataEnd->setVirtualAddress(memoryPtr);
724256
725 log("mem: static data = " + Twine(MemoryPtr - DataStart));257 log("mem: static data = " + Twine(memoryPtr - dataStart));
726258
727 if (Config->Shared) {259 if (config->shared) {
728 MemSize = MemoryPtr;260 out.dylinkSec->memSize = memoryPtr;
729 return;261 return;
730 }262 }
731263
732 if (!Config->StackFirst)264 if (!config->stackFirst)
733 PlaceStack();265 placeStack();
734266
735 // Set `__heap_base` to directly follow the end of the stack or global data.267 // Set `__heap_base` to directly follow the end of the stack or global data.
736 // The fact that this comes last means that a malloc/brk implementation268 // The fact that this comes last means that a malloc/brk implementation
737 // can grow the heap at runtime.269 // can grow the heap at runtime.
738 if (!Config->Relocatable) {270 log("mem: heap base = " + Twine(memoryPtr));
739 WasmSym::HeapBase->setVirtualAddress(MemoryPtr);271 if (WasmSym::heapBase)
740 log("mem: heap base = " + Twine(MemoryPtr));272 WasmSym::heapBase->setVirtualAddress(memoryPtr);
741 }
742273
743 if (Config->InitialMemory != 0) {274 if (config->initialMemory != 0) {
744 if (Config->InitialMemory != alignTo(Config->InitialMemory, WasmPageSize))275 if (config->initialMemory != alignTo(config->initialMemory, WasmPageSize))
745 error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned");276 error("initial memory must be " + Twine(WasmPageSize) + "-byte aligned");
746 if (MemoryPtr > Config->InitialMemory)277 if (memoryPtr > config->initialMemory)
747 error("initial memory too small, " + Twine(MemoryPtr) + " bytes needed");278 error("initial memory too small, " + Twine(memoryPtr) + " bytes needed");
748 else279 else
749 MemoryPtr = Config->InitialMemory;280 memoryPtr = config->initialMemory;
750 }281 }
751 MemSize = MemoryPtr;282 out.dylinkSec->memSize = memoryPtr;
752 NumMemoryPages = alignTo(MemoryPtr, WasmPageSize) / WasmPageSize;283 out.memorySec->numMemoryPages =
753 log("mem: total pages = " + Twine(NumMemoryPages));284 alignTo(memoryPtr, WasmPageSize) / WasmPageSize;
285 log("mem: total pages = " + Twine(out.memorySec->numMemoryPages));
754286
755 if (Config->MaxMemory != 0) {287 // Check max if explicitly supplied or required by shared memory
756 if (Config->MaxMemory != alignTo(Config->MaxMemory, WasmPageSize))288 if (config->maxMemory != 0 || config->sharedMemory) {
289 if (config->maxMemory != alignTo(config->maxMemory, WasmPageSize))
757 error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned");290 error("maximum memory must be " + Twine(WasmPageSize) + "-byte aligned");
758 if (MemoryPtr > Config->MaxMemory)291 if (memoryPtr > config->maxMemory)
759 error("maximum memory too small, " + Twine(MemoryPtr) + " bytes needed");292 error("maximum memory too small, " + Twine(memoryPtr) + " bytes needed");
760 MaxMemoryPages = Config->MaxMemory / WasmPageSize;293 out.memorySec->maxMemoryPages = config->maxMemory / WasmPageSize;
761 log("mem: max pages = " + Twine(MaxMemoryPages));294 log("mem: max pages = " + Twine(out.memorySec->maxMemoryPages));
762 }295 }
763}296}
764297
765SyntheticSection *Writer::createSyntheticSection(uint32_t Type,298void Writer::addSection(OutputSection *sec) {
766 StringRef Name) {299 if (!sec->isNeeded())
767 auto Sec = make<SyntheticSection>(Type, Name);300 return;
768 log("createSection: " + toString(*Sec));301 log("addSection: " + toString(*sec));
769 OutputSections.push_back(Sec);302 sec->sectionIndex = outputSections.size();
770 return Sec;303 outputSections.push_back(sec);
771}304}
305
306// If a section name is valid as a C identifier (which is rare because of
307// the leading '.'), linkers are expected to define __start_<secname> and
308// __stop_<secname> symbols. They are at beginning and end of the section,
309// respectively. This is not requested by the ELF standard, but GNU ld and
310// gold provide the feature, and used by many programs.
311static void addStartStopSymbols(const OutputSegment *seg) {
312 StringRef name = seg->name;
313 if (!isValidCIdentifier(name))
314 return;
315 LLVM_DEBUG(dbgs() << "addStartStopSymbols: " << name << "\n");
316 uint32_t start = seg->startVA;
317 uint32_t stop = start + seg->size;
318 symtab->addOptionalDataSymbol(saver.save("__start_" + name), start);
319 symtab->addOptionalDataSymbol(saver.save("__stop_" + name), stop);
320}
321
322void Writer::addSections() {
323 addSection(out.dylinkSec);
324 addSection(out.typeSec);
325 addSection(out.importSec);
326 addSection(out.functionSec);
327 addSection(out.tableSec);
328 addSection(out.memorySec);
329 addSection(out.globalSec);
330 addSection(out.eventSec);
331 addSection(out.exportSec);
332 addSection(out.elemSec);
333 addSection(out.dataCountSec);
334
335 addSection(make<CodeSection>(out.functionSec->inputFunctions));
336 addSection(make<DataSection>(segments));
772337
773void Writer::createSections() {
774 // Known sections
775 if (Config->Pic)
776 createDylinkSection();
777 createTypeSection();
778 createImportSection();
779 createFunctionSection();
780 createTableSection();
781 createMemorySection();
782 createGlobalSection();
783 createEventSection();
784 createExportSection();
785 createElemSection();
786 createCodeSection();
787 createDataSection();
788 createCustomSections();338 createCustomSections();
789339
790 // Custom sections340 addSection(out.linkingSec);
791 if (Config->Relocatable) {341 if (config->emitRelocs || config->relocatable) {
792 createLinkingSection();
793 createRelocSections();342 createRelocSections();
794 }343 }
795 if (!Config->StripDebug && !Config->StripAll)
796 createNameSection();
797344
798 for (OutputSection *S : OutputSections) {345 addSection(out.nameSec);
799 S->setOffset(FileSize);346 addSection(out.producersSec);
800 S->finalizeContents();347 addSection(out.targetFeaturesSec);
801 FileSize += S->getSize();348}
349
350void Writer::finalizeSections() {
351 for (OutputSection *s : outputSections) {
352 s->setOffset(fileSize);
353 s->finalizeContents();
354 fileSize += s->getSize();
355 }
356}
357
358void Writer::populateTargetFeatures() {
359 StringMap<std::string> used;
360 StringMap<std::string> required;
361 StringMap<std::string> disallowed;
362 bool tlsUsed = false;
363
364 // Only infer used features if user did not specify features
365 bool inferFeatures = !config->features.hasValue();
366
367 if (!inferFeatures) {
368 for (auto &feature : config->features.getValue())
369 out.targetFeaturesSec->features.insert(feature);
370 // No need to read or check features
371 if (!config->checkFeatures)
372 return;
373 }
374
375 // Find the sets of used, required, and disallowed features
376 for (ObjFile *file : symtab->objectFiles) {
377 StringRef fileName(file->getName());
378 for (auto &feature : file->getWasmObj()->getTargetFeatures()) {
379 switch (feature.Prefix) {
380 case WASM_FEATURE_PREFIX_USED:
381 used.insert({feature.Name, fileName});
382 break;
383 case WASM_FEATURE_PREFIX_REQUIRED:
384 used.insert({feature.Name, fileName});
385 required.insert({feature.Name, fileName});
386 break;
387 case WASM_FEATURE_PREFIX_DISALLOWED:
388 disallowed.insert({feature.Name, fileName});
389 break;
390 default:
391 error("Unrecognized feature policy prefix " +
392 std::to_string(feature.Prefix));
393 }
394 }
395
396 for (InputSegment *segment : file->segments) {
397 if (!segment->live)
398 continue;
399 StringRef name = segment->getName();
400 if (name.startswith(".tdata") || name.startswith(".tbss"))
401 tlsUsed = true;
402 }
403 }
404
405 if (inferFeatures)
406 out.targetFeaturesSec->features.insert(used.keys().begin(),
407 used.keys().end());
408
409 if (out.targetFeaturesSec->features.count("atomics") &&
410 !config->sharedMemory) {
411 if (inferFeatures)
412 error(Twine("'atomics' feature is used by ") + used["atomics"] +
413 ", so --shared-memory must be used");
414 else
415 error("'atomics' feature is used, so --shared-memory must be used");
416 }
417
418 if (!config->checkFeatures)
419 return;
420
421 if (disallowed.count("atomics") && config->sharedMemory)
422 error("'atomics' feature is disallowed by " + disallowed["atomics"] +
423 ", so --shared-memory must not be used");
424
425 if (!used.count("bulk-memory") && config->passiveSegments)
426 error("'bulk-memory' feature must be used in order to emit passive "
427 "segments");
428
429 if (!used.count("bulk-memory") && tlsUsed)
430 error("'bulk-memory' feature must be used in order to use thread-local "
431 "storage");
432
433 // Validate that used features are allowed in output
434 if (!inferFeatures) {
435 for (auto &feature : used.keys()) {
436 if (!out.targetFeaturesSec->features.count(feature))
437 error(Twine("Target feature '") + feature + "' used by " +
438 used[feature] + " is not allowed.");
439 }
440 }
441
442 // Validate the required and disallowed constraints for each file
443 for (ObjFile *file : symtab->objectFiles) {
444 StringRef fileName(file->getName());
445 SmallSet<std::string, 8> objectFeatures;
446 for (auto &feature : file->getWasmObj()->getTargetFeatures()) {
447 if (feature.Prefix == WASM_FEATURE_PREFIX_DISALLOWED)
448 continue;
449 objectFeatures.insert(feature.Name);
450 if (disallowed.count(feature.Name))
451 error(Twine("Target feature '") + feature.Name + "' used in " +
452 fileName + " is disallowed by " + disallowed[feature.Name] +
453 ". Use --no-check-features to suppress.");
454 }
455 for (auto &feature : required.keys()) {
456 if (!objectFeatures.count(feature))
457 error(Twine("Missing target feature '") + feature + "' in " + fileName +
458 ", required by " + required[feature] +
459 ". Use --no-check-features to suppress.");
460 }
802 }461 }
803}462}
804463
805void Writer::calculateImports() {464void Writer::calculateImports() {
806 for (Symbol *Sym : Symtab->getSymbols()) {465 for (Symbol *sym : symtab->getSymbols()) {
807 if (!Sym->isUndefined())466 if (!sym->isUndefined())
808 continue;467 continue;
809 if (isa<DataSymbol>(Sym))468 if (sym->isWeak() && !config->relocatable)
810 continue;469 continue;
811 if (Sym->isWeak() && !Config->Relocatable)470 if (!sym->isLive())
812 continue;471 continue;
813 if (!Sym->isLive())472 if (!sym->isUsedInRegularObj)
814 continue;473 continue;
815 if (!Sym->IsUsedInRegularObj)474 // We don't generate imports for data symbols. They however can be imported
475 // as GOT entries.
476 if (isa<DataSymbol>(sym))
816 continue;477 continue;
817478
818 LLVM_DEBUG(dbgs() << "import: " << Sym->getName() << "\n");479 LLVM_DEBUG(dbgs() << "import: " << sym->getName() << "\n");
819 ImportedSymbols.emplace_back(Sym);480 out.importSec->addImport(sym);
820 if (auto *F = dyn_cast<FunctionSymbol>(Sym))
821 F->setFunctionIndex(NumImportedFunctions++);
822 else if (auto *G = dyn_cast<GlobalSymbol>(Sym))
823 G->setGlobalIndex(NumImportedGlobals++);
824 else
825 cast<EventSymbol>(Sym)->setEventIndex(NumImportedEvents++);
826 }481 }
827}482}
828483
829void Writer::calculateExports() {484void Writer::calculateExports() {
830 if (Config->Relocatable)485 if (config->relocatable)
831 return;486 return;
832487
833 if (!Config->Relocatable && !Config->ImportMemory)488 if (!config->relocatable && !config->importMemory)
834 Exports.push_back(WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0});489 out.exportSec->exports.push_back(
490 WasmExport{"memory", WASM_EXTERNAL_MEMORY, 0});
835491
836 if (!Config->Relocatable && Config->ExportTable)492 if (!config->relocatable && config->exportTable)
837 Exports.push_back(WasmExport{FunctionTableName, WASM_EXTERNAL_TABLE, 0});493 out.exportSec->exports.push_back(
494 WasmExport{functionTableName, WASM_EXTERNAL_TABLE, 0});
838495
839 unsigned FakeGlobalIndex = NumImportedGlobals + InputGlobals.size();496 unsigned fakeGlobalIndex = out.importSec->getNumImportedGlobals() +
497 out.globalSec->inputGlobals.size();
840498
841 for (Symbol *Sym : Symtab->getSymbols()) {499 for (Symbol *sym : symtab->getSymbols()) {
842 if (!Sym->isExported())500 if (!sym->isExported())
843 continue;501 continue;
844 if (!Sym->isLive())502 if (!sym->isLive())
845 continue;503 continue;
846504
847 StringRef Name = Sym->getName();505 StringRef name = sym->getName();
848 WasmExport Export;506 WasmExport export_;
849 if (auto *F = dyn_cast<DefinedFunction>(Sym)) {507 if (auto *f = dyn_cast<DefinedFunction>(sym)) {
850 Export = {Name, WASM_EXTERNAL_FUNCTION, F->getFunctionIndex()};508 export_ = {name, WASM_EXTERNAL_FUNCTION, f->getFunctionIndex()};
851 } else if (auto *G = dyn_cast<DefinedGlobal>(Sym)) {509 } else if (auto *g = dyn_cast<DefinedGlobal>(sym)) {
852 // TODO(sbc): Remove this check once to mutable global proposal is510 // TODO(sbc): Remove this check once to mutable global proposal is
853 // implement in all major browsers.511 // implement in all major browsers.
854 // See: https://github.com/WebAssembly/mutable-global512 // See: https://github.com/WebAssembly/mutable-global
855 if (G->getGlobalType()->Mutable) {513 if (g->getGlobalType()->Mutable) {
856 // Only the __stack_pointer should ever be create as mutable.514 // Only __stack_pointer and __tls_base should ever be create as mutable.
857 assert(G == WasmSym::StackPointer);515 assert(g == WasmSym::stackPointer || g == WasmSym::tlsBase);
858 continue;516 continue;
859 }517 }
860 Export = {Name, WASM_EXTERNAL_GLOBAL, G->getGlobalIndex()};518 export_ = {name, WASM_EXTERNAL_GLOBAL, g->getGlobalIndex()};
861 } else if (auto *E = dyn_cast<DefinedEvent>(Sym)) {519 } else if (auto *e = dyn_cast<DefinedEvent>(sym)) {
862 Export = {Name, WASM_EXTERNAL_EVENT, E->getEventIndex()};520 export_ = {name, WASM_EXTERNAL_EVENT, e->getEventIndex()};
863 } else {521 } else {
864 auto *D = cast<DefinedData>(Sym);522 auto *d = cast<DefinedData>(sym);
865 DefinedFakeGlobals.emplace_back(D);523 out.globalSec->definedFakeGlobals.emplace_back(d);
866 Export = {Name, WASM_EXTERNAL_GLOBAL, FakeGlobalIndex++};524 export_ = {name, WASM_EXTERNAL_GLOBAL, fakeGlobalIndex++};
867 }525 }
868526
869 LLVM_DEBUG(dbgs() << "Export: " << Name << "\n");527 LLVM_DEBUG(dbgs() << "Export: " << name << "\n");
870 Exports.push_back(Export);528 out.exportSec->exports.push_back(export_);
871 }529 }
872}530}
873531
874void Writer::assignSymtab() {532void Writer::populateSymtab() {
875 if (!Config->Relocatable)533 if (!config->relocatable && !config->emitRelocs)
876 return;534 return;
877535
878 StringMap<uint32_t> SectionSymbolIndices;536 for (Symbol *sym : symtab->getSymbols())
879537 if (sym->isUsedInRegularObj && sym->isLive())
880 unsigned SymbolIndex = SymtabEntries.size();538 out.linkingSec->addToSymtab(sym);
881
882 auto AddSymbol = [&](Symbol *Sym) {
883 if (auto *S = dyn_cast<SectionSymbol>(Sym)) {
884 StringRef Name = S->getName();
885 if (CustomSectionMapping.count(Name) == 0)
886 return;
887
888 auto SSI = SectionSymbolIndices.find(Name);
889 if (SSI != SectionSymbolIndices.end()) {
890 Sym->setOutputSymbolIndex(SSI->second);
891 return;
892 }
893
894 SectionSymbolIndices[Name] = SymbolIndex;
895 CustomSectionSymbols[Name] = cast<SectionSymbol>(Sym);
896
897 Sym->markLive();
898 }
899
900 // (Since this is relocatable output, GC is not performed so symbols must
901 // be live.)
902 assert(Sym->isLive());
903 Sym->setOutputSymbolIndex(SymbolIndex++);
904 SymtabEntries.emplace_back(Sym);
905 };
906
907 for (Symbol *Sym : Symtab->getSymbols())
908 if (!Sym->isLazy())
909 AddSymbol(Sym);
910539
911 for (ObjFile *File : Symtab->ObjectFiles) {540 for (ObjFile *file : symtab->objectFiles) {
912 LLVM_DEBUG(dbgs() << "Local symtab entries: " << File->getName() << "\n");541 LLVM_DEBUG(dbgs() << "Local symtab entries: " << file->getName() << "\n");
913 for (Symbol *Sym : File->getSymbols())542 for (Symbol *sym : file->getSymbols())
914 if (Sym->isLocal())543 if (sym->isLocal() && !isa<SectionSymbol>(sym) && sym->isLive())
915 AddSymbol(Sym);544 out.linkingSec->addToSymtab(sym);
916 }545 }
917}546}
918547
919uint32_t Writer::lookupType(const WasmSignature &Sig) {
920 auto It = TypeIndices.find(Sig);
921 if (It == TypeIndices.end()) {
922 error("type not found: " + toString(Sig));
923 return 0;
924 }
925 return It->second;
926}
927
928uint32_t Writer::registerType(const WasmSignature &Sig) {
929 auto Pair = TypeIndices.insert(std::make_pair(Sig, Types.size()));
930 if (Pair.second) {
931 LLVM_DEBUG(dbgs() << "type " << toString(Sig) << "\n");
932 Types.push_back(&Sig);
933 }
934 return Pair.first->second;
935}
936
937void Writer::calculateTypes() {548void Writer::calculateTypes() {
938 // The output type section is the union of the following sets:549 // The output type section is the union of the following sets:
939 // 1. Any signature used in the TYPE relocation550 // 1. Any signature used in the TYPE relocation
...@@ -942,244 +553,383 @@ void Writer::calculateTypes() {...@@ -942,244 +553,383 @@ void Writer::calculateTypes() {
942 // 4. The signatures of all imported events553 // 4. The signatures of all imported events
943 // 5. The signatures of all defined events554 // 5. The signatures of all defined events
944555
945 for (ObjFile *File : Symtab->ObjectFiles) {556 for (ObjFile *file : symtab->objectFiles) {
946 ArrayRef<WasmSignature> Types = File->getWasmObj()->types();557 ArrayRef<WasmSignature> types = file->getWasmObj()->types();
947 for (uint32_t I = 0; I < Types.size(); I++)558 for (uint32_t i = 0; i < types.size(); i++)
948 if (File->TypeIsUsed[I])559 if (file->typeIsUsed[i])
949 File->TypeMap[I] = registerType(Types[I]);560 file->typeMap[i] = out.typeSec->registerType(types[i]);
950 }561 }
951562
952 for (const Symbol *Sym : ImportedSymbols) {563 for (const Symbol *sym : out.importSec->importedSymbols) {
953 if (auto *F = dyn_cast<FunctionSymbol>(Sym))564 if (auto *f = dyn_cast<FunctionSymbol>(sym))
954 registerType(*F->Signature);565 out.typeSec->registerType(*f->signature);
955 else if (auto *E = dyn_cast<EventSymbol>(Sym))566 else if (auto *e = dyn_cast<EventSymbol>(sym))
956 registerType(*E->Signature);567 out.typeSec->registerType(*e->signature);
957 }568 }
958569
959 for (const InputFunction *F : InputFunctions)570 for (const InputFunction *f : out.functionSec->inputFunctions)
960 registerType(F->Signature);571 out.typeSec->registerType(f->signature);
961572
962 for (const InputEvent *E : InputEvents)573 for (const InputEvent *e : out.eventSec->inputEvents)
963 registerType(E->Signature);574 out.typeSec->registerType(e->signature);
964}575}
965576
966void Writer::assignIndexes() {577static void scanRelocations() {
967 assert(InputFunctions.empty());578 for (ObjFile *file : symtab->objectFiles) {
968 uint32_t FunctionIndex = NumImportedFunctions;579 LLVM_DEBUG(dbgs() << "scanRelocations: " << file->getName() << "\n");
969 auto AddDefinedFunction = [&](InputFunction *Func) {580 for (InputChunk *chunk : file->functions)
970 if (!Func->Live)581 scanRelocations(chunk);
971 return;582 for (InputChunk *chunk : file->segments)
972 InputFunctions.emplace_back(Func);583 scanRelocations(chunk);
973 Func->setFunctionIndex(FunctionIndex++);584 for (auto &p : file->customSections)
974 };585 scanRelocations(p);
975
976 for (InputFunction *Func : Symtab->SyntheticFunctions)
977 AddDefinedFunction(Func);
978
979 for (ObjFile *File : Symtab->ObjectFiles) {
980 LLVM_DEBUG(dbgs() << "Functions: " << File->getName() << "\n");
981 for (InputFunction *Func : File->Functions)
982 AddDefinedFunction(Func);
983 }586 }
587}
984588
985 uint32_t TableIndex = TableBase;589void Writer::assignIndexes() {
986 auto HandleRelocs = [&](InputChunk *Chunk) {590 // Seal the import section, since other index spaces such as function and
987 if (!Chunk->Live)591 // global are effected by the number of imports.
988 return;592 out.importSec->seal();
989 ObjFile *File = Chunk->File;
990 ArrayRef<WasmSignature> Types = File->getWasmObj()->types();
991 for (const WasmRelocation &Reloc : Chunk->getRelocations()) {
992 if (Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_I32 ||
993 Reloc.Type == R_WEBASSEMBLY_TABLE_INDEX_SLEB) {
994 FunctionSymbol *Sym = File->getFunctionSymbol(Reloc.Index);
995 if (Sym->hasTableIndex() || !Sym->hasFunctionIndex())
996 continue;
997 Sym->setTableIndex(TableIndex++);
998 IndirectFunctions.emplace_back(Sym);
999 } else if (Reloc.Type == R_WEBASSEMBLY_TYPE_INDEX_LEB) {
1000 // Mark target type as live
1001 File->TypeMap[Reloc.Index] = registerType(Types[Reloc.Index]);
1002 File->TypeIsUsed[Reloc.Index] = true;
1003 }
1004 }
1005 };
1006593
1007 for (ObjFile *File : Symtab->ObjectFiles) {594 for (InputFunction *func : symtab->syntheticFunctions)
1008 LLVM_DEBUG(dbgs() << "Handle relocs: " << File->getName() << "\n");595 out.functionSec->addFunction(func);
1009 for (InputChunk *Chunk : File->Functions)
1010 HandleRelocs(Chunk);
1011 for (InputChunk *Chunk : File->Segments)
1012 HandleRelocs(Chunk);
1013 for (auto &P : File->CustomSections)
1014 HandleRelocs(P);
1015 }
1016596
1017 assert(InputGlobals.empty());597 for (ObjFile *file : symtab->objectFiles) {
1018 uint32_t GlobalIndex = NumImportedGlobals;598 LLVM_DEBUG(dbgs() << "Functions: " << file->getName() << "\n");
1019 auto AddDefinedGlobal = [&](InputGlobal *Global) {599 for (InputFunction *func : file->functions)
1020 if (Global->Live) {600 out.functionSec->addFunction(func);
1021 LLVM_DEBUG(dbgs() << "AddDefinedGlobal: " << GlobalIndex << "\n");601 }
1022 Global->setGlobalIndex(GlobalIndex++);
1023 InputGlobals.push_back(Global);
1024 }
1025 };
1026602
1027 for (InputGlobal *Global : Symtab->SyntheticGlobals)603 for (InputGlobal *global : symtab->syntheticGlobals)
1028 AddDefinedGlobal(Global);604 out.globalSec->addGlobal(global);
1029605
1030 for (ObjFile *File : Symtab->ObjectFiles) {606 for (ObjFile *file : symtab->objectFiles) {
1031 LLVM_DEBUG(dbgs() << "Globals: " << File->getName() << "\n");607 LLVM_DEBUG(dbgs() << "Globals: " << file->getName() << "\n");
1032 for (InputGlobal *Global : File->Globals)608 for (InputGlobal *global : file->globals)
1033 AddDefinedGlobal(Global);609 out.globalSec->addGlobal(global);
1034 }610 }
1035611
1036 assert(InputEvents.empty());612 for (ObjFile *file : symtab->objectFiles) {
1037 uint32_t EventIndex = NumImportedEvents;613 LLVM_DEBUG(dbgs() << "Events: " << file->getName() << "\n");
1038 auto AddDefinedEvent = [&](InputEvent *Event) {614 for (InputEvent *event : file->events)
1039 if (Event->Live) {615 out.eventSec->addEvent(event);
1040 LLVM_DEBUG(dbgs() << "AddDefinedEvent: " << EventIndex << "\n");
1041 Event->setEventIndex(EventIndex++);
1042 InputEvents.push_back(Event);
1043 }
1044 };
1045
1046 for (ObjFile *File : Symtab->ObjectFiles) {
1047 LLVM_DEBUG(dbgs() << "Events: " << File->getName() << "\n");
1048 for (InputEvent *Event : File->Events)
1049 AddDefinedEvent(Event);
1050 }616 }
1051}617}
1052618
1053static StringRef getOutputDataSegmentName(StringRef Name) {619static StringRef getOutputDataSegmentName(StringRef name) {
1054 // With PIC code we currently only support a single data segment since620 // With PIC code we currently only support a single data segment since
1055 // we only have a single __memory_base to use as our base address.621 // we only have a single __memory_base to use as our base address.
1056 if (Config->Pic)622 if (config->isPic)
1057 return "data";623 return ".data";
1058 if (!Config->MergeDataSegments)624 // We only support one thread-local segment, so we must merge the segments
1059 return Name;625 // despite --no-merge-data-segments.
1060 if (Name.startswith(".text."))626 // We also need to merge .tbss into .tdata so they share the same offsets.
627 if (name.startswith(".tdata") || name.startswith(".tbss"))
628 return ".tdata";
629 if (!config->mergeDataSegments)
630 return name;
631 if (name.startswith(".text."))
1061 return ".text";632 return ".text";
1062 if (Name.startswith(".data."))633 if (name.startswith(".data."))
1063 return ".data";634 return ".data";
1064 if (Name.startswith(".bss."))635 if (name.startswith(".bss."))
1065 return ".bss";636 return ".bss";
1066 if (Name.startswith(".rodata."))637 if (name.startswith(".rodata."))
1067 return ".rodata";638 return ".rodata";
1068 return Name;639 return name;
1069}640}
1070641
1071void Writer::createOutputSegments() {642void Writer::createOutputSegments() {
1072 for (ObjFile *File : Symtab->ObjectFiles) {643 for (ObjFile *file : symtab->objectFiles) {
1073 for (InputSegment *Segment : File->Segments) {644 for (InputSegment *segment : file->segments) {
1074 if (!Segment->Live)645 if (!segment->live)
1075 continue;646 continue;
1076 StringRef Name = getOutputDataSegmentName(Segment->getName());647 StringRef name = getOutputDataSegmentName(segment->getName());
1077 OutputSegment *&S = SegmentMap[Name];648 OutputSegment *&s = segmentMap[name];
1078 if (S == nullptr) {649 if (s == nullptr) {
1079 LLVM_DEBUG(dbgs() << "new segment: " << Name << "\n");650 LLVM_DEBUG(dbgs() << "new segment: " << name << "\n");
1080 S = make<OutputSegment>(Name, Segments.size());651 s = make<OutputSegment>(name, segments.size());
1081 Segments.push_back(S);652 if (config->passiveSegments || name == ".tdata")
653 s->initFlags = WASM_SEGMENT_IS_PASSIVE;
654 segments.push_back(s);
655 }
656 s->addInputSegment(segment);
657 LLVM_DEBUG(dbgs() << "added data: " << name << ": " << s->size << "\n");
658 }
659 }
660}
661
662static void createFunction(DefinedFunction *func, StringRef bodyContent) {
663 std::string functionBody;
664 {
665 raw_string_ostream os(functionBody);
666 writeUleb128(os, bodyContent.size(), "function size");
667 os << bodyContent;
668 }
669 ArrayRef<uint8_t> body = arrayRefFromStringRef(saver.save(functionBody));
670 cast<SyntheticFunction>(func->function)->setBody(body);
671}
672
673void Writer::createInitMemoryFunction() {
674 LLVM_DEBUG(dbgs() << "createInitMemoryFunction\n");
675 std::string bodyContent;
676 {
677 raw_string_ostream os(bodyContent);
678 writeUleb128(os, 0, "num locals");
679
680 // initialize passive data segments
681 for (const OutputSegment *s : segments) {
682 if (s->initFlags & WASM_SEGMENT_IS_PASSIVE && s->name != ".tdata") {
683 // destination address
684 writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
685 writeSleb128(os, s->startVA, "destination address");
686 // source segment offset
687 writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
688 writeSleb128(os, 0, "segment offset");
689 // memory region size
690 writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
691 writeSleb128(os, s->size, "memory region size");
692 // memory.init instruction
693 writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
694 writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT");
695 writeUleb128(os, s->index, "segment index immediate");
696 writeU8(os, 0, "memory index immediate");
697 // data.drop instruction
698 writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
699 writeUleb128(os, WASM_OPCODE_DATA_DROP, "DATA.DROP");
700 writeUleb128(os, s->index, "segment index immediate");
1082 }701 }
1083 S->addInputSegment(Segment);
1084 LLVM_DEBUG(dbgs() << "added data: " << Name << ": " << S->Size << "\n");
1085 }702 }
703 writeU8(os, WASM_OPCODE_END, "END");
1086 }704 }
705
706 createFunction(WasmSym::initMemory, bodyContent);
1087}707}
1088708
1089static const int OPCODE_CALL = 0x10;709// For -shared (PIC) output, we create create a synthetic function which will
1090static const int OPCODE_END = 0xb;710// apply any relocations to the data segments on startup. This function is
711// called __wasm_apply_relocs and is added at the beginning of __wasm_call_ctors
712// before any of the constructors run.
713void Writer::createApplyRelocationsFunction() {
714 LLVM_DEBUG(dbgs() << "createApplyRelocationsFunction\n");
715 // First write the body's contents to a string.
716 std::string bodyContent;
717 {
718 raw_string_ostream os(bodyContent);
719 writeUleb128(os, 0, "num locals");
720 for (const OutputSegment *seg : segments)
721 for (const InputSegment *inSeg : seg->inputSegments)
722 inSeg->generateRelocationCode(os);
723 writeU8(os, WASM_OPCODE_END, "END");
724 }
725
726 createFunction(WasmSym::applyRelocs, bodyContent);
727}
1091728
1092// Create synthetic "__wasm_call_ctors" function based on ctor functions729// Create synthetic "__wasm_call_ctors" function based on ctor functions
1093// in input object.730// in input object.
1094void Writer::createCtorFunction() {731void Writer::createCallCtorsFunction() {
732 if (!WasmSym::callCtors->isLive())
733 return;
734
1095 // First write the body's contents to a string.735 // First write the body's contents to a string.
1096 std::string BodyContent;736 std::string bodyContent;
1097 {737 {
1098 raw_string_ostream OS(BodyContent);738 raw_string_ostream os(bodyContent);
1099 writeUleb128(OS, 0, "num locals");739 writeUleb128(os, 0, "num locals");
1100 for (const WasmInitEntry &F : InitFunctions) {740
1101 writeU8(OS, OPCODE_CALL, "CALL");741 if (config->passiveSegments) {
1102 writeUleb128(OS, F.Sym->getFunctionIndex(), "function index");742 writeU8(os, WASM_OPCODE_CALL, "CALL");
743 writeUleb128(os, WasmSym::initMemory->getFunctionIndex(),
744 "function index");
745 }
746
747 if (config->isPic) {
748 writeU8(os, WASM_OPCODE_CALL, "CALL");
749 writeUleb128(os, WasmSym::applyRelocs->getFunctionIndex(),
750 "function index");
751 }
752
753 // Call constructors
754 for (const WasmInitEntry &f : initFunctions) {
755 writeU8(os, WASM_OPCODE_CALL, "CALL");
756 writeUleb128(os, f.sym->getFunctionIndex(), "function index");
1103 }757 }
1104 writeU8(OS, OPCODE_END, "END");758 writeU8(os, WASM_OPCODE_END, "END");
1105 }759 }
1106760
1107 // Once we know the size of the body we can create the final function body761 createFunction(WasmSym::callCtors, bodyContent);
1108 std::string FunctionBody;762}
763
764void Writer::createInitTLSFunction() {
765 if (!WasmSym::initTLS->isLive())
766 return;
767
768 std::string bodyContent;
1109 {769 {
1110 raw_string_ostream OS(FunctionBody);770 raw_string_ostream os(bodyContent);
1111 writeUleb128(OS, BodyContent.size(), "function size");771
1112 OS << BodyContent;772 OutputSegment *tlsSeg = nullptr;
773 for (auto *seg : segments) {
774 if (seg->name == ".tdata") {
775 tlsSeg = seg;
776 break;
777 }
778 }
779
780 writeUleb128(os, 0, "num locals");
781 if (tlsSeg) {
782 writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get");
783 writeUleb128(os, 0, "local index");
784
785 writeU8(os, WASM_OPCODE_GLOBAL_SET, "global.set");
786 writeUleb128(os, WasmSym::tlsBase->getGlobalIndex(), "global index");
787
788 writeU8(os, WASM_OPCODE_LOCAL_GET, "local.get");
789 writeUleb128(os, 0, "local index");
790
791 writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
792 writeSleb128(os, 0, "segment offset");
793
794 writeU8(os, WASM_OPCODE_I32_CONST, "i32.const");
795 writeSleb128(os, tlsSeg->size, "memory region size");
796
797 writeU8(os, WASM_OPCODE_MISC_PREFIX, "bulk-memory prefix");
798 writeUleb128(os, WASM_OPCODE_MEMORY_INIT, "MEMORY.INIT");
799 writeUleb128(os, tlsSeg->index, "segment index immediate");
800 writeU8(os, 0, "memory index immediate");
801 }
802 writeU8(os, WASM_OPCODE_END, "end function");
1113 }803 }
1114804
1115 ArrayRef<uint8_t> Body = arrayRefFromStringRef(Saver.save(FunctionBody));805 createFunction(WasmSym::initTLS, bodyContent);
1116 cast<SyntheticFunction>(WasmSym::CallCtors->Function)->setBody(Body);
1117}806}
1118807
1119// Populate InitFunctions vector with init functions from all input objects.808// Populate InitFunctions vector with init functions from all input objects.
1120// This is then used either when creating the output linking section or to809// This is then used either when creating the output linking section or to
1121// synthesize the "__wasm_call_ctors" function.810// synthesize the "__wasm_call_ctors" function.
1122void Writer::calculateInitFunctions() {811void Writer::calculateInitFunctions() {
1123 for (ObjFile *File : Symtab->ObjectFiles) {812 if (!config->relocatable && !WasmSym::callCtors->isLive())
1124 const WasmLinkingData &L = File->getWasmObj()->linkingData();813 return;
1125 for (const WasmInitFunc &F : L.InitFunctions) {814
1126 FunctionSymbol *Sym = File->getFunctionSymbol(F.Symbol);815 for (ObjFile *file : symtab->objectFiles) {
1127 if (*Sym->Signature != WasmSignature{{}, {}})816 const WasmLinkingData &l = file->getWasmObj()->linkingData();
1128 error("invalid signature for init func: " + toString(*Sym));817 for (const WasmInitFunc &f : l.InitFunctions) {
1129 InitFunctions.emplace_back(WasmInitEntry{Sym, F.Priority});818 FunctionSymbol *sym = file->getFunctionSymbol(f.Symbol);
819 // comdat exclusions can cause init functions be discarded.
820 if (sym->isDiscarded())
821 continue;
822 assert(sym->isLive());
823 if (*sym->signature != WasmSignature{{}, {}})
824 error("invalid signature for init func: " + toString(*sym));
825 LLVM_DEBUG(dbgs() << "initFunctions: " << toString(*sym) << "\n");
826 initFunctions.emplace_back(WasmInitEntry{sym, f.Priority});
1130 }827 }
1131 }828 }
1132829
1133 // Sort in order of priority (lowest first) so that they are called830 // Sort in order of priority (lowest first) so that they are called
1134 // in the correct order.831 // in the correct order.
1135 std::stable_sort(InitFunctions.begin(), InitFunctions.end(),832 llvm::stable_sort(initFunctions,
1136 [](const WasmInitEntry &L, const WasmInitEntry &R) {833 [](const WasmInitEntry &l, const WasmInitEntry &r) {
1137 return L.Priority < R.Priority;834 return l.priority < r.priority;
1138 });835 });
836}
837
838void Writer::createSyntheticSections() {
839 out.dylinkSec = make<DylinkSection>();
840 out.typeSec = make<TypeSection>();
841 out.importSec = make<ImportSection>();
842 out.functionSec = make<FunctionSection>();
843 out.tableSec = make<TableSection>();
844 out.memorySec = make<MemorySection>();
845 out.globalSec = make<GlobalSection>();
846 out.eventSec = make<EventSection>();
847 out.exportSec = make<ExportSection>();
848 out.elemSec = make<ElemSection>(tableBase);
849 out.dataCountSec = make<DataCountSection>(segments.size());
850 out.linkingSec = make<LinkingSection>(initFunctions, segments);
851 out.nameSec = make<NameSection>();
852 out.producersSec = make<ProducersSection>();
853 out.targetFeaturesSec = make<TargetFeaturesSection>();
1139}854}
1140855
1141void Writer::run() {856void Writer::run() {
1142 if (Config->Relocatable || Config->Pic)857 if (config->relocatable || config->isPic)
1143 Config->GlobalBase = 0;858 config->globalBase = 0;
1144859
1145 // For PIC code the table base is assigned dynamically by the loader.860 // For PIC code the table base is assigned dynamically by the loader.
1146 // For non-PIC, we start at 1 so that accessing table index 0 always traps.861 // For non-PIC, we start at 1 so that accessing table index 0 always traps.
1147 if (!Config->Pic)862 if (!config->isPic)
1148 TableBase = 1;863 tableBase = 1;
1149864
865 log("-- createOutputSegments");
866 createOutputSegments();
867 log("-- createSyntheticSections");
868 createSyntheticSections();
869 log("-- populateProducers");
870 populateProducers();
871 log("-- populateTargetFeatures");
872 populateTargetFeatures();
1150 log("-- calculateImports");873 log("-- calculateImports");
1151 calculateImports();874 calculateImports();
875 log("-- layoutMemory");
876 layoutMemory();
877
878 if (!config->relocatable) {
879 // Create linker synthesized __start_SECNAME/__stop_SECNAME symbols
880 // This has to be done after memory layout is performed.
881 for (const OutputSegment *seg : segments)
882 addStartStopSymbols(seg);
883 }
884
885 log("-- scanRelocations");
886 scanRelocations();
1152 log("-- assignIndexes");887 log("-- assignIndexes");
1153 assignIndexes();888 assignIndexes();
1154 log("-- calculateInitFunctions");889 log("-- calculateInitFunctions");
1155 calculateInitFunctions();890 calculateInitFunctions();
1156 if (!Config->Relocatable)891
1157 createCtorFunction();892 if (!config->relocatable) {
893 // Create linker synthesized functions
894 if (config->passiveSegments)
895 createInitMemoryFunction();
896 if (config->isPic)
897 createApplyRelocationsFunction();
898 createCallCtorsFunction();
899 }
900
901 if (config->sharedMemory && !config->shared)
902 createInitTLSFunction();
903
904 if (errorCount())
905 return;
906
1158 log("-- calculateTypes");907 log("-- calculateTypes");
1159 calculateTypes();908 calculateTypes();
1160 log("-- layoutMemory");
1161 layoutMemory();
1162 log("-- calculateExports");909 log("-- calculateExports");
1163 calculateExports();910 calculateExports();
1164 log("-- calculateCustomSections");911 log("-- calculateCustomSections");
1165 calculateCustomSections();912 calculateCustomSections();
1166 log("-- assignSymtab");913 log("-- populateSymtab");
1167 assignSymtab();914 populateSymtab();
1168915 log("-- addSections");
1169 if (errorHandler().Verbose) {916 addSections();
1170 log("Defined Functions: " + Twine(InputFunctions.size()));917
1171 log("Defined Globals : " + Twine(InputGlobals.size()));918 if (errorHandler().verbose) {
1172 log("Defined Events : " + Twine(InputEvents.size()));919 log("Defined Functions: " + Twine(out.functionSec->inputFunctions.size()));
1173 log("Function Imports : " + Twine(NumImportedFunctions));920 log("Defined Globals : " + Twine(out.globalSec->inputGlobals.size()));
1174 log("Global Imports : " + Twine(NumImportedGlobals));921 log("Defined Events : " + Twine(out.eventSec->inputEvents.size()));
1175 log("Event Imports : " + Twine(NumImportedEvents));922 log("Function Imports : " +
1176 for (ObjFile *File : Symtab->ObjectFiles)923 Twine(out.importSec->getNumImportedFunctions()));
1177 File->dumpInfo();924 log("Global Imports : " + Twine(out.importSec->getNumImportedGlobals()));
925 log("Event Imports : " + Twine(out.importSec->getNumImportedEvents()));
926 for (ObjFile *file : symtab->objectFiles)
927 file->dumpInfo();
1178 }928 }
1179929
1180 createHeader();930 createHeader();
1181 log("-- createSections");931 log("-- finalizeSections");
1182 createSections();932 finalizeSections();
1183933
1184 log("-- openFile");934 log("-- openFile");
1185 openFile();935 openFile();
...@@ -1193,31 +943,31 @@ void Writer::run() {...@@ -1193,31 +943,31 @@ void Writer::run() {
1193 if (errorCount())943 if (errorCount())
1194 return;944 return;
1195945
1196 if (Error E = Buffer->commit())946 if (Error e = buffer->commit())
1197 fatal("failed to write the output file: " + toString(std::move(E)));947 fatal("failed to write the output file: " + toString(std::move(e)));
1198}948}
1199949
1200// Open a result file.950// Open a result file.
1201void Writer::openFile() {951void Writer::openFile() {
1202 log("writing: " + Config->OutputFile);952 log("writing: " + config->outputFile);
1203953
1204 Expected<std::unique_ptr<FileOutputBuffer>> BufferOrErr =954 Expected<std::unique_ptr<FileOutputBuffer>> bufferOrErr =
1205 FileOutputBuffer::create(Config->OutputFile, FileSize,955 FileOutputBuffer::create(config->outputFile, fileSize,
1206 FileOutputBuffer::F_executable);956 FileOutputBuffer::F_executable);
1207957
1208 if (!BufferOrErr)958 if (!bufferOrErr)
1209 error("failed to open " + Config->OutputFile + ": " +959 error("failed to open " + config->outputFile + ": " +
1210 toString(BufferOrErr.takeError()));960 toString(bufferOrErr.takeError()));
1211 else961 else
1212 Buffer = std::move(*BufferOrErr);962 buffer = std::move(*bufferOrErr);
1213}963}
1214964
1215void Writer::createHeader() {965void Writer::createHeader() {
1216 raw_string_ostream OS(Header);966 raw_string_ostream os(header);
1217 writeBytes(OS, WasmMagic, sizeof(WasmMagic), "wasm magic");967 writeBytes(os, WasmMagic, sizeof(WasmMagic), "wasm magic");
1218 writeU32(OS, WasmVersion, "wasm version");968 writeU32(os, WasmVersion, "wasm version");
1219 OS.flush();969 os.flush();
1220 FileSize += Header.size();970 fileSize += header.size();
1221}971}
1222972
1223void lld::wasm::writeResult() { Writer().run(); }973void lld::wasm::writeResult() { Writer().run(); }
deps/lld/wasm/Writer.h+3-6
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- Writer.h -------------------------------------------------*- C++ -*-===//1//===- Writer.h -------------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -15,8 +14,6 @@ namespace wasm {...@@ -15,8 +14,6 @@ namespace wasm {
1514
16void writeResult();15void writeResult();
1716
18extern const char *DefaultModule;
19
20} // namespace wasm17} // namespace wasm
21} // namespace lld18} // namespace lld
2219
deps/lld/wasm/WriterUtils.cpp+104-105
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- WriterUtils.cpp ----------------------------------------------------===//1//===- WriterUtils.cpp ----------------------------------------------------===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -20,159 +19,159 @@ using namespace llvm::wasm;...@@ -20,159 +19,159 @@ using namespace llvm::wasm;
2019
21namespace lld {20namespace lld {
2221
23void wasm::debugWrite(uint64_t Offset, const Twine &Msg) {22void wasm::debugWrite(uint64_t offset, const Twine &msg) {
24 LLVM_DEBUG(dbgs() << format(" | %08lld: ", Offset) << Msg << "\n");23 LLVM_DEBUG(dbgs() << format(" | %08lld: ", offset) << msg << "\n");
25}24}
2625
27void wasm::writeUleb128(raw_ostream &OS, uint32_t Number, const Twine &Msg) {26void wasm::writeUleb128(raw_ostream &os, uint32_t number, const Twine &msg) {
28 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");27 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
29 encodeULEB128(Number, OS);28 encodeULEB128(number, os);
30}29}
3130
32void wasm::writeSleb128(raw_ostream &OS, int32_t Number, const Twine &Msg) {31void wasm::writeSleb128(raw_ostream &os, int32_t number, const Twine &msg) {
33 debugWrite(OS.tell(), Msg + "[" + utohexstr(Number) + "]");32 debugWrite(os.tell(), msg + "[" + utohexstr(number) + "]");
34 encodeSLEB128(Number, OS);33 encodeSLEB128(number, os);
35}34}
3635
37void wasm::writeBytes(raw_ostream &OS, const char *Bytes, size_t Count,36void wasm::writeBytes(raw_ostream &os, const char *bytes, size_t count,
38 const Twine &Msg) {37 const Twine &msg) {
39 debugWrite(OS.tell(), Msg + " [data[" + Twine(Count) + "]]");38 debugWrite(os.tell(), msg + " [data[" + Twine(count) + "]]");
40 OS.write(Bytes, Count);39 os.write(bytes, count);
41}40}
4241
43void wasm::writeStr(raw_ostream &OS, StringRef String, const Twine &Msg) {42void wasm::writeStr(raw_ostream &os, StringRef string, const Twine &msg) {
44 debugWrite(OS.tell(),43 debugWrite(os.tell(),
45 Msg + " [str[" + Twine(String.size()) + "]: " + String + "]");44 msg + " [str[" + Twine(string.size()) + "]: " + string + "]");
46 encodeULEB128(String.size(), OS);45 encodeULEB128(string.size(), os);
47 OS.write(String.data(), String.size());46 os.write(string.data(), string.size());
48}47}
4948
50void wasm::writeU8(raw_ostream &OS, uint8_t Byte, const Twine &Msg) {49void wasm::writeU8(raw_ostream &os, uint8_t byte, const Twine &msg) {
51 debugWrite(OS.tell(), Msg + " [0x" + utohexstr(Byte) + "]");50 debugWrite(os.tell(), msg + " [0x" + utohexstr(byte) + "]");
52 OS << Byte;51 os << byte;
53}52}
5453
55void wasm::writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg) {54void wasm::writeU32(raw_ostream &os, uint32_t number, const Twine &msg) {
56 debugWrite(OS.tell(), Msg + "[0x" + utohexstr(Number) + "]");55 debugWrite(os.tell(), msg + "[0x" + utohexstr(number) + "]");
57 support::endian::write(OS, Number, support::little);56 support::endian::write(os, number, support::little);
58}57}
5958
60void wasm::writeValueType(raw_ostream &OS, ValType Type, const Twine &Msg) {59void wasm::writeValueType(raw_ostream &os, ValType type, const Twine &msg) {
61 writeU8(OS, static_cast<uint8_t>(Type),60 writeU8(os, static_cast<uint8_t>(type),
62 Msg + "[type: " + toString(Type) + "]");61 msg + "[type: " + toString(type) + "]");
63}62}
6463
65void wasm::writeSig(raw_ostream &OS, const WasmSignature &Sig) {64void wasm::writeSig(raw_ostream &os, const WasmSignature &sig) {
66 writeU8(OS, WASM_TYPE_FUNC, "signature type");65 writeU8(os, WASM_TYPE_FUNC, "signature type");
67 writeUleb128(OS, Sig.Params.size(), "param Count");66 writeUleb128(os, sig.Params.size(), "param Count");
68 for (ValType ParamType : Sig.Params) {67 for (ValType paramType : sig.Params) {
69 writeValueType(OS, ParamType, "param type");68 writeValueType(os, paramType, "param type");
70 }69 }
71 writeUleb128(OS, Sig.Returns.size(), "result Count");70 writeUleb128(os, sig.Returns.size(), "result Count");
72 if (Sig.Returns.size()) {71 if (sig.Returns.size()) {
73 writeValueType(OS, Sig.Returns[0], "result type");72 writeValueType(os, sig.Returns[0], "result type");
74 }73 }
75}74}
7675
77void wasm::writeInitExpr(raw_ostream &OS, const WasmInitExpr &InitExpr) {76void wasm::writeInitExpr(raw_ostream &os, const WasmInitExpr &initExpr) {
78 writeU8(OS, InitExpr.Opcode, "opcode");77 writeU8(os, initExpr.Opcode, "opcode");
79 switch (InitExpr.Opcode) {78 switch (initExpr.Opcode) {
80 case WASM_OPCODE_I32_CONST:79 case WASM_OPCODE_I32_CONST:
81 writeSleb128(OS, InitExpr.Value.Int32, "literal (i32)");80 writeSleb128(os, initExpr.Value.Int32, "literal (i32)");
82 break;81 break;
83 case WASM_OPCODE_I64_CONST:82 case WASM_OPCODE_I64_CONST:
84 writeSleb128(OS, InitExpr.Value.Int64, "literal (i64)");83 writeSleb128(os, initExpr.Value.Int64, "literal (i64)");
85 break;84 break;
86 case WASM_OPCODE_GLOBAL_GET:85 case WASM_OPCODE_GLOBAL_GET:
87 writeUleb128(OS, InitExpr.Value.Global, "literal (global index)");86 writeUleb128(os, initExpr.Value.Global, "literal (global index)");
88 break;87 break;
89 default:88 default:
90 fatal("unknown opcode in init expr: " + Twine(InitExpr.Opcode));89 fatal("unknown opcode in init expr: " + Twine(initExpr.Opcode));
91 }90 }
92 writeU8(OS, WASM_OPCODE_END, "opcode:end");91 writeU8(os, WASM_OPCODE_END, "opcode:end");
93}92}
9493
95void wasm::writeLimits(raw_ostream &OS, const WasmLimits &Limits) {94void wasm::writeLimits(raw_ostream &os, const WasmLimits &limits) {
96 writeU8(OS, Limits.Flags, "limits flags");95 writeU8(os, limits.Flags, "limits flags");
97 writeUleb128(OS, Limits.Initial, "limits initial");96 writeUleb128(os, limits.Initial, "limits initial");
98 if (Limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)97 if (limits.Flags & WASM_LIMITS_FLAG_HAS_MAX)
99 writeUleb128(OS, Limits.Maximum, "limits max");98 writeUleb128(os, limits.Maximum, "limits max");
100}99}
101100
102void wasm::writeGlobalType(raw_ostream &OS, const WasmGlobalType &Type) {101void wasm::writeGlobalType(raw_ostream &os, const WasmGlobalType &type) {
103 // TODO: Update WasmGlobalType to use ValType and remove this cast.102 // TODO: Update WasmGlobalType to use ValType and remove this cast.
104 writeValueType(OS, ValType(Type.Type), "global type");103 writeValueType(os, ValType(type.Type), "global type");
105 writeU8(OS, Type.Mutable, "global mutable");104 writeU8(os, type.Mutable, "global mutable");
106}105}
107106
108void wasm::writeGlobal(raw_ostream &OS, const WasmGlobal &Global) {107void wasm::writeGlobal(raw_ostream &os, const WasmGlobal &global) {
109 writeGlobalType(OS, Global.Type);108 writeGlobalType(os, global.Type);
110 writeInitExpr(OS, Global.InitExpr);109 writeInitExpr(os, global.InitExpr);
111}110}
112111
113void wasm::writeEventType(raw_ostream &OS, const WasmEventType &Type) {112void wasm::writeEventType(raw_ostream &os, const WasmEventType &type) {
114 writeUleb128(OS, Type.Attribute, "event attribute");113 writeUleb128(os, type.Attribute, "event attribute");
115 writeUleb128(OS, Type.SigIndex, "sig index");114 writeUleb128(os, type.SigIndex, "sig index");
116}115}
117116
118void wasm::writeEvent(raw_ostream &OS, const WasmEvent &Event) {117void wasm::writeEvent(raw_ostream &os, const WasmEvent &event) {
119 writeEventType(OS, Event.Type);118 writeEventType(os, event.Type);
120}119}
121120
122void wasm::writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type) {121void wasm::writeTableType(raw_ostream &os, const llvm::wasm::WasmTable &type) {
123 writeU8(OS, WASM_TYPE_FUNCREF, "table type");122 writeU8(os, WASM_TYPE_FUNCREF, "table type");
124 writeLimits(OS, Type.Limits);123 writeLimits(os, type.Limits);
125}124}
126125
127void wasm::writeImport(raw_ostream &OS, const WasmImport &Import) {126void wasm::writeImport(raw_ostream &os, const WasmImport &import) {
128 writeStr(OS, Import.Module, "import module name");127 writeStr(os, import.Module, "import module name");
129 writeStr(OS, Import.Field, "import field name");128 writeStr(os, import.Field, "import field name");
130 writeU8(OS, Import.Kind, "import kind");129 writeU8(os, import.Kind, "import kind");
131 switch (Import.Kind) {130 switch (import.Kind) {
132 case WASM_EXTERNAL_FUNCTION:131 case WASM_EXTERNAL_FUNCTION:
133 writeUleb128(OS, Import.SigIndex, "import sig index");132 writeUleb128(os, import.SigIndex, "import sig index");
134 break;133 break;
135 case WASM_EXTERNAL_GLOBAL:134 case WASM_EXTERNAL_GLOBAL:
136 writeGlobalType(OS, Import.Global);135 writeGlobalType(os, import.Global);
137 break;136 break;
138 case WASM_EXTERNAL_EVENT:137 case WASM_EXTERNAL_EVENT:
139 writeEventType(OS, Import.Event);138 writeEventType(os, import.Event);
140 break;139 break;
141 case WASM_EXTERNAL_MEMORY:140 case WASM_EXTERNAL_MEMORY:
142 writeLimits(OS, Import.Memory);141 writeLimits(os, import.Memory);
143 break;142 break;
144 case WASM_EXTERNAL_TABLE:143 case WASM_EXTERNAL_TABLE:
145 writeTableType(OS, Import.Table);144 writeTableType(os, import.Table);
146 break;145 break;
147 default:146 default:
148 fatal("unsupported import type: " + Twine(Import.Kind));147 fatal("unsupported import type: " + Twine(import.Kind));
149 }148 }
150}149}
151150
152void wasm::writeExport(raw_ostream &OS, const WasmExport &Export) {151void wasm::writeExport(raw_ostream &os, const WasmExport &export_) {
153 writeStr(OS, Export.Name, "export name");152 writeStr(os, export_.Name, "export name");
154 writeU8(OS, Export.Kind, "export kind");153 writeU8(os, export_.Kind, "export kind");
155 switch (Export.Kind) {154 switch (export_.Kind) {
156 case WASM_EXTERNAL_FUNCTION:155 case WASM_EXTERNAL_FUNCTION:
157 writeUleb128(OS, Export.Index, "function index");156 writeUleb128(os, export_.Index, "function index");
158 break;157 break;
159 case WASM_EXTERNAL_GLOBAL:158 case WASM_EXTERNAL_GLOBAL:
160 writeUleb128(OS, Export.Index, "global index");159 writeUleb128(os, export_.Index, "global index");
161 break;160 break;
162 case WASM_EXTERNAL_MEMORY:161 case WASM_EXTERNAL_MEMORY:
163 writeUleb128(OS, Export.Index, "memory index");162 writeUleb128(os, export_.Index, "memory index");
164 break;163 break;
165 case WASM_EXTERNAL_TABLE:164 case WASM_EXTERNAL_TABLE:
166 writeUleb128(OS, Export.Index, "table index");165 writeUleb128(os, export_.Index, "table index");
167 break;166 break;
168 default:167 default:
169 fatal("unsupported export type: " + Twine(Export.Kind));168 fatal("unsupported export type: " + Twine(export_.Kind));
170 }169 }
171}170}
172} // namespace lld171} // namespace lld
173172
174std::string lld::toString(ValType Type) {173std::string lld::toString(ValType type) {
175 switch (Type) {174 switch (type) {
176 case ValType::I32:175 case ValType::I32:
177 return "i32";176 return "i32";
178 case ValType::I64:177 case ValType::I64:
...@@ -183,34 +182,34 @@ std::string lld::toString(ValType Type) {...@@ -183,34 +182,34 @@ std::string lld::toString(ValType Type) {
183 return "f64";182 return "f64";
184 case ValType::V128:183 case ValType::V128:
185 return "v128";184 return "v128";
186 case ValType::EXCEPT_REF:185 case ValType::EXNREF:
187 return "except_ref";186 return "exnref";
188 }187 }
189 llvm_unreachable("Invalid wasm::ValType");188 llvm_unreachable("Invalid wasm::ValType");
190}189}
191190
192std::string lld::toString(const WasmSignature &Sig) {191std::string lld::toString(const WasmSignature &sig) {
193 SmallString<128> S("(");192 SmallString<128> s("(");
194 for (ValType Type : Sig.Params) {193 for (ValType type : sig.Params) {
195 if (S.size() != 1)194 if (s.size() != 1)
196 S += ", ";195 s += ", ";
197 S += toString(Type);196 s += toString(type);
198 }197 }
199 S += ") -> ";198 s += ") -> ";
200 if (Sig.Returns.size() == 0)199 if (sig.Returns.empty())
201 S += "void";200 s += "void";
202 else201 else
203 S += toString(Sig.Returns[0]);202 s += toString(sig.Returns[0]);
204 return S.str();203 return s.str();
205}204}
206205
207std::string lld::toString(const WasmGlobalType &Type) {206std::string lld::toString(const WasmGlobalType &type) {
208 return (Type.Mutable ? "var " : "const ") +207 return (type.Mutable ? "var " : "const ") +
209 toString(static_cast<ValType>(Type.Type));208 toString(static_cast<ValType>(type.Type));
210}209}
211210
212std::string lld::toString(const WasmEventType &Type) {211std::string lld::toString(const WasmEventType &type) {
213 if (Type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION)212 if (type.Attribute == WASM_EVENT_ATTRIBUTE_EXCEPTION)
214 return "exception";213 return "exception";
215 return "unknown";214 return "unknown";
216}215}
deps/lld/wasm/WriterUtils.h+27-28
...@@ -1,9 +1,8 @@...@@ -1,9 +1,8 @@
1//===- WriterUtils.h --------------------------------------------*- C++ -*-===//1//===- WriterUtils.h --------------------------------------------*- C++ -*-===//
2//2//
3// The LLVM Linker3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4//4// See https://llvm.org/LICENSE.txt for license information.
5// This file is distributed under the University of Illinois Open Source5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6// License. See LICENSE.TXT for details.
7//6//
8//===----------------------------------------------------------------------===//7//===----------------------------------------------------------------------===//
98
...@@ -17,50 +16,50 @@...@@ -17,50 +16,50 @@
17namespace lld {16namespace lld {
18namespace wasm {17namespace wasm {
1918
20void debugWrite(uint64_t Offset, const Twine &Msg);19void debugWrite(uint64_t offset, const Twine &msg);
2120
22void writeUleb128(raw_ostream &OS, uint32_t Number, const Twine &Msg);21void writeUleb128(raw_ostream &os, uint32_t number, const Twine &msg);
2322
24void writeSleb128(raw_ostream &OS, int32_t Number, const Twine &Msg);23void writeSleb128(raw_ostream &os, int32_t number, const Twine &msg);
2524
26void writeBytes(raw_ostream &OS, const char *Bytes, size_t count,25void writeBytes(raw_ostream &os, const char *bytes, size_t count,
27 const Twine &Msg);26 const Twine &msg);
2827
29void writeStr(raw_ostream &OS, StringRef String, const Twine &Msg);28void writeStr(raw_ostream &os, StringRef string, const Twine &msg);
3029
31void writeU8(raw_ostream &OS, uint8_t byte, const Twine &Msg);30void writeU8(raw_ostream &os, uint8_t byte, const Twine &msg);
3231
33void writeU32(raw_ostream &OS, uint32_t Number, const Twine &Msg);32void writeU32(raw_ostream &os, uint32_t number, const Twine &msg);
3433
35void writeValueType(raw_ostream &OS, llvm::wasm::ValType Type,34void writeValueType(raw_ostream &os, llvm::wasm::ValType type,
36 const Twine &Msg);35 const Twine &msg);
3736
38void writeSig(raw_ostream &OS, const llvm::wasm::WasmSignature &Sig);37void writeSig(raw_ostream &os, const llvm::wasm::WasmSignature &sig);
3938
40void writeInitExpr(raw_ostream &OS, const llvm::wasm::WasmInitExpr &InitExpr);39void writeInitExpr(raw_ostream &os, const llvm::wasm::WasmInitExpr &initExpr);
4140
42void writeLimits(raw_ostream &OS, const llvm::wasm::WasmLimits &Limits);41void writeLimits(raw_ostream &os, const llvm::wasm::WasmLimits &limits);
4342
44void writeGlobalType(raw_ostream &OS, const llvm::wasm::WasmGlobalType &Type);43void writeGlobalType(raw_ostream &os, const llvm::wasm::WasmGlobalType &type);
4544
46void writeGlobal(raw_ostream &OS, const llvm::wasm::WasmGlobal &Global);45void writeGlobal(raw_ostream &os, const llvm::wasm::WasmGlobal &global);
4746
48void writeEventType(raw_ostream &OS, const llvm::wasm::WasmEventType &Type);47void writeEventType(raw_ostream &os, const llvm::wasm::WasmEventType &type);
4948
50void writeEvent(raw_ostream &OS, const llvm::wasm::WasmEvent &Event);49void writeEvent(raw_ostream &os, const llvm::wasm::WasmEvent &event);
5150
52void writeTableType(raw_ostream &OS, const llvm::wasm::WasmTable &Type);51void writeTableType(raw_ostream &os, const llvm::wasm::WasmTable &type);
5352
54void writeImport(raw_ostream &OS, const llvm::wasm::WasmImport &Import);53void writeImport(raw_ostream &os, const llvm::wasm::WasmImport &import);
5554
56void writeExport(raw_ostream &OS, const llvm::wasm::WasmExport &Export);55void writeExport(raw_ostream &os, const llvm::wasm::WasmExport &export_);
5756
58} // namespace wasm57} // namespace wasm
5958
60std::string toString(llvm::wasm::ValType Type);59std::string toString(llvm::wasm::ValType type);
61std::string toString(const llvm::wasm::WasmSignature &Sig);60std::string toString(const llvm::wasm::WasmSignature &sig);
62std::string toString(const llvm::wasm::WasmGlobalType &Type);61std::string toString(const llvm::wasm::WasmGlobalType &type);
63std::string toString(const llvm::wasm::WasmEventType &Type);62std::string toString(const llvm::wasm::WasmEventType &type);
6463
65} // namespace lld64} // namespace lld
6665